From 24162255023a05726d19cf31bb2bfc257f81a539 Mon Sep 17 00:00:00 2001 From: Swung0x48 Date: Wed, 29 Oct 2025 10:28:59 +0800 Subject: [PATCH] [Fix] (MG_State/ProgramState): select correct binary to do reflection --- .../GLState/ProgramState/ProgramObject.cpp | 46 ++++--- MobileGL/MG_Test/Program/ProgramTest.cpp | 125 ++++++++++++++++++ .../MG_Util/ShaderTranspiler/SpvcSession.cpp | 7 +- .../MG_Util/ShaderTranspiler/SpvcSession.h | 2 +- 4 files changed, 158 insertions(+), 22 deletions(-) diff --git a/MobileGL/MG_State/GLState/ProgramState/ProgramObject.cpp b/MobileGL/MG_State/GLState/ProgramState/ProgramObject.cpp index d9dff9da..2a970564 100644 --- a/MobileGL/MG_State/GLState/ProgramState/ProgramObject.cpp +++ b/MobileGL/MG_State/GLState/ProgramState/ProgramObject.cpp @@ -244,27 +244,35 @@ namespace MobileGL { assert(binaryResult); m_generatedSpirv = Move(binaryResult.value()); - SpvcSession session(m_generatedSpirv[0]); - auto srcResult = ShaderCompiler::DecompileShader(session); - assert(srcResult); - // auto src = srcResult.value(); - // printf("decompiled src: \n%s\n", src.c_str()); + for (auto spv: m_generatedSpirv) { + SpvcSession session(spv); + auto result = session.ParseMetaData(); + if (result < 0) { + continue; + } + // auto srcResult = ShaderCompiler::DecompileShader(session); + // assert(srcResult); + // auto src = srcResult.value(); + // printf("decompiled src: \n%s\n", src.c_str()); - auto& meta = session.GetMetadata(); - auto size = meta.uboSize; - m_uboScratch.resize(size); - m_uniformOffsets.resize(m_maxUniformLocation + 1); - for (const auto& [name, offset] : meta.plainUniformOffsetsInUBO) { - if (m_uniformLocations.find(name) != m_uniformLocations.end()) - m_uniformOffsets[m_uniformLocations[name]] = offset; + + auto& meta = session.GetMetadata(); + auto size = meta.uboSize; + m_uboScratch.resize(size); + m_uniformOffsets.resize(m_maxUniformLocation + 1); + for (const auto& [name, offset] : meta.plainUniformOffsetsInUBO) { + if (m_uniformLocations.find(name) != m_uniformLocations.end()) + m_uniformOffsets[m_uniformLocations[name]] = offset; + } + m_uniformSizesInBytes.resize(m_maxUniformLocation + 1); + for (const auto& [name, size] : meta.plainUniformMemberSizesInBytes) { + if (m_uniformLocations.find(name) != m_uniformLocations.end()) + m_uniformSizesInBytes[m_uniformLocations[name]] = size; + } + // assert(m_uniformOffsets.size() == GetUniformCount()); + // assert(m_uniformSizesInBytes.size() == GetUniformCount()); + break; } - m_uniformSizesInBytes.resize(m_maxUniformLocation + 1); - for (const auto& [name, size] : meta.plainUniformMemberSizesInBytes) { - if (m_uniformLocations.find(name) != m_uniformLocations.end()) - m_uniformSizesInBytes[m_uniformLocations[name]] = size; - } - // assert(m_uniformOffsets.size() == GetUniformCount()); - // assert(m_uniformSizesInBytes.size() == GetUniformCount()); } void ProgramObject::WaitUntilGenerationCompleted() {} diff --git a/MobileGL/MG_Test/Program/ProgramTest.cpp b/MobileGL/MG_Test/Program/ProgramTest.cpp index f5e20e65..afc9141a 100644 --- a/MobileGL/MG_Test/Program/ProgramTest.cpp +++ b/MobileGL/MG_Test/Program/ProgramTest.cpp @@ -564,3 +564,128 @@ TEST_F(ProgramTest, MinecraftPositionTex) { ASSERT_GE(sampler0Loc, 0); ASSERT_LT(sampler0Loc, 4000); } + +const char* minecraft_core_blit_screen_vs = R"(#version 150 + +in vec3 Position; + +out vec2 texCoord; + +void main() { + vec2 screenPos = Position.xy * 2.0 - 1.0; + gl_Position = vec4(screenPos.x, screenPos.y, 1.0, 1.0); + texCoord = Position.xy; +} + +)"; + +const char* minecraft_core_lightmap = R"(#version 150 + +uniform float AmbientLightFactor; +uniform float SkyFactor; +uniform float BlockFactor; +uniform int UseBrightLightmap; +uniform vec3 SkyLightColor; +uniform float NightVisionFactor; +uniform float DarknessScale; +uniform float DarkenWorldFactor; +uniform float BrightnessFactor; + +in vec2 texCoord; + +out vec4 fragColor; + +float get_brightness(float level) { + float curved_level = level / (4.0 - 3.0 * level); + return mix(curved_level, 1.0, AmbientLightFactor); +} + +vec3 notGamma(vec3 x) { + vec3 nx = 1.0 - x; + return 1.0 - nx * nx * nx * nx; +} + +void main() { + float block_brightness = get_brightness(floor(texCoord.x * 16) / 15) * BlockFactor; + float sky_brightness = get_brightness(floor(texCoord.y * 16) / 15) * SkyFactor; + + // cubic nonsense, dips to yellowish in the middle, white when fully saturated + vec3 color = vec3( + block_brightness, + block_brightness * ((block_brightness * 0.6 + 0.4) * 0.6 + 0.4), + block_brightness * (block_brightness * block_brightness * 0.6 + 0.4) + ); + + if (UseBrightLightmap != 0) { + color = mix(color, vec3(0.99, 1.12, 1.0), 0.25); + color = clamp(color, 0.0, 1.0); + } else { + color += SkyLightColor * sky_brightness; + color = mix(color, vec3(0.75), 0.04); + + vec3 darkened_color = color * vec3(0.7, 0.6, 0.6); + color = mix(color, darkened_color, DarkenWorldFactor); + } + + if (NightVisionFactor > 0.0) { + // scale up uniformly until 1.0 is hit by one of the colors + float max_component = max(color.r, max(color.g, color.b)); + if (max_component < 1.0) { + vec3 bright_color = color / max_component; + color = mix(color, bright_color, NightVisionFactor); + } + } + + if (UseBrightLightmap == 0) { + color = clamp(color - vec3(DarknessScale), 0.0, 1.0); + } + + vec3 notGamma = notGamma(color); + color = mix(color, notGamma, BrightnessFactor); + color = mix(color, vec3(0.75), 0.04); + color = clamp(color, 0.0, 1.0); + + fragColor = vec4(color, 1.0); +} + +)"; + +TEST_F(ProgramTest, MinecraftBlitScreenLightmap) { + char infoLog[1024] = ""; + + GLuint vs = CreateShader(GL_VERTEX_SHADER); + ShaderSource(vs, 1, &minecraft_core_blit_screen_vs, NULL); + CompileShader(vs); + GLint vsStatus = GL_FALSE; + GetShaderiv(vs, GL_COMPILE_STATUS, &vsStatus); + GetShaderInfoLog(vs, 1024, nullptr, infoLog); + ASSERT_EQ(vsStatus, GL_TRUE) << infoLog; + + GLuint fs = CreateShader(GL_FRAGMENT_SHADER); + ShaderSource(fs, 1, &minecraft_core_lightmap, NULL); + CompileShader(fs); + GLint fsStatus = GL_FALSE; + GetShaderiv(fs, GL_COMPILE_STATUS, &fsStatus); + GetShaderInfoLog(fs, 1024, nullptr, infoLog); + ASSERT_EQ(fsStatus, GL_TRUE) << infoLog; + + GLuint program = CreateProgram(); + AttachShader(program, vs); + AttachShader(program, fs); + + LinkProgram(program); + + UseProgram(program); + + int uniformCount = 0; + GetProgramiv(program, GL_ACTIVE_UNIFORMS, &uniformCount); + ASSERT_LT(uniformCount, 4000); + + int loc = GetUniformLocation(program, "AmbientLightFactor"); + ASSERT_GE(loc, 0); + ASSERT_LT(loc, 4000); + + auto programObject = MG_State::pGLContext->GetCurrentProgram(); + ASSERT_GT(programObject->GetUBOSize(), 0); +} + diff --git a/MobileGL/MG_Util/ShaderTranspiler/SpvcSession.cpp b/MobileGL/MG_Util/ShaderTranspiler/SpvcSession.cpp index d14c2b85..a02604f7 100644 --- a/MobileGL/MG_Util/ShaderTranspiler/SpvcSession.cpp +++ b/MobileGL/MG_Util/ShaderTranspiler/SpvcSession.cpp @@ -63,7 +63,7 @@ namespace MobileGL { spvc_result SpvcSession::Compile(const char** result) { SPVC_CHK_INIT SPVC_CHK_RESULT(spvc_compiler_compile(compiler, result)); - SPVC_CHK_RESULT(ParseMetaData()); + // SPVC_CHK_RESULT(ParseMetaData()); SPVC_CHK_RETURN } @@ -109,9 +109,12 @@ namespace MobileGL { .matCol = matCol, }; } + SPVC_CHK_RETURN } } - SPVC_CHK_RETURN + // This means this spv binary does not have + // auto-generated UBO in it + return SPVC_ERROR_INVALID_SPIRV; } const SpvcMetadata& SpvcSession::GetMetadata() const { diff --git a/MobileGL/MG_Util/ShaderTranspiler/SpvcSession.h b/MobileGL/MG_Util/ShaderTranspiler/SpvcSession.h index a72d5ba8..b0fbb246 100644 --- a/MobileGL/MG_Util/ShaderTranspiler/SpvcSession.h +++ b/MobileGL/MG_Util/ShaderTranspiler/SpvcSession.h @@ -77,9 +77,9 @@ namespace MobileGL { const SpvcMetadata& GetMetadata() const; const char* GetLastErrorString() const; - private: // Should be called once, and only once, for every SPIR-V binary spvc_result ParseMetaData(); + private: spvc_context context = nullptr; spvc_parsed_ir ir = nullptr;