forked from eden-emu/eden
		
	Shader_IR: Implement TXD instruction.
This commit is contained in:
		
							parent
							
								
									6267529837
								
							
						
					
					
						commit
						206d13c987
					
				
					 5 changed files with 120 additions and 8 deletions
				
			
		|  | @ -1445,6 +1445,26 @@ union Instruction { | ||||||
|         } |         } | ||||||
|     } tlds; |     } tlds; | ||||||
| 
 | 
 | ||||||
|  |     union { | ||||||
|  |         BitField<28, 1, u64> is_array; | ||||||
|  |         BitField<29, 2, TextureType> texture_type; | ||||||
|  |         BitField<35, 1, u64> aoffi_flag; | ||||||
|  |         BitField<49, 1, u64> nodep_flag; | ||||||
|  | 
 | ||||||
|  |         bool UsesMiscMode(TextureMiscMode mode) const { | ||||||
|  |             switch (mode) { | ||||||
|  |             case TextureMiscMode::AOFFI: | ||||||
|  |                 return aoffi_flag != 0; | ||||||
|  |             case TextureMiscMode::NODEP: | ||||||
|  |                 return nodep_flag != 0; | ||||||
|  |             default: | ||||||
|  |                 break; | ||||||
|  |             } | ||||||
|  |             return false; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |     } txd; | ||||||
|  | 
 | ||||||
|     union { |     union { | ||||||
|         BitField<24, 2, StoreCacheManagement> cache_management; |         BitField<24, 2, StoreCacheManagement> cache_management; | ||||||
|         BitField<33, 3, ImageType> image_type; |         BitField<33, 3, ImageType> image_type; | ||||||
|  |  | ||||||
|  | @ -44,8 +44,9 @@ using Operation = const OperationNode&; | ||||||
| enum class Type { Void, Bool, Bool2, Float, Int, Uint, HalfFloat }; | enum class Type { Void, Bool, Bool2, Float, Int, Uint, HalfFloat }; | ||||||
| 
 | 
 | ||||||
| struct TextureAoffi {}; | struct TextureAoffi {}; | ||||||
|  | struct TextureDerivates {}; | ||||||
| using TextureArgument = std::pair<Type, Node>; | using TextureArgument = std::pair<Type, Node>; | ||||||
| using TextureIR = std::variant<TextureAoffi, TextureArgument>; | using TextureIR = std::variant<TextureAoffi, TextureDerivates, TextureArgument>; | ||||||
| 
 | 
 | ||||||
| constexpr u32 MAX_CONSTBUFFER_ELEMENTS = | constexpr u32 MAX_CONSTBUFFER_ELEMENTS = | ||||||
|     static_cast<u32>(Maxwell::MaxConstBufferSize) / (4 * sizeof(float)); |     static_cast<u32>(Maxwell::MaxConstBufferSize) / (4 * sizeof(float)); | ||||||
|  | @ -1129,6 +1130,8 @@ private: | ||||||
|                 expr += GenerateTextureArgument(*argument); |                 expr += GenerateTextureArgument(*argument); | ||||||
|             } else if (std::holds_alternative<TextureAoffi>(variant)) { |             } else if (std::holds_alternative<TextureAoffi>(variant)) { | ||||||
|                 expr += GenerateTextureAoffi(meta->aoffi); |                 expr += GenerateTextureAoffi(meta->aoffi); | ||||||
|  |             } else if (std::holds_alternative<TextureDerivates>(variant)) { | ||||||
|  |                 expr += GenerateTextureDerivates(meta->derivates); | ||||||
|             } else { |             } else { | ||||||
|                 UNREACHABLE(); |                 UNREACHABLE(); | ||||||
|             } |             } | ||||||
|  | @ -1198,6 +1201,36 @@ private: | ||||||
|         return expr; |         return expr; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     std::string GenerateTextureDerivates(const std::vector<Node>& derivates) { | ||||||
|  |         if (derivates.empty()) { | ||||||
|  |             return {}; | ||||||
|  |         } | ||||||
|  |         constexpr std::array coord_constructors = {"float", "vec2", "vec3"}; | ||||||
|  |         std::string expr = ", "; | ||||||
|  |         const std::size_t components = derivates.size() / 2; | ||||||
|  |         std::string dx = coord_constructors.at(components - 1); | ||||||
|  |         std::string dy = coord_constructors.at(components - 1); | ||||||
|  |         dx += '('; | ||||||
|  |         dy += '('; | ||||||
|  | 
 | ||||||
|  |         for (std::size_t index = 0; index < components; ++index) { | ||||||
|  |             const auto operand_x{derivates.at(index * 2)}; | ||||||
|  |             const auto operand_y{derivates.at(index * 2 + 1)}; | ||||||
|  |             dx += Visit(operand_x).AsFloat(); | ||||||
|  |             dy += Visit(operand_y).AsFloat(); | ||||||
|  | 
 | ||||||
|  |             if (index + 1 < components) { | ||||||
|  |                 dx += ", "; | ||||||
|  |                 dy += ", "; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         dx += ')'; | ||||||
|  |         dy += ')'; | ||||||
|  |         expr += dx + ", " + dy; | ||||||
|  | 
 | ||||||
|  |         return expr; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     std::string BuildIntegerCoordinates(Operation operation) { |     std::string BuildIntegerCoordinates(Operation operation) { | ||||||
|         constexpr std::array constructors{"int(", "ivec2(", "ivec3(", "ivec4("}; |         constexpr std::array constructors{"int(", "ivec2(", "ivec3(", "ivec4("}; | ||||||
|         const std::size_t coords_count{operation.GetOperandsCount()}; |         const std::size_t coords_count{operation.GetOperandsCount()}; | ||||||
|  | @ -1777,6 +1810,14 @@ private: | ||||||
|         return {tmp, Type::Float}; |         return {tmp, Type::Float}; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     Expression TextureGradient(Operation operation) { | ||||||
|  |         const auto meta = std::get_if<MetaTexture>(&operation.GetMeta()); | ||||||
|  |         ASSERT(meta); | ||||||
|  | 
 | ||||||
|  |         std::string expr = GenerateTexture(operation, "Grad", {TextureDerivates{}, TextureAoffi{}}); | ||||||
|  |         return {expr + GetSwizzle(meta->element), Type::Float}; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     Expression ImageLoad(Operation operation) { |     Expression ImageLoad(Operation operation) { | ||||||
|         if (!device.HasImageLoadFormatted()) { |         if (!device.HasImageLoadFormatted()) { | ||||||
|             LOG_ERROR(Render_OpenGL, |             LOG_ERROR(Render_OpenGL, | ||||||
|  | @ -2131,6 +2172,7 @@ private: | ||||||
|         &GLSLDecompiler::TextureQueryDimensions, |         &GLSLDecompiler::TextureQueryDimensions, | ||||||
|         &GLSLDecompiler::TextureQueryLod, |         &GLSLDecompiler::TextureQueryLod, | ||||||
|         &GLSLDecompiler::TexelFetch, |         &GLSLDecompiler::TexelFetch, | ||||||
|  |         &GLSLDecompiler::TextureGradient, | ||||||
| 
 | 
 | ||||||
|         &GLSLDecompiler::ImageLoad, |         &GLSLDecompiler::ImageLoad, | ||||||
|         &GLSLDecompiler::ImageStore, |         &GLSLDecompiler::ImageStore, | ||||||
|  |  | ||||||
|  | @ -982,6 +982,11 @@ private: | ||||||
|         return {}; |         return {}; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     Id TextureGradient(Operation operation) { | ||||||
|  |         UNIMPLEMENTED(); | ||||||
|  |         return {}; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     Id ImageLoad(Operation operation) { |     Id ImageLoad(Operation operation) { | ||||||
|         UNIMPLEMENTED(); |         UNIMPLEMENTED(); | ||||||
|         return {}; |         return {}; | ||||||
|  | @ -1474,6 +1479,7 @@ private: | ||||||
|         &SPIRVDecompiler::TextureQueryDimensions, |         &SPIRVDecompiler::TextureQueryDimensions, | ||||||
|         &SPIRVDecompiler::TextureQueryLod, |         &SPIRVDecompiler::TextureQueryLod, | ||||||
|         &SPIRVDecompiler::TexelFetch, |         &SPIRVDecompiler::TexelFetch, | ||||||
|  |         &SPIRVDecompiler::TextureGradient, | ||||||
| 
 | 
 | ||||||
|         &SPIRVDecompiler::ImageLoad, |         &SPIRVDecompiler::ImageLoad, | ||||||
|         &SPIRVDecompiler::ImageStore, |         &SPIRVDecompiler::ImageStore, | ||||||
|  |  | ||||||
|  | @ -134,13 +134,55 @@ 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, {}, {}, {}, {}, {}, component, element}; |             MetaTexture meta{sampler, {}, {}, {}, {}, {}, {}, component, element}; | ||||||
|             values[element] = Operation(OperationCode::TextureGather, meta, std::move(coords_copy)); |             values[element] = Operation(OperationCode::TextureGather, meta, std::move(coords_copy)); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         WriteTexsInstructionFloat(bb, instr, values, true); |         WriteTexsInstructionFloat(bb, instr, values, true); | ||||||
|         break; |         break; | ||||||
|     } |     } | ||||||
|  |     case OpCode::Id::TXD_B: | ||||||
|  |         is_bindless = true; | ||||||
|  |         [[fallthrough]]; | ||||||
|  |     case OpCode::Id::TXD: { | ||||||
|  |         UNIMPLEMENTED_IF_MSG(instr.txd.UsesMiscMode(TextureMiscMode::AOFFI), | ||||||
|  |                              "AOFFI is not implemented"); | ||||||
|  |         const auto is_array = static_cast<bool>(instr.txd.is_array != 0); | ||||||
|  |         UNIMPLEMENTED_IF_MSG(is_array, "TXD Array is not implemented"); | ||||||
|  | 
 | ||||||
|  |         u64 base_reg = instr.gpr8.Value(); | ||||||
|  |         const auto derivate_reg = instr.gpr20.Value(); | ||||||
|  |         const auto texture_type = instr.txd.texture_type.Value(); | ||||||
|  |         const auto coord_count = GetCoordCount(texture_type); | ||||||
|  | 
 | ||||||
|  |         const auto& sampler = is_bindless | ||||||
|  |                                   ? GetBindlessSampler(base_reg, {{texture_type, false, false}}) | ||||||
|  |                                   : GetSampler(instr.sampler, {{texture_type, false, false}}); | ||||||
|  |         if (is_bindless) { | ||||||
|  |             base_reg++; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         std::vector<Node> coords; | ||||||
|  |         std::vector<Node> derivates; | ||||||
|  |         for (std::size_t i = 0; i < coord_count; ++i) { | ||||||
|  |             coords.push_back(GetRegister(base_reg + i)); | ||||||
|  |             const std::size_t derivate = i * 2; | ||||||
|  |             derivates.push_back(GetRegister(derivate_reg + derivate)); | ||||||
|  |             derivates.push_back(GetRegister(derivate_reg + derivate + 1)); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         Node4 values; | ||||||
|  |         for (u32 element = 0; element < values.size(); ++element) { | ||||||
|  |             auto coords_copy = coords; | ||||||
|  |             MetaTexture meta{sampler, {}, {}, {}, derivates, {}, {}, {}, element}; | ||||||
|  |             values[element] = | ||||||
|  |                 Operation(OperationCode::TextureGradient, meta, std::move(coords_copy)); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         WriteTexInstructionFloat(bb, instr, values); | ||||||
|  | 
 | ||||||
|  |         break; | ||||||
|  |     } | ||||||
|     case OpCode::Id::TXQ_B: |     case OpCode::Id::TXQ_B: | ||||||
|         is_bindless = true; |         is_bindless = true; | ||||||
|         [[fallthrough]]; |         [[fallthrough]]; | ||||||
|  | @ -158,7 +200,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}; | ||||||
|                 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))); | ||||||
|  | @ -213,7 +255,7 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) { | ||||||
|                 continue; |                 continue; | ||||||
|             } |             } | ||||||
|             auto params = coords; |             auto params = coords; | ||||||
|             MetaTexture meta{sampler, {}, {}, {}, {}, {}, {}, element}; |             MetaTexture meta{sampler, {}, {}, {}, {}, {}, {}, {}, element}; | ||||||
|             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); | ||||||
|         } |         } | ||||||
|  | @ -461,7 +503,7 @@ Node4 ShaderIR::GetTextureCode(Instruction instr, TextureType texture_type, | ||||||
|     Node4 values; |     Node4 values; | ||||||
|     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}; | ||||||
|         values[element] = Operation(read_method, meta, std::move(copy_coords)); |         values[element] = Operation(read_method, meta, std::move(copy_coords)); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -594,7 +636,7 @@ Node4 ShaderIR::GetTld4Code(Instruction instr, TextureType texture_type, bool de | ||||||
|     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, GetRegister(array_register), dc, aoffi, {}, {}, component, |         MetaTexture meta{sampler, GetRegister(array_register), dc, aoffi, {}, {}, {}, component, | ||||||
|                          element}; |                          element}; | ||||||
|         values[element] = Operation(OperationCode::TextureGather, meta, std::move(coords_copy)); |         values[element] = Operation(OperationCode::TextureGather, meta, std::move(coords_copy)); | ||||||
|     } |     } | ||||||
|  | @ -628,7 +670,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)); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -664,7 +706,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; | ||||||
|  |  | ||||||
|  | @ -151,6 +151,7 @@ enum class OperationCode { | ||||||
|     TextureQueryDimensions, /// (MetaTexture, float a) -> float4
 |     TextureQueryDimensions, /// (MetaTexture, float a) -> float4
 | ||||||
|     TextureQueryLod,        /// (MetaTexture, float[N] coords) -> float4
 |     TextureQueryLod,        /// (MetaTexture, float[N] coords) -> float4
 | ||||||
|     TexelFetch,             /// (MetaTexture, int[N], int) -> float4
 |     TexelFetch,             /// (MetaTexture, int[N], int) -> float4
 | ||||||
|  |     TextureGradient,        /// (MetaTexture, float[N] coords, float[N*2] derivates) -> float4
 | ||||||
| 
 | 
 | ||||||
|     ImageLoad,  /// (MetaImage, int[N] coords) -> void
 |     ImageLoad,  /// (MetaImage, int[N] coords) -> void
 | ||||||
|     ImageStore, /// (MetaImage, int[N] coords) -> void
 |     ImageStore, /// (MetaImage, int[N] coords) -> void
 | ||||||
|  | @ -363,6 +364,7 @@ struct MetaTexture { | ||||||
|     Node array; |     Node array; | ||||||
|     Node depth_compare; |     Node depth_compare; | ||||||
|     std::vector<Node> aoffi; |     std::vector<Node> aoffi; | ||||||
|  |     std::vector<Node> derivates; | ||||||
|     Node bias; |     Node bias; | ||||||
|     Node lod; |     Node lod; | ||||||
|     Node component{}; |     Node component{}; | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Fernando Sahmkow
						Fernando Sahmkow