diff options
Diffstat (limited to '')
-rw-r--r-- | src/video_core/shader/shader_ir.cpp | 162 |
1 files changed, 109 insertions, 53 deletions
diff --git a/src/video_core/shader/shader_ir.cpp b/src/video_core/shader/shader_ir.cpp index 11b545cca..2c357f310 100644 --- a/src/video_core/shader/shader_ir.cpp +++ b/src/video_core/shader/shader_ir.cpp @@ -22,8 +22,8 @@ using Tegra::Shader::PredCondition; using Tegra::Shader::PredOperation; using Tegra::Shader::Register; -ShaderIR::ShaderIR(const ProgramCode& program_code, u32 main_offset) - : program_code{program_code}, main_offset{main_offset} { +ShaderIR::ShaderIR(const ProgramCode& program_code, u32 main_offset, const std::size_t size) + : program_code{program_code}, main_offset{main_offset}, program_size{size} { Decode(); } @@ -61,8 +61,17 @@ Node ShaderIR::GetConstBufferIndirect(u64 index_, u64 offset_, Node node) { 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 MakeNode<CbufNode>(index, final_offset); + Node final_offset = [&] { + // Attempt to inline constant buffer without a variable offset. This is done to allow + // tracking LDC calls. + if (const auto gpr = std::get_if<GprNode>(&*node)) { + if (gpr->GetIndex() == Register::ZeroIndex) { + return Immediate(offset); + } + } + return Operation(OperationCode::UAdd, NO_PRECISE, std::move(node), Immediate(offset)); + }(); + return MakeNode<CbufNode>(index, std::move(final_offset)); } Node ShaderIR::GetPredicate(u64 pred_, bool negated) { @@ -80,7 +89,7 @@ Node ShaderIR::GetPredicate(bool immediate) { Node ShaderIR::GetInputAttribute(Attribute::Index index, u64 element, Node buffer) { used_input_attributes.emplace(index); - return MakeNode<AbufNode>(index, static_cast<u32>(element), buffer); + return MakeNode<AbufNode>(index, static_cast<u32>(element), std::move(buffer)); } Node ShaderIR::GetPhysicalInputAttribute(Tegra::Shader::Register physical_address, Node buffer) { @@ -89,6 +98,34 @@ Node ShaderIR::GetPhysicalInputAttribute(Tegra::Shader::Register physical_addres } Node ShaderIR::GetOutputAttribute(Attribute::Index index, u64 element, Node buffer) { + if (index == Attribute::Index::LayerViewportPointSize) { + switch (element) { + case 0: + UNIMPLEMENTED(); + break; + case 1: + uses_layer = true; + break; + case 2: + uses_viewport_index = true; + break; + case 3: + uses_point_size = true; + break; + } + } + if (index == Attribute::Index::TessCoordInstanceIDVertexID) { + switch (element) { + case 2: + uses_instance_id = true; + break; + case 3: + uses_vertex_id = true; + break; + default: + break; + } + } if (index == Attribute::Index::ClipDistances0123 || index == Attribute::Index::ClipDistances4567) { const auto clip_index = @@ -97,7 +134,7 @@ Node ShaderIR::GetOutputAttribute(Attribute::Index index, u64 element, Node buff } used_output_attributes.insert(index); - return MakeNode<AbufNode>(index, static_cast<u32>(element), buffer); + return MakeNode<AbufNode>(index, static_cast<u32>(element), std::move(buffer)); } Node ShaderIR::GetInternalFlag(InternalFlag flag, bool negated) { @@ -109,19 +146,23 @@ Node ShaderIR::GetInternalFlag(InternalFlag flag, bool negated) { } Node ShaderIR::GetLocalMemory(Node address) { - return MakeNode<LmemNode>(address); + return MakeNode<LmemNode>(std::move(address)); +} + +Node ShaderIR::GetSharedMemory(Node address) { + return MakeNode<SmemNode>(std::move(address)); } -Node ShaderIR::GetTemporal(u32 id) { +Node ShaderIR::GetTemporary(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); + value = Operation(OperationCode::FAbsolute, NO_PRECISE, std::move(value)); } if (negate) { - value = Operation(OperationCode::FNegate, NO_PRECISE, value); + value = Operation(OperationCode::FNegate, NO_PRECISE, std::move(value)); } return value; } @@ -130,24 +171,26 @@ 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); + + Node positive_zero = Immediate(std::copysignf(0, 1)); + Node positive_one = Immediate(1.0f); + return Operation(OperationCode::FClamp, NO_PRECISE, std::move(value), std::move(positive_zero), + std::move(positive_one)); } -Node ShaderIR::ConvertIntegerSize(Node value, Tegra::Shader::Register::Size size, bool is_signed) { +Node ShaderIR::ConvertIntegerSize(Node value, 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)); + value = SignedOperation(OperationCode::ILogicalShiftLeft, is_signed, NO_PRECISE, + std::move(value), Immediate(24)); + value = SignedOperation(OperationCode::IArithmeticShiftRight, is_signed, NO_PRECISE, + std::move(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)); + value = SignedOperation(OperationCode::ILogicalShiftLeft, is_signed, NO_PRECISE, + std::move(value), Immediate(16)); + value = SignedOperation(OperationCode::IArithmeticShiftRight, is_signed, NO_PRECISE, + std::move(value), Immediate(16)); case Register::Size::Word: // Default - do nothing return value; @@ -163,27 +206,29 @@ Node ShaderIR::GetOperandAbsNegInteger(Node value, bool absolute, bool negate, b return value; } if (absolute) { - value = Operation(OperationCode::IAbsolute, NO_PRECISE, value); + value = Operation(OperationCode::IAbsolute, NO_PRECISE, std::move(value)); } if (negate) { - value = Operation(OperationCode::INegate, NO_PRECISE, value); + value = Operation(OperationCode::INegate, NO_PRECISE, std::move(value)); } return value; } Node ShaderIR::UnpackHalfImmediate(Instruction instr, bool has_negation) { - const Node value = Immediate(instr.half_imm.PackImmediates()); + 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, NO_PRECISE, value, first_negate, second_negate); + Node first_negate = GetPredicate(instr.half_imm.first_negate != 0); + Node second_negate = GetPredicate(instr.half_imm.second_negate != 0); + + return Operation(OperationCode::HNegate, NO_PRECISE, std::move(value), std::move(first_negate), + std::move(second_negate)); } Node ShaderIR::UnpackHalfFloat(Node value, Tegra::Shader::HalfType type) { - return Operation(OperationCode::HUnpack, type, value); + return Operation(OperationCode::HUnpack, type, std::move(value)); } Node ShaderIR::HalfMerge(Node dest, Node src, Tegra::Shader::HalfMerge merge) { @@ -191,11 +236,11 @@ Node ShaderIR::HalfMerge(Node dest, Node src, Tegra::Shader::HalfMerge merge) { case Tegra::Shader::HalfMerge::H0_H1: return src; case Tegra::Shader::HalfMerge::F32: - return Operation(OperationCode::HMergeF32, src); + return Operation(OperationCode::HMergeF32, std::move(src)); case Tegra::Shader::HalfMerge::Mrg_H0: - return Operation(OperationCode::HMergeH0, dest, src); + return Operation(OperationCode::HMergeH0, std::move(dest), std::move(src)); case Tegra::Shader::HalfMerge::Mrg_H1: - return Operation(OperationCode::HMergeH1, dest, src); + return Operation(OperationCode::HMergeH1, std::move(dest), std::move(src)); } UNREACHABLE(); return src; @@ -203,10 +248,10 @@ Node ShaderIR::HalfMerge(Node dest, Node src, Tegra::Shader::HalfMerge merge) { Node ShaderIR::GetOperandAbsNegHalf(Node value, bool absolute, bool negate) { if (absolute) { - value = Operation(OperationCode::HAbsolute, NO_PRECISE, value); + value = Operation(OperationCode::HAbsolute, NO_PRECISE, std::move(value)); } if (negate) { - value = Operation(OperationCode::HNegate, NO_PRECISE, value, GetPredicate(true), + value = Operation(OperationCode::HNegate, NO_PRECISE, std::move(value), GetPredicate(true), GetPredicate(true)); } return value; @@ -216,9 +261,11 @@ Node ShaderIR::GetSaturatedHalfFloat(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::HClamp, NO_PRECISE, value, positive_zero, positive_one); + + Node positive_zero = Immediate(std::copysignf(0, 1)); + Node positive_one = Immediate(1.0f); + return Operation(OperationCode::HClamp, NO_PRECISE, std::move(value), std::move(positive_zero), + std::move(positive_one)); } Node ShaderIR::GetPredicateComparisonFloat(PredCondition condition, Node op_a, Node op_b) { @@ -246,7 +293,6 @@ Node ShaderIR::GetPredicateComparisonFloat(PredCondition condition, Node op_a, N condition == PredCondition::LessEqualWithNan || condition == PredCondition::GreaterThanWithNan || condition == PredCondition::GreaterEqualWithNan) { - predicate = Operation(OperationCode::LogicalOr, predicate, Operation(OperationCode::LogicalFIsNan, op_a)); predicate = Operation(OperationCode::LogicalOr, predicate, @@ -275,7 +321,8 @@ Node ShaderIR::GetPredicateComparisonInteger(PredCondition condition, bool is_si UNIMPLEMENTED_IF_MSG(comparison == PredicateComparisonTable.end(), "Unknown predicate comparison operation"); - Node predicate = SignedOperation(comparison->second, is_signed, NO_PRECISE, op_a, op_b); + Node predicate = SignedOperation(comparison->second, is_signed, NO_PRECISE, std::move(op_a), + std::move(op_b)); UNIMPLEMENTED_IF_MSG(condition == PredCondition::LessThanWithNan || condition == PredCondition::NotEqualWithNan || @@ -305,9 +352,7 @@ Node ShaderIR::GetPredicateComparisonHalf(Tegra::Shader::PredCondition condition UNIMPLEMENTED_IF_MSG(comparison == PredicateComparisonTable.end(), "Unknown predicate comparison operation"); - const Node predicate = Operation(comparison->second, NO_PRECISE, op_a, op_b); - - return predicate; + return Operation(comparison->second, NO_PRECISE, std::move(op_a), std::move(op_b)); } OperationCode ShaderIR::GetPredicateCombiner(PredOperation operation) { @@ -333,31 +378,37 @@ Node ShaderIR::GetConditionCode(Tegra::Shader::ConditionCode cc) { } void ShaderIR::SetRegister(NodeBlock& bb, Register dest, Node src) { - bb.push_back(Operation(OperationCode::Assign, GetRegister(dest), src)); + bb.push_back(Operation(OperationCode::Assign, GetRegister(dest), std::move(src))); } void ShaderIR::SetPredicate(NodeBlock& bb, u64 dest, Node src) { - bb.push_back(Operation(OperationCode::LogicalAssign, GetPredicate(dest), src)); + bb.push_back(Operation(OperationCode::LogicalAssign, GetPredicate(dest), std::move(src))); } void ShaderIR::SetInternalFlag(NodeBlock& bb, InternalFlag flag, Node value) { - bb.push_back(Operation(OperationCode::LogicalAssign, GetInternalFlag(flag), value)); + bb.push_back(Operation(OperationCode::LogicalAssign, GetInternalFlag(flag), std::move(value))); } void ShaderIR::SetLocalMemory(NodeBlock& bb, Node address, Node value) { - bb.push_back(Operation(OperationCode::Assign, GetLocalMemory(address), value)); + bb.push_back( + Operation(OperationCode::Assign, GetLocalMemory(std::move(address)), std::move(value))); } -void ShaderIR::SetTemporal(NodeBlock& bb, u32 id, Node value) { - SetRegister(bb, Register::ZeroIndex + 1 + id, value); +void ShaderIR::SetSharedMemory(NodeBlock& bb, Node address, Node value) { + bb.push_back( + Operation(OperationCode::Assign, GetSharedMemory(std::move(address)), std::move(value))); +} + +void ShaderIR::SetTemporary(NodeBlock& bb, u32 id, Node value) { + SetRegister(bb, Register::ZeroIndex + 1 + id, std::move(value)); } void ShaderIR::SetInternalFlagsFromFloat(NodeBlock& 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); + Node zerop = Operation(OperationCode::LogicalFEqual, std::move(value), Immediate(0.0f)); + SetInternalFlag(bb, InternalFlag::Zero, std::move(zerop)); LOG_WARNING(HW_GPU, "Condition codes implementation is incomplete"); } @@ -365,13 +416,18 @@ void ShaderIR::SetInternalFlagsFromInteger(NodeBlock& bb, Node value, bool sets_ if (!sets_cc) { return; } - const Node zerop = Operation(OperationCode::LogicalIEqual, value, Immediate(0)); - SetInternalFlag(bb, InternalFlag::Zero, zerop); + Node zerop = Operation(OperationCode::LogicalIEqual, std::move(value), Immediate(0)); + SetInternalFlag(bb, InternalFlag::Zero, std::move(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), + return Operation(OperationCode::UBitfieldExtract, NO_PRECISE, std::move(value), + Immediate(offset), Immediate(bits)); +} + +Node ShaderIR::BitfieldInsert(Node base, Node insert, u32 offset, u32 bits) { + return Operation(OperationCode::UBitfieldInsert, NO_PRECISE, base, insert, Immediate(offset), Immediate(bits)); } |