Răsfoiți Sursa

Merge pull request #3109 from FernandoS27/new-instr

Implement FLO & TXD Instructions on GPU Shaders
bunnei 6 ani în urmă
părinte
comite
e36814d6d5

+ 44 - 0
src/video_core/engines/shader_bytecode.h

@@ -799,6 +799,12 @@ union Instruction {
         BitField<40, 1, u64> invert;
     } popc;
 
+    union {
+        BitField<41, 1, u64> sh;
+        BitField<40, 1, u64> invert;
+        BitField<48, 1, u64> is_signed;
+    } flo;
+
     union {
         BitField<39, 3, u64> pred;
         BitField<42, 1, u64> neg_pred;
@@ -1439,6 +1445,26 @@ union Instruction {
         }
     } 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 {
         BitField<24, 2, StoreCacheManagement> cache_management;
         BitField<33, 3, ImageType> image_type;
@@ -1632,6 +1658,8 @@ public:
         TLD4S,  // Texture Load 4 with scalar / non - vec4 source / destinations
         TMML_B, // Texture Mip Map Level
         TMML,   // Texture Mip Map Level
+        TXD,    // Texture Gradient/Load with Derivates
+        TXD_B,  // Texture Gradient/Load with Derivates Bindless
         SUST,   // Surface Store
         SULD,   // Surface Load
         SUATOM, // Surface Atomic Operation
@@ -1664,6 +1692,9 @@ public:
         ISCADD_C, // Scale and Add
         ISCADD_R,
         ISCADD_IMM,
+        FLO_R,
+        FLO_C,
+        FLO_IMM,
         LEA_R1,
         LEA_R2,
         LEA_RZ,
@@ -1727,6 +1758,10 @@ public:
         SHR_C,
         SHR_R,
         SHR_IMM,
+        SHF_RIGHT_R,
+        SHF_RIGHT_IMM,
+        SHF_LEFT_R,
+        SHF_LEFT_IMM,
         FMNMX_C,
         FMNMX_R,
         FMNMX_IMM,
@@ -1924,6 +1959,8 @@ private:
             INST("1101111100------", Id::TLD4S, Type::Texture, "TLD4S"),
             INST("110111110110----", Id::TMML_B, Type::Texture, "TMML_B"),
             INST("1101111101011---", Id::TMML, Type::Texture, "TMML"),
+            INST("11011110011110--", Id::TXD_B, Type::Texture, "TXD_B"),
+            INST("11011110001110--", Id::TXD, Type::Texture, "TXD"),
             INST("11101011001-----", Id::SUST, Type::Image, "SUST"),
             INST("11101011000-----", Id::SULD, Type::Image, "SULD"),
             INST("1110101000------", Id::SUATOM, Type::Image, "SUATOM_D"),
@@ -1965,6 +2002,9 @@ private:
             INST("010110110100----", Id::ICMP_R, Type::ArithmeticInteger, "ICMP_R"),
             INST("010010110100----", Id::ICMP_CR, Type::ArithmeticInteger, "ICMP_CR"),
             INST("0011011-0100----", Id::ICMP_IMM, Type::ArithmeticInteger, "ICMP_IMM"),
+            INST("010111000011‬0---", Id::FLO_R, Type::ArithmeticInteger, "FLO_R"),
+            INST("0100110000110---", Id::FLO_C, Type::ArithmeticInteger, "FLO_C"),
+            INST("0011100-00110---", Id::FLO_IMM, Type::ArithmeticInteger, "FLO_IMM"),
             INST("0101101111011---", Id::LEA_R2, Type::ArithmeticInteger, "LEA_R2"),
             INST("0101101111010---", Id::LEA_R1, Type::ArithmeticInteger, "LEA_R1"),
             INST("001101101101----", Id::LEA_IMM, Type::ArithmeticInteger, "LEA_IMM"),
@@ -2022,6 +2062,10 @@ private:
             INST("0100110000101---", Id::SHR_C, Type::Shift, "SHR_C"),
             INST("0101110000101---", Id::SHR_R, Type::Shift, "SHR_R"),
             INST("0011100-00101---", Id::SHR_IMM, Type::Shift, "SHR_IMM"),
+            INST("0101110011111---", Id::SHF_RIGHT_R, Type::Shift, "SHF_RIGHT_R"),
+            INST("0011100-11111---", Id::SHF_RIGHT_IMM, Type::Shift, "SHF_RIGHT_IMM"),
+            INST("0101101111111---", Id::SHF_LEFT_R, Type::Shift, "SHF_LEFT_R"),
+            INST("0011011-11111---", Id::SHF_LEFT_IMM, Type::Shift, "SHF_LEFT_IMM"),
             INST("0100110011100---", Id::I2I_C, Type::Conversion, "I2I_C"),
             INST("0101110011100---", Id::I2I_R, Type::Conversion, "I2I_R"),
             INST("0011101-11100---", Id::I2I_IMM, Type::Conversion, "I2I_IMM"),

+ 50 - 1
src/video_core/renderer_opengl/gl_shader_decompiler.cpp

@@ -49,8 +49,9 @@ class ExprDecompiler;
 enum class Type { Void, Bool, Bool2, Float, Int, Uint, HalfFloat };
 
 struct TextureAoffi {};
+struct TextureDerivates {};
 using TextureArgument = std::pair<Type, Node>;
-using TextureIR = std::variant<TextureAoffi, TextureArgument>;
+using TextureIR = std::variant<TextureAoffi, TextureDerivates, TextureArgument>;
 
 constexpr u32 MAX_CONSTBUFFER_ELEMENTS =
     static_cast<u32>(Maxwell::MaxConstBufferSize) / (4 * sizeof(float));
@@ -1112,6 +1113,8 @@ private:
                 expr += GenerateTextureArgument(*argument);
             } else if (std::holds_alternative<TextureAoffi>(variant)) {
                 expr += GenerateTextureAoffi(meta->aoffi);
+            } else if (std::holds_alternative<TextureDerivates>(variant)) {
+                expr += GenerateTextureDerivates(meta->derivates);
             } else {
                 UNREACHABLE();
             }
