Просмотр исходного кода

gl_shader_decompiler: Implement LD_C instruction.

bunnei 8 лет назад
Родитель
Сommit
4669f15f8b

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

@@ -175,6 +175,15 @@ enum class FloatRoundingOp : u64 {
     Trunc = 3,
 };
 
+enum class UniformType : u64 {
+    UnsignedByte = 0,
+    SignedByte = 1,
+    UnsignedShort = 2,
+    SignedShort = 3,
+    Single = 4,
+    Double = 5,
+};
+
 union Instruction {
     Instruction& operator=(const Instruction& instr) {
         value = instr.value;
@@ -252,6 +261,11 @@ union Instruction {
         BitField<49, 1, u64> negate_c;
     } ffma;
 
+    union {
+        BitField<48, 3, UniformType> type;
+        BitField<44, 2, u64> unknown;
+    } ld_c;
+
     union {
         BitField<0, 3, u64> pred0;
         BitField<3, 3, u64> pred3;
@@ -378,6 +392,7 @@ public:
         KIL,
         BRA,
         LD_A,
+        LD_C,
         ST_A,
         TEX,
         TEXQ, // Texture Query
@@ -552,6 +567,7 @@ private:
             INST("111000110011----", Id::KIL, Type::Flow, "KIL"),
             INST("111000100100----", Id::BRA, Type::Flow, "BRA"),
             INST("1110111111011---", Id::LD_A, Type::Memory, "LD_A"),
+            INST("1110111110010---", Id::LD_C, Type::Memory, "LD_C"),
             INST("1110111111110---", Id::ST_A, Type::Memory, "ST_A"),
             INST("1100000000111---", Id::TEX, Type::Memory, "TEX"),
             INST("1101111101001---", Id::TEXQ, Type::Memory, "TEXQ"),

+ 27 - 0
src/video_core/renderer_opengl/gl_shader_decompiler.cpp

@@ -1090,6 +1090,33 @@ private:
                                                 attribute);
                 break;
             }
+            case OpCode::Id::LD_C: {
+                ASSERT_MSG(instr.ld_c.unknown == 0, "Unimplemented");
+
+                std::string op_a =
+                    regs.GetUniformIndirect(instr.cbuf36.index, instr.cbuf36.offset + 0, instr.gpr8,
+                                            GLSLRegister::Type::Float);
+                std::string op_b =
+                    regs.GetUniformIndirect(instr.cbuf36.index, instr.cbuf36.offset + 4, instr.gpr8,
+                                            GLSLRegister::Type::Float);
+
+                switch (instr.ld_c.type.Value()) {
+                case Tegra::Shader::UniformType::Single:
+                    regs.SetRegisterToFloat(instr.gpr0, 0, op_a, 1, 1);
+                    break;
+
+                case Tegra::Shader::UniformType::Double:
+                    regs.SetRegisterToFloat(instr.gpr0, 0, op_a, 1, 1);
+                    regs.SetRegisterToFloat(instr.gpr0.Value() + 1, 0, op_b, 1, 1);
+                    break;
+
+                default:
+                    NGLOG_CRITICAL(HW_GPU, "Unhandled type: {}",
+                                   static_cast<unsigned>(instr.ld_c.type.Value()));
+                    UNREACHABLE();
+                }
+                break;
+            }
             case OpCode::Id::ST_A: {
                 ASSERT_MSG(instr.attribute.fmt20.size == 0, "untested");
                 regs.SetOutputAttributeToRegister(attribute, instr.attribute.fmt20.element,