diff options
author | Hans-Kristian Arntzen <post@arntzen-software.no> | 2021-04-16 13:18:31 +0300 |
---|---|---|
committer | Hans-Kristian Arntzen <post@arntzen-software.no> | 2021-04-19 13:10:49 +0300 |
commit | 682a227f4b2e251a5bae89fa76849ace743926ad (patch) | |
tree | 386a3a10015b231332157c317f170c2c4479040f | |
parent | c1edd35d579e708336cf8f8e2c981960ce6dd6e8 (diff) |
MSL: Make builtin argument type declaration context sensitive.
Sometimes we'll need array template, sometimes not :shrug:.
7 files changed, 196 insertions, 10 deletions
diff --git a/reference/opt/shaders-msl/frag/read-cull-clip-distance-in-function.frag b/reference/opt/shaders-msl/frag/read-cull-clip-distance-in-function.frag new file mode 100644 index 00000000..3c9757eb --- /dev/null +++ b/reference/opt/shaders-msl/frag/read-cull-clip-distance-in-function.frag @@ -0,0 +1,72 @@ +#pragma clang diagnostic ignored "-Wmissing-prototypes" +#pragma clang diagnostic ignored "-Wmissing-braces" + +#include <metal_stdlib> +#include <simd/simd.h> + +using namespace metal; + +template<typename T, size_t Num> +struct spvUnsafeArray +{ + T elements[Num ? Num : 1]; + + thread T& operator [] (size_t pos) thread + { + return elements[pos]; + } + constexpr const thread T& operator [] (size_t pos) const thread + { + return elements[pos]; + } + + device T& operator [] (size_t pos) device + { + return elements[pos]; + } + constexpr const device T& operator [] (size_t pos) const device + { + return elements[pos]; + } + + constexpr const constant T& operator [] (size_t pos) const constant + { + return elements[pos]; + } + + threadgroup T& operator [] (size_t pos) threadgroup + { + return elements[pos]; + } + constexpr const threadgroup T& operator [] (size_t pos) const threadgroup + { + return elements[pos]; + } +}; + +struct main0_out +{ + float4 FragColor [[color(0)]]; +}; + +struct main0_in +{ + float gl_ClipDistance_0 [[user(clip0)]]; + float gl_ClipDistance_1 [[user(clip1)]]; + float gl_CullDistance_0 [[user(cull0)]]; + float gl_CullDistance_1 [[user(cull1)]]; +}; + +fragment main0_out main0(main0_in in [[stage_in]]) +{ + main0_out out = {}; + spvUnsafeArray<float, 2> gl_CullDistance = {}; + spvUnsafeArray<float, 2> gl_ClipDistance = {}; + gl_CullDistance[0] = in.gl_CullDistance_0; + gl_CullDistance[1] = in.gl_CullDistance_1; + gl_ClipDistance[0] = in.gl_ClipDistance_0; + gl_ClipDistance[1] = in.gl_ClipDistance_1; + out.FragColor = float4(gl_CullDistance[0], gl_CullDistance[1], gl_ClipDistance[0], gl_ClipDistance[1]); + return out; +} + diff --git a/reference/shaders-msl/frag/read-cull-clip-distance-in-function.frag b/reference/shaders-msl/frag/read-cull-clip-distance-in-function.frag new file mode 100644 index 00000000..02d57d9b --- /dev/null +++ b/reference/shaders-msl/frag/read-cull-clip-distance-in-function.frag @@ -0,0 +1,78 @@ +#pragma clang diagnostic ignored "-Wmissing-prototypes" +#pragma clang diagnostic ignored "-Wmissing-braces" + +#include <metal_stdlib> +#include <simd/simd.h> + +using namespace metal; + +template<typename T, size_t Num> +struct spvUnsafeArray +{ + T elements[Num ? Num : 1]; + + thread T& operator [] (size_t pos) thread + { + return elements[pos]; + } + constexpr const thread T& operator [] (size_t pos) const thread + { + return elements[pos]; + } + + device T& operator [] (size_t pos) device + { + return elements[pos]; + } + constexpr const device T& operator [] (size_t pos) const device + { + return elements[pos]; + } + + constexpr const constant T& operator [] (size_t pos) const constant + { + return elements[pos]; + } + + threadgroup T& operator [] (size_t pos) threadgroup + { + return elements[pos]; + } + constexpr const threadgroup T& operator [] (size_t pos) const threadgroup + { + return elements[pos]; + } +}; + +struct main0_out +{ + float4 FragColor [[color(0)]]; +}; + +struct main0_in +{ + float gl_ClipDistance_0 [[user(clip0)]]; + float gl_ClipDistance_1 [[user(clip1)]]; + float gl_CullDistance_0 [[user(cull0)]]; + float gl_CullDistance_1 [[user(cull1)]]; +}; + +static inline __attribute__((always_inline)) +float4 read_in_func(thread spvUnsafeArray<float, 2>& gl_CullDistance, thread spvUnsafeArray<float, 2>& gl_ClipDistance) +{ + return float4(gl_CullDistance[0], gl_CullDistance[1], gl_ClipDistance[0], gl_ClipDistance[1]); +} + +fragment main0_out main0(main0_in in [[stage_in]]) +{ + main0_out out = {}; + spvUnsafeArray<float, 2> gl_CullDistance = {}; + spvUnsafeArray<float, 2> gl_ClipDistance = {}; + gl_CullDistance[0] = in.gl_CullDistance_0; + gl_CullDistance[1] = in.gl_CullDistance_1; + gl_ClipDistance[0] = in.gl_ClipDistance_0; + gl_ClipDistance[1] = in.gl_ClipDistance_1; + out.FragColor = read_in_func(gl_CullDistance, gl_ClipDistance); + return out; +} + diff --git a/reference/shaders-msl/masking/write-outputs.mask-location-0.for-tess.vert b/reference/shaders-msl/masking/write-outputs.mask-location-0.for-tess.vert index a004a380..53f76b57 100644 --- a/reference/shaders-msl/masking/write-outputs.mask-location-0.for-tess.vert +++ b/reference/shaders-msl/masking/write-outputs.mask-location-0.for-tess.vert @@ -53,7 +53,7 @@ struct main0_out }; static inline __attribute__((always_inline)) -void write_in_func(thread float4& v0, device float4& v1, device float4& gl_Position, device float& gl_PointSize, device float (&gl_ClipDistance)[2]) +void write_in_func(thread float4& v0, device float4& v1, device float4& gl_Position, device float& gl_PointSize, device spvUnsafeArray<float, 2>& gl_ClipDistance) { v0 = float4(1.0); v1 = float4(2.0); diff --git a/reference/shaders-msl/masking/write-outputs.mask-location-1.for-tess.vert b/reference/shaders-msl/masking/write-outputs.mask-location-1.for-tess.vert index 02288822..8f9cfce5 100644 --- a/reference/shaders-msl/masking/write-outputs.mask-location-1.for-tess.vert +++ b/reference/shaders-msl/masking/write-outputs.mask-location-1.for-tess.vert @@ -53,7 +53,7 @@ struct main0_out }; static inline __attribute__((always_inline)) -void write_in_func(device float4& v0, thread float4& v1, device float4& gl_Position, device float& gl_PointSize, device float (&gl_ClipDistance)[2]) +void write_in_func(device float4& v0, thread float4& v1, device float4& gl_Position, device float& gl_PointSize, device spvUnsafeArray<float, 2>& gl_ClipDistance) { v0 = float4(1.0); v1 = float4(2.0); diff --git a/reference/shaders-msl/masking/write-outputs.mask-point-size.for-tess.vert b/reference/shaders-msl/masking/write-outputs.mask-point-size.for-tess.vert index 1307b5b8..07494ea3 100644 --- a/reference/shaders-msl/masking/write-outputs.mask-point-size.for-tess.vert +++ b/reference/shaders-msl/masking/write-outputs.mask-point-size.for-tess.vert @@ -53,7 +53,7 @@ struct main0_out }; static inline __attribute__((always_inline)) -void write_in_func(device float4& v0, device float4& v1, device float4& gl_Position, thread float& gl_PointSize, device float (&gl_ClipDistance)[2]) +void write_in_func(device float4& v0, device float4& v1, device float4& gl_Position, thread float& gl_PointSize, device spvUnsafeArray<float, 2>& gl_ClipDistance) { v0 = float4(1.0); v1 = float4(2.0); diff --git a/shaders-msl/frag/read-cull-clip-distance-in-function.frag b/shaders-msl/frag/read-cull-clip-distance-in-function.frag new file mode 100644 index 00000000..0b82dc2d --- /dev/null +++ b/shaders-msl/frag/read-cull-clip-distance-in-function.frag @@ -0,0 +1,20 @@ +#version 450 + +layout(location = 0) out vec4 FragColor; + +in float gl_CullDistance[2]; +in float gl_ClipDistance[2]; + +vec4 read_in_func() +{ + return vec4( + gl_CullDistance[0], + gl_CullDistance[1], + gl_ClipDistance[0], + gl_ClipDistance[1]); +} + +void main() +{ + FragColor = read_in_func(); +} diff --git a/spirv_msl.cpp b/spirv_msl.cpp index f13e8451..3c9338fb 100644 --- a/spirv_msl.cpp +++ b/spirv_msl.cpp @@ -12387,7 +12387,7 @@ string CompilerMSL::argument_decl(const SPIRFunction::Parameter &arg) auto &var = get<SPIRVariable>(arg.id); auto &type = get_variable_data_type(var); auto &var_type = get<SPIRType>(arg.type); - StorageClass storage = var_type.storage; + StorageClass type_storage = var_type.storage; bool is_pointer = var_type.pointer; // If we need to modify the name of the variable, make sure we use the original variable. @@ -12424,15 +12424,30 @@ string CompilerMSL::argument_decl(const SPIRFunction::Parameter &arg) string address_space = get_argument_address_space(var); bool builtin = has_decoration(var.self, DecorationBuiltIn); auto builtin_type = BuiltIn(get_decoration(arg.id, DecorationBuiltIn)); - is_using_builtin_array = builtin; + if (address_space == "threadgroup") is_using_builtin_array = true; if (var.basevariable && (var.basevariable == stage_in_ptr_var_id || var.basevariable == stage_out_ptr_var_id)) decl = join(cv_qualifier, type_to_glsl(type, arg.id)); else if (builtin) - decl = join(cv_qualifier, builtin_type_decl(builtin_type, arg.id)); - else if ((storage == StorageClassUniform || storage == StorageClassStorageBuffer) && is_array(type)) + { + // Only use templated array for Clip/Cull distance when feasible. + // In other scenarios, we need need to override array length for tess levels, + // or we need to emit the expected type for builtins (uint vs int). + if (builtin_type != BuiltInClipDistance && builtin_type != BuiltInCullDistance) + is_using_builtin_array = true; + + auto storage = get<SPIRType>(var.basetype).storage; + if (storage == StorageClassOutput && variable_storage_requires_stage_io(storage)) + is_using_builtin_array = true; + + if (is_using_builtin_array) + decl = join(cv_qualifier, builtin_type_decl(builtin_type, arg.id)); + else + decl = join(cv_qualifier, type_to_glsl(type, arg.id)); + } + else if ((type_storage == StorageClassUniform || type_storage == StorageClassStorageBuffer) && is_array(type)) { is_using_builtin_array = true; decl += join(cv_qualifier, type_to_glsl(type, arg.id), "*"); @@ -12456,10 +12471,10 @@ string CompilerMSL::argument_decl(const SPIRFunction::Parameter &arg) decl = join(cv_qualifier, type_to_glsl(type, arg.id)); } - bool opaque_handle = storage == StorageClassUniformConstant; + bool opaque_handle = type_storage == StorageClassUniformConstant; if (!builtin && !opaque_handle && !is_pointer && - (storage == StorageClassFunction || storage == StorageClassGeneric)) + (type_storage == StorageClassFunction || type_storage == StorageClassGeneric)) { // If the argument is a pure value and not an opaque type, we will pass by value. if (msl_options.force_native_arrays && is_array(type)) @@ -12500,7 +12515,7 @@ string CompilerMSL::argument_decl(const SPIRFunction::Parameter &arg) if (msl_options.argument_buffers) { uint32_t desc_set = get_decoration(name_id, DecorationDescriptorSet); - if ((storage == StorageClassUniform || storage == StorageClassStorageBuffer) && + if ((type_storage == StorageClassUniform || type_storage == StorageClassStorageBuffer) && descriptor_set_is_argument_buffer(desc_set)) { // An awkward case where we need to emit *more* address space declarations (yay!). @@ -14226,6 +14241,7 @@ string CompilerMSL::builtin_type_decl(BuiltIn builtin, uint32_t id) // Vertex function out case BuiltInClipDistance: + case BuiltInCullDistance: return "float"; case BuiltInPointSize: return "float"; |