mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-28 05:46:56 +01:00
graphics: implement RDNA2 D16 image packing
This commit is contained in:
@@ -310,6 +310,7 @@ void DecodeMimg(uint32_t pc, std::span<const uint32_t> code, uint32_t word_index
|
||||
const uint32_t srsrc = (word1 >> 16u) & 0x1fu;
|
||||
const uint32_t ssamp = (word1 >> 21u) & 0x1fu;
|
||||
const bool a16 = ((word1 >> 30u) & 0x1u) != 0u;
|
||||
const bool d16 = ((word1 >> 31u) & 0x1u) != 0u;
|
||||
const auto* sample = LookupSample(opcode);
|
||||
const auto* gather = LookupGather(opcode);
|
||||
const auto* atomic = LookupAtomic(opcode);
|
||||
@@ -321,7 +322,9 @@ void DecodeMimg(uint32_t pc, std::span<const uint32_t> code, uint32_t word_index
|
||||
inst.opcode_id = opcode;
|
||||
inst.opcode = DecodeMimgOpcode(opcode, sample, gather, atomic);
|
||||
inst.dmask = (word0 >> 8u) & 0xfu;
|
||||
inst.data_dwords = gather != nullptr ? 4u : CountDmaskComponents(inst.dmask);
|
||||
inst.data_components = gather != nullptr ? 4u : CountDmaskComponents(inst.dmask);
|
||||
inst.data_bits = d16 ? 16u : 32u;
|
||||
inst.data_dwords = d16 ? (inst.data_components + 1u) / 2u : inst.data_components;
|
||||
inst.glc = ((word0 >> 13u) & 1u) != 0;
|
||||
inst.slc = ((word0 >> 25u) & 1u) != 0;
|
||||
inst.image_sample_flags = DecodeMimgSampleFlags(sample, gather);
|
||||
@@ -344,6 +347,11 @@ void DecodeMimg(uint32_t pc, std::span<const uint32_t> code, uint32_t word_index
|
||||
SetUnsupported(inst, Family::MIMG, opcode,
|
||||
"MIMG image gather requires exactly one dmask bit");
|
||||
}
|
||||
const bool supports_d16 = sample != nullptr || gather != nullptr || opcode == 0x00u ||
|
||||
opcode == 0x01u || opcode == 0x08u || opcode == 0x09u;
|
||||
if (d16 && !supports_d16) {
|
||||
SetUnsupported(inst, Family::MIMG, opcode, "MIMG opcode does not support D16 data");
|
||||
}
|
||||
|
||||
DecodeVectorGpr(vdata, inst.dst);
|
||||
DecodeVectorGpr(vaddr, inst.src0);
|
||||
|
||||
@@ -154,6 +154,9 @@ std::string FormatMimg(const Instruction& inst) {
|
||||
OperandToString(inst.dst).c_str(), OperandToString(inst.src0).c_str(),
|
||||
OperandToString(inst.src1).c_str(), OperandToString(inst.src2).c_str(),
|
||||
inst.dmask, ImageDimensionToString(inst.image_dimension));
|
||||
if (inst.data_bits == 16u) {
|
||||
text += " d16=1";
|
||||
}
|
||||
switch (inst.opcode) {
|
||||
case Opcode::IMAGE_SAMPLE:
|
||||
case Opcode::IMAGE_GATHER4_LZ:
|
||||
|
||||
@@ -648,6 +648,7 @@ struct Instruction {
|
||||
uint32_t offset = 0;
|
||||
uint32_t secondary_offset = 0;
|
||||
uint32_t dmask = 0;
|
||||
uint32_t data_components = 0;
|
||||
uint32_t data_dwords = 1;
|
||||
uint32_t data_bits = 32;
|
||||
uint32_t data_format = 0;
|
||||
|
||||
@@ -94,9 +94,17 @@ IR::Value Translator::ConstructU32x4(const IR::Operand& base, uint32_t count) {
|
||||
{components[0], components[1], components[2], components[3]});
|
||||
}
|
||||
|
||||
void Translator::WriteImageComponents(const IR::Operand& dst, IR::Value value, uint32_t dmask,
|
||||
uint32_t component_limit) {
|
||||
const auto mask = dmask != 0u ? dmask : 1u;
|
||||
void Translator::WriteImageComponents(const IR::Operand& dst, IR::Value value,
|
||||
const IR::MemoryInfo& memory, uint32_t component_limit) {
|
||||
if (memory.data_bits == 16u) {
|
||||
for (uint32_t index = 0; index < memory.data_dwords; index++) {
|
||||
WriteOperand(OffsetOperand(dst, index),
|
||||
ir.Emit(IR::ValueOpcode::CompositeExtractU32x4,
|
||||
{value, IR::Value(index)}));
|
||||
}
|
||||
return;
|
||||
}
|
||||
const auto mask = memory.dmask != 0u ? memory.dmask : 1u;
|
||||
uint32_t dst_index = 0;
|
||||
for (uint32_t component = 0; component < component_limit; component++) {
|
||||
if (((mask >> component) & 1u) == 0u) {
|
||||
@@ -435,20 +443,20 @@ bool Translator::TranslateImageMemory(const IR::Instruction& inst) {
|
||||
case IR::Opcode::ImageGetResinfo: {
|
||||
const auto result =
|
||||
ir.Emit(IR::ValueOpcode::ImageQueryDimensions, {resource, address}, flags);
|
||||
WriteImageComponents(inst.dst, result, inst.memory.dmask, 4u);
|
||||
WriteImageComponents(inst.dst, result, inst.memory, 4u);
|
||||
return true;
|
||||
}
|
||||
case IR::Opcode::ImageGetLod: {
|
||||
const auto sampler = GetSamplerResource(inst.memory);
|
||||
const auto result =
|
||||
ir.Emit(IR::ValueOpcode::ImageQueryLod, {resource, sampler, address}, flags);
|
||||
WriteImageComponents(inst.dst, result, inst.memory.dmask, 2u);
|
||||
WriteImageComponents(inst.dst, result, inst.memory, 2u);
|
||||
return true;
|
||||
}
|
||||
case IR::Opcode::ImageLoad: {
|
||||
const auto result =
|
||||
ir.Emit(IR::ValueOpcode::ImageRead, {resource, address, ir.GetExec()}, flags);
|
||||
WriteImageComponents(inst.dst, result, inst.memory.dmask, 4u);
|
||||
WriteImageComponents(inst.dst, result, inst.memory, 4u);
|
||||
return true;
|
||||
}
|
||||
case IR::Opcode::ImageStore: {
|
||||
@@ -465,7 +473,7 @@ bool Translator::TranslateImageMemory(const IR::Instruction& inst) {
|
||||
const auto result = ir.Emit(opcode, {resource, sampler, address}, flags);
|
||||
const bool dref =
|
||||
(inst.memory.image_sample_flags & Decoder::ImageSampleFlagCompare) != 0u;
|
||||
if (inst.op == IR::Opcode::ImageSample && dref) {
|
||||
if (inst.op == IR::Opcode::ImageSample && dref && inst.memory.data_bits != 16u) {
|
||||
const auto component =
|
||||
ir.Emit(IR::ValueOpcode::CompositeExtractU32x4, {result, IR::Value(0u)});
|
||||
for (uint32_t index = 0; index < inst.memory.data_dwords; index++) {
|
||||
@@ -478,7 +486,7 @@ bool Translator::TranslateImageMemory(const IR::Instruction& inst) {
|
||||
{result, IR::Value(index)}));
|
||||
}
|
||||
} else {
|
||||
WriteImageComponents(inst.dst, result, inst.memory.dmask, 4u);
|
||||
WriteImageComponents(inst.dst, result, inst.memory, 4u);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -75,8 +75,8 @@ private:
|
||||
IR::Value GetSamplerResource(const IR::MemoryInfo& memory);
|
||||
IR::Value MakeImageAddress(const IR::Instruction& inst, const IR::Operand& base);
|
||||
IR::Value ConstructU32x4(const IR::Operand& base, uint32_t count);
|
||||
void WriteImageComponents(const IR::Operand& dst, IR::Value value, uint32_t dmask,
|
||||
uint32_t component_limit);
|
||||
void WriteImageComponents(const IR::Operand& dst, IR::Value value,
|
||||
const IR::MemoryInfo& memory, uint32_t component_limit);
|
||||
IR::ValueOpcode ImageAtomicOpcode(IR::Opcode opcode);
|
||||
BufferAddress ReadBufferAddress(const IR::Instruction& inst, uint32_t source_offset);
|
||||
IR::U32 WidenSubdword(IR::Value value, uint32_t bits, bool sign);
|
||||
|
||||
Reference in New Issue
Block a user