diff --git a/core/libs/prx/libSceAgcDriver/CMakeLists.txt b/core/libs/prx/libSceAgcDriver/CMakeLists.txt index 6fcb807da9..0d40a3705c 100644 --- a/core/libs/prx/libSceAgcDriver/CMakeLists.txt +++ b/core/libs/prx/libSceAgcDriver/CMakeLists.txt @@ -1929,6 +1929,20 @@ if(BUILD_TESTING) endif() endif() +add_test_executable(agc_buffer_resource_vcc_tests EXCLUDE_FROM_ALL tests/BufferResourceVcc.cpp) +target_link_libraries(agc_buffer_resource_vcc_tests PRIVATE shader_recompiler_agc_driver libc) +set_target_properties(agc_buffer_resource_vcc_tests PROPERTIES CXX_EXTENSIONS OFF) +configure_windows_unwind(agc_buffer_resource_vcc_tests) +if(BUILD_TESTING) + set_target_properties(agc_buffer_resource_vcc_tests PROPERTIES EXCLUDE_FROM_ALL OFF) + add_test(NAME agc_buffer_resource_vcc COMMAND agc_buffer_resource_vcc_tests) + set_tests_properties(agc_buffer_resource_vcc PROPERTIES TIMEOUT 30) + if(WIN32) + set_tests_properties(agc_buffer_resource_vcc PROPERTIES ENVIRONMENT_MODIFICATION + "PATH=path_list_prepend:$") + endif() +endif() + add_test_executable(agc_vop1_sdwa_move_decode_tests EXCLUDE_FROM_ALL tests/Vop1SdwaMoveDecode.cpp) target_link_libraries(agc_vop1_sdwa_move_decode_tests PRIVATE shader_recompiler_agc_driver libc) set_target_properties(agc_vop1_sdwa_move_decode_tests PROPERTIES CXX_EXTENSIONS OFF) diff --git a/core/libs/prx/libSceAgcDriver/tests/BufferResourceVcc.cpp b/core/libs/prx/libSceAgcDriver/tests/BufferResourceVcc.cpp new file mode 100644 index 0000000000..58fc43f06f --- /dev/null +++ b/core/libs/prx/libSceAgcDriver/tests/BufferResourceVcc.cpp @@ -0,0 +1,40 @@ +#include "RdnaDecoder/RdnaMemoryOpDecoder.hpp" +#include +#include +#include +#include + +using namespace ShaderRecompiler; + +int main() { + try { + for (const auto first : {0xe0000000u, 0xe0300000u, 0xe0700000u, 0xeba00000u, 0xeba40000u}) { + const auto decode = [&](std::uint32_t resource) { + const std::array code{first, (128u << 24u) | (resource << 16u) | (7u << 8u) | 3u}; + return first >> 26u == 0x3au ? DecodeRdnaMtbuf(0x100u, code, 0u) : DecodeRdnaMubuf(0x100u, code, 0u); + }; + for (std::uint32_t resource = 0u; resource <= 26u; ++resource) { + const auto instruction = decode(resource); + if (instruction.programCounter != 0x100u || instruction.sourceCount != 3u || + instruction.source1.kind != RdnaOperandKind::ScalarRegister || instruction.source1.reg != resource * 4u || + instruction.source0.kind != RdnaOperandKind::VectorRegister || instruction.source0.reg != 3u || + instruction.destination.kind != RdnaOperandKind::VectorRegister || instruction.destination.reg != 7u) + throw std::runtime_error("buffer descriptor decode changed another operand"); + if (first >> 26u == 0x3au && (instruction.dataFormat != 4u || instruction.numberFormat != 7u)) + throw std::runtime_error("MTBUF VCC descriptor changed the instruction format"); + } + for (std::uint32_t resource = 27u; resource < 32u; ++resource) { + bool refused = false; + try { static_cast(decode(resource)); } + catch (const std::runtime_error&) { refused = true; } + if (!refused) throw std::runtime_error("buffer descriptor extends past the VCC tuple"); + } + } + std::puts("MUBUF and MTBUF mixed SGPR/VCC descriptors and invalid-base refusals pass"); + return 0; + } catch (const std::exception& error) { + std::fprintf(stderr, "%s\n", error.what()); + return 1; + } +} + diff --git a/core/shader/recompiler/RdnaDecoder/src/RdnaMemoryOpDecoder.cpp b/core/shader/recompiler/RdnaDecoder/src/RdnaMemoryOpDecoder.cpp index 77ea8f0322..98950f77cb 100644 --- a/core/shader/recompiler/RdnaDecoder/src/RdnaMemoryOpDecoder.cpp +++ b/core/shader/recompiler/RdnaDecoder/src/RdnaMemoryOpDecoder.cpp @@ -469,6 +469,9 @@ RdnaOperand scalarDestination(std::uint32_t code) { RdnaOperand scalarDescriptorBase(std::uint32_t reg, std::uint32_t registerCount, const char* reason) { const auto operand = scalarSource(reg); + if (registerCount == 4u && reg == 104u && operand.kind == RdnaOperandKind::ScalarRegister) { + return operand; + } if (registerCount == 2u && operand.kind == RdnaOperandKind::VccLo) { return operand; }