mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-26 04:46:53 +01:00
shader: remove second IR layer
This commit is contained in:
+18
-8
@@ -1,11 +1,13 @@
|
||||
#include "graphics/shader/recompiler/ir/ValueProgram.h"
|
||||
#include "graphics/shader/recompiler/ir/ShaderIR.h"
|
||||
|
||||
#include "graphics/shader/shader.h"
|
||||
|
||||
#include <fmt/format.h>
|
||||
#include <map>
|
||||
#include <new>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <utility>
|
||||
|
||||
namespace Libs::Graphics::ShaderRecompiler::IR {
|
||||
|
||||
@@ -50,7 +52,7 @@ bool IsRuntimeRead(ValueOpcode opcode) {
|
||||
AddressOpcodeInfoOf(opcode).access == AddressAccess::Read;
|
||||
}
|
||||
|
||||
bool EquivalentValue(const ValueProgram& program, Value left, Value right,
|
||||
bool EquivalentValue(const Program& program, Value left, Value right,
|
||||
std::vector<std::pair<const Inst*, const Inst*>>& visited) {
|
||||
left = left.Resolve();
|
||||
right = right.Resolve();
|
||||
@@ -93,7 +95,7 @@ bool EquivalentValue(const ValueProgram& program, Value left, Value right,
|
||||
|
||||
} // namespace
|
||||
|
||||
ValueProgram::~ValueProgram() {
|
||||
Program::~Program() {
|
||||
// Values may cross block boundaries. Detach all arguments before any block starts destroying
|
||||
// its instruction storage so reverse-use links always point to live definitions.
|
||||
for (auto* block: blocks) {
|
||||
@@ -103,12 +105,20 @@ ValueProgram::~ValueProgram() {
|
||||
}
|
||||
}
|
||||
|
||||
bool EquivalentValue(const ValueProgram& program, Value left, Value right) {
|
||||
Program& Program::operator=(Program&& other) noexcept {
|
||||
if (this != &other) {
|
||||
this->~Program();
|
||||
new (this) Program(std::move(other));
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool EquivalentValue(const Program& program, Value left, Value right) {
|
||||
std::vector<std::pair<const Inst*, const Inst*>> visited;
|
||||
return EquivalentValue(program, left, right, visited);
|
||||
}
|
||||
|
||||
Value ResolveInvariantPhi(const ValueProgram& program, Value value) {
|
||||
Value ResolveInvariantPhi(const Program& program, Value value) {
|
||||
value = value.Resolve();
|
||||
const auto* root = value.TryInstruction();
|
||||
if (root == nullptr || root->GetOpcode() != ValueOpcode::Phi) {
|
||||
@@ -139,7 +149,7 @@ Value ResolveInvariantPhi(const ValueProgram& program, Value value) {
|
||||
return invariant;
|
||||
}
|
||||
|
||||
bool ValidateValueProgram(const ValueProgram& program, bool require_ssa, std::string* error) {
|
||||
bool ValidateProgram(const Program& program, bool require_ssa, std::string* error) {
|
||||
if (program.blocks.size() != program.block_info.size() ||
|
||||
program.blocks.size() != program.block_storage.size()) {
|
||||
return Fail(error, "value IR block storage is inconsistent");
|
||||
@@ -591,14 +601,14 @@ bool ValidateValueProgram(const ValueProgram& program, bool require_ssa, std::st
|
||||
return true;
|
||||
}
|
||||
|
||||
void ResolveControlFlowIdentities(ValueProgram& program) {
|
||||
void ResolveControlFlowIdentities(Program& program) {
|
||||
for (auto& info: program.block_info) {
|
||||
info.condition = info.condition.Resolve();
|
||||
info.indirect_target = info.indirect_target.Resolve();
|
||||
}
|
||||
}
|
||||
|
||||
std::string ValueProgramToString(const ValueProgram& program) {
|
||||
std::string ProgramToString(const Program& program) {
|
||||
std::map<const Inst*, size_t> ids;
|
||||
size_t next_id = 1;
|
||||
for (const auto* block: program.blocks) {
|
||||
File diff suppressed because it is too large
Load Diff
@@ -6,7 +6,7 @@
|
||||
#include "graphics/guest_gpu/gpu_defs.h"
|
||||
#include "graphics/shader/recompiler/frontend/cfg/ShaderCFG.h"
|
||||
#include "graphics/shader/recompiler/frontend/decode/ShaderDecoder.h"
|
||||
#include "graphics/shader/recompiler/ir/opcodes/Opcodes.h"
|
||||
#include "graphics/shader/recompiler/ir/Block.h"
|
||||
#include "graphics/shader/recompiler/ir/opcodes/ValueOpcodes.h"
|
||||
#include "graphics/shader/shader.h"
|
||||
|
||||
@@ -19,47 +19,6 @@
|
||||
|
||||
namespace Libs::Graphics::ShaderRecompiler::IR {
|
||||
|
||||
struct ValueProgram;
|
||||
|
||||
enum class RegisterFile { Scalar, Vector, Vcc, Exec, Scc, M0 };
|
||||
|
||||
struct Register {
|
||||
RegisterFile file = RegisterFile::Scalar;
|
||||
uint32_t index = 0;
|
||||
|
||||
bool operator==(const Register& other) const {
|
||||
return file == other.file && index == other.index;
|
||||
}
|
||||
};
|
||||
|
||||
enum class OperandKind { Register, ImmediateU32, PcRelativeU32, PcRelativeHighU32, Null };
|
||||
|
||||
struct Operand {
|
||||
OperandKind kind = OperandKind::Null;
|
||||
Register reg;
|
||||
uint32_t imm = 0;
|
||||
bool float_inline = false;
|
||||
bool sext_64 = false;
|
||||
uint32_t sdwa_sel = 6;
|
||||
uint32_t sdwa_dst_unused = 2;
|
||||
uint32_t omod = 0;
|
||||
bool sdwa_sext = false;
|
||||
bool op_sel = false;
|
||||
bool op_sel_hi = false;
|
||||
bool negate = false;
|
||||
bool negate_hi = false;
|
||||
bool absolute = false;
|
||||
bool clamp = false;
|
||||
uint32_t dpp_ctrl = 0;
|
||||
uint32_t dpp_row_mask = 0xf;
|
||||
uint32_t dpp_bank_mask = 0xf;
|
||||
bool dpp_fetch_inactive = false;
|
||||
bool dpp_bound_ctrl = false;
|
||||
bool dpp = false;
|
||||
|
||||
bool operator==(const Operand& other) const = default;
|
||||
};
|
||||
|
||||
enum class ResourceKind {
|
||||
None,
|
||||
ScalarBuffer,
|
||||
@@ -144,44 +103,6 @@ struct ExportInfo {
|
||||
bool operator==(const ExportInfo& other) const = default;
|
||||
};
|
||||
|
||||
struct InputInfo {
|
||||
uint32_t attr = 0;
|
||||
uint32_t chan = 0;
|
||||
uint32_t component_count = 1;
|
||||
uint32_t interpolation_mode = 3;
|
||||
|
||||
bool operator==(const InputInfo& other) const = default;
|
||||
};
|
||||
|
||||
enum class SaveexecMode { And, Orn2, Andn1 };
|
||||
|
||||
struct Instruction {
|
||||
uint32_t pc = 0;
|
||||
Opcode op = Opcode::MoveU32;
|
||||
Operand dst;
|
||||
Operand dst2;
|
||||
Operand src[4];
|
||||
uint32_t src_count = 0;
|
||||
MemoryInfo memory;
|
||||
ExportInfo export_info;
|
||||
InputInfo input_info;
|
||||
SaveexecMode saveexec_mode = SaveexecMode::And;
|
||||
|
||||
bool operator==(const Instruction& other) const = default;
|
||||
};
|
||||
|
||||
struct BasicBlock {
|
||||
uint32_t id = 0;
|
||||
uint32_t start_pc = 0;
|
||||
uint32_t end_pc = 0;
|
||||
uint32_t inst_begin = 0;
|
||||
uint32_t inst_end = 0;
|
||||
std::vector<uint32_t> predecessors;
|
||||
std::vector<uint32_t> successors;
|
||||
CFG::Terminator terminator;
|
||||
std::vector<Instruction> instructions;
|
||||
};
|
||||
|
||||
struct DescriptorValue {
|
||||
std::array<uint32_t, 8> dwords = {};
|
||||
uint32_t dword_count = 0;
|
||||
@@ -522,6 +443,7 @@ struct ShaderInfo {
|
||||
std::vector<SampledResourcePair> sampled_pairs;
|
||||
std::vector<StageInput> inputs;
|
||||
std::vector<StageOutput> outputs;
|
||||
std::array<uint8_t, 32> vertex_fetch_components {};
|
||||
int32_t vertex_offset_sgpr = -1;
|
||||
bool has_bitwise_xor = false;
|
||||
|
||||
@@ -539,7 +461,50 @@ struct SpirvRequirements {
|
||||
bool pixel_valid_mask = false;
|
||||
};
|
||||
|
||||
struct BlockInfo {
|
||||
uint32_t id = 0;
|
||||
uint32_t start_pc = 0;
|
||||
uint32_t end_pc = 0;
|
||||
CFG::Terminator terminator;
|
||||
Value condition;
|
||||
Value indirect_target;
|
||||
};
|
||||
|
||||
struct DescriptorSource {
|
||||
struct IndirectImage {
|
||||
uint32_t material_source = 0;
|
||||
uint32_t heap_source = 0;
|
||||
uint32_t selector_stride = 0;
|
||||
uint32_t selector_offset = 0;
|
||||
uint32_t key_arg = 0;
|
||||
|
||||
bool operator==(const IndirectImage& other) const = default;
|
||||
};
|
||||
|
||||
std::array<Value, 8> dwords {};
|
||||
uint32_t dword_count = 0;
|
||||
std::optional<IndirectImage> indirect_image;
|
||||
|
||||
bool operator==(const DescriptorSource& other) const = default;
|
||||
};
|
||||
|
||||
struct SrtRead {
|
||||
Value value;
|
||||
uint32_t flat_offset = 0;
|
||||
uint32_t use_pc = 0;
|
||||
|
||||
bool operator==(const SrtRead& other) const = default;
|
||||
};
|
||||
|
||||
struct Program {
|
||||
Program() = default;
|
||||
~Program();
|
||||
|
||||
Program(const Program&) = delete;
|
||||
Program& operator=(const Program&) = delete;
|
||||
Program(Program&&) noexcept = default;
|
||||
Program& operator=(Program&& other) noexcept;
|
||||
|
||||
ShaderType stage = ShaderType::Unknown;
|
||||
uint64_t shader_hash = 0;
|
||||
uint32_t wave_size = 64;
|
||||
@@ -549,8 +514,17 @@ struct Program {
|
||||
bool dispatcher_fallback = false;
|
||||
CFG::FailureKind cfg_failure_kind = CFG::FailureKind::None;
|
||||
std::string fallback_reason;
|
||||
std::vector<BasicBlock> blocks;
|
||||
std::shared_ptr<ValueProgram> values;
|
||||
std::vector<std::unique_ptr<Block>> block_storage;
|
||||
BlockList blocks;
|
||||
std::vector<BlockInfo> block_info;
|
||||
// Decoded MIMG/VMEM metadata carries details such as RDNA2 NSA address registers and
|
||||
// storage-image swizzles. Typed memory instructions carry a dense index into these shader-local
|
||||
// tables until those fields are consumed by emission.
|
||||
std::vector<MemoryInfo> memory_info;
|
||||
std::vector<ExportInfo> export_info;
|
||||
std::vector<DescriptorSource> descriptor_sources;
|
||||
std::vector<SrtRead> srt_reads;
|
||||
std::vector<Value> dynamic_reads;
|
||||
bool srt_plan_complete = false;
|
||||
ShaderInfo info;
|
||||
bool resource_tracking_complete = false;
|
||||
@@ -561,15 +535,13 @@ struct Program {
|
||||
std::optional<SpirvRequirements> spirv_requirements;
|
||||
};
|
||||
|
||||
bool LowerProgram(const Decoder::Program& decoded, const CFG::Graph& cfg, ShaderType stage,
|
||||
uint32_t wave_size, Program& program, std::string* error);
|
||||
|
||||
std::string RegisterToString(Register reg);
|
||||
std::string OperandToString(const Operand& operand);
|
||||
std::string ExportTargetKindToString(ExportTargetKind kind);
|
||||
std::string InstructionToString(const Instruction& inst);
|
||||
std::string ProgramToString(const Program& program);
|
||||
|
||||
bool ValidateProgram(const Program& program, bool require_ssa, std::string* error);
|
||||
void ResolveControlFlowIdentities(Program& program);
|
||||
bool EquivalentValue(const Program& program, Value left, Value right);
|
||||
Value ResolveInvariantPhi(const Program& program, Value value);
|
||||
|
||||
} // namespace Libs::Graphics::ShaderRecompiler::IR
|
||||
|
||||
#endif /* EMULATOR_INCLUDE_EMULATOR_GRAPHICS_SHADER_RECOMPILER_SHADERIR_H_ */
|
||||
|
||||
@@ -1,51 +0,0 @@
|
||||
#ifndef EMULATOR_SRC_GRAPHICS_SHADER_RECOMPILER_SHADERIR_SHADERIRINTERNAL_H_
|
||||
#define EMULATOR_SRC_GRAPHICS_SHADER_RECOMPILER_SHADERIR_SHADERIRINTERNAL_H_
|
||||
|
||||
#include "graphics/shader/recompiler/ir/ShaderIR.h"
|
||||
|
||||
#include <optional>
|
||||
|
||||
namespace Libs::Graphics::ShaderRecompiler::IR {
|
||||
|
||||
void SetError(std::string* error, const char* message);
|
||||
|
||||
std::optional<Opcode> LookupIrOpcode(Decoder::Opcode opcode);
|
||||
bool IsReversedBinary(Decoder::Opcode opcode);
|
||||
bool IsVectorCarryOutOpcode(Decoder::Opcode opcode);
|
||||
bool ScalarResultWritesSccNonZero(Decoder::Opcode opcode);
|
||||
bool ScalarResultIs64Bit(Decoder::Opcode opcode);
|
||||
|
||||
Operand MakeSccOperand();
|
||||
Operand MakeImmediateU32(uint32_t value);
|
||||
Operand MakePcRelativeU32(uint32_t value);
|
||||
Operand MakePcRelativeHighU32(uint32_t value);
|
||||
bool AppendScalarResultSccNonZero(const Decoder::Instruction& decoded, BasicBlock& block,
|
||||
std::string* error);
|
||||
uint32_t VectorByteConvertIndex(Decoder::Opcode opcode);
|
||||
void CopyOperandModifiers(const Decoder::Operand& decoded, Operand& operand);
|
||||
bool LowerRegisterOperand(const Decoder::Operand& decoded, Operand& operand, std::string* error);
|
||||
bool LowerSourceOperand(const Decoder::Operand& decoded, Operand& operand, std::string* error);
|
||||
void ApplyDppDestinationMask(const Decoder::Instruction& decoded, Operand& dst);
|
||||
uint32_t ResourceIndexFromOperand(const Decoder::Operand& operand);
|
||||
MemoryInfo MemoryInfoFromDecoded(const Decoder::Instruction& decoded, ResourceKind kind);
|
||||
uint32_t RawScalarLoadBase(const Decoder::Operand& operand);
|
||||
void ClearRegisterOffsetModifiers(Decoder::Operand& operand);
|
||||
bool TryGetEncodedScalarCode(const Decoder::Operand& operand, uint32_t& code);
|
||||
bool TryOffsetScalarDestination(const Decoder::Operand& operand, uint32_t index,
|
||||
Decoder::Operand& result);
|
||||
Decoder::Operand OffsetDecodedRegister(const Decoder::Operand& operand, uint32_t index);
|
||||
MemoryInfo OffsetMemoryInfo(const Decoder::Instruction& decoded, ResourceKind kind,
|
||||
uint32_t dword_index);
|
||||
MemoryInfo ByteOffsetMemoryInfo(const Decoder::Instruction& decoded, ResourceKind kind,
|
||||
uint32_t byte_offset);
|
||||
ResourceKind FlatSegmentResourceKind(uint32_t segment);
|
||||
const Decoder::Operand& DecodedSourceAt(const Decoder::Instruction& decoded, uint32_t index);
|
||||
Decoder::Operand M0Operand();
|
||||
|
||||
bool IsMemoryOpcode(Decoder::Opcode opcode);
|
||||
bool LowerMemoryInstruction(const Decoder::Instruction& decoded, BasicBlock& block,
|
||||
std::string* error);
|
||||
|
||||
} // namespace Libs::Graphics::ShaderRecompiler::IR
|
||||
|
||||
#endif // EMULATOR_SRC_GRAPHICS_SHADER_RECOMPILER_SHADERIR_SHADERIRINTERNAL_H_
|
||||
@@ -1,214 +0,0 @@
|
||||
#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 {
|
||||
|
||||
std::string RegisterToString(Register reg) {
|
||||
switch (reg.file) {
|
||||
case RegisterFile::Scalar: return fmt::format("s{}", reg.index);
|
||||
case RegisterFile::Vector: return fmt::format("v{}", reg.index);
|
||||
case RegisterFile::Vcc:
|
||||
return reg.index == 0 ? std::string("vcc_lo") : std::string("vcc_hi");
|
||||
case RegisterFile::Exec:
|
||||
return reg.index == 0 ? std::string("exec_lo") : std::string("exec_hi");
|
||||
case RegisterFile::Scc:
|
||||
if (reg.index == static_cast<uint32_t>(Decoder::OperandKind::Scc)) {
|
||||
return "scc";
|
||||
}
|
||||
if (reg.index == static_cast<uint32_t>(Decoder::OperandKind::VccZ)) {
|
||||
return "vccz";
|
||||
}
|
||||
if (reg.index == static_cast<uint32_t>(Decoder::OperandKind::ExecZ)) {
|
||||
return "execz";
|
||||
}
|
||||
return fmt::format("scc_like_{}", reg.index);
|
||||
case RegisterFile::M0: return "m0";
|
||||
default: return "unknown_reg";
|
||||
}
|
||||
}
|
||||
|
||||
std::string OperandToString(const Operand& operand) {
|
||||
std::string text;
|
||||
switch (operand.kind) {
|
||||
case OperandKind::Register: text = RegisterToString(operand.reg); break;
|
||||
case OperandKind::ImmediateU32: text = fmt::format("0x{:08x}", operand.imm); break;
|
||||
case OperandKind::PcRelativeU32: text = fmt::format("pc_rel(0x{:08x})", operand.imm); break;
|
||||
case OperandKind::PcRelativeHighU32:
|
||||
text = fmt::format("pc_rel_hi(0x{:08x})", operand.imm);
|
||||
break;
|
||||
case OperandKind::Null: text = "null"; break;
|
||||
default: text = "unknown"; break;
|
||||
}
|
||||
if (operand.sdwa_sel != 6 || operand.sdwa_sext) {
|
||||
text += fmt::format(".sdwa(sel={},sext={})", operand.sdwa_sel, operand.sdwa_sext ? 1u : 0u);
|
||||
}
|
||||
if (operand.absolute) {
|
||||
text += ".abs";
|
||||
}
|
||||
if (operand.negate) {
|
||||
text += ".neg";
|
||||
}
|
||||
if (operand.op_sel || operand.op_sel_hi || operand.negate_hi) {
|
||||
text += fmt::format(".opsel(lo={},hi={},neghi={})", operand.op_sel ? 1u : 0u,
|
||||
operand.op_sel_hi ? 1u : 0u, operand.negate_hi ? 1u : 0u);
|
||||
}
|
||||
if (operand.omod != 0) {
|
||||
text += fmt::format(".omod({})", operand.omod);
|
||||
}
|
||||
if (operand.clamp) {
|
||||
text += ".clamp";
|
||||
}
|
||||
if (operand.dpp) {
|
||||
text += fmt::format(".dpp(ctrl=0x{:x},fi={},bc={})", operand.dpp_ctrl,
|
||||
operand.dpp_fetch_inactive ? 1u : 0u, operand.dpp_bound_ctrl ? 1u : 0u);
|
||||
}
|
||||
return text;
|
||||
}
|
||||
|
||||
std::string ResourceKindToString(ResourceKind kind) {
|
||||
switch (kind) {
|
||||
case ResourceKind::ScalarBuffer: return "scalar_buffer";
|
||||
case ResourceKind::ScalarAddress: return "scalar_address";
|
||||
case ResourceKind::Buffer: return "buffer";
|
||||
case ResourceKind::Flat: return "flat";
|
||||
case ResourceKind::Global: return "global";
|
||||
case ResourceKind::Scratch: return "scratch";
|
||||
case ResourceKind::Lds: return "lds";
|
||||
case ResourceKind::Gds: return "gds";
|
||||
case ResourceKind::Image: return "image";
|
||||
case ResourceKind::ImageUint: return "image_uint";
|
||||
case ResourceKind::StorageImage: return "storage_image";
|
||||
case ResourceKind::StorageImageUint: return "storage_image_uint";
|
||||
case ResourceKind::Sampler: return "sampler";
|
||||
default: return "none";
|
||||
}
|
||||
}
|
||||
|
||||
std::string MemoryInfoToString(const MemoryInfo& mem) {
|
||||
if (mem.kind == ResourceKind::None) {
|
||||
return "";
|
||||
}
|
||||
std::string text = fmt::format(
|
||||
" ; {} resource={} sampler={} offset={} offset2={} dmask=0x{:x} data_dwords={} "
|
||||
"data_bits={} component={}/{} dfmt={} nfmt={} signed={} typed={} formatted={} segment={} "
|
||||
"glc={} slc={} idxen={} offen={} image_flags=0x{:x} image_dim={} image_addr={} "
|
||||
"image_mip={} image_r128={}",
|
||||
ResourceKindToString(mem.kind).c_str(), mem.resource, mem.sampler, mem.offset,
|
||||
mem.secondary_offset, mem.dmask, mem.data_dwords, mem.data_bits, mem.component_index,
|
||||
mem.component_count, mem.data_format, mem.number_format, mem.data_signed ? 1u : 0u,
|
||||
mem.typed ? 1u : 0u, mem.formatted ? 1u : 0u, mem.memory_segment, mem.glc ? 1u : 0u,
|
||||
mem.slc ? 1u : 0u, mem.idxen ? 1u : 0u, mem.offen ? 1u : 0u, mem.image_sample_flags,
|
||||
Decoder::ImageDimensionToString(mem.image_dimension), mem.image_address_components,
|
||||
mem.image_has_mip ? 1u : 0u, mem.image_r128 ? 1u : 0u);
|
||||
if (mem.image_nsa_dwords != 0) {
|
||||
text += fmt::format(" image_nsa_dwords={} image_nsa_addr=", mem.image_nsa_dwords);
|
||||
const auto count =
|
||||
std::min<uint32_t>(mem.image_nsa_dwords * 4u, Decoder::MaxImageNsaAddressComponents);
|
||||
for (uint32_t i = 0; i < count; i++) {
|
||||
if (i != 0) {
|
||||
text += ",";
|
||||
}
|
||||
text += fmt::format("{}", mem.image_nsa_addr[i]);
|
||||
}
|
||||
}
|
||||
return text;
|
||||
}
|
||||
|
||||
std::string ExportInfoToString(const ExportInfo& exp) {
|
||||
return fmt::format(" ; target={} index={} raw=0x{:02x} en=0x{:x} done={} compr={} vm={}",
|
||||
ExportTargetKindToString(exp.kind).c_str(), exp.index, exp.target, exp.en,
|
||||
exp.done ? 1u : 0u, exp.compr ? 1u : 0u, exp.vm ? 1u : 0u);
|
||||
}
|
||||
|
||||
std::string InputInfoToString(Opcode op, const InputInfo& input) {
|
||||
if (op != Opcode::LoadInputF32) {
|
||||
return "";
|
||||
}
|
||||
return fmt::format(" ; input_attr={} input_chan={} input_components={}", input.attr, input.chan,
|
||||
input.component_count);
|
||||
}
|
||||
|
||||
std::string TerminatorToString(const CFG::Terminator& term) {
|
||||
return fmt::format(
|
||||
"term={} cond={} true={} false={} merge={} continue={} loop={} indirect_sgpr={} "
|
||||
"indirect_selector={} indirect_targets={} selector_values={}",
|
||||
static_cast<uint32_t>(term.kind), CFG::BranchConditionToString(term.condition).c_str(),
|
||||
term.true_block, term.false_block, term.merge_block, term.continue_block,
|
||||
term.loop_header ? 1u : 0u, term.indirect_pc_sgpr, term.indirect_selector_code,
|
||||
static_cast<uint32_t>(term.indirect_targets.size()),
|
||||
static_cast<uint32_t>(term.indirect_selector_values.size()));
|
||||
}
|
||||
|
||||
std::string ExportSourcesToString(const Instruction& inst) {
|
||||
std::string text;
|
||||
for (uint32_t i = 0; i < inst.src_count && i < 4u; i++) {
|
||||
text += i == 0 ? " " : ", ";
|
||||
text += OperandToString(inst.src[i]);
|
||||
}
|
||||
return text;
|
||||
}
|
||||
|
||||
std::string InstructionToString(const Instruction& inst) {
|
||||
std::string text = fmt::format("0x{:08x}: ", inst.pc);
|
||||
if (inst.op == Opcode::Export) {
|
||||
text += "Export";
|
||||
text += ExportSourcesToString(inst);
|
||||
text += ExportInfoToString(inst.export_info);
|
||||
return text;
|
||||
}
|
||||
text += OpcodeName(inst.op);
|
||||
text += " ";
|
||||
text += OperandToString(inst.dst);
|
||||
if (inst.dst2.kind != OperandKind::Null) {
|
||||
text += ", ";
|
||||
text += OperandToString(inst.dst2);
|
||||
}
|
||||
for (uint32_t i = 0; i < inst.src_count; i++) {
|
||||
text += i == 0 ? ", " : ", ";
|
||||
text += OperandToString(inst.src[i]);
|
||||
}
|
||||
text += MemoryInfoToString(inst.memory);
|
||||
text += InputInfoToString(inst.op, inst.input_info);
|
||||
return text;
|
||||
}
|
||||
|
||||
std::string ExportTargetKindToString(ExportTargetKind kind) {
|
||||
switch (kind) {
|
||||
case ExportTargetKind::Null: return "null";
|
||||
case ExportTargetKind::Position: return "position";
|
||||
case ExportTargetKind::Primitive: return "primitive";
|
||||
case ExportTargetKind::Parameter: return "parameter";
|
||||
case ExportTargetKind::Mrt: return "mrt";
|
||||
case ExportTargetKind::MrtZ: return "mrtz";
|
||||
default: return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
std::string ProgramToString(const Program& program) {
|
||||
std::string text;
|
||||
text += fmt::format("mode={} fallback={} reason={}\n",
|
||||
program.dispatcher_fallback ? "dispatcher" : "structured",
|
||||
CFG::FailureKindToString(program.cfg_failure_kind).c_str(),
|
||||
program.fallback_reason.c_str());
|
||||
for (const auto& block: program.blocks) {
|
||||
text += fmt::format("block_{} pc=0x{:08x} end=0x{:08x} preds={} succs={} {}\n", block.id,
|
||||
block.start_pc, block.end_pc,
|
||||
static_cast<uint32_t>(block.predecessors.size()),
|
||||
static_cast<uint32_t>(block.successors.size()),
|
||||
TerminatorToString(block.terminator).c_str());
|
||||
for (const auto& inst: block.instructions) {
|
||||
text += " ";
|
||||
text += InstructionToString(inst);
|
||||
text += "\n";
|
||||
}
|
||||
}
|
||||
return text;
|
||||
}
|
||||
|
||||
} // namespace Libs::Graphics::ShaderRecompiler::IR
|
||||
@@ -1,812 +0,0 @@
|
||||
#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) {
|
||||
uint32_t destination_code = 0;
|
||||
const auto alignment = decoded.data_dwords == 1u ? 1u
|
||||
: decoded.data_dwords == 2u ? 2u
|
||||
: 4u;
|
||||
if (!TryGetEncodedScalarCode(decoded.dst, destination_code) ||
|
||||
destination_code % alignment != 0u ||
|
||||
destination_code + decoded.data_dwords > 108u) {
|
||||
SetError(error, "scalar-memory destination has an invalid aligned SGPR span");
|
||||
return false;
|
||||
}
|
||||
uint32_t base_code = 0;
|
||||
const auto base_alignment = op == Opcode::SLoadDword ? 2u : 4u;
|
||||
const auto base_width = op == Opcode::SLoadDword ? 2u : 4u;
|
||||
if (!TryGetEncodedScalarCode(decoded.src0, base_code) ||
|
||||
base_code % base_alignment != 0u || base_code + base_width > 108u) {
|
||||
SetError(error, "scalar-memory base has an invalid aligned SGPR span");
|
||||
return false;
|
||||
}
|
||||
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 = MemoryInfoFromDecoded(decoded, kind);
|
||||
// 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(decoded.dst, 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_U16_D16:
|
||||
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_READ_U16_D16:
|
||||
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
|
||||
@@ -1,76 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "graphics/shader/recompiler/ir/Block.h"
|
||||
#include "graphics/shader/recompiler/ir/ShaderIR.h"
|
||||
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace Libs::Graphics::ShaderRecompiler::IR {
|
||||
|
||||
struct ValueBlockInfo {
|
||||
uint32_t id = 0;
|
||||
uint32_t start_pc = 0;
|
||||
uint32_t end_pc = 0;
|
||||
CFG::Terminator terminator;
|
||||
Value condition;
|
||||
Value indirect_target;
|
||||
};
|
||||
|
||||
struct DescriptorSource {
|
||||
struct IndirectImage {
|
||||
uint32_t material_source = 0;
|
||||
uint32_t heap_source = 0;
|
||||
uint32_t selector_stride = 0;
|
||||
uint32_t selector_offset = 0;
|
||||
uint32_t key_arg = 0;
|
||||
|
||||
bool operator==(const IndirectImage& other) const = default;
|
||||
};
|
||||
|
||||
std::array<Value, 8> dwords {};
|
||||
uint32_t dword_count = 0;
|
||||
std::optional<IndirectImage> indirect_image;
|
||||
|
||||
bool operator==(const DescriptorSource& other) const = default;
|
||||
};
|
||||
|
||||
struct SrtRead {
|
||||
Value value;
|
||||
uint32_t flat_offset = 0;
|
||||
uint32_t use_pc = 0;
|
||||
|
||||
bool operator==(const SrtRead& other) const = default;
|
||||
};
|
||||
|
||||
struct ValueProgram {
|
||||
ValueProgram() = default;
|
||||
~ValueProgram();
|
||||
|
||||
ValueProgram(const ValueProgram&) = delete;
|
||||
ValueProgram& operator=(const ValueProgram&) = delete;
|
||||
ValueProgram(ValueProgram&&) = default;
|
||||
ValueProgram& operator=(ValueProgram&&) = default;
|
||||
|
||||
std::vector<std::unique_ptr<Block>> block_storage;
|
||||
BlockList blocks;
|
||||
std::vector<ValueBlockInfo> block_info;
|
||||
// Decoded MIMG/VMEM metadata carries details such as RDNA2 NSA address registers and
|
||||
// storage-image swizzles. Typed memory instructions carry a dense index into these shader-local
|
||||
// tables until those fields are consumed by emission.
|
||||
std::vector<MemoryInfo> memory_info;
|
||||
std::vector<ExportInfo> export_info;
|
||||
std::vector<DescriptorSource> descriptor_sources;
|
||||
std::vector<SrtRead> srt_reads;
|
||||
std::vector<Value> dynamic_reads;
|
||||
};
|
||||
|
||||
bool ValidateValueProgram(const ValueProgram& program, bool require_ssa, std::string* error);
|
||||
void ResolveControlFlowIdentities(ValueProgram& program);
|
||||
bool EquivalentValue(const ValueProgram& program, Value left, Value right);
|
||||
Value ResolveInvariantPhi(const ValueProgram& program, Value value);
|
||||
std::string ValueProgramToString(const ValueProgram& program);
|
||||
|
||||
} // namespace Libs::Graphics::ShaderRecompiler::IR
|
||||
@@ -1,71 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "graphics/shader/recompiler/ir/Type.h"
|
||||
|
||||
#include <array>
|
||||
#include <cstddef>
|
||||
#include <string_view>
|
||||
|
||||
namespace Libs::Graphics::ShaderRecompiler::IR {
|
||||
|
||||
enum class Opcode {
|
||||
#define IR_OPCODE(name, category, lowering, ...) name,
|
||||
#include "graphics/shader/recompiler/ir/opcodes/ShaderIROpcodes.inc"
|
||||
#undef IR_OPCODE
|
||||
Count,
|
||||
};
|
||||
|
||||
enum class OpcodeClass { General, Compare, Compare64 };
|
||||
enum class LoweringClass {
|
||||
Control,
|
||||
Move,
|
||||
Lane,
|
||||
State,
|
||||
Memory,
|
||||
Attribute,
|
||||
IntegerCompare,
|
||||
Integer16Compare,
|
||||
FloatCompare,
|
||||
Conversion,
|
||||
Integer16,
|
||||
PackedInteger16,
|
||||
PackedFloat16,
|
||||
Float16,
|
||||
Float,
|
||||
U64Mask,
|
||||
SimpleInteger,
|
||||
ComposedInteger,
|
||||
ExtendedInteger,
|
||||
};
|
||||
|
||||
struct OpcodeInfo {
|
||||
std::string_view name;
|
||||
OpcodeClass opcode_class = OpcodeClass::General;
|
||||
LoweringClass lowering_class = LoweringClass::Control;
|
||||
};
|
||||
|
||||
inline constexpr OpcodeInfo OPCODE_INFO[] = {
|
||||
#define IR_OPCODE(name, category, lowering, ...) \
|
||||
{#name, OpcodeClass::category, LoweringClass::lowering},
|
||||
#include "graphics/shader/recompiler/ir/opcodes/ShaderIROpcodes.inc"
|
||||
#undef IR_OPCODE
|
||||
};
|
||||
static_assert(std::size(OPCODE_INFO) == static_cast<size_t>(Opcode::Count));
|
||||
|
||||
constexpr const OpcodeInfo& GetOpcodeInfo(Opcode opcode) {
|
||||
return OPCODE_INFO[static_cast<size_t>(opcode)];
|
||||
}
|
||||
|
||||
constexpr std::string_view OpcodeName(Opcode opcode) {
|
||||
return GetOpcodeInfo(opcode).name;
|
||||
}
|
||||
|
||||
constexpr bool IsCompareOpcode(Opcode opcode) {
|
||||
return GetOpcodeInfo(opcode).opcode_class != OpcodeClass::General;
|
||||
}
|
||||
|
||||
constexpr bool IsCompare64Opcode(Opcode opcode) {
|
||||
return GetOpcodeInfo(opcode).opcode_class == OpcodeClass::Compare64;
|
||||
}
|
||||
|
||||
} // namespace Libs::Graphics::ShaderRecompiler::IR
|
||||
@@ -1,548 +0,0 @@
|
||||
#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 {
|
||||
|
||||
struct LowerMap {
|
||||
Decoder::Opcode decoded = Decoder::Opcode::UNKNOWN;
|
||||
Opcode ir = Opcode::MoveU32;
|
||||
};
|
||||
|
||||
constexpr LowerMap LOWER_OPS[] = {
|
||||
{Decoder::Opcode::S_MOV_B32, Opcode::MoveU32},
|
||||
{Decoder::Opcode::S_MOV_B64, Opcode::MoveU64},
|
||||
{Decoder::Opcode::S_WQM_B64, Opcode::WqmB64},
|
||||
{Decoder::Opcode::S_MOVK_I32, Opcode::MoveU32},
|
||||
{Decoder::Opcode::S_ABS_I32, Opcode::AbsI32},
|
||||
{Decoder::Opcode::S_BREV_B32, Opcode::BitReverseU32},
|
||||
{Decoder::Opcode::S_BCNT1_I32_B32, Opcode::BitCountU32},
|
||||
{Decoder::Opcode::S_BCNT1_I32_B64, Opcode::BitCountU64},
|
||||
{Decoder::Opcode::S_FF1_I32_B32, Opcode::FindLsbU32},
|
||||
{Decoder::Opcode::S_FF1_I32_B64, Opcode::FindLsbU64},
|
||||
{Decoder::Opcode::S_FLBIT_I32_B64, Opcode::FindMsbFromHighU64},
|
||||
{Decoder::Opcode::S_BITREPLICATE_B64_B32, Opcode::BitReplicateB64B32},
|
||||
{Decoder::Opcode::S_QUADMASK_B64, Opcode::QuadmaskB64},
|
||||
{Decoder::Opcode::S_NOT_B32, Opcode::BitwiseNotU32},
|
||||
{Decoder::Opcode::S_NOT_B64, Opcode::BitwiseNotU64},
|
||||
{Decoder::Opcode::S_ADD_U32, Opcode::IAddU32},
|
||||
{Decoder::Opcode::S_SUB_U32, Opcode::ISubU32},
|
||||
{Decoder::Opcode::S_ADD_I32, Opcode::IAddU32},
|
||||
{Decoder::Opcode::S_SUB_I32, Opcode::ISubU32},
|
||||
{Decoder::Opcode::S_MIN_I32, Opcode::IMinI32},
|
||||
{Decoder::Opcode::S_MAX_I32, Opcode::IMaxI32},
|
||||
{Decoder::Opcode::S_MIN_U32, Opcode::UMinU32},
|
||||
{Decoder::Opcode::S_MAX_U32, Opcode::UMaxU32},
|
||||
{Decoder::Opcode::S_AND_B32, Opcode::BitwiseAndU32},
|
||||
{Decoder::Opcode::S_AND_B64, Opcode::BitwiseAndU64},
|
||||
{Decoder::Opcode::S_ANDN2_B32, Opcode::BitwiseAndNotU32},
|
||||
{Decoder::Opcode::S_ANDN2_B64, Opcode::BitwiseAndNotU64},
|
||||
{Decoder::Opcode::S_OR_B32, Opcode::BitwiseOrU32},
|
||||
{Decoder::Opcode::S_OR_B64, Opcode::BitwiseOrU64},
|
||||
{Decoder::Opcode::S_ORN2_B32, Opcode::BitwiseOrNotU32},
|
||||
{Decoder::Opcode::S_ORN2_B64, Opcode::BitwiseOrNotU64},
|
||||
{Decoder::Opcode::S_XOR_B32, Opcode::BitwiseXorU32},
|
||||
{Decoder::Opcode::S_XOR_B64, Opcode::BitwiseXorU64},
|
||||
{Decoder::Opcode::S_NAND_B32, Opcode::BitwiseNandU32},
|
||||
{Decoder::Opcode::S_NAND_B64, Opcode::BitwiseNandU64},
|
||||
{Decoder::Opcode::S_NOR_B32, Opcode::BitwiseNorU32},
|
||||
{Decoder::Opcode::S_NOR_B64, Opcode::BitwiseNorU64},
|
||||
{Decoder::Opcode::S_XNOR_B32, Opcode::BitwiseXnorU32},
|
||||
{Decoder::Opcode::S_XNOR_B64, Opcode::BitwiseXnorU64},
|
||||
{Decoder::Opcode::S_LSHL_B32, Opcode::ShiftLeftLogicalU32},
|
||||
{Decoder::Opcode::S_LSHL_B64, Opcode::ShiftLeftLogicalU64},
|
||||
{Decoder::Opcode::S_LSHR_B32, Opcode::ShiftRightLogicalU32},
|
||||
{Decoder::Opcode::S_LSHR_B64, Opcode::ShiftRightLogicalU64},
|
||||
{Decoder::Opcode::S_ASHR_I32, Opcode::ShiftRightArithmeticI32},
|
||||
{Decoder::Opcode::S_MUL_I32, Opcode::IMulU32},
|
||||
{Decoder::Opcode::S_MUL_HI_U32, Opcode::UMulHighU32},
|
||||
{Decoder::Opcode::S_MULK_I32, Opcode::IMulU32},
|
||||
{Decoder::Opcode::S_BFE_U32, Opcode::BitFieldExtractU32},
|
||||
{Decoder::Opcode::S_BFE_I32, Opcode::BitFieldExtractI32},
|
||||
{Decoder::Opcode::S_BFE_U64, Opcode::BitFieldExtractU64},
|
||||
{Decoder::Opcode::S_BFM_B32, Opcode::BitFieldMaskU32},
|
||||
{Decoder::Opcode::S_BFM_B64, Opcode::BitFieldMaskU64},
|
||||
{Decoder::Opcode::S_BITCMP0_B32, Opcode::BitCompare0B32},
|
||||
{Decoder::Opcode::S_BITCMP1_B32, Opcode::BitCompare1B32},
|
||||
{Decoder::Opcode::S_PACK_LL_B32_B16, Opcode::PackLowLowU16},
|
||||
{Decoder::Opcode::S_PACK_LH_B32_B16, Opcode::PackLowHighU16},
|
||||
{Decoder::Opcode::S_PACK_HH_B32_B16, Opcode::PackHighHighU16},
|
||||
{Decoder::Opcode::S_CMP_EQ_I32, Opcode::CompareEqI32},
|
||||
{Decoder::Opcode::S_CMP_LG_I32, Opcode::CompareNeI32},
|
||||
{Decoder::Opcode::S_CMP_GT_I32, Opcode::CompareGtI32},
|
||||
{Decoder::Opcode::S_CMP_GE_I32, Opcode::CompareGeI32},
|
||||
{Decoder::Opcode::S_CMP_LT_I32, Opcode::CompareLtI32},
|
||||
{Decoder::Opcode::S_CMP_LE_I32, Opcode::CompareLeI32},
|
||||
{Decoder::Opcode::S_CMP_EQ_U32, Opcode::CompareEqU32},
|
||||
{Decoder::Opcode::S_CMP_LG_U32, Opcode::CompareNeU32},
|
||||
{Decoder::Opcode::S_CMP_GT_U32, Opcode::CompareGtU32},
|
||||
{Decoder::Opcode::S_CMP_GE_U32, Opcode::CompareGeU32},
|
||||
{Decoder::Opcode::S_CMP_LT_U32, Opcode::CompareLtU32},
|
||||
{Decoder::Opcode::S_CMP_LE_U32, Opcode::CompareLeU32},
|
||||
{Decoder::Opcode::S_CMP_EQ_U64, Opcode::CompareEqU64},
|
||||
{Decoder::Opcode::S_CMP_LG_U64, Opcode::CompareNeU64},
|
||||
{Decoder::Opcode::V_READFIRSTLANE_B32, Opcode::ReadFirstLaneU32},
|
||||
{Decoder::Opcode::V_READLANE_B32, Opcode::ReadLaneU32},
|
||||
{Decoder::Opcode::V_WRITELANE_B32, Opcode::WriteLaneU32},
|
||||
{Decoder::Opcode::V_PERMLANE16_B32, Opcode::Permlane16B32},
|
||||
{Decoder::Opcode::V_PERMLANEX16_B32, Opcode::Permlanex16B32},
|
||||
{Decoder::Opcode::V_CVT_F32_I32, Opcode::ConvertI32ToF32},
|
||||
{Decoder::Opcode::V_CVT_F32_U32, Opcode::ConvertU32ToF32},
|
||||
{Decoder::Opcode::V_CVT_U32_F32, Opcode::ConvertF32ToU32},
|
||||
{Decoder::Opcode::V_CVT_I32_F32, Opcode::ConvertF32ToI32},
|
||||
{Decoder::Opcode::V_CVT_F16_F32, Opcode::ConvertF32ToF16},
|
||||
{Decoder::Opcode::V_CVT_F32_F16, Opcode::ConvertF16ToF32},
|
||||
{Decoder::Opcode::V_CVT_F16_U16, Opcode::ConvertU16ToF16},
|
||||
{Decoder::Opcode::V_CVT_U16_F16, Opcode::ConvertF16ToU16},
|
||||
{Decoder::Opcode::V_CVT_F16_I16, Opcode::ConvertI16ToF16},
|
||||
{Decoder::Opcode::V_CVT_I16_F16, Opcode::ConvertF16ToI16},
|
||||
{Decoder::Opcode::V_CVT_RPI_I32_F32, Opcode::ConvertRoundPlusInfF32ToI32},
|
||||
{Decoder::Opcode::V_CVT_FLR_I32_F32, Opcode::ConvertFloorF32ToI32},
|
||||
{Decoder::Opcode::V_FREXP_EXP_I32_F32, Opcode::FrexpExpI32F32},
|
||||
{Decoder::Opcode::V_FREXP_MANT_F32, Opcode::FrexpMantF32},
|
||||
{Decoder::Opcode::V_CVT_OFF_F32_I4, Opcode::ConvertI4ToOffsetF32},
|
||||
{Decoder::Opcode::V_RCP_F32, Opcode::RcpF32},
|
||||
{Decoder::Opcode::V_RCP_IFLAG_F32, Opcode::RcpIflagF32},
|
||||
{Decoder::Opcode::V_FRACT_F32, Opcode::FractF32},
|
||||
{Decoder::Opcode::V_TRUNC_F32, Opcode::TruncF32},
|
||||
{Decoder::Opcode::V_CEIL_F32, Opcode::CeilF32},
|
||||
{Decoder::Opcode::V_RNDNE_F32, Opcode::RoundEvenF32},
|
||||
{Decoder::Opcode::V_FLOOR_F32, Opcode::FloorF32},
|
||||
{Decoder::Opcode::V_EXP_F32, Opcode::Exp2F32},
|
||||
{Decoder::Opcode::V_LOG_F32, Opcode::Log2F32},
|
||||
{Decoder::Opcode::V_RSQ_F32, Opcode::InverseSqrtF32},
|
||||
{Decoder::Opcode::V_SQRT_F32, Opcode::SqrtF32},
|
||||
{Decoder::Opcode::V_RCP_F16, Opcode::RcpF16},
|
||||
{Decoder::Opcode::V_SQRT_F16, Opcode::SqrtF16},
|
||||
{Decoder::Opcode::V_RSQ_F16, Opcode::InverseSqrtF16},
|
||||
{Decoder::Opcode::V_LOG_F16, Opcode::Log2F16},
|
||||
{Decoder::Opcode::V_EXP_F16, Opcode::Exp2F16},
|
||||
{Decoder::Opcode::V_FLOOR_F16, Opcode::FloorF16},
|
||||
{Decoder::Opcode::V_CEIL_F16, Opcode::CeilF16},
|
||||
{Decoder::Opcode::V_TRUNC_F16, Opcode::TruncF16},
|
||||
{Decoder::Opcode::V_RNDNE_F16, Opcode::RoundEvenF16},
|
||||
{Decoder::Opcode::V_SIN_F32, Opcode::SinF32},
|
||||
{Decoder::Opcode::V_COS_F32, Opcode::CosF32},
|
||||
{Decoder::Opcode::V_NOT_B32, Opcode::BitwiseNotU32},
|
||||
{Decoder::Opcode::V_BFREV_B32, Opcode::BitReverseU32},
|
||||
{Decoder::Opcode::V_FFBL_B32, Opcode::FindLsbU32},
|
||||
{Decoder::Opcode::V_FFBH_U32, Opcode::FindMsbFromHighU32},
|
||||
{Decoder::Opcode::V_ADD_F32, Opcode::FAddF32},
|
||||
{Decoder::Opcode::V_SUB_F32, Opcode::FSubF32},
|
||||
{Decoder::Opcode::V_SUBREV_F32, Opcode::FSubF32},
|
||||
{Decoder::Opcode::V_MUL_F32, Opcode::FMulF32},
|
||||
{Decoder::Opcode::V_MAC_F32, Opcode::FMadF32},
|
||||
{Decoder::Opcode::V_MADMK_F32, Opcode::FMadF32},
|
||||
{Decoder::Opcode::V_MADAK_F32, Opcode::FMadF32},
|
||||
{Decoder::Opcode::V_MIN_F32, Opcode::FMinF32},
|
||||
{Decoder::Opcode::V_MAX_F32, Opcode::FMaxF32},
|
||||
{Decoder::Opcode::V_MIN_I32, Opcode::IMinI32},
|
||||
{Decoder::Opcode::V_MAX_I32, Opcode::IMaxI32},
|
||||
{Decoder::Opcode::V_MAD_F32, Opcode::FMadF32},
|
||||
{Decoder::Opcode::V_MAD_I32_I24, Opcode::IMadI24U32},
|
||||
{Decoder::Opcode::V_MAD_U32_U24, Opcode::UMadU24U32},
|
||||
{Decoder::Opcode::V_CUBEID_F32, Opcode::CubeIdF32},
|
||||
{Decoder::Opcode::V_CUBESC_F32, Opcode::CubeScF32},
|
||||
{Decoder::Opcode::V_CUBETC_F32, Opcode::CubeTcF32},
|
||||
{Decoder::Opcode::V_CUBEMA_F32, Opcode::CubeMaF32},
|
||||
{Decoder::Opcode::V_FMA_F32, Opcode::FMadF32},
|
||||
{Decoder::Opcode::V_BFE_U32, Opcode::BitFieldExtract3U32},
|
||||
{Decoder::Opcode::V_BFE_I32, Opcode::BitFieldExtract3I32},
|
||||
{Decoder::Opcode::V_BFI_B32, Opcode::BitFieldInsertSelectU32},
|
||||
{Decoder::Opcode::V_ALIGNBIT_B32, Opcode::AlignBitU32},
|
||||
{Decoder::Opcode::V_ALIGNBYTE_B32, Opcode::AlignByteU32},
|
||||
{Decoder::Opcode::V_MIN3_F32, Opcode::FMin3F32},
|
||||
{Decoder::Opcode::V_MIN3_I32, Opcode::IMin3I32},
|
||||
{Decoder::Opcode::V_MIN3_U32, Opcode::UMin3U32},
|
||||
{Decoder::Opcode::V_MIN3_F16, Opcode::Min3F16},
|
||||
{Decoder::Opcode::V_MAX3_F32, Opcode::FMax3F32},
|
||||
{Decoder::Opcode::V_MAX3_I32, Opcode::IMax3I32},
|
||||
{Decoder::Opcode::V_MAX3_U32, Opcode::UMax3U32},
|
||||
{Decoder::Opcode::V_MAX3_F16, Opcode::Max3F16},
|
||||
{Decoder::Opcode::V_MED3_F32, Opcode::FMed3F32},
|
||||
{Decoder::Opcode::V_MED3_I32, Opcode::IMed3I32},
|
||||
{Decoder::Opcode::V_MED3_U32, Opcode::UMed3U32},
|
||||
{Decoder::Opcode::V_MED3_F16, Opcode::Med3F16},
|
||||
{Decoder::Opcode::V_MED3_I16, Opcode::IMed3I16},
|
||||
{Decoder::Opcode::V_SAD_U32, Opcode::SadU32},
|
||||
{Decoder::Opcode::V_ADD3_U32, Opcode::IAdd3U32},
|
||||
{Decoder::Opcode::V_LSHL_ADD_U32, Opcode::ShiftLeftAddU32},
|
||||
{Decoder::Opcode::V_ADD_LSHL_U32, Opcode::AddShiftLeftU32},
|
||||
{Decoder::Opcode::V_XAD_U32, Opcode::XorAddU32},
|
||||
{Decoder::Opcode::V_LSHL_OR_B32, Opcode::ShiftLeftOrU32},
|
||||
{Decoder::Opcode::V_AND_OR_B32, Opcode::BitwiseAndOrU32},
|
||||
{Decoder::Opcode::V_OR3_B32, Opcode::BitwiseOr3U32},
|
||||
{Decoder::Opcode::V_XOR3_B32, Opcode::BitwiseXor3U32},
|
||||
{Decoder::Opcode::V_ADD_NC_U32, Opcode::IAddU32},
|
||||
{Decoder::Opcode::V_SUB_NC_U32, Opcode::ISubU32},
|
||||
{Decoder::Opcode::V_SUBREV_NC_U32, Opcode::ISubU32},
|
||||
{Decoder::Opcode::V_ADD_NC_U16, Opcode::IAddU16},
|
||||
{Decoder::Opcode::V_SUB_NC_U16, Opcode::ISubI16},
|
||||
{Decoder::Opcode::V_MAX_U16, Opcode::UMaxU16},
|
||||
{Decoder::Opcode::V_MAX_I16, Opcode::IMaxI16},
|
||||
{Decoder::Opcode::V_MIN_U16, Opcode::UMinU16},
|
||||
{Decoder::Opcode::V_MIN_I16, Opcode::IMinI16},
|
||||
{Decoder::Opcode::V_ADD_NC_I16, Opcode::IAddU16},
|
||||
{Decoder::Opcode::V_SUB_NC_I16, Opcode::ISubI16},
|
||||
{Decoder::Opcode::V_MUL_I32_I24, Opcode::IMulI24U32},
|
||||
{Decoder::Opcode::V_MUL_U32_U24, Opcode::UMulU24U32},
|
||||
{Decoder::Opcode::V_MUL_LO_U32, Opcode::IMulU32},
|
||||
{Decoder::Opcode::V_MUL_HI_U32, Opcode::UMulHighU32},
|
||||
{Decoder::Opcode::V_MUL_LO_I32, Opcode::IMulU32},
|
||||
{Decoder::Opcode::V_MUL_HI_I32, Opcode::SMulHighI32},
|
||||
{Decoder::Opcode::V_ADD_I32, Opcode::IAddU32},
|
||||
{Decoder::Opcode::V_SUB_I32, Opcode::ISubU32},
|
||||
{Decoder::Opcode::V_SUBREV_I32, Opcode::ISubU32},
|
||||
{Decoder::Opcode::V_BFM_B32, Opcode::BitFieldMaskU32},
|
||||
{Decoder::Opcode::V_CVT_PKRTZ_F16_F32, Opcode::PackF32ToF16Rtz},
|
||||
{Decoder::Opcode::V_LDEXP_F32, Opcode::LdexpF32},
|
||||
{Decoder::Opcode::V_CVT_PKNORM_I16_F32, Opcode::PackSnorm2x16F32},
|
||||
{Decoder::Opcode::V_CVT_PKNORM_U16_F32, Opcode::PackUnorm2x16F32},
|
||||
{Decoder::Opcode::V_CVT_PK_U16_U32, Opcode::PackU16U32},
|
||||
{Decoder::Opcode::V_CVT_PK_I16_I32, Opcode::PackU16U32},
|
||||
{Decoder::Opcode::V_CVT_PK_U8_F32, Opcode::PackU8F32},
|
||||
{Decoder::Opcode::V_PACK_B32_F16, Opcode::PackB32F16},
|
||||
{Decoder::Opcode::V_PK_MAD_I16, Opcode::PackedMadI16},
|
||||
{Decoder::Opcode::V_PK_MUL_LO_U16, Opcode::PackedMulLoU16},
|
||||
{Decoder::Opcode::V_PK_ADD_I16, Opcode::PackedAddI16},
|
||||
{Decoder::Opcode::V_PK_SUB_I16, Opcode::PackedSubI16},
|
||||
{Decoder::Opcode::V_PK_LSHLREV_B16, Opcode::PackedLshlrevB16},
|
||||
{Decoder::Opcode::V_PK_LSHRREV_B16, Opcode::PackedLshrrevB16},
|
||||
{Decoder::Opcode::V_PK_ASHRREV_I16, Opcode::PackedAshrrevI16},
|
||||
{Decoder::Opcode::V_PK_MAX_I16, Opcode::PackedMaxI16},
|
||||
{Decoder::Opcode::V_PK_MIN_I16, Opcode::PackedMinI16},
|
||||
{Decoder::Opcode::V_PK_MAD_U16, Opcode::PackedMadU16},
|
||||
{Decoder::Opcode::V_PK_ADD_U16, Opcode::PackedAddU16},
|
||||
{Decoder::Opcode::V_PK_SUB_U16, Opcode::PackedSubU16},
|
||||
{Decoder::Opcode::V_PK_MAX_U16, Opcode::PackedMaxU16},
|
||||
{Decoder::Opcode::V_PK_MIN_U16, Opcode::PackedMinU16},
|
||||
{Decoder::Opcode::V_PK_ADD_F16, Opcode::PackedAddF16},
|
||||
{Decoder::Opcode::V_PK_MUL_F16, Opcode::PackedMulF16},
|
||||
{Decoder::Opcode::V_PK_MIN_F16, Opcode::PackedMinF16},
|
||||
{Decoder::Opcode::V_PK_MAX_F16, Opcode::PackedMaxF16},
|
||||
{Decoder::Opcode::V_PK_FMA_F16, Opcode::PackedFmaF16},
|
||||
{Decoder::Opcode::V_PK_FMAC_F16, Opcode::PackedFmaF16},
|
||||
{Decoder::Opcode::V_ADD_F16, Opcode::AddF16},
|
||||
{Decoder::Opcode::V_SUB_F16, Opcode::SubF16},
|
||||
{Decoder::Opcode::V_SUBREV_F16, Opcode::SubF16},
|
||||
{Decoder::Opcode::V_MUL_F16, Opcode::MulF16},
|
||||
{Decoder::Opcode::V_FMAC_F16, Opcode::FmaF16},
|
||||
{Decoder::Opcode::V_FMAMK_F16, Opcode::FmaF16},
|
||||
{Decoder::Opcode::V_FMAAK_F16, Opcode::FmaF16},
|
||||
{Decoder::Opcode::V_FMA_F16, Opcode::FmaF16},
|
||||
{Decoder::Opcode::V_MAD_MIXLO_F16, Opcode::MadMixF16},
|
||||
{Decoder::Opcode::V_MAD_MIXHI_F16, Opcode::MadMixF16},
|
||||
{Decoder::Opcode::V_AND_B32, Opcode::BitwiseAndU32},
|
||||
{Decoder::Opcode::V_OR_B32, Opcode::BitwiseOrU32},
|
||||
{Decoder::Opcode::V_XOR_B32, Opcode::BitwiseXorU32},
|
||||
{Decoder::Opcode::V_XNOR_B32, Opcode::BitwiseXnorU32},
|
||||
{Decoder::Opcode::V_BCNT_U32_B32, Opcode::BitCountAddU32},
|
||||
{Decoder::Opcode::V_MBCNT_LO_U32_B32, Opcode::MaskedBitCountLowU32},
|
||||
{Decoder::Opcode::V_MBCNT_HI_U32_B32, Opcode::MaskedBitCountHighU32},
|
||||
{Decoder::Opcode::V_LSHL_B32, Opcode::ShiftLeftLogicalU32},
|
||||
{Decoder::Opcode::V_LSHLREV_B32, Opcode::ShiftLeftLogicalU32},
|
||||
{Decoder::Opcode::V_LSHLREV_B16, Opcode::ShiftLeftLogicalU16},
|
||||
{Decoder::Opcode::V_LSHR_B32, Opcode::ShiftRightLogicalU32},
|
||||
{Decoder::Opcode::V_LSHRREV_B32, Opcode::ShiftRightLogicalU32},
|
||||
{Decoder::Opcode::V_LSHLREV_B64, Opcode::ShiftLeftLogicalU64},
|
||||
{Decoder::Opcode::V_LSHRREV_B64, Opcode::ShiftRightLogicalU64},
|
||||
{Decoder::Opcode::V_LSHRREV_B16, Opcode::ShiftRightLogicalU16},
|
||||
{Decoder::Opcode::V_ASHR_I32, Opcode::ShiftRightArithmeticI32},
|
||||
{Decoder::Opcode::V_ASHRREV_I32, Opcode::ShiftRightArithmeticI32},
|
||||
{Decoder::Opcode::V_ASHRREV_I16, Opcode::ShiftRightArithmeticI16},
|
||||
{Decoder::Opcode::V_MIN_U32, Opcode::UMinU32},
|
||||
{Decoder::Opcode::V_MAX_U32, Opcode::UMaxU32},
|
||||
{Decoder::Opcode::V_MAX_F16, Opcode::MaxF16},
|
||||
{Decoder::Opcode::V_MIN_F16, Opcode::MinF16},
|
||||
{Decoder::Opcode::V_CMP_F_F32, Opcode::CompareFalse},
|
||||
{Decoder::Opcode::V_CMP_LT_F32, Opcode::CompareLtF32},
|
||||
{Decoder::Opcode::V_CMP_EQ_F32, Opcode::CompareEqF32},
|
||||
{Decoder::Opcode::V_CMP_LE_F32, Opcode::CompareLeF32},
|
||||
{Decoder::Opcode::V_CMP_GT_F32, Opcode::CompareGtF32},
|
||||
{Decoder::Opcode::V_CMP_LG_F32, Opcode::CompareNeF32},
|
||||
{Decoder::Opcode::V_CMP_GE_F32, Opcode::CompareGeF32},
|
||||
{Decoder::Opcode::V_CMP_O_F32, Opcode::CompareOrderedF32},
|
||||
{Decoder::Opcode::V_CMP_U_F32, Opcode::CompareUnorderedF32},
|
||||
{Decoder::Opcode::V_CMP_NGE_F32, Opcode::CompareUnordLtF32},
|
||||
{Decoder::Opcode::V_CMP_NLG_F32, Opcode::CompareUnordEqF32},
|
||||
{Decoder::Opcode::V_CMP_NGT_F32, Opcode::CompareUnordLeF32},
|
||||
{Decoder::Opcode::V_CMP_NLE_F32, Opcode::CompareUnordGtF32},
|
||||
{Decoder::Opcode::V_CMP_NEQ_F32, Opcode::CompareUnordNeF32},
|
||||
{Decoder::Opcode::V_CMP_NLT_F32, Opcode::CompareUnordGeF32},
|
||||
{Decoder::Opcode::V_CMP_TRU_F32, Opcode::CompareTrue},
|
||||
{Decoder::Opcode::V_CMP_CLASS_F32, Opcode::CompareClassF32},
|
||||
{Decoder::Opcode::V_CMP_LT_F16, Opcode::CompareLtF16},
|
||||
{Decoder::Opcode::V_CMP_EQ_F16, Opcode::CompareEqF16},
|
||||
{Decoder::Opcode::V_CMP_LE_F16, Opcode::CompareLeF16},
|
||||
{Decoder::Opcode::V_CMP_GT_F16, Opcode::CompareGtF16},
|
||||
{Decoder::Opcode::V_CMP_LG_F16, Opcode::CompareNeF16},
|
||||
{Decoder::Opcode::V_CMP_GE_F16, Opcode::CompareGeF16},
|
||||
{Decoder::Opcode::V_CMP_NEQ_F16, Opcode::CompareUnordNeF16},
|
||||
{Decoder::Opcode::V_CMPX_LT_F16, Opcode::CompareMaskLtF16},
|
||||
{Decoder::Opcode::V_CMPX_EQ_F16, Opcode::CompareMaskEqF16},
|
||||
{Decoder::Opcode::V_CMPX_LE_F16, Opcode::CompareMaskLeF16},
|
||||
{Decoder::Opcode::V_CMPX_GT_F16, Opcode::CompareMaskGtF16},
|
||||
{Decoder::Opcode::V_CMPX_GE_F16, Opcode::CompareMaskGeF16},
|
||||
{Decoder::Opcode::V_CMPX_NEQ_F16, Opcode::CompareMaskUnordNeF16},
|
||||
{Decoder::Opcode::V_CMPX_NLT_F16, Opcode::CompareMaskUnordGeF16},
|
||||
{Decoder::Opcode::V_CMPX_LT_F32, Opcode::CompareMaskLtF32},
|
||||
{Decoder::Opcode::V_CMPX_EQ_F32, Opcode::CompareMaskEqF32},
|
||||
{Decoder::Opcode::V_CMPX_LE_F32, Opcode::CompareMaskLeF32},
|
||||
{Decoder::Opcode::V_CMPX_GT_F32, Opcode::CompareMaskGtF32},
|
||||
{Decoder::Opcode::V_CMPX_LG_F32, Opcode::CompareMaskNeF32},
|
||||
{Decoder::Opcode::V_CMPX_GE_F32, Opcode::CompareMaskGeF32},
|
||||
{Decoder::Opcode::V_CMPX_NGE_F32, Opcode::CompareMaskUnordLtF32},
|
||||
{Decoder::Opcode::V_CMPX_NLG_F32, Opcode::CompareMaskUnordEqF32},
|
||||
{Decoder::Opcode::V_CMPX_NGT_F32, Opcode::CompareMaskUnordLeF32},
|
||||
{Decoder::Opcode::V_CMPX_NLE_F32, Opcode::CompareMaskUnordGtF32},
|
||||
{Decoder::Opcode::V_CMPX_NEQ_F32, Opcode::CompareMaskUnordNeF32},
|
||||
{Decoder::Opcode::V_CMPX_NLT_F32, Opcode::CompareMaskUnordGeF32},
|
||||
{Decoder::Opcode::V_CMP_F_I32, Opcode::CompareFalse},
|
||||
{Decoder::Opcode::V_CMP_LT_I32, Opcode::CompareLtI32},
|
||||
{Decoder::Opcode::V_CMP_EQ_I32, Opcode::CompareEqI32},
|
||||
{Decoder::Opcode::V_CMP_LE_I32, Opcode::CompareLeI32},
|
||||
{Decoder::Opcode::V_CMP_GT_I32, Opcode::CompareGtI32},
|
||||
{Decoder::Opcode::V_CMP_NE_I32, Opcode::CompareNeI32},
|
||||
{Decoder::Opcode::V_CMP_GE_I32, Opcode::CompareGeI32},
|
||||
{Decoder::Opcode::V_CMP_T_I32, Opcode::CompareTrue},
|
||||
{Decoder::Opcode::V_CMP_LT_I16, Opcode::CompareLtI16},
|
||||
{Decoder::Opcode::V_CMP_EQ_I16, Opcode::CompareEqI16},
|
||||
{Decoder::Opcode::V_CMP_LE_I16, Opcode::CompareLeI16},
|
||||
{Decoder::Opcode::V_CMP_GT_I16, Opcode::CompareGtI16},
|
||||
{Decoder::Opcode::V_CMP_NE_I16, Opcode::CompareNeI16},
|
||||
{Decoder::Opcode::V_CMP_GE_I16, Opcode::CompareGeI16},
|
||||
{Decoder::Opcode::V_CMPX_LT_I32, Opcode::CompareMaskLtI32},
|
||||
{Decoder::Opcode::V_CMPX_EQ_I32, Opcode::CompareMaskEqI32},
|
||||
{Decoder::Opcode::V_CMPX_LE_I32, Opcode::CompareMaskLeI32},
|
||||
{Decoder::Opcode::V_CMPX_GT_I32, Opcode::CompareMaskGtI32},
|
||||
{Decoder::Opcode::V_CMPX_NE_I32, Opcode::CompareMaskNeI32},
|
||||
{Decoder::Opcode::V_CMPX_GE_I32, Opcode::CompareMaskGeI32},
|
||||
{Decoder::Opcode::V_CMP_LT_U16, Opcode::CompareLtU16},
|
||||
{Decoder::Opcode::V_CMP_EQ_U16, Opcode::CompareEqU16},
|
||||
{Decoder::Opcode::V_CMP_LE_U16, Opcode::CompareLeU16},
|
||||
{Decoder::Opcode::V_CMP_GT_U16, Opcode::CompareGtU16},
|
||||
{Decoder::Opcode::V_CMP_NE_U16, Opcode::CompareNeU16},
|
||||
{Decoder::Opcode::V_CMP_GE_U16, Opcode::CompareGeU16},
|
||||
{Decoder::Opcode::V_CMP_F_U32, Opcode::CompareFalse},
|
||||
{Decoder::Opcode::V_CMP_LT_U32, Opcode::CompareLtU32},
|
||||
{Decoder::Opcode::V_CMP_EQ_U32, Opcode::CompareEqU32},
|
||||
{Decoder::Opcode::V_CMP_LE_U32, Opcode::CompareLeU32},
|
||||
{Decoder::Opcode::V_CMP_GT_U32, Opcode::CompareGtU32},
|
||||
{Decoder::Opcode::V_CMP_NE_U32, Opcode::CompareNeU32},
|
||||
{Decoder::Opcode::V_CMP_GE_U32, Opcode::CompareGeU32},
|
||||
{Decoder::Opcode::V_CMP_T_U32, Opcode::CompareTrue},
|
||||
{Decoder::Opcode::V_CMP_EQ_I64, Opcode::CompareEqU64},
|
||||
{Decoder::Opcode::V_CMP_GT_U64, Opcode::CompareGtU64},
|
||||
{Decoder::Opcode::V_CMP_NE_U64, Opcode::CompareNeU64},
|
||||
{Decoder::Opcode::V_CMPX_NE_I64, Opcode::CompareNeU64},
|
||||
{Decoder::Opcode::V_CMPX_NE_U64, Opcode::CompareNeU64},
|
||||
{Decoder::Opcode::V_CMPX_LT_U32, Opcode::CompareMaskLtU32},
|
||||
{Decoder::Opcode::V_CMPX_EQ_U32, Opcode::CompareMaskEqU32},
|
||||
{Decoder::Opcode::V_CMPX_LE_U32, Opcode::CompareMaskLeU32},
|
||||
{Decoder::Opcode::V_CMPX_GT_U32, Opcode::CompareMaskGtU32},
|
||||
{Decoder::Opcode::V_CMPX_NE_U32, Opcode::CompareMaskNeU32},
|
||||
{Decoder::Opcode::V_CMPX_GE_U32, Opcode::CompareMaskGeU32},
|
||||
{Decoder::Opcode::S_LOAD_DWORD, Opcode::SLoadDword},
|
||||
{Decoder::Opcode::S_BUFFER_LOAD_DWORD, Opcode::SBufferLoadDword},
|
||||
{Decoder::Opcode::BUFFER_LOAD_DWORD, Opcode::BufferLoadDword},
|
||||
{Decoder::Opcode::BUFFER_LOAD_SBYTE, Opcode::BufferLoadSbyte},
|
||||
{Decoder::Opcode::BUFFER_LOAD_SSHORT, Opcode::BufferLoadSshort},
|
||||
{Decoder::Opcode::BUFFER_STORE_BYTE, Opcode::BufferStoreByte},
|
||||
{Decoder::Opcode::BUFFER_STORE_SHORT, Opcode::BufferStoreShort},
|
||||
{Decoder::Opcode::BUFFER_STORE_DWORD, Opcode::BufferStoreDword},
|
||||
{Decoder::Opcode::BUFFER_ATOMIC_SWAP, Opcode::AtomicSwapU32},
|
||||
{Decoder::Opcode::BUFFER_ATOMIC_ADD, Opcode::AtomicAddU32},
|
||||
{Decoder::Opcode::BUFFER_ATOMIC_SUB, Opcode::AtomicSubU32},
|
||||
{Decoder::Opcode::BUFFER_ATOMIC_SMIN, Opcode::AtomicSMinI32},
|
||||
{Decoder::Opcode::BUFFER_ATOMIC_UMIN, Opcode::AtomicUMinU32},
|
||||
{Decoder::Opcode::BUFFER_ATOMIC_SMAX, Opcode::AtomicSMaxI32},
|
||||
{Decoder::Opcode::BUFFER_ATOMIC_UMAX, Opcode::AtomicUMaxU32},
|
||||
{Decoder::Opcode::BUFFER_ATOMIC_AND, Opcode::AtomicAndU32},
|
||||
{Decoder::Opcode::BUFFER_ATOMIC_OR, Opcode::AtomicOrU32},
|
||||
{Decoder::Opcode::BUFFER_ATOMIC_XOR, Opcode::AtomicXorU32},
|
||||
{Decoder::Opcode::BUFFER_ATOMIC_FMIN, Opcode::AtomicFMinF32},
|
||||
{Decoder::Opcode::BUFFER_ATOMIC_FMAX, Opcode::AtomicFMaxF32},
|
||||
{Decoder::Opcode::FLAT_LOAD_UBYTE, Opcode::FlatLoadUbyte},
|
||||
{Decoder::Opcode::FLAT_LOAD_SBYTE, Opcode::FlatLoadSbyte},
|
||||
{Decoder::Opcode::FLAT_LOAD_SSHORT, Opcode::FlatLoadSshort},
|
||||
{Decoder::Opcode::FLAT_STORE_BYTE, Opcode::FlatStoreByte},
|
||||
{Decoder::Opcode::FLAT_STORE_SHORT, Opcode::FlatStoreShort},
|
||||
{Decoder::Opcode::FLAT_STORE_DWORD, Opcode::FlatStoreDword},
|
||||
{Decoder::Opcode::DS_ADD_U32, Opcode::AtomicAddU32},
|
||||
{Decoder::Opcode::DS_ADD_RTN_U32, Opcode::AtomicAddU32},
|
||||
{Decoder::Opcode::DS_SUB_U32, Opcode::AtomicSubU32},
|
||||
{Decoder::Opcode::DS_SUB_RTN_U32, Opcode::AtomicSubU32},
|
||||
{Decoder::Opcode::DS_MIN_I32, Opcode::AtomicSMinI32},
|
||||
{Decoder::Opcode::DS_MIN_RTN_I32, Opcode::AtomicSMinI32},
|
||||
{Decoder::Opcode::DS_MAX_I32, Opcode::AtomicSMaxI32},
|
||||
{Decoder::Opcode::DS_MAX_RTN_I32, Opcode::AtomicSMaxI32},
|
||||
{Decoder::Opcode::DS_MIN_U32, Opcode::AtomicUMinU32},
|
||||
{Decoder::Opcode::DS_MIN_RTN_U32, Opcode::AtomicUMinU32},
|
||||
{Decoder::Opcode::DS_MAX_U32, Opcode::AtomicUMaxU32},
|
||||
{Decoder::Opcode::DS_MAX_RTN_U32, Opcode::AtomicUMaxU32},
|
||||
{Decoder::Opcode::DS_AND_B32, Opcode::AtomicAndU32},
|
||||
{Decoder::Opcode::DS_AND_RTN_B32, Opcode::AtomicAndU32},
|
||||
{Decoder::Opcode::DS_OR_B32, Opcode::AtomicOrU32},
|
||||
{Decoder::Opcode::DS_OR_RTN_B32, Opcode::AtomicOrU32},
|
||||
{Decoder::Opcode::DS_XOR_B32, Opcode::AtomicXorU32},
|
||||
{Decoder::Opcode::DS_XOR_RTN_B32, Opcode::AtomicXorU32},
|
||||
{Decoder::Opcode::DS_WRXCHG_RTN_B32, Opcode::AtomicSwapU32},
|
||||
{Decoder::Opcode::DS_READ_I8, Opcode::DsReadSbyte},
|
||||
{Decoder::Opcode::DS_READ_U8, Opcode::DsReadUbyte},
|
||||
{Decoder::Opcode::DS_READ_I16, Opcode::DsReadSshort},
|
||||
{Decoder::Opcode::DS_READ_U16, Opcode::DsReadUshort},
|
||||
{Decoder::Opcode::DS_READ_U16_D16, Opcode::DsReadUshort},
|
||||
{Decoder::Opcode::DS_READ2_B32, Opcode::DsRead2B32},
|
||||
{Decoder::Opcode::DS_READ2ST64_B32, Opcode::DsRead2B32},
|
||||
{Decoder::Opcode::DS_READ_B32, Opcode::DsReadB32},
|
||||
{Decoder::Opcode::DS_READ_B64, Opcode::DsReadB32},
|
||||
{Decoder::Opcode::DS_READ2_B64, Opcode::DsRead2B32},
|
||||
{Decoder::Opcode::DS_READ2ST64_B64, Opcode::DsRead2B32},
|
||||
{Decoder::Opcode::DS_READ_B96, Opcode::DsReadB32},
|
||||
{Decoder::Opcode::DS_READ_B128, Opcode::DsReadB32},
|
||||
{Decoder::Opcode::DS_WRITE_B8, Opcode::DsWriteByte},
|
||||
{Decoder::Opcode::DS_WRITE_B16, Opcode::DsWriteShort},
|
||||
{Decoder::Opcode::DS_WRITE2_B32, Opcode::DsWrite2B32},
|
||||
{Decoder::Opcode::DS_WRITE2ST64_B32, Opcode::DsWrite2B32},
|
||||
{Decoder::Opcode::DS_WRITE2_B64, Opcode::DsWrite2B32},
|
||||
{Decoder::Opcode::DS_WRITE2ST64_B64, Opcode::DsWrite2B32},
|
||||
{Decoder::Opcode::DS_WRITE_B32, Opcode::DsWriteB32},
|
||||
{Decoder::Opcode::DS_WRITE_B64, Opcode::DsWriteB32},
|
||||
{Decoder::Opcode::DS_WRITE_B96, Opcode::DsWriteB32},
|
||||
{Decoder::Opcode::DS_WRITE_B128, Opcode::DsWriteB32},
|
||||
{Decoder::Opcode::DS_MIN_F32, Opcode::DsMinF32},
|
||||
{Decoder::Opcode::DS_MAX_F32, Opcode::DsMaxF32},
|
||||
{Decoder::Opcode::DS_CONSUME, Opcode::DsConsume},
|
||||
{Decoder::Opcode::DS_APPEND, Opcode::DsAppend},
|
||||
{Decoder::Opcode::DS_WRITE_ADDTID_B32, Opcode::DsWriteAddtidB32},
|
||||
{Decoder::Opcode::DS_READ_ADDTID_B32, Opcode::DsReadAddtidB32},
|
||||
{Decoder::Opcode::IMAGE_GET_RESINFO, Opcode::ImageGetResinfo},
|
||||
{Decoder::Opcode::IMAGE_GET_LOD, Opcode::ImageGetLod},
|
||||
{Decoder::Opcode::IMAGE_LOAD, Opcode::ImageLoad},
|
||||
{Decoder::Opcode::IMAGE_LOAD_MIP, Opcode::ImageLoad},
|
||||
{Decoder::Opcode::IMAGE_STORE, Opcode::ImageStore},
|
||||
{Decoder::Opcode::IMAGE_STORE_MIP, Opcode::ImageStore},
|
||||
{Decoder::Opcode::IMAGE_ATOMIC_ADD, Opcode::AtomicAddU32},
|
||||
{Decoder::Opcode::IMAGE_ATOMIC_UMIN, Opcode::AtomicUMinU32},
|
||||
{Decoder::Opcode::IMAGE_ATOMIC_UMAX, Opcode::AtomicUMaxU32},
|
||||
{Decoder::Opcode::IMAGE_ATOMIC_AND, Opcode::AtomicAndU32},
|
||||
{Decoder::Opcode::IMAGE_ATOMIC_OR, Opcode::AtomicOrU32},
|
||||
{Decoder::Opcode::IMAGE_ATOMIC_XOR, Opcode::AtomicXorU32},
|
||||
{Decoder::Opcode::IMAGE_SAMPLE, Opcode::ImageSample},
|
||||
{Decoder::Opcode::IMAGE_GATHER4_LZ, Opcode::ImageGather4},
|
||||
{Decoder::Opcode::IMAGE_GATHER4_C, Opcode::ImageGather4},
|
||||
{Decoder::Opcode::IMAGE_GATHER4_C_LZ, Opcode::ImageGather4},
|
||||
{Decoder::Opcode::IMAGE_GATHER4_LZ_O, Opcode::ImageGather4},
|
||||
{Decoder::Opcode::IMAGE_GATHER4_C_O, Opcode::ImageGather4},
|
||||
{Decoder::Opcode::IMAGE_GATHER4_C_LZ_O, Opcode::ImageGather4},
|
||||
{Decoder::Opcode::IMAGE_GATHER4H, Opcode::ImageGather4},
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
void SetError(std::string* error, const char* message) {
|
||||
if (error != nullptr) {
|
||||
*error = message;
|
||||
}
|
||||
}
|
||||
|
||||
std::optional<Opcode> LookupIrOpcode(Decoder::Opcode opcode) {
|
||||
for (const auto& op: LOWER_OPS) {
|
||||
if (op.decoded == opcode) {
|
||||
return op.ir;
|
||||
}
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
bool IsReversedBinary(Decoder::Opcode opcode) {
|
||||
switch (opcode) {
|
||||
case Decoder::Opcode::V_SUBREV_F32:
|
||||
case Decoder::Opcode::V_SUBREV_F16:
|
||||
case Decoder::Opcode::V_SUBREV_NC_U32:
|
||||
case Decoder::Opcode::V_LSHLREV_B32:
|
||||
case Decoder::Opcode::V_LSHRREV_B32:
|
||||
case Decoder::Opcode::V_ASHRREV_I32:
|
||||
case Decoder::Opcode::V_LSHLREV_B64:
|
||||
case Decoder::Opcode::V_LSHRREV_B64:
|
||||
case Decoder::Opcode::V_LSHLREV_B16:
|
||||
case Decoder::Opcode::V_LSHRREV_B16:
|
||||
case Decoder::Opcode::V_ASHRREV_I16:
|
||||
case Decoder::Opcode::V_SUBREV_I32: return true;
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool IsVectorCarryOutOpcode(Decoder::Opcode opcode) {
|
||||
switch (opcode) {
|
||||
case Decoder::Opcode::V_ADD_I32:
|
||||
case Decoder::Opcode::V_SUB_I32:
|
||||
case Decoder::Opcode::V_SUBREV_I32: return true;
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool ScalarResultWritesSccNonZero(Decoder::Opcode opcode) {
|
||||
switch (opcode) {
|
||||
case Decoder::Opcode::S_ABS_I32:
|
||||
case Decoder::Opcode::S_BCNT1_I32_B32:
|
||||
case Decoder::Opcode::S_BCNT1_I32_B64:
|
||||
case Decoder::Opcode::S_AND_B32:
|
||||
case Decoder::Opcode::S_ANDN2_B32:
|
||||
case Decoder::Opcode::S_OR_B32:
|
||||
case Decoder::Opcode::S_ORN2_B32:
|
||||
case Decoder::Opcode::S_XOR_B32:
|
||||
case Decoder::Opcode::S_NAND_B32:
|
||||
case Decoder::Opcode::S_NOR_B32:
|
||||
case Decoder::Opcode::S_XNOR_B32:
|
||||
case Decoder::Opcode::S_NOT_B32:
|
||||
case Decoder::Opcode::S_LSHL_B32:
|
||||
case Decoder::Opcode::S_LSHR_B32:
|
||||
case Decoder::Opcode::S_ASHR_I32:
|
||||
case Decoder::Opcode::S_BFE_U32:
|
||||
case Decoder::Opcode::S_BFE_I32:
|
||||
case Decoder::Opcode::S_AND_B64:
|
||||
case Decoder::Opcode::S_ANDN2_B64:
|
||||
case Decoder::Opcode::S_NOT_B64:
|
||||
case Decoder::Opcode::S_OR_B64:
|
||||
case Decoder::Opcode::S_ORN2_B64:
|
||||
case Decoder::Opcode::S_XOR_B64:
|
||||
case Decoder::Opcode::S_NAND_B64:
|
||||
case Decoder::Opcode::S_NOR_B64:
|
||||
case Decoder::Opcode::S_XNOR_B64:
|
||||
case Decoder::Opcode::S_LSHL_B64:
|
||||
case Decoder::Opcode::S_LSHR_B64:
|
||||
case Decoder::Opcode::S_BFE_U64:
|
||||
case Decoder::Opcode::S_WQM_B64:
|
||||
case Decoder::Opcode::S_QUADMASK_B64: return true;
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool ScalarResultIs64Bit(Decoder::Opcode opcode) {
|
||||
switch (opcode) {
|
||||
case Decoder::Opcode::S_AND_B64:
|
||||
case Decoder::Opcode::S_ANDN2_B64:
|
||||
case Decoder::Opcode::S_NOT_B64:
|
||||
case Decoder::Opcode::S_OR_B64:
|
||||
case Decoder::Opcode::S_ORN2_B64:
|
||||
case Decoder::Opcode::S_XOR_B64:
|
||||
case Decoder::Opcode::S_NAND_B64:
|
||||
case Decoder::Opcode::S_NOR_B64:
|
||||
case Decoder::Opcode::S_XNOR_B64:
|
||||
case Decoder::Opcode::S_LSHL_B64:
|
||||
case Decoder::Opcode::S_LSHR_B64:
|
||||
case Decoder::Opcode::S_BFE_U64:
|
||||
case Decoder::Opcode::S_WQM_B64:
|
||||
case Decoder::Opcode::S_QUADMASK_B64: return true;
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Libs::Graphics::ShaderRecompiler::IR
|
||||
@@ -1,354 +0,0 @@
|
||||
// Semantic operations produced by RDNA2 instruction lowering. The typed frontend consumes this
|
||||
// baseline set before optimization and resource planning; it must not grow without decoder support.
|
||||
IR_OPCODE(ControlNop, General, Control, Void)
|
||||
IR_OPCODE(Waitcnt, General, Control, Void)
|
||||
IR_OPCODE(Barrier, General, Control, Void)
|
||||
IR_OPCODE(Sendmsg, General, Control, Void)
|
||||
IR_OPCODE(TtraceData, General, Control, Void)
|
||||
IR_OPCODE(InstPrefetch, General, Control, Void)
|
||||
IR_OPCODE(MoveU32, General, Move)
|
||||
IR_OPCODE(MoveF32Bits, General, Move)
|
||||
IR_OPCODE(MoveRelDestU32, General, Lane)
|
||||
IR_OPCODE(MoveRelSourceU32, General, Lane)
|
||||
IR_OPCODE(MoveU64, General, Move)
|
||||
IR_OPCODE(WqmB64, General, Move)
|
||||
IR_OPCODE(SaveexecB32, General, State)
|
||||
IR_OPCODE(SaveexecB64, General, State)
|
||||
IR_OPCODE(ReadFirstLaneU32, General, Lane)
|
||||
IR_OPCODE(ReadLaneU32, General, Lane)
|
||||
IR_OPCODE(WriteLaneU32, General, Lane)
|
||||
IR_OPCODE(Permlane16B32, General, Lane)
|
||||
IR_OPCODE(Permlanex16B32, General, Lane)
|
||||
IR_OPCODE(AbsI32, General, SimpleInteger)
|
||||
IR_OPCODE(IAddU32, General, SimpleInteger)
|
||||
IR_OPCODE(IAddCarryU32, General, State)
|
||||
IR_OPCODE(ISubBorrowCarryU32, General, State)
|
||||
IR_OPCODE(ISubBorrowU32, General, State)
|
||||
IR_OPCODE(ScalarAddCarryU32, General, State)
|
||||
IR_OPCODE(ScalarSubBorrowU32, General, State)
|
||||
IR_OPCODE(ScalarSubBorrowCarryU32, General, State)
|
||||
IR_OPCODE(ScalarSignedAddOverflowI32, General, State)
|
||||
IR_OPCODE(ScalarSignedSubOverflowI32, General, State)
|
||||
IR_OPCODE(ScalarShiftLeftAddCarryU32, General, State)
|
||||
IR_OPCODE(ISubU32, General, SimpleInteger)
|
||||
IR_OPCODE(IMulU32, General, SimpleInteger)
|
||||
IR_OPCODE(UMulHighU32, General, SimpleInteger)
|
||||
IR_OPCODE(SMulHighI32, General, SimpleInteger)
|
||||
IR_OPCODE(IMadI24U32, General, ExtendedInteger)
|
||||
IR_OPCODE(UMadU24U32, General, ExtendedInteger)
|
||||
IR_OPCODE(UMadU64U32, General, ExtendedInteger)
|
||||
IR_OPCODE(SadU32, General, ExtendedInteger)
|
||||
IR_OPCODE(IAdd3U32, General, ExtendedInteger)
|
||||
IR_OPCODE(IMulI24U32, General, ExtendedInteger)
|
||||
IR_OPCODE(UMulU24U32, General, ExtendedInteger)
|
||||
IR_OPCODE(IMinI32, General, SimpleInteger)
|
||||
IR_OPCODE(IMaxI32, General, SimpleInteger)
|
||||
IR_OPCODE(IMin3I32, General, SimpleInteger)
|
||||
IR_OPCODE(IMax3I32, General, SimpleInteger)
|
||||
IR_OPCODE(IMed3I32, General, SimpleInteger)
|
||||
IR_OPCODE(UMinU32, General, SimpleInteger)
|
||||
IR_OPCODE(UMaxU32, General, SimpleInteger)
|
||||
IR_OPCODE(UMin3U32, General, SimpleInteger)
|
||||
IR_OPCODE(UMax3U32, General, SimpleInteger)
|
||||
IR_OPCODE(UMed3U32, General, SimpleInteger)
|
||||
IR_OPCODE(BitwiseAndU32, General, SimpleInteger)
|
||||
IR_OPCODE(BitwiseAndU64, General, U64Mask)
|
||||
IR_OPCODE(BitwiseAndNotU32, General, ComposedInteger)
|
||||
IR_OPCODE(BitwiseAndNotU64, General, U64Mask)
|
||||
IR_OPCODE(BitwiseOrU32, General, SimpleInteger)
|
||||
IR_OPCODE(BitwiseOrU64, General, U64Mask)
|
||||
IR_OPCODE(BitwiseOrNotU32, General, ComposedInteger)
|
||||
IR_OPCODE(BitwiseOrNotU64, General, U64Mask)
|
||||
IR_OPCODE(BitwiseAndOrU32, General, ComposedInteger)
|
||||
IR_OPCODE(BitwiseOr3U32, General, ComposedInteger)
|
||||
IR_OPCODE(BitwiseXorU32, General, SimpleInteger)
|
||||
IR_OPCODE(BitwiseXorU64, General, U64Mask)
|
||||
IR_OPCODE(BitwiseXor3U32, General, ComposedInteger)
|
||||
IR_OPCODE(BitwiseNandU32, General, ComposedInteger)
|
||||
IR_OPCODE(BitwiseNandU64, General, U64Mask)
|
||||
IR_OPCODE(BitwiseNorU32, General, ComposedInteger)
|
||||
IR_OPCODE(BitwiseNorU64, General, U64Mask)
|
||||
IR_OPCODE(BitwiseXnorU32, General, ComposedInteger)
|
||||
IR_OPCODE(BitwiseXnorU64, General, U64Mask)
|
||||
IR_OPCODE(BitwiseNotU32, General, SimpleInteger)
|
||||
IR_OPCODE(BitwiseNotU64, General, U64Mask)
|
||||
IR_OPCODE(BitClearU32, General, ExtendedInteger)
|
||||
IR_OPCODE(BitSetU32, General, ExtendedInteger)
|
||||
IR_OPCODE(BitReverseU32, General, SimpleInteger)
|
||||
IR_OPCODE(BitCountU32, General, SimpleInteger)
|
||||
IR_OPCODE(BitCountU64, General, SimpleInteger)
|
||||
IR_OPCODE(BitReplicateB64B32, General, ExtendedInteger)
|
||||
IR_OPCODE(QuadmaskB64, General, ExtendedInteger)
|
||||
IR_OPCODE(BitCountAddU32, General, ExtendedInteger)
|
||||
IR_OPCODE(MaskedBitCountLowU32, General, ExtendedInteger)
|
||||
IR_OPCODE(MaskedBitCountHighU32, General, ExtendedInteger)
|
||||
IR_OPCODE(FindLsbU32, General, SimpleInteger)
|
||||
IR_OPCODE(FindLsbU64, General, ComposedInteger)
|
||||
IR_OPCODE(FindMsbFromHighU32, General, ComposedInteger)
|
||||
IR_OPCODE(FindMsbFromHighU64, General, ComposedInteger)
|
||||
IR_OPCODE(BitFieldMaskU32, General, ExtendedInteger)
|
||||
IR_OPCODE(BitFieldMaskU64, General, ExtendedInteger)
|
||||
IR_OPCODE(BitFieldExtractU32, General, ExtendedInteger)
|
||||
IR_OPCODE(BitFieldExtractI32, General, ExtendedInteger)
|
||||
IR_OPCODE(BitFieldExtractU64, General, ExtendedInteger)
|
||||
IR_OPCODE(BitFieldExtract3U32, General, ExtendedInteger)
|
||||
IR_OPCODE(BitFieldExtract3I32, General, ExtendedInteger)
|
||||
IR_OPCODE(BitFieldInsertSelectU32, General, ExtendedInteger)
|
||||
IR_OPCODE(BitCompare0B32, General, ExtendedInteger)
|
||||
IR_OPCODE(BitCompare1B32, General, ExtendedInteger)
|
||||
IR_OPCODE(AlignBitU32, General, ExtendedInteger)
|
||||
IR_OPCODE(AlignByteU32, General, ExtendedInteger)
|
||||
IR_OPCODE(ShiftLeftAddU32, General, ExtendedInteger)
|
||||
IR_OPCODE(AddShiftLeftU32, General, ExtendedInteger)
|
||||
IR_OPCODE(XorAddU32, General, ExtendedInteger)
|
||||
IR_OPCODE(ShiftLeftOrU32, General, ExtendedInteger)
|
||||
IR_OPCODE(ShiftLeftLogicalU32, General, SimpleInteger)
|
||||
IR_OPCODE(ShiftLeftLogicalU64, General, SimpleInteger)
|
||||
IR_OPCODE(ShiftLeftLogicalU16, General, Integer16)
|
||||
IR_OPCODE(ShiftRightLogicalU32, General, SimpleInteger)
|
||||
IR_OPCODE(ShiftRightLogicalU64, General, SimpleInteger)
|
||||
IR_OPCODE(ShiftRightLogicalU16, General, Integer16)
|
||||
IR_OPCODE(ShiftRightArithmeticI32, General, SimpleInteger)
|
||||
IR_OPCODE(ShiftRightArithmeticI16, General, Integer16)
|
||||
IR_OPCODE(SelectU32, General, ExtendedInteger, U32, U1, U32, U32)
|
||||
IR_OPCODE(SelectMaskU32, General, ExtendedInteger)
|
||||
IR_OPCODE(SelectF32Bits, General, ExtendedInteger)
|
||||
IR_OPCODE(SelectMaskF32Bits, General, ExtendedInteger)
|
||||
IR_OPCODE(SelectU64, General, ExtendedInteger)
|
||||
IR_OPCODE(PackLowLowU16, General, ExtendedInteger)
|
||||
IR_OPCODE(PackLowHighU16, General, ExtendedInteger)
|
||||
IR_OPCODE(PackHighHighU16, General, ExtendedInteger)
|
||||
IR_OPCODE(CompareFalse, Compare, IntegerCompare)
|
||||
IR_OPCODE(CompareTrue, Compare, IntegerCompare)
|
||||
IR_OPCODE(CompareEqU32, Compare, IntegerCompare)
|
||||
IR_OPCODE(CompareNeU32, Compare, IntegerCompare)
|
||||
IR_OPCODE(CompareGtU32, Compare, IntegerCompare)
|
||||
IR_OPCODE(CompareGeU32, Compare, IntegerCompare)
|
||||
IR_OPCODE(CompareLtU32, Compare, IntegerCompare)
|
||||
IR_OPCODE(CompareLeU32, Compare, IntegerCompare)
|
||||
IR_OPCODE(CompareEqU64, Compare64, IntegerCompare)
|
||||
IR_OPCODE(CompareGtU64, Compare64, IntegerCompare)
|
||||
IR_OPCODE(CompareNeU64, Compare64, IntegerCompare)
|
||||
IR_OPCODE(CompareMaskEqU32, Compare, IntegerCompare)
|
||||
IR_OPCODE(CompareMaskNeU32, Compare, IntegerCompare)
|
||||
IR_OPCODE(CompareMaskGtU32, Compare, IntegerCompare)
|
||||
IR_OPCODE(CompareMaskGeU32, Compare, IntegerCompare)
|
||||
IR_OPCODE(CompareMaskLtU32, Compare, IntegerCompare)
|
||||
IR_OPCODE(CompareMaskLeU32, Compare, IntegerCompare)
|
||||
IR_OPCODE(CompareEqI32, Compare, IntegerCompare)
|
||||
IR_OPCODE(CompareNeI32, Compare, IntegerCompare)
|
||||
IR_OPCODE(CompareGtI32, Compare, IntegerCompare)
|
||||
IR_OPCODE(CompareGeI32, Compare, IntegerCompare)
|
||||
IR_OPCODE(CompareLtI32, Compare, IntegerCompare)
|
||||
IR_OPCODE(CompareLeI32, Compare, IntegerCompare)
|
||||
IR_OPCODE(CompareEqI16, Compare, Integer16Compare)
|
||||
IR_OPCODE(CompareNeI16, Compare, Integer16Compare)
|
||||
IR_OPCODE(CompareGtI16, Compare, Integer16Compare)
|
||||
IR_OPCODE(CompareGeI16, Compare, Integer16Compare)
|
||||
IR_OPCODE(CompareLtI16, Compare, Integer16Compare)
|
||||
IR_OPCODE(CompareLeI16, Compare, Integer16Compare)
|
||||
IR_OPCODE(CompareMaskEqI32, Compare, IntegerCompare)
|
||||
IR_OPCODE(CompareMaskNeI32, Compare, IntegerCompare)
|
||||
IR_OPCODE(CompareMaskGtI32, Compare, IntegerCompare)
|
||||
IR_OPCODE(CompareMaskGeI32, Compare, IntegerCompare)
|
||||
IR_OPCODE(CompareMaskLtI32, Compare, IntegerCompare)
|
||||
IR_OPCODE(CompareMaskLeI32, Compare, IntegerCompare)
|
||||
IR_OPCODE(CompareEqU16, Compare, Integer16Compare)
|
||||
IR_OPCODE(CompareNeU16, Compare, Integer16Compare)
|
||||
IR_OPCODE(CompareGtU16, Compare, Integer16Compare)
|
||||
IR_OPCODE(CompareGeU16, Compare, Integer16Compare)
|
||||
IR_OPCODE(CompareLtU16, Compare, Integer16Compare)
|
||||
IR_OPCODE(CompareLeU16, Compare, Integer16Compare)
|
||||
IR_OPCODE(CompareEqF32, Compare, FloatCompare)
|
||||
IR_OPCODE(CompareNeF32, Compare, FloatCompare)
|
||||
IR_OPCODE(CompareGtF32, Compare, FloatCompare)
|
||||
IR_OPCODE(CompareGeF32, Compare, FloatCompare)
|
||||
IR_OPCODE(CompareLtF32, Compare, FloatCompare)
|
||||
IR_OPCODE(CompareLeF32, Compare, FloatCompare)
|
||||
IR_OPCODE(CompareOrderedF32, Compare, FloatCompare)
|
||||
IR_OPCODE(CompareUnorderedF32, Compare, FloatCompare)
|
||||
IR_OPCODE(CompareUnordEqF32, Compare, FloatCompare)
|
||||
IR_OPCODE(CompareUnordNeF32, Compare, FloatCompare)
|
||||
IR_OPCODE(CompareUnordGtF32, Compare, FloatCompare)
|
||||
IR_OPCODE(CompareUnordGeF32, Compare, FloatCompare)
|
||||
IR_OPCODE(CompareUnordLtF32, Compare, FloatCompare)
|
||||
IR_OPCODE(CompareUnordLeF32, Compare, FloatCompare)
|
||||
IR_OPCODE(CompareClassF32, Compare, FloatCompare)
|
||||
IR_OPCODE(CompareEqF16, Compare, FloatCompare)
|
||||
IR_OPCODE(CompareNeF16, Compare, FloatCompare)
|
||||
IR_OPCODE(CompareGtF16, Compare, FloatCompare)
|
||||
IR_OPCODE(CompareGeF16, Compare, FloatCompare)
|
||||
IR_OPCODE(CompareLtF16, Compare, FloatCompare)
|
||||
IR_OPCODE(CompareLeF16, Compare, FloatCompare)
|
||||
IR_OPCODE(CompareUnordNeF16, Compare, FloatCompare)
|
||||
IR_OPCODE(CompareMaskEqF16, Compare, FloatCompare)
|
||||
IR_OPCODE(CompareMaskNeF16, Compare, FloatCompare)
|
||||
IR_OPCODE(CompareMaskGtF16, Compare, FloatCompare)
|
||||
IR_OPCODE(CompareMaskGeF16, Compare, FloatCompare)
|
||||
IR_OPCODE(CompareMaskLtF16, Compare, FloatCompare)
|
||||
IR_OPCODE(CompareMaskLeF16, Compare, FloatCompare)
|
||||
IR_OPCODE(CompareMaskUnordNeF16, Compare, FloatCompare)
|
||||
IR_OPCODE(CompareMaskUnordGeF16, Compare, FloatCompare)
|
||||
IR_OPCODE(CompareMaskEqF32, Compare, FloatCompare)
|
||||
IR_OPCODE(CompareMaskNeF32, Compare, FloatCompare)
|
||||
IR_OPCODE(CompareMaskGtF32, Compare, FloatCompare)
|
||||
IR_OPCODE(CompareMaskGeF32, Compare, FloatCompare)
|
||||
IR_OPCODE(CompareMaskLtF32, Compare, FloatCompare)
|
||||
IR_OPCODE(CompareMaskLeF32, Compare, FloatCompare)
|
||||
IR_OPCODE(CompareMaskUnordEqF32, Compare, FloatCompare)
|
||||
IR_OPCODE(CompareMaskUnordNeF32, Compare, FloatCompare)
|
||||
IR_OPCODE(CompareMaskUnordGtF32, Compare, FloatCompare)
|
||||
IR_OPCODE(CompareMaskUnordGeF32, Compare, FloatCompare)
|
||||
IR_OPCODE(CompareMaskUnordLtF32, Compare, FloatCompare)
|
||||
IR_OPCODE(CompareMaskUnordLeF32, Compare, FloatCompare)
|
||||
IR_OPCODE(ConvertByteU32ToF32, General, Conversion)
|
||||
IR_OPCODE(ConvertU32ToF32, General, Conversion)
|
||||
IR_OPCODE(ConvertI32ToF32, General, Conversion)
|
||||
IR_OPCODE(ConvertF32ToU32, General, Conversion)
|
||||
IR_OPCODE(ConvertF32ToI32, General, Conversion)
|
||||
IR_OPCODE(ConvertF32ToF16, General, Conversion)
|
||||
IR_OPCODE(ConvertF16ToF32, General, Conversion)
|
||||
IR_OPCODE(ConvertU16ToF16, General, Conversion)
|
||||
IR_OPCODE(ConvertF16ToU16, General, Conversion)
|
||||
IR_OPCODE(ConvertI16ToF16, General, Conversion)
|
||||
IR_OPCODE(ConvertF16ToI16, General, Conversion)
|
||||
IR_OPCODE(ConvertRoundPlusInfF32ToI32, General, Conversion)
|
||||
IR_OPCODE(ConvertFloorF32ToI32, General, Conversion)
|
||||
IR_OPCODE(FrexpExpI32F32, General, Conversion)
|
||||
IR_OPCODE(FrexpMantF32, General, Float)
|
||||
IR_OPCODE(ConvertI4ToOffsetF32, General, Conversion)
|
||||
IR_OPCODE(LdexpF32, General, Float)
|
||||
IR_OPCODE(PackF32ToF16Rtz, General, Conversion)
|
||||
IR_OPCODE(PackSnorm2x16F32, General, Conversion)
|
||||
IR_OPCODE(PackUnorm2x16F32, General, Conversion)
|
||||
IR_OPCODE(PackU16U32, General, ExtendedInteger)
|
||||
IR_OPCODE(PackU8F32, General, Conversion)
|
||||
IR_OPCODE(PackB32F16, General, Conversion)
|
||||
IR_OPCODE(PackedMadI16, General, PackedInteger16)
|
||||
IR_OPCODE(PackedMulLoU16, General, PackedInteger16)
|
||||
IR_OPCODE(PackedAddI16, General, PackedInteger16)
|
||||
IR_OPCODE(PackedSubI16, General, PackedInteger16)
|
||||
IR_OPCODE(PackedLshlrevB16, General, PackedInteger16)
|
||||
IR_OPCODE(PackedLshrrevB16, General, PackedInteger16)
|
||||
IR_OPCODE(PackedAshrrevI16, General, PackedInteger16)
|
||||
IR_OPCODE(PackedMaxI16, General, PackedInteger16)
|
||||
IR_OPCODE(PackedMinI16, General, PackedInteger16)
|
||||
IR_OPCODE(PackedMadU16, General, PackedInteger16)
|
||||
IR_OPCODE(PackedAddU16, General, PackedInteger16)
|
||||
IR_OPCODE(PackedSubU16, General, PackedInteger16)
|
||||
IR_OPCODE(PackedMaxU16, General, PackedInteger16)
|
||||
IR_OPCODE(PackedMinU16, General, PackedInteger16)
|
||||
IR_OPCODE(PackedAddF16, General, PackedFloat16)
|
||||
IR_OPCODE(PackedMulF16, General, PackedFloat16)
|
||||
IR_OPCODE(PackedMinF16, General, PackedFloat16)
|
||||
IR_OPCODE(PackedMaxF16, General, PackedFloat16)
|
||||
IR_OPCODE(PackedFmaF16, General, PackedFloat16)
|
||||
IR_OPCODE(AddF16, General, Float16)
|
||||
IR_OPCODE(SubF16, General, Float16)
|
||||
IR_OPCODE(MulF16, General, Float16)
|
||||
IR_OPCODE(MinF16, General, Float16)
|
||||
IR_OPCODE(MaxF16, General, Float16)
|
||||
IR_OPCODE(FmaF16, General, Float16)
|
||||
IR_OPCODE(MadMixF16, General, Float16)
|
||||
IR_OPCODE(IAddU16, General, Integer16)
|
||||
IR_OPCODE(ISubI16, General, Integer16)
|
||||
IR_OPCODE(IMinI16, General, Integer16)
|
||||
IR_OPCODE(IMaxI16, General, Integer16)
|
||||
IR_OPCODE(IMed3I16, General, Integer16)
|
||||
IR_OPCODE(UMinU16, General, Integer16)
|
||||
IR_OPCODE(UMaxU16, General, Integer16)
|
||||
IR_OPCODE(RcpF32, General, Float)
|
||||
IR_OPCODE(RcpIflagF32, General, Float)
|
||||
IR_OPCODE(FractF32, General, Float)
|
||||
IR_OPCODE(TruncF32, General, Float)
|
||||
IR_OPCODE(CeilF32, General, Float)
|
||||
IR_OPCODE(RoundEvenF32, General, Float)
|
||||
IR_OPCODE(FloorF32, General, Float)
|
||||
IR_OPCODE(Exp2F32, General, Float)
|
||||
IR_OPCODE(Log2F32, General, Float)
|
||||
IR_OPCODE(InverseSqrtF32, General, Float)
|
||||
IR_OPCODE(SqrtF32, General, Float)
|
||||
IR_OPCODE(RcpF16, General, Float16)
|
||||
IR_OPCODE(SqrtF16, General, Float16)
|
||||
IR_OPCODE(InverseSqrtF16, General, Float16)
|
||||
IR_OPCODE(Log2F16, General, Float16)
|
||||
IR_OPCODE(Exp2F16, General, Float16)
|
||||
IR_OPCODE(FloorF16, General, Float16)
|
||||
IR_OPCODE(CeilF16, General, Float16)
|
||||
IR_OPCODE(TruncF16, General, Float16)
|
||||
IR_OPCODE(RoundEvenF16, General, Float16)
|
||||
IR_OPCODE(SinF32, General, Float)
|
||||
IR_OPCODE(CosF32, General, Float)
|
||||
IR_OPCODE(CubeIdF32, General, Float)
|
||||
IR_OPCODE(CubeScF32, General, Float)
|
||||
IR_OPCODE(CubeTcF32, General, Float)
|
||||
IR_OPCODE(CubeMaF32, General, Float)
|
||||
IR_OPCODE(FAddF32, General, Float)
|
||||
IR_OPCODE(FSubF32, General, Float)
|
||||
IR_OPCODE(FMulF32, General, Float)
|
||||
IR_OPCODE(FMinF32, General, Float)
|
||||
IR_OPCODE(FMaxF32, General, Float)
|
||||
IR_OPCODE(FMadF32, General, Float)
|
||||
IR_OPCODE(Dot2AccF32F16, General, Float)
|
||||
IR_OPCODE(FMin3F32, General, Float)
|
||||
IR_OPCODE(FMax3F32, General, Float)
|
||||
IR_OPCODE(FMed3F32, General, Float)
|
||||
IR_OPCODE(Min3F16, General, Float16)
|
||||
IR_OPCODE(Max3F16, General, Float16)
|
||||
IR_OPCODE(Med3F16, General, Float16)
|
||||
IR_OPCODE(LoadSrtDword, General, Memory)
|
||||
IR_OPCODE(SLoadDword, General, Memory)
|
||||
IR_OPCODE(SBufferLoadDword, General, Memory)
|
||||
IR_OPCODE(BufferLoadUbyte, General, Memory)
|
||||
IR_OPCODE(BufferLoadSbyte, General, Memory)
|
||||
IR_OPCODE(BufferLoadUshort, General, Memory)
|
||||
IR_OPCODE(BufferLoadSshort, General, Memory)
|
||||
IR_OPCODE(BufferLoadDword, General, Memory)
|
||||
IR_OPCODE(BufferStoreByte, General, Memory)
|
||||
IR_OPCODE(BufferStoreShort, General, Memory)
|
||||
IR_OPCODE(BufferStoreDword, General, Memory)
|
||||
IR_OPCODE(AtomicSwapU32, General, Memory)
|
||||
IR_OPCODE(AtomicAddU32, General, Memory)
|
||||
IR_OPCODE(AtomicSubU32, General, Memory)
|
||||
IR_OPCODE(AtomicSMinI32, General, Memory)
|
||||
IR_OPCODE(AtomicUMinU32, General, Memory)
|
||||
IR_OPCODE(AtomicSMaxI32, General, Memory)
|
||||
IR_OPCODE(AtomicUMaxU32, General, Memory)
|
||||
IR_OPCODE(AtomicAndU32, General, Memory)
|
||||
IR_OPCODE(AtomicOrU32, General, Memory)
|
||||
IR_OPCODE(AtomicXorU32, General, Memory)
|
||||
IR_OPCODE(AtomicFMinF32, General, Memory)
|
||||
IR_OPCODE(AtomicFMaxF32, General, Memory)
|
||||
IR_OPCODE(FlatLoadUbyte, General, Memory)
|
||||
IR_OPCODE(FlatLoadSbyte, General, Memory)
|
||||
IR_OPCODE(FlatLoadUshort, General, Memory)
|
||||
IR_OPCODE(FlatLoadSshort, General, Memory)
|
||||
IR_OPCODE(FlatLoadDword, General, Memory)
|
||||
IR_OPCODE(FlatStoreByte, General, Memory)
|
||||
IR_OPCODE(FlatStoreShort, General, Memory)
|
||||
IR_OPCODE(FlatStoreDword, General, Memory)
|
||||
IR_OPCODE(DsReadUbyte, General, Memory)
|
||||
IR_OPCODE(DsReadSbyte, General, Memory)
|
||||
IR_OPCODE(DsReadUshort, General, Memory)
|
||||
IR_OPCODE(DsReadSshort, General, Memory)
|
||||
IR_OPCODE(DsReadB32, General, Memory)
|
||||
IR_OPCODE(DsRead2B32, General, Memory)
|
||||
IR_OPCODE(DsWriteByte, General, Memory)
|
||||
IR_OPCODE(DsWriteShort, General, Memory)
|
||||
IR_OPCODE(DsWriteB32, General, Memory)
|
||||
IR_OPCODE(DsWrite2B32, General, Memory)
|
||||
IR_OPCODE(DsMinF32, General, Memory)
|
||||
IR_OPCODE(DsMaxF32, General, Memory)
|
||||
IR_OPCODE(DsSwizzleB32, General, Memory)
|
||||
IR_OPCODE(DsConsume, General, Memory)
|
||||
IR_OPCODE(DsAppend, General, Memory)
|
||||
IR_OPCODE(DsWriteAddtidB32, General, Memory)
|
||||
IR_OPCODE(DsReadAddtidB32, General, Memory)
|
||||
IR_OPCODE(ImageGetResinfo, General, Memory)
|
||||
IR_OPCODE(ImageGetLod, General, Memory)
|
||||
IR_OPCODE(ImageLoad, General, Memory)
|
||||
IR_OPCODE(ImageStore, General, Memory)
|
||||
IR_OPCODE(ImageSample, General, Memory)
|
||||
IR_OPCODE(ImageGather4, General, Memory)
|
||||
IR_OPCODE(LoadInputF32, General, Attribute)
|
||||
IR_OPCODE(Export, General, Attribute)
|
||||
@@ -1,6 +1,6 @@
|
||||
#include "graphics/shader/recompiler/ir/passes/BindingLayout.h"
|
||||
|
||||
#include "graphics/shader/recompiler/ir/ValueProgram.h"
|
||||
#include "graphics/shader/recompiler/ir/ShaderIR.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
@@ -16,7 +16,7 @@ constexpr uint32_t ImageBindingCount =
|
||||
|
||||
bool CollectUserData(const Program& program, std::vector<uint32_t>& result) {
|
||||
std::array<bool, NumScalarRegs> registers {};
|
||||
for (const auto* block: program.values->blocks) {
|
||||
for (const auto* block: program.blocks) {
|
||||
for (const auto& inst: *block) {
|
||||
if (inst.GetOpcode() != ValueOpcode::GetUserData || !inst.HasUses()) {
|
||||
continue;
|
||||
@@ -47,16 +47,16 @@ void AddBinding(BindingLayout& layout, DescriptorBindingKind kind,
|
||||
|
||||
bool UsesGds(const Program& program, bool& uses_gds) {
|
||||
uses_gds = false;
|
||||
for (const auto* block: program.values->blocks) {
|
||||
for (const auto* block: program.blocks) {
|
||||
for (const auto& inst: *block) {
|
||||
if (SharedAccessOf(inst.GetOpcode()) == SharedAccess::None) {
|
||||
continue;
|
||||
}
|
||||
const auto index = inst.Flags<MemoryFlags>().index;
|
||||
if (index >= program.values->memory_info.size()) {
|
||||
if (index >= program.memory_info.size()) {
|
||||
return false;
|
||||
}
|
||||
const auto kind = program.values->memory_info[index].kind;
|
||||
const auto kind = program.memory_info[index].kind;
|
||||
if (kind != ResourceKind::Lds && kind != ResourceKind::Gds) {
|
||||
return false;
|
||||
}
|
||||
@@ -76,12 +76,6 @@ bool AllocateBindings(Program& program, uint32_t push_constant_offset, std::stri
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (program.values == nullptr) {
|
||||
if (error != nullptr) {
|
||||
*error = "typed value program is not available";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (push_constant_offset > NativePushConstantSize ||
|
||||
push_constant_offset % sizeof(uint32_t) != 0) {
|
||||
if (error != nullptr) {
|
||||
@@ -171,7 +165,7 @@ bool AllocateBindings(Program& program, uint32_t push_constant_offset, std::stri
|
||||
AddBinding(next, DescriptorBindingKind::AddressMemory, std::move(resources));
|
||||
}
|
||||
const bool uses_flattened_runtime =
|
||||
!program.values->srt_reads.empty() ||
|
||||
!program.srt_reads.empty() ||
|
||||
std::ranges::any_of(program.info.images, [](const ImageResource& image) {
|
||||
return image.indirect_mapping_capacity != 0u;
|
||||
});
|
||||
|
||||
@@ -101,7 +101,7 @@ Value GetRealValue(PhiMap& phi_map, Value source, uint32_t lane, uint32_t wave_s
|
||||
|
||||
} // namespace
|
||||
|
||||
ReadLaneStats EliminateReadLane(ValueProgram& program, uint32_t wave_size) {
|
||||
ReadLaneStats EliminateReadLane(Program& program, uint32_t wave_size) {
|
||||
ReadLaneStats stats;
|
||||
if (wave_size != 32u && wave_size != 64u) {
|
||||
return stats;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "graphics/shader/recompiler/ir/ValueProgram.h"
|
||||
#include "graphics/shader/recompiler/ir/ShaderIR.h"
|
||||
|
||||
namespace Libs::Graphics::ShaderRecompiler::IR {
|
||||
|
||||
@@ -8,6 +8,6 @@ struct ReadLaneStats {
|
||||
uint32_t rewritten_reads = 0;
|
||||
};
|
||||
|
||||
[[nodiscard]] ReadLaneStats EliminateReadLane(ValueProgram& program, uint32_t wave_size);
|
||||
[[nodiscard]] ReadLaneStats EliminateReadLane(Program& program, uint32_t wave_size);
|
||||
|
||||
} // namespace Libs::Graphics::ShaderRecompiler::IR
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#include "graphics/shader/recompiler/ir/passes/ResourceMaterialization.h"
|
||||
|
||||
#include "graphics/guest_gpu/gpu_format.h"
|
||||
#include "graphics/shader/recompiler/ir/ValueProgram.h"
|
||||
#include "graphics/shader/recompiler/ir/ShaderIR.h"
|
||||
#include "graphics/shader/shaderBindings.h"
|
||||
|
||||
#include <algorithm>
|
||||
@@ -105,10 +105,10 @@ bool DecodeBufferDescriptor(const DescriptorValue& descriptor, ShaderBufferResou
|
||||
}
|
||||
|
||||
const DescriptorSource* Source(const Program& program, uint32_t source) {
|
||||
if (program.values == nullptr || source >= program.values->descriptor_sources.size()) {
|
||||
if (source >= program.descriptor_sources.size()) {
|
||||
return nullptr;
|
||||
}
|
||||
return &program.values->descriptor_sources[source];
|
||||
return &program.descriptor_sources[source];
|
||||
}
|
||||
|
||||
void MarkCleanFlatSlots(const Program& program, const DescriptorSource* source,
|
||||
@@ -131,7 +131,7 @@ void MarkCleanFlatSlots(const Program& program, const DescriptorSource* source,
|
||||
const auto slot = inst->Arg(1).Resolve();
|
||||
if (slot.IsImmediate() && slot.GetType() == Type::U32 && slot.U32() < slots.size()) {
|
||||
slots[slot.U32()] = 1u;
|
||||
pending.push_back(program.values->srt_reads[slot.U32()].value);
|
||||
pending.push_back(program.srt_reads[slot.U32()].value);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
@@ -275,7 +275,7 @@ uint64_t AddressSpecialization(const AddressResource& resource,
|
||||
}
|
||||
|
||||
size_t FlattenedRuntimeDwords(const Program& program) {
|
||||
size_t size = program.values != nullptr ? program.values->srt_reads.size() : 0u;
|
||||
size_t size = program.srt_reads.size();
|
||||
for (uint32_t resource = 0; resource < program.info.images.size(); resource++) {
|
||||
const auto& image = program.info.images[resource];
|
||||
if (image.indirect_root == resource) {
|
||||
@@ -305,8 +305,7 @@ bool ValidateResourceSnapshot(const Program& program, const ResourceSnapshot& sn
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (program.values == nullptr ||
|
||||
snapshot.flattened_srt.size() != FlattenedRuntimeDwords(program)) {
|
||||
if (snapshot.flattened_srt.size() != FlattenedRuntimeDwords(program)) {
|
||||
if (error != nullptr) {
|
||||
*error = "flattened SRT snapshot does not match the shader plan";
|
||||
}
|
||||
@@ -549,7 +548,7 @@ bool MaterializeResources(const Program& program, const SrtRuntime& runtime,
|
||||
}
|
||||
|
||||
std::vector<DescriptorSourceRequest> requests;
|
||||
std::vector<uint8_t> clean_flat_slots(program.values->srt_reads.size());
|
||||
std::vector<uint8_t> clean_flat_slots(program.srt_reads.size());
|
||||
requests.reserve(program.info.buffers.size() + program.info.images.size() * 2u +
|
||||
program.info.samplers.size() + program.info.addresses.size());
|
||||
for (const auto& buffer: program.info.buffers) {
|
||||
@@ -925,13 +924,7 @@ bool SpecializeResources(Program& program, ResourceSnapshot& snapshot, std::stri
|
||||
}
|
||||
}
|
||||
}
|
||||
if (program.values == nullptr) {
|
||||
if (error != nullptr) {
|
||||
*error = "typed SSA is not ready";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
auto memory_info = program.values->memory_info;
|
||||
auto memory_info = program.memory_info;
|
||||
|
||||
struct SamplerUsage {
|
||||
bool native = false;
|
||||
@@ -980,7 +973,7 @@ bool SpecializeResources(Program& program, ResourceSnapshot& snapshot, std::stri
|
||||
pair.sampler = point_sampler[pair.sampler];
|
||||
}
|
||||
}
|
||||
for (const auto* block: program.values->blocks) {
|
||||
for (const auto* block: program.blocks) {
|
||||
for (const auto& inst: *block) {
|
||||
const auto image_opcode = ImageOpcodeInfoOf(inst.GetOpcode());
|
||||
if (image_opcode.access == ImageAccess::None) {
|
||||
@@ -1023,7 +1016,7 @@ bool SpecializeResources(Program& program, ResourceSnapshot& snapshot, std::stri
|
||||
}
|
||||
}
|
||||
program.info = std::move(next);
|
||||
program.values->memory_info = std::move(memory_info);
|
||||
program.memory_info = std::move(memory_info);
|
||||
snapshot = std::move(next_snapshot);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#include "graphics/shader/recompiler/ir/passes/ResourceTracking.h"
|
||||
|
||||
#include "graphics/shader/recompiler/ir/ValueProgram.h"
|
||||
#include "graphics/shader/recompiler/ir/ShaderIR.h"
|
||||
#include "graphics/shader/recompiler/ir/passes/SrtWalker.h"
|
||||
#include "graphics/shader/shader.h"
|
||||
|
||||
@@ -94,8 +94,7 @@ ImageMipMode MipMode(const MemoryInfo& memory) {
|
||||
|
||||
class Tracker {
|
||||
public:
|
||||
Tracker(Program& program, ValueProgram& values)
|
||||
: m_program(program), m_values(values), m_info(program.info) {
|
||||
explicit Tracker(Program& program): m_program(program), m_info(program.info) {
|
||||
m_info.buffers.clear();
|
||||
m_info.addresses.clear();
|
||||
m_info.images.clear();
|
||||
@@ -111,7 +110,7 @@ public:
|
||||
return Fail(0, error, "SRT plan is not ready");
|
||||
}
|
||||
PlanIndirectImages();
|
||||
for (auto* block: m_values.blocks) {
|
||||
for (auto* block: m_program.blocks) {
|
||||
for (auto& inst: *block) {
|
||||
if (!Collect(inst, error)) {
|
||||
return false;
|
||||
@@ -123,7 +122,7 @@ public:
|
||||
patch.handle->SetFlags<uint32_t>(patch.resource);
|
||||
}
|
||||
for (const auto& patch: m_memory_patches) {
|
||||
auto& memory = m_values.memory_info[patch.index];
|
||||
auto& memory = m_program.memory_info[patch.index];
|
||||
memory.resource = patch.resource;
|
||||
if (patch.has_sampler) {
|
||||
memory.sampler = patch.sampler;
|
||||
@@ -138,16 +137,16 @@ public:
|
||||
plan.handle->SetArg(dword, plan.key);
|
||||
}
|
||||
for (const auto index: plan.memory) {
|
||||
m_values.memory_info[index].planning_only = true;
|
||||
m_program.memory_info[index].planning_only = true;
|
||||
}
|
||||
}
|
||||
std::erase_if(m_values.dynamic_reads, [&](Value value) {
|
||||
std::erase_if(m_program.dynamic_reads, [&](Value value) {
|
||||
const auto* inst = value.Resolve().TryInstruction();
|
||||
return std::ranges::any_of(m_indirect_images, [&](const IndirectImagePlan& plan) {
|
||||
return std::ranges::find(plan.reads, inst) != plan.reads.end();
|
||||
});
|
||||
});
|
||||
m_values.descriptor_sources = std::move(m_sources);
|
||||
m_program.descriptor_sources = std::move(m_sources);
|
||||
m_program.info = std::move(m_info);
|
||||
m_program.resource_tracking_complete = true;
|
||||
return true;
|
||||
@@ -208,19 +207,19 @@ private:
|
||||
if (left.value.IsEmpty() || right.value.IsEmpty()) {
|
||||
return require_both ? AddressPart {} : (left.value.IsEmpty() ? right : left);
|
||||
}
|
||||
return EquivalentValue(m_values, left.value, right.value)
|
||||
return EquivalentValue(m_program, left.value, right.value)
|
||||
? AddressPart {left.value, left.rooted || right.rooted}
|
||||
: AddressPart {};
|
||||
};
|
||||
switch (inst->GetOpcode()) {
|
||||
case ValueOpcode::SelectU32:
|
||||
if (EquivalentValue(m_values, inst->Arg(0), active)) {
|
||||
if (EquivalentValue(m_program, inst->Arg(0), active)) {
|
||||
return finish(FindAddressPart(inst->Arg(1), active, visiting));
|
||||
}
|
||||
return finish(merge(FindAddressPart(inst->Arg(1), active, visiting),
|
||||
FindAddressPart(inst->Arg(2), active, visiting), true));
|
||||
case ValueOpcode::Phi: {
|
||||
const auto invariant = ResolveInvariantPhi(m_values, value);
|
||||
const auto invariant = ResolveInvariantPhi(m_program, value);
|
||||
return finish(invariant.IsEmpty() ? AddressPart {}
|
||||
: FindAddressPart(invariant, active, visiting));
|
||||
}
|
||||
@@ -312,7 +311,7 @@ private:
|
||||
}
|
||||
bool same = true;
|
||||
for (uint32_t i = 0; i < descriptor.dword_count; i++) {
|
||||
same = same && EquivalentValue(m_values, current.dwords[i], descriptor.dwords[i]);
|
||||
same = same && EquivalentValue(m_program, current.dwords[i], descriptor.dwords[i]);
|
||||
}
|
||||
if (same) {
|
||||
return candidate;
|
||||
@@ -342,10 +341,10 @@ private:
|
||||
return nullptr;
|
||||
}
|
||||
index = read.Flags<MemoryFlags>().index;
|
||||
if (index >= m_values.memory_info.size()) {
|
||||
if (index >= m_program.memory_info.size()) {
|
||||
return nullptr;
|
||||
}
|
||||
const auto& memory = m_values.memory_info[index];
|
||||
const auto& memory = m_program.memory_info[index];
|
||||
return memory.kind == ResourceKind::ScalarBuffer && memory.data_bits == 32u &&
|
||||
memory.data_dwords == 1u
|
||||
? &memory
|
||||
@@ -353,7 +352,7 @@ private:
|
||||
}
|
||||
|
||||
bool MemoryIndexBelongsTo(uint32_t index, const Inst& owner) const {
|
||||
for (const auto* block: m_values.blocks) {
|
||||
for (const auto* block: m_program.blocks) {
|
||||
for (const auto& inst: *block) {
|
||||
const auto op = inst.GetOpcode();
|
||||
if ((BufferAccessOf(op) == BufferAccess::None &&
|
||||
@@ -446,7 +445,7 @@ private:
|
||||
heap_handle = current_handle;
|
||||
if (dword == 0u) {
|
||||
heap_offset = heap_reads[dword]->Arg(1).Resolve();
|
||||
} else if (!EquivalentValue(m_values, heap_offset, heap_reads[dword]->Arg(1))) {
|
||||
} else if (!EquivalentValue(m_program, heap_offset, heap_reads[dword]->Arg(1))) {
|
||||
return false;
|
||||
}
|
||||
plan.memory[dword] = memory_index;
|
||||
@@ -537,7 +536,7 @@ private:
|
||||
}
|
||||
|
||||
void PlanIndirectImages() {
|
||||
for (auto* block: m_values.blocks) {
|
||||
for (auto* block: m_program.blocks) {
|
||||
for (auto& inst: *block) {
|
||||
if (ImageOpcodeInfoOf(inst.GetOpcode()).access == ImageAccess::None ||
|
||||
inst.NumArgs() == 0u) {
|
||||
@@ -588,7 +587,7 @@ private:
|
||||
return Fail(pc, error, "GetAddressResource must have two address dwords");
|
||||
}
|
||||
DescriptorSource descriptor;
|
||||
const auto& memory = m_values.memory_info[memory_inst.Flags<MemoryFlags>().index];
|
||||
const auto& memory = m_program.memory_info[memory_inst.Flags<MemoryFlags>().index];
|
||||
if (memory.address_is_full) {
|
||||
const auto active = memory_inst.Arg(memory_inst.NumArgs() - 1u);
|
||||
if (memory.kind != ResourceKind::Flat ||
|
||||
@@ -797,14 +796,14 @@ private:
|
||||
return true;
|
||||
}
|
||||
const auto flags = inst.Flags<MemoryFlags>();
|
||||
if (flags.index >= m_values.memory_info.size()) {
|
||||
if (flags.index >= m_program.memory_info.size()) {
|
||||
return Fail(flags.pc, error,
|
||||
fmt::format("memory metadata index {} is out of range", flags.index));
|
||||
}
|
||||
if (inst.NumArgs() == 0) {
|
||||
return Fail(flags.pc, error, "memory operation has no resource handle");
|
||||
}
|
||||
const auto& memory = m_values.memory_info[flags.index];
|
||||
const auto& memory = m_program.memory_info[flags.index];
|
||||
if (memory.planning_only || IsIndirectPlanningMemory(flags.index)) {
|
||||
return true;
|
||||
}
|
||||
@@ -914,7 +913,7 @@ private:
|
||||
}
|
||||
bool alias = true;
|
||||
for (uint32_t dword = 0; dword < 4; dword++) {
|
||||
alias = alias && EquivalentValue(m_values, buffer_source->dwords[dword],
|
||||
alias = alias && EquivalentValue(m_program, buffer_source->dwords[dword],
|
||||
image_source->dwords[dword]);
|
||||
}
|
||||
if (alias) {
|
||||
@@ -926,7 +925,6 @@ private:
|
||||
}
|
||||
|
||||
Program& m_program;
|
||||
ValueProgram& m_values;
|
||||
ShaderInfo m_info;
|
||||
std::vector<DescriptorSource> m_sources;
|
||||
std::vector<HandlePatch> m_handle_patches;
|
||||
@@ -937,13 +935,7 @@ private:
|
||||
} // namespace
|
||||
|
||||
bool TrackResources(Program& program, std::string* error) {
|
||||
if (program.values == nullptr) {
|
||||
if (error != nullptr) {
|
||||
*error = "shader resource tracking requires typed IR";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return Tracker(program, *program.values).Run(error);
|
||||
return Tracker(program).Run(error);
|
||||
}
|
||||
|
||||
} // namespace Libs::Graphics::ShaderRecompiler::IR
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#include "graphics/shader/recompiler/ir/passes/ShaderInfoCollection.h"
|
||||
|
||||
#include "graphics/shader/recompiler/ir/ValueProgram.h"
|
||||
#include "graphics/shader/recompiler/ir/ShaderIR.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <fmt/format.h>
|
||||
@@ -66,7 +66,7 @@ bool ValidateValueReferences(const Program& program, const ShaderInfoOptions& op
|
||||
}
|
||||
return false;
|
||||
};
|
||||
for (const auto* block: program.values->blocks) {
|
||||
for (const auto* block: program.blocks) {
|
||||
for (const auto& inst: *block) {
|
||||
switch (inst.GetOpcode()) {
|
||||
case ValueOpcode::GetAttribute: {
|
||||
@@ -140,7 +140,7 @@ bool ValidateValueReferences(const Program& program, const ShaderInfoOptions& op
|
||||
break;
|
||||
}
|
||||
case ValueOpcode::SetAttribute:
|
||||
if (inst.Flags<ExportFlags>().index >= program.values->export_info.size()) {
|
||||
if (inst.Flags<ExportFlags>().index >= program.export_info.size()) {
|
||||
return Fail("typed export metadata index is out of range");
|
||||
}
|
||||
break;
|
||||
@@ -156,7 +156,7 @@ void CollectVertexInputs(const Program& program, const ShaderVertexInputInfo* ve
|
||||
AddInput(info, StageInputKind::VertexIndex, 0, 1, "gl_VertexIndex");
|
||||
AddInput(info, StageInputKind::InstanceIndex, 0, 1, "gl_InstanceIndex");
|
||||
uint32_t used_components[ShaderVertexInputInfo::RES_MAX] = {};
|
||||
for (const auto* block: program.values->blocks) {
|
||||
for (const auto* block: program.blocks) {
|
||||
for (const auto& inst: *block) {
|
||||
if (inst.GetOpcode() == ValueOpcode::GetAttribute) {
|
||||
const auto attr = inst.Arg(0).U32();
|
||||
@@ -185,7 +185,7 @@ void CollectPixelInputs(const Program& program, const ShaderPixelInputInfo* pixe
|
||||
}
|
||||
std::array<bool, 32> per_vertex {};
|
||||
std::array<bool, 32> interpolated {};
|
||||
for (const auto* block: program.values->blocks) {
|
||||
for (const auto* block: program.blocks) {
|
||||
for (const auto& inst: *block) {
|
||||
if (inst.GetOpcode() == ValueOpcode::GetAttribute) {
|
||||
interpolated[inst.Arg(0).U32()] = true;
|
||||
@@ -228,7 +228,7 @@ void CollectComputeInputs(const ShaderComputeInputInfo* compute, ShaderInfo& inf
|
||||
}
|
||||
|
||||
void CollectBuiltinInputs(const Program& program, ShaderInfo& info) {
|
||||
for (const auto* block: program.values->blocks) {
|
||||
for (const auto* block: program.blocks) {
|
||||
for (const auto& inst: *block) {
|
||||
if (inst.GetOpcode() != ValueOpcode::GetBuiltin) {
|
||||
continue;
|
||||
@@ -277,12 +277,12 @@ bool CollectOutputs(const Program& program, const ShaderVertexInputInfo* vertex,
|
||||
}
|
||||
return false;
|
||||
};
|
||||
for (const auto* block: program.values->blocks) {
|
||||
for (const auto* block: program.blocks) {
|
||||
for (const auto& inst: *block) {
|
||||
if (inst.GetOpcode() != ValueOpcode::SetAttribute) {
|
||||
continue;
|
||||
}
|
||||
const auto& export_info = program.values->export_info[inst.Flags<ExportFlags>().index];
|
||||
const auto& export_info = program.export_info[inst.Flags<ExportFlags>().index];
|
||||
if (export_info.kind == ExportTargetKind::MrtZ) {
|
||||
if (program.stage == ShaderType::Pixel && (export_info.en & 0x1u) != 0 &&
|
||||
pixel->ps_depth_export_enable) {
|
||||
@@ -360,12 +360,6 @@ bool CollectShaderInfo(Program& program, const ShaderInfoOptions& options, std::
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (program.values == nullptr) {
|
||||
if (error != nullptr) {
|
||||
*error = "typed value program is not available";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (!ValidateOptions(program, options, error)) {
|
||||
return false;
|
||||
}
|
||||
@@ -377,7 +371,7 @@ bool CollectShaderInfo(Program& program, const ShaderInfoOptions& options, std::
|
||||
next.inputs.clear();
|
||||
next.outputs.clear();
|
||||
next.has_bitwise_xor = std::any_of(
|
||||
program.values->blocks.begin(), program.values->blocks.end(), [](const auto* block) {
|
||||
program.blocks.begin(), program.blocks.end(), [](const auto* block) {
|
||||
return std::any_of(block->begin(), block->end(), [](const auto& inst) {
|
||||
return inst.GetOpcode() == ValueOpcode::BitwiseXor32;
|
||||
});
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#include "graphics/shader/recompiler/ir/passes/SharedMemoryBarrier.h"
|
||||
|
||||
#include "graphics/shader/recompiler/ir/ValueProgram.h"
|
||||
#include "graphics/shader/recompiler/ir/ShaderIR.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <queue>
|
||||
@@ -12,7 +12,7 @@ namespace {
|
||||
|
||||
enum class LdsPhase { None, Read, Write };
|
||||
|
||||
LdsPhase GetLdsPhase(const ValueProgram& program, const Inst& inst) {
|
||||
LdsPhase GetLdsPhase(const Program& program, const Inst& inst) {
|
||||
const auto access = SharedAccessOf(inst.GetOpcode());
|
||||
if (access != SharedAccess::Read && access != SharedAccess::Write) {
|
||||
return LdsPhase::None;
|
||||
@@ -59,7 +59,7 @@ uint32_t InsertBarrier(Block& block, Block::iterator position) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint32_t InsertBlockBarriers(ValueProgram& program, Block& block) {
|
||||
uint32_t InsertBlockBarriers(Program& program, Block& block) {
|
||||
uint32_t inserted = 0;
|
||||
LdsPhase phase = LdsPhase::None;
|
||||
for (auto inst = block.begin(); inst != block.end(); ++inst) {
|
||||
@@ -94,7 +94,7 @@ uint32_t InsertMergeBarrier(Block& block) {
|
||||
|
||||
} // namespace
|
||||
|
||||
SharedMemoryBarrierStats InsertSharedMemoryBarriers(ValueProgram& program, uint32_t wave_size,
|
||||
SharedMemoryBarrierStats InsertSharedMemoryBarriers(Program& program, uint32_t wave_size,
|
||||
const ShaderComputeInputInfo& compute_info) {
|
||||
SharedMemoryBarrierStats stats;
|
||||
const auto threadgroup_size = compute_info.threads_num[0] * compute_info.threads_num[1] *
|
||||
|
||||
@@ -9,7 +9,7 @@ struct SharedMemoryBarrierStats {
|
||||
};
|
||||
|
||||
[[nodiscard]] SharedMemoryBarrierStats
|
||||
InsertSharedMemoryBarriers(ValueProgram& program, uint32_t wave_size,
|
||||
InsertSharedMemoryBarriers(Program& program, uint32_t wave_size,
|
||||
const ShaderComputeInputInfo& compute_info);
|
||||
|
||||
} // namespace Libs::Graphics::ShaderRecompiler::IR
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#include "graphics/shader/recompiler/ir/passes/SrtWalker.h"
|
||||
|
||||
#include "graphics/shader/recompiler/ir/ValueProgram.h"
|
||||
#include "graphics/shader/recompiler/ir/ShaderIR.h"
|
||||
#include "graphics/shader/shader.h"
|
||||
|
||||
#include <algorithm>
|
||||
@@ -50,7 +50,7 @@ bool AddSignedAddress(uint64_t base, int64_t offset, uint64_t& result) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IsRawRead(const ValueProgram& values, const Inst& inst) {
|
||||
bool IsRawRead(const Program& values, const Inst& inst) {
|
||||
const auto op = inst.GetOpcode();
|
||||
if (op != ValueOpcode::LoadAddressU32 && op != ValueOpcode::ReadConstBuffer) {
|
||||
return false;
|
||||
@@ -118,8 +118,7 @@ bool IsRuntimeIntegerOp(ValueOpcode op) {
|
||||
|
||||
class RuntimeValidator {
|
||||
public:
|
||||
RuntimeValidator(const Program& program, const ValueProgram& values)
|
||||
: m_program(program), m_values(values) {}
|
||||
explicit RuntimeValidator(const Program& program): m_program(program) {}
|
||||
|
||||
bool Run(Value value, std::string& reason) { return Validate(value, reason); }
|
||||
|
||||
@@ -176,7 +175,7 @@ private:
|
||||
return finish(true);
|
||||
}
|
||||
if (op == ValueOpcode::Phi) {
|
||||
const auto invariant = ResolveInvariantPhi(m_values, value);
|
||||
const auto invariant = ResolveInvariantPhi(m_program, value);
|
||||
if (invariant.IsEmpty()) {
|
||||
reason = "contains a control-dependent phi";
|
||||
return finish(false);
|
||||
@@ -196,7 +195,7 @@ private:
|
||||
inst->Arg(0).Resolve().TryInstruction()->GetOpcode() !=
|
||||
ValueOpcode::GetSrtResource ||
|
||||
!slot.IsImmediate() || slot.GetType() != Type::U32 ||
|
||||
slot.U32() >= m_values.srt_reads.size()) {
|
||||
slot.U32() >= m_program.srt_reads.size()) {
|
||||
reason = "contains a malformed flattened SRT read";
|
||||
return finish(false);
|
||||
}
|
||||
@@ -205,7 +204,7 @@ private:
|
||||
? ValueOpcode::GetAddressResource
|
||||
: ValueOpcode::GetBufferResource;
|
||||
const auto* handle = inst->NumArgs() != 0 ? inst->Arg(0).ResolveInstruction() : nullptr;
|
||||
if (!IsRawRead(m_values, *inst) || handle == nullptr ||
|
||||
if (!IsRawRead(m_program, *inst) || handle == nullptr ||
|
||||
handle->GetOpcode() != expected) {
|
||||
reason = fmt::format("contains a non-scalar {}", ValueOpcodeName(op));
|
||||
return finish(false);
|
||||
@@ -252,24 +251,23 @@ private:
|
||||
}
|
||||
|
||||
const Program& m_program;
|
||||
const ValueProgram& m_values;
|
||||
std::unordered_set<const Inst*> m_visiting;
|
||||
};
|
||||
|
||||
class PlanBuilder {
|
||||
public:
|
||||
PlanBuilder(Program& program, ValueProgram& values): m_program(program), m_values(values) {}
|
||||
explicit PlanBuilder(Program& program): m_program(program) {}
|
||||
|
||||
bool Run(std::string* error) {
|
||||
m_values.srt_reads.clear();
|
||||
m_values.dynamic_reads.clear();
|
||||
for (auto* block: m_values.blocks) {
|
||||
m_program.srt_reads.clear();
|
||||
m_program.dynamic_reads.clear();
|
||||
for (auto* block: m_program.blocks) {
|
||||
for (auto& inst: *block) {
|
||||
const auto op = inst.GetOpcode();
|
||||
if (op == ValueOpcode::LoadAddressU32 || op == ValueOpcode::ReadConstBuffer) {
|
||||
const auto flags = inst.Flags<MemoryFlags>();
|
||||
if (flags.index < m_values.memory_info.size()) {
|
||||
const auto kind = m_values.memory_info[flags.index].kind;
|
||||
if (flags.index < m_program.memory_info.size()) {
|
||||
const auto kind = m_program.memory_info[flags.index].kind;
|
||||
const bool crosswired = (op == ValueOpcode::LoadAddressU32 &&
|
||||
kind == ResourceKind::ScalarBuffer) ||
|
||||
(op == ValueOpcode::ReadConstBuffer &&
|
||||
@@ -290,10 +288,10 @@ public:
|
||||
}
|
||||
}
|
||||
}
|
||||
for (auto* block: m_values.blocks) {
|
||||
for (auto* block: m_program.blocks) {
|
||||
for (auto& inst: *block) {
|
||||
std::string reason;
|
||||
if (inst.GetOpcode() == ValueOpcode::LoadAddressU32 && IsRawRead(m_values, inst) &&
|
||||
if (inst.GetOpcode() == ValueOpcode::LoadAddressU32 && IsRawRead(m_program, inst) &&
|
||||
inst.Arg(1).Resolve().IsImmediate() &&
|
||||
ValidateRuntimeValue(m_program, Value(&inst), reason) &&
|
||||
!Collect(Value(&inst), inst.Flags<MemoryFlags>().pc, error)) {
|
||||
@@ -348,25 +346,25 @@ private:
|
||||
}
|
||||
m_visiting.pop_back();
|
||||
m_visited.push_back(inst);
|
||||
if (!IsRawRead(m_values, *inst)) {
|
||||
if (!IsRawRead(m_program, *inst)) {
|
||||
return true;
|
||||
}
|
||||
const auto offset = inst->Arg(1).Resolve();
|
||||
if (!offset.IsImmediate() || offset.GetType() != Type::U32) {
|
||||
if (std::ranges::find(m_values.dynamic_reads, value) == m_values.dynamic_reads.end()) {
|
||||
m_values.dynamic_reads.push_back(value);
|
||||
if (std::ranges::find(m_program.dynamic_reads, value) == m_program.dynamic_reads.end()) {
|
||||
m_program.dynamic_reads.push_back(value);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
use_pc = inst->Flags<MemoryFlags>().pc;
|
||||
for (uint32_t slot = 0; slot < m_values.srt_reads.size(); slot++) {
|
||||
if (EquivalentValue(m_values, value, m_values.srt_reads[slot].value)) {
|
||||
for (uint32_t slot = 0; slot < m_program.srt_reads.size(); slot++) {
|
||||
if (EquivalentValue(m_program, value, m_program.srt_reads[slot].value)) {
|
||||
m_patches.push_back({inst, slot, false});
|
||||
return true;
|
||||
}
|
||||
}
|
||||
const auto slot = static_cast<uint32_t>(m_values.srt_reads.size());
|
||||
m_values.srt_reads.push_back({value, slot, use_pc});
|
||||
const auto slot = static_cast<uint32_t>(m_program.srt_reads.size());
|
||||
m_program.srt_reads.push_back({value, slot, use_pc});
|
||||
m_patches.push_back({inst, slot, true});
|
||||
return true;
|
||||
}
|
||||
@@ -385,7 +383,7 @@ private:
|
||||
for (const auto& use: uses) {
|
||||
use.user->SetArg(use.operand, flat);
|
||||
}
|
||||
for (auto& info: m_values.block_info) {
|
||||
for (auto& info: m_program.block_info) {
|
||||
if (info.condition.Resolve() == Value(patch.inst)) {
|
||||
info.condition = flat;
|
||||
}
|
||||
@@ -395,8 +393,8 @@ private:
|
||||
}
|
||||
if (patch.keep) {
|
||||
const auto memory = patch.inst->Flags<MemoryFlags>().index;
|
||||
if (memory < m_values.memory_info.size()) {
|
||||
m_values.memory_info[memory].planning_only = true;
|
||||
if (memory < m_program.memory_info.size()) {
|
||||
m_program.memory_info[memory].planning_only = true;
|
||||
}
|
||||
block->AppendNewInst(ValueOpcode::ReferenceU32, {Value(patch.inst)});
|
||||
}
|
||||
@@ -404,7 +402,6 @@ private:
|
||||
}
|
||||
|
||||
Program& m_program;
|
||||
ValueProgram& m_values;
|
||||
std::vector<Inst*> m_visiting;
|
||||
std::vector<Inst*> m_visited;
|
||||
std::vector<Patch> m_patches;
|
||||
@@ -414,7 +411,7 @@ class Evaluator {
|
||||
public:
|
||||
Evaluator(const Program& program, const SrtRuntime& runtime,
|
||||
std::span<const uint8_t> clean_flat_slots = {}, Evaluator* clean_evaluator = nullptr)
|
||||
: m_program(program), m_values(*program.values), m_runtime(runtime),
|
||||
: m_program(program), m_runtime(runtime),
|
||||
m_clean_flat_slots(clean_flat_slots), m_clean_evaluator(clean_evaluator) {}
|
||||
|
||||
void SetUsePc(uint32_t pc) { m_use_pc = pc; }
|
||||
@@ -472,7 +469,7 @@ private:
|
||||
}
|
||||
|
||||
bool EvaluatePhi(const Inst& inst, uint64_t& result, std::string* error) {
|
||||
const auto value = ResolveInvariantPhi(m_values, Value(const_cast<Inst*>(&inst)));
|
||||
const auto value = ResolveInvariantPhi(m_program, Value(const_cast<Inst*>(&inst)));
|
||||
return !value.IsEmpty() ? EvaluateWide(value, result, error)
|
||||
: Fail(error, "typed phi has runtime-dependent values");
|
||||
}
|
||||
@@ -518,10 +515,10 @@ private:
|
||||
|
||||
bool EvaluateRawRead(const Inst& inst, uint64_t& result, std::string* error) {
|
||||
const auto flags = inst.Flags<MemoryFlags>();
|
||||
if (flags.index >= m_values.memory_info.size()) {
|
||||
if (flags.index >= m_program.memory_info.size()) {
|
||||
return Fail(error, "raw scalar read has invalid metadata");
|
||||
}
|
||||
const auto& mem = m_values.memory_info[flags.index];
|
||||
const auto& mem = m_program.memory_info[flags.index];
|
||||
const auto* handle = inst.Arg(0).ResolveInstruction();
|
||||
if (handle == nullptr) {
|
||||
return Fail(error, "raw scalar read has no descriptor handle");
|
||||
@@ -609,20 +606,20 @@ private:
|
||||
case ValueOpcode::ReadConst: {
|
||||
const auto slot = inst.Arg(1).Resolve();
|
||||
if (!slot.IsImmediate() || slot.GetType() != Type::U32 ||
|
||||
slot.U32() >= m_values.srt_reads.size()) {
|
||||
slot.U32() >= m_program.srt_reads.size()) {
|
||||
return Fail(error, "invalid flattened SRT index");
|
||||
}
|
||||
if (slot.U32() < m_clean_flat_slots.size() &&
|
||||
m_clean_flat_slots[slot.U32()] != 0u && m_clean_evaluator != nullptr) {
|
||||
m_clean_evaluator->SetUsePc(m_use_pc);
|
||||
return m_clean_evaluator->EvaluateWide(m_values.srt_reads[slot.U32()].value,
|
||||
return m_clean_evaluator->EvaluateWide(m_program.srt_reads[slot.U32()].value,
|
||||
result, error);
|
||||
}
|
||||
return EvaluateWide(m_values.srt_reads[slot.U32()].value, result, error);
|
||||
return EvaluateWide(m_program.srt_reads[slot.U32()].value, result, error);
|
||||
}
|
||||
case ValueOpcode::LoadAddressU32:
|
||||
case ValueOpcode::ReadConstBuffer:
|
||||
if (IsRawRead(m_values, inst)) {
|
||||
if (IsRawRead(m_program, inst)) {
|
||||
return EvaluateRawRead(inst, result, error);
|
||||
}
|
||||
break;
|
||||
@@ -856,7 +853,6 @@ private:
|
||||
}
|
||||
|
||||
const Program& m_program;
|
||||
const ValueProgram& m_values;
|
||||
const SrtRuntime& m_runtime;
|
||||
std::span<const uint8_t> m_clean_flat_slots;
|
||||
Evaluator* m_clean_evaluator = nullptr;
|
||||
@@ -866,10 +862,10 @@ private:
|
||||
};
|
||||
|
||||
const DescriptorSource* Source(const Program& program, uint32_t source) {
|
||||
if (program.values == nullptr || source >= program.values->descriptor_sources.size()) {
|
||||
if (source >= program.descriptor_sources.size()) {
|
||||
return nullptr;
|
||||
}
|
||||
return &program.values->descriptor_sources[source];
|
||||
return &program.descriptor_sources[source];
|
||||
}
|
||||
|
||||
bool EvaluateRuntimeSourcesImpl(const Program& program,
|
||||
@@ -877,7 +873,7 @@ bool EvaluateRuntimeSourcesImpl(const Program& program
|
||||
const SrtRuntime& runtime, std::vector<DescriptorValue>& results,
|
||||
std::vector<uint32_t>& flat, bool evaluate_flat,
|
||||
std::span<const uint8_t> clean_flat_slots, std::string* error) {
|
||||
if (program.values == nullptr || !program.srt_plan_complete) {
|
||||
if (!program.srt_plan_complete) {
|
||||
if (error != nullptr) {
|
||||
*error = Diagnostic(program, 0, "typed SRT plan is not ready");
|
||||
}
|
||||
@@ -917,8 +913,8 @@ bool EvaluateRuntimeSourcesImpl(const Program& program
|
||||
}
|
||||
std::vector<uint32_t> flattened;
|
||||
if (evaluate_flat) {
|
||||
flattened.resize(program.values->srt_reads.size());
|
||||
for (const auto& read: program.values->srt_reads) {
|
||||
flattened.resize(program.srt_reads.size());
|
||||
for (const auto& read: program.srt_reads) {
|
||||
const bool clean = read.flat_offset < clean_flat_slots.size() &&
|
||||
clean_flat_slots[read.flat_offset] != 0u;
|
||||
auto& selected = clean ? clean_evaluator : evaluator;
|
||||
@@ -939,23 +935,18 @@ bool EvaluateRuntimeSourcesImpl(const Program& program
|
||||
} // namespace
|
||||
|
||||
bool ValidateRuntimeValue(const Program& program, Value value, std::string& reason) {
|
||||
if (program.values == nullptr) {
|
||||
reason = "typed SSA is not ready";
|
||||
return false;
|
||||
}
|
||||
return RuntimeValidator(program, *program.values).Run(value, reason);
|
||||
return RuntimeValidator(program).Run(value, reason);
|
||||
}
|
||||
|
||||
bool BuildSrtPlan(Program& program, std::string* error) {
|
||||
if (program.values == nullptr || program.resource_tracking_complete) {
|
||||
if (program.resource_tracking_complete) {
|
||||
if (error != nullptr) {
|
||||
*error = program.values == nullptr ? "typed SSA is not ready"
|
||||
: "cannot rebuild SRT after resource tracking";
|
||||
*error = "cannot rebuild SRT after resource tracking";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
program.srt_plan_complete = false;
|
||||
if (!PlanBuilder(program, *program.values).Run(error)) {
|
||||
if (!PlanBuilder(program).Run(error)) {
|
||||
return false;
|
||||
}
|
||||
program.srt_plan_complete = true;
|
||||
|
||||
Reference in New Issue
Block a user