@@ -1181,6 +1184,36 @@ private:
         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) {
         constexpr std::array constructors{"int(", "ivec2(", "ivec3(", "ivec4("};
         const std::size_t coords_count{operation.GetOperandsCount()};
@@ -1450,6 +1483,11 @@ private:
         return GenerateUnary(operation, "bitCount", type, type);
     }
 
+    template <Type type>
+    Expression BitMSB(Operation operation) {
+        return GenerateUnary(operation, "findMSB", type, type);
+    }
+
     Expression HNegate(Operation operation) {
         const auto GetNegate = [&](std::size_t index) {
             return VisitOperand(operation, index).AsBool() + " ? -1 : 1";
@@ -1738,6 +1776,14 @@ private:
         return {std::move(expr), 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 {std::move(expr) + GetSwizzle(meta->element), Type::Float};
+    }
+
     Expression ImageLoad(Operation operation) {
         if (!device.HasImageLoadFormatted()) {
             LOG_ERROR(Render_OpenGL,
@@ -2003,6 +2049,7 @@ private:
         &GLSLDecompiler::BitfieldInsert<Type::Int>,
         &GLSLDecompiler::BitfieldExtract<Type::Int>,
         &GLSLDecompiler::BitCount<Type::Int>,
+        &GLSLDecompiler::BitMSB<Type::Int>,
 
         &GLSLDecompiler::Add<Type::Uint>,
         &GLSLDecompiler::Mul<Type::Uint>,
@@ -2021,6 +2068,7 @@ private:
         &GLSLDecompiler::BitfieldInsert<Type::Uint>,
         &GLSLDecompiler::BitfieldExtract<Type::Uint>,
         &GLSLDecompiler::BitCount<Type::Uint>,
+        &GLSLDecompiler::BitMSB<Type::Uint>,
 
         &GLSLDecompiler::Add<Type::HalfFloat>,
         &GLSLDecompiler::Mul<Type::HalfFloat>,
@@ -2084,6 +2132,7 @@ private:
         &GLSLDecompiler::TextureQueryDimensions,
         &GLSLDecompiler::TextureQueryLod,
         &GLSLDecompiler::TexelFetch,
+        &GLSLDecompiler::TextureGradient,
 
         &GLSLDecompiler::ImageLoad,
         &GLSLDecompiler::ImageStore,

+ 8 - 0
src/video_core/renderer_vulkan/vk_shader_decompiler.cpp

@@ -983,6 +983,11 @@ private:
         return {};
     }
 
+    Id TextureGradient(Operation operation) {
+        UNIMPLEMENTED();
+        return {};
+    }
+
     Id ImageLoad(Operation operation) {
         UNIMPLEMENTED();
         return {};
@@ -1391,6 +1396,7 @@ private:
         &SPIRVDecompiler::Quaternary<&Module::OpBitFieldInsert, Type::Int>,
         &SPIRVDecompiler::Ternary<&Module::OpBitFieldSExtract, Type::Int>,
         &SPIRVDecompiler::Unary<&Module::OpBitCount, Type::Int>,
+        &SPIRVDecompiler::Unary<&Module::OpFindSMsb, Type::Int>,
 
         &SPIRVDecompiler::Binary<&Module::OpIAdd, Type::Uint>,
         &SPIRVDecompiler::Binary<&Module::OpIMul, Type::Uint>,
@@ -1409,6 +1415,7 @@ private:
         &SPIRVDecompiler::Quaternary<&Module::OpBitFieldInsert, Type::Uint>,
         &SPIRVDecompiler::Ternary<&Module::OpBitFieldUExtract, Type::Uint>,
         &SPIRVDecompiler::Unary<&Module::OpBitCount, Type::Uint>,
+        &SPIRVDecompiler::Unary<&Module::OpFindUMsb, Type::Uint>,
 
         &SPIRVDecompiler::Binary<&Module::OpFAdd, Type::HalfFloat>,
         &SPIRVDecompiler::Binary<&Module::OpFMul, Type::HalfFloat>,
@@ -1473,6 +1480,7 @@ private:
         &SPIRVDecompiler::TextureQueryDimensions,
         &SPIRVDecompiler::TextureQueryLod,
         &SPIRVDecompiler::TexelFetch,
+        &SPIRVDecompiler::TextureGradient,
 
         &SPIRVDecompiler::ImageLoad,
         &SPIRVDecompiler::ImageStore,

+ 19 - 0
src/video_core/shader/decode/arithmetic_integer.cpp

@@ -130,6 +130,25 @@ u32 ShaderIR::DecodeArithmeticInteger(NodeBlock& bb, u32 pc) {
         SetRegister(bb, instr.gpr0, value);
         break;
     }
+    case OpCode::Id::FLO_R:
+    case OpCode::Id::FLO_C:
+    case OpCode::Id::FLO_IMM: {
+        Node value;
+        if (instr.flo.invert) {
+            op_b = Operation(OperationCode::IBitwiseNot, NO_PRECISE, std::move(op_b));
+        }
+        if (instr.flo.is_signed) {
+            value = Operation(OperationCode::IBitMSB, NO_PRECISE, std::move(op_b));
+        } else {
+            value = Operation(OperationCode::UBitMSB, NO_PRECISE, std::move(op_b));
+        }
+        if (instr.flo.sh) {
+            value =
+                Operation(OperationCode::UBitwiseXor, NO_PRECISE, std::move(value), Immediate(31));
+        }
+        SetRegister(bb, instr.gpr0, std::move(value));
+        break;
+    }
     case OpCode::Id::SEL_C:
     case OpCode::Id::SEL_R:
     case OpCode::Id::SEL_IMM: {

+ 46 - 7
src/video_core/shader/decode/texture.cpp

@@ -134,13 +134,52 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) {
         Node4 values;
         for (u32 element = 0; element < values.size(); ++element) {
             auto coords_copy = coords;
-            MetaTexture meta{sampler, {}, {}, {}, {}, {}, component, element};
+            MetaTexture meta{sampler, {}, {}, {}, {}, {}, {}, component, element};
             values[element] = Operation(OperationCode::TextureGather, meta, std::move(coords_copy));
         }
 
         WriteTexsInstructionFloat(bb, instr, values, true);
         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");
+        UNIMPLEMENTED_IF_MSG(instr.txd.is_array != 0, "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) {
+            MetaTexture meta{sampler, {}, {}, {}, derivates, {}, {}, {}, element};
+            values[element] = Operation(OperationCode::TextureGradient, std::move(meta), coords);
+        }
+
+        WriteTexInstructionFloat(bb, instr, values);
+
+        break;
+    }
     case OpCode::Id::TXQ_B:
         is_bindless = true;
         [[fallthrough]];
@@ -158,7 +197,7 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) {
                 if (!instr.txq.IsComponentEnabled(element)) {
                     continue;
                 }
-                MetaTexture meta{sampler, {}, {}, {}, {}, {}, {}, element};
+                MetaTexture meta{sampler, {}, {}, {}, {}, {}, {}, {}, element};
                 const Node value =
                     Operation(OperationCode::TextureQueryDimensions, meta,
                               GetRegister(instr.gpr8.Value() + (is_bindless ? 1 : 0)));
@@ -212,7 +251,7 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) {
                 continue;
             }
             auto params = coords;
-            MetaTexture meta{sampler, {}, {}, {}, {}, {}, {}, element};
+            MetaTexture meta{sampler, {}, {}, {}, {}, {}, {}, {}, element};
             const Node value = Operation(OperationCode::TextureQueryLod, meta, std::move(params));
             SetTemporary(bb, indexer++, value);
         }
@@ -442,7 +481,7 @@ Node4 ShaderIR::GetTextureCode(Instruction instr, TextureType texture_type,
     Node4 values;
     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};
         values[element] = Operation(read_method, meta, std::move(copy_coords));
     }
 
@@ -574,7 +613,7 @@ Node4 ShaderIR::GetTld4Code(Instruction instr, TextureType texture_type, bool de
     Node4 values;
     for (u32 element = 0; element < values.size(); ++element) {
         auto coords_copy = coords;
-        MetaTexture meta{sampler, GetRegister(array_register), dc, aoffi, {}, {}, component,
+        MetaTexture meta{sampler, GetRegister(array_register), dc, aoffi, {}, {}, {}, component,
                          element};
         values[element] = Operation(OperationCode::TextureGather, meta, std::move(coords_copy));
     }
@@ -608,7 +647,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));
     }
 
@@ -653,7 +692,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;

+ 4 - 0
src/video_core/shader/node.h

@@ -68,6 +68,7 @@ enum class OperationCode {
     IBitfieldInsert,       /// (MetaArithmetic, int base, int insert, int offset, int bits) -> int
     IBitfieldExtract,      /// (MetaArithmetic, int value, int offset, int offset) -> int
     IBitCount,             /// (MetaArithmetic, int) -> int
+    IBitMSB,               /// (MetaArithmetic, int) -> int
 
     UAdd,                  /// (MetaArithmetic, uint a, uint b) -> uint
     UMul,                  /// (MetaArithmetic, uint a, uint b) -> uint
@@ -86,6 +87,7 @@ enum class OperationCode {
     UBitfieldInsert,  /// (MetaArithmetic, uint base, uint insert, int offset, int bits) -> uint
     UBitfieldExtract, /// (MetaArithmetic, uint value, int offset, int offset) -> uint
     UBitCount,        /// (MetaArithmetic, uint) -> uint
+    UBitMSB,          /// (MetaArithmetic, uint) -> uint
 
     HAdd,       /// (MetaArithmetic, f16vec2 a, f16vec2 b) -> f16vec2
     HMul,       /// (MetaArithmetic, f16vec2 a, f16vec2 b) -> f16vec2
@@ -149,6 +151,7 @@ enum class OperationCode {
     TextureQueryDimensions, /// (MetaTexture, float a) -> float4
     TextureQueryLod,        /// (MetaTexture, float[N] coords) -> float4
     TexelFetch,             /// (MetaTexture, int[N], int) -> float4
+    TextureGradient,        /// (MetaTexture, float[N] coords, float[N*2] derivates) -> float4
 
     ImageLoad,  /// (MetaImage, int[N] coords) -> void
     ImageStore, /// (MetaImage, int[N] coords) -> void
@@ -367,6 +370,7 @@ struct MetaTexture {
     Node array;
     Node depth_compare;
     std::vector<Node> aoffi;
+    std::vector<Node> derivates;
     Node bias;
     Node lod;
     Node component{};