diff options
-rw-r--r-- | src/glsl/linker.cpp | 41 |
1 files changed, 40 insertions, 1 deletions
diff --git a/src/glsl/linker.cpp b/src/glsl/linker.cpp index 52a277eb719..ea73c6f9da1 100644 --- a/src/glsl/linker.cpp +++ b/src/glsl/linker.cpp @@ -1977,6 +1977,7 @@ assign_attribute_or_color_locations(gl_shader_program *prog, } to_assign[16]; unsigned num_attr = 0; + unsigned total_attribs_size = 0; foreach_in_list(ir_instruction, node, sh->ir) { ir_variable *const var = node->as_variable(); @@ -2018,12 +2019,41 @@ assign_attribute_or_color_locations(gl_shader_program *prog, } } + const unsigned slots = var->type->count_attribute_slots(); + + /* From GL4.5 core spec, section 11.1.1 (Vertex Attributes): + * + * "A program with more than the value of MAX_VERTEX_ATTRIBS active + * attribute variables may fail to link, unless device-dependent + * optimizations are able to make the program fit within available + * hardware resources. For the purposes of this test, attribute variables + * of the type dvec3, dvec4, dmat2x3, dmat2x4, dmat3, dmat3x4, dmat4x3, + * and dmat4 may count as consuming twice as many attributes as equivalent + * single-precision types. While these types use the same number of + * generic attributes as their single-precision equivalents, + * implementations are permitted to consume two single-precision vectors + * of internal storage for each three- or four-component double-precision + * vector." + * Until someone has a good reason in Mesa, enforce that now. + */ + if (target_index == MESA_SHADER_VERTEX) { + total_attribs_size += slots; + if (var->type->without_array() == glsl_type::dvec3_type || + var->type->without_array() == glsl_type::dvec4_type || + var->type->without_array() == glsl_type::dmat2x3_type || + var->type->without_array() == glsl_type::dmat2x4_type || + var->type->without_array() == glsl_type::dmat3_type || + var->type->without_array() == glsl_type::dmat3x4_type || + var->type->without_array() == glsl_type::dmat4x3_type || + var->type->without_array() == glsl_type::dmat4_type) + total_attribs_size += slots; + } + /* If the variable is not a built-in and has a location statically * assigned in the shader (presumably via a layout qualifier), make sure * that it doesn't collide with other assigned locations. Otherwise, * add it to the list of variables that need linker-assigned locations. */ - const unsigned slots = var->type->count_attribute_slots(); if (var->data.location != -1) { if (var->data.location >= generic_base && var->data.index < 1) { /* From page 61 of the OpenGL 4.0 spec: @@ -2143,6 +2173,15 @@ assign_attribute_or_color_locations(gl_shader_program *prog, num_attr++; } + if (target_index == MESA_SHADER_VERTEX) { + if (total_attribs_size > max_index) { + linker_error(prog, + "attempt to use %d vertex attribute slots only %d available ", + total_attribs_size, max_index); + return false; + } + } + /* If all of the attributes were assigned locations by the application (or * are built-in attributes with fixed locations), return early. This should * be the common case. |