Commit cd055f81 by Jamie Madill

Add state for the new fence sync objects in ES3.

TRAC #23446 Signed-off-by: Geoff Lang Signed-off-by: Shannon Woods Authored-by: Jamie Madill
parent be26b522
......@@ -789,6 +789,18 @@ GLuint Context::createRenderbuffer()
return mResourceManager->createRenderbuffer();
}
GLsync Context::createFenceSync(GLenum condition)
{
GLuint handle = mResourceManager->createFenceSync();
gl::FenceSync *fenceSync = mResourceManager->getFenceSync(handle);
ASSERT(fenceSync);
fenceSync->set(condition);
return reinterpret_cast<GLsync>(handle);
}
GLuint Context::createVertexArray()
{
GLuint handle = mVertexArrayHandleAllocator.allocate();
......@@ -875,6 +887,15 @@ void Context::deleteRenderbuffer(GLuint renderbuffer)
mResourceManager->deleteRenderbuffer(renderbuffer);
}
void Context::deleteFenceSync(GLsync fenceSync)
{
// The spec specifies the underlying Fence object is not deleted until all current
// wait commands finish. However, since the name becomes invalid, we cannot query the fence,
// and since our API is currently designed for being called from a single thread, we can delete
// the fence immediately.
mResourceManager->deleteFenceSync(reinterpret_cast<GLuint>(fenceSync));
}
void Context::deleteVertexArray(GLuint vertexArray)
{
auto vertexArrayObject = mVertexArrayMap.find(vertexArray);
......@@ -964,6 +985,11 @@ Renderbuffer *Context::getRenderbuffer(GLuint handle)
return mResourceManager->getRenderbuffer(handle);
}
FenceSync *Context::getFenceSync(GLsync handle) const
{
return mResourceManager->getFenceSync(reinterpret_cast<GLuint>(handle));
}
VertexArray *Context::getVertexArray(GLuint handle) const
{
auto vertexArray = mVertexArrayMap.find(handle);
......
......@@ -64,6 +64,7 @@ class Depthbuffer;
class Stencilbuffer;
class DepthStencilbuffer;
class FenceNV;
class FenceSync;
class Query;
class ResourceManager;
class Buffer;
......@@ -257,6 +258,7 @@ class Context
GLuint createTexture();
GLuint createRenderbuffer();
GLuint createSampler();
GLsync createFenceSync(GLenum condition);
void deleteBuffer(GLuint buffer);
void deleteShader(GLuint shader);
......@@ -264,12 +266,13 @@ class Context
void deleteTexture(GLuint texture);
void deleteRenderbuffer(GLuint renderbuffer);
void deleteSampler(GLuint sampler);
void deleteFenceSync(GLsync fenceSync);
// Framebuffers are owned by the Context, so these methods do not pass through
GLuint createFramebuffer();
void deleteFramebuffer(GLuint framebuffer);
// Fences are owned by the Context.
// NV Fences are owned by the Context.
GLuint createFenceNV();
void deleteFenceNV(GLuint fence);
......@@ -323,6 +326,7 @@ class Context
Buffer *getBuffer(GLuint handle);
FenceNV *getFenceNV(GLuint handle);
FenceSync *getFenceSync(GLsync handle) const;
Shader *getShader(GLuint handle);
Program *getProgram(GLuint handle);
Texture *getTexture(GLuint handle);
......
......@@ -7,6 +7,17 @@
// Fence.cpp: Implements the gl::Fence class, which supports the GL_NV_fence extension.
// Important note on accurate timers in Windows:
//
// QueryPerformanceCounter has a few major issues, including being 10x as expensive to call
// as timeGetTime on laptops and "jumping" during certain hardware events.
//
// See the comments at the top of the Chromium source file "chromium/src/base/time/time_win.cc"
// https://code.google.com/p/chromium/codesearch#chromium/src/base/time/time_win.cc
//
// We still opt to use QPC. In the present and moving forward, most newer systems will not suffer
// from buggy implementations.
#include "libGLESv2/Fence.h"
#include "libGLESv2/renderer/FenceImpl.h"
#include "libGLESv2/renderer/Renderer.h"
......@@ -86,4 +97,91 @@ GLint FenceNV::getFencei(GLenum pname)
}
}
FenceSync::FenceSync(rx::Renderer *renderer, GLuint id)
: RefCountObject(id)
{
mFence = renderer->createFence();
LARGE_INTEGER counterFreqency;
ASSERT(QueryPerformanceFrequency(&counterFreqency));
mCounterFrequency = counterFreqency.QuadPart;
}
FenceSync::~FenceSync()
{
delete mFence;
}
void FenceSync::set(GLenum condition)
{
mCondition = condition;
mFence->set();
}
GLenum FenceSync::clientWait(GLbitfield flags, GLuint64 timeout)
{
ASSERT(mFence->isSet());
bool flushCommandBuffer = ((flags & GL_SYNC_FLUSH_COMMANDS_BIT) != 0);
if (mFence->test(flushCommandBuffer))
{
return GL_ALREADY_SIGNALED;
}
if (mFence->hasError())
{
return GL_WAIT_FAILED;
}
if (timeout == 0)
{
return GL_TIMEOUT_EXPIRED;
}
LARGE_INTEGER currentCounter;
ASSERT(QueryPerformanceCounter(&currentCounter));
LONGLONG timeoutInSeconds = static_cast<LONGLONG>(timeout) * static_cast<LONGLONG>(1000000ll);
LONGLONG endCounter = currentCounter.QuadPart + mCounterFrequency * timeoutInSeconds;
while (currentCounter.QuadPart < endCounter && !mFence->test(flushCommandBuffer))
{
Sleep(0);
ASSERT(QueryPerformanceCounter(&currentCounter));
}
if (mFence->hasError())
{
return GL_WAIT_FAILED;
}
if (currentCounter.QuadPart >= endCounter)
{
return GL_TIMEOUT_EXPIRED;
}
return GL_CONDITION_SATISFIED;
}
void 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.
}
GLenum FenceSync::getStatus() const
{
if (mFence->test(false))
{
// 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;
}
return GL_UNSIGNALED;
}
}
......@@ -10,6 +10,7 @@
#define LIBGLESV2_FENCE_H_
#include "common/angleutils.h"
#include "common/RefCountObject.h"
namespace rx
{
......@@ -44,6 +45,28 @@ class FenceNV
GLenum mCondition;
};
class FenceSync : public RefCountObject
{
public:
explicit FenceSync(rx::Renderer *renderer, GLuint id);
virtual ~FenceSync();
void set(GLenum condition);
GLenum clientWait(GLbitfield flags, GLuint64 timeout);
void serverWait();
GLenum getStatus() const;
GLuint getCondition() const { return mCondition; }
private:
DISALLOW_COPY_AND_ASSIGN(FenceSync);
rx::FenceImpl *mFence;
LONGLONG mCounterFrequency;
GLenum mCondition;
};
}
#endif // LIBGLESV2_FENCE_H_
......@@ -16,6 +16,7 @@
#include "libGLESv2/Shader.h"
#include "libGLESv2/Texture.h"
#include "libGLESv2/Sampler.h"
#include "libGLESv2/Fence.h"
namespace gl
{
......@@ -56,6 +57,11 @@ ResourceManager::~ResourceManager()
{
deleteSampler(mSamplerMap.begin()->first);
}
while (!mFenceSyncMap.empty())
{
deleteFenceSync(mFenceSyncMap.begin()->first);
}
}
void ResourceManager::addRef()
......@@ -139,6 +145,16 @@ GLuint ResourceManager::createSampler()
return handle;
}
// Returns the next unused fence name, and allocates the fence
GLuint ResourceManager::createFenceSync()
{
GLuint handle = mFenceSyncHandleAllocator.allocate();
mFenceSyncMap[handle] = new FenceSync(mRenderer, handle);
return handle;
}
void ResourceManager::deleteBuffer(GLuint buffer)
{
BufferMap::iterator bufferObject = mBufferMap.find(buffer);
......@@ -225,6 +241,18 @@ void ResourceManager::deleteSampler(GLuint sampler)
}
}
void ResourceManager::deleteFenceSync(GLuint fenceSync)
{
auto fenceObjectIt = mFenceSyncMap.find(fenceSync);
if (fenceObjectIt != mFenceSyncMap.end())
{
mFenceSyncHandleAllocator.release(fenceObjectIt->first);
if (fenceObjectIt->second) fenceObjectIt->second->release();
mFenceSyncMap.erase(fenceObjectIt);
}
}
Buffer *ResourceManager::getBuffer(unsigned int handle)
{
BufferMap::iterator buffer = mBufferMap.find(handle);
......@@ -311,6 +339,20 @@ Sampler *ResourceManager::getSampler(unsigned int handle)
}
}
FenceSync *ResourceManager::getFenceSync(unsigned int handle)
{
auto fenceObjectIt = mFenceSyncMap.find(handle);
if (fenceObjectIt == mFenceSyncMap.end())
{
return NULL;
}
else
{
return fenceObjectIt->second;
}
}
void ResourceManager::setRenderbuffer(GLuint handle, Renderbuffer *buffer)
{
mRenderbufferMap[handle] = buffer;
......
......@@ -37,6 +37,7 @@ class Program;
class Texture;
class Renderbuffer;
class Sampler;
class FenceSync;
class ResourceManager
{
......@@ -53,6 +54,7 @@ class ResourceManager
GLuint createTexture();
GLuint createRenderbuffer();
GLuint createSampler();
GLuint createFenceSync();
void deleteBuffer(GLuint buffer);
void deleteShader(GLuint shader);
......@@ -60,6 +62,7 @@ class ResourceManager
void deleteTexture(GLuint texture);
void deleteRenderbuffer(GLuint renderbuffer);
void deleteSampler(GLuint sampler);
void deleteFenceSync(GLuint fenceSync);
Buffer *getBuffer(GLuint handle);
Shader *getShader(GLuint handle);
......@@ -67,6 +70,7 @@ class ResourceManager
Texture *getTexture(GLuint handle);
Renderbuffer *getRenderbuffer(GLuint handle);
Sampler *getSampler(GLuint handle);
FenceSync *getFenceSync(GLuint handle);
void setRenderbuffer(GLuint handle, Renderbuffer *renderbuffer);
......@@ -112,6 +116,9 @@ class ResourceManager
HASH_MAP<GLuint, Sampler*> mSamplerMap;
HandleAllocator mSamplerHandleAllocator;
HASH_MAP<GLuint, FenceSync*> mFenceSyncMap;
HandleAllocator mFenceSyncHandleAllocator;
};
}
......
......@@ -67,4 +67,9 @@ bool Fence11::test(bool flushCommandBuffer)
return (result == S_OK);
}
bool Fence11::hasError() const
{
return mRenderer->isDeviceLost();
}
}
......@@ -24,6 +24,7 @@ class Fence11 : public FenceImpl
bool isSet() const;
void set();
bool test(bool flushCommandBuffer);
bool hasError() const;
private:
DISALLOW_COPY_AND_ASSIGN(Fence11);
......
......@@ -68,4 +68,9 @@ bool Fence9::test(bool flushCommandBuffer)
return (result == S_OK);
}
bool Fence9::hasError() const
{
return mRenderer->isDeviceLost();
}
}
......@@ -24,6 +24,7 @@ class Fence9 : public FenceImpl
bool isSet() const;
void set();
bool test(bool flushCommandBuffer);
bool hasError() const;
private:
DISALLOW_COPY_AND_ASSIGN(Fence9);
......
......@@ -23,6 +23,7 @@ class FenceImpl
virtual bool isSet() const = 0;
virtual void set() = 0;
virtual bool test(bool flushCommandBuffer) = 0;
virtual bool hasError() const = 0;
private:
DISALLOW_COPY_AND_ASSIGN(FenceImpl);
......
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