[Feat] (MG_State/Program): BindAttribLocation WIP

This commit is contained in:
2025-08-16 22:50:46 +08:00
parent e50d4bb19c
commit d6620959b3
4 changed files with 69 additions and 2 deletions
+21 -1
View File
@@ -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<GenericErrorInfo>("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<GenericErrorInfo>("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) {
@@ -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();
@@ -14,6 +14,9 @@ namespace MobileGL {
SizeT DetachShader(SharedPtr<ShaderObject> shader);
void Link();
void MarkAsDeleted();
void SetExplicitAttribLocation(Uint index, const char* name);
Vector<SharedPtr<ShaderObject>>& GetAttachedShaders();
const String& GetInfoLog() const { return m_infoLog; }
Int GetUniformMaxLength() const { return m_uniformNameMaxLength; }
@@ -48,11 +51,18 @@ namespace MobileGL {
SharedPtr<glslang::TProgram> m_program;
// Attributes
UnorderedMap<String, Uint> m_explicitAttribLocations;
Vector<String> m_attribs;
// Uniforms
// MG_Util::ShaderTranspiler::SpvcMetadata m_metadata;
UnorderedMap<String, Uint> m_uniformLocations;
// Ordered by location,
// aka. m_uniformNames[loc] == "name at location `loc`"
Vector<String> m_uniformNames;
// ditto.
Vector<GLenum> m_uniformTypes;
// Need to be reflected after linking of SPIR-V binary
+2 -1
View File
@@ -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;
})";