mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-12 06:08: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_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, 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_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_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_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_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_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_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_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, 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_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, 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)
|
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));
|
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.
|
// Callers must hold g_queryObjectsMutex.
|
||||||
QueryObject* FindQueryObjectLocked(GLuint id) {
|
QueryObject* FindQueryObjectLocked(GLuint id) {
|
||||||
const auto it = g_liveQueryObjects.find(id);
|
const auto it = g_liveQueryObjects.find(id);
|
||||||
@@ -160,6 +188,18 @@ namespace MobileGL::MG_Impl::GLImpl {
|
|||||||
return false;
|
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
|
} // namespace
|
||||||
|
|
||||||
void GenQueries(GLsizei n, GLuint* ids) {
|
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) {
|
void GetQueryObjectiv(GLuint id, GLenum pname, GLint* params) {
|
||||||
Uint64 value = 0;
|
Uint64 value = 0;
|
||||||
if (!GetQueryObjectValue(id, pname, __FUNCTION__, value) || !params) {
|
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 GetQueryObjectuiv(GLuint id, GLenum pname, GLuint* params);
|
||||||
void GetQueryObjecti64v(GLuint id, GLenum pname, GLint64* params);
|
void GetQueryObjecti64v(GLuint id, GLenum pname, GLint64* params);
|
||||||
void GetQueryObjectui64v(GLuint id, GLenum pname, GLuint64* 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);
|
void QueryCounter(GLuint id, GLenum target);
|
||||||
} // namespace MobileGL::MG_Impl::GLImpl
|
} // namespace MobileGL::MG_Impl::GLImpl
|
||||||
|
|||||||
Reference in New Issue
Block a user