[Fix] (MG_Impl/GLImpl, MG_State/GLState): fix frag data location queries [skip ci]

This commit is contained in:
2026-07-02 16:20:43 +08:00
parent 76f5a23b7f
commit b9de562491
5 changed files with 46 additions and 2 deletions
@@ -1200,6 +1200,19 @@ namespace MobileGL::MG_Impl::GLImpl {
std::to_string(program) + " is not the name of a program object."));
return -1;
}
if (name == nullptr) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidValue,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", __func__, "name cannot be null."));
return -1;
}
if (!programObject->GetLinkStatus()) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", __func__,
std::to_string(program) + " has not been linked successfully."));
return -1;
}
return programObject->GetFragmentDataLocation(name);
}
@@ -214,6 +214,7 @@ namespace MobileGL::MG_State::GLState {
if (result) {
m_linkStatus = true;
m_program = result.value();
m_linkedFragDataLocation = m_explicitFragDataLocation;
MGLOG_D("ProgramObject %u: LinkProgram succeeded, TProgram ptr %p", m_externalIndex, m_program.get());
} else {
m_infoLog = result.error().log;
@@ -592,12 +593,12 @@ namespace MobileGL::MG_State::GLState {
Int ProgramObject::GetFragmentDataLocation(const char* name) {
if (!m_program || !name) return -1;
const auto explicitLocation = m_explicitFragDataLocation.find(name);
const auto explicitLocation = m_linkedFragDataLocation.find(name);
const Int outputCount = m_program->getNumPipeOutputs();
for (Int index = 0; index < outputCount; ++index) {
const auto& output = m_program->getPipeOutput(index);
if (output.name != name) continue;
if (explicitLocation != m_explicitFragDataLocation.end()) return static_cast<Int>(explicitLocation->second);
if (explicitLocation != m_linkedFragDataLocation.end()) return static_cast<Int>(explicitLocation->second);
return static_cast<Int>(output.layoutLocation());
}
return -1;
@@ -257,6 +257,7 @@ namespace MobileGL::MG_State::GLState {
// FragData (Frag out)
UnorderedMap<String, Uint> m_explicitFragDataLocation;
UnorderedMap<String, Uint> m_linkedFragDataLocation;
// Uniforms
UnorderedMap<String, Uint> m_uniformLocations;
@@ -142,6 +142,30 @@ void main() {
EXPECT_EQ(source.find("#define"), String::npos);
}
TEST_F(ProgramUtilTest, PreprocessLegacyFragmentShaderModernizesFragData) {
using namespace MG_Util::ShaderTranspiler;
String source = R"(#version 130
void main() {
gl_FragData[0] = vec4(1.0);
gl_FragData[1].a = 0.5;
})";
PreprocessShaderSource(ShaderStage::Fragment, source);
EXPECT_EQ(source.find("#version 460 core\n"), 0);
EXPECT_NE(source.find("layout(location = 0) out vec4 mg_FragData[8];\n"), String::npos);
EXPECT_NE(source.find("mg_FragData[0] = vec4(1.0);"), String::npos);
EXPECT_NE(source.find("mg_FragData[1].a = 0.5;"), String::npos);
EXPECT_EQ(source.find("gl_FragData"), String::npos);
ShaderAttrib attrib{.shaderType = GL_FRAGMENT_SHADER, .sourceStr = source};
auto res = ShaderCompiler::CompileShader(attrib);
if (!res) {
FAIL() << "errc: " << res.error().errc << "\nlog: " << res.error().log << "\nsource:\n" << source;
}
}
TEST_F(ProgramUtilTest, PreprocessFragmentShaderInjectsDepthRangeShim) {
using namespace MG_Util::ShaderTranspiler;
@@ -286,10 +286,15 @@ namespace {
if (stage == MobileGL::ShaderStage::Fragment) {
ReplaceIdentifier(source, "varying", "in");
const bool usesFragColor = source.find("gl_FragColor") != MobileGL::String::npos;
const bool usesFragData = source.find("gl_FragData") != MobileGL::String::npos;
if (usesFragColor) {
ReplaceIdentifier(source, "gl_FragColor", "mg_FragColor");
source.insert(FindAfterVersionDirective(source), "out vec4 mg_FragColor;\n");
}
if (usesFragData) {
ReplaceIdentifier(source, "gl_FragData", "mg_FragData");
source.insert(FindAfterVersionDirective(source), "layout(location = 0) out vec4 mg_FragData[8];\n");
}
}
}