summaryrefslogtreecommitdiffstats
path: root/src/compiler/glsl
diff options
context:
space:
mode:
Diffstat (limited to 'src/compiler/glsl')
-rw-r--r--src/compiler/glsl/ast.h23
-rw-r--r--src/compiler/glsl/ast_type.cpp43
-rw-r--r--src/compiler/glsl/glsl_parser.yy25
-rw-r--r--src/compiler/glsl/glsl_parser_extras.cpp7
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) {