Files
KytyPS5/src/graphics/shader/recompiler/frontend/translate/Attribute.cpp
T

119 lines
4.5 KiB
C++

#include "common/assert.h"
#include "graphics/shader/recompiler/BufferFormat.h"
#include "graphics/shader/recompiler/frontend/translate/Translator.h"
#include <algorithm>
#include <array>
namespace Libs::Graphics::ShaderRecompiler::Frontend {
namespace {
IR::ExportTargetKind ExportTargetKindFromTarget(uint32_t target, uint32_t& index) {
index = 0;
switch (target) {
case 0x08u: return IR::ExportTargetKind::MrtZ;
case 0x09u: return IR::ExportTargetKind::Null;
case 0x14u: return IR::ExportTargetKind::Primitive;
default: break;
}
if (target <= 0x07u) {
index = target;
return IR::ExportTargetKind::Mrt;
}
if (target >= 0x0cu && target <= 0x0fu) {
index = target - 0x0cu;
return IR::ExportTargetKind::Position;
}
if (target >= 0x20u && target <= 0x3fu) {
index = target - 0x20u;
return IR::ExportTargetKind::Parameter;
}
return IR::ExportTargetKind::Unknown;
}
} // namespace
IR::ExportFlags Translator::AddExportInfo(const Decoder::Instruction& inst) {
IR::ExportInfo info;
info.kind = ExportTargetKindFromTarget(inst.exp.target, info.index);
info.target = inst.exp.target;
info.en = inst.exp.en;
info.done = inst.exp.done;
info.compr = inst.exp.compr;
info.vm = inst.exp.vm;
const auto index = static_cast<uint32_t>(program.export_info.size());
program.export_info.push_back(info);
return {.index = index, .pc = inst.pc};
}
void Translator::TranslateEmbeddedFetch(const Decoder::Instruction& inst, uint32_t attribute,
uint32_t component_count,
const ShaderBufferResource& resource) {
const auto format = Format::GetFormatInfo(resource.Format());
for (uint32_t component = 0; component < component_count; component++) {
auto source = Format::FormattedSource {Format::FormattedSourceKind::Memory, component};
if (inst.formatted && !inst.typed) {
source = Format::ResolveFormattedSource(
format, GetDstSel(resource.DstSelXYZW(), component));
if (source.kind == Format::FormattedSourceKind::Invalid) {
EXIT("invalid formatted vertex input %u at pc 0x%08x", attribute, inst.pc);
}
}
IR::Value value;
if (source.kind == Format::FormattedSourceKind::Memory) {
value = ir.Emit(IR::ValueOpcode::GetAttribute,
{IR::Value(attribute), IR::Value(source.component)});
auto& required = program.info.vertex_fetch_components[attribute];
required = static_cast<uint8_t>(std::max<uint32_t>(required, source.component + 1u));
} else {
value = IR::Value(Format::FormattedConstantBits(format, source.kind));
}
WriteOperand(OffsetOperand(inst.dst, component), value);
}
}
void Translator::V_INTERP_P1_F32() {}
void Translator::V_INTERP_P2_F32(const Decoder::Instruction& inst) {
const auto value = ir.Emit(IR::ValueOpcode::GetAttribute,
{IR::Value(inst.src1.value), IR::Value(inst.src2.value)});
WriteOperand(inst.dst, value);
}
void Translator::V_INTERP_MOV_F32(const Decoder::Instruction& inst) {
if (inst.src0.value >= 3u) {
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);
}
void Translator::EXP(const Decoder::Instruction& inst) {
uint32_t index = 0;
if (ExportTargetKindFromTarget(inst.exp.target, index) == IR::ExportTargetKind::Unknown) {
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)};
for (uint32_t source = 0; source < std::min(inst.src_count, 4u); source++) {
components[source] = ReadRawU32(PlainOperand(SourceAt(inst, source)));
}
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));
}
void Translator::EmitInterpolation(const Decoder::Instruction& inst) {
switch (inst.opcode) {
case Decoder::Opcode::V_INTERP_P1_F32: V_INTERP_P1_F32(); return;
case Decoder::Opcode::V_INTERP_P2_F32: V_INTERP_P2_F32(inst); return;
case Decoder::Opcode::V_INTERP_MOV_F32: V_INTERP_MOV_F32(inst); return;
default: return FailMissingTranslation(inst);
}
}
} // namespace Libs::Graphics::ShaderRecompiler::Frontend