summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJordan Justen <jordan.l.justen@intel.com>2014-02-02 17:49:15 -0800
committerJordan Justen <jordan.l.justen@intel.com>2014-02-20 10:33:08 -0800
commit0c558f9ee6cfc412037dc56ad4c3686e0f116852 (patch)
treebca51f236da9cfebecd2dd01494ee366f7241d78
parent5bc0b2f4321fe623e37535aa1ff1848aa5a2dec1 (diff)
downloadexternal_mesa3d-0c558f9ee6cfc412037dc56ad4c3686e0f116852.zip
external_mesa3d-0c558f9ee6cfc412037dc56ad4c3686e0f116852.tar.gz
external_mesa3d-0c558f9ee6cfc412037dc56ad4c3686e0f116852.tar.bz2
glsl: convert GS input primitive to use ast_type_qualifier
We introduce a new merge_in_qualifier ast_type_qualifier which allows specialized handling of merging input layout qualifiers. By merging layout qualifiers into state->in_qualifier, we allow multiple input qualifiers. For example, the primitive type can be specified specified separately from the invocations count (ARB_gpu_shader5). state->gs_input_prim_type is moved into state->in_qualifier->prim_type state->gs_input_prim_type_specified is still processed separately so we can determine when the input primitive is specified. This is important since certain scenerios are not supported until after the primitive type has been specified in the shader code. v4: * Merge with compute shader input layout qualifiers Signed-off-by: Jordan Justen <jordan.l.justen@intel.com> Reviewed-by: Anuj Phogat <anuj.phogat@gmail.com>
-rw-r--r--src/glsl/ast.h6
-rw-r--r--src/glsl/ast_to_hir.cpp5
-rw-r--r--src/glsl/ast_type.cpp81
-rw-r--r--src/glsl/glsl_parser.yy57
-rw-r--r--src/glsl/glsl_parser_extras.cpp6
-rw-r--r--src/glsl/glsl_parser_extras.h7
6 files changed, 96 insertions, 66 deletions
diff --git a/src/glsl/ast.h b/src/glsl/ast.h
index 9140ca1..c4f28b0 100644
--- a/src/glsl/ast.h
+++ b/src/glsl/ast.h
@@ -587,6 +587,12 @@ struct ast_type_qualifier {
bool merge_qualifier(YYLTYPE *loc,
_mesa_glsl_parse_state *state,
ast_type_qualifier q);
+
+ bool merge_in_qualifier(YYLTYPE *loc,
+ _mesa_glsl_parse_state *state,
+ ast_type_qualifier q,
+ ast_node* &node);
+
};
class ast_declarator_list;
diff --git a/src/glsl/ast_to_hir.cpp b/src/glsl/ast_to_hir.cpp
index e731d83..f754652 100644
--- a/src/glsl/ast_to_hir.cpp
+++ b/src/glsl/ast_to_hir.cpp
@@ -2842,7 +2842,7 @@ handle_geometry_shader_input_decl(struct _mesa_glsl_parse_state *state,
{
unsigned num_vertices = 0;
if (state->gs_input_prim_type_specified) {
- num_vertices = vertices_per_prim(state->gs_input_prim_type);
+ num_vertices = vertices_per_prim(state->in_qualifier->prim_type);
}
/* Geometry shader input variables must be arrays. Caller should have
@@ -5332,7 +5332,7 @@ ast_gs_input_layout::hir(exec_list *instructions,
* was consistent with this one.
*/
if (state->gs_input_prim_type_specified &&
- state->gs_input_prim_type != this->prim_type) {
+ state->in_qualifier->prim_type != this->prim_type) {
_mesa_glsl_error(&loc, state,
"geometry shader input layout does not match"
" previous declaration");
@@ -5353,7 +5353,6 @@ ast_gs_input_layout::hir(exec_list *instructions,
}
state->gs_input_prim_type_specified = true;
- state->gs_input_prim_type = this->prim_type;
/* If any shader inputs occurred before this declaration and did not
* specify an array size, their size is determined now.
diff --git a/src/glsl/ast_type.cpp b/src/glsl/ast_type.cpp
index 200566c..2f36cf4 100644
--- a/src/glsl/ast_type.cpp
+++ b/src/glsl/ast_type.cpp
@@ -198,3 +198,84 @@ ast_type_qualifier::merge_qualifier(YYLTYPE *loc,
return true;
}
+bool
+ast_type_qualifier::merge_in_qualifier(YYLTYPE *loc,
+ _mesa_glsl_parse_state *state,
+ ast_type_qualifier q,
+ ast_node* &node)
+{
+ void *mem_ctx = state;
+ bool create_gs_ast = false;
+ bool create_cs_ast = false;
+
+ switch (state->stage) {
+ case MESA_SHADER_GEOMETRY:
+ if (q.flags.q.prim_type) {
+ /* Make sure this is a valid input primitive type. */
+ switch (q.prim_type) {
+ case GL_POINTS:
+ case GL_LINES:
+ case GL_LINES_ADJACENCY:
+ case GL_TRIANGLES:
+ case GL_TRIANGLES_ADJACENCY:
+ break;
+ default:
+ _mesa_glsl_error(loc, state,
+ "invalid geometry shader input primitive type");
+ break;
+ }
+ }
+
+ create_gs_ast |=
+ q.flags.q.prim_type &&
+ !state->in_qualifier->flags.q.prim_type;
+ break;
+ case MESA_SHADER_FRAGMENT:
+ if (q.flags.q.early_fragment_tests) {
+ state->early_fragment_tests = true;
+ } else {
+ _mesa_glsl_error(loc, state, "invalid input layout qualifier");
+ }
+ break;
+ case MESA_SHADER_COMPUTE:
+ create_cs_ast |=
+ q.flags.q.local_size != 0 &&
+ state->in_qualifier->flags.q.local_size == 0;
+ break;
+ default:
+ _mesa_glsl_error(loc, state,
+ "input layout qualifiers only valid in "
+ "geometry, fragment and compute shaders");
+ break;
+ }
+
+ /* Input layout qualifiers can be specified multiple
+ * times in separate declarations, as long as they match.
+ */
+ if (this->flags.q.prim_type) {
+ if (q.flags.q.prim_type &&
+ this->prim_type != q.prim_type) {
+ _mesa_glsl_error(loc, state,
+ "conflicting input primitive types specified");
+ }
+ } else if (q.flags.q.prim_type) {
+ state->in_qualifier->flags.q.prim_type = 1;
+ state->in_qualifier->prim_type = q.prim_type;
+ }
+
+ if (create_gs_ast) {
+ node = new(mem_ctx) ast_gs_input_layout(*loc, q.prim_type);
+ } else if (create_cs_ast) {
+ /* Infer a local_size of 1 for every unspecified dimension */
+ unsigned local_size[3];
+ for (int i = 0; i < 3; i++) {
+ if (q.flags.q.local_size & (1 << i))
+ local_size[i] = q.local_size[i];
+ else
+ local_size[i] = 1;
+ }
+ node = new(mem_ctx) ast_cs_input_layout(*loc, local_size);
+ }
+
+ return true;
+}
diff --git a/src/glsl/glsl_parser.yy b/src/glsl/glsl_parser.yy
index 369da50..c3fa455 100644
--- a/src/glsl/glsl_parser.yy
+++ b/src/glsl/glsl_parser.yy
@@ -2487,62 +2487,9 @@ layout_defaults:
| layout_qualifier IN_TOK ';'
{
- void *ctx = state;
$$ = NULL;
- switch (state->stage) {
- case MESA_SHADER_GEOMETRY: {
- if (!$1.flags.q.prim_type) {
- _mesa_glsl_error(& @1, state,
- "input layout qualifiers must specify a primitive"
- " type");
- } else {
- /* Make sure this is a valid input primitive type. */
- switch ($1.prim_type) {
- case GL_POINTS:
- case GL_LINES:
- case GL_LINES_ADJACENCY:
- case GL_TRIANGLES:
- case GL_TRIANGLES_ADJACENCY:
- $$ = new(ctx) ast_gs_input_layout(@1, $1.prim_type);
- break;
- default:
- _mesa_glsl_error(&@1, state,
- "invalid geometry shader input primitive type");
- break;
- }
- }
- }
- break;
- case MESA_SHADER_FRAGMENT:
- if ($1.flags.q.early_fragment_tests) {
- state->early_fragment_tests = true;
- } else {
- _mesa_glsl_error(& @1, state, "invalid input layout qualifier");
- }
- break;
- case MESA_SHADER_COMPUTE: {
- if ($1.flags.q.local_size == 0) {
- _mesa_glsl_error(& @1, state,
- "input layout qualifiers must specify a local "
- "size");
- } else {
- /* Infer a local_size of 1 for every unspecified dimension */
- unsigned local_size[3];
- for (int i = 0; i < 3; i++) {
- if ($1.flags.q.local_size & (1 << i))
- local_size[i] = $1.local_size[i];
- else
- local_size[i] = 1;
- }
- $$ = new(ctx) ast_cs_input_layout(@1, local_size);
- }
- }
- break;
- default:
- _mesa_glsl_error(& @1, state,
- "input layout qualifiers only valid in "
- "geometry, fragment and compute shaders");
- break;
+ if (!state->in_qualifier->merge_in_qualifier(& @1, state, $1, $$)) {
+ YYERROR;
}
}
diff --git a/src/glsl/glsl_parser_extras.cpp b/src/glsl/glsl_parser_extras.cpp
index 901124d..f102b11 100644
--- a/src/glsl/glsl_parser_extras.cpp
+++ b/src/glsl/glsl_parser_extras.cpp
@@ -202,8 +202,8 @@ _mesa_glsl_parse_state::_mesa_glsl_parse_state(struct gl_context *_ctx,
this->default_uniform_qualifier->flags.q.column_major = 1;
this->gs_input_prim_type_specified = false;
- this->gs_input_prim_type = GL_POINTS;
this->gs_input_size = 0;
+ this->in_qualifier = new(this) ast_type_qualifier();
this->out_qualifier = new(this) ast_type_qualifier();
this->early_fragment_tests = false;
memset(this->atomic_counter_offsets, 0,
@@ -1348,7 +1348,7 @@ set_shader_inout_layout(struct gl_shader *shader,
{
if (shader->Stage != MESA_SHADER_GEOMETRY) {
/* Should have been prevented by the parser. */
- assert(!state->gs_input_prim_type_specified);
+ assert(!state->in_qualifier->flags.i);
assert(!state->out_qualifier->flags.i);
}
@@ -1364,7 +1364,7 @@ set_shader_inout_layout(struct gl_shader *shader,
shader->Geom.VerticesOut = state->out_qualifier->max_vertices;
if (state->gs_input_prim_type_specified) {
- shader->Geom.InputType = state->gs_input_prim_type;
+ shader->Geom.InputType = state->in_qualifier->prim_type;
} else {
shader->Geom.InputType = PRIM_UNKNOWN;
}
diff --git a/src/glsl/glsl_parser_extras.h b/src/glsl/glsl_parser_extras.h
index ad4ef01..d98474e 100644
--- a/src/glsl/glsl_parser_extras.h
+++ b/src/glsl/glsl_parser_extras.h
@@ -190,11 +190,8 @@ struct _mesa_glsl_parse_state {
*/
bool gs_input_prim_type_specified;
- /**
- * If gs_input_prim_type_specified is true, the primitive type that was
- * specified. Otherwise ignored.
- */
- GLenum gs_input_prim_type;
+ /** Input layout qualifiers from GLSL 1.50. (geometry shader controls)*/
+ struct ast_type_qualifier *in_qualifier;
/**
* True if a compute shader input local size was specified using a layout