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

shader_ir: Add half float helpers

ReinUsesLisp 7 лет назад
Родитель
Сommit
60f044df56
2 измененных файлов с 44 добавлено и 0 удалено
  1. 37 0
      src/video_core/shader/shader_ir.cpp
  2. 7 0
      src/video_core/shader/shader_ir.h

+ 37 - 0
src/video_core/shader/shader_ir.cpp

@@ -175,6 +175,43 @@ Node ShaderIR::GetOperandAbsNegInteger(Node value, bool absolute, bool negate, b
     return value;
 }
 
+Node ShaderIR::UnpackHalfImmediate(Instruction instr, bool has_negation) {
+    const Node value = Immediate(instr.half_imm.PackImmediates());
+    if (!has_negation) {
+        return value;
+    }
+    const Node first_negate = GetPredicate(instr.half_imm.first_negate != 0);
+    const Node second_negate = GetPredicate(instr.half_imm.second_negate != 0);
+
+    return Operation(OperationCode::HNegate, HALF_NO_PRECISE, value, first_negate, second_negate);
+}
+
+Node ShaderIR::HalfMerge(Node dest, Node src, Tegra::Shader::HalfMerge merge) {
+    switch (merge) {
+    case Tegra::Shader::HalfMerge::H0_H1:
+        return src;
+    case Tegra::Shader::HalfMerge::F32:
+        return Operation(OperationCode::HMergeF32, src);
+    case Tegra::Shader::HalfMerge::Mrg_H0:
+        return Operation(OperationCode::HMergeH0, dest, src);
+    case Tegra::Shader::HalfMerge::Mrg_H1:
+        return Operation(OperationCode::HMergeH1, dest, src);
+    }
+    UNREACHABLE();
+    return src;
+}
+
+Node ShaderIR::GetOperandAbsNegHalf(Node value, bool absolute, bool negate) {
+    if (absolute) {
+        value = Operation(OperationCode::HAbsolute, HALF_NO_PRECISE, value);
+    }
+    if (negate) {
+        value = Operation(OperationCode::HNegate, HALF_NO_PRECISE, value, GetPredicate(true),
+                          GetPredicate(true));
+    }
+    return value;
+}
+
 void ShaderIR::SetRegister(BasicBlock& bb, Register dest, Node src) {
     bb.push_back(Operation(OperationCode::Assign, GetRegister(dest), src));
 }

+ 7 - 0
src/video_core/shader/shader_ir.h

@@ -653,6 +653,13 @@ private:
     /// Conditionally absolute/negated integer. Absolute is applied first
     Node GetOperandAbsNegInteger(Node value, bool absolute, bool negate, bool is_signed);
 
+    /// Unpacks a half immediate from an instruction
+    Node UnpackHalfImmediate(Tegra::Shader::Instruction instr, bool has_negation);
+    /// Merges a half pair into another value
+    Node HalfMerge(Node dest, Node src, Tegra::Shader::HalfMerge merge);
+    /// Conditionally absolute/negated half float pair. Absolute is applied first
+    Node GetOperandAbsNegHalf(Node value, bool absolute, bool negate);
+
     template <typename... T>
     inline Node Operation(OperationCode code, const T*... operands) {
         return StoreNode(OperationNode(code, operands...));