mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-26 12:56:54 +01:00
795 lines
31 KiB
C++
795 lines
31 KiB
C++
#include "common/assert.h"
|
|
#include "graphics/shader/recompiler/BufferFormat.h"
|
|
#include "graphics/shader/recompiler/ir/ShaderIR.h"
|
|
#include "graphics/shader/recompiler/ir/ShaderIRInternal.h"
|
|
|
|
#include <algorithm>
|
|
#include <fmt/format.h>
|
|
#include <utility>
|
|
|
|
namespace Libs::Graphics::ShaderRecompiler::IR {
|
|
namespace {
|
|
|
|
Opcode BufferLoadOpcode(const Decoder::Instruction& decoded) {
|
|
switch (decoded.data_bits) {
|
|
case 8u: return decoded.data_signed ? Opcode::BufferLoadSbyte : Opcode::BufferLoadUbyte;
|
|
case 16u: return decoded.data_signed ? Opcode::BufferLoadSshort : Opcode::BufferLoadUshort;
|
|
default: return Opcode::BufferLoadDword;
|
|
}
|
|
}
|
|
|
|
Opcode BufferStoreOpcode(uint32_t data_bits) {
|
|
switch (data_bits) {
|
|
case 8u: return Opcode::BufferStoreByte;
|
|
case 16u: return Opcode::BufferStoreShort;
|
|
default: return Opcode::BufferStoreDword;
|
|
}
|
|
}
|
|
|
|
Opcode DsReadOpcode(const Decoder::Instruction& decoded) {
|
|
switch (decoded.data_bits) {
|
|
case 8u: return decoded.data_signed ? Opcode::DsReadSbyte : Opcode::DsReadUbyte;
|
|
case 16u: return decoded.data_signed ? Opcode::DsReadSshort : Opcode::DsReadUshort;
|
|
default: return Opcode::DsReadB32;
|
|
}
|
|
}
|
|
|
|
Opcode FlatLoadOpcode(const Decoder::Instruction& decoded) {
|
|
switch (decoded.data_bits) {
|
|
case 8u: return decoded.data_signed ? Opcode::FlatLoadSbyte : Opcode::FlatLoadUbyte;
|
|
case 16u: return decoded.data_signed ? Opcode::FlatLoadSshort : Opcode::FlatLoadUshort;
|
|
default: return Opcode::FlatLoadDword;
|
|
}
|
|
}
|
|
|
|
Opcode FlatStoreOpcode(uint32_t data_bits) {
|
|
switch (data_bits) {
|
|
case 8u: return Opcode::FlatStoreByte;
|
|
case 16u: return Opcode::FlatStoreShort;
|
|
default: return Opcode::FlatStoreDword;
|
|
}
|
|
}
|
|
|
|
Opcode DsWriteOpcode(uint32_t data_bits) {
|
|
switch (data_bits) {
|
|
case 8u: return Opcode::DsWriteByte;
|
|
case 16u: return Opcode::DsWriteShort;
|
|
default: return Opcode::DsWriteB32;
|
|
}
|
|
}
|
|
|
|
Opcode LoweredImageOpcode(Decoder::Opcode opcode) {
|
|
switch (opcode) {
|
|
case Decoder::Opcode::IMAGE_GET_RESINFO: return Opcode::ImageGetResinfo;
|
|
case Decoder::Opcode::IMAGE_GET_LOD: return Opcode::ImageGetLod;
|
|
case Decoder::Opcode::IMAGE_LOAD:
|
|
case Decoder::Opcode::IMAGE_LOAD_MIP: return Opcode::ImageLoad;
|
|
case Decoder::Opcode::IMAGE_GATHER4_LZ:
|
|
case Decoder::Opcode::IMAGE_GATHER4_C:
|
|
case Decoder::Opcode::IMAGE_GATHER4_C_LZ:
|
|
case Decoder::Opcode::IMAGE_GATHER4_LZ_O:
|
|
case Decoder::Opcode::IMAGE_GATHER4_C_O:
|
|
case Decoder::Opcode::IMAGE_GATHER4_C_LZ_O:
|
|
case Decoder::Opcode::IMAGE_GATHER4H: return Opcode::ImageGather4;
|
|
default: return Opcode::ImageSample;
|
|
}
|
|
}
|
|
|
|
bool LowerScalarMemoryLoadDword(const Decoder::Instruction& decoded, BasicBlock& block, Opcode op,
|
|
std::string* error) {
|
|
for (uint32_t i = 0; i < decoded.data_dwords; i++) {
|
|
Instruction inst;
|
|
inst.pc = decoded.pc;
|
|
inst.op = op;
|
|
inst.src_count = 1;
|
|
const auto kind =
|
|
op == Opcode::SLoadDword ? ResourceKind::ScalarAddress : ResourceKind::ScalarBuffer;
|
|
inst.memory = OffsetMemoryInfo(decoded, kind, i);
|
|
// Raw s_load uses a two-SGPR pointer base; s_buffer_load uses a four-SGPR
|
|
// descriptor resource index.
|
|
inst.memory.resource = op == Opcode::SLoadDword ? RawScalarLoadBase(decoded.src0)
|
|
: ResourceIndexFromOperand(decoded.src0);
|
|
if (!LowerRegisterOperand(OffsetDecodedRegister(decoded.dst, i), inst.dst, error) ||
|
|
!LowerSourceOperand(decoded.src1, inst.src[0], error)) {
|
|
return false;
|
|
}
|
|
block.instructions.push_back(inst);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool LowerBufferAddressSources(const Decoder::Instruction& decoded, Instruction& inst,
|
|
uint32_t first_src, std::string* error) {
|
|
uint32_t src = first_src;
|
|
if (decoded.idxen) {
|
|
if (!LowerSourceOperand(decoded.src0, inst.src[src++], error)) {
|
|
return false;
|
|
}
|
|
}
|
|
if (decoded.offen) {
|
|
const auto offset_source =
|
|
decoded.idxen ? OffsetDecodedRegister(decoded.src0, 1) : decoded.src0;
|
|
if (!LowerSourceOperand(offset_source, inst.src[src++], error)) {
|
|
return false;
|
|
}
|
|
}
|
|
if (!LowerSourceOperand(decoded.src2, inst.src[src++], error)) {
|
|
return false;
|
|
}
|
|
inst.src_count = src;
|
|
return true;
|
|
}
|
|
|
|
bool LowerBufferLoad(const Decoder::Instruction& decoded, BasicBlock& block, std::string* error) {
|
|
Instruction inst;
|
|
inst.pc = decoded.pc;
|
|
inst.op = BufferLoadOpcode(decoded);
|
|
inst.memory = MemoryInfoFromDecoded(decoded, ResourceKind::Buffer);
|
|
if (!LowerRegisterOperand(decoded.dst, inst.dst, error) ||
|
|
!LowerBufferAddressSources(decoded, inst, 0, error)) {
|
|
return false;
|
|
}
|
|
block.instructions.push_back(inst);
|
|
return true;
|
|
}
|
|
|
|
bool LowerBufferStore(const Decoder::Instruction& decoded, BasicBlock& block, std::string* error) {
|
|
Instruction inst;
|
|
inst.pc = decoded.pc;
|
|
inst.op = BufferStoreOpcode(decoded.data_bits);
|
|
inst.memory = MemoryInfoFromDecoded(decoded, ResourceKind::Buffer);
|
|
inst.dst.kind = OperandKind::Null;
|
|
if (!LowerSourceOperand(decoded.dst, inst.src[0], error) ||
|
|
!LowerBufferAddressSources(decoded, inst, 1, error)) {
|
|
return false;
|
|
}
|
|
block.instructions.push_back(inst);
|
|
return true;
|
|
}
|
|
|
|
bool LowerBufferAtomicDword(const Decoder::Instruction& decoded, BasicBlock& block, Opcode op,
|
|
std::string* error) {
|
|
Instruction inst;
|
|
inst.pc = decoded.pc;
|
|
inst.op = op;
|
|
inst.memory = MemoryInfoFromDecoded(decoded, ResourceKind::Buffer);
|
|
inst.dst.kind = OperandKind::Null;
|
|
if ((decoded.glc && !LowerRegisterOperand(decoded.dst, inst.dst, error)) ||
|
|
!LowerSourceOperand(decoded.dst, inst.src[0], error) ||
|
|
!LowerBufferAddressSources(decoded, inst, 1, error)) {
|
|
return false;
|
|
}
|
|
block.instructions.push_back(inst);
|
|
return true;
|
|
}
|
|
|
|
ResourceKind DsMemoryKind(const Decoder::Instruction& decoded) {
|
|
return decoded.gds ? ResourceKind::Gds : ResourceKind::Lds;
|
|
}
|
|
|
|
bool LowerDsRead(const Decoder::Instruction& decoded, BasicBlock& block, std::string* error) {
|
|
const auto ir_op = DsReadOpcode(decoded);
|
|
Instruction inst;
|
|
inst.pc = decoded.pc;
|
|
inst.op = ir_op;
|
|
inst.src_count = 1;
|
|
inst.memory = MemoryInfoFromDecoded(decoded, DsMemoryKind(decoded));
|
|
if (!LowerRegisterOperand(decoded.dst, inst.dst, error) ||
|
|
!LowerSourceOperand(decoded.src0, inst.src[0], error)) {
|
|
return false;
|
|
}
|
|
block.instructions.push_back(inst);
|
|
return true;
|
|
}
|
|
|
|
bool LowerDsRead2(const Decoder::Instruction& decoded, BasicBlock& block, uint32_t dwords_per_read,
|
|
std::string* error) {
|
|
Instruction inst;
|
|
inst.pc = decoded.pc;
|
|
inst.op = Opcode::DsRead2B32;
|
|
inst.src_count = 1;
|
|
inst.memory = MemoryInfoFromDecoded(decoded, DsMemoryKind(decoded));
|
|
inst.memory.data_dwords = dwords_per_read * 2u;
|
|
if (!LowerRegisterOperand(decoded.dst, inst.dst, error) ||
|
|
!LowerSourceOperand(decoded.src0, inst.src[0], error)) {
|
|
return false;
|
|
}
|
|
block.instructions.push_back(inst);
|
|
return true;
|
|
}
|
|
|
|
bool LowerDsAtomicU32(const Decoder::Instruction& decoded, BasicBlock& block, Opcode op,
|
|
bool return_old, std::string* error) {
|
|
Instruction inst;
|
|
inst.pc = decoded.pc;
|
|
inst.op = op;
|
|
inst.src_count = 2;
|
|
inst.memory = MemoryInfoFromDecoded(decoded, DsMemoryKind(decoded));
|
|
inst.dst.kind = return_old ? OperandKind::Register : OperandKind::Null;
|
|
if ((return_old && !LowerRegisterOperand(decoded.dst, inst.dst, error)) ||
|
|
!LowerSourceOperand(decoded.src1, inst.src[0], error) ||
|
|
!LowerSourceOperand(decoded.src0, inst.src[1], error)) {
|
|
return false;
|
|
}
|
|
block.instructions.push_back(inst);
|
|
return true;
|
|
}
|
|
|
|
bool LowerDsSwizzleB32(const Decoder::Instruction& decoded, BasicBlock& block, std::string* error) {
|
|
Instruction inst;
|
|
inst.pc = decoded.pc;
|
|
inst.op = Opcode::DsSwizzleB32;
|
|
inst.src_count = 2;
|
|
inst.src[1].kind = OperandKind::ImmediateU32;
|
|
inst.src[1].imm = decoded.offset & 0xffffu;
|
|
if (!LowerRegisterOperand(decoded.dst, inst.dst, error) ||
|
|
!LowerSourceOperand(decoded.src0, inst.src[0], error)) {
|
|
return false;
|
|
}
|
|
block.instructions.push_back(inst);
|
|
return true;
|
|
}
|
|
|
|
bool LowerDsFloatMinMaxF32(const Decoder::Instruction& decoded, BasicBlock& block, Opcode op,
|
|
std::string* error) {
|
|
Instruction inst;
|
|
inst.pc = decoded.pc;
|
|
inst.op = op;
|
|
inst.src_count = 2;
|
|
inst.memory = MemoryInfoFromDecoded(decoded, DsMemoryKind(decoded));
|
|
inst.memory.resource = 0;
|
|
inst.dst.kind = OperandKind::Null;
|
|
if (!LowerSourceOperand(decoded.src1, inst.src[0], error) ||
|
|
!LowerSourceOperand(decoded.src0, inst.src[1], error) ||
|
|
!LowerSourceOperand(decoded.src2, inst.src[2], error)) {
|
|
return false;
|
|
}
|
|
inst.src_count = 3;
|
|
block.instructions.push_back(inst);
|
|
return true;
|
|
}
|
|
|
|
bool LowerDsWriteAddtidB32(const Decoder::Instruction& decoded, BasicBlock& block,
|
|
std::string* error) {
|
|
Instruction inst;
|
|
inst.pc = decoded.pc;
|
|
inst.op = Opcode::DsWriteAddtidB32;
|
|
inst.src_count = 2;
|
|
inst.memory = MemoryInfoFromDecoded(decoded, DsMemoryKind(decoded));
|
|
inst.memory.resource = 0;
|
|
inst.dst.kind = OperandKind::Null;
|
|
const auto m0 = M0Operand();
|
|
if (!LowerSourceOperand(decoded.src1, inst.src[0], error) ||
|
|
!LowerSourceOperand(m0, inst.src[1], error)) {
|
|
return false;
|
|
}
|
|
block.instructions.push_back(inst);
|
|
return true;
|
|
}
|
|
|
|
bool LowerDsReadAddtidB32(const Decoder::Instruction& decoded, BasicBlock& block,
|
|
std::string* error) {
|
|
Instruction inst;
|
|
inst.pc = decoded.pc;
|
|
inst.op = Opcode::DsReadAddtidB32;
|
|
inst.src_count = 1;
|
|
inst.memory = MemoryInfoFromDecoded(decoded, DsMemoryKind(decoded));
|
|
inst.memory.resource = 0;
|
|
const auto m0 = M0Operand();
|
|
if (!LowerRegisterOperand(decoded.dst, inst.dst, error) ||
|
|
!LowerSourceOperand(m0, inst.src[0], error)) {
|
|
return false;
|
|
}
|
|
block.instructions.push_back(inst);
|
|
return true;
|
|
}
|
|
|
|
bool LowerDsAppendConsume(const Decoder::Instruction& decoded, BasicBlock& block, Opcode op,
|
|
std::string* error) {
|
|
Instruction inst;
|
|
inst.pc = decoded.pc;
|
|
inst.op = op;
|
|
inst.src_count = 1;
|
|
inst.memory = MemoryInfoFromDecoded(decoded, DsMemoryKind(decoded));
|
|
const auto m0 = M0Operand();
|
|
if (!LowerRegisterOperand(decoded.dst, inst.dst, error) ||
|
|
!LowerSourceOperand(m0, inst.src[0], error)) {
|
|
return false;
|
|
}
|
|
block.instructions.push_back(inst);
|
|
return true;
|
|
}
|
|
|
|
Opcode ImageAtomicIrOpcode(Decoder::Opcode opcode) {
|
|
switch (opcode) {
|
|
case Decoder::Opcode::IMAGE_ATOMIC_ADD: return Opcode::AtomicAddU32;
|
|
case Decoder::Opcode::IMAGE_ATOMIC_UMIN: return Opcode::AtomicUMinU32;
|
|
case Decoder::Opcode::IMAGE_ATOMIC_UMAX: return Opcode::AtomicUMaxU32;
|
|
case Decoder::Opcode::IMAGE_ATOMIC_AND: return Opcode::AtomicAndU32;
|
|
case Decoder::Opcode::IMAGE_ATOMIC_OR: return Opcode::AtomicOrU32;
|
|
case Decoder::Opcode::IMAGE_ATOMIC_XOR: return Opcode::AtomicXorU32;
|
|
default: return Opcode::AtomicAddU32;
|
|
}
|
|
}
|
|
|
|
bool LowerImageAtomicU32(const Decoder::Instruction& decoded, BasicBlock& block,
|
|
std::string* error) {
|
|
Instruction inst;
|
|
inst.pc = decoded.pc;
|
|
inst.op = ImageAtomicIrOpcode(decoded.opcode);
|
|
inst.src_count = 2;
|
|
inst.memory = MemoryInfoFromDecoded(decoded, ResourceKind::StorageImageUint);
|
|
inst.memory.sampler = 0;
|
|
inst.dst.kind = OperandKind::Null;
|
|
if ((decoded.glc && !LowerRegisterOperand(decoded.dst, inst.dst, error)) ||
|
|
!LowerSourceOperand(decoded.dst, inst.src[0], error) ||
|
|
!LowerSourceOperand(decoded.src0, inst.src[1], error)) {
|
|
return false;
|
|
}
|
|
block.instructions.push_back(inst);
|
|
return true;
|
|
}
|
|
|
|
bool LowerFlatLoad(const Decoder::Instruction& decoded, BasicBlock& block, std::string* error) {
|
|
const auto kind = FlatSegmentResourceKind(decoded.memory_segment);
|
|
const auto ir_op = FlatLoadOpcode(decoded);
|
|
const auto count = decoded.data_bits == 32u ? decoded.data_dwords : 1u;
|
|
if (decoded.data_bits == 32u && count > 1u) {
|
|
Instruction inst;
|
|
inst.pc = decoded.pc;
|
|
inst.op = ir_op;
|
|
inst.src_count = decoded.src_count;
|
|
inst.memory = MemoryInfoFromDecoded(decoded, kind);
|
|
inst.memory.resource = 0;
|
|
if (!LowerRegisterOperand(decoded.dst, inst.dst, error)) {
|
|
return false;
|
|
}
|
|
for (uint32_t i = 0; i < decoded.src_count && i < 3u; i++) {
|
|
if (!LowerSourceOperand(DecodedSourceAt(decoded, i), inst.src[i], error)) {
|
|
return false;
|
|
}
|
|
}
|
|
block.instructions.push_back(inst);
|
|
return true;
|
|
}
|
|
|
|
for (uint32_t dword = 0; dword < count; dword++) {
|
|
Instruction inst;
|
|
inst.pc = decoded.pc;
|
|
inst.op = ir_op;
|
|
inst.src_count = decoded.src_count;
|
|
inst.memory = OffsetMemoryInfo(decoded, kind, dword);
|
|
inst.memory.resource = 0;
|
|
if (!LowerRegisterOperand(OffsetDecodedRegister(decoded.dst, dword), inst.dst, error)) {
|
|
return false;
|
|
}
|
|
for (uint32_t i = 0; i < decoded.src_count && i < 3u; i++) {
|
|
if (!LowerSourceOperand(DecodedSourceAt(decoded, i), inst.src[i], error)) {
|
|
return false;
|
|
}
|
|
}
|
|
block.instructions.push_back(inst);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool LowerFlatStore(const Decoder::Instruction& decoded, BasicBlock& block, std::string* error) {
|
|
const auto kind = FlatSegmentResourceKind(decoded.memory_segment);
|
|
const auto ir_op = FlatStoreOpcode(decoded.data_bits);
|
|
const auto count = decoded.data_bits == 32u ? decoded.data_dwords : 1u;
|
|
for (uint32_t dword = 0; dword < count; dword++) {
|
|
Instruction inst;
|
|
inst.pc = decoded.pc;
|
|
inst.op = ir_op;
|
|
inst.src_count = decoded.src_count + 1u;
|
|
inst.memory = OffsetMemoryInfo(decoded, kind, dword);
|
|
inst.memory.resource = 0;
|
|
inst.dst.kind = OperandKind::Null;
|
|
if (!LowerSourceOperand(OffsetDecodedRegister(decoded.dst, dword), inst.src[0], error)) {
|
|
return false;
|
|
}
|
|
for (uint32_t i = 0; i < decoded.src_count && i + 1u < 3u; i++) {
|
|
if (!LowerSourceOperand(DecodedSourceAt(decoded, i), inst.src[i + 1u], error)) {
|
|
return false;
|
|
}
|
|
}
|
|
block.instructions.push_back(inst);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool LowerDsWrite(const Decoder::Instruction& decoded, BasicBlock& block, std::string* error) {
|
|
const auto ir_op = DsWriteOpcode(decoded.data_bits);
|
|
Instruction inst;
|
|
inst.pc = decoded.pc;
|
|
inst.op = ir_op;
|
|
inst.src_count = 2;
|
|
inst.memory = MemoryInfoFromDecoded(decoded, DsMemoryKind(decoded));
|
|
inst.dst.kind = OperandKind::Null;
|
|
if (!LowerSourceOperand(decoded.src1, inst.src[0], error) ||
|
|
!LowerSourceOperand(decoded.src0, inst.src[1], error)) {
|
|
return false;
|
|
}
|
|
block.instructions.push_back(inst);
|
|
return true;
|
|
}
|
|
|
|
bool LowerDsWrite2(const Decoder::Instruction& decoded, BasicBlock& block,
|
|
uint32_t dwords_per_write, std::string* error) {
|
|
Instruction inst;
|
|
inst.pc = decoded.pc;
|
|
inst.op = Opcode::DsWrite2B32;
|
|
inst.src_count = 3;
|
|
inst.memory = MemoryInfoFromDecoded(decoded, DsMemoryKind(decoded));
|
|
inst.memory.data_dwords = dwords_per_write * 2u;
|
|
inst.dst.kind = OperandKind::Null;
|
|
if (!LowerSourceOperand(decoded.src1, inst.src[0], error) ||
|
|
!LowerSourceOperand(decoded.src0, inst.src[1], error) ||
|
|
!LowerSourceOperand(decoded.src2, inst.src[2], error)) {
|
|
return false;
|
|
}
|
|
block.instructions.push_back(inst);
|
|
return true;
|
|
}
|
|
|
|
bool LowerImageOperation(const Decoder::Instruction& decoded, BasicBlock& block,
|
|
std::string* error) {
|
|
Instruction inst;
|
|
inst.pc = decoded.pc;
|
|
if (decoded.opcode == Decoder::Opcode::IMAGE_STORE ||
|
|
decoded.opcode == Decoder::Opcode::IMAGE_STORE_MIP) {
|
|
inst.op = Opcode::ImageStore;
|
|
inst.src_count = 2;
|
|
inst.memory = MemoryInfoFromDecoded(decoded, ResourceKind::StorageImage);
|
|
inst.memory.sampler = 0;
|
|
inst.dst.kind = OperandKind::Null;
|
|
if (!LowerSourceOperand(decoded.dst, inst.src[0], error) ||
|
|
!LowerSourceOperand(decoded.src0, inst.src[1], error)) {
|
|
return false;
|
|
}
|
|
block.instructions.push_back(inst);
|
|
return true;
|
|
}
|
|
|
|
inst.op = LoweredImageOpcode(decoded.opcode);
|
|
inst.src_count = 1;
|
|
inst.memory = MemoryInfoFromDecoded(decoded, ResourceKind::Image);
|
|
if (!LowerRegisterOperand(decoded.dst, inst.dst, error) ||
|
|
!LowerSourceOperand(decoded.src0, inst.src[0], error)) {
|
|
return false;
|
|
}
|
|
block.instructions.push_back(inst);
|
|
return true;
|
|
}
|
|
|
|
} // namespace
|
|
|
|
bool LowerMemoryInstruction(const Decoder::Instruction& decoded, BasicBlock& block,
|
|
std::string* error) {
|
|
switch (decoded.opcode) {
|
|
case Decoder::Opcode::S_LOAD_DWORD:
|
|
case Decoder::Opcode::S_LOAD_DWORDX2:
|
|
case Decoder::Opcode::S_LOAD_DWORDX4:
|
|
case Decoder::Opcode::S_LOAD_DWORDX8:
|
|
case Decoder::Opcode::S_LOAD_DWORDX16:
|
|
return LowerScalarMemoryLoadDword(decoded, block, Opcode::SLoadDword, error);
|
|
case Decoder::Opcode::S_BUFFER_LOAD_DWORD:
|
|
case Decoder::Opcode::S_BUFFER_LOAD_DWORDX2:
|
|
case Decoder::Opcode::S_BUFFER_LOAD_DWORDX4:
|
|
case Decoder::Opcode::S_BUFFER_LOAD_DWORDX8:
|
|
case Decoder::Opcode::S_BUFFER_LOAD_DWORDX16:
|
|
return LowerScalarMemoryLoadDword(decoded, block, Opcode::SBufferLoadDword, error);
|
|
case Decoder::Opcode::BUFFER_LOAD_UBYTE:
|
|
case Decoder::Opcode::BUFFER_LOAD_SBYTE:
|
|
case Decoder::Opcode::BUFFER_LOAD_USHORT:
|
|
case Decoder::Opcode::BUFFER_LOAD_SSHORT:
|
|
case Decoder::Opcode::BUFFER_LOAD_DWORD:
|
|
case Decoder::Opcode::BUFFER_LOAD_DWORDX2:
|
|
case Decoder::Opcode::BUFFER_LOAD_DWORDX3:
|
|
case Decoder::Opcode::BUFFER_LOAD_DWORDX4:
|
|
case Decoder::Opcode::BUFFER_LOAD_FORMAT_X:
|
|
case Decoder::Opcode::BUFFER_LOAD_FORMAT_XY:
|
|
case Decoder::Opcode::BUFFER_LOAD_FORMAT_XYZ:
|
|
case Decoder::Opcode::BUFFER_LOAD_FORMAT_XYZW:
|
|
case Decoder::Opcode::TBUFFER_LOAD_FORMAT_X:
|
|
case Decoder::Opcode::TBUFFER_LOAD_FORMAT_XY:
|
|
case Decoder::Opcode::TBUFFER_LOAD_FORMAT_XYZ:
|
|
case Decoder::Opcode::TBUFFER_LOAD_FORMAT_XYZW:
|
|
return LowerBufferLoad(decoded, block, error);
|
|
case Decoder::Opcode::BUFFER_STORE_DWORD:
|
|
case Decoder::Opcode::BUFFER_STORE_DWORDX2:
|
|
case Decoder::Opcode::BUFFER_STORE_DWORDX3:
|
|
case Decoder::Opcode::BUFFER_STORE_DWORDX4:
|
|
case Decoder::Opcode::BUFFER_STORE_BYTE:
|
|
case Decoder::Opcode::BUFFER_STORE_SHORT:
|
|
case Decoder::Opcode::BUFFER_STORE_FORMAT_X:
|
|
case Decoder::Opcode::BUFFER_STORE_FORMAT_XY:
|
|
case Decoder::Opcode::BUFFER_STORE_FORMAT_XYZ:
|
|
case Decoder::Opcode::BUFFER_STORE_FORMAT_XYZW:
|
|
case Decoder::Opcode::TBUFFER_STORE_FORMAT_X:
|
|
case Decoder::Opcode::TBUFFER_STORE_FORMAT_XY:
|
|
case Decoder::Opcode::TBUFFER_STORE_FORMAT_XYZ:
|
|
case Decoder::Opcode::TBUFFER_STORE_FORMAT_XYZW:
|
|
return LowerBufferStore(decoded, block, error);
|
|
case Decoder::Opcode::BUFFER_ATOMIC_SWAP:
|
|
return LowerBufferAtomicDword(decoded, block, Opcode::AtomicSwapU32, error);
|
|
case Decoder::Opcode::BUFFER_ATOMIC_ADD:
|
|
return LowerBufferAtomicDword(decoded, block, Opcode::AtomicAddU32, error);
|
|
case Decoder::Opcode::BUFFER_ATOMIC_SUB:
|
|
return LowerBufferAtomicDword(decoded, block, Opcode::AtomicSubU32, error);
|
|
case Decoder::Opcode::BUFFER_ATOMIC_SMIN:
|
|
return LowerBufferAtomicDword(decoded, block, Opcode::AtomicSMinI32, error);
|
|
case Decoder::Opcode::BUFFER_ATOMIC_UMIN:
|
|
return LowerBufferAtomicDword(decoded, block, Opcode::AtomicUMinU32, error);
|
|
case Decoder::Opcode::BUFFER_ATOMIC_SMAX:
|
|
return LowerBufferAtomicDword(decoded, block, Opcode::AtomicSMaxI32, error);
|
|
case Decoder::Opcode::BUFFER_ATOMIC_UMAX:
|
|
return LowerBufferAtomicDword(decoded, block, Opcode::AtomicUMaxU32, error);
|
|
case Decoder::Opcode::BUFFER_ATOMIC_AND:
|
|
return LowerBufferAtomicDword(decoded, block, Opcode::AtomicAndU32, error);
|
|
case Decoder::Opcode::BUFFER_ATOMIC_OR:
|
|
return LowerBufferAtomicDword(decoded, block, Opcode::AtomicOrU32, error);
|
|
case Decoder::Opcode::BUFFER_ATOMIC_XOR:
|
|
return LowerBufferAtomicDword(decoded, block, Opcode::AtomicXorU32, error);
|
|
case Decoder::Opcode::BUFFER_ATOMIC_FMIN:
|
|
return LowerBufferAtomicDword(decoded, block, Opcode::AtomicFMinF32, error);
|
|
case Decoder::Opcode::BUFFER_ATOMIC_FMAX:
|
|
return LowerBufferAtomicDword(decoded, block, Opcode::AtomicFMaxF32, error);
|
|
case Decoder::Opcode::FLAT_LOAD_UBYTE:
|
|
case Decoder::Opcode::FLAT_LOAD_SBYTE:
|
|
case Decoder::Opcode::FLAT_LOAD_USHORT:
|
|
case Decoder::Opcode::FLAT_LOAD_SSHORT:
|
|
case Decoder::Opcode::FLAT_LOAD_DWORD:
|
|
case Decoder::Opcode::FLAT_LOAD_DWORDX2:
|
|
case Decoder::Opcode::FLAT_LOAD_DWORDX3:
|
|
case Decoder::Opcode::FLAT_LOAD_DWORDX4: return LowerFlatLoad(decoded, block, error);
|
|
case Decoder::Opcode::FLAT_STORE_BYTE:
|
|
case Decoder::Opcode::FLAT_STORE_SHORT:
|
|
case Decoder::Opcode::FLAT_STORE_DWORD:
|
|
case Decoder::Opcode::FLAT_STORE_DWORDX2:
|
|
case Decoder::Opcode::FLAT_STORE_DWORDX3:
|
|
case Decoder::Opcode::FLAT_STORE_DWORDX4: return LowerFlatStore(decoded, block, error);
|
|
case Decoder::Opcode::DS_ADD_U32:
|
|
return LowerDsAtomicU32(decoded, block, Opcode::AtomicAddU32, false, error);
|
|
case Decoder::Opcode::DS_ADD_RTN_U32:
|
|
return LowerDsAtomicU32(decoded, block, Opcode::AtomicAddU32, true, error);
|
|
case Decoder::Opcode::DS_SUB_U32:
|
|
return LowerDsAtomicU32(decoded, block, Opcode::AtomicSubU32, false, error);
|
|
case Decoder::Opcode::DS_SUB_RTN_U32:
|
|
return LowerDsAtomicU32(decoded, block, Opcode::AtomicSubU32, true, error);
|
|
case Decoder::Opcode::DS_MIN_I32:
|
|
return LowerDsAtomicU32(decoded, block, Opcode::AtomicSMinI32, false, error);
|
|
case Decoder::Opcode::DS_MIN_RTN_I32:
|
|
return LowerDsAtomicU32(decoded, block, Opcode::AtomicSMinI32, true, error);
|
|
case Decoder::Opcode::DS_MAX_I32:
|
|
return LowerDsAtomicU32(decoded, block, Opcode::AtomicSMaxI32, false, error);
|
|
case Decoder::Opcode::DS_MAX_RTN_I32:
|
|
return LowerDsAtomicU32(decoded, block, Opcode::AtomicSMaxI32, true, error);
|
|
case Decoder::Opcode::DS_MIN_U32:
|
|
return LowerDsAtomicU32(decoded, block, Opcode::AtomicUMinU32, false, error);
|
|
case Decoder::Opcode::DS_MIN_RTN_U32:
|
|
return LowerDsAtomicU32(decoded, block, Opcode::AtomicUMinU32, true, error);
|
|
case Decoder::Opcode::DS_MAX_U32:
|
|
return LowerDsAtomicU32(decoded, block, Opcode::AtomicUMaxU32, false, error);
|
|
case Decoder::Opcode::DS_MAX_RTN_U32:
|
|
return LowerDsAtomicU32(decoded, block, Opcode::AtomicUMaxU32, true, error);
|
|
case Decoder::Opcode::DS_AND_B32:
|
|
return LowerDsAtomicU32(decoded, block, Opcode::AtomicAndU32, false, error);
|
|
case Decoder::Opcode::DS_AND_RTN_B32:
|
|
return LowerDsAtomicU32(decoded, block, Opcode::AtomicAndU32, true, error);
|
|
case Decoder::Opcode::DS_OR_B32:
|
|
return LowerDsAtomicU32(decoded, block, Opcode::AtomicOrU32, false, error);
|
|
case Decoder::Opcode::DS_OR_RTN_B32:
|
|
return LowerDsAtomicU32(decoded, block, Opcode::AtomicOrU32, true, error);
|
|
case Decoder::Opcode::DS_XOR_B32:
|
|
return LowerDsAtomicU32(decoded, block, Opcode::AtomicXorU32, false, error);
|
|
case Decoder::Opcode::DS_XOR_RTN_B32:
|
|
return LowerDsAtomicU32(decoded, block, Opcode::AtomicXorU32, true, error);
|
|
case Decoder::Opcode::DS_WRXCHG_RTN_B32:
|
|
return LowerDsAtomicU32(decoded, block, Opcode::AtomicSwapU32, true, error);
|
|
case Decoder::Opcode::DS_MIN_F32:
|
|
return LowerDsFloatMinMaxF32(decoded, block, Opcode::DsMinF32, error);
|
|
case Decoder::Opcode::DS_MAX_F32:
|
|
return LowerDsFloatMinMaxF32(decoded, block, Opcode::DsMaxF32, error);
|
|
case Decoder::Opcode::DS_SWIZZLE_B32: return LowerDsSwizzleB32(decoded, block, error);
|
|
case Decoder::Opcode::DS_CONSUME:
|
|
return LowerDsAppendConsume(decoded, block, Opcode::DsConsume, error);
|
|
case Decoder::Opcode::DS_APPEND:
|
|
return LowerDsAppendConsume(decoded, block, Opcode::DsAppend, error);
|
|
case Decoder::Opcode::DS_WRITE_ADDTID_B32:
|
|
return LowerDsWriteAddtidB32(decoded, block, error);
|
|
case Decoder::Opcode::DS_READ_ADDTID_B32:
|
|
return LowerDsReadAddtidB32(decoded, block, error);
|
|
case Decoder::Opcode::DS_READ2_B32:
|
|
case Decoder::Opcode::DS_READ2ST64_B32: return LowerDsRead2(decoded, block, 1, error);
|
|
case Decoder::Opcode::DS_READ2_B64:
|
|
case Decoder::Opcode::DS_READ2ST64_B64: return LowerDsRead2(decoded, block, 2, error);
|
|
case Decoder::Opcode::DS_READ_I8:
|
|
case Decoder::Opcode::DS_READ_U8:
|
|
case Decoder::Opcode::DS_READ_I16:
|
|
case Decoder::Opcode::DS_READ_U16:
|
|
case Decoder::Opcode::DS_READ_B32:
|
|
case Decoder::Opcode::DS_READ_B64:
|
|
case Decoder::Opcode::DS_READ_B96:
|
|
case Decoder::Opcode::DS_READ_B128: return LowerDsRead(decoded, block, error);
|
|
case Decoder::Opcode::DS_WRITE2_B32:
|
|
case Decoder::Opcode::DS_WRITE2ST64_B32: return LowerDsWrite2(decoded, block, 1, error);
|
|
case Decoder::Opcode::DS_WRITE2_B64:
|
|
case Decoder::Opcode::DS_WRITE2ST64_B64: return LowerDsWrite2(decoded, block, 2, error);
|
|
case Decoder::Opcode::DS_WRITE_B8:
|
|
case Decoder::Opcode::DS_WRITE_B16:
|
|
case Decoder::Opcode::DS_WRITE_B32:
|
|
case Decoder::Opcode::DS_WRITE_B64:
|
|
case Decoder::Opcode::DS_WRITE_B96:
|
|
case Decoder::Opcode::DS_WRITE_B128: return LowerDsWrite(decoded, block, error);
|
|
case Decoder::Opcode::IMAGE_GET_RESINFO:
|
|
case Decoder::Opcode::IMAGE_GET_LOD:
|
|
case Decoder::Opcode::IMAGE_LOAD:
|
|
case Decoder::Opcode::IMAGE_LOAD_MIP:
|
|
case Decoder::Opcode::IMAGE_STORE:
|
|
case Decoder::Opcode::IMAGE_STORE_MIP:
|
|
case Decoder::Opcode::IMAGE_GATHER4_LZ:
|
|
case Decoder::Opcode::IMAGE_GATHER4_C:
|
|
case Decoder::Opcode::IMAGE_GATHER4_C_LZ:
|
|
case Decoder::Opcode::IMAGE_GATHER4_LZ_O:
|
|
case Decoder::Opcode::IMAGE_GATHER4_C_O:
|
|
case Decoder::Opcode::IMAGE_GATHER4_C_LZ_O:
|
|
case Decoder::Opcode::IMAGE_GATHER4H:
|
|
case Decoder::Opcode::IMAGE_SAMPLE: return LowerImageOperation(decoded, block, error);
|
|
case Decoder::Opcode::IMAGE_ATOMIC_ADD:
|
|
case Decoder::Opcode::IMAGE_ATOMIC_UMIN:
|
|
case Decoder::Opcode::IMAGE_ATOMIC_UMAX:
|
|
case Decoder::Opcode::IMAGE_ATOMIC_AND:
|
|
case Decoder::Opcode::IMAGE_ATOMIC_OR:
|
|
case Decoder::Opcode::IMAGE_ATOMIC_XOR: return LowerImageAtomicU32(decoded, block, error);
|
|
default:
|
|
if (error != nullptr) {
|
|
*error = fmt::format("memory opcode has no specialized IR lowering: {}",
|
|
magic_enum::enum_name(decoded.opcode));
|
|
}
|
|
return false;
|
|
}
|
|
}
|
|
|
|
bool IsMemoryOpcode(Decoder::Opcode opcode) {
|
|
switch (opcode) {
|
|
case Decoder::Opcode::S_LOAD_DWORD:
|
|
case Decoder::Opcode::S_LOAD_DWORDX2:
|
|
case Decoder::Opcode::S_LOAD_DWORDX4:
|
|
case Decoder::Opcode::S_LOAD_DWORDX8:
|
|
case Decoder::Opcode::S_LOAD_DWORDX16:
|
|
case Decoder::Opcode::S_BUFFER_LOAD_DWORD:
|
|
case Decoder::Opcode::S_BUFFER_LOAD_DWORDX2:
|
|
case Decoder::Opcode::S_BUFFER_LOAD_DWORDX4:
|
|
case Decoder::Opcode::S_BUFFER_LOAD_DWORDX8:
|
|
case Decoder::Opcode::S_BUFFER_LOAD_DWORDX16:
|
|
case Decoder::Opcode::BUFFER_LOAD_UBYTE:
|
|
case Decoder::Opcode::BUFFER_LOAD_SBYTE:
|
|
case Decoder::Opcode::BUFFER_LOAD_USHORT:
|
|
case Decoder::Opcode::BUFFER_LOAD_SSHORT:
|
|
case Decoder::Opcode::BUFFER_LOAD_DWORD:
|
|
case Decoder::Opcode::BUFFER_LOAD_DWORDX2:
|
|
case Decoder::Opcode::BUFFER_LOAD_DWORDX3:
|
|
case Decoder::Opcode::BUFFER_LOAD_DWORDX4:
|
|
case Decoder::Opcode::BUFFER_LOAD_FORMAT_X:
|
|
case Decoder::Opcode::BUFFER_LOAD_FORMAT_XY:
|
|
case Decoder::Opcode::BUFFER_LOAD_FORMAT_XYZ:
|
|
case Decoder::Opcode::BUFFER_LOAD_FORMAT_XYZW:
|
|
case Decoder::Opcode::TBUFFER_LOAD_FORMAT_X:
|
|
case Decoder::Opcode::TBUFFER_LOAD_FORMAT_XY:
|
|
case Decoder::Opcode::TBUFFER_LOAD_FORMAT_XYZ:
|
|
case Decoder::Opcode::TBUFFER_LOAD_FORMAT_XYZW:
|
|
case Decoder::Opcode::BUFFER_STORE_DWORD:
|
|
case Decoder::Opcode::BUFFER_STORE_DWORDX2:
|
|
case Decoder::Opcode::BUFFER_STORE_DWORDX3:
|
|
case Decoder::Opcode::BUFFER_STORE_DWORDX4:
|
|
case Decoder::Opcode::BUFFER_STORE_BYTE:
|
|
case Decoder::Opcode::BUFFER_STORE_SHORT:
|
|
case Decoder::Opcode::BUFFER_STORE_FORMAT_X:
|
|
case Decoder::Opcode::BUFFER_STORE_FORMAT_XY:
|
|
case Decoder::Opcode::BUFFER_STORE_FORMAT_XYZ:
|
|
case Decoder::Opcode::BUFFER_STORE_FORMAT_XYZW:
|
|
case Decoder::Opcode::TBUFFER_STORE_FORMAT_X:
|
|
case Decoder::Opcode::TBUFFER_STORE_FORMAT_XY:
|
|
case Decoder::Opcode::TBUFFER_STORE_FORMAT_XYZ:
|
|
case Decoder::Opcode::TBUFFER_STORE_FORMAT_XYZW:
|
|
case Decoder::Opcode::BUFFER_ATOMIC_SWAP:
|
|
case Decoder::Opcode::BUFFER_ATOMIC_ADD:
|
|
case Decoder::Opcode::BUFFER_ATOMIC_SUB:
|
|
case Decoder::Opcode::BUFFER_ATOMIC_SMIN:
|
|
case Decoder::Opcode::BUFFER_ATOMIC_UMIN:
|
|
case Decoder::Opcode::BUFFER_ATOMIC_SMAX:
|
|
case Decoder::Opcode::BUFFER_ATOMIC_UMAX:
|
|
case Decoder::Opcode::BUFFER_ATOMIC_AND:
|
|
case Decoder::Opcode::BUFFER_ATOMIC_OR:
|
|
case Decoder::Opcode::BUFFER_ATOMIC_XOR:
|
|
case Decoder::Opcode::BUFFER_ATOMIC_FMIN:
|
|
case Decoder::Opcode::BUFFER_ATOMIC_FMAX:
|
|
case Decoder::Opcode::FLAT_LOAD_UBYTE:
|
|
case Decoder::Opcode::FLAT_LOAD_SBYTE:
|
|
case Decoder::Opcode::FLAT_LOAD_USHORT:
|
|
case Decoder::Opcode::FLAT_LOAD_SSHORT:
|
|
case Decoder::Opcode::FLAT_LOAD_DWORD:
|
|
case Decoder::Opcode::FLAT_LOAD_DWORDX2:
|
|
case Decoder::Opcode::FLAT_LOAD_DWORDX3:
|
|
case Decoder::Opcode::FLAT_LOAD_DWORDX4:
|
|
case Decoder::Opcode::FLAT_STORE_BYTE:
|
|
case Decoder::Opcode::FLAT_STORE_SHORT:
|
|
case Decoder::Opcode::FLAT_STORE_DWORD:
|
|
case Decoder::Opcode::FLAT_STORE_DWORDX2:
|
|
case Decoder::Opcode::FLAT_STORE_DWORDX3:
|
|
case Decoder::Opcode::FLAT_STORE_DWORDX4:
|
|
case Decoder::Opcode::DS_ADD_U32:
|
|
case Decoder::Opcode::DS_ADD_RTN_U32:
|
|
case Decoder::Opcode::DS_SUB_U32:
|
|
case Decoder::Opcode::DS_SUB_RTN_U32:
|
|
case Decoder::Opcode::DS_MIN_I32:
|
|
case Decoder::Opcode::DS_MIN_RTN_I32:
|
|
case Decoder::Opcode::DS_MAX_I32:
|
|
case Decoder::Opcode::DS_MAX_RTN_I32:
|
|
case Decoder::Opcode::DS_MIN_U32:
|
|
case Decoder::Opcode::DS_MIN_RTN_U32:
|
|
case Decoder::Opcode::DS_MAX_U32:
|
|
case Decoder::Opcode::DS_MAX_RTN_U32:
|
|
case Decoder::Opcode::DS_AND_B32:
|
|
case Decoder::Opcode::DS_AND_RTN_B32:
|
|
case Decoder::Opcode::DS_OR_B32:
|
|
case Decoder::Opcode::DS_OR_RTN_B32:
|
|
case Decoder::Opcode::DS_XOR_B32:
|
|
case Decoder::Opcode::DS_XOR_RTN_B32:
|
|
case Decoder::Opcode::DS_WRXCHG_RTN_B32:
|
|
case Decoder::Opcode::DS_MIN_F32:
|
|
case Decoder::Opcode::DS_MAX_F32:
|
|
case Decoder::Opcode::DS_SWIZZLE_B32:
|
|
case Decoder::Opcode::DS_CONSUME:
|
|
case Decoder::Opcode::DS_APPEND:
|
|
case Decoder::Opcode::DS_READ_I8:
|
|
case Decoder::Opcode::DS_READ_U8:
|
|
case Decoder::Opcode::DS_READ_I16:
|
|
case Decoder::Opcode::DS_READ_U16:
|
|
case Decoder::Opcode::DS_READ2_B32:
|
|
case Decoder::Opcode::DS_READ2ST64_B32:
|
|
case Decoder::Opcode::DS_READ_B32:
|
|
case Decoder::Opcode::DS_READ_B64:
|
|
case Decoder::Opcode::DS_READ2_B64:
|
|
case Decoder::Opcode::DS_READ2ST64_B64:
|
|
case Decoder::Opcode::DS_READ_B96:
|
|
case Decoder::Opcode::DS_READ_B128:
|
|
case Decoder::Opcode::DS_WRITE_B8:
|
|
case Decoder::Opcode::DS_WRITE_B16:
|
|
case Decoder::Opcode::DS_WRITE2_B32:
|
|
case Decoder::Opcode::DS_WRITE2ST64_B32:
|
|
case Decoder::Opcode::DS_WRITE2_B64:
|
|
case Decoder::Opcode::DS_WRITE2ST64_B64:
|
|
case Decoder::Opcode::DS_WRITE_B32:
|
|
case Decoder::Opcode::DS_WRITE_B64:
|
|
case Decoder::Opcode::DS_WRITE_B96:
|
|
case Decoder::Opcode::DS_WRITE_B128:
|
|
case Decoder::Opcode::DS_WRITE_ADDTID_B32:
|
|
case Decoder::Opcode::DS_READ_ADDTID_B32:
|
|
case Decoder::Opcode::IMAGE_GET_RESINFO:
|
|
case Decoder::Opcode::IMAGE_GET_LOD:
|
|
case Decoder::Opcode::IMAGE_LOAD:
|
|
case Decoder::Opcode::IMAGE_LOAD_MIP:
|
|
case Decoder::Opcode::IMAGE_STORE:
|
|
case Decoder::Opcode::IMAGE_STORE_MIP:
|
|
case Decoder::Opcode::IMAGE_ATOMIC_ADD:
|
|
case Decoder::Opcode::IMAGE_ATOMIC_UMIN:
|
|
case Decoder::Opcode::IMAGE_ATOMIC_UMAX:
|
|
case Decoder::Opcode::IMAGE_ATOMIC_AND:
|
|
case Decoder::Opcode::IMAGE_ATOMIC_OR:
|
|
case Decoder::Opcode::IMAGE_ATOMIC_XOR:
|
|
case Decoder::Opcode::IMAGE_GATHER4_LZ:
|
|
case Decoder::Opcode::IMAGE_GATHER4_C:
|
|
case Decoder::Opcode::IMAGE_GATHER4_C_LZ:
|
|
case Decoder::Opcode::IMAGE_GATHER4_LZ_O:
|
|
case Decoder::Opcode::IMAGE_GATHER4_C_O:
|
|
case Decoder::Opcode::IMAGE_GATHER4_C_LZ_O:
|
|
case Decoder::Opcode::IMAGE_GATHER4H:
|
|
case Decoder::Opcode::IMAGE_SAMPLE: return true;
|
|
default: return false;
|
|
}
|
|
}
|
|
|
|
} // namespace Libs::Graphics::ShaderRecompiler::IR
|