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() ...@@ -789,6 +789,18 @@ GLuint Context::createRenderbuffer()
return mResourceManager->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 Context::createVertexArray()
{ {
GLuint handle = mVertexArrayHandleAllocator.allocate(); GLuint handle = mVertexArrayHandleAllocator.allocate();
...@@ -875,6 +887,15 @@ void Context::deleteRenderbuffer(GLuint renderbuffer) ...@@ -875,6 +887,15 @@ void Context::deleteRenderbuffer(GLuint renderbuffer)
mResourceManager->deleteRenderbuffer(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) void Context::deleteVertexArray(GLuint vertexArray)
{ {
auto vertexArrayObject = mVertexArrayMap.find(vertexArray); auto vertexArrayObject = mVertexArrayMap.find(vertexArray);
...@@ -964,6 +985,11 @@ Renderbuffer *Context::getRenderbuffer(GLuint handle) ...@@ -964,6 +985,11 @@ Renderbuffer *Context::getRenderbuffer(GLuint handle)
return mResourceManager->getRenderbuffer(handle); return mResourceManager->getRenderbuffer(handle);
} }
FenceSync *Context::getFenceSync(GLsync handle) const
{
return mResourceManager->getFenceSync(reinterpret_cast<GLuint>(handle));
}
VertexArray *Context::getVertexArray(GLuint handle) const VertexArray *Context::getVertexArray(GLuint handle) const
{ {
auto vertexArray = mVertexArrayMap.find(handle); auto vertexArray = mVertexArrayMap.find(handle);
......
...@@ -64,6 +64,7 @@ class Depthbuffer; ...@@ -64,6 +64,7 @@ class Depthbuffer;
class Stencilbuffer; class Stencilbuffer;
class DepthStencilbuffer; class DepthStencilbuffer;
class FenceNV; class FenceNV;
class FenceSync;
class Query; class Query;
class ResourceManager; class ResourceManager;
class Buffer; class Buffer;
...@@ -257,6 +258,7 @@ class Context ...@@ -257,6 +258,7 @@ class Context
GLuint createTexture(); GLuint createTexture();
GLuint createRenderbuffer(); GLuint createRenderbuffer();
GLuint createSampler(); GLuint createSampler();
GLsync createFenceSync(GLenum condition);
void deleteBuffer(GLuint buffer); void deleteBuffer(GLuint buffer);
void deleteShader(GLuint shader); void deleteShader(GLuint shader);
...@@ -264,12 +266,13 @@ class Context ...@@ -264,12 +266,13 @@ class Context
void deleteTexture(GLuint texture); void deleteTexture(GLuint texture);
void deleteRenderbuffer(GLuint renderbuffer); void deleteRenderbuffer(GLuint renderbuffer);
void deleteSampler(GLuint sampler); void deleteSampler(GLuint sampler);
void deleteFenceSync(GLsync fenceSync);
// Framebuffers are owned by the Context, so these methods do not pass through // Framebuffers are owned by the Context, so these methods do not pass through
GLuint createFramebuffer(); GLuint createFramebuffer();
void deleteFramebuffer(GLuint framebuffer); void deleteFramebuffer(GLuint framebuffer);
// Fences are owned by the Context. // NV Fences are owned by the Context.
GLuint createFenceNV(); GLuint createFenceNV();
void deleteFenceNV(GLuint fence); void deleteFenceNV(GLuint fence);
...@@ -323,6 +326,7 @@ class Context ...@@ -323,6 +326,7 @@ class Context
Buffer *getBuffer(GLuint handle); Buffer *getBuffer(GLuint handle);
FenceNV *getFenceNV(GLuint handle); FenceNV *getFenceNV(GLuint handle);
FenceSync *getFenceSync(GLsync handle) const;
Shader *getShader(GLuint handle); Shader *getShader(GLuint handle);
Program *getProgram(GLuint handle); Program *getProgram(GLuint handle);
Texture *getTexture(GLuint handle); Texture *getTexture(GLuint handle);
......
...@@ -7,6 +7,17 @@ ...@@ -7,6 +7,17 @@
// Fence.cpp: Implements the gl::Fence class, which supports the GL_NV_fence extension. // 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/Fence.h"
#include "libGLESv2/renderer/FenceImpl.h" #include "libGLESv2/renderer/FenceImpl.h"
#include "libGLESv2/renderer/Renderer.h" #include "libGLESv2/renderer/Renderer.h"
...@@ -86,4 +97,91 @@ GLint FenceNV::getFencei(GLenum pname) ...@@ -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 @@ ...@@ -10,6 +10,7 @@
#define LIBGLESV2_FENCE_H_ #define LIBGLESV2_FENCE_H_
#include "common/angleutils.h" #include "common/angleutils.h"
#include "common/RefCountObject.h"
namespace rx namespace rx
{ {
...@@ -44,6 +45,28 @@ class FenceNV ...@@ -44,6 +45,28 @@ class FenceNV
GLenum mCondition; 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_ #endif // LIBGLESV2_FENCE_H_
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include "libGLESv2/Shader.h" #include "libGLESv2/Shader.h"
#include "libGLESv2/Texture.h" #include "libGLESv2/Texture.h"
#include "libGLESv2/Sampler.h" #include "libGLESv2/Sampler.h"
#include "libGLESv2/Fence.h"
namespace gl namespace gl
{ {
...@@ -56,6 +57,11 @@ ResourceManager::~ResourceManager() ...@@ -56,6 +57,11 @@ ResourceManager::~ResourceManager()
{ {
deleteSampler(mSamplerMap.begin()->first); deleteSampler(mSamplerMap.begin()->first);
} }
while (!mFenceSyncMap.empty())
{
deleteFenceSync(mFenceSyncMap.begin()->first);
}
} }
void ResourceManager::addRef() void ResourceManager::addRef()
...@@ -139,6 +145,16 @@ GLuint ResourceManager::createSampler() ...@@ -139,6 +145,16 @@ GLuint ResourceManager::createSampler()
return handle; 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) void ResourceManager::deleteBuffer(GLuint buffer)
{ {
BufferMap::iterator bufferObject = mBufferMap.find(buffer); BufferMap::iterator bufferObject = mBufferMap.find(buffer);
...@@ -225,6 +241,18 @@ void ResourceManager::deleteSampler(GLuint sampler) ...@@ -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) Buffer *ResourceManager::getBuffer(unsigned int handle)
{ {
BufferMap::iterator buffer = mBufferMap.find(handle); BufferMap::iterator buffer = mBufferMap.find(handle);
...@@ -311,6 +339,20 @@ Sampler *ResourceManager::getSampler(unsigned int 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) void ResourceManager::setRenderbuffer(GLuint handle, Renderbuffer *buffer)
{ {
mRenderbufferMap[handle] = buffer; mRenderbufferMap[handle] = buffer;
......
...@@ -37,6 +37,7 @@ class Program; ...@@ -37,6 +37,7 @@ class Program;
class Texture; class Texture;
class Renderbuffer; class Renderbuffer;
class Sampler; class Sampler;
class FenceSync;
class ResourceManager class ResourceManager
{ {
...@@ -53,6 +54,7 @@ class ResourceManager ...@@ -53,6 +54,7 @@ class ResourceManager
GLuint createTexture(); GLuint createTexture();
GLuint createRenderbuffer(); GLuint createRenderbuffer();
GLuint createSampler(); GLuint createSampler();
GLuint createFenceSync();
void deleteBuffer(GLuint buffer); void deleteBuffer(GLuint buffer);
void deleteShader(GLuint shader); void deleteShader(GLuint shader);
...@@ -60,6 +62,7 @@ class ResourceManager ...@@ -60,6 +62,7 @@ class ResourceManager
void deleteTexture(GLuint texture); void deleteTexture(GLuint texture);
void deleteRenderbuffer(GLuint renderbuffer); void deleteRenderbuffer(GLuint renderbuffer);
void deleteSampler(GLuint sampler); void deleteSampler(GLuint sampler);
void deleteFenceSync(GLuint fenceSync);
Buffer *getBuffer(GLuint handle); Buffer *getBuffer(GLuint handle);
Shader *getShader(GLuint handle); Shader *getShader(GLuint handle);
...@@ -67,6 +70,7 @@ class ResourceManager ...@@ -67,6 +70,7 @@ class ResourceManager
Texture *getTexture(GLuint handle); Texture *getTexture(GLuint handle);
Renderbuffer *getRenderbuffer(GLuint handle); Renderbuffer *getRenderbuffer(GLuint handle);
Sampler *getSampler(GLuint handle); Sampler *getSampler(GLuint handle);
FenceSync *getFenceSync(GLuint handle);
void setRenderbuffer(GLuint handle, Renderbuffer *renderbuffer); void setRenderbuffer(GLuint handle, Renderbuffer *renderbuffer);
...@@ -112,6 +116,9 @@ class ResourceManager ...@@ -112,6 +116,9 @@ class ResourceManager
HASH_MAP<GLuint, Sampler*> mSamplerMap; HASH_MAP<GLuint, Sampler*> mSamplerMap;
HandleAllocator mSamplerHandleAllocator; HandleAllocator mSamplerHandleAllocator;
HASH_MAP<GLuint, FenceSync*> mFenceSyncMap;
HandleAllocator mFenceSyncHandleAllocator;
}; };
} }
......
...@@ -67,4 +67,9 @@ bool Fence11::test(bool flushCommandBuffer) ...@@ -67,4 +67,9 @@ bool Fence11::test(bool flushCommandBuffer)
return (result == S_OK); return (result == S_OK);
} }
bool Fence11::hasError() const
{
return mRenderer->isDeviceLost();
}
} }
...@@ -24,6 +24,7 @@ class Fence11 : public FenceImpl ...@@ -24,6 +24,7 @@ class Fence11 : public FenceImpl
bool isSet() const; bool isSet() const;
void set(); void set();
bool test(bool flushCommandBuffer); bool test(bool flushCommandBuffer);
bool hasError() const;
private: private:
DISALLOW_COPY_AND_ASSIGN(Fence11); DISALLOW_COPY_AND_ASSIGN(Fence11);
......
...@@ -68,4 +68,9 @@ bool Fence9::test(bool flushCommandBuffer) ...@@ -68,4 +68,9 @@ bool Fence9::test(bool flushCommandBuffer)
return (result == S_OK); return (result == S_OK);
} }
bool Fence9::hasError() const
{
return mRenderer->isDeviceLost();
}
} }
...@@ -24,6 +24,7 @@ class Fence9 : public FenceImpl ...@@ -24,6 +24,7 @@ class Fence9 : public FenceImpl
bool isSet() const; bool isSet() const;
void set(); void set();
bool test(bool flushCommandBuffer); bool test(bool flushCommandBuffer);
bool hasError() const;
private: private:
DISALLOW_COPY_AND_ASSIGN(Fence9); DISALLOW_COPY_AND_ASSIGN(Fence9);
......
...@@ -23,6 +23,7 @@ class FenceImpl ...@@ -23,6 +23,7 @@ class FenceImpl
virtual bool isSet() const = 0; virtual bool isSet() const = 0;
virtual void set() = 0; virtual void set() = 0;
virtual bool test(bool flushCommandBuffer) = 0; virtual bool test(bool flushCommandBuffer) = 0;
virtual bool hasError() const = 0;
private: private:
DISALLOW_COPY_AND_ASSIGN(FenceImpl); 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