diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h b/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h index 86bbeacc4..ad18caedd 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h +++ b/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h @@ -50,7 +50,8 @@ 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); -void EmitDebugPrint(EmitContext& ctx, IR::Inst* inst); +Id EmitStringLiteral(EmitContext& ctx, IR::Inst* inst); +void EmitDebugPrint(EmitContext& ctx, IR::Inst* inst, Id fmt); void EmitBarrier(EmitContext& ctx); void EmitWorkgroupMemoryBarrier(EmitContext& ctx); void EmitDeviceMemoryBarrier(EmitContext& ctx); diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_special.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_special.cpp index cef70b16a..ce3f303d9 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_special.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv_special.cpp @@ -2,11 +2,13 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include +#include #include #include "common/assert.h" #include "shader_recompiler/backend/spirv/emit_spirv_instructions.h" #include "shader_recompiler/backend/spirv/spirv_emit_context.h" #include "shader_recompiler/ir/debug_print.h" +#include "shader_recompiler/ir/opcodes.h" namespace Shader::Backend::SPIRV { @@ -53,10 +55,17 @@ 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 EmitVaArg(EmitContext& ctx, IR::Inst* inst, Id arg, Id next) { IR::Value next_val = inst->Arg(1); u32 va_arglist_idx; - if (next_val.IsEmpty()) { + if (isEmptyInst(next_val)) { va_arglist_idx = ctx.va_arg_lists.size(); ctx.va_arg_lists.emplace_back(); } else { @@ -64,26 +73,27 @@ void EmitVaArg(EmitContext& ctx, IR::Inst* inst, Id arg, Id next) { } ctx.va_arg_lists[va_arglist_idx].push_back(arg); - VariadicArgInfo va_info; + auto va_info = inst->Flags(); va_info.va_arg_idx.Assign(va_arglist_idx); + inst->SetFlags(va_info); } -void EmitDebugPrint(EmitContext& ctx, IR::Inst* inst) { - const std::string& fmt = - ctx.info.debug_print_strings.at(inst->Flags().string_idx); - Id fmt_id = ctx.String(fmt); +Id EmitStringLiteral(EmitContext& ctx, IR::Inst* inst) { + // ctx. + return ctx.String(inst->StringLiteral()); +} - IR::Value va_arg_list_val = inst->Arg(0); +void EmitDebugPrint(EmitContext& ctx, IR::Inst* inst, Id fmt) { + IR::Value arglist = inst->Arg(1); boost::container::small_vector fmt_arg_operands; - if (!va_arg_list_val.IsEmpty()) { - u32 va_arglist_idx = va_arg_list_val.Inst()->Flags().va_arg_idx; + if (!isEmptyInst(arglist)) { + u32 va_arglist_idx = arglist.Inst()->Flags().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(), fmt_arg_operands.end()); + std::copy(va_arglist.rbegin(), va_arglist.rend(), std::back_inserter(fmt_arg_operands)); } - ASSERT(fmt_arg_operands.size() == inst->Flags().num_args); - ctx.OpDebugPrintf(fmt_id, fmt_arg_operands); + ctx.OpDebugPrintf(fmt, fmt_arg_operands); } } // namespace Shader::Backend::SPIRV diff --git a/src/shader_recompiler/info.h b/src/shader_recompiler/info.h index d1ca61be6..739214ec9 100644 --- a/src/shader_recompiler/info.h +++ b/src/shader_recompiler/info.h @@ -179,8 +179,6 @@ struct Info { std::span user_data; Stage stage; - boost::container::small_vector debug_print_strings; - u64 pgm_hash{}; VAddr pgm_base; bool has_storage_images{}; diff --git a/src/shader_recompiler/ir/debug_print.h b/src/shader_recompiler/ir/debug_print.h index e2b5a537f..5e1bf43b3 100644 --- a/src/shader_recompiler/ir/debug_print.h +++ b/src/shader_recompiler/ir/debug_print.h @@ -7,10 +7,4 @@ union VariadicArgInfo { u32 raw; BitField<0, 12, u32> va_arg_idx; -}; - -union DebugPrintInfo { - u32 raw; - BitField<0, 16, u32> string_idx; - BitField<16, 16, u32> num_args; }; \ No newline at end of file diff --git a/src/shader_recompiler/ir/ir_emitter.cpp b/src/shader_recompiler/ir/ir_emitter.cpp index de1eab250..3d6772bea 100644 --- a/src/shader_recompiler/ir/ir_emitter.cpp +++ b/src/shader_recompiler/ir/ir_emitter.cpp @@ -1562,6 +1562,12 @@ 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 args, bool infer_specifiers) { auto infer_specifier = [&](IR::Value arg) -> const char* { @@ -1611,16 +1617,13 @@ void IREmitter::DebugPrint(std::string_view format, boost::container::small_vect // could use param pack for this function, but less flexible } - DebugPrintInfo info{}; - info.string_idx.Assign(debug_print_strings.size()); - info.num_args.Assign(args.size()); - Value arg_list = Inst(Opcode::Void); for (Value arg : args) { arg_list = VaArg(arg, arg_list); } - Inst(Opcode::DebugPrint, Flags{info}, arg_list); + Value string_val = StringLiteral(format); + Inst(Opcode::DebugPrint, string_val, arg_list); } } // namespace Shader::IR diff --git a/src/shader_recompiler/ir/ir_emitter.h b/src/shader_recompiler/ir/ir_emitter.h index 65716f0fe..eb0df2d3f 100644 --- a/src/shader_recompiler/ir/ir_emitter.h +++ b/src/shader_recompiler/ir/ir_emitter.h @@ -47,6 +47,7 @@ public: 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 args, bool infer_specifiers = false); @@ -319,7 +320,6 @@ public: private: IR::Block::iterator insertion_point; - boost::container::small_vector debug_print_strings; template T Inst(Opcode op, Args... args) { diff --git a/src/shader_recompiler/ir/opcodes.inc b/src/shader_recompiler/ir/opcodes.inc index bef4943f5..1e3be0671 100644 --- a/src/shader_recompiler/ir/opcodes.inc +++ b/src/shader_recompiler/ir/opcodes.inc @@ -14,8 +14,9 @@ OPCODE(Prologue, Void, OPCODE(Epilogue, Void, ) OPCODE(Discard, Void, ) OPCODE(DiscardCond, Void, U1, ) -OPCODE(DebugPrint, Void, Opaque, ) +OPCODE(DebugPrint, Void, Opaque, Opaque, ) OPCODE(VaArg, Opaque, Opaque, Opaque ) +OPCODE(StringLiteral, Opaque, ) // Constant memory operations OPCODE(ReadConst, U32, U32x2, U32, ) diff --git a/src/shader_recompiler/ir/value.h b/src/shader_recompiler/ir/value.h index db939eaa5..c5dd5f5b4 100644 --- a/src/shader_recompiler/ir/value.h +++ b/src/shader_recompiler/ir/value.h @@ -6,9 +6,11 @@ #include #include #include +#include #include #include #include +#include #include #include "common/assert.h" @@ -146,6 +148,7 @@ public: if (op == IR::Opcode::Phi) { return phi_args[index].second; } else { + ASSERT(op != IR::Opcode::StringLiteral); return args[index]; } } @@ -158,6 +161,16 @@ 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(); @@ -207,6 +220,7 @@ private: NonTriviallyDummy dummy{}; boost::container::small_vector, 2> phi_args; std::array args; + boost::container::string string_literal; }; }; static_assert(sizeof(Inst) <= 128, "Inst size unintentionally increased");