mesa: add support for GL_INTEL_conservative_rasterization
[mesa.git] / src / compiler / glsl / glsl_parser.yy
index 7d709c78c57838384395e52b740c263d5acad95d..e3893d5ec3b259d61475ea688ded7916e9dbd845 100644 (file)
@@ -297,10 +297,10 @@ static bool match_layout_qualifier(const char *s1, const char *s2,
 %type <node> for_init_statement
 %type <for_rest_statement> for_rest_statement
 %type <node> layout_defaults
-%type <node> layout_uniform_defaults
-%type <node> layout_buffer_defaults
-%type <node> layout_in_defaults
-%type <node> layout_out_defaults
+%type <type_qualifier> layout_uniform_defaults
+%type <type_qualifier> layout_buffer_defaults
+%type <type_qualifier> layout_in_defaults
+%type <type_qualifier> layout_out_defaults
 
 %right THEN ELSE
 %%
@@ -838,6 +838,16 @@ declaration:
    }
    | interface_block
    {
+      ast_interface_block *block = (ast_interface_block *) $1;
+      if (block->layout.has_layout() || block->layout.has_memory()) {
+         if (!block->default_layout.merge_qualifier(& @1, state, block->layout, false)) {
+            YYERROR;
+         }
+      }
+      block->layout = block->default_layout;
+      if (!block->layout.push_to_global(& @1, state)) {
+         YYERROR;
+      }
       $$ = $1;
    }
    ;
@@ -913,6 +923,9 @@ parameter_declaration:
    {
       $$ = $2;
       $$->type->qualifier = $1;
+      if (!$$->type->qualifier.push_to_global(& @1, state)) {
+         YYERROR;
+      }
    }
    | parameter_qualifier parameter_type_specifier
    {
@@ -922,6 +935,9 @@ parameter_declaration:
       $$->type = new(ctx) ast_fully_specified_type();
       $$->type->set_location_range(@1, @2);
       $$->type->qualifier = $1;
+      if (!$$->type->qualifier.push_to_global(& @1, state)) {
+         YYERROR;
+      }
       $$->type->specifier = $2;
    }
    ;
@@ -1137,6 +1153,9 @@ fully_specified_type:
       $$ = new(ctx) ast_fully_specified_type();
       $$->set_location_range(@1, @2);
       $$->qualifier = $1;
