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 */
/** 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.
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.
}
}
+ 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);
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)
"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;
}
}
}
+ 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",
$$.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
{
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) {