summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/video_core/shader/shader_ir.cpp37
-rw-r--r--src/video_core/shader/shader_ir.h7
2 files changed, 44 insertions, 0 deletions
diff --git a/src/video_core/shader/shader_ir.cpp b/src/video_core/shader/shader_ir.cpp
index e4b81040d..5951bdc7b 100644
--- a/src/video_core/shader/shader_ir.cpp
+++ b/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));
}
diff --git a/src/video_core/shader/shader_ir.h b/src/video_core/shader/shader_ir.h
index 84c016da6..f3b17d2eb 100644
--- a/src/video_core/shader/shader_ir.h
+++ b/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...));