feat(shader): decode mixed SGPR and VCC buffer descriptors

This commit is contained in:
Romans Pokrovskis committed 2026-10-14 12:26:01 +03:00
1 parent 43349d4337
commit c8d44e651e
3 files changed
+57

No files matched your search

@@ -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:$<TARGET_FILE_DIR:libc>")
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)
@@ -0,0 +1,40 @@
#include "RdnaDecoder/RdnaMemoryOpDecoder.hpp"
#include <array>
#include <cstdint>
#include <cstdio>
#include <stdexcept>
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<std::uint32_t, 2> 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<void>(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;
}
}
@@ -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;
}