#include "main/core.h"
#include "glsl_symbol_table.h"
+#include "glsl_parser_extras.h"
#include "ir.h"
#include "program.h"
#include "program/hash_table.h"
}
+/**
+ * Given a string identifying a program resource, break it into a base name
+ * and an optional array index in square brackets.
+ *
+ * If an array index is present, \c out_base_name_end is set to point to the
+ * "[" that precedes the array index, and the array index itself is returned
+ * as a long.
+ *
+ * If no array index is present (or if the array index is negative or
+ * mal-formed), \c out_base_name_end, is set to point to the null terminator
+ * at the end of the input string, and -1 is returned.
+ *
+ * Only the final array index is parsed; if the string contains other array
+ * indices (or structure field accesses), they are left in the base name.
+ *
+ * No attempt is made to check that the base name is properly formed;
+ * typically the caller will look up the base name in a hash table, so
+ * ill-formed base names simply turn into hash table lookup failures.
+ */
+long
+parse_program_resource_name(const GLchar *name,
+ const GLchar **out_base_name_end)
+{
+ /* Section 7.3.1 ("Program Interfaces") of the OpenGL 4.3 spec says:
+ *
+ * "When an integer array element or block instance number is part of
+ * the name string, it will be specified in decimal form without a "+"
+ * or "-" sign or any extra leading zeroes. Additionally, the name
+ * string will not include white space anywhere in the string."
+ */
+
+ const size_t len = strlen(name);
+ *out_base_name_end = name + len;
+
+ if (len == 0 || name[len-1] != ']')
+ return -1;
+
+ /* Walk backwards over the string looking for a non-digit character. This
+ * had better be the opening bracket for an array index.
+ *
+ * Initially, i specifies the location of the ']'. Since the string may
+ * contain only the ']' charcater, walk backwards very carefully.
+ */
+ unsigned i;
+ for (i = len - 1; (i > 0) && isdigit(name[i-1]); --i)
+ /* empty */ ;
+
+ if ((i == 0) || name[i-1] != '[')
+ return -1;
+
+ long array_index = strtol(&name[i], NULL, 10);
+ if (array_index < 0)
+ return -1;
+
+ *out_base_name_end = name + (i - 1);
+ return array_index;
+}
+
+
void
link_invalidate_variable_locations(gl_shader *sh, int input_base,
int output_base)
if (!cross_validate_globals(prog, shader_list, num_shaders, false))
return NULL;
+ /* Check that interface blocks defined in multiple shaders are consistent.
+ */
+ if (!validate_intrastage_interface_blocks((const gl_shader **)shader_list,
+ num_shaders))
+ return NULL;
+
/* Check that uniform blocks between shaders for a stage agree. */
const int num_uniform_blocks =
link_uniform_blocks(mem_ctx, prog, shader_list, num_shaders,
if (main == NULL) {
linker_error(prog, "%s shader lacks `main'\n",
- (shader_list[0]->Type == GL_VERTEX_SHADER)
- ? "vertex" : "fragment");
+ _mesa_glsl_shader_target_name(shader_list[0]->Type));
return NULL;
}
free(linking_shaders);
-#ifdef DEBUG
/* At this point linked should contain all of the linked IR, so
* validate it to make sure nothing went wrong.
*/
if (linked)
validate_ir_tree(linked->ir);
-#endif
/* Make a pass over all variable declarations to ensure that arrays with
* unspecified sizes have a size specified. The size is inferred from the
};
const unsigned max_samplers[MESA_SHADER_TYPES] = {
- ctx->Const.MaxVertexTextureImageUnits,
- ctx->Const.MaxTextureImageUnits,
- ctx->Const.MaxGeometryTextureImageUnits
+ ctx->Const.VertexProgram.MaxTextureImageUnits,
+ ctx->Const.FragmentProgram.MaxTextureImageUnits,
+ ctx->Const.GeometryProgram.MaxTextureImageUnits
};
- const unsigned max_uniform_components[MESA_SHADER_TYPES] = {
+ const unsigned max_default_uniform_components[MESA_SHADER_TYPES] = {
ctx->Const.VertexProgram.MaxUniformComponents,
ctx->Const.FragmentProgram.MaxUniformComponents,
- 0 /* FINISHME: Geometry shaders. */
+ ctx->Const.GeometryProgram.MaxUniformComponents
+ };
+
+ const unsigned max_combined_uniform_components[MESA_SHADER_TYPES] = {
+ ctx->Const.VertexProgram.MaxCombinedUniformComponents,
+ ctx->Const.FragmentProgram.MaxCombinedUniformComponents,
+ ctx->Const.GeometryProgram.MaxCombinedUniformComponents
};
const unsigned max_uniform_blocks[MESA_SHADER_TYPES] = {
shader_names[i]);
}
- if (sh->num_uniform_components > max_uniform_components[i]) {
+ if (sh->num_uniform_components > max_default_uniform_components[i]) {
+ if (ctx->Const.GLSLSkipStrictMaxUniformLimitCheck) {
+ linker_warning(prog, "Too many %s shader default uniform block "
+ "components, but the driver will try to optimize "
+ "them out; this is non-portable out-of-spec "
+ "behavior\n",
+ shader_names[i]);
+ } else {
+ linker_error(prog, "Too many %s shader default uniform block "
+ "components",
+ shader_names[i]);
+ }
+ }
+
+ if (sh->num_combined_uniform_components >
+ max_combined_uniform_components[i]) {
if (ctx->Const.GLSLSkipStrictMaxUniformLimitCheck) {
linker_warning(prog, "Too many %s shader uniform components, "
"but the driver will try to optimize them out; "
if (prog->_LinkedShaders[i] == NULL)
continue;
+ if (!validate_interstage_interface_blocks(prog->_LinkedShaders[prev],
+ prog->_LinkedShaders[i])) {
+ linker_error(prog, "interface block mismatch between shader stages\n");
+ goto done;
+ }
+
if (!cross_validate_outputs_to_inputs(prog,
prog->_LinkedShaders[prev],
prog->_LinkedShaders[i]))
prog->LinkStatus = true;
}
+
+ for (unsigned int i = 0; i < MESA_SHADER_TYPES; i++) {
+ if (prog->_LinkedShaders[i] != NULL)
+ lower_named_interface_blocks(mem_ctx, prog->_LinkedShaders[i]);
+ }
+
/* Implement the GLSL 1.30+ rule for discard vs infinite loops Do
* it before optimization because we want most of the checks to get
* dropped thanks to constant propagation.
unsigned max_unroll = ctx->ShaderCompilerOptions[i].MaxUnrollIterations;
- while (do_common_optimization(prog->_LinkedShaders[i]->ir, true, false, max_unroll))
+ while (do_common_optimization(prog->_LinkedShaders[i]->ir, true, false, max_unroll, &ctx->ShaderCompilerOptions[i]))
;
}
if (prog->_LinkedShaders[MESA_SHADER_VERTEX] != NULL) {
link_invalidate_variable_locations(
prog->_LinkedShaders[MESA_SHADER_VERTEX],
- VERT_ATTRIB_GENERIC0, VERT_RESULT_VAR0);
+ VERT_ATTRIB_GENERIC0, VARYING_SLOT_VAR0);
}
/* FINISHME: Geometry shaders not implemented yet */
if (prog->_LinkedShaders[MESA_SHADER_FRAGMENT] != NULL) {
link_invalidate_variable_locations(
prog->_LinkedShaders[MESA_SHADER_FRAGMENT],
- FRAG_ATTRIB_VAR0, FRAG_RESULT_DATA0);
+ VARYING_SLOT_VAR0, FRAG_RESULT_DATA0);
}
/* FINISHME: The value of the max_attribute_index parameter is