diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/video_core/engines/shader_bytecode.h | 12 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_shader_decompiler.cpp | 84 | ||||
| -rw-r--r-- | src/video_core/shader/decode/texture.cpp | 74 | ||||
| -rw-r--r-- | src/video_core/shader/node.h | 1 | ||||
| -rw-r--r-- | src/video_core/shader/shader_ir.h | 5 |
5 files changed, 120 insertions, 56 deletions
diff --git a/src/video_core/engines/shader_bytecode.h b/src/video_core/engines/shader_bytecode.h index d6a2cc8b8..1cb0ac0c2 100644 --- a/src/video_core/engines/shader_bytecode.h +++ b/src/video_core/engines/shader_bytecode.h | |||
| @@ -1239,7 +1239,7 @@ union Instruction { | |||
| 1239 | BitField<35, 1, u64> ndv_flag; | 1239 | BitField<35, 1, u64> ndv_flag; |
| 1240 | BitField<49, 1, u64> nodep_flag; | 1240 | BitField<49, 1, u64> nodep_flag; |
| 1241 | BitField<50, 1, u64> dc_flag; | 1241 | BitField<50, 1, u64> dc_flag; |
| 1242 | BitField<54, 2, u64> info; | 1242 | BitField<54, 2, u64> offset_mode; |
| 1243 | BitField<56, 2, u64> component; | 1243 | BitField<56, 2, u64> component; |
| 1244 | 1244 | ||
| 1245 | bool UsesMiscMode(TextureMiscMode mode) const { | 1245 | bool UsesMiscMode(TextureMiscMode mode) const { |
| @@ -1251,9 +1251,9 @@ union Instruction { | |||
| 1251 | case TextureMiscMode::DC: | 1251 | case TextureMiscMode::DC: |
| 1252 | return dc_flag != 0; | 1252 | return dc_flag != 0; |
| 1253 | case TextureMiscMode::AOFFI: | 1253 | case TextureMiscMode::AOFFI: |
| 1254 | return info == 1; | 1254 | return offset_mode == 1; |
| 1255 | case TextureMiscMode::PTP: | 1255 | case TextureMiscMode::PTP: |
| 1256 | return info == 2; | 1256 | return offset_mode == 2; |
| 1257 | default: | 1257 | default: |
| 1258 | break; | 1258 | break; |
| 1259 | } | 1259 | } |
| @@ -1265,7 +1265,7 @@ union Instruction { | |||
| 1265 | BitField<35, 1, u64> ndv_flag; | 1265 | BitField<35, 1, u64> ndv_flag; |
| 1266 | BitField<49, 1, u64> nodep_flag; | 1266 | BitField<49, 1, u64> nodep_flag; |
| 1267 | BitField<50, 1, u64> dc_flag; | 1267 | BitField<50, 1, u64> dc_flag; |
| 1268 | BitField<33, 2, u64> info; | 1268 | BitField<33, 2, u64> offset_mode; |
| 1269 | BitField<37, 2, u64> component; | 1269 | BitField<37, 2, u64> component; |
| 1270 | 1270 | ||
| 1271 | bool UsesMiscMode(TextureMiscMode mode) const { | 1271 | bool UsesMiscMode(TextureMiscMode mode) const { |
| @@ -1277,9 +1277,9 @@ union Instruction { | |||
| 1277 | case TextureMiscMode::DC: | 1277 | case TextureMiscMode::DC: |
| 1278 | return dc_flag != 0; | 1278 | return dc_flag != 0; |
| 1279 | case TextureMiscMode::AOFFI: | 1279 | case TextureMiscMode::AOFFI: |
| 1280 | return info == 1; | 1280 | return offset_mode == 1; |
| 1281 | case TextureMiscMode::PTP: | 1281 | case TextureMiscMode::PTP: |
| 1282 | return info == 2; | 1282 | return offset_mode == 2; |
| 1283 | default: | 1283 | default: |
| 1284 | break; | 1284 | break; |
| 1285 | } | 1285 | } |
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp index 6b4b8ff67..83a6769ae 100644 --- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp +++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp | |||
| @@ -48,10 +48,10 @@ class ExprDecompiler; | |||
| 48 | 48 | ||
| 49 | enum class Type { Void, Bool, Bool2, Float, Int, Uint, HalfFloat }; | 49 | enum class Type { Void, Bool, Bool2, Float, Int, Uint, HalfFloat }; |
| 50 | 50 | ||
| 51 | struct TextureAoffi {}; | 51 | struct TextureOffset {}; |
| 52 | struct TextureDerivates {}; | 52 | struct TextureDerivates {}; |
| 53 | using TextureArgument = std::pair<Type, Node>; | 53 | using TextureArgument = std::pair<Type, Node>; |
| 54 | using TextureIR = std::variant<TextureAoffi, TextureDerivates, TextureArgument>; | 54 | using TextureIR = std::variant<TextureOffset, TextureDerivates, TextureArgument>; |
| 55 | 55 | ||
| 56 | constexpr u32 MAX_CONSTBUFFER_ELEMENTS = | 56 | constexpr u32 MAX_CONSTBUFFER_ELEMENTS = |
| 57 | static_cast<u32>(Maxwell::MaxConstBufferSize) / (4 * sizeof(float)); | 57 | static_cast<u32>(Maxwell::MaxConstBufferSize) / (4 * sizeof(float)); |
| @@ -1089,6 +1089,8 @@ private: | |||
| 1089 | std::string expr = "texture" + function_suffix; | 1089 | std::string expr = "texture" + function_suffix; |
| 1090 | if (!meta->aoffi.empty()) { | 1090 | if (!meta->aoffi.empty()) { |
| 1091 | expr += "Offset"; | 1091 | expr += "Offset"; |
| 1092 | } else if (!meta->ptp.empty()) { | ||
| 1093 | expr += "Offsets"; | ||
| 1092 | } | 1094 | } |
| 1093 | expr += '(' + GetSampler(meta->sampler) + ", "; | 1095 | expr += '(' + GetSampler(meta->sampler) + ", "; |
| 1094 | expr += coord_constructors.at(count + (has_array ? 1 : 0) + | 1096 | expr += coord_constructors.at(count + (has_array ? 1 : 0) + |
| @@ -1117,8 +1119,12 @@ private: | |||
| 1117 | for (const auto& variant : extras) { | 1119 | for (const auto& variant : extras) { |
| 1118 | if (const auto argument = std::get_if<TextureArgument>(&variant)) { | 1120 | if (const auto argument = std::get_if<TextureArgument>(&variant)) { |
| 1119 | expr += GenerateTextureArgument(*argument); | 1121 | expr += GenerateTextureArgument(*argument); |
| 1120 | } else if (std::holds_alternative<TextureAoffi>(variant)) { | 1122 | } else if (std::holds_alternative<TextureOffset>(variant)) { |
| 1121 | expr += GenerateTextureAoffi(meta->aoffi); | 1123 | if (!meta->aoffi.empty()) { |
| 1124 | expr += GenerateTextureAoffi(meta->aoffi); | ||
| 1125 | } else if (!meta->ptp.empty()) { | ||
| 1126 | expr += GenerateTexturePtp(meta->ptp); | ||
| 1127 | } | ||
| 1122 | } else if (std::holds_alternative<TextureDerivates>(variant)) { | 1128 | } else if (std::holds_alternative<TextureDerivates>(variant)) { |
| 1123 | expr += GenerateTextureDerivates(meta->derivates); | 1129 | expr += GenerateTextureDerivates(meta->derivates); |
| 1124 | } else { | 1130 | } else { |
| @@ -1159,6 +1165,20 @@ private: | |||
| 1159 | return expr; | 1165 | return expr; |
| 1160 | } | 1166 | } |
| 1161 | 1167 | ||
| 1168 | std::string ReadTextureOffset(const Node& value) { | ||
| 1169 | if (const auto immediate = std::get_if<ImmediateNode>(&*value)) { | ||
| 1170 | // Inline the string as an immediate integer in GLSL (AOFFI arguments are required | ||
| 1171 | // to be constant by the standard). | ||
| 1172 | return std::to_string(static_cast<s32>(immediate->GetValue())); | ||
| 1173 | } else if (device.HasVariableAoffi()) { | ||
| 1174 | // Avoid using variable AOFFI on unsupported devices. | ||
| 1175 | return Visit(value).AsInt(); | ||
| 1176 | } else { | ||
| 1177 | // Insert 0 on devices not supporting variable AOFFI. | ||
| 1178 | return "0"; | ||
| 1179 | } | ||
| 1180 | } | ||
| 1181 | |||
| 1162 | std::string GenerateTextureAoffi(const std::vector<Node>& aoffi) { | 1182 | std::string GenerateTextureAoffi(const std::vector<Node>& aoffi) { |
| 1163 | if (aoffi.empty()) { | 1183 | if (aoffi.empty()) { |
| 1164 | return {}; | 1184 | return {}; |
| @@ -1169,18 +1189,7 @@ private: | |||
| 1169 | expr += '('; | 1189 | expr += '('; |
| 1170 | 1190 | ||
| 1171 | for (std::size_t index = 0; index < aoffi.size(); ++index) { | 1191 | for (std::size_t index = 0; index < aoffi.size(); ++index) { |
| 1172 | const auto operand{aoffi.at(index)}; | 1192 | expr += ReadTextureOffset(aoffi.at(index)); |
| 1173 | if (const auto immediate = std::get_if<ImmediateNode>(&*operand)) { | ||
| 1174 | // Inline the string as an immediate integer in GLSL (AOFFI arguments are required | ||
| 1175 | // to be constant by the standard). | ||
| 1176 | expr += std::to_string(static_cast<s32>(immediate->GetValue())); | ||
| 1177 | } else if (device.HasVariableAoffi()) { | ||
| 1178 | // Avoid using variable AOFFI on unsupported devices. | ||
| 1179 | expr += Visit(operand).AsInt(); | ||
| 1180 | } else { | ||
| 1181 | // Insert 0 on devices not supporting variable AOFFI. | ||
| 1182 | expr += '0'; | ||
| 1183 | } | ||
| 1184 | if (index + 1 < aoffi.size()) { | 1193 | if (index + 1 < aoffi.size()) { |
| 1185 | expr += ", "; | 1194 | expr += ", "; |
| 1186 | } | 1195 | } |
| @@ -1190,6 +1199,20 @@ private: | |||
| 1190 | return expr; | 1199 | return expr; |
| 1191 | } | 1200 | } |
| 1192 | 1201 | ||
| 1202 | std::string GenerateTexturePtp(const std::vector<Node>& ptp) { | ||
| 1203 | static constexpr std::size_t num_vectors = 4; | ||
| 1204 | ASSERT(ptp.size() == num_vectors * 2); | ||
| 1205 | |||
| 1206 | std::string expr = ", ivec2[]("; | ||
| 1207 | for (std::size_t vector = 0; vector < num_vectors; ++vector) { | ||
| 1208 | const bool has_next = vector + 1 < num_vectors; | ||
| 1209 | expr += fmt::format("ivec2({}, {}){}", ReadTextureOffset(ptp.at(vector * 2)), | ||
| 1210 | ReadTextureOffset(ptp.at(vector * 2 + 1)), has_next ? ", " : ""); | ||
| 1211 | } | ||
| 1212 | expr += ')'; | ||
| 1213 | return expr; | ||
| 1214 | } | ||
| 1215 | |||
| 1193 | std::string GenerateTextureDerivates(const std::vector<Node>& derivates) { | 1216 | std::string GenerateTextureDerivates(const std::vector<Node>& derivates) { |
| 1194 | if (derivates.empty()) { | 1217 | if (derivates.empty()) { |
| 1195 | return {}; | 1218 | return {}; |
| @@ -1688,7 +1711,7 @@ private: | |||
| 1688 | ASSERT(meta); | 1711 | ASSERT(meta); |
| 1689 | 1712 | ||
| 1690 | std::string expr = GenerateTexture( | 1713 | std::string expr = GenerateTexture( |
| 1691 | operation, "", {TextureAoffi{}, TextureArgument{Type::Float, meta->bias}}); | 1714 | operation, "", {TextureOffset{}, TextureArgument{Type::Float, meta->bias}}); |
| 1692 | if (meta->sampler.IsShadow()) { | 1715 | if (meta->sampler.IsShadow()) { |
| 1693 | expr = "vec4(" + expr + ')'; | 1716 | expr = "vec4(" + expr + ')'; |
| 1694 | } | 1717 | } |
| @@ -1700,7 +1723,7 @@ private: | |||
| 1700 | ASSERT(meta); | 1723 | ASSERT(meta); |
| 1701 | 1724 | ||
| 1702 | std::string expr = GenerateTexture( | 1725 | std::string expr = GenerateTexture( |
| 1703 | operation, "Lod", {TextureArgument{Type::Float, meta->lod}, TextureAoffi{}}); | 1726 | operation, "Lod", {TextureArgument{Type::Float, meta->lod}, TextureOffset{}}); |
| 1704 | if (meta->sampler.IsShadow()) { | 1727 | if (meta->sampler.IsShadow()) { |
| 1705 | expr = "vec4(" + expr + ')'; | 1728 | expr = "vec4(" + expr + ')'; |
| 1706 | } | 1729 | } |
| @@ -1708,21 +1731,19 @@ private: | |||
| 1708 | } | 1731 | } |
| 1709 | 1732 | ||
| 1710 | Expression TextureGather(Operation operation) { | 1733 | Expression TextureGather(Operation operation) { |
| 1711 | const auto meta = std::get_if<MetaTexture>(&operation.GetMeta()); | 1734 | const auto& meta = std::get<MetaTexture>(operation.GetMeta()); |
| 1712 | ASSERT(meta); | ||
| 1713 | 1735 | ||
| 1714 | const auto type = meta->sampler.IsShadow() ? Type::Float : Type::Int; | 1736 | const auto type = meta.sampler.IsShadow() ? Type::Float : Type::Int; |
| 1715 | if (meta->sampler.IsShadow()) { | 1737 | const bool separate_dc = meta.sampler.IsShadow(); |
| 1716 | return {GenerateTexture(operation, "Gather", {TextureAoffi{}}, true) + | 1738 | |
| 1717 | GetSwizzle(meta->element), | 1739 | std::vector<TextureIR> ir; |
| 1718 | Type::Float}; | 1740 | if (meta.sampler.IsShadow()) { |
| 1741 | ir = {TextureOffset{}}; | ||
| 1719 | } else { | 1742 | } else { |
| 1720 | return {GenerateTexture(operation, "Gather", | 1743 | ir = {TextureOffset{}, TextureArgument{type, meta.component}}; |
| 1721 | {TextureAoffi{}, TextureArgument{type, meta->component}}, | ||
| 1722 | false) + | ||
| 1723 | GetSwizzle(meta->element), | ||
| 1724 | Type::Float}; | ||
| 1725 | } | 1744 | } |
| 1745 | return {GenerateTexture(operation, "Gather", ir, separate_dc) + GetSwizzle(meta.element), | ||
| 1746 | Type::Float}; | ||
| 1726 | } | 1747 | } |
| 1727 | 1748 | ||
| 1728 | Expression TextureQueryDimensions(Operation operation) { | 1749 | Expression TextureQueryDimensions(Operation operation) { |
| @@ -1793,7 +1814,8 @@ private: | |||
| 1793 | const auto meta = std::get_if<MetaTexture>(&operation.GetMeta()); | 1814 | const auto meta = std::get_if<MetaTexture>(&operation.GetMeta()); |
| 1794 | ASSERT(meta); | 1815 | ASSERT(meta); |
| 1795 | 1816 | ||
| 1796 | std::string expr = GenerateTexture(operation, "Grad", {TextureDerivates{}, TextureAoffi{}}); | 1817 | std::string expr = |
| 1818 | GenerateTexture(operation, "Grad", {TextureDerivates{}, TextureOffset{}}); | ||
| 1797 | return {std::move(expr) + GetSwizzle(meta->element), Type::Float}; | 1819 | return {std::move(expr) + GetSwizzle(meta->element), Type::Float}; |
| 1798 | } | 1820 | } |
| 1799 | 1821 | ||
diff --git a/src/video_core/shader/decode/texture.cpp b/src/video_core/shader/decode/texture.cpp index 6b6458993..dd8ff851e 100644 --- a/src/video_core/shader/decode/texture.cpp +++ b/src/video_core/shader/decode/texture.cpp | |||
| @@ -91,18 +91,17 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) { | |||
| 91 | case OpCode::Id::TLD4: { | 91 | case OpCode::Id::TLD4: { |
| 92 | UNIMPLEMENTED_IF_MSG(instr.tld4.UsesMiscMode(TextureMiscMode::NDV), | 92 | UNIMPLEMENTED_IF_MSG(instr.tld4.UsesMiscMode(TextureMiscMode::NDV), |
| 93 | "NDV is not implemented"); | 93 | "NDV is not implemented"); |
| 94 | UNIMPLEMENTED_IF_MSG(instr.tld4.UsesMiscMode(TextureMiscMode::PTP), | ||
| 95 | "PTP is not implemented"); | ||
| 96 | |||
| 97 | const auto texture_type = instr.tld4.texture_type.Value(); | 94 | const auto texture_type = instr.tld4.texture_type.Value(); |
| 98 | const bool depth_compare = is_bindless ? instr.tld4_b.UsesMiscMode(TextureMiscMode::DC) | 95 | const bool depth_compare = is_bindless ? instr.tld4_b.UsesMiscMode(TextureMiscMode::DC) |
| 99 | : instr.tld4.UsesMiscMode(TextureMiscMode::DC); | 96 | : instr.tld4.UsesMiscMode(TextureMiscMode::DC); |
| 100 | const bool is_array = instr.tld4.array != 0; | 97 | const bool is_array = instr.tld4.array != 0; |
| 101 | const bool is_aoffi = is_bindless ? instr.tld4_b.UsesMiscMode(TextureMiscMode::AOFFI) | 98 | const bool is_aoffi = is_bindless ? instr.tld4_b.UsesMiscMode(TextureMiscMode::AOFFI) |
| 102 | : instr.tld4.UsesMiscMode(TextureMiscMode::AOFFI); | 99 | : instr.tld4.UsesMiscMode(TextureMiscMode::AOFFI); |
| 103 | WriteTexInstructionFloat( | 100 | const bool is_ptp = is_bindless ? instr.tld4_b.UsesMiscMode(TextureMiscMode::PTP) |
| 104 | bb, instr, | 101 | : instr.tld4.UsesMiscMode(TextureMiscMode::PTP); |
| 105 | GetTld4Code(instr, texture_type, depth_compare, is_array, is_aoffi, is_bindless)); | 102 | WriteTexInstructionFloat(bb, instr, |
| 103 | GetTld4Code(instr, texture_type, depth_compare, is_array, is_aoffi, | ||
| 104 | is_ptp, is_bindless)); | ||
| 106 | break; | 105 | break; |
| 107 | } | 106 | } |
| 108 | case OpCode::Id::TLD4S: { | 107 | case OpCode::Id::TLD4S: { |
| @@ -145,7 +144,7 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) { | |||
| 145 | Node4 values; | 144 | Node4 values; |
| 146 | for (u32 element = 0; element < values.size(); ++element) { | 145 | for (u32 element = 0; element < values.size(); ++element) { |
| 147 | auto coords_copy = coords; | 146 | auto coords_copy = coords; |
| 148 | MetaTexture meta{sampler, {}, depth_compare, aoffi, {}, {}, {}, component, element}; | 147 | MetaTexture meta{sampler, {}, depth_compare, aoffi, {}, {}, {}, {}, component, element}; |
| 149 | values[element] = Operation(OperationCode::TextureGather, meta, std::move(coords_copy)); | 148 | values[element] = Operation(OperationCode::TextureGather, meta, std::move(coords_copy)); |
| 150 | } | 149 | } |
| 151 | 150 | ||
| @@ -194,7 +193,7 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) { | |||
| 194 | } | 193 | } |
| 195 | 194 | ||
| 196 | for (u32 element = 0; element < values.size(); ++element) { | 195 | for (u32 element = 0; element < values.size(); ++element) { |
| 197 | MetaTexture meta{*sampler, {}, {}, {}, derivates, {}, {}, {}, element}; | 196 | MetaTexture meta{*sampler, {}, {}, {}, {}, derivates, {}, {}, {}, element}; |
| 198 | values[element] = Operation(OperationCode::TextureGradient, std::move(meta), coords); | 197 | values[element] = Operation(OperationCode::TextureGradient, std::move(meta), coords); |
| 199 | } | 198 | } |
| 200 | 199 | ||
| @@ -234,7 +233,7 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) { | |||
| 234 | if (!instr.txq.IsComponentEnabled(element)) { | 233 | if (!instr.txq.IsComponentEnabled(element)) { |
| 235 | continue; | 234 | continue; |
| 236 | } | 235 | } |
| 237 | MetaTexture meta{*sampler, {}, {}, {}, {}, {}, {}, {}, element}; | 236 | MetaTexture meta{*sampler, {}, {}, {}, {}, {}, {}, {}, {}, element}; |
| 238 | const Node value = | 237 | const Node value = |
| 239 | Operation(OperationCode::TextureQueryDimensions, meta, | 238 | Operation(OperationCode::TextureQueryDimensions, meta, |
| 240 | GetRegister(instr.gpr8.Value() + (is_bindless ? 1 : 0))); | 239 | GetRegister(instr.gpr8.Value() + (is_bindless ? 1 : 0))); |
| @@ -303,7 +302,7 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) { | |||
| 303 | continue; | 302 | continue; |
| 304 | } | 303 | } |
| 305 | auto params = coords; | 304 | auto params = coords; |
| 306 | MetaTexture meta{*sampler, {}, {}, {}, {}, {}, {}, {}, element}; | 305 | MetaTexture meta{*sampler, {}, {}, {}, {}, {}, {}, {}, {}, element}; |
| 307 | const Node value = Operation(OperationCode::TextureQueryLod, meta, std::move(params)); | 306 | const Node value = Operation(OperationCode::TextureQueryLod, meta, std::move(params)); |
| 308 | SetTemporary(bb, indexer++, value); | 307 | SetTemporary(bb, indexer++, value); |
| 309 | } | 308 | } |
| @@ -542,7 +541,7 @@ Node4 ShaderIR::GetTextureCode(Instruction instr, TextureType texture_type, | |||
| 542 | 541 | ||
| 543 | for (u32 element = 0; element < values.size(); ++element) { | 542 | for (u32 element = 0; element < values.size(); ++element) { |
| 544 | auto copy_coords = coords; | 543 | auto copy_coords = coords; |
| 545 | MetaTexture meta{*sampler, array, depth_compare, aoffi, {}, bias, lod, {}, element}; | 544 | MetaTexture meta{*sampler, array, depth_compare, aoffi, {}, {}, bias, lod, {}, element}; |
| 546 | values[element] = Operation(read_method, meta, std::move(copy_coords)); | 545 | values[element] = Operation(read_method, meta, std::move(copy_coords)); |
| 547 | } | 546 | } |
| 548 | 547 | ||
| @@ -639,7 +638,9 @@ Node4 ShaderIR::GetTexsCode(Instruction instr, TextureType texture_type, | |||
| 639 | } | 638 | } |
| 640 | 639 | ||
| 641 | Node4 ShaderIR::GetTld4Code(Instruction instr, TextureType texture_type, bool depth_compare, | 640 | Node4 ShaderIR::GetTld4Code(Instruction instr, TextureType texture_type, bool depth_compare, |
| 642 | bool is_array, bool is_aoffi, bool is_bindless) { | 641 | bool is_array, bool is_aoffi, bool is_ptp, bool is_bindless) { |
| 642 | ASSERT_MSG(!(is_aoffi && is_ptp), "AOFFI and PTP can't be enabled at the same time"); | ||
| 643 | |||
| 643 | const std::size_t coord_count = GetCoordCount(texture_type); | 644 | const std::size_t coord_count = GetCoordCount(texture_type); |
| 644 | 645 | ||
| 645 | // If enabled arrays index is always stored in the gpr8 field | 646 | // If enabled arrays index is always stored in the gpr8 field |
| @@ -665,12 +666,15 @@ Node4 ShaderIR::GetTld4Code(Instruction instr, TextureType texture_type, bool de | |||
| 665 | return values; | 666 | return values; |
| 666 | } | 667 | } |
| 667 | 668 | ||
| 668 | std::vector<Node> aoffi; | 669 | std::vector<Node> aoffi, ptp; |
| 669 | if (is_aoffi) { | 670 | if (is_aoffi) { |
| 670 | aoffi = GetAoffiCoordinates(GetRegister(parameter_register++), coord_count, true); | 671 | aoffi = GetAoffiCoordinates(GetRegister(parameter_register++), coord_count, true); |
| 672 | } else if (is_ptp) { | ||
| 673 | ptp = GetPtpCoordinates( | ||
| 674 | {GetRegister(parameter_register++), GetRegister(parameter_register++)}); | ||
| 671 | } | 675 | } |
| 672 | 676 | ||
| 673 | Node dc{}; | 677 | Node dc; |
| 674 | if (depth_compare) { | 678 | if (depth_compare) { |
| 675 | dc = GetRegister(parameter_register++); | 679 | dc = GetRegister(parameter_register++); |
| 676 | } | 680 | } |
| @@ -680,8 +684,8 @@ Node4 ShaderIR::GetTld4Code(Instruction instr, TextureType texture_type, bool de | |||
| 680 | 684 | ||
| 681 | for (u32 element = 0; element < values.size(); ++element) { | 685 | for (u32 element = 0; element < values.size(); ++element) { |
| 682 | auto coords_copy = coords; | 686 | auto coords_copy = coords; |
| 683 | MetaTexture meta{*sampler, GetRegister(array_register), dc, aoffi, {}, {}, {}, component, | 687 | MetaTexture meta{ |
| 684 | element}; | 688 | *sampler, GetRegister(array_register), dc, aoffi, ptp, {}, {}, {}, component, element}; |
| 685 | values[element] = Operation(OperationCode::TextureGather, meta, std::move(coords_copy)); | 689 | values[element] = Operation(OperationCode::TextureGather, meta, std::move(coords_copy)); |
| 686 | } | 690 | } |
| 687 | 691 | ||
| @@ -714,7 +718,7 @@ Node4 ShaderIR::GetTldCode(Tegra::Shader::Instruction instr) { | |||
| 714 | Node4 values; | 718 | Node4 values; |
| 715 | for (u32 element = 0; element < values.size(); ++element) { | 719 | for (u32 element = 0; element < values.size(); ++element) { |
| 716 | auto coords_copy = coords; | 720 | auto coords_copy = coords; |
| 717 | MetaTexture meta{sampler, array_register, {}, {}, {}, {}, lod, {}, element}; | 721 | MetaTexture meta{sampler, array_register, {}, {}, {}, {}, {}, lod, {}, element}; |
| 718 | values[element] = Operation(OperationCode::TexelFetch, meta, std::move(coords_copy)); | 722 | values[element] = Operation(OperationCode::TexelFetch, meta, std::move(coords_copy)); |
| 719 | } | 723 | } |
| 720 | 724 | ||
| @@ -759,7 +763,7 @@ Node4 ShaderIR::GetTldsCode(Instruction instr, TextureType texture_type, bool is | |||
| 759 | Node4 values; | 763 | Node4 values; |
| 760 | for (u32 element = 0; element < values.size(); ++element) { | 764 | for (u32 element = 0; element < values.size(); ++element) { |
| 761 | auto coords_copy = coords; | 765 | auto coords_copy = coords; |
| 762 | MetaTexture meta{sampler, array, {}, {}, {}, {}, lod, {}, element}; | 766 | MetaTexture meta{sampler, array, {}, {}, {}, {}, {}, lod, {}, element}; |
| 763 | values[element] = Operation(OperationCode::TexelFetch, meta, std::move(coords_copy)); | 767 | values[element] = Operation(OperationCode::TexelFetch, meta, std::move(coords_copy)); |
| 764 | } | 768 | } |
| 765 | return values; | 769 | return values; |
| @@ -824,4 +828,38 @@ std::vector<Node> ShaderIR::GetAoffiCoordinates(Node aoffi_reg, std::size_t coor | |||
| 824 | return aoffi; | 828 | return aoffi; |
| 825 | } | 829 | } |
| 826 | 830 | ||
| 831 | std::vector<Node> ShaderIR::GetPtpCoordinates(std::array<Node, 2> ptp_regs) { | ||
| 832 | static constexpr u32 num_entries = 8; | ||
| 833 | |||
| 834 | std::vector<Node> ptp; | ||
| 835 | ptp.reserve(num_entries); | ||
| 836 | |||
| 837 | const auto global_size = static_cast<s64>(global_code.size()); | ||
| 838 | const std::optional low = TrackImmediate(ptp_regs[0], global_code, global_size); | ||
| 839 | const std::optional high = TrackImmediate(ptp_regs[1], global_code, global_size); | ||
| 840 | if (!low || !high) { | ||
| 841 | for (u32 entry = 0; entry < num_entries; ++entry) { | ||
| 842 | const u32 reg = entry / 4; | ||
| 843 | const u32 offset = entry % 4; | ||
| 844 | const Node value = BitfieldExtract(ptp_regs[reg], offset * 8, 6); | ||
| 845 | const Node condition = | ||
| 846 | Operation(OperationCode::LogicalIGreaterEqual, value, Immediate(32)); | ||
| 847 | const Node negative = Operation(OperationCode::IAdd, value, Immediate(-64)); | ||
| 848 | ptp.push_back(Operation(OperationCode::Select, condition, negative, value)); | ||
| 849 | } | ||
| 850 | return ptp; | ||
| 851 | } | ||
| 852 | |||
| 853 | const u64 immediate = (static_cast<u64>(*high) << 32) | static_cast<u64>(*low); | ||
| 854 | for (u32 entry = 0; entry < num_entries; ++entry) { | ||
| 855 | s32 value = (immediate >> (entry * 8)) & 0b111111; | ||
| 856 | if (value >= 32) { | ||
| 857 | value -= 64; | ||
| 858 | } | ||
| 859 | ptp.push_back(Immediate(value)); | ||
| 860 | } | ||
| 861 | |||
| 862 | return ptp; | ||
| 863 | } | ||
| 864 | |||
| 827 | } // namespace VideoCommon::Shader | 865 | } // namespace VideoCommon::Shader |
diff --git a/src/video_core/shader/node.h b/src/video_core/shader/node.h index abd40f582..4d2f4d6a8 100644 --- a/src/video_core/shader/node.h +++ b/src/video_core/shader/node.h | |||
| @@ -374,6 +374,7 @@ struct MetaTexture { | |||
| 374 | Node array; | 374 | Node array; |
| 375 | Node depth_compare; | 375 | Node depth_compare; |
| 376 | std::vector<Node> aoffi; | 376 | std::vector<Node> aoffi; |
| 377 | std::vector<Node> ptp; | ||
| 377 | std::vector<Node> derivates; | 378 | std::vector<Node> derivates; |
| 378 | Node bias; | 379 | Node bias; |
| 379 | Node lod; | 380 | Node lod; |
diff --git a/src/video_core/shader/shader_ir.h b/src/video_core/shader/shader_ir.h index 04ae5f822..baed06ccd 100644 --- a/src/video_core/shader/shader_ir.h +++ b/src/video_core/shader/shader_ir.h | |||
| @@ -350,7 +350,8 @@ private: | |||
| 350 | bool is_array); | 350 | bool is_array); |
| 351 | 351 | ||
| 352 | Node4 GetTld4Code(Tegra::Shader::Instruction instr, Tegra::Shader::TextureType texture_type, | 352 | Node4 GetTld4Code(Tegra::Shader::Instruction instr, Tegra::Shader::TextureType texture_type, |
| 353 | bool depth_compare, bool is_array, bool is_aoffi, bool is_bindless); | 353 | bool depth_compare, bool is_array, bool is_aoffi, bool is_ptp, |
| 354 | bool is_bindless); | ||
| 354 | 355 | ||
| 355 | Node4 GetTldCode(Tegra::Shader::Instruction instr); | 356 | Node4 GetTldCode(Tegra::Shader::Instruction instr); |
| 356 | 357 | ||
| @@ -363,6 +364,8 @@ private: | |||
| 363 | 364 | ||
| 364 | std::vector<Node> GetAoffiCoordinates(Node aoffi_reg, std::size_t coord_count, bool is_tld4); | 365 | std::vector<Node> GetAoffiCoordinates(Node aoffi_reg, std::size_t coord_count, bool is_tld4); |
| 365 | 366 | ||
| 367 | std::vector<Node> GetPtpCoordinates(std::array<Node, 2> ptp_regs); | ||
| 368 | |||
| 366 | Node4 GetTextureCode(Tegra::Shader::Instruction instr, Tegra::Shader::TextureType texture_type, | 369 | Node4 GetTextureCode(Tegra::Shader::Instruction instr, Tegra::Shader::TextureType texture_type, |
| 367 | Tegra::Shader::TextureProcessMode process_mode, std::vector<Node> coords, | 370 | Tegra::Shader::TextureProcessMode process_mode, std::vector<Node> coords, |
| 368 | Node array, Node depth_compare, u32 bias_offset, std::vector<Node> aoffi, | 371 | Node array, Node depth_compare, u32 bias_offset, std::vector<Node> aoffi, |