diff --git a/src/graphics/shader/recompiler/ShaderRecompiler.cpp b/src/graphics/shader/recompiler/ShaderRecompiler.cpp index 05b03c915..dee56e426 100644 --- a/src/graphics/shader/recompiler/ShaderRecompiler.cpp +++ b/src/graphics/shader/recompiler/ShaderRecompiler.cpp @@ -87,7 +87,6 @@ struct EmbeddedFetchSgprInfo { EmbeddedFetchValueType type = EmbeddedFetchValueType::Unknown; int attrib_id = 0; uint32_t value = 0; - std::vector prolog_loads; }; using EmbeddedFetchVectorLanes = std::map; @@ -326,7 +325,6 @@ EmbeddedFetchData DetectEmbeddedVertexFetch(const Decoder::Program& decoded auto& dst = sgprs[DecodedSgprReg(inst.dst)]; dst.type = EmbeddedFetchValueType::Constant; dst.value = value; - dst.prolog_loads.clear(); } else { ClearEmbeddedFetchSgprs(sgprs, inst.dst, 1); } @@ -337,7 +335,6 @@ EmbeddedFetchData DetectEmbeddedVertexFetch(const Decoder::Program& decoded auto& dst = sgprs[DecodedSgprReg(inst.dst)]; dst.type = EmbeddedFetchValueType::Constant; dst.value = inst.src0.value; - dst.prolog_loads.clear(); } break; default: @@ -354,7 +351,6 @@ EmbeddedFetchData DetectEmbeddedVertexFetch(const Decoder::Program& decoded auto& dst = sgprs[register_id + i]; dst.type = EmbeddedFetchValueType::Attrib; dst.attrib_id = index + static_cast(i); - dst.prolog_loads = {inst.pc}; } } else { ClearEmbeddedFetchSgprs(sgprs, inst.dst, DecodedDstSize(inst)); @@ -372,7 +368,6 @@ EmbeddedFetchData DetectEmbeddedVertexFetch(const Decoder::Program& decoded dst.type = EmbeddedFetchValueType::Buffer; dst.attrib_id = BufferTableAttribFromOffset(raw_offset, static_cast(i)); - dst.prolog_loads = {inst.pc}; } } else if (IsDecodedSgpr(inst.src1) && DecodedSgprReg(inst.src1) < sgprs.size() && @@ -384,8 +379,6 @@ EmbeddedFetchData DetectEmbeddedVertexFetch(const Decoder::Program& decoded auto& dst = sgprs[register_id + i]; dst.type = EmbeddedFetchValueType::Buffer; dst.attrib_id = sgprs[DecodedSgprReg(inst.src1)].attrib_id; - dst.prolog_loads = sgprs[DecodedSgprReg(inst.src1)].prolog_loads; - dst.prolog_loads.push_back(inst.pc); } } else { ClearEmbeddedFetchSgprs(sgprs, inst.dst, DecodedDstSize(inst)); @@ -424,7 +417,6 @@ EmbeddedFetchData DetectEmbeddedVertexFetch(const Decoder::Program& decoded break; default: dst.value = src0 + src1; break; } - dst.prolog_loads.clear(); } else { ClearEmbeddedFetchSgprs(sgprs, inst.dst, 1); } @@ -447,7 +439,6 @@ EmbeddedFetchData DetectEmbeddedVertexFetch(const Decoder::Program& decoded load.pc = inst.pc; load.attrib_id = buffer.attrib_id; load.components = DecodedDstSize(inst); - load.prolog_loads = buffer.prolog_loads; } } break; diff --git a/src/graphics/shader/recompiler/frontend/translate/Translate.cpp b/src/graphics/shader/recompiler/frontend/translate/Translate.cpp index 68f20ef75..8ab24afc0 100644 --- a/src/graphics/shader/recompiler/frontend/translate/Translate.cpp +++ b/src/graphics/shader/recompiler/frontend/translate/Translate.cpp @@ -789,15 +789,6 @@ const EmbeddedFetchLoad* FindEmbeddedFetchLoad(const EmbeddedFetchPlan* plan, ui return found != plan->loads.end() ? &*found : nullptr; } -bool IsEmbeddedFetchPrologLoad(const EmbeddedFetchPlan* plan, uint32_t pc) { - if (plan == nullptr) { - return false; - } - return std::ranges::any_of(plan->loads, [pc](const auto& load) { - return std::ranges::find(load.prolog_loads, pc) != load.prolog_loads.end(); - }); -} - int ResolveEmbeddedFetchResource(const ShaderVertexInputInfo& input, const EmbeddedFetchLoad& load) { if (load.attrib_id >= 0 && load.attrib_id < input.resources_num && @@ -819,22 +810,6 @@ int ResolveEmbeddedFetchResource(const ShaderVertexInputInfo& input, return -1; } -bool IsScalarMemoryLoad(Decoder::Opcode opcode) { - switch (opcode) { - case Decoder::Opcode::S_LOAD_DWORD: - case Decoder::Opcode::S_LOAD_DWORDX2: - case Decoder::Opcode::S_LOAD_DWORDX4: - case Decoder::Opcode::S_LOAD_DWORDX8: - case Decoder::Opcode::S_LOAD_DWORDX16: - case Decoder::Opcode::S_BUFFER_LOAD_DWORD: - case Decoder::Opcode::S_BUFFER_LOAD_DWORDX2: - case Decoder::Opcode::S_BUFFER_LOAD_DWORDX4: - case Decoder::Opcode::S_BUFFER_LOAD_DWORDX8: - case Decoder::Opcode::S_BUFFER_LOAD_DWORDX16: return true; - default: return false; - } -} - bool IsBufferDwordLoad(Decoder::Opcode opcode) { switch (opcode) { case Decoder::Opcode::BUFFER_LOAD_DWORD: @@ -1258,10 +1233,6 @@ IR::Program TranslateProgram(const Decoder::Program& decoded, const CFG::Graph& if (IsCodeTableLoad(cfg, instruction.pc)) { continue; } - if (IsScalarMemoryLoad(instruction.opcode) && - IsEmbeddedFetchPrologLoad(options.embedded_fetch, instruction.pc)) { - continue; - } const auto* embedded = FindEmbeddedFetchLoad(options.embedded_fetch, instruction.pc); if (embedded != nullptr && IsBufferDwordLoad(instruction.opcode) && instruction.data_dwords == embedded->components && diff --git a/src/graphics/shader/recompiler/frontend/translate/Translate.h b/src/graphics/shader/recompiler/frontend/translate/Translate.h index c012933de..dd6b7137a 100644 --- a/src/graphics/shader/recompiler/frontend/translate/Translate.h +++ b/src/graphics/shader/recompiler/frontend/translate/Translate.h @@ -13,7 +13,6 @@ struct EmbeddedFetchLoad { uint32_t pc = 0; int attrib_id = -1; uint32_t components = 0; - std::vector prolog_loads; }; struct EmbeddedFetchPlan { diff --git a/tests/shaderCfgTests.cpp b/tests/shaderCfgTests.cpp index 75916773d..e7222e7b0 100644 --- a/tests/shaderCfgTests.cpp +++ b/tests/shaderCfgTests.cpp @@ -9561,6 +9561,54 @@ void TestMergedShaderUserDataSnapshot() { } } +void TestEmbeddedFetchPreservesSharedScalarLoad() { + using namespace ShaderRecompiler; + const uint32_t code[] = { + EncodeSMovB32(5, 255), 0x47f, + EncodeSmem0(0x03, 0, 11), (125u << 25u) | 4u, // s_load_dwordx8 s[0:7], s[22:23], 4 + EncodeSop2(0x1e, 9, 0, 132), // s_lshl_b32 s9, s0, 4 + EncodeSop2(0x0e, 9, 9, 255), 0x1f0, + EncodeSmem0(0x02, 24, 10), 9u << 25u, + EncodeVop2(0x01, 0, 256 + 8, 5), // vertex/instance index selection + EncodeMubuf0(0x02), EncodeMubuf1(9, 6, 0), // replaced vertex fetch + EncodeSop2(0x1e, 9, 5, 132), // another component of the same scalar load + EncodeSop2(0x0e, 9, 9, 255), 0x1f0, + EncodeSmem0(0x02, 28, 10), 9u << 25u, + EncodeMubuf0(0x0c), EncodeMubuf1(12, 7, 1), + EncodeExp0(0x0c, 0xf), EncodeExp1(9, 10, 11, 12), EncodeSopp(0x01), + }; + std::array, 32> buffers{}; + buffers[2] = {0x12340000, 0, 64, 0x00027000}; + buffers[31] = {0x56780000, 0, 64, 0x00027000}; + const std::array attributes = {0, 0, 0, 0, 0, 0, 2, 0, 0}; + std::array user_data{}; + const uint64_t tables[] = {reinterpret_cast(buffers.data()), + reinterpret_cast(attributes.data())}; + std::memcpy(user_data.data() + 12, tables, sizeof(tables)); + ShaderVertexInputInfo input{}; + input.fetch_embedded = true; + input.fetch_buffer_reg = 12; + input.fetch_attrib_reg = 14; + input.resources_num = 1; + input.resources_dst[0].attr_id = 1; + input.resources[0].fields[1] = 12u << 16u; + input.resources[0].fields[2] = 1; + input.resources[0].fields[3] = + (static_cast(Prospero::BufferFormat::k32_32_32Float) << 12u) | + DstSel(4, 5, 6, 7); + auto options = MakeCompileOptions(ShaderType::Vertex); + options.user_data_base = 8; + options.user_data = user_data; + options.input_info.vertex = &input; + auto result = RecompileForTest(code, options); + Check(result.program.info.vertex_fetch_components[0] == 3 && + result.resources.buffers.size() == 1 && + std::equal(buffers[2].begin(), buffers[2].end(), + result.resources.buffers[0].dwords.begin()), + "embedded fetch discarded a scalar-load component used by another buffer read"); + CheckSpirvBinaryValidates(result.spirv); +} + void TestEmbeddedVertexFormatSwizzle() { using namespace ShaderRecompiler; using namespace ShaderRecompiler::IR; @@ -13346,6 +13394,7 @@ int main() { TestMeshExportStorage(); TestMergedShaderUserDataSnapshot(); TestMeshInputAssembly(); + TestEmbeddedFetchPreservesSharedScalarLoad(); TestEmbeddedVertexFormatSwizzle(); TestNewShaderRecompilerSetpcJumpTable(); TestNewShaderRecompilerPrunesUnreachableSetpcMetadata();