diff --git a/MobileGL/MG_Backend/DirectGLES/DirectGLES.cpp b/MobileGL/MG_Backend/DirectGLES/DirectGLES.cpp index 12f27795..7a9b77df 100644 --- a/MobileGL/MG_Backend/DirectGLES/DirectGLES.cpp +++ b/MobileGL/MG_Backend/DirectGLES/DirectGLES.cpp @@ -2792,9 +2792,9 @@ namespace MobileGL::MG_Backend::DirectGLES { MG_Util::ConvertGLEnumToString(format).c_str()); MOBILEGL_ASSERT(type == GL_UNSIGNED_BYTE || type == GL_UNSIGNED_INT || type == GL_UNSIGNED_INT_2_10_10_10_REV || type == GL_INT || type == GL_FLOAT || type == GL_UNSIGNED_INT_8_8_8_8 || - type == GL_UNSIGNED_INT_8_8_8_8_REV, + type == GL_UNSIGNED_INT_8_8_8_8_REV || type == GL_HALF_FLOAT, "Only GL_UNSIGNED_BYTE, GL_UNSIGNED_INT, GL_UNSIGNED_INT_2_10_10_10_REV, " - "GL_INT, GL_FLOAT, GL_UNSIGNED_INT_8_8_8_8 and GL_UNSIGNED_INT_8_8_8_8_REV " + "GL_INT, GL_FLOAT, GL_HALF_FLOAT, GL_UNSIGNED_INT_8_8_8_8 and GL_UNSIGNED_INT_8_8_8_8_REV " "are supported currently, while requested %s.", MG_Util::ConvertGLEnumToString(type).c_str()); diff --git a/MobileGL/MG_Impl/GLImpl/Exporting/Definitions.cpp b/MobileGL/MG_Impl/GLImpl/Exporting/Definitions.cpp index 5dd9e99c..acef6daa 100644 --- a/MobileGL/MG_Impl/GLImpl/Exporting/Definitions.cpp +++ b/MobileGL/MG_Impl/GLImpl/Exporting/Definitions.cpp @@ -227,12 +227,12 @@ DECLARE_GL_FUNCTION_STUB_HEAD(void, GetQueryObjectuiv, GLuint id, GLenum pname, DECLARE_GL_FUNCTION_HEAD(GLboolean, UnmapBuffer, GLenum target) DECLARE_GL_FUNCTION_END(GLboolean, UnmapBuffer, target) DECLARE_GL_FUNCTION_HEAD(void, GetBufferPointerv, GLenum target, GLenum pname, void** params) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetBufferPointerv, target, pname, params) DECLARE_GL_FUNCTION_HEAD(void, DrawBuffers, GLsizei n, const GLenum* bufs) DECLARE_GL_FUNCTION_END_NO_RETURN(void, DrawBuffers, n, bufs) -DECLARE_GL_FUNCTION_STUB_HEAD(void, UniformMatrix2x3fv, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, UniformMatrix2x3fv, location, count, transpose, value) -DECLARE_GL_FUNCTION_STUB_HEAD(void, UniformMatrix3x2fv, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, UniformMatrix3x2fv, location, count, transpose, value) -DECLARE_GL_FUNCTION_STUB_HEAD(void, UniformMatrix2x4fv, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, UniformMatrix2x4fv, location, count, transpose, value) -DECLARE_GL_FUNCTION_STUB_HEAD(void, UniformMatrix4x2fv, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, UniformMatrix4x2fv, location, count, transpose, value) -DECLARE_GL_FUNCTION_STUB_HEAD(void, UniformMatrix3x4fv, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, UniformMatrix3x4fv, location, count, transpose, value) -DECLARE_GL_FUNCTION_STUB_HEAD(void, UniformMatrix4x3fv, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, UniformMatrix4x3fv, location, count, transpose, value) +DECLARE_GL_FUNCTION_HEAD(void, UniformMatrix2x3fv, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) DECLARE_GL_FUNCTION_END_NO_RETURN(void, UniformMatrix2x3fv, location, count, transpose, value) +DECLARE_GL_FUNCTION_HEAD(void, UniformMatrix3x2fv, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) DECLARE_GL_FUNCTION_END_NO_RETURN(void, UniformMatrix3x2fv, location, count, transpose, value) +DECLARE_GL_FUNCTION_HEAD(void, UniformMatrix2x4fv, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) DECLARE_GL_FUNCTION_END_NO_RETURN(void, UniformMatrix2x4fv, location, count, transpose, value) +DECLARE_GL_FUNCTION_HEAD(void, UniformMatrix4x2fv, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) DECLARE_GL_FUNCTION_END_NO_RETURN(void, UniformMatrix4x2fv, location, count, transpose, value) +DECLARE_GL_FUNCTION_HEAD(void, UniformMatrix3x4fv, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) DECLARE_GL_FUNCTION_END_NO_RETURN(void, UniformMatrix3x4fv, location, count, transpose, value) +DECLARE_GL_FUNCTION_HEAD(void, UniformMatrix4x3fv, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) DECLARE_GL_FUNCTION_END_NO_RETURN(void, UniformMatrix4x3fv, location, count, transpose, value) DECLARE_GL_FUNCTION_HEAD(void, BlitFramebuffer, GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter) DECLARE_GL_FUNCTION_END_NO_RETURN(void, BlitFramebuffer, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter) //DECLARE_GL_FUNCTION_HEAD(void, BlitFramebuffer, GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter) DECLARE_GL_FUNCTION_END_NO_RETURN(void, BlitFramebuffer, srcX0,srcY0,srcX1,srcY1,dstX0,dstY0,dstX1,dstY1,mask,filter) DECLARE_GL_FUNCTION_HEAD(void, RenderbufferStorageMultisample, GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height) DECLARE_GL_FUNCTION_END_NO_RETURN(void, RenderbufferStorageMultisample, target, samples, internalformat, width, height) @@ -359,12 +359,12 @@ DECLARE_GL_FUNCTION_HEAD(void, ProgramUniform4fv, GLuint program, GLint location DECLARE_GL_FUNCTION_HEAD(void, ProgramUniformMatrix2fv, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) DECLARE_GL_FUNCTION_END_NO_RETURN(void, ProgramUniformMatrix2fv, program, location, count, transpose, value) DECLARE_GL_FUNCTION_HEAD(void, ProgramUniformMatrix3fv, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) DECLARE_GL_FUNCTION_END_NO_RETURN(void, ProgramUniformMatrix3fv, program, location, count, transpose, value) DECLARE_GL_FUNCTION_HEAD(void, ProgramUniformMatrix4fv, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) DECLARE_GL_FUNCTION_END_NO_RETURN(void, ProgramUniformMatrix4fv, program, location, count, transpose, value) -DECLARE_GL_FUNCTION_STUB_HEAD(void, ProgramUniformMatrix2x3fv, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, ProgramUniformMatrix2x3fv, program, location, count, transpose, value) -DECLARE_GL_FUNCTION_STUB_HEAD(void, ProgramUniformMatrix3x2fv, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, ProgramUniformMatrix3x2fv, program, location, count, transpose, value) -DECLARE_GL_FUNCTION_STUB_HEAD(void, ProgramUniformMatrix2x4fv, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, ProgramUniformMatrix2x4fv, program, location, count, transpose, value) -DECLARE_GL_FUNCTION_STUB_HEAD(void, ProgramUniformMatrix4x2fv, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, ProgramUniformMatrix4x2fv, program, location, count, transpose, value) -DECLARE_GL_FUNCTION_STUB_HEAD(void, ProgramUniformMatrix3x4fv, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, ProgramUniformMatrix3x4fv, program, location, count, transpose, value) -DECLARE_GL_FUNCTION_STUB_HEAD(void, ProgramUniformMatrix4x3fv, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, ProgramUniformMatrix4x3fv, program, location, count, transpose, value) +DECLARE_GL_FUNCTION_HEAD(void, ProgramUniformMatrix2x3fv, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) DECLARE_GL_FUNCTION_END_NO_RETURN(void, ProgramUniformMatrix2x3fv, program, location, count, transpose, value) +DECLARE_GL_FUNCTION_HEAD(void, ProgramUniformMatrix3x2fv, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) DECLARE_GL_FUNCTION_END_NO_RETURN(void, ProgramUniformMatrix3x2fv, program, location, count, transpose, value) +DECLARE_GL_FUNCTION_HEAD(void, ProgramUniformMatrix2x4fv, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) DECLARE_GL_FUNCTION_END_NO_RETURN(void, ProgramUniformMatrix2x4fv, program, location, count, transpose, value) +DECLARE_GL_FUNCTION_HEAD(void, ProgramUniformMatrix4x2fv, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) DECLARE_GL_FUNCTION_END_NO_RETURN(void, ProgramUniformMatrix4x2fv, program, location, count, transpose, value) +DECLARE_GL_FUNCTION_HEAD(void, ProgramUniformMatrix3x4fv, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) DECLARE_GL_FUNCTION_END_NO_RETURN(void, ProgramUniformMatrix3x4fv, program, location, count, transpose, value) +DECLARE_GL_FUNCTION_HEAD(void, ProgramUniformMatrix4x3fv, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) DECLARE_GL_FUNCTION_END_NO_RETURN(void, ProgramUniformMatrix4x3fv, program, location, count, transpose, value) DECLARE_GL_FUNCTION_STUB_HEAD(void, ValidateProgramPipeline, GLuint pipeline) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, ValidateProgramPipeline, pipeline) DECLARE_GL_FUNCTION_STUB_HEAD(void, GetProgramPipelineInfoLog, GLuint pipeline, GLsizei bufSize, GLsizei* length, GLchar* infoLog) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetProgramPipelineInfoLog, pipeline, bufSize, length, infoLog) DECLARE_GL_FUNCTION_HEAD(void, BindImageTexture, GLuint unit, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access, GLenum format) DECLARE_GL_FUNCTION_END_NO_RETURN(void, BindImageTexture, unit, texture, level, layered, layer, access, format) diff --git a/MobileGL/MG_Impl/GLImpl/Getter/GL_Getter.cpp b/MobileGL/MG_Impl/GLImpl/Getter/GL_Getter.cpp index e793fc23..42be082e 100644 --- a/MobileGL/MG_Impl/GLImpl/Getter/GL_Getter.cpp +++ b/MobileGL/MG_Impl/GLImpl/Getter/GL_Getter.cpp @@ -646,6 +646,52 @@ namespace MobileGL::MG_Impl::GLImpl { } } + switch (target) { + case GL_IMAGE_BINDING_NAME: + case GL_IMAGE_BINDING_LEVEL: + case GL_IMAGE_BINDING_LAYERED: + case GL_IMAGE_BINDING_LAYER: + case GL_IMAGE_BINDING_ACCESS: + case GL_IMAGE_BINDING_FORMAT: { + const auto maxImageUnits = static_cast(std::min( + MG_Backend::pActiveBackendObject->GetDynamicParameters().MaxImageUnits, + MG_State::GLState::TextureState::MAX_TEXTURE_IMAGE_UNITS)); + if (index >= maxImageUnits) { + *data = 0; + MG_State::pGLContext->RecordError( + ErrorCode::InvalidValue, + MakeUnique("MG_Impl/GLImpl", __func__, "Image unit index is out of range.")); + return; + } + + const auto& binding = MG_State::pGLContext->GetImageTextureBinding(static_cast(index)); + switch (target) { + case GL_IMAGE_BINDING_NAME: + *data = binding.Texture ? static_cast(binding.Texture->GetExternalIndex()) : 0; + return; + case GL_IMAGE_BINDING_LEVEL: + *data = binding.Level; + return; + case GL_IMAGE_BINDING_LAYERED: + *data = binding.Layered; + return; + case GL_IMAGE_BINDING_LAYER: + *data = binding.Layer; + return; + case GL_IMAGE_BINDING_ACCESS: + *data = static_cast(binding.Access); + return; + case GL_IMAGE_BINDING_FORMAT: + *data = static_cast(binding.Format); + return; + default: + break; + } + } + default: + break; + } + auto getIntegeri = MG_Backend::gBackendFunctionsTable.GL.GetIntegeri_v; if (target == GL_MAX_COMPUTE_WORK_GROUP_COUNT || target == GL_MAX_COMPUTE_WORK_GROUP_SIZE) { if (index >= 3) { diff --git a/MobileGL/MG_Impl/GLImpl/Program/GL_Program.cpp b/MobileGL/MG_Impl/GLImpl/Program/GL_Program.cpp index 17a3cf74..e5a0b551 100644 --- a/MobileGL/MG_Impl/GLImpl/Program/GL_Program.cpp +++ b/MobileGL/MG_Impl/GLImpl/Program/GL_Program.cpp @@ -216,6 +216,25 @@ namespace MobileGL::MG_Impl::GLImpl { return false; } + GLint GetOpaqueUniformUnitLimit(const glslang::TType* type) { + const auto& dynamicParameters = MG_Backend::pActiveBackendObject->GetDynamicParameters(); + if (type && type->isImage()) return dynamicParameters.MaxImageUnits; + if (type && type->isTexture()) return dynamicParameters.MaxCombinedTextureImageUnits; + return 0; + } + + bool ValidateOpaqueUniformUnit(const char* functionName, const glslang::TType* type, GLint unit) { + const GLint limit = GetOpaqueUniformUnitLimit(type); + if (unit < 0 || unit >= limit) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidValue, + MakeUnique("MG_Impl/GLImpl", functionName, + "Opaque uniform unit is out of range.")); + return false; + } + return true; + } + void AttachShader_State(GLuint program, GLuint shader) { auto& programObject = TryToGetProgramObject(program); if (!programObject) return; @@ -776,12 +795,19 @@ namespace MobileGL::MG_Impl::GLImpl { Memcpy((char*)programObject.MapUBO() + offset + byteOffsetInsideUniform, value, ItemCount * sizeof(T)); } else { auto* ttype = programObject.GetUniformTType(location); - if (ttype->isTexture() || ttype->isImage()) { - MGLOG_D("%s: program = %d, opaque uniform location = %d, name = '%s', unit = %d", __func__, - programObject.GetExternalIndex(), location, programObject.GetUniformName(location).c_str(), - static_cast(*value)); - programObject.SetUniformSamplerOrImageUnitIndex(location, *value); + if (!ttype->isTexture() && !ttype->isImage()) return; + if constexpr (!std::is_same_v, GLint> || ItemCount != 1) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidOperation, + MakeUnique("MG_Impl/GLImpl", __func__, + "Opaque uniforms can only be set with Uniform1i/Uniform1iv.")); + return; } + if (!ValidateOpaqueUniformUnit(__func__, ttype, *value)) return; + MGLOG_D("%s: program = %d, opaque uniform location = %d, name = '%s', unit = %d", __func__, + programObject.GetExternalIndex(), location, programObject.GetUniformName(location).c_str(), + static_cast(*value)); + programObject.SetUniformSamplerOrImageUnitIndex(location, *value); } } @@ -1033,6 +1059,34 @@ namespace MobileGL::MG_Impl::GLImpl { } } + void UniformMatrixNonSquarefv_State(const char* caller, GLint location, GLsizei count) { + if (location == -1) return; + + auto& programObject = MG_State::pGLContext->GetCurrentProgram(); + if (programObject == nullptr) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidOperation, + MakeUnique("MG_Impl/GLImpl", caller, "There is no current program object.")); + return; + } + + for (GLint i = 0; i < count; i++) { + if (!programObject->IsValidUniformLocation(location + i)) { + RecordInvalidUniformLocationError(caller, location + i, "the current program object"); + return; + } + if (programObject->IsUniformOpaqueAtLocation(location + i)) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidOperation, + MakeUnique("MG_Impl/GLImpl", caller, + "Opaque uniforms cannot be set with matrix Uniform calls.")); + return; + } + } + + // TODO: Implement non-square matrix uniform uploads for non-opaque uniforms. + } + void ProgramUniformMatrix2fv_State(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) { if (location == -1) return; @@ -1127,6 +1181,37 @@ namespace MobileGL::MG_Impl::GLImpl { } } + void ProgramUniformMatrixNonSquarefv_State(const char* caller, GLuint program, GLint location, GLsizei count) { + if (location == -1) return; + + auto& programObject = TryToGetProgramObject(program); + if (!programObject) return; + + if (!programObject->GetLinkStatus()) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidOperation, + MakeUnique("MG_Impl/GLImpl", caller, + "program " + std::to_string(program) + " is not linked.")); + return; + } + + for (GLint i = 0; i < count; i++) { + if (!programObject->IsValidUniformLocation(location + i)) { + RecordInvalidUniformLocationError(caller, location + i, "program " + std::to_string(program)); + return; + } + if (programObject->IsUniformOpaqueAtLocation(location + i)) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidOperation, + MakeUnique("MG_Impl/GLImpl", caller, + "Opaque uniforms cannot be set with matrix Uniform calls.")); + return; + } + } + + // TODO: Implement non-square matrix uniform uploads for non-opaque uniforms. + } + GLuint GetUniformBlockIndex_State(GLuint program, const GLchar* uniformBlockName) { const auto& programObject = TryToGetProgramObject(program); if (!programObject) return GL_INVALID_INDEX; @@ -1576,6 +1661,30 @@ namespace MobileGL::MG_Impl::GLImpl { UniformMatrix4fv_State(location, count, transpose, value); } + void UniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) { + UniformMatrixNonSquarefv_State(__func__, location, count); + } + + void UniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) { + UniformMatrixNonSquarefv_State(__func__, location, count); + } + + void UniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) { + UniformMatrixNonSquarefv_State(__func__, location, count); + } + + void UniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) { + UniformMatrixNonSquarefv_State(__func__, location, count); + } + + void UniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) { + UniformMatrixNonSquarefv_State(__func__, location, count); + } + + void UniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) { + UniformMatrixNonSquarefv_State(__func__, location, count); + } + void ProgramUniform1f(GLuint program, GLint location, GLfloat v0) { ProgramUniform1fv(program, location, 1, &v0); } @@ -1696,6 +1805,36 @@ namespace MobileGL::MG_Impl::GLImpl { ProgramUniformMatrix4fv_State(program, location, count, transpose, value); } + void ProgramUniformMatrix2x3fv(GLuint program, GLint location, GLsizei count, GLboolean transpose, + const GLfloat* value) { + ProgramUniformMatrixNonSquarefv_State(__func__, program, location, count); + } + + void ProgramUniformMatrix3x2fv(GLuint program, GLint location, GLsizei count, GLboolean transpose, + const GLfloat* value) { + ProgramUniformMatrixNonSquarefv_State(__func__, program, location, count); + } + + void ProgramUniformMatrix2x4fv(GLuint program, GLint location, GLsizei count, GLboolean transpose, + const GLfloat* value) { + ProgramUniformMatrixNonSquarefv_State(__func__, program, location, count); + } + + void ProgramUniformMatrix4x2fv(GLuint program, GLint location, GLsizei count, GLboolean transpose, + const GLfloat* value) { + ProgramUniformMatrixNonSquarefv_State(__func__, program, location, count); + } + + void ProgramUniformMatrix3x4fv(GLuint program, GLint location, GLsizei count, GLboolean transpose, + const GLfloat* value) { + ProgramUniformMatrixNonSquarefv_State(__func__, program, location, count); + } + + void ProgramUniformMatrix4x3fv(GLuint program, GLint location, GLsizei count, GLboolean transpose, + const GLfloat* value) { + ProgramUniformMatrixNonSquarefv_State(__func__, program, location, count); + } + GLuint GetUniformBlockIndex(GLuint program, const GLchar* uniformBlockName) { return GetUniformBlockIndex_State(program, uniformBlockName); } diff --git a/MobileGL/MG_Impl/GLImpl/Program/GL_Program.h b/MobileGL/MG_Impl/GLImpl/Program/GL_Program.h index 97707865..91b243aa 100644 --- a/MobileGL/MG_Impl/GLImpl/Program/GL_Program.h +++ b/MobileGL/MG_Impl/GLImpl/Program/GL_Program.h @@ -99,6 +99,24 @@ namespace MobileGL::MG_Impl::GLImpl { const GLfloat* value); void ProgramUniformMatrix4fv(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); + void UniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); + void UniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); + void UniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); + void UniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); + void UniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); + void UniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); + void ProgramUniformMatrix2x3fv(GLuint program, GLint location, GLsizei count, GLboolean transpose, + const GLfloat* value); + void ProgramUniformMatrix3x2fv(GLuint program, GLint location, GLsizei count, GLboolean transpose, + const GLfloat* value); + void ProgramUniformMatrix2x4fv(GLuint program, GLint location, GLsizei count, GLboolean transpose, + const GLfloat* value); + void ProgramUniformMatrix4x2fv(GLuint program, GLint location, GLsizei count, GLboolean transpose, + const GLfloat* value); + void ProgramUniformMatrix3x4fv(GLuint program, GLint location, GLsizei count, GLboolean transpose, + const GLfloat* value); + void ProgramUniformMatrix4x3fv(GLuint program, GLint location, GLsizei count, GLboolean transpose, + const GLfloat* value); GLuint GetUniformBlockIndex(GLuint program, const GLchar* uniformBlockName); void UniformBlockBinding(GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding); void GetActiveUniformBlockiv(GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint* params); diff --git a/MobileGL/MG_Impl/GLImpl/Texture/GL_Texture.cpp b/MobileGL/MG_Impl/GLImpl/Texture/GL_Texture.cpp index fc4a3ba7..01139594 100644 --- a/MobileGL/MG_Impl/GLImpl/Texture/GL_Texture.cpp +++ b/MobileGL/MG_Impl/GLImpl/Texture/GL_Texture.cpp @@ -231,6 +231,59 @@ namespace MobileGL::MG_Impl::GLImpl { } } + Bool IsValidImageTextureFormat(GLenum format) { + switch (format) { + case GL_RGBA32F: + case GL_RGBA16F: + case GL_RG32F: + case GL_RG16F: + case GL_R11F_G11F_B10F: + case GL_R32F: + case GL_R16F: + case GL_RGBA32UI: + case GL_RGBA16UI: + case GL_RGB10_A2UI: + case GL_RGBA8UI: + case GL_RG32UI: + case GL_RG16UI: + case GL_RG8UI: + case GL_R32UI: + case GL_R16UI: + case GL_R8UI: + case GL_RGBA32I: + case GL_RGBA16I: + case GL_RGBA8I: + case GL_RG32I: + case GL_RG16I: + case GL_RG8I: + case GL_R32I: + case GL_R16I: + case GL_R8I: + case GL_RGBA16: + case GL_RGB10_A2: + case GL_RGBA8: + case GL_RG16: + case GL_RG8: + case GL_R16: + case GL_R8: + case GL_RGBA16_SNORM: + case GL_RGBA8_SNORM: + case GL_RG16_SNORM: + case GL_RG8_SNORM: + case GL_R16_SNORM: + case GL_R8_SNORM: + return true; + default: + return false; + } + } + + GLuint GetAdvertisedImageUnitCount() { + return static_cast(std::min( + MG_Backend::pActiveBackendObject->GetDynamicParameters().MaxImageUnits, + MG_State::GLState::TextureState::MAX_TEXTURE_IMAGE_UNITS)); + } + Uint ComputeFullMipmapLevelCount(const IntVec3& baseTexelSize) { Int maxDimension = std::max( baseTexelSize.x(), @@ -1752,6 +1805,11 @@ namespace MobileGL::MG_Impl::GLImpl { textureObject->GetSamplerObject()->GetSamplerCompareFunc()); } break; + case GL_IMAGE_FORMAT_COMPATIBILITY_TYPE: + if (params) { + *params = GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE; + } + break; default: MG_State::pGLContext->RecordError(ErrorCode::InvalidEnum, MakeUnique("MG_Impl/GLImpl", "GetTexParameteriv_State", @@ -3102,7 +3160,7 @@ namespace MobileGL::MG_Impl::GLImpl { void BindImageTexture(GLuint unit, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access, GLenum format) { - if (unit >= MG_State::GLState::TextureState::MAX_TEXTURE_IMAGE_UNITS) { + if (unit >= GetAdvertisedImageUnitCount()) { MG_State::pGLContext->RecordError( ErrorCode::InvalidValue, MakeUnique("MG_Impl/GLImpl", __func__, "Image texture unit is out of range.")); @@ -3126,6 +3184,12 @@ namespace MobileGL::MG_Impl::GLImpl { MakeUnique("MG_Impl/GLImpl", __func__, "Invalid image texture access.")); return; } + if (!IsValidImageTextureFormat(format)) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidValue, + MakeUnique("MG_Impl/GLImpl", __func__, "Invalid image texture format.")); + return; + } SharedPtr textureObject; if (texture != 0) { diff --git a/MobileGL/MG_State/GLState/ProgramState/ProgramObject.cpp b/MobileGL/MG_State/GLState/ProgramState/ProgramObject.cpp index 367953ec..ed89d523 100644 --- a/MobileGL/MG_State/GLState/ProgramState/ProgramObject.cpp +++ b/MobileGL/MG_State/GLState/ProgramState/ProgramObject.cpp @@ -321,12 +321,16 @@ namespace MobileGL::MG_State::GLState { // ------------ Uniforms (GL Plain) ---------------- // Allocate uniform locations m_activeUniformCount = m_program->getNumUniformVariables(); + Int requiredUniformLocations = 0; MGLOG_D("ProgramObject %u: Reflection - active uniform count = %d", m_externalIndex, m_activeUniformCount); for (int i = 0; i < m_activeUniformCount; i++) { auto& uniform = m_program->getUniform(i); auto location = uniform.layoutLocation(); + const Int locationSpan = + (uniform.getType() && uniform.getType()->isOpaque()) ? std::max(1, uniform.size) : 1; + requiredUniformLocations += locationSpan; if (location != glslang::TQualifier::layoutLocationEnd) { - m_maxUniformLocation = std::max(m_maxUniformLocation, location); + m_maxUniformLocation = std::max(m_maxUniformLocation, location + locationSpan - 1); } m_uniformNameMaxLength = std::max(m_uniformNameMaxLength, (Int)uniform.name.length()); m_uniformLocations[uniform.name] = location; @@ -337,13 +341,13 @@ namespace MobileGL::MG_State::GLState { MGLOG_D("ProgramObject %u: Reflection - computed m_maxUniformLocation=%u m_uniformNameMaxLength=%d", m_externalIndex, m_maxUniformLocation, m_uniformNameMaxLength); - if (m_maxUniformLocation + 1 < m_activeUniformCount) { - MGLOG_D("ProgramObject %u: Reflection - maxUniformLocation+1 (%u) < activeUniformCount (%d), " + if (m_maxUniformLocation + 1 < requiredUniformLocations) { + MGLOG_D("ProgramObject %u: Reflection - maxUniformLocation+1 (%u) < requiredUniformLocations (%d), " "adjusting", - m_externalIndex, m_maxUniformLocation + 1, m_activeUniformCount); + m_externalIndex, m_maxUniformLocation + 1, requiredUniformLocations); // This means we have fewer than enough gaps to fit // unallocated uniforms - m_maxUniformLocation = m_activeUniformCount; + m_maxUniformLocation = requiredUniformLocations - 1; } // i-th elements refers to uniform at layout(location = i, ...) @@ -362,9 +366,14 @@ namespace MobileGL::MG_State::GLState { m_externalIndex, uniform.name.c_str()); continue; // will allocate unallocated uniforms later } - m_uniformIndexInTProgram[location] = i; - MGLOG_D("ProgramObject %u: Reflection - assigned uniform '%s' to location %d (indexInTProgram=%d)", - m_externalIndex, uniform.name.c_str(), location, i); + const Int locationSpan = + (uniform.getType() && uniform.getType()->isOpaque()) ? std::max(1, uniform.size) : 1; + for (Int element = 0; element < locationSpan; ++element) { + m_uniformIndexInTProgram[location + element] = i; + } + MGLOG_D("ProgramObject %u: Reflection - assigned uniform '%s' to locations %d..%d " + "(indexInTProgram=%d)", + m_externalIndex, uniform.name.c_str(), location, location + locationSpan - 1, i); } SizeT locNeedle = 0; @@ -375,15 +384,24 @@ namespace MobileGL::MG_State::GLState { }); for (auto index : unallocatedUniformIndex) { auto& uniform = m_program->getUniform(index); + const Int locationSpan = + (uniform.getType() && uniform.getType()->isOpaque()) ? std::max(1, uniform.size) : 1; for (; locNeedle <= m_maxUniformLocation; locNeedle++) { - if (m_uniformIndexInTProgram[locNeedle] != glslang::TQualifier::layoutLocationEnd) continue; + bool hasRoom = locNeedle + locationSpan - 1 <= m_maxUniformLocation; + for (Int element = 0; hasRoom && element < locationSpan; ++element) { + hasRoom = m_uniformIndexInTProgram[locNeedle + element] == + glslang::TQualifier::layoutLocationEnd; + } + if (!hasRoom) continue; // Found a vacant location at locNeedle - m_uniformIndexInTProgram[locNeedle] = index; + for (Int element = 0; element < locationSpan; ++element) { + m_uniformIndexInTProgram[locNeedle + element] = index; + } m_uniformLocations[uniform.name] = locNeedle; - MGLOG_D("ProgramObject %u: Reflection - assigned unallocated uniform '%s' to location %zu " + MGLOG_D("ProgramObject %u: Reflection - assigned unallocated uniform '%s' to locations %zu..%zu " "(index %d)", - m_externalIndex, uniform.name.c_str(), locNeedle, index); - locNeedle++; + m_externalIndex, uniform.name.c_str(), locNeedle, locNeedle + locationSpan - 1, index); + locNeedle += locationSpan; break; } } @@ -404,9 +422,14 @@ namespace MobileGL::MG_State::GLState { const auto explicitBinding = m_explicitOpaqueUniformBindings.find(uniform.name); const int initialUnit = explicitBinding != m_explicitOpaqueUniformBindings.end() ? static_cast(explicitBinding->second) : 0; - m_uniformSamplerOrImageUnitIndex[location] = initialUnit; - MGLOG_D("ProgramObject %u: Reflection - opaque uniform '%s' location=%u initialUnit=%d", - m_externalIndex, uniform.name.c_str(), location, initialUnit); + const Int locationSpan = std::max(1, uniform.size); + for (Int element = 0; element < locationSpan && + location + element < m_uniformSamplerOrImageUnitIndex.size(); ++element) { + m_uniformSamplerOrImageUnitIndex[location + element] = + initialUnit + (explicitBinding != m_explicitOpaqueUniformBindings.end() ? element : 0); + } + MGLOG_D("ProgramObject %u: Reflection - opaque uniform '%s' locations=%u..%u initialUnit=%d", + m_externalIndex, uniform.name.c_str(), location, location + locationSpan - 1, initialUnit); } // ------------ attributes (vertex in) ---------------