shader: allow partial SDWA destinations for V_NOT_B32 (#684)

This commit is contained in:
Elija 2026-09-20 16:21:40 +02:00 committed by GitHub
parent e930657bf6
commit cfb110e0aa
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 83 additions and 1 deletions

View File

@ -521,7 +521,8 @@ constexpr Vop1SdwaRule VOP1_SDWA_RULES[] = {
{Opcode::V_CVT_F32_U32, SdwaSelBytes() | SdwaSelWords() | SdwaSelFull(), 0, 0, false},
{Opcode::V_CVT_F32_I32, SdwaSelBytes() | SdwaSelWords() | SdwaSelFull(), 0, 0, false},
{Opcode::V_CVT_F32_UBYTE0, SdwaSelBytes() | SdwaSelWords() | SdwaSelFull(), 0, 0, false},
{Opcode::V_NOT_B32, SdwaSelBytes() | SdwaSelWords() | SdwaSelFull(), 0, 0, false},
{Opcode::V_NOT_B32, SdwaSelBytes() | SdwaSelWords() | SdwaSelFull(), SdwaSelBytes() | SdwaSelWords(),
SdwaSelFull(), false},
{Opcode::V_FFBL_B32, SdwaSelBytes() | SdwaSelWords() | SdwaSelFull(), 0, 0, false},
{Opcode::V_CVT_F32_F16, SdwaSelWords() | SdwaSelFull(), 0, 0, true},
{Opcode::V_CVT_F16_F32, SdwaSelBytes() | SdwaSelWords() | SdwaSelFull(), SdwaSelWords(),

View File

@ -18065,6 +18065,29 @@ TestCase Vop1SdwaNotCapturedByte0Source() {
return test;
}
TestCase Vop1SdwaNotPreservesHighWordDestination() {
using O = ShaderOpcode;
std::vector<u32> code;
AppendBufferLoadDword(&code, 0, 30);
AppendVMovLiteral(&code, 3, 0xabcd5555u);
code.push_back(0x7e066ef9u);
code.push_back(0x00061400u);
AppendStoreVgpr(&code, 3, 0);
AppendEnd(&code);
TestCase test;
test.name = "Vop1SdwaNotPreservesHighWordDestination";
test.code = std::move(code);
test.initial = {0x12345678u};
test.expected = {0xabcda987u};
test.opcodes = {O::BUFFER_LOAD_DWORD, O::V_MOV_B32, O::V_NOT_B32,
O::BUFFER_STORE_DWORD, O::S_ENDPGM};
test.ir_counts = {{" = BitwiseNot32 ", 1}};
test.required_spirv = {"OpNot"};
return test;
}
TestCase Vop1SdwaMovByteDestinations() {
using O = ShaderOpcode;
@ -27176,6 +27199,7 @@ std::vector<TestCase> MakeCases() {
AddCase(VectorFfbhI32NativeAndVop3OnGpu);
AddCase(Vop1SdwaFfblCapturedHighWordSource);
AddCase(Vop1SdwaNotCapturedByte0Source);
AddCase(Vop1SdwaNotPreservesHighWordDestination);
AddCase(Vop1SdwaMovByteDestinations);
AddCase(Vop2SdwaSubNcExactByte2Destination);
AddCase(Vop2SdwaAddNcCapturedHighWordDestination);

View File

@ -3435,6 +3435,62 @@ void TestNewShaderRecompilerCapturedVop1SdwaByteConvert() {
CheckSpirvBinaryValidates(result.spirv);
}
void TestNewShaderRecompilerVop1SdwaNotDestination() {
auto options = MakeCompileOptions(ShaderType::Pixel);
const auto check_destination = [&](uint32_t modifier, uint32_t dst_sel,
uint32_t dst_unused) {
const uint32_t shader[] = {
0x7e066ef9u, modifier, EncodeExp0(0x00, 0x1),
EncodeExp1(3, 0, 0, 0), EncodeSopp(0x01),
};
ShaderRecompiler::Decoder::Instruction decoded;
ShaderRecompiler::Decoder::DecodeInstruction(shader, 0, decoded);
Check(decoded.opcode == ShaderRecompiler::Decoder::Opcode::V_NOT_B32,
"V_NOT_B32 SDWA opcode did not decode");
Check(decoded.word_count == 2u,
"V_NOT_B32 SDWA instruction has the wrong word count");
Check(decoded.dst.kind == ShaderRecompiler::Decoder::OperandKind::Vgpr &&
decoded.dst.reg == 3u && decoded.dst.sdwa_sel == dst_sel &&
decoded.dst.sdwa_dst_unused == dst_unused &&
decoded.dst.explicit_sdwa_dst,
"V_NOT_B32 SDWA destination metadata is incorrect");
Check(decoded.src0.kind == ShaderRecompiler::Decoder::OperandKind::Vgpr &&
decoded.src0.reg == 0u && decoded.src0.sdwa_sel == 6u &&
!decoded.src0.negate && !decoded.src0.absolute,
"V_NOT_B32 SDWA source metadata is incorrect");
auto result = RecompileForTest(shader, options);
CheckSpirvBinaryValidates(result.spirv);
};
check_destination(0x00061400u, 4u, 2u);
check_destination(0x00060500u, 5u, 0u);
check_destination(0x00060000u, 0u, 0u);
const auto check_rejected = [&](uint32_t modifier, const char *message) {
const uint32_t instruction[] = {0x7e066ef9u, modifier};
ShaderRecompiler::Decoder::Instruction decoded;
ShaderRecompiler::Decoder::DecodeInstruction(instruction, 0, decoded);
Check(decoded.word_count == 2u &&
decoded.opcode == ShaderRecompiler::Decoder::Opcode::UNSUPPORTED,
message);
};
check_rejected(0x00060700u, "V_NOT_B32 SDWA accepted destination selector 7");
check_rejected(0x00070600u, "V_NOT_B32 SDWA accepted source selector 7");
check_rejected(0x00061c00u,
"V_NOT_B32 SDWA accepted destination unused value 3");
check_rejected(0x00160400u, "V_NOT_B32 SDWA accepted source negation");
check_rejected(0x00260400u, "V_NOT_B32 SDWA accepted source absolute");
check_rejected(0x00062400u, "V_NOT_B32 SDWA accepted clamp");
check_rejected(0x00064400u, "V_NOT_B32 SDWA accepted output modifier");
check_rejected(0x00000400u,
"V_NOT_B32 SDWA partial destination accepted a byte source");
}
void TestNewShaderRecompilerBootB16PackedAndSdwaOpcodes() {
const uint32_t shader[] = {
0xd7070001u,
@ -13397,6 +13453,7 @@ int main() {
TestNewShaderRecompilerDsReadWrite2Translation();
TestNewShaderRecompilerDsWideAndAtomicTranslation();
TestNewShaderRecompilerCapturedVop1SdwaByteConvert();
TestNewShaderRecompilerVop1SdwaNotDestination();
TestNewShaderRecompilerScalarMemoryBindingDomains();
// Opcode semantics and optimized SPIR-V are exercised by
// ShaderRecompilerComputeTests; keep the distinct decoder contract checks