summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar ReinUsesLisp2019-03-14 02:48:16 -0300
committerGravatar ReinUsesLisp2019-04-10 14:20:25 -0300
commit75d23a36790a18e00e2d102ddd9ccbc4943d7a2f (patch)
tree8e83468c0b1d63db637048504de658b676adabd1 /src
parentvk_shader_decompiler: Implement most common texture primitives (diff)
downloadyuzu-75d23a36790a18e00e2d102ddd9ccbc4943d7a2f.tar.gz
yuzu-75d23a36790a18e00e2d102ddd9ccbc4943d7a2f.tar.xz
yuzu-75d23a36790a18e00e2d102ddd9ccbc4943d7a2f.zip
vk_shader_decompiler: Implement flow primitives
Diffstat (limited to 'src')
-rw-r--r--src/video_core/renderer_vulkan/vk_shader_decompiler.cpp87
1 files changed, 82 insertions, 5 deletions
diff --git a/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp b/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp
index 6c5c6500a..e0a6f5e87 100644
--- a/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp
+++ b/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp
@@ -924,27 +924,93 @@ private:
924 } 924 }
925 925
926 Id Branch(Operation operation) { 926 Id Branch(Operation operation) {
927 UNIMPLEMENTED(); 927 const auto target = std::get_if<ImmediateNode>(operation[0]);
928 UNIMPLEMENTED_IF(!target);
929
930 Emit(OpStore(jmp_to, Constant(t_uint, target->GetValue())));
931 BranchingOp([&]() { Emit(OpBranch(continue_label)); });
928 return {}; 932 return {};
929 } 933 }
930 934
931 Id PushFlowStack(Operation operation) { 935 Id PushFlowStack(Operation operation) {
932 UNIMPLEMENTED(); 936 const auto target = std::get_if<ImmediateNode>(operation[0]);
937 ASSERT(target);
938
939 const Id current = Emit(OpLoad(t_uint, flow_stack_top));
940 const Id next = Emit(OpIAdd(t_uint, current, Constant(t_uint, 1)));
941 const Id access = Emit(OpAccessChain(t_func_uint, flow_stack, current));
942
943 Emit(OpStore(access, Constant(t_uint, target->GetValue())));
944 Emit(OpStore(flow_stack_top, next));
933 return {}; 945 return {};
934 } 946 }
935 947
936 Id PopFlowStack(Operation operation) { 948 Id PopFlowStack(Operation operation) {
937 UNIMPLEMENTED(); 949 const Id current = Emit(OpLoad(t_uint, flow_stack_top));
950 const Id previous = Emit(OpISub(t_uint, current, Constant(t_uint, 1)));
951 const Id access = Emit(OpAccessChain(t_func_uint, flow_stack, previous));
952 const Id target = Emit(OpLoad(t_uint, access));
953
954 Emit(OpStore(flow_stack_top, previous));
955 Emit(OpStore(jmp_to, target));
956 BranchingOp([&]() { Emit(OpBranch(continue_label)); });
938 return {}; 957 return {};
939 } 958 }
940 959
941 Id Exit(Operation operation) { 960 Id Exit(Operation operation) {
942 UNIMPLEMENTED(); 961 switch (stage) {
962 case ShaderStage::Vertex: {
963 // TODO(Rodrigo): We should use VK_EXT_depth_range_unrestricted instead, but it doesn't
964 // seem to be working on Nvidia's drivers and Intel (mesa and blob) doesn't support it.
965 const Id position = AccessElement(t_float4, per_vertex, position_index);
966 Id depth = Emit(OpLoad(t_float, AccessElement(t_out_float, position, 2)));
967 depth = Emit(OpFAdd(t_float, depth, Constant(t_float, 1.0f)));
968 depth = Emit(OpFMul(t_float, depth, Constant(t_float, 0.5f)));
969 Emit(OpStore(AccessElement(t_out_float, position, 2), depth));
970 break;
971 }
972 case ShaderStage::Fragment: {
973 const auto SafeGetRegister = [&](u32 reg) {
974 // TODO(Rodrigo): Replace with contains once C++20 releases
975 if (const auto it = registers.find(reg); it != registers.end()) {
976 return Emit(OpLoad(t_float, it->second));
977 }
978 return Constant(t_float, 0.0f);
979 };
980
981 UNIMPLEMENTED_IF_MSG(header.ps.omap.sample_mask != 0,
982 "Sample mask write is unimplemented");
983
984 // TODO(Rodrigo): Alpha testing
985
986 // Write the color outputs using the data in the shader registers, disabled
987 // rendertargets/components are skipped in the register assignment.
988 u32 current_reg = 0;
989 for (u32 rt = 0; rt < Maxwell::NumRenderTargets; ++rt) {
990 // TODO(Subv): Figure out how dual-source blending is configured in the Switch.
991 for (u32 component = 0; component < 4; ++component) {
992 if (header.ps.IsColorComponentOutputEnabled(rt, component)) {
993 Emit(OpStore(AccessElement(t_out_float, frag_colors.at(rt), component),
994 SafeGetRegister(current_reg)));
995 ++current_reg;
996 }
997 }
998 }
999 if (header.ps.omap.depth) {
1000 // The depth output is always 2 registers after the last color output, and
1001 // current_reg already contains one past the last color register.
1002 Emit(OpStore(frag_depth, SafeGetRegister(current_reg + 1)));
1003 }
1004 break;
1005 }
1006 }
1007
1008 BranchingOp([&]() { Emit(OpReturn()); });
943 return {}; 1009 return {};
944 } 1010 }
945 1011
946 Id Discard(Operation operation) { 1012 Id Discard(Operation operation) {
947 UNIMPLEMENTED(); 1013 BranchingOp([&]() { Emit(OpKill()); });
948 return {}; 1014 return {};
949 } 1015 }
950 1016
@@ -1067,6 +1133,17 @@ private:
1067 return {}; 1133 return {};
1068 } 1134 }
1069 1135
1136 void BranchingOp(std::function<void()> call) {
1137 const Id true_label = OpLabel();
1138 const Id skip_label = OpLabel();
1139 Emit(OpSelectionMerge(skip_label, spv::SelectionControlMask::Flatten));
1140 Emit(OpBranchConditional(v_true, true_label, skip_label, 1, 0));
1141 Emit(true_label);
1142 call();
1143
1144 Emit(skip_label);
1145 }
1146
1070 static constexpr OperationDecompilersArray operation_decompilers = { 1147 static constexpr OperationDecompilersArray operation_decompilers = {
1071 &SPIRVDecompiler::Assign, 1148 &SPIRVDecompiler::Assign,
1072 1149