From d6620959b3a2f6626a60efee2620194c65ed36ba Mon Sep 17 00:00:00 2001 From: Swung0x48 Date: Sat, 16 Aug 2025 01:10:04 +0800 Subject: [PATCH] [Feat] (MG_State/Program): BindAttribLocation WIP --- .../MG_Impl/GLImpl/Program/GL_Program.cpp | 22 +++++++++++- .../GLState/ProgramState/ProgramObject.cpp | 36 +++++++++++++++++++ .../GLState/ProgramState/ProgramObject.h | 10 ++++++ MobileGL/MG_Test/Program/ProgramTest.cpp | 3 +- 4 files changed, 69 insertions(+), 2 deletions(-) diff --git a/MobileGL/MG_Impl/GLImpl/Program/GL_Program.cpp b/MobileGL/MG_Impl/GLImpl/Program/GL_Program.cpp index a8ba513c..1ec29ee4 100644 --- a/MobileGL/MG_Impl/GLImpl/Program/GL_Program.cpp +++ b/MobileGL/MG_Impl/GLImpl/Program/GL_Program.cpp @@ -85,7 +85,27 @@ namespace MobileGL { } void BindAttribLocation_State(GLuint program, GLuint index, const GLchar* name) { - THROW_UNIMPL_EXCEPTION; + if (index >= MG_State::GLState::VertexArrayObject::MAX_VERTEX_ATTRIBS) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidValue, + MakeShared("MG_Impl/GLImpl", __func__, + "`index` is greater than or equal to `GL_MAX_VERTEX_ATTRIBS`.")); + return; + } + + if (strncmp(name, "gl_", 3) == 0) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidOperation, + MakeShared("MG_Impl/GLImpl", __func__, + "`name` starts with the reserved prefix `gl_`.")); + return; + } + + auto programObject = TryToGetProgramObject(program); + if (!programObject) + return; + + programObject->SetExplicitAttribLocation(index, name); } void CompileShader_State(GLuint shader) { diff --git a/MobileGL/MG_State/GLState/ProgramState/ProgramObject.cpp b/MobileGL/MG_State/GLState/ProgramState/ProgramObject.cpp index f4534ed4..f38d2885 100644 --- a/MobileGL/MG_State/GLState/ProgramState/ProgramObject.cpp +++ b/MobileGL/MG_State/GLState/ProgramState/ProgramObject.cpp @@ -89,12 +89,44 @@ namespace MobileGL { m_uniformTypes[location] = uniform.glDefineType; } + // attributes (pipe in) int inCount = m_program->getNumPipeInputs(); + m_attribs.resize(inCount); + + // Parse explicit location in shader for (int i = 0; i < inCount; i++) { auto& inVar = m_program->getPipeInput(i); + auto location = inVar.layoutLocation(); m_attribInNameMaxLength = std::max(m_attribInNameMaxLength, (Int)inVar.name.length()); + // TODO: how to parse location specified in shader? + } + // Place explicitly set locations + for (int i = 0; i < inCount; i++) { + auto& inVar = m_program->getPipeInput(i); + + auto it = m_explicitAttribLocations.find(inVar.name); + if (it != m_explicitAttribLocations.end()) { + m_attribs[it->second] = inVar.name; + } + } + // Place yet placed attributes + int nextAvailLoc = 0; + for (int i = 0; i < inCount; i++) { + auto& inVar = m_program->getPipeInput(i); + auto it = m_explicitAttribLocations.find(inVar.name); + if (it != m_explicitAttribLocations.end()) { + continue; + } + while (nextAvailLoc < inCount && !m_attribs[nextAvailLoc].empty()) + ++nextAvailLoc; + + assert(nextAvailLoc < inCount); + + m_attribs[nextAvailLoc] = inVar.name; } + + // UBO int uboCount = m_program->getNumUniformBlocks(); for (int i = 0; i < uboCount; i++) { auto& ubo = m_program->getUniformBlock(i); @@ -102,6 +134,10 @@ namespace MobileGL { } } + void ProgramObject::SetExplicitAttribLocation(Uint index, const char *name) { + m_explicitAttribLocations[name] = index; + } + // void ProgramObject::PreLink() { // m_uniforms.clear(); // m_uniformOffsets.clear(); diff --git a/MobileGL/MG_State/GLState/ProgramState/ProgramObject.h b/MobileGL/MG_State/GLState/ProgramState/ProgramObject.h index 76a65543..9947c633 100644 --- a/MobileGL/MG_State/GLState/ProgramState/ProgramObject.h +++ b/MobileGL/MG_State/GLState/ProgramState/ProgramObject.h @@ -14,6 +14,9 @@ namespace MobileGL { SizeT DetachShader(SharedPtr shader); void Link(); void MarkAsDeleted(); + + void SetExplicitAttribLocation(Uint index, const char* name); + Vector>& GetAttachedShaders(); const String& GetInfoLog() const { return m_infoLog; } Int GetUniformMaxLength() const { return m_uniformNameMaxLength; } @@ -48,11 +51,18 @@ namespace MobileGL { SharedPtr m_program; + // Attributes + UnorderedMap m_explicitAttribLocations; + Vector m_attribs; + // Uniforms // MG_Util::ShaderTranspiler::SpvcMetadata m_metadata; UnorderedMap m_uniformLocations; + // Ordered by location, + // aka. m_uniformNames[loc] == "name at location `loc`" Vector m_uniformNames; + // ditto. Vector m_uniformTypes; // Need to be reflected after linking of SPIR-V binary diff --git a/MobileGL/MG_Test/Program/ProgramTest.cpp b/MobileGL/MG_Test/Program/ProgramTest.cpp index 6e0cd42a..95118920 100644 --- a/MobileGL/MG_Test/Program/ProgramTest.cpp +++ b/MobileGL/MG_Test/Program/ProgramTest.cpp @@ -24,6 +24,7 @@ TEST_F(ProgramTest, Sanity) { const char* vsSrc = R"(#version 460 in vec4 Position; +in float fIn; layout(location = 0) uniform mat4 ProjMat; uniform vec2 InSize; @@ -36,7 +37,7 @@ void main(){ vec4 outPos = ProjMat * vec4(Position.xy, 0.0, 1.0); gl_Position = vec4(outPos.xy, 0.2, 1.0); - oneTexel = 1.0 / InSize; + oneTexel = (1.0 * fIn) / InSize; texCoord = Position.xy / OutSize; })";