diff options
Diffstat (limited to 'src/shader_recompiler')
| -rw-r--r-- | src/shader_recompiler/backend/spirv/spirv_emit_context.cpp | 60 |
1 files changed, 38 insertions, 22 deletions
diff --git a/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp b/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp index ed023fcfe..89ebab08e 100644 --- a/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp +++ b/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp | |||
| @@ -96,9 +96,9 @@ Id ImageType(EmitContext& ctx, const ImageDescriptor& desc, Id sampled_type) { | |||
| 96 | } | 96 | } |
| 97 | 97 | ||
| 98 | Id DefineVariable(EmitContext& ctx, Id type, std::optional<spv::BuiltIn> builtin, | 98 | Id DefineVariable(EmitContext& ctx, Id type, std::optional<spv::BuiltIn> builtin, |
| 99 | spv::StorageClass storage_class) { | 99 | spv::StorageClass storage_class, std::optional<Id> initializer = std::nullopt) { |
| 100 | const Id pointer_type{ctx.TypePointer(storage_class, type)}; | 100 | const Id pointer_type{ctx.TypePointer(storage_class, type)}; |
| 101 | const Id id{ctx.AddGlobalVariable(pointer_type, storage_class)}; | 101 | const Id id{ctx.AddGlobalVariable(pointer_type, storage_class, initializer)}; |
| 102 | if (builtin) { | 102 | if (builtin) { |
| 103 | ctx.Decorate(id, spv::Decoration::BuiltIn, *builtin); | 103 | ctx.Decorate(id, spv::Decoration::BuiltIn, *builtin); |
| 104 | } | 104 | } |
| @@ -144,11 +144,12 @@ Id DefineInput(EmitContext& ctx, Id type, bool per_invocation, | |||
| 144 | } | 144 | } |
| 145 | 145 | ||
| 146 | Id DefineOutput(EmitContext& ctx, Id type, std::optional<u32> invocations, | 146 | Id DefineOutput(EmitContext& ctx, Id type, std::optional<u32> invocations, |
| 147 | std::optional<spv::BuiltIn> builtin = std::nullopt) { | 147 | std::optional<spv::BuiltIn> builtin = std::nullopt, |
| 148 | std::optional<Id> initializer = std::nullopt) { | ||
| 148 | if (invocations && ctx.stage == Stage::TessellationControl) { | 149 | if (invocations && ctx.stage == Stage::TessellationControl) { |
| 149 | type = ctx.TypeArray(type, ctx.Const(*invocations)); | 150 | type = ctx.TypeArray(type, ctx.Const(*invocations)); |
| 150 | } | 151 | } |
| 151 | return DefineVariable(ctx, type, builtin, spv::StorageClass::Output); | 152 | return DefineVariable(ctx, type, builtin, spv::StorageClass::Output, initializer); |
| 152 | } | 153 | } |
| 153 | 154 | ||
| 154 | void DefineGenericOutput(EmitContext& ctx, size_t index, std::optional<u32> invocations) { | 155 | void DefineGenericOutput(EmitContext& ctx, size_t index, std::optional<u32> invocations) { |
| @@ -811,10 +812,14 @@ void EmitContext::DefineAttributeMemAccess(const Info& info) { | |||
| 811 | labels.push_back(OpLabel()); | 812 | labels.push_back(OpLabel()); |
| 812 | } | 813 | } |
| 813 | if (info.stores.ClipDistances()) { | 814 | if (info.stores.ClipDistances()) { |
| 814 | literals.push_back(static_cast<u32>(IR::Attribute::ClipDistance0) >> 2); | 815 | if (profile.max_user_clip_distances >= 4) { |
| 815 | labels.push_back(OpLabel()); | 816 | literals.push_back(static_cast<u32>(IR::Attribute::ClipDistance0) >> 2); |
| 816 | literals.push_back(static_cast<u32>(IR::Attribute::ClipDistance4) >> 2); | 817 | labels.push_back(OpLabel()); |
| 817 | labels.push_back(OpLabel()); | 818 | } |
| 819 | if (profile.max_user_clip_distances >= 8) { | ||
| 820 | literals.push_back(static_cast<u32>(IR::Attribute::ClipDistance4) >> 2); | ||
| 821 | labels.push_back(OpLabel()); | ||
| 822 | } | ||
| 818 | } | 823 | } |
| 819 | OpSelectionMerge(end_block, spv::SelectionControlMask::MaskNone); | 824 | OpSelectionMerge(end_block, spv::SelectionControlMask::MaskNone); |
| 820 | OpSwitch(compare_index, default_label, literals, labels); | 825 | OpSwitch(compare_index, default_label, literals, labels); |
| @@ -843,17 +848,21 @@ void EmitContext::DefineAttributeMemAccess(const Info& info) { | |||
| 843 | ++label_index; | 848 | ++label_index; |
| 844 | } | 849 | } |
| 845 | if (info.stores.ClipDistances()) { | 850 | if (info.stores.ClipDistances()) { |
| 846 | AddLabel(labels[label_index]); | 851 | if (profile.max_user_clip_distances >= 4) { |
| 847 | const Id pointer{OpAccessChain(output_f32, clip_distances, masked_index)}; | 852 | AddLabel(labels[label_index]); |
| 848 | OpStore(pointer, store_value); | 853 | const Id pointer{OpAccessChain(output_f32, clip_distances, masked_index)}; |
| 849 | OpReturn(); | 854 | OpStore(pointer, store_value); |
| 850 | ++label_index; | 855 | OpReturn(); |
| 851 | AddLabel(labels[label_index]); | 856 | ++label_index; |
| 852 | const Id fixed_index{OpIAdd(U32[1], masked_index, Const(4U))}; | 857 | } |
| 853 | const Id pointer2{OpAccessChain(output_f32, clip_distances, fixed_index)}; | 858 | if (profile.max_user_clip_distances >= 8) { |
| 854 | OpStore(pointer2, store_value); | 859 | AddLabel(labels[label_index]); |
| 855 | OpReturn(); | 860 | const Id fixed_index{OpIAdd(U32[1], masked_index, Const(4U))}; |
| 856 | ++label_index; | 861 | const Id pointer{OpAccessChain(output_f32, clip_distances, fixed_index)}; |
| 862 | OpStore(pointer, store_value); | ||
| 863 | OpReturn(); | ||
| 864 | ++label_index; | ||
| 865 | } | ||
| 857 | } | 866 | } |
| 858 | AddLabel(end_block); | 867 | AddLabel(end_block); |
| 859 | OpUnreachable(); | 868 | OpUnreachable(); |
| @@ -1532,9 +1541,16 @@ void EmitContext::DefineOutputs(const IR::Program& program) { | |||
| 1532 | if (stage == Stage::Fragment) { | 1541 | if (stage == Stage::Fragment) { |
| 1533 | throw NotImplementedException("Storing ClipDistance in fragment stage"); | 1542 | throw NotImplementedException("Storing ClipDistance in fragment stage"); |
| 1534 | } | 1543 | } |
| 1535 | const Id type{TypeArray( | 1544 | if (profile.max_user_clip_distances > 0) { |
| 1536 | F32[1], Const(std::min(info.used_clip_distances, profile.max_user_clip_distances)))}; | 1545 | const u32 used{std::min(profile.max_user_clip_distances, 8u)}; |
| 1537 | clip_distances = DefineOutput(*this, type, invocations, spv::BuiltIn::ClipDistance); | 1546 | const std::array<Id, 8> zero{f32_zero_value, f32_zero_value, f32_zero_value, |
| 1547 | f32_zero_value, f32_zero_value, f32_zero_value, | ||
| 1548 | f32_zero_value, f32_zero_value}; | ||
| 1549 | const Id type{TypeArray(F32[1], Const(used))}; | ||
| 1550 | const Id initializer{ConstantComposite(type, std::span(zero).subspan(0, used))}; | ||
| 1551 | clip_distances = | ||
| 1552 | DefineOutput(*this, type, invocations, spv::BuiltIn::ClipDistance, initializer); | ||
| 1553 | } | ||
| 1538 | } | 1554 | } |
| 1539 | if (info.stores[IR::Attribute::Layer] && | 1555 | if (info.stores[IR::Attribute::Layer] && |
| 1540 | (profile.support_viewport_index_layer_non_geometry || stage == Stage::Geometry)) { | 1556 | (profile.support_viewport_index_layer_non_geometry || stage == Stage::Geometry)) { |