Commit 882033e7 by Geoff Lang

Updated the FenceSync and FenceNV objects to use Error objects.

BUG=angle:520 Change-Id: I1e49b35905d8916baadb129c8aa58a11bd721500 Reviewed-on: https://chromium-review.googlesource.com/220781Reviewed-by: 's avatarShannon Woods <shannonwoods@chromium.org> Tested-by: 's avatarGeoff Lang <geofflang@chromium.org>
parent ed13636a
......@@ -240,15 +240,10 @@ GLuint Context::createRenderbuffer()
return mResourceManager->createRenderbuffer();
}
GLsync Context::createFenceSync(GLenum condition)
GLsync Context::createFenceSync()
{
GLuint handle = mResourceManager->createFenceSync();
gl::FenceSync *fenceSync = mResourceManager->getFenceSync(handle);
ASSERT(fenceSync);
fenceSync->set(condition);
return reinterpret_cast<GLsync>(handle);
}
......
......@@ -86,7 +86,7 @@ class Context
GLuint createRenderbuffer();
GLuint createSampler();
GLuint createTransformFeedback();
GLsync createFenceSync(GLenum condition);
GLsync createFenceSync();
void deleteBuffer(GLuint buffer);
void deleteShader(GLuint shader);
......
......@@ -28,81 +28,110 @@ namespace gl
{
FenceNV::FenceNV(rx::Renderer *renderer)
: mFence(renderer->createFence()),
mIsSet(false),
mStatus(GL_FALSE),
mCondition(GL_NONE)
{
mFence = renderer->createFence();
}
FenceNV::~FenceNV()
{
delete mFence;
SafeDelete(mFence);
}
GLboolean FenceNV::isFence() const
{
// GL_NV_fence spec:
// A name returned by GenFencesNV, but not yet set via SetFenceNV, is not the name of an existing fence.
return (mFence->isSet() ? GL_TRUE : GL_FALSE);
return (mIsSet ? GL_TRUE : GL_FALSE);
}
void FenceNV::setFence(GLenum condition)
Error FenceNV::setFence(GLenum condition)
{
mFence->set();
Error error = mFence->set();
if (error.isError())
{
return error;
}
mCondition = condition;
mStatus = GL_FALSE;
mIsSet = true;
return Error(GL_NO_ERROR);
}
GLboolean FenceNV::testFence()
Error FenceNV::testFence(GLboolean *outResult)
{
// Flush the command buffer by default
bool result = mFence->test(true);
Error error = mFence->test(true, &mStatus);
if (error.isError())
{
return error;
}
mStatus = (result ? GL_TRUE : GL_FALSE);
return mStatus;
*outResult = mStatus;
return Error(GL_NO_ERROR);
}
void FenceNV::finishFence()
Error FenceNV::finishFence()
{
ASSERT(mFence->isSet());
ASSERT(mIsSet);
while (!mFence->test(true))
while (mStatus != GL_TRUE)
{
Error error = mFence->test(true, &mStatus);
if (error.isError())
{
return error;
}
Sleep(0);
}
return Error(GL_NO_ERROR);
}
GLint FenceNV::getFencei(GLenum pname)
Error FenceNV::getFencei(GLenum pname, GLint *params)
{
ASSERT(mFence->isSet());
ASSERT(mIsSet);
switch (pname)
{
case GL_FENCE_STATUS_NV:
// GL_NV_fence spec:
// Once the status of a fence has been finished (via FinishFenceNV) or tested and the returned status is TRUE (via either TestFenceNV
// or GetFenceivNV querying the FENCE_STATUS_NV), the status remains TRUE until the next SetFenceNV of the fence.
if (mStatus != GL_TRUE)
{
// GL_NV_fence spec:
// Once the status of a fence has been finished (via FinishFenceNV) or tested and the returned status is TRUE (via either TestFenceNV
// or GetFenceivNV querying the FENCE_STATUS_NV), the status remains TRUE until the next SetFenceNV of the fence.
if (mStatus == GL_TRUE)
Error error = mFence->test(false, &mStatus);
if (error.isError())
{
return GL_TRUE;
return error;
}
mStatus = (mFence->test(false) ? GL_TRUE : GL_FALSE);
return mStatus;
}
*params = mStatus;
break;
case GL_FENCE_CONDITION_NV:
return mCondition;
*params = mCondition;
break;
default: UNREACHABLE(); return 0;
default:
UNREACHABLE();
return gl::Error(GL_INVALID_OPERATION);
}
return Error(GL_NO_ERROR);
}
FenceSync::FenceSync(rx::Renderer *renderer, GLuint id)
: RefCountObject(id)
: RefCountObject(id),
mFence(renderer->createFence()),
mCounterFrequency(0),
mCondition(GL_NONE)
{
mFence = renderer->createFence();
LARGE_INTEGER counterFreqency = { 0 };
BOOL success = QueryPerformanceFrequency(&counterFreqency);
UNUSED_ASSERTION_VARIABLE(success);
......@@ -113,34 +142,45 @@ FenceSync::FenceSync(rx::Renderer *renderer, GLuint id)
FenceSync::~FenceSync()
{
delete mFence;
SafeDelete(mFence);
}
void FenceSync::set(GLenum condition)
Error FenceSync::set(GLenum condition)
{
Error error = mFence->set();
if (error.isError())
{
return error;
}
mCondition = condition;
mFence->set();
return Error(GL_NO_ERROR);
}
GLenum FenceSync::clientWait(GLbitfield flags, GLuint64 timeout)
Error FenceSync::clientWait(GLbitfield flags, GLuint64 timeout, GLenum *outResult)
{
ASSERT(mFence->isSet());
ASSERT(mCondition != GL_NONE);
bool flushCommandBuffer = ((flags & GL_SYNC_FLUSH_COMMANDS_BIT) != 0);
if (mFence->test(flushCommandBuffer))
GLboolean result = GL_FALSE;
Error error = mFence->test(flushCommandBuffer, &result);
if (error.isError())
{
return GL_ALREADY_SIGNALED;
*outResult = GL_WAIT_FAILED;
return error;
}
if (mFence->hasError())
if (result == GL_TRUE)
{
return GL_WAIT_FAILED;
*outResult = GL_ALREADY_SIGNALED;
return Error(GL_NO_ERROR);
}
if (timeout == 0)
{
return GL_TIMEOUT_EXPIRED;
*outResult = GL_TIMEOUT_EXPIRED;
return Error(GL_NO_ERROR);
}
LARGE_INTEGER currentCounter = { 0 };
......@@ -151,44 +191,56 @@ GLenum FenceSync::clientWait(GLbitfield flags, GLuint64 timeout)
LONGLONG timeoutInSeconds = static_cast<LONGLONG>(timeout) * static_cast<LONGLONG>(1000000ll);
LONGLONG endCounter = currentCounter.QuadPart + mCounterFrequency * timeoutInSeconds;
while (currentCounter.QuadPart < endCounter && !mFence->test(flushCommandBuffer))
while (currentCounter.QuadPart < endCounter && !result)
{
Sleep(0);
BOOL success = QueryPerformanceCounter(&currentCounter);
UNUSED_ASSERTION_VARIABLE(success);
ASSERT(success);
}
if (mFence->hasError())
{
return GL_WAIT_FAILED;
error = mFence->test(flushCommandBuffer, &result);
if (error.isError())
{
*outResult = GL_WAIT_FAILED;
return error;
}
}
if (currentCounter.QuadPart >= endCounter)
{
return GL_TIMEOUT_EXPIRED;
*outResult = GL_TIMEOUT_EXPIRED;
}
else
{
*outResult = GL_CONDITION_SATISFIED;
}
return GL_CONDITION_SATISFIED;
return Error(GL_NO_ERROR);
}
void FenceSync::serverWait()
Error FenceSync::serverWait()
{
// Because our API is currently designed to be called from a single thread, we don't need to do
// extra work for a server-side fence. GPU commands issued after the fence is created will always
// be processed after the fence is signaled.
return Error(GL_NO_ERROR);
}
GLenum FenceSync::getStatus() const
Error FenceSync::getStatus(GLint *outResult) const
{
if (mFence->test(false))
GLboolean result = GL_FALSE;
Error error = mFence->test(false, &result);
if (error.isError())
{
// The spec does not specify any way to report errors during the status test (e.g. device lost)
// so we report the fence is unblocked in case of error or signaled.
return GL_SIGNALED;
*outResult = GL_SIGNALED;
return error;
}
return GL_UNSIGNALED;
*outResult = (result ? GL_SIGNALED : GL_UNSIGNALED);
return Error(GL_NO_ERROR);
}
}
......@@ -9,6 +9,8 @@
#ifndef LIBGLESV2_FENCE_H_
#define LIBGLESV2_FENCE_H_
#include "libGLESv2/Error.h"
#include "common/angleutils.h"
#include "common/RefCountObject.h"
......@@ -28,10 +30,10 @@ class FenceNV
virtual ~FenceNV();
GLboolean isFence() const;
void setFence(GLenum condition);
GLboolean testFence();
void finishFence();
GLint getFencei(GLenum pname);
Error setFence(GLenum condition);
Error testFence(GLboolean *outResult);
Error finishFence();
Error getFencei(GLenum pname, GLint *params);
GLboolean getStatus() const { return mStatus; }
GLuint getCondition() const { return mCondition; }
......@@ -41,6 +43,8 @@ class FenceNV
rx::FenceImpl *mFence;
bool mIsSet;
GLboolean mStatus;
GLenum mCondition;
};
......@@ -51,10 +55,10 @@ class FenceSync : public RefCountObject
explicit FenceSync(rx::Renderer *renderer, GLuint id);
virtual ~FenceSync();
void set(GLenum condition);
GLenum clientWait(GLbitfield flags, GLuint64 timeout);
void serverWait();
GLenum getStatus() const;
Error set(GLenum condition);
Error clientWait(GLbitfield flags, GLuint64 timeout, GLenum *outResult);
Error serverWait();
Error getStatus(GLint *outResult) const;
GLuint getCondition() const { return mCondition; }
......
......@@ -2117,7 +2117,12 @@ void __stdcall glGetFenceivNV(GLuint fence, GLenum pname, GLint *params)
return;
}
params[0] = fenceObject->getFencei(pname);
gl::Error error = fenceObject->getFencei(pname, params);
if (error.isError())
{
context->recordError(error);
return;
}
}
}
......@@ -3861,7 +3866,12 @@ void __stdcall glSetFenceNV(GLuint fence, GLenum condition)
return;
}
fenceObject->setFence(condition);
gl::Error error = fenceObject->setFence(condition);
if (error.isError())
{
context->recordError(error);
return;
}
}
}
......@@ -4135,7 +4145,15 @@ GLboolean __stdcall glTestFenceNV(GLuint fence)
return GL_TRUE;
}
return fenceObject->testFence();
GLboolean result;
gl::Error error = fenceObject->testFence(&result);
if (error.isError())
{
context->recordError(error);
return GL_TRUE;
}
return result;
}
return GL_TRUE;
......@@ -7350,7 +7368,18 @@ GLsync __stdcall glFenceSync(GLenum condition, GLbitfield flags)
return 0;
}
return context->createFenceSync(condition);
GLsync fenceSync = context->createFenceSync();
gl::FenceSync *fenceSyncObject = context->getFenceSync(fenceSync);
gl::Error error = fenceSyncObject->set(condition);
if (error.isError())
{
context->deleteFenceSync(fenceSync);
context->recordError(error);
return NULL;
}
return fenceSync;
}
return NULL;
......@@ -7426,7 +7455,15 @@ GLenum __stdcall glClientWaitSync(GLsync sync, GLbitfield flags, GLuint64 timeou
return GL_WAIT_FAILED;
}
return fenceSync->clientWait(flags, timeout);
GLenum result = GL_WAIT_FAILED;
gl::Error error = fenceSync->clientWait(flags, timeout, &result);
if (error.isError())
{
context->recordError(error);
return GL_WAIT_FAILED;
}
return result;
}
return GL_FALSE;
......@@ -7466,7 +7503,11 @@ void __stdcall glWaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout)
return;
}
fenceSync->serverWait();
gl::Error error = fenceSync->serverWait();
if (error.isError())
{
context->recordError(error);
}
}
}
......@@ -7533,10 +7574,20 @@ void __stdcall glGetSynciv(GLsync sync, GLenum pname, GLsizei bufSize, GLsizei*
switch (pname)
{
case GL_OBJECT_TYPE: values[0] = static_cast<GLint>(GL_SYNC_FENCE); break;
case GL_SYNC_STATUS: values[0] = static_cast<GLint>(fenceSync->getStatus()); break;
case GL_SYNC_CONDITION: values[0] = static_cast<GLint>(fenceSync->getCondition()); break;
case GL_SYNC_FLAGS: values[0] = 0; break;
case GL_SYNC_STATUS:
{
gl::Error error = fenceSync->getStatus(values);
if (error.isError())
{
context->recordError(error);
return;
}
break;
}
default:
context->recordError(gl::Error(GL_INVALID_ENUM));
return;
......
......@@ -9,6 +9,8 @@
#ifndef LIBGLESV2_RENDERER_FENCEIMPL_H_
#define LIBGLESV2_RENDERER_FENCEIMPL_H_
#include "libGLESv2/Error.h"
#include "common/angleutils.h"
namespace rx
......@@ -20,10 +22,8 @@ class FenceImpl
FenceImpl() { };
virtual ~FenceImpl() { };
virtual bool isSet() const = 0;
virtual void set() = 0;
virtual bool test(bool flushCommandBuffer) = 0;
virtual bool hasError() const = 0;
virtual gl::Error set() = 0;
virtual gl::Error test(bool flushCommandBuffer, GLboolean *outFinished) = 0;
private:
DISALLOW_COPY_AND_ASSIGN(FenceImpl);
......
......@@ -14,9 +14,9 @@ namespace rx
{
Fence11::Fence11(rx::Renderer11 *renderer)
: mRenderer(renderer),
mQuery(NULL)
{
mRenderer = renderer;
mQuery = NULL;
}
Fence11::~Fence11()
......@@ -24,12 +24,7 @@ Fence11::~Fence11()
SafeRelease(mQuery);
}
bool Fence11::isSet() const
{
return mQuery != NULL;
}
void Fence11::set()
gl::Error Fence11::set()
{
if (!mQuery)
{
......@@ -37,34 +32,36 @@ void Fence11::set()
queryDesc.Query = D3D11_QUERY_EVENT;
queryDesc.MiscFlags = 0;
if (FAILED(mRenderer->getDevice()->CreateQuery(&queryDesc, &mQuery)))
HRESULT result = mRenderer->getDevice()->CreateQuery(&queryDesc, &mQuery);
if (FAILED(result))
{
return gl::error(GL_OUT_OF_MEMORY);
return gl::Error(GL_OUT_OF_MEMORY, "Failed to create event query, result: 0x%X.", result);
}
}
mRenderer->getDeviceContext()->End(mQuery);
return gl::Error(GL_NO_ERROR);
}
bool Fence11::test(bool flushCommandBuffer)
gl::Error Fence11::test(bool flushCommandBuffer, GLboolean *outFinished)
{
ASSERT(mQuery);
UINT getDataFlags = (flushCommandBuffer ? 0 : D3D11_ASYNC_GETDATA_DONOTFLUSH);
HRESULT result = mRenderer->getDeviceContext()->GetData(mQuery, NULL, 0, getDataFlags);
if (mRenderer->isDeviceLost())
if (FAILED(result))
{
return gl::Error(GL_OUT_OF_MEMORY, "Failed to get query data, result: 0x%X.", result);
}
else if (mRenderer->isDeviceLost())
{
return gl::error(GL_OUT_OF_MEMORY, true);
return gl::Error(GL_OUT_OF_MEMORY, "Device was lost while querying result of an event query.");
}
ASSERT(result == S_OK || result == S_FALSE);
return (result == S_OK);
}
bool Fence11::hasError() const
{
return mRenderer->isDeviceLost();
*outFinished = ((result == S_OK) ? GL_TRUE : GL_FALSE);
return gl::Error(GL_NO_ERROR);
}
}
......@@ -21,10 +21,8 @@ class Fence11 : public FenceImpl
explicit Fence11(rx::Renderer11 *renderer);
virtual ~Fence11();
bool isSet() const;
void set();
bool test(bool flushCommandBuffer);
bool hasError() const;
gl::Error set();
gl::Error test(bool flushCommandBuffer, GLboolean *outFinished);
private:
DISALLOW_COPY_AND_ASSIGN(Fence11);
......
......@@ -15,9 +15,9 @@ namespace rx
{
Fence9::Fence9(rx::Renderer9 *renderer)
: mRenderer(renderer),
mQuery(NULL)
{
mRenderer = renderer;
mQuery = NULL;
}
Fence9::~Fence9()
......@@ -25,28 +25,29 @@ Fence9::~Fence9()
SafeRelease(mQuery);
}
bool Fence9::isSet() const
{
return mQuery != NULL;
}
void Fence9::set()
gl::Error Fence9::set()
{
if (!mQuery)
{
mQuery = mRenderer->allocateEventQuery();
if (!mQuery)
gl::Error error = mRenderer->allocateEventQuery(&mQuery);
if (error.isError())
{
return gl::error(GL_OUT_OF_MEMORY);
return error;
}
}
HRESULT result = mQuery->Issue(D3DISSUE_END);
UNUSED_ASSERTION_VARIABLE(result);
ASSERT(SUCCEEDED(result));
if (FAILED(result))
{
ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
SafeRelease(mQuery);
return gl::Error(GL_OUT_OF_MEMORY, "Failed to end event query, result: 0x%X.", result);
}
return gl::Error(GL_NO_ERROR);
}
bool Fence9::test(bool flushCommandBuffer)
gl::Error Fence9::test(bool flushCommandBuffer, GLboolean *outFinished)
{
ASSERT(mQuery);
......@@ -56,17 +57,16 @@ bool Fence9::test(bool flushCommandBuffer)
if (d3d9::isDeviceLostError(result))
{
mRenderer->notifyDeviceLost();
return gl::error(GL_OUT_OF_MEMORY, true);
return gl::Error(GL_OUT_OF_MEMORY, "Device was lost while querying result of an event query.");
}
else if (FAILED(result))
{
return gl::Error(GL_OUT_OF_MEMORY, "Failed to get query data, result: 0x%X.", result);
}
ASSERT(result == S_OK || result == S_FALSE);
return (result == S_OK);
}
bool Fence9::hasError() const
{
return mRenderer->isDeviceLost();
*outFinished = ((result == S_OK) ? GL_TRUE : GL_FALSE);
return gl::Error(GL_NO_ERROR);
}
}
......@@ -21,10 +21,8 @@ class Fence9 : public FenceImpl
explicit Fence9(rx::Renderer9 *renderer);
virtual ~Fence9();
bool isSet() const;
void set();
bool test(bool flushCommandBuffer);
bool hasError() const;
gl::Error set();
gl::Error test(bool flushCommandBuffer, GLboolean *outFinished);
private:
DISALLOW_COPY_AND_ASSIGN(Fence9);
......
......@@ -492,15 +492,14 @@ void Renderer9::endScene()
void Renderer9::sync(bool block)
{
HRESULT result;
IDirect3DQuery9* query = allocateEventQuery();
if (!query)
IDirect3DQuery9* query = NULL;
gl::Error error = allocateEventQuery(&query);
if (error.isError())
{
return;
}
result = query->Issue(D3DISSUE_END);
HRESULT result = query->Issue(D3DISSUE_END);
ASSERT(SUCCEEDED(result));
do
......@@ -535,23 +534,24 @@ SwapChain *Renderer9::createSwapChain(rx::NativeWindow nativeWindow, HANDLE shar
return new rx::SwapChain9(this, nativeWindow, shareHandle, backBufferFormat, depthBufferFormat);
}
IDirect3DQuery9* Renderer9::allocateEventQuery()
gl::Error Renderer9::allocateEventQuery(IDirect3DQuery9 **outQuery)
{
IDirect3DQuery9 *query = NULL;
if (mEventQueryPool.empty())
{
HRESULT result = mDevice->CreateQuery(D3DQUERYTYPE_EVENT, &query);
UNUSED_ASSERTION_VARIABLE(result);
ASSERT(SUCCEEDED(result));
HRESULT result = mDevice->CreateQuery(D3DQUERYTYPE_EVENT, outQuery);
if (FAILED(result))
{
ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate event query, result: 0x%X.", result);
}
}
else
{
query = mEventQueryPool.back();
*outQuery = mEventQueryPool.back();
mEventQueryPool.pop_back();
}
return query;
return gl::Error(GL_NO_ERROR);
}
void Renderer9::freeEventQuery(IDirect3DQuery9* query)
......
......@@ -52,7 +52,7 @@ class Renderer9 : public Renderer
virtual SwapChain *createSwapChain(rx::NativeWindow nativeWindow, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat);
IDirect3DQuery9* allocateEventQuery();
gl::Error allocateEventQuery(IDirect3DQuery9 **outQuery);
void freeEventQuery(IDirect3DQuery9* query);
// resource creation
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment