|
|
|
@ -693,7 +693,49 @@ private: |
|
|
|
} |
|
|
|
|
|
|
|
Id Assign(Operation operation) { |
|
|
|
UNIMPLEMENTED(); |
|
|
|
const Node dest = operation[0]; |
|
|
|
const Node src = operation[1]; |
|
|
|
|
|
|
|
Id target{}; |
|
|
|
if (const auto gpr = std::get_if<GprNode>(dest)) { |
|
|
|
if (gpr->GetIndex() == Register::ZeroIndex) { |
|
|
|
// Writing to Register::ZeroIndex is a no op
|
|
|
|
return {}; |
|
|
|
} |
|
|
|
target = registers.at(gpr->GetIndex()); |
|
|
|
|
|
|
|
} else if (const auto abuf = std::get_if<AbufNode>(dest)) { |
|
|
|
target = [&]() -> Id { |
|
|
|
switch (const auto attribute = abuf->GetIndex(); attribute) { |
|
|
|
case Attribute::Index::Position: |
|
|
|
return AccessElement(t_out_float, per_vertex, position_index, |
|
|
|
abuf->GetElement()); |
|
|
|
case Attribute::Index::PointSize: |
|
|
|
return AccessElement(t_out_float, per_vertex, point_size_index); |
|
|
|
case Attribute::Index::ClipDistances0123: |
|
|
|
return AccessElement(t_out_float, per_vertex, clip_distances_index, |
|
|
|
abuf->GetElement()); |
|
|
|
case Attribute::Index::ClipDistances4567: |
|
|
|
return AccessElement(t_out_float, per_vertex, clip_distances_index, |
|
|
|
abuf->GetElement() + 4); |
|
|
|
default: |
|
|
|
if (IsGenericAttribute(attribute)) { |
|
|
|
return AccessElement(t_out_float, output_attributes.at(attribute), |
|
|
|
abuf->GetElement()); |
|
|
|
} |
|
|
|
UNIMPLEMENTED_MSG("Unhandled output attribute: {}", |
|
|
|
static_cast<u32>(attribute)); |
|
|
|
return {}; |
|
|
|
} |
|
|
|
}(); |
|
|
|
|
|
|
|
} else if (const auto lmem = std::get_if<LmemNode>(dest)) { |
|
|
|
Id address = BitcastTo<Type::Uint>(Visit(lmem->GetAddress())); |
|
|
|
address = Emit(OpUDiv(t_uint, address, Constant(t_uint, 4))); |
|
|
|
target = Emit(OpAccessChain(t_prv_float, local_memory, {address})); |
|
|
|
} |
|
|
|
|
|
|
|
Emit(OpStore(target, Visit(src))); |
|
|
|
return {}; |
|
|
|
} |
|
|
|
|
|
|
|
@ -723,7 +765,27 @@ private: |
|
|
|
} |
|
|
|
|
|
|
|
Id LogicalAssign(Operation operation) { |
|
|
|
UNIMPLEMENTED(); |
|
|
|
const Node dest = operation[0]; |
|
|
|
const Node src = operation[1]; |
|
|
|
|
|
|
|
Id target{}; |
|
|
|
if (const auto pred = std::get_if<PredicateNode>(dest)) { |
|
|
|
ASSERT_MSG(!pred->IsNegated(), "Negating logical assignment"); |
|
|
|
|
|
|
|
const auto index = pred->GetIndex(); |
|
|
|
switch (index) { |
|
|
|
case Tegra::Shader::Pred::NeverExecute: |
|
|
|
case Tegra::Shader::Pred::UnusedIndex: |
|
|
|
// Writing to these predicates is a no-op
|
|
|
|
return {}; |
|
|
|
} |
|
|
|
target = predicates.at(index); |
|
|
|
|
|
|
|
} else if (const auto flag = std::get_if<InternalFlagNode>(dest)) { |
|
|
|
target = internal_flags.at(static_cast<u32>(flag->GetFlag())); |
|
|
|
} |
|
|
|
|
|
|
|
Emit(OpStore(target, Visit(src))); |
|
|
|
return {}; |
|
|
|
} |
|
|
|
|
|
|
|
|