summaryrefslogtreecommitdiff
path: root/src/shader_recompiler
diff options
context:
space:
mode:
Diffstat (limited to 'src/shader_recompiler')
-rw-r--r--src/shader_recompiler/backend/spirv/spirv_emit_context.cpp60
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
98Id DefineVariable(EmitContext& ctx, Id type, std::optional<spv::BuiltIn> builtin, 98Id 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
146Id DefineOutput(EmitContext& ctx, Id type, std::optional<u32> invocations, 146Id 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
154void DefineGenericOutput(EmitContext& ctx, size_t index, std::optional<u32> invocations) { 155void 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)) {