diff options
Diffstat (limited to 'src/video_core/shader/track.cpp')
| -rw-r--r-- | src/video_core/shader/track.cpp | 78 |
1 files changed, 50 insertions, 28 deletions
diff --git a/src/video_core/shader/track.cpp b/src/video_core/shader/track.cpp index eb97bfd41..d5ed81442 100644 --- a/src/video_core/shader/track.cpp +++ b/src/video_core/shader/track.cpp | |||
| @@ -14,6 +14,7 @@ | |||
| 14 | namespace VideoCommon::Shader { | 14 | namespace VideoCommon::Shader { |
| 15 | 15 | ||
| 16 | namespace { | 16 | namespace { |
| 17 | |||
| 17 | std::pair<Node, s64> FindOperation(const NodeBlock& code, s64 cursor, | 18 | std::pair<Node, s64> FindOperation(const NodeBlock& code, s64 cursor, |
| 18 | OperationCode operation_code) { | 19 | OperationCode operation_code) { |
| 19 | for (; cursor >= 0; --cursor) { | 20 | for (; cursor >= 0; --cursor) { |
| @@ -63,7 +64,8 @@ bool AmendNodeCv(std::size_t amend_index, Node node) { | |||
| 63 | if (const auto operation = std::get_if<OperationNode>(&*node)) { | 64 | if (const auto operation = std::get_if<OperationNode>(&*node)) { |
| 64 | operation->SetAmendIndex(amend_index); | 65 | operation->SetAmendIndex(amend_index); |
| 65 | return true; | 66 | return true; |
| 66 | } else if (const auto conditional = std::get_if<ConditionalNode>(&*node)) { | 67 | } |
| 68 | if (const auto conditional = std::get_if<ConditionalNode>(&*node)) { | ||
| 67 | conditional->SetAmendIndex(amend_index); | 69 | conditional->SetAmendIndex(amend_index); |
| 68 | return true; | 70 | return true; |
| 69 | } | 71 | } |
| @@ -72,40 +74,27 @@ bool AmendNodeCv(std::size_t amend_index, Node node) { | |||
| 72 | 74 | ||
| 73 | } // Anonymous namespace | 75 | } // Anonymous namespace |
| 74 | 76 | ||
| 75 | std::tuple<Node, TrackSampler> ShaderIR::TrackBindlessSampler(Node tracked, const NodeBlock& code, | 77 | std::pair<Node, TrackSampler> ShaderIR::TrackBindlessSampler(Node tracked, const NodeBlock& code, |
| 76 | s64 cursor) { | 78 | s64 cursor) { |
| 77 | if (const auto cbuf = std::get_if<CbufNode>(&*tracked)) { | 79 | if (const auto cbuf = std::get_if<CbufNode>(&*tracked)) { |
| 80 | const u32 cbuf_index = cbuf->GetIndex(); | ||
| 81 | |||
| 78 | // Constant buffer found, test if it's an immediate | 82 | // Constant buffer found, test if it's an immediate |
| 79 | const auto& offset = cbuf->GetOffset(); | 83 | const auto& offset = cbuf->GetOffset(); |
| 80 | if (const auto immediate = std::get_if<ImmediateNode>(&*offset)) { | 84 | if (const auto immediate = std::get_if<ImmediateNode>(&*offset)) { |
| 81 | auto track = | 85 | auto track = MakeTrackSampler<BindlessSamplerNode>(cbuf_index, immediate->GetValue()); |
| 82 | MakeTrackSampler<BindlessSamplerNode>(cbuf->GetIndex(), immediate->GetValue()); | ||
| 83 | return {tracked, track}; | 86 | return {tracked, track}; |
| 84 | } | 87 | } |
| 85 | if (const auto operation = std::get_if<OperationNode>(&*offset)) { | 88 | if (const auto operation = std::get_if<OperationNode>(&*offset)) { |
| 86 | const u32 bound_buffer = registry.GetBoundBuffer(); | 89 | const u32 bound_buffer = registry.GetBoundBuffer(); |
| 87 | if (bound_buffer != cbuf->GetIndex()) { | 90 | if (bound_buffer != cbuf_index) { |
| 88 | return {}; | 91 | return {}; |
| 89 | } | 92 | } |
| 90 | const auto pair = DecoupleIndirectRead(*operation); | 93 | if (const std::optional pair = DecoupleIndirectRead(*operation)) { |
| 91 | if (!pair) { | 94 | auto [gpr, base_offset] = *pair; |
| 92 | return {}; | 95 | return HandleBindlessIndirectRead(*cbuf, *operation, gpr, base_offset, tracked, |
| 96 | code, cursor); | ||
| 93 | } | 97 | } |
| 94 | auto [gpr, base_offset] = *pair; | ||
| 95 | const auto offset_inm = std::get_if<ImmediateNode>(&*base_offset); | ||
| 96 | const auto& gpu_driver = registry.AccessGuestDriverProfile(); | ||
| 97 | const u32 bindless_cv = NewCustomVariable(); | ||
| 98 | Node op = | ||
| 99 | Operation(OperationCode::UDiv, gpr, Immediate(gpu_driver.GetTextureHandlerSize())); | ||
| 100 | |||
| 101 | const Node cv_node = GetCustomVariable(bindless_cv); | ||
| 102 | Node amend_op = Operation(OperationCode::Assign, cv_node, std::move(op)); | ||
| 103 | const std::size_t amend_index = DeclareAmend(std::move(amend_op)); | ||
| 104 | AmendNodeCv(amend_index, code[cursor]); | ||
| 105 | // TODO Implement Bindless Index custom variable | ||
| 106 | auto track = MakeTrackSampler<ArraySamplerNode>(cbuf->GetIndex(), | ||
| 107 | offset_inm->GetValue(), bindless_cv); | ||
| 108 | return {tracked, track}; | ||
| 109 | } | 98 | } |
| 110 | return {}; | 99 | return {}; |
| 111 | } | 100 | } |
| @@ -122,10 +111,23 @@ std::tuple<Node, TrackSampler> ShaderIR::TrackBindlessSampler(Node tracked, cons | |||
| 122 | return TrackBindlessSampler(source, code, new_cursor); | 111 | return TrackBindlessSampler(source, code, new_cursor); |
| 123 | } | 112 | } |
| 124 | if (const auto operation = std::get_if<OperationNode>(&*tracked)) { | 113 | if (const auto operation = std::get_if<OperationNode>(&*tracked)) { |
| 125 | for (std::size_t i = operation->GetOperandsCount(); i > 0; --i) { | 114 | const OperationNode& op = *operation; |
| 126 | if (auto found = TrackBindlessSampler((*operation)[i - 1], code, cursor); | 115 | |
| 127 | std::get<0>(found)) { | 116 | const OperationCode opcode = operation->GetCode(); |
| 128 | // Cbuf found in operand. | 117 | if (opcode == OperationCode::IBitwiseOr || opcode == OperationCode::UBitwiseOr) { |
| 118 | ASSERT(op.GetOperandsCount() == 2); | ||
| 119 | auto [node_a, index_a, offset_a] = TrackCbuf(op[0], code, cursor); | ||
| 120 | auto [node_b, index_b, offset_b] = TrackCbuf(op[1], code, cursor); | ||
| 121 | if (node_a && node_b) { | ||
| 122 | auto track = MakeTrackSampler<SeparateSamplerNode>(std::pair{index_a, index_b}, | ||
| 123 | std::pair{offset_a, offset_b}); | ||
| 124 | return {tracked, std::move(track)}; | ||
| 125 | } | ||
| 126 | } | ||
| 127 | std::size_t i = op.GetOperandsCount(); | ||
| 128 | while (i--) { | ||
| 129 | if (auto found = TrackBindlessSampler(op[i - 1], code, cursor); std::get<0>(found)) { | ||
| 130 | // Constant buffer found in operand. | ||
| 129 | return found; | 131 | return found; |
| 130 | } | 132 | } |
| 131 | } | 133 | } |
| @@ -139,6 +141,26 @@ std::tuple<Node, TrackSampler> ShaderIR::TrackBindlessSampler(Node tracked, cons | |||
| 139 | return {}; | 141 | return {}; |
| 140 | } | 142 | } |
| 141 | 143 | ||
| 144 | std::pair<Node, TrackSampler> ShaderIR::HandleBindlessIndirectRead( | ||
| 145 | const CbufNode& cbuf, const OperationNode& operation, Node gpr, Node base_offset, Node tracked, | ||
| 146 | const NodeBlock& code, s64 cursor) { | ||
| 147 | const auto offset_imm = std::get<ImmediateNode>(*base_offset); | ||
| 148 | const auto& gpu_driver = registry.AccessGuestDriverProfile(); | ||
| 149 | const u32 bindless_cv = NewCustomVariable(); | ||
| 150 | const u32 texture_handler_size = gpu_driver.GetTextureHandlerSize(); | ||
| 151 | Node op = Operation(OperationCode::UDiv, gpr, Immediate(texture_handler_size)); | ||
| 152 | |||
| 153 | Node cv_node = GetCustomVariable(bindless_cv); | ||
| 154 | Node amend_op = Operation(OperationCode::Assign, std::move(cv_node), std::move(op)); | ||
| 155 | const std::size_t amend_index = DeclareAmend(std::move(amend_op)); | ||
| 156 | AmendNodeCv(amend_index, code[cursor]); | ||
| 157 | |||
| 158 | // TODO: Implement bindless index custom variable | ||
| 159 | auto track = | ||
| 160 | MakeTrackSampler<ArraySamplerNode>(cbuf.GetIndex(), offset_imm.GetValue(), bindless_cv); | ||
| 161 | return {tracked, track}; | ||
| 162 | } | ||
| 163 | |||
| 142 | std::tuple<Node, u32, u32> ShaderIR::TrackCbuf(Node tracked, const NodeBlock& code, | 164 | std::tuple<Node, u32, u32> ShaderIR::TrackCbuf(Node tracked, const NodeBlock& code, |
| 143 | s64 cursor) const { | 165 | s64 cursor) const { |
| 144 | if (const auto cbuf = std::get_if<CbufNode>(&*tracked)) { | 166 | if (const auto cbuf = std::get_if<CbufNode>(&*tracked)) { |