fix(shader): stop decoding gfx6/7-only VOP2 opcodes on RDNA
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
d70b899894
commit
2ea1f6fb71
|
|
@ -344,6 +344,18 @@ add_test_executable(agc_vop1_control_decode_tests EXCLUDE_FROM_ALL tests/Vop1Con
|
|||
target_link_libraries(agc_vop1_control_decode_tests PRIVATE shader_recompiler_agc_driver libc)
|
||||
set_target_properties(agc_vop1_control_decode_tests PROPERTIES CXX_EXTENSIONS OFF)
|
||||
configure_windows_unwind(agc_vop1_control_decode_tests)
|
||||
add_test_executable(agc_vop2_encoding_decode_tests EXCLUDE_FROM_ALL tests/Vop2EncodingDecode.cpp)
|
||||
target_link_libraries(agc_vop2_encoding_decode_tests PRIVATE shader_recompiler_agc_driver libc)
|
||||
set_target_properties(agc_vop2_encoding_decode_tests PROPERTIES CXX_EXTENSIONS OFF)
|
||||
configure_windows_unwind(agc_vop2_encoding_decode_tests)
|
||||
if(BUILD_TESTING)
|
||||
set_target_properties(agc_vop2_encoding_decode_tests PROPERTIES EXCLUDE_FROM_ALL OFF)
|
||||
add_test(NAME agc_vop2_encoding_decode COMMAND agc_vop2_encoding_decode_tests)
|
||||
if(WIN32)
|
||||
set_tests_properties(agc_vop2_encoding_decode PROPERTIES ENVIRONMENT_MODIFICATION
|
||||
"PATH=path_list_prepend:$<TARGET_FILE_DIR:libc>")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
add_test_executable(agc_dcc_key_sharing_tests EXCLUDE_FROM_ALL tests/DccKeySharing.cpp)
|
||||
target_include_directories(agc_dcc_key_sharing_tests PRIVATE ${LIBS_INCLUDE_DIR} ${CMAKE_SOURCE_DIR}/core/shader/recompiler ${CMAKE_SOURCE_DIR}/3rdparty/Vulkan-Headers/include)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,82 @@
|
|||
#include "RdnaDecoder/RdnaInstructionDecoder.hpp"
|
||||
#include <cstdio>
|
||||
#include <exception>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
using namespace ShaderRecompiler;
|
||||
|
||||
namespace {
|
||||
|
||||
struct Accepted {
|
||||
std::vector<std::uint32_t> words;
|
||||
RdnaOpcode op;
|
||||
const char* name;
|
||||
};
|
||||
|
||||
struct Refused {
|
||||
std::vector<std::uint32_t> words;
|
||||
const char* reason;
|
||||
const char* name;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
int main() {
|
||||
const std::vector<Accepted> accepted{
|
||||
{{0x2c040300u}, RdnaOpcode::VLshrrevB32, "v_lshrrev_b32"},
|
||||
{{0x6e040300u, 0x00003c00u}, RdnaOpcode::VFmamkF16, "v_fmamk_f16"},
|
||||
{{0x78040300u}, RdnaOpcode::VPkFmacF16, "v_pk_fmac_f16"},
|
||||
{{0xd5160002u, 0x00020300u}, RdnaOpcode::VLshrrevB32, "VOP3 v_lshrrev_b32"},
|
||||
{{0xd7640002u, 0x00020300u}, RdnaOpcode::VBcntU32B32, "VOP3 v_bcnt_u32_b32"},
|
||||
{{0xd7650002u, 0x00020300u}, RdnaOpcode::VMbcntLoU32B32, "VOP3 v_mbcnt_lo_u32_b32"},
|
||||
{{0xd7660002u, 0x00020300u}, RdnaOpcode::VMbcntHiU32B32, "VOP3 v_mbcnt_hi_u32_b32"},
|
||||
};
|
||||
const std::vector<Refused> refused{
|
||||
{{0x2a040300u}, "VOP2 opcode is not implemented", "VOP2 opcode 0x15"},
|
||||
{{0x2e040300u}, "VOP2 opcode is not implemented", "VOP2 opcode 0x17"},
|
||||
{{0x32040300u}, "VOP2 opcode is not implemented", "VOP2 opcode 0x19"},
|
||||
{{0x44040300u}, "VOP2 opcode is not implemented", "VOP2 opcode 0x22"},
|
||||
{{0x46040300u}, "VOP2 opcode is not implemented", "VOP2 opcode 0x23"},
|
||||
{{0x48040300u}, "VOP2 opcode is not implemented", "VOP2 opcode 0x24"},
|
||||
{{0xd5150002u, 0x00020300u}, "VOP3 opcode is not implemented", "VOP3 opcode 0x115"},
|
||||
{{0xd5170002u, 0x00020300u}, "VOP3 opcode is not implemented", "VOP3 opcode 0x117"},
|
||||
{{0xd5190002u, 0x00020300u}, "VOP3 opcode is not implemented", "VOP3 opcode 0x119"},
|
||||
{{0xd5220002u, 0x00020300u}, "VOP3 opcode is not implemented", "VOP3 opcode 0x122"},
|
||||
{{0xd5230002u, 0x00020300u}, "VOP3 opcode is not implemented", "VOP3 opcode 0x123"},
|
||||
{{0xd5240002u, 0x00020300u}, "VOP3 opcode is not implemented", "VOP3 opcode 0x124"},
|
||||
{{0xd5370002u, 0x00020300u}, "VOP3 opcode is not implemented", "VOP3 opcode 0x137"},
|
||||
{{0xd5380002u, 0x00020300u}, "VOP3 opcode is not implemented", "VOP3 opcode 0x138"},
|
||||
{{0xd53c0002u, 0x00020300u}, "VOP3 opcode is not implemented", "VOP3 opcode 0x13c"},
|
||||
};
|
||||
int failures = 0;
|
||||
for (const auto& test : accepted) {
|
||||
auto code = test.words;
|
||||
code.push_back(0xbf810000u);
|
||||
try {
|
||||
const auto decoded = RdnaInstructionDecoder{}.Decode(code);
|
||||
if (decoded.instructions.empty() || decoded.instructions[0].op != test.op || decoded.instructions[0].wordCount != test.words.size()) {
|
||||
std::fprintf(stderr, "%s decodes to the wrong opcode or length\n", test.name);
|
||||
++failures;
|
||||
}
|
||||
} catch (const std::exception& error) {
|
||||
std::fprintf(stderr, "%s was refused: %s\n", test.name, error.what());
|
||||
++failures;
|
||||
}
|
||||
}
|
||||
for (const auto& test : refused) {
|
||||
auto code = test.words;
|
||||
code.push_back(0xbf810000u);
|
||||
std::string refusal;
|
||||
try {
|
||||
static_cast<void>(RdnaInstructionDecoder{}.Decode(code));
|
||||
} catch (const std::exception& error) {
|
||||
refusal = error.what();
|
||||
}
|
||||
if (refusal.find(test.reason) == std::string::npos) {
|
||||
std::fprintf(stderr, "%s was not refused\n", test.name);
|
||||
++failures;
|
||||
}
|
||||
}
|
||||
return failures == 0 ? 0 : 1;
|
||||
}
|
||||
|
|
@ -28,12 +28,12 @@ constexpr std::uint32_t SharedExhausted = 1000u;
|
|||
alignas(256) std::array<std::uint32_t, MaxThreads * Inputs> Input{};
|
||||
alignas(256) std::array<std::uint32_t, MaxThreads * Results + SharedWords> Output{};
|
||||
|
||||
alignas(256) constexpr std::array<std::uint32_t, 35> Code{
|
||||
alignas(256) constexpr std::array<std::uint32_t, 37> Code{
|
||||
0x34020084, 0x34040085, 0xe0301000, 0x80000401, 0xe0301004, 0x80000501, 0xe0301008, 0x80000601,
|
||||
0xbf8c3f70, 0x7e140280, 0x461414c1, 0x481414c1, 0x7e0e0304, 0xe0d05000, 0x80010702, 0x7e100304,
|
||||
0xbefe03ff, 0x55555555, 0xe0d05004, 0x80010802, 0xbefe03c1, 0x7e120305, 0xe0d04800, 0x80010900,
|
||||
0x7e160306, 0xe0d04804, 0x80010b00, 0xbf8c3f70, 0xe0701008, 0x80010702, 0xe070100c, 0x80010802,
|
||||
0xe0701010, 0x80010a02, 0xbf810000,
|
||||
0xbf8c3f70, 0x7e140280, 0xd765000a, 0x000214c1, 0xd766000a, 0x000214c1, 0x7e0e0304, 0xe0d05000,
|
||||
0x80010702, 0x7e100304, 0xbefe03ff, 0x55555555, 0xe0d05004, 0x80010802, 0xbefe03c1, 0x7e120305,
|
||||
0xe0d04800, 0x80010900, 0x7e160306, 0xe0d04804, 0x80010b00, 0xbf8c3f70, 0xe0701008, 0x80010702,
|
||||
0xe070100c, 0x80010802, 0xe0701010, 0x80010a02, 0xbf810000,
|
||||
};
|
||||
|
||||
alignas(256) constexpr std::array<std::uint32_t, 3> NoReturnCode{
|
||||
|
|
|
|||
|
|
@ -28,12 +28,13 @@ constexpr std::uint32_t MaskedExecLo = 0x55555555u;
|
|||
alignas(256) std::array<std::uint32_t, TableDwords> Table{};
|
||||
alignas(256) std::array<std::uint32_t, MaxThreads * Results> Output{};
|
||||
|
||||
alignas(256) constexpr std::array<std::uint32_t, 39> AddtidCode{
|
||||
alignas(256) constexpr std::array<std::uint32_t, 41> AddtidCode{
|
||||
0x34020085, 0x34040082, 0xbe880300, 0x8709ff01, 0x0000ffff, 0x800aff08, 0x00000200, 0x820b8009,
|
||||
0x7e080280, 0x460808c1, 0x480808c1, 0x7e0a02ff, 0xabcdabcd, 0x7e0c02ff, 0xabcdabcd, 0x7e0e02ff,
|
||||
0xabcdabcd, 0xe0301000, 0x80000802, 0xdc588040, 0x05080000, 0xdc588fe4, 0x060a0000, 0xbefe03ff,
|
||||
0x55555555, 0xdc588000, 0x07080000, 0xbefe03c1, 0xe0701000, 0x80010401, 0xe0701004, 0x80010501,
|
||||
0xe0701008, 0x80010601, 0xe070100c, 0x80010701, 0xe0701010, 0x80010801, 0xbf810000,
|
||||
0x7e080280, 0xd7650004, 0x000208c1, 0xd7660004, 0x000208c1, 0x7e0a02ff, 0xabcdabcd, 0x7e0c02ff,
|
||||
0xabcdabcd, 0x7e0e02ff, 0xabcdabcd, 0xe0301000, 0x80000802, 0xdc588040, 0x05080000, 0xdc588fe4,
|
||||
0x060a0000, 0xbefe03ff, 0x55555555, 0xdc588000, 0x07080000, 0xbefe03c1, 0xe0701000, 0x80010401,
|
||||
0xe0701004, 0x80010501, 0xe0701008, 0x80010601, 0xe070100c, 0x80010701, 0xe0701010, 0x80010801,
|
||||
0xbf810000,
|
||||
};
|
||||
|
||||
struct Workgroup {
|
||||
|
|
|
|||
|
|
@ -70,9 +70,6 @@ enum class RdnaOpcode : std::uint16_t {
|
|||
VAndB32,
|
||||
VOrB32,
|
||||
VXorB32,
|
||||
VLshlB32,
|
||||
VLshrB32,
|
||||
VAshrI32,
|
||||
VCmpEqF32,
|
||||
VCmpLtF32,
|
||||
VCmpGtF32,
|
||||
|
|
|
|||
|
|
@ -183,9 +183,6 @@ bool IsVectorAluOpcode(RdnaOpcode opcode) {
|
|||
case RdnaOpcode::VAndB32:
|
||||
case RdnaOpcode::VOrB32:
|
||||
case RdnaOpcode::VXorB32:
|
||||
case RdnaOpcode::VLshlB32:
|
||||
case RdnaOpcode::VLshrB32:
|
||||
case RdnaOpcode::VAshrI32:
|
||||
case RdnaOpcode::VCmpEqF32:
|
||||
case RdnaOpcode::VCmpLtF32:
|
||||
case RdnaOpcode::VCmpGtF32:
|
||||
|
|
|
|||
|
|
@ -58,11 +58,8 @@ constexpr Vop2OpcodeInfo vop2Opcodes[] = {
|
|||
{0x12u, RdnaOpcode::VMaxI32, Vop2SdwaProfile::Integer},
|
||||
{0x13u, RdnaOpcode::VMinU32, Vop2SdwaProfile::Integer},
|
||||
{0x14u, RdnaOpcode::VMaxU32, Vop2SdwaProfile::Integer},
|
||||
{0x15u, RdnaOpcode::VLshrB32},
|
||||
{0x16u, RdnaOpcode::VLshrrevB32, Vop2SdwaProfile::Integer},
|
||||
{0x17u, RdnaOpcode::VAshrI32},
|
||||
{0x18u, RdnaOpcode::VAshrrevI32, Vop2SdwaProfile::Integer},
|
||||
{0x19u, RdnaOpcode::VLshlB32},
|
||||
{0x1au, RdnaOpcode::VLshlrevB32, Vop2SdwaProfile::Integer},
|
||||
{0x1bu, RdnaOpcode::VAndB32, Vop2SdwaProfile::Integer},
|
||||
{0x1cu, RdnaOpcode::VOrB32, Vop2SdwaProfile::Integer},
|
||||
|
|
@ -71,9 +68,6 @@ constexpr Vop2OpcodeInfo vop2Opcodes[] = {
|
|||
{0x1fu, RdnaOpcode::VMacF32},
|
||||
{0x20u, RdnaOpcode::VMadmkF32},
|
||||
{0x21u, RdnaOpcode::VMadakF32},
|
||||
{0x22u, RdnaOpcode::VBcntU32B32},
|
||||
{0x23u, RdnaOpcode::VMbcntLoU32B32},
|
||||
{0x24u, RdnaOpcode::VMbcntHiU32B32},
|
||||
{0x25u, RdnaOpcode::VAddNcU32, Vop2SdwaProfile::Integer},
|
||||
{0x28u, RdnaOpcode::VAddcU32, Vop2SdwaProfile::Integer},
|
||||
{0x29u, RdnaOpcode::VSubCoCiU32, Vop2SdwaProfile::Integer},
|
||||
|
|
@ -630,11 +624,11 @@ RdnaOpcode lookupVectorOpcode(const TEntry (&table)[Size], std::uint32_t encodin
|
|||
}
|
||||
|
||||
bool isVop2LiteralMadOpcode(std::uint32_t opcode) {
|
||||
return opcode == 0x20u || opcode == 0x21u || opcode == 0x2cu || opcode == 0x2du;
|
||||
return opcode == 0x20u || opcode == 0x21u || opcode == 0x2cu || opcode == 0x2du || opcode == 0x37u || opcode == 0x38u;
|
||||
}
|
||||
|
||||
bool isUnsupportedVop3EncodedVop2Alias(std::uint32_t opcode) {
|
||||
return isVop2LiteralMadOpcode(opcode) || opcode == 0x02u || opcode == 0x0du;
|
||||
return isVop2LiteralMadOpcode(opcode) || opcode == 0x02u || opcode == 0x0du || opcode == 0x3cu;
|
||||
}
|
||||
|
||||
bool isVop3EncodedVopc(std::uint32_t opcode) {
|
||||
|
|
|
|||
|
|
@ -1113,16 +1113,10 @@ bool TranslationContext::emitVector(const RdnaInstruction& inst) {
|
|||
return simpleInteger(inst, IrOpcode::BitReverse32, IrType::U32, false, false, false);
|
||||
case RdnaOpcode::VFfblB32:
|
||||
return simpleInteger(inst, IrOpcode::FindILsb32, IrType::U32, false, false, false);
|
||||
case RdnaOpcode::VLshlB32:
|
||||
return simpleInteger(inst, IrOpcode::ShiftLeftLogical32, IrType::U32, false, true, false);
|
||||
case RdnaOpcode::VLshlrevB32:
|
||||
return simpleInteger(inst, IrOpcode::ShiftLeftLogical32, IrType::U32, true, true, false);
|
||||
case RdnaOpcode::VLshrB32:
|
||||
return simpleInteger(inst, IrOpcode::ShiftRightLogical32, IrType::U32, false, true, false);
|
||||
case RdnaOpcode::VLshrrevB32:
|
||||
return simpleInteger(inst, IrOpcode::ShiftRightLogical32, IrType::U32, true, true, false);
|
||||
case RdnaOpcode::VAshrI32:
|
||||
return simpleInteger(inst, IrOpcode::ShiftRightArithmetic32, IrType::U32, false, true, false);
|
||||
case RdnaOpcode::VAshrrevI32:
|
||||
return simpleInteger(inst, IrOpcode::ShiftRightArithmetic32, IrType::U32, true, true, false);
|
||||
case RdnaOpcode::VLshlrevB64:
|
||||
|
|
|
|||
Loading…
Reference in New Issue