[Mesa-dev] [PATCH 01/18] glsl: Add parsing support for multi-stream output in geometry shaders.

Iago Toral Quiroga itoral at igalia.com
Wed Jun 11 00:49:24 PDT 2014


From: Samuel Iglesias Gonsalvez <siglesias at igalia.com>

This implements parsing requirements for multi-stream support in
geometry shaders as defined in ARB_gpu_shader5.

Signed-off-by: Samuel Iglesias Gonsalvez <siglesias at igalia.com>
---
 src/glsl/ast.h          |  5 +++++
 src/glsl/ast_to_hir.cpp |  6 ++++++
 src/glsl/ast_type.cpp   | 19 ++++++++++++++++++-
 src/glsl/glsl_parser.yy | 45 +++++++++++++++++++++++++++++++++++++++++++++
 src/glsl/ir.h           |  5 +++++
 5 files changed, 79 insertions(+), 1 deletion(-)

diff --git a/src/glsl/ast.h b/src/glsl/ast.h
index 56e7bd8..823b1d2 100644
--- a/src/glsl/ast.h
+++ b/src/glsl/ast.h
@@ -509,6 +509,8 @@ struct ast_type_qualifier {
          /** \name Layout qualifiers for GL_ARB_gpu_shader5 */
          /** \{ */
          unsigned invocations:1;
+         unsigned streamId:1; /* Has streamId value assigned  */
+         unsigned explicit_streamId:1; /* streamId value assigned explicitely by shader code */
          /** \} */
       }
       /** \brief Set of flags, accessed by name. */
