mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-04-22 04:24:44 +00:00
cleanup. delete vaarg stuff. Smuggle format string in Info and flags
This commit is contained in:
parent
6b830f641c
commit
e69b2d410c
12 changed files with 52 additions and 160 deletions
|
@ -49,9 +49,7 @@ void EmitPrologue(EmitContext& ctx);
|
|||
void EmitEpilogue(EmitContext& ctx);
|
||||
void EmitDiscard(EmitContext& ctx);
|
||||
void EmitDiscardCond(EmitContext& ctx, Id condition);
|
||||
void EmitVaArg(EmitContext& ctx, IR::Inst* inst, Id arg, Id next);
|
||||
Id EmitStringLiteral(EmitContext& ctx, IR::Inst* inst);
|
||||
void EmitDebugPrint(EmitContext& ctx, IR::Inst* inst, Id fmt);
|
||||
void EmitDebugPrint(EmitContext& ctx, IR::Inst* inst, Id arg0, Id arg1, Id arg2, Id arg3, Id arg4);
|
||||
void EmitBarrier(EmitContext& ctx);
|
||||
void EmitWorkgroupMemoryBarrier(EmitContext& ctx);
|
||||
void EmitDeviceMemoryBarrier(EmitContext& ctx);
|
||||
|
|
|
@ -55,45 +55,15 @@ void EmitEndPrimitive(EmitContext& ctx, const IR::Value& stream) {
|
|||
throw NotImplementedException("Geometry streams");
|
||||
}
|
||||
|
||||
static bool isEmptyInst(IR::Value val) {
|
||||
if (auto* inst = val.TryInstRecursive()) {
|
||||
return inst->GetOpcode() == IR::Opcode::Void;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
void EmitDebugPrint(EmitContext& ctx, IR::Inst* inst, Id arg0, Id arg1, Id arg2, Id arg3, Id arg4) {
|
||||
DebugPrintFlags flags = inst->Flags<DebugPrintFlags>();
|
||||
const std::string& format_string = ctx.info.string_pool[flags.string_idx];
|
||||
Id fmt = ctx.String(format_string);
|
||||
|
||||
void EmitVaArg(EmitContext& ctx, IR::Inst* inst, Id arg, Id next) {
|
||||
IR::Value next_val = inst->Arg(1);
|
||||
u32 va_arglist_idx;
|
||||
if (isEmptyInst(next_val)) {
|
||||
va_arglist_idx = ctx.va_arg_lists.size();
|
||||
ctx.va_arg_lists.emplace_back();
|
||||
} else {
|
||||
va_arglist_idx = next_val.Inst()->Flags<VariadicArgInfo>().va_arg_idx;
|
||||
}
|
||||
|
||||
ctx.va_arg_lists[va_arglist_idx].push_back(arg);
|
||||
auto va_info = inst->Flags<VariadicArgInfo>();
|
||||
va_info.va_arg_idx.Assign(va_arglist_idx);
|
||||
inst->SetFlags(va_info);
|
||||
}
|
||||
|
||||
Id EmitStringLiteral(EmitContext& ctx, IR::Inst* inst) {
|
||||
// ctx.
|
||||
return ctx.String(inst->StringLiteral());
|
||||
}
|
||||
|
||||
void EmitDebugPrint(EmitContext& ctx, IR::Inst* inst, Id fmt) {
|
||||
IR::Value arglist = inst->Arg(1);
|
||||
boost::container::small_vector<Id, 4> fmt_arg_operands;
|
||||
if (!isEmptyInst(arglist)) {
|
||||
u32 va_arglist_idx = arglist.Inst()->Flags<VariadicArgInfo>().va_arg_idx;
|
||||
const auto& va_arglist = ctx.va_arg_lists[va_arglist_idx];
|
||||
// reverse the order
|
||||
std::copy(va_arglist.rbegin(), va_arglist.rend(), std::back_inserter(fmt_arg_operands));
|
||||
}
|
||||
|
||||
ctx.OpDebugPrintf(fmt, fmt_arg_operands);
|
||||
std::array<Id, 5> fmt_args = {arg0, arg1, arg2, arg3, arg4};
|
||||
const std::span<Id> fmt_args_span =
|
||||
std::span<Id>(fmt_args.begin(), fmt_args.begin() + flags.num_args);
|
||||
ctx.OpDebugPrintf(fmt, fmt_args_span);
|
||||
}
|
||||
|
||||
} // namespace Shader::Backend::SPIRV
|
||||
|
|
|
@ -644,7 +644,7 @@ private:
|
|||
}
|
||||
case StatementType::SetVariable: {
|
||||
ensure_block();
|
||||
IR::IREmitter ir{*current_block};
|
||||
IR::IREmitter ir{*current_block, info};
|
||||
ir.SetGotoVariable(stmt.id, VisitExpr(ir, *stmt.op));
|
||||
break;
|
||||
}
|
||||
|
@ -653,7 +653,7 @@ private:
|
|||
IR::Block* const merge_block{MergeBlock(parent, stmt)};
|
||||
|
||||
// Implement if header block
|
||||
IR::IREmitter ir{*current_block};
|
||||
IR::IREmitter ir{*current_block, info};
|
||||
const IR::U1 cond{ir.ConditionRef(VisitExpr(ir, *stmt.cond))};
|
||||
|
||||
const size_t if_node_index{syntax_list.size()};
|
||||
|
@ -703,7 +703,7 @@ private:
|
|||
Visit(stmt, merge_block, continue_block);
|
||||
|
||||
// The continue block is located at the end of the loop
|
||||
IR::IREmitter ir{*continue_block};
|
||||
IR::IREmitter ir{*continue_block, info};
|
||||
const IR::U1 cond{ir.ConditionRef(VisitExpr(ir, *stmt.cond))};
|
||||
|
||||
IR::Block* const body_block{syntax_list.at(body_block_index).data.block};
|
||||
|
@ -739,7 +739,7 @@ private:
|
|||
ensure_block();
|
||||
IR::Block* const skip_block{MergeBlock(parent, stmt)};
|
||||
|
||||
IR::IREmitter ir{*current_block};
|
||||
IR::IREmitter ir{*current_block, info};
|
||||
const IR::U1 cond{ir.ConditionRef(VisitExpr(ir, *stmt.cond))};
|
||||
current_block->AddBranch(break_block);
|
||||
current_block->AddBranch(skip_block);
|
||||
|
@ -759,7 +759,7 @@ private:
|
|||
case StatementType::Return: {
|
||||
ensure_block();
|
||||
IR::Block* return_block{block_pool.Create(inst_pool)};
|
||||
IR::IREmitter{*return_block}.Epilogue();
|
||||
IR::IREmitter{*return_block, info}.Epilogue();
|
||||
current_block->AddBranch(return_block);
|
||||
|
||||
auto& merge{syntax_list.emplace_back()};
|
||||
|
@ -773,7 +773,7 @@ private:
|
|||
case StatementType::Kill: {
|
||||
ensure_block();
|
||||
IR::Block* demote_block{MergeBlock(parent, stmt)};
|
||||
IR::IREmitter{*current_block}.Discard();
|
||||
IR::IREmitter{*current_block, info}.Discard();
|
||||
current_block->AddBranch(demote_block);
|
||||
current_block = demote_block;
|
||||
|
||||
|
|
|
@ -19,7 +19,8 @@ namespace Shader::Gcn {
|
|||
|
||||
Translator::Translator(IR::Block* block_, Info& info_, const RuntimeInfo& runtime_info_,
|
||||
const Profile& profile_)
|
||||
: ir{*block_, block_->begin()}, info{info_}, runtime_info{runtime_info_}, profile{profile_} {}
|
||||
: ir{*block_, block_->begin(), info_}, info{info_}, runtime_info{runtime_info_},
|
||||
profile{profile_} {}
|
||||
|
||||
void Translator::EmitPrologue() {
|
||||
ir.Prologue();
|
||||
|
|
|
@ -179,6 +179,9 @@ struct Info {
|
|||
std::span<const u32> user_data;
|
||||
Stage stage;
|
||||
|
||||
using StringPool = boost::container::small_vector<std::string, 4>;
|
||||
StringPool string_pool;
|
||||
|
||||
u64 pgm_hash{};
|
||||
VAddr pgm_base;
|
||||
bool has_storage_images{};
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
#include "common/bit_field.h"
|
||||
#include "src/common/enum.h"
|
||||
#include "src/common/types.h"
|
||||
|
||||
#pragma once
|
||||
|
||||
union VariadicArgInfo {
|
||||
union DebugPrintFlags {
|
||||
u32 raw;
|
||||
|
||||
BitField<0, 12, u32> va_arg_idx;
|
||||
BitField<0, 16, u32> string_idx;
|
||||
BitField<16, 16, u32> num_args;
|
||||
};
|
|
@ -1,15 +1,13 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include <array>
|
||||
#include <bit>
|
||||
#include <iterator>
|
||||
#include <source_location>
|
||||
#include <boost/container/small_vector.hpp>
|
||||
#include "common/assert.h"
|
||||
#include "shader_recompiler/exception.h"
|
||||
#include "shader_recompiler/ir/debug_print.h"
|
||||
#include "shader_recompiler/ir/ir_emitter.h"
|
||||
#include "shader_recompiler/ir/opcodes.h"
|
||||
#include "shader_recompiler/ir/value.h"
|
||||
|
||||
namespace Shader::IR {
|
||||
|
@ -1558,72 +1556,27 @@ void IREmitter::ImageWrite(const Value& handle, const Value& coords, const Value
|
|||
Inst(Opcode::ImageWrite, Flags{info}, handle, coords, color);
|
||||
}
|
||||
|
||||
Value IREmitter::VaArg(Value arg, Value next) {
|
||||
return Inst(Opcode::VaArg, arg, next);
|
||||
}
|
||||
|
||||
Value IREmitter::StringLiteral(std::string_view s) {
|
||||
Value val = Inst(Opcode::StringLiteral);
|
||||
val.Inst()->SetStringLiteral(s);
|
||||
return val;
|
||||
}
|
||||
|
||||
void IREmitter::DebugPrint(std::string_view format, boost::container::small_vector<Value, 4> args,
|
||||
void IREmitter::DebugPrint(std::string_view format,
|
||||
boost::container::small_vector<Value, 5> format_args,
|
||||
bool infer_specifiers) {
|
||||
auto infer_specifier = [&](IR::Value arg) -> const char* {
|
||||
switch (arg.Type()) {
|
||||
case Shader::IR::Type::U1:
|
||||
case Shader::IR::Type::U8:
|
||||
case Shader::IR::Type::U16:
|
||||
case Shader::IR::Type::U32:
|
||||
return "%u";
|
||||
case Shader::IR::Type::U64:
|
||||
return "%lu";
|
||||
case Shader::IR::Type::F16:
|
||||
case Shader::IR::Type::F32:
|
||||
case Shader::IR::Type::F64:
|
||||
return "%lf";
|
||||
case Shader::IR::Type::U32x2:
|
||||
return "%v2u";
|
||||
case Shader::IR::Type::U32x3:
|
||||
return "%v3u";
|
||||
case Shader::IR::Type::U32x4:
|
||||
return "%v4u";
|
||||
case Shader::IR::Type::F16x2:
|
||||
case Shader::IR::Type::F32x2:
|
||||
case Shader::IR::Type::F64x2:
|
||||
return "%v2f";
|
||||
case Shader::IR::Type::F16x3:
|
||||
case Shader::IR::Type::F32x3:
|
||||
case Shader::IR::Type::F64x3:
|
||||
return "%v3f";
|
||||
case Shader::IR::Type::F16x4:
|
||||
case Shader::IR::Type::F32x4:
|
||||
case Shader::IR::Type::F64x4:
|
||||
return "%v4f";
|
||||
case Shader::IR::Type::Void:
|
||||
case Shader::IR::Type::Opaque:
|
||||
case Shader::IR::Type::ScalarReg:
|
||||
case Shader::IR::Type::VectorReg:
|
||||
case Shader::IR::Type::Attribute:
|
||||
case Shader::IR::Type::SystemValue:
|
||||
UNREACHABLE();
|
||||
}
|
||||
};
|
||||
std::array<Value, 5> args;
|
||||
|
||||
if (infer_specifiers) {
|
||||
UNREACHABLE();
|
||||
// need to fmt the format string with dynamic sized array of format spec strings
|
||||
// could use param pack for this function, but less flexible
|
||||
for (int i = 0; i < format_args.size(); i++) {
|
||||
args[i] = format_args[i];
|
||||
}
|
||||
|
||||
Value arg_list = Inst(Opcode::Void);
|
||||
for (Value arg : args) {
|
||||
arg_list = VaArg(arg, arg_list);
|
||||
for (int i = format_args.size(); i < 4; i++) {
|
||||
args[i] = Inst(Opcode::Void);
|
||||
}
|
||||
|
||||
Value string_val = StringLiteral(format);
|
||||
Inst(Opcode::DebugPrint, string_val, arg_list);
|
||||
Value val = Inst(Opcode::DebugPrint, args[0], args[1], args[2], args[3], args[4]);
|
||||
DebugPrintFlags flags;
|
||||
|
||||
flags.string_idx.Assign(info.string_pool.size());
|
||||
info.string_pool.emplace_back(format);
|
||||
flags.num_args.Assign(format_args.size());
|
||||
|
||||
val.Inst()->SetFlags<DebugPrintFlags>(flags);
|
||||
}
|
||||
|
||||
} // namespace Shader::IR
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include <type_traits>
|
||||
#include <boost/container/small_vector.hpp>
|
||||
|
||||
#include "shader_recompiler/info.h"
|
||||
#include "shader_recompiler/ir/attribute.h"
|
||||
#include "shader_recompiler/ir/basic_block.h"
|
||||
#include "shader_recompiler/ir/condition.h"
|
||||
|
@ -17,9 +18,10 @@ namespace Shader::IR {
|
|||
|
||||
class IREmitter {
|
||||
public:
|
||||
explicit IREmitter(Block& block_) : block{&block_}, insertion_point{block->end()} {}
|
||||
explicit IREmitter(Block& block_, Block::iterator insertion_point_)
|
||||
: block{&block_}, insertion_point{insertion_point_} {}
|
||||
explicit IREmitter(Block& block_, Shader::Info& info_)
|
||||
: block{&block_}, insertion_point{block->end()}, info(info_) {}
|
||||
explicit IREmitter(Block& block_, Block::iterator insertion_point_, Shader::Info& info_)
|
||||
: block{&block_}, insertion_point{insertion_point_}, info(info_) {}
|
||||
|
||||
Block* block;
|
||||
|
||||
|
@ -45,11 +47,7 @@ public:
|
|||
void Epilogue();
|
||||
void Discard();
|
||||
void Discard(const U1& cond);
|
||||
|
||||
Value VaArg(Value arg, Value next);
|
||||
Value StringLiteral(std::string_view s);
|
||||
|
||||
void DebugPrint(std::string_view format, boost::container::small_vector<Value, 4> args,
|
||||
void DebugPrint(std::string_view format, boost::container::small_vector<Value, 5> args,
|
||||
bool infer_specifiers = false);
|
||||
|
||||
void Barrier();
|
||||
|
@ -320,6 +318,7 @@ public:
|
|||
|
||||
private:
|
||||
IR::Block::iterator insertion_point;
|
||||
Shader::Info& info;
|
||||
|
||||
template <typename T = Value, typename... Args>
|
||||
T Inst(Opcode op, Args... args) {
|
||||
|
|
|
@ -14,8 +14,6 @@ namespace Shader::IR {
|
|||
Inst::Inst(IR::Opcode op_, u32 flags_) noexcept : op{op_}, flags{flags_} {
|
||||
if (op == Opcode::Phi) {
|
||||
std::construct_at(&phi_args);
|
||||
} else if (op == Opcode::StringLiteral) {
|
||||
std::construct_at(&string_literal);
|
||||
} else {
|
||||
std::construct_at(&args);
|
||||
}
|
||||
|
@ -24,8 +22,6 @@ Inst::Inst(IR::Opcode op_, u32 flags_) noexcept : op{op_}, flags{flags_} {
|
|||
Inst::Inst(const Inst& base) : op{base.op}, flags{base.flags} {
|
||||
if (base.op == Opcode::Phi) {
|
||||
throw NotImplementedException("Copying phi node");
|
||||
} else if (base.op == Opcode::StringLiteral) {
|
||||
std::construct_at(&string_literal, base.string_literal);
|
||||
} else {
|
||||
std::construct_at(&args);
|
||||
const size_t num_args{base.NumArgs()};
|
||||
|
@ -38,8 +34,6 @@ Inst::Inst(const Inst& base) : op{base.op}, flags{base.flags} {
|
|||
Inst::~Inst() {
|
||||
if (op == Opcode::Phi) {
|
||||
std::destroy_at(&phi_args);
|
||||
} else if (op == Opcode::StringLiteral) {
|
||||
std::destroy_at(&string_literal);
|
||||
} else {
|
||||
std::destroy_at(&args);
|
||||
}
|
||||
|
@ -107,9 +101,6 @@ bool Inst::AreAllArgsImmediates() const {
|
|||
if (op == Opcode::Phi) {
|
||||
UNREACHABLE_MSG("Testing for all arguments are immediates on phi instruction");
|
||||
}
|
||||
if (op == Opcode::StringLiteral) {
|
||||
UNREACHABLE_MSG("Testing for all arguments are immediates on StringLiteral instruction");
|
||||
}
|
||||
return std::all_of(args.begin(), args.begin() + NumArgs(),
|
||||
[](const IR::Value& value) { return value.IsImmediate(); });
|
||||
}
|
||||
|
@ -131,8 +122,6 @@ void Inst::SetArg(size_t index, Value value) {
|
|||
}
|
||||
if (op == Opcode::Phi) {
|
||||
phi_args[index].second = value;
|
||||
} else if (op == Opcode::StringLiteral) {
|
||||
UNREACHABLE_MSG("SetArg on StringLiteral instruction");
|
||||
} else {
|
||||
args[index] = value;
|
||||
}
|
||||
|
@ -169,8 +158,6 @@ void Inst::ClearArgs() {
|
|||
}
|
||||
}
|
||||
phi_args.clear();
|
||||
} else if (op == Opcode::StringLiteral) {
|
||||
string_literal.clear();
|
||||
} else {
|
||||
for (auto& value : args) {
|
||||
if (!value.IsImmediate()) {
|
||||
|
@ -196,9 +183,6 @@ void Inst::ReplaceOpcode(IR::Opcode opcode) {
|
|||
if (opcode == IR::Opcode::Phi) {
|
||||
UNREACHABLE_MSG("Cannot transition into Phi");
|
||||
}
|
||||
if (op == IR::Opcode::StringLiteral || opcode == IR::Opcode::StringLiteral) {
|
||||
UNREACHABLE_MSG("Cannot transition to or from StringLiteral");
|
||||
}
|
||||
if (op == Opcode::Phi) {
|
||||
// Transition out of phi arguments into non-phi
|
||||
std::destroy_at(&phi_args);
|
||||
|
|
|
@ -14,9 +14,7 @@ OPCODE(Prologue, Void,
|
|||
OPCODE(Epilogue, Void, )
|
||||
OPCODE(Discard, Void, )
|
||||
OPCODE(DiscardCond, Void, U1, )
|
||||
OPCODE(DebugPrint, Void, Opaque, Opaque, )
|
||||
OPCODE(VaArg, Opaque, Opaque, Opaque )
|
||||
OPCODE(StringLiteral, Opaque, )
|
||||
OPCODE(DebugPrint, Void, Opaque, Opaque, Opaque, Opaque, Opaque, )
|
||||
|
||||
// Constant memory operations
|
||||
OPCODE(ReadConst, U32, U32x2, U32, )
|
||||
|
|
|
@ -377,7 +377,7 @@ void PatchBufferInstruction(IR::Block& block, IR::Inst& inst, Info& info,
|
|||
const auto inst_info = inst.Flags<IR::BufferInstInfo>();
|
||||
|
||||
// Replace handle with binding index in buffer resource list.
|
||||
IR::IREmitter ir{block, IR::Block::InstructionList::s_iterator_to(inst)};
|
||||
IR::IREmitter ir{block, IR::Block::InstructionList::s_iterator_to(inst), info};
|
||||
inst.SetArg(0, ir.Imm32(binding));
|
||||
ASSERT(!buffer.add_tid_enable);
|
||||
|
||||
|
@ -436,7 +436,7 @@ void PatchTextureBufferInstruction(IR::Block& block, IR::Inst& inst, Info& info,
|
|||
});
|
||||
|
||||
// Replace handle with binding index in texture buffer resource list.
|
||||
IR::IREmitter ir{block, IR::Block::InstructionList::s_iterator_to(inst)};
|
||||
IR::IREmitter ir{block, IR::Block::InstructionList::s_iterator_to(inst), info};
|
||||
inst.SetArg(0, ir.Imm32(binding));
|
||||
ASSERT(!buffer.swizzle_enable && !buffer.add_tid_enable);
|
||||
}
|
||||
|
@ -534,7 +534,7 @@ void PatchImageInstruction(IR::Block& block, IR::Inst& inst, Info& info, Descrip
|
|||
image_binding |= (sampler_binding << 16);
|
||||
|
||||
// Patch image handle
|
||||
IR::IREmitter ir{block, IR::Block::InstructionList::s_iterator_to(inst)};
|
||||
IR::IREmitter ir{block, IR::Block::InstructionList::s_iterator_to(inst), info};
|
||||
inst.SetArg(0, ir.Imm32(image_binding));
|
||||
|
||||
// No need to patch coordinates if we are just querying.
|
||||
|
@ -667,7 +667,7 @@ void PatchDataRingInstruction(IR::Block& block, IR::Inst& inst, Info& info,
|
|||
}();
|
||||
|
||||
// Patch instruction.
|
||||
IR::IREmitter ir{block, IR::Block::InstructionList::s_iterator_to(inst)};
|
||||
IR::IREmitter ir{block, IR::Block::InstructionList::s_iterator_to(inst), info};
|
||||
inst.SetArg(0, ir.Imm32(gds_addr >> 2));
|
||||
inst.SetArg(1, ir.Imm32(binding));
|
||||
}
|
||||
|
|
|
@ -6,11 +6,9 @@
|
|||
#include <array>
|
||||
#include <bit>
|
||||
#include <cstring>
|
||||
#include <string_view>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
#include <boost/container/small_vector.hpp>
|
||||
#include <boost/container/string.hpp>
|
||||
#include <boost/intrusive/list.hpp>
|
||||
|
||||
#include "common/assert.h"
|
||||
|
@ -148,7 +146,6 @@ public:
|
|||
if (op == IR::Opcode::Phi) {
|
||||
return phi_args[index].second;
|
||||
} else {
|
||||
ASSERT(op != IR::Opcode::StringLiteral);
|
||||
return args[index];
|
||||
}
|
||||
}
|
||||
|
@ -161,16 +158,6 @@ public:
|
|||
/// Add phi operand to a phi instruction.
|
||||
void AddPhiOperand(Block* predecessor, const Value& value);
|
||||
|
||||
[[nodiscard]] std::string_view StringLiteral() const {
|
||||
ASSERT(op == IR::Opcode::StringLiteral);
|
||||
return string_literal;
|
||||
}
|
||||
|
||||
void SetStringLiteral(std::string_view s) noexcept {
|
||||
ASSERT(op == IR::Opcode::StringLiteral);
|
||||
string_literal = s;
|
||||
}
|
||||
|
||||
void Invalidate();
|
||||
void ClearArgs();
|
||||
|
||||
|
@ -220,7 +207,6 @@ private:
|
|||
NonTriviallyDummy dummy{};
|
||||
boost::container::small_vector<std::pair<Block*, Value>, 2> phi_args;
|
||||
std::array<Value, 5> args;
|
||||
boost::container::string string_literal;
|
||||
};
|
||||
};
|
||||
static_assert(sizeof(Inst) <= 128, "Inst size unintentionally increased");
|
||||
|
|
Loading…
Add table
Reference in a new issue