diff --git a/MobileGL/MG_Impl/GLImpl/Exporting/Definitions.cpp b/MobileGL/MG_Impl/GLImpl/Exporting/Definitions.cpp index e3ca2e2e..df6f5c9f 100644 --- a/MobileGL/MG_Impl/GLImpl/Exporting/Definitions.cpp +++ b/MobileGL/MG_Impl/GLImpl/Exporting/Definitions.cpp @@ -1097,7 +1097,7 @@ DECLARE_GL_FUNCTION_STUB_HEAD(void, GetVertexArrayIndexediv, GLuint vaobj, GLuin DECLARE_GL_FUNCTION_STUB_HEAD(void, GetVertexArrayIndexed64iv, GLuint vaobj, GLuint index, GLenum pname, GLint64* param) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetVertexArrayIndexed64iv, vaobj, index, pname, param) DECLARE_GL_FUNCTION_HEAD(void, CreateSamplers, GLsizei n, GLuint* samplers) DECLARE_GL_FUNCTION_END_NO_RETURN(void, CreateSamplers, n, samplers) DECLARE_GL_FUNCTION_STUB_HEAD(void, CreateProgramPipelines, GLsizei n, GLuint* pipelines) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, CreateProgramPipelines, n, pipelines) -DECLARE_GL_FUNCTION_STUB_HEAD(void, CreateQueries, GLenum target, GLsizei n, GLuint* ids) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, CreateQueries, target, n, ids) +DECLARE_GL_FUNCTION_HEAD(void, CreateQueries, GLenum target, GLsizei n, GLuint* ids) DECLARE_GL_FUNCTION_END_NO_RETURN(void, CreateQueries, target, n, ids) DECLARE_GL_FUNCTION_STUB_HEAD(void, GetQueryBufferObjecti64v, GLuint id, GLuint buffer, GLenum pname, GLintptr offset) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetQueryBufferObjecti64v, id, buffer, pname, offset) DECLARE_GL_FUNCTION_STUB_HEAD(void, GetQueryBufferObjectiv, GLuint id, GLuint buffer, GLenum pname, GLintptr offset) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetQueryBufferObjectiv, id, buffer, pname, offset) DECLARE_GL_FUNCTION_STUB_HEAD(void, GetQueryBufferObjectui64v, GLuint id, GLuint buffer, GLenum pname, GLintptr offset) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetQueryBufferObjectui64v, id, buffer, pname, offset) diff --git a/MobileGL/MG_Impl/GLImpl/Query/GL_Query.cpp b/MobileGL/MG_Impl/GLImpl/Query/GL_Query.cpp index 1676722f..1889823c 100644 --- a/MobileGL/MG_Impl/GLImpl/Query/GL_Query.cpp +++ b/MobileGL/MG_Impl/GLImpl/Query/GL_Query.cpp @@ -23,6 +23,9 @@ namespace MobileGL::MG_Impl::GLImpl { struct QueryObject { GLuint id = 0; GLenum target = 0; // 0 = gen'd but never used with BeginQuery/QueryCounter + // glCreateQueries makes the object outright; glGenQueries only reserves the name, + // and the object appears when the name is first used (GL 4.6 core 4.2.1). + Bool created = false; MG_Backend::BackendQueryHandle backendHandle = nullptr; Bool active = false; Bool ended = false; @@ -177,6 +180,41 @@ namespace MobileGL::MG_Impl::GLImpl { } } + // glCreateQueries differs from glGenQueries in creating the objects outright, with their + // target already fixed and the rest of their state at the defaults (GL 4.6 core 4.2.1). + void CreateQueries(GLenum target, GLsizei n, GLuint* ids) { + switch (target) { + case GL_SAMPLES_PASSED: + case GL_ANY_SAMPLES_PASSED: + case GL_ANY_SAMPLES_PASSED_CONSERVATIVE: + case GL_TIME_ELAPSED: + case GL_TIMESTAMP: + case GL_PRIMITIVES_GENERATED: + case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN: + break; + default: + RecordQueryError(ErrorCode::InvalidEnum, __FUNCTION__, "Query target is not accepted."); + return; + } + if (n < 0) { + RecordQueryError(ErrorCode::InvalidValue, __FUNCTION__, "n cannot be negative."); + return; + } + if (!ids) { + return; + } + const std::lock_guard lock(g_queryObjectsMutex); + for (GLsizei i = 0; i < n; ++i) { + const GLuint id = g_nextQueryId++; + auto* queryObject = new QueryObject; + queryObject->id = id; + queryObject->target = target; + queryObject->created = true; + g_liveQueryObjects[id] = queryObject; + ids[i] = id; + } + } + void DeleteQueries(GLsizei n, const GLuint* ids) { if (n < 0) { RecordQueryError(ErrorCode::InvalidValue, __FUNCTION__, "n cannot be negative."); @@ -228,9 +266,11 @@ namespace MobileGL::MG_Impl::GLImpl { return GL_FALSE; } const std::lock_guard lock(g_queryObjectsMutex); - // Gen'd ids count as query objects here: the registry creates live - // objects at GenQueries time. - return FindQueryObjectLocked(id) != nullptr ? GL_TRUE : GL_FALSE; + // A name from glGenQueries is not yet a query object: it becomes one when it is first + // used with BeginQuery/QueryCounter (which is what a non-zero target records), or + // immediately if it came from glCreateQueries. + const auto* queryObject = FindQueryObjectLocked(id); + return (queryObject != nullptr && (queryObject->created || queryObject->target != 0)) ? GL_TRUE : GL_FALSE; } void BeginQuery(GLenum target, GLuint id) { diff --git a/MobileGL/MG_Impl/GLImpl/Query/GL_Query.h b/MobileGL/MG_Impl/GLImpl/Query/GL_Query.h index 841e6443..35d79214 100644 --- a/MobileGL/MG_Impl/GLImpl/Query/GL_Query.h +++ b/MobileGL/MG_Impl/GLImpl/Query/GL_Query.h @@ -11,6 +11,7 @@ namespace MobileGL::MG_Impl::GLImpl { void GenQueries(GLsizei n, GLuint* ids); + void CreateQueries(GLenum target, GLsizei n, GLuint* ids); void DeleteQueries(GLsizei n, const GLuint* ids); GLboolean IsQuery(GLuint id); void BeginQuery(GLenum target, GLuint id);