summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar ReinUsesLisp2019-05-31 19:14:34 -0300
committerGravatar ReinUsesLisp2019-07-14 22:36:44 -0300
commitafa8096df5e3c24cb3b639a7fbc65f7225a17137 (patch)
tree1787485f5b47e86d2c0b2f277cd1085266e5e9b8 /src
parentMerge pull request #2675 from ReinUsesLisp/opengl-buffer-cache (diff)
downloadyuzu-afa8096df5e3c24cb3b639a7fbc65f7225a17137.tar.gz
yuzu-afa8096df5e3c24cb3b639a7fbc65f7225a17137.tar.xz
yuzu-afa8096df5e3c24cb3b639a7fbc65f7225a17137.zip
shader: Allow tracking of indirect buffers without variable offset
While changing this code, simplify tracking code to allow returning the base address node, this way callers don't have to manually rebuild it on each invocation.
Diffstat (limited to 'src')
-rw-r--r--src/video_core/shader/decode/image.cpp6
-rw-r--r--src/video_core/shader/decode/memory.cpp19
-rw-r--r--src/video_core/shader/decode/texture.cpp8
-rw-r--r--src/video_core/shader/shader_ir.cpp11
-rw-r--r--src/video_core/shader/shader_ir.h2
-rw-r--r--src/video_core/shader/track.cpp25
6 files changed, 36 insertions, 35 deletions
diff --git a/src/video_core/shader/decode/image.cpp b/src/video_core/shader/decode/image.cpp
index 24f022cc0..77151a24b 100644
--- a/src/video_core/shader/decode/image.cpp
+++ b/src/video_core/shader/decode/image.cpp
@@ -95,12 +95,8 @@ const Image& ShaderIR::GetImage(Tegra::Shader::Image image, Tegra::Shader::Image
95const Image& ShaderIR::GetBindlessImage(Tegra::Shader::Register reg, 95const Image& ShaderIR::GetBindlessImage(Tegra::Shader::Register reg,
96 Tegra::Shader::ImageType type) { 96 Tegra::Shader::ImageType type) {
97 const Node image_register{GetRegister(reg)}; 97 const Node image_register{GetRegister(reg)};
98 const Node base_image{ 98 const auto [base_image, cbuf_index, cbuf_offset]{
99 TrackCbuf(image_register, global_code, static_cast<s64>(global_code.size()))}; 99 TrackCbuf(image_register, global_code, static_cast<s64>(global_code.size()))};
100 const auto cbuf{std::get_if<CbufNode>(&*base_image)};
101 const auto cbuf_offset_imm{std::get_if<ImmediateNode>(&*cbuf->GetOffset())};
102 const auto cbuf_offset{cbuf_offset_imm->GetValue()};
103 const auto cbuf_index{cbuf->GetIndex()};
104 const auto cbuf_key{(static_cast<u64>(cbuf_index) << 32) | static_cast<u64>(cbuf_offset)}; 100 const auto cbuf_key{(static_cast<u64>(cbuf_index) << 32) | static_cast<u64>(cbuf_offset)};
105 101
106 // If this image has already been used, return the existing mapping. 102 // If this image has already been used, return the existing mapping.
diff --git a/src/video_core/shader/decode/memory.cpp b/src/video_core/shader/decode/memory.cpp
index 80fc0ccfc..ab207a33b 100644
--- a/src/video_core/shader/decode/memory.cpp
+++ b/src/video_core/shader/decode/memory.cpp
@@ -297,18 +297,13 @@ std::tuple<Node, Node, GlobalMemoryBase> ShaderIR::TrackAndGetGlobalMemory(NodeB
297 const auto addr_register{GetRegister(instr.gmem.gpr)}; 297 const auto addr_register{GetRegister(instr.gmem.gpr)};
298 const auto immediate_offset{static_cast<u32>(instr.gmem.offset)}; 298 const auto immediate_offset{static_cast<u32>(instr.gmem.offset)};
299 299
300 const Node base_address{ 300 const auto [base_address, index, offset] =
301 TrackCbuf(addr_register, global_code, static_cast<s64>(global_code.size()))}; 301 TrackCbuf(addr_register, global_code, static_cast<s64>(global_code.size()));
302 const auto cbuf = std::get_if<CbufNode>(&*base_address); 302 ASSERT(base_address != nullptr);
303 ASSERT(cbuf != nullptr); 303
304 const auto cbuf_offset_imm = std::get_if<ImmediateNode>(&*cbuf->GetOffset()); 304 bb.push_back(Comment(fmt::format("Base address is c[0x{:x}][0x{:x}]", index, offset)));
305 ASSERT(cbuf_offset_imm != nullptr); 305
306 const auto cbuf_offset = cbuf_offset_imm->GetValue(); 306 const GlobalMemoryBase descriptor{index, offset};
307
308 bb.push_back(
309 Comment(fmt::format("Base address is c[0x{:x}][0x{:x}]", cbuf->GetIndex(), cbuf_offset)));
310
311 const GlobalMemoryBase descriptor{cbuf->GetIndex(), cbuf_offset};
312 const auto& [entry, is_new] = used_global_memory.try_emplace(descriptor); 307 const auto& [entry, is_new] = used_global_memory.try_emplace(descriptor);
313 auto& usage = entry->second; 308 auto& usage = entry->second;
314 if (is_write) { 309 if (is_write) {
diff --git a/src/video_core/shader/decode/texture.cpp b/src/video_core/shader/decode/texture.cpp
index 323be3f14..e1ee5c190 100644
--- a/src/video_core/shader/decode/texture.cpp
+++ b/src/video_core/shader/decode/texture.cpp
@@ -308,13 +308,9 @@ const Sampler& ShaderIR::GetSampler(const Tegra::Shader::Sampler& sampler, Textu
308const Sampler& ShaderIR::GetBindlessSampler(const Tegra::Shader::Register& reg, TextureType type, 308const Sampler& ShaderIR::GetBindlessSampler(const Tegra::Shader::Register& reg, TextureType type,
309 bool is_array, bool is_shadow) { 309 bool is_array, bool is_shadow) {
310 const Node sampler_register = GetRegister(reg); 310 const Node sampler_register = GetRegister(reg);
311 const Node base_sampler = 311 const auto [base_sampler, cbuf_index, cbuf_offset] =
312 TrackCbuf(sampler_register, global_code, static_cast<s64>(global_code.size())); 312 TrackCbuf(sampler_register, global_code, static_cast<s64>(global_code.size()));
313 const auto cbuf = std::get_if<CbufNode>(&*base_sampler); 313 ASSERT(base_sampler != nullptr);
314 const auto cbuf_offset_imm = std::get_if<ImmediateNode>(&*cbuf->GetOffset());
315 ASSERT(cbuf_offset_imm != nullptr);
316 const auto cbuf_offset = cbuf_offset_imm->GetValue();
317 const auto cbuf_index = cbuf->GetIndex();
318 const auto cbuf_key = (static_cast<u64>(cbuf_index) << 32) | static_cast<u64>(cbuf_offset); 314 const auto cbuf_key = (static_cast<u64>(cbuf_index) << 32) | static_cast<u64>(cbuf_offset);
319 315
320 // If this sampler has already been used, return the existing mapping. 316 // If this sampler has already been used, return the existing mapping.
diff --git a/src/video_core/shader/shader_ir.cpp b/src/video_core/shader/shader_ir.cpp
index 5994bfc4e..972defff3 100644
--- a/src/video_core/shader/shader_ir.cpp
+++ b/src/video_core/shader/shader_ir.cpp
@@ -61,7 +61,16 @@ Node ShaderIR::GetConstBufferIndirect(u64 index_, u64 offset_, Node node) {
61 const auto [entry, is_new] = used_cbufs.try_emplace(index); 61 const auto [entry, is_new] = used_cbufs.try_emplace(index);
62 entry->second.MarkAsUsedIndirect(); 62 entry->second.MarkAsUsedIndirect();
63 63
64 const Node final_offset = Operation(OperationCode::UAdd, NO_PRECISE, node, Immediate(offset)); 64 const Node final_offset = [&]() {
65 // Attempt to inline constant buffer without a variable offset. This is done to allow
66 // tracking LDC calls.
67 if (const auto gpr = std::get_if<GprNode>(&*node)) {
68 if (gpr->GetIndex() == Register::ZeroIndex) {
69 return Immediate(offset);
70 }
71 }
72 return Operation(OperationCode::UAdd, NO_PRECISE, node, Immediate(offset));
73 }();
65 return MakeNode<CbufNode>(index, final_offset); 74 return MakeNode<CbufNode>(index, final_offset);
66} 75}
67 76
diff --git a/src/video_core/shader/shader_ir.h b/src/video_core/shader/shader_ir.h
index 6145f0a70..b6faf7ad3 100644
--- a/src/video_core/shader/shader_ir.h
+++ b/src/video_core/shader/shader_ir.h
@@ -316,7 +316,7 @@ private:
316 void WriteLop3Instruction(NodeBlock& bb, Tegra::Shader::Register dest, Node op_a, Node op_b, 316 void WriteLop3Instruction(NodeBlock& bb, Tegra::Shader::Register dest, Node op_a, Node op_b,
317 Node op_c, Node imm_lut, bool sets_cc); 317 Node op_c, Node imm_lut, bool sets_cc);
318 318
319 Node TrackCbuf(Node tracked, const NodeBlock& code, s64 cursor) const; 319 std::tuple<Node, u32, u32> TrackCbuf(Node tracked, const NodeBlock& code, s64 cursor) const;
320 320
321 std::optional<u32> TrackImmediate(Node tracked, const NodeBlock& code, s64 cursor) const; 321 std::optional<u32> TrackImmediate(Node tracked, const NodeBlock& code, s64 cursor) const;
322 322
diff --git a/src/video_core/shader/track.cpp b/src/video_core/shader/track.cpp
index fc957d980..dc132a4a3 100644
--- a/src/video_core/shader/track.cpp
+++ b/src/video_core/shader/track.cpp
@@ -32,39 +32,44 @@ std::pair<Node, s64> FindOperation(const NodeBlock& code, s64 cursor,
32 } 32 }
33 return {}; 33 return {};
34} 34}
35} // namespace 35} // Anonymous namespace
36 36
37Node ShaderIR::TrackCbuf(Node tracked, const NodeBlock& code, s64 cursor) const { 37std::tuple<Node, u32, u32> ShaderIR::TrackCbuf(Node tracked, const NodeBlock& code,
38 s64 cursor) const {
38 if (const auto cbuf = std::get_if<CbufNode>(&*tracked)) { 39 if (const auto cbuf = std::get_if<CbufNode>(&*tracked)) {
39 // Cbuf found, but it has to be immediate 40 // Constant buffer found, test if it's an immediate
40 return std::holds_alternative<ImmediateNode>(*cbuf->GetOffset()) ? tracked : nullptr; 41 const auto offset = cbuf->GetOffset();
42 if (const auto immediate = std::get_if<ImmediateNode>(&*offset)) {
43 return {tracked, cbuf->GetIndex(), immediate->GetValue()};
44 }
45 return {};
41 } 46 }
42 if (const auto gpr = std::get_if<GprNode>(&*tracked)) { 47 if (const auto gpr = std::get_if<GprNode>(&*tracked)) {
43 if (gpr->GetIndex() == Tegra::Shader::Register::ZeroIndex) { 48 if (gpr->GetIndex() == Tegra::Shader::Register::ZeroIndex) {
44 return nullptr; 49 return {};
45 } 50 }
46 // Reduce the cursor in one to avoid infinite loops when the instruction sets the same 51 // Reduce the cursor in one to avoid infinite loops when the instruction sets the same
47 // register that it uses as operand 52 // register that it uses as operand
48 const auto [source, new_cursor] = TrackRegister(gpr, code, cursor - 1); 53 const auto [source, new_cursor] = TrackRegister(gpr, code, cursor - 1);
49 if (!source) { 54 if (!source) {
50 return nullptr; 55 return {};
51 } 56 }
52 return TrackCbuf(source, code, new_cursor); 57 return TrackCbuf(source, code, new_cursor);
53 } 58 }
54 if (const auto operation = std::get_if<OperationNode>(&*tracked)) { 59 if (const auto operation = std::get_if<OperationNode>(&*tracked)) {
55 for (std::size_t i = 0; i < operation->GetOperandsCount(); ++i) { 60 for (std::size_t i = 0; i < operation->GetOperandsCount(); ++i) {
56 if (const auto found = TrackCbuf((*operation)[i], code, cursor)) { 61 if (auto found = TrackCbuf((*operation)[i], code, cursor); std::get<0>(found)) {
57 // Cbuf found in operand 62 // Cbuf found in operand.
58 return found; 63 return found;
59 } 64 }
60 } 65 }
61 return nullptr; 66 return {};
62 } 67 }
63 if (const auto conditional = std::get_if<ConditionalNode>(&*tracked)) { 68 if (const auto conditional = std::get_if<ConditionalNode>(&*tracked)) {
64 const auto& conditional_code = conditional->GetCode(); 69 const auto& conditional_code = conditional->GetCode();
65 return TrackCbuf(tracked, conditional_code, static_cast<s64>(conditional_code.size())); 70 return TrackCbuf(tracked, conditional_code, static_cast<s64>(conditional_code.size()));
66 } 71 }
67 return nullptr; 72 return {};
68} 73}
69 74
70std::optional<u32> ShaderIR::TrackImmediate(Node tracked, const NodeBlock& code, s64 cursor) const { 75std::optional<u32> ShaderIR::TrackImmediate(Node tracked, const NodeBlock& code, s64 cursor) const {