feat(shader): rdna export op decoder impl

This commit is contained in:
boykopovar 2026-09-14 16:02:29 +03:00
parent 6e9ad53bd5
commit 6da6ebad97
2 changed files with 82 additions and 2 deletions

View File

@ -42,6 +42,10 @@ struct RdnaInstruction {
std::uint32_t dataDwordCount;
bool clampResult;
bool is64Bit;
std::uint32_t exportTarget;
std::uint32_t exportEnableMask;
bool exportIsCompressed;
bool exportIsLast;
};
}

View File

@ -3,8 +3,84 @@
namespace ShaderRecompiler {
RdnaInstruction DecodeRdnaExportOp(std::span<const std::uint32_t> code, std::uint32_t wordIndex) {
throw std::runtime_error("DecodeRdnaExportOp not implemented");
namespace {
[[nodiscard]] RdnaOpcode MapExportTargetToOpcode(std::uint32_t target) {
if (target <= 7u) {
return RdnaOpcode::ExpMrt;
}
if (target >= 12u && target <= 15u) {
return RdnaOpcode::ExpPos;
}
if (target >= 32u && target <= 63u) {
return RdnaOpcode::ExpParam;
}
throw std::runtime_error("unsupported export target");
}
[[nodiscard]] RdnaOperand DecodeExportSourceRegister(std::uint32_t reg) {
RdnaOperand operand{};
operand.kind = RdnaOperandKind::VectorRegister;
operand.reg = reg;
operand.value = 0;
operand.negate = false;
operand.absolute = false;
return operand;
}
}
RdnaInstruction DecodeRdnaExportOp(std::span<const std::uint32_t> code, std::uint32_t wordIndex) {
if (wordIndex + 1u >= code.size()) {
throw std::runtime_error("truncated export instruction");
}
const std::uint32_t word0 = code[wordIndex];
const std::uint32_t word1 = code[wordIndex + 1u];
const std::uint32_t target = (word0 >> 4u) & 0x3Fu;
const std::uint32_t en = word0 & 0xFu;
const bool compr = ((word0 >> 10u) & 0x1u) != 0u;
const bool done = ((word0 >> 11u) & 0x1u) != 0u;
const RdnaOpcode op = MapExportTargetToOpcode(target);
RdnaInstruction instruction{};
instruction.op = op;
instruction.programCounter = wordIndex * 4u;
instruction.destination = RdnaOperand{};
instruction.destination.kind = RdnaOperandKind::Null;
instruction.destination.reg = 0;
instruction.destination.value = 0;
instruction.destination.negate = false;
instruction.destination.absolute = false;
instruction.source0 = DecodeExportSourceRegister(word1 & 0xFFu);
instruction.source1 = DecodeExportSourceRegister((word1 >> 8u) & 0xFFu);
instruction.source2 = DecodeExportSourceRegister((word1 >> 16u) & 0xFFu);
instruction.source3 = DecodeExportSourceRegister((word1 >> 24u) & 0xFFu);
instruction.branchOffset = 0;
instruction.memoryOffset = 0;
if (en == 0u) {
instruction.dataDwordCount = 0u;
} else if (compr) {
instruction.dataDwordCount = 2u;
} else {
instruction.dataDwordCount = 4u;
}
instruction.clampResult = false;
instruction.is64Bit = false;
instruction.exportTarget = target;
instruction.exportEnableMask = en;
instruction.exportIsCompressed = compr;
instruction.exportIsLast = done;
return instruction;
}
}