From d317f7f99b80716a6eef8f174ebd712ed67a6d0b Mon Sep 17 00:00:00 2001 From: Swung0x48 Date: Tue, 22 Jul 2025 13:03:06 +0800 Subject: [PATCH] [Chore] (MG_Util/Program): auto generate ubo for plain GL uniforms --- MobileGL/MG_Test/Program/ProgramTest.cpp | 62 ++----------------- .../ShaderTranspiler/ShaderCompiler.cpp | 5 +- MobileGL/MG_Util/ShaderTranspiler/Types.h | 43 ++++++++++++- 3 files changed, 49 insertions(+), 61 deletions(-) diff --git a/MobileGL/MG_Test/Program/ProgramTest.cpp b/MobileGL/MG_Test/Program/ProgramTest.cpp index f35bbd69..21d87417 100644 --- a/MobileGL/MG_Test/Program/ProgramTest.cpp +++ b/MobileGL/MG_Test/Program/ProgramTest.cpp @@ -10,56 +10,6 @@ class ProgramTest : public ::testing::Test { protected: }; -struct InterfaceVariable { - std::string name; - uint32_t location; - - bool operator<(const InterfaceVariable& other) const { - return location < other.location; - } - - bool operator==(const InterfaceVariable& other) const { - return location == other.location && name == other.name; - } -}; - -static std::vector GetShaderInterface(const std::vector& spirv, spvc_resource_type resource_type) { - spvc_context context = nullptr; - spvc_context_create(&context); - - spvc_parsed_ir ir = nullptr; - spvc_context_parse_spirv(context, spirv.data(), spirv.size(), &ir); - - spvc_compiler compiler = nullptr; - spvc_context_create_compiler(context, SPVC_BACKEND_NONE, ir, SPVC_CAPTURE_MODE_TAKE_OWNERSHIP, &compiler); - - spvc_resources resources = nullptr; - spvc_compiler_create_shader_resources(compiler, &resources); - - const spvc_reflected_resource *list = nullptr; - size_t count = 0; - spvc_resources_get_resource_list_for_type(resources, resource_type, &list, &count); - - std::vector variables; - for (size_t i = 0; i < count; ++i) { - unsigned int builtin; - if (spvc_compiler_has_decoration(compiler, list[i].id, SpvDecorationBuiltIn)) { - continue; - } - - InterfaceVariable var; - var.name = list[i].name; - var.location = spvc_compiler_get_decoration(compiler, list[i].id, SpvDecorationLocation); - variables.push_back(var); - } - - spvc_context_destroy(context); - - std::sort(variables.begin(), variables.end()); - - return variables; -} - TEST_F(ProgramTest, Sanity) { ASSERT_TRUE(true); } @@ -235,8 +185,8 @@ TEST_F(ProgramTest, DecompProgram) { } // spirv link check - auto vs_outputs = GetShaderInterface(spirvs[0], SPVC_RESOURCE_TYPE_STAGE_OUTPUT); - auto fs_inputs = GetShaderInterface(spirvs[1], SPVC_RESOURCE_TYPE_STAGE_INPUT); + auto vs_outputs = sessions[0].GetShaderInterface(SPVC_RESOURCE_TYPE_STAGE_OUTPUT); + auto fs_inputs = sessions[1].GetShaderInterface(SPVC_RESOURCE_TYPE_STAGE_INPUT); ASSERT_EQ(vs_outputs.size(), fs_inputs.size()); @@ -244,8 +194,8 @@ TEST_F(ProgramTest, DecompProgram) { EXPECT_EQ(vs_outputs[i].location, fs_inputs[i].location); } - auto vs_uniforms = GetShaderInterface(spirvs[0], SPVC_RESOURCE_TYPE_GL_PLAIN_UNIFORM); - auto fs_uniforms = GetShaderInterface(spirvs[1], SPVC_RESOURCE_TYPE_GL_PLAIN_UNIFORM); + auto vs_uniforms = sessions[0].GetShaderInterface(SPVC_RESOURCE_TYPE_GL_PLAIN_UNIFORM); + auto fs_uniforms = sessions[1].GetShaderInterface(SPVC_RESOURCE_TYPE_GL_PLAIN_UNIFORM); std::unordered_map uniform_locations; for (const auto& uniform : vs_uniforms) { @@ -259,8 +209,8 @@ TEST_F(ProgramTest, DecompProgram) { } } - auto vs_samplers = GetShaderInterface(spirvs[0], SPVC_RESOURCE_TYPE_SAMPLED_IMAGE); - auto fs_samplers = GetShaderInterface(spirvs[1], SPVC_RESOURCE_TYPE_SAMPLED_IMAGE); + auto vs_samplers = sessions[0].GetShaderInterface(SPVC_RESOURCE_TYPE_SAMPLED_IMAGE); + auto fs_samplers = sessions[1].GetShaderInterface(SPVC_RESOURCE_TYPE_SAMPLED_IMAGE); std::unordered_map sampler_locations; for (const auto& uniform : vs_uniforms) { diff --git a/MobileGL/MG_Util/ShaderTranspiler/ShaderCompiler.cpp b/MobileGL/MG_Util/ShaderTranspiler/ShaderCompiler.cpp index 2e17227b..f99425a1 100644 --- a/MobileGL/MG_Util/ShaderTranspiler/ShaderCompiler.cpp +++ b/MobileGL/MG_Util/ShaderTranspiler/ShaderCompiler.cpp @@ -136,12 +136,13 @@ namespace MobileGL { tshader->setStrings(src, 1); tshader->setInvertY(true); tshader->setEnvInput(glslang::EShSourceGlsl, lang, glslang::EShClientVulkan, 450); - tshader->setEnvClient(glslang::EShClientOpenGL, glslang::EShTargetOpenGL_450); + tshader->setEnvClient(glslang::EShClientVulkan, glslang::EShTargetVulkan_1_3); tshader->setEnvTarget(glslang::EShTargetSpv, glslang::EShTargetSpv_1_6); tshader->setAutoMapLocations(true); tshader->setAutoMapBindings(true); tshader->setEnvInputVulkanRulesRelaxed(); // using EXT_vulkan_glsl_relaxed for gl_VertexID and gl_InstanceID? - if (!tshader->parse(&GetTBuiltInResourceInstance(), 150, ECompatibilityProfile, + tshader->setGlobalUniformBlockName("MGL_GLOBAL_UBO"); + if (!tshader->parse(&GetTBuiltInResourceInstance(), 150, ECoreProfile, /*forceDefaultVersionAndProfile: */false, /*forwardCompatible: */true, EShMsgDefault)) { ResultInfo r; diff --git a/MobileGL/MG_Util/ShaderTranspiler/Types.h b/MobileGL/MG_Util/ShaderTranspiler/Types.h index 3fb8da13..8dfe9675 100644 --- a/MobileGL/MG_Util/ShaderTranspiler/Types.h +++ b/MobileGL/MG_Util/ShaderTranspiler/Types.h @@ -28,17 +28,31 @@ namespace MobileGL { template using Result = std::expected; + struct InterfaceVariable { + std::string name; + uint32_t location; + + bool operator<(const InterfaceVariable& other) const { + return location < other.location; + } + + bool operator==(const InterfaceVariable& other) const { + return location == other.location && name == other.name; + } + }; + class SpvcSession { public: SpvcSession() {} - explicit SpvcSession(Vector spirv) { + explicit SpvcSession(const Vector& spirv) { const SpvId *p_spirv = spirv.data(); size_t word_count = spirv.size(); spvc_context_create(&context); spvc_context_parse_spirv(context, p_spirv, word_count, &ir); spvc_context_create_compiler(context, SPVC_BACKEND_GLSL, ir, SPVC_CAPTURE_MODE_TAKE_OWNERSHIP, &compiler); + spvc_compiler_create_shader_resources(compiler, &resources); } SpvcSession(SpvcSession&) = delete; @@ -48,6 +62,7 @@ namespace MobileGL { std::swap(this->compiler, that.compiler); std::swap(this->ir, that.ir); std::swap(this->compiler_options, that.compiler_options); + std::swap(this->resources, that.resources); } SpvcSession& operator=(SpvcSession& session) = delete; @@ -57,6 +72,7 @@ namespace MobileGL { std::swap(this->compiler, that.compiler); std::swap(this->ir, that.ir); std::swap(this->compiler_options, that.compiler_options); + std::swap(this->resources, that.resources); return *this; } @@ -69,11 +85,31 @@ namespace MobileGL { return spvc_compiler_install_compiler_options(compiler, options); } - spvc_result Compile(const char** result) { + Vector GetShaderInterface(spvc_resource_type resource_type) const { + const spvc_reflected_resource *list = nullptr; + size_t count = 0; + spvc_resources_get_resource_list_for_type(resources, resource_type, &list, &count); + + Vector variables; + for (size_t i = 0; i < count; ++i) { + if (spvc_compiler_has_decoration(compiler, list[i].id, SpvDecorationBuiltIn)) { + continue; + } + + InterfaceVariable var; + var.name = list[i].name; + var.location = spvc_compiler_get_decoration(compiler, list[i].id, SpvDecorationLocation); + variables.push_back(var); + } + std::sort(variables.begin(), variables.end()); + return variables; + } + + spvc_result Compile(const char** result) const { return spvc_compiler_compile(compiler, result); } - const char* GetLastErrorString() { + const char* GetLastErrorString() const { return spvc_context_get_last_error_string(context); } @@ -83,6 +119,7 @@ namespace MobileGL { spvc_parsed_ir ir = nullptr; spvc_compiler compiler = nullptr; spvc_compiler_options compiler_options = nullptr; + spvc_resources resources = nullptr; }; inline static EShLanguage GetEShLanguageByShaderType(GLenum shaderType) {