mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-28 13:56:59 +01:00
shader: generalize D16 buffer format component handling
This commit is contained in:
@@ -6,13 +6,14 @@ namespace Libs::Graphics::ShaderRecompiler::Decoder {
|
|||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
struct MemoryOpcodeInfo {
|
struct MemoryOpcodeInfo {
|
||||||
uint32_t encoding = 0;
|
uint32_t encoding = 0;
|
||||||
Opcode decoded = Opcode::UNSUPPORTED;
|
Opcode decoded = Opcode::UNSUPPORTED;
|
||||||
uint32_t data_dwords = 1;
|
uint32_t data_dwords = 1;
|
||||||
uint32_t data_bits = 32;
|
uint32_t data_bits = 32;
|
||||||
bool data_signed = false;
|
bool data_signed = false;
|
||||||
bool typed = false;
|
bool typed = false;
|
||||||
bool formatted = false;
|
bool formatted = false;
|
||||||
|
uint32_t data_components = 0; // D16 formats pack two components per dword
|
||||||
};
|
};
|
||||||
|
|
||||||
constexpr MemoryOpcodeInfo SMEM_OPCODE_LIST[] = {
|
constexpr MemoryOpcodeInfo SMEM_OPCODE_LIST[] = {
|
||||||
@@ -73,9 +74,9 @@ constexpr MemoryOpcodeInfo MUBUF_OPCODE_LIST[] = {
|
|||||||
{0x71u, Opcode::BUFFER_GL0_INV, 0, 0},
|
{0x71u, Opcode::BUFFER_GL0_INV, 0, 0},
|
||||||
{0x72u, Opcode::BUFFER_GL1_INV, 0, 0},
|
{0x72u, Opcode::BUFFER_GL1_INV, 0, 0},
|
||||||
{0x80u, Opcode::BUFFER_LOAD_FORMAT_D16_X, 1, 16, false, false, true},
|
{0x80u, Opcode::BUFFER_LOAD_FORMAT_D16_X, 1, 16, false, false, true},
|
||||||
{0x83u, Opcode::BUFFER_LOAD_FORMAT_D16_XYZW, 2, 16, false, false, true},
|
{0x83u, Opcode::BUFFER_LOAD_FORMAT_D16_XYZW, 2, 16, false, false, true, 4},
|
||||||
{0x84u, Opcode::BUFFER_STORE_FORMAT_D16_X, 1, 16, false, false, true},
|
{0x84u, Opcode::BUFFER_STORE_FORMAT_D16_X, 1, 16, false, false, true},
|
||||||
{0x87u, Opcode::BUFFER_STORE_FORMAT_D16_XYZW, 2, 16, false, false, true},
|
{0x87u, Opcode::BUFFER_STORE_FORMAT_D16_XYZW, 2, 16, false, false, true, 4},
|
||||||
};
|
};
|
||||||
|
|
||||||
constexpr MemoryOpcodeInfo MTBUF_OPCODE_LIST[] = {
|
constexpr MemoryOpcodeInfo MTBUF_OPCODE_LIST[] = {
|
||||||
@@ -158,12 +159,13 @@ void ApplyMemoryInfo(Instruction& inst, const MemoryOpcodeInfo* info) {
|
|||||||
inst.opcode = Opcode::UNSUPPORTED;
|
inst.opcode = Opcode::UNSUPPORTED;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
inst.opcode = info->decoded;
|
inst.opcode = info->decoded;
|
||||||
inst.data_dwords = info->data_dwords;
|
inst.data_dwords = info->data_dwords;
|
||||||
inst.data_bits = info->data_bits;
|
inst.data_bits = info->data_bits;
|
||||||
inst.data_signed = info->data_signed;
|
inst.data_signed = info->data_signed;
|
||||||
inst.typed = info->typed;
|
inst.typed = info->typed;
|
||||||
inst.formatted = info->formatted;
|
inst.formatted = info->formatted;
|
||||||
|
inst.data_components = info->data_components;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
@@ -323,12 +325,7 @@ void DecodeMubuf(uint32_t pc, std::span<const uint32_t> code, uint32_t word_inde
|
|||||||
}
|
}
|
||||||
|
|
||||||
DecodeVectorGpr(vdata, inst.dst);
|
DecodeVectorGpr(vdata, inst.dst);
|
||||||
if (inst.opcode == Opcode::BUFFER_LOAD_FORMAT_D16_XYZW ||
|
if (inst.opcode == Opcode::BUFFER_LOAD_UBYTE_D16 ||
|
||||||
inst.opcode == Opcode::BUFFER_STORE_FORMAT_D16_XYZW) {
|
|
||||||
inst.data_components = 4u;
|
|
||||||
}
|
|
||||||
if (inst.opcode == Opcode::BUFFER_LOAD_FORMAT_D16_X ||
|
|
||||||
inst.opcode == Opcode::BUFFER_LOAD_UBYTE_D16 ||
|
|
||||||
inst.opcode == Opcode::BUFFER_LOAD_SHORT_D16 ||
|
inst.opcode == Opcode::BUFFER_LOAD_SHORT_D16 ||
|
||||||
inst.opcode == Opcode::BUFFER_LOAD_SHORT_D16_HI) {
|
inst.opcode == Opcode::BUFFER_LOAD_SHORT_D16_HI) {
|
||||||
inst.dst.sdwa_sel = inst.opcode == Opcode::BUFFER_LOAD_SHORT_D16_HI ? 5u : 4u;
|
inst.dst.sdwa_sel = inst.opcode == Opcode::BUFFER_LOAD_SHORT_D16_HI ? 5u : 4u;
|
||||||
|
|||||||
@@ -455,12 +455,17 @@ void Translator::BUFFER_LOAD(const Decoder::Instruction& inst) {
|
|||||||
AddMemoryInfo(memory, inst.pc));
|
AddMemoryInfo(memory, inst.pc));
|
||||||
if (bits != 32u) {
|
if (bits != 32u) {
|
||||||
WriteOperand(inst.dst, WidenSubdword(loaded, bits, sign));
|
WriteOperand(inst.dst, WidenSubdword(loaded, bits, sign));
|
||||||
} else if (memory.data_dwords == 1u) {
|
return;
|
||||||
WriteOperand(inst.dst, loaded);
|
}
|
||||||
} else {
|
for (uint32_t component = 0; component < memory.data_dwords; component++) {
|
||||||
for (uint32_t component = 0; component < memory.data_dwords; component++) {
|
const auto dst = OffsetOperand(inst.dst, component);
|
||||||
WriteOperand(OffsetOperand(inst.dst, component),
|
const auto value =
|
||||||
ir.CompositeExtract(loaded, component));
|
memory.data_dwords == 1u ? IR::U32(loaded) : ir.CompositeExtract(loaded, component);
|
||||||
|
// D16 formats with an odd component count keep the high half of their final VGPR.
|
||||||
|
if (memory.data_bits == 16u && component * 2u + 1u == memory.component_count) {
|
||||||
|
Write16Bits(dst, value);
|
||||||
|
} else {
|
||||||
|
WriteOperand(dst, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16068,6 +16068,23 @@ void TestCapturedBufferStoreFormatD16HiXDecode() {
|
|||||||
"captured BUFFER_STORE_FORMAT_D16_HI_X lost its high half, index, or coherence flags");
|
"captured BUFFER_STORE_FORMAT_D16_HI_X lost its high half, index, or coherence flags");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TestCapturedBufferLoadD16XyzwDecode() {
|
||||||
|
namespace Decoder = ShaderRecompiler::Decoder;
|
||||||
|
const uint32_t code[] = {0xe20c2000u, 0x8001100cu};
|
||||||
|
Decoder::Instruction inst;
|
||||||
|
Decoder::DecodeInstruction(code, 0, inst);
|
||||||
|
Check(inst.opcode == Decoder::Opcode::BUFFER_LOAD_FORMAT_D16_XYZW &&
|
||||||
|
inst.word_count == 2 && inst.data_dwords == 2 && inst.data_bits == 16 &&
|
||||||
|
inst.data_components == 4 && inst.formatted && !inst.typed,
|
||||||
|
"captured D16 XYZW load lost its four components in two packed VGPRs");
|
||||||
|
Check(inst.dst.kind == Decoder::OperandKind::Vgpr && inst.dst.reg == 16 &&
|
||||||
|
inst.dst.sdwa_sel == 6 &&
|
||||||
|
inst.src0.kind == Decoder::OperandKind::Vgpr && inst.src0.reg == 12 &&
|
||||||
|
inst.src1.kind == Decoder::OperandKind::Sgpr && inst.src1.reg == 4 &&
|
||||||
|
inst.idxen && !inst.offen,
|
||||||
|
"captured D16 XYZW load lost its full destination VGPRs or index");
|
||||||
|
}
|
||||||
|
|
||||||
void TestCapturedBufferStoreD16XyzwDecode() {
|
void TestCapturedBufferStoreD16XyzwDecode() {
|
||||||
namespace Decoder = ShaderRecompiler::Decoder;
|
namespace Decoder = ShaderRecompiler::Decoder;
|
||||||
const uint32_t code[] = {0xe21c6000u, 0x8002000eu};
|
const uint32_t code[] = {0xe21c6000u, 0x8002000eu};
|
||||||
@@ -16883,6 +16900,7 @@ int main() {
|
|||||||
TestCapturedBufferLoadUbyteD16Decode();
|
TestCapturedBufferLoadUbyteD16Decode();
|
||||||
TestCapturedBufferStoreShortD16HiDecode();
|
TestCapturedBufferStoreShortD16HiDecode();
|
||||||
TestCapturedBufferStoreFormatD16HiXDecode();
|
TestCapturedBufferStoreFormatD16HiXDecode();
|
||||||
|
TestCapturedBufferLoadD16XyzwDecode();
|
||||||
TestCapturedBufferStoreD16XyzwDecode();
|
TestCapturedBufferStoreD16XyzwDecode();
|
||||||
TestNewShaderRecompilerUnsupportedMemoryDecode();
|
TestNewShaderRecompilerUnsupportedMemoryDecode();
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user