+      if (!$$->qualifier.push_to_global(& @1, state)) {
+         YYERROR;
+      }
       $$->specifier = $2;
       if ($$->specifier->structure != NULL &&
           $$->specifier->structure->is_declaration) {
@@ -1296,51 +1315,55 @@ layout_qualifier_id:
                unsigned required_glsl;
                /** Minimum GLSL ES version required for the image format. */
                unsigned required_essl;
+               /* NV_image_formats */
+               bool nv_image_formats;
             } map[] = {
-               { "rgba32f", GL_RGBA32F, GLSL_TYPE_FLOAT, 130, 310 },
-               { "rgba16f", GL_RGBA16F, GLSL_TYPE_FLOAT, 130, 310 },
-               { "rg32f", GL_RG32F, GLSL_TYPE_FLOAT, 130, 0 },
-               { "rg16f", GL_RG16F, GLSL_TYPE_FLOAT, 130, 0 },
-               { "r11f_g11f_b10f", GL_R11F_G11F_B10F, GLSL_TYPE_FLOAT, 130, 0 },
-               { "r32f", GL_R32F, GLSL_TYPE_FLOAT, 130, 310 },
-               { "r16f", GL_R16F, GLSL_TYPE_FLOAT, 130, 0 },
-               { "rgba32ui", GL_RGBA32UI, GLSL_TYPE_UINT, 130, 310 },
-               { "rgba16ui", GL_RGBA16UI, GLSL_TYPE_UINT, 130, 310 },
-               { "rgb10_a2ui", GL_RGB10_A2UI, GLSL_TYPE_UINT, 130, 0 },
-               { "rgba8ui", GL_RGBA8UI, GLSL_TYPE_UINT, 130, 310 },
-               { "rg32ui", GL_RG32UI, GLSL_TYPE_UINT, 130, 0 },
-               { "rg16ui", GL_RG16UI, GLSL_TYPE_UINT, 130, 0 },
-               { "rg8ui", GL_RG8UI, GLSL_TYPE_UINT, 130, 0 },
-               { "r32ui", GL_R32UI, GLSL_TYPE_UINT, 130, 310 },
-               { "r16ui", GL_R16UI, GLSL_TYPE_UINT, 130, 0 },
-               { "r8ui", GL_R8UI, GLSL_TYPE_UINT, 130, 0 },
-               { "rgba32i", GL_RGBA32I, GLSL_TYPE_INT, 130, 310 },
-               { "rgba16i", GL_RGBA16I, GLSL_TYPE_INT, 130, 310 },
-               { "rgba8i", GL_RGBA8I, GLSL_TYPE_INT, 130, 310 },
-               { "rg32i", GL_RG32I, GLSL_TYPE_INT, 130, 0 },
-               { "rg16i", GL_RG16I, GLSL_TYPE_INT, 130, 0 },
-               { "rg8i", GL_RG8I, GLSL_TYPE_INT, 130, 0 },
-               { "r32i", GL_R32I, GLSL_TYPE_INT, 130, 310 },
-               { "r16i", GL_R16I, GLSL_TYPE_INT, 130, 0 },
-               { "r8i", GL_R8I, GLSL_TYPE_INT, 130, 0 },
-               { "rgba16", GL_RGBA16, GLSL_TYPE_FLOAT, 130, 0 },
-               { "rgb10_a2", GL_RGB10_A2, GLSL_TYPE_FLOAT, 130, 0 },
-               { "rgba8", GL_RGBA8, GLSL_TYPE_FLOAT, 130, 310 },
-               { "rg16", GL_RG16, GLSL_TYPE_FLOAT, 130, 0 },
-               { "rg8", GL_RG8, GLSL_TYPE_FLOAT, 130, 0 },
-               { "r16", GL_R16, GLSL_TYPE_FLOAT, 130, 0 },
-               { "r8", GL_R8, GLSL_TYPE_FLOAT, 130, 0 },
-               { "rgba16_snorm", GL_RGBA16_SNORM, GLSL_TYPE_FLOAT, 130, 0 },
-               { "rgba8_snorm", GL_RGBA8_SNORM, GLSL_TYPE_FLOAT, 130, 310 },
-               { "rg16_snorm", GL_RG16_SNORM, GLSL_TYPE_FLOAT, 130, 0 },
-               { "rg8_snorm", GL_RG8_SNORM, GLSL_TYPE_FLOAT, 130, 0 },
-               { "r16_snorm", GL_R16_SNORM, GLSL_TYPE_FLOAT, 130, 0 },
-               { "r8_snorm", GL_R8_SNORM, GLSL_TYPE_FLOAT, 130, 0 }
+               { "rgba32f", GL_RGBA32F, GLSL_TYPE_FLOAT, 130, 310, false },
+               { "rgba16f", GL_RGBA16F, GLSL_TYPE_FLOAT, 130, 310, false },
+               { "rg32f", GL_RG32F, GLSL_TYPE_FLOAT, 130, 0, true },
+               { "rg16f", GL_RG16F, GLSL_TYPE_FLOAT, 130, 0, true },
+               { "r11f_g11f_b10f", GL_R11F_G11F_B10F, GLSL_TYPE_FLOAT, 130, 0, true },
+               { "r32f", GL_R32F, GLSL_TYPE_FLOAT, 130, 310, false },
+               { "r16f", GL_R16F, GLSL_TYPE_FLOAT, 130, 0, true },
+               { "rgba32ui", GL_RGBA32UI, GLSL_TYPE_UINT, 130, 310, false },
+               { "rgba16ui", GL_RGBA16UI, GLSL_TYPE_UINT, 130, 310, false },
+               { "rgb10_a2ui", GL_RGB10_A2UI, GLSL_TYPE_UINT, 130, 0, true },
+               { "rgba8ui", GL_RGBA8UI, GLSL_TYPE_UINT, 130, 310, false },
+               { "rg32ui", GL_RG32UI, GLSL_TYPE_UINT, 130, 0, true },
+               { "rg16ui", GL_RG16UI, GLSL_TYPE_UINT, 130, 0, true },
+               { "rg8ui", GL_RG8UI, GLSL_TYPE_UINT, 130, 0, true },
+               { "r32ui", GL_R32UI, GLSL_TYPE_UINT, 130, 310, false },
+               { "r16ui", GL_R16UI, GLSL_TYPE_UINT, 130, 0, true },
+               { "r8ui", GL_R8UI, GLSL_TYPE_UINT, 130, 0, true },
+               { "rgba32i", GL_RGBA32I, GLSL_TYPE_INT, 130, 310, false },
+               { "rgba16i", GL_RGBA16I, GLSL_TYPE_INT, 130, 310, false },
+               { "rgba8i", GL_RGBA8I, GLSL_TYPE_INT, 130, 310, false },
+               { "rg32i", GL_RG32I, GLSL_TYPE_INT, 130, 0, true },
+               { "rg16i", GL_RG16I, GLSL_TYPE_INT, 130, 0, true },
+               { "rg8i", GL_RG8I, GLSL_TYPE_INT, 130, 0, true },
+               { "r32i", GL_R32I, GLSL_TYPE_INT, 130, 310, false },
+               { "r16i", GL_R16I, GLSL_TYPE_INT, 130, 0, true },
+               { "r8i", GL_R8I, GLSL_TYPE_INT, 130, 0, true },
+               { "rgba16", GL_RGBA16, GLSL_TYPE_FLOAT, 130, 0, false },
+               { "rgb10_a2", GL_RGB10_A2, GLSL_TYPE_FLOAT, 130, 0, true },
+               { "rgba8", GL_RGBA8, GLSL_TYPE_FLOAT, 130, 310, false },
+               { "rg16", GL_RG16, GLSL_TYPE_FLOAT, 130, 0, false },
+               { "rg8", GL_RG8, GLSL_TYPE_FLOAT, 130, 0, true },
+               { "r16", GL_R16, GLSL_TYPE_FLOAT, 130, 0, false },
+               { "r8", GL_R8, GLSL_TYPE_FLOAT, 130, 0, true },
+               { "rgba16_snorm", GL_RGBA16_SNORM, GLSL_TYPE_FLOAT, 130, 0, false },
+               { "rgba8_snorm", GL_RGBA8_SNORM, GLSL_TYPE_FLOAT, 130, 310, false },
+               { "rg16_snorm", GL_RG16_SNORM, GLSL_TYPE_FLOAT, 130, 0, false },
+               { "rg8_snorm", GL_RG8_SNORM, GLSL_TYPE_FLOAT, 130, 0, true },
+               { "r16_snorm", GL_R16_SNORM, GLSL_TYPE_FLOAT, 130, 0, false },
+               { "r8_snorm", GL_R8_SNORM, GLSL_TYPE_FLOAT, 130, 0, true }
             };
 
             for (unsigned i = 0; i < ARRAY_SIZE(map); i++) {
-               if (state->is_version(map[i].required_glsl,
-                                     map[i].required_essl) &&
+               if ((state->is_version(map[i].required_glsl,
+                                      map[i].required_essl) ||
+                    (state->NV_image_formats_enable &&
+                     map[i].nv_image_formats)) &&
                    match_layout_qualifier($1, map[i].name, state) == 0) {
                   $$.flags.q.explicit_image_format = 1;
                   $$.image_format = map[i].format;
@@ -1349,9 +1372,10 @@ layout_qualifier_id:
                }
             }
          }
