From 6ef47d665794b7f67a2204ffdb18dacd404bae29 Mon Sep 17 00:00:00 2001 From: Hans-Kristian Arntzen Date: Mon, 27 Apr 2020 11:23:24 +0200 Subject: [PATCH] MSL: Fix case where subpassInput is passed to leaf functions. --- ...nction-argument.framebuffer-fetch.ios.frag | 37 +++++++++++++++++++ ...nction-argument.framebuffer-fetch.ios.frag | 24 ++++++++++++ spirv_msl.cpp | 28 +++++++++++--- spirv_msl.hpp | 6 ++- 4 files changed, 87 insertions(+), 8 deletions(-) create mode 100644 reference/shaders-msl-no-opt/frag/subpass-input-function-argument.framebuffer-fetch.ios.frag create mode 100644 shaders-msl-no-opt/frag/subpass-input-function-argument.framebuffer-fetch.ios.frag diff --git a/reference/shaders-msl-no-opt/frag/subpass-input-function-argument.framebuffer-fetch.ios.frag b/reference/shaders-msl-no-opt/frag/subpass-input-function-argument.framebuffer-fetch.ios.frag new file mode 100644 index 00000000..950895d0 --- /dev/null +++ b/reference/shaders-msl-no-opt/frag/subpass-input-function-argument.framebuffer-fetch.ios.frag @@ -0,0 +1,37 @@ +#pragma clang diagnostic ignored "-Wmissing-prototypes" + +#include +#include + +using namespace metal; + +struct main0_out +{ + float4 FragColor [[color(0)]]; +}; + +static inline __attribute__((always_inline)) +float4 samp3(float4 uS) +{ + return uS; +} + +static inline __attribute__((always_inline)) +float4 samp(float4 uSub) +{ + return uSub + samp3(uSub); +} + +static inline __attribute__((always_inline)) +float4 samp2(float4 uS) +{ + return uS + samp3(uS); +} + +fragment main0_out main0(float4 uSub [[color(0)]]) +{ + main0_out out = {}; + out.FragColor = samp(uSub) + samp2(uSub); + return out; +} + diff --git a/shaders-msl-no-opt/frag/subpass-input-function-argument.framebuffer-fetch.ios.frag b/shaders-msl-no-opt/frag/subpass-input-function-argument.framebuffer-fetch.ios.frag new file mode 100644 index 00000000..ef9ef77d --- /dev/null +++ b/shaders-msl-no-opt/frag/subpass-input-function-argument.framebuffer-fetch.ios.frag @@ -0,0 +1,24 @@ +#version 450 + +layout(set = 0, input_attachment_index = 0, binding = 0) uniform subpassInput uSub; +layout(location = 0) out vec4 FragColor; + +vec4 samp3(subpassInput uS) +{ + return subpassLoad(uS); +} + +vec4 samp2(subpassInput uS) +{ + return subpassLoad(uS) + samp3(uS); +} + +vec4 samp() +{ + return subpassLoad(uSub) + samp3(uSub); +} + +void main() +{ + FragColor = samp() + samp2(uSub); +} diff --git a/spirv_msl.cpp b/spirv_msl.cpp index 597cf89c..e3a44f79 100644 --- a/spirv_msl.cpp +++ b/spirv_msl.cpp @@ -9185,7 +9185,14 @@ string CompilerMSL::get_type_address_space(const SPIRType &type, uint32_t id, bo addr_space = "constant"; } else if (!argument) + { addr_space = "constant"; + } + else if (type_is_msl_framebuffer_fetch(type)) + { + // Subpass inputs are passed around by value. + addr_space = ""; + } break; case StorageClassFunction: @@ -9626,8 +9633,7 @@ void CompilerMSL::entry_point_args_discrete_descriptors(string &ep_args) // Use Metal's native frame-buffer fetch API for subpass inputs. const auto &basetype = get(var.basetype); - if (basetype.image.dim != DimSubpassData || !msl_options.is_ios() || - !msl_options.ios_use_framebuffer_fetch_subpasses) + if (!type_is_msl_framebuffer_fetch(basetype)) { ep_args += image_type_glsl(type, var_id) + " " + r.name; if (r.plane > 0) @@ -9639,7 +9645,7 @@ void CompilerMSL::entry_point_args_discrete_descriptors(string &ep_args) } else { - ep_args += image_type_glsl(type, var_id) + "4 " + r.name; + ep_args += image_type_glsl(type, var_id) + " " + r.name; ep_args += " [[color(" + convert_to_string(r.index) + ")]]"; } @@ -10125,6 +10131,12 @@ uint32_t CompilerMSL::get_metal_resource_index(SPIRVariable &var, SPIRType::Base return resource_index; } +bool CompilerMSL::type_is_msl_framebuffer_fetch(const SPIRType &type) const +{ + return type.basetype == SPIRType::Image && type.image.dim == DimSubpassData && + msl_options.is_ios() && msl_options.ios_use_framebuffer_fetch_subpasses; +} + string CompilerMSL::argument_decl(const SPIRFunction::Parameter &arg) { auto &var = get(arg.id); @@ -10140,6 +10152,9 @@ string CompilerMSL::argument_decl(const SPIRFunction::Parameter &arg) name_id = var.basevariable; bool constref = !arg.alias_global_variable && is_pointer && arg.write_count == 0; + // Framebuffer fetch is plain value, const looks out of place, but it is not wrong. + if (type_is_msl_framebuffer_fetch(type)) + constref = false; bool type_is_image = type.basetype == SPIRType::Image || type.basetype == SPIRType::SampledImage || type.basetype == SPIRType::Sampler; @@ -10983,10 +10998,11 @@ string CompilerMSL::image_type_glsl(const SPIRType &type, uint32_t id) } // Use Metal's native frame-buffer fetch API for subpass inputs. - if (img_type.dim == DimSubpassData && msl_options.is_ios() && - msl_options.ios_use_framebuffer_fetch_subpasses) + if (type_is_msl_framebuffer_fetch(type)) { - return type_to_glsl(get(img_type.type)); + auto img_type_4 = get(img_type.type); + img_type_4.vecsize = 4; + return type_to_glsl(img_type_4); } if (img_type.ms && img_type.arrayed) { diff --git a/spirv_msl.hpp b/spirv_msl.hpp index 50a795de..e56d27b9 100644 --- a/spirv_msl.hpp +++ b/spirv_msl.hpp @@ -324,12 +324,12 @@ public: // can be read in subsequent stages. bool enable_clip_distance_user_varying = true; - bool is_ios() + bool is_ios() const { return platform == iOS; } - bool is_macos() + bool is_macos() const { return platform == macOS; } @@ -898,6 +898,8 @@ protected: void activate_argument_buffer_resources(); + bool type_is_msl_framebuffer_fetch(const SPIRType &type) const; + // OpcodeHandler that handles several MSL preprocessing operations. struct OpCodePreprocessor : OpcodeHandler {