shader: allow RDNA2 SDWA partial destinations for i24 multiply
This commit is contained in:
parent
5c83060481
commit
1d41ddb378
|
|
@ -35,7 +35,7 @@ constexpr Vop2OpcodeInfo VOP2_OPCODE_LIST[] = {
|
|||
{0x04u, Opcode::V_SUB_F32, Vop2SdwaProfile::Float32},
|
||||
{0x05u, Opcode::V_SUBREV_F32},
|
||||
{0x08u, Opcode::V_MUL_F32, Vop2SdwaProfile::Float32},
|
||||
{0x09u, Opcode::V_MUL_I32_I24, Vop2SdwaProfile::IntegerFullDestination},
|
||||
{0x09u, Opcode::V_MUL_I32_I24, Vop2SdwaProfile::IntegerPartialDestination},
|
||||
{0x0bu, Opcode::V_MUL_U32_U24, Vop2SdwaProfile::IntegerFullDestination},
|
||||
{0x0fu, Opcode::V_MIN_F32},
|
||||
{0x10u, Opcode::V_MAX_F32},
|
||||
|
|
|
|||
|
|
@ -21531,6 +21531,65 @@ TestCase Vop2SdwaMaxI32CapturedHighWord(u32 wave_size) {
|
|||
return test;
|
||||
}
|
||||
|
||||
TestCase Vop2SdwaMulI24Destinations(u32 wave_size) {
|
||||
using O = ShaderOpcode;
|
||||
constexpr std::array<u32, 5> sources{
|
||||
0xdead1234u, 0xabcdffffu, 0x98768001u, 0x34560000u, 0x56789abcu};
|
||||
constexpr std::array<u32, 10> captured_expected{
|
||||
0xdead91a0u, 0xdead3400u, 0xabcdfff8u, 0xabcdff00u,
|
||||
0x98760008u, 0x98760100u, 0x34560000u, 0x34560000u,
|
||||
0x56789abcu, 0x56789abcu};
|
||||
constexpr std::array<u32, 18> partial_expected{
|
||||
0x00000080u, 0xffffff80u, 0xa1b2c380u,
|
||||
0x00008000u, 0xffff8000u, 0xa1b280d4u,
|
||||
0x00800000u, 0xff800000u, 0xa180c3d4u,
|
||||
0x80000000u, 0x80000000u, 0x80b2c3d4u,
|
||||
0x0000a180u, 0xffffa180u, 0xa1b2a180u,
|
||||
0xa1800000u, 0xa1800000u, 0xa180c3d4u};
|
||||
TestCase test;
|
||||
test.name = wave_size == 64 ? "Vop2SdwaMulI24DestinationsWave64"
|
||||
: "Vop2SdwaMulI24DestinationsWave32";
|
||||
test.initial.assign(sources.begin(), sources.end());
|
||||
test.initial.push_back(0xabcde080u);
|
||||
test.expected = test.initial;
|
||||
auto &code = test.code;
|
||||
for (u32 index = 0; index < sources.size(); ++index) {
|
||||
AppendVMovU32(&code, 30, index * sizeof(u32));
|
||||
AppendBufferLoadDword(&code, 12, 30);
|
||||
AppendBufferLoadDword(&code, 26, 30);
|
||||
AppendSMovLiteral(&code, 106, 256);
|
||||
code.push_back(EncodeSMovB32(126, InlineU32(index + 1u == sources.size() ? 0 : 1)));
|
||||
// Captured WORD0/PRESERVE encodings alias their source and destination.
|
||||
code.insert(code.end(), {0x121818f9u, 0x04861488u,
|
||||
0x123434f9u, 0x0486146au});
|
||||
code.push_back(EncodeSMovB32(126, InlineU32(1)));
|
||||
AppendStoreVgpr(&code, 12, static_cast<u32>(test.expected.size()));
|
||||
AppendStoreVgpr(&code, 26, static_cast<u32>(test.expected.size()) + 1u);
|
||||
test.expected.push_back(captured_expected[index * 2u]);
|
||||
test.expected.push_back(captured_expected[index * 2u + 1u]);
|
||||
}
|
||||
AppendVMovU32(&code, 30, sources.size() * sizeof(u32));
|
||||
AppendBufferLoadDword(&code, 12, 30);
|
||||
for (u32 selector = 0; selector < 6; ++selector) {
|
||||
for (u32 unused = 0; unused < 3; ++unused) {
|
||||
AppendVMovLiteral(&code, 26, 0xa1b2c3d4u);
|
||||
code.push_back(EncodeVop2(0x09, 26, 249, 12));
|
||||
code.push_back(EncodeVop2Sdwa(InlineU32(3), selector, unused, 6, 4,
|
||||
0, 0, 0, 0, 0, 0, 1));
|
||||
AppendStoreVgpr(&code, 26, static_cast<u32>(test.expected.size()));
|
||||
test.expected.push_back(partial_expected[selector * 3u + unused]);
|
||||
}
|
||||
}
|
||||
AppendEnd(&code);
|
||||
test.initial.resize(test.expected.size());
|
||||
test.opcodes = {O::V_MOV_B32, O::S_MOV_B32, O::BUFFER_LOAD_DWORD,
|
||||
O::V_MUL_I32_I24, O::BUFFER_STORE_DWORD, O::S_ENDPGM};
|
||||
test.required_spirv = {"OpIMul", "OpBitFieldUExtract"};
|
||||
test.compute_info.wave_size = wave_size;
|
||||
test.has_compute_info = true;
|
||||
return test;
|
||||
}
|
||||
|
||||
TestCase Vop2SdwaLshrrevCapturedByte1Source() {
|
||||
using O = ShaderOpcode;
|
||||
|
||||
|
|
@ -34595,6 +34654,8 @@ std::vector<TestCase> MakeCases() {
|
|||
AddCase(Vop2SdwaAshrrevCapturedWord0SignExtends);
|
||||
cases.push_back(Vop2SdwaMaxI32CapturedHighWord(32));
|
||||
cases.push_back(Vop2SdwaMaxI32CapturedHighWord(64));
|
||||
cases.push_back(Vop2SdwaMulI24Destinations(32));
|
||||
cases.push_back(Vop2SdwaMulI24Destinations(64));
|
||||
AddCase(Vop2SdwaLshrrevCapturedByte1Source);
|
||||
AddCase(Vop2SdwaSubNcPreservesByteAndWordDestinations);
|
||||
AddCase(Vop3CvtPkI16I32Captured);
|
||||
|
|
@ -40415,6 +40476,13 @@ int main(int argc, char **argv) {
|
|||
RunCase(&vulkan, VectorAddcWritesPerLaneCarryOut());
|
||||
return 0;
|
||||
}
|
||||
if (argc == 2 && std::strcmp(argv[1], "--sdwa-mul-i24-only") == 0) {
|
||||
VulkanHarness vulkan;
|
||||
RunCase(&vulkan, Vop2SdwaMulI24Destinations(32));
|
||||
RunCase(&vulkan, Vop2SdwaMulI24Destinations(64));
|
||||
RunCase(&vulkan, VectorIntegerOps());
|
||||
return 0;
|
||||
}
|
||||
if (argc == 2 && std::strcmp(argv[1], "--cvt-pk-i16-only") == 0) {
|
||||
VulkanHarness vulkan;
|
||||
RunCase(&vulkan, Vop3CvtPkI16I32Captured());
|
||||
|
|
|
|||
|
|
@ -3668,6 +3668,39 @@ void TestNewShaderRecompilerVop1SdwaBfrev() {
|
|||
}
|
||||
}
|
||||
|
||||
void TestVop2SdwaMulI24Destination() {
|
||||
using namespace ShaderRecompiler::Decoder;
|
||||
const uint32_t captured[][2] = {
|
||||
{0x121818f9u, 0x04861488u}, {0x123434f9u, 0x0486146au}};
|
||||
for (uint32_t index = 0; index < 2; ++index) {
|
||||
Instruction decoded;
|
||||
DecodeInstruction(captured[index], 0, decoded);
|
||||
const uint32_t reg = index == 0 ? 12u : 26u;
|
||||
Check(decoded.opcode == Opcode::V_MUL_I32_I24 && decoded.word_count == 2 &&
|
||||
decoded.dst.kind == OperandKind::Vgpr && decoded.dst.reg == reg &&
|
||||
decoded.dst.sdwa_sel == 4 && decoded.dst.sdwa_dst_unused == 2 &&
|
||||
decoded.dst.explicit_sdwa_dst && !decoded.dst.clamp &&
|
||||
decoded.dst.omod == 0 && decoded.src0.sdwa_sel == 6 &&
|
||||
decoded.src1.kind == OperandKind::Vgpr && decoded.src1.reg == reg &&
|
||||
decoded.src1.sdwa_sel == 4 && !decoded.src1.sdwa_sext,
|
||||
"captured V_MUL_I32_I24 SDWA destination/source metadata is incorrect");
|
||||
Check(index == 0 ? decoded.src0.kind == OperandKind::IntegerInlineConstant &&
|
||||
decoded.src0.value == 8
|
||||
: decoded.src0.kind == OperandKind::VccLo,
|
||||
"captured V_MUL_I32_I24 SDWA scalar source is incorrect");
|
||||
}
|
||||
for (const uint32_t modifier : {
|
||||
0x04861788u, 0x04861c88u, 0x04871488u, 0x07861488u,
|
||||
0x04961488u, 0x04a61488u, 0x14861488u, 0x24861488u,
|
||||
0x04863488u, 0x04865488u}) {
|
||||
const uint32_t invalid[] = {captured[0][0], modifier};
|
||||
Instruction decoded;
|
||||
DecodeInstruction(invalid, 0, decoded);
|
||||
Check(decoded.opcode == Opcode::UNSUPPORTED && decoded.word_count == 2,
|
||||
"V_MUL_I32_I24 SDWA accepted reserved selectors or float modifiers");
|
||||
}
|
||||
}
|
||||
|
||||
void TestNewShaderRecompilerVop1SdwaNotDestination() {
|
||||
auto options = MakeCompileOptions(ShaderType::Pixel);
|
||||
|
||||
|
|
@ -14784,6 +14817,7 @@ int main() {
|
|||
TestNewShaderRecompilerF64AluEncodings();
|
||||
TestNewShaderRecompilerVop1SdwaBfrev();
|
||||
TestNewShaderRecompilerVop1SdwaNotDestination();
|
||||
TestVop2SdwaMulI24Destination();
|
||||
TestNewShaderRecompilerScalarMemoryBindingDomains();
|
||||
// Opcode semantics and optimized SPIR-V are exercised by
|
||||
// ShaderRecompilerComputeTests; keep the distinct decoder contract checks
|
||||
|
|
|
|||
Loading…
Reference in New Issue