diff options
-rw-r--r-- | reference/opt/shaders-msl/frag/depth-out-early-frag-tests.frag | 19 | ||||
-rw-r--r-- | reference/opt/shaders-msl/frag/depth-out-no-early-frag-tests.frag | 19 | ||||
-rw-r--r-- | reference/shaders-msl/frag/depth-out-early-frag-tests.frag | 19 | ||||
-rw-r--r-- | reference/shaders-msl/frag/depth-out-no-early-frag-tests.frag | 19 | ||||
-rw-r--r-- | shaders-msl/frag/depth-out-early-frag-tests.frag | 11 | ||||
-rw-r--r-- | shaders-msl/frag/depth-out-no-early-frag-tests.frag | 10 | ||||
-rw-r--r-- | spirv_msl.cpp | 23 | ||||
-rw-r--r-- | spirv_msl.hpp | 2 |
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; |