summaryrefslogtreecommitdiffstats
path: root/src/video_core/shader
diff options
context:
space:
mode:
Diffstat (limited to 'src/video_core/shader')
-rw-r--r--src/video_core/shader/ast.cpp85
-rw-r--r--src/video_core/shader/ast.h6
-rw-r--r--src/video_core/shader/decode/memory.cpp39
-rw-r--r--src/video_core/shader/shader_ir.h5
4 files changed, 77 insertions, 58 deletions
diff --git a/src/video_core/shader/ast.cpp b/src/video_core/shader/ast.cpp
index 436d45f4b..e43aecc18 100644
--- a/src/video_core/shader/ast.cpp
+++ b/src/video_core/shader/ast.cpp
@@ -3,6 +3,9 @@
// Refer to the license.txt file included.
#include <string>
+#include <string_view>
+
+#include <fmt/format.h>
#include "common/assert.h"
#include "common/common_types.h"
@@ -229,7 +232,8 @@ public:
return inner;
}
- std::string inner{};
+private:
+ std::string inner;
};
class ASTPrinter {
@@ -249,7 +253,7 @@ public:
void operator()(const ASTIfThen& ast) {
ExprPrinter expr_parser{};
std::visit(expr_parser, *ast.condition);
- inner += Ident() + "if (" + expr_parser.GetResult() + ") {\n";
+ inner += fmt::format("{}if ({}) {{\n", Indent(), expr_parser.GetResult());
scope++;
ASTNode current = ast.nodes.GetFirst();
while (current) {
@@ -257,11 +261,13 @@ public:
current = current->GetNext();
}
scope--;
- inner += Ident() + "}\n";
+ inner += fmt::format("{}}}\n", Indent());
}
void operator()(const ASTIfElse& ast) {
- inner += Ident() + "else {\n";
+ inner += Indent();
+ inner += "else {\n";
+
scope++;
ASTNode current = ast.nodes.GetFirst();
while (current) {
@@ -269,40 +275,41 @@ public:
current = current->GetNext();
}
scope--;
- inner += Ident() + "}\n";
+
+ inner += Indent();
+ inner += "}\n";
}
void operator()(const ASTBlockEncoded& ast) {
- inner += Ident() + "Block(" + std::to_string(ast.start) + ", " + std::to_string(ast.end) +
- ");\n";
+ inner += fmt::format("{}Block({}, {});\n", Indent(), ast.start, ast.end);
}
- void operator()(const ASTBlockDecoded& ast) {
- inner += Ident() + "Block;\n";
+ void operator()([[maybe_unused]] const ASTBlockDecoded& ast) {
+ inner += Indent();
+ inner += "Block;\n";
}
void operator()(const ASTVarSet& ast) {
ExprPrinter expr_parser{};
std::visit(expr_parser, *ast.condition);
- inner +=
- Ident() + "V" + std::to_string(ast.index) + " := " + expr_parser.GetResult() + ";\n";
+ inner += fmt::format("{}V{} := {};\n", Indent(), ast.index, expr_parser.GetResult());
}
void operator()(const ASTLabel& ast) {
- inner += "Label_" + std::to_string(ast.index) + ":\n";
+ inner += fmt::format("Label_{}:\n", ast.index);
}
void operator()(const ASTGoto& ast) {
ExprPrinter expr_parser{};
std::visit(expr_parser, *ast.condition);
- inner += Ident() + "(" + expr_parser.GetResult() + ") -> goto Label_" +
- std::to_string(ast.label) + ";\n";
+ inner +=
+ fmt::format("{}({}) -> goto Label_{};\n", Indent(), expr_parser.GetResult(), ast.label);
}
void operator()(const ASTDoWhile& ast) {
ExprPrinter expr_parser{};
std::visit(expr_parser, *ast.condition);
- inner += Ident() + "do {\n";
+ inner += fmt::format("{}do {{\n", Indent());
scope++;
ASTNode current = ast.nodes.GetFirst();
while (current) {
@@ -310,32 +317,23 @@ public:
current = current->GetNext();
}
scope--;
- inner += Ident() + "} while (" + expr_parser.GetResult() + ");\n";
+ inner += fmt::format("{}}} while ({});\n", Indent(), expr_parser.GetResult());
}
void operator()(const ASTReturn& ast) {
ExprPrinter expr_parser{};
std::visit(expr_parser, *ast.condition);
- inner += Ident() + "(" + expr_parser.GetResult() + ") -> " +
- (ast.kills ? "discard" : "exit") + ";\n";
+ inner += fmt::format("{}({}) -> {};\n", Indent(), expr_parser.GetResult(),
+ ast.kills ? "discard" : "exit");
}
void operator()(const ASTBreak& ast) {
ExprPrinter expr_parser{};
std::visit(expr_parser, *ast.condition);
- inner += Ident() + "(" + expr_parser.GetResult() + ") -> break;\n";
+ inner += fmt::format("{}({}) -> break;\n", Indent(), expr_parser.GetResult());
}
- std::string& Ident() {
- if (memo_scope == scope) {
- return tabs_memo;
- }
- tabs_memo = tabs.substr(0, scope * 2);
- memo_scope = scope;
- return tabs_memo;
- }
-
- void Visit(ASTNode& node) {
+ void Visit(const ASTNode& node) {
std::visit(*this, *node->GetInnerData());
}
@@ -344,16 +342,29 @@ public:
}
private:
+ std::string_view Indent() {
+ if (space_segment_scope == scope) {
+ return space_segment;
+ }
+
+ // Ensure that we don't exceed our view.
+ ASSERT(scope * 2 < spaces.size());
+
+ space_segment = spaces.substr(0, scope * 2);
+ space_segment_scope = scope;
+ return space_segment;
+ }
+
std::string inner{};
- u32 scope{};
+ std::string_view space_segment;
- std::string tabs_memo{};
- u32 memo_scope{};
+ u32 scope{};
+ u32 space_segment_scope{};
- static constexpr std::string_view tabs{" "};
+ static constexpr std::string_view spaces{" "};
};
-std::string ASTManager::Print() {
+std::string ASTManager::Print() const {
ASTPrinter printer{};
printer.Visit(main_node);
return printer.GetResult();
@@ -549,13 +560,13 @@ bool ASTManager::DirectlyRelated(const ASTNode& first, const ASTNode& second) co
return min->GetParent() == max->GetParent();
}
-void ASTManager::ShowCurrentState(std::string_view state) {
+void ASTManager::ShowCurrentState(std::string_view state) const {
LOG_CRITICAL(HW_GPU, "\nState {}:\n\n{}\n", state, Print());
SanityCheck();
}
-void ASTManager::SanityCheck() {
- for (auto& label : labels) {
+void ASTManager::SanityCheck() const {
+ for (const auto& label : labels) {
if (!label->GetParent()) {
LOG_CRITICAL(HW_GPU, "Sanity Check Failed");
}
diff --git a/src/video_core/shader/ast.h b/src/video_core/shader/ast.h
index d7bf11821..a2f0044ba 100644
--- a/src/video_core/shader/ast.h
+++ b/src/video_core/shader/ast.h
@@ -328,13 +328,13 @@ public:
void InsertReturn(Expr condition, bool kills);
- std::string Print();
+ std::string Print() const;
void Decompile();
- void ShowCurrentState(std::string_view state);
+ void ShowCurrentState(std::string_view state) const;
- void SanityCheck();
+ void SanityCheck() const;
void Clear();
diff --git a/src/video_core/shader/decode/memory.cpp b/src/video_core/shader/decode/memory.cpp
index 7923d4d69..335d78146 100644
--- a/src/video_core/shader/decode/memory.cpp
+++ b/src/video_core/shader/decode/memory.cpp
@@ -166,9 +166,17 @@ u32 ShaderIR::DecodeMemory(NodeBlock& bb, u32 pc) {
}();
const auto [real_address_base, base_address, descriptor] =
- TrackAndGetGlobalMemory(bb, instr, false);
+ TrackGlobalMemory(bb, instr, false);
const u32 count = GetUniformTypeElementsCount(type);
+ if (!real_address_base || !base_address) {
+ // Tracking failed, load zeroes.
+ for (u32 i = 0; i < count; ++i) {
+ SetRegister(bb, instr.gpr0.Value() + i, Immediate(0.0f));
+ }
+ break;
+ }
+
for (u32 i = 0; i < count; ++i) {
const Node it_offset = Immediate(i * 4);
const Node real_address =
@@ -260,22 +268,19 @@ u32 ShaderIR::DecodeMemory(NodeBlock& bb, u32 pc) {
}();
const auto [real_address_base, base_address, descriptor] =
- TrackAndGetGlobalMemory(bb, instr, true);
-
- // Encode in temporary registers like this: real_base_address, {registers_to_be_written...}
- SetTemporary(bb, 0, real_address_base);
+ TrackGlobalMemory(bb, instr, true);
+ if (!real_address_base || !base_address) {
+ // Tracking failed, skip the store.
+ break;
+ }
const u32 count = GetUniformTypeElementsCount(type);
for (u32 i = 0; i < count; ++i) {
- SetTemporary(bb, i + 1, GetRegister(instr.gpr0.Value() + i));
- }
- for (u32 i = 0; i < count; ++i) {
const Node it_offset = Immediate(i * 4);
- const Node real_address =
- Operation(OperationCode::UAdd, NO_PRECISE, real_address_base, it_offset);
+ const Node real_address = Operation(OperationCode::UAdd, real_address_base, it_offset);
const Node gmem = MakeNode<GmemNode>(real_address, base_address, descriptor);
-
- bb.push_back(Operation(OperationCode::Assign, gmem, GetTemporary(i + 1)));
+ const Node value = GetRegister(instr.gpr0.Value() + i);
+ bb.push_back(Operation(OperationCode::Assign, gmem, value));
}
break;
}
@@ -301,15 +306,17 @@ u32 ShaderIR::DecodeMemory(NodeBlock& bb, u32 pc) {
return pc;
}
-std::tuple<Node, Node, GlobalMemoryBase> ShaderIR::TrackAndGetGlobalMemory(NodeBlock& bb,
- Instruction instr,
- bool is_write) {
+std::tuple<Node, Node, GlobalMemoryBase> ShaderIR::TrackGlobalMemory(NodeBlock& bb,
+ Instruction instr,
+ bool is_write) {
const auto addr_register{GetRegister(instr.gmem.gpr)};
const auto immediate_offset{static_cast<u32>(instr.gmem.offset)};
const auto [base_address, index, offset] =
TrackCbuf(addr_register, global_code, static_cast<s64>(global_code.size()));
- ASSERT(base_address != nullptr);
+ ASSERT_OR_EXECUTE_MSG(base_address != nullptr,
+ { return std::make_tuple(nullptr, nullptr, GlobalMemoryBase{}); },
+ "Global memory tracking failed");
bb.push_back(Comment(fmt::format("Base address is c[0x{:x}][0x{:x}]", index, offset)));
diff --git a/src/video_core/shader/shader_ir.h b/src/video_core/shader/shader_ir.h
index 105981d67..91cd0a534 100644
--- a/src/video_core/shader/shader_ir.h
+++ b/src/video_core/shader/shader_ir.h
@@ -371,8 +371,9 @@ private:
std::pair<Node, s64> TrackRegister(const GprNode* tracked, const NodeBlock& code,
s64 cursor) const;
- std::tuple<Node, Node, GlobalMemoryBase> TrackAndGetGlobalMemory(
- NodeBlock& bb, Tegra::Shader::Instruction instr, bool is_write);
+ std::tuple<Node, Node, GlobalMemoryBase> TrackGlobalMemory(NodeBlock& bb,
+ Tegra::Shader::Instruction instr,
+ bool is_write);
const ProgramCode& program_code;
const u32 main_offset;