diff options
| author | 2019-03-14 02:48:16 -0300 | |
|---|---|---|
| committer | 2019-04-10 14:20:25 -0300 | |
| commit | 75d23a36790a18e00e2d102ddd9ccbc4943d7a2f (patch) | |
| tree | 8e83468c0b1d63db637048504de658b676adabd1 /src | |
| parent | vk_shader_decompiler: Implement most common texture primitives (diff) | |
| download | yuzu-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.cpp | 87 |
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 | ||