#include <string.h>
#include <assert.h>
-extern "C" {
#include "main/core.h" /* for struct gl_context */
#include "main/context.h"
#include "main/shaderobj.h"
-}
-
-#include "ralloc.h"
+#include "util/u_atomic.h" /* for p_atomic_cmpxchg */
+#include "util/ralloc.h"
#include "ast.h"
#include "glsl_parser_extras.h"
#include "glsl_parser.h"
static const unsigned known_desktop_glsl_versions[] =
- { 110, 120, 130, 140, 150, 330, 400, 410, 420, 430, 440 };
+ { 110, 120, 130, 140, 150, 330, 400, 410, 420, 430, 440, 450 };
_mesa_glsl_parse_state::_mesa_glsl_parse_state(struct gl_context *_ctx,
this->uses_builtin_functions = false;
/* Set default language version and extensions */
- this->language_version = ctx->Const.ForceGLSLVersion ?
- ctx->Const.ForceGLSLVersion : 110;
+ this->language_version = 110;
+ this->forced_language_version = ctx->Const.ForceGLSLVersion;
this->es_shader = false;
this->ARB_texture_rectangle_enable = true;
this->extensions = &ctx->Extensions;
+ this->ARB_compute_shader_enable = true;
+
this->Const.MaxLights = ctx->Const.MaxLights;
this->Const.MaxClipPlanes = ctx->Const.MaxClipPlanes;
this->Const.MaxTextureUnits = ctx->Const.MaxTextureUnits;
this->Const.MaxDrawBuffers = ctx->Const.MaxDrawBuffers;
+ this->Const.MaxDualSourceDrawBuffers = ctx->Const.MaxDualSourceDrawBuffers;
+
/* 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.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 < Elements(this->Const.MaxComputeWorkGroupCount); i++)
+ for (unsigned i = 0; i < ARRAY_SIZE(this->Const.MaxComputeWorkGroupCount); i++)
this->Const.MaxComputeWorkGroupCount[i] = ctx->Const.MaxComputeWorkGroupCount[i];
- for (unsigned i = 0; i < Elements(this->Const.MaxComputeWorkGroupSize); i++)
+ for (unsigned i = 0; i < ARRAY_SIZE(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.MaxCombinedShaderOutputResources = ctx->Const.MaxCombinedShaderOutputResources;
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;
+ /* 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 3 GLES versions (ES 1.00, ES 3.00, and ES 3.10))
+ */
+ STATIC_ASSERT((ARRAY_SIZE(known_desktop_glsl_versions) + 3) ==
+ ARRAY_SIZE(this->supported_versions));
/* Populate the list of supported GLSL versions */
/* FINISHME: Once the OpenGL 3.0 'forward compatible' context or
this->supported_versions[this->num_supported_versions].es = true;
this->num_supported_versions++;
}
- assert(this->num_supported_versions
- <= ARRAY_SIZE(this->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.
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;
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();
- this->early_fragment_tests = false;
+ this->fs_early_fragment_tests = false;
memset(this->atomic_counter_offsets, 0,
sizeof(this->atomic_counter_offsets));
+ this->allow_extension_directive_midshader =
+ ctx->Const.AllowGLSLExtensionDirectiveMidShader;
}
/**
this->ARB_texture_rectangle_enable = false;
}
- this->language_version = version;
+ if (this->forced_language_version)
+ this->language_version = this->forced_language_version;
+ else
+ this->language_version = version;
bool supported = false;
for (unsigned i = 0; i < this->num_supported_versions; i++) {
- if (this->supported_versions[i].ver == (unsigned) version
+ if (this->supported_versions[i].ver == this->language_version
&& this->supported_versions[i].es == this->es_shader) {
supported = true;
break;
case MESA_SHADER_VERTEX: return "vertex";
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";
}
- assert(!"Should not get here.");
- return "unknown";
+ unreachable("Unknown shader stage.");
+}
+
+/**
+ * Translate a gl_shader_stage to a shader stage abbreviation (VS, GS, FS)
+ * for debug printouts and error messages.
+ */
+const char *
+_mesa_shader_stage_to_abbrev(unsigned stage)
+{
+ switch (stage) {
+ case MESA_SHADER_VERTEX: return "VS";
+ 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.");
}
/* This helper function will append the given message to the shader's
struct gl_context *ctx = state->ctx;
/* Report the error via GL_ARB_debug_output. */
- _mesa_shader_debug(ctx, type, &msg_id, msg, strlen(msg));
+ _mesa_shader_debug(ctx, type, &msg_id, msg);
ralloc_strcat(&state->info_log, "\n");
}
/* 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_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_fragment_coord_conventions, true, false, ARB_fragment_coord_conventions),
- 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),
+ 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_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),
/* KHR 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),
+ EXT(OES_texture_3D, false, true, dummy_true),
+ EXT(OES_texture_storage_multisample_2d_array, false, true, ARB_texture_multisample),
/* All other extensions go here, sorted alphabetically.
*/
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),
};
*/
static const _mesa_glsl_extension *find_extension(const char *name)
{
- for (unsigned i = 0; i < Elements(_mesa_glsl_supported_extensions); ++i) {
+ for (unsigned i = 0; i < ARRAY_SIZE(_mesa_glsl_supported_extensions); ++i) {
if (strcmp(name, _mesa_glsl_supported_extensions[i].name) == 0) {
return &_mesa_glsl_supported_extensions[i];
}
return false;
} else {
for (unsigned i = 0;
- i < Elements(_mesa_glsl_supported_extensions); ++i) {
+ 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 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.
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. */
}
}
+void
+_mesa_ast_process_interface_block(YYLTYPE *locp,
+ _mesa_glsl_parse_state *state,
+ ast_interface_block *const block,
+ const struct ast_type_qualifier &q)
+{
+ if (q.flags.q.buffer) {
+ if (!state->has_shader_storage_buffer_objects()) {
+ _mesa_glsl_error(locp, state,
+ "#version 430 / GL_ARB_shader_storage_buffer_object "
+ "required for defining shader storage blocks");
+ } else if (state->ARB_shader_storage_buffer_object_warn) {
+ _mesa_glsl_warning(locp, state,
+ "#version 430 / GL_ARB_shader_storage_buffer_object "
+ "required for defining shader storage blocks");
+ }
+ } else if (q.flags.q.uniform) {
+ if (!state->has_uniform_buffer_objects()) {
+ _mesa_glsl_error(locp, state,
+ "#version 140 / GL_ARB_uniform_buffer_object "
+ "required for defining uniform blocks");
+ } else if (state->ARB_uniform_buffer_object_warn) {
+ _mesa_glsl_warning(locp, state,
+ "#version 140 / GL_ARB_uniform_buffer_object "
+ "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");
+ }
+ }
+
+ /* From the GLSL 1.50.11 spec, section 4.3.7 ("Interface Blocks"):
+ * "It is illegal to have an input block in a vertex shader
+ * or an output block in a fragment shader"
+ */
+ if ((state->stage == MESA_SHADER_VERTEX) && q.flags.q.in) {
+ _mesa_glsl_error(locp, state,
+ "`in' interface block is not allowed for "
+ "a vertex shader");
+ } else if ((state->stage == MESA_SHADER_FRAGMENT) && q.flags.q.out) {
+ _mesa_glsl_error(locp, state,
+ "`out' interface block is not allowed for "
+ "a fragment shader");
+ }
+
+ /* Since block arrays require names, and both features are added in
+ * the same language versions, we don't have to explicitly
+ * version-check both things.
+ */
+ if (block->instance_name != NULL) {
+ state->check_version(150, 300, locp, "interface blocks with "
+ "an instance name are not allowed");
+ }
+
+ uint64_t interface_type_mask;
+ struct ast_type_qualifier temp_type_qualifier;
+
+ /* Get a bitmask containing only the in/out/uniform/buffer
+ * flags, allowing us to ignore other irrelevant flags like
+ * interpolation qualifiers.
+ */
+ temp_type_qualifier.flags.i = 0;
+ temp_type_qualifier.flags.q.uniform = true;
+ temp_type_qualifier.flags.q.in = true;
+ temp_type_qualifier.flags.q.out = true;
+ temp_type_qualifier.flags.q.buffer = true;
+ interface_type_mask = temp_type_qualifier.flags.i;
+
+ /* Get the block's interface qualifier. The interface_qualifier
+ * production rule guarantees that only one bit will be set (and
+ * it will be in/out/uniform).
+ */
+ uint64_t block_interface_qualifier = q.flags.i;
+
+ block->layout.flags.i |= block_interface_qualifier;
+
+ if (state->stage == MESA_SHADER_GEOMETRY &&
+ state->has_explicit_attrib_stream()) {
+ /* 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;
+ }
+
+ foreach_list_typed (ast_declarator_list, member, link, &block->declarations) {
+ ast_type_qualifier& qualifier = member->type->qualifier;
+ if ((qualifier.flags.i & interface_type_mask) == 0) {
+ /* GLSLangSpec.1.50.11, 4.3.7 (Interface Blocks):
+ * "If no optional qualifier is used in a member declaration, the
+ * qualifier of the variable is just in, out, or uniform as declared
+ * by interface-qualifier."
+ */
+ qualifier.flags.i |= block_interface_qualifier;
+ } else if ((qualifier.flags.i & interface_type_mask) !=
+ block_interface_qualifier) {
+ /* GLSLangSpec.1.50.11, 4.3.7 (Interface Blocks):
+ * "If optional qualifiers are used, they can include interpolation
+ * and storage qualifiers and they must declare an input, output,
+ * or uniform variable consistent with the interface qualifier of
+ * the block."
+ */
+ _mesa_glsl_error(locp, state,
+ "uniform/in/out qualifier on "
+ "interface block member does not match "
+ "the interface block");
+ }
+
+ /* From GLSL ES 3.0, chapter 4.3.7 "Interface Blocks":
+ *
+ * "GLSL ES 3.0 does not support interface blocks for shader inputs or
+ * outputs."
+ *
+ * And from GLSL ES 3.0, chapter 4.6.1 "The invariant qualifier":.
+ *
+ * "Only variables output from a shader can be candidates for
+ * invariance."
+ *
+ * From GLSL 4.40 and GLSL 1.50, section "Interface Blocks":
+ *
+ * "If optional qualifiers are used, they can include interpolation
+ * qualifiers, auxiliary storage qualifiers, and storage qualifiers
+ * and they must declare an input, output, or uniform member
+ * consistent with the interface qualifier of the block"
+ */
+ if (qualifier.flags.q.invariant)
+ _mesa_glsl_error(locp, state,
+ "invariant qualifiers cannot be used "
+ "with interface blocks members");
+ }
+}
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 ");
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)
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();
}
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();
}
printf("%f ", primary_expression.float_constant);
break;
+ case ast_double_constant:
+ printf("%f ", primary_expression.double_constant);
+ break;
+
case ast_bool_constant:
printf("%s ",
primary_expression.bool_constant
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(") ");
case ast_aggregate: {
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("} ");
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();
}
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();
}
{
this->type = type;
this->invariant = false;
+ this->precise = false;
}
void
printf("else ");
else_statement->print();
}
-
}
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");
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");
}
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();
}
}
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("} ");
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;
}
+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);
}
assert(!state->fs_redeclares_gl_fragcoord);
assert(!state->fs_pixel_center_integer);
assert(!state->fs_origin_upper_left);
+ assert(!state->fs_early_fragment_tests);
}
switch (shader->Stage) {
+ case MESA_SHADER_TESS_CTRL:
+ shader->TessCtrl.VerticesOut = 0;
+ if (state->tcs_output_vertices_specified) {
+ unsigned vertices;
+ if (state->out_qualifier->vertices->
+ process_qualifier_constant(state, "vertices", &vertices,
+ false)) {
+
+ YYLTYPE loc = state->out_qualifier->vertices->get_location();
+ if (vertices > state->Const.MaxPatchVertices) {
+ _mesa_glsl_error(&loc, state, "vertices (%d) exceeds "
+ "GL_MAX_PATCH_VERTICES", vertices);
+ }
+ shader->TessCtrl.VerticesOut = 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)
- shader->Geom.VerticesOut = state->out_qualifier->max_vertices;
+ 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 (state->gs_input_prim_type_specified) {
shader->Geom.InputType = state->in_qualifier->prim_type;
}
shader->Geom.Invocations = 0;
- if (state->in_qualifier->flags.q.invocations)
- shader->Geom.Invocations = state->in_qualifier->invocations;
+ if (state->in_qualifier->flags.q.invocations) {
+ unsigned invocations;
+ if (state->in_qualifier->invocations->
+ process_qualifier_constant(state, "invocations",
+ &invocations, false)) {
+
+ YYLTYPE loc = state->in_qualifier->invocations->get_location();
+ if (invocations > MAX_GEOMETRY_SHADER_INVOCATIONS) {
+ _mesa_glsl_error(&loc, state,
+ "invocations (%d) exceeds "
+ "GL_MAX_GEOMETRY_SHADER_INVOCATIONS",
+ invocations);
+ }
+ shader->Geom.Invocations = invocations;
+ }
+ }
break;
case MESA_SHADER_COMPUTE:
shader->origin_upper_left = state->fs_origin_upper_left;
shader->ARB_fragment_coord_conventions_enable =
state->ARB_fragment_coord_conventions_enable;
+ shader->EarlyFragmentTests = state->fs_early_fragment_tests;
break;
default:
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 (dump_ast) {
- foreach_list_const(n, &state->translation_unit) {
- ast_node *ast = exec_node_data(ast_node, n, link);
+ foreach_list_typed(ast_node, ast, link, &state->translation_unit) {
ast->print();
}
printf("\n\n");
if (!state->error && !shader->ir->is_empty()) {
struct gl_shader_compiler_options *options =
- &ctx->ShaderCompilerOptions[shader->Stage];
+ &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
*/
;
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 = state->symbols;
+ if (!state->error)
+ set_shader_inout_layout(shader, state);
+
+ 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;
+ }
+ }
+
+ _mesa_glsl_initialize_derived_variables(shader);
+
+ delete state->symbols;
ralloc_free(state);
}
}
progress = do_if_simplification(ir) || progress;
progress = opt_flatten_nested_if_blocks(ir) || progress;
+ progress = opt_conditional_discard(ir) || progress;
progress = do_copy_propagation(ir) || progress;
progress = do_copy_propagation_elements(ir) || progress;
else
progress = do_constant_variable_unlinked(ir) || progress;
progress = do_constant_folding(ir) || progress;
- progress = do_cse(ir) || progress;
- progress = do_algebraic(ir, native_integers) || progress;
+ progress = do_minmax_prune(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;