Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/KhronosGroup/SPIRV-Cross.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBill Hollings <bill.hollings@brenwill.com>2021-11-12 22:17:00 +0300
committerBill Hollings <bill.hollings@brenwill.com>2021-11-12 22:17:00 +0300
commit248e9ae9ed583f37b2bc5205535a9530fd2ac90b (patch)
tree52d1343dea5321239257467ac59b0e05bc5c7b75
parent401296d3b8fc60193e99ccabb81eb3e4fe2dd802 (diff)
MSL: Don't output depth and stencil values with explicit early fragment tests.
Fragment shaders that require explicit early fragment tests are incompatible with specifying depth and stencil values within the shader. If explicit early fragment tests is specified, remove the depth and stencil outputs from the output structure, and replace them with dummy local variables. Add CompilerMSL:uses_explicit_early_fragment_test() function to consolidate testing for whether early fragment tests are required. Add two unit tests for depth-out with, and without, early fragment tests.
-rw-r--r--reference/opt/shaders-msl/frag/depth-out-early-frag-tests.frag19
-rw-r--r--reference/opt/shaders-msl/frag/depth-out-no-early-frag-tests.frag19
-rw-r--r--reference/shaders-msl/frag/depth-out-early-frag-tests.frag19
-rw-r--r--reference/shaders-msl/frag/depth-out-no-early-frag-tests.frag19
-rw-r--r--shaders-msl/frag/depth-out-early-frag-tests.frag11
-rw-r--r--shaders-msl/frag/depth-out-no-early-frag-tests.frag10
-rw-r--r--spirv_msl.cpp23
-rw-r--r--spirv_msl.hpp2
8 files changed, 115 insertions, 7 deletions
diff --git a/reference/opt/shaders-msl/frag/depth-out-early-frag-tests.frag b/reference/opt/shaders-msl/frag/depth-out-early-frag-tests.frag
new file mode 100644
index 00000000..21884d81
--- /dev/null
+++ b/reference/opt/shaders-msl/frag/depth-out-early-frag-tests.frag
@@ -0,0 +1,19 @@
+#include <metal_stdlib>
+#include <simd/simd.h>
+
+using namespace metal;
+
+struct main0_out
+{
+ float4 color_out [[color(0)]];
+};
+
+[[ early_fragment_tests ]] fragment main0_out main0()
+{
+ float gl_FragDepth;
+ main0_out out = {};
+ out.color_out = float4(1.0, 0.0, 0.0, 1.0);
+ gl_FragDepth = 0.699999988079071044921875;
+ return out;
+}
+
diff --git a/reference/opt/shaders-msl/frag/depth-out-no-early-frag-tests.frag b/reference/opt/shaders-msl/frag/depth-out-no-early-frag-tests.frag
new file mode 100644
index 00000000..57d810fa
--- /dev/null
+++ b/reference/opt/shaders-msl/frag/depth-out-no-early-frag-tests.frag
@@ -0,0 +1,19 @@
+#include <metal_stdlib>
+#include <simd/simd.h>
+
+using namespace metal;
+
+struct main0_out
+{
+ float4 color_out [[color(0)]];
+ float gl_FragDepth [[depth(less)]];
+};
+
+fragment main0_out main0()
+{
+ main0_out out = {};
+ out.color_out = float4(1.0, 0.0, 0.0, 1.0);
+ out.gl_FragDepth = 0.699999988079071044921875;
+ return out;
+}
+
diff --git a/reference/shaders-msl/frag/depth-out-early-frag-tests.frag b/reference/shaders-msl/frag/depth-out-early-frag-tests.frag
new file mode 100644
index 00000000..21884d81
--- /dev/null
+++ b/reference/shaders-msl/frag/depth-out-early-frag-tests.frag
@@ -0,0 +1,19 @@
+#include <metal_stdlib>
+#include <simd/simd.h>
+
+using namespace metal;
+
+struct main0_out
+{
+ float4 color_out [[color(0)]];
+};
+
+[[ early_fragment_tests ]] fragment main0_out main0()
+{
+ float gl_FragDepth;
+ main0_out out = {};
+ out.color_out = float4(1.0, 0.0, 0.0, 1.0);
+ gl_FragDepth = 0.699999988079071044921875;
+ return out;
+}
+
diff --git a/reference/shaders-msl/frag/depth-out-no-early-frag-tests.frag b/reference/shaders-msl/frag/depth-out-no-early-frag-tests.frag
new file mode 100644
index 00000000..57d810fa
--- /dev/null
+++ b/reference/shaders-msl/frag/depth-out-no-early-frag-tests.frag
@@ -0,0 +1,19 @@
+#include <metal_stdlib>
+#include <simd/simd.h>
+
+using namespace metal;
+
+struct main0_out
+{
+ float4 color_out [[color(0)]];
+ float gl_FragDepth [[depth(less)]];
+};
+
+fragment main0_out main0()
+{
+ main0_out out = {};
+ out.color_out = float4(1.0, 0.0, 0.0, 1.0);
+ out.gl_FragDepth = 0.699999988079071044921875;
+ return out;
+}
+
diff --git a/shaders-msl/frag/depth-out-early-frag-tests.frag b/shaders-msl/frag/depth-out-early-frag-tests.frag
new file mode 100644
index 00000000..4208d79a
--- /dev/null
+++ b/shaders-msl/frag/depth-out-early-frag-tests.frag
@@ -0,0 +1,11 @@
+#version 430
+layout(depth_less) out float gl_FragDepth;
+layout(early_fragment_tests) in;
+
+layout(location = 0) out vec4 color_out;
+
+void main()
+{
+ color_out = vec4(1.0, 0.0, 0.0, 1.0);
+ gl_FragDepth = 0.699999988079071044921875;
+}
diff --git a/shaders-msl/frag/depth-out-no-early-frag-tests.frag b/shaders-msl/frag/depth-out-no-early-frag-tests.frag
new file mode 100644
index 00000000..84502079
--- /dev/null
+++ b/shaders-msl/frag/depth-out-no-early-frag-tests.frag
@@ -0,0 +1,10 @@
+#version 430
+layout(depth_less) out float gl_FragDepth;
+
+layout(location = 0) out vec4 color_out;
+
+void main()
+{
+ color_out = vec4(1.0, 0.0, 0.0, 1.0);
+ gl_FragDepth = 0.699999988079071044921875;
+}
diff --git a/spirv_msl.cpp b/spirv_msl.cpp
index b08bb86f..fabf2e9c 100644
--- a/spirv_msl.cpp
+++ b/spirv_msl.cpp
@@ -3364,16 +3364,22 @@ uint32_t CompilerMSL::add_interface_block(StorageClass storage, bool patch)
// It's not enough to simply avoid marking fragment outputs if the pipeline won't
// accept them. We can't put them in the struct at all, or otherwise the compiler
// complains that the outputs weren't explicitly marked.
+ // Frag depth and stencil outputs are incompatible with explicit early fragment tests.
+ // In GLSL, depth and stencil outputs are just ignored when explicit early fragment tests are required.
+ // In Metal, it's a compilation error, so we need to exclude them from the output struct.
if (get_execution_model() == ExecutionModelFragment && storage == StorageClassOutput && !patch &&
- ((is_builtin && ((bi_type == BuiltInFragDepth && !msl_options.enable_frag_depth_builtin) ||
- (bi_type == BuiltInFragStencilRefEXT && !msl_options.enable_frag_stencil_ref_builtin))) ||
+ ((is_builtin && ((bi_type == BuiltInFragDepth && (!msl_options.enable_frag_depth_builtin || uses_explicit_early_fragment_test())) ||
+ (bi_type == BuiltInFragStencilRefEXT && (!msl_options.enable_frag_stencil_ref_builtin || uses_explicit_early_fragment_test())))) ||
(!is_builtin && !(msl_options.enable_frag_output_mask & (1 << location)))))
{
hidden = true;
disabled_frag_outputs.push_back(var_id);
- // If a builtin, force it to have the proper name.
+ // If a builtin, force it to have the proper name, and mark it as not part of the output struct.
if (is_builtin)
+ {
set_name(var_id, builtin_to_glsl(bi_type, StorageClassFunction));
+ mask_stage_output_by_builtin(bi_type);
+ }
}
// Barycentric inputs must be emitted in stage-in, because they can have interpolation arguments.
@@ -11156,10 +11162,7 @@ string CompilerMSL::func_type_decl(SPIRType &type)
execution.output_vertices, ") ]] vertex");
break;
case ExecutionModelFragment:
- entry_type = execution.flags.get(ExecutionModeEarlyFragmentTests) ||
- execution.flags.get(ExecutionModePostDepthCoverage) ?
- "[[ early_fragment_tests ]] fragment" :
- "fragment";
+ entry_type = uses_explicit_early_fragment_test() ? "[[ early_fragment_tests ]] fragment" : "fragment";
break;
case ExecutionModelTessellationControl:
if (!msl_options.supports_msl_version(1, 2))
@@ -11179,6 +11182,12 @@ string CompilerMSL::func_type_decl(SPIRType &type)
return entry_type + " " + return_type;
}
+bool CompilerMSL::uses_explicit_early_fragment_test()
+{
+ auto &ep_flags = get_entry_point().flags;
+ return ep_flags.get(ExecutionModeEarlyFragmentTests) || ep_flags.get(ExecutionModePostDepthCoverage);
+}
+
// In MSL, address space qualifiers are required for all pointer or reference variables
string CompilerMSL::get_argument_address_space(const SPIRVariable &argument)
{
diff --git a/spirv_msl.hpp b/spirv_msl.hpp
index d1d2ef3e..f01cceaf 100644
--- a/spirv_msl.hpp
+++ b/spirv_msl.hpp
@@ -932,6 +932,8 @@ protected:
void build_implicit_builtins();
uint32_t build_constant_uint_array_pointer();
void emit_entry_point_declarations() override;
+ bool uses_explicit_early_fragment_test();
+
uint32_t builtin_frag_coord_id = 0;
uint32_t builtin_sample_id_id = 0;
uint32_t builtin_sample_mask_id = 0;