Fix SSO for HLSL vertex shaders.

This commit is contained in:
Hans-Kristian Arntzen 2017-11-17 13:37:28 +01:00
Родитель debe269a16
Коммит dd604fec9a
3 изменённых файлов: 165 добавлений и 34 удалений

Просмотреть файл

@ -0,0 +1,35 @@
#version 450
out gl_PerVertex
{
vec4 gl_Position;
};
struct VSOut
{
float a;
vec4 pos;
};
struct VSOut_1
{
float a;
};
layout(location = 0) out VSOut_1 _entryPointOutput;
VSOut _main()
{
VSOut vout;
vout.a = 40.0;
vout.pos = vec4(1.0);
return vout;
}
void main()
{
VSOut flattenTemp = _main();
_entryPointOutput.a = flattenTemp.a;
gl_Position = flattenTemp.pos;
}

Просмотреть файл

@ -0,0 +1,68 @@
; SPIR-V
; Version: 1.0
; Generator: Khronos Glslang Reference Front End; 1
; Bound: 40
; Schema: 0
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint Vertex %main "main" %_entryPointOutput %_entryPointOutput_pos
OpSource HLSL 500
OpName %main "main"
OpName %VSOut "VSOut"
OpMemberName %VSOut 0 "a"
OpMemberName %VSOut 1 "pos"
OpName %_main_ "@main("
OpName %vout "vout"
OpName %flattenTemp "flattenTemp"
OpName %VSOut_0 "VSOut"
OpMemberName %VSOut_0 0 "a"
OpName %_entryPointOutput "@entryPointOutput"
OpName %_entryPointOutput_pos "@entryPointOutput_pos"
OpDecorate %_entryPointOutput Location 0
OpDecorate %_entryPointOutput_pos BuiltIn Position
%void = OpTypeVoid
%3 = OpTypeFunction %void
%float = OpTypeFloat 32
%v4float = OpTypeVector %float 4
%VSOut = OpTypeStruct %float %v4float
%9 = OpTypeFunction %VSOut
%_ptr_Function_VSOut = OpTypePointer Function %VSOut
%int = OpTypeInt 32 1
%int_0 = OpConstant %int 0
%float_40 = OpConstant %float 40
%_ptr_Function_float = OpTypePointer Function %float
%int_1 = OpConstant %int 1
%float_1 = OpConstant %float 1
%21 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1
%_ptr_Function_v4float = OpTypePointer Function %v4float
%VSOut_0 = OpTypeStruct %float
%_ptr_Output_VSOut_0 = OpTypePointer Output %VSOut_0
%_entryPointOutput = OpVariable %_ptr_Output_VSOut_0 Output
%_ptr_Output_float = OpTypePointer Output %float
%_ptr_Output_v4float = OpTypePointer Output %v4float
%_entryPointOutput_pos = OpVariable %_ptr_Output_v4float Output
%main = OpFunction %void None %3
%5 = OpLabel
%flattenTemp = OpVariable %_ptr_Function_VSOut Function
%28 = OpFunctionCall %VSOut %_main_
OpStore %flattenTemp %28
%32 = OpAccessChain %_ptr_Function_float %flattenTemp %int_0
%33 = OpLoad %float %32
%35 = OpAccessChain %_ptr_Output_float %_entryPointOutput %int_0
OpStore %35 %33
%38 = OpAccessChain %_ptr_Function_v4float %flattenTemp %int_1
%39 = OpLoad %v4float %38
OpStore %_entryPointOutput_pos %39
OpReturn
OpFunctionEnd
%_main_ = OpFunction %VSOut None %9
%11 = OpLabel
%vout = OpVariable %_ptr_Function_VSOut Function
%18 = OpAccessChain %_ptr_Function_float %vout %int_0
OpStore %18 %float_40
%23 = OpAccessChain %_ptr_Function_v4float %vout %int_1
OpStore %23 %21
%24 = OpLoad %VSOut %vout
OpReturnValue %24
OpFunctionEnd

Просмотреть файл

