diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/video_core/shader/decode/image.cpp | 6 | ||||
| -rw-r--r-- | src/video_core/shader/decode/memory.cpp | 19 | ||||
| -rw-r--r-- | src/video_core/shader/decode/texture.cpp | 8 | ||||
| -rw-r--r-- | src/video_core/shader/shader_ir.cpp | 11 | ||||
| -rw-r--r-- | src/video_core/shader/shader_ir.h | 2 | ||||
| -rw-r--r-- | src/video_core/shader/track.cpp | 25 |
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 | |||
| 95 | const Image& ShaderIR::GetBindlessImage(Tegra::Shader::Register reg, | 95 | const 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 | |||
| 308 | const Sampler& ShaderIR::GetBindlessSampler(const Tegra::Shader::Register& reg, TextureType type, | 308 | const 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 caa409788..78bd1cf1e 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 03c888def..126c78136 100644 --- a/src/video_core/shader/shader_ir.h +++ b/src/video_core/shader/shader_ir.h | |||
| @@ -328,7 +328,7 @@ private: | |||
| 328 | void WriteLop3Instruction(NodeBlock& bb, Tegra::Shader::Register dest, Node op_a, Node op_b, | 328 | void WriteLop3Instruction(NodeBlock& bb, Tegra::Shader::Register dest, Node op_a, Node op_b, |
| 329 | Node op_c, Node imm_lut, bool sets_cc); | 329 | Node op_c, Node imm_lut, bool sets_cc); |
| 330 | 330 | ||
| 331 | Node TrackCbuf(Node tracked, const NodeBlock& code, s64 cursor) const; | 331 | std::tuple<Node, u32, u32> TrackCbuf(Node tracked, const NodeBlock& code, s64 cursor) const; |
| 332 | 332 | ||
| 333 | std::optional<u32> TrackImmediate(Node tracked, const NodeBlock& code, s64 cursor) const; | 333 | std::optional<u32> TrackImmediate(Node tracked, const NodeBlock& code, s64 cursor) const; |
| 334 | 334 | ||
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 | ||
| 37 | Node ShaderIR::TrackCbuf(Node tracked, const NodeBlock& code, s64 cursor) const { | 37 | std::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 | ||
| 70 | std::optional<u32> ShaderIR::TrackImmediate(Node tracked, const NodeBlock& code, s64 cursor) const { | 75 | std::optional<u32> ShaderIR::TrackImmediate(Node tracked, const NodeBlock& code, s64 cursor) const { |