From 3c1b147272b767128ceea84e6ab3b2b7639e5bca Mon Sep 17 00:00:00 2001 From: Hans-Kristian Arntzen Date: Thu, 1 Mar 2018 12:30:55 +0100 Subject: [PATCH] Support Invariant for BuiltInPosition. --- .../shaders/asm/vert/invariant-block.asm.vert | 9 ++++ .../asm/vert/invariant-block.sso.asm.vert | 17 +++++++ .../opt/shaders/asm/vert/invariant.asm.vert | 9 ++++ .../shaders/asm/vert/invariant.sso.asm.vert | 14 ++++++ .../shaders/asm/vert/invariant-block.asm.vert | 9 ++++ .../asm/vert/invariant-block.sso.asm.vert | 17 +++++++ reference/shaders/asm/vert/invariant.asm.vert | 14 ++++++ .../shaders/asm/vert/invariant.sso.asm.vert | 19 ++++++++ shaders/asm/vert/invariant-block.asm.vert | 44 +++++++++++++++++++ shaders/asm/vert/invariant-block.sso.asm.vert | 44 +++++++++++++++++++ shaders/asm/vert/invariant.asm.vert | 34 ++++++++++++++ shaders/asm/vert/invariant.sso.asm.vert | 34 ++++++++++++++ spirv_cross.cpp | 17 ++++--- spirv_cross.hpp | 3 +- spirv_glsl.cpp | 31 ++++++++++++- 15 files changed, 307 insertions(+), 8 deletions(-) create mode 100644 reference/opt/shaders/asm/vert/invariant-block.asm.vert create mode 100644 reference/opt/shaders/asm/vert/invariant-block.sso.asm.vert create mode 100644 reference/opt/shaders/asm/vert/invariant.asm.vert create mode 100644 reference/opt/shaders/asm/vert/invariant.sso.asm.vert create mode 100644 reference/shaders/asm/vert/invariant-block.asm.vert create mode 100644 reference/shaders/asm/vert/invariant-block.sso.asm.vert create mode 100644 reference/shaders/asm/vert/invariant.asm.vert create mode 100644 reference/shaders/asm/vert/invariant.sso.asm.vert create mode 100644 shaders/asm/vert/invariant-block.asm.vert create mode 100644 shaders/asm/vert/invariant-block.sso.asm.vert create mode 100644 shaders/asm/vert/invariant.asm.vert create mode 100644 shaders/asm/vert/invariant.sso.asm.vert diff --git a/reference/opt/shaders/asm/vert/invariant-block.asm.vert b/reference/opt/shaders/asm/vert/invariant-block.asm.vert new file mode 100644 index 00000000..9b2f05a8 --- /dev/null +++ b/reference/opt/shaders/asm/vert/invariant-block.asm.vert @@ -0,0 +1,9 @@ +#version 450 + +invariant gl_Position; + +void main() +{ + gl_Position = vec4(1.0); +} + diff --git a/reference/opt/shaders/asm/vert/invariant-block.sso.asm.vert b/reference/opt/shaders/asm/vert/invariant-block.sso.asm.vert new file mode 100644 index 00000000..eb886941 --- /dev/null +++ b/reference/opt/shaders/asm/vert/invariant-block.sso.asm.vert @@ -0,0 +1,17 @@ +#version 450 + +out gl_PerVertex +{ + vec4 gl_Position; + float gl_PointSize; + float gl_ClipDistance[1]; + float gl_CullDistance[1]; +}; + +invariant gl_Position; + +void main() +{ + gl_Position = vec4(1.0); +} + diff --git a/reference/opt/shaders/asm/vert/invariant.asm.vert b/reference/opt/shaders/asm/vert/invariant.asm.vert new file mode 100644 index 00000000..9b2f05a8 --- /dev/null +++ b/reference/opt/shaders/asm/vert/invariant.asm.vert @@ -0,0 +1,9 @@ +#version 450 + +invariant gl_Position; + +void main() +{ + gl_Position = vec4(1.0); +} + diff --git a/reference/opt/shaders/asm/vert/invariant.sso.asm.vert b/reference/opt/shaders/asm/vert/invariant.sso.asm.vert new file mode 100644 index 00000000..4f7e2f5f --- /dev/null +++ b/reference/opt/shaders/asm/vert/invariant.sso.asm.vert @@ -0,0 +1,14 @@ +#version 450 + +out gl_PerVertex +{ + vec4 gl_Position; +}; + +invariant gl_Position; + +void main() +{ + gl_Position = vec4(1.0); +} + diff --git a/reference/shaders/asm/vert/invariant-block.asm.vert b/reference/shaders/asm/vert/invariant-block.asm.vert new file mode 100644 index 00000000..9b2f05a8 --- /dev/null +++ b/reference/shaders/asm/vert/invariant-block.asm.vert @@ -0,0 +1,9 @@ +#version 450 + +invariant gl_Position; + +void main() +{ + gl_Position = vec4(1.0); +} + diff --git a/reference/shaders/asm/vert/invariant-block.sso.asm.vert b/reference/shaders/asm/vert/invariant-block.sso.asm.vert new file mode 100644 index 00000000..eb886941 --- /dev/null +++ b/reference/shaders/asm/vert/invariant-block.sso.asm.vert @@ -0,0 +1,17 @@ +#version 450 + +out gl_PerVertex +{ + vec4 gl_Position; + float gl_PointSize; + float gl_ClipDistance[1]; + float gl_CullDistance[1]; +}; + +invariant gl_Position; + +void main() +{ + gl_Position = vec4(1.0); +} + diff --git a/reference/shaders/asm/vert/invariant.asm.vert b/reference/shaders/asm/vert/invariant.asm.vert new file mode 100644 index 00000000..a151c1d0 --- /dev/null +++ b/reference/shaders/asm/vert/invariant.asm.vert @@ -0,0 +1,14 @@ +#version 450 + +invariant gl_Position; + +vec4 _main() +{ + return vec4(1.0); +} + +void main() +{ + gl_Position = _main(); +} + diff --git a/reference/shaders/asm/vert/invariant.sso.asm.vert b/reference/shaders/asm/vert/invariant.sso.asm.vert new file mode 100644 index 00000000..a52c7e5a --- /dev/null +++ b/reference/shaders/asm/vert/invariant.sso.asm.vert @@ -0,0 +1,19 @@ +#version 450 + +out gl_PerVertex +{ + vec4 gl_Position; +}; + +invariant gl_Position; + +vec4 _main() +{ + return vec4(1.0); +} + +void main() +{ + gl_Position = _main(); +} + diff --git a/shaders/asm/vert/invariant-block.asm.vert b/shaders/asm/vert/invariant-block.asm.vert new file mode 100644 index 00000000..5984935c --- /dev/null +++ b/shaders/asm/vert/invariant-block.asm.vert @@ -0,0 +1,44 @@ +; SPIR-V +; Version: 1.0 +; Generator: Khronos Glslang Reference Front End; 3 +; Bound: 20 +; Schema: 0 + OpCapability Shader + %1 = OpExtInstImport "GLSL.std.450" + OpMemoryModel Logical GLSL450 + OpEntryPoint Vertex %main "main" %_ + OpSource GLSL 450 + OpName %main "main" + OpName %gl_PerVertex "gl_PerVertex" + OpMemberName %gl_PerVertex 0 "gl_Position" + OpMemberName %gl_PerVertex 1 "gl_PointSize" + OpMemberName %gl_PerVertex 2 "gl_ClipDistance" + OpMemberName %gl_PerVertex 3 "gl_CullDistance" + OpName %_ "" + OpMemberDecorate %gl_PerVertex 0 Invariant + OpMemberDecorate %gl_PerVertex 0 BuiltIn Position + OpMemberDecorate %gl_PerVertex 1 BuiltIn PointSize + OpMemberDecorate %gl_PerVertex 2 BuiltIn ClipDistance + OpMemberDecorate %gl_PerVertex 3 BuiltIn CullDistance + OpDecorate %gl_PerVertex Block + %void = OpTypeVoid + %3 = OpTypeFunction %void + %float = OpTypeFloat 32 + %v4float = OpTypeVector %float 4 + %uint = OpTypeInt 32 0 + %uint_1 = OpConstant %uint 1 +%_arr_float_uint_1 = OpTypeArray %float %uint_1 +%gl_PerVertex = OpTypeStruct %v4float %float %_arr_float_uint_1 %_arr_float_uint_1 +%_ptr_Output_gl_PerVertex = OpTypePointer Output %gl_PerVertex + %_ = OpVariable %_ptr_Output_gl_PerVertex Output + %int = OpTypeInt 32 1 + %int_0 = OpConstant %int 0 + %float_1 = OpConstant %float 1 + %17 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1 +%_ptr_Output_v4float = OpTypePointer Output %v4float + %main = OpFunction %void None %3 + %5 = OpLabel + %19 = OpAccessChain %_ptr_Output_v4float %_ %int_0 + OpStore %19 %17 + OpReturn + OpFunctionEnd diff --git a/shaders/asm/vert/invariant-block.sso.asm.vert b/shaders/asm/vert/invariant-block.sso.asm.vert new file mode 100644 index 00000000..5984935c --- /dev/null +++ b/shaders/asm/vert/invariant-block.sso.asm.vert @@ -0,0 +1,44 @@ +; SPIR-V +; Version: 1.0 +; Generator: Khronos Glslang Reference Front End; 3 +; Bound: 20 +; Schema: 0 + OpCapability Shader + %1 = OpExtInstImport "GLSL.std.450" + OpMemoryModel Logical GLSL450 + OpEntryPoint Vertex %main "main" %_ + OpSource GLSL 450 + OpName %main "main" + OpName %gl_PerVertex "gl_PerVertex" + OpMemberName %gl_PerVertex 0 "gl_Position" + OpMemberName %gl_PerVertex 1 "gl_PointSize" + OpMemberName %gl_PerVertex 2 "gl_ClipDistance" + OpMemberName %gl_PerVertex 3 "gl_CullDistance" + OpName %_ "" + OpMemberDecorate %gl_PerVertex 0 Invariant + OpMemberDecorate %gl_PerVertex 0 BuiltIn Position + OpMemberDecorate %gl_PerVertex 1 BuiltIn PointSize + OpMemberDecorate %gl_PerVertex 2 BuiltIn ClipDistance + OpMemberDecorate %gl_PerVertex 3 BuiltIn CullDistance + OpDecorate %gl_PerVertex Block + %void = OpTypeVoid + %3 = OpTypeFunction %void + %float = OpTypeFloat 32 + %v4float = OpTypeVector %float 4 + %uint = OpTypeInt 32 0 + %uint_1 = OpConstant %uint 1 +%_arr_float_uint_1 = OpTypeArray %float %uint_1 +%gl_PerVertex = OpTypeStruct %v4float %float %_arr_float_uint_1 %_arr_float_uint_1 +%_ptr_Output_gl_PerVertex = OpTypePointer Output %gl_PerVertex + %_ = OpVariable %_ptr_Output_gl_PerVertex Output + %int = OpTypeInt 32 1 + %int_0 = OpConstant %int 0 + %float_1 = OpConstant %float 1 + %17 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1 +%_ptr_Output_v4float = OpTypePointer Output %v4float + %main = OpFunction %void None %3 + %5 = OpLabel + %19 = OpAccessChain %_ptr_Output_v4float %_ %int_0 + OpStore %19 %17 + OpReturn + OpFunctionEnd diff --git a/shaders/asm/vert/invariant.asm.vert b/shaders/asm/vert/invariant.asm.vert new file mode 100644 index 00000000..c0d381ee --- /dev/null +++ b/shaders/asm/vert/invariant.asm.vert @@ -0,0 +1,34 @@ +; SPIR-V +; Version: 1.0 +; Generator: Khronos Glslang Reference Front End; 3 +; Bound: 18 +; Schema: 0 + OpCapability Shader + %1 = OpExtInstImport "GLSL.std.450" + OpMemoryModel Logical GLSL450 + OpEntryPoint Vertex %main "main" %_entryPointOutput + OpSource HLSL 500 + OpName %main "main" + OpName %_main_ "@main(" + OpName %_entryPointOutput "@entryPointOutput" + OpDecorate %_entryPointOutput Invariant + OpDecorate %_entryPointOutput BuiltIn Position + %void = OpTypeVoid + %3 = OpTypeFunction %void + %float = OpTypeFloat 32 + %v4float = OpTypeVector %float 4 + %8 = OpTypeFunction %v4float + %float_1 = OpConstant %float 1 + %12 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1 +%_ptr_Output_v4float = OpTypePointer Output %v4float +%_entryPointOutput = OpVariable %_ptr_Output_v4float Output + %main = OpFunction %void None %3 + %5 = OpLabel + %17 = OpFunctionCall %v4float %_main_ + OpStore %_entryPointOutput %17 + OpReturn + OpFunctionEnd + %_main_ = OpFunction %v4float None %8 + %10 = OpLabel + OpReturnValue %12 + OpFunctionEnd diff --git a/shaders/asm/vert/invariant.sso.asm.vert b/shaders/asm/vert/invariant.sso.asm.vert new file mode 100644 index 00000000..c0d381ee --- /dev/null +++ b/shaders/asm/vert/invariant.sso.asm.vert @@ -0,0 +1,34 @@ +; SPIR-V +; Version: 1.0 +; Generator: Khronos Glslang Reference Front End; 3 +; Bound: 18 +; Schema: 0 + OpCapability Shader + %1 = OpExtInstImport "GLSL.std.450" + OpMemoryModel Logical GLSL450 + OpEntryPoint Vertex %main "main" %_entryPointOutput + OpSource HLSL 500 + OpName %main "main" + OpName %_main_ "@main(" + OpName %_entryPointOutput "@entryPointOutput" + OpDecorate %_entryPointOutput Invariant + OpDecorate %_entryPointOutput BuiltIn Position + %void = OpTypeVoid + %3 = OpTypeFunction %void + %float = OpTypeFloat 32 + %v4float = OpTypeVector %float 4 + %8 = OpTypeFunction %v4float + %float_1 = OpConstant %float 1 + %12 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1 +%_ptr_Output_v4float = OpTypePointer Output %v4float +%_entryPointOutput = OpVariable %_ptr_Output_v4float Output + %main = OpFunction %void None %3 + %5 = OpLabel + %17 = OpFunctionCall %v4float %_main_ + OpStore %_entryPointOutput %17 + OpReturn + OpFunctionEnd + %_main_ = OpFunction %v4float None %8 + %10 = OpLabel + OpReturnValue %12 + OpFunctionEnd diff --git a/spirv_cross.cpp b/spirv_cross.cpp index a5808529..52683a51 100644 --- a/spirv_cross.cpp +++ b/spirv_cross.cpp @@ -3751,7 +3751,7 @@ bool Compiler::get_common_basic_type(const SPIRType &type, SPIRType::BaseType &b } } -void Compiler::ActiveBuiltinHandler::handle_builtin(const SPIRType &type, BuiltIn builtin) +void Compiler::ActiveBuiltinHandler::handle_builtin(const SPIRType &type, BuiltIn builtin, uint64_t decoration_flags) { // If used, we will need to explicitly declare a new array size for these builtins. @@ -3773,6 +3773,11 @@ void Compiler::ActiveBuiltinHandler::handle_builtin(const SPIRType &type, BuiltI SPIRV_CROSS_THROW("Array size for CullDistance must not be unsized."); compiler.cull_distance_count = array_size; } + else if (builtin == BuiltInPosition) + { + if (decoration_flags & (1ull << DecorationInvariant)) + compiler.position_invariant = true; + } } bool Compiler::ActiveBuiltinHandler::handle(spv::Op opcode, const uint32_t *args, uint32_t length) @@ -3781,13 +3786,14 @@ bool Compiler::ActiveBuiltinHandler::handle(spv::Op opcode, const uint32_t *args // Only handles variables here. // Builtins which are part of a block are handled in AccessChain. auto *var = compiler.maybe_get(id); - if (var && compiler.meta[id].decoration.builtin) + auto &decorations = compiler.meta[id].decoration; + if (var && decorations.builtin) { auto &type = compiler.get(var->basetype); auto &flags = type.storage == StorageClassInput ? compiler.active_input_builtins : compiler.active_output_builtins; - flags |= 1ull << compiler.meta[id].decoration.builtin_type; - handle_builtin(type, compiler.meta[id].decoration.builtin_type); + flags |= 1ull << decorations.builtin_type; + handle_builtin(type, decorations.builtin_type, decorations.decoration_flags); } }; @@ -3875,7 +3881,8 @@ bool Compiler::ActiveBuiltinHandler::handle(spv::Op opcode, const uint32_t *args if (decorations.builtin) { flags |= 1ull << decorations.builtin_type; - handle_builtin(compiler.get(type->member_types[index]), decorations.builtin_type); + handle_builtin(compiler.get(type->member_types[index]), decorations.builtin_type, + decorations.decoration_flags); } } diff --git a/spirv_cross.hpp b/spirv_cross.hpp index 69079232..795dbc45 100644 --- a/spirv_cross.hpp +++ b/spirv_cross.hpp @@ -716,7 +716,7 @@ protected: bool handle(spv::Op opcode, const uint32_t *args, uint32_t length) override; Compiler &compiler; - void handle_builtin(const SPIRType &type, spv::BuiltIn builtin); + void handle_builtin(const SPIRType &type, spv::BuiltIn builtin, uint64_t decoration_flags); }; bool traverse_all_reachable_opcodes(const SPIRBlock &block, OpcodeHandler &handler) const; @@ -739,6 +739,7 @@ protected: uint64_t active_output_builtins = 0; uint32_t clip_distance_count = 0; uint32_t cull_distance_count = 0; + bool position_invariant = false; // Traverses all reachable opcodes and sets active_builtins to a bitmask of all builtin variables which are accessed in the shader. void update_active_builtins(); diff --git a/spirv_glsl.cpp b/spirv_glsl.cpp index 93518eb8..882d241f 100644 --- a/spirv_glsl.cpp +++ b/spirv_glsl.cpp @@ -1816,6 +1816,11 @@ void CompilerGLSL::emit_declared_builtin_block(StorageClass storage, ExecutionMo bool emitted_block = false; bool builtin_array = false; + // Need to use declared size in the type. + // These variables might have been declared, but not statically used, so we haven't deduced their size yet. + uint32_t cull_distance_size = 0; + uint32_t clip_distance_size = 0; + for (auto &id : ids) { if (id.get_type() != TypeVariable) @@ -1828,16 +1833,32 @@ void CompilerGLSL::emit_declared_builtin_block(StorageClass storage, ExecutionMo if (var.storage == storage && block && is_builtin_variable(var)) { + uint32_t index = 0; for (auto &m : meta[type.self].members) + { if (m.builtin) + { builtins |= 1ull << m.builtin_type; + if (m.builtin_type == BuiltInCullDistance) + cull_distance_size = get(type.member_types[index]).array.front(); + else if (m.builtin_type == BuiltInClipDistance) + clip_distance_size = get(type.member_types[index]).array.front(); + } + index++; + } } else if (var.storage == storage && !block && is_builtin_variable(var)) { // While we're at it, collect all declared global builtins (HLSL mostly ...). auto &m = meta[var.self].decoration; if (m.builtin) + { global_builtins |= 1ull << m.builtin_type; + if (m.builtin_type == BuiltInCullDistance) + cull_distance_size = type.array.front(); + else if (m.builtin_type == BuiltInClipDistance) + clip_distance_size = type.array.front(); + } } if (!builtins) @@ -1874,9 +1895,9 @@ void CompilerGLSL::emit_declared_builtin_block(StorageClass storage, ExecutionMo if (emitted_builtins & (1ull << BuiltInPointSize)) statement("float gl_PointSize;"); if (emitted_builtins & (1ull << BuiltInClipDistance)) - statement("float gl_ClipDistance[", clip_distance_count, "];"); + statement("float gl_ClipDistance[", clip_distance_size, "];"); if (emitted_builtins & (1ull << BuiltInCullDistance)) - statement("float gl_CullDistance[", cull_distance_count, "];"); + statement("float gl_CullDistance[", cull_distance_size, "];"); bool tessellation = model == ExecutionModelTessellationEvaluation || model == ExecutionModelTessellationControl; if (builtin_array) @@ -1962,6 +1983,12 @@ void CompilerGLSL::emit_resources() statement(""); } + if (position_invariant) + { + statement("invariant gl_Position;"); + statement(""); + } + bool emitted = false; // If emitted Vulkan GLSL,