diff options
| author | 2019-11-12 13:43:08 -0400 | |
|---|---|---|
| committer | 2019-11-14 11:15:27 -0400 | |
| commit | cd0f5dfc17209eab146879faad51186b130c4951 (patch) | |
| tree | 0185de18a433f22edb69260d3f54779419e2b807 /src | |
| parent | Shader_IR: Implement FLO instruction. (diff) | |
| download | yuzu-cd0f5dfc17209eab146879faad51186b130c4951.tar.gz yuzu-cd0f5dfc17209eab146879faad51186b130c4951.tar.xz yuzu-cd0f5dfc17209eab146879faad51186b130c4951.zip | |
Shader_IR: Implement TXD instruction.
Diffstat (limited to 'src')
| -rw-r--r-- | src/video_core/engines/shader_bytecode.h | 20 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_shader_decompiler.cpp | 44 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_shader_decompiler.cpp | 6 | ||||
| -rw-r--r-- | src/video_core/shader/decode/texture.cpp | 56 | ||||
| -rw-r--r-- | src/video_core/shader/node.h | 2 |
5 files changed, 120 insertions, 8 deletions
diff --git a/src/video_core/engines/shader_bytecode.h b/src/video_core/engines/shader_bytecode.h index 16f410538..9c7b9b370 100644 --- a/src/video_core/engines/shader_bytecode.h +++ b/src/video_core/engines/shader_bytecode.h | |||
| @@ -1446,6 +1446,26 @@ union Instruction { | |||
| 1446 | } tlds; | 1446 | } tlds; |
| 1447 | 1447 | ||
| 1448 | union { | 1448 | union { |
| 1449 | BitField<28, 1, u64> is_array; | ||
| 1450 | BitField<29, 2, TextureType> texture_type; | ||
| 1451 | BitField<35, 1, u64> aoffi_flag; | ||
| 1452 | BitField<49, 1, u64> nodep_flag; | ||
| 1453 | |||
| 1454 | bool UsesMiscMode(TextureMiscMode mode) const { | ||
| 1455 | switch (mode) { | ||
| 1456 | case TextureMiscMode::AOFFI: | ||
| 1457 | return aoffi_flag != 0; | ||
| 1458 | case TextureMiscMode::NODEP: | ||
| 1459 | return nodep_flag != 0; | ||
| 1460 | default: | ||
| 1461 | break; | ||
| 1462 | } | ||
| 1463 | return false; | ||
| 1464 | } | ||
| 1465 | |||
| 1466 | } txd; | ||
| 1467 | |||
| 1468 | union { | ||
| 1449 | BitField<24, 2, StoreCacheManagement> cache_management; | 1469 | BitField<24, 2, StoreCacheManagement> cache_management; |
| 1450 | BitField<33, 3, ImageType> image_type; | 1470 | BitField<33, 3, ImageType> image_type; |
| 1451 | BitField<49, 2, OutOfBoundsStore> out_of_bounds_store; | 1471 | BitField<49, 2, OutOfBoundsStore> out_of_bounds_store; |
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp index b87ee2ae8..49f0b1620 100644 --- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp +++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp | |||
| @@ -44,8 +44,9 @@ using Operation = const OperationNode&; | |||
| 44 | enum class Type { Void, Bool, Bool2, Float, Int, Uint, HalfFloat }; | 44 | enum class Type { Void, Bool, Bool2, Float, Int, Uint, HalfFloat }; |
| 45 | 45 | ||
| 46 | struct TextureAoffi {}; | 46 | struct TextureAoffi {}; |
| 47 | struct TextureDerivates {}; | ||
| 47 | using TextureArgument = std::pair<Type, Node>; | 48 | using TextureArgument = std::pair<Type, Node>; |
| 48 | using TextureIR = std::variant<TextureAoffi, TextureArgument>; | 49 | using TextureIR = std::variant<TextureAoffi, TextureDerivates, TextureArgument>; |
| 49 | 50 | ||
| 50 | constexpr u32 MAX_CONSTBUFFER_ELEMENTS = | 51 | constexpr u32 MAX_CONSTBUFFER_ELEMENTS = |
| 51 | static_cast<u32>(Maxwell::MaxConstBufferSize) / (4 * sizeof(float)); | 52 | static_cast<u32>(Maxwell::MaxConstBufferSize) / (4 * sizeof(float)); |
| @@ -1129,6 +1130,8 @@ private: | |||
| 1129 | expr += GenerateTextureArgument(*argument); | 1130 | expr += GenerateTextureArgument(*argument); |
| 1130 | } else if (std::holds_alternative<TextureAoffi>(variant)) { | 1131 | } else if (std::holds_alternative<TextureAoffi>(variant)) { |
| 1131 | expr += GenerateTextureAoffi(meta->aoffi); | 1132 | expr += GenerateTextureAoffi(meta->aoffi); |
| 1133 | } else if (std::holds_alternative<TextureDerivates>(variant)) { | ||
| 1134 | expr += GenerateTextureDerivates(meta->derivates); | ||
| 1132 | } else { | 1135 | } else { |
| 1133 | UNREACHABLE(); | 1136 | UNREACHABLE(); |
| 1134 | } | 1137 | } |
| @@ -1198,6 +1201,36 @@ private: | |||
| 1198 | return expr; | 1201 | return expr; |
| 1199 | } | 1202 | } |
| 1200 | 1203 | ||
| 1204 | std::string GenerateTextureDerivates(const std::vector<Node>& derivates) { | ||
| 1205 | if (derivates.empty()) { | ||
| 1206 | return {}; | ||
| 1207 | } | ||
| 1208 | constexpr std::array coord_constructors = {"float", "vec2", "vec3"}; | ||
| 1209 | std::string expr = ", "; | ||
| 1210 | const std::size_t components = derivates.size() / 2; | ||
| 1211 | std::string dx = coord_constructors.at(components - 1); | ||
| 1212 | std::string dy = coord_constructors.at(components - 1); | ||
| 1213 | dx += '('; | ||
| 1214 | dy += '('; | ||
| 1215 | |||
| 1216 | for (std::size_t index = 0; index < components; ++index) { | ||
| 1217 | const auto operand_x{derivates.at(index * 2)}; | ||
| 1218 | const auto operand_y{derivates.at(index * 2 + 1)}; | ||
| 1219 | dx += Visit(operand_x).AsFloat(); | ||
| 1220 | dy += Visit(operand_y).AsFloat(); | ||
| 1221 | |||
| 1222 | if (index + 1 < components) { | ||
| 1223 | dx += ", "; | ||
| 1224 | dy += ", "; | ||
| 1225 | } | ||
| 1226 | } | ||
| 1227 | dx += ')'; | ||
| 1228 | dy += ')'; | ||
| 1229 | expr += dx + ", " + dy; | ||
| 1230 | |||
| 1231 | return expr; | ||
| 1232 | } | ||
| 1233 | |||
| 1201 | std::string BuildIntegerCoordinates(Operation operation) { | 1234 | std::string BuildIntegerCoordinates(Operation operation) { |
| 1202 | constexpr std::array constructors{"int(", "ivec2(", "ivec3(", "ivec4("}; | 1235 | constexpr std::array constructors{"int(", "ivec2(", "ivec3(", "ivec4("}; |
| 1203 | const std::size_t coords_count{operation.GetOperandsCount()}; | 1236 | const std::size_t coords_count{operation.GetOperandsCount()}; |
| @@ -1777,6 +1810,14 @@ private: | |||
| 1777 | return {tmp, Type::Float}; | 1810 | return {tmp, Type::Float}; |
| 1778 | } | 1811 | } |
| 1779 | 1812 | ||
| 1813 | Expression TextureGradient(Operation operation) { | ||
| 1814 | const auto meta = std::get_if<MetaTexture>(&operation.GetMeta()); | ||
| 1815 | ASSERT(meta); | ||
| 1816 | |||
| 1817 | std::string expr = GenerateTexture(operation, "Grad", {TextureDerivates{}, TextureAoffi{}}); | ||
| 1818 | return {expr + GetSwizzle(meta->element), Type::Float}; | ||
| 1819 | } | ||
| 1820 | |||
| 1780 | Expression ImageLoad(Operation operation) { | 1821 | Expression ImageLoad(Operation operation) { |
| 1781 | if (!device.HasImageLoadFormatted()) { | 1822 | if (!device.HasImageLoadFormatted()) { |
| 1782 | LOG_ERROR(Render_OpenGL, | 1823 | LOG_ERROR(Render_OpenGL, |
| @@ -2131,6 +2172,7 @@ private: | |||
| 2131 | &GLSLDecompiler::TextureQueryDimensions, | 2172 | &GLSLDecompiler::TextureQueryDimensions, |
| 2132 | &GLSLDecompiler::TextureQueryLod, | 2173 | &GLSLDecompiler::TextureQueryLod, |
| 2133 | &GLSLDecompiler::TexelFetch, | 2174 | &GLSLDecompiler::TexelFetch, |
| 2175 | &GLSLDecompiler::TextureGradient, | ||
| 2134 | 2176 | ||
| 2135 | &GLSLDecompiler::ImageLoad, | 2177 | &GLSLDecompiler::ImageLoad, |
| 2136 | &GLSLDecompiler::ImageStore, | 2178 | &GLSLDecompiler::ImageStore, |
diff --git a/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp b/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp index 8378b35ac..30a525e5d 100644 --- a/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp +++ b/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp | |||
| @@ -982,6 +982,11 @@ private: | |||
| 982 | return {}; | 982 | return {}; |
| 983 | } | 983 | } |
| 984 | 984 | ||
| 985 | Id TextureGradient(Operation operation) { | ||
| 986 | UNIMPLEMENTED(); | ||
| 987 | return {}; | ||
| 988 | } | ||
| 989 | |||
| 985 | Id ImageLoad(Operation operation) { | 990 | Id ImageLoad(Operation operation) { |
| 986 | UNIMPLEMENTED(); | 991 | UNIMPLEMENTED(); |
| 987 | return {}; | 992 | return {}; |
| @@ -1474,6 +1479,7 @@ private: | |||
| 1474 | &SPIRVDecompiler::TextureQueryDimensions, | 1479 | &SPIRVDecompiler::TextureQueryDimensions, |
| 1475 | &SPIRVDecompiler::TextureQueryLod, | 1480 | &SPIRVDecompiler::TextureQueryLod, |
| 1476 | &SPIRVDecompiler::TexelFetch, | 1481 | &SPIRVDecompiler::TexelFetch, |
| 1482 | &SPIRVDecompiler::TextureGradient, | ||
| 1477 | 1483 | ||
| 1478 | &SPIRVDecompiler::ImageLoad, | 1484 | &SPIRVDecompiler::ImageLoad, |
| 1479 | &SPIRVDecompiler::ImageStore, | 1485 | &SPIRVDecompiler::ImageStore, |
diff --git a/src/video_core/shader/decode/texture.cpp b/src/video_core/shader/decode/texture.cpp index bb926a132..0e501919d 100644 --- a/src/video_core/shader/decode/texture.cpp +++ b/src/video_core/shader/decode/texture.cpp | |||
| @@ -134,13 +134,55 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) { | |||
| 134 | Node4 values; | 134 | Node4 values; |
| 135 | for (u32 element = 0; element < values.size(); ++element) { | 135 | for (u32 element = 0; element < values.size(); ++element) { |
| 136 | auto coords_copy = coords; | 136 | auto coords_copy = coords; |
| 137 | MetaTexture meta{sampler, {}, {}, {}, {}, {}, component, element}; | 137 | MetaTexture meta{sampler, {}, {}, {}, {}, {}, {}, component, element}; |
| 138 | values[element] = Operation(OperationCode::TextureGather, meta, std::move(coords_copy)); | 138 | values[element] = Operation(OperationCode::TextureGather, meta, std::move(coords_copy)); |
| 139 | } | 139 | } |
| 140 | 140 | ||
| 141 | WriteTexsInstructionFloat(bb, instr, values, true); | 141 | WriteTexsInstructionFloat(bb, instr, values, true); |
| 142 | break; | 142 | break; |
| 143 | } | 143 | } |
| 144 | case OpCode::Id::TXD_B: | ||
| 145 | is_bindless = true; | ||
| 146 | [[fallthrough]]; | ||
| 147 | case OpCode::Id::TXD: { | ||
| 148 | UNIMPLEMENTED_IF_MSG(instr.txd.UsesMiscMode(TextureMiscMode::AOFFI), | ||
| 149 | "AOFFI is not implemented"); | ||
| 150 | const auto is_array = static_cast<bool>(instr.txd.is_array != 0); | ||
| 151 | UNIMPLEMENTED_IF_MSG(is_array, "TXD Array is not implemented"); | ||
| 152 | |||
| 153 | u64 base_reg = instr.gpr8.Value(); | ||
| 154 | const auto derivate_reg = instr.gpr20.Value(); | ||
| 155 | const auto texture_type = instr.txd.texture_type.Value(); | ||
| 156 | const auto coord_count = GetCoordCount(texture_type); | ||
| 157 | |||
| 158 | const auto& sampler = is_bindless | ||
| 159 | ? GetBindlessSampler(base_reg, {{texture_type, false, false}}) | ||
| 160 | : GetSampler(instr.sampler, {{texture_type, false, false}}); | ||
| 161 | if (is_bindless) { | ||
| 162 | base_reg++; | ||
| 163 | } | ||
| 164 | |||
| 165 | std::vector<Node> coords; | ||
| 166 | std::vector<Node> derivates; | ||
| 167 | for (std::size_t i = 0; i < coord_count; ++i) { | ||
| 168 | coords.push_back(GetRegister(base_reg + i)); | ||
| 169 | const std::size_t derivate = i * 2; | ||
| 170 | derivates.push_back(GetRegister(derivate_reg + derivate)); | ||
| 171 | derivates.push_back(GetRegister(derivate_reg + derivate + 1)); | ||
| 172 | } | ||
| 173 | |||
| 174 | Node4 values; | ||
| 175 | for (u32 element = 0; element < values.size(); ++element) { | ||
| 176 | auto coords_copy = coords; | ||
| 177 | MetaTexture meta{sampler, {}, {}, {}, derivates, {}, {}, {}, element}; | ||
| 178 | values[element] = | ||
| 179 | Operation(OperationCode::TextureGradient, meta, std::move(coords_copy)); | ||
| 180 | } | ||
| 181 | |||
| 182 | WriteTexInstructionFloat(bb, instr, values); | ||
| 183 | |||
| 184 | break; | ||
| 185 | } | ||
| 144 | case OpCode::Id::TXQ_B: | 186 | case OpCode::Id::TXQ_B: |
| 145 | is_bindless = true; | 187 | is_bindless = true; |
| 146 | [[fallthrough]]; | 188 | [[fallthrough]]; |
| @@ -158,7 +200,7 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) { | |||
| 158 | if (!instr.txq.IsComponentEnabled(element)) { | 200 | if (!instr.txq.IsComponentEnabled(element)) { |
| 159 | continue; | 201 | continue; |
| 160 | } | 202 | } |
| 161 | MetaTexture meta{sampler, {}, {}, {}, {}, {}, {}, element}; | 203 | MetaTexture meta{sampler, {}, {}, {}, {}, {}, {}, {}, element}; |
| 162 | const Node value = | 204 | const Node value = |
| 163 | Operation(OperationCode::TextureQueryDimensions, meta, | 205 | Operation(OperationCode::TextureQueryDimensions, meta, |
| 164 | GetRegister(instr.gpr8.Value() + (is_bindless ? 1 : 0))); | 206 | GetRegister(instr.gpr8.Value() + (is_bindless ? 1 : 0))); |
| @@ -213,7 +255,7 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) { | |||
| 213 | continue; | 255 | continue; |
| 214 | } | 256 | } |
| 215 | auto params = coords; | 257 | auto params = coords; |
| 216 | MetaTexture meta{sampler, {}, {}, {}, {}, {}, {}, element}; | 258 | MetaTexture meta{sampler, {}, {}, {}, {}, {}, {}, {}, element}; |
| 217 | const Node value = Operation(OperationCode::TextureQueryLod, meta, std::move(params)); | 259 | const Node value = Operation(OperationCode::TextureQueryLod, meta, std::move(params)); |
| 218 | SetTemporary(bb, indexer++, value); | 260 | SetTemporary(bb, indexer++, value); |
| 219 | } | 261 | } |
| @@ -461,7 +503,7 @@ Node4 ShaderIR::GetTextureCode(Instruction instr, TextureType texture_type, | |||
| 461 | Node4 values; | 503 | Node4 values; |
| 462 | for (u32 element = 0; element < values.size(); ++element) { | 504 | for (u32 element = 0; element < values.size(); ++element) { |
| 463 | auto copy_coords = coords; | 505 | auto copy_coords = coords; |
| 464 | MetaTexture meta{sampler, array, depth_compare, aoffi, bias, lod, {}, element}; | 506 | MetaTexture meta{sampler, array, depth_compare, aoffi, {}, bias, lod, {}, element}; |
| 465 | values[element] = Operation(read_method, meta, std::move(copy_coords)); | 507 | values[element] = Operation(read_method, meta, std::move(copy_coords)); |
| 466 | } | 508 | } |
| 467 | 509 | ||
| @@ -594,7 +636,7 @@ Node4 ShaderIR::GetTld4Code(Instruction instr, TextureType texture_type, bool de | |||
| 594 | Node4 values; | 636 | Node4 values; |
| 595 | for (u32 element = 0; element < values.size(); ++element) { | 637 | for (u32 element = 0; element < values.size(); ++element) { |
| 596 | auto coords_copy = coords; | 638 | auto coords_copy = coords; |
| 597 | MetaTexture meta{sampler, GetRegister(array_register), dc, aoffi, {}, {}, component, | 639 | MetaTexture meta{sampler, GetRegister(array_register), dc, aoffi, {}, {}, {}, component, |
| 598 | element}; | 640 | element}; |
| 599 | values[element] = Operation(OperationCode::TextureGather, meta, std::move(coords_copy)); | 641 | values[element] = Operation(OperationCode::TextureGather, meta, std::move(coords_copy)); |
| 600 | } | 642 | } |
| @@ -628,7 +670,7 @@ Node4 ShaderIR::GetTldCode(Tegra::Shader::Instruction instr) { | |||
| 628 | Node4 values; | 670 | Node4 values; |
| 629 | for (u32 element = 0; element < values.size(); ++element) { | 671 | for (u32 element = 0; element < values.size(); ++element) { |
| 630 | auto coords_copy = coords; | 672 | auto coords_copy = coords; |
| 631 | MetaTexture meta{sampler, array_register, {}, {}, {}, lod, {}, element}; | 673 | MetaTexture meta{sampler, array_register, {}, {}, {}, {}, lod, {}, element}; |
| 632 | values[element] = Operation(OperationCode::TexelFetch, meta, std::move(coords_copy)); | 674 | values[element] = Operation(OperationCode::TexelFetch, meta, std::move(coords_copy)); |
| 633 | } | 675 | } |
| 634 | 676 | ||
| @@ -664,7 +706,7 @@ Node4 ShaderIR::GetTldsCode(Instruction instr, TextureType texture_type, bool is | |||
| 664 | Node4 values; | 706 | Node4 values; |
| 665 | for (u32 element = 0; element < values.size(); ++element) { | 707 | for (u32 element = 0; element < values.size(); ++element) { |
| 666 | auto coords_copy = coords; | 708 | auto coords_copy = coords; |
| 667 | MetaTexture meta{sampler, array, {}, {}, {}, lod, {}, element}; | 709 | MetaTexture meta{sampler, array, {}, {}, {}, {}, lod, {}, element}; |
| 668 | values[element] = Operation(OperationCode::TexelFetch, meta, std::move(coords_copy)); | 710 | values[element] = Operation(OperationCode::TexelFetch, meta, std::move(coords_copy)); |
| 669 | } | 711 | } |
| 670 | return values; | 712 | return values; |
diff --git a/src/video_core/shader/node.h b/src/video_core/shader/node.h index 2d11facaf..6c5046d3b 100644 --- a/src/video_core/shader/node.h +++ b/src/video_core/shader/node.h | |||
| @@ -151,6 +151,7 @@ enum class OperationCode { | |||
| 151 | TextureQueryDimensions, /// (MetaTexture, float a) -> float4 | 151 | TextureQueryDimensions, /// (MetaTexture, float a) -> float4 |
| 152 | TextureQueryLod, /// (MetaTexture, float[N] coords) -> float4 | 152 | TextureQueryLod, /// (MetaTexture, float[N] coords) -> float4 |
| 153 | TexelFetch, /// (MetaTexture, int[N], int) -> float4 | 153 | TexelFetch, /// (MetaTexture, int[N], int) -> float4 |
| 154 | TextureGradient, /// (MetaTexture, float[N] coords, float[N*2] derivates) -> float4 | ||
| 154 | 155 | ||
| 155 | ImageLoad, /// (MetaImage, int[N] coords) -> void | 156 | ImageLoad, /// (MetaImage, int[N] coords) -> void |
| 156 | ImageStore, /// (MetaImage, int[N] coords) -> void | 157 | ImageStore, /// (MetaImage, int[N] coords) -> void |
| @@ -363,6 +364,7 @@ struct MetaTexture { | |||
| 363 | Node array; | 364 | Node array; |
| 364 | Node depth_compare; | 365 | Node depth_compare; |
| 365 | std::vector<Node> aoffi; | 366 | std::vector<Node> aoffi; |
| 367 | std::vector<Node> derivates; | ||
| 366 | Node bias; | 368 | Node bias; |
| 367 | Node lod; | 369 | Node lod; |
| 368 | Node component{}; | 370 | Node component{}; |