summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar bunnei2019-12-06 18:18:16 -0500
committerGravatar GitHub2019-12-06 18:18:16 -0500
commite36814d6d592167cbb9c5440cb7b1f9bbb33449c (patch)
treefb93c0eeaa46d1ee738f9373cbb1b858e79ca37a
parentMerge pull request #3196 from jmerdich/fix-ea-source-build (diff)
parentShader_IR: Address Feedback (diff)
downloadyuzu-e36814d6d592167cbb9c5440cb7b1f9bbb33449c.tar.gz
yuzu-e36814d6d592167cbb9c5440cb7b1f9bbb33449c.tar.xz
yuzu-e36814d6d592167cbb9c5440cb7b1f9bbb33449c.zip
Merge pull request #3109 from FernandoS27/new-instr
Implement FLO & TXD Instructions on GPU Shaders
-rw-r--r--src/video_core/engines/shader_bytecode.h44
-rw-r--r--src/video_core/renderer_opengl/gl_shader_decompiler.cpp51
-rw-r--r--src/video_core/renderer_vulkan/vk_shader_decompiler.cpp8
-rw-r--r--src/video_core/shader/decode/arithmetic_integer.cpp19
-rw-r--r--src/video_core/shader/decode/texture.cpp53
-rw-r--r--src/video_core/shader/node.h4
6 files changed, 171 insertions, 8 deletions
diff --git a/src/video_core/engines/shader_bytecode.h b/src/video_core/engines/shader_bytecode.h
index 9fafed4a2..9c7b9b370 100644
--- a/src/video_core/engines/shader_bytecode.h
+++ b/src/video_core/engines/shader_bytecode.h
@@ -800,6 +800,12 @@ union Instruction {
800 } popc; 800 } popc;
801 801
802 union { 802 union {
803 BitField<41, 1, u64> sh;
804 BitField<40, 1, u64> invert;
805 BitField<48, 1, u64> is_signed;
806 } flo;
807
808 union {
803 BitField<39, 3, u64> pred; 809 BitField<39, 3, u64> pred;
804 BitField<42, 1, u64> neg_pred; 810 BitField<42, 1, u64> neg_pred;
805 } sel; 811 } sel;
@@ -1440,6 +1446,26 @@ union Instruction {
1440 } tlds; 1446 } tlds;
1441 1447
1442 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 {
1443 BitField<24, 2, StoreCacheManagement> cache_management; 1469 BitField<24, 2, StoreCacheManagement> cache_management;
1444 BitField<33, 3, ImageType> image_type; 1470 BitField<33, 3, ImageType> image_type;
1445 BitField<49, 2, OutOfBoundsStore> out_of_bounds_store; 1471 BitField<49, 2, OutOfBoundsStore> out_of_bounds_store;
@@ -1632,6 +1658,8 @@ public:
1632 TLD4S, // Texture Load 4 with scalar / non - vec4 source / destinations 1658 TLD4S, // Texture Load 4 with scalar / non - vec4 source / destinations
1633 TMML_B, // Texture Mip Map Level 1659 TMML_B, // Texture Mip Map Level
1634 TMML, // Texture Mip Map Level 1660 TMML, // Texture Mip Map Level
1661 TXD, // Texture Gradient/Load with Derivates
1662 TXD_B, // Texture Gradient/Load with Derivates Bindless
1635 SUST, // Surface Store 1663 SUST, // Surface Store
1636 SULD, // Surface Load 1664 SULD, // Surface Load
1637 SUATOM, // Surface Atomic Operation 1665 SUATOM, // Surface Atomic Operation
@@ -1664,6 +1692,9 @@ public:
1664 ISCADD_C, // Scale and Add 1692 ISCADD_C, // Scale and Add
1665 ISCADD_R, 1693 ISCADD_R,
1666 ISCADD_IMM, 1694 ISCADD_IMM,
1695 FLO_R,
1696 FLO_C,
1697 FLO_IMM,
1667 LEA_R1, 1698 LEA_R1,
1668 LEA_R2, 1699 LEA_R2,
1669 LEA_RZ, 1700 LEA_RZ,
@@ -1727,6 +1758,10 @@ public:
1727 SHR_C, 1758 SHR_C,
1728 SHR_R, 1759 SHR_R,
1729 SHR_IMM, 1760 SHR_IMM,
1761 SHF_RIGHT_R,
1762 SHF_RIGHT_IMM,
1763 SHF_LEFT_R,
1764 SHF_LEFT_IMM,
1730 FMNMX_C, 1765 FMNMX_C,
1731 FMNMX_R, 1766 FMNMX_R,
1732 FMNMX_IMM, 1767 FMNMX_IMM,
@@ -1924,6 +1959,8 @@ private:
1924 INST("1101111100------", Id::TLD4S, Type::Texture, "TLD4S"), 1959 INST("1101111100------", Id::TLD4S, Type::Texture, "TLD4S"),
1925 INST("110111110110----", Id::TMML_B, Type::Texture, "TMML_B"), 1960 INST("110111110110----", Id::TMML_B, Type::Texture, "TMML_B"),
1926 INST("1101111101011---", Id::TMML, Type::Texture, "TMML"), 1961 INST("1101111101011---", Id::TMML, Type::Texture, "TMML"),
1962 INST("11011110011110--", Id::TXD_B, Type::Texture, "TXD_B"),
1963 INST("11011110001110--", Id::TXD, Type::Texture, "TXD"),
1927 INST("11101011001-----", Id::SUST, Type::Image, "SUST"), 1964 INST("11101011001-----", Id::SUST, Type::Image, "SUST"),
1928 INST("11101011000-----", Id::SULD, Type::Image, "SULD"), 1965 INST("11101011000-----", Id::SULD, Type::Image, "SULD"),
1929 INST("1110101000------", Id::SUATOM, Type::Image, "SUATOM_D"), 1966 INST("1110101000------", Id::SUATOM, Type::Image, "SUATOM_D"),
@@ -1965,6 +2002,9 @@ private:
1965 INST("010110110100----", Id::ICMP_R, Type::ArithmeticInteger, "ICMP_R"), 2002 INST("010110110100----", Id::ICMP_R, Type::ArithmeticInteger, "ICMP_R"),
1966 INST("010010110100----", Id::ICMP_CR, Type::ArithmeticInteger, "ICMP_CR"), 2003 INST("010010110100----", Id::ICMP_CR, Type::ArithmeticInteger, "ICMP_CR"),
1967 INST("0011011-0100----", Id::ICMP_IMM, Type::ArithmeticInteger, "ICMP_IMM"), 2004 INST("0011011-0100----", Id::ICMP_IMM, Type::ArithmeticInteger, "ICMP_IMM"),
2005 INST("010111000011‬0---", Id::FLO_R, Type::ArithmeticInteger, "FLO_R"),
2006 INST("0100110000110---", Id::FLO_C, Type::ArithmeticInteger, "FLO_C"),
2007 INST("0011100-00110---", Id::FLO_IMM, Type::ArithmeticInteger, "FLO_IMM"),
1968 INST("0101101111011---", Id::LEA_R2, Type::ArithmeticInteger, "LEA_R2"), 2008 INST("0101101111011---", Id::LEA_R2, Type::ArithmeticInteger, "LEA_R2"),
1969 INST("0101101111010---", Id::LEA_R1, Type::ArithmeticInteger, "LEA_R1"), 2009 INST("0101101111010---", Id::LEA_R1, Type::ArithmeticInteger, "LEA_R1"),
1970 INST("001101101101----", Id::LEA_IMM, Type::ArithmeticInteger, "LEA_IMM"), 2010 INST("001101101101----", Id::LEA_IMM, Type::ArithmeticInteger, "LEA_IMM"),
@@ -2022,6 +2062,10 @@ private:
2022 INST("0100110000101---", Id::SHR_C, Type::Shift, "SHR_C"), 2062 INST("0100110000101---", Id::SHR_C, Type::Shift, "SHR_C"),
2023 INST("0101110000101---", Id::SHR_R, Type::Shift, "SHR_R"), 2063 INST("0101110000101---", Id::SHR_R, Type::Shift, "SHR_R"),
2024 INST("0011100-00101---", Id::SHR_IMM, Type::Shift, "SHR_IMM"), 2064 INST("0011100-00101---", Id::SHR_IMM, Type::Shift, "SHR_IMM"),
2065 INST("0101110011111---", Id::SHF_RIGHT_R, Type::Shift, "SHF_RIGHT_R"),
2066 INST("0011100-11111---", Id::SHF_RIGHT_IMM, Type::Shift, "SHF_RIGHT_IMM"),
2067 INST("0101101111111---", Id::SHF_LEFT_R, Type::Shift, "SHF_LEFT_R"),
2068 INST("0011011-11111---", Id::SHF_LEFT_IMM, Type::Shift, "SHF_LEFT_IMM"),
2025 INST("0100110011100---", Id::I2I_C, Type::Conversion, "I2I_C"), 2069 INST("0100110011100---", Id::I2I_C, Type::Conversion, "I2I_C"),
2026 INST("0101110011100---", Id::I2I_R, Type::Conversion, "I2I_R"), 2070 INST("0101110011100---", Id::I2I_R, Type::Conversion, "I2I_R"),
2027 INST("0011101-11100---", Id::I2I_IMM, Type::Conversion, "I2I_IMM"), 2071 INST("0011101-11100---", Id::I2I_IMM, Type::Conversion, "I2I_IMM"),
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
index 0e644564a..3d3cd21f3 100644
--- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
@@ -49,8 +49,9 @@ class ExprDecompiler;
49enum class Type { Void, Bool, Bool2, Float, Int, Uint, HalfFloat }; 49enum class Type { Void, Bool, Bool2, Float, Int, Uint, HalfFloat };
50 50
51struct TextureAoffi {}; 51struct TextureAoffi {};
52struct TextureDerivates {};
52using TextureArgument = std::pair<Type, Node>; 53using TextureArgument = std::pair<Type, Node>;
53using TextureIR = std::variant<TextureAoffi, TextureArgument>; 54using TextureIR = std::variant<TextureAoffi, TextureDerivates, TextureArgument>;
54 55
55constexpr u32 MAX_CONSTBUFFER_ELEMENTS = 56constexpr u32 MAX_CONSTBUFFER_ELEMENTS =
56 static_cast<u32>(Maxwell::MaxConstBufferSize) / (4 * sizeof(float)); 57 static_cast<u32>(Maxwell::MaxConstBufferSize) / (4 * sizeof(float));
@@ -1112,6 +1113,8 @@ private:
1112 expr += GenerateTextureArgument(*argument); 1113 expr += GenerateTextureArgument(*argument);
1113 } else if (std::holds_alternative<TextureAoffi>(variant)) { 1114 } else if (std::holds_alternative<TextureAoffi>(variant)) {
1114 expr += GenerateTextureAoffi(meta->aoffi); 1115 expr += GenerateTextureAoffi(meta->aoffi);
1116 } else if (std::holds_alternative<TextureDerivates>(variant)) {
1117 expr += GenerateTextureDerivates(meta->derivates);
1115 } else { 1118 } else {
1116 UNREACHABLE(); 1119 UNREACHABLE();
1117 } 1120 }
@@ -1181,6 +1184,36 @@ private:
1181 return expr; 1184 return expr;
1182 } 1185 }
1183 1186
1187 std::string GenerateTextureDerivates(const std::vector<Node>& derivates) {
1188 if (derivates.empty()) {
1189 return {};
1190 }
1191 constexpr std::array coord_constructors = {"float", "vec2", "vec3"};
1192 std::string expr = ", ";
1193 const std::size_t components = derivates.size() / 2;
1194 std::string dx = coord_constructors.at(components - 1);
1195 std::string dy = coord_constructors.at(components - 1);
1196 dx += '(';
1197 dy += '(';
1198
1199 for (std::size_t index = 0; index < components; ++index) {
1200 const auto operand_x{derivates.at(index * 2)};
1201 const auto operand_y{derivates.at(index * 2 + 1)};
1202 dx += Visit(operand_x).AsFloat();
1203 dy += Visit(operand_y).AsFloat();
1204
1205 if (index + 1 < components) {
1206 dx += ", ";
1207 dy += ", ";
1208 }
1209 }
1210 dx += ')';
1211 dy += ')';
1212 expr += dx + ", " + dy;
1213
1214 return expr;
1215 }
1216
1184 std::string BuildIntegerCoordinates(Operation operation) { 1217 std::string BuildIntegerCoordinates(Operation operation) {
1185 constexpr std::array constructors{"int(", "ivec2(", "ivec3(", "ivec4("}; 1218 constexpr std::array constructors{"int(", "ivec2(", "ivec3(", "ivec4("};
1186 const std::size_t coords_count{operation.GetOperandsCount()}; 1219 const std::size_t coords_count{operation.GetOperandsCount()};
@@ -1450,6 +1483,11 @@ private:
1450 return GenerateUnary(operation, "bitCount", type, type); 1483 return GenerateUnary(operation, "bitCount", type, type);
1451 } 1484 }
1452 1485
1486 template <Type type>
1487 Expression BitMSB(Operation operation) {
1488 return GenerateUnary(operation, "findMSB", type, type);
1489 }
1490
1453 Expression HNegate(Operation operation) { 1491 Expression HNegate(Operation operation) {
1454 const auto GetNegate = [&](std::size_t index) { 1492 const auto GetNegate = [&](std::size_t index) {
1455 return VisitOperand(operation, index).AsBool() + " ? -1 : 1"; 1493 return VisitOperand(operation, index).AsBool() + " ? -1 : 1";
@@ -1738,6 +1776,14 @@ private:
1738 return {std::move(expr), Type::Float}; 1776 return {std::move(expr), Type::Float};
1739 } 1777 }
1740 1778
1779 Expression TextureGradient(Operation operation) {
1780 const auto meta = std::get_if<MetaTexture>(&operation.GetMeta());
1781 ASSERT(meta);
1782
1783 std::string expr = GenerateTexture(operation, "Grad", {TextureDerivates{}, TextureAoffi{}});
1784 return {std::move(expr) + GetSwizzle(meta->element), Type::Float};
1785 }
1786
1741 Expression ImageLoad(Operation operation) { 1787 Expression ImageLoad(Operation operation) {
1742 if (!device.HasImageLoadFormatted()) { 1788 if (!device.HasImageLoadFormatted()) {
1743 LOG_ERROR(Render_OpenGL, 1789 LOG_ERROR(Render_OpenGL,
@@ -2003,6 +2049,7 @@ private:
2003 &GLSLDecompiler::BitfieldInsert<Type::Int>, 2049 &GLSLDecompiler::BitfieldInsert<Type::Int>,
2004 &GLSLDecompiler::BitfieldExtract<Type::Int>, 2050 &GLSLDecompiler::BitfieldExtract<Type::Int>,
2005 &GLSLDecompiler::BitCount<Type::Int>, 2051 &GLSLDecompiler::BitCount<Type::Int>,
2052 &GLSLDecompiler::BitMSB<Type::Int>,
2006 2053
2007 &GLSLDecompiler::Add<Type::Uint>, 2054 &GLSLDecompiler::Add<Type::Uint>,
2008 &GLSLDecompiler::Mul<Type::Uint>, 2055 &GLSLDecompiler::Mul<Type::Uint>,
@@ -2021,6 +2068,7 @@ private:
2021 &GLSLDecompiler::BitfieldInsert<Type::Uint>, 2068 &GLSLDecompiler::BitfieldInsert<Type::Uint>,
2022 &GLSLDecompiler::BitfieldExtract<Type::Uint>, 2069 &GLSLDecompiler::BitfieldExtract<Type::Uint>,
2023 &GLSLDecompiler::BitCount<Type::Uint>, 2070 &GLSLDecompiler::BitCount<Type::Uint>,
2071 &GLSLDecompiler::BitMSB<Type::Uint>,
2024 2072
2025 &GLSLDecompiler::Add<Type::HalfFloat>, 2073 &GLSLDecompiler::Add<Type::HalfFloat>,
2026 &GLSLDecompiler::Mul<Type::HalfFloat>, 2074 &GLSLDecompiler::Mul<Type::HalfFloat>,
@@ -2084,6 +2132,7 @@ private:
2084 &GLSLDecompiler::TextureQueryDimensions, 2132 &GLSLDecompiler::TextureQueryDimensions,
2085 &GLSLDecompiler::TextureQueryLod, 2133 &GLSLDecompiler::TextureQueryLod,
2086 &GLSLDecompiler::TexelFetch, 2134 &GLSLDecompiler::TexelFetch,
2135 &GLSLDecompiler::TextureGradient,
2087 2136
2088 &GLSLDecompiler::ImageLoad, 2137 &GLSLDecompiler::ImageLoad,
2089 &GLSLDecompiler::ImageStore, 2138 &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 80738d3d0..76894275b 100644
--- a/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp
+++ b/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp
@@ -983,6 +983,11 @@ private:
983 return {}; 983 return {};
984 } 984 }
985 985
986 Id TextureGradient(Operation operation) {
987 UNIMPLEMENTED();
988 return {};
989 }
990
986 Id ImageLoad(Operation operation) { 991 Id ImageLoad(Operation operation) {
987 UNIMPLEMENTED(); 992 UNIMPLEMENTED();
988 return {}; 993 return {};
@@ -1391,6 +1396,7 @@ private:
1391 &SPIRVDecompiler::Quaternary<&Module::OpBitFieldInsert, Type::Int>, 1396 &SPIRVDecompiler::Quaternary<&Module::OpBitFieldInsert, Type::Int>,
1392 &SPIRVDecompiler::Ternary<&Module::OpBitFieldSExtract, Type::Int>, 1397 &SPIRVDecompiler::Ternary<&Module::OpBitFieldSExtract, Type::Int>,
1393 &SPIRVDecompiler::Unary<&Module::OpBitCount, Type::Int>, 1398 &SPIRVDecompiler::Unary<&Module::OpBitCount, Type::Int>,
1399 &SPIRVDecompiler::Unary<&Module::OpFindSMsb, Type::Int>,
1394 1400
1395 &SPIRVDecompiler::Binary<&Module::OpIAdd, Type::Uint>, 1401 &SPIRVDecompiler::Binary<&Module::OpIAdd, Type::Uint>,
1396 &SPIRVDecompiler::Binary<&Module::OpIMul, Type::Uint>, 1402 &SPIRVDecompiler::Binary<&Module::OpIMul, Type::Uint>,
@@ -1409,6 +1415,7 @@ private:
1409 &SPIRVDecompiler::Quaternary<&Module::OpBitFieldInsert, Type::Uint>, 1415 &SPIRVDecompiler::Quaternary<&Module::OpBitFieldInsert, Type::Uint>,
1410 &SPIRVDecompiler::Ternary<&Module::OpBitFieldUExtract, Type::Uint>, 1416 &SPIRVDecompiler::Ternary<&Module::OpBitFieldUExtract, Type::Uint>,
1411 &SPIRVDecompiler::Unary<&Module::OpBitCount, Type::Uint>, 1417 &SPIRVDecompiler::Unary<&Module::OpBitCount, Type::Uint>,
1418 &SPIRVDecompiler::Unary<&Module::OpFindUMsb, Type::Uint>,
1412 1419
1413 &SPIRVDecompiler::Binary<&Module::OpFAdd, Type::HalfFloat>, 1420 &SPIRVDecompiler::Binary<&Module::OpFAdd, Type::HalfFloat>,
1414 &SPIRVDecompiler::Binary<&Module::OpFMul, Type::HalfFloat>, 1421 &SPIRVDecompiler::Binary<&Module::OpFMul, Type::HalfFloat>,
@@ -1473,6 +1480,7 @@ private:
1473 &SPIRVDecompiler::TextureQueryDimensions, 1480 &SPIRVDecompiler::TextureQueryDimensions,
1474 &SPIRVDecompiler::TextureQueryLod, 1481 &SPIRVDecompiler::TextureQueryLod,
1475 &SPIRVDecompiler::TexelFetch, 1482 &SPIRVDecompiler::TexelFetch,
1483 &SPIRVDecompiler::TextureGradient,
1476 1484
1477 &SPIRVDecompiler::ImageLoad, 1485 &SPIRVDecompiler::ImageLoad,
1478 &SPIRVDecompiler::ImageStore, 1486 &SPIRVDecompiler::ImageStore,
diff --git a/src/video_core/shader/decode/arithmetic_integer.cpp b/src/video_core/shader/decode/arithmetic_integer.cpp
index a33d242e9..371fae127 100644
--- a/src/video_core/shader/decode/arithmetic_integer.cpp
+++ b/src/video_core/shader/decode/arithmetic_integer.cpp
@@ -130,6 +130,25 @@ u32 ShaderIR::DecodeArithmeticInteger(NodeBlock& bb, u32 pc) {
130 SetRegister(bb, instr.gpr0, value); 130 SetRegister(bb, instr.gpr0, value);
131 break; 131 break;
132 } 132 }
133 case OpCode::Id::FLO_R:
134 case OpCode::Id::FLO_C:
135 case OpCode::Id::FLO_IMM: {
136 Node value;
137 if (instr.flo.invert) {
138 op_b = Operation(OperationCode::IBitwiseNot, NO_PRECISE, std::move(op_b));
139 }
140 if (instr.flo.is_signed) {
141 value = Operation(OperationCode::IBitMSB, NO_PRECISE, std::move(op_b));
142 } else {
143 value = Operation(OperationCode::UBitMSB, NO_PRECISE, std::move(op_b));
144 }
145 if (instr.flo.sh) {
146 value =
147 Operation(OperationCode::UBitwiseXor, NO_PRECISE, std::move(value), Immediate(31));
148 }
149 SetRegister(bb, instr.gpr0, std::move(value));
150 break;
151 }
133 case OpCode::Id::SEL_C: 152 case OpCode::Id::SEL_C:
134 case OpCode::Id::SEL_R: 153 case OpCode::Id::SEL_R:
135 case OpCode::Id::SEL_IMM: { 154 case OpCode::Id::SEL_IMM: {
diff --git a/src/video_core/shader/decode/texture.cpp b/src/video_core/shader/decode/texture.cpp
index b094e5a06..da8e886df 100644
--- a/src/video_core/shader/decode/texture.cpp
+++ b/src/video_core/shader/decode/texture.cpp
@@ -134,13 +134,52 @@ 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 UNIMPLEMENTED_IF_MSG(instr.txd.is_array != 0, "TXD Array is not implemented");
151
152 u64 base_reg = instr.gpr8.Value();
153 const auto derivate_reg = instr.gpr20.Value();
154 const auto texture_type = instr.txd.texture_type.Value();
155 const auto coord_count = GetCoordCount(texture_type);
156
157 const auto& sampler = is_bindless
158 ? GetBindlessSampler(base_reg, {{texture_type, false, false}})
159 : GetSampler(instr.sampler, {{texture_type, false, false}});
160 if (is_bindless) {
161 base_reg++;
162 }
163
164 std::vector<Node> coords;
165 std::vector<Node> derivates;
166 for (std::size_t i = 0; i < coord_count; ++i) {
167 coords.push_back(GetRegister(base_reg + i));
168 const std::size_t derivate = i * 2;
169 derivates.push_back(GetRegister(derivate_reg + derivate));
170 derivates.push_back(GetRegister(derivate_reg + derivate + 1));
171 }
172
173 Node4 values;
174 for (u32 element = 0; element < values.size(); ++element) {
175 MetaTexture meta{sampler, {}, {}, {}, derivates, {}, {}, {}, element};
176 values[element] = Operation(OperationCode::TextureGradient, std::move(meta), coords);
177 }
178
179 WriteTexInstructionFloat(bb, instr, values);
180
181 break;
182 }
144 case OpCode::Id::TXQ_B: 183 case OpCode::Id::TXQ_B:
145 is_bindless = true; 184 is_bindless = true;
146 [[fallthrough]]; 185 [[fallthrough]];
@@ -158,7 +197,7 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) {
158 if (!instr.txq.IsComponentEnabled(element)) { 197 if (!instr.txq.IsComponentEnabled(element)) {
159 continue; 198 continue;
160 } 199 }
161 MetaTexture meta{sampler, {}, {}, {}, {}, {}, {}, element}; 200 MetaTexture meta{sampler, {}, {}, {}, {}, {}, {}, {}, element};
162 const Node value = 201 const Node value =
163 Operation(OperationCode::TextureQueryDimensions, meta, 202 Operation(OperationCode::TextureQueryDimensions, meta,
164 GetRegister(instr.gpr8.Value() + (is_bindless ? 1 : 0))); 203 GetRegister(instr.gpr8.Value() + (is_bindless ? 1 : 0)));
@@ -212,7 +251,7 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) {
212 continue; 251 continue;
213 } 252 }
214 auto params = coords; 253 auto params = coords;
215 MetaTexture meta{sampler, {}, {}, {}, {}, {}, {}, element}; 254 MetaTexture meta{sampler, {}, {}, {}, {}, {}, {}, {}, element};
216 const Node value = Operation(OperationCode::TextureQueryLod, meta, std::move(params)); 255 const Node value = Operation(OperationCode::TextureQueryLod, meta, std::move(params));
217 SetTemporary(bb, indexer++, value); 256 SetTemporary(bb, indexer++, value);
218 } 257 }
@@ -442,7 +481,7 @@ Node4 ShaderIR::GetTextureCode(Instruction instr, TextureType texture_type,
442 Node4 values; 481 Node4 values;
443 for (u32 element = 0; element < values.size(); ++element) { 482 for (u32 element = 0; element < values.size(); ++element) {
444 auto copy_coords = coords; 483 auto copy_coords = coords;
445 MetaTexture meta{sampler, array, depth_compare, aoffi, bias, lod, {}, element}; 484 MetaTexture meta{sampler, array, depth_compare, aoffi, {}, bias, lod, {}, element};
446 values[element] = Operation(read_method, meta, std::move(copy_coords)); 485 values[element] = Operation(read_method, meta, std::move(copy_coords));
447 } 486 }
448 487
@@ -574,7 +613,7 @@ Node4 ShaderIR::GetTld4Code(Instruction instr, TextureType texture_type, bool de
574 Node4 values; 613 Node4 values;
575 for (u32 element = 0; element < values.size(); ++element) { 614 for (u32 element = 0; element < values.size(); ++element) {
576 auto coords_copy = coords; 615 auto coords_copy = coords;
577 MetaTexture meta{sampler, GetRegister(array_register), dc, aoffi, {}, {}, component, 616 MetaTexture meta{sampler, GetRegister(array_register), dc, aoffi, {}, {}, {}, component,
578 element}; 617 element};
579 values[element] = Operation(OperationCode::TextureGather, meta, std::move(coords_copy)); 618 values[element] = Operation(OperationCode::TextureGather, meta, std::move(coords_copy));
580 } 619 }
@@ -608,7 +647,7 @@ Node4 ShaderIR::GetTldCode(Tegra::Shader::Instruction instr) {
608 Node4 values; 647 Node4 values;
609 for (u32 element = 0; element < values.size(); ++element) { 648 for (u32 element = 0; element < values.size(); ++element) {
610 auto coords_copy = coords; 649 auto coords_copy = coords;
611 MetaTexture meta{sampler, array_register, {}, {}, {}, lod, {}, element}; 650 MetaTexture meta{sampler, array_register, {}, {}, {}, {}, lod, {}, element};
612 values[element] = Operation(OperationCode::TexelFetch, meta, std::move(coords_copy)); 651 values[element] = Operation(OperationCode::TexelFetch, meta, std::move(coords_copy));
613 } 652 }
614 653
@@ -653,7 +692,7 @@ Node4 ShaderIR::GetTldsCode(Instruction instr, TextureType texture_type, bool is
653 Node4 values; 692 Node4 values;
654 for (u32 element = 0; element < values.size(); ++element) { 693 for (u32 element = 0; element < values.size(); ++element) {
655 auto coords_copy = coords; 694 auto coords_copy = coords;
656 MetaTexture meta{sampler, array, {}, {}, {}, lod, {}, element}; 695 MetaTexture meta{sampler, array, {}, {}, {}, {}, lod, {}, element};
657 values[element] = Operation(OperationCode::TexelFetch, meta, std::move(coords_copy)); 696 values[element] = Operation(OperationCode::TexelFetch, meta, std::move(coords_copy));
658 } 697 }
659 return values; 698 return values;
diff --git a/src/video_core/shader/node.h b/src/video_core/shader/node.h
index 44d85d434..b2576bdd6 100644
--- a/src/video_core/shader/node.h
+++ b/src/video_core/shader/node.h
@@ -68,6 +68,7 @@ enum class OperationCode {
68 IBitfieldInsert, /// (MetaArithmetic, int base, int insert, int offset, int bits) -> int 68 IBitfieldInsert, /// (MetaArithmetic, int base, int insert, int offset, int bits) -> int
69 IBitfieldExtract, /// (MetaArithmetic, int value, int offset, int offset) -> int 69 IBitfieldExtract, /// (MetaArithmetic, int value, int offset, int offset) -> int
70 IBitCount, /// (MetaArithmetic, int) -> int 70 IBitCount, /// (MetaArithmetic, int) -> int
71 IBitMSB, /// (MetaArithmetic, int) -> int
71 72
72 UAdd, /// (MetaArithmetic, uint a, uint b) -> uint 73 UAdd, /// (MetaArithmetic, uint a, uint b) -> uint
73 UMul, /// (MetaArithmetic, uint a, uint b) -> uint 74 UMul, /// (MetaArithmetic, uint a, uint b) -> uint
@@ -86,6 +87,7 @@ enum class OperationCode {
86 UBitfieldInsert, /// (MetaArithmetic, uint base, uint insert, int offset, int bits) -> uint 87 UBitfieldInsert, /// (MetaArithmetic, uint base, uint insert, int offset, int bits) -> uint
87 UBitfieldExtract, /// (MetaArithmetic, uint value, int offset, int offset) -> uint 88 UBitfieldExtract, /// (MetaArithmetic, uint value, int offset, int offset) -> uint
88 UBitCount, /// (MetaArithmetic, uint) -> uint 89 UBitCount, /// (MetaArithmetic, uint) -> uint
90 UBitMSB, /// (MetaArithmetic, uint) -> uint
89 91
90 HAdd, /// (MetaArithmetic, f16vec2 a, f16vec2 b) -> f16vec2 92 HAdd, /// (MetaArithmetic, f16vec2 a, f16vec2 b) -> f16vec2
91 HMul, /// (MetaArithmetic, f16vec2 a, f16vec2 b) -> f16vec2 93 HMul, /// (MetaArithmetic, f16vec2 a, f16vec2 b) -> f16vec2
@@ -149,6 +151,7 @@ enum class OperationCode {
149 TextureQueryDimensions, /// (MetaTexture, float a) -> float4 151 TextureQueryDimensions, /// (MetaTexture, float a) -> float4
150 TextureQueryLod, /// (MetaTexture, float[N] coords) -> float4 152 TextureQueryLod, /// (MetaTexture, float[N] coords) -> float4
151 TexelFetch, /// (MetaTexture, int[N], int) -> float4 153 TexelFetch, /// (MetaTexture, int[N], int) -> float4
154 TextureGradient, /// (MetaTexture, float[N] coords, float[N*2] derivates) -> float4
152 155
153 ImageLoad, /// (MetaImage, int[N] coords) -> void 156 ImageLoad, /// (MetaImage, int[N] coords) -> void
154 ImageStore, /// (MetaImage, int[N] coords) -> void 157 ImageStore, /// (MetaImage, int[N] coords) -> void
@@ -367,6 +370,7 @@ struct MetaTexture {
367 Node array; 370 Node array;
368 Node depth_compare; 371 Node depth_compare;
369 std::vector<Node> aoffi; 372 std::vector<Node> aoffi;
373 std::vector<Node> derivates;
370 Node bias; 374 Node bias;
371 Node lod; 375 Node lod;
372 Node component{}; 376 Node component{};