diff --git a/core/libs/prx/libSceAgcDriver/CMakeLists.txt b/core/libs/prx/libSceAgcDriver/CMakeLists.txt index 67bfd2605..961da74a0 100644 --- a/core/libs/prx/libSceAgcDriver/CMakeLists.txt +++ b/core/libs/prx/libSceAgcDriver/CMakeLists.txt @@ -1485,3 +1485,16 @@ if(BUILD_TESTING) "PATH=path_list_prepend:$") endif() endif() + +add_test_executable(agc_embedded_vertex_fetch_aliasing_tests EXCLUDE_FROM_ALL tests/EmbeddedVertexFetchAliasing.cpp) +target_link_libraries(agc_embedded_vertex_fetch_aliasing_tests PRIVATE shader_recompiler_agc_driver libc) +set_target_properties(agc_embedded_vertex_fetch_aliasing_tests PROPERTIES CXX_EXTENSIONS OFF) +configure_windows_unwind(agc_embedded_vertex_fetch_aliasing_tests) +if(BUILD_TESTING) + set_target_properties(agc_embedded_vertex_fetch_aliasing_tests PROPERTIES EXCLUDE_FROM_ALL OFF) + add_test(NAME agc_embedded_vertex_fetch_aliasing COMMAND agc_embedded_vertex_fetch_aliasing_tests) + if(WIN32) + set_tests_properties(agc_embedded_vertex_fetch_aliasing PROPERTIES ENVIRONMENT_MODIFICATION + "PATH=path_list_prepend:$") + endif() +endif() diff --git a/core/libs/prx/libSceAgcDriver/tests/EmbeddedVertexFetchAliasing.cpp b/core/libs/prx/libSceAgcDriver/tests/EmbeddedVertexFetchAliasing.cpp new file mode 100644 index 000000000..3e38216df --- /dev/null +++ b/core/libs/prx/libSceAgcDriver/tests/EmbeddedVertexFetchAliasing.cpp @@ -0,0 +1,31 @@ +#include "RdnaDecoder/RdnaInstructionDecoder.hpp" +#include "Translation/EmbeddedVertexFetch.hpp" +#include +#include +#include +#include + +using namespace ShaderRecompiler; + +int main() { + int failures = 0; + for (const std::uint32_t waveSize : {32u, 64u}) { + for (const std::uint32_t indexRegister : {0u, 1u, 2u, 3u, 16u}) { + const std::array code{ + 0xf4000004u | (indexRegister << 6u), 0xfa00000cu, + 0xf4080005u, indexRegister << 25u, + 0x02140b08u, + 0xe00c2000u, 0x80000b0au, + 0xbf810000u, + }; + const auto decoded = RdnaInstructionDecoder{}.Decode(code); + const auto plan = EmbeddedVertexFetchAnalyzer{}.Analyze(decoded, 0, 2, 0, 16, waveSize); + if (plan.loads.size() != 1 || plan.loads.front().attributeId != 3 || plan.loads.front().componentCount != 4 || + plan.loads.front().programCounter != 20 || plan.loads.front().prologLoads != std::vector{0, 8}) { + std::fprintf(stderr, "wave%u descriptor offset s%u lost its attribute or load provenance\n", waveSize, indexRegister); + ++failures; + } + } + } + return failures == 0 ? 0 : 1; +} diff --git a/core/shader/recompiler/Translation/src/EmbeddedVertexFetch.cpp b/core/shader/recompiler/Translation/src/EmbeddedVertexFetch.cpp index a5ba98424..7bc692922 100644 --- a/core/shader/recompiler/Translation/src/EmbeddedVertexFetch.cpp +++ b/core/shader/recompiler/Translation/src/EmbeddedVertexFetch.cpp @@ -516,12 +516,13 @@ EmbeddedFetchPlan EmbeddedVertexFetchAnalyzer::Analyze(const RdnaProgram& progra dst.loadPcs.push_back(inst.programCounter); } } else if (isScalarOperand(inst.source1) && scalarSlot(inst.source1) < sgprs.size() && sgprs[scalarSlot(inst.source1)].kind == SgprValueKind::Attribute && (inst.memoryOffset & 0x3u) == 0u) { + const auto attribute = sgprs[scalarSlot(inst.source1)]; for (std::uint32_t i = 0u; i < decodedDstSize(inst) && slot + i < sgprs.size(); i++) { auto& dst = sgprs[slot + i]; dst = SgprValue{}; dst.kind = SgprValueKind::Buffer; - dst.attributeId = sgprs[scalarSlot(inst.source1)].attributeId; - dst.loadPcs = sgprs[scalarSlot(inst.source1)].loadPcs; + dst.attributeId = attribute.attributeId; + dst.loadPcs = attribute.loadPcs; dst.loadPcs.push_back(inst.programCounter); } } else {