MSL: Don't set the layer for multiview if the device doesn't support it.
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.
This commit is contained in:
parent
4752a44f9e
commit
cab7335e64
@ -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)
|
||||
|
6
main.cpp
6
main.cpp
@ -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;
|
||||
@ -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"
|
||||
@ -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;
|
||||
@ -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; });
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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]);
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
@ -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:
|
||||
|
@ -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
|
||||
|
||||
@ -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;
|
||||
|
||||
|
@ -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 &&
|
||||
@ -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:
|
||||
@ -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:
|
||||
@ -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
|
||||
|
@ -290,6 +290,7 @@ public:
|
||||
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;
|
||||
|
@ -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:
|
||||
|
Loading…
Reference in New Issue
Block a user