diff options
| author | 2020-01-07 17:45:12 -0400 | |
|---|---|---|
| committer | 2020-01-24 16:44:47 -0400 | |
| commit | 7c530e06661d760eb6366724d109468423363072 (patch) | |
| tree | 529a0bdfb0aa41773468be8966d9f5c8738e6e3d /src | |
| parent | Shader_IR: Implement Injectable Custom Variables to the IR. (diff) | |
| download | yuzu-7c530e06661d760eb6366724d109468423363072.tar.gz yuzu-7c530e06661d760eb6366724d109468423363072.tar.xz yuzu-7c530e06661d760eb6366724d109468423363072.zip | |
Shader_IR: Propagate bindless index into the GL compiler.
Diffstat (limited to 'src')
| -rw-r--r-- | src/video_core/renderer_opengl/gl_shader_decompiler.cpp | 2 | ||||
| -rw-r--r-- | src/video_core/shader/decode/texture.cpp | 40 | ||||
| -rw-r--r-- | src/video_core/shader/node.h | 2 | ||||
| -rw-r--r-- | src/video_core/shader/shader_ir.h | 5 | ||||
| -rw-r--r-- | src/video_core/shader/track.cpp | 29 |
5 files changed, 54 insertions, 24 deletions
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp index 8b413ae9a..df681bdcb 100644 --- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp +++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp | |||
| @@ -1123,7 +1123,7 @@ private: | |||
| 1123 | if (!meta->sampler.IsIndexed()) { | 1123 | if (!meta->sampler.IsIndexed()) { |
| 1124 | expr += '(' + GetSampler(meta->sampler) + ", "; | 1124 | expr += '(' + GetSampler(meta->sampler) + ", "; |
| 1125 | } else { | 1125 | } else { |
| 1126 | expr += '(' + GetSampler(meta->sampler) + "[0], "; | 1126 | expr += '(' + GetSampler(meta->sampler) + '[' + Visit(meta->index).AsUint() + "], "; |
| 1127 | } | 1127 | } |
| 1128 | expr += coord_constructors.at(count + (has_array ? 1 : 0) + | 1128 | expr += coord_constructors.at(count + (has_array ? 1 : 0) + |
| 1129 | (has_shadow && !separate_dc ? 1 : 0) - 1); | 1129 | (has_shadow && !separate_dc ? 1 : 0) - 1); |
diff --git a/src/video_core/shader/decode/texture.cpp b/src/video_core/shader/decode/texture.cpp index e7c38f5d6..31b09b18c 100644 --- a/src/video_core/shader/decode/texture.cpp +++ b/src/video_core/shader/decode/texture.cpp | |||
| @@ -144,7 +144,8 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) { | |||
| 144 | Node4 values; | 144 | Node4 values; |
| 145 | for (u32 element = 0; element < values.size(); ++element) { | 145 | for (u32 element = 0; element < values.size(); ++element) { |
| 146 | auto coords_copy = coords; | 146 | auto coords_copy = coords; |
| 147 | MetaTexture meta{sampler, {}, depth_compare, aoffi, {}, {}, {}, {}, component, element}; | 147 | MetaTexture meta{sampler, {}, depth_compare, aoffi, {}, {}, |
| 148 | {}, {}, component, element, {}}; | ||
| 148 | values[element] = Operation(OperationCode::TextureGather, meta, std::move(coords_copy)); | 149 | values[element] = Operation(OperationCode::TextureGather, meta, std::move(coords_copy)); |
| 149 | } | 150 | } |
| 150 | 151 | ||
| @@ -167,9 +168,9 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) { | |||
| 167 | const auto derivate_reg = instr.gpr20.Value(); | 168 | const auto derivate_reg = instr.gpr20.Value(); |
| 168 | const auto texture_type = instr.txd.texture_type.Value(); | 169 | const auto texture_type = instr.txd.texture_type.Value(); |
| 169 | const auto coord_count = GetCoordCount(texture_type); | 170 | const auto coord_count = GetCoordCount(texture_type); |
| 170 | 171 | Node index_var{}; | |
| 171 | const Sampler* sampler = | 172 | const Sampler* sampler = |
| 172 | is_bindless ? GetBindlessSampler(base_reg, {{texture_type, is_array, false}}) | 173 | is_bindless ? GetBindlessSampler(base_reg, index_var, {{texture_type, is_array, false}}) |
| 173 | : GetSampler(instr.sampler, {{texture_type, is_array, false}}); | 174 | : GetSampler(instr.sampler, {{texture_type, is_array, false}}); |
| 174 | Node4 values; | 175 | Node4 values; |
| 175 | if (sampler == nullptr) { | 176 | if (sampler == nullptr) { |
| @@ -200,7 +201,7 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) { | |||
| 200 | } | 201 | } |
| 201 | 202 | ||
| 202 | for (u32 element = 0; element < values.size(); ++element) { | 203 | for (u32 element = 0; element < values.size(); ++element) { |
| 203 | MetaTexture meta{*sampler, array_node, {}, {}, {}, derivates, {}, {}, {}, element}; | 204 | MetaTexture meta{*sampler, array_node, {}, {}, {}, derivates, {}, {}, {}, element, index_var}; |
| 204 | values[element] = Operation(OperationCode::TextureGradient, std::move(meta), coords); | 205 | values[element] = Operation(OperationCode::TextureGradient, std::move(meta), coords); |
| 205 | } | 206 | } |
| 206 | 207 | ||
| @@ -215,8 +216,9 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) { | |||
| 215 | // TODO: The new commits on the texture refactor, change the way samplers work. | 216 | // TODO: The new commits on the texture refactor, change the way samplers work. |
| 216 | // Sadly, not all texture instructions specify the type of texture their sampler | 217 | // Sadly, not all texture instructions specify the type of texture their sampler |
| 217 | // uses. This must be fixed at a later instance. | 218 | // uses. This must be fixed at a later instance. |
| 219 | Node index_var{}; | ||
| 218 | const Sampler* sampler = | 220 | const Sampler* sampler = |
| 219 | is_bindless ? GetBindlessSampler(instr.gpr8) : GetSampler(instr.sampler); | 221 | is_bindless ? GetBindlessSampler(instr.gpr8, index_var) : GetSampler(instr.sampler); |
| 220 | 222 | ||
| 221 | if (sampler == nullptr) { | 223 | if (sampler == nullptr) { |
| 222 | u32 indexer = 0; | 224 | u32 indexer = 0; |
| @@ -240,7 +242,7 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) { | |||
| 240 | if (!instr.txq.IsComponentEnabled(element)) { | 242 | if (!instr.txq.IsComponentEnabled(element)) { |
| 241 | continue; | 243 | continue; |
| 242 | } | 244 | } |
| 243 | MetaTexture meta{*sampler, {}, {}, {}, {}, {}, {}, {}, {}, element}; | 245 | MetaTexture meta{*sampler, {}, {}, {}, {}, {}, {}, {}, {}, element, index_var}; |
| 244 | const Node value = | 246 | const Node value = |
| 245 | Operation(OperationCode::TextureQueryDimensions, meta, | 247 | Operation(OperationCode::TextureQueryDimensions, meta, |
| 246 | GetRegister(instr.gpr8.Value() + (is_bindless ? 1 : 0))); | 248 | GetRegister(instr.gpr8.Value() + (is_bindless ? 1 : 0))); |
| @@ -266,8 +268,9 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) { | |||
| 266 | 268 | ||
| 267 | auto texture_type = instr.tmml.texture_type.Value(); | 269 | auto texture_type = instr.tmml.texture_type.Value(); |
| 268 | const bool is_array = instr.tmml.array != 0; | 270 | const bool is_array = instr.tmml.array != 0; |
| 271 | Node index_var{}; | ||
| 269 | const Sampler* sampler = | 272 | const Sampler* sampler = |
| 270 | is_bindless ? GetBindlessSampler(instr.gpr20) : GetSampler(instr.sampler); | 273 | is_bindless ? GetBindlessSampler(instr.gpr20, index_var) : GetSampler(instr.sampler); |
| 271 | 274 | ||
| 272 | if (sampler == nullptr) { | 275 | if (sampler == nullptr) { |
| 273 | u32 indexer = 0; | 276 | u32 indexer = 0; |
| @@ -309,7 +312,7 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) { | |||
| 309 | continue; | 312 | continue; |
| 310 | } | 313 | } |
| 311 | auto params = coords; | 314 | auto params = coords; |
| 312 | MetaTexture meta{*sampler, {}, {}, {}, {}, {}, {}, {}, {}, element}; | 315 | MetaTexture meta{*sampler, {}, {}, {}, {}, {}, {}, {}, {}, element, index_var}; |
| 313 | const Node value = Operation(OperationCode::TextureQueryLod, meta, std::move(params)); | 316 | const Node value = Operation(OperationCode::TextureQueryLod, meta, std::move(params)); |
| 314 | SetTemporary(bb, indexer++, value); | 317 | SetTemporary(bb, indexer++, value); |
| 315 | } | 318 | } |
| @@ -386,7 +389,7 @@ const Sampler* ShaderIR::GetSampler(const Tegra::Shader::Sampler& sampler, | |||
| 386 | info.is_buffer, false); | 389 | info.is_buffer, false); |
| 387 | } | 390 | } |
| 388 | 391 | ||
| 389 | const Sampler* ShaderIR::GetBindlessSampler(Tegra::Shader::Register reg, | 392 | const Sampler* ShaderIR::GetBindlessSampler(Tegra::Shader::Register reg, Node& index_var, |
| 390 | std::optional<SamplerInfo> sampler_info) { | 393 | std::optional<SamplerInfo> sampler_info) { |
| 391 | const Node sampler_register = GetRegister(reg); | 394 | const Node sampler_register = GetRegister(reg); |
| 392 | const auto [base_node, tracked_sampler_info] = | 395 | const auto [base_node, tracked_sampler_info] = |
| @@ -421,6 +424,7 @@ const Sampler* ShaderIR::GetBindlessSampler(Tegra::Shader::Register reg, | |||
| 421 | } else if (const auto array_sampler_info = | 424 | } else if (const auto array_sampler_info = |
| 422 | std::get_if<ArraySamplerNode>(&*tracked_sampler_info)) { | 425 | std::get_if<ArraySamplerNode>(&*tracked_sampler_info)) { |
| 423 | const u32 base_offset = array_sampler_info->GetBaseOffset() / 4; | 426 | const u32 base_offset = array_sampler_info->GetBaseOffset() / 4; |
| 427 | index_var = GetCustomVariable(array_sampler_info->GetIndexVar()); | ||
| 424 | const auto info = GetSamplerInfo(sampler_info, base_offset); | 428 | const auto info = GetSamplerInfo(sampler_info, base_offset); |
| 425 | 429 | ||
| 426 | // If this sampler has already been used, return the existing mapping. | 430 | // If this sampler has already been used, return the existing mapping. |
| @@ -526,8 +530,9 @@ Node4 ShaderIR::GetTextureCode(Instruction instr, TextureType texture_type, | |||
| 526 | "This method is not supported."); | 530 | "This method is not supported."); |
| 527 | 531 | ||
| 528 | const SamplerInfo info{texture_type, is_array, is_shadow, false}; | 532 | const SamplerInfo info{texture_type, is_array, is_shadow, false}; |
| 529 | const Sampler* sampler = | 533 | Node index_var{}; |
| 530 | is_bindless ? GetBindlessSampler(*bindless_reg, info) : GetSampler(instr.sampler, info); | 534 | const Sampler* sampler = is_bindless ? GetBindlessSampler(*bindless_reg, index_var, info) |
| 535 | : GetSampler(instr.sampler, info); | ||
| 531 | Node4 values; | 536 | Node4 values; |
| 532 | if (sampler == nullptr) { | 537 | if (sampler == nullptr) { |
| 533 | for (u32 element = 0; element < values.size(); ++element) { | 538 | for (u32 element = 0; element < values.size(); ++element) { |
| @@ -575,7 +580,8 @@ Node4 ShaderIR::GetTextureCode(Instruction instr, TextureType texture_type, | |||
| 575 | 580 | ||
| 576 | for (u32 element = 0; element < values.size(); ++element) { | 581 | for (u32 element = 0; element < values.size(); ++element) { |
| 577 | auto copy_coords = coords; | 582 | auto copy_coords = coords; |
| 578 | MetaTexture meta{*sampler, array, depth_compare, aoffi, {}, {}, bias, lod, {}, element}; | 583 | MetaTexture meta{*sampler, array, depth_compare, aoffi, {}, {}, bias, |
| 584 | lod, {}, element, index_var}; | ||
| 579 | values[element] = Operation(read_method, meta, std::move(copy_coords)); | 585 | values[element] = Operation(read_method, meta, std::move(copy_coords)); |
| 580 | } | 586 | } |
| 581 | 587 | ||
| @@ -690,7 +696,8 @@ Node4 ShaderIR::GetTld4Code(Instruction instr, TextureType texture_type, bool de | |||
| 690 | u64 parameter_register = instr.gpr20.Value(); | 696 | u64 parameter_register = instr.gpr20.Value(); |
| 691 | 697 | ||
| 692 | const SamplerInfo info{texture_type, is_array, depth_compare, false}; | 698 | const SamplerInfo info{texture_type, is_array, depth_compare, false}; |
| 693 | const Sampler* sampler = is_bindless ? GetBindlessSampler(parameter_register++, info) | 699 | Node index_var{}; |
| 700 | const Sampler* sampler = is_bindless ? GetBindlessSampler(parameter_register++, index_var, info) | ||
| 694 | : GetSampler(instr.sampler, info); | 701 | : GetSampler(instr.sampler, info); |
| 695 | Node4 values; | 702 | Node4 values; |
| 696 | if (sampler == nullptr) { | 703 | if (sampler == nullptr) { |
| @@ -719,7 +726,8 @@ Node4 ShaderIR::GetTld4Code(Instruction instr, TextureType texture_type, bool de | |||
| 719 | for (u32 element = 0; element < values.size(); ++element) { | 726 | for (u32 element = 0; element < values.size(); ++element) { |
| 720 | auto coords_copy = coords; | 727 | auto coords_copy = coords; |
| 721 | MetaTexture meta{ | 728 | MetaTexture meta{ |
| 722 | *sampler, GetRegister(array_register), dc, aoffi, ptp, {}, {}, {}, component, element}; | 729 | *sampler, GetRegister(array_register), dc, aoffi, ptp, {}, {}, {}, component, element, |
| 730 | index_var}; | ||
| 723 | values[element] = Operation(OperationCode::TextureGather, meta, std::move(coords_copy)); | 731 | values[element] = Operation(OperationCode::TextureGather, meta, std::move(coords_copy)); |
| 724 | } | 732 | } |
| 725 | 733 | ||
| @@ -752,7 +760,7 @@ Node4 ShaderIR::GetTldCode(Tegra::Shader::Instruction instr) { | |||
| 752 | Node4 values; | 760 | Node4 values; |
| 753 | for (u32 element = 0; element < values.size(); ++element) { | 761 | for (u32 element = 0; element < values.size(); ++element) { |
| 754 | auto coords_copy = coords; | 762 | auto coords_copy = coords; |
| 755 | MetaTexture meta{sampler, array_register, {}, {}, {}, {}, {}, lod, {}, element}; | 763 | MetaTexture meta{sampler, array_register, {}, {}, {}, {}, {}, lod, {}, element, {}}; |
| 756 | values[element] = Operation(OperationCode::TexelFetch, meta, std::move(coords_copy)); | 764 | values[element] = Operation(OperationCode::TexelFetch, meta, std::move(coords_copy)); |
| 757 | } | 765 | } |
| 758 | 766 | ||
| @@ -802,7 +810,7 @@ Node4 ShaderIR::GetTldsCode(Instruction instr, TextureType texture_type, bool is | |||
| 802 | Node4 values; | 810 | Node4 values; |
| 803 | for (u32 element = 0; element < values.size(); ++element) { | 811 | for (u32 element = 0; element < values.size(); ++element) { |
| 804 | auto coords_copy = coords; | 812 | auto coords_copy = coords; |
| 805 | MetaTexture meta{sampler, array, {}, {}, {}, {}, {}, lod, {}, element}; | 813 | MetaTexture meta{sampler, array, {}, {}, {}, {}, {}, lod, {}, element, {}}; |
| 806 | values[element] = Operation(OperationCode::TexelFetch, meta, std::move(coords_copy)); | 814 | values[element] = Operation(OperationCode::TexelFetch, meta, std::move(coords_copy)); |
| 807 | } | 815 | } |
| 808 | return values; | 816 | return values; |
diff --git a/src/video_core/shader/node.h b/src/video_core/shader/node.h index db06767f6..d75453458 100644 --- a/src/video_core/shader/node.h +++ b/src/video_core/shader/node.h | |||
| @@ -445,6 +445,7 @@ struct MetaTexture { | |||
| 445 | Node lod; | 445 | Node lod; |
| 446 | Node component{}; | 446 | Node component{}; |
| 447 | u32 element{}; | 447 | u32 element{}; |
| 448 | Node index{}; | ||
| 448 | }; | 449 | }; |
| 449 | 450 | ||
| 450 | struct MetaImage { | 451 | struct MetaImage { |
| @@ -564,7 +565,6 @@ private: | |||
| 564 | u32 index{}; | 565 | u32 index{}; |
| 565 | }; | 566 | }; |
| 566 | 567 | ||
| 567 | |||
| 568 | /// A 32-bits value that represents an immediate value | 568 | /// A 32-bits value that represents an immediate value |
| 569 | class ImmediateNode final { | 569 | class ImmediateNode final { |
| 570 | public: | 570 | public: |
diff --git a/src/video_core/shader/shader_ir.h b/src/video_core/shader/shader_ir.h index 2fe14e815..0421dac0c 100644 --- a/src/video_core/shader/shader_ir.h +++ b/src/video_core/shader/shader_ir.h | |||
| @@ -328,7 +328,7 @@ private: | |||
| 328 | std::optional<SamplerInfo> sampler_info = std::nullopt); | 328 | std::optional<SamplerInfo> sampler_info = std::nullopt); |
| 329 | 329 | ||
| 330 | /// Accesses a texture sampler for a bindless texture. | 330 | /// Accesses a texture sampler for a bindless texture. |
| 331 | const Sampler* GetBindlessSampler(Tegra::Shader::Register reg, | 331 | const Sampler* GetBindlessSampler(Tegra::Shader::Register reg, Node& index_var, |
| 332 | std::optional<SamplerInfo> sampler_info = std::nullopt); | 332 | std::optional<SamplerInfo> sampler_info = std::nullopt); |
| 333 | 333 | ||
| 334 | /// Accesses an image. | 334 | /// Accesses an image. |
| @@ -394,8 +394,7 @@ private: | |||
| 394 | 394 | ||
| 395 | std::tuple<Node, u32, u32> TrackCbuf(Node tracked, const NodeBlock& code, s64 cursor) const; | 395 | std::tuple<Node, u32, u32> TrackCbuf(Node tracked, const NodeBlock& code, s64 cursor) const; |
| 396 | 396 | ||
| 397 | std::tuple<Node, TrackSampler> TrackSampler(Node tracked, const NodeBlock& code, | 397 | std::tuple<Node, TrackSampler> TrackSampler(Node tracked, const NodeBlock& code, s64 cursor); |
| 398 | s64 cursor) const; | ||
| 399 | 398 | ||
| 400 | std::optional<u32> TrackImmediate(Node tracked, const NodeBlock& code, s64 cursor) const; | 399 | std::optional<u32> TrackImmediate(Node tracked, const NodeBlock& code, s64 cursor) const; |
| 401 | 400 | ||
diff --git a/src/video_core/shader/track.cpp b/src/video_core/shader/track.cpp index 69a677394..d449b625e 100644 --- a/src/video_core/shader/track.cpp +++ b/src/video_core/shader/track.cpp | |||
| @@ -61,8 +61,19 @@ std::optional<std::pair<Node, Node>> DecoupleIndirectRead(const OperationNode& o | |||
| 61 | return std::nullopt; | 61 | return std::nullopt; |
| 62 | } | 62 | } |
| 63 | 63 | ||
| 64 | bool AmendNodeCv(std::size_t amend_index, Node node) { | ||
| 65 | if (const auto operation = std::get_if<OperationNode>(&*node)) { | ||
| 66 | operation->SetAmendIndex(amend_index); | ||
| 67 | return true; | ||
| 68 | } else if (const auto conditional = std::get_if<ConditionalNode>(&*node)) { | ||
| 69 | conditional->SetAmendIndex(amend_index); | ||
| 70 | return true; | ||
| 71 | } | ||
| 72 | return false; | ||
| 73 | } | ||
| 74 | |||
| 64 | std::tuple<Node, TrackSampler> ShaderIR::TrackSampler(Node tracked, const NodeBlock& code, | 75 | std::tuple<Node, TrackSampler> ShaderIR::TrackSampler(Node tracked, const NodeBlock& code, |
| 65 | s64 cursor) const { | 76 | s64 cursor) { |
| 66 | if (const auto cbuf = std::get_if<CbufNode>(&*tracked)) { | 77 | if (const auto cbuf = std::get_if<CbufNode>(&*tracked)) { |
| 67 | // Constant buffer found, test if it's an immediate | 78 | // Constant buffer found, test if it's an immediate |
| 68 | const auto offset = cbuf->GetOffset(); | 79 | const auto offset = cbuf->GetOffset(); |
| @@ -84,9 +95,21 @@ std::tuple<Node, TrackSampler> ShaderIR::TrackSampler(Node tracked, const NodeBl | |||
| 84 | } | 95 | } |
| 85 | auto [gpr, base_offset] = *pair; | 96 | auto [gpr, base_offset] = *pair; |
| 86 | const auto offset_inm = std::get_if<ImmediateNode>(&*base_offset); | 97 | const auto offset_inm = std::get_if<ImmediateNode>(&*base_offset); |
| 98 | auto gpu_driver = locker.AccessGuestDriverProfile(); | ||
| 99 | if (gpu_driver == nullptr) { | ||
| 100 | return {}; | ||
| 101 | } | ||
| 102 | const u32 bindless_cv = NewCustomVariable(); | ||
| 103 | const Node op = Operation(OperationCode::UDiv, NO_PRECISE, gpr, | ||
| 104 | Immediate(gpu_driver->GetTextureHandlerSize())); | ||
| 105 | |||
| 106 | const Node cv_node = GetCustomVariable(bindless_cv); | ||
| 107 | Node amend_op = Operation(OperationCode::Assign, cv_node, std::move(op)); | ||
| 108 | const std::size_t amend_index = DeclareAmend(amend_op); | ||
| 109 | AmendNodeCv(amend_index, code[cursor]); | ||
| 87 | // TODO Implement Bindless Index custom variable | 110 | // TODO Implement Bindless Index custom variable |
| 88 | auto track = | 111 | auto track = MakeTrackSampler<ArraySamplerNode>(cbuf->GetIndex(), |
| 89 | MakeTrackSampler<ArraySamplerNode>(cbuf->GetIndex(), offset_inm->GetValue(), 0); | 112 | offset_inm->GetValue(), bindless_cv); |
| 90 | return {tracked, track}; | 113 | return {tracked, track}; |
| 91 | } | 114 | } |
| 92 | return {}; | 115 | return {}; |