summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/video_core/renderer_vulkan/vk_shader_decompiler.cpp66
1 files changed, 64 insertions, 2 deletions
diff --git a/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp b/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp
index 5060dbba9..9f717b836 100644
--- a/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp
+++ b/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp
@@ -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 {};
}