From c9afd94af6fa129370eb001077724a77093ecd5a Mon Sep 17 00:00:00 2001 From: Timothy Arceri Date: Fri, 22 Jan 2016 12:45:10 +1100 Subject: [PATCH] glsl: parse new transform feedback layout qualifiers We reuse the existing offset field for holding the xfb_offset expression but create a new flag as to avoid hitting the rules for the offset qualifier for UBOs. xfb_buffer qualifiers require extra processing when merging as they can be applied to global out defaults. We just apply the same rules as we do for the stream qualifier as the spec says: "The *xfb_buffer* qualifier follows the same conventions, behavior, defaults, and inheritance rules as the qualifier stream, and the examples for stream apply here as well." For xfb_stride we push everything into a global out field for later processing as xfb_stride applies to the entire buffer. We still need to have a separate field to store per variable strides because they can still effect implicit offsets e.g. when applied to block members with implicit offsets. Reviewed-by: Dave Airlie --- src/compiler/glsl/ast.h | 23 +++++++++++-- src/compiler/glsl/ast_type.cpp | 43 +++++++++++++++++++++++- src/compiler/glsl/glsl_parser.yy | 25 ++++++++++++++ src/compiler/glsl/glsl_parser_extras.cpp | 7 ++++ 4 files changed, 95 insertions(+), 3 deletions(-) diff --git a/src/compiler/glsl/ast.h b/src/compiler/glsl/ast.h index b144e24de88..7436edce88a 100644 --- a/src/compiler/glsl/ast.h +++ b/src/compiler/glsl/ast.h @@ -562,6 +562,15 @@ struct ast_type_qualifier { unsigned explicit_stream:1; /**< stream value assigned explicitly by shader code */ /** \} */ + /** \name Layout qualifiers for GL_ARB_enhanced_layouts */ + /** \{ */ + unsigned explicit_xfb_offset:1; /**< xfb_offset value assigned explicitly by shader code */ + unsigned xfb_buffer:1; /**< Has xfb_buffer value assigned */ + unsigned explicit_xfb_buffer:1; /**< xfb_buffer value assigned explicitly by shader code */ + unsigned xfb_stride:1; /**< Is xfb_stride value yet to be merged with global values */ + unsigned explicit_xfb_stride:1; /**< xfb_stride value assigned explicitly by shader code */ + /** \} */ + /** \name Layout qualifiers for GL_ARB_tessellation_shader */ /** \{ */ /* tess eval input layout */ @@ -618,6 +627,15 @@ struct ast_type_qualifier { /** Stream in GLSL 1.50 geometry shaders. */ ast_expression *stream; + /** xfb_buffer specified via the GL_ARB_enhanced_layouts keyword. */ + ast_expression *xfb_buffer; + + /** xfb_stride specified via the GL_ARB_enhanced_layouts keyword. */ + ast_expression *xfb_stride; + + /** global xfb_stride values for each buffer */ + ast_layout_expression *out_xfb_stride[MAX_FEEDBACK_BUFFERS]; + /** * Input or output primitive type in GLSL 1.50 geometry shaders * and tessellation shaders. @@ -633,8 +651,9 @@ struct ast_type_qualifier { ast_expression *binding; /** - * Offset specified via GL_ARB_shader_atomic_counter's "offset" - * keyword. + * Offset specified via GL_ARB_shader_atomic_counter's or + * GL_ARB_enhanced_layouts "offset" keyword, or by GL_ARB_enhanced_layouts + * "xfb_offset" keyword. * * \note * This field is only valid if \c explicit_offset is set. diff --git a/src/compiler/glsl/ast_type.cpp b/src/compiler/glsl/ast_type.cpp index ede6cc4500f..ab86577cc3e 100644 --- a/src/compiler/glsl/ast_type.cpp +++ b/src/compiler/glsl/ast_type.cpp @@ -229,6 +229,43 @@ ast_type_qualifier::merge_qualifier(YYLTYPE *loc, } } + if (state->has_enhanced_layouts()) { + if (!this->flags.q.explicit_xfb_buffer) { + if (q.flags.q.xfb_buffer) { + this->flags.q.xfb_buffer = 1; + this->xfb_buffer = q.xfb_buffer; + } else if (!this->flags.q.xfb_buffer && this->flags.q.out) { + /* Assign global xfb_buffer value */ + this->flags.q.xfb_buffer = 1; + this->xfb_buffer = state->out_qualifier->xfb_buffer; + } + } + + if (q.flags.q.explicit_xfb_stride) + this->xfb_stride = q.xfb_stride; + + /* Merge all we xfb_stride qualifiers into the global out */ + if (q.flags.q.explicit_xfb_stride || this->flags.q.xfb_stride) { + + /* Set xfb_stride flag to 0 to avoid adding duplicates every time + * there is a merge. + */ + this->flags.q.xfb_stride = 0; + + unsigned buff_idx; + if (process_qualifier_constant(state, loc, "xfb_buffer", + this->xfb_buffer, &buff_idx)) { + if (state->out_qualifier->out_xfb_stride[buff_idx]) { + state->out_qualifier->out_xfb_stride[buff_idx]->merge_qualifier( + new(state) ast_layout_expression(*loc, this->xfb_stride)); + } else { + state->out_qualifier->out_xfb_stride[buff_idx] = + new(state) ast_layout_expression(*loc, this->xfb_stride); + } + } + } + } + if (q.flags.q.vertices) { if (this->vertices) { this->vertices->merge_qualifier(q.vertices); @@ -300,7 +337,7 @@ ast_type_qualifier::merge_qualifier(YYLTYPE *loc, if (q.flags.q.explicit_binding) this->binding = q.binding; - if (q.flags.q.explicit_offset) + if (q.flags.q.explicit_offset || q.flags.q.explicit_xfb_offset) this->offset = q.offset; if (q.precision != ast_precision_none) @@ -349,6 +386,10 @@ ast_type_qualifier::merge_out_qualifier(YYLTYPE *loc, "tessellation control or geometry shaders"); } + /* Allow future assigments of global out's */ + this->flags.q.explicit_xfb_buffer = 0; + this->flags.q.explicit_xfb_stride = 0; + return r; } diff --git a/src/compiler/glsl/glsl_parser.yy b/src/compiler/glsl/glsl_parser.yy index 5ed051a6705..1cecc09b8c8 100644 --- a/src/compiler/glsl/glsl_parser.yy +++ b/src/compiler/glsl/glsl_parser.yy @@ -1541,6 +1541,25 @@ layout_qualifier_id: } } + if (state->has_enhanced_layouts()) { + if (match_layout_qualifier("xfb_buffer", $1, state) == 0) { + $$.flags.q.xfb_buffer = 1; + $$.flags.q.explicit_xfb_buffer = 1; + $$.xfb_buffer = $3; + } + + if (match_layout_qualifier("xfb_offset", $1, state) == 0) { + $$.flags.q.explicit_xfb_offset = 1; + $$.offset = $3; + } + + if (match_layout_qualifier("xfb_stride", $1, state) == 0) { + $$.flags.q.xfb_stride = 1; + $$.flags.q.explicit_xfb_stride = 1; + $$.xfb_stride = $3; + } + } + static const char * const local_size_qualifiers[3] = { "local_size_x", "local_size_y", @@ -1915,6 +1934,12 @@ storage_qualifier: $$.flags.q.explicit_stream = 0; $$.stream = state->out_qualifier->stream; } + + if (state->has_enhanced_layouts()) { + $$.flags.q.xfb_buffer = 1; + $$.flags.q.explicit_xfb_buffer = 0; + $$.xfb_buffer = state->out_qualifier->xfb_buffer; + } } | UNIFORM { diff --git a/src/compiler/glsl/glsl_parser_extras.cpp b/src/compiler/glsl/glsl_parser_extras.cpp index a8fa75395e0..76ae0f88167 100644 --- a/src/compiler/glsl/glsl_parser_extras.cpp +++ b/src/compiler/glsl/glsl_parser_extras.cpp @@ -939,6 +939,13 @@ _mesa_ast_process_interface_block(YYLTYPE *locp, block->layout.stream = state->out_qualifier->stream; } + if (state->has_enhanced_layouts() && block->layout.flags.q.out) { + /* Assign global layout's xfb_buffer value. */ + block->layout.flags.q.xfb_buffer = 1; + block->layout.flags.q.explicit_xfb_buffer = 0; + block->layout.xfb_buffer = state->out_qualifier->xfb_buffer; + } + foreach_list_typed (ast_declarator_list, member, link, &block->declarations) { ast_type_qualifier& qualifier = member->type->qualifier; if ((qualifier.flags.i & interface_type_mask) == 0) { -- 2.30.2