#include "common/assert.h" #include "graphics/shader/recompiler/BufferFormat.h" #include "graphics/shader/recompiler/frontend/translate/Translator.h" #include #include 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(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(std::max(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 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