[Feat]: implement glBindVertexAttribLocation in DirectGLES backend (fixing OptiFine?)

This commit is contained in:
2025-11-04 22:16:16 +08:00
parent 2f67620a6e
commit 57dd0fe480
6 changed files with 66 additions and 4 deletions
@@ -501,6 +501,9 @@ namespace MobileGL::MG_Backend::DirectGLES {
auto& spirvCode = shaderSpirvs[index];
MG_Util::ShaderTranspiler::SpvcSession spvcSession(spirvCode);
if (glShaderType == GL_VERTEX_SHADER) {
spvcSession.SetVertexAttribLocation(stateProgramObject->GetAttribLocationMap());
}
spvc_compiler_options options;
spvcSession.CreateOptions(&options);
@@ -195,6 +195,10 @@ namespace MobileGL {
std::swap(m_attribs[location], m_attribs[idx]);
std::swap(m_attribTypes[location], m_attribTypes[idx]);
}
for (SizeT idx = 0; idx < m_attribs.size(); ++idx) {
m_attribLocation[m_attribs[idx]] = idx;
}
}
// ---------- UBO ----------
@@ -207,7 +211,6 @@ namespace MobileGL {
m_uniformBlockIndex[ubo.name] = ubo.getBinding();
m_uniformBlockIndexInTProgram[ubo.getBinding()] = i;
}
}
void ProgramObject::GenerateBinary() {
@@ -244,7 +247,9 @@ namespace MobileGL {
assert(binaryResult);
m_generatedSpirv = Move(binaryResult.value());
for (auto spv : m_generatedSpirv) {
for (SizeT i = 0; i < m_generatedSpirv.size(); i++) {
auto& spv = m_generatedSpirv[i];
auto shaderType = shaderTypes[i];
SpvcSession session(spv);
auto result = session.ParseMetaData();
if (result < 0) {
@@ -108,6 +108,8 @@ namespace MobileGL {
Uint GetExternalIndex() const { return m_externalIndex; }
const UnorderedMap<String, Uint>& GetAttribLocationMap() const { return m_attribLocation; }
private:
void DoReflection();
void GenerateBinary();
@@ -124,6 +126,8 @@ namespace MobileGL {
UnorderedMap<String, Uint> m_explicitAttribLocations;
Vector<String> m_attribs;
Vector<GLenum> m_attribTypes;
// For SpvcSession::SetVertexAttribLocation()
UnorderedMap<String, Uint> m_attribLocation;
// Uniforms
UnorderedMap<String, Uint> m_uniformLocations;
+32 -2
View File
@@ -19,7 +19,7 @@ TEST_F(ProgramTest, Sanity) {
const char* vsSrc = R"(#version 460
layout (location = 0) in vec4 Position;
layout (location = 2) in vec4 Position;
in float fIn4;
in float fIn2;
in float fIn5;
@@ -146,7 +146,7 @@ TEST_F(ProgramTest, CompileAndLink) {
GetProgramiv(program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &uniformNameMaxLength);
ASSERT_EQ(uniformNameMaxLength, 12);
ASSERT_EQ(GetAttribLocation(program, "Position"), 0);
ASSERT_EQ(GetAttribLocation(program, "Position"), 2);
ASSERT_EQ(GetAttribLocation(program, "fIn1"), 1);
ASSERT_EQ(GetAttribLocation(program, "fIn3"), 3);
ASSERT_EQ(GetAttribLocation(program, "fIn5"), 5);
@@ -169,6 +169,36 @@ TEST_F(ProgramTest, CompileAndLink) {
int intVal;
GetUniformiv(program, locInt, &intVal);
EXPECT_EQ(intVal, 114514);
auto programObj = MG_State::pGLContext->GetProgramObject(program);
auto& shaderSpirvs = programObj->GetGeneratedSpirv();
for (int index = 0; index < shaderSpirvs.size(); ++index) {
String source;
auto& spirvCode = shaderSpirvs[index];
MG_Util::ShaderTranspiler::SpvcSession spvcSession(spirvCode);
spvc_compiler_options options;
spvcSession.CreateOptions(&options);
spvc_compiler_options_set_uint(options, SPVC_COMPILER_OPTION_GLSL_VERSION, 320);
spvc_compiler_options_set_bool(options, SPVC_COMPILER_OPTION_GLSL_ES, SPVC_TRUE);
spvc_compiler_options_set_bool(options, SPVC_COMPILER_OPTION_GLSL_VULKAN_SEMANTICS, SPVC_FALSE);
spvcSession.SetOptions(options);
const char* result = nullptr;
spvcSession.Compile(&result);
if (!result) {
MG_Util::ShaderTranspiler::ResultInfo r;
r.log += "Failed to compile the shader to GLSL: \n";
r.log += spvcSession.GetLastErrorString();
r.errc = -5;
FAIL() << r.log;
}
printf("shader dump: \n%s\n", result);
}
}
TEST_F(ProgramTest, UniformMatrixFunctions) {
@@ -60,6 +60,25 @@ namespace MobileGL {
return variables;
}
spvc_result SpvcSession::SetVertexAttribLocation(const UnorderedMap<String, Uint>& location) {
// TODO: We should assert we're really dealing with vertex shader here
SPVC_CHK_INIT
const spvc_reflected_resource *list = nullptr;
size_t count = 0;
SPVC_CHK_RESULT(spvc_resources_get_resource_list_for_type(resources, SPVC_RESOURCE_TYPE_STAGE_INPUT, &list, &count));
for (size_t i = 0; i < count; ++i) {
auto& resource = list[i];
auto it = location.find(resource.name);
if (it != location.end()) {
// realize glBindVertexAttribLocation here
// it->second should be the location explicitly requested
spvc_compiler_set_decoration(compiler, resource.id, SpvDecorationLocation, it->second);
}
}
SPVC_CHK_RETURN
}
spvc_result SpvcSession::Compile(const char** result) {
SPVC_CHK_INIT
SPVC_CHK_RESULT(spvc_compiler_compile(compiler, result));
@@ -73,6 +73,7 @@ namespace MobileGL {
spvc_result CreateOptions(spvc_compiler_options* options);
spvc_result SetOptions(spvc_compiler_options options);
Vector<InterfaceVariable> GetShaderInterface(spvc_resource_type resource_type) const;
spvc_result SetVertexAttribLocation(const UnorderedMap<String, Uint>& location);
spvc_result Compile(const char** result);
const SpvcMetadata& GetMetadata() const;
const char* GetLastErrorString() const;