Support Invariant for BuiltInPosition.

This commit is contained in:
Hans-Kristian Arntzen 2018-03-01 12:30:55 +01:00
parent cae17224a0
commit 3c1b147272
15 changed files with 307 additions and 8 deletions

View File

@ -0,0 +1,9 @@
#version 450
invariant gl_Position;
void main()
{
gl_Position = vec4(1.0);
}

View File

@ -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);
}

View File

@ -0,0 +1,9 @@
#version 450
invariant gl_Position;
void main()
{
gl_Position = vec4(1.0);
}

View File

@ -0,0 +1,14 @@
#version 450
out gl_PerVertex
{
vec4 gl_Position;
};
invariant gl_Position;
void main()
{
gl_Position = vec4(1.0);
}

View File

@ -0,0 +1,9 @@
#version 450
invariant gl_Position;
void main()
{
gl_Position = vec4(1.0);
}

View File

@ -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);
}

View File

@ -0,0 +1,14 @@
#version 450
invariant gl_Position;
vec4 _main()
{
return vec4(1.0);
}
void main()
{
gl_Position = _main();
}

View File

@ -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();
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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<SPIRVariable>(id);
if (var && compiler.meta[id].decoration.builtin)
auto &decorations = compiler.meta[id].decoration;
if (var && decorations.builtin)
{
auto &type = compiler.get<SPIRType>(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<SPIRType>(type->member_types[index]), decorations.builtin_type);
handle_builtin(compiler.get<SPIRType>(type->member_types[index]), decorations.builtin_type,
decorations.decoration_flags);
}
}

View File

@ -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();

View File

@ -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<SPIRType>(type.member_types[index]).array.front();
else if (m.builtin_type == BuiltInClipDistance)
clip_distance_size = get<SPIRType>(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,