mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-04-22 04:24:44 +00:00
Fix IR Debug Print. Add StringLiteral op
This commit is contained in:
parent
060cbe5391
commit
69b3eff9c9
8 changed files with 49 additions and 28 deletions
|
@ -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);
|
||||
|
|
|
@ -2,11 +2,13 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
#include <boost/container/small_vector.hpp>
|
||||
#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<VariadicArgInfo>();
|
||||
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<DebugPrintInfo>().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<Id, 4> fmt_arg_operands;
|
||||
if (!va_arg_list_val.IsEmpty()) {
|
||||
u32 va_arglist_idx = va_arg_list_val.Inst()->Flags<VariadicArgInfo>().va_arg_idx;
|
||||
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(), 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_id, fmt_arg_operands);
|
||||
ctx.OpDebugPrintf(fmt, fmt_arg_operands);
|
||||
}
|
||||
|
||||
} // namespace Shader::Backend::SPIRV
|
||||
|
|
|
@ -179,8 +179,6 @@ struct Info {
|
|||
std::span<const u32> user_data;
|
||||
Stage stage;
|
||||
|
||||
boost::container::small_vector<std::string, 4> debug_print_strings;
|
||||
|
||||
u64 pgm_hash{};
|
||||
VAddr pgm_base;
|
||||
bool has_storage_images{};
|
||||
|
|
|
@ -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;
|
||||
};
|
|
@ -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<Value, 4> 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
|
||||
|
|
|
@ -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<Value, 4> args,
|
||||
bool infer_specifiers = false);
|
||||
|
@ -319,7 +320,6 @@ public:
|
|||
|
||||
private:
|
||||
IR::Block::iterator insertion_point;
|
||||
boost::container::small_vector<std::string, 4> debug_print_strings;
|
||||
|
||||
template <typename T = Value, typename... Args>
|
||||
T Inst(Opcode op, Args... args) {
|
||||
|
|
|
@ -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, )
|
||||
|
|
|
@ -6,9 +6,11 @@
|
|||
#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"
|
||||
|
@ -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<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