From f3a6d28a1daf2a19299d58fd397a98b169ed30cb Mon Sep 17 00:00:00 2001 From: Lukas Hermanns Date: Fri, 27 Sep 2019 15:49:54 -0400 Subject: [PATCH] Further updates for pull request #1162; also added two test cases for spvCubemapTo2DArrayFace function and added '--msl-framebuffer-fetch'/ '--msl-emulate-cube-array' compiler options. --- main.cpp | 10 +++ ...pass-input.ios.framebuffer-fetch.asm.frag} | 4 +- .../shaders-msl/frag/texture-cube-array.frag | 22 +++++ ...ure-cube-array.ios.emulate-cube-array.frag | 58 +++++++++++++ ...pass-input.ios.framebuffer-fetch.asm.frag} | 4 +- .../shaders-msl/frag/texture-cube-array.frag | 25 ++++++ ...ure-cube-array.ios.emulate-cube-array.frag | 61 ++++++++++++++ ...pass-input.ios.framebuffer-fetch.asm.frag} | 0 shaders-msl/frag/texture-cube-array.frag | 16 ++++ ...ure-cube-array.ios.emulate-cube-array.frag | 16 ++++ spirv_cross.hpp | 6 +- spirv_glsl.cpp | 17 ++-- spirv_msl.cpp | 84 +++++++++---------- spirv_msl.hpp | 15 +++- test_shaders.py | 4 + 15 files changed, 276 insertions(+), 66 deletions(-) rename reference/opt/shaders-msl/asm/frag/{frame-buffer-fetch-subpass-input.asm.frag => subpass-input.ios.framebuffer-fetch.asm.frag} (96%) create mode 100644 reference/opt/shaders-msl/frag/texture-cube-array.frag create mode 100644 reference/opt/shaders-msl/frag/texture-cube-array.ios.emulate-cube-array.frag rename reference/shaders-msl/asm/frag/{frame-buffer-fetch-subpass-input.asm.frag => subpass-input.ios.framebuffer-fetch.asm.frag} (96%) create mode 100644 reference/shaders-msl/frag/texture-cube-array.frag create mode 100644 reference/shaders-msl/frag/texture-cube-array.ios.emulate-cube-array.frag rename shaders-msl/asm/frag/{frame-buffer-fetch-subpass-input.asm.frag => subpass-input.ios.framebuffer-fetch.asm.frag} (100%) create mode 100644 shaders-msl/frag/texture-cube-array.frag create mode 100644 shaders-msl/frag/texture-cube-array.ios.emulate-cube-array.frag diff --git a/main.cpp b/main.cpp index b05e8126..9ed0d7db 100644 --- a/main.cpp +++ b/main.cpp @@ -514,6 +514,8 @@ struct CLIArguments bool msl_domain_lower_left = false; bool msl_argument_buffers = false; bool msl_texture_buffer_native = false; + bool msl_framebuffer_fetch = false; + bool msl_emulate_cube_array = false; bool msl_multiview = false; bool msl_view_index_from_device_index = false; bool msl_dispatch_base = false; @@ -597,6 +599,8 @@ static void print_help() "\t[--msl-domain-lower-left]\n" "\t[--msl-argument-buffers]\n" "\t[--msl-texture-buffer-native]\n" + "\t[--msl-framebuffer-fetch]\n" + "\t[--msl-emulate-cube-array]\n" "\t[--msl-discrete-descriptor-set ]\n" "\t[--msl-multiview]\n" "\t[--msl-view-index-from-device-index]\n" @@ -755,7 +759,11 @@ static string compile_iteration(const CLIArguments &args, std::vector msl_opts.capture_output_to_buffer = args.msl_capture_output_to_buffer; msl_opts.swizzle_texture_samples = args.msl_swizzle_texture_samples; if (args.msl_ios) + { msl_opts.platform = CompilerMSL::Options::iOS; + msl_opts.ios_use_framebuffer_fetch_subpasses = args.msl_framebuffer_fetch; + msl_opts.emulate_cube_array = args.msl_emulate_cube_array; + } msl_opts.pad_fragment_output_components = args.msl_pad_fragment_output; msl_opts.tess_domain_origin_lower_left = args.msl_domain_lower_left; msl_opts.argument_buffers = args.msl_argument_buffers; @@ -1087,6 +1095,8 @@ static int main_inner(int argc, char *argv[]) cbs.add("--msl-discrete-descriptor-set", [&args](CLIParser &parser) { args.msl_discrete_descriptor_sets.push_back(parser.next_uint()); }); cbs.add("--msl-texture-buffer-native", [&args](CLIParser &) { args.msl_texture_buffer_native = true; }); + cbs.add("--msl-framebuffer-fetch", [&args](CLIParser &) { args.msl_framebuffer_fetch = true; }); + cbs.add("--msl-emulate-cube-array", [&args](CLIParser &) { args.msl_emulate_cube_array = true; }); cbs.add("--msl-multiview", [&args](CLIParser &) { args.msl_multiview = true; }); cbs.add("--msl-view-index-from-device-index", [&args](CLIParser &) { args.msl_view_index_from_device_index = true; }); diff --git a/reference/opt/shaders-msl/asm/frag/frame-buffer-fetch-subpass-input.asm.frag b/reference/opt/shaders-msl/asm/frag/subpass-input.ios.framebuffer-fetch.asm.frag similarity index 96% rename from reference/opt/shaders-msl/asm/frag/frame-buffer-fetch-subpass-input.asm.frag rename to reference/opt/shaders-msl/asm/frag/subpass-input.ios.framebuffer-fetch.asm.frag index 61d9ad1e..f0e48f51 100644 --- a/reference/opt/shaders-msl/asm/frag/frame-buffer-fetch-subpass-input.asm.frag +++ b/reference/opt/shaders-msl/asm/frag/subpass-input.ios.framebuffer-fetch.asm.frag @@ -238,10 +238,10 @@ struct main0_out float4 out_var_SV_Target0 [[color(0)]]; }; -fragment main0_out main0(constant type_View& View [[buffer(0)]], constant type_Globals& _Globals [[buffer(1)]], texture2d _gl_LastFragData [[texture(0)]], texture2d ShadowDepthTexture [[texture(1)]], sampler ShadowDepthTextureSampler [[sampler(0)]], float4 gl_FragCoord [[position]]) +fragment main0_out main0(constant type_View& View [[buffer(0)]], constant type_Globals& _Globals [[buffer(1)]], float4 _gl_LastFragData [[color(0)]], texture2d ShadowDepthTexture [[texture(1)]], sampler ShadowDepthTextureSampler [[sampler(0)]], float4 gl_FragCoord [[position]]) { main0_out out = {}; - float4 _67 = _gl_LastFragData.read(uint2(gl_FragCoord.xy), 0); + float4 _67 = _gl_LastFragData; float _68 = _67.w; float4 _82 = _Globals.ScreenToShadowMatrix * float4((((gl_FragCoord.xy * View.View_BufferSizeAndInvSize.zw) - View.View_ScreenPositionScaleBias.wz) / View.View_ScreenPositionScaleBias.xy) * float2(_68), _68, 1.0); float _118 = fast::clamp(((fast::clamp((ShadowDepthTexture.sample(ShadowDepthTextureSampler, (((_82.xyz / float3(_82.w)).xy * _Globals.ShadowTileOffsetAndSize.zw).xy + _Globals.ShadowTileOffsetAndSize.xy).xy, level(0.0)).xxx * float3(_Globals.SoftTransitionScale.z)) - float3((fast::min(_82.z, 0.999989986419677734375) * _Globals.SoftTransitionScale.z) - 1.0), float3(0.0), float3(1.0)).x - 0.5) * _Globals.ShadowSharpen) + 0.5, 0.0, 1.0); diff --git a/reference/opt/shaders-msl/frag/texture-cube-array.frag b/reference/opt/shaders-msl/frag/texture-cube-array.frag new file mode 100644 index 00000000..0af8a047 --- /dev/null +++ b/reference/opt/shaders-msl/frag/texture-cube-array.frag @@ -0,0 +1,22 @@ +#include +#include + +using namespace metal; + +struct main0_out +{ + float4 FragColor [[color(0)]]; +}; + +struct main0_in +{ + float4 vUV [[user(locn0)]]; +}; + +fragment main0_out main0(main0_in in [[stage_in]], texturecube cubeSampler [[texture(0)]], texturecube_array cubeArraySampler [[texture(1)]], texture2d_array texArraySampler [[texture(2)]], sampler cubeSamplerSmplr [[sampler(0)]], sampler cubeArraySamplerSmplr [[sampler(1)]], sampler texArraySamplerSmplr [[sampler(2)]]) +{ + main0_out out = {}; + out.FragColor = (cubeSampler.sample(cubeSamplerSmplr, in.vUV.xyz) + cubeArraySampler.sample(cubeArraySamplerSmplr, in.vUV.xyz, uint(round(in.vUV.w)))) + texArraySampler.sample(texArraySamplerSmplr, in.vUV.xyz.xy, uint(round(in.vUV.xyz.z))); + return out; +} + diff --git a/reference/opt/shaders-msl/frag/texture-cube-array.ios.emulate-cube-array.frag b/reference/opt/shaders-msl/frag/texture-cube-array.ios.emulate-cube-array.frag new file mode 100644 index 00000000..217a7a9e --- /dev/null +++ b/reference/opt/shaders-msl/frag/texture-cube-array.ios.emulate-cube-array.frag @@ -0,0 +1,58 @@ +#pragma clang diagnostic ignored "-Wmissing-prototypes" + +#include +#include + +using namespace metal; + +struct main0_out +{ + float4 FragColor [[color(0)]]; +}; + +struct main0_in +{ + float4 vUV [[user(locn0)]]; +}; + +static inline __attribute__((always_inline)) +float3 spvCubemapTo2DArrayFace(float3 P) +{ + float3 Coords = abs(P.xyz); + float CubeFace = 0; + float ProjectionAxis = 0; + float u = 0; + float v = 0; + if (Coords.x >= Coords.y && Coords.x >= Coords.z) + { + CubeFace = P.x >= 0 ? 0 : 1; + ProjectionAxis = Coords.x; + u = P.x >= 0 ? -P.z : P.z; + v = -P.y; + } + else if (Coords.y >= Coords.x && Coords.y >= Coords.z) + { + CubeFace = P.y >= 0 ? 2 : 3; + ProjectionAxis = Coords.y; + u = P.x; + v = P.y >= 0 ? P.z : -P.z; + } + else + { + CubeFace = P.z >= 0 ? 4 : 5; + ProjectionAxis = Coords.z; + u = P.z >= 0 ? P.x : -P.x; + v = -P.y; + } + u = 0.5 * (u/ProjectionAxis + 1); + v = 0.5 * (v/ProjectionAxis + 1); + return float3(u, v, CubeFace); +} + +fragment main0_out main0(main0_in in [[stage_in]], texturecube cubeSampler [[texture(0)]], texture2d_array cubeArraySampler [[texture(1)]], texture2d_array texArraySampler [[texture(2)]], sampler cubeSamplerSmplr [[sampler(0)]], sampler cubeArraySamplerSmplr [[sampler(1)]], sampler texArraySamplerSmplr [[sampler(2)]]) +{ + main0_out out = {}; + out.FragColor = (cubeSampler.sample(cubeSamplerSmplr, in.vUV.xyz) + cubeArraySampler.sample(cubeArraySamplerSmplr, spvCubemapTo2DArrayFace(in.vUV.xyz).xy, uint(spvCubemapTo2DArrayFace(in.vUV.xyz).z) + (uint(round(in.vUV.w)) * 6u))) + texArraySampler.sample(texArraySamplerSmplr, in.vUV.xyz.xy, uint(round(in.vUV.xyz.z))); + return out; +} + diff --git a/reference/shaders-msl/asm/frag/frame-buffer-fetch-subpass-input.asm.frag b/reference/shaders-msl/asm/frag/subpass-input.ios.framebuffer-fetch.asm.frag similarity index 96% rename from reference/shaders-msl/asm/frag/frame-buffer-fetch-subpass-input.asm.frag rename to reference/shaders-msl/asm/frag/subpass-input.ios.framebuffer-fetch.asm.frag index 61d9ad1e..f0e48f51 100644 --- a/reference/shaders-msl/asm/frag/frame-buffer-fetch-subpass-input.asm.frag +++ b/reference/shaders-msl/asm/frag/subpass-input.ios.framebuffer-fetch.asm.frag @@ -238,10 +238,10 @@ struct main0_out float4 out_var_SV_Target0 [[color(0)]]; }; -fragment main0_out main0(constant type_View& View [[buffer(0)]], constant type_Globals& _Globals [[buffer(1)]], texture2d _gl_LastFragData [[texture(0)]], texture2d ShadowDepthTexture [[texture(1)]], sampler ShadowDepthTextureSampler [[sampler(0)]], float4 gl_FragCoord [[position]]) +fragment main0_out main0(constant type_View& View [[buffer(0)]], constant type_Globals& _Globals [[buffer(1)]], float4 _gl_LastFragData [[color(0)]], texture2d ShadowDepthTexture [[texture(1)]], sampler ShadowDepthTextureSampler [[sampler(0)]], float4 gl_FragCoord [[position]]) { main0_out out = {}; - float4 _67 = _gl_LastFragData.read(uint2(gl_FragCoord.xy), 0); + float4 _67 = _gl_LastFragData; float _68 = _67.w; float4 _82 = _Globals.ScreenToShadowMatrix * float4((((gl_FragCoord.xy * View.View_BufferSizeAndInvSize.zw) - View.View_ScreenPositionScaleBias.wz) / View.View_ScreenPositionScaleBias.xy) * float2(_68), _68, 1.0); float _118 = fast::clamp(((fast::clamp((ShadowDepthTexture.sample(ShadowDepthTextureSampler, (((_82.xyz / float3(_82.w)).xy * _Globals.ShadowTileOffsetAndSize.zw).xy + _Globals.ShadowTileOffsetAndSize.xy).xy, level(0.0)).xxx * float3(_Globals.SoftTransitionScale.z)) - float3((fast::min(_82.z, 0.999989986419677734375) * _Globals.SoftTransitionScale.z) - 1.0), float3(0.0), float3(1.0)).x - 0.5) * _Globals.ShadowSharpen) + 0.5, 0.0, 1.0); diff --git a/reference/shaders-msl/frag/texture-cube-array.frag b/reference/shaders-msl/frag/texture-cube-array.frag new file mode 100644 index 00000000..9f1832ec --- /dev/null +++ b/reference/shaders-msl/frag/texture-cube-array.frag @@ -0,0 +1,25 @@ +#include +#include + +using namespace metal; + +struct main0_out +{ + float4 FragColor [[color(0)]]; +}; + +struct main0_in +{ + float4 vUV [[user(locn0)]]; +}; + +fragment main0_out main0(main0_in in [[stage_in]], texturecube cubeSampler [[texture(0)]], texturecube_array cubeArraySampler [[texture(1)]], texture2d_array texArraySampler [[texture(2)]], sampler cubeSamplerSmplr [[sampler(0)]], sampler cubeArraySamplerSmplr [[sampler(1)]], sampler texArraySamplerSmplr [[sampler(2)]]) +{ + main0_out out = {}; + float4 a = cubeSampler.sample(cubeSamplerSmplr, in.vUV.xyz); + float4 b = cubeArraySampler.sample(cubeArraySamplerSmplr, in.vUV.xyz, uint(round(in.vUV.w))); + float4 c = texArraySampler.sample(texArraySamplerSmplr, in.vUV.xyz.xy, uint(round(in.vUV.xyz.z))); + out.FragColor = (a + b) + c; + return out; +} + diff --git a/reference/shaders-msl/frag/texture-cube-array.ios.emulate-cube-array.frag b/reference/shaders-msl/frag/texture-cube-array.ios.emulate-cube-array.frag new file mode 100644 index 00000000..3c4d0adb --- /dev/null +++ b/reference/shaders-msl/frag/texture-cube-array.ios.emulate-cube-array.frag @@ -0,0 +1,61 @@ +#pragma clang diagnostic ignored "-Wmissing-prototypes" + +#include +#include + +using namespace metal; + +struct main0_out +{ + float4 FragColor [[color(0)]]; +}; + +struct main0_in +{ + float4 vUV [[user(locn0)]]; +}; + +static inline __attribute__((always_inline)) +float3 spvCubemapTo2DArrayFace(float3 P) +{ + float3 Coords = abs(P.xyz); + float CubeFace = 0; + float ProjectionAxis = 0; + float u = 0; + float v = 0; + if (Coords.x >= Coords.y && Coords.x >= Coords.z) + { + CubeFace = P.x >= 0 ? 0 : 1; + ProjectionAxis = Coords.x; + u = P.x >= 0 ? -P.z : P.z; + v = -P.y; + } + else if (Coords.y >= Coords.x && Coords.y >= Coords.z) + { + CubeFace = P.y >= 0 ? 2 : 3; + ProjectionAxis = Coords.y; + u = P.x; + v = P.y >= 0 ? P.z : -P.z; + } + else + { + CubeFace = P.z >= 0 ? 4 : 5; + ProjectionAxis = Coords.z; + u = P.z >= 0 ? P.x : -P.x; + v = -P.y; + } + u = 0.5 * (u/ProjectionAxis + 1); + v = 0.5 * (v/ProjectionAxis + 1); + return float3(u, v, CubeFace); +} + +fragment main0_out main0(main0_in in [[stage_in]], texturecube cubeSampler [[texture(0)]], texture2d_array cubeArraySampler [[texture(1)]], texture2d_array texArraySampler [[texture(2)]], sampler cubeSamplerSmplr [[sampler(0)]], sampler cubeArraySamplerSmplr [[sampler(1)]], sampler texArraySamplerSmplr [[sampler(2)]]) +{ + main0_out out = {}; + float4 a = cubeSampler.sample(cubeSamplerSmplr, in.vUV.xyz); + float4 b = cubeArraySampler.sample(cubeArraySamplerSmplr, spvCubemapTo2DArrayFace(in.vUV.xyz).xy, uint(spvCubemapTo2DArrayFace(in.vUV.xyz).z) + (uint(round(in.vUV.w)) * 6u)); + float4 c = texArraySampler.sample(texArraySamplerSmplr, in.vUV.xyz.xy, uint(round(in.vUV.xyz.z))); + out.FragColor = (a + b) + c; + return out; +} + diff --git a/shaders-msl/asm/frag/frame-buffer-fetch-subpass-input.asm.frag b/shaders-msl/asm/frag/subpass-input.ios.framebuffer-fetch.asm.frag similarity index 100% rename from shaders-msl/asm/frag/frame-buffer-fetch-subpass-input.asm.frag rename to shaders-msl/asm/frag/subpass-input.ios.framebuffer-fetch.asm.frag diff --git a/shaders-msl/frag/texture-cube-array.frag b/shaders-msl/frag/texture-cube-array.frag new file mode 100644 index 00000000..91a55f93 --- /dev/null +++ b/shaders-msl/frag/texture-cube-array.frag @@ -0,0 +1,16 @@ +#version 450 + +layout(set = 0, binding = 0) uniform samplerCube cubeSampler; +layout(set = 0, binding = 1) uniform samplerCubeArray cubeArraySampler; +layout(set = 0, binding = 2) uniform sampler2DArray texArraySampler; + +layout(location = 0) in vec4 vUV; +layout(location = 0) out vec4 FragColor; + +void main() +{ + vec4 a = texture(cubeSampler, vUV.xyz); + vec4 b = texture(cubeArraySampler, vUV); + vec4 c = texture(texArraySampler, vUV.xyz); + FragColor = a + b + c; +} diff --git a/shaders-msl/frag/texture-cube-array.ios.emulate-cube-array.frag b/shaders-msl/frag/texture-cube-array.ios.emulate-cube-array.frag new file mode 100644 index 00000000..91a55f93 --- /dev/null +++ b/shaders-msl/frag/texture-cube-array.ios.emulate-cube-array.frag @@ -0,0 +1,16 @@ +#version 450 + +layout(set = 0, binding = 0) uniform samplerCube cubeSampler; +layout(set = 0, binding = 1) uniform samplerCubeArray cubeArraySampler; +layout(set = 0, binding = 2) uniform sampler2DArray texArraySampler; + +layout(location = 0) in vec4 vUV; +layout(location = 0) out vec4 FragColor; + +void main() +{ + vec4 a = texture(cubeSampler, vUV.xyz); + vec4 b = texture(cubeArraySampler, vUV); + vec4 c = texture(texArraySampler, vUV.xyz); + FragColor = a + b + c; +} diff --git a/spirv_cross.hpp b/spirv_cross.hpp index 8f8a8cf4..f2286c84 100644 --- a/spirv_cross.hpp +++ b/spirv_cross.hpp @@ -487,9 +487,6 @@ public: // The most common use here is to check if a buffer is readonly or writeonly. Bitset get_buffer_block_flags(VariableID id) const; - // Returns true if the target language supports combined texture-samplers. Returns fasle by default. - virtual bool supports_combined_samplers() const; - protected: const uint32_t *stream(const Instruction &instr) const { @@ -615,6 +612,9 @@ protected: void register_read(uint32_t expr, uint32_t chain, bool forwarded); void register_write(uint32_t chain); + // Returns true if the target language supports combined texture-samplers. Returns fasle by default. + virtual bool supports_combined_samplers() const; + inline bool is_continue(uint32_t next) const { return (ir.block_meta[next] & ParsedIR::BLOCK_META_CONTINUE_BIT) != 0; diff --git a/spirv_glsl.cpp b/spirv_glsl.cpp index 51de2661..d5616cac 100644 --- a/spirv_glsl.cpp +++ b/spirv_glsl.cpp @@ -3437,6 +3437,11 @@ string CompilerGLSL::constant_expression(const SPIRConstant &c) return res; } + else if (type.basetype == SPIRType::Struct && type.member_types.size() == 0) + { + // Metal tessellation likes empty structs which are then constant expressions. + return "{ }"; + } else if (c.columns() == 1) { return constant_expression_vector(c, 0); @@ -4023,18 +4028,6 @@ string CompilerGLSL::constant_expression_vector(const SPIRConstant &c, uint32_t } break; - // Metal tessellation likes empty structs which are then constant expressions. - case SPIRType::Struct: - if (type.member_types.size() == 0) - { - res += "{ }"; - } - else - { - SPIRV_CROSS_THROW("Invalid constant struct initialisation missing member initializers."); - } - break; - default: SPIRV_CROSS_THROW("Invalid constant expression basetype."); } diff --git a/spirv_msl.cpp b/spirv_msl.cpp index 63cc8e5d..6e933207 100644 --- a/spirv_msl.cpp +++ b/spirv_msl.cpp @@ -4782,7 +4782,7 @@ void CompilerMSL::declare_undefined_values() bool emitted = false; ir.for_each_typed_id([&](uint32_t, SPIRUndef &undef) { auto &type = this->get(undef.basetype); - statement("constant ", CompilerGLSL::variable_decl(type, to_name(undef.self), undef.self), " = {};"); + statement("constant ", variable_decl(type, to_name(undef.self), undef.self), " = {};"); emitted = true; }); @@ -4805,7 +4805,7 @@ void CompilerMSL::declare_constant_arrays() if (!type.array.empty() && (is_scalar(type) || is_vector(type))) { auto name = to_name(c.self); - statement("constant ", CompilerGLSL::variable_decl(type, name), " = ", constant_expression(c), ";"); + statement("constant ", variable_decl(type, name), " = ", constant_expression(c), ";"); emitted = true; } }); @@ -4829,7 +4829,7 @@ void CompilerMSL::declare_complex_constant_arrays() if (!type.array.empty() && !(is_scalar(type) || is_vector(type))) { auto name = to_name(c.self); - statement("", CompilerGLSL::variable_decl(type, name), " = ", constant_expression(c), ";"); + statement("", variable_decl(type, name), " = ", constant_expression(c), ";"); emitted = true; } }); @@ -4940,7 +4940,7 @@ void CompilerMSL::emit_specialization_constants_and_structs() auto &c = id.get(); auto &type = get(c.basetype); auto name = to_name(c.self); - statement("constant ", CompilerGLSL::variable_decl(type, name), " = ", constant_op_expression(c), ";"); + statement("constant ", variable_decl(type, name), " = ", constant_op_expression(c), ";"); emitted = true; } else if (id.get_type() == TypeType) @@ -5066,7 +5066,7 @@ bool CompilerMSL::emit_tessellation_access_chain(const uint32_t *ops, uint32_t l if (is_matrix(*type) || is_array(*type) || type->basetype == SPIRType::Struct) { std::string temp_name = join(to_name(var->self), "_", ops[1]); - statement(CompilerGLSL::variable_decl(*type, temp_name, var->self), ";"); + statement(variable_decl(*type, temp_name, var->self), ";"); // Set up the initializer for this temporary variable. indices.push_back(const_mbr_id); if (type->basetype == SPIRType::Struct) @@ -6123,43 +6123,32 @@ void CompilerMSL::emit_instruction(const Instruction &instruction) void CompilerMSL::emit_texture_op(const Instruction &i) { - auto *ops = stream(i); - auto op = static_cast(i.op); - - SmallVector inherited_expressions; - - uint32_t result_type_id = ops[0]; - uint32_t id = ops[1]; - uint32_t img = ops[2]; - - auto &type = expression_type(img); - auto &imgtype = get(type.self); - - bool forward = false; - string expr = to_texture_op(i, &forward, inherited_expressions); - - // Use Metal's native frame-buffer fetch API for subpass inputs. - if (imgtype.image.dim == DimSubpassData && msl_options.is_ios() && msl_options.ios_use_framebuffer_fetch_subpasses) + if (msl_options.is_ios() && msl_options.ios_use_framebuffer_fetch_subpasses) { - expr = to_expression(img); + auto *ops = stream(i); + + uint32_t result_type_id = ops[0]; + uint32_t id = ops[1]; + uint32_t img = ops[2]; + + auto &type = expression_type(img); + auto &imgtype = get(type.self); + + // Use Metal's native frame-buffer fetch API for subpass inputs. + if (imgtype.image.dim == DimSubpassData) + { + SmallVector inherited_expressions; + bool forward = false; + to_texture_op(i, &forward, inherited_expressions); + + string expr = to_expression(img); + emit_op(result_type_id, id, expr, forward); + return; + } } - emit_op(result_type_id, id, expr, forward); - for (auto &inherit : inherited_expressions) - inherit_expression_dependencies(id, inherit); - - switch (op) - { - case OpImageSampleDrefImplicitLod: - case OpImageSampleImplicitLod: - case OpImageSampleProjImplicitLod: - case OpImageSampleProjDrefImplicitLod: - register_control_dependent_expression(id); - break; - - default: - break; - } + // Fallback to default implementation + CompilerGLSL::emit_texture_op(i); } void CompilerMSL::emit_barrier(uint32_t id_exe_scope, uint32_t id_mem_scope, uint32_t id_mem_sem) @@ -7261,7 +7250,7 @@ string CompilerMSL::to_function_args(VariableID img, const SPIRType &imgtype, bo if (!farg_str.empty()) farg_str += ", "; - if (imgtype.image.arrayed && msl_options.emulate_cube_array) + if (imgtype.image.dim == DimCube && imgtype.image.arrayed && msl_options.emulate_cube_array) { farg_str += "spvCubemapTo2DArrayFace(" + tex_coords + ").xy"; @@ -7269,7 +7258,7 @@ string CompilerMSL::to_function_args(VariableID img, const SPIRType &imgtype, bo farg_str += ", uint(" + to_extract_component_expression(coord, 2) + ")"; else farg_str += ", uint(spvCubemapTo2DArrayFace(" + tex_coords + ").z) + (uint(" + - to_extract_component_expression(coord, 2) + ") * 6u)"; + round_fp_tex_coords(to_extract_component_expression(coord, alt_coord_component), coord_is_fp) + ") * 6u)"; add_spv_func_and_recompile(SPVFuncImplCubemapTo2DArrayFace); } @@ -10275,6 +10264,12 @@ std::string CompilerMSL::variable_decl(const SPIRVariable &variable) return expr; } +// GCC workaround of lambdas calling protected funcs +std::string CompilerMSL::variable_decl(const SPIRType &type, const std::string &name, uint32_t id) +{ + return CompilerGLSL::variable_decl(type, name, id); +} + std::string CompilerMSL::sampler_type(const SPIRType &type) { if (!type.array.empty()) @@ -10395,11 +10390,14 @@ string CompilerMSL::image_type_glsl(const SPIRType &type, uint32_t id) else img_type_name += "texture2d"; break; + case Dim2D: case DimSubpassData: // Use Metal's native frame-buffer fetch API for subpass inputs. - if (msl_options.is_ios() && msl_options.ios_use_framebuffer_fetch_subpasses) + if (img_type.dim == DimSubpassData && msl_options.is_ios() && + msl_options.ios_use_framebuffer_fetch_subpasses) + { return type_to_glsl(get(img_type.type)); - case Dim2D: + } if (img_type.ms && img_type.arrayed) { if (!msl_options.supports_msl_version(2, 1)) diff --git a/spirv_msl.hpp b/spirv_msl.hpp index acbeca13..e4fd6b3e 100644 --- a/spirv_msl.hpp +++ b/spirv_msl.hpp @@ -291,7 +291,7 @@ public: bool ios_support_base_vertex_instance = false; // Use Metal's native frame-buffer fetch API for subpass inputs. - bool ios_use_framebuffer_fetch_subpasses = true; + bool ios_use_framebuffer_fetch_subpasses = false; // Storage buffer robustness - clamps access to SSBOs to the size of the buffer bool enforce_storge_buffer_bounds = false; @@ -576,9 +576,16 @@ protected: const std::string &qualifier = "", uint32_t base_offset = 0) override; void emit_struct_padding_target(const SPIRType &type) override; std::string type_to_glsl(const SPIRType &type, uint32_t id = 0) override; - std::string type_to_array_glsl( - const SPIRType &type) override; // Allow Metal to use the array template to make arrays a value type - std::string variable_decl(const SPIRVariable &variable) override; // Threadgroup arrays can't have a wrapper type + + // Allow Metal to use the array template to make arrays a value type + std::string type_to_array_glsl(const SPIRType &type) override; + + // Threadgroup arrays can't have a wrapper type + std::string variable_decl(const SPIRVariable &variable) override; + + // GCC workaround of lambdas calling protected functions (for older GCC versions) + std::string variable_decl(const SPIRType &type, const std::string &name, uint32_t id = 0) override; + std::string image_type_glsl(const SPIRType &type, uint32_t id = 0) override; std::string sampler_type(const SPIRType &type); std::string builtin_to_glsl(spv::BuiltIn builtin, spv::StorageClass storage) override; diff --git a/test_shaders.py b/test_shaders.py index a47f41b3..6e873826 100755 --- a/test_shaders.py +++ b/test_shaders.py @@ -195,6 +195,10 @@ def cross_compile_msl(shader, spirv, opt, iterations, paths): msl_args.append('--msl-argument-buffers') if '.texture-buffer-native.' in shader: msl_args.append('--msl-texture-buffer-native') + if '.framebuffer-fetch.' in shader: + msl_args.append('--msl-framebuffer-fetch') + if '.emulate-cube-array.' in shader: + msl_args.append('--msl-emulate-cube-array') if '.discrete.' in shader: # Arbitrary for testing purposes. msl_args.append('--msl-discrete-descriptor-set')