mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-11 05:38:31 +09:00
[Feat] (MG_Impl): answer the two query parameters the getters were missing
GetQueryObjectValue implemented GL_QUERY_RESULT_AVAILABLE and GL_QUERY_RESULT and rejected everything else, so direct_state_access.queries_functional threw on its very first probe - GL_QUERY_TARGET - and never reached any of the checks it was written for. GL_QUERY_TARGET is state the object has carried all along; it just had no case. GL_QUERY_RESULT_NO_WAIT is GL_QUERY_RESULT with the backend asked not to block, and it brings a wrinkle the shared getter could not express: when the result has not landed, GL_ARB_query_buffer_object leaves the destination untouched rather than writing a placeholder. GetQueryObjectValue now reports "succeeded but produced no value" through an optional out-parameter, and all five callers - the four buffer forms and the four client-memory forms - skip the write on it. The switch is deliberately widened by exactly these two names: its default INVALID_ENUM is what the GL33 and GL40 query error cases rely on. queries_functional passes on Espryt. On Magma it stops throwing and fails on a value instead, which is a separate problem in the query results themselves.
This commit is contained in:
@@ -123,8 +123,13 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
}
|
||||
|
||||
// Shared GetQueryObject* implementation. Returns false when an error
|
||||
// was recorded and no value should be written back.
|
||||
Bool GetQueryObjectValue(GLuint id, GLenum pname, const char* function, Uint64& outValue) {
|
||||
// was recorded and no value should be written back. `outValueProduced`, when given,
|
||||
// additionally distinguishes "succeeded with a value" from "succeeded but the result is not
|
||||
// ready" - the GL_QUERY_RESULT_NO_WAIT case, where GL_ARB_query_buffer_object says the
|
||||
// destination is left alone rather than written with a placeholder.
|
||||
Bool GetQueryObjectValue(GLuint id, GLenum pname, const char* function, Uint64& outValue,
|
||||
Bool* outValueProduced = nullptr) {
|
||||
if (outValueProduced) *outValueProduced = true;
|
||||
const std::lock_guard<std::mutex> lock(g_queryObjectsMutex);
|
||||
auto* queryObject = FindQueryObjectLocked(id);
|
||||
if (!queryObject) {
|
||||
@@ -137,6 +142,41 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
}
|
||||
|
||||
switch (pname) {
|
||||
case GL_QUERY_TARGET:
|
||||
// The target a query was begun with (or created with, for glCreateQueries) - state
|
||||
// the object has carried all along, GL 4.6 core table 23.35.
|
||||
outValue = queryObject->target;
|
||||
return true;
|
||||
case GL_QUERY_RESULT_NO_WAIT: {
|
||||
if (queryObject->resultCached) {
|
||||
outValue = queryObject->cachedResult;
|
||||
return true;
|
||||
}
|
||||
Uint64 result = 0;
|
||||
const auto getQueryResult64 = MG_Backend::gBackendFunctionsTable.GL.GetQueryResult64;
|
||||
if (queryObject->backendHandle && getQueryResult64 &&
|
||||
!getQueryResult64(queryObject->backendHandle, /*wait=*/false, &result)) {
|
||||
// Not ready. The whole point of the no-wait form is that the caller's
|
||||
// destination keeps whatever it already held.
|
||||
if (outValueProduced) *outValueProduced = false;
|
||||
outValue = 0;
|
||||
return true;
|
||||
}
|
||||
if (queryObject->target == GL_ANY_SAMPLES_PASSED ||
|
||||
queryObject->target == GL_ANY_SAMPLES_PASSED_CONSERVATIVE) {
|
||||
result = result != 0 ? 1 : 0;
|
||||
}
|
||||
if (queryObject->backendHandle) {
|
||||
if (const auto deleteBackendQuery = MG_Backend::gBackendFunctionsTable.GL.DeleteBackendQuery) {
|
||||
deleteBackendQuery(queryObject->backendHandle);
|
||||
}
|
||||
queryObject->backendHandle = nullptr;
|
||||
}
|
||||
queryObject->cachedResult = result;
|
||||
queryObject->resultCached = true;
|
||||
outValue = result;
|
||||
return true;
|
||||
}
|
||||
case GL_QUERY_RESULT_AVAILABLE: {
|
||||
if (queryObject->resultCached || !queryObject->backendHandle) {
|
||||
outValue = 1;
|
||||
@@ -195,7 +235,10 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
if (!ResolveQueryResultDestination(buffer, offset, sizeof(T), function, bufferObject)) return;
|
||||
|
||||
Uint64 value = 0;
|
||||
if (!GetQueryObjectValue(id, pname, function, value)) return;
|
||||
Bool valueProduced = false;
|
||||
if (!GetQueryObjectValue(id, pname, function, value, &valueProduced)) return;
|
||||
// GL_QUERY_RESULT_NO_WAIT on a result that has not landed writes nothing at all.
|
||||
if (!valueProduced) return;
|
||||
|
||||
const T narrowed = static_cast<T>(value);
|
||||
bufferObject->UploadSubData({const_cast<T*>(&narrowed), sizeof(T)}, static_cast<SizeT>(offset));
|
||||
@@ -533,7 +576,8 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
|
||||
void GetQueryObjectiv(GLuint id, GLenum pname, GLint* params) {
|
||||
Uint64 value = 0;
|
||||
if (!GetQueryObjectValue(id, pname, __FUNCTION__, value) || !params) {
|
||||
Bool valueProduced = false;
|
||||
if (!GetQueryObjectValue(id, pname, __FUNCTION__, value, &valueProduced) || !valueProduced || !params) {
|
||||
return;
|
||||
}
|
||||
constexpr Uint64 kMaxInt = static_cast<Uint64>(INT_MAX);
|
||||
@@ -542,7 +586,8 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
|
||||
void GetQueryObjectuiv(GLuint id, GLenum pname, GLuint* params) {
|
||||
Uint64 value = 0;
|
||||
if (!GetQueryObjectValue(id, pname, __FUNCTION__, value) || !params) {
|
||||
Bool valueProduced = false;
|
||||
if (!GetQueryObjectValue(id, pname, __FUNCTION__, value, &valueProduced) || !valueProduced || !params) {
|
||||
return;
|
||||
}
|
||||
*params = static_cast<GLuint>(value & 0xFFFFFFFFull);
|
||||
@@ -550,7 +595,8 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
|
||||
void GetQueryObjecti64v(GLuint id, GLenum pname, GLint64* params) {
|
||||
Uint64 value = 0;
|
||||
if (!GetQueryObjectValue(id, pname, __FUNCTION__, value) || !params) {
|
||||
Bool valueProduced = false;
|
||||
if (!GetQueryObjectValue(id, pname, __FUNCTION__, value, &valueProduced) || !valueProduced || !params) {
|
||||
return;
|
||||
}
|
||||
*params = static_cast<GLint64>(value);
|
||||
@@ -558,7 +604,8 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
|
||||
void GetQueryObjectui64v(GLuint id, GLenum pname, GLuint64* params) {
|
||||
Uint64 value = 0;
|
||||
if (!GetQueryObjectValue(id, pname, __FUNCTION__, value) || !params) {
|
||||
Bool valueProduced = false;
|
||||
if (!GetQueryObjectValue(id, pname, __FUNCTION__, value, &valueProduced) || !valueProduced || !params) {
|
||||
return;
|
||||
}
|
||||
*params = static_cast<GLuint64>(value);
|
||||
|
||||
Reference in New Issue
Block a user