summaryrefslogtreecommitdiff
path: root/src/video_core/shader/track.cpp
diff options
context:
space:
mode:
authorGravatar bunnei2019-01-29 22:02:01 -0500
committerGravatar GitHub2019-01-29 22:02:01 -0500
commit52bb5245268e113bfacc4c4bb27a74ea3058adbc (patch)
tree4ba30f0ad404bd4120dd5b2e4f21193bf03952fd /src/video_core/shader/track.cpp
parentvideo_core/GPU Implemented the GPU PFIFO puller semaphore operations. (#1908) (diff)
parentgl_rasterizer: Implement global memory management (diff)
downloadyuzu-52bb5245268e113bfacc4c4bb27a74ea3058adbc.tar.gz
yuzu-52bb5245268e113bfacc4c4bb27a74ea3058adbc.tar.xz
yuzu-52bb5245268e113bfacc4c4bb27a74ea3058adbc.zip
Merge pull request #1960 from ReinUsesLisp/shader-ir-ldg
video_core: Implement LDG through heuristics based on IR
Diffstat (limited to 'src/video_core/shader/track.cpp')
-rw-r--r--src/video_core/shader/track.cpp76
1 files changed, 76 insertions, 0 deletions
diff --git a/src/video_core/shader/track.cpp b/src/video_core/shader/track.cpp
new file mode 100644
index 000000000..d6d29ee9f
--- /dev/null
+++ b/src/video_core/shader/track.cpp
@@ -0,0 +1,76 @@
1// Copyright 2018 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include <algorithm>
6#include <utility>
7#include <variant>
8
9#include "video_core/shader/shader_ir.h"
10
11namespace VideoCommon::Shader {
12
13namespace {
14std::pair<Node, s64> FindOperation(const BasicBlock& code, s64 cursor,
15 OperationCode operation_code) {
16 for (; cursor >= 0; --cursor) {
17 const Node node = code[cursor];
18 if (const auto operation = std::get_if<OperationNode>(node)) {
19 if (operation->GetCode() == operation_code)
20 return {node, cursor};
21 }
22 }
23 return {};
24}
25} // namespace
26
27Node ShaderIR::TrackCbuf(Node tracked, const BasicBlock& code, s64 cursor) {
28 if (const auto cbuf = std::get_if<CbufNode>(tracked)) {
29 // Cbuf found, but it has to be immediate
30 return std::holds_alternative<ImmediateNode>(*cbuf->GetOffset()) ? tracked : nullptr;
31 }
32 if (const auto gpr = std::get_if<GprNode>(tracked)) {
33 if (gpr->GetIndex() == Tegra::Shader::Register::ZeroIndex) {
34 return nullptr;
35 }
36 // Reduce the cursor in one to avoid infinite loops when the instruction sets the same
37 // register that it uses as operand
38 const auto [source, new_cursor] = TrackRegister(gpr, code, cursor - 1);
39 if (!source) {
40 return nullptr;
41 }
42 return TrackCbuf(source, code, new_cursor);
43 }
44 if (const auto operation = std::get_if<OperationNode>(tracked)) {
45 for (std::size_t i = 0; i < operation->GetOperandsCount(); ++i) {
46 if (const auto found = TrackCbuf((*operation)[i], code, cursor)) {
47 // Cbuf found in operand
48 return found;
49 }
50 }
51 return nullptr;
52 }
53 return nullptr;
54}
55
56std::pair<Node, s64> ShaderIR::TrackRegister(const GprNode* tracked, const BasicBlock& code,
57 s64 cursor) {
58 for (; cursor >= 0; --cursor) {
59 const auto [found_node, new_cursor] = FindOperation(code, cursor, OperationCode::Assign);
60 if (!found_node) {
61 return {};
62 }
63 const auto operation = std::get_if<OperationNode>(found_node);
64 ASSERT(operation);
65
66 const auto& target = (*operation)[0];
67 if (const auto gpr_target = std::get_if<GprNode>(target)) {
68 if (gpr_target->GetIndex() == tracked->GetIndex()) {
69 return {(*operation)[1], new_cursor};
70 }
71 }
72 }
73 return {};
74}
75
76} // namespace VideoCommon::Shader