X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;ds=sidebyside;f=src%2Fglsl%2Fglsl_parser_extras.cpp;h=6893c7b82cca1db1e94a5f2712b9f03db925e5e8;hb=cd1b0f04be041fa1750cac332d5539c48a3f272d;hp=c0dd713703f9d20c652c45fba3f176c1cd9ab7aa;hpb=220f70667dacc37f0e5cb871f6054214519d191f;p=mesa.git diff --git a/src/glsl/glsl_parser_extras.cpp b/src/glsl/glsl_parser_extras.cpp index c0dd713703f..6893c7b82cc 100644 --- a/src/glsl/glsl_parser_extras.cpp +++ b/src/glsl/glsl_parser_extras.cpp @@ -28,9 +28,11 @@ extern "C" { #include "main/core.h" /* for struct gl_context */ #include "main/context.h" +#include "main/shaderobj.h" +#include "util/u_atomic.h" /* for p_atomic_cmpxchg */ } -#include "ralloc.h" +#include "util/ralloc.h" #include "ast.h" #include "glsl_parser_extras.h" #include "glsl_parser.h" @@ -48,32 +50,34 @@ glsl_compute_version_string(void *mem_ctx, bool is_es, unsigned version) } -static unsigned known_desktop_glsl_versions[] = - { 110, 120, 130, 140, 150, 330, 400, 410, 420, 430 }; +static const unsigned known_desktop_glsl_versions[] = + { 110, 120, 130, 140, 150, 330, 400, 410, 420, 430, 440, 450 }; _mesa_glsl_parse_state::_mesa_glsl_parse_state(struct gl_context *_ctx, - GLenum target, void *mem_ctx) - : ctx(_ctx) + gl_shader_stage stage, + void *mem_ctx) + : ctx(_ctx), cs_input_local_size_specified(false), cs_input_local_size(), + switch_state() { - switch (target) { - case GL_VERTEX_SHADER: this->target = vertex_shader; break; - case GL_FRAGMENT_SHADER: this->target = fragment_shader; break; - case GL_GEOMETRY_SHADER: this->target = geometry_shader; break; - } + assert(stage < MESA_SHADER_STAGES); + this->stage = stage; this->scanner = NULL; this->translation_unit.make_empty(); this->symbols = new(mem_ctx) glsl_symbol_table; + this->info_log = ralloc_strdup(mem_ctx, ""); this->error = false; this->loop_nesting_ast = NULL; - this->switch_state.switch_nesting_ast = NULL; - this->num_builtins_to_link = 0; + this->struct_specifier_depth = 0; + + this->uses_builtin_functions = false; /* Set default language version and extensions */ - this->language_version = 110; + this->language_version = ctx->Const.ForceGLSLVersion ? + ctx->Const.ForceGLSLVersion : 110; this->es_shader = false; this->ARB_texture_rectangle_enable = true; @@ -90,18 +94,60 @@ _mesa_glsl_parse_state::_mesa_glsl_parse_state(struct gl_context *_ctx, this->Const.MaxClipPlanes = ctx->Const.MaxClipPlanes; this->Const.MaxTextureUnits = ctx->Const.MaxTextureUnits; this->Const.MaxTextureCoords = ctx->Const.MaxTextureCoordUnits; - this->Const.MaxVertexAttribs = ctx->Const.VertexProgram.MaxAttribs; - this->Const.MaxVertexUniformComponents = ctx->Const.VertexProgram.MaxUniformComponents; - this->Const.MaxVaryingFloats = ctx->Const.MaxVarying * 4; - this->Const.MaxVertexTextureImageUnits = ctx->Const.VertexProgram.MaxTextureImageUnits; + this->Const.MaxVertexAttribs = ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs; + this->Const.MaxVertexUniformComponents = ctx->Const.Program[MESA_SHADER_VERTEX].MaxUniformComponents; + this->Const.MaxVertexTextureImageUnits = ctx->Const.Program[MESA_SHADER_VERTEX].MaxTextureImageUnits; this->Const.MaxCombinedTextureImageUnits = ctx->Const.MaxCombinedTextureImageUnits; - this->Const.MaxTextureImageUnits = ctx->Const.FragmentProgram.MaxTextureImageUnits; - this->Const.MaxFragmentUniformComponents = ctx->Const.FragmentProgram.MaxUniformComponents; + this->Const.MaxTextureImageUnits = ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxTextureImageUnits; + this->Const.MaxFragmentUniformComponents = ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxUniformComponents; this->Const.MinProgramTexelOffset = ctx->Const.MinProgramTexelOffset; this->Const.MaxProgramTexelOffset = ctx->Const.MaxProgramTexelOffset; this->Const.MaxDrawBuffers = ctx->Const.MaxDrawBuffers; + /* 1.50 constants */ + this->Const.MaxVertexOutputComponents = ctx->Const.Program[MESA_SHADER_VERTEX].MaxOutputComponents; + this->Const.MaxGeometryInputComponents = ctx->Const.Program[MESA_SHADER_GEOMETRY].MaxInputComponents; + this->Const.MaxGeometryOutputComponents = ctx->Const.Program[MESA_SHADER_GEOMETRY].MaxOutputComponents; + this->Const.MaxFragmentInputComponents = ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxInputComponents; + this->Const.MaxGeometryTextureImageUnits = ctx->Const.Program[MESA_SHADER_GEOMETRY].MaxTextureImageUnits; + this->Const.MaxGeometryOutputVertices = ctx->Const.MaxGeometryOutputVertices; + this->Const.MaxGeometryTotalOutputComponents = ctx->Const.MaxGeometryTotalOutputComponents; + this->Const.MaxGeometryUniformComponents = ctx->Const.Program[MESA_SHADER_GEOMETRY].MaxUniformComponents; + + this->Const.MaxVertexAtomicCounters = ctx->Const.Program[MESA_SHADER_VERTEX].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; + + /* Compute shader constants */ + for (unsigned i = 0; i < Elements(this->Const.MaxComputeWorkGroupCount); i++) + this->Const.MaxComputeWorkGroupCount[i] = ctx->Const.MaxComputeWorkGroupCount[i]; + for (unsigned i = 0; i < Elements(this->Const.MaxComputeWorkGroupSize); i++) + this->Const.MaxComputeWorkGroupSize[i] = ctx->Const.MaxComputeWorkGroupSize[i]; + + this->Const.MaxImageUnits = ctx->Const.MaxImageUnits; + this->Const.MaxCombinedImageUnitsAndFragmentOutputs = ctx->Const.MaxCombinedImageUnitsAndFragmentOutputs; + this->Const.MaxImageSamples = ctx->Const.MaxImageSamples; + this->Const.MaxVertexImageUniforms = ctx->Const.Program[MESA_SHADER_VERTEX].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; + + 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; + + /* supported_versions should be large enough to support the known desktop + * GLSL versions plus 2 GLES versions (ES2 & ES3) + */ + STATIC_ASSERT((ARRAY_SIZE(known_desktop_glsl_versions) + 2) == + ARRAY_SIZE(this->supported_versions)); + /* Populate the list of supported GLSL versions */ /* FINISHME: Once the OpenGL 3.0 'forward compatible' context or * the OpenGL 3.2 Core context is supported, this logic will need @@ -129,8 +175,6 @@ _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++; } - assert(this->num_supported_versions - <= ARRAY_SIZE(this->supported_versions)); /* Create a string for use in error messages to tell the user which GLSL * versions are supported. @@ -157,6 +201,22 @@ _mesa_glsl_parse_state::_mesa_glsl_parse_state(struct gl_context *_ctx, this->default_uniform_qualifier = new(this) ast_type_qualifier(); this->default_uniform_qualifier->flags.q.shared = 1; this->default_uniform_qualifier->flags.q.column_major = 1; + + this->fs_uses_gl_fragcoord = false; + this->fs_redeclares_gl_fragcoord = false; + this->fs_origin_upper_left = false; + this->fs_pixel_center_integer = false; + this->fs_redeclares_gl_fragcoord_with_no_layout_qualifiers = false; + + this->gs_input_prim_type_specified = false; + 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, + sizeof(this->atomic_counter_offsets)); + this->allow_extension_directive_midshader = + ctx->Const.AllowGLSLExtensionDirectiveMidShader; } /** @@ -203,7 +263,7 @@ _mesa_glsl_parse_state::check_version(unsigned required_glsl_version, requirement_string = ralloc_asprintf(this, " (%s required)", glsl_es_version_string); } - _mesa_glsl_error(locp, this, "%s in %s%s.", + _mesa_glsl_error(locp, this, "%s in %s%s", problem, this->get_version_string(), requirement_string); @@ -226,9 +286,22 @@ _mesa_glsl_parse_state::process_version_directive(YYLTYPE *locp, int version, if (ident) { if (strcmp(ident, "es") == 0) { es_token_present = true; + } else if (version >= 150) { + if (strcmp(ident, "core") == 0) { + /* Accept the token. There's no need to record that this is + * a core profile shader since that's the only profile we support. + */ + } else if (strcmp(ident, "compatibility") == 0) { + _mesa_glsl_error(locp, this, + "the compatibility profile is not supported"); + } else { + _mesa_glsl_error(locp, this, + "\"%s\" is not a valid shading language profile; " + "if present, it must be \"core\"", ident); + } } else { _mesa_glsl_error(locp, this, - "Illegal text following version number\n"); + "illegal text following version number"); } } @@ -237,12 +310,16 @@ _mesa_glsl_parse_state::process_version_directive(YYLTYPE *locp, int version, if (es_token_present) { _mesa_glsl_error(locp, this, "GLSL 1.00 ES should be selected using " - "`#version 100'\n"); + "`#version 100'"); } else { this->es_shader = true; } } + if (this->es_shader) { + this->ARB_texture_rectangle_enable = false; + } + this->language_version = version; bool supported = false; @@ -256,7 +333,7 @@ _mesa_glsl_parse_state::process_version_directive(YYLTYPE *locp, int version, if (!supported) { _mesa_glsl_error(locp, this, "%s is not supported. " - "Supported versions are: %s\n", + "Supported versions are: %s", this->get_version_string(), this->supported_version_string); @@ -279,23 +356,20 @@ _mesa_glsl_parse_state::process_version_directive(YYLTYPE *locp, int version, break; } } - - if (this->language_version >= 140) { - this->ARB_uniform_buffer_object_enable = true; - } - - if (this->language_version == 300 && this->es_shader) { - this->ARB_explicit_attrib_location_enable = true; - } } + +/** + * Translate a gl_shader_stage to a short shader stage name for debug + * printouts and error messages. + */ const char * -_mesa_glsl_shader_target_name(enum _mesa_glsl_parser_targets target) +_mesa_shader_stage_to_string(unsigned stage) { - switch (target) { - case vertex_shader: return "vertex"; - case fragment_shader: return "fragment"; - case geometry_shader: return "geometry"; + switch (stage) { + case MESA_SHADER_VERTEX: return "vertex"; + case MESA_SHADER_FRAGMENT: return "fragment"; + case MESA_SHADER_GEOMETRY: return "geometry"; } assert(!"Should not get here."); @@ -381,15 +455,6 @@ struct _mesa_glsl_extension { */ const char *name; - /** True if this extension is available to vertex shaders */ - bool avail_in_VS; - - /** True if this extension is available to geometry shaders */ - bool avail_in_GS; - - /** True if this extension is available to fragment shaders */ - bool avail_in_FS; - /** True if this extension is available to desktop GL shaders */ bool avail_in_GL; @@ -436,9 +501,9 @@ struct _mesa_glsl_extension { void set_flags(_mesa_glsl_parse_state *state, ext_behavior behavior) const; }; -#define EXT(NAME, VS, GS, FS, GL, ES, SUPPORTED_FLAG) \ - { "GL_" #NAME, VS, GS, FS, GL, ES, &gl_extensions::SUPPORTED_FLAG, \ - &_mesa_glsl_parse_state::NAME##_enable, \ +#define EXT(NAME, GL, ES, SUPPORTED_FLAG) \ + { "GL_" #NAME, GL, ES, &gl_extensions::SUPPORTED_FLAG, \ + &_mesa_glsl_parse_state::NAME##_enable, \ &_mesa_glsl_parse_state::NAME##_warn } /** @@ -446,30 +511,59 @@ struct _mesa_glsl_extension { * and the conditions under which they are supported. */ static const _mesa_glsl_extension _mesa_glsl_supported_extensions[] = { - /* target availability API availability */ - /* name VS GS FS GL ES supported flag */ - EXT(ARB_conservative_depth, false, false, true, true, false, ARB_conservative_depth), - EXT(ARB_draw_buffers, false, false, true, true, false, dummy_true), - EXT(ARB_draw_instanced, true, false, false, true, false, ARB_draw_instanced), - EXT(ARB_explicit_attrib_location, true, false, true, true, false, ARB_explicit_attrib_location), - EXT(ARB_fragment_coord_conventions, true, false, true, true, false, ARB_fragment_coord_conventions), - EXT(ARB_texture_rectangle, true, false, true, true, false, dummy_true), - EXT(EXT_texture_array, true, false, true, true, false, EXT_texture_array), - EXT(ARB_shader_texture_lod, true, false, true, true, false, ARB_shader_texture_lod), - EXT(ARB_shader_stencil_export, false, false, true, true, false, ARB_shader_stencil_export), - EXT(AMD_conservative_depth, false, false, true, true, false, ARB_conservative_depth), - EXT(AMD_shader_stencil_export, false, false, true, true, false, ARB_shader_stencil_export), - EXT(OES_texture_3D, true, false, true, false, true, EXT_texture3D), - EXT(OES_EGL_image_external, true, false, true, false, true, OES_EGL_image_external), - EXT(ARB_shader_bit_encoding, true, true, true, true, false, ARB_shader_bit_encoding), - EXT(ARB_uniform_buffer_object, true, false, true, true, false, ARB_uniform_buffer_object), - EXT(OES_standard_derivatives, false, false, true, false, true, OES_standard_derivatives), - EXT(ARB_texture_cube_map_array, true, false, true, true, false, ARB_texture_cube_map_array), - EXT(ARB_shading_language_packing, true, false, true, true, false, ARB_shading_language_packing), - EXT(ARB_texture_multisample, true, false, true, true, false, ARB_texture_multisample), - EXT(ARB_texture_query_lod, false, false, true, true, false, ARB_texture_query_lod), - EXT(ARB_gpu_shader5, true, true, true, true, false, ARB_gpu_shader5), - EXT(AMD_vertex_shader_layer, true, false, false, true, false, AMD_vertex_shader_layer), + /* API availability */ + /* name GL ES supported flag */ + + /* 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_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_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), + + /* KHR extensions go here, sorted alphabetically. + */ + + /* OES extensions go here, sorted alphabetically. + */ + EXT(OES_EGL_image_external, false, true, OES_EGL_image_external), + EXT(OES_standard_derivatives, false, true, OES_standard_derivatives), + EXT(OES_texture_3D, false, true, EXT_texture3D), + + /* All other extensions go here, sorted alphabetically. + */ + EXT(AMD_conservative_depth, true, false, ARB_conservative_depth), + EXT(AMD_shader_stencil_export, true, false, ARB_shader_stencil_export), + EXT(AMD_shader_trinary_minmax, true, false, dummy_true), + EXT(AMD_vertex_shader_layer, true, false, AMD_vertex_shader_layer), + EXT(AMD_vertex_shader_viewport_index, true, false, AMD_vertex_shader_viewport_index), + EXT(EXT_separate_shader_objects, false, true, dummy_true), + EXT(EXT_shader_integer_mix, true, true, EXT_shader_integer_mix), + EXT(EXT_texture_array, true, false, EXT_texture_array), }; #undef EXT @@ -482,30 +576,6 @@ static const _mesa_glsl_extension _mesa_glsl_supported_extensions[] = { bool _mesa_glsl_extension::compatible_with_state(const _mesa_glsl_parse_state * state) const { - /* Check that this extension matches the type of shader we are - * compiling to. - */ - switch (state->target) { - case vertex_shader: - if (!this->avail_in_VS) { - return false; - } - break; - case geometry_shader: - if (!this->avail_in_GS) { - return false; - } - break; - case fragment_shader: - if (!this->avail_in_FS) { - return false; - } - break; - default: - assert (!"Unrecognized shader target"); - return false; - } - /* Check that this extension matches whether we are compiling * for desktop GL or GLES. */ @@ -571,14 +641,14 @@ _mesa_glsl_process_extension(const char *name, YYLTYPE *name_locp, behavior = extension_disable; } else { _mesa_glsl_error(behavior_locp, state, - "Unknown extension behavior `%s'", + "unknown extension behavior `%s'", behavior_string); return false; } if (strcmp(name, "all") == 0) { if ((behavior == extension_enable) || (behavior == extension_require)) { - _mesa_glsl_error(name_locp, state, "Cannot %s all extensions", + _mesa_glsl_error(name_locp, state, "cannot %s all extensions", (behavior == extension_enable) ? "enable" : "require"); return false; @@ -597,15 +667,15 @@ _mesa_glsl_process_extension(const char *name, YYLTYPE *name_locp, if (extension && extension->compatible_with_state(state)) { extension->set_flags(state, behavior); } else { - static const char *const fmt = "extension `%s' unsupported in %s shader"; + static const char fmt[] = "extension `%s' unsupported in %s shader"; if (behavior == extension_require) { _mesa_glsl_error(name_locp, state, fmt, - name, _mesa_glsl_shader_target_name(state->target)); + name, _mesa_shader_stage_to_string(state->stage)); return false; } else { _mesa_glsl_warning(name_locp, state, fmt, - name, _mesa_glsl_shader_target_name(state->target)); + name, _mesa_shader_stage_to_string(state->stage)); } } } @@ -613,6 +683,106 @@ _mesa_glsl_process_extension(const char *name, YYLTYPE *name_locp, return true; } + +/** + * Recurses through and if is an aggregate initializer + * and sets 's field to . Gives later functions + * (process_array_constructor, et al) sufficient information to do type + * checking. + * + * Operates on assignments involving an aggregate initializer. E.g., + * + * vec4 pos = {1.0, -1.0, 0.0, 1.0}; + * + * or more ridiculously, + * + * struct S { + * vec4 v[2]; + * }; + * + * struct { + * S a[2], b; + * int c; + * } aggregate = { + * { + * { + * { + * {1.0, 2.0, 3.0, 4.0}, // a[0].v[0] + * {5.0, 6.0, 7.0, 8.0} // a[0].v[1] + * } // a[0].v + * }, // a[0] + * { + * { + * {1.0, 2.0, 3.0, 4.0}, // a[1].v[0] + * {5.0, 6.0, 7.0, 8.0} // a[1].v[1] + * } // a[1].v + * } // a[1] + * }, // a + * { + * { + * {1.0, 2.0, 3.0, 4.0}, // b.v[0] + * {5.0, 6.0, 7.0, 8.0} // b.v[1] + * } // b.v + * }, // b + * 4 // c + * }; + * + * This pass is necessary because the right-hand side of e = { ... } + * doesn't contain sufficient information to determine if the types match. + */ +void +_mesa_ast_set_aggregate_type(const glsl_type *type, + ast_expression *expr) +{ + ast_aggregate_initializer *ai = (ast_aggregate_initializer *)expr; + ai->constructor_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(). + * + * E.g., if if struct S[2] we want to set each element's type to + * struct S. + */ + for (exec_node *expr_node = ai->expressions.head; + !expr_node->is_tail_sentinel(); + expr_node = expr_node->next) { + ast_expression *expr = exec_node_data(ast_expression, expr_node, + link); + + if (expr->oper == ast_aggregate) + _mesa_ast_set_aggregate_type(type->element_type(), expr); + } + + /* If the aggregate is a struct, recursively set its fields' types. */ + } else if (type->is_record()) { + exec_node *expr_node = ai->expressions.head; + + /* Iterate through the struct's fields. */ + for (unsigned i = 0; !expr_node->is_tail_sentinel() && i < type->length; + i++, expr_node = expr_node->next) { + ast_expression *expr = exec_node_data(ast_expression, expr_node, + link); + + if (expr->oper == ast_aggregate) { + _mesa_ast_set_aggregate_type(type->fields.structure[i].type, expr); + } + } + /* If the aggregate is a matrix, set its columns' types. */ + } else if (type->is_matrix()) { + for (exec_node *expr_node = ai->expressions.head; + !expr_node->is_tail_sentinel(); + expr_node = expr_node->next) { + ast_expression *expr = exec_node_data(ast_expression, expr_node, + link); + + if (expr->oper == ast_aggregate) + _mesa_ast_set_aggregate_type(type->column_type(), expr); + } + } +} + + void _mesa_ast_type_qualifier_print(const struct ast_type_qualifier *q) { @@ -640,6 +810,8 @@ _mesa_ast_type_qualifier_print(const struct ast_type_qualifier *q) if (q->flags.q.centroid) printf("centroid "); + if (q->flags.q.sample) + printf("sample "); if (q->flags.q.uniform) printf("uniform "); if (q->flags.q.smooth) @@ -661,22 +833,18 @@ ast_node::print(void) const ast_node::ast_node(void) { this->location.source = 0; - this->location.line = 0; - this->location.column = 0; + this->location.first_line = 0; + this->location.first_column = 0; + this->location.last_line = 0; + this->location.last_column = 0; } static void -ast_opt_array_size_print(bool is_array, const ast_expression *array_size) +ast_opt_array_dimensions_print(const ast_array_specifier *array_specifier) { - if (is_array) { - printf("[ "); - - if (array_size) - array_size->print(); - - printf("] "); - } + if (array_specifier) + array_specifier->print(); } @@ -685,8 +853,7 @@ ast_compound_statement::print(void) const { printf("{\n"); - foreach_list_const(n, &this->statements) { - ast_node *ast = exec_node_data(ast_node, n, link); + foreach_list_typed(ast_node, ast, link, &this->statements) { ast->print(); } @@ -765,11 +932,10 @@ ast_expression::print(void) const subexpressions[0]->print(); printf("( "); - foreach_list_const (n, &this->expressions) { - if (n != this->expressions.get_head()) + foreach_list_typed (ast_node, ast, link, &this->expressions) { + if (&ast->link != this->expressions.get_head()) printf(", "); - ast_node *ast = exec_node_data(ast_node, n, link); ast->print(); } @@ -801,17 +967,28 @@ ast_expression::print(void) const case ast_sequence: { printf("( "); - foreach_list_const(n, & this->expressions) { - if (n != this->expressions.get_head()) + foreach_list_typed (ast_node, ast, link, & this->expressions) { + if (&ast->link != this->expressions.get_head()) printf(", "); - ast_node *ast = exec_node_data(ast_node, n, link); ast->print(); } printf(") "); break; } + case ast_aggregate: { + printf("{ "); + foreach_list_typed (ast_node, ast, link, & this->expressions) { + if (&ast->link != this->expressions.get_head()) + printf(", "); + + ast->print(); + } + printf("} "); + break; + } + default: assert(0); break; @@ -821,7 +998,8 @@ ast_expression::print(void) const ast_expression::ast_expression(int oper, ast_expression *ex0, ast_expression *ex1, - ast_expression *ex2) + ast_expression *ex2) : + primary_expression() { this->oper = ast_operators(oper); this->subexpressions[0] = ex0; @@ -854,8 +1032,7 @@ ast_function::print(void) const return_type->print(); printf(" %s (", identifier); - foreach_list_const(n, & this->parameters) { - ast_node *ast = exec_node_data(ast_node, n, link); + foreach_list_typed(ast_node, ast, link, & this->parameters) { ast->print(); } @@ -864,7 +1041,8 @@ ast_function::print(void) const ast_function::ast_function(void) - : is_definition(false), signature(NULL) + : return_type(NULL), identifier(NULL), is_definition(false), + signature(NULL) { /* empty */ } @@ -884,7 +1062,7 @@ ast_parameter_declarator::print(void) const type->print(); if (identifier) printf("%s ", identifier); - ast_opt_array_size_print(is_array, array_size); + ast_opt_array_dimensions_print(array_specifier); } @@ -900,7 +1078,7 @@ void ast_declaration::print(void) const { printf("%s ", identifier); - ast_opt_array_size_print(is_array, array_size); + ast_opt_array_dimensions_print(array_specifier); if (initializer) { printf("= "); @@ -909,13 +1087,12 @@ ast_declaration::print(void) const } -ast_declaration::ast_declaration(const char *identifier, int is_array, - ast_expression *array_size, +ast_declaration::ast_declaration(const char *identifier, + ast_array_specifier *array_specifier, ast_expression *initializer) { this->identifier = identifier; - this->is_array = is_array; - this->array_size = array_size; + this->array_specifier = array_specifier; this->initializer = initializer; } @@ -927,14 +1104,15 @@ ast_declarator_list::print(void) const if (type) type->print(); - else + else if (invariant) printf("invariant "); + else + printf("precise "); - foreach_list_const (ptr, & this->declarations) { - if (ptr != this->declarations.get_head()) + foreach_list_typed (ast_node, ast, link, & this->declarations) { + if (&ast->link != this->declarations.get_head()) printf(", "); - ast_node *ast = exec_node_data(ast_node, ptr, link); ast->print(); } @@ -946,7 +1124,7 @@ ast_declarator_list::ast_declarator_list(ast_fully_specified_type *type) { this->type = type; this->invariant = false; - this->ubo_qualifiers_valid = false; + this->precise = false; } void @@ -974,6 +1152,7 @@ ast_jump_statement::print(void) const ast_jump_statement::ast_jump_statement(int mode, ast_expression *return_value) + : opt_return_value(NULL) { this->mode = ast_jump_modes(mode); @@ -1065,8 +1244,7 @@ ast_case_label::ast_case_label(ast_expression *test_value) void ast_case_label_list::print(void) const { - foreach_list_const(n, & this->labels) { - ast_node *ast = exec_node_data(ast_node, n, link); + foreach_list_typed(ast_node, ast, link, & this->labels) { ast->print(); } printf("\n"); @@ -1081,8 +1259,7 @@ ast_case_label_list::ast_case_label_list(void) void ast_case_statement::print(void) const { labels->print(); - foreach_list_const(n, & this->stmts) { - ast_node *ast = exec_node_data(ast_node, n, link); + foreach_list_typed(ast_node, ast, link, & this->stmts) { ast->print(); printf("\n"); } @@ -1097,8 +1274,7 @@ ast_case_statement::ast_case_statement(ast_case_label_list *labels) void ast_case_statement_list::print(void) const { - foreach_list_const(n, & this->cases) { - ast_node *ast = exec_node_data(ast_node, n, link); + foreach_list_typed(ast_node, ast, link, & this->cases) { ast->print(); } } @@ -1168,8 +1344,7 @@ void ast_struct_specifier::print(void) const { printf("struct %s { ", name); - foreach_list_const(n, &this->declarations) { - ast_node *ast = exec_node_data(ast_node, n, link); + foreach_list_typed(ast_node, ast, link, &this->declarations) { ast->print(); } printf("} "); @@ -1180,14 +1355,219 @@ ast_struct_specifier::ast_struct_specifier(const char *identifier, ast_declarator_list *declarator_list) { if (identifier == NULL) { + static mtx_t mutex = _MTX_INITIALIZER_NP; static unsigned anon_count = 1; - identifier = ralloc_asprintf(this, "#anon_struct_%04x", anon_count); - anon_count++; + unsigned count; + + mtx_lock(&mutex); + count = anon_count++; + mtx_unlock(&mutex); + + identifier = ralloc_asprintf(this, "#anon_struct_%04x", count); } name = identifier; this->declarations.push_degenerate_list_at_head(&declarator_list->link); + is_declaration = true; } +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. */ + assert(!state->in_qualifier->flags.i); + assert(!state->out_qualifier->flags.i); + } + + if (shader->Stage != MESA_SHADER_COMPUTE) { + /* Should have been prevented by the parser. */ + assert(!state->cs_input_local_size_specified); + } + + if (shader->Stage != MESA_SHADER_FRAGMENT) { + /* Should have been prevented by the parser. */ + assert(!state->fs_uses_gl_fragcoord); + assert(!state->fs_redeclares_gl_fragcoord); + assert(!state->fs_pixel_center_integer); + assert(!state->fs_origin_upper_left); + } + + switch (shader->Stage) { + case MESA_SHADER_GEOMETRY: + shader->Geom.VerticesOut = 0; + if (state->out_qualifier->flags.q.max_vertices) + shader->Geom.VerticesOut = state->out_qualifier->max_vertices; + + if (state->gs_input_prim_type_specified) { + shader->Geom.InputType = state->in_qualifier->prim_type; + } else { + shader->Geom.InputType = PRIM_UNKNOWN; + } + + if (state->out_qualifier->flags.q.prim_type) { + shader->Geom.OutputType = state->out_qualifier->prim_type; + } else { + shader->Geom.OutputType = PRIM_UNKNOWN; + } + + shader->Geom.Invocations = 0; + if (state->in_qualifier->flags.q.invocations) + shader->Geom.Invocations = state->in_qualifier->invocations; + break; + + case MESA_SHADER_COMPUTE: + if (state->cs_input_local_size_specified) { + for (int i = 0; i < 3; i++) + shader->Comp.LocalSize[i] = state->cs_input_local_size[i]; + } else { + for (int i = 0; i < 3; i++) + shader->Comp.LocalSize[i] = 0; + } + break; + + case MESA_SHADER_FRAGMENT: + shader->redeclares_gl_fragcoord = state->fs_redeclares_gl_fragcoord; + shader->uses_gl_fragcoord = state->fs_uses_gl_fragcoord; + shader->pixel_center_integer = state->fs_pixel_center_integer; + shader->origin_upper_left = state->fs_origin_upper_left; + shader->ARB_fragment_coord_conventions_enable = + state->ARB_fragment_coord_conventions_enable; + break; + + default: + /* Nothing to do. */ + break; + } +} + +extern "C" { + +void +_mesa_glsl_compile_shader(struct gl_context *ctx, struct gl_shader *shader, + bool dump_ast, bool dump_hir) +{ + struct _mesa_glsl_parse_state *state = + new(shader) _mesa_glsl_parse_state(ctx, shader->Stage, shader); + const char *source = shader->Source; + + if (ctx->Const.GenerateTemporaryNames) + (void) p_atomic_cmpxchg(&ir_variable::temporaries_allocate_names, + false, true); + + state->error = glcpp_preprocess(state, &source, &state->info_log, + &ctx->Extensions, ctx); + + if (!state->error) { + _mesa_glsl_lexer_ctor(state, source); + _mesa_glsl_parse(state); + _mesa_glsl_lexer_dtor(state); + } + + if (dump_ast) { + foreach_list_typed(ast_node, ast, link, &state->translation_unit) { + ast->print(); + } + printf("\n\n"); + } + + ralloc_free(shader->ir); + shader->ir = new(shader) exec_list; + if (!state->error && !state->translation_unit.is_empty()) + _mesa_ast_to_hir(shader->ir, state); + + if (!state->error) { + validate_ir_tree(shader->ir); + + /* Print out the unoptimized IR. */ + if (dump_hir) { + _mesa_print_ir(stdout, shader->ir, state); + } + } + + + if (!state->error && !shader->ir->is_empty()) { + struct gl_shader_compiler_options *options = + &ctx->Const.ShaderCompilerOptions[shader->Stage]; + + /* Do some optimization at compile time to reduce shader IR size + * and reduce later work if the same shader is linked multiple times + */ + while (do_common_optimization(shader->ir, false, false, options, + ctx->Const.NativeIntegers)) + ; + + validate_ir_tree(shader->ir); + + enum ir_variable_mode other; + switch (shader->Stage) { + case MESA_SHADER_VERTEX: + other = ir_var_shader_in; + break; + case MESA_SHADER_FRAGMENT: + other = ir_var_shader_out; + break; + default: + /* Something invalid to ensure optimize_dead_builtin_uniforms + * doesn't remove anything other than uniforms or constants. + */ + other = ir_var_mode_count; + break; + } + + optimize_dead_builtin_variables(shader->ir, other); + + validate_ir_tree(shader->ir); + } + + if (shader->InfoLog) + ralloc_free(shader->InfoLog); + + shader->symbols = new(shader->ir) glsl_symbol_table; + shader->CompileStatus = !state->error; + shader->InfoLog = state->info_log; + shader->Version = state->language_version; + shader->IsES = state->es_shader; + shader->uses_builtin_functions = state->uses_builtin_functions; + + if (!state->error) + set_shader_inout_layout(shader, state); + + /* Retain any live IR, but trash the rest. */ + reparent_ir(shader->ir, shader->ir); + + /* Destroy the symbol table. Create a new symbol table that contains only + * the variables and functions that still exist in the IR. The symbol + * table will be used later during linking. + * + * There must NOT be any freed objects still referenced by the symbol + * table. That could cause the linker to dereference freed memory. + * + * We don't have to worry about types or interface-types here because those + * are fly-weights that are looked up by glsl_type. + */ + foreach_in_list (ir_instruction, ir, shader->ir) { + switch (ir->ir_type) { + case ir_type_function: + shader->symbols->add_function((ir_function *) ir); + break; + case ir_type_variable: { + ir_variable *const var = (ir_variable *) ir; + + if (var->data.mode != ir_var_temporary) + shader->symbols->add_variable(var); + break; + } + default: + break; + } + } + + delete state->symbols; + ralloc_free(state); +} + +} /* extern "C" */ /** * Do the set of common optimizations passes * @@ -1209,8 +1589,8 @@ ast_struct_specifier::ast_struct_specifier(const char *identifier, bool do_common_optimization(exec_list *ir, bool linked, bool uniform_locations_assigned, - unsigned max_unroll_iterations, - const struct gl_shader_compiler_options *options) + const struct gl_shader_compiler_options *options, + bool native_integers) { GLboolean progress = GL_FALSE; @@ -1226,9 +1606,13 @@ do_common_optimization(exec_list *ir, bool linked, progress = do_copy_propagation(ir) || progress; progress = do_copy_propagation_elements(ir) || progress; - if (options->PreferDP4 && !linked) + if (options->OptimizeForAOS && !linked) progress = opt_flip_matrices(ir) || progress; + if (linked && options->OptimizeForAOS) { + progress = do_vectorize(ir) || progress; + } + if (linked) progress = do_dead_code(ir, uniform_locations_assigned) || progress; else @@ -1241,7 +1625,10 @@ do_common_optimization(exec_list *ir, bool linked, else progress = do_constant_variable_unlinked(ir) || progress; progress = do_constant_folding(ir) || progress; - progress = do_algebraic(ir) || progress; + progress = do_minmax_prune(ir) || progress; + progress = do_cse(ir) || progress; + progress = do_rebalance_tree(ir) || progress; + progress = do_algebraic(ir, native_integers, options) || progress; progress = do_lower_jumps(ir) || progress; progress = do_vec_index_to_swizzle(ir) || progress; progress = lower_vector_insert(ir, false) || progress; @@ -1254,7 +1641,7 @@ do_common_optimization(exec_list *ir, bool linked, loop_state *ls = analyze_loop_variables(ir); if (ls->loop_found) { progress = set_loop_controls(ir, ls) || progress; - progress = unroll_loops(ir, ls, max_unroll_iterations) || progress; + progress = unroll_loops(ir, ls, options) || progress; } delete ls; @@ -1286,7 +1673,7 @@ _mesa_destroy_shader_compiler(void) void _mesa_destroy_shader_compiler_caches(void) { - _mesa_glsl_release_functions(); + _mesa_glsl_release_builtin_functions(); } }