Commit 617103ed by Geoff Lang Committed by Commit Bot

GL: Implement GL_NV_fence on top of GLsync objects.

When ANGLE exposes an ES2 context, there is often no way to create fence objects because GL_NV_fence is not available. BUG=882580 Change-Id: Ic18539e0243317a188545f3945f6b33d3401f1a8 Reviewed-on: https://chromium-review.googlesource.com/c/1348769Reviewed-by: 's avatarYuly Novikov <ynovikov@chromium.org> Reviewed-by: 's avatarShahbaz Youssefi <syoussefi@chromium.org> Commit-Queue: Geoff Lang <geofflang@chromium.org>
parent 0d665139
...@@ -117,7 +117,16 @@ QueryImpl *ContextGL::createQuery(gl::QueryType type) ...@@ -117,7 +117,16 @@ QueryImpl *ContextGL::createQuery(gl::QueryType type)
FenceNVImpl *ContextGL::createFenceNV() FenceNVImpl *ContextGL::createFenceNV()
{ {
return new FenceNVGL(getFunctions()); const FunctionsGL *functions = getFunctions();
if (FenceNVGL::Supported(functions))
{
return new FenceNVGL(functions);
}
else
{
ASSERT(FenceNVSyncGL::Supported(functions));
return new FenceNVSyncGL(functions);
}
} }
SyncImpl *ContextGL::createSync() SyncImpl *ContextGL::createSync()
......
...@@ -9,6 +9,8 @@ ...@@ -9,6 +9,8 @@
#include "libANGLE/renderer/gl/FenceNVGL.h" #include "libANGLE/renderer/gl/FenceNVGL.h"
#include "common/debug.h" #include "common/debug.h"
#include "libANGLE/Context.h"
#include "libANGLE/renderer/gl/ContextGL.h"
#include "libANGLE/renderer/gl/FunctionsGL.h" #include "libANGLE/renderer/gl/FunctionsGL.h"
...@@ -48,4 +50,61 @@ angle::Result FenceNVGL::finish(const gl::Context *context) ...@@ -48,4 +50,61 @@ angle::Result FenceNVGL::finish(const gl::Context *context)
return angle::Result::Continue(); return angle::Result::Continue();
} }
// static
bool FenceNVGL::Supported(const FunctionsGL *functions)
{
return functions->hasGLESExtension("GL_NV_fence") || functions->hasGLExtension("GL_NV_fence");
}
FenceNVSyncGL::FenceNVSyncGL(const FunctionsGL *functions)
: FenceNVImpl(), mSyncObject(0), mFunctions(functions)
{
}
FenceNVSyncGL::~FenceNVSyncGL()
{
if (mSyncObject != 0)
{
mFunctions->deleteSync(mSyncObject);
mSyncObject = 0;
}
}
angle::Result FenceNVSyncGL::set(const gl::Context *context, GLenum condition)
{
ASSERT(condition == GL_ALL_COMPLETED_NV);
mSyncObject = mFunctions->fenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
ANGLE_CHECK(GetImplAs<ContextGL>(context), mSyncObject != 0,
"glFenceSync failed to create a GLsync object.", GL_OUT_OF_MEMORY);
return angle::Result::Continue();
} }
angle::Result FenceNVSyncGL::test(const gl::Context *context, GLboolean *outFinished)
{
ASSERT(mFunctions->isSync(mSyncObject));
GLint result = 0;
mFunctions->getSynciv(mSyncObject, GL_SYNC_STATUS, 1, nullptr, &result);
*outFinished = (result == GL_SIGNALED);
return angle::Result::Continue();
}
angle::Result FenceNVSyncGL::finish(const gl::Context *context)
{
ASSERT(mFunctions->isSync(mSyncObject));
GLenum result =
mFunctions->clientWaitSync(mSyncObject, GL_SYNC_FLUSH_COMMANDS_BIT, GL_TIMEOUT_IGNORED);
ANGLE_CHECK(GetImplAs<ContextGL>(context),
result == GL_ALREADY_SIGNALED || result == GL_CONDITION_SATISFIED,
"glClientWaitSync did not return GL_ALREADY_SIGNALED or GL_CONDITION_SATISFIED.",
GL_OUT_OF_MEMORY);
return angle::Result::Continue();
}
// static
bool FenceNVSyncGL::Supported(const FunctionsGL *functions)
{
return functions->isAtLeastGL(gl::Version(3, 2)) ||
functions->isAtLeastGLES(gl::Version(3, 0)) || functions->hasGLExtension("GL_ARB_sync");
}
} // namespace gl
...@@ -15,6 +15,7 @@ namespace rx ...@@ -15,6 +15,7 @@ namespace rx
{ {
class FunctionsGL; class FunctionsGL;
// FenceNV implemented with the native GL_NV_fence extension
class FenceNVGL : public FenceNVImpl class FenceNVGL : public FenceNVImpl
{ {
public: public:
...@@ -25,12 +26,32 @@ class FenceNVGL : public FenceNVImpl ...@@ -25,12 +26,32 @@ class FenceNVGL : public FenceNVImpl
angle::Result test(const gl::Context *context, GLboolean *outFinished) override; angle::Result test(const gl::Context *context, GLboolean *outFinished) override;
angle::Result finish(const gl::Context *context) override; angle::Result finish(const gl::Context *context) override;
static bool Supported(const FunctionsGL *functions);
private: private:
GLuint mFence; GLuint mFence;
const FunctionsGL *mFunctions; const FunctionsGL *mFunctions;
}; };
// FenceNV implemented with the GLsync API
class FenceNVSyncGL : public FenceNVImpl
{
public:
explicit FenceNVSyncGL(const FunctionsGL *functions);
~FenceNVSyncGL() override;
angle::Result set(const gl::Context *context, GLenum condition) override;
angle::Result test(const gl::Context *context, GLboolean *outFinished) override;
angle::Result finish(const gl::Context *context) override;
static bool Supported(const FunctionsGL *functions);
private:
GLsync mSyncObject;
const FunctionsGL *mFunctions;
};
} }
#endif // LIBANGLE_RENDERER_GL_FENCENVGL_H_ #endif // LIBANGLE_RENDERER_GL_FENCENVGL_H_
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include "libANGLE/formatutils.h" #include "libANGLE/formatutils.h"
#include "libANGLE/queryconversions.h" #include "libANGLE/queryconversions.h"
#include "libANGLE/renderer/gl/ContextGL.h" #include "libANGLE/renderer/gl/ContextGL.h"
#include "libANGLE/renderer/gl/FenceNVGL.h"
#include "libANGLE/renderer/gl/FunctionsGL.h" #include "libANGLE/renderer/gl/FunctionsGL.h"
#include "libANGLE/renderer/gl/QueryGL.h" #include "libANGLE/renderer/gl/QueryGL.h"
#include "libANGLE/renderer/gl/WorkaroundsGL.h" #include "libANGLE/renderer/gl/WorkaroundsGL.h"
...@@ -943,8 +944,7 @@ void GenerateCaps(const FunctionsGL *functions, ...@@ -943,8 +944,7 @@ void GenerateCaps(const FunctionsGL *functions,
extensions->textureFilterAnisotropic extensions->textureFilterAnisotropic
? QuerySingleGLFloat(functions, GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT) ? QuerySingleGLFloat(functions, GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT)
: 0.0f; : 0.0f;
extensions->fence = extensions->fence = FenceNVGL::Supported(functions) || FenceNVSyncGL::Supported(functions);
functions->hasGLExtension("GL_NV_fence") || functions->hasGLESExtension("GL_NV_fence");
extensions->blendMinMax = functions->isAtLeastGL(gl::Version(1, 5)) || extensions->blendMinMax = functions->isAtLeastGL(gl::Version(1, 5)) ||
functions->hasGLExtension("GL_EXT_blend_minmax") || functions->hasGLExtension("GL_EXT_blend_minmax") ||
functions->isAtLeastGLES(gl::Version(3, 0)) || functions->isAtLeastGLES(gl::Version(3, 0)) ||
......
...@@ -107,18 +107,19 @@ TEST_P(FenceNVTest, BasicOperations) ...@@ -107,18 +107,19 @@ TEST_P(FenceNVTest, BasicOperations)
glClearColor(1.0f, 0.0f, 1.0f, 1.0f); glClearColor(1.0f, 0.0f, 1.0f, 1.0f);
GLuint fences[20] = { 0 }; constexpr size_t kFenceCount = 20;
GLuint fences[kFenceCount] = {0};
glGenFencesNV(static_cast<GLsizei>(ArraySize(fences)), fences); glGenFencesNV(static_cast<GLsizei>(ArraySize(fences)), fences);
EXPECT_GL_NO_ERROR(); EXPECT_GL_NO_ERROR();
for (GLuint fence : fences) for (GLuint fence : fences)
{ {
glSetFenceNV(fence, GL_ALL_COMPLETED_NV);
glClear(GL_COLOR_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT);
glSetFenceNV(fence, GL_ALL_COMPLETED_NV);
} }
glFinish(); // Finish the last fence, all fences before should be marked complete
glFinishFenceNV(fences[kFenceCount - 1]);
for (GLuint fence : fences) for (GLuint fence : fences)
{ {
......
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