mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-12 22:28:32 +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
|
// Shared GetQueryObject* implementation. Returns false when an error
|
||||||
// was recorded and no value should be written back.
|
// was recorded and no value should be written back. `outValueProduced`, when given,
|
||||||
Bool GetQueryObjectValue(GLuint id, GLenum pname, const char* function, Uint64& outValue) {
|
// 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);
|
const std::lock_guard<std::mutex> lock(g_queryObjectsMutex);
|
||||||
auto* queryObject = FindQueryObjectLocked(id);
|
auto* queryObject = FindQueryObjectLocked(id);
|
||||||
if (!queryObject) {
|
if (!queryObject) {
|
||||||
@@ -137,6 +142,41 @@ namespace MobileGL::MG_Impl::GLImpl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch (pname) {
|
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: {
|
case GL_QUERY_RESULT_AVAILABLE: {
|
||||||
if (queryObject->resultCached || !queryObject->backendHandle) {
|
if (queryObject->resultCached || !queryObject->backendHandle) {
|
||||||
outValue = 1;
|
outValue = 1;
|
||||||
@@ -195,7 +235,10 @@ namespace MobileGL::MG_Impl::GLImpl {
|
|||||||
if (!ResolveQueryResultDestination(buffer, offset, sizeof(T), function, bufferObject)) return;
|
if (!ResolveQueryResultDestination(buffer, offset, sizeof(T), function, bufferObject)) return;
|
||||||
|
|
||||||
Uint64 value = 0;
|
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);
|
const T narrowed = static_cast<T>(value);
|
||||||
bufferObject->UploadSubData({const_cast<T*>(&narrowed), sizeof(T)}, static_cast<SizeT>(offset));
|
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) {
|
void GetQueryObjectiv(GLuint id, GLenum pname, GLint* params) {
|
||||||
Uint64 value = 0;
|
Uint64 value = 0;
|
||||||
if (!GetQueryObjectValue(id, pname, __FUNCTION__, value) || !params) {
|
Bool valueProduced = false;
|
||||||
|
if (!GetQueryObjectValue(id, pname, __FUNCTION__, value, &valueProduced) || !valueProduced || !params) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
constexpr Uint64 kMaxInt = static_cast<Uint64>(INT_MAX);
|
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) {
|
void GetQueryObjectuiv(GLuint id, GLenum pname, GLuint* params) {
|
||||||
Uint64 value = 0;
|
Uint64 value = 0;
|
||||||
if (!GetQueryObjectValue(id, pname, __FUNCTION__, value) || !params) {
|
Bool valueProduced = false;
|
||||||
|
if (!GetQueryObjectValue(id, pname, __FUNCTION__, value, &valueProduced) || !valueProduced || !params) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
*params = static_cast<GLuint>(value & 0xFFFFFFFFull);
|
*params = static_cast<GLuint>(value & 0xFFFFFFFFull);
|
||||||
@@ -550,7 +595,8 @@ namespace MobileGL::MG_Impl::GLImpl {
|
|||||||
|
|
||||||
void GetQueryObjecti64v(GLuint id, GLenum pname, GLint64* params) {
|
void GetQueryObjecti64v(GLuint id, GLenum pname, GLint64* params) {
|
||||||
Uint64 value = 0;
|
Uint64 value = 0;
|
||||||
if (!GetQueryObjectValue(id, pname, __FUNCTION__, value) || !params) {
|
Bool valueProduced = false;
|
||||||
|
if (!GetQueryObjectValue(id, pname, __FUNCTION__, value, &valueProduced) || !valueProduced || !params) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
*params = static_cast<GLint64>(value);
|
*params = static_cast<GLint64>(value);
|
||||||
@@ -558,7 +604,8 @@ namespace MobileGL::MG_Impl::GLImpl {
|
|||||||
|
|
||||||
void GetQueryObjectui64v(GLuint id, GLenum pname, GLuint64* params) {
|
void GetQueryObjectui64v(GLuint id, GLenum pname, GLuint64* params) {
|
||||||
Uint64 value = 0;
|
Uint64 value = 0;
|
||||||
if (!GetQueryObjectValue(id, pname, __FUNCTION__, value) || !params) {
|
Bool valueProduced = false;
|
||||||
|
if (!GetQueryObjectValue(id, pname, __FUNCTION__, value, &valueProduced) || !valueProduced || !params) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
*params = static_cast<GLuint64>(value);
|
*params = static_cast<GLuint64>(value);
|
||||||
|
|||||||
Reference in New Issue
Block a user