mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-09 04:38:30 +09:00
[Feat] (MG_Impl): implement the query getters that write into a buffer object
glGetQueryBufferObjectiv and its three siblings were stubs. They are the ordinary query getters with the destination changed from client memory to a buffer object, so everything about the query itself - the name, whether it is still active, the parameter - is already answered by the shared GetQueryObjectValue, including the errors it raises. What was left is the destination: a negative offset is INVALID_VALUE, a name that is not a buffer object is INVALID_OPERATION, and so is a write that would run past the end of the buffer. The four differ only in the width they store, so they share one template. direct_state_access.queries_errors passes on both backends, putting the group at 4 of 5. queries_functional now reaches further into the test and ends in an unrelated InternalError rather than a plain failure.
This commit is contained in:
@@ -1098,10 +1098,10 @@ DECLARE_GL_FUNCTION_HEAD(void, GetVertexArrayIndexed64iv, GLuint vaobj, GLuint i
|
||||
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_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)
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, GetQueryBufferObjectuiv, GLuint id, GLuint buffer, GLenum pname, GLintptr offset) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetQueryBufferObjectuiv, id, buffer, pname, offset)
|
||||
DECLARE_GL_FUNCTION_HEAD(void, GetQueryBufferObjecti64v, GLuint id, GLuint buffer, GLenum pname, GLintptr offset) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetQueryBufferObjecti64v, id, buffer, pname, offset)
|
||||
DECLARE_GL_FUNCTION_HEAD(void, GetQueryBufferObjectiv, GLuint id, GLuint buffer, GLenum pname, GLintptr offset) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetQueryBufferObjectiv, id, buffer, pname, offset)
|
||||
DECLARE_GL_FUNCTION_HEAD(void, GetQueryBufferObjectui64v, GLuint id, GLuint buffer, GLenum pname, GLintptr offset) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetQueryBufferObjectui64v, id, buffer, pname, offset)
|
||||
DECLARE_GL_FUNCTION_HEAD(void, GetQueryBufferObjectuiv, GLuint id, GLuint buffer, GLenum pname, GLintptr offset) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetQueryBufferObjectuiv, id, buffer, pname, offset)
|
||||
DECLARE_GL_FUNCTION_HEAD(void, GetTextureSubImage, GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, GLsizei bufSize, void* pixels) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetTextureSubImage, texture, level, xoffset, yoffset, zoffset, width, height, depth, format, type, bufSize, pixels)
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, GetCompressedTextureSubImage, GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLsizei bufSize, void* pixels) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetCompressedTextureSubImage, texture, level, xoffset, yoffset, zoffset, width, height, depth, bufSize, pixels)
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, GetnCompressedTexImage, GLenum target, GLint lod, GLsizei bufSize, void* pixels) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetnCompressedTexImage, target, lod, bufSize, pixels)
|
||||
|
||||
@@ -62,6 +62,34 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", function, message));
|
||||
}
|
||||
|
||||
// The by-buffer query getters write the result into a buffer object instead of client
|
||||
// memory. Everything about the query itself - the name, whether it is still active, the
|
||||
// parameter - is checked by GetQueryObjectValue; what is left is the destination, so this
|
||||
// resolves the buffer and confirms the write lands inside it (GL 4.6 core 4.2.1).
|
||||
Bool ResolveQueryResultDestination(GLuint buffer, GLintptr offset, SizeT writeSize, const char* function,
|
||||
SharedPtr<MG_State::GLState::BufferObject>& outBuffer) {
|
||||
if (offset < 0) {
|
||||
RecordQueryError(ErrorCode::InvalidValue, function, "Offset cannot be negative.");
|
||||
return false;
|
||||
}
|
||||
if (!MG_State::pGLContext->ValidateBufferObject(buffer)) {
|
||||
RecordQueryError(ErrorCode::InvalidOperation, function, "Buffer object does not exist.");
|
||||
return false;
|
||||
}
|
||||
auto bufferObject = MG_State::pGLContext->GetBufferObject(buffer);
|
||||
if (!bufferObject) {
|
||||
RecordQueryError(ErrorCode::InvalidOperation, function, "Buffer object does not exist.");
|
||||
return false;
|
||||
}
|
||||
if (static_cast<SizeT>(offset) + writeSize > bufferObject->GetSize()) {
|
||||
RecordQueryError(ErrorCode::InvalidOperation, function,
|
||||
"The query result does not fit in the buffer object at this offset.");
|
||||
return false;
|
||||
}
|
||||
outBuffer = bufferObject;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Callers must hold g_queryObjectsMutex.
|
||||
QueryObject* FindQueryObjectLocked(GLuint id) {
|
||||
const auto it = g_liveQueryObjects.find(id);
|
||||
@@ -160,6 +188,18 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void GetQueryBufferObject(GLuint id, GLuint buffer, GLenum pname, GLintptr offset, const char* function) {
|
||||
SharedPtr<MG_State::GLState::BufferObject> bufferObject;
|
||||
if (!ResolveQueryResultDestination(buffer, offset, sizeof(T), function, bufferObject)) return;
|
||||
|
||||
Uint64 value = 0;
|
||||
if (!GetQueryObjectValue(id, pname, function, value)) return;
|
||||
|
||||
const T narrowed = static_cast<T>(value);
|
||||
bufferObject->UploadSubData({const_cast<T*>(&narrowed), sizeof(T)}, static_cast<SizeT>(offset));
|
||||
}
|
||||
} // namespace
|
||||
|
||||
void GenQueries(GLsizei n, GLuint* ids) {
|
||||
@@ -475,6 +515,22 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
}
|
||||
}
|
||||
|
||||
void GetQueryBufferObjectiv(GLuint id, GLuint buffer, GLenum pname, GLintptr offset) {
|
||||
GetQueryBufferObject<GLint>(id, buffer, pname, offset, __FUNCTION__);
|
||||
}
|
||||
|
||||
void GetQueryBufferObjectuiv(GLuint id, GLuint buffer, GLenum pname, GLintptr offset) {
|
||||
GetQueryBufferObject<GLuint>(id, buffer, pname, offset, __FUNCTION__);
|
||||
}
|
||||
|
||||
void GetQueryBufferObjecti64v(GLuint id, GLuint buffer, GLenum pname, GLintptr offset) {
|
||||
GetQueryBufferObject<GLint64>(id, buffer, pname, offset, __FUNCTION__);
|
||||
}
|
||||
|
||||
void GetQueryBufferObjectui64v(GLuint id, GLuint buffer, GLenum pname, GLintptr offset) {
|
||||
GetQueryBufferObject<GLuint64>(id, buffer, pname, offset, __FUNCTION__);
|
||||
}
|
||||
|
||||
void GetQueryObjectiv(GLuint id, GLenum pname, GLint* params) {
|
||||
Uint64 value = 0;
|
||||
if (!GetQueryObjectValue(id, pname, __FUNCTION__, value) || !params) {
|
||||
|
||||
@@ -24,5 +24,9 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
void GetQueryObjectuiv(GLuint id, GLenum pname, GLuint* params);
|
||||
void GetQueryObjecti64v(GLuint id, GLenum pname, GLint64* params);
|
||||
void GetQueryObjectui64v(GLuint id, GLenum pname, GLuint64* params);
|
||||
void GetQueryBufferObjectiv(GLuint id, GLuint buffer, GLenum pname, GLintptr offset);
|
||||
void GetQueryBufferObjectuiv(GLuint id, GLuint buffer, GLenum pname, GLintptr offset);
|
||||
void GetQueryBufferObjecti64v(GLuint id, GLuint buffer, GLenum pname, GLintptr offset);
|
||||
void GetQueryBufferObjectui64v(GLuint id, GLuint buffer, GLenum pname, GLintptr offset);
|
||||
void QueryCounter(GLuint id, GLenum target);
|
||||
} // namespace MobileGL::MG_Impl::GLImpl
|
||||
|
||||
Reference in New Issue
Block a user