mirror of
				https://git.suyu.dev/suyu/suyu
				synced 2025-10-30 23:49:01 -05:00 
			
		
		
		
	Shader_IR: Propagate bindless index into the GL compiler.
This commit is contained in:
		 Fernando Sahmkow
					Fernando Sahmkow
				
			
				
					committed by
					
						 FernandoS27
						FernandoS27
					
				
			
			
				
	
			
			
			 FernandoS27
						FernandoS27
					
				
			
						parent
						
							3c34678627
						
					
				
				
					commit
					7c530e0666
				
			| @@ -1123,7 +1123,7 @@ private: | |||||||
|         if (!meta->sampler.IsIndexed()) { |         if (!meta->sampler.IsIndexed()) { | ||||||
|             expr += '(' + GetSampler(meta->sampler) + ", "; |             expr += '(' + GetSampler(meta->sampler) + ", "; | ||||||
|         } else { |         } else { | ||||||
|             expr += '(' + GetSampler(meta->sampler) + "[0], "; |             expr += '(' + GetSampler(meta->sampler) + '[' + Visit(meta->index).AsUint() + "], "; | ||||||
|         } |         } | ||||||
|         expr += coord_constructors.at(count + (has_array ? 1 : 0) + |         expr += coord_constructors.at(count + (has_array ? 1 : 0) + | ||||||
|                                       (has_shadow && !separate_dc ? 1 : 0) - 1); |                                       (has_shadow && !separate_dc ? 1 : 0) - 1); | ||||||
|   | |||||||
| @@ -144,7 +144,8 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) { | |||||||
|         Node4 values; |         Node4 values; | ||||||
|         for (u32 element = 0; element < values.size(); ++element) { |         for (u32 element = 0; element < values.size(); ++element) { | ||||||
|             auto coords_copy = coords; |             auto coords_copy = coords; | ||||||
|             MetaTexture meta{sampler, {}, depth_compare, aoffi, {}, {}, {}, {}, component, element}; |             MetaTexture meta{sampler, {}, depth_compare, aoffi,   {}, {}, | ||||||
|  |                              {},      {}, component,     element, {}}; | ||||||
|             values[element] = Operation(OperationCode::TextureGather, meta, std::move(coords_copy)); |             values[element] = Operation(OperationCode::TextureGather, meta, std::move(coords_copy)); | ||||||
|         } |         } | ||||||
|  |  | ||||||
| @@ -167,9 +168,9 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) { | |||||||
|         const auto derivate_reg = instr.gpr20.Value(); |         const auto derivate_reg = instr.gpr20.Value(); | ||||||
|         const auto texture_type = instr.txd.texture_type.Value(); |         const auto texture_type = instr.txd.texture_type.Value(); | ||||||
|         const auto coord_count = GetCoordCount(texture_type); |         const auto coord_count = GetCoordCount(texture_type); | ||||||
|  |         Node index_var{}; | ||||||
|         const Sampler* sampler = |         const Sampler* sampler = | ||||||
|             is_bindless ? GetBindlessSampler(base_reg, {{texture_type, is_array, false}}) |             is_bindless ? GetBindlessSampler(base_reg, index_var, {{texture_type, is_array, false}}) | ||||||
|                         : GetSampler(instr.sampler, {{texture_type, is_array, false}}); |                         : GetSampler(instr.sampler, {{texture_type, is_array, false}}); | ||||||
|         Node4 values; |         Node4 values; | ||||||
|         if (sampler == nullptr) { |         if (sampler == nullptr) { | ||||||
| @@ -200,7 +201,7 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) { | |||||||
|         } |         } | ||||||
|  |  | ||||||
|         for (u32 element = 0; element < values.size(); ++element) { |         for (u32 element = 0; element < values.size(); ++element) { | ||||||
|             MetaTexture meta{*sampler, array_node, {}, {}, {}, derivates, {}, {}, {}, element}; |             MetaTexture meta{*sampler, array_node, {}, {}, {}, derivates, {}, {}, {}, element, index_var}; | ||||||
|             values[element] = Operation(OperationCode::TextureGradient, std::move(meta), coords); |             values[element] = Operation(OperationCode::TextureGradient, std::move(meta), coords); | ||||||
|         } |         } | ||||||
|  |  | ||||||
| @@ -215,8 +216,9 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) { | |||||||
|         // TODO: The new commits on the texture refactor, change the way samplers work. |         // TODO: The new commits on the texture refactor, change the way samplers work. | ||||||
|         // Sadly, not all texture instructions specify the type of texture their sampler |         // Sadly, not all texture instructions specify the type of texture their sampler | ||||||
|         // uses. This must be fixed at a later instance. |         // uses. This must be fixed at a later instance. | ||||||
|  |         Node index_var{}; | ||||||
|         const Sampler* sampler = |         const Sampler* sampler = | ||||||
|             is_bindless ? GetBindlessSampler(instr.gpr8) : GetSampler(instr.sampler); |             is_bindless ? GetBindlessSampler(instr.gpr8, index_var) : GetSampler(instr.sampler); | ||||||
|  |  | ||||||
|         if (sampler == nullptr) { |         if (sampler == nullptr) { | ||||||
|             u32 indexer = 0; |             u32 indexer = 0; | ||||||
| @@ -240,7 +242,7 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) { | |||||||
|                 if (!instr.txq.IsComponentEnabled(element)) { |                 if (!instr.txq.IsComponentEnabled(element)) { | ||||||
|                     continue; |                     continue; | ||||||
|                 } |                 } | ||||||
|                 MetaTexture meta{*sampler, {}, {}, {}, {}, {}, {}, {}, {}, element}; |                 MetaTexture meta{*sampler, {}, {}, {}, {}, {}, {}, {}, {}, element, index_var}; | ||||||
|                 const Node value = |                 const Node value = | ||||||
|                     Operation(OperationCode::TextureQueryDimensions, meta, |                     Operation(OperationCode::TextureQueryDimensions, meta, | ||||||
|                               GetRegister(instr.gpr8.Value() + (is_bindless ? 1 : 0))); |                               GetRegister(instr.gpr8.Value() + (is_bindless ? 1 : 0))); | ||||||
| @@ -266,8 +268,9 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) { | |||||||
|  |  | ||||||
|         auto texture_type = instr.tmml.texture_type.Value(); |         auto texture_type = instr.tmml.texture_type.Value(); | ||||||
|         const bool is_array = instr.tmml.array != 0; |         const bool is_array = instr.tmml.array != 0; | ||||||
|  |         Node index_var{}; | ||||||
|         const Sampler* sampler = |         const Sampler* sampler = | ||||||
|             is_bindless ? GetBindlessSampler(instr.gpr20) : GetSampler(instr.sampler); |             is_bindless ? GetBindlessSampler(instr.gpr20, index_var) : GetSampler(instr.sampler); | ||||||
|  |  | ||||||
|         if (sampler == nullptr) { |         if (sampler == nullptr) { | ||||||
|             u32 indexer = 0; |             u32 indexer = 0; | ||||||
| @@ -309,7 +312,7 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) { | |||||||
|                 continue; |                 continue; | ||||||
|             } |             } | ||||||
|             auto params = coords; |             auto params = coords; | ||||||
|             MetaTexture meta{*sampler, {}, {}, {}, {}, {}, {}, {}, {}, element}; |             MetaTexture meta{*sampler, {}, {}, {}, {}, {}, {}, {}, {}, element, index_var}; | ||||||
|             const Node value = Operation(OperationCode::TextureQueryLod, meta, std::move(params)); |             const Node value = Operation(OperationCode::TextureQueryLod, meta, std::move(params)); | ||||||
|             SetTemporary(bb, indexer++, value); |             SetTemporary(bb, indexer++, value); | ||||||
|         } |         } | ||||||
| @@ -386,7 +389,7 @@ const Sampler* ShaderIR::GetSampler(const Tegra::Shader::Sampler& sampler, | |||||||
|                                        info.is_buffer, false); |                                        info.is_buffer, false); | ||||||
| } | } | ||||||
|  |  | ||||||
| const Sampler* ShaderIR::GetBindlessSampler(Tegra::Shader::Register reg, | const Sampler* ShaderIR::GetBindlessSampler(Tegra::Shader::Register reg, Node& index_var, | ||||||
|                                             std::optional<SamplerInfo> sampler_info) { |                                             std::optional<SamplerInfo> sampler_info) { | ||||||
|     const Node sampler_register = GetRegister(reg); |     const Node sampler_register = GetRegister(reg); | ||||||
|     const auto [base_node, tracked_sampler_info] = |     const auto [base_node, tracked_sampler_info] = | ||||||
| @@ -421,6 +424,7 @@ const Sampler* ShaderIR::GetBindlessSampler(Tegra::Shader::Register reg, | |||||||
|     } else if (const auto array_sampler_info = |     } else if (const auto array_sampler_info = | ||||||
|                    std::get_if<ArraySamplerNode>(&*tracked_sampler_info)) { |                    std::get_if<ArraySamplerNode>(&*tracked_sampler_info)) { | ||||||
|         const u32 base_offset = array_sampler_info->GetBaseOffset() / 4; |         const u32 base_offset = array_sampler_info->GetBaseOffset() / 4; | ||||||
|  |         index_var = GetCustomVariable(array_sampler_info->GetIndexVar()); | ||||||
|         const auto info = GetSamplerInfo(sampler_info, base_offset); |         const auto info = GetSamplerInfo(sampler_info, base_offset); | ||||||
|  |  | ||||||
|         // If this sampler has already been used, return the existing mapping. |         // If this sampler has already been used, return the existing mapping. | ||||||
| @@ -526,8 +530,9 @@ Node4 ShaderIR::GetTextureCode(Instruction instr, TextureType texture_type, | |||||||
|                          "This method is not supported."); |                          "This method is not supported."); | ||||||
|  |  | ||||||
|     const SamplerInfo info{texture_type, is_array, is_shadow, false}; |     const SamplerInfo info{texture_type, is_array, is_shadow, false}; | ||||||
|     const Sampler* sampler = |     Node index_var{}; | ||||||
|         is_bindless ? GetBindlessSampler(*bindless_reg, info) : GetSampler(instr.sampler, info); |     const Sampler* sampler = is_bindless ? GetBindlessSampler(*bindless_reg, index_var, info) | ||||||
|  |                                          : GetSampler(instr.sampler, info); | ||||||
|     Node4 values; |     Node4 values; | ||||||
|     if (sampler == nullptr) { |     if (sampler == nullptr) { | ||||||
|         for (u32 element = 0; element < values.size(); ++element) { |         for (u32 element = 0; element < values.size(); ++element) { | ||||||
| @@ -575,7 +580,8 @@ Node4 ShaderIR::GetTextureCode(Instruction instr, TextureType texture_type, | |||||||
|  |  | ||||||
|     for (u32 element = 0; element < values.size(); ++element) { |     for (u32 element = 0; element < values.size(); ++element) { | ||||||
|         auto copy_coords = coords; |         auto copy_coords = coords; | ||||||
|         MetaTexture meta{*sampler, array, depth_compare, aoffi, {}, {}, bias, lod, {}, element}; |         MetaTexture meta{*sampler, array, depth_compare, aoffi,    {}, {}, bias, | ||||||
|  |                          lod,      {},    element,       index_var}; | ||||||
|         values[element] = Operation(read_method, meta, std::move(copy_coords)); |         values[element] = Operation(read_method, meta, std::move(copy_coords)); | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -690,7 +696,8 @@ Node4 ShaderIR::GetTld4Code(Instruction instr, TextureType texture_type, bool de | |||||||
|     u64 parameter_register = instr.gpr20.Value(); |     u64 parameter_register = instr.gpr20.Value(); | ||||||
|  |  | ||||||
|     const SamplerInfo info{texture_type, is_array, depth_compare, false}; |     const SamplerInfo info{texture_type, is_array, depth_compare, false}; | ||||||
|     const Sampler* sampler = is_bindless ? GetBindlessSampler(parameter_register++, info) |     Node index_var{}; | ||||||
|  |     const Sampler* sampler = is_bindless ? GetBindlessSampler(parameter_register++, index_var, info) | ||||||
|                                          : GetSampler(instr.sampler, info); |                                          : GetSampler(instr.sampler, info); | ||||||
|     Node4 values; |     Node4 values; | ||||||
|     if (sampler == nullptr) { |     if (sampler == nullptr) { | ||||||
| @@ -719,7 +726,8 @@ Node4 ShaderIR::GetTld4Code(Instruction instr, TextureType texture_type, bool de | |||||||
|     for (u32 element = 0; element < values.size(); ++element) { |     for (u32 element = 0; element < values.size(); ++element) { | ||||||
|         auto coords_copy = coords; |         auto coords_copy = coords; | ||||||
|         MetaTexture meta{ |         MetaTexture meta{ | ||||||
|             *sampler, GetRegister(array_register), dc, aoffi, ptp, {}, {}, {}, component, element}; |             *sampler, GetRegister(array_register), dc, aoffi, ptp, {}, {}, {}, component, element, | ||||||
|  |             index_var}; | ||||||
|         values[element] = Operation(OperationCode::TextureGather, meta, std::move(coords_copy)); |         values[element] = Operation(OperationCode::TextureGather, meta, std::move(coords_copy)); | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -752,7 +760,7 @@ Node4 ShaderIR::GetTldCode(Tegra::Shader::Instruction instr) { | |||||||
|     Node4 values; |     Node4 values; | ||||||
|     for (u32 element = 0; element < values.size(); ++element) { |     for (u32 element = 0; element < values.size(); ++element) { | ||||||
|         auto coords_copy = coords; |         auto coords_copy = coords; | ||||||
|         MetaTexture meta{sampler, array_register, {}, {}, {}, {}, {}, lod, {}, element}; |         MetaTexture meta{sampler, array_register, {}, {}, {}, {}, {}, lod, {}, element, {}}; | ||||||
|         values[element] = Operation(OperationCode::TexelFetch, meta, std::move(coords_copy)); |         values[element] = Operation(OperationCode::TexelFetch, meta, std::move(coords_copy)); | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -802,7 +810,7 @@ Node4 ShaderIR::GetTldsCode(Instruction instr, TextureType texture_type, bool is | |||||||
|     Node4 values; |     Node4 values; | ||||||
|     for (u32 element = 0; element < values.size(); ++element) { |     for (u32 element = 0; element < values.size(); ++element) { | ||||||
|         auto coords_copy = coords; |         auto coords_copy = coords; | ||||||
|         MetaTexture meta{sampler, array, {}, {}, {}, {}, {}, lod, {}, element}; |         MetaTexture meta{sampler, array, {}, {}, {}, {}, {}, lod, {}, element, {}}; | ||||||
|         values[element] = Operation(OperationCode::TexelFetch, meta, std::move(coords_copy)); |         values[element] = Operation(OperationCode::TexelFetch, meta, std::move(coords_copy)); | ||||||
|     } |     } | ||||||
|     return values; |     return values; | ||||||
|   | |||||||
| @@ -445,6 +445,7 @@ struct MetaTexture { | |||||||
|     Node lod; |     Node lod; | ||||||
|     Node component{}; |     Node component{}; | ||||||
|     u32 element{}; |     u32 element{}; | ||||||
|  |     Node index{}; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| struct MetaImage { | struct MetaImage { | ||||||
| @@ -564,7 +565,6 @@ private: | |||||||
|     u32 index{}; |     u32 index{}; | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  |  | ||||||
| /// A 32-bits value that represents an immediate value | /// A 32-bits value that represents an immediate value | ||||||
| class ImmediateNode final { | class ImmediateNode final { | ||||||
| public: | public: | ||||||
|   | |||||||
| @@ -328,7 +328,7 @@ private: | |||||||
|                               std::optional<SamplerInfo> sampler_info = std::nullopt); |                               std::optional<SamplerInfo> sampler_info = std::nullopt); | ||||||
|  |  | ||||||
|     /// Accesses a texture sampler for a bindless texture. |     /// Accesses a texture sampler for a bindless texture. | ||||||
|     const Sampler* GetBindlessSampler(Tegra::Shader::Register reg, |     const Sampler* GetBindlessSampler(Tegra::Shader::Register reg, Node& index_var, | ||||||
|                                       std::optional<SamplerInfo> sampler_info = std::nullopt); |                                       std::optional<SamplerInfo> sampler_info = std::nullopt); | ||||||
|  |  | ||||||
|     /// Accesses an image. |     /// Accesses an image. | ||||||
| @@ -394,8 +394,7 @@ private: | |||||||
|  |  | ||||||
|     std::tuple<Node, u32, u32> TrackCbuf(Node tracked, const NodeBlock& code, s64 cursor) const; |     std::tuple<Node, u32, u32> TrackCbuf(Node tracked, const NodeBlock& code, s64 cursor) const; | ||||||
|  |  | ||||||
|     std::tuple<Node, TrackSampler> TrackSampler(Node tracked, const NodeBlock& code, |     std::tuple<Node, TrackSampler> TrackSampler(Node tracked, const NodeBlock& code, s64 cursor); | ||||||
|                                                 s64 cursor) const; |  | ||||||
|  |  | ||||||
|     std::optional<u32> TrackImmediate(Node tracked, const NodeBlock& code, s64 cursor) const; |     std::optional<u32> TrackImmediate(Node tracked, const NodeBlock& code, s64 cursor) const; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -61,8 +61,19 @@ std::optional<std::pair<Node, Node>> DecoupleIndirectRead(const OperationNode& o | |||||||
|     return std::nullopt; |     return std::nullopt; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | bool AmendNodeCv(std::size_t amend_index, Node node) { | ||||||
|  |     if (const auto operation = std::get_if<OperationNode>(&*node)) { | ||||||
|  |         operation->SetAmendIndex(amend_index); | ||||||
|  |         return true; | ||||||
|  |     } else if (const auto conditional = std::get_if<ConditionalNode>(&*node)) { | ||||||
|  |         conditional->SetAmendIndex(amend_index); | ||||||
|  |         return true; | ||||||
|  |     } | ||||||
|  |     return false; | ||||||
|  | } | ||||||
|  |  | ||||||
| std::tuple<Node, TrackSampler> ShaderIR::TrackSampler(Node tracked, const NodeBlock& code, | std::tuple<Node, TrackSampler> ShaderIR::TrackSampler(Node tracked, const NodeBlock& code, | ||||||
|                                                       s64 cursor) const { |                                                       s64 cursor) { | ||||||
|     if (const auto cbuf = std::get_if<CbufNode>(&*tracked)) { |     if (const auto cbuf = std::get_if<CbufNode>(&*tracked)) { | ||||||
|         // Constant buffer found, test if it's an immediate |         // Constant buffer found, test if it's an immediate | ||||||
|         const auto offset = cbuf->GetOffset(); |         const auto offset = cbuf->GetOffset(); | ||||||
| @@ -84,9 +95,21 @@ std::tuple<Node, TrackSampler> ShaderIR::TrackSampler(Node tracked, const NodeBl | |||||||
|             } |             } | ||||||
|             auto [gpr, base_offset] = *pair; |             auto [gpr, base_offset] = *pair; | ||||||
|             const auto offset_inm = std::get_if<ImmediateNode>(&*base_offset); |             const auto offset_inm = std::get_if<ImmediateNode>(&*base_offset); | ||||||
|  |             auto gpu_driver = locker.AccessGuestDriverProfile(); | ||||||
|  |             if (gpu_driver == nullptr) { | ||||||
|  |                 return {}; | ||||||
|  |             } | ||||||
|  |             const u32 bindless_cv = NewCustomVariable(); | ||||||
|  |             const Node op = Operation(OperationCode::UDiv, NO_PRECISE, gpr, | ||||||
|  |                                       Immediate(gpu_driver->GetTextureHandlerSize())); | ||||||
|  |  | ||||||
|  |             const Node cv_node = GetCustomVariable(bindless_cv); | ||||||
|  |             Node amend_op = Operation(OperationCode::Assign, cv_node, std::move(op)); | ||||||
|  |             const std::size_t amend_index = DeclareAmend(amend_op); | ||||||
|  |             AmendNodeCv(amend_index, code[cursor]); | ||||||
|             // TODO Implement Bindless Index custom variable |             // TODO Implement Bindless Index custom variable | ||||||
|             auto track = |             auto track = MakeTrackSampler<ArraySamplerNode>(cbuf->GetIndex(), | ||||||
|                 MakeTrackSampler<ArraySamplerNode>(cbuf->GetIndex(), offset_inm->GetValue(), 0); |                                                             offset_inm->GetValue(), bindless_cv); | ||||||
|             return {tracked, track}; |             return {tracked, track}; | ||||||
|         } |         } | ||||||
|         return {}; |         return {}; | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user