@@ -542,6 +544,9 @@ struct ast_type_qualifier {
    /** Maximum output vertices in GLSL 1.50 geometry shaders. */
    int max_vertices;
 
+   /** Stream ID in GLSL 1.50 geometry shaders. */
+   unsigned streamId;
+
    /** Input or output primitive type in GLSL 1.50 geometry shaders */
    GLenum prim_type;
 
diff --git a/src/glsl/ast_to_hir.cpp b/src/glsl/ast_to_hir.cpp
index 140bb74..ab0f50f 100644
--- a/src/glsl/ast_to_hir.cpp
+++ b/src/glsl/ast_to_hir.cpp
@@ -2426,6 +2426,11 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual,
    if (qual->flags.q.sample)
       var->data.sample = 1;
 
+   if (state->stage == MESA_SHADER_GEOMETRY &&
+       qual->flags.q.out && qual->flags.q.streamId) {
+      var->data.streamId = qual->streamId;
+   }
+
    if (qual->flags.q.attribute && state->stage != MESA_SHADER_VERTEX) {
       var->type = glsl_type::error_type;
       _mesa_glsl_error(loc, state,
@@ -5455,6 +5460,7 @@ ast_interface_block::hir(exec_list *instructions,
          var->data.centroid = fields[i].centroid;
          var->data.sample = fields[i].sample;
          var->init_interface_type(block_type);
+         var->data.streamId = this->layout.streamId;
 
          if (redeclaring_per_vertex) {
             ir_variable *earlier =
diff --git a/src/glsl/ast_type.cpp b/src/glsl/ast_type.cpp
index 0ee2c49..749f161 100644
--- a/src/glsl/ast_type.cpp
+++ b/src/glsl/ast_type.cpp
@@ -125,9 +125,13 @@ ast_type_qualifier::merge_qualifier(YYLTYPE *loc,
    /* Uniform block layout qualifiers get to overwrite each
     * other (rightmost having priority), while all other
     * qualifiers currently don't allow duplicates.
+    *
+    * Geometry shaders can have several layout qualifiers
+    * assigning different stream ID values.
     */
 
-   if ((this->flags.i & q.flags.i & ~(ubo_mat_mask.flags.i |
+   if ((state->stage != MESA_SHADER_GEOMETRY) &&
+       (this->flags.i & q.flags.i & ~(ubo_mat_mask.flags.i |
 				      ubo_layout_mask.flags.i |
                                       ubo_binding_mask.flags.i)) != 0) {
       _mesa_glsl_error(loc, state,
@@ -154,6 +158,19 @@ ast_type_qualifier::merge_qualifier(YYLTYPE *loc,
       this->max_vertices = q.max_vertices;
    }
 
+   if (state->stage == MESA_SHADER_GEOMETRY &&
+       state->ARB_gpu_shader5_enable &&
+       !this->flags.q.explicit_streamId) {
+      if (q.flags.q.streamId) {
+         this->flags.q.streamId = 1;
+         this->streamId = q.streamId;
+      } else if(this->flags.q.streamId == 0) {
+         /* Assign default global streamId value */
+         this->flags.q.streamId = 1;
+         this->streamId = state->out_qualifier->streamId;
+      }
+   }
+
    if ((q.flags.i & ubo_mat_mask.flags.i) != 0)
       this->flags.i &= ~ubo_mat_mask.flags.i;
    if ((q.flags.i & ubo_layout_mask.flags.i) != 0)
diff --git a/src/glsl/glsl_parser.yy b/src/glsl/glsl_parser.yy
index eddab05..caebfe7 100644
--- a/src/glsl/glsl_parser.yy
+++ b/src/glsl/glsl_parser.yy
@@ -1395,6 +1395,21 @@ layout_qualifier_id:
          }
       }
 
+      if (state->ARB_gpu_shader5_enable && state->stage == MESA_SHADER_GEOMETRY) {
+         if (match_layout_qualifier("stream", $1, state) == 0) {
+            $$.flags.q.streamId = 1;
+
+            if (($3 < 0) || ($3 >= MAX_VERTEX_STREAMS)) {
+               _mesa_glsl_error(& @3, state,
+                                "invalid stream %d specified", $3);
+               YYERROR;
+            } else {
+               $$.flags.q.explicit_streamId = 1;
+               $$.streamId = $3;
+            }
+         }
+      }
+
       static const char * const local_size_qualifiers[3] = {
          "local_size_x",
          "local_size_y",
@@ -1713,6 +1728,16 @@ storage_qualifier:
    {
       memset(& $$, 0, sizeof($$));
       $$.flags.q.out = 1;
+
+      if (state->ARB_gpu_shader5_enable && state->stage == MESA_SHADER_GEOMETRY) {
+         /*
+          * According to the GL_ARB_gpu_shader5 spec, assign a default value
+          * to the streamId
+          */
+          $$.flags.q.streamId = 1;
+          $$.flags.q.explicit_streamId = 0;
+          $$.streamId = state->out_qualifier->streamId;
+      }
    }
    | UNIFORM
    {
@@ -2381,6 +2406,18 @@ interface_block:
       if (!block->layout.merge_qualifier(& @1, state, $1)) {
          YYERROR;
       }
+
+      foreach_list_typed (ast_declarator_list, member, link, &block->declarations) {
+         ast_type_qualifier& qualifier = member->type->qualifier;
+         if (qualifier.flags.q.streamId && qualifier.streamId != block->layout.streamId) {
+               _mesa_glsl_error(& @1, state,
+                             "stream layout qualifier on "
+                             "interface block member does not match "
+                             "the interface block (%d and %d)",
+                             qualifier.streamId, block->layout.streamId);
+               YYERROR;
+         }
+      }
       $$ = block;
    }
    ;
@@ -2454,6 +2491,12 @@ basic_interface_block:
 
       block->layout.flags.i |= block_interface_qualifier;
 
+      if (state->ARB_gpu_shader5_enable && state->stage == MESA_SHADER_GEOMETRY) {
+         /* Assign global layout's streamId value. */
+         block->layout.flags.q.streamId = 1;
+         block->layout.streamId = state->out_qualifier->streamId;
+      }
+
       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) {
@@ -2596,6 +2639,8 @@ layout_defaults:
          }
          if (!state->out_qualifier->merge_qualifier(& @1, state, $1))
             YYERROR;
+         /* Allow future assigments of global out's stream id value */
+         state->out_qualifier->flags.q.explicit_streamId = 0;
       }
       $$ = NULL;
    }
diff --git a/src/glsl/ir.h b/src/glsl/ir.h
index b4e52d3..8cc58af 100644
--- a/src/glsl/ir.h
+++ b/src/glsl/ir.h
@@ -705,6 +705,11 @@ public:
        */
       int location;
 
+      /*
+       * Vertex stream output identifier.
+       */
+      unsigned streamId;
+
       /**
        * output index for dual source blending.
        */
-- 
1.9.1



More information about the mesa-dev mailing list