+      }
 
-         if (!$$.flags.i &&
-             match_layout_qualifier($1, "early_fragment_tests", state) == 0) {
+      if (!$$.flags.i) {
+         if (match_layout_qualifier($1, "early_fragment_tests", state) == 0) {
             /* From section 4.4.1.3 of the GLSL 4.50 specification
              * (Fragment Shader Inputs):
              *
@@ -1369,6 +1393,47 @@ layout_qualifier_id:
 
             $$.flags.q.early_fragment_tests = 1;
          }
+
+         if (match_layout_qualifier($1, "inner_coverage", state) == 0) {
+            if (state->stage != MESA_SHADER_FRAGMENT) {
+               _mesa_glsl_error(& @1, state,
+                                "inner_coverage layout qualifier only "
+                                "valid in fragment shaders");
+            }
+
+           if (state->INTEL_conservative_rasterization_enable) {
+              $$.flags.q.inner_coverage = 1;
+           } else {
+              _mesa_glsl_error(& @1, state,
+                                "inner_coverage layout qualifier present, "
+                                "but the INTEL_conservative_rasterization extension "
+                                "is not enabled.");
+            }
+         }
+
+         if (match_layout_qualifier($1, "post_depth_coverage", state) == 0) {
+            if (state->stage != MESA_SHADER_FRAGMENT) {
+               _mesa_glsl_error(& @1, state,
+                                "post_depth_coverage layout qualifier only "
+                                "valid in fragment shaders");
+            }
+
+            if (state->ARB_post_depth_coverage_enable ||
+               state->INTEL_conservative_rasterization_enable) {
+               $$.flags.q.post_depth_coverage = 1;
+            } else {
+               _mesa_glsl_error(& @1, state,
+                                "post_depth_coverage layout qualifier present, "
+                                "but the GL_ARB_post_depth_coverage extension "
+                                "is not enabled.");
+            }
+         }
+
+         if ($$.flags.q.post_depth_coverage && $$.flags.q.inner_coverage) {
+            _mesa_glsl_error(& @1, state,
+                             "post_depth_coverage & inner_coverage layout qualifiers "
+                             "are mutually exclusive");
+         }
       }
 
       /* Layout qualifiers for tessellation evaluation shaders. */
@@ -1875,11 +1940,8 @@ type_qualifier:
        * precise qualifiers since these are useful in ARB_separate_shader_objects.
        * There is no clear spec guidance on this either.
        */
-      if (!state->has_420pack_or_es31() && $2.has_layout())
-         _mesa_glsl_error(&@1, state, "duplicate layout(...) qualifiers");
-
       $$ = $1;
-      $$.merge_qualifier(&@1, state, $2, false);
+      $$.merge_qualifier(& @1, state, $2, false, $2.has_layout());
    }
    | subroutine_qualifier type_qualifier
    {
@@ -2701,17 +2763,12 @@ interface_block:
    {
       ast_interface_block *block = (ast_interface_block *) $2;
 
-      if (!state->has_420pack_or_es31() && block->layout.has_layout() &&
-          !block->layout.is_default_qualifier) {
-         _mesa_glsl_error(&@1, state, "duplicate layout(...) qualifiers");
-         YYERROR;
-      }
-
-      if (!block->layout.merge_qualifier(& @1, state, $1, false)) {
+      if (!$1.merge_qualifier(& @1, state, block->layout, false,
+                              block->layout.has_layout())) {
          YYERROR;
       }
 
-      block->layout.is_default_qualifier = false;
+      block->layout = $1;
 
       $$ = block;
    }
@@ -2719,14 +2776,15 @@ interface_block:
    {
       ast_interface_block *block = (ast_interface_block *)$2;
 
-      if (!block->layout.flags.q.buffer) {
+      if (!block->default_layout.flags.q.buffer) {
             _mesa_glsl_error(& @1, state,
                              "memory qualifiers can only be used in the "
                              "declaration of shader storage blocks");
       }
-      if (!block->layout.merge_qualifier(& @1, state, $1, false)) {
+      if (!$1.merge_qualifier(& @1, state, block->layout, false)) {
          YYERROR;
       }
+      block->layout = $1;
       $$ = block;
    }
    ;
@@ -2737,9 +2795,9 @@ basic_interface_block:
       ast_interface_block *const block = $6;
 
       if ($1.flags.q.uniform) {
-         block->layout = *state->default_uniform_qualifier;
+         block->default_layout = *state->default_uniform_qualifier;
       } else if ($1.flags.q.buffer) {
-         block->layout = *state->default_shader_storage_qualifier;
+         block->default_layout = *state->default_shader_storage_qualifier;
       }
       block->block_name = $2;
       block->declarations.push_degenerate_list_at_head(& $4->link);
@@ -2841,82 +2899,39 @@ member_declaration:
 layout_uniform_defaults:
    layout_qualifier layout_uniform_defaults
    {
-      $$ = NULL;
-      if (!state->has_420pack_or_es31()) {
-         _mesa_glsl_error(&@1, state, "duplicate layout(...) qualifiers");
+      $$ = $1;
+      if (!$$.merge_qualifier(& @1, state, $2, false, true)) {
          YYERROR;
-      } else {
-         if (!state->default_uniform_qualifier->
-                merge_qualifier(& @1, state, $1, false)) {
-            YYERROR;
-         }
       }
    }
    | layout_qualifier UNIFORM ';'
-   {
-      if (!state->default_uniform_qualifier->
-             merge_qualifier(& @1, state, $1, false)) {
-         YYERROR;
-      }
-      $$ = NULL;
-   }
    ;
 
 layout_buffer_defaults:
    layout_qualifier layout_buffer_defaults
    {
-      $$ = NULL;
-      if (!state->has_420pack_or_es31()) {
-         _mesa_glsl_error(&@1, state, "duplicate layout(...) qualifiers");
+      $$ = $1;
+      if (!$$.merge_qualifier(& @1, state, $2, false, true)) {
          YYERROR;
-      } else {
-         if (!state->default_shader_storage_qualifier->
-                merge_qualifier(& @1, state, $1, false)) {
-            YYERROR;
-         }
       }
    }
    | layout_qualifier BUFFER ';'
-   {
-      if (!state->default_shader_storage_qualifier->
-             merge_qualifier(& @1, state, $1, false)) {
-         YYERROR;
-      }
-
-      /* From the GLSL 4.50 spec, section 4.4.5:
-       *
-       *     "It is a compile-time error to specify the binding identifier for
-       *     the global scope or for block member declarations."
-       */
-      if (state->default_shader_storage_qualifier->flags.q.explicit_binding) {
-         _mesa_glsl_error(& @1, state,
-                          "binding qualifier cannot be set for default layout");
-      }
-
-      $$ = NULL;
-   }
    ;
 
 layout_in_defaults:
    layout_qualifier layout_in_defaults
    {
-      $$ = NULL;
-      if (!state->has_420pack_or_es31()) {
-         _mesa_glsl_error(&@1, state, "duplicate layout(...) qualifiers");
+      $$ = $1;
+      if (!$$.merge_qualifier(& @1, state, $2, false, true)) {
+         YYERROR;
+      }
+      if (!$$.validate_in_qualifier(& @1, state)) {
          YYERROR;
-      } else {
-         if (!state->in_qualifier->
-                merge_in_qualifier(& @1, state, $1, $$, false)) {
-            YYERROR;
-         }
-         $$ = $2;
       }
    }
    | layout_qualifier IN_TOK ';'
    {
-      $$ = NULL;
-      if (!state->in_qualifier->
-             merge_in_qualifier(& @1, state, $1, $$, true)) {
+      if (!$1.validate_in_qualifier(& @1, state)) {
          YYERROR;
       }
    }
@@ -2925,30 +2940,75 @@ layout_in_defaults:
 layout_out_defaults:
    layout_qualifier layout_out_defaults
    {
-      $$ = NULL;
-      if (!state->has_420pack_or_es31()) {
-         _mesa_glsl_error(&@1, state, "duplicate layout(...) qualifiers");
+      $$ = $1;
+      if (!$$.merge_qualifier(& @1, state, $2, false, true)) {
+         YYERROR;
+      }
+      if (!$$.validate_out_qualifier(& @1, state)) {
          YYERROR;
-      } else {
-         if (!state->out_qualifier->
-                merge_out_qualifier(& @1, state, $1, $$, false)) {
-            YYERROR;
-         }
-         $$ = $2;
       }
    }
    | layout_qualifier OUT_TOK ';'
    {
-      $$ = NULL;
-      if (!state->out_qualifier->
-             merge_out_qualifier(& @1, state, $1, $$, true))
+      if (!$1.validate_out_qualifier(& @1, state)) {
          YYERROR;
+      }
    }
    ;
 
 layout_defaults:
    layout_uniform_defaults
+   {
+      $$ = NULL;
+      if (!state->default_uniform_qualifier->
+             merge_qualifier(& @1, state, $1, false)) {
+         YYERROR;
+      }
+      if (!state->default_uniform_qualifier->
+             push_to_global(& @1, state)) {
+         YYERROR;
+      }
+   }
    | layout_buffer_defaults
+   {
+      $$ = NULL;
+      if (!state->default_shader_storage_qualifier->
+             merge_qualifier(& @1, state, $1, false)) {
+         YYERROR;
+      }
+      if (!state->default_shader_storage_qualifier->
+             push_to_global(& @1, state)) {
+         YYERROR;
+      }
+
+      /* From the GLSL 4.50 spec, section 4.4.5:
+       *
+       *     "It is a compile-time error to specify the binding identifier for
+       *     the global scope or for block member declarations."
+       */
+      if (state->default_shader_storage_qualifier->flags.q.explicit_binding) {
+         _mesa_glsl_error(& @1, state,
+                          "binding qualifier cannot be set for default layout");
+      }
+   }
    | layout_in_defaults
+   {
+      $$ = NULL;
+      if (!$1.merge_into_in_qualifier(& @1, state, $$)) {
+         YYERROR;
+      }
+      if (!state->in_qualifier->push_to_global(& @1, state)) {
+         YYERROR;
+      }
+   }
    | layout_out_defaults
+   {
+      $$ = NULL;
+      if (!$1.merge_into_out_qualifier(& @1, state, $$)) {
+         YYERROR;
+      }
+      if (!state->out_qualifier->push_to_global(& @1, state)) {
+         YYERROR;
+      }
+   }
    ;