glsl: Fix locations of variables in patch qualified interface blocks.
[mesa.git] / src / compiler / glsl / glsl_parser.yy
index 3885688d9b8e5a07ddd73cde432c363710611c50..9e1fd9e3e67f268524b1399c0bcaacf812171b1d 100644 (file)
@@ -219,8 +219,6 @@ static bool match_layout_qualifier(const char *s1, const char *s2,
 %type <type_qualifier> subroutine_qualifier
 %type <subroutine_list> subroutine_type_list
 %type <type_qualifier> interface_qualifier
-%type <type_qualifier> uniform_interface_qualifier
-%type <type_qualifier> buffer_interface_qualifier
 %type <type_specifier> type_specifier
 %type <type_specifier> type_specifier_nonarray
 %type <array_specifier> array_specifier
@@ -1276,7 +1274,8 @@ layout_qualifier_id:
             }
          }
 
-         if ($$.flags.i && !state->has_geometry_shader()) {
+         if ($$.flags.i && !state->has_geometry_shader() &&
+             !state->has_tessellation_shader()) {
             _mesa_glsl_error(& @1, state, "#version 150 layout "
                              "qualifier `%s' used", $1);
          }
@@ -1374,7 +1373,7 @@ layout_qualifier_id:
 
       /* Layout qualifiers for tessellation evaluation shaders. */
       if (!$$.flags.i) {
-         struct {
+         static const struct {
             const char *s;
             GLenum e;
          } map[] = {
@@ -1390,16 +1389,14 @@ layout_qualifier_id:
             }
          }
 
-         if ($$.flags.i &&
-             !state->ARB_tessellation_shader_enable &&
-             !state->is_version(400, 0)) {
+         if ($$.flags.i && !state->has_tessellation_shader()) {
             _mesa_glsl_error(& @1, state,
                              "primitive mode qualifier `%s' requires "
                              "GLSL 4.00 or ARB_tessellation_shader", $1);
          }
       }
       if (!$$.flags.i) {
-         struct {
+         static const struct {
             const char *s;
             GLenum e;
          } map[] = {
@@ -1415,9 +1412,7 @@ layout_qualifier_id:
             }
          }
 
-         if ($$.flags.i &&
-             !state->ARB_tessellation_shader_enable &&
-             !state->is_version(400, 0)) {
+         if ($$.flags.i && !state->has_tessellation_shader()) {
             _mesa_glsl_error(& @1, state,
                              "vertex spacing qualifier `%s' requires "
                              "GLSL 4.00 or ARB_tessellation_shader", $1);
@@ -1432,9 +1427,7 @@ layout_qualifier_id:
             $$.ordering = GL_CCW;
          }
 
-         if ($$.flags.i &&
-             !state->ARB_tessellation_shader_enable &&
-             !state->is_version(400, 0)) {
+         if ($$.flags.i && !state->has_tessellation_shader()) {
             _mesa_glsl_error(& @1, state,
                              "ordering qualifier `%s' requires "
                              "GLSL 4.00 or ARB_tessellation_shader", $1);
@@ -1446,15 +1439,58 @@ layout_qualifier_id:
             $$.point_mode = true;
          }
 
-         if ($$.flags.i &&
-             !state->ARB_tessellation_shader_enable &&
-             !state->is_version(400, 0)) {
+         if ($$.flags.i && !state->has_tessellation_shader()) {
             _mesa_glsl_error(& @1, state,
                              "qualifier `point_mode' requires "
                              "GLSL 4.00 or ARB_tessellation_shader");
          }
       }
 
+      if (!$$.flags.i) {
+         static const struct {
+            const char *s;
+            uint32_t mask;
+         } map[] = {
+                 { "blend_support_multiply",       BLEND_MULTIPLY },
+                 { "blend_support_screen",         BLEND_SCREEN },
+                 { "blend_support_overlay",        BLEND_OVERLAY },
+                 { "blend_support_darken",         BLEND_DARKEN },
+                 { "blend_support_lighten",        BLEND_LIGHTEN },
+                 { "blend_support_colordodge",     BLEND_COLORDODGE },
+                 { "blend_support_colorburn",      BLEND_COLORBURN },
+                 { "blend_support_hardlight",      BLEND_HARDLIGHT },
+                 { "blend_support_softlight",      BLEND_SOFTLIGHT },
+                 { "blend_support_difference",     BLEND_DIFFERENCE },
+                 { "blend_support_exclusion",      BLEND_EXCLUSION },
+                 { "blend_support_hsl_hue",        BLEND_HSL_HUE },
+                 { "blend_support_hsl_saturation", BLEND_HSL_SATURATION },
+                 { "blend_support_hsl_color",      BLEND_HSL_COLOR },
+                 { "blend_support_hsl_luminosity", BLEND_HSL_LUMINOSITY },
+                 { "blend_support_all_equations",  BLEND_ALL },
+         };
+         for (unsigned i = 0; i < ARRAY_SIZE(map); i++) {
+            if (match_layout_qualifier($1, map[i].s, state) == 0) {
+               $$.flags.q.blend_support = 1;
+               state->fs_blend_support |= map[i].mask;
+               break;
+            }
+         }
+
+         if ($$.flags.i &&
+             !state->KHR_blend_equation_advanced_enable &&
+             !state->is_version(0, 320)) {
+            _mesa_glsl_error(& @1, state,
+                             "advanced blending layout qualifiers require "
+                             "ESSL 3.20 or KHR_blend_equation_advanced");
+         }
+
+         if ($$.flags.i && state->stage != MESA_SHADER_FRAGMENT) {
+            _mesa_glsl_error(& @1, state,
+                             "advanced blending layout qualifiers only "
+                             "valid in fragment shaders");
+         }
+      }
+
       if (!$$.flags.i) {
          _mesa_glsl_error(& @1, state, "unrecognized layout identifier "
                           "`%s'", $1);
@@ -1596,8 +1632,10 @@ layout_qualifier_id:
       if (match_layout_qualifier("invocations", $1, state) == 0) {
          $$.flags.q.invocations = 1;
          $$.invocations = new(ctx) ast_layout_expression(@1, $3);
-         if (!state->is_version(400, 0) &&
-             !state->ARB_gpu_shader5_enable) {
+         if (!state->is_version(400, 320) &&
+             !state->ARB_gpu_shader5_enable &&
+             !state->OES_geometry_shader_enable &&
+             !state->EXT_geometry_shader_enable) {
             _mesa_glsl_error(& @3, state,
                              "GL_ARB_gpu_shader5 invocations "
                              "qualifier specified", $3);
@@ -1608,8 +1646,7 @@ layout_qualifier_id:
       if (match_layout_qualifier("vertices", $1, state) == 0) {
          $$.flags.q.vertices = 1;
          $$.vertices = new(ctx) ast_layout_expression(@1, $3);
-         if (!state->ARB_tessellation_shader_enable &&
-             !state->is_version(400, 0)) {
+         if (!state->has_tessellation_shader()) {
             _mesa_glsl_error(& @1, state,
                              "vertices qualifier requires GLSL 4.00 or "
                              "ARB_tessellation_shader");
@@ -1784,8 +1821,10 @@ type_qualifier:
        * variables. As only outputs can be declared as invariant, an invariant
        * output from one shader stage will still match an input of a subsequent
        * stage without the input being declared as invariant."
+       *
+       * On the desktop side, this text first appears in GLSL 4.30.
        */
-      if (state->es_shader && state->language_version >= 300 && $$.flags.q.in)
+      if (state->is_version(430, 300) && $$.flags.q.in)
          _mesa_glsl_error(&@1, state, "invariant qualifiers cannot be used with shader inputs");
    }
    | interpolation_qualifier type_qualifier
@@ -1952,6 +1991,18 @@ storage_qualifier:
           $$.xfb_buffer = state->out_qualifier->xfb_buffer;
       }
    }
+   | INOUT_TOK
+   {
+      memset(& $$, 0, sizeof($$));
+      $$.flags.q.in = 1;
+      $$.flags.q.out = 1;
+
+      if (!state->has_framebuffer_fetch() ||
+          !state->is_version(130, 300) ||
+          state->stage != MESA_SHADER_FRAGMENT)
+         _mesa_glsl_error(&@1, state, "A single interface variable cannot be "
+                          "declared as both input and output");
+   }
    | UNIFORM
    {
       memset(& $$, 0, sizeof($$));
@@ -2672,30 +2723,11 @@ basic_interface_block:
    {
       ast_interface_block *const block = $6;
 
-      block->block_name = $2;
-      block->declarations.push_degenerate_list_at_head(& $4->link);
-
-      _mesa_ast_process_interface_block(& @1, state, block, $1);
-
-      $$ = block;
-   }
-   | uniform_interface_qualifier NEW_IDENTIFIER '{' member_list '}' instance_name_opt ';'
-   {
-      ast_interface_block *const block = $6;
-
-      block->layout = *state->default_uniform_qualifier;
-      block->block_name = $2;
-      block->declarations.push_degenerate_list_at_head(& $4->link);
-
-      _mesa_ast_process_interface_block(& @1, state, block, $1);
-
-      $$ = block;
-   }
-   | buffer_interface_qualifier NEW_IDENTIFIER '{' member_list '}' instance_name_opt ';'
-   {
-      ast_interface_block *const block = $6;
-
-      block->layout = *state->default_shader_storage_qualifier;
+      if ($1.flags.q.uniform) {
+         block->layout = *state->default_uniform_qualifier;
+      } else if ($1.flags.q.buffer) {
+         block->layout = *state->default_shader_storage_qualifier;
+      }
       block->block_name = $2;
       block->declarations.push_degenerate_list_at_head(& $4->link);
 
@@ -2716,22 +2748,27 @@ interface_qualifier:
       memset(& $$, 0, sizeof($$));
       $$.flags.q.out = 1;
    }
-   ;
-
-uniform_interface_qualifier:
-   UNIFORM
+   | UNIFORM
    {
       memset(& $$, 0, sizeof($$));
       $$.flags.q.uniform = 1;
    }
-   ;
-
-buffer_interface_qualifier:
-   BUFFER
+   | BUFFER
    {
       memset(& $$, 0, sizeof($$));
       $$.flags.q.buffer = 1;
    }
+   | auxiliary_storage_qualifier interface_qualifier
+   {
+      if (!$1.flags.q.patch) {
+         _mesa_glsl_error(&@1, state, "invalid interface qualifier");
+      }
+      if ($2.has_auxiliary_storage()) {
+         _mesa_glsl_error(&@1, state, "duplicate patch qualifier");
+      }
+      $$ = $2;
+      $$.flags.q.patch = 1;
+   }
    ;
 
 instance_name_opt: