X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;ds=sidebyside;f=src%2Fcompiler%2Fglsl%2Fglsl_parser_extras.cpp;h=59821732b989ee1a173209ffeb9c5d3f5d3abdc3;hb=992aabf2393f22969a3333a3f680384f752ffd1b;hp=f020e8002af6ea3aba403ad11a556ec9ad0b1bb9;hpb=61ceb36ead2e88cce4b4bac63793e94d343a3cc4;p=mesa.git diff --git a/src/compiler/glsl/glsl_parser_extras.cpp b/src/compiler/glsl/glsl_parser_extras.cpp index f020e8002af..59821732b98 100644 --- a/src/compiler/glsl/glsl_parser_extras.cpp +++ b/src/compiler/glsl/glsl_parser_extras.cpp @@ -20,6 +20,7 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ +#include /* for PRIx64 macro */ #include #include #include @@ -28,14 +29,18 @@ #include "main/core.h" /* for struct gl_context */ #include "main/context.h" #include "main/debug_output.h" +#include "main/formats.h" #include "main/shaderobj.h" #include "util/u_atomic.h" /* for p_atomic_cmpxchg */ #include "util/ralloc.h" +#include "util/disk_cache.h" +#include "util/mesa-sha1.h" #include "ast.h" #include "glsl_parser_extras.h" #include "glsl_parser.h" #include "ir_optimization.h" #include "loop_analysis.h" +#include "builtin_functions.h" /** * Format a short human-readable description of the given GLSL version. @@ -49,7 +54,9 @@ glsl_compute_version_string(void *mem_ctx, bool is_es, unsigned version) static const unsigned known_desktop_glsl_versions[] = - { 110, 120, 130, 140, 150, 330, 400, 410, 420, 430, 440, 450 }; + { 110, 120, 130, 140, 150, 330, 400, 410, 420, 430, 440, 450, 460 }; +static const unsigned known_desktop_gl_versions[] = + { 20, 21, 30, 31, 32, 33, 40, 41, 42, 43, 44, 45, 46 }; _mesa_glsl_parse_state::_mesa_glsl_parse_state(struct gl_context *_ctx, @@ -65,6 +72,8 @@ _mesa_glsl_parse_state::_mesa_glsl_parse_state(struct gl_context *_ctx, this->translation_unit.make_empty(); this->symbols = new(mem_ctx) glsl_symbol_table; + this->linalloc = linear_alloc_parent(this, 0); + this->info_log = ralloc_strdup(mem_ctx, ""); this->error = false; this->loop_nesting_ast = NULL; @@ -74,6 +83,9 @@ _mesa_glsl_parse_state::_mesa_glsl_parse_state(struct gl_context *_ctx, /* Set default language version and extensions */ this->language_version = 110; this->forced_language_version = ctx->Const.ForceGLSLVersion; + this->zero_init = ctx->Const.GLSLZeroInit; + this->gl_version = 20; + this->compat_shader = true; this->es_shader = false; this->ARB_texture_rectangle_enable = true; @@ -118,6 +130,7 @@ _mesa_glsl_parse_state::_mesa_glsl_parse_state(struct gl_context *_ctx, 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.MaxComputeAtomicCounters = ctx->Const.Program[MESA_SHADER_COMPUTE].MaxAtomicCounters; this->Const.MaxCombinedAtomicCounters = ctx->Const.MaxCombinedAtomicCounters; this->Const.MaxAtomicBufferBindings = ctx->Const.MaxAtomicBufferBindings; this->Const.MaxVertexAtomicCounterBuffers = @@ -130,17 +143,26 @@ _mesa_glsl_parse_state::_mesa_glsl_parse_state(struct gl_context *_ctx, ctx->Const.Program[MESA_SHADER_GEOMETRY].MaxAtomicBuffers; this->Const.MaxFragmentAtomicCounterBuffers = ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxAtomicBuffers; + this->Const.MaxComputeAtomicCounterBuffers = + ctx->Const.Program[MESA_SHADER_COMPUTE].MaxAtomicBuffers; this->Const.MaxCombinedAtomicCounterBuffers = ctx->Const.MaxCombinedAtomicBuffers; this->Const.MaxAtomicCounterBufferSize = ctx->Const.MaxAtomicBufferSize; + /* ARB_enhanced_layouts constants */ + this->Const.MaxTransformFeedbackBuffers = ctx->Const.MaxTransformFeedbackBuffers; + this->Const.MaxTransformFeedbackInterleavedComponents = ctx->Const.MaxTransformFeedbackInterleavedComponents; + /* Compute shader constants */ for (unsigned i = 0; i < ARRAY_SIZE(this->Const.MaxComputeWorkGroupCount); i++) this->Const.MaxComputeWorkGroupCount[i] = ctx->Const.MaxComputeWorkGroupCount[i]; for (unsigned i = 0; i < ARRAY_SIZE(this->Const.MaxComputeWorkGroupSize); i++) this->Const.MaxComputeWorkGroupSize[i] = ctx->Const.MaxComputeWorkGroupSize[i]; + this->Const.MaxComputeTextureImageUnits = ctx->Const.Program[MESA_SHADER_COMPUTE].MaxTextureImageUnits; + this->Const.MaxComputeUniformComponents = ctx->Const.Program[MESA_SHADER_COMPUTE].MaxUniformComponents; + this->Const.MaxImageUnits = ctx->Const.MaxImageUnits; this->Const.MaxCombinedShaderOutputResources = ctx->Const.MaxCombinedShaderOutputResources; this->Const.MaxImageSamples = ctx->Const.MaxImageSamples; @@ -149,6 +171,7 @@ _mesa_glsl_parse_state::_mesa_glsl_parse_state(struct gl_context *_ctx, 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.MaxComputeImageUniforms = ctx->Const.Program[MESA_SHADER_COMPUTE].MaxImageUniforms; this->Const.MaxCombinedImageUniforms = ctx->Const.MaxCombinedImageUniforms; /* ARB_viewport_array */ @@ -168,6 +191,9 @@ _mesa_glsl_parse_state::_mesa_glsl_parse_state(struct gl_context *_ctx, this->Const.MaxTessControlUniformComponents = ctx->Const.Program[MESA_SHADER_TESS_CTRL].MaxUniformComponents; this->Const.MaxTessEvaluationUniformComponents = ctx->Const.Program[MESA_SHADER_TESS_EVAL].MaxUniformComponents; + /* GL 4.5 / OES_sample_variables */ + this->Const.MaxSamples = ctx->Const.MaxSamples; + this->current_function = NULL; this->toplevel_ir = NULL; this->found_return = false; @@ -180,9 +206,9 @@ _mesa_glsl_parse_state::_mesa_glsl_parse_state(struct gl_context *_ctx, this->subroutine_types = NULL; /* supported_versions should be large enough to support the known desktop - * GLSL versions plus 3 GLES versions (ES 1.00, ES 3.00, and ES 3.10)) + * GLSL versions plus 4 GLES versions (ES 1.00, ES 3.00, ES 3.10, ES 3.20) */ - STATIC_ASSERT((ARRAY_SIZE(known_desktop_glsl_versions) + 3) == + STATIC_ASSERT((ARRAY_SIZE(known_desktop_glsl_versions) + 4) == ARRAY_SIZE(this->supported_versions)); /* Populate the list of supported GLSL versions */ @@ -197,6 +223,8 @@ _mesa_glsl_parse_state::_mesa_glsl_parse_state(struct gl_context *_ctx, if (known_desktop_glsl_versions[i] <= ctx->Const.GLSLVersion) { this->supported_versions[this->num_supported_versions].ver = known_desktop_glsl_versions[i]; + this->supported_versions[this->num_supported_versions].gl_ver + = known_desktop_gl_versions[i]; this->supported_versions[this->num_supported_versions].es = false; this->num_supported_versions++; } @@ -204,16 +232,26 @@ _mesa_glsl_parse_state::_mesa_glsl_parse_state(struct gl_context *_ctx, } if (ctx->API == API_OPENGLES2 || ctx->Extensions.ARB_ES2_compatibility) { this->supported_versions[this->num_supported_versions].ver = 100; + this->supported_versions[this->num_supported_versions].gl_ver = 20; this->supported_versions[this->num_supported_versions].es = true; this->num_supported_versions++; } if (_mesa_is_gles3(ctx) || ctx->Extensions.ARB_ES3_compatibility) { this->supported_versions[this->num_supported_versions].ver = 300; + this->supported_versions[this->num_supported_versions].gl_ver = 30; this->supported_versions[this->num_supported_versions].es = true; this->num_supported_versions++; } - if (_mesa_is_gles31(ctx)) { + if (_mesa_is_gles31(ctx) || ctx->Extensions.ARB_ES3_1_compatibility) { this->supported_versions[this->num_supported_versions].ver = 310; + this->supported_versions[this->num_supported_versions].gl_ver = 31; + this->supported_versions[this->num_supported_versions].es = true; + this->num_supported_versions++; + } + if ((ctx->API == API_OPENGLES2 && ctx->Version >= 32) || + ctx->Extensions.ARB_ES3_2_compatibility) { + this->supported_versions[this->num_supported_versions].ver = 320; + this->supported_versions[this->num_supported_versions].gl_ver = 32; this->supported_versions[this->num_supported_versions].es = true; this->num_supported_versions++; } @@ -243,12 +281,10 @@ _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->default_uniform_qualifier->is_default_qualifier = true; this->default_shader_storage_qualifier = new(this) ast_type_qualifier(); this->default_shader_storage_qualifier->flags.q.shared = 1; this->default_shader_storage_qualifier->flags.q.column_major = 1; - this->default_shader_storage_qualifier->is_default_qualifier = true; this->fs_uses_gl_fragcoord = false; this->fs_redeclares_gl_fragcoord = false; @@ -262,10 +298,23 @@ _mesa_glsl_parse_state::_mesa_glsl_parse_state(struct gl_context *_ctx, this->in_qualifier = new(this) ast_type_qualifier(); this->out_qualifier = new(this) ast_type_qualifier(); this->fs_early_fragment_tests = false; + this->fs_inner_coverage = false; + this->fs_post_depth_coverage = false; + this->fs_blend_support = 0; memset(this->atomic_counter_offsets, 0, sizeof(this->atomic_counter_offsets)); this->allow_extension_directive_midshader = ctx->Const.AllowGLSLExtensionDirectiveMidShader; + this->allow_builtin_variable_redeclaration = + ctx->Const.AllowGLSLBuiltinVariableRedeclaration; + + this->cs_input_local_size_variable_specified = false; + + /* ARB_bindless_texture */ + this->bindless_sampler_specified = false; + this->bindless_image_specified = false; + this->bound_sampler_specified = false; + this->bound_image_specified = false; } /** @@ -332,6 +381,7 @@ _mesa_glsl_parse_state::process_version_directive(YYLTYPE *locp, int version, const char *ident) { bool es_token_present = false; + bool compat_token_present = false; if (ident) { if (strcmp(ident, "es") == 0) { es_token_present = true; @@ -341,8 +391,12 @@ _mesa_glsl_parse_state::process_version_directive(YYLTYPE *locp, int version, * 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"); + compat_token_present = true; + + if (this->ctx->API != API_OPENGL_COMPAT) { + _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; " @@ -374,10 +428,14 @@ _mesa_glsl_parse_state::process_version_directive(YYLTYPE *locp, int version, else this->language_version = version; + this->compat_shader = compat_token_present || + (!this->es_shader && this->language_version < 140); + bool supported = false; for (unsigned i = 0; i < this->num_supported_versions; i++) { if (this->supported_versions[i].ver == this->language_version && this->supported_versions[i].es == this->es_shader) { + this->gl_version = this->supported_versions[i].gl_ver; supported = true; break; } @@ -490,28 +548,17 @@ struct _mesa_glsl_extension { */ const char *name; - /** True if this extension is available to desktop GL shaders */ - bool avail_in_GL; - - /** True if this extension is available to GLES shaders */ - bool avail_in_ES; + /** + * Whether this extension is a part of AEP + */ + bool aep; /** - * Flag in the gl_extensions struct indicating whether this - * extension is supported by the driver, or - * &gl_extensions::dummy_true if supported by all drivers. - * - * Note: the type (GLboolean gl_extensions::*) is a "pointer to - * member" type, the type-safe alternative to the "offsetof" macro. - * In a nutshell: - * - * - foo bar::* p declares p to be an "offset" to a field of type - * foo that exists within struct bar - * - &bar::baz computes the "offset" of field baz within struct bar - * - x.*p accesses the field of x that exists at "offset" p - * - x->*p is equivalent to (*x).*p + * Predicate that checks whether the relevant extension is available for + * this context. */ - const GLboolean gl_extensions::* supported_flag; + bool (*available_pred)(const struct gl_context *, + gl_api api, uint8_t version); /** * Flag in the _mesa_glsl_parse_state struct that should be set @@ -532,90 +579,143 @@ struct _mesa_glsl_extension { bool _mesa_glsl_parse_state::* warn_flag; - bool compatible_with_state(const _mesa_glsl_parse_state *state) const; + bool compatible_with_state(const _mesa_glsl_parse_state *state, + gl_api api, uint8_t gl_version) const; void set_flags(_mesa_glsl_parse_state *state, ext_behavior behavior) const; }; -#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 } +/** Checks if the context supports a user-facing extension */ +#define EXT(name_str, driver_cap, ...) \ +static MAYBE_UNUSED bool \ +has_##name_str(const struct gl_context *ctx, gl_api api, uint8_t version) \ +{ \ + return ctx->Extensions.driver_cap && (version >= \ + _mesa_extension_table[MESA_EXTENSION_##name_str].version[api]); \ +} +#include "main/extensions_table.h" +#undef EXT + +#define EXT(NAME) \ + { "GL_" #NAME, false, has_##NAME, \ + &_mesa_glsl_parse_state::NAME##_enable, \ + &_mesa_glsl_parse_state::NAME##_warn } + +#define EXT_AEP(NAME) \ + { "GL_" #NAME, true, has_##NAME, \ + &_mesa_glsl_parse_state::NAME##_enable, \ + &_mesa_glsl_parse_state::NAME##_warn } /** * Table of extensions that can be enabled/disabled within a shader, * and the conditions under which they are supported. */ static const _mesa_glsl_extension _mesa_glsl_supported_extensions[] = { - /* 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_enhanced_layouts, true, false, ARB_enhanced_layouts), - 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_clock, true, false, ARB_shader_clock), - EXT(ARB_shader_draw_parameters, true, false, ARB_shader_draw_parameters), - EXT(ARB_shader_image_load_store, true, false, ARB_shader_image_load_store), - EXT(ARB_shader_image_size, true, false, ARB_shader_image_size), - 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, true, ARB_shader_storage_buffer_object), - EXT(ARB_shader_subroutine, true, false, ARB_shader_subroutine), - EXT(ARB_shader_texture_image_samples, true, false, ARB_shader_texture_image_samples), - 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), + EXT(ARB_ES3_1_compatibility), + EXT(ARB_ES3_2_compatibility), + EXT(ARB_arrays_of_arrays), + EXT(ARB_bindless_texture), + EXT(ARB_compute_shader), + EXT(ARB_compute_variable_group_size), + EXT(ARB_conservative_depth), + EXT(ARB_cull_distance), + EXT(ARB_derivative_control), + EXT(ARB_draw_buffers), + EXT(ARB_draw_instanced), + EXT(ARB_enhanced_layouts), + EXT(ARB_explicit_attrib_location), + EXT(ARB_explicit_uniform_location), + EXT(ARB_fragment_coord_conventions), + EXT(ARB_fragment_layer_viewport), + EXT(ARB_gpu_shader5), + EXT(ARB_gpu_shader_fp64), + EXT(ARB_gpu_shader_int64), + EXT(ARB_post_depth_coverage), + EXT(ARB_sample_shading), + EXT(ARB_separate_shader_objects), + EXT(ARB_shader_atomic_counter_ops), + EXT(ARB_shader_atomic_counters), + EXT(ARB_shader_ballot), + EXT(ARB_shader_bit_encoding), + EXT(ARB_shader_clock), + EXT(ARB_shader_draw_parameters), + EXT(ARB_shader_group_vote), + EXT(ARB_shader_image_load_store), + EXT(ARB_shader_image_size), + EXT(ARB_shader_precision), + EXT(ARB_shader_stencil_export), + EXT(ARB_shader_storage_buffer_object), + EXT(ARB_shader_subroutine), + EXT(ARB_shader_texture_image_samples), + EXT(ARB_shader_texture_lod), + EXT(ARB_shader_viewport_layer_array), + EXT(ARB_shading_language_420pack), + EXT(ARB_shading_language_packing), + EXT(ARB_tessellation_shader), + EXT(ARB_texture_cube_map_array), + EXT(ARB_texture_gather), + EXT(ARB_texture_multisample), + EXT(ARB_texture_query_levels), + EXT(ARB_texture_query_lod), + EXT(ARB_texture_rectangle), + EXT(ARB_uniform_buffer_object), + EXT(ARB_vertex_attrib_64bit), + EXT(ARB_viewport_array), /* KHR extensions go here, sorted alphabetically. */ + EXT_AEP(KHR_blend_equation_advanced), /* OES extensions go here, sorted alphabetically. */ - EXT(OES_EGL_image_external, false, true, OES_EGL_image_external), - EXT(OES_geometry_point_size, false, true, OES_geometry_shader), - EXT(OES_geometry_shader, false, true, OES_geometry_shader), - EXT(OES_standard_derivatives, false, true, OES_standard_derivatives), - EXT(OES_texture_3D, false, true, dummy_true), - EXT(OES_texture_storage_multisample_2d_array, false, true, ARB_texture_multisample), + EXT(OES_EGL_image_external), + EXT(OES_geometry_point_size), + EXT(OES_geometry_shader), + EXT(OES_gpu_shader5), + EXT(OES_primitive_bounding_box), + EXT_AEP(OES_sample_variables), + EXT_AEP(OES_shader_image_atomic), + EXT(OES_shader_io_blocks), + EXT_AEP(OES_shader_multisample_interpolation), + EXT(OES_standard_derivatives), + EXT(OES_tessellation_point_size), + EXT(OES_tessellation_shader), + EXT(OES_texture_3D), + EXT(OES_texture_buffer), + EXT(OES_texture_cube_map_array), + EXT_AEP(OES_texture_storage_multisample_2d_array), + EXT(OES_viewport_array), /* 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_blend_func_extended, false, true, ARB_blend_func_extended), - EXT(EXT_draw_buffers, false, true, dummy_true), - EXT(EXT_separate_shader_objects, false, true, dummy_true), - EXT(EXT_shader_integer_mix, true, true, EXT_shader_integer_mix), - EXT(EXT_shader_samples_identical, true, true, EXT_shader_samples_identical), - EXT(EXT_texture_array, true, false, EXT_texture_array), + EXT(AMD_conservative_depth), + EXT(AMD_shader_stencil_export), + EXT(AMD_shader_trinary_minmax), + EXT(AMD_vertex_shader_layer), + EXT(AMD_vertex_shader_viewport_index), + EXT(ANDROID_extension_pack_es31a), + EXT(EXT_blend_func_extended), + EXT(EXT_frag_depth), + EXT(EXT_draw_buffers), + EXT(EXT_clip_cull_distance), + EXT(EXT_geometry_point_size), + EXT_AEP(EXT_geometry_shader), + EXT_AEP(EXT_gpu_shader5), + EXT_AEP(EXT_primitive_bounding_box), + EXT(EXT_separate_shader_objects), + EXT(EXT_shader_framebuffer_fetch), + EXT(EXT_shader_integer_mix), + EXT_AEP(EXT_shader_io_blocks), + EXT(EXT_shader_samples_identical), + EXT(EXT_tessellation_point_size), + EXT_AEP(EXT_tessellation_shader), + EXT(EXT_texture_array), + EXT_AEP(EXT_texture_buffer), + EXT_AEP(EXT_texture_cube_map_array), + EXT(INTEL_conservative_rasterization), + EXT(MESA_shader_integer_functions), + EXT(NV_image_formats), }; #undef EXT @@ -625,26 +725,10 @@ static const _mesa_glsl_extension _mesa_glsl_supported_extensions[] = { * Determine whether a given extension is compatible with the target, * API, and extension information in the current parser state. */ -bool _mesa_glsl_extension::compatible_with_state(const _mesa_glsl_parse_state * - state) const +bool _mesa_glsl_extension::compatible_with_state( + const _mesa_glsl_parse_state *state, gl_api api, uint8_t gl_version) const { - /* Check that this extension matches whether we are compiling - * for desktop GL or GLES. - */ - if (state->es_shader) { - if (!this->avail_in_ES) return false; - } else { - if (!this->avail_in_GL) return false; - } - - /* Check that this extension is supported by the OpenGL - * implementation. - * - * Note: the ->* operator indexes into state->extensions by the - * offset this->supported_flag. See - * _mesa_glsl_extension::supported_flag for more info. - */ - return state->extensions->*(this->supported_flag); + return this->available_pred(state->ctx, api, gl_version); } /** @@ -676,12 +760,13 @@ static const _mesa_glsl_extension *find_extension(const char *name) return NULL; } - bool _mesa_glsl_process_extension(const char *name, YYLTYPE *name_locp, const char *behavior_string, YYLTYPE *behavior_locp, _mesa_glsl_parse_state *state) { + uint8_t gl_version = state->ctx->Extensions.Version; + gl_api api = state->ctx->API; ext_behavior behavior; if (strcmp(behavior_string, "warn") == 0) { behavior = extension_warn; @@ -698,6 +783,17 @@ _mesa_glsl_process_extension(const char *name, YYLTYPE *name_locp, return false; } + /* If we're in a desktop context but with an ES shader, use an ES API enum + * to verify extension availability. + */ + if (state->es_shader && api != API_OPENGLES2) + api = API_OPENGLES2; + /* Use the language-version derived GL version to extension checks, unless + * we're using meta, which sets the version to the max. + */ + if (gl_version != 0xff) + gl_version = state->gl_version; + if (strcmp(name, "all") == 0) { if ((behavior == extension_enable) || (behavior == extension_require)) { _mesa_glsl_error(name_locp, state, "cannot %s all extensions", @@ -709,15 +805,31 @@ _mesa_glsl_process_extension(const char *name, YYLTYPE *name_locp, i < ARRAY_SIZE(_mesa_glsl_supported_extensions); ++i) { const _mesa_glsl_extension *extension = &_mesa_glsl_supported_extensions[i]; - if (extension->compatible_with_state(state)) { + if (extension->compatible_with_state(state, api, gl_version)) { _mesa_glsl_supported_extensions[i].set_flags(state, behavior); } } } } else { const _mesa_glsl_extension *extension = find_extension(name); - if (extension && extension->compatible_with_state(state)) { + if (extension && extension->compatible_with_state(state, api, gl_version)) { extension->set_flags(state, behavior); + if (extension->available_pred == has_ANDROID_extension_pack_es31a) { + for (unsigned i = 0; + i < ARRAY_SIZE(_mesa_glsl_supported_extensions); ++i) { + const _mesa_glsl_extension *extension = + &_mesa_glsl_supported_extensions[i]; + + if (!extension->aep) + continue; + /* AEP should not be enabled if all of the sub-extensions can't + * also be enabled. This is not the proper layer to do such + * error-checking though. + */ + assert(extension->compatible_with_state(state, api, gl_version)); + extension->set_flags(state, behavior); + } + } } else { static const char fmt[] = "extension `%s' unsupported in %s shader"; @@ -796,7 +908,7 @@ _mesa_ast_set_aggregate_type(const glsl_type *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; + for (exec_node *expr_node = ai->expressions.get_head_raw(); !expr_node->is_tail_sentinel(); expr_node = expr_node->next) { ast_expression *expr = exec_node_data(ast_expression, expr_node, @@ -808,7 +920,7 @@ _mesa_ast_set_aggregate_type(const glsl_type *type, /* If the aggregate is a struct, recursively set its fields' types. */ } else if (type->is_record()) { - exec_node *expr_node = ai->expressions.head; + exec_node *expr_node = ai->expressions.get_head_raw(); /* Iterate through the struct's fields. */ for (unsigned i = 0; !expr_node->is_tail_sentinel() && i < type->length; @@ -822,7 +934,7 @@ _mesa_ast_set_aggregate_type(const glsl_type *type, } /* If the aggregate is a matrix, set its columns' types. */ } else if (type->is_matrix()) { - for (exec_node *expr_node = ai->expressions.head; + for (exec_node *expr_node = ai->expressions.get_head_raw(); !expr_node->is_tail_sentinel(); expr_node = expr_node->next) { ast_expression *expr = exec_node_data(ast_expression, expr_node, @@ -861,10 +973,16 @@ _mesa_ast_process_interface_block(YYLTYPE *locp, "required for defining uniform blocks"); } } else { - if (state->es_shader || state->language_version < 150) { - _mesa_glsl_error(locp, state, - "#version 150 required for using " - "interface blocks"); + if (!state->has_shader_io_blocks()) { + if (state->es_shader) { + _mesa_glsl_error(locp, state, + "GL_OES_shader_io_blocks or #version 320 " + "required for using interface blocks"); + } else { + _mesa_glsl_error(locp, state, + "#version 150 required for using " + "interface blocks"); + } } } @@ -903,6 +1021,7 @@ _mesa_ast_process_interface_block(YYLTYPE *locp, temp_type_qualifier.flags.q.in = true; temp_type_qualifier.flags.q.out = true; temp_type_qualifier.flags.q.buffer = true; + temp_type_qualifier.flags.q.patch = true; interface_type_mask = temp_type_qualifier.flags.i; /* Get the block's interface qualifier. The interface_qualifier @@ -911,14 +1030,22 @@ _mesa_ast_process_interface_block(YYLTYPE *locp, */ uint64_t block_interface_qualifier = q.flags.i; - block->layout.flags.i |= block_interface_qualifier; + block->default_layout.flags.i |= block_interface_qualifier; if (state->stage == MESA_SHADER_GEOMETRY && - state->has_explicit_attrib_stream()) { + state->has_explicit_attrib_stream() && + block->default_layout.flags.q.out) { /* Assign global layout's stream value. */ - block->layout.flags.q.stream = 1; - block->layout.flags.q.explicit_stream = 0; - block->layout.stream = state->out_qualifier->stream; + block->default_layout.flags.q.stream = 1; + block->default_layout.flags.q.explicit_stream = 0; + block->default_layout.stream = state->out_qualifier->stream; + } + + if (state->has_enhanced_layouts() && block->default_layout.flags.q.out) { + /* Assign global layout's xfb_buffer value. */ + block->default_layout.flags.q.xfb_buffer = 1; + block->default_layout.flags.q.explicit_xfb_buffer = 0; + block->default_layout.xfb_buffer = state->out_qualifier->xfb_buffer; } foreach_list_typed (ast_declarator_list, member, link, &block->declarations) { @@ -952,13 +1079,13 @@ _mesa_ast_process_interface_block(YYLTYPE *locp, } } -void +static void _mesa_ast_type_qualifier_print(const struct ast_type_qualifier *q) { - if (q->flags.q.subroutine) + if (q->is_subroutine_decl()) printf("subroutine "); - if (q->flags.q.subroutine_def) { + if (q->subroutine_list) { printf("subroutine ("); q->subroutine_list->print(); printf(")"); @@ -1145,6 +1272,14 @@ ast_expression::print(void) const printf("%f ", primary_expression.double_constant); break; + case ast_int64_constant: + printf("%" PRId64 " ", primary_expression.int64_constant); + break; + + case ast_uint64_constant: + printf("%" PRIu64 " ", primary_expression.uint64_constant); + break; + case ast_bool_constant: printf("%s ", primary_expression.bool_constant @@ -1192,6 +1327,7 @@ ast_expression::ast_expression(int oper, this->subexpressions[1] = ex1; this->subexpressions[2] = ex2; this->non_lvalue_description = NULL; + this->is_lhs = false; } @@ -1538,21 +1674,10 @@ ast_struct_specifier::print(void) const ast_struct_specifier::ast_struct_specifier(const char *identifier, ast_declarator_list *declarator_list) + : name(identifier), layout(NULL), declarations(), is_declaration(true), + type(NULL) { - if (identifier == NULL) { - static mtx_t mutex = _MTX_INITIALIZER_NP; - static unsigned anon_count = 1; - 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; } void ast_subroutine_list::print(void) const @@ -1569,18 +1694,18 @@ set_shader_inout_layout(struct gl_shader *shader, struct _mesa_glsl_parse_state *state) { /* Should have been prevented by the parser. */ - if (shader->Stage == MESA_SHADER_TESS_CTRL) { + if (shader->Stage == MESA_SHADER_TESS_CTRL || + shader->Stage == MESA_SHADER_VERTEX) { 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) { + } else if (shader->Stage != MESA_SHADER_GEOMETRY && + shader->Stage != MESA_SHADER_TESS_EVAL) { 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); + assert(!state->cs_input_local_size_variable_specified); } if (shader->Stage != MESA_SHADER_FRAGMENT) { @@ -1590,11 +1715,24 @@ set_shader_inout_layout(struct gl_shader *shader, assert(!state->fs_pixel_center_integer); assert(!state->fs_origin_upper_left); assert(!state->fs_early_fragment_tests); + assert(!state->fs_inner_coverage); + assert(!state->fs_post_depth_coverage); + } + + for (unsigned i = 0; i < MAX_FEEDBACK_BUFFERS; i++) { + if (state->out_qualifier->out_xfb_stride[i]) { + unsigned xfb_stride; + if (state->out_qualifier->out_xfb_stride[i]-> + process_qualifier_constant(state, "xfb_stride", &xfb_stride, + true)) { + shader->TransformFeedbackBufferStride[i] = xfb_stride; + } + } } switch (shader->Stage) { case MESA_SHADER_TESS_CTRL: - shader->TessCtrl.VerticesOut = 0; + shader->info.TessCtrl.VerticesOut = 0; if (state->tcs_output_vertices_specified) { unsigned vertices; if (state->out_qualifier->vertices-> @@ -1606,51 +1744,59 @@ set_shader_inout_layout(struct gl_shader *shader, _mesa_glsl_error(&loc, state, "vertices (%d) exceeds " "GL_MAX_PATCH_VERTICES", vertices); } - shader->TessCtrl.VerticesOut = vertices; + shader->info.TessCtrl.VerticesOut = vertices; } } break; case MESA_SHADER_TESS_EVAL: - shader->TessEval.PrimitiveMode = PRIM_UNKNOWN; + shader->info.TessEval.PrimitiveMode = PRIM_UNKNOWN; if (state->in_qualifier->flags.q.prim_type) - shader->TessEval.PrimitiveMode = state->in_qualifier->prim_type; + shader->info.TessEval.PrimitiveMode = state->in_qualifier->prim_type; - shader->TessEval.Spacing = 0; + shader->info.TessEval.Spacing = TESS_SPACING_UNSPECIFIED; if (state->in_qualifier->flags.q.vertex_spacing) - shader->TessEval.Spacing = state->in_qualifier->vertex_spacing; + shader->info.TessEval.Spacing = state->in_qualifier->vertex_spacing; - shader->TessEval.VertexOrder = 0; + shader->info.TessEval.VertexOrder = 0; if (state->in_qualifier->flags.q.ordering) - shader->TessEval.VertexOrder = state->in_qualifier->ordering; + shader->info.TessEval.VertexOrder = state->in_qualifier->ordering; - shader->TessEval.PointMode = -1; + shader->info.TessEval.PointMode = -1; if (state->in_qualifier->flags.q.point_mode) - shader->TessEval.PointMode = state->in_qualifier->point_mode; + shader->info.TessEval.PointMode = state->in_qualifier->point_mode; break; case MESA_SHADER_GEOMETRY: - shader->Geom.VerticesOut = 0; + shader->info.Geom.VerticesOut = -1; if (state->out_qualifier->flags.q.max_vertices) { unsigned qual_max_vertices; if (state->out_qualifier->max_vertices-> process_qualifier_constant(state, "max_vertices", &qual_max_vertices, true)) { - shader->Geom.VerticesOut = qual_max_vertices; + + if (qual_max_vertices > state->Const.MaxGeometryOutputVertices) { + YYLTYPE loc = state->out_qualifier->max_vertices->get_location(); + _mesa_glsl_error(&loc, state, + "maximum output vertices (%d) exceeds " + "GL_MAX_GEOMETRY_OUTPUT_VERTICES", + qual_max_vertices); + } + shader->info.Geom.VerticesOut = qual_max_vertices; } } if (state->gs_input_prim_type_specified) { - shader->Geom.InputType = state->in_qualifier->prim_type; + shader->info.Geom.InputType = state->in_qualifier->prim_type; } else { - shader->Geom.InputType = PRIM_UNKNOWN; + shader->info.Geom.InputType = PRIM_UNKNOWN; } if (state->out_qualifier->flags.q.prim_type) { - shader->Geom.OutputType = state->out_qualifier->prim_type; + shader->info.Geom.OutputType = state->out_qualifier->prim_type; } else { - shader->Geom.OutputType = PRIM_UNKNOWN; + shader->info.Geom.OutputType = PRIM_UNKNOWN; } - shader->Geom.Invocations = 0; + shader->info.Geom.Invocations = 0; if (state->in_qualifier->flags.q.invocations) { unsigned invocations; if (state->in_qualifier->invocations-> @@ -1664,7 +1810,7 @@ set_shader_inout_layout(struct gl_shader *shader, "GL_MAX_GEOMETRY_SHADER_INVOCATIONS", invocations); } - shader->Geom.Invocations = invocations; + shader->info.Geom.Invocations = invocations; } } break; @@ -1672,11 +1818,14 @@ set_shader_inout_layout(struct gl_shader *shader, 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]; + shader->info.Comp.LocalSize[i] = state->cs_input_local_size[i]; } else { for (int i = 0; i < 3; i++) - shader->Comp.LocalSize[i] = 0; + shader->info.Comp.LocalSize[i] = 0; } + + shader->info.Comp.LocalSizeVariable = + state->cs_input_local_size_variable_specified; break; case MESA_SHADER_FRAGMENT: @@ -1687,35 +1836,257 @@ set_shader_inout_layout(struct gl_shader *shader, shader->ARB_fragment_coord_conventions_enable = state->ARB_fragment_coord_conventions_enable; shader->EarlyFragmentTests = state->fs_early_fragment_tests; + shader->InnerCoverage = state->fs_inner_coverage; + shader->PostDepthCoverage = state->fs_post_depth_coverage; + shader->BlendSupport = state->fs_blend_support; break; default: /* Nothing to do. */ break; } + + shader->bindless_sampler = state->bindless_sampler_specified; + shader->bindless_image = state->bindless_image_specified; + shader->bound_sampler = state->bound_sampler_specified; + shader->bound_image = state->bound_image_specified; +} + +/* src can be NULL if only the symbols found in the exec_list should be + * copied + */ +void +_mesa_glsl_copy_symbols_from_table(struct exec_list *shader_ir, + struct glsl_symbol_table *src, + struct glsl_symbol_table *dest) +{ + foreach_in_list (ir_instruction, ir, shader_ir) { + switch (ir->ir_type) { + case ir_type_function: + dest->add_function((ir_function *) ir); + break; + case ir_type_variable: { + ir_variable *const var = (ir_variable *) ir; + + if (var->data.mode != ir_var_temporary) + dest->add_variable(var); + break; + } + default: + break; + } + } + + if (src != NULL) { + /* Explicitly copy the gl_PerVertex interface definitions because these + * are needed to check they are the same during the interstage link. + * They can’t necessarily be found via the exec_list because the members + * might not be referenced. The GL spec still requires that they match + * in that case. + */ + const glsl_type *iface = + src->get_interface("gl_PerVertex", ir_var_shader_in); + if (iface) + dest->add_interface(iface->name, iface, ir_var_shader_in); + + iface = src->get_interface("gl_PerVertex", ir_var_shader_out); + if (iface) + dest->add_interface(iface->name, iface, ir_var_shader_out); + } } extern "C" { +static void +assign_subroutine_indexes(struct _mesa_glsl_parse_state *state) +{ + int j, k; + int index = 0; + + for (j = 0; j < state->num_subroutines; j++) { + while (state->subroutines[j]->subroutine_index == -1) { + for (k = 0; k < state->num_subroutines; k++) { + if (state->subroutines[k]->subroutine_index == index) + break; + else if (k == state->num_subroutines - 1) { + state->subroutines[j]->subroutine_index = index; + } + } + index++; + } + } +} + +static void +add_builtin_defines(struct _mesa_glsl_parse_state *state, + void (*add_builtin_define)(struct glcpp_parser *, const char *, int), + struct glcpp_parser *data, + unsigned version, + bool es) +{ + unsigned gl_version = state->ctx->Extensions.Version; + gl_api api = state->ctx->API; + + if (gl_version != 0xff) { + unsigned i; + for (i = 0; i < state->num_supported_versions; i++) { + if (state->supported_versions[i].ver == version && + state->supported_versions[i].es == es) { + gl_version = state->supported_versions[i].gl_ver; + break; + } + } + + if (i == state->num_supported_versions) + return; + } + + if (es) + api = API_OPENGLES2; + + for (unsigned i = 0; + i < ARRAY_SIZE(_mesa_glsl_supported_extensions); ++i) { + const _mesa_glsl_extension *extension + = &_mesa_glsl_supported_extensions[i]; + if (extension->compatible_with_state(state, api, gl_version)) { + add_builtin_define(data, extension->name, 1); + } + } +} + +/* Implements parsing checks that we can't do during parsing */ +static void +do_late_parsing_checks(struct _mesa_glsl_parse_state *state) +{ + if (state->stage == MESA_SHADER_COMPUTE && !state->has_compute_shader()) { + YYLTYPE loc; + memset(&loc, 0, sizeof(loc)); + _mesa_glsl_error(&loc, state, "Compute shaders require " + "GLSL 4.30 or GLSL ES 3.10"); + } +} + +static void +opt_shader_and_create_symbol_table(struct gl_context *ctx, + struct glsl_symbol_table *source_symbols, + struct gl_shader *shader) +{ + assert(shader->CompileStatus != compile_failure && + !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 + */ + if (ctx->Const.GLSLOptimizeConservatively) { + /* Run it just once. */ + do_common_optimization(shader->ir, false, false, options, + ctx->Const.NativeIntegers); + } else { + /* Repeat it until it stops making changes. */ + 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); + + /* 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. + */ + _mesa_glsl_copy_symbols_from_table(shader->ir, source_symbols, + shader->symbols); +} + void _mesa_glsl_compile_shader(struct gl_context *ctx, struct gl_shader *shader, - bool dump_ast, bool dump_hir) + bool dump_ast, bool dump_hir, bool force_recompile) { + const char *source = force_recompile && shader->FallbackSource ? + shader->FallbackSource : shader->Source; + + if (!force_recompile) { + if (ctx->Cache) { + char buf[41]; + disk_cache_compute_key(ctx->Cache, source, strlen(source), + shader->sha1); + if (disk_cache_has_key(ctx->Cache, shader->sha1)) { + /* We've seen this shader before and know it compiles */ + if (ctx->_Shader->Flags & GLSL_CACHE_INFO) { + _mesa_sha1_format(buf, shader->sha1); + fprintf(stderr, "deferring compile of shader: %s\n", buf); + } + shader->CompileStatus = compile_skipped; + + free((void *)shader->FallbackSource); + shader->FallbackSource = NULL; + return; + } + } + } else { + /* We should only ever end up here if a re-compile has been forced by a + * shader cache miss. In which case we can skip the compile if its + * already be done by a previous fallback or the initial compile call. + */ + if (shader->CompileStatus == compile_success) + return; + + if (shader->CompileStatus == compiled_no_opts) { + opt_shader_and_create_symbol_table(ctx, + NULL, /* source_symbols */ + shader); + shader->CompileStatus = compile_success; + return; + } + } + 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); + add_builtin_defines, state, ctx); if (!state->error) { _mesa_glsl_lexer_ctor(state, source); _mesa_glsl_parse(state); _mesa_glsl_lexer_dtor(state); + do_late_parsing_checks(state); } if (dump_ast) { @@ -1739,42 +2110,6 @@ _mesa_glsl_compile_shader(struct gl_context *ctx, struct gl_shader *shader, } } - - if (!state->error && !shader->ir->is_empty()) { - struct gl_shader_compiler_options *options = - &ctx->Const.ShaderCompilerOptions[shader->Stage]; - - lower_subroutine(shader->ir, state); - /* 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); @@ -1782,43 +2117,27 @@ _mesa_glsl_compile_shader(struct gl_context *ctx, struct gl_shader *shader, set_shader_inout_layout(shader, state); shader->symbols = new(shader->ir) glsl_symbol_table; - shader->CompileStatus = !state->error; + shader->CompileStatus = state->error ? compile_failure : compile_success; shader->InfoLog = state->info_log; shader->Version = state->language_version; shader->IsES = state->es_shader; - shader->uses_builtin_functions = state->uses_builtin_functions; - - /* 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 (!state->error && !shader->ir->is_empty()) { + assign_subroutine_indexes(state); + lower_subroutine(shader->ir, state); - if (var->data.mode != ir_var_temporary) - shader->symbols->add_variable(var); - break; - } - default: - break; + if (!ctx->Cache || force_recompile) + opt_shader_and_create_symbol_table(ctx, state->symbols, shader); + else { + reparent_ir(shader->ir, shader->ir); + shader->CompileStatus = compiled_no_opts; } } - _mesa_glsl_initialize_derived_variables(shader); + if (!force_recompile) { + free((void *)shader->FallbackSource); + shader->FallbackSource = NULL; + } delete state->symbols; ralloc_free(state); @@ -1838,10 +2157,11 @@ _mesa_glsl_compile_shader(struct gl_context *ctx, struct gl_shader *shader, * of unused uniforms from being removed. * The setting of this flag only matters if * \c linked is \c true. - * \param max_unroll_iterations Maximum number of loop iterations to be - * unrolled. Setting to 0 disables loop - * unrolling. * \param options The driver's preferred shader options. + * \param native_integers Selects optimizations that depend on the + * implementations supporting integers + * natively (as opposed to supporting + * integers in floating point registers). */ bool do_common_optimization(exec_list *ir, bool linked, @@ -1873,6 +2193,7 @@ do_common_optimization(exec_list *ir, bool linked, OPT(do_dead_functions, ir); OPT(do_structure_splitting, ir); } + propagate_invariance(ir); OPT(do_if_simplification, ir); OPT(opt_flatten_nested_if_blocks, ir); OPT(opt_conditional_discard, ir); @@ -1901,21 +2222,28 @@ do_common_optimization(exec_list *ir, bool linked, OPT(do_minmax_prune, ir); OPT(do_rebalance_tree, ir); OPT(do_algebraic, ir, native_integers, options); - OPT(do_lower_jumps, ir); + OPT(do_lower_jumps, ir, true, true, options->EmitNoMainReturn, + options->EmitNoCont, options->EmitNoLoops); OPT(do_vec_index_to_swizzle, ir); OPT(lower_vector_insert, ir, false); - OPT(do_swizzle_swizzle, ir); - OPT(do_noop_swizzle, ir); + OPT(optimize_swizzles, ir); OPT(optimize_split_arrays, ir, linked); OPT(optimize_redundant_jumps, ir); - loop_state *ls = analyze_loop_variables(ir); - if (ls->loop_found) { - OPT(set_loop_controls, ir, ls); - OPT(unroll_loops, ir, ls, options); + if (options->MaxUnrollIterations) { + loop_state *ls = analyze_loop_variables(ir); + if (ls->loop_found) { + bool loop_progress = unroll_loops(ir, ls, options); + while (loop_progress) { + loop_progress = false; + loop_progress |= do_constant_propagation(ir); + loop_progress |= do_if_simplification(ir); + } + progress |= loop_progress; + } + delete ls; } - delete ls; #undef OPT