glsl: add ast/parser support for subroutine parsing storage (v3.2)
[mesa.git] / src / glsl / glsl_parser_extras.cpp
index a8ba89eda3ab05b13b144b8587b8c453c98ce480..59a312fc6471f61c55cba35cfd81b3fa40b09444 100644 (file)
@@ -113,10 +113,26 @@ _mesa_glsl_parse_state::_mesa_glsl_parse_state(struct gl_context *_ctx,
    this->Const.MaxGeometryUniformComponents = ctx->Const.Program[MESA_SHADER_GEOMETRY].MaxUniformComponents;
 
    this->Const.MaxVertexAtomicCounters = ctx->Const.Program[MESA_SHADER_VERTEX].MaxAtomicCounters;
+   this->Const.MaxTessControlAtomicCounters = ctx->Const.Program[MESA_SHADER_TESS_CTRL].MaxAtomicCounters;
+   this->Const.MaxTessEvaluationAtomicCounters = ctx->Const.Program[MESA_SHADER_TESS_EVAL].MaxAtomicCounters;
    this->Const.MaxGeometryAtomicCounters = ctx->Const.Program[MESA_SHADER_GEOMETRY].MaxAtomicCounters;
    this->Const.MaxFragmentAtomicCounters = ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxAtomicCounters;
    this->Const.MaxCombinedAtomicCounters = ctx->Const.MaxCombinedAtomicCounters;
    this->Const.MaxAtomicBufferBindings = ctx->Const.MaxAtomicBufferBindings;
+   this->Const.MaxVertexAtomicCounterBuffers =
+      ctx->Const.Program[MESA_SHADER_VERTEX].MaxAtomicBuffers;
+   this->Const.MaxTessControlAtomicCounterBuffers =
+      ctx->Const.Program[MESA_SHADER_TESS_CTRL].MaxAtomicBuffers;
+   this->Const.MaxTessEvaluationAtomicCounterBuffers =
+      ctx->Const.Program[MESA_SHADER_TESS_EVAL].MaxAtomicBuffers;
+   this->Const.MaxGeometryAtomicCounterBuffers =
+      ctx->Const.Program[MESA_SHADER_GEOMETRY].MaxAtomicBuffers;
+   this->Const.MaxFragmentAtomicCounterBuffers =
+      ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxAtomicBuffers;
+   this->Const.MaxCombinedAtomicCounterBuffers =
+      ctx->Const.MaxCombinedAtomicBuffers;
+   this->Const.MaxAtomicCounterBufferSize =
+      ctx->Const.MaxAtomicBufferSize;
 
    /* Compute shader constants */
    for (unsigned i = 0; i < ARRAY_SIZE(this->Const.MaxComputeWorkGroupCount); i++)
@@ -128,6 +144,8 @@ _mesa_glsl_parse_state::_mesa_glsl_parse_state(struct gl_context *_ctx,
    this->Const.MaxCombinedImageUnitsAndFragmentOutputs = ctx->Const.MaxCombinedImageUnitsAndFragmentOutputs;
    this->Const.MaxImageSamples = ctx->Const.MaxImageSamples;
    this->Const.MaxVertexImageUniforms = ctx->Const.Program[MESA_SHADER_VERTEX].MaxImageUniforms;
+   this->Const.MaxTessControlImageUniforms = ctx->Const.Program[MESA_SHADER_TESS_CTRL].MaxImageUniforms;
+   this->Const.MaxTessEvaluationImageUniforms = ctx->Const.Program[MESA_SHADER_TESS_EVAL].MaxImageUniforms;
    this->Const.MaxGeometryImageUniforms = ctx->Const.Program[MESA_SHADER_GEOMETRY].MaxImageUniforms;
    this->Const.MaxFragmentImageUniforms = ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxImageUniforms;
    this->Const.MaxCombinedImageUniforms = ctx->Const.MaxCombinedImageUniforms;
@@ -135,17 +153,35 @@ _mesa_glsl_parse_state::_mesa_glsl_parse_state(struct gl_context *_ctx,
    /* ARB_viewport_array */
    this->Const.MaxViewports = ctx->Const.MaxViewports;
 
+   /* tessellation shader constants */
+   this->Const.MaxPatchVertices = ctx->Const.MaxPatchVertices;
+   this->Const.MaxTessGenLevel = ctx->Const.MaxTessGenLevel;
+   this->Const.MaxTessControlInputComponents = ctx->Const.Program[MESA_SHADER_TESS_CTRL].MaxInputComponents;
+   this->Const.MaxTessControlOutputComponents = ctx->Const.Program[MESA_SHADER_TESS_CTRL].MaxOutputComponents;
+   this->Const.MaxTessControlTextureImageUnits = ctx->Const.Program[MESA_SHADER_TESS_CTRL].MaxTextureImageUnits;
+   this->Const.MaxTessEvaluationInputComponents = ctx->Const.Program[MESA_SHADER_TESS_EVAL].MaxInputComponents;
+   this->Const.MaxTessEvaluationOutputComponents = ctx->Const.Program[MESA_SHADER_TESS_EVAL].MaxOutputComponents;
+   this->Const.MaxTessEvaluationTextureImageUnits = ctx->Const.Program[MESA_SHADER_TESS_EVAL].MaxTextureImageUnits;
+   this->Const.MaxTessPatchComponents = ctx->Const.MaxTessPatchComponents;
+   this->Const.MaxTessControlTotalOutputComponents = ctx->Const.MaxTessControlTotalOutputComponents;
+   this->Const.MaxTessControlUniformComponents = ctx->Const.Program[MESA_SHADER_TESS_CTRL].MaxUniformComponents;
+   this->Const.MaxTessEvaluationUniformComponents = ctx->Const.Program[MESA_SHADER_TESS_EVAL].MaxUniformComponents;
+
    this->current_function = NULL;
    this->toplevel_ir = NULL;
    this->found_return = false;
    this->all_invariant = false;
    this->user_structures = NULL;
    this->num_user_structures = 0;
+   this->num_subroutines = 0;
+   this->subroutines = NULL;
+   this->num_subroutine_types = 0;
+   this->subroutine_types = NULL;
 
    /* supported_versions should be large enough to support the known desktop
-    * GLSL versions plus 2 GLES versions (ES2 & ES3)
+    * GLSL versions plus 3 GLES versions (ES 1.00, ES 3.00, and ES 3.10))
     */
-   STATIC_ASSERT((ARRAY_SIZE(known_desktop_glsl_versions) + 2) ==
+   STATIC_ASSERT((ARRAY_SIZE(known_desktop_glsl_versions) + 3) ==
                  ARRAY_SIZE(this->supported_versions));
 
    /* Populate the list of supported GLSL versions */
@@ -175,6 +211,11 @@ _mesa_glsl_parse_state::_mesa_glsl_parse_state(struct gl_context *_ctx,
       this->supported_versions[this->num_supported_versions].es = true;
       this->num_supported_versions++;
    }
+   if (_mesa_is_gles31(ctx)) {
+      this->supported_versions[this->num_supported_versions].ver = 310;
+      this->supported_versions[this->num_supported_versions].es = true;
+      this->num_supported_versions++;
+   }
 
    /* Create a string for use in error messages to tell the user which GLSL
     * versions are supported.
@@ -209,6 +250,7 @@ _mesa_glsl_parse_state::_mesa_glsl_parse_state(struct gl_context *_ctx,
    this->fs_redeclares_gl_fragcoord_with_no_layout_qualifiers = false;
 
    this->gs_input_prim_type_specified = false;
+   this->tcs_output_vertices_specified = false;
    this->gs_input_size = 0;
    this->in_qualifier = new(this) ast_type_qualifier();
    this->out_qualifier = new(this) ast_type_qualifier();
@@ -374,6 +416,8 @@ _mesa_shader_stage_to_string(unsigned stage)
    case MESA_SHADER_FRAGMENT: return "fragment";
    case MESA_SHADER_GEOMETRY: return "geometry";
    case MESA_SHADER_COMPUTE:  return "compute";
+   case MESA_SHADER_TESS_CTRL: return "tess ctrl";
+   case MESA_SHADER_TESS_EVAL: return "tess eval";
    }
 
    unreachable("Unknown shader stage.");
@@ -391,6 +435,8 @@ _mesa_shader_stage_to_abbrev(unsigned stage)
    case MESA_SHADER_FRAGMENT: return "FS";
    case MESA_SHADER_GEOMETRY: return "GS";
    case MESA_SHADER_COMPUTE:  return "CS";
+   case MESA_SHADER_TESS_CTRL: return "TCS";
+   case MESA_SHADER_TESS_EVAL: return "TES";
    }
 
    unreachable("Unknown shader stage.");
@@ -536,36 +582,40 @@ static const _mesa_glsl_extension _mesa_glsl_supported_extensions[] = {
 
    /* ARB extensions go here, sorted alphabetically.
     */
-   EXT(ARB_arrays_of_arrays,           true,  false,     ARB_arrays_of_arrays),
-   EXT(ARB_compute_shader,             true,  false,     ARB_compute_shader),
-   EXT(ARB_conservative_depth,         true,  false,     ARB_conservative_depth),
-   EXT(ARB_derivative_control,         true,  false,     ARB_derivative_control),
-   EXT(ARB_draw_buffers,               true,  false,     dummy_true),
-   EXT(ARB_draw_instanced,             true,  false,     ARB_draw_instanced),
-   EXT(ARB_explicit_attrib_location,   true,  false,     ARB_explicit_attrib_location),
-   EXT(ARB_explicit_uniform_location,  true,  false,     ARB_explicit_uniform_location),
-   EXT(ARB_fragment_coord_conventions, true,  false,     ARB_fragment_coord_conventions),
-   EXT(ARB_fragment_layer_viewport,    true,  false,     ARB_fragment_layer_viewport),
-   EXT(ARB_gpu_shader5,                true,  false,     ARB_gpu_shader5),
-   EXT(ARB_gpu_shader_fp64,            true,  false,     ARB_gpu_shader_fp64),
-   EXT(ARB_sample_shading,             true,  false,     ARB_sample_shading),
-   EXT(ARB_separate_shader_objects,    true,  false,     dummy_true),
-   EXT(ARB_shader_atomic_counters,     true,  false,     ARB_shader_atomic_counters),
-   EXT(ARB_shader_bit_encoding,        true,  false,     ARB_shader_bit_encoding),
-   EXT(ARB_shader_image_load_store,    true,  false,     ARB_shader_image_load_store),
-   EXT(ARB_shader_precision,           true,  false,     ARB_shader_precision),
-   EXT(ARB_shader_stencil_export,      true,  false,     ARB_shader_stencil_export),
-   EXT(ARB_shader_texture_lod,         true,  false,     ARB_shader_texture_lod),
-   EXT(ARB_shading_language_420pack,   true,  false,     ARB_shading_language_420pack),
-   EXT(ARB_shading_language_packing,   true,  false,     ARB_shading_language_packing),
-   EXT(ARB_texture_cube_map_array,     true,  false,     ARB_texture_cube_map_array),
-   EXT(ARB_texture_gather,             true,  false,     ARB_texture_gather),
-   EXT(ARB_texture_multisample,        true,  false,     ARB_texture_multisample),
-   EXT(ARB_texture_query_levels,       true,  false,     ARB_texture_query_levels),
-   EXT(ARB_texture_query_lod,          true,  false,     ARB_texture_query_lod),
-   EXT(ARB_texture_rectangle,          true,  false,     dummy_true),
-   EXT(ARB_uniform_buffer_object,      true,  false,     ARB_uniform_buffer_object),
-   EXT(ARB_viewport_array,             true,  false,     ARB_viewport_array),
+   EXT(ARB_arrays_of_arrays,             true,  false,     ARB_arrays_of_arrays),
+   EXT(ARB_compute_shader,               true,  false,     ARB_compute_shader),
+   EXT(ARB_conservative_depth,           true,  false,     ARB_conservative_depth),
+   EXT(ARB_derivative_control,           true,  false,     ARB_derivative_control),
+   EXT(ARB_draw_buffers,                 true,  false,     dummy_true),
+   EXT(ARB_draw_instanced,               true,  false,     ARB_draw_instanced),
+   EXT(ARB_explicit_attrib_location,     true,  false,     ARB_explicit_attrib_location),
+   EXT(ARB_explicit_uniform_location,    true,  false,     ARB_explicit_uniform_location),
+   EXT(ARB_fragment_coord_conventions,   true,  false,     ARB_fragment_coord_conventions),
+   EXT(ARB_fragment_layer_viewport,      true,  false,     ARB_fragment_layer_viewport),
+   EXT(ARB_gpu_shader5,                  true,  false,     ARB_gpu_shader5),
+   EXT(ARB_gpu_shader_fp64,              true,  false,     ARB_gpu_shader_fp64),
+   EXT(ARB_sample_shading,               true,  false,     ARB_sample_shading),
+   EXT(ARB_separate_shader_objects,      true,  false,     dummy_true),
+   EXT(ARB_shader_atomic_counters,       true,  false,     ARB_shader_atomic_counters),
+   EXT(ARB_shader_bit_encoding,          true,  false,     ARB_shader_bit_encoding),
+   EXT(ARB_shader_image_load_store,      true,  false,     ARB_shader_image_load_store),
+   EXT(ARB_shader_precision,             true,  false,     ARB_shader_precision),
+   EXT(ARB_shader_stencil_export,        true,  false,     ARB_shader_stencil_export),
+   EXT(ARB_shader_storage_buffer_object, true,  false,     ARB_shader_storage_buffer_object),
+   EXT(ARB_shader_subroutine,            true,  false,     ARB_shader_subroutine),
+   EXT(ARB_shader_texture_lod,           true,  false,     ARB_shader_texture_lod),
+   EXT(ARB_shading_language_420pack,     true,  false,     ARB_shading_language_420pack),
+   EXT(ARB_shading_language_packing,     true,  false,     ARB_shading_language_packing),
+   EXT(ARB_tessellation_shader,          true,  false,     ARB_tessellation_shader),
+   EXT(ARB_texture_cube_map_array,       true,  false,     ARB_texture_cube_map_array),
+   EXT(ARB_texture_gather,               true,  false,     ARB_texture_gather),
+   EXT(ARB_texture_multisample,          true,  false,     ARB_texture_multisample),
+   EXT(ARB_texture_query_levels,         true,  false,     ARB_texture_query_levels),
+   EXT(ARB_texture_query_lod,            true,  false,     ARB_texture_query_lod),
+   EXT(ARB_texture_rectangle,            true,  false,     dummy_true),
+   EXT(ARB_uniform_buffer_object,        true,  false,     ARB_uniform_buffer_object),
+   EXT(ARB_vertex_attrib_64bit,          true,  false,     ARB_vertex_attrib_64bit),
+   EXT(ARB_viewport_array,               true,  false,     ARB_viewport_array),
 
    /* KHR extensions go here, sorted alphabetically.
     */
@@ -762,7 +812,7 @@ _mesa_ast_set_aggregate_type(const glsl_type *type,
 
    /* If the aggregate is an array, recursively set its elements' types. */
    if (type->is_array()) {
-      /* Each array element has the type type->element_type().
+      /* Each array element has the type type->fields.array.
        *
        * E.g., if <type> if struct S[2] we want to set each element's type to
        * struct S.
@@ -774,7 +824,7 @@ _mesa_ast_set_aggregate_type(const glsl_type *type,
                                                link);
 
          if (expr->oper == ast_aggregate)
-            _mesa_ast_set_aggregate_type(type->element_type(), expr);
+            _mesa_ast_set_aggregate_type(type->fields.array, expr);
       }
 
    /* If the aggregate is a struct, recursively set its fields' types. */
@@ -809,6 +859,15 @@ _mesa_ast_set_aggregate_type(const glsl_type *type,
 void
 _mesa_ast_type_qualifier_print(const struct ast_type_qualifier *q)
 {
+   if (q->flags.q.subroutine)
+      printf("subroutine ");
+
+   if (q->flags.q.subroutine_def) {
+      printf("subroutine (");
+      q->subroutine_list->print();
+      printf(")");
+   }
+
    if (q->flags.q.constant)
       printf("const ");
 
@@ -835,8 +894,12 @@ _mesa_ast_type_qualifier_print(const struct ast_type_qualifier *q)
       printf("centroid ");
    if (q->flags.q.sample)
       printf("sample ");
+   if (q->flags.q.patch)
+      printf("patch ");
    if (q->flags.q.uniform)
       printf("uniform ");
+   if (q->flags.q.buffer)
+      printf("buffer ");
    if (q->flags.q.smooth)
       printf("smooth ");
    if (q->flags.q.flat)
@@ -1397,12 +1460,25 @@ ast_struct_specifier::ast_struct_specifier(const char *identifier,
    is_declaration = true;
 }
 
+void ast_subroutine_list::print(void) const
+{
+   foreach_list_typed (ast_node, ast, link, & this->declarations) {
+      if (&ast->link != this->declarations.get_head())
+         printf(", ");
+      ast->print();
+   }
+}
+
 static void
 set_shader_inout_layout(struct gl_shader *shader,
                     struct _mesa_glsl_parse_state *state)
 {
-   if (shader->Stage != MESA_SHADER_GEOMETRY) {
-      /* Should have been prevented by the parser. */
+   /* Should have been prevented by the parser. */
+   if (shader->Stage == MESA_SHADER_TESS_CTRL) {
+      assert(!state->in_qualifier->flags.i);
+   } else if (shader->Stage == MESA_SHADER_TESS_EVAL) {
+      assert(!state->out_qualifier->flags.i);
+   } else if (shader->Stage != MESA_SHADER_GEOMETRY) {
       assert(!state->in_qualifier->flags.i);
       assert(!state->out_qualifier->flags.i);
    }
@@ -1422,6 +1498,28 @@ set_shader_inout_layout(struct gl_shader *shader,
    }
 
    switch (shader->Stage) {
+   case MESA_SHADER_TESS_CTRL:
+      shader->TessCtrl.VerticesOut = 0;
+      if (state->tcs_output_vertices_specified)
+         shader->TessCtrl.VerticesOut = state->out_qualifier->vertices;
+      break;
+   case MESA_SHADER_TESS_EVAL:
+      shader->TessEval.PrimitiveMode = PRIM_UNKNOWN;
+      if (state->in_qualifier->flags.q.prim_type)
+         shader->TessEval.PrimitiveMode = state->in_qualifier->prim_type;
+
+      shader->TessEval.Spacing = 0;
+      if (state->in_qualifier->flags.q.vertex_spacing)
+         shader->TessEval.Spacing = state->in_qualifier->vertex_spacing;
+
+      shader->TessEval.VertexOrder = 0;
+      if (state->in_qualifier->flags.q.ordering)
+         shader->TessEval.VertexOrder = state->in_qualifier->ordering;
+
+      shader->TessEval.PointMode = -1;
+      if (state->in_qualifier->flags.q.point_mode)
+         shader->TessEval.PointMode = state->in_qualifier->point_mode;
+      break;
    case MESA_SHADER_GEOMETRY:
       shader->Geom.VerticesOut = 0;
       if (state->out_qualifier->flags.q.max_vertices)