Skip to content

Commit

Permalink
MSL: Don't set the layer for multiview if the device doesn't support it.
Browse files Browse the repository at this point in the history
Some older iOS devices don't support layered rendering. In that case,
don't set `[[render_target_array_index]]`, because the compiler will
reject the shader in that case. The client will then have to unroll the
render pass manually.
  • Loading branch information
cdavis5e committed Sep 2, 2020
1 parent 4752a44 commit cab7335
Show file tree
Hide file tree
Showing 13 changed files with 260 additions and 4 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -323,7 +323,7 @@ if (SPIRV_CROSS_STATIC)
endif()

set(spirv-cross-abi-major 0)
set(spirv-cross-abi-minor 37)
set(spirv-cross-abi-minor 38)
set(spirv-cross-abi-patch 0)

if (SPIRV_CROSS_SHARED)
Expand Down
6 changes: 6 additions & 0 deletions main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -549,6 +549,7 @@ struct CLIArguments
bool msl_invariant_float_math = false;
bool msl_emulate_cube_array = false;
bool msl_multiview = false;
bool msl_multiview_layered_rendering = true;
bool msl_view_index_from_device_index = false;
bool msl_dispatch_base = false;
bool msl_decoration_binding = false;
Expand Down Expand Up @@ -732,6 +733,8 @@ static void print_help_msl()
"\t[--msl-device-argument-buffer <descriptor set index>]:\n\t\tUse device address space to hold indirect argument buffers instead of constant.\n"
"\t\tComes up when trying to support argument buffers which are larger than 64 KiB.\n"
"\t[--msl-multiview]:\n\t\tEnable SPV_KHR_multiview emulation.\n"
"\t[--msl-multiview-no-layered-rendering]:\n\t\tDon't set [[render_target_array_index]] in multiview shaders.\n"
"\t\tUseful for devices which don't support layered rendering. Only effective when --msl-multiview is enabled.\n"
"\t[--msl-view-index-from-device-index]:\n\t\tTreat the view index as the device index instead.\n"
"\t\tFor multi-GPU rendering.\n"
"\t[--msl-dispatch-base]:\n\t\tAdd support for vkCmdDispatchBase() or similar APIs.\n"
Expand Down Expand Up @@ -987,6 +990,7 @@ static string compile_iteration(const CLIArguments &args, std::vector<uint32_t>
msl_opts.argument_buffers = args.msl_argument_buffers;
msl_opts.texture_buffer_native = args.msl_texture_buffer_native;
msl_opts.multiview = args.msl_multiview;
msl_opts.multiview_layered_rendering = args.msl_multiview_layered_rendering;
msl_opts.view_index_from_device_index = args.msl_view_index_from_device_index;
msl_opts.dispatch_base = args.msl_dispatch_base;
msl_opts.enable_decoration_binding = args.msl_decoration_binding;
Expand Down Expand Up @@ -1366,6 +1370,8 @@ static int main_inner(int argc, char *argv[])
cbs.add("--msl-invariant-float-math", [&args](CLIParser &) { args.msl_invariant_float_math = 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-multiview-no-layered-rendering",
[&args](CLIParser &) { args.msl_multiview_layered_rendering = false; });
cbs.add("--msl-view-index-from-device-index",
[&args](CLIParser &) { args.msl_view_index_from_device_index = true; });
cbs.add("--msl-dispatch-base", [&args](CLIParser &) { args.msl_dispatch_base = true; });
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
#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
{
float4 vColor [[user(locn0)]];
float2 vTex_0 [[user(locn1)]];
float2 vTex_1 [[user(locn2)]];
float2 vTex_2 [[user(locn3)]];
float2 vTex_3 [[user(locn4)]];
};

fragment main0_out main0(main0_in in [[stage_in]], constant uint* spvViewMask [[buffer(24)]], texture2d<float> uTex [[texture(0)]], sampler uTexSmplr [[sampler(0)]])
{
main0_out out = {};
spvUnsafeArray<float2, 4> vTex = {};
vTex[0] = in.vTex_0;
vTex[1] = in.vTex_1;
vTex[2] = in.vTex_2;
vTex[3] = in.vTex_3;
const uint gl_ViewIndex = spvViewMask[0];
out.FragColor = in.vColor * uTex.sample(uTexSmplr, vTex[int(gl_ViewIndex)]);
return out;
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#include <metal_stdlib>
#include <simd/simd.h>

using namespace metal;

struct MVPs
{
float4x4 MVP[2];
};

struct main0_out
{
float4 gl_Position [[position]];
};

struct main0_in
{
float4 Position [[attribute(0)]];
};

vertex main0_out main0(main0_in in [[stage_in]], constant uint* spvViewMask [[buffer(24)]], constant MVPs& _19 [[buffer(0)]])
{
main0_out out = {};
const uint gl_ViewIndex = spvViewMask[0];
out.gl_Position = _19.MVP[int(gl_ViewIndex)] * in.Position;
return out;
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
#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
{
float4 vColor [[user(locn0)]];
float2 vTex_0 [[user(locn1)]];
float2 vTex_1 [[user(locn2)]];
float2 vTex_2 [[user(locn3)]];
float2 vTex_3 [[user(locn4)]];
};

fragment main0_out main0(main0_in in [[stage_in]], constant uint* spvViewMask [[buffer(24)]], texture2d<float> uTex [[texture(0)]], sampler uTexSmplr [[sampler(0)]])
{
main0_out out = {};
spvUnsafeArray<float2, 4> vTex = {};
vTex[0] = in.vTex_0;
vTex[1] = in.vTex_1;
vTex[2] = in.vTex_2;
vTex[3] = in.vTex_3;
const uint gl_ViewIndex = spvViewMask[0];
out.FragColor = in.vColor * uTex.sample(uTexSmplr, vTex[int(gl_ViewIndex)]);
return out;
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#include <metal_stdlib>
#include <simd/simd.h>

using namespace metal;

struct MVPs
{
float4x4 MVP[2];
};

struct main0_out
{
float4 gl_Position [[position]];
};

struct main0_in
{
float4 Position [[attribute(0)]];
};

vertex main0_out main0(main0_in in [[stage_in]], constant uint* spvViewMask [[buffer(24)]], constant MVPs& _19 [[buffer(0)]])
{
main0_out out = {};
const uint gl_ViewIndex = spvViewMask[0];
out.gl_Position = _19.MVP[int(gl_ViewIndex)] * in.Position;
return out;
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#version 310 es
#extension GL_EXT_multiview : require
precision mediump float;

layout(location = 0) in vec4 vColor;
layout(location = 1) in vec2 vTex[4];
layout(binding = 0) uniform sampler2D uTex;
layout(location = 0) out vec4 FragColor;

void main()
{
FragColor = vColor * texture(uTex, vTex[gl_ViewIndex]);
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#version 310 es
#extension GL_EXT_multiview : require

layout(std140, binding = 0) uniform MVPs
{
mat4 MVP[2];
};

layout(location = 0) in vec4 Position;

void main()
{
gl_Position = MVP[gl_ViewIndex] * Position;
}
4 changes: 4 additions & 0 deletions spirv_cross_c.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -658,6 +658,10 @@ spvc_result spvc_compiler_options_set_uint(spvc_compiler_options options, spvc_c
case SPVC_COMPILER_OPTION_MSL_VERTEX_INDEX_TYPE:
options->msl.vertex_index_type = static_cast<CompilerMSL::Options::IndexType>(value);
break;

case SPVC_COMPILER_OPTION_MSL_MULTIVIEW_LAYERED_RENDERING:
options->msl.multiview_layered_rendering = value != 0;
break;
#endif

default:
Expand Down
4 changes: 3 additions & 1 deletion spirv_cross_c.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ extern "C" {
/* Bumped if ABI or API breaks backwards compatibility. */
#define SPVC_C_API_VERSION_MAJOR 0
/* Bumped if APIs or enumerations are added in a backwards compatible way. */
#define SPVC_C_API_VERSION_MINOR 37
#define SPVC_C_API_VERSION_MINOR 38
/* Bumped if internal implementation details change. */
#define SPVC_C_API_VERSION_PATCH 0

Expand Down Expand Up @@ -636,6 +636,8 @@ typedef enum spvc_compiler_option

SPVC_COMPILER_OPTION_GLSL_FORCE_FLATTENED_IO_BLOCKS = 66 | SPVC_COMPILER_OPTION_GLSL_BIT,

SPVC_COMPILER_OPTION_MSL_MULTIVIEW_LAYERED_RENDERING = 67 | SPVC_COMPILER_OPTION_MSL_BIT,

SPVC_COMPILER_OPTION_INT_MAX = 0x7fffffff
} spvc_compiler_option;

Expand Down
15 changes: 13 additions & 2 deletions spirv_msl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ void CompilerMSL::build_implicit_builtins()
bool need_subgroup_ge_mask = !msl_options.is_ios() && (active_input_builtins.get(BuiltInSubgroupGeMask) ||
active_input_builtins.get(BuiltInSubgroupGtMask));
bool need_multiview = get_execution_model() == ExecutionModelVertex && !msl_options.view_index_from_device_index &&
msl_options.multiview_layered_rendering &&
(msl_options.multiview || active_input_builtins.get(BuiltInViewIndex));
bool need_dispatch_base =
msl_options.dispatch_base && get_execution_model() == ExecutionModelGLCompute &&
Expand Down Expand Up @@ -9242,7 +9243,7 @@ string CompilerMSL::member_attribute_qualifier(const SPIRType &type, uint32_t in
switch (builtin)
{
case BuiltInViewIndex:
if (!msl_options.multiview)
if (!msl_options.multiview || !msl_options.multiview_layered_rendering)
break;
/* fallthrough */
case BuiltInFrontFacing:
Expand Down Expand Up @@ -9660,7 +9661,8 @@ bool CompilerMSL::is_direct_input_builtin(BuiltIn bi_type)
case BuiltInBaryCoordNoPerspNV:
return false;
case BuiltInViewIndex:
return get_execution_model() == ExecutionModelFragment && msl_options.multiview;
return get_execution_model() == ExecutionModelFragment && msl_options.multiview &&
msl_options.multiview_layered_rendering;
// Any stage function in
case BuiltInDeviceIndex:
case BuiltInSubgroupEqMask:
Expand Down Expand Up @@ -10430,6 +10432,15 @@ void CompilerMSL::fix_up_shader_inputs_outputs()
// Since every physical device is rendering a different view,
// there's no need for layered rendering here.
}
else if (!msl_options.multiview_layered_rendering)
{
// In this case, the views are rendered one at a time. The view index, then,
// is just the first part of the "view mask".
entry_func.fixup_hooks_in.push_back([=]() {
statement("const ", builtin_type_decl(bi_type), " ", to_expression(var_id), " = ",
to_expression(view_mask_buffer_id), "[0];");
});
}
else if (get_execution_model() == ExecutionModelFragment)
{
// Because we adjusted the view index in the vertex shader, we have to
Expand Down
1 change: 1 addition & 0 deletions spirv_msl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,7 @@ class CompilerMSL : public CompilerGLSL
bool swizzle_texture_samples = false;
bool tess_domain_origin_lower_left = false;
bool multiview = false;
bool multiview_layered_rendering = true;
bool view_index_from_device_index = false;
bool dispatch_base = false;
bool texture_1D_as_2D = false;
Expand Down
2 changes: 2 additions & 0 deletions test_shaders.py
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,8 @@ def cross_compile_msl(shader, spirv, opt, iterations, paths):
msl_args.append('--emit-line-directives')
if '.multiview.' in shader:
msl_args.append('--msl-multiview')
if '.no-layered.' in shader:
msl_args.append('--msl-multiview-no-layered-rendering')
if '.viewfromdev.' in shader:
msl_args.append('--msl-view-index-from-device-index')
if '.dispatchbase.' in shader:
Expand Down

0 comments on commit cab7335

Please sign in to comment.