diff --git a/MobileGL/MG_Test/Program/ProgramUtilTest.cpp b/MobileGL/MG_Test/Program/ProgramUtilTest.cpp index d9e875ba..ef645cac 100644 --- a/MobileGL/MG_Test/Program/ProgramUtilTest.cpp +++ b/MobileGL/MG_Test/Program/ProgramUtilTest.cpp @@ -822,6 +822,10 @@ layout(std430, binding = 0) writeonly buffer OutputBuffer { vec4 out_data[]; }; +vec3 evaluate_row(vec3 row_values[9], uint col) { + return row_values[col] + row_values[0]; +} + void main() { uint row = gl_LocalInvocationIndex; uint col = u_col; @@ -837,7 +841,7 @@ void main() { memoryBarrierShared(); barrier(); - out_data[gl_GlobalInvocationID.x] = vec4(loaded + rowCopy[col] + vec3(x), 1.0); + out_data[gl_GlobalInvocationID.x] = vec4(loaded + rowCopy[col] + evaluate_row(shared_memory[0], col) + vec3(x), 1.0); } )"; @@ -874,13 +878,17 @@ TEST_F(ProgramUtilTest, DecomposeWorkgroupVec3InSpirvPass) { << "SanitizeAndOptimizeBinary failed - the DecomposeWorkgroupVec3Pass may have " "encountered an unsupported pattern"; + spvtools::Optimizer parseOnlyOptimizer(SPV_ENV_VULKAN_1_1); + Vector parsedBinary; + ASSERT_TRUE(parseOnlyOptimizer.Run(optimized.data(), optimized.size(), &parsedBinary)) + << "DecomposeWorkgroupVec3Pass emitted SPIR-V with invalid physical layout"; + SpvcSession session(optimized, SessionUsageBit::Transpile); auto sourceRes = ShaderCompiler::DecompileShader(session); ASSERT_TRUE(sourceRes.has_value()) << "errc: " << sourceRes.error().errc << "\nlog: " << sourceRes.error().log; const String& source = sourceRes.value(); - // The decomposed output must not contain a `shared vec3` declaration. EXPECT_EQ(source.find("shared vec3"), std::string::npos) << "DecomposeWorkgroupVec3Pass did not eliminate `shared vec3`:\n" diff --git a/MobileGL/MG_Util/ShaderTranspiler/SpirvPasses/DecomposeWorkgroupVec3Pass.cpp b/MobileGL/MG_Util/ShaderTranspiler/SpirvPasses/DecomposeWorkgroupVec3Pass.cpp index dc4b5d3e..1a2a7a66 100644 --- a/MobileGL/MG_Util/ShaderTranspiler/SpirvPasses/DecomposeWorkgroupVec3Pass.cpp +++ b/MobileGL/MG_Util/ShaderTranspiler/SpirvPasses/DecomposeWorkgroupVec3Pass.cpp @@ -13,6 +13,7 @@ #include "source/opt/instruction.h" #include "source/opt/ir_context.h" #include "source/opt/module.h" +#include "source/opt/reflect.h" #include "source/opt/type_manager.h" #include "spirv.hpp" @@ -308,6 +309,39 @@ namespace MobileGL { assert(false && "DecomposeWorkgroupVec3Pass: unsupported composite store type"); } + + void MoveLateTypesConstantsBeforeGlobalVariables(IRContext* context) { + Instruction* firstVariable = nullptr; + for (Instruction& inst : context->module()->types_values()) { + if (inst.opcode() == spv::Op::OpVariable) { + firstVariable = &inst; + break; + } + } + + if (firstVariable == nullptr) { + return; + } + + bool sawFirstVariable = false; + for (auto it = context->module()->types_values_begin(); + it != context->module()->types_values_end();) { + Instruction* inst = &*it; + ++it; + + if (inst == firstVariable) { + sawFirstVariable = true; + continue; + } + + if (sawFirstVariable && + (spvtools::opt::IsTypeInst(inst->opcode()) || + spvtools::opt::IsConstantInst(inst->opcode()) || + inst->opcode() == spv::Op::OpUndef)) { + inst->InsertBefore(firstVariable); + } + } + } } // namespace spvtools::opt::Pass::Status DecomposeWorkgroupVec3Pass::Process() { @@ -605,6 +639,8 @@ namespace MobileGL { } } + MoveLateTypesConstantsBeforeGlobalVariables(ctx); + return Status::SuccessWithChange; }