shader: support DS_READ_U16_D16_HI (#356)

Decode the high-half D16 LDS read and route it through the existing unsigned-short load lowering. Represent the destination as a high-half partial write so the low 16 bits of the VGPR remain intact. Add captured-instruction decode coverage and a Vulkan execution regression that verifies the preserved half.

Co-authored-by: SueryRD <the.ai.tester2@gmail.com>
This commit is contained in:
GodsWill Dev 2026-08-29 02:39:45 -04:00 committed by GitHub
parent 715539804b
commit 18b6c9059b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 45 additions and 3 deletions

View File

@ -104,6 +104,7 @@ constexpr MemoryOpcodeInfo DS_OPCODE_LIST[] = {
{0x4fu, Opcode::DS_WRITE2ST64_B64, 4, 32}, {0x76u, Opcode::DS_READ_B64, 2, 32},
{0x77u, Opcode::DS_READ2_B64, 4, 32}, {0x78u, Opcode::DS_READ2ST64_B64, 4, 32},
{0xa6u, Opcode::DS_READ_U16_D16, 1, 16},
{0xa7u, Opcode::DS_READ_U16_D16_HI, 1, 16},
{0xb0u, Opcode::DS_WRITE_ADDTID_B32, 1, 32}, {0xb1u, Opcode::DS_READ_ADDTID_B32, 1, 32},
{0xdeu, Opcode::DS_WRITE_B96, 3, 32}, {0xdfu, Opcode::DS_WRITE_B128, 4, 32},
{0xfeu, Opcode::DS_READ_B96, 3, 32}, {0xffu, Opcode::DS_READ_B128, 4, 32},
@ -421,10 +422,11 @@ void DecodeDs(uint32_t pc, std::span<const uint32_t> code, uint32_t word_index,
}
DecodeVectorGpr(vdst, inst.dst);
if (inst.opcode == Opcode::DS_READ_U16_D16) {
if (inst.opcode == Opcode::DS_READ_U16_D16 ||
inst.opcode == Opcode::DS_READ_U16_D16_HI) {
// Native D16 reads update only the selected destination half. Reuse the partial
// destination representation so typed IR translation preserves the upper word.
inst.dst.sdwa_sel = 4u;
// destination representation so typed IR translation preserves the other half.
inst.dst.sdwa_sel = inst.opcode == Opcode::DS_READ_U16_D16 ? 4u : 5u;
}
DecodeVectorGpr(addr, inst.src0);
DecodeVectorGpr(data0, inst.src1);

View File

@ -497,6 +497,7 @@ enum class Opcode {
DS_READ_I16,
DS_READ_U16,
DS_READ_U16_D16,
DS_READ_U16_D16_HI,
DS_READ2_B32,
DS_READ2ST64_B32,
DS_READ_B32,

View File

@ -1050,6 +1050,7 @@ bool Translator::EmitMemory(const Decoder::Instruction& inst, std::string* error
case Decoder::Opcode::DS_READ_I16:
case Decoder::Opcode::DS_READ_U16:
case Decoder::Opcode::DS_READ_U16_D16:
case Decoder::Opcode::DS_READ_U16_D16_HI:
case Decoder::Opcode::DS_READ_B32:
case Decoder::Opcode::DS_READ_B64:
case Decoder::Opcode::DS_READ_B96:

View File

@ -12018,6 +12018,7 @@ CoverageClass ClassifyOpcode(ShaderOpcode opcode,
case Opcode::DS_READ_I16:
case Opcode::DS_READ_U16:
case Opcode::DS_READ_U16_D16:
case Opcode::DS_READ_U16_D16_HI:
case Opcode::DS_READ2_B32:
case Opcode::DS_READ_B32:
case Opcode::DS_READ_B64:
@ -18038,6 +18039,33 @@ TestCase DsReadU16D16CapturedPreservesHighHalf() {
return test;
}
TestCase DsReadU16D16HiCapturedPreservesLowHalf() {
using O = ShaderOpcode;
std::vector<u32> code;
AppendVMovU32(&code, 1, 0);
AppendVMovLiteral(&code, 2, 0x89abcdefu);
code.push_back(EncodeDs0(0x0d));
code.push_back(EncodeDs1(0, 2, 1)); // ds_write_b32 v2, v1
AppendVMovLiteral(&code, 5, 0x12345678u);
AppendVMovU32(&code, 6, 0);
code.push_back(0xda9c0000u);
code.push_back(0x05000006u); // captured ds_read_u16_d16_hi v5, v6
AppendStoreVgpr(&code, 5, 0);
AppendEnd(&code);
TestCase test{"DsReadU16D16HiCapturedPreservesLowHalf",
code,
std::vector<u32>(1, 0),
{0xcdef5678u},
{O::V_MOV_B32, O::DS_WRITE_B32, O::DS_READ_U16_D16_HI,
O::BUFFER_STORE_DWORD, O::S_ENDPGM}};
test.decoded_counts = {{"DS_READ_U16_D16_HI", 1}};
return test;
}
TestCase DsReadWrite2Variants() {
using O = ShaderOpcode;
@ -20556,6 +20584,7 @@ std::vector<TestCase> MakeCases() {
AddCase(FlatStoreVariants);
AddCase(DsReadWriteVariants);
AddCase(DsReadU16D16CapturedPreservesHighHalf);
AddCase(DsReadU16D16HiCapturedPreservesLowHalf);
AddCase(DsAppendConsumeUsesEncodedLdsSelector);
AddCase(DsAppendUsesEncodedGdsSelector);
AddCase(DsGdsSubdwordAndAtomicWrites);

View File

@ -4099,6 +4099,15 @@ void TestNewShaderDecoderArchitecture() {
Check(boot.opcode == Opcode::DS_SWIZZLE_B32 && boot.offset == 0xc480u,
"DS decoder rejected a captured boot-shader instruction");
const uint32_t d16_hi_ds[] = {0xda9c0000u, 0x05000006u};
Instruction d16_hi;
Check(DecodeInstruction(d16_hi_ds, 0u, d16_hi, &error), error.c_str());
Check(d16_hi.opcode == Opcode::DS_READ_U16_D16_HI &&
d16_hi.src_count == 1u && d16_hi.data_bits == 16u &&
d16_hi.dst.reg == 5u && d16_hi.dst.sdwa_sel == 5u &&
d16_hi.dst.sdwa_dst_unused == 2u && d16_hi.src0.reg == 6u,
"DS decoder rejected the captured high-half D16 read");
constexpr uint32_t packed_source_selectors[][2] = {
{0xcc0e0000u, 0x0c0a0300u}, // Source 0: instruction bit 59.
{0xcc0e0000u, 0x140a0300u}, // Source 1: instruction bit 60.