summaryrefslogtreecommitdiffstats
path: root/src/video_core
diff options
context:
space:
mode:
authorReinUsesLisp <reinuseslisp@airmail.cc>2018-12-21 02:58:33 +0100
committerReinUsesLisp <reinuseslisp@airmail.cc>2019-01-15 21:54:49 +0100
commit60f044df566569d00106a7bce28110aaca9fa534 (patch)
treee3084b477057c9c8d32de5ea0a306bd07f811381 /src/video_core
parentshader_ir: Add integer helpers (diff)
downloadyuzu-60f044df566569d00106a7bce28110aaca9fa534.tar
yuzu-60f044df566569d00106a7bce28110aaca9fa534.tar.gz
yuzu-60f044df566569d00106a7bce28110aaca9fa534.tar.bz2
yuzu-60f044df566569d00106a7bce28110aaca9fa534.tar.lz
yuzu-60f044df566569d00106a7bce28110aaca9fa534.tar.xz
yuzu-60f044df566569d00106a7bce28110aaca9fa534.tar.zst
yuzu-60f044df566569d00106a7bce28110aaca9fa534.zip
Diffstat (limited to 'src/video_core')
-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...));