shader_ir: std::move Node instance where applicable
These are std::shared_ptr instances underneath the hood, which means copying them isn't as cheap as a regular pointer. Particularly so on weakly-ordered systems. This avoids atomic reference count increments and decrements where they aren't necessary for the core set of operations.
This commit is contained in:
parent
60926ac16b
commit
bebbdc2067
|
@ -46,12 +46,12 @@ void ShaderIR::Decode() {
|
|||
coverage_end = shader_info.end;
|
||||
if (shader_info.decompilable) {
|
||||
disable_flow_stack = true;
|
||||
const auto insert_block = ([this](NodeBlock& nodes, u32 label) {
|
||||
const auto insert_block = [this](NodeBlock& nodes, u32 label) {
|
||||
if (label == exit_branch) {
|
||||
return;
|
||||
}
|
||||
basic_blocks.insert({label, nodes});
|
||||
});
|
||||
};
|
||||
const auto& blocks = shader_info.blocks;
|
||||
NodeBlock current_block;
|
||||
u32 current_label = exit_branch;
|
||||
|
@ -103,7 +103,7 @@ void ShaderIR::DecodeRangeInner(NodeBlock& bb, u32 begin, u32 end) {
|
|||
}
|
||||
|
||||
void ShaderIR::InsertControlFlow(NodeBlock& bb, const ShaderBlock& block) {
|
||||
const auto apply_conditions = ([&](const Condition& cond, Node n) -> Node {
|
||||
const auto apply_conditions = [&](const Condition& cond, Node n) -> Node {
|
||||
Node result = n;
|
||||
if (cond.cc != ConditionCode::T) {
|
||||
result = Conditional(GetConditionCode(cond.cc), {result});
|
||||
|
@ -117,7 +117,7 @@ void ShaderIR::InsertControlFlow(NodeBlock& bb, const ShaderBlock& block) {
|
|||
result = Conditional(GetPredicate(pred, is_neg), {result});
|
||||
}
|
||||
return result;
|
||||
});
|
||||
};
|
||||
if (block.branch.address < 0) {
|
||||
if (block.branch.kills) {
|
||||
Node n = Operation(OperationCode::Discard);
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
namespace VideoCommon::Shader {
|
||||
|
||||
Node Conditional(Node condition, std::vector<Node> code) {
|
||||
return MakeNode<ConditionalNode>(condition, std::move(code));
|
||||
return MakeNode<ConditionalNode>(std::move(condition), std::move(code));
|
||||
}
|
||||
|
||||
Node Comment(std::string text) {
|
||||
|
|
|
@ -61,7 +61,7 @@ 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 = [&]() {
|
||||
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)) {
|
||||
|
@ -69,9 +69,9 @@ Node ShaderIR::GetConstBufferIndirect(u64 index_, u64 offset_, Node node) {
|
|||
return Immediate(offset);
|
||||
}
|
||||
}
|
||||
return Operation(OperationCode::UAdd, NO_PRECISE, node, Immediate(offset));
|
||||
return Operation(OperationCode::UAdd, NO_PRECISE, std::move(node), Immediate(offset));
|
||||
}();
|
||||
return MakeNode<CbufNode>(index, final_offset);
|
||||
return MakeNode<CbufNode>(index, std::move(final_offset));
|
||||
}
|
||||
|
||||
Node ShaderIR::GetPredicate(u64 pred_, bool negated) {
|
||||
|
@ -89,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) {
|
||||
|
@ -122,7 +122,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) {
|
||||
|
@ -134,7 +134,7 @@ Node ShaderIR::GetInternalFlag(InternalFlag flag, bool negated) {
|
|||
}
|
||||
|
||||
Node ShaderIR::GetLocalMemory(Node address) {
|
||||
return MakeNode<LmemNode>(address);
|
||||
return MakeNode<LmemNode>(std::move(address));
|
||||
}
|
||||
|
||||
Node ShaderIR::GetTemporary(u32 id) {
|
||||
|
@ -143,10 +143,10 @@ Node ShaderIR::GetTemporary(u32 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;
|
||||
}
|
||||
|
@ -155,24 +155,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;
|
||||
|
@ -188,27 +190,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) {
|
||||
|
@ -216,11 +220,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;
|
||||
|
@ -228,10 +232,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;
|
||||
|
@ -241,9 +245,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) {
|
||||
|
@ -271,7 +277,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,
|
||||
|
@ -300,7 +305,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 ||
|
||||
|
@ -330,9 +336,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) {
|
||||
|
@ -358,31 +362,32 @@ 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::SetTemporary(NodeBlock& bb, u32 id, Node value) {
|
||||
SetRegister(bb, Register::ZeroIndex + 1 + id, 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");
|
||||
}
|
||||
|
||||
|
@ -390,14 +395,14 @@ 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),
|
||||
Immediate(bits));
|
||||
return Operation(OperationCode::UBitfieldExtract, NO_PRECISE, std::move(value),
|
||||
Immediate(offset), Immediate(bits));
|
||||
}
|
||||
|
||||
} // namespace VideoCommon::Shader
|
||||
|
|
|
@ -15,18 +15,20 @@ namespace {
|
|||
std::pair<Node, s64> FindOperation(const NodeBlock& code, s64 cursor,
|
||||
OperationCode operation_code) {
|
||||
for (; cursor >= 0; --cursor) {
|
||||
const Node node = code.at(cursor);
|
||||
Node node = code.at(cursor);
|
||||
|
||||
if (const auto operation = std::get_if<OperationNode>(&*node)) {
|
||||
if (operation->GetCode() == operation_code) {
|
||||
return {node, cursor};
|
||||
return {std::move(node), cursor};
|
||||
}
|
||||
}
|
||||
|
||||
if (const auto conditional = std::get_if<ConditionalNode>(&*node)) {
|
||||
const auto& conditional_code = conditional->GetCode();
|
||||
const auto [found, internal_cursor] = FindOperation(
|
||||
auto [found, internal_cursor] = FindOperation(
|
||||
conditional_code, static_cast<s64>(conditional_code.size() - 1), operation_code);
|
||||
if (found) {
|
||||
return {found, cursor};
|
||||
return {std::move(found), cursor};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Reference in New Issue