shader: remove recompiler error-string propagation

This commit is contained in:
nmzik
2026-08-31 05:30:18 +04:00
parent 13533bd053
commit af8aecfdde
47 changed files with 2040 additions and 3253 deletions
@@ -1,9 +1,8 @@
#include "common/assert.h"
#include "graphics/shader/recompiler/frontend/translate/Translator.h"
#include "graphics/shader/shader.h"
#include <algorithm>
#include <array>
#include <fmt/format.h>
namespace Libs::Graphics::ShaderRecompiler::Frontend {
@@ -47,14 +46,13 @@ IR::ExportFlags Translator::AddExportInfo(const Decoder::Instruction& inst) {
return {.index = index, .pc = inst.pc};
}
bool Translator::TranslateEmbeddedFetch(const Decoder::Instruction& inst, uint32_t attribute,
void Translator::TranslateEmbeddedFetch(const Decoder::Instruction& inst, uint32_t attribute,
uint32_t component_count) {
for (uint32_t component = 0; component < component_count; component++) {
const auto value =
ir.Emit(IR::ValueOpcode::GetAttribute, {IR::Value(attribute), IR::Value(component)});
WriteOperand(OffsetOperand(inst.dst, component), value);
}
return true;
}
void Translator::V_INTERP_P1_F32() {}
@@ -65,25 +63,20 @@ void Translator::V_INTERP_P2_F32(const Decoder::Instruction& inst) {
WriteOperand(inst.dst, value);
}
bool Translator::V_INTERP_MOV_F32(const Decoder::Instruction& inst, std::string* error) {
void Translator::V_INTERP_MOV_F32(const Decoder::Instruction& inst) {
if (inst.src0.value >= 3u) {
return ShaderError::Fail(error,
fmt::format("v_interp_mov_f32 mode {} is reserved at pc 0x{:08x}",
inst.src0.value, inst.pc));
EXIT("v_interp_mov_f32 mode %u is reserved at pc 0x%08x", inst.src0.value, inst.pc);
}
const auto value = ir.Emit(
IR::ValueOpcode::GetInterpolationParameter,
{IR::Value(inst.src1.value), IR::Value(inst.src2.value), IR::Value(inst.src0.value)});
WriteOperand(inst.dst, value);
return true;
}
bool Translator::EXP(const Decoder::Instruction& inst, std::string* error) {
void Translator::EXP(const Decoder::Instruction& inst) {
uint32_t index = 0;
if (ExportTargetKindFromTarget(inst.exp.target, index) == IR::ExportTargetKind::Unknown) {
return ShaderError::Fail(error,
fmt::format("unsupported EXP target 0x{:02x} at pc 0x{:08x}",
inst.exp.target, inst.pc));
EXIT("unsupported EXP target 0x%02x at pc 0x%08x", inst.exp.target, inst.pc);
}
std::array<IR::Value, 4> components {IR::Value(0u), IR::Value(0u), IR::Value(0u),
IR::Value(0u)};
@@ -93,14 +86,13 @@ bool Translator::EXP(const Decoder::Instruction& inst, std::string* error) {
const auto data = ir.Emit(IR::ValueOpcode::CompositeConstructU32x4,
{components[0], components[1], components[2], components[3]});
ir.Emit(IR::ValueOpcode::SetAttribute, {data, ir.GetExec()}, AddExportInfo(inst));
return true;
}
bool Translator::EmitInterpolation(const Decoder::Instruction& inst, std::string* error) {
bool Translator::EmitInterpolation(const Decoder::Instruction& inst) {
switch (inst.opcode) {
case Decoder::Opcode::V_INTERP_P1_F32: V_INTERP_P1_F32(); return true;
case Decoder::Opcode::V_INTERP_P2_F32: V_INTERP_P2_F32(inst); return true;
case Decoder::Opcode::V_INTERP_MOV_F32: return V_INTERP_MOV_F32(inst, error);
case Decoder::Opcode::V_INTERP_MOV_F32: V_INTERP_MOV_F32(inst); return true;
default: return false;
}
}
@@ -1,3 +1,4 @@
#include "common/assert.h"
#include "graphics/shader/recompiler/frontend/translate/Translator.h"
namespace Libs::Graphics::ShaderRecompiler::Frontend {
@@ -163,12 +164,12 @@ void Translator::S_INST_PREFETCH() {
ir.Emit(IR::ValueOpcode::InstPrefetch);
}
bool Translator::S_GETPC_B64(const Decoder::Instruction& inst, std::string* error) {
void Translator::S_GETPC_B64(const Decoder::Instruction& inst) {
const auto base = IR::U64(ir.Emit(IR::ValueOpcode::GetShaderBase));
const auto address = IR::U64(
ir.Emit(IR::ValueOpcode::IAdd64, {base, IR::Value(static_cast<uint64_t>(inst.pc) + 4u)}));
if (inst.dst.kind == Decoder::OperandKind::Null) {
return true;
return;
}
auto high = PlainOperand(inst.dst);
switch (inst.dst.kind) {
@@ -179,25 +180,19 @@ bool Translator::S_GETPC_B64(const Decoder::Instruction& inst, std::string* erro
high.kind = Decoder::OperandKind::VccLo;
high.reg = 0u;
} else {
if (error != nullptr) {
*error = "S_GETPC_B64 destination does not name a valid scalar pair";
}
return false;
EXIT("S_GETPC_B64 destination does not name a valid scalar pair at pc 0x%08x",
inst.pc);
}
break;
case Decoder::OperandKind::VccLo: high.kind = Decoder::OperandKind::VccHi; break;
case Decoder::OperandKind::M0: high.kind = Decoder::OperandKind::Null; break;
case Decoder::OperandKind::ExecLo: high.kind = Decoder::OperandKind::ExecHi; break;
default:
if (error != nullptr) {
*error = "S_GETPC_B64 destination does not name a valid scalar pair";
}
return false;
EXIT("S_GETPC_B64 destination does not name a valid scalar pair at pc 0x%08x", inst.pc);
}
const auto words = ExtractU64(address);
WriteOperand(inst.dst, words[0]);
WriteOperand(high, words[1]);
return true;
}
void Translator::S_CSELECT_B32(const Decoder::Instruction& inst) {
@@ -213,8 +208,8 @@ void Translator::S_CSELECT_B64(const Decoder::Instruction& inst) {
}
void Translator::MOV_B32(const Decoder::Instruction& inst, bool apply_float_modifiers) {
if (inst.src0.kind == Decoder::OperandKind::Sgpr && inst.dst.kind == Decoder::OperandKind::Sgpr &&
inst.src0.reg == inst.dst.reg) {
if (inst.src0.kind == Decoder::OperandKind::Sgpr &&
inst.dst.kind == Decoder::OperandKind::Sgpr && inst.src0.reg == inst.dst.reg) {
return;
}
if (IsExecOrVcc(inst.src0) && IsExecOrVcc(inst.dst)) {
@@ -242,21 +237,15 @@ void Translator::S_WQM_B64(const Decoder::Instruction& inst) {
ir.SetScc(ScalarU64NonZero(result));
}
bool Translator::V_MOVRELS_B32(const Decoder::Instruction& inst, std::string* error) {
void Translator::V_MOVRELS_B32(const Decoder::Instruction& inst) {
if (inst.dst.kind != Decoder::OperandKind::Vgpr ||
inst.src0.kind != Decoder::OperandKind::Vgpr) {
if (error != nullptr) {
*error = "V_MOVRELS_B32 requires VGPR source and destination";
}
return false;
EXIT("V_MOVRELS_B32 requires VGPR source and destination at pc 0x%08x", inst.pc);
}
if (inst.dst.sdwa_sel != 6u || inst.dst.omod != 0u || inst.dst.clamp ||
inst.src0.sdwa_sel != 6u || inst.src0.sdwa_sext || inst.src0.negate || inst.src0.absolute ||
inst.src0.dpp) {
if (error != nullptr) {
*error = "V_MOVRELS_B32 modifiers are not implemented";
}
return false;
EXIT("V_MOVRELS_B32 modifiers are not implemented at pc 0x%08x", inst.pc);
}
const auto base = inst.src0.reg;
const auto m0 = ir.BitwiseAnd(ReadU32(ConditionOperand(Decoder::OperandKind::M0)),
@@ -267,23 +256,16 @@ bool Translator::V_MOVRELS_B32(const Decoder::Instruction& inst, std::string* er
selected = ir.Select(match, ir.GetVectorReg(static_cast<IR::VectorReg>(index)), selected);
}
WriteOperand(DestinationOperand(inst), selected);
return true;
}
bool Translator::V_MOVRELD_B32(const Decoder::Instruction& inst, std::string* error) {
void Translator::V_MOVRELD_B32(const Decoder::Instruction& inst) {
if (inst.dst.kind != Decoder::OperandKind::Vgpr) {
if (error != nullptr) {
*error = "V_MOVRELD_B32 requires VGPR destination";
}
return false;
EXIT("V_MOVRELD_B32 requires VGPR destination at pc 0x%08x", inst.pc);
}
if (inst.dst.sdwa_sel != 6u || inst.dst.omod != 0u || inst.dst.clamp ||
inst.src0.sdwa_sel != 6u || inst.src0.sdwa_sext || inst.src0.negate || inst.src0.absolute ||
inst.src0.dpp) {
if (error != nullptr) {
*error = "V_MOVRELD_B32 modifiers are not implemented";
}
return false;
EXIT("V_MOVRELD_B32 modifiers are not implemented at pc 0x%08x", inst.pc);
}
const auto base = inst.dst.reg;
const auto value = ReadU32(inst.src0);
@@ -295,7 +277,6 @@ bool Translator::V_MOVRELD_B32(const Decoder::Instruction& inst, std::string* er
const auto write = ir.LogicalAnd(ir.GetExec(), match);
ir.SetVectorReg(reg, ir.Select(write, value, ir.GetVectorReg(reg)));
}
return true;
}
void Translator::V_READFIRSTLANE_B32(const Decoder::Instruction& inst) {
@@ -1,23 +1,18 @@
#include "common/assert.h"
#include "graphics/shader/recompiler/frontend/translate/Translator.h"
namespace Libs::Graphics::ShaderRecompiler::Frontend {
bool Translator::TranslateInstruction(const Decoder::Instruction& inst, std::string* error) {
void Translator::TranslateInstruction(const Decoder::Instruction& inst) {
current_opcode = inst.opcode;
current_pc = inst.pc;
switch (inst.opcode) {
case Decoder::Opcode::UNKNOWN:
case Decoder::Opcode::COUNT:
if (error != nullptr) {
*error = "decoded opcode has no IR translation";
}
return false;
EXIT("decoded opcode has no IR translation at pc 0x%08x", inst.pc);
case Decoder::Opcode::UNSUPPORTED:
if (error != nullptr) {
*error = "unsupported decoded instruction: " + Decoder::InstructionToString(inst);
}
return false;
EXIT("unsupported decoded instruction: %s", Decoder::InstructionToString(inst).c_str());
default: break;
}
@@ -27,27 +22,30 @@ bool Translator::TranslateInstruction(const Decoder::Instruction& inst, std::str
case Decoder::Family::SOP2:
case Decoder::Family::SOPK:
case Decoder::Family::SOPC:
case Decoder::Family::SOPP: translated = EmitScalar(inst, error); break;
case Decoder::Family::SOPP: translated = EmitScalar(inst); break;
case Decoder::Family::VOP1:
case Decoder::Family::VOP2:
case Decoder::Family::VOP3:
case Decoder::Family::VOP3P:
case Decoder::Family::VOPC: translated = EmitVector(inst, error); break;
case Decoder::Family::VOPC: translated = EmitVector(inst); break;
case Decoder::Family::SMEM:
case Decoder::Family::MUBUF:
case Decoder::Family::MTBUF:
case Decoder::Family::FLAT:
case Decoder::Family::DS:
case Decoder::Family::MIMG: translated = EmitMemory(inst, error); break;
case Decoder::Family::VINTRP: translated = EmitInterpolation(inst, error); break;
case Decoder::Family::EXP: translated = EXP(inst, error); break;
case Decoder::Family::MIMG: translated = EmitMemory(inst); break;
case Decoder::Family::VINTRP: translated = EmitInterpolation(inst); break;
case Decoder::Family::EXP:
EXP(inst);
translated = true;
break;
default: break;
}
if (!translated && error != nullptr && error->empty()) {
*error = "decoded opcode has no IR translation";
if (!translated) {
EXIT("opcode %s at pc 0x%08x has no IR translation",
Decoder::InstructionToString(inst).c_str(), inst.pc);
}
return translated;
}
} // namespace Libs::Graphics::ShaderRecompiler::Frontend
@@ -1,9 +1,7 @@
#include "common/magicEnum.h"
#include "graphics/shader/recompiler/frontend/translate/Translator.h"
#include <algorithm>
#include <array>
#include <fmt/format.h>
namespace Libs::Graphics::ShaderRecompiler::Frontend {
@@ -890,7 +888,7 @@ bool Translator::DS_BPERMUTE_B32(const Decoder::Instruction& inst) {
return true;
}
bool Translator::EmitMemory(const Decoder::Instruction& inst, std::string* error) {
bool Translator::EmitMemory(const Decoder::Instruction& inst) {
switch (inst.opcode) {
case Decoder::Opcode::S_LOAD_DWORD:
case Decoder::Opcode::S_LOAD_DWORDX2:
@@ -1080,12 +1078,7 @@ bool Translator::EmitMemory(const Decoder::Instruction& inst, std::string* error
case Decoder::Opcode::DS_WRITE_B64:
case Decoder::Opcode::DS_WRITE_B96:
case Decoder::Opcode::DS_WRITE_B128: return DS_WRITE(inst);
default:
if (error != nullptr) {
*error = fmt::format("memory-family opcode has no specialized IR translation: {}",
magic_enum::enum_name(inst.opcode));
}
return false;
default: return false;
}
}
@@ -2,14 +2,14 @@
namespace Libs::Graphics::ShaderRecompiler::Frontend {
bool Translator::EmitScalar(const Decoder::Instruction& inst, std::string* error) {
bool Translator::EmitScalar(const Decoder::Instruction& inst) {
using O = Decoder::Opcode;
switch (inst.opcode) {
case O::S_MOV_B32:
case O::S_MOVK_I32: MOV_B32(inst, false); return true;
case O::S_MOV_B64: S_MOV_B64(inst); return true;
case O::S_WQM_B64: S_WQM_B64(inst); return true;
case O::S_GETPC_B64: return S_GETPC_B64(inst, error);
case O::S_GETPC_B64: S_GETPC_B64(inst); return true;
case O::S_SETPC_B64: return true;
case O::S_CSELECT_B32: S_CSELECT_B32(inst); return true;
case O::S_CSELECT_B64: S_CSELECT_B64(inst); return true;
@@ -1,16 +1,14 @@
#include "common/assert.h"
#include "graphics/shader/recompiler/frontend/translate/Translator.h"
#include "graphics/shader/shader.h"
#include <algorithm>
#include <array>
#include <fmt/format.h>
#include <unordered_map>
#include <utility>
namespace Libs::Graphics::ShaderRecompiler::Frontend {
using ShaderError::Fail;
Decoder::Operand Translator::SourceAt(const Decoder::Instruction& inst, uint32_t index) {
switch (index) {
case 0: return inst.src0;
@@ -396,8 +394,7 @@ void Translator::WriteOperand(const Decoder::Operand& operand, IR::Value value)
}
}
if (type == IR::Type::U16) {
Write16Bits(operand,
IR::U32(ir.Emit(IR::ValueOpcode::ConvertU32U16, {IR::U16(value)})));
Write16Bits(operand, IR::U32(ir.Emit(IR::ValueOpcode::ConvertU32U16, {IR::U16(value)})));
return;
}
if (type == IR::Type::F16) {
@@ -811,11 +808,10 @@ void Translator::WriteCompareResult(const Decoder::Operand& operand, IR::U1 valu
WriteMask(operand, ir.LogicalAnd(ir.GetExec(), value));
}
bool Translator::AddBranchCondition(const CFG::BasicBlock& source, IR::BlockInfo& info,
std::string* error) {
void Translator::AddBranchCondition(const CFG::BasicBlock& source, IR::BlockInfo& info) {
if (source.terminator.goto_value >= 0) {
if (source.terminator.goto_variable == UINT32_MAX) {
return Fail(error, fmt::format("block {} sets an invalid goto variable", source.id));
EXIT("block %u sets an invalid goto variable", source.id);
}
ir.SetGotoVariable(source.terminator.goto_variable,
IR::U1(IR::Value(source.terminator.goto_value != 0)));
@@ -827,13 +823,13 @@ bool Translator::AddBranchCondition(const CFG::BasicBlock& source, IR::BlockInfo
info.indirect_target =
ir.GetScalarReg(static_cast<IR::ScalarReg>(source.terminator.indirect_pc_sgpr));
} else {
return Fail(error, fmt::format("block {} has no indirect branch selector", source.id));
EXIT("block %u has no indirect branch selector", source.id);
}
ir.Emit(IR::ValueOpcode::ReferenceU32, {info.indirect_target});
return true;
return;
}
if (source.terminator.kind != CFG::TerminatorKind::ConditionalBranch) {
return true;
return;
}
// EXEC and VCC are invocation-local Boolean masks. Branching on that Boolean lets inactive
// invocations leave the region without reconstructing a host-subgroup mask.
@@ -848,17 +844,15 @@ bool Translator::AddBranchCondition(const CFG::BasicBlock& source, IR::BlockInfo
case CFG::BranchCondition::ExecNonZero: condition = ir.GetExec(); break;
case CFG::BranchCondition::GotoVariable:
if (source.terminator.goto_variable == UINT32_MAX) {
return Fail(error,
fmt::format("block {} reads an invalid goto variable", source.id));
EXIT("block %u reads an invalid goto variable", source.id);
}
condition = ir.GetGotoVariable(source.terminator.goto_variable);
break;
case CFG::BranchCondition::Unknown:
return Fail(error, fmt::format("block {} has an unknown branch condition", source.id));
EXIT("block %u has an unknown branch condition", source.id);
}
info.condition = condition;
ir.Emit(IR::ValueOpcode::Reference, {condition});
return true;
}
namespace {
@@ -980,47 +974,42 @@ void IncludeInstructionVectorRegisters(const Decoder::Instruction& inst, uint32_
}
}
bool ValidateTranslateOptions(const TranslateOptions& options, std::string* error) {
void ValidateTranslateOptions(const TranslateOptions& options) {
if (options.wave_size != 32u && options.wave_size != 64u) {
return Fail(error, "shader translation requires wave32 or wave64");
EXIT("shader translation requires wave32 or wave64, got %u", options.wave_size);
}
switch (options.stage) {
case ShaderType::Vertex:
return options.vertex != nullptr ||
Fail(error, "vertex shader translation has no vertex input metadata");
if (options.vertex == nullptr) {
EXIT("vertex shader translation has no vertex input metadata");
}
return;
case ShaderType::Pixel:
return options.pixel != nullptr ||
Fail(error, "pixel shader translation has no pixel input metadata");
if (options.pixel == nullptr) {
EXIT("pixel shader translation has no pixel input metadata");
}
return;
case ShaderType::Compute:
return options.compute != nullptr ||
Fail(error, "compute shader translation has no compute input metadata");
default: return Fail(error, "shader translation has an unsupported stage");
if (options.compute == nullptr) {
EXIT("compute shader translation has no compute input metadata");
}
return;
default:
EXIT("shader translation has unsupported stage %u",
static_cast<uint32_t>(options.stage));
}
}
} // namespace
bool TranslateProgram(const Decoder::Program& decoded, const CFG::Graph& cfg,
const TranslateOptions& options, IR::Program& result, std::string* error) {
result = {};
struct ResetOnFailure {
IR::Program& program;
bool complete = false;
~ResetOnFailure() {
if (!complete) {
program = {};
}
}
} reset_on_failure {result};
if (!ValidateTranslateOptions(options, error)) {
return false;
}
IR::Program TranslateProgram(const Decoder::Program& decoded, const CFG::Graph& cfg,
const TranslateOptions& options) {
ValidateTranslateOptions(options);
if (cfg.blocks.empty()) {
return Fail(error, "cannot translate an empty CFG");
EXIT("cannot translate an empty CFG");
}
IR::Program result;
result.stage = options.stage;
result.wave_size = options.wave_size;
result.shader_hash = options.shader_hash;
@@ -1038,8 +1027,8 @@ bool TranslateProgram(const Decoder::Program& decoded, const CFG::Graph& cfg,
for (const auto& cfg_block: cfg.blocks) {
for (uint32_t index = cfg_block.inst_begin; index < cfg_block.inst_end; index++) {
if (index >= decoded.instructions.size()) {
return Fail(error,
"CFG block references an instruction outside the decoded program");
EXIT("CFG block %u references instruction %u outside decoded program of size %zu",
cfg_block.id, index, decoded.instructions.size());
}
const auto& instruction = decoded.instructions[index];
if (IsCodeTableLoad(cfg, instruction.pc)) {
@@ -1056,7 +1045,7 @@ bool TranslateProgram(const Decoder::Program& decoded, const CFG::Graph& cfg,
return block.id;
})->id;
if (max_id == UINT32_MAX) {
return Fail(error, "cannot allocate a typed entry block id");
EXIT("cannot allocate a typed entry block id");
}
CFG::Terminator terminator;
terminator.kind = CFG::TerminatorKind::Branch;
@@ -1070,7 +1059,7 @@ bool TranslateProgram(const Decoder::Program& decoded, const CFG::Graph& cfg,
block_indices.reserve(cfg.blocks.size());
for (const auto& source_block: cfg.blocks) {
if (!block_indices.emplace(source_block.id, result.blocks.size()).second) {
return Fail(error, fmt::format("CFG contains duplicate block id {}", source_block.id));
EXIT("CFG contains duplicate block id %u", source_block.id);
}
result.block_storage.push_back(std::make_unique<IR::Block>());
result.blocks.push_back(result.block_storage.back().get());
@@ -1082,8 +1071,7 @@ bool TranslateProgram(const Decoder::Program& decoded, const CFG::Graph& cfg,
for (const auto successor: source_block.successors) {
const auto target = block_indices.find(successor);
if (target == block_indices.end()) {
return Fail(error, fmt::format("CFG block {} has unknown successor {}",
source_block.id, successor));
EXIT("CFG block %u has unknown successor %u", source_block.id, successor);
}
result.blocks[source_index]->AddBranch(result.blocks[target->second]);
}
@@ -1182,7 +1170,7 @@ bool TranslateProgram(const Decoder::Program& decoded, const CFG::Graph& cfg,
}
}
for (const auto& cfg_block: cfg.blocks) {
const auto typed_index = block_indices.at(cfg_block.id);
const auto typed_index = block_indices.at(cfg_block.id);
Translator translator(result, result.blocks[typed_index], vector_limit, options.wave_size);
for (uint32_t index = cfg_block.inst_begin; index < cfg_block.inst_end; index++) {
const auto& instruction = decoded.instructions[index];
@@ -1198,44 +1186,27 @@ bool TranslateProgram(const Decoder::Program& decoded, const CFG::Graph& cfg,
instruction.data_dwords == embedded->components &&
instruction.dst.kind == Decoder::OperandKind::Vgpr) {
if (options.vertex == nullptr) {
return Fail(error, "embedded vertex fetch plan has no vertex input metadata");
EXIT("embedded vertex fetch plan has no vertex input metadata");
}
const auto resource = ResolveEmbeddedFetchResource(*options.vertex, *embedded);
if (resource < 0 || resource >= options.vertex->resources_num) {
return Fail(
error,
fmt::format(
"embedded vertex fetch at 0x{:08x} has no resource for attribute {}",
instruction.pc, embedded->attrib_id));
EXIT("embedded vertex fetch at 0x%08x has no resource for attribute %d",
instruction.pc, embedded->attrib_id);
}
result.info.vertex_fetch_components[static_cast<size_t>(resource)] =
static_cast<uint8_t>(std::max<uint32_t>(
result.info.vertex_fetch_components[static_cast<size_t>(resource)],
embedded->components));
if (!translator.TranslateEmbeddedFetch(instruction, static_cast<uint32_t>(resource),
embedded->components)) {
return false;
}
translator.TranslateEmbeddedFetch(instruction, static_cast<uint32_t>(resource),
embedded->components);
continue;
}
if (!translator.TranslateInstruction(instruction, error)) {
if (error == nullptr || error->empty()) {
return Fail(error, fmt::format("opcode {} at 0x{:08x} has no IR translation",
magic_enum::enum_name(instruction.opcode),
instruction.pc));
}
return false;
}
}
if (!translator.AddBranchCondition(cfg_block, result.block_info[typed_index], error)) {
return false;
translator.TranslateInstruction(instruction);
}
translator.AddBranchCondition(cfg_block, result.block_info[typed_index]);
}
if (!IR::ValidateProgram(result, false, error)) {
return false;
}
reset_on_failure.complete = true;
return true;
IR::ValidateProgram(result, false);
return result;
}
} // namespace Libs::Graphics::ShaderRecompiler::Frontend
@@ -38,7 +38,7 @@ struct TranslateOptions {
const EmbeddedFetchPlan* embedded_fetch = nullptr;
};
bool TranslateProgram(const Decoder::Program& decoded, const CFG::Graph& cfg,
const TranslateOptions& options, IR::Program& result, std::string* error);
IR::Program TranslateProgram(const Decoder::Program& decoded, const CFG::Graph& cfg,
const TranslateOptions& options);
} // namespace Libs::Graphics::ShaderRecompiler::Frontend
@@ -13,10 +13,10 @@ public:
: program(program), ir(block), current_vector_limit(vector_limit),
current_wave_size(wave_size) {}
bool TranslateInstruction(const Decoder::Instruction& inst, std::string* error);
bool TranslateEmbeddedFetch(const Decoder::Instruction& inst, uint32_t attribute,
void TranslateInstruction(const Decoder::Instruction& inst);
void TranslateEmbeddedFetch(const Decoder::Instruction& inst, uint32_t attribute,
uint32_t component_count);
bool AddBranchCondition(const CFG::BasicBlock& source, IR::BlockInfo& info, std::string* error);
void AddBranchCondition(const CFG::BasicBlock& source, IR::BlockInfo& info);
private:
struct ScalarU64 {
@@ -194,26 +194,26 @@ private:
bool PackedInteger16MinMax(const Decoder::Instruction& inst, IR::ValueOpcode opcode, bool sign);
bool S_U64_MASK(const Decoder::Instruction& inst, IR::ValueOpcode logical_opcode,
IR::ValueOpcode bit_opcode, bool negate_rhs, bool negate_result, bool unary);
bool SimpleInteger(const Decoder::Instruction& inst, IR::ValueOpcode opcode, IR::Type type,
bool reverse, bool mask_shift_count, bool update_scc);
bool ComposedIntegerBinary(const Decoder::Instruction& inst, IR::ValueOpcode opcode,
bool negate_rhs, bool negate_result, bool update_scc);
bool V_AND_OR_B32(const Decoder::Instruction& inst);
bool V_OR3_B32(const Decoder::Instruction& inst);
bool V_XOR3_B32(const Decoder::Instruction& inst);
bool S_FF1_I32_B64(const Decoder::Instruction& inst);
bool V_FFBH_32(const Decoder::Instruction& inst, bool sign);
bool S_FLBIT_I32_B64(const Decoder::Instruction& inst);
bool Integer24(const Decoder::Instruction& inst, bool sign, bool addend);
bool V_MAD_U64_U32(const Decoder::Instruction& inst);
bool V_SAD_U32(const Decoder::Instruction& inst);
bool V_ADD3_U32(const Decoder::Instruction& inst);
bool S_BITSET_B32(const Decoder::Instruction& inst, bool set);
bool V_BCNT_U32_B32(const Decoder::Instruction& inst);
bool V_MBCNT_U32_B32(const Decoder::Instruction& inst, bool low);
bool S_BITREPLICATE_B64_B32(const Decoder::Instruction& inst);
bool S_QUADMASK_B64(const Decoder::Instruction& inst);
bool BFM_B32(const Decoder::Instruction& inst);
bool SimpleInteger(const Decoder::Instruction& inst, IR::ValueOpcode opcode, IR::Type type,
bool reverse, bool mask_shift_count, bool update_scc);
bool ComposedIntegerBinary(const Decoder::Instruction& inst, IR::ValueOpcode opcode,
bool negate_rhs, bool negate_result, bool update_scc);
bool V_AND_OR_B32(const Decoder::Instruction& inst);
bool V_OR3_B32(const Decoder::Instruction& inst);
bool V_XOR3_B32(const Decoder::Instruction& inst);
bool S_FF1_I32_B64(const Decoder::Instruction& inst);
bool V_FFBH_32(const Decoder::Instruction& inst, bool sign);
bool S_FLBIT_I32_B64(const Decoder::Instruction& inst);
bool Integer24(const Decoder::Instruction& inst, bool sign, bool addend);
bool V_MAD_U64_U32(const Decoder::Instruction& inst);
bool V_SAD_U32(const Decoder::Instruction& inst);
bool V_ADD3_U32(const Decoder::Instruction& inst);
bool S_BITSET_B32(const Decoder::Instruction& inst, bool set);
bool V_BCNT_U32_B32(const Decoder::Instruction& inst);
bool V_MBCNT_U32_B32(const Decoder::Instruction& inst, bool low);
bool S_BITREPLICATE_B64_B32(const Decoder::Instruction& inst);
bool S_QUADMASK_B64(const Decoder::Instruction& inst);
bool BFM_B32(const Decoder::Instruction& inst);
IR::U32 RightMask32(IR::U32 count);
IR::U64 RightMask64(IR::U32 count);
bool S_BFM_B64(const Decoder::Instruction& inst);
@@ -246,27 +246,27 @@ private:
void S_SENDMSG();
void S_TTRACEDATA();
void S_INST_PREFETCH();
bool S_GETPC_B64(const Decoder::Instruction& inst, std::string* error);
void S_GETPC_B64(const Decoder::Instruction& inst);
void S_CSELECT_B32(const Decoder::Instruction& inst);
void S_CSELECT_B64(const Decoder::Instruction& inst);
void MOV_B32(const Decoder::Instruction& inst, bool apply_float_modifiers);
void S_MOV_B64(const Decoder::Instruction& inst);
void S_WQM_B64(const Decoder::Instruction& inst);
bool V_MOVRELS_B32(const Decoder::Instruction& inst, std::string* error);
bool V_MOVRELD_B32(const Decoder::Instruction& inst, std::string* error);
void V_MOVRELS_B32(const Decoder::Instruction& inst);
void V_MOVRELD_B32(const Decoder::Instruction& inst);
void V_READFIRSTLANE_B32(const Decoder::Instruction& inst);
void V_READLANE_B32(const Decoder::Instruction& inst);
void V_WRITELANE_B32(const Decoder::Instruction& inst);
void V_PERMLANE16_B32(const Decoder::Instruction& inst, bool x16);
void V_INTERP_P1_F32();
void V_INTERP_P2_F32(const Decoder::Instruction& inst);
bool V_INTERP_MOV_F32(const Decoder::Instruction& inst, std::string* error);
bool EXP(const Decoder::Instruction& inst, std::string* error);
void V_INTERP_MOV_F32(const Decoder::Instruction& inst);
void EXP(const Decoder::Instruction& inst);
bool EmitScalar(const Decoder::Instruction& inst, std::string* error);
bool EmitVector(const Decoder::Instruction& inst, std::string* error);
bool EmitInterpolation(const Decoder::Instruction& inst, std::string* error);
bool EmitMemory(const Decoder::Instruction& inst, std::string* error);
bool EmitScalar(const Decoder::Instruction& inst);
bool EmitVector(const Decoder::Instruction& inst);
bool EmitInterpolation(const Decoder::Instruction& inst);
bool EmitMemory(const Decoder::Instruction& inst);
IR::Program& program;
IR::IREmitter ir;
@@ -2,7 +2,7 @@
namespace Libs::Graphics::ShaderRecompiler::Frontend {
bool Translator::EmitVector(const Decoder::Instruction& inst, std::string* error) {
bool Translator::EmitVector(const Decoder::Instruction& inst) {
using O = Decoder::Opcode;
switch (inst.opcode) {
case O::V_NOP: return true;
@@ -13,8 +13,8 @@ bool Translator::EmitVector(const Decoder::Instruction& inst, std::string* error
case O::V_SUBREV_CO_CI_U32: SUBB_U32(inst, true); return true;
case O::V_MOV_B32: MOV_B32(inst, true); return true;
case O::V_MOVRELS_B32: return V_MOVRELS_B32(inst, error);
case O::V_MOVRELD_B32: return V_MOVRELD_B32(inst, error);
case O::V_MOVRELS_B32: V_MOVRELS_B32(inst); return true;
case O::V_MOVRELD_B32: V_MOVRELD_B32(inst); return true;
case O::V_READFIRSTLANE_B32: V_READFIRSTLANE_B32(inst); return true;
case O::V_READLANE_B32: V_READLANE_B32(inst); return true;
case O::V_WRITELANE_B32: V_WRITELANE_B32(inst); return true;