mirror of
				https://git.suyu.dev/suyu/suyu
				synced 2025-10-30 15:39:02 -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()) { | ||||
|             expr += '(' + GetSampler(meta->sampler) + ", "; | ||||
|         } else { | ||||
|             expr += '(' + GetSampler(meta->sampler) + "[0], "; | ||||
|             expr += '(' + GetSampler(meta->sampler) + '[' + Visit(meta->index).AsUint() + "], "; | ||||
|         } | ||||
|         expr += coord_constructors.at(count + (has_array ? 1 : 0) + | ||||
|                                       (has_shadow && !separate_dc ? 1 : 0) - 1); | ||||
|   | ||||
| @@ -144,7 +144,8 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) { | ||||
|         Node4 values; | ||||
|         for (u32 element = 0; element < values.size(); ++element) { | ||||
|             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)); | ||||
|         } | ||||
|  | ||||
| @@ -167,9 +168,9 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) { | ||||
|         const auto derivate_reg = instr.gpr20.Value(); | ||||
|         const auto texture_type = instr.txd.texture_type.Value(); | ||||
|         const auto coord_count = GetCoordCount(texture_type); | ||||
|  | ||||
|         Node index_var{}; | ||||
|         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}}); | ||||
|         Node4 values; | ||||
|         if (sampler == nullptr) { | ||||
| @@ -200,7 +201,7 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) { | ||||
|         } | ||||
|  | ||||
|         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); | ||||
|         } | ||||
|  | ||||
| @@ -215,8 +216,9 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) { | ||||
|         // 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 | ||||
|         // uses. This must be fixed at a later instance. | ||||
|         Node index_var{}; | ||||
|         const Sampler* sampler = | ||||
|             is_bindless ? GetBindlessSampler(instr.gpr8) : GetSampler(instr.sampler); | ||||
|             is_bindless ? GetBindlessSampler(instr.gpr8, index_var) : GetSampler(instr.sampler); | ||||
|  | ||||
|         if (sampler == nullptr) { | ||||
|             u32 indexer = 0; | ||||
| @@ -240,7 +242,7 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) { | ||||
|                 if (!instr.txq.IsComponentEnabled(element)) { | ||||
|                     continue; | ||||
|                 } | ||||
|                 MetaTexture meta{*sampler, {}, {}, {}, {}, {}, {}, {}, {}, element}; | ||||
|                 MetaTexture meta{*sampler, {}, {}, {}, {}, {}, {}, {}, {}, element, index_var}; | ||||
|                 const Node value = | ||||
|                     Operation(OperationCode::TextureQueryDimensions, meta, | ||||
|                               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(); | ||||
|         const bool is_array = instr.tmml.array != 0; | ||||
|         Node index_var{}; | ||||
|         const Sampler* sampler = | ||||
|             is_bindless ? GetBindlessSampler(instr.gpr20) : GetSampler(instr.sampler); | ||||
|             is_bindless ? GetBindlessSampler(instr.gpr20, index_var) : GetSampler(instr.sampler); | ||||
|  | ||||
|         if (sampler == nullptr) { | ||||
|             u32 indexer = 0; | ||||
| @@ -309,7 +312,7 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) { | ||||
|                 continue; | ||||
|             } | ||||
|             auto params = coords; | ||||
|             MetaTexture meta{*sampler, {}, {}, {}, {}, {}, {}, {}, {}, element}; | ||||
|             MetaTexture meta{*sampler, {}, {}, {}, {}, {}, {}, {}, {}, element, index_var}; | ||||
|             const Node value = Operation(OperationCode::TextureQueryLod, meta, std::move(params)); | ||||
|             SetTemporary(bb, indexer++, value); | ||||
|         } | ||||
| @@ -386,7 +389,7 @@ const Sampler* ShaderIR::GetSampler(const Tegra::Shader::Sampler& sampler, | ||||
|                                        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) { | ||||
|     const Node sampler_register = GetRegister(reg); | ||||
|     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 = | ||||
|                    std::get_if<ArraySamplerNode>(&*tracked_sampler_info)) { | ||||
|         const u32 base_offset = array_sampler_info->GetBaseOffset() / 4; | ||||
|         index_var = GetCustomVariable(array_sampler_info->GetIndexVar()); | ||||
|         const auto info = GetSamplerInfo(sampler_info, base_offset); | ||||
|  | ||||
|         // 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."); | ||||
|  | ||||
|     const SamplerInfo info{texture_type, is_array, is_shadow, false}; | ||||
|     const Sampler* sampler = | ||||
|         is_bindless ? GetBindlessSampler(*bindless_reg, info) : GetSampler(instr.sampler, info); | ||||
|     Node index_var{}; | ||||
|     const Sampler* sampler = is_bindless ? GetBindlessSampler(*bindless_reg, index_var, info) | ||||
|                                          : GetSampler(instr.sampler, info); | ||||
|     Node4 values; | ||||
|     if (sampler == nullptr) { | ||||
|         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) { | ||||
|         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)); | ||||
|     } | ||||
|  | ||||
| @@ -690,7 +696,8 @@ Node4 ShaderIR::GetTld4Code(Instruction instr, TextureType texture_type, bool de | ||||
|     u64 parameter_register = instr.gpr20.Value(); | ||||
|  | ||||
|     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); | ||||
|     Node4 values; | ||||
|     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) { | ||||
|         auto coords_copy = coords; | ||||
|         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)); | ||||
|     } | ||||
|  | ||||
| @@ -752,7 +760,7 @@ Node4 ShaderIR::GetTldCode(Tegra::Shader::Instruction instr) { | ||||
|     Node4 values; | ||||
|     for (u32 element = 0; element < values.size(); ++element) { | ||||
|         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)); | ||||
|     } | ||||
|  | ||||
| @@ -802,7 +810,7 @@ Node4 ShaderIR::GetTldsCode(Instruction instr, TextureType texture_type, bool is | ||||
|     Node4 values; | ||||
|     for (u32 element = 0; element < values.size(); ++element) { | ||||
|         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)); | ||||
|     } | ||||
|     return values; | ||||
|   | ||||
| @@ -445,6 +445,7 @@ struct MetaTexture { | ||||
|     Node lod; | ||||
|     Node component{}; | ||||
|     u32 element{}; | ||||
|     Node index{}; | ||||
| }; | ||||
|  | ||||
| struct MetaImage { | ||||
| @@ -564,7 +565,6 @@ private: | ||||
|     u32 index{}; | ||||
| }; | ||||
|  | ||||
|  | ||||
| /// A 32-bits value that represents an immediate value | ||||
| class ImmediateNode final { | ||||
| public: | ||||
|   | ||||
| @@ -328,7 +328,7 @@ private: | ||||
|                               std::optional<SamplerInfo> sampler_info = std::nullopt); | ||||
|  | ||||
|     /// 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); | ||||
|  | ||||
|     /// 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, TrackSampler> TrackSampler(Node tracked, const NodeBlock& code, | ||||
|                                                 s64 cursor) const; | ||||
|     std::tuple<Node, TrackSampler> TrackSampler(Node tracked, const NodeBlock& code, s64 cursor); | ||||
|  | ||||
|     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; | ||||
| } | ||||
|  | ||||
| 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, | ||||
|                                                       s64 cursor) const { | ||||
|                                                       s64 cursor) { | ||||
|     if (const auto cbuf = std::get_if<CbufNode>(&*tracked)) { | ||||
|         // Constant buffer found, test if it's an immediate | ||||
|         const auto offset = cbuf->GetOffset(); | ||||
| @@ -84,9 +95,21 @@ std::tuple<Node, TrackSampler> ShaderIR::TrackSampler(Node tracked, const NodeBl | ||||
|             } | ||||
|             auto [gpr, base_offset] = *pair; | ||||
|             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 | ||||
|             auto track = | ||||
|                 MakeTrackSampler<ArraySamplerNode>(cbuf->GetIndex(), offset_inm->GetValue(), 0); | ||||
|             auto track = MakeTrackSampler<ArraySamplerNode>(cbuf->GetIndex(), | ||||
|                                                             offset_inm->GetValue(), bindless_cv); | ||||
|             return {tracked, track}; | ||||
|         } | ||||
|         return {}; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user