diff --git a/MobileGL/MG_Impl/GLImpl/Program/GL_Program.cpp b/MobileGL/MG_Impl/GLImpl/Program/GL_Program.cpp index 3e1f3fe8..b33c49eb 100644 --- a/MobileGL/MG_Impl/GLImpl/Program/GL_Program.cpp +++ b/MobileGL/MG_Impl/GLImpl/Program/GL_Program.cpp @@ -383,12 +383,43 @@ namespace MobileGL { return programObject->GetUniformLocation(name); } + void GetUniform_State(GLuint program, GLint location, void* params) { + auto programObject = TryToGetProgramObject(program); + if (!programObject) + return; + + if (!programObject->GetLinkStatus()) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidOperation, + MakeShared("MG_Impl/GLImpl", __func__, + "`program` has not been successfully linked.")); + return; + } + + if (location >= programObject->GetUniformCount() || programObject->GetUniformName(location).empty()) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidOperation, + MakeShared("MG_Impl/GLImpl", __func__, + "`location` does not correspond to a valid uniform variable location for the specified program object.")); + return; + } + auto isOpaque = programObject->IsUniformOpaqueAtLocation(location); + if (!isOpaque) { + // TODO: probably handle int/float differences + auto offset = programObject->GetUniformOffset(location); + auto size = programObject->GetUniformSizesInBytes(location); + char* pUBO = (char*)programObject->MapUBO(); + memcpy(params, pUBO + offset, size); + } + // TODO: handle 1i variant as texture unit + } + void GetUniformfv_State(GLuint program, GLint location, GLfloat* params) { - THROW_UNIMPL_EXCEPTION; + GetUniform_State(program, location, params); } void GetUniformiv_State(GLuint program, GLint location, GLint* params) { - THROW_UNIMPL_EXCEPTION; + GetUniform_State(program, location, params); } GLboolean IsProgram_State(GLuint program) { @@ -447,6 +478,7 @@ namespace MobileGL { } void Uniform1fv_State(GLint location, GLsizei count, const GLfloat* value) { + THROW_UNIMPL_EXCEPTION; } diff --git a/MobileGL/MG_State/GLState/Core.cpp b/MobileGL/MG_State/GLState/Core.cpp index 57f35fad..a00fe537 100644 --- a/MobileGL/MG_State/GLState/Core.cpp +++ b/MobileGL/MG_State/GLState/Core.cpp @@ -191,6 +191,10 @@ namespace MobileGL { void GLContext::UseProgram(Uint program) { return m_programState.UseProgram(program); } + + SharedPtr GLContext::GetCurrentProgram() { + return m_programState.GetCurrentProgram(); + } } // namespace GLState GLState::GLContext* pGLContext; diff --git a/MobileGL/MG_State/GLState/Core.h b/MobileGL/MG_State/GLState/Core.h index 3efc751b..25ccea97 100644 --- a/MobileGL/MG_State/GLState/Core.h +++ b/MobileGL/MG_State/GLState/Core.h @@ -64,7 +64,7 @@ namespace MobileGL { SharedPtr GetProgramObject(Uint index); SharedPtr GetShaderObject(Uint index); void UseProgram(Uint program); - + SharedPtr GetCurrentProgram(); private: // Error ErrorState m_errorState; diff --git a/MobileGL/MG_State/GLState/ProgramState/ProgramObject.cpp b/MobileGL/MG_State/GLState/ProgramState/ProgramObject.cpp index 7bbd4c94..d1da8fef 100644 --- a/MobileGL/MG_State/GLState/ProgramState/ProgramObject.cpp +++ b/MobileGL/MG_State/GLState/ProgramState/ProgramObject.cpp @@ -81,13 +81,17 @@ namespace MobileGL { m_uniformNames.resize(m_maxUniformLocation + 1); m_uniformTypes.resize(m_maxUniformLocation + 1); + m_uniformIsOpaqueType.resize(m_maxUniformLocation + 1); m_uniformOffsets.resize(m_maxUniformLocation + 1); + m_uniformArraySizes.resize(m_maxUniformLocation + 1); for (int i = 0; i < uniformCount; i++) { auto& uniform = m_program->getUniform(i); auto location = uniform.layoutLocation(); m_uniformNames[location] = uniform.name; m_uniformTypes[location] = uniform.glDefineType; + m_uniformIsOpaqueType[location] = uniform.getType()->isOpaque(); + m_uniformArraySizes[location] = uniform.size; } // attributes (pipe in) @@ -159,7 +163,12 @@ namespace MobileGL { auto binaryResult = ShaderCompiler::GetSpirvBinaryFromProgram(binaryAttrib); assert(binaryResult); m_generatedSpirv = Move(binaryResult.value()); + SpvcSession session(m_generatedSpirv[0]); + auto srcResult = ShaderCompiler::DecompileShader(session); + assert(srcResult); + auto src = srcResult.value(); + auto& meta = session.GetMetadata(); auto size = meta.uboSize; m_uboScratch.resize(size); @@ -167,11 +176,12 @@ namespace MobileGL { for (const auto& [name, offset] : meta.plainUniformOffsetsInUBO) { m_uniformOffsets[m_uniformLocations[name]] = offset; } - - auto srcResult = ShaderCompiler::DecompileShader(session); - assert(srcResult); - auto src = srcResult.value(); - printf("decompiled src: \n%s", src.c_str()); + m_uniformSizesInBytes.resize(meta.plainUniformMemberSizesInBytes.size()); + for (const auto& [name, size] : meta.plainUniformMemberSizesInBytes) { + m_uniformSizesInBytes[m_uniformLocations[name]] = size; + } + assert(m_uniformOffsets.size() == GetUniformCount()); + assert(m_uniformSizesInBytes.size() == GetUniformCount()); } void ProgramObject::WaitUntilGenerationCompleted() { diff --git a/MobileGL/MG_State/GLState/ProgramState/ProgramObject.h b/MobileGL/MG_State/GLState/ProgramState/ProgramObject.h index 5357d166..dec3b366 100644 --- a/MobileGL/MG_State/GLState/ProgramState/ProgramObject.h +++ b/MobileGL/MG_State/GLState/ProgramState/ProgramObject.h @@ -23,15 +23,25 @@ namespace MobileGL { Uint GetUniformCount() { return m_uniformNames.size(); } Int GetUniformLocation(const String& name) { const auto it = m_uniformLocations.find(name); - return (it == m_uniformLocations.end()) ? -1 : it->second; + return (it == m_uniformLocations.end()) ? -1 : (Int)it->second; } GLenum GetUniformType(Uint index) const { return m_uniformTypes[index]; } + Bool IsUniformOpaqueAtLocation(Uint location) const { + return m_uniformIsOpaqueType[location]; + } + const String& GetUniformName(Uint index) const { return m_uniformNames[index]; } + Uint GetUniformOffset(Uint location) const { + return m_uniformOffsets[location]; + } + Uint GetUniformSizesInBytes(Uint location) const { + return m_uniformSizesInBytes[location]; + } Int GetAttributeLocation(const String& name) { const auto it = std::find(m_attribs.begin(), m_attribs.end(), name); @@ -43,6 +53,9 @@ namespace MobileGL { const String& GetAttribName(Uint index) const { return m_attribs[index]; } + void* MapUBO() { + return m_uboScratch.data(); + } Bool GetDeleteStatus() const { return m_deleteStatus; } Bool GetLinkStatus() const { return m_linkStatus; } @@ -80,9 +93,12 @@ namespace MobileGL { Vector m_uniformNames; // ditto. Vector m_uniformTypes; + Vector m_uniformIsOpaqueType; + Vector m_uniformArraySizes; // Need to be reflected after linking of SPIR-V binary Vector m_uniformOffsets; + Vector m_uniformSizesInBytes; Vector m_uboScratch; Uint m_maxUniformLocation = 0; diff --git a/MobileGL/MG_State/GLState/ProgramState/ProgramState.h b/MobileGL/MG_State/GLState/ProgramState/ProgramState.h index ff981cb1..068792f3 100644 --- a/MobileGL/MG_State/GLState/ProgramState/ProgramState.h +++ b/MobileGL/MG_State/GLState/ProgramState/ProgramState.h @@ -21,6 +21,10 @@ namespace MobileGL { SharedPtr GetShaderObject(Uint shader); void MarkShaderObjectForDeletion(Uint shader); Bool ValidateShaderObject(Uint shader) const; + + SharedPtr GetCurrentProgram() const { + return m_currentProgram; + } private: template static Bool CheckIndexAvail(const SizeT idx, const Vector& vec) {