extern "C" {
#include "main/core.h" /* for struct gl_context */
#include "main/context.h"
+#include "main/shaderobj.h"
}
#include "ralloc.h"
version / 100, version % 100);
}
+
+static unsigned known_desktop_glsl_versions[] =
+ { 110, 120, 130, 140, 150, 330, 400, 410, 420, 430, 440 };
+
+
_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;
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.MaxVertexTextureImageUnits;
+ 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.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;
- const unsigned lowest_version =
- (ctx->API == API_OPENGLES2) || ctx->Extensions.ARB_ES2_compatibility
- ? 100 : 110;
- const unsigned highest_version =
- _mesa_is_desktop_gl(ctx) ? ctx->Const.GLSLVersion : 100;
- char *supported = ralloc_strdup(this, "");
+ /* 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;
+
+ /* 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
+ * change. Older versions of GLSL are no longer supported
+ * outside the compatibility contexts of 3.x.
+ */
+ this->num_supported_versions = 0;
+ if (_mesa_is_desktop_gl(ctx)) {
+ for (unsigned i = 0; i < ARRAY_SIZE(known_desktop_glsl_versions); i++) {
+ 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].es = false;
+ this->num_supported_versions++;
+ }
+ }
+ }
+ 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].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].es = true;
+ this->num_supported_versions++;
+ }
+ assert(this->num_supported_versions
+ <= ARRAY_SIZE(this->supported_versions));
- for (unsigned ver = lowest_version; ver <= highest_version; ver += 10) {
- const char *const prefix = (ver == lowest_version)
+ /* Create a string for use in error messages to tell the user which GLSL
+ * versions are supported.
+ */
+ char *supported = ralloc_strdup(this, "");
+ for (unsigned i = 0; i < this->num_supported_versions; i++) {
+ unsigned ver = this->supported_versions[i].ver;
+ const char *const prefix = (i == 0)
? ""
- : ((ver == highest_version) ? ", and " : ", ");
+ : ((i == this->num_supported_versions - 1) ? ", and " : ", ");
+ const char *const suffix = (this->supported_versions[i].es) ? " ES" : "";
- ralloc_asprintf_append(& supported, "%s%d.%02d%s",
+ ralloc_asprintf_append(& supported, "%s%u.%02u%s",
prefix,
ver / 100, ver % 100,
- (ver == 100) ? " ES" : "");
+ suffix);
}
this->supported_version_string = 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->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));
}
/**
va_list args;
va_start(args, fmt);
- char *problem = ralloc_vasprintf(ctx, fmt, args);
+ char *problem = ralloc_vasprintf(this, fmt, args);
va_end(args);
const char *glsl_version_string
- = glsl_compute_version_string(ctx, false, required_glsl_version);
+ = glsl_compute_version_string(this, false, required_glsl_version);
const char *glsl_es_version_string
- = glsl_compute_version_string(ctx, true, required_glsl_es_version);
+ = glsl_compute_version_string(this, true, required_glsl_es_version);
const char *requirement_string = "";
if (required_glsl_version && required_glsl_es_version) {
- requirement_string = ralloc_asprintf(ctx, " (%s or %s required)",
+ requirement_string = ralloc_asprintf(this, " (%s or %s required)",
glsl_version_string,
glsl_es_version_string);
} else if (required_glsl_version) {
- requirement_string = ralloc_asprintf(ctx, " (%s required)",
+ requirement_string = ralloc_asprintf(this, " (%s required)",
glsl_version_string);
} else if (required_glsl_es_version) {
- requirement_string = ralloc_asprintf(ctx, " (%s required)",
+ 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);
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");
}
}
- bool supported = false;
-
- if (es_token_present) {
- this->es_shader = true;
- switch (version) {
- case 100:
+ this->es_shader = es_token_present;
+ if (version == 100) {
+ if (es_token_present) {
_mesa_glsl_error(locp, this,
"GLSL 1.00 ES should be selected using "
- "`#version 100'\n");
- supported = this->ctx->API == API_OPENGLES2 ||
- this->ctx->Extensions.ARB_ES2_compatibility;
- break;
- case 300:
- supported = _mesa_is_gles3(this->ctx) ||
- this->ctx->Extensions.ARB_ES3_compatibility;
- break;
- default:
- supported = false;
- break;
- }
- } else {
- switch (version) {
- case 100:
+ "`#version 100'");
+ } else {
this->es_shader = true;
- supported = this->ctx->API == API_OPENGLES2 ||
- this->ctx->Extensions.ARB_ES2_compatibility;
- break;
- case 110:
- case 120:
- /* FINISHME: Once the OpenGL 3.0 'forward compatible' context or
- * the OpenGL 3.2 Core context is supported, this logic will need
- * change. Older versions of GLSL are no longer supported
- * outside the compatibility contexts of 3.x.
- */
- case 130:
- case 140:
- case 150:
- case 330:
- case 400:
- case 410:
- case 420:
- supported = _mesa_is_desktop_gl(this->ctx) &&
- ((unsigned) version) <= this->ctx->Const.GLSLVersion;
- break;
- default:
- supported = false;
- break;
}
}
+ if (this->es_shader) {
+ this->ARB_texture_rectangle_enable = false;
+ }
+
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
+ && this->supported_versions[i].es == this->es_shader) {
+ supported = true;
+ break;
+ }
+ }
+
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);
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.");
'id' is the implementation-defined ID of the given message. */
static void
_mesa_glsl_msg(const YYLTYPE *locp, _mesa_glsl_parse_state *state,
- GLenum type, GLuint id, const char *fmt, va_list ap)
+ GLenum type, const char *fmt, va_list ap)
{
- bool error = (type == GL_DEBUG_TYPE_ERROR_ARB);
+ bool error = (type == MESA_DEBUG_TYPE_ERROR);
+ GLuint msg_id = 0;
assert(state->info_log != NULL);
const char *const msg = &state->info_log[msg_offset];
struct gl_context *ctx = state->ctx;
+
/* Report the error via GL_ARB_debug_output. */
- if (error)
- _mesa_shader_debug(ctx, type, id, msg, strlen(msg));
+ _mesa_shader_debug(ctx, type, &msg_id, msg, strlen(msg));
ralloc_strcat(&state->info_log, "\n");
}
const char *fmt, ...)
{
va_list ap;
- GLenum type = GL_DEBUG_TYPE_ERROR_ARB;
state->error = true;
va_start(ap, fmt);
- _mesa_glsl_msg(locp, state, type, SHADER_ERROR_UNKNOWN, fmt, ap);
+ _mesa_glsl_msg(locp, state, MESA_DEBUG_TYPE_ERROR, fmt, ap);
va_end(ap);
}
const char *fmt, ...)
{
va_list ap;
- GLenum type = GL_DEBUG_TYPE_OTHER_ARB;
va_start(ap, fmt);
- _mesa_glsl_msg(locp, state, type, 0, fmt, ap);
+ _mesa_glsl_msg(locp, state, MESA_DEBUG_TYPE_OTHER, fmt, ap);
va_end(ap);
}
*/
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;
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 }
/**
* 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),
+ /* API availability */
+ /* name GL ES supported flag */
+ EXT(ARB_arrays_of_arrays, true, false, ARB_arrays_of_arrays),
+ 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_texture_rectangle, true, false, dummy_true),
+ EXT(EXT_texture_array, true, false, EXT_texture_array),
+ EXT(ARB_separate_shader_objects, true, false, ARB_separate_shader_objects),
+ EXT(ARB_shader_texture_lod, true, false, ARB_shader_texture_lod),
+ EXT(ARB_shader_stencil_export, true, false, ARB_shader_stencil_export),
+ EXT(AMD_conservative_depth, true, false, ARB_conservative_depth),
+ EXT(AMD_shader_stencil_export, true, false, ARB_shader_stencil_export),
+ EXT(OES_texture_3D, false, true, EXT_texture3D),
+ EXT(OES_EGL_image_external, false, true, OES_EGL_image_external),
+ EXT(ARB_shader_bit_encoding, true, false, ARB_shader_bit_encoding),
+ EXT(ARB_uniform_buffer_object, true, false, ARB_uniform_buffer_object),
+ EXT(OES_standard_derivatives, false, true, OES_standard_derivatives),
+ EXT(ARB_texture_cube_map_array, true, false, ARB_texture_cube_map_array),
+ EXT(ARB_shading_language_packing, true, false, ARB_shading_language_packing),
+ EXT(ARB_shading_language_420pack, true, false, ARB_shading_language_420pack),
+ 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_gpu_shader5, true, false, ARB_gpu_shader5),
+ EXT(AMD_vertex_shader_layer, true, false, AMD_vertex_shader_layer),
+ EXT(EXT_shader_integer_mix, true, true, EXT_shader_integer_mix),
+ EXT(ARB_texture_gather, true, false, ARB_texture_gather),
+ EXT(ARB_shader_atomic_counters, true, false, ARB_shader_atomic_counters),
+ EXT(ARB_sample_shading, true, false, ARB_sample_shading),
+ EXT(AMD_shader_trinary_minmax, true, false, dummy_true),
+ EXT(ARB_viewport_array, true, false, ARB_viewport_array),
+ EXT(ARB_compute_shader, true, false, ARB_compute_shader),
+ EXT(ARB_shader_image_load_store, true, false, ARB_shader_image_load_store),
};
#undef EXT
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.
*/
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;
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));
}
}
}
return true;
}
+
+/**
+ * Recurses through <type> and <expr> if <expr> is an aggregate initializer
+ * and sets <expr>'s <constructor_type> field to <type>. 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 <type> 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 <type> 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)
{
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)
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();
}
break;
}
+ case ast_aggregate: {
+ printf("{ ");
+ foreach_list_const(n, & this->expressions) {
+ if (n != this->expressions.get_head())
+ printf(", ");
+
+ ast_node *ast = exec_node_data(ast_node, n, link);
+ ast->print();
+ }
+ printf("} ");
+ break;
+ }
+
default:
assert(0);
break;
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;
ast_function::ast_function(void)
- : is_definition(false), signature(NULL)
+ : return_type(NULL), identifier(NULL), is_definition(false),
+ signature(NULL)
{
/* empty */
}
type->print();
if (identifier)
printf("%s ", identifier);
- ast_opt_array_size_print(is_array, array_size);
+ ast_opt_array_dimensions_print(array_specifier);
}
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("= ");
}
-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;
}
{
this->type = type;
this->invariant = false;
- this->ubo_qualifiers_valid = false;
}
void
ast_jump_statement::ast_jump_statement(int mode, ast_expression *return_value)
+ : opt_return_value(NULL)
{
this->mode = ast_jump_modes(mode);
}
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;
+ 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;
+
+ 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_const(n, &state->translation_unit) {
+ ast_node *ast = exec_node_data(ast_node, n, link);
+ 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->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);
+ }
+
+ if (shader->InfoLog)
+ ralloc_free(shader->InfoLog);
+
+ shader->symbols = state->symbols;
+ 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);
+
+ ralloc_free(state);
+}
+
+} /* extern "C" */
/**
* Do the set of common optimizations passes
*
* 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 forces all loops
- * to be unrolled.
+ * unrolled. Setting to 0 disables loop
+ * unrolling.
+ * \param options The driver's preferred shader options.
*/
bool
do_common_optimization(exec_list *ir, bool linked,
bool uniform_locations_assigned,
- unsigned max_unroll_iterations)
+ const struct gl_shader_compiler_options *options,
+ bool native_integers)
{
GLboolean progress = GL_FALSE;
progress = do_structure_splitting(ir) || progress;
}
progress = do_if_simplification(ir) || progress;
+ progress = opt_flatten_nested_if_blocks(ir) || progress;
progress = do_copy_propagation(ir) || progress;
progress = do_copy_propagation_elements(ir) || progress;
+
+ 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
else
progress = do_constant_variable_unlinked(ir) || progress;
progress = do_constant_folding(ir) || progress;
- progress = do_algebraic(ir) || progress;
+ progress = do_cse(ir) || progress;
+ progress = do_algebraic(ir, native_integers) || progress;
progress = do_lower_jumps(ir) || progress;
progress = do_vec_index_to_swizzle(ir) || progress;
+ progress = lower_vector_insert(ir, false) || progress;
progress = do_swizzle_swizzle(ir) || progress;
progress = do_noop_swizzle(ir) || progress;
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;
void
_mesa_destroy_shader_compiler_caches(void)
{
- _mesa_glsl_release_functions();
+ _mesa_glsl_release_builtin_functions();
}
}