From 15a0e1481d9a1efb3e3aa61cbaf2fa1ba0392d71 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Thu, 20 Dec 2018 19:09:21 -0300 Subject: shader_ir: Initial implementation --- src/video_core/shader/shader_ir.cpp | 105 ++++++++++++++++++++++++++++++++++++ 1 file changed, 105 insertions(+) create mode 100644 src/video_core/shader/shader_ir.cpp (limited to 'src/video_core/shader/shader_ir.cpp') diff --git a/src/video_core/shader/shader_ir.cpp b/src/video_core/shader/shader_ir.cpp new file mode 100644 index 000000000..db00c8902 --- /dev/null +++ b/src/video_core/shader/shader_ir.cpp @@ -0,0 +1,105 @@ +// Copyright 2018 yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include +#include + +#include "common/assert.h" +#include "common/common_types.h" +#include "video_core/engines/shader_bytecode.h" +#include "video_core/shader/shader_ir.h" + +namespace VideoCommon::Shader { + +using Tegra::Shader::Attribute; +using Tegra::Shader::Instruction; +using Tegra::Shader::IpaMode; +using Tegra::Shader::Pred; +using Tegra::Shader::PredCondition; +using Tegra::Shader::PredOperation; +using Tegra::Shader::Register; + +Node ShaderIR::StoreNode(NodeData&& node_data) { + auto store = std::make_unique(node_data); + const Node node = store.get(); + stored_nodes.push_back(std::move(store)); + return node; +} + +Node ShaderIR::Conditional(Node condition, std::vector&& code) { + return StoreNode(ConditionalNode(condition, std::move(code))); +} + +Node ShaderIR::Comment(const std::string& text) { + return StoreNode(CommentNode(text)); +} + +Node ShaderIR::GetPredicate(u64 pred_, bool negated) { + const auto pred = static_cast(pred_); + if (pred != Pred::UnusedIndex && pred != Pred::NeverExecute) { + used_predicates.insert(pred); + } + + return StoreNode(PredicateNode(pred, negated)); +} + +/*static*/ OperationCode ShaderIR::SignedToUnsignedCode(OperationCode operation_code, + bool is_signed) { + if (is_signed) { + return operation_code; + } + switch (operation_code) { + case OperationCode::FCastInteger: + return OperationCode::FCastUInteger; + case OperationCode::IAdd: + return OperationCode::UAdd; + case OperationCode::IMul: + return OperationCode::UMul; + case OperationCode::IDiv: + return OperationCode::UDiv; + case OperationCode::IMin: + return OperationCode::UMin; + case OperationCode::IMax: + return OperationCode::UMax; + case OperationCode::ICastFloat: + return OperationCode::UCastFloat; + case OperationCode::ICastUnsigned: + return OperationCode::UCastSigned; + case OperationCode::ILogicalShiftLeft: + return OperationCode::ULogicalShiftLeft; + case OperationCode::ILogicalShiftRight: + return OperationCode::ULogicalShiftRight; + case OperationCode::IArithmeticShiftRight: + return OperationCode::UArithmeticShiftRight; + case OperationCode::IBitwiseAnd: + return OperationCode::UBitwiseAnd; + case OperationCode::IBitwiseOr: + return OperationCode::UBitwiseOr; + case OperationCode::IBitwiseXor: + return OperationCode::UBitwiseXor; + case OperationCode::IBitwiseNot: + return OperationCode::UBitwiseNot; + case OperationCode::IBitfieldInsert: + return OperationCode::UBitfieldInsert; + case OperationCode::LogicalILessThan: + return OperationCode::LogicalULessThan; + case OperationCode::LogicalIEqual: + return OperationCode::LogicalUEqual; + case OperationCode::LogicalILessEqual: + return OperationCode::LogicalULessEqual; + case OperationCode::LogicalIGreaterThan: + return OperationCode::LogicalUGreaterThan; + case OperationCode::LogicalINotEqual: + return OperationCode::LogicalUNotEqual; + case OperationCode::LogicalIGreaterEqual: + return OperationCode::LogicalUGreaterEqual; + case OperationCode::INegate: + UNREACHABLE_MSG("Can't negate an unsigned integer"); + case OperationCode::IAbsolute: + UNREACHABLE_MSG("Can't apply absolute to an unsigned integer"); + } + UNREACHABLE_MSG("Unknown signed operation with code={}", static_cast(operation_code)); +} + +} // namespace VideoCommon::Shader \ No newline at end of file -- cgit v1.2.3 From 4aaa2192b993411f63d46a57b93e9e787b6a836d Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Thu, 20 Dec 2018 22:36:17 -0300 Subject: shader_ir: Add immediate node constructors --- src/video_core/shader/shader_ir.cpp | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'src/video_core/shader/shader_ir.cpp') diff --git a/src/video_core/shader/shader_ir.cpp b/src/video_core/shader/shader_ir.cpp index db00c8902..c59ecf457 100644 --- a/src/video_core/shader/shader_ir.cpp +++ b/src/video_core/shader/shader_ir.cpp @@ -35,6 +35,18 @@ Node ShaderIR::Comment(const std::string& text) { return StoreNode(CommentNode(text)); } +Node ShaderIR::Immediate(u32 value) { + return StoreNode(ImmediateNode(value)); +} + +Node ShaderIR::GetImmediate19(Instruction instr) { + return Immediate(instr.alu.GetImm20_19()); +} + +Node ShaderIR::GetImmediate32(Instruction instr) { + return Immediate(instr.alu.GetImm20_32()); +} + Node ShaderIR::GetPredicate(u64 pred_, bool negated) { const auto pred = static_cast(pred_); if (pred != Pred::UnusedIndex && pred != Pred::NeverExecute) { @@ -44,6 +56,10 @@ Node ShaderIR::GetPredicate(u64 pred_, bool negated) { return StoreNode(PredicateNode(pred, negated)); } +Node ShaderIR::GetPredicate(bool immediate) { + return GetPredicate(static_cast(immediate ? Pred::UnusedIndex : Pred::NeverExecute)); +} + /*static*/ OperationCode ShaderIR::SignedToUnsignedCode(OperationCode operation_code, bool is_signed) { if (is_signed) { -- cgit v1.2.3 From 5e639bfcf6d764714cc9814fc47142ca85f889cf Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Thu, 20 Dec 2018 22:41:31 -0300 Subject: shader_ir: Add register getter --- src/video_core/shader/shader_ir.cpp | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'src/video_core/shader/shader_ir.cpp') diff --git a/src/video_core/shader/shader_ir.cpp b/src/video_core/shader/shader_ir.cpp index c59ecf457..ff4e462f2 100644 --- a/src/video_core/shader/shader_ir.cpp +++ b/src/video_core/shader/shader_ir.cpp @@ -39,6 +39,13 @@ Node ShaderIR::Immediate(u32 value) { return StoreNode(ImmediateNode(value)); } +Node ShaderIR::GetRegister(Register reg) { + if (reg != Register::ZeroIndex) { + used_registers.insert(static_cast(reg)); + } + return StoreNode(GprNode(reg)); +} + Node ShaderIR::GetImmediate19(Instruction instr) { return Immediate(instr.alu.GetImm20_19()); } -- cgit v1.2.3 From 864e8f55cf48bc6c8ad95c35cbe9217449936662 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Thu, 20 Dec 2018 22:42:47 -0300 Subject: shader_ir: Add constant buffer getters --- src/video_core/shader/shader_ir.cpp | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'src/video_core/shader/shader_ir.cpp') diff --git a/src/video_core/shader/shader_ir.cpp b/src/video_core/shader/shader_ir.cpp index ff4e462f2..3bc9f72f5 100644 --- a/src/video_core/shader/shader_ir.cpp +++ b/src/video_core/shader/shader_ir.cpp @@ -54,6 +54,27 @@ Node ShaderIR::GetImmediate32(Instruction instr) { return Immediate(instr.alu.GetImm20_32()); } +Node ShaderIR::GetConstBuffer(u64 index_, u64 offset_) { + const auto index = static_cast(index_); + const auto offset = static_cast(offset_); + + const auto [entry, is_new] = used_cbufs.try_emplace(index); + entry->second.MarkAsUsed(offset); + + return StoreNode(CbufNode(index, Immediate(offset))); +} + +Node ShaderIR::GetConstBufferIndirect(u64 index_, u64 offset_, Node node) { + const auto index = static_cast(index_); + const auto offset = static_cast(offset_); + + const auto [entry, is_new] = used_cbufs.try_emplace(index); + entry->second.MarkAsUsedIndirect(); + + const Node final_offset = Operation(OperationCode::UAdd, NO_PRECISE, node, Immediate(offset)); + return StoreNode(CbufNode(index, final_offset)); +} + Node ShaderIR::GetPredicate(u64 pred_, bool negated) { const auto pred = static_cast(pred_); if (pred != Pred::UnusedIndex && pred != Pred::NeverExecute) { -- cgit v1.2.3 From 15f431f0cb9f8d9d142ce631c59335ca99eb9ab4 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Thu, 20 Dec 2018 22:45:34 -0300 Subject: shader_ir: Add attribute getters --- src/video_core/shader/shader_ir.cpp | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'src/video_core/shader/shader_ir.cpp') diff --git a/src/video_core/shader/shader_ir.cpp b/src/video_core/shader/shader_ir.cpp index 3bc9f72f5..0c814fc80 100644 --- a/src/video_core/shader/shader_ir.cpp +++ b/src/video_core/shader/shader_ir.cpp @@ -88,6 +88,27 @@ Node ShaderIR::GetPredicate(bool immediate) { return GetPredicate(static_cast(immediate ? Pred::UnusedIndex : Pred::NeverExecute)); } +Node ShaderIR::GetInputAttribute(Attribute::Index index, u64 element, + const Tegra::Shader::IpaMode& input_mode, Node buffer) { + const auto [entry, is_new] = + used_input_attributes.emplace(std::make_pair(index, std::set{})); + entry->second.insert(input_mode); + + return StoreNode(AbufNode(index, static_cast(element), input_mode, buffer)); +} + +Node ShaderIR::GetOutputAttribute(Attribute::Index index, u64 element, Node buffer) { + if (index == Attribute::Index::ClipDistances0123 || + index == Attribute::Index::ClipDistances4567) { + const auto clip_index = + static_cast((index == Attribute::Index::ClipDistances4567 ? 1 : 0) + element); + used_clip_distances.at(clip_index) = true; + } + used_output_attributes.insert(index); + + return StoreNode(AbufNode(index, static_cast(element), buffer)); +} + /*static*/ OperationCode ShaderIR::SignedToUnsignedCode(OperationCode operation_code, bool is_signed) { if (is_signed) { -- cgit v1.2.3 From 2f87fd060d6bed70fb90d97f8c847a0bd03d4c43 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Thu, 20 Dec 2018 22:49:59 -0300 Subject: shader_ir: Add internal flag getters --- src/video_core/shader/shader_ir.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'src/video_core/shader/shader_ir.cpp') diff --git a/src/video_core/shader/shader_ir.cpp b/src/video_core/shader/shader_ir.cpp index 0c814fc80..62a139e56 100644 --- a/src/video_core/shader/shader_ir.cpp +++ b/src/video_core/shader/shader_ir.cpp @@ -109,6 +109,14 @@ Node ShaderIR::GetOutputAttribute(Attribute::Index index, u64 element, Node buff return StoreNode(AbufNode(index, static_cast(element), buffer)); } +Node ShaderIR::GetInternalFlag(InternalFlag flag, bool negated) { + const Node node = StoreNode(InternalFlagNode(flag)); + if (negated) { + return Operation(OperationCode::LogicalNegate, node); + } + return node; +} + /*static*/ OperationCode ShaderIR::SignedToUnsignedCode(OperationCode operation_code, bool is_signed) { if (is_signed) { -- cgit v1.2.3 From 12a95ff4532f7133893d55c964f1a62c6611d753 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Thu, 20 Dec 2018 22:51:38 -0300 Subject: shader_ir: Add local memory getters --- src/video_core/shader/shader_ir.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src/video_core/shader/shader_ir.cpp') diff --git a/src/video_core/shader/shader_ir.cpp b/src/video_core/shader/shader_ir.cpp index 62a139e56..42695149f 100644 --- a/src/video_core/shader/shader_ir.cpp +++ b/src/video_core/shader/shader_ir.cpp @@ -117,6 +117,10 @@ Node ShaderIR::GetInternalFlag(InternalFlag flag, bool negated) { return node; } +Node ShaderIR::GetLocalMemory(Node address) { + return StoreNode(LmemNode(address)); +} + /*static*/ OperationCode ShaderIR::SignedToUnsignedCode(OperationCode operation_code, bool is_signed) { if (is_signed) { -- cgit v1.2.3 From 6b9eea3fe55f882d624211415c7777e1eec7f1bd Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Thu, 20 Dec 2018 22:53:43 -0300 Subject: shader_ir: Add setters --- src/video_core/shader/shader_ir.cpp | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'src/video_core/shader/shader_ir.cpp') diff --git a/src/video_core/shader/shader_ir.cpp b/src/video_core/shader/shader_ir.cpp index 42695149f..48046d967 100644 --- a/src/video_core/shader/shader_ir.cpp +++ b/src/video_core/shader/shader_ir.cpp @@ -121,6 +121,22 @@ Node ShaderIR::GetLocalMemory(Node address) { return StoreNode(LmemNode(address)); } +void ShaderIR::SetRegister(BasicBlock& bb, Register dest, Node src) { + bb.push_back(Operation(OperationCode::Assign, GetRegister(dest), src)); +} + +void ShaderIR::SetPredicate(BasicBlock& bb, u64 dest, Node src) { + bb.push_back(Operation(OperationCode::LogicalAssign, GetPredicate(dest), src)); +} + +void ShaderIR::SetInternalFlag(BasicBlock& bb, InternalFlag flag, Node value) { + bb.push_back(Operation(OperationCode::LogicalAssign, GetInternalFlag(flag), value)); +} + +void ShaderIR::SetLocalMemory(BasicBlock& bb, Node address, Node value) { + bb.push_back(Operation(OperationCode::Assign, GetLocalMemory(address), value)); +} + /*static*/ OperationCode ShaderIR::SignedToUnsignedCode(OperationCode operation_code, bool is_signed) { if (is_signed) { -- cgit v1.2.3 From 833d0806f92b893220cf43d63c223a7cd9af9022 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Thu, 20 Dec 2018 22:56:08 -0300 Subject: shader_ir: Add float helpers --- src/video_core/shader/shader_ir.cpp | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'src/video_core/shader/shader_ir.cpp') diff --git a/src/video_core/shader/shader_ir.cpp b/src/video_core/shader/shader_ir.cpp index 48046d967..af95e54ef 100644 --- a/src/video_core/shader/shader_ir.cpp +++ b/src/video_core/shader/shader_ir.cpp @@ -121,6 +121,25 @@ Node ShaderIR::GetLocalMemory(Node address) { return StoreNode(LmemNode(address)); } +Node ShaderIR::GetOperandAbsNegFloat(Node value, bool absolute, bool negate) { + if (absolute) { + value = Operation(OperationCode::FAbsolute, NO_PRECISE, value); + } + if (negate) { + value = Operation(OperationCode::FNegate, NO_PRECISE, value); + } + return value; +} + +Node ShaderIR::GetSaturatedFloat(Node value, bool saturate) { + if (!saturate) { + return value; + } + const Node positive_zero = Immediate(std::copysignf(0, 1)); + const Node positive_one = Immediate(1.0f); + return Operation(OperationCode::FClamp, NO_PRECISE, value, positive_zero, positive_one); +} + void ShaderIR::SetRegister(BasicBlock& bb, Register dest, Node src) { bb.push_back(Operation(OperationCode::Assign, GetRegister(dest), src)); } -- cgit v1.2.3 From e3c55e31d7d15066d565e6cd728d12526e91d8e2 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Thu, 20 Dec 2018 22:57:16 -0300 Subject: shader_ir: Add integer helpers --- src/video_core/shader/shader_ir.cpp | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) (limited to 'src/video_core/shader/shader_ir.cpp') diff --git a/src/video_core/shader/shader_ir.cpp b/src/video_core/shader/shader_ir.cpp index af95e54ef..e4b81040d 100644 --- a/src/video_core/shader/shader_ir.cpp +++ b/src/video_core/shader/shader_ir.cpp @@ -140,6 +140,41 @@ Node ShaderIR::GetSaturatedFloat(Node value, bool saturate) { return Operation(OperationCode::FClamp, NO_PRECISE, value, positive_zero, positive_one); } +Node ShaderIR::ConvertIntegerSize(Node value, Tegra::Shader::Register::Size size, bool is_signed) { + switch (size) { + case Register::Size::Byte: + value = SignedOperation(OperationCode::ILogicalShiftLeft, is_signed, NO_PRECISE, value, + Immediate(24)); + value = SignedOperation(OperationCode::IArithmeticShiftRight, is_signed, NO_PRECISE, value, + Immediate(24)); + return value; + case Register::Size::Short: + value = SignedOperation(OperationCode::ILogicalShiftLeft, is_signed, NO_PRECISE, value, + Immediate(16)); + value = SignedOperation(OperationCode::IArithmeticShiftRight, is_signed, NO_PRECISE, value, + Immediate(16)); + case Register::Size::Word: + // Default - do nothing + return value; + default: + UNREACHABLE_MSG("Unimplemented conversion size: {}", static_cast(size)); + } +} + +Node ShaderIR::GetOperandAbsNegInteger(Node value, bool absolute, bool negate, bool is_signed) { + if (!is_signed) { + // Absolute or negate on an unsigned is pointless + return value; + } + if (absolute) { + value = Operation(OperationCode::IAbsolute, NO_PRECISE, value); + } + if (negate) { + value = Operation(OperationCode::INegate, NO_PRECISE, value); + } + return value; +} + void ShaderIR::SetRegister(BasicBlock& bb, Register dest, Node src) { bb.push_back(Operation(OperationCode::Assign, GetRegister(dest), src)); } -- cgit v1.2.3 From 60f044df566569d00106a7bce28110aaca9fa534 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Thu, 20 Dec 2018 22:58:33 -0300 Subject: shader_ir: Add half float helpers --- src/video_core/shader/shader_ir.cpp | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) (limited to 'src/video_core/shader/shader_ir.cpp') 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)); } -- cgit v1.2.3 From bf07272695b718d09f8ef532539ba625dab01d3c Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Thu, 20 Dec 2018 23:01:03 -0300 Subject: shader_ir: Add comparison helpers --- src/video_core/shader/shader_ir.cpp | 97 +++++++++++++++++++++++++++++++++++++ 1 file changed, 97 insertions(+) (limited to 'src/video_core/shader/shader_ir.cpp') diff --git a/src/video_core/shader/shader_ir.cpp b/src/video_core/shader/shader_ir.cpp index 5951bdc7b..20a1a50ef 100644 --- a/src/video_core/shader/shader_ir.cpp +++ b/src/video_core/shader/shader_ir.cpp @@ -212,6 +212,103 @@ Node ShaderIR::GetOperandAbsNegHalf(Node value, bool absolute, bool negate) { return value; } +Node ShaderIR::GetPredicateComparisonFloat(PredCondition condition, Node op_a, Node op_b) { + static const std::unordered_map PredicateComparisonTable = { + {PredCondition::LessThan, OperationCode::LogicalFLessThan}, + {PredCondition::Equal, OperationCode::LogicalFEqual}, + {PredCondition::LessEqual, OperationCode::LogicalFLessEqual}, + {PredCondition::GreaterThan, OperationCode::LogicalFGreaterThan}, + {PredCondition::NotEqual, OperationCode::LogicalFNotEqual}, + {PredCondition::GreaterEqual, OperationCode::LogicalFGreaterEqual}, + {PredCondition::LessThanWithNan, OperationCode::LogicalFLessThan}, + {PredCondition::NotEqualWithNan, OperationCode::LogicalFNotEqual}, + {PredCondition::LessEqualWithNan, OperationCode::LogicalFLessEqual}, + {PredCondition::GreaterThanWithNan, OperationCode::LogicalFGreaterThan}, + {PredCondition::GreaterEqualWithNan, OperationCode::LogicalFGreaterEqual}}; + + const auto comparison{PredicateComparisonTable.find(condition)}; + UNIMPLEMENTED_IF_MSG(comparison == PredicateComparisonTable.end(), + "Unknown predicate comparison operation"); + + Node predicate = Operation(comparison->second, NO_PRECISE, op_a, op_b); + + if (condition == PredCondition::LessThanWithNan || + condition == PredCondition::NotEqualWithNan || + condition == PredCondition::LessEqualWithNan || + condition == PredCondition::GreaterThanWithNan || + condition == PredCondition::GreaterEqualWithNan) { + + predicate = Operation(OperationCode::LogicalOr, predicate, + Operation(OperationCode::LogicalFIsNan, op_a)); + predicate = Operation(OperationCode::LogicalOr, predicate, + Operation(OperationCode::LogicalFIsNan, op_b)); + } + + return predicate; +} + +Node ShaderIR::GetPredicateComparisonInteger(PredCondition condition, bool is_signed, Node op_a, + Node op_b) { + static const std::unordered_map PredicateComparisonTable = { + {PredCondition::LessThan, OperationCode::LogicalILessThan}, + {PredCondition::Equal, OperationCode::LogicalIEqual}, + {PredCondition::LessEqual, OperationCode::LogicalILessEqual}, + {PredCondition::GreaterThan, OperationCode::LogicalIGreaterThan}, + {PredCondition::NotEqual, OperationCode::LogicalINotEqual}, + {PredCondition::GreaterEqual, OperationCode::LogicalIGreaterEqual}, + {PredCondition::LessThanWithNan, OperationCode::LogicalILessThan}, + {PredCondition::NotEqualWithNan, OperationCode::LogicalINotEqual}, + {PredCondition::LessEqualWithNan, OperationCode::LogicalILessEqual}, + {PredCondition::GreaterThanWithNan, OperationCode::LogicalIGreaterThan}, + {PredCondition::GreaterEqualWithNan, OperationCode::LogicalIGreaterEqual}}; + + const auto comparison{PredicateComparisonTable.find(condition)}; + UNIMPLEMENTED_IF_MSG(comparison == PredicateComparisonTable.end(), + "Unknown predicate comparison operation"); + + Node predicate = SignedOperation(comparison->second, is_signed, NO_PRECISE, op_a, op_b); + + UNIMPLEMENTED_IF_MSG(condition == PredCondition::LessThanWithNan || + condition == PredCondition::NotEqualWithNan || + condition == PredCondition::LessEqualWithNan || + condition == PredCondition::GreaterThanWithNan || + condition == PredCondition::GreaterEqualWithNan, + "NaN comparisons for integers are not implemented"); + return predicate; +} + +Node ShaderIR::GetPredicateComparisonHalf(Tegra::Shader::PredCondition condition, + const MetaHalfArithmetic& meta, Node op_a, Node op_b) { + + UNIMPLEMENTED_IF_MSG(condition == PredCondition::LessThanWithNan || + condition == PredCondition::NotEqualWithNan || + condition == PredCondition::LessEqualWithNan || + condition == PredCondition::GreaterThanWithNan || + condition == PredCondition::GreaterEqualWithNan, + "Unimplemented NaN comparison for half floats"); + + static const std::unordered_map PredicateComparisonTable = { + {PredCondition::LessThan, OperationCode::LogicalHLessThan}, + {PredCondition::Equal, OperationCode::LogicalHEqual}, + {PredCondition::LessEqual, OperationCode::LogicalHLessEqual}, + {PredCondition::GreaterThan, OperationCode::LogicalHGreaterThan}, + {PredCondition::NotEqual, OperationCode::LogicalHNotEqual}, + {PredCondition::GreaterEqual, OperationCode::LogicalHGreaterEqual}, + {PredCondition::LessThanWithNan, OperationCode::LogicalHLessThan}, + {PredCondition::NotEqualWithNan, OperationCode::LogicalHNotEqual}, + {PredCondition::LessEqualWithNan, OperationCode::LogicalHLessEqual}, + {PredCondition::GreaterThanWithNan, OperationCode::LogicalHGreaterThan}, + {PredCondition::GreaterEqualWithNan, OperationCode::LogicalHGreaterEqual}}; + + const auto comparison{PredicateComparisonTable.find(condition)}; + UNIMPLEMENTED_IF_MSG(comparison == PredicateComparisonTable.end(), + "Unknown predicate comparison operation"); + + const Node predicate = Operation(comparison->second, meta, op_a, op_b); + + return predicate; +} + void ShaderIR::SetRegister(BasicBlock& bb, Register dest, Node src) { bb.push_back(Operation(OperationCode::Assign, GetRegister(dest), src)); } -- cgit v1.2.3 From a58abbcfc4580c8d43935e2aecc6fa151509bf5b Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Thu, 20 Dec 2018 23:40:54 -0300 Subject: shader_ir: Add predicate combiner helper --- src/video_core/shader/shader_ir.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'src/video_core/shader/shader_ir.cpp') diff --git a/src/video_core/shader/shader_ir.cpp b/src/video_core/shader/shader_ir.cpp index 20a1a50ef..aec1fb36b 100644 --- a/src/video_core/shader/shader_ir.cpp +++ b/src/video_core/shader/shader_ir.cpp @@ -309,6 +309,18 @@ Node ShaderIR::GetPredicateComparisonHalf(Tegra::Shader::PredCondition condition return predicate; } +OperationCode ShaderIR::GetPredicateCombiner(PredOperation operation) { + static const std::unordered_map PredicateOperationTable = { + {PredOperation::And, OperationCode::LogicalAnd}, + {PredOperation::Or, OperationCode::LogicalOr}, + {PredOperation::Xor, OperationCode::LogicalXor}, + }; + + const auto op = PredicateOperationTable.find(operation); + UNIMPLEMENTED_IF_MSG(op == PredicateOperationTable.end(), "Unknown predicate operation"); + return op->second; +} + void ShaderIR::SetRegister(BasicBlock& bb, Register dest, Node src) { bb.push_back(Operation(OperationCode::Assign, GetRegister(dest), src)); } -- cgit v1.2.3 From fbc67a05637f3acb47f933066fb2e548f9d35d8c Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Thu, 20 Dec 2018 23:42:02 -0300 Subject: shader_ir: Add condition code helper --- src/video_core/shader/shader_ir.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'src/video_core/shader/shader_ir.cpp') diff --git a/src/video_core/shader/shader_ir.cpp b/src/video_core/shader/shader_ir.cpp index aec1fb36b..3c37c7145 100644 --- a/src/video_core/shader/shader_ir.cpp +++ b/src/video_core/shader/shader_ir.cpp @@ -321,6 +321,16 @@ OperationCode ShaderIR::GetPredicateCombiner(PredOperation operation) { return op->second; } +Node ShaderIR::GetConditionCode(Tegra::Shader::ConditionCode cc) { + switch (cc) { + case Tegra::Shader::ConditionCode::NEU: + return GetInternalFlag(InternalFlag::Zero, true); + default: + UNIMPLEMENTED_MSG("Unimplemented condition code: {}", static_cast(cc)); + return GetPredicate(static_cast(Pred::NeverExecute)); + } +} + void ShaderIR::SetRegister(BasicBlock& bb, Register dest, Node src) { bb.push_back(Operation(OperationCode::Assign, GetRegister(dest), src)); } -- cgit v1.2.3 From fc46ecddb3bca4861babbf610cd64ab9fdc1bb08 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Fri, 21 Dec 2018 18:47:22 -0300 Subject: video_core: Return safe values after an assert hits --- src/video_core/shader/shader_ir.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/video_core/shader/shader_ir.cpp') diff --git a/src/video_core/shader/shader_ir.cpp b/src/video_core/shader/shader_ir.cpp index 3c37c7145..1f39dc6d0 100644 --- a/src/video_core/shader/shader_ir.cpp +++ b/src/video_core/shader/shader_ir.cpp @@ -158,6 +158,7 @@ Node ShaderIR::ConvertIntegerSize(Node value, Tegra::Shader::Register::Size size return value; default: UNREACHABLE_MSG("Unimplemented conversion size: {}", static_cast(size)); + return value; } } @@ -403,6 +404,7 @@ void ShaderIR::SetLocalMemory(BasicBlock& bb, Node address, Node value) { UNREACHABLE_MSG("Can't apply absolute to an unsigned integer"); } UNREACHABLE_MSG("Unknown signed operation with code={}", static_cast(operation_code)); + return {}; } } // namespace VideoCommon::Shader \ No newline at end of file -- cgit v1.2.3 From 027f443e699652fc30a849efaf8c12725a7b5729 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Sun, 23 Dec 2018 01:33:47 -0300 Subject: shader_decode: Implement POPC --- src/video_core/shader/shader_ir.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/video_core/shader/shader_ir.cpp') diff --git a/src/video_core/shader/shader_ir.cpp b/src/video_core/shader/shader_ir.cpp index 1f39dc6d0..1fc838d15 100644 --- a/src/video_core/shader/shader_ir.cpp +++ b/src/video_core/shader/shader_ir.cpp @@ -386,6 +386,8 @@ void ShaderIR::SetLocalMemory(BasicBlock& bb, Node address, Node value) { return OperationCode::UBitwiseNot; case OperationCode::IBitfieldInsert: return OperationCode::UBitfieldInsert; + case OperationCode::IBitCount: + return OperationCode::UBitCount; case OperationCode::LogicalILessThan: return OperationCode::LogicalULessThan; case OperationCode::LogicalIEqual: -- cgit v1.2.3 From 2df55985b691d659073dce2d857d46bc152b4842 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Sun, 23 Dec 2018 20:59:49 -0300 Subject: shader_decode: Rework HSETP2 --- src/video_core/shader/shader_ir.cpp | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'src/video_core/shader/shader_ir.cpp') diff --git a/src/video_core/shader/shader_ir.cpp b/src/video_core/shader/shader_ir.cpp index 1fc838d15..b07642517 100644 --- a/src/video_core/shader/shader_ir.cpp +++ b/src/video_core/shader/shader_ir.cpp @@ -289,17 +289,17 @@ Node ShaderIR::GetPredicateComparisonHalf(Tegra::Shader::PredCondition condition "Unimplemented NaN comparison for half floats"); static const std::unordered_map PredicateComparisonTable = { - {PredCondition::LessThan, OperationCode::LogicalHLessThan}, - {PredCondition::Equal, OperationCode::LogicalHEqual}, - {PredCondition::LessEqual, OperationCode::LogicalHLessEqual}, - {PredCondition::GreaterThan, OperationCode::LogicalHGreaterThan}, - {PredCondition::NotEqual, OperationCode::LogicalHNotEqual}, - {PredCondition::GreaterEqual, OperationCode::LogicalHGreaterEqual}, - {PredCondition::LessThanWithNan, OperationCode::LogicalHLessThan}, - {PredCondition::NotEqualWithNan, OperationCode::LogicalHNotEqual}, - {PredCondition::LessEqualWithNan, OperationCode::LogicalHLessEqual}, - {PredCondition::GreaterThanWithNan, OperationCode::LogicalHGreaterThan}, - {PredCondition::GreaterEqualWithNan, OperationCode::LogicalHGreaterEqual}}; + {PredCondition::LessThan, OperationCode::Logical2HLessThan}, + {PredCondition::Equal, OperationCode::Logical2HEqual}, + {PredCondition::LessEqual, OperationCode::Logical2HLessEqual}, + {PredCondition::GreaterThan, OperationCode::Logical2HGreaterThan}, + {PredCondition::NotEqual, OperationCode::Logical2HNotEqual}, + {PredCondition::GreaterEqual, OperationCode::Logical2HGreaterEqual}, + {PredCondition::LessThanWithNan, OperationCode::Logical2HLessThan}, + {PredCondition::NotEqualWithNan, OperationCode::Logical2HNotEqual}, + {PredCondition::LessEqualWithNan, OperationCode::Logical2HLessEqual}, + {PredCondition::GreaterThanWithNan, OperationCode::Logical2HGreaterThan}, + {PredCondition::GreaterEqualWithNan, OperationCode::Logical2HGreaterEqual}}; const auto comparison{PredicateComparisonTable.find(condition)}; UNIMPLEMENTED_IF_MSG(comparison == PredicateComparisonTable.end(), -- cgit v1.2.3 From 2faad9bf23dbcedc80dca7ed9ad4b81c0416dd5e Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Wed, 26 Dec 2018 02:58:47 -0300 Subject: shader_decode: Use BitfieldExtract instead of shift + and --- src/video_core/shader/shader_ir.cpp | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'src/video_core/shader/shader_ir.cpp') diff --git a/src/video_core/shader/shader_ir.cpp b/src/video_core/shader/shader_ir.cpp index b07642517..d4e304b4e 100644 --- a/src/video_core/shader/shader_ir.cpp +++ b/src/video_core/shader/shader_ir.cpp @@ -348,6 +348,11 @@ void ShaderIR::SetLocalMemory(BasicBlock& bb, Node address, Node value) { bb.push_back(Operation(OperationCode::Assign, GetLocalMemory(address), value)); } +Node ShaderIR::BitfieldExtract(Node value, u32 offset, u32 bits) { + return Operation(OperationCode::UBitfieldExtract, NO_PRECISE, value, Immediate(offset), + Immediate(bits)); +} + /*static*/ OperationCode ShaderIR::SignedToUnsignedCode(OperationCode operation_code, bool is_signed) { if (is_signed) { -- cgit v1.2.3 From d911740e5d474ae459f9e05d82a7dba9c7e06340 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Thu, 27 Dec 2018 01:50:22 -0300 Subject: shader_ir: Remove composite primitives and use temporals instead --- src/video_core/shader/shader_ir.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'src/video_core/shader/shader_ir.cpp') diff --git a/src/video_core/shader/shader_ir.cpp b/src/video_core/shader/shader_ir.cpp index d4e304b4e..4474af7c4 100644 --- a/src/video_core/shader/shader_ir.cpp +++ b/src/video_core/shader/shader_ir.cpp @@ -121,6 +121,10 @@ Node ShaderIR::GetLocalMemory(Node address) { return StoreNode(LmemNode(address)); } +Node ShaderIR::GetTemporal(u32 id) { + return GetRegister(Register::ZeroIndex + 1 + id); +} + Node ShaderIR::GetOperandAbsNegFloat(Node value, bool absolute, bool negate) { if (absolute) { value = Operation(OperationCode::FAbsolute, NO_PRECISE, value); @@ -348,6 +352,10 @@ void ShaderIR::SetLocalMemory(BasicBlock& bb, Node address, Node value) { bb.push_back(Operation(OperationCode::Assign, GetLocalMemory(address), value)); } +void ShaderIR::SetTemporal(BasicBlock& bb, u32 id, Node value) { + SetRegister(bb, Register::ZeroIndex + 1 + id, value); +} + Node ShaderIR::BitfieldExtract(Node value, u32 offset, u32 bits) { return Operation(OperationCode::UBitfieldExtract, NO_PRECISE, value, Immediate(offset), Immediate(bits)); -- cgit v1.2.3 From 2d6c064e66bac4cb871aa26a12066441a8852008 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Thu, 27 Dec 2018 16:50:36 -0300 Subject: shader_decode: Improve zero flag implementation --- src/video_core/shader/shader_ir.cpp | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'src/video_core/shader/shader_ir.cpp') diff --git a/src/video_core/shader/shader_ir.cpp b/src/video_core/shader/shader_ir.cpp index 4474af7c4..d7747103e 100644 --- a/src/video_core/shader/shader_ir.cpp +++ b/src/video_core/shader/shader_ir.cpp @@ -7,6 +7,7 @@ #include "common/assert.h" #include "common/common_types.h" +#include "common/logging/log.h" #include "video_core/engines/shader_bytecode.h" #include "video_core/shader/shader_ir.h" @@ -356,6 +357,24 @@ void ShaderIR::SetTemporal(BasicBlock& bb, u32 id, Node value) { SetRegister(bb, Register::ZeroIndex + 1 + id, value); } +void ShaderIR::SetInternalFlagsFromFloat(BasicBlock& bb, Node value, bool sets_cc) { + if (!sets_cc) { + return; + } + const Node zerop = Operation(OperationCode::LogicalFEqual, value, Immediate(0.0f)); + SetInternalFlag(bb, InternalFlag::Zero, zerop); + LOG_WARNING(HW_GPU, "Condition codes implementation is incomplete"); +} + +void ShaderIR::SetInternalFlagsFromInteger(BasicBlock& bb, Node value, bool sets_cc) { + if (!sets_cc) { + return; + } + const Node zerop = Operation(OperationCode::LogicalIEqual, value, Immediate(0)); + SetInternalFlag(bb, InternalFlag::Zero, zerop); + LOG_WARNING(HW_GPU, "Condition codes implementation is incomplete"); +} + Node ShaderIR::BitfieldExtract(Node value, u32 offset, u32 bits) { return Operation(OperationCode::UBitfieldExtract, NO_PRECISE, value, Immediate(offset), Immediate(bits)); -- cgit v1.2.3