Fix IR Debug Print. Add StringLiteral op

This commit is contained in:
Frodo Baggins 2024-09-19 19:39:48 -07:00
commit 69b3eff9c9
8 changed files with 49 additions and 28 deletions

View file

@ -50,7 +50,8 @@ void EmitEpilogue(EmitContext& ctx);
void EmitDiscard(EmitContext& ctx); void EmitDiscard(EmitContext& ctx);
void EmitDiscardCond(EmitContext& ctx, Id condition); void EmitDiscardCond(EmitContext& ctx, Id condition);
void EmitVaArg(EmitContext& ctx, IR::Inst* inst, Id arg, Id next); 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 EmitBarrier(EmitContext& ctx);
void EmitWorkgroupMemoryBarrier(EmitContext& ctx); void EmitWorkgroupMemoryBarrier(EmitContext& ctx);
void EmitDeviceMemoryBarrier(EmitContext& ctx); void EmitDeviceMemoryBarrier(EmitContext& ctx);

View file

@ -2,11 +2,13 @@
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
#include <algorithm> #include <algorithm>
#include <iterator>
#include <boost/container/small_vector.hpp> #include <boost/container/small_vector.hpp>
#include "common/assert.h" #include "common/assert.h"
#include "shader_recompiler/backend/spirv/emit_spirv_instructions.h" #include "shader_recompiler/backend/spirv/emit_spirv_instructions.h"
#include "shader_recompiler/backend/spirv/spirv_emit_context.h" #include "shader_recompiler/backend/spirv/spirv_emit_context.h"
#include "shader_recompiler/ir/debug_print.h" #include "shader_recompiler/ir/debug_print.h"
#include "shader_recompiler/ir/opcodes.h"
namespace Shader::Backend::SPIRV { namespace Shader::Backend::SPIRV {
@ -53,10 +55,17 @@ void EmitEndPrimitive(EmitContext& ctx, const IR::Value& stream) {
throw NotImplementedException("Geometry streams"); 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) { void EmitVaArg(EmitContext& ctx, IR::Inst* inst, Id arg, Id next) {
IR::Value next_val = inst->Arg(1); IR::Value next_val = inst->Arg(1);
u32 va_arglist_idx; u32 va_arglist_idx;
if (next_val.IsEmpty()) { if (isEmptyInst(next_val)) {
va_arglist_idx = ctx.va_arg_lists.size(); va_arglist_idx = ctx.va_arg_lists.size();
ctx.va_arg_lists.emplace_back(); ctx.va_arg_lists.emplace_back();
} else { } 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); ctx.va_arg_lists[va_arglist_idx].push_back(arg);
VariadicArgInfo va_info; auto va_info = inst->Flags<VariadicArgInfo>();
va_info.va_arg_idx.Assign(va_arglist_idx); va_info.va_arg_idx.Assign(va_arglist_idx);
inst->SetFlags(va_info);
} }
void EmitDebugPrint(EmitContext& ctx, IR::Inst* inst) { Id EmitStringLiteral(EmitContext& ctx, IR::Inst* inst) {
const std::string& fmt = // ctx.
ctx.info.debug_print_strings.at(inst->Flags<DebugPrintInfo>().string_idx); return ctx.String(inst->StringLiteral());
Id fmt_id = ctx.String(fmt); }
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<Id, 4> fmt_arg_operands; boost::container::small_vector<Id, 4> fmt_arg_operands;
if (!va_arg_list_val.IsEmpty()) { if (!isEmptyInst(arglist)) {
u32 va_arglist_idx = va_arg_list_val.Inst()->Flags<VariadicArgInfo>().va_arg_idx; u32 va_arglist_idx = arglist.Inst()->Flags<VariadicArgInfo>().va_arg_idx;
const auto& va_arglist = ctx.va_arg_lists[va_arglist_idx]; const auto& va_arglist = ctx.va_arg_lists[va_arglist_idx];
// reverse the order // 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<DebugPrintInfo>().num_args); ctx.OpDebugPrintf(fmt, fmt_arg_operands);
ctx.OpDebugPrintf(fmt_id, fmt_arg_operands);
} }
} // namespace Shader::Backend::SPIRV } // namespace Shader::Backend::SPIRV

View file

@ -179,8 +179,6 @@ struct Info {
std::span<const u32> user_data; std::span<const u32> user_data;
Stage stage; Stage stage;
boost::container::small_vector<std::string, 4> debug_print_strings;
u64 pgm_hash{}; u64 pgm_hash{};
VAddr pgm_base; VAddr pgm_base;
bool has_storage_images{}; bool has_storage_images{};

View file

@ -7,10 +7,4 @@ union VariadicArgInfo {
u32 raw; u32 raw;
BitField<0, 12, u32> va_arg_idx; BitField<0, 12, u32> va_arg_idx;
};
union DebugPrintInfo {
u32 raw;
BitField<0, 16, u32> string_idx;
BitField<16, 16, u32> num_args;
}; };

View file

@ -1562,6 +1562,12 @@ Value IREmitter::VaArg(Value arg, Value next) {
return Inst(Opcode::VaArg, arg, 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, 4> args,
bool infer_specifiers) { bool infer_specifiers) {
auto infer_specifier = [&](IR::Value arg) -> const char* { 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 // 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); Value arg_list = Inst(Opcode::Void);
for (Value arg : args) { for (Value arg : args) {
arg_list = VaArg(arg, arg_list); 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 } // namespace Shader::IR

View file

@ -47,6 +47,7 @@ public:
void Discard(const U1& cond); void Discard(const U1& cond);
Value VaArg(Value arg, Value next); 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, 4> args,
bool infer_specifiers = false); bool infer_specifiers = false);
@ -319,7 +320,6 @@ public:
private: private:
IR::Block::iterator insertion_point; IR::Block::iterator insertion_point;
boost::container::small_vector<std::string, 4> debug_print_strings;
template <typename T = Value, typename... Args> template <typename T = Value, typename... Args>
T Inst(Opcode op, Args... args) { T Inst(Opcode op, Args... args) {

View file

@ -14,8 +14,9 @@ OPCODE(Prologue, Void,
OPCODE(Epilogue, Void, ) OPCODE(Epilogue, Void, )
OPCODE(Discard, Void, ) OPCODE(Discard, Void, )
OPCODE(DiscardCond, Void, U1, ) OPCODE(DiscardCond, Void, U1, )
OPCODE(DebugPrint, Void, Opaque, ) OPCODE(DebugPrint, Void, Opaque, Opaque, )
OPCODE(VaArg, Opaque, Opaque, Opaque ) OPCODE(VaArg, Opaque, Opaque, Opaque )
OPCODE(StringLiteral, Opaque, )
// Constant memory operations // Constant memory operations
OPCODE(ReadConst, U32, U32x2, U32, ) OPCODE(ReadConst, U32, U32x2, U32, )

View file

@ -6,9 +6,11 @@
#include <array> #include <array>
#include <bit> #include <bit>
#include <cstring> #include <cstring>
#include <string_view>
#include <type_traits> #include <type_traits>
#include <utility> #include <utility>
#include <boost/container/small_vector.hpp> #include <boost/container/small_vector.hpp>
#include <boost/container/string.hpp>
#include <boost/intrusive/list.hpp> #include <boost/intrusive/list.hpp>
#include "common/assert.h" #include "common/assert.h"
@ -146,6 +148,7 @@ public:
if (op == IR::Opcode::Phi) { if (op == IR::Opcode::Phi) {
return phi_args[index].second; return phi_args[index].second;
} else { } else {
ASSERT(op != IR::Opcode::StringLiteral);
return args[index]; return args[index];
} }
} }
@ -158,6 +161,16 @@ public:
/// Add phi operand to a phi instruction. /// Add phi operand to a phi instruction.
void AddPhiOperand(Block* predecessor, const Value& value); 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 Invalidate();
void ClearArgs(); void ClearArgs();
@ -207,6 +220,7 @@ private:
NonTriviallyDummy dummy{}; NonTriviallyDummy dummy{};
boost::container::small_vector<std::pair<Block*, Value>, 2> phi_args; boost::container::small_vector<std::pair<Block*, Value>, 2> phi_args;
std::array<Value, 5> args; std::array<Value, 5> args;
boost::container::string string_literal;
}; };
}; };
static_assert(sizeof(Inst) <= 128, "Inst size unintentionally increased"); static_assert(sizeof(Inst) <= 128, "Inst size unintentionally increased");