Implement GL_CHROMIUM_sync_query for GL.
BUG=angleproject:1366
Change-Id: I9e44679754eb704b390191c28206dedc3dc7cc4f
Reviewed-on: https://chromium-review.googlesource.com/367082
Commit-Queue: Geoff Lang <geofflang@chromium.org>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
diff --git a/src/libANGLE/renderer/gl/QueryGL.cpp b/src/libANGLE/renderer/gl/QueryGL.cpp
index 6d9df5d..c9f9aee 100644
--- a/src/libANGLE/renderer/gl/QueryGL.cpp
+++ b/src/libANGLE/renderer/gl/QueryGL.cpp
@@ -11,6 +11,7 @@
#include "common/debug.h"
#include "libANGLE/renderer/gl/FunctionsGL.h"
#include "libANGLE/renderer/gl/StateManagerGL.h"
+#include "libANGLE/renderer/gl/renderergl_utils.h"
namespace
{
@@ -43,8 +44,18 @@
namespace rx
{
-QueryGL::QueryGL(GLenum type, const FunctionsGL *functions, StateManagerGL *stateManager)
- : QueryImpl(type),
+QueryGL::QueryGL(GLenum type) : QueryImpl(type)
+{
+}
+
+QueryGL::~QueryGL()
+{
+}
+
+StandardQueryGL::StandardQueryGL(GLenum type,
+ const FunctionsGL *functions,
+ StateManagerGL *stateManager)
+ : QueryGL(type),
mType(type),
mFunctions(functions),
mStateManager(stateManager),
@@ -54,7 +65,7 @@
{
}
-QueryGL::~QueryGL()
+StandardQueryGL::~StandardQueryGL()
{
mStateManager->deleteQuery(mActiveQuery);
mStateManager->onDeleteQueryObject(this);
@@ -65,19 +76,19 @@
}
}
-gl::Error QueryGL::begin()
+gl::Error StandardQueryGL::begin()
{
mResultSum = 0;
mStateManager->onBeginQuery(this);
return resume();
}
-gl::Error QueryGL::end()
+gl::Error StandardQueryGL::end()
{
return pause();
}
-gl::Error QueryGL::queryCounter()
+gl::Error StandardQueryGL::queryCounter()
{
ASSERT(mType == GL_TIMESTAMP);
@@ -92,7 +103,7 @@
}
template <typename T>
-gl::Error QueryGL::getResultBase(T *params)
+gl::Error StandardQueryGL::getResultBase(T *params)
{
ASSERT(mActiveQuery == 0);
@@ -108,27 +119,27 @@
return gl::Error(GL_NO_ERROR);
}
-gl::Error QueryGL::getResult(GLint *params)
+gl::Error StandardQueryGL::getResult(GLint *params)
{
return getResultBase(params);
}
-gl::Error QueryGL::getResult(GLuint *params)
+gl::Error StandardQueryGL::getResult(GLuint *params)
{
return getResultBase(params);
}
-gl::Error QueryGL::getResult(GLint64 *params)
+gl::Error StandardQueryGL::getResult(GLint64 *params)
{
return getResultBase(params);
}
-gl::Error QueryGL::getResult(GLuint64 *params)
+gl::Error StandardQueryGL::getResult(GLuint64 *params)
{
return getResultBase(params);
}
-gl::Error QueryGL::isResultAvailable(bool *available)
+gl::Error StandardQueryGL::isResultAvailable(bool *available)
{
ASSERT(mActiveQuery == 0);
@@ -142,7 +153,7 @@
return gl::Error(GL_NO_ERROR);
}
-gl::Error QueryGL::pause()
+gl::Error StandardQueryGL::pause()
{
if (mActiveQuery != 0)
{
@@ -162,7 +173,7 @@
return gl::Error(GL_NO_ERROR);
}
-gl::Error QueryGL::resume()
+gl::Error StandardQueryGL::resume()
{
if (mActiveQuery == 0)
{
@@ -180,7 +191,7 @@
return gl::Error(GL_NO_ERROR);
}
-gl::Error QueryGL::flush(bool force)
+gl::Error StandardQueryGL::flush(bool force)
{
while (!mPendingQueries.empty())
{
@@ -219,4 +230,194 @@
return gl::Error(GL_NO_ERROR);
}
+class SyncProviderGL
+{
+ public:
+ virtual ~SyncProviderGL() {}
+ virtual gl::Error flush(bool force, bool *finished) = 0;
+};
+
+class SyncProviderGLSync : public SyncProviderGL
+{
+ public:
+ SyncProviderGLSync(const FunctionsGL *functions) : mFunctions(functions), mSync(nullptr)
+ {
+ mSync = mFunctions->fenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
+ }
+
+ virtual ~SyncProviderGLSync() { mFunctions->deleteSync(mSync); }
+
+ gl::Error flush(bool force, bool *finished) override
+ {
+ if (force)
+ {
+ mFunctions->clientWaitSync(mSync, 0, 0);
+ *finished = true;
+ }
+ else
+ {
+ GLint value = 0;
+ mFunctions->getSynciv(mSync, GL_SYNC_STATUS, 1, nullptr, &value);
+ *finished = (value == GL_SIGNALED);
+ }
+
+ return gl::NoError();
+ }
+
+ private:
+ const FunctionsGL *mFunctions;
+ GLsync mSync;
+};
+
+class SyncProviderGLQuery : public SyncProviderGL
+{
+ public:
+ SyncProviderGLQuery(const FunctionsGL *functions,
+ StateManagerGL *stateManager,
+ GLenum queryType)
+ : mFunctions(functions), mQuery(0)
+ {
+ mFunctions->genQueries(1, &mQuery);
+ stateManager->pauseQuery(queryType);
+ mFunctions->beginQuery(queryType, mQuery);
+ mFunctions->endQuery(queryType);
+ stateManager->resumeQuery(queryType);
+ }
+
+ virtual ~SyncProviderGLQuery() { mFunctions->deleteQueries(1, &mQuery); }
+
+ gl::Error flush(bool force, bool *finished) override
+ {
+ if (force)
+ {
+ GLint result = 0;
+ mFunctions->getQueryObjectiv(mQuery, GL_QUERY_RESULT, &result);
+ *finished = true;
+ }
+ else
+ {
+ GLint available = 0;
+ mFunctions->getQueryObjectiv(mQuery, GL_QUERY_RESULT_AVAILABLE, &available);
+ *finished = (available == GL_TRUE);
+ }
+
+ return gl::NoError();
+ }
+
+ private:
+ const FunctionsGL *mFunctions;
+ GLuint mQuery;
+};
+
+SyncQueryGL::SyncQueryGL(GLenum type, const FunctionsGL *functions, StateManagerGL *stateManager)
+ : QueryGL(type),
+ mFunctions(functions),
+ mStateManager(stateManager),
+ mSyncProvider(nullptr),
+ mFinished(false)
+{
+ ASSERT(IsSupported(mFunctions));
+ ASSERT(type == GL_COMMANDS_COMPLETED_CHROMIUM);
+}
+
+SyncQueryGL::~SyncQueryGL()
+{
+}
+
+bool SyncQueryGL::IsSupported(const FunctionsGL *functions)
+{
+ return nativegl::SupportsFenceSync(functions) || nativegl::SupportsOcclusionQueries(functions);
+}
+
+gl::Error SyncQueryGL::begin()
+{
+ return gl::NoError();
+}
+
+gl::Error SyncQueryGL::end()
+{
+ if (nativegl::SupportsFenceSync(mFunctions))
+ {
+ mSyncProvider.reset(new SyncProviderGLSync(mFunctions));
+ }
+ else if (nativegl::SupportsOcclusionQueries(mFunctions))
+ {
+ mSyncProvider.reset(
+ new SyncProviderGLQuery(mFunctions, mStateManager, GL_ANY_SAMPLES_PASSED));
+ }
+ else
+ {
+ ASSERT(false);
+ return gl::Error(GL_INVALID_OPERATION, "No native support for sync queries.");
+ }
+ return gl::NoError();
+}
+
+gl::Error SyncQueryGL::queryCounter()
+{
+ UNREACHABLE();
+ return gl::NoError();
+}
+
+gl::Error SyncQueryGL::getResult(GLint *params)
+{
+ return getResultBase(params);
+}
+
+gl::Error SyncQueryGL::getResult(GLuint *params)
+{
+ return getResultBase(params);
+}
+
+gl::Error SyncQueryGL::getResult(GLint64 *params)
+{
+ return getResultBase(params);
+}
+
+gl::Error SyncQueryGL::getResult(GLuint64 *params)
+{
+ return getResultBase(params);
+}
+
+gl::Error SyncQueryGL::isResultAvailable(bool *available)
+{
+ ANGLE_TRY(flush(false));
+ *available = mFinished;
+ return gl::NoError();
+}
+
+gl::Error SyncQueryGL::pause()
+{
+ return gl::NoError();
+}
+
+gl::Error SyncQueryGL::resume()
+{
+ return gl::NoError();
+}
+
+gl::Error SyncQueryGL::flush(bool force)
+{
+ if (mSyncProvider == nullptr)
+ {
+ ASSERT(mFinished);
+ return gl::NoError();
+ }
+
+ ANGLE_TRY(mSyncProvider->flush(force, &mFinished));
+ if (mFinished)
+ {
+ mSyncProvider.reset();
+ }
+
+ return gl::NoError();
+}
+
+template <typename T>
+gl::Error SyncQueryGL::getResultBase(T *params)
+{
+ ANGLE_TRY(flush(true));
+ *params = static_cast<T>(mFinished ? GL_TRUE : GL_FALSE);
+ return gl::NoError();
+}
}