@ -1784,7 +1784,12 @@ void CompilerGLSL::fixup_image_load_store_access()
void CompilerGLSL::emit_declared_builtin_block(StorageClass storage, ExecutionModel model)
{
uint64_t emitted_builtins = 0;
uint64_t global_builtins = 0;
const SPIRVariable *block_var = nullptr;
bool emitted_block = false;
bool builtin_array = false;
for (auto &id : ids)
{
if (id.get_type() != TypeVariable)
@ -1801,6 +1806,13 @@ void CompilerGLSL::emit_declared_builtin_block(StorageClass storage, ExecutionMo
if (m.builtin)
builtins |= 1ull << m.builtin_type;
}
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 (!builtins)
continue;
@ -1808,42 +1820,58 @@ void CompilerGLSL::emit_declared_builtin_block(StorageClass storage, ExecutionMo
if (emitted_block)
SPIRV_CROSS_THROW("Cannot use more than one builtin I/O block.");
if (storage == StorageClassOutput)
statement("out gl_PerVertex");
else
statement("in gl_PerVertex");
begin_scope();
if (builtins & (1ull << BuiltInPosition))
statement("vec4 gl_Position;");
if (builtins & (1ull << BuiltInPointSize))
statement("float gl_PointSize;");
if (builtins & (1ull << BuiltInClipDistance))
statement("float gl_ClipDistance[];"); // TODO: Do we need a fixed array size here?
if (builtins & (1ull << BuiltInCullDistance))
statement("float gl_CullDistance[];"); // TODO: Do we need a fixed array size here?
bool builtin_array = !type.array.empty();
bool tessellation = model == ExecutionModelTessellationEvaluation || model == ExecutionModelTessellationControl;
if (builtin_array)
{
// Make sure the array has a supported name in the code.
if (storage == StorageClassOutput)
set_name(var.self, "gl_out");
else if (storage == StorageClassInput)
set_name(var.self, "gl_in");
if (model == ExecutionModelTessellationControl && storage == StorageClassOutput)
end_scope_decl(join(to_name(var.self), "[", get_entry_point().output_vertices, "]"));
else
end_scope_decl(join(to_name(var.self), tessellation ? "[gl_MaxPatchVertices]" : "[]"));
}
else
end_scope_decl();
statement("");
emitted_builtins = builtins;
emitted_block = true;
builtin_array = !type.array.empty();
block_var = &var;
}
global_builtins &=
(1ull << BuiltInPosition) |
(1ull << BuiltInPointSize) |
(1ull << BuiltInClipDistance) |
(1ull << BuiltInCullDistance);
// Try to collect all other declared builtins.
if (!emitted_block)
emitted_builtins = global_builtins;
// Can't declare an empty interface block.
if (!emitted_builtins)
return;
if (storage == StorageClassOutput)
statement("out gl_PerVertex");
else
statement("in gl_PerVertex");
begin_scope();
if (emitted_builtins & (1ull << BuiltInPosition))
statement("vec4 gl_Position;");
if (emitted_builtins & (1ull << BuiltInPointSize))
statement("float gl_PointSize;");
if (emitted_builtins & (1ull << BuiltInClipDistance))
statement("float gl_ClipDistance[];"); // TODO: Do we need a fixed array size here?
if (emitted_builtins & (1ull << BuiltInCullDistance))
statement("float gl_CullDistance[];"); // TODO: Do we need a fixed array size here?
bool tessellation = model == ExecutionModelTessellationEvaluation || model == ExecutionModelTessellationControl;
if (builtin_array)
{
// Make sure the array has a supported name in the code.
if (storage == StorageClassOutput)
set_name(block_var->self, "gl_out");
else if (storage == StorageClassInput)
set_name(block_var->self, "gl_in");
if (model == ExecutionModelTessellationControl && storage == StorageClassOutput)
end_scope_decl(join(to_name(block_var->self), "[", get_entry_point().output_vertices, "]"));
else
end_scope_decl(join(to_name(block_var->self), tessellation ? "[gl_MaxPatchVertices]" : "[]"));
}
else
end_scope_decl();
statement("");
}
void CompilerGLSL::declare_undefined_values()