From 38497174c81eaf94364d81bf2e6fd88a0723e1b1 Mon Sep 17 00:00:00 2001 From: BZLZHH Date: Tue, 4 Aug 2026 11:06:15 -0400 Subject: [PATCH] [Feat] (MG_Impl): implement the double-precision uniform state glUniform*d, glUniformMatrix*dv, their glProgramUniform twins and glGetUniformdv were all stubs - 35 entry points - so a GL 4.0 program's double uniforms could be declared and located but never set or read. Worse, glGetUniformfv on one did reach the storage: the generic getter memcpy'd the uniform's declared size into the caller's buffer, so a 4-byte float pointer received 8 bytes. That overrun is what took the process down in KHR-GL40.gpu_shader_fp64.fp64.state_query. The upload path is already templated on the component type, so the vector forms are wiring. A matrix is not: the column stride the linker used for a double matrix is not the 16 bytes a float one gets. It is not guessed - the slot the uniform was given is exactly `columns` columns wide, so dividing states the stride the rest of the pipeline already agreed on, for both the upload and the readback. The four getters now convert instead of reinterpreting when the uniform holds doubles, following GL 4.6 core 7.6: round to nearest for the integer queries, and clamp into the queried type's range so a negative double read through glGetUniformuiv is 0 rather than its two's complement. The case still fails one step further on, where it queries the same uniforms through GL_ARB_program_interface_query: those calls are answered by the backend program, and an fp64 shader has none - ESSL has no doubles, so it never links. Answering them from the frontend reflection is a separate change. --- .../MG_Impl/GLImpl/Exporting/Definitions.cpp | 70 ++-- .../MG_Impl/GLImpl/Program/GL_Program.cpp | 380 +++++++++++++++++- MobileGL/MG_Impl/GLImpl/Program/GL_Program.h | 35 ++ 3 files changed, 449 insertions(+), 36 deletions(-) diff --git a/MobileGL/MG_Impl/GLImpl/Exporting/Definitions.cpp b/MobileGL/MG_Impl/GLImpl/Exporting/Definitions.cpp index 2897364b..1732fbbe 100644 --- a/MobileGL/MG_Impl/GLImpl/Exporting/Definitions.cpp +++ b/MobileGL/MG_Impl/GLImpl/Exporting/Definitions.cpp @@ -909,24 +909,24 @@ DECLARE_GL_FUNCTION_STUB_HEAD(void, ColorP4ui, GLenum type, GLuint color) DECLAR DECLARE_GL_FUNCTION_STUB_HEAD(void, ColorP4uiv, GLenum type, const GLuint* color) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, ColorP4uiv, type, color) DECLARE_GL_FUNCTION_STUB_HEAD(void, SecondaryColorP3ui, GLenum type, GLuint color) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, SecondaryColorP3ui, type, color) DECLARE_GL_FUNCTION_STUB_HEAD(void, SecondaryColorP3uiv, GLenum type, const GLuint* color) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, SecondaryColorP3uiv, type, color) -DECLARE_GL_FUNCTION_STUB_HEAD(void, Uniform1d, GLint location, GLdouble x) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, Uniform1d, location, x) -DECLARE_GL_FUNCTION_STUB_HEAD(void, Uniform2d, GLint location, GLdouble x, GLdouble y) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, Uniform2d, location, x, y) -DECLARE_GL_FUNCTION_STUB_HEAD(void, Uniform3d, GLint location, GLdouble x, GLdouble y, GLdouble z) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, Uniform3d, location, x, y, z) -DECLARE_GL_FUNCTION_STUB_HEAD(void, Uniform4d, GLint location, GLdouble x, GLdouble y, GLdouble z, GLdouble w) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, Uniform4d, location, x, y, z, w) -DECLARE_GL_FUNCTION_STUB_HEAD(void, Uniform1dv, GLint location, GLsizei count, const GLdouble* value) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, Uniform1dv, location, count, value) -DECLARE_GL_FUNCTION_STUB_HEAD(void, Uniform2dv, GLint location, GLsizei count, const GLdouble* value) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, Uniform2dv, location, count, value) -DECLARE_GL_FUNCTION_STUB_HEAD(void, Uniform3dv, GLint location, GLsizei count, const GLdouble* value) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, Uniform3dv, location, count, value) -DECLARE_GL_FUNCTION_STUB_HEAD(void, Uniform4dv, GLint location, GLsizei count, const GLdouble* value) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, Uniform4dv, location, count, value) -DECLARE_GL_FUNCTION_STUB_HEAD(void, UniformMatrix2dv, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, UniformMatrix2dv, location, count, transpose, value) -DECLARE_GL_FUNCTION_STUB_HEAD(void, UniformMatrix3dv, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, UniformMatrix3dv, location, count, transpose, value) -DECLARE_GL_FUNCTION_STUB_HEAD(void, UniformMatrix4dv, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, UniformMatrix4dv, location, count, transpose, value) -DECLARE_GL_FUNCTION_STUB_HEAD(void, UniformMatrix2x3dv, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, UniformMatrix2x3dv, location, count, transpose, value) -DECLARE_GL_FUNCTION_STUB_HEAD(void, UniformMatrix2x4dv, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, UniformMatrix2x4dv, location, count, transpose, value) -DECLARE_GL_FUNCTION_STUB_HEAD(void, UniformMatrix3x2dv, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, UniformMatrix3x2dv, location, count, transpose, value) -DECLARE_GL_FUNCTION_STUB_HEAD(void, UniformMatrix3x4dv, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, UniformMatrix3x4dv, location, count, transpose, value) -DECLARE_GL_FUNCTION_STUB_HEAD(void, UniformMatrix4x2dv, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, UniformMatrix4x2dv, location, count, transpose, value) -DECLARE_GL_FUNCTION_STUB_HEAD(void, UniformMatrix4x3dv, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, UniformMatrix4x3dv, location, count, transpose, value) -DECLARE_GL_FUNCTION_STUB_HEAD(void, GetUniformdv, GLuint program, GLint location, GLdouble* params) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetUniformdv, program, location, params) +DECLARE_GL_FUNCTION_HEAD(void, Uniform1d, GLint location, GLdouble x) DECLARE_GL_FUNCTION_END_NO_RETURN(void, Uniform1d, location, x) +DECLARE_GL_FUNCTION_HEAD(void, Uniform2d, GLint location, GLdouble x, GLdouble y) DECLARE_GL_FUNCTION_END_NO_RETURN(void, Uniform2d, location, x, y) +DECLARE_GL_FUNCTION_HEAD(void, Uniform3d, GLint location, GLdouble x, GLdouble y, GLdouble z) DECLARE_GL_FUNCTION_END_NO_RETURN(void, Uniform3d, location, x, y, z) +DECLARE_GL_FUNCTION_HEAD(void, Uniform4d, GLint location, GLdouble x, GLdouble y, GLdouble z, GLdouble w) DECLARE_GL_FUNCTION_END_NO_RETURN(void, Uniform4d, location, x, y, z, w) +DECLARE_GL_FUNCTION_HEAD(void, Uniform1dv, GLint location, GLsizei count, const GLdouble* value) DECLARE_GL_FUNCTION_END_NO_RETURN(void, Uniform1dv, location, count, value) +DECLARE_GL_FUNCTION_HEAD(void, Uniform2dv, GLint location, GLsizei count, const GLdouble* value) DECLARE_GL_FUNCTION_END_NO_RETURN(void, Uniform2dv, location, count, value) +DECLARE_GL_FUNCTION_HEAD(void, Uniform3dv, GLint location, GLsizei count, const GLdouble* value) DECLARE_GL_FUNCTION_END_NO_RETURN(void, Uniform3dv, location, count, value) +DECLARE_GL_FUNCTION_HEAD(void, Uniform4dv, GLint location, GLsizei count, const GLdouble* value) DECLARE_GL_FUNCTION_END_NO_RETURN(void, Uniform4dv, location, count, value) +DECLARE_GL_FUNCTION_HEAD(void, UniformMatrix2dv, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value) DECLARE_GL_FUNCTION_END_NO_RETURN(void, UniformMatrix2dv, location, count, transpose, value) +DECLARE_GL_FUNCTION_HEAD(void, UniformMatrix3dv, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value) DECLARE_GL_FUNCTION_END_NO_RETURN(void, UniformMatrix3dv, location, count, transpose, value) +DECLARE_GL_FUNCTION_HEAD(void, UniformMatrix4dv, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value) DECLARE_GL_FUNCTION_END_NO_RETURN(void, UniformMatrix4dv, location, count, transpose, value) +DECLARE_GL_FUNCTION_HEAD(void, UniformMatrix2x3dv, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value) DECLARE_GL_FUNCTION_END_NO_RETURN(void, UniformMatrix2x3dv, location, count, transpose, value) +DECLARE_GL_FUNCTION_HEAD(void, UniformMatrix2x4dv, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value) DECLARE_GL_FUNCTION_END_NO_RETURN(void, UniformMatrix2x4dv, location, count, transpose, value) +DECLARE_GL_FUNCTION_HEAD(void, UniformMatrix3x2dv, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value) DECLARE_GL_FUNCTION_END_NO_RETURN(void, UniformMatrix3x2dv, location, count, transpose, value) +DECLARE_GL_FUNCTION_HEAD(void, UniformMatrix3x4dv, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value) DECLARE_GL_FUNCTION_END_NO_RETURN(void, UniformMatrix3x4dv, location, count, transpose, value) +DECLARE_GL_FUNCTION_HEAD(void, UniformMatrix4x2dv, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value) DECLARE_GL_FUNCTION_END_NO_RETURN(void, UniformMatrix4x2dv, location, count, transpose, value) +DECLARE_GL_FUNCTION_HEAD(void, UniformMatrix4x3dv, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value) DECLARE_GL_FUNCTION_END_NO_RETURN(void, UniformMatrix4x3dv, location, count, transpose, value) +DECLARE_GL_FUNCTION_HEAD(void, GetUniformdv, GLuint program, GLint location, GLdouble* params) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetUniformdv, program, location, params) DECLARE_GL_FUNCTION_STUB_HEAD(GLint, GetSubroutineUniformLocation, GLuint program, GLenum shadertype, const GLchar* name) DECLARE_GL_FUNCTION_STUB_END(GLint, GetSubroutineUniformLocation, program, shadertype, name) DECLARE_GL_FUNCTION_STUB_HEAD(GLuint, GetSubroutineIndex, GLuint program, GLenum shadertype, const GLchar* name) DECLARE_GL_FUNCTION_STUB_END(GLuint, GetSubroutineIndex, program, shadertype, name) DECLARE_GL_FUNCTION_STUB_HEAD(void, GetActiveSubroutineUniformiv, GLuint program, GLenum shadertype, GLuint index, GLenum pname, GLint* values) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetActiveSubroutineUniformiv, program, shadertype, index, pname, values) @@ -941,23 +941,23 @@ DECLARE_GL_FUNCTION_HEAD(void, DrawTransformFeedbackStream, GLenum mode, GLuint DECLARE_GL_FUNCTION_HEAD(void, BeginQueryIndexed, GLenum target, GLuint index, GLuint id) DECLARE_GL_FUNCTION_END_NO_RETURN(void, BeginQueryIndexed, target, index, id) DECLARE_GL_FUNCTION_HEAD(void, EndQueryIndexed, GLenum target, GLuint index) DECLARE_GL_FUNCTION_END_NO_RETURN(void, EndQueryIndexed, target, index) DECLARE_GL_FUNCTION_HEAD(void, GetQueryIndexediv, GLenum target, GLuint index, GLenum pname, GLint* params) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetQueryIndexediv, target, index, pname, params) -DECLARE_GL_FUNCTION_STUB_HEAD(void, ProgramUniform1d, GLuint program, GLint location, GLdouble v0) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, ProgramUniform1d, program, location, v0) -DECLARE_GL_FUNCTION_STUB_HEAD(void, ProgramUniform1dv, GLuint program, GLint location, GLsizei count, const GLdouble* value) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, ProgramUniform1dv, program, location, count, value) -DECLARE_GL_FUNCTION_STUB_HEAD(void, ProgramUniform2d, GLuint program, GLint location, GLdouble v0, GLdouble v1) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, ProgramUniform2d, program, location, v0, v1) -DECLARE_GL_FUNCTION_STUB_HEAD(void, ProgramUniform2dv, GLuint program, GLint location, GLsizei count, const GLdouble* value) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, ProgramUniform2dv, program, location, count, value) -DECLARE_GL_FUNCTION_STUB_HEAD(void, ProgramUniform3d, GLuint program, GLint location, GLdouble v0, GLdouble v1, GLdouble v2) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, ProgramUniform3d, program, location, v0, v1, v2) -DECLARE_GL_FUNCTION_STUB_HEAD(void, ProgramUniform3dv, GLuint program, GLint location, GLsizei count, const GLdouble* value) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, ProgramUniform3dv, program, location, count, value) -DECLARE_GL_FUNCTION_STUB_HEAD(void, ProgramUniform4d, GLuint program, GLint location, GLdouble v0, GLdouble v1, GLdouble v2, GLdouble v3) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, ProgramUniform4d, program, location, v0, v1, v2, v3) -DECLARE_GL_FUNCTION_STUB_HEAD(void, ProgramUniform4dv, GLuint program, GLint location, GLsizei count, const GLdouble* value) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, ProgramUniform4dv, program, location, count, value) -DECLARE_GL_FUNCTION_STUB_HEAD(void, ProgramUniformMatrix2dv, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, ProgramUniformMatrix2dv, program, location, count, transpose, value) -DECLARE_GL_FUNCTION_STUB_HEAD(void, ProgramUniformMatrix3dv, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, ProgramUniformMatrix3dv, program, location, count, transpose, value) -DECLARE_GL_FUNCTION_STUB_HEAD(void, ProgramUniformMatrix4dv, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, ProgramUniformMatrix4dv, program, location, count, transpose, value) -DECLARE_GL_FUNCTION_STUB_HEAD(void, ProgramUniformMatrix2x3dv, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, ProgramUniformMatrix2x3dv, program, location, count, transpose, value) -DECLARE_GL_FUNCTION_STUB_HEAD(void, ProgramUniformMatrix3x2dv, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, ProgramUniformMatrix3x2dv, program, location, count, transpose, value) -DECLARE_GL_FUNCTION_STUB_HEAD(void, ProgramUniformMatrix2x4dv, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, ProgramUniformMatrix2x4dv, program, location, count, transpose, value) -DECLARE_GL_FUNCTION_STUB_HEAD(void, ProgramUniformMatrix4x2dv, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, ProgramUniformMatrix4x2dv, program, location, count, transpose, value) -DECLARE_GL_FUNCTION_STUB_HEAD(void, ProgramUniformMatrix3x4dv, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, ProgramUniformMatrix3x4dv, program, location, count, transpose, value) -DECLARE_GL_FUNCTION_STUB_HEAD(void, ProgramUniformMatrix4x3dv, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, ProgramUniformMatrix4x3dv, program, location, count, transpose, value) +DECLARE_GL_FUNCTION_HEAD(void, ProgramUniform1d, GLuint program, GLint location, GLdouble v0) DECLARE_GL_FUNCTION_END_NO_RETURN(void, ProgramUniform1d, program, location, v0) +DECLARE_GL_FUNCTION_HEAD(void, ProgramUniform1dv, GLuint program, GLint location, GLsizei count, const GLdouble* value) DECLARE_GL_FUNCTION_END_NO_RETURN(void, ProgramUniform1dv, program, location, count, value) +DECLARE_GL_FUNCTION_HEAD(void, ProgramUniform2d, GLuint program, GLint location, GLdouble v0, GLdouble v1) DECLARE_GL_FUNCTION_END_NO_RETURN(void, ProgramUniform2d, program, location, v0, v1) +DECLARE_GL_FUNCTION_HEAD(void, ProgramUniform2dv, GLuint program, GLint location, GLsizei count, const GLdouble* value) DECLARE_GL_FUNCTION_END_NO_RETURN(void, ProgramUniform2dv, program, location, count, value) +DECLARE_GL_FUNCTION_HEAD(void, ProgramUniform3d, GLuint program, GLint location, GLdouble v0, GLdouble v1, GLdouble v2) DECLARE_GL_FUNCTION_END_NO_RETURN(void, ProgramUniform3d, program, location, v0, v1, v2) +DECLARE_GL_FUNCTION_HEAD(void, ProgramUniform3dv, GLuint program, GLint location, GLsizei count, const GLdouble* value) DECLARE_GL_FUNCTION_END_NO_RETURN(void, ProgramUniform3dv, program, location, count, value) +DECLARE_GL_FUNCTION_HEAD(void, ProgramUniform4d, GLuint program, GLint location, GLdouble v0, GLdouble v1, GLdouble v2, GLdouble v3) DECLARE_GL_FUNCTION_END_NO_RETURN(void, ProgramUniform4d, program, location, v0, v1, v2, v3) +DECLARE_GL_FUNCTION_HEAD(void, ProgramUniform4dv, GLuint program, GLint location, GLsizei count, const GLdouble* value) DECLARE_GL_FUNCTION_END_NO_RETURN(void, ProgramUniform4dv, program, location, count, value) +DECLARE_GL_FUNCTION_HEAD(void, ProgramUniformMatrix2dv, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value) DECLARE_GL_FUNCTION_END_NO_RETURN(void, ProgramUniformMatrix2dv, program, location, count, transpose, value) +DECLARE_GL_FUNCTION_HEAD(void, ProgramUniformMatrix3dv, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value) DECLARE_GL_FUNCTION_END_NO_RETURN(void, ProgramUniformMatrix3dv, program, location, count, transpose, value) +DECLARE_GL_FUNCTION_HEAD(void, ProgramUniformMatrix4dv, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value) DECLARE_GL_FUNCTION_END_NO_RETURN(void, ProgramUniformMatrix4dv, program, location, count, transpose, value) +DECLARE_GL_FUNCTION_HEAD(void, ProgramUniformMatrix2x3dv, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value) DECLARE_GL_FUNCTION_END_NO_RETURN(void, ProgramUniformMatrix2x3dv, program, location, count, transpose, value) +DECLARE_GL_FUNCTION_HEAD(void, ProgramUniformMatrix3x2dv, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value) DECLARE_GL_FUNCTION_END_NO_RETURN(void, ProgramUniformMatrix3x2dv, program, location, count, transpose, value) +DECLARE_GL_FUNCTION_HEAD(void, ProgramUniformMatrix2x4dv, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value) DECLARE_GL_FUNCTION_END_NO_RETURN(void, ProgramUniformMatrix2x4dv, program, location, count, transpose, value) +DECLARE_GL_FUNCTION_HEAD(void, ProgramUniformMatrix4x2dv, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value) DECLARE_GL_FUNCTION_END_NO_RETURN(void, ProgramUniformMatrix4x2dv, program, location, count, transpose, value) +DECLARE_GL_FUNCTION_HEAD(void, ProgramUniformMatrix3x4dv, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value) DECLARE_GL_FUNCTION_END_NO_RETURN(void, ProgramUniformMatrix3x4dv, program, location, count, transpose, value) +DECLARE_GL_FUNCTION_HEAD(void, ProgramUniformMatrix4x3dv, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value) DECLARE_GL_FUNCTION_END_NO_RETURN(void, ProgramUniformMatrix4x3dv, program, location, count, transpose, value) DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttribL1d, GLuint index, GLdouble x) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexAttribL1d, index, x) DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttribL2d, GLuint index, GLdouble x, GLdouble y) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexAttribL2d, index, x, y) DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttribL3d, GLuint index, GLdouble x, GLdouble y, GLdouble z) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexAttribL3d, index, x, y, z) diff --git a/MobileGL/MG_Impl/GLImpl/Program/GL_Program.cpp b/MobileGL/MG_Impl/GLImpl/Program/GL_Program.cpp index 16049656..446eb336 100644 --- a/MobileGL/MG_Impl/GLImpl/Program/GL_Program.cpp +++ b/MobileGL/MG_Impl/GLImpl/Program/GL_Program.cpp @@ -8,6 +8,8 @@ #include "GL_Program.h" #include "Config.h" +#include +#include #include #include #include @@ -830,7 +832,8 @@ namespace MobileGL::MG_Impl::GLImpl { } if constexpr (std::is_same_v) { - if (ttype->isMatrix() && ttype->getMatrixCols() == 3) { + if (ttype->getBasicType() != glslang::EbtDouble && ttype->isMatrix() && + ttype->getMatrixCols() == 3) { auto* pBase = pUBO + offset; for (int i = 0; i < ttype->getMatrixRows(); i++) { Memcpy(reinterpret_cast(params) + ttype->getMatrixCols() * sizeof(GLfloat) * i, @@ -840,9 +843,46 @@ namespace MobileGL::MG_Impl::GLImpl { } } + // A double-precision uniform is the one case where the stored component type can + // differ from the queried one for a non-opaque uniform, and the difference is not + // just a reinterpretation: it is twice as wide, so a raw copy would overrun the + // caller's buffer as well as return nonsense. Read component by component and let + // GL's conversion rules (7.6: round to nearest for the integer queries) apply. + if (ttype->getBasicType() == glslang::EbtDouble) { + const Int columns = ttype->isMatrix() ? ttype->getMatrixCols() : 1; + const Int rows = ttype->isMatrix() ? ttype->getMatrixRows() + : (ttype->isVector() ? ttype->getVectorSize() : 1); + // The slot the linker handed out is exactly `columns` columns wide, so it also + // states the column stride - which for a double matrix is not a float's 16 bytes. + const SizeT columnStride = columns > 0 ? size / static_cast(columns) : size; + for (Int column = 0; column < columns; ++column) { + for (Int row = 0; row < rows; ++row) { + GLdouble component = 0.0; + Memcpy(&component, pUBO + offset + column * columnStride + row * sizeof(GLdouble), + sizeof(component)); + if constexpr (std::is_integral_v) { + // Rounded to the nearest integer and clamped into the queried type's + // range, so a negative double read through glGetUniformuiv is 0 + // rather than its two's complement. + const GLdouble rounded = std::nearbyint(component); + const GLdouble lowest = static_cast(std::numeric_limits::lowest()); + const GLdouble highest = static_cast(std::numeric_limits::max()); + params[column * rows + row] = static_cast(std::clamp(rounded, lowest, highest)); + } else { + params[column * rows + row] = static_cast(component); + } + } + } + return; + } + Memcpy(params, pUBO + offset, size); } + void GetUniformdv_State(GLuint program, GLint location, GLdouble* params) { + GetUniformScalar_State(program, location, params); + } + void GetUniformfv_State(GLuint program, GLint location, GLfloat* params) { GetUniformScalar_State(program, location, params); } @@ -1061,6 +1101,38 @@ namespace MobileGL::MG_Impl::GLImpl { } } + // glUniform*d / glUniformMatrix*dv. The vector forms need nothing beyond the shared + // upload template - it is already typed on the component - but a matrix does: the + // column stride the linker used for a double matrix is not the 16 bytes a float one + // gets. It is not guessed here; the slot the uniform was given is exactly `columns` + // columns wide, so dividing states the stride the rest of the pipeline agreed on. + template + void UniformMatrixdv_Object(Program& programObject, GLint location, GLsizei count, GLboolean transpose, + const GLdouble* value, Int columns, Int rows) { + const SizeT slotSize = programObject.GetUniformSizesInBytes(location); + const SizeT columnStride = columns > 0 ? slotSize / static_cast(columns) : slotSize; + const SizeT componentCount = static_cast(columns) * static_cast(rows); + Vector column(static_cast(rows)); + for (GLint matrix = 0; matrix < count; ++matrix) { + if (matrix > 0 && !programObject.UniformLocationsAliasSameUniform(location, location + matrix)) break; + if (!programObject.IsValidUniformLocation(location + matrix)) { + RecordInvalidUniformLocationError(__func__, location + matrix, "the current program object"); + return; + } + const GLdouble* source = value + matrix * componentCount; + for (Int c = 0; c < columns; ++c) { + for (Int r = 0; r < rows; ++r) { + column[r] = transpose == GL_TRUE ? source[r * columns + c] : source[c * rows + r]; + } + Uniform_State<1>(programObject, location + matrix, column.data(), c * columnStride); + for (Int r = 1; r < rows; ++r) { + Uniform_State<1>(programObject, location + matrix, column.data() + r, + c * columnStride + r * sizeof(GLdouble)); + } + } + } + } + // Helper function to transpose a 2x2 matrix void TransposeMatrix2x2(const GLfloat* input, GLfloat* output) { // Input matrix is in column-major order (OpenGL default) @@ -1869,6 +1941,312 @@ namespace MobileGL::MG_Impl::GLImpl { GLuint v[] = {v0, v1, v2, v3}; Uniform4uiv(location, 1, v); } + void Uniform1d(GLint location, GLdouble v0) { + const GLdouble v[] = {v0}; + Uniformv_State<1>(location, 1, v); + } + + void Uniform1dv(GLint location, GLsizei count, const GLdouble* value) { + Uniformv_State<1>(location, count, value); + } + + void ProgramUniform1d(GLuint program, GLint location, GLdouble v0) { + const GLdouble v[] = {v0}; + ProgramUniformv_State<1>(program, location, 1, v); + } + + void ProgramUniform1dv(GLuint program, GLint location, GLsizei count, const GLdouble* value) { + ProgramUniformv_State<1>(program, location, count, value); + } + void Uniform2d(GLint location, GLdouble v0, GLdouble v1) { + const GLdouble v[] = {v0, v1}; + Uniformv_State<2>(location, 1, v); + } + + void Uniform2dv(GLint location, GLsizei count, const GLdouble* value) { + Uniformv_State<2>(location, count, value); + } + + void ProgramUniform2d(GLuint program, GLint location, GLdouble v0, GLdouble v1) { + const GLdouble v[] = {v0, v1}; + ProgramUniformv_State<2>(program, location, 1, v); + } + + void ProgramUniform2dv(GLuint program, GLint location, GLsizei count, const GLdouble* value) { + ProgramUniformv_State<2>(program, location, count, value); + } + void Uniform3d(GLint location, GLdouble v0, GLdouble v1, GLdouble v2) { + const GLdouble v[] = {v0, v1, v2}; + Uniformv_State<3>(location, 1, v); + } + + void Uniform3dv(GLint location, GLsizei count, const GLdouble* value) { + Uniformv_State<3>(location, count, value); + } + + void ProgramUniform3d(GLuint program, GLint location, GLdouble v0, GLdouble v1, GLdouble v2) { + const GLdouble v[] = {v0, v1, v2}; + ProgramUniformv_State<3>(program, location, 1, v); + } + + void ProgramUniform3dv(GLuint program, GLint location, GLsizei count, const GLdouble* value) { + ProgramUniformv_State<3>(program, location, count, value); + } + void Uniform4d(GLint location, GLdouble v0, GLdouble v1, GLdouble v2, GLdouble v3) { + const GLdouble v[] = {v0, v1, v2, v3}; + Uniformv_State<4>(location, 1, v); + } + + void Uniform4dv(GLint location, GLsizei count, const GLdouble* value) { + Uniformv_State<4>(location, count, value); + } + + void ProgramUniform4d(GLuint program, GLint location, GLdouble v0, GLdouble v1, GLdouble v2, GLdouble v3) { + const GLdouble v[] = {v0, v1, v2, v3}; + ProgramUniformv_State<4>(program, location, 1, v); + } + + void ProgramUniform4dv(GLuint program, GLint location, GLsizei count, const GLdouble* value) { + ProgramUniformv_State<4>(program, location, count, value); + } + void UniformMatrix2dv(GLint location, GLsizei count, GLboolean transpose, const GLdouble* value) { + if (location == -1) return; + auto& programObject = MG_State::pGLContext->GetCurrentProgram(); + if (programObject == nullptr) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidOperation, + MakeUnique("MG_Impl/GLImpl", __func__, "There is no current program object.")); + return; + } + UniformMatrixdv_Object(*programObject, location, count, transpose, value, 2, 2); + } + + void ProgramUniformMatrix2dv(GLuint program, GLint location, GLsizei count, GLboolean transpose, + const GLdouble* value) { + if (location == -1) return; + auto& programObject = TryToGetProgramObject(program); + if (!programObject) return; + if (!programObject->GetLinkStatus()) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidOperation, + MakeUnique("MG_Impl/GLImpl", __func__, + "program " + std::to_string(program) + " is not linked.")); + return; + } + UniformMatrixdv_Object(*programObject, location, count, transpose, value, 2, 2); + } + void UniformMatrix3dv(GLint location, GLsizei count, GLboolean transpose, const GLdouble* value) { + if (location == -1) return; + auto& programObject = MG_State::pGLContext->GetCurrentProgram(); + if (programObject == nullptr) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidOperation, + MakeUnique("MG_Impl/GLImpl", __func__, "There is no current program object.")); + return; + } + UniformMatrixdv_Object(*programObject, location, count, transpose, value, 3, 3); + } + + void ProgramUniformMatrix3dv(GLuint program, GLint location, GLsizei count, GLboolean transpose, + const GLdouble* value) { + if (location == -1) return; + auto& programObject = TryToGetProgramObject(program); + if (!programObject) return; + if (!programObject->GetLinkStatus()) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidOperation, + MakeUnique("MG_Impl/GLImpl", __func__, + "program " + std::to_string(program) + " is not linked.")); + return; + } + UniformMatrixdv_Object(*programObject, location, count, transpose, value, 3, 3); + } + void UniformMatrix4dv(GLint location, GLsizei count, GLboolean transpose, const GLdouble* value) { + if (location == -1) return; + auto& programObject = MG_State::pGLContext->GetCurrentProgram(); + if (programObject == nullptr) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidOperation, + MakeUnique("MG_Impl/GLImpl", __func__, "There is no current program object.")); + return; + } + UniformMatrixdv_Object(*programObject, location, count, transpose, value, 4, 4); + } + + void ProgramUniformMatrix4dv(GLuint program, GLint location, GLsizei count, GLboolean transpose, + const GLdouble* value) { + if (location == -1) return; + auto& programObject = TryToGetProgramObject(program); + if (!programObject) return; + if (!programObject->GetLinkStatus()) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidOperation, + MakeUnique("MG_Impl/GLImpl", __func__, + "program " + std::to_string(program) + " is not linked.")); + return; + } + UniformMatrixdv_Object(*programObject, location, count, transpose, value, 4, 4); + } + void UniformMatrix2x3dv(GLint location, GLsizei count, GLboolean transpose, const GLdouble* value) { + if (location == -1) return; + auto& programObject = MG_State::pGLContext->GetCurrentProgram(); + if (programObject == nullptr) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidOperation, + MakeUnique("MG_Impl/GLImpl", __func__, "There is no current program object.")); + return; + } + UniformMatrixdv_Object(*programObject, location, count, transpose, value, 2, 3); + } + + void ProgramUniformMatrix2x3dv(GLuint program, GLint location, GLsizei count, GLboolean transpose, + const GLdouble* value) { + if (location == -1) return; + auto& programObject = TryToGetProgramObject(program); + if (!programObject) return; + if (!programObject->GetLinkStatus()) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidOperation, + MakeUnique("MG_Impl/GLImpl", __func__, + "program " + std::to_string(program) + " is not linked.")); + return; + } + UniformMatrixdv_Object(*programObject, location, count, transpose, value, 2, 3); + } + void UniformMatrix2x4dv(GLint location, GLsizei count, GLboolean transpose, const GLdouble* value) { + if (location == -1) return; + auto& programObject = MG_State::pGLContext->GetCurrentProgram(); + if (programObject == nullptr) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidOperation, + MakeUnique("MG_Impl/GLImpl", __func__, "There is no current program object.")); + return; + } + UniformMatrixdv_Object(*programObject, location, count, transpose, value, 2, 4); + } + + void ProgramUniformMatrix2x4dv(GLuint program, GLint location, GLsizei count, GLboolean transpose, + const GLdouble* value) { + if (location == -1) return; + auto& programObject = TryToGetProgramObject(program); + if (!programObject) return; + if (!programObject->GetLinkStatus()) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidOperation, + MakeUnique("MG_Impl/GLImpl", __func__, + "program " + std::to_string(program) + " is not linked.")); + return; + } + UniformMatrixdv_Object(*programObject, location, count, transpose, value, 2, 4); + } + void UniformMatrix3x2dv(GLint location, GLsizei count, GLboolean transpose, const GLdouble* value) { + if (location == -1) return; + auto& programObject = MG_State::pGLContext->GetCurrentProgram(); + if (programObject == nullptr) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidOperation, + MakeUnique("MG_Impl/GLImpl", __func__, "There is no current program object.")); + return; + } + UniformMatrixdv_Object(*programObject, location, count, transpose, value, 3, 2); + } + + void ProgramUniformMatrix3x2dv(GLuint program, GLint location, GLsizei count, GLboolean transpose, + const GLdouble* value) { + if (location == -1) return; + auto& programObject = TryToGetProgramObject(program); + if (!programObject) return; + if (!programObject->GetLinkStatus()) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidOperation, + MakeUnique("MG_Impl/GLImpl", __func__, + "program " + std::to_string(program) + " is not linked.")); + return; + } + UniformMatrixdv_Object(*programObject, location, count, transpose, value, 3, 2); + } + void UniformMatrix3x4dv(GLint location, GLsizei count, GLboolean transpose, const GLdouble* value) { + if (location == -1) return; + auto& programObject = MG_State::pGLContext->GetCurrentProgram(); + if (programObject == nullptr) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidOperation, + MakeUnique("MG_Impl/GLImpl", __func__, "There is no current program object.")); + return; + } + UniformMatrixdv_Object(*programObject, location, count, transpose, value, 3, 4); + } + + void ProgramUniformMatrix3x4dv(GLuint program, GLint location, GLsizei count, GLboolean transpose, + const GLdouble* value) { + if (location == -1) return; + auto& programObject = TryToGetProgramObject(program); + if (!programObject) return; + if (!programObject->GetLinkStatus()) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidOperation, + MakeUnique("MG_Impl/GLImpl", __func__, + "program " + std::to_string(program) + " is not linked.")); + return; + } + UniformMatrixdv_Object(*programObject, location, count, transpose, value, 3, 4); + } + void UniformMatrix4x2dv(GLint location, GLsizei count, GLboolean transpose, const GLdouble* value) { + if (location == -1) return; + auto& programObject = MG_State::pGLContext->GetCurrentProgram(); + if (programObject == nullptr) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidOperation, + MakeUnique("MG_Impl/GLImpl", __func__, "There is no current program object.")); + return; + } + UniformMatrixdv_Object(*programObject, location, count, transpose, value, 4, 2); + } + + void ProgramUniformMatrix4x2dv(GLuint program, GLint location, GLsizei count, GLboolean transpose, + const GLdouble* value) { + if (location == -1) return; + auto& programObject = TryToGetProgramObject(program); + if (!programObject) return; + if (!programObject->GetLinkStatus()) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidOperation, + MakeUnique("MG_Impl/GLImpl", __func__, + "program " + std::to_string(program) + " is not linked.")); + return; + } + UniformMatrixdv_Object(*programObject, location, count, transpose, value, 4, 2); + } + void UniformMatrix4x3dv(GLint location, GLsizei count, GLboolean transpose, const GLdouble* value) { + if (location == -1) return; + auto& programObject = MG_State::pGLContext->GetCurrentProgram(); + if (programObject == nullptr) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidOperation, + MakeUnique("MG_Impl/GLImpl", __func__, "There is no current program object.")); + return; + } + UniformMatrixdv_Object(*programObject, location, count, transpose, value, 4, 3); + } + + void ProgramUniformMatrix4x3dv(GLuint program, GLint location, GLsizei count, GLboolean transpose, + const GLdouble* value) { + if (location == -1) return; + auto& programObject = TryToGetProgramObject(program); + if (!programObject) return; + if (!programObject->GetLinkStatus()) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidOperation, + MakeUnique("MG_Impl/GLImpl", __func__, + "program " + std::to_string(program) + " is not linked.")); + return; + } + UniformMatrixdv_Object(*programObject, location, count, transpose, value, 4, 3); + } + void GetUniformdv(GLuint program, GLint location, GLdouble* params) { + GetUniformdv_State(program, location, params); + } + void Uniform1fv(GLint location, GLsizei count, const GLfloat* value) { Uniform1fv_State(location, count, value); } diff --git a/MobileGL/MG_Impl/GLImpl/Program/GL_Program.h b/MobileGL/MG_Impl/GLImpl/Program/GL_Program.h index 2cf45640..7ac81a1b 100644 --- a/MobileGL/MG_Impl/GLImpl/Program/GL_Program.h +++ b/MobileGL/MG_Impl/GLImpl/Program/GL_Program.h @@ -137,6 +137,41 @@ namespace MobileGL::MG_Impl::GLImpl { GLint GetProgramResourceLocation(GLuint program, GLenum programInterface, const GLchar* name); GLint GetProgramResourceLocationIndex(GLuint program, GLenum programInterface, const GLchar* name); void ShaderStorageBlockBinding(GLuint program, GLuint storageBlockIndex, GLuint storageBlockBinding); + void Uniform1d(GLint location, GLdouble v0); + void Uniform1dv(GLint location, GLsizei count, const GLdouble* value); + void ProgramUniform1d(GLuint program, GLint location, GLdouble v0); + void ProgramUniform1dv(GLuint program, GLint location, GLsizei count, const GLdouble* value); + void Uniform2d(GLint location, GLdouble v0, GLdouble v1); + void Uniform2dv(GLint location, GLsizei count, const GLdouble* value); + void ProgramUniform2d(GLuint program, GLint location, GLdouble v0, GLdouble v1); + void ProgramUniform2dv(GLuint program, GLint location, GLsizei count, const GLdouble* value); + void Uniform3d(GLint location, GLdouble v0, GLdouble v1, GLdouble v2); + void Uniform3dv(GLint location, GLsizei count, const GLdouble* value); + void ProgramUniform3d(GLuint program, GLint location, GLdouble v0, GLdouble v1, GLdouble v2); + void ProgramUniform3dv(GLuint program, GLint location, GLsizei count, const GLdouble* value); + void Uniform4d(GLint location, GLdouble v0, GLdouble v1, GLdouble v2, GLdouble v3); + void Uniform4dv(GLint location, GLsizei count, const GLdouble* value); + void ProgramUniform4d(GLuint program, GLint location, GLdouble v0, GLdouble v1, GLdouble v2, GLdouble v3); + void ProgramUniform4dv(GLuint program, GLint location, GLsizei count, const GLdouble* value); + void UniformMatrix2dv(GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); + void ProgramUniformMatrix2dv(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); + void UniformMatrix3dv(GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); + void ProgramUniformMatrix3dv(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); + void UniformMatrix4dv(GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); + void ProgramUniformMatrix4dv(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); + void UniformMatrix2x3dv(GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); + void ProgramUniformMatrix2x3dv(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); + void UniformMatrix2x4dv(GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); + void ProgramUniformMatrix2x4dv(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); + void UniformMatrix3x2dv(GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); + void ProgramUniformMatrix3x2dv(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); + void UniformMatrix3x4dv(GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); + void ProgramUniformMatrix3x4dv(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); + void UniformMatrix4x2dv(GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); + void ProgramUniformMatrix4x2dv(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); + void UniformMatrix4x3dv(GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); + void ProgramUniformMatrix4x3dv(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); + void GetUniformdv(GLuint program, GLint location, GLdouble* params); void ValidateProgram(GLuint program); void ProgramParameteri(GLuint program, GLenum pname, GLint value); void GetProgramBinary(GLuint program, GLsizei bufSize, GLsizei* length, GLenum* binaryFormat, void* binary);