Merge pull request #1475 from KhronosGroup/fix-1474
GLSL: Support geometry streams.
This commit is contained in:
commit
5cc2e4f634
26
reference/opt/shaders/geom/transform-feedback-streams.geom
Normal file
26
reference/opt/shaders/geom/transform-feedback-streams.geom
Normal file
@ -0,0 +1,26 @@
|
||||
#version 450
|
||||
layout(points) in;
|
||||
layout(max_vertices = 2, points) out;
|
||||
|
||||
layout(xfb_buffer = 1, xfb_stride = 20, stream = 1) out gl_PerVertex
|
||||
{
|
||||
layout(xfb_offset = 4) vec4 gl_Position;
|
||||
float gl_PointSize;
|
||||
};
|
||||
|
||||
layout(location = 0, xfb_buffer = 2, xfb_stride = 32, xfb_offset = 16, stream = 1) out vec4 vFoo;
|
||||
layout(xfb_buffer = 3, xfb_stride = 16, stream = 2) out VertOut
|
||||
{
|
||||
layout(location = 1, xfb_offset = 0) vec4 vBar;
|
||||
} _23;
|
||||
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = vec4(1.0);
|
||||
vFoo = vec4(3.0);
|
||||
EmitStreamVertex(1);
|
||||
_23.vBar = vec4(5.0);
|
||||
EmitStreamVertex(2);
|
||||
}
|
||||
|
26
reference/shaders/geom/transform-feedback-streams.geom
Normal file
26
reference/shaders/geom/transform-feedback-streams.geom
Normal file
@ -0,0 +1,26 @@
|
||||
#version 450
|
||||
layout(points) in;
|
||||
layout(max_vertices = 2, points) out;
|
||||
|
||||
layout(xfb_buffer = 1, xfb_stride = 20, stream = 1) out gl_PerVertex
|
||||
{
|
||||
layout(xfb_offset = 4) vec4 gl_Position;
|
||||
float gl_PointSize;
|
||||
};
|
||||
|
||||
layout(location = 0, xfb_buffer = 2, xfb_stride = 32, xfb_offset = 16, stream = 1) out vec4 vFoo;
|
||||
layout(xfb_buffer = 3, xfb_stride = 16, stream = 2) out VertOut
|
||||
{
|
||||
layout(location = 1, xfb_offset = 0) vec4 vBar;
|
||||
} _23;
|
||||
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = vec4(1.0);
|
||||
vFoo = vec4(3.0);
|
||||
EmitStreamVertex(1);
|
||||
_23.vBar = vec4(5.0);
|
||||
EmitStreamVertex(2);
|
||||
}
|
||||
|
24
shaders/geom/transform-feedback-streams.geom
Normal file
24
shaders/geom/transform-feedback-streams.geom
Normal file
@ -0,0 +1,24 @@
|
||||
#version 450
|
||||
layout(max_vertices = 2, points) out;
|
||||
layout(points) in;
|
||||
layout(stream = 1, xfb_stride = 32, xfb_offset = 16, xfb_buffer = 2, location = 0) out vec4 vFoo;
|
||||
|
||||
layout(stream = 1, xfb_buffer = 1, xfb_stride = 20) out gl_PerVertex
|
||||
{
|
||||
layout(xfb_offset = 4) vec4 gl_Position;
|
||||
float gl_PointSize;
|
||||
};
|
||||
|
||||
layout(stream = 2, xfb_buffer = 3) out VertOut
|
||||
{
|
||||
layout(xfb_stride = 16, xfb_offset = 0, location = 1) vec4 vBar;
|
||||
};
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = vec4(1.0);
|
||||
vFoo = vec4(3.0);
|
||||
EmitStreamVertex(1);
|
||||
vBar = vec4(5.0);
|
||||
EmitStreamVertex(2);
|
||||
}
|
@ -1634,6 +1634,7 @@ struct Meta
|
||||
uint32_t offset = 0;
|
||||
uint32_t xfb_buffer = 0;
|
||||
uint32_t xfb_stride = 0;
|
||||
uint32_t stream = 0;
|
||||
uint32_t array_stride = 0;
|
||||
uint32_t matrix_stride = 0;
|
||||
uint32_t input_attachment = 0;
|
||||
|
@ -388,6 +388,10 @@ void ParsedIR::set_decoration(ID id, Decoration decoration, uint32_t argument)
|
||||
dec.xfb_stride = argument;
|
||||
break;
|
||||
|
||||
case DecorationStream:
|
||||
dec.stream = argument;
|
||||
break;
|
||||
|
||||
case DecorationArrayStride:
|
||||
dec.array_stride = argument;
|
||||
break;
|
||||
@ -467,6 +471,10 @@ void ParsedIR::set_member_decoration(TypeID id, uint32_t index, Decoration decor
|
||||
dec.xfb_stride = argument;
|
||||
break;
|
||||
|
||||
case DecorationStream:
|
||||
dec.stream = argument;
|
||||
break;
|
||||
|
||||
case DecorationSpecId:
|
||||
dec.spec_id = argument;
|
||||
break;
|
||||
@ -584,6 +592,8 @@ uint32_t ParsedIR::get_decoration(ID id, Decoration decoration) const
|
||||
return dec.xfb_buffer;
|
||||
case DecorationXfbStride:
|
||||
return dec.xfb_stride;
|
||||
case DecorationStream:
|
||||
return dec.stream;
|
||||
case DecorationBinding:
|
||||
return dec.binding;
|
||||
case DecorationDescriptorSet:
|
||||
@ -656,6 +666,10 @@ void ParsedIR::unset_decoration(ID id, Decoration decoration)
|
||||
dec.xfb_stride = 0;
|
||||
break;
|
||||
|
||||
case DecorationStream:
|
||||
dec.stream = 0;
|
||||
break;
|
||||
|
||||
case DecorationBinding:
|
||||
dec.binding = 0;
|
||||
break;
|
||||
@ -730,6 +744,8 @@ uint32_t ParsedIR::get_member_decoration(TypeID id, uint32_t index, Decoration d
|
||||
return dec.xfb_buffer;
|
||||
case DecorationXfbStride:
|
||||
return dec.xfb_stride;
|
||||
case DecorationStream:
|
||||
return dec.stream;
|
||||
case DecorationSpecId:
|
||||
return dec.spec_id;
|
||||
case DecorationIndex:
|
||||
@ -826,6 +842,10 @@ void ParsedIR::unset_member_decoration(TypeID id, uint32_t index, Decoration dec
|
||||
dec.xfb_stride = 0;
|
||||
break;
|
||||
|
||||
case DecorationStream:
|
||||
dec.stream = 0;
|
||||
break;
|
||||
|
||||
case DecorationSpecId:
|
||||
dec.spec_id = 0;
|
||||
break;
|
||||
|
112
spirv_glsl.cpp
112
spirv_glsl.cpp
@ -1590,7 +1590,8 @@ string CompilerGLSL::layout_for_variable(const SPIRVariable &var)
|
||||
uint32_t member_count = uint32_t(type.member_types.size());
|
||||
bool have_xfb_buffer_stride = false;
|
||||
bool have_any_xfb_offset = false;
|
||||
uint32_t xfb_stride = 0, xfb_buffer = 0;
|
||||
bool have_geom_stream = false;
|
||||
uint32_t xfb_stride = 0, xfb_buffer = 0, geom_stream = 0;
|
||||
|
||||
if (flags.get(DecorationXfbBuffer) && flags.get(DecorationXfbStride))
|
||||
{
|
||||
@ -1599,9 +1600,24 @@ string CompilerGLSL::layout_for_variable(const SPIRVariable &var)
|
||||
xfb_stride = get_decoration(var.self, DecorationXfbStride);
|
||||
}
|
||||
|
||||
if (flags.get(DecorationStream))
|
||||
{
|
||||
have_geom_stream = true;
|
||||
geom_stream = get_decoration(var.self, DecorationStream);
|
||||
}
|
||||
|
||||
// Verify that none of the members violate our assumption.
|
||||
for (uint32_t i = 0; i < member_count; i++)
|
||||
{
|
||||
if (has_member_decoration(type.self, i, DecorationStream))
|
||||
{
|
||||
uint32_t member_geom_stream = get_member_decoration(type.self, i, DecorationStream);
|
||||
if (have_geom_stream && member_geom_stream != geom_stream)
|
||||
SPIRV_CROSS_THROW("IO block member Stream mismatch.");
|
||||
have_geom_stream = true;
|
||||
geom_stream = member_geom_stream;
|
||||
}
|
||||
|
||||
// Only members with an Offset decoration participate in XFB.
|
||||
if (!has_member_decoration(type.self, i, DecorationOffset))
|
||||
continue;
|
||||
@ -1632,15 +1648,40 @@ string CompilerGLSL::layout_for_variable(const SPIRVariable &var)
|
||||
attr.push_back(join("xfb_stride = ", xfb_stride));
|
||||
uses_enhanced_layouts = true;
|
||||
}
|
||||
|
||||
if (have_geom_stream)
|
||||
{
|
||||
if (get_execution_model() != ExecutionModelGeometry)
|
||||
SPIRV_CROSS_THROW("Geometry streams can only be used in geometry shaders.");
|
||||
if (options.es)
|
||||
SPIRV_CROSS_THROW("Multiple geometry streams not supported in ESSL.");
|
||||
if (options.version < 400)
|
||||
require_extension_internal("GL_ARB_transform_feedback3");
|
||||
attr.push_back(join("stream = ", get_decoration(var.self, DecorationStream)));
|
||||
}
|
||||
}
|
||||
else if (var.storage == StorageClassOutput && flags.get(DecorationXfbBuffer) && flags.get(DecorationXfbStride) &&
|
||||
flags.get(DecorationOffset))
|
||||
else if (var.storage == StorageClassOutput)
|
||||
{
|
||||
// XFB for standalone variables, we can emit all decorations.
|
||||
attr.push_back(join("xfb_buffer = ", get_decoration(var.self, DecorationXfbBuffer)));
|
||||
attr.push_back(join("xfb_stride = ", get_decoration(var.self, DecorationXfbStride)));
|
||||
attr.push_back(join("xfb_offset = ", get_decoration(var.self, DecorationOffset)));
|
||||
uses_enhanced_layouts = true;
|
||||
if (flags.get(DecorationXfbBuffer) && flags.get(DecorationXfbStride) &&
|
||||
flags.get(DecorationOffset))
|
||||
{
|
||||
// XFB for standalone variables, we can emit all decorations.
|
||||
attr.push_back(join("xfb_buffer = ", get_decoration(var.self, DecorationXfbBuffer)));
|
||||
attr.push_back(join("xfb_stride = ", get_decoration(var.self, DecorationXfbStride)));
|
||||
attr.push_back(join("xfb_offset = ", get_decoration(var.self, DecorationOffset)));
|
||||
uses_enhanced_layouts = true;
|
||||
}
|
||||
|
||||
if (flags.get(DecorationStream))
|
||||
{
|
||||
if (get_execution_model() != ExecutionModelGeometry)
|
||||
SPIRV_CROSS_THROW("Geometry streams can only be used in geometry shaders.");
|
||||
if (options.es)
|
||||
SPIRV_CROSS_THROW("Multiple geometry streams not supported in ESSL.");
|
||||
if (options.version < 400)
|
||||
require_extension_internal("GL_ARB_transform_feedback3");
|
||||
attr.push_back(join("stream = ", get_decoration(var.self, DecorationStream)));
|
||||
}
|
||||
}
|
||||
|
||||
// Can only declare Component if we can declare location.
|
||||
@ -2700,8 +2741,9 @@ void CompilerGLSL::emit_declared_builtin_block(StorageClass storage, ExecutionMo
|
||||
uint32_t clip_distance_size = 0;
|
||||
|
||||
bool have_xfb_buffer_stride = false;
|
||||
bool have_geom_stream = false;
|
||||
bool have_any_xfb_offset = false;
|
||||
uint32_t xfb_stride = 0, xfb_buffer = 0;
|
||||
uint32_t xfb_stride = 0, xfb_buffer = 0, geom_stream = 0;
|
||||
std::unordered_map<uint32_t, uint32_t> builtin_xfb_offsets;
|
||||
|
||||
ir.for_each_typed_id<SPIRVariable>([&](uint32_t, SPIRVariable &var) {
|
||||
@ -2718,15 +2760,24 @@ void CompilerGLSL::emit_declared_builtin_block(StorageClass storage, ExecutionMo
|
||||
{
|
||||
builtins.set(m.builtin_type);
|
||||
if (m.builtin_type == BuiltInCullDistance)
|
||||
cull_distance_size = this->get<SPIRType>(type.member_types[index]).array.front();
|
||||
cull_distance_size = to_array_size_literal(this->get<SPIRType>(type.member_types[index]));
|
||||
else if (m.builtin_type == BuiltInClipDistance)
|
||||
clip_distance_size = this->get<SPIRType>(type.member_types[index]).array.front();
|
||||
clip_distance_size = to_array_size_literal(this->get<SPIRType>(type.member_types[index]));
|
||||
|
||||
if (is_block_builtin(m.builtin_type) && m.decoration_flags.get(DecorationOffset))
|
||||
{
|
||||
have_any_xfb_offset = true;
|
||||
builtin_xfb_offsets[m.builtin_type] = m.offset;
|
||||
}
|
||||
|
||||
if (is_block_builtin(m.builtin_type) && m.decoration_flags.get(DecorationStream))
|
||||
{
|
||||
uint32_t stream = m.stream;
|
||||
if (have_geom_stream && geom_stream != stream)
|
||||
SPIRV_CROSS_THROW("IO block member Stream mismatch.");
|
||||
have_geom_stream = true;
|
||||
geom_stream = stream;
|
||||
}
|
||||
}
|
||||
index++;
|
||||
}
|
||||
@ -2744,6 +2795,15 @@ void CompilerGLSL::emit_declared_builtin_block(StorageClass storage, ExecutionMo
|
||||
xfb_buffer = buffer_index;
|
||||
xfb_stride = stride;
|
||||
}
|
||||
|
||||
if (storage == StorageClassOutput && has_decoration(var.self, DecorationStream))
|
||||
{
|
||||
uint32_t stream = get_decoration(var.self, DecorationStream);
|
||||
if (have_geom_stream && geom_stream != stream)
|
||||
SPIRV_CROSS_THROW("IO block member Stream mismatch.");
|
||||
have_geom_stream = true;
|
||||
geom_stream = stream;
|
||||
}
|
||||
}
|
||||
else if (var.storage == storage && !block && is_builtin_variable(var))
|
||||
{
|
||||
@ -2753,9 +2813,9 @@ void CompilerGLSL::emit_declared_builtin_block(StorageClass storage, ExecutionMo
|
||||
{
|
||||
global_builtins.set(m.builtin_type);
|
||||
if (m.builtin_type == BuiltInCullDistance)
|
||||
cull_distance_size = type.array.front();
|
||||
cull_distance_size = to_array_size_literal(type);
|
||||
else if (m.builtin_type == BuiltInClipDistance)
|
||||
clip_distance_size = type.array.front();
|
||||
clip_distance_size = to_array_size_literal(type);
|
||||
|
||||
if (is_block_builtin(m.builtin_type) && m.decoration_flags.get(DecorationXfbStride) &&
|
||||
m.decoration_flags.get(DecorationXfbBuffer) && m.decoration_flags.get(DecorationOffset))
|
||||
@ -2772,6 +2832,15 @@ void CompilerGLSL::emit_declared_builtin_block(StorageClass storage, ExecutionMo
|
||||
xfb_buffer = buffer_index;
|
||||
xfb_stride = stride;
|
||||
}
|
||||
|
||||
if (is_block_builtin(m.builtin_type) && m.decoration_flags.get(DecorationStream))
|
||||
{
|
||||
uint32_t stream = get_decoration(var.self, DecorationStream);
|
||||
if (have_geom_stream && geom_stream != stream)
|
||||
SPIRV_CROSS_THROW("IO block member Stream mismatch.");
|
||||
have_geom_stream = true;
|
||||
geom_stream = stream;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -2801,9 +2870,9 @@ void CompilerGLSL::emit_declared_builtin_block(StorageClass storage, ExecutionMo
|
||||
|
||||
if (storage == StorageClassOutput)
|
||||
{
|
||||
SmallVector<string> attr;
|
||||
if (have_xfb_buffer_stride && have_any_xfb_offset)
|
||||
{
|
||||
statement("layout(xfb_buffer = ", xfb_buffer, ", xfb_stride = ", xfb_stride, ") out gl_PerVertex");
|
||||
if (!options.es)
|
||||
{
|
||||
if (options.version < 440 && options.version >= 140)
|
||||
@ -2815,7 +2884,22 @@ void CompilerGLSL::emit_declared_builtin_block(StorageClass storage, ExecutionMo
|
||||
}
|
||||
else if (options.es)
|
||||
SPIRV_CROSS_THROW("Need GL_ARB_enhanced_layouts for xfb_stride or xfb_buffer.");
|
||||
attr.push_back(join("xfb_buffer = ", xfb_buffer, ", xfb_stride = ", xfb_stride));
|
||||
}
|
||||
|
||||
if (have_geom_stream)
|
||||
{
|
||||
if (get_execution_model() != ExecutionModelGeometry)
|
||||
SPIRV_CROSS_THROW("Geometry streams can only be used in geometry shaders.");
|
||||
if (options.es)
|
||||
SPIRV_CROSS_THROW("Multiple geometry streams not supported in ESSL.");
|
||||
if (options.version < 400)
|
||||
require_extension_internal("GL_ARB_transform_feedback3");
|
||||
attr.push_back(join("stream = ", geom_stream));
|
||||
}
|
||||
|
||||
if (!attr.empty())
|
||||
statement("layout(", merge(attr), ") out gl_PerVertex");
|
||||
else
|
||||
statement("out gl_PerVertex");
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user