GLSL: Add option to force flattening IO blocks.

It is not always desirable to use actual blocks.
A prime example in the case where EXT_shader_io_blocks is not supported
on the target implementation.
This commit is contained in:
Hans-Kristian Arntzen 2020-07-28 15:15:24 +02:00
parent f5e9f4a172
commit 57c93d44ac
9 changed files with 71 additions and 4 deletions

View File

@ -323,7 +323,7 @@ if (SPIRV_CROSS_STATIC)
endif()
set(spirv-cross-abi-major 0)
set(spirv-cross-abi-minor 36)
set(spirv-cross-abi-minor 37)
set(spirv-cross-abi-patch 0)
if (SPIRV_CROSS_SHARED)

View File

@ -563,6 +563,7 @@ struct CLIArguments
uint32_t msl_additional_fixed_sample_mask = 0xffffffff;
bool glsl_emit_push_constant_as_ubo = false;
bool glsl_emit_ubo_as_plain_uniforms = false;
bool glsl_force_flattened_io_blocks = false;
SmallVector<pair<uint32_t, uint32_t>> glsl_ext_framebuffer_fetch;
bool vulkan_glsl_disable_ext_samplerless_texture_functions = false;
bool emit_line_directives = false;
@ -674,6 +675,7 @@ static void print_help_glsl()
"\t[--no-420pack-extension]:\n\t\tDo not make use of GL_ARB_shading_language_420pack in older GL targets to support layout(binding).\n"
"\t[--remap-variable-type <variable_name> <new_variable_type>]:\n\t\tRemaps a variable type based on name.\n"
"\t\tPrimary use case is supporting external samplers in ESSL for video rendering on Android where you could remap a texture to a YUV one.\n"
"\t[--glsl-force-flattened-io-blocks]:\n\t\tAlways flatten I/O blocks and structs.\n"
);
// clang-format on
}
@ -1131,6 +1133,7 @@ static string compile_iteration(const CLIArguments &args, std::vector<uint32_t>
opts.vertex.support_nonzero_base_instance = args.support_nonzero_baseinstance;
opts.emit_push_constant_as_uniform_buffer = args.glsl_emit_push_constant_as_ubo;
opts.emit_uniform_buffer_as_plain_uniforms = args.glsl_emit_ubo_as_plain_uniforms;
opts.force_flattened_io_blocks = args.glsl_force_flattened_io_blocks;
opts.emit_line_directives = args.emit_line_directives;
opts.enable_storage_image_qualifier_deduction = args.enable_storage_image_qualifier_deduction;
opts.force_zero_initialized_variables = args.force_zero_initialized_variables;
@ -1319,6 +1322,7 @@ static int main_inner(int argc, char *argv[])
cbs.add("--metal", [&args](CLIParser &) { args.msl = true; }); // Legacy compatibility
cbs.add("--glsl-emit-push-constant-as-ubo", [&args](CLIParser &) { args.glsl_emit_push_constant_as_ubo = true; });
cbs.add("--glsl-emit-ubo-as-plain-uniforms", [&args](CLIParser &) { args.glsl_emit_ubo_as_plain_uniforms = true; });
cbs.add("--glsl-force-flattened-io-blocks", [&args](CLIParser &) { args.glsl_force_flattened_io_blocks = true; });
cbs.add("--glsl-remap-ext-framebuffer-fetch", [&args](CLIParser &parser) {
uint32_t input_index = parser.next_uint();
uint32_t color_attachment = parser.next_uint();

View File

@ -0,0 +1,25 @@
#version 450
struct Foo
{
vec4 bar[2];
vec4 baz[2];
};
out vec4 _14_foo_bar[2];
out vec4 _14_foo_baz[2];
out vec4 _14_foo2_bar[2];
out vec4 _14_foo2_baz[2];
out vec4 foo3_bar[2];
out vec4 foo3_baz[2];
void main()
{
_14_foo_bar[0] = vec4(1.0);
_14_foo_baz[1] = vec4(2.0);
_14_foo2_bar[0] = vec4(3.0);
_14_foo2_baz[1] = vec4(4.0);
foo3_bar[0] = vec4(5.0);
foo3_baz[1] = vec4(6.0);
}

View File

@ -0,0 +1,25 @@
#version 450
struct Foo
{
vec4 bar[2];
vec4 baz[2];
};
layout(location = 0) out Vertex
{
Foo foo;
Foo foo2;
};
layout(location = 8) out Foo foo3;
void main()
{
foo.bar[0] = vec4(1.0);
foo.baz[1] = vec4(2.0);
foo2.bar[0] = vec4(3.0);
foo2.baz[1] = vec4(4.0);
foo3.bar[0] = vec4(5.0);
foo3.baz[1] = vec4(6.0);
}

View File

@ -459,6 +459,9 @@ spvc_result spvc_compiler_options_set_uint(spvc_compiler_options options, spvc_c
case SPVC_COMPILER_OPTION_GLSL_EMIT_UNIFORM_BUFFER_AS_PLAIN_UNIFORMS:
options->glsl.emit_uniform_buffer_as_plain_uniforms = value != 0;
break;
case SPVC_COMPILER_OPTION_GLSL_FORCE_FLATTENED_IO_BLOCKS:
options->glsl.force_flattened_io_blocks = value != 0;
break;
#endif
#if SPIRV_CROSS_C_API_HLSL

View File

@ -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 36
#define SPVC_C_API_VERSION_MINOR 37
/* Bumped if internal implementation details change. */
#define SPVC_C_API_VERSION_PATCH 0
@ -634,6 +634,8 @@ typedef enum spvc_compiler_option
SPVC_COMPILER_OPTION_MSL_VERTEX_FOR_TESSELLATION = 64 | SPVC_COMPILER_OPTION_MSL_BIT,
SPVC_COMPILER_OPTION_MSL_VERTEX_INDEX_TYPE = 65 | SPVC_COMPILER_OPTION_MSL_BIT,
SPVC_COMPILER_OPTION_GLSL_FORCE_FLATTENED_IO_BLOCKS = 66 | SPVC_COMPILER_OPTION_GLSL_BIT,
SPVC_COMPILER_OPTION_INT_MAX = 0x7fffffff
} spvc_compiler_option;

View File

@ -2232,7 +2232,8 @@ void CompilerGLSL::emit_interface_block(const SPIRVariable &var)
// ESSL earlier than 310 and GLSL earlier than 150 did not support
// I/O variables which are struct types.
// To support this, flatten the struct into separate varyings instead.
if ((options.es && options.version < 310) || (!options.es && options.version < 150))
if (options.force_flattened_io_blocks || (options.es && options.version < 310) ||
(!options.es && options.version < 150))
{
// I/O blocks on ES require version 310 with Android Extension Pack extensions, or core version 320.
// On desktop, I/O blocks were introduced with geometry shaders in GL 3.2 (GLSL 150).
@ -2292,7 +2293,8 @@ void CompilerGLSL::emit_interface_block(const SPIRVariable &var)
// I/O variables which are struct types.
// To support this, flatten the struct into separate varyings instead.
if (type.basetype == SPIRType::Struct &&
((options.es && options.version < 310) || (!options.es && options.version < 150)))
(options.force_flattened_io_blocks || (options.es && options.version < 310) ||
(!options.es && options.version < 150)))
{
emit_flattened_io_block(var, qual);
}

View File

@ -121,6 +121,10 @@ public:
// which would otherwise be uninitialized will now be initialized to 0 instead.
bool force_zero_initialized_variables = false;
// In GLSL, force use of I/O block flattening, similar to
// what happens on legacy GLSL targets for blocks and structs.
bool force_flattened_io_blocks = false;
enum Precision
{
DontCare,

View File

@ -501,6 +501,8 @@ def cross_compile(shader, vulkan, spirv, invalid_spirv, eliminate, is_legacy, fl
extra_args += ['--glsl-remap-ext-framebuffer-fetch', '3', '3']
if '.zero-initialize.' in shader:
extra_args += ['--force-zero-initialized-variables']
if '.force-flattened-io.' in shader:
extra_args += ['--glsl-force-flattened-io-blocks']
spirv_cross_path = paths.spirv_cross