From 676172e20d0a0c2f92ace94ca7cfb37a862fd8dc Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Thu, 14 Mar 2019 02:44:23 -0300 Subject: [PATCH] vk_shader_decompiler: Implement Assign and LogicalAssign --- .../renderer_vulkan/vk_shader_decompiler.cpp | 66 ++++++++++++++++++- 1 file 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(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(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(attribute)); + return {}; + } + }(); + + } else if (const auto lmem = std::get_if(dest)) { + Id address = BitcastTo(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(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(dest)) { + target = internal_flags.at(static_cast(flag->GetFlag())); + } + + Emit(OpStore(target, Visit(src))); return {}; }