X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;ds=sidebyside;f=src%2Fcompiler%2Fglsl%2Flinker.cpp;h=4dcef2b260e2db93581031ddf0c03d45817d3ba4;hb=8834c74fef4ab405397833e4499b622b6ce9c116;hp=764938bdb6e9a09efefd3239049eed07319e6f71;hpb=2ea021a1ebb768b13c533f6bea56cdfb4a9cc3b3;p=mesa.git diff --git a/src/compiler/glsl/linker.cpp b/src/compiler/glsl/linker.cpp index 764938bdb6e..4dcef2b260e 100644 --- a/src/compiler/glsl/linker.cpp +++ b/src/compiler/glsl/linker.cpp @@ -73,6 +73,7 @@ #include "program.h" #include "program/prog_instruction.h" #include "program/program.h" +#include "util/mesa-sha1.h" #include "util/set.h" #include "util/string_to_uint_map.h" #include "linker.h" @@ -80,6 +81,8 @@ #include "ir_optimization.h" #include "ir_rvalue_visitor.h" #include "ir_uniform.h" +#include "builtin_functions.h" +#include "shader_cache.h" #include "main/shaderobj.h" #include "main/enums.h" @@ -420,7 +423,7 @@ linker_error(gl_shader_program *prog, const char *fmt, ...) ralloc_vasprintf_append(&prog->data->InfoLog, fmt, ap); va_end(ap); - prog->data->LinkStatus = false; + prog->data->LinkStatus = linking_failure; } @@ -553,7 +556,7 @@ analyze_clip_cull_usage(struct gl_shader_program *prog, *clip_distance_array_size = 0; *cull_distance_array_size = 0; - if (prog->Version >= (prog->IsES ? 300 : 130)) { + if (prog->data->Version >= (prog->IsES ? 300 : 130)) { /* From section 7.1 (Vertex Shader Special Variables) of the * GLSL 1.30 spec: * @@ -633,8 +636,8 @@ analyze_clip_cull_usage(struct gl_shader_program *prog, /** * Verify that a vertex shader executable meets all semantic requirements. * - * Also sets prog->Vert.ClipDistanceArraySize and - * prog->Vert.CullDistanceArraySize as a side effect. + * Also sets info.clip_distance_array_size and + * info.cull_distance_array_size as a side effect. * * \param shader Vertex shader executable to be verified */ @@ -672,7 +675,7 @@ validate_vertex_shader_executable(struct gl_shader_program *prog, * All GLSL ES Versions are similar to GLSL 1.40--failing to write to * gl_Position is not an error. */ - if (prog->Version < (prog->IsES ? 300 : 140)) { + if (prog->data->Version < (prog->IsES ? 300 : 140)) { find_assignment_visitor find("gl_Position"); find.run(shader->ir); if (!find.variable_found()) { @@ -689,8 +692,8 @@ validate_vertex_shader_executable(struct gl_shader_program *prog, } analyze_clip_cull_usage(prog, shader, ctx, - &prog->Vert.ClipDistanceArraySize, - &prog->Vert.CullDistanceArraySize); + &shader->Program->info.clip_distance_array_size, + &shader->Program->info.cull_distance_array_size); } void @@ -702,8 +705,8 @@ validate_tess_eval_shader_executable(struct gl_shader_program *prog, return; analyze_clip_cull_usage(prog, shader, ctx, - &prog->TessEval.ClipDistanceArraySize, - &prog->TessEval.CullDistanceArraySize); + &shader->Program->info.clip_distance_array_size, + &shader->Program->info.cull_distance_array_size); } @@ -734,8 +737,8 @@ validate_fragment_shader_executable(struct gl_shader_program *prog, /** * Verify that a geometry shader executable meets all semantic requirements * - * Also sets prog->Geom.VerticesIn, and prog->Geom.ClipDistanceArraySize and - * prog->Geom.CullDistanceArraySize as a side effect. + * Also sets prog->Geom.VerticesIn, and info.clip_distance_array_sizeand + * info.cull_distance_array_size as a side effect. * * \param shader Geometry shader executable to be verified */ @@ -747,12 +750,13 @@ validate_geometry_shader_executable(struct gl_shader_program *prog, if (shader == NULL) return; - unsigned num_vertices = vertices_per_prim(shader->info.Geom.InputType); + unsigned num_vertices = + vertices_per_prim(shader->Program->info.gs.input_primitive); prog->Geom.VerticesIn = num_vertices; analyze_clip_cull_usage(prog, shader, ctx, - &prog->Geom.ClipDistanceArraySize, - &prog->Geom.CullDistanceArraySize); + &shader->Program->info.clip_distance_array_size, + &shader->Program->info.cull_distance_array_size); } /** @@ -802,7 +806,8 @@ validate_geometry_shader_emissions(struct gl_context *ctx, * EmitStreamVertex() or EmitEndPrimitive() are called with a non-zero * stream. */ - if (prog->Geom.UsesStreams && sh->info.Geom.OutputType != GL_POINTS) { + if (prog->Geom.UsesStreams && + sh->Program->info.gs.output_primitive != GL_POINTS) { linker_error(prog, "EmitStreamVertex(n) and EndStreamPrimitive(n) " "with n>0 requires point output\n"); } @@ -880,6 +885,13 @@ cross_validate_globals(struct gl_shader_program *prog, if (var->type->contains_subroutine()) continue; + /* Don't cross validate interface instances. These are only relevant + * inside a shader. The cross validation is done at the Interface Block + * name level. + */ + if (var->is_interface_instance()) + continue; + /* Don't cross validate temporaries that are at global scope. These * will eventually get pulled into the shaders 'main'. */ @@ -892,11 +904,8 @@ cross_validate_globals(struct gl_shader_program *prog, */ ir_variable *const existing = variables->get_variable(var->name); if (existing != NULL) { - /* Check if types match. Interface blocks have some special - * rules so we handle those elsewhere. - */ - if (var->type != existing->type && - !var->is_interface_instance()) { + /* Check if types match. */ + if (var->type != existing->type) { if (!validate_intrastage_arrays(prog, var, existing)) { if (var->type->is_record() && existing->type->is_record() && existing->type->record_compare(var->type)) { @@ -1089,7 +1098,8 @@ cross_validate_globals(struct gl_shader_program *prog, * In GLSL ES 3.00 and ES 3.20, precision qualifier for each block * member should match. */ - if (prog->IsES && (prog->Version != 310 || !var->get_interface_type()) && + if (prog->IsES && (prog->data->Version != 310 || + !var->get_interface_type()) && existing->data.precision != var->data.precision) { linker_error(prog, "declarations for %s `%s` have " "mismatching precision qualifiers\n", @@ -1136,10 +1146,10 @@ interstage_cross_validate_uniform_blocks(struct gl_shader_program *prog, if (prog->_LinkedShaders[i]) { if (validate_ssbo) { max_num_buffer_blocks += - prog->_LinkedShaders[i]->NumShaderStorageBlocks; + prog->_LinkedShaders[i]->Program->info.num_ssbos; } else { max_num_buffer_blocks += - prog->_LinkedShaders[i]->NumUniformBlocks; + prog->_LinkedShaders[i]->Program->info.num_ubos; } } } @@ -1157,11 +1167,11 @@ interstage_cross_validate_uniform_blocks(struct gl_shader_program *prog, unsigned sh_num_blocks; struct gl_uniform_block **sh_blks; if (validate_ssbo) { - sh_num_blocks = prog->_LinkedShaders[i]->NumShaderStorageBlocks; - sh_blks = sh->ShaderStorageBlocks; + sh_num_blocks = prog->_LinkedShaders[i]->Program->info.num_ssbos; + sh_blks = sh->Program->sh.ShaderStorageBlocks; } else { - sh_num_blocks = prog->_LinkedShaders[i]->NumUniformBlocks; - sh_blks = sh->UniformBlocks; + sh_num_blocks = prog->_LinkedShaders[i]->Program->info.num_ubos; + sh_blks = sh->Program->sh.UniformBlocks; } for (unsigned int j = 0; j < sh_num_blocks; j++) { @@ -1175,6 +1185,12 @@ interstage_cross_validate_uniform_blocks(struct gl_shader_program *prog, for (unsigned k = 0; k <= i; k++) { delete[] InterfaceBlockStageIndex[k]; } + + /* Reset the block count. This will help avoid various segfaults + * from api calls that assume the array exists due to the count + * being non-zero. + */ + *num_blks = 0; return false; } @@ -1193,7 +1209,8 @@ interstage_cross_validate_uniform_blocks(struct gl_shader_program *prog, struct gl_linked_shader *sh = prog->_LinkedShaders[i]; struct gl_uniform_block **sh_blks = validate_ssbo ? - sh->ShaderStorageBlocks : sh->UniformBlocks; + sh->Program->sh.ShaderStorageBlocks : + sh->Program->sh.UniformBlocks; blks[j].stageref |= sh_blks[stage_index]->stageref; sh_blks[stage_index] = &blks[j]; @@ -1585,6 +1602,29 @@ private: hash_table *unnamed_interfaces; }; +static bool +validate_xfb_buffer_stride(struct gl_context *ctx, unsigned idx, + struct gl_shader_program *prog) +{ + /* We will validate doubles at a later stage */ + if (prog->TransformFeedback.BufferStride[idx] % 4) { + linker_error(prog, "invalid qualifier xfb_stride=%d must be a " + "multiple of 4 or if its applied to a type that is " + "or contains a double a multiple of 8.", + prog->TransformFeedback.BufferStride[idx]); + return false; + } + + if (prog->TransformFeedback.BufferStride[idx] / 4 > + ctx->Const.MaxTransformFeedbackInterleavedComponents) { + linker_error(prog, "The MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS " + "limit has been exceeded."); + return false; + } + + return true; +} + /** * Check for conflicting xfb_stride default qualifiers and store buffer stride * for later use. @@ -1597,54 +1637,28 @@ link_xfb_stride_layout_qualifiers(struct gl_context *ctx, unsigned num_shaders) { for (unsigned i = 0; i < MAX_FEEDBACK_BUFFERS; i++) { - linked_shader->info.TransformFeedback.BufferStride[i] = 0; + prog->TransformFeedback.BufferStride[i] = 0; } for (unsigned i = 0; i < num_shaders; i++) { struct gl_shader *shader = shader_list[i]; for (unsigned j = 0; j < MAX_FEEDBACK_BUFFERS; j++) { - if (shader->info.TransformFeedback.BufferStride[j]) { - if (linked_shader->info.TransformFeedback.BufferStride[j] != 0 && - shader->info.TransformFeedback.BufferStride[j] != 0 && - linked_shader->info.TransformFeedback.BufferStride[j] != - shader->info.TransformFeedback.BufferStride[j]) { + if (shader->TransformFeedbackBufferStride[j]) { + if (prog->TransformFeedback.BufferStride[j] == 0) { + prog->TransformFeedback.BufferStride[j] = + shader->TransformFeedbackBufferStride[j]; + if (!validate_xfb_buffer_stride(ctx, j, prog)) + return; + } else if (prog->TransformFeedback.BufferStride[j] != + shader->TransformFeedbackBufferStride[j]){ linker_error(prog, "intrastage shaders defined with conflicting " "xfb_stride for buffer %d (%d and %d)\n", j, - linked_shader-> - info.TransformFeedback.BufferStride[j], - shader->info.TransformFeedback.BufferStride[j]); + prog->TransformFeedback.BufferStride[j], + shader->TransformFeedbackBufferStride[j]); return; } - - if (shader->info.TransformFeedback.BufferStride[j]) - linked_shader->info.TransformFeedback.BufferStride[j] = - shader->info.TransformFeedback.BufferStride[j]; - } - } - } - - for (unsigned j = 0; j < MAX_FEEDBACK_BUFFERS; j++) { - if (linked_shader->info.TransformFeedback.BufferStride[j]) { - prog->TransformFeedback.BufferStride[j] = - linked_shader->info.TransformFeedback.BufferStride[j]; - - /* We will validate doubles at a later stage */ - if (prog->TransformFeedback.BufferStride[j] % 4) { - linker_error(prog, "invalid qualifier xfb_stride=%d must be a " - "multiple of 4 or if its applied to a type that is " - "or contains a double a multiple of 8.", - prog->TransformFeedback.BufferStride[j]); - return; - } - - if (prog->TransformFeedback.BufferStride[j] / 4 > - ctx->Const.MaxTransformFeedbackInterleavedComponents) { - linker_error(prog, - "The MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS " - "limit has been exceeded."); - return; } } } @@ -1657,15 +1671,15 @@ link_xfb_stride_layout_qualifiers(struct gl_context *ctx, */ static void link_tcs_out_layout_qualifiers(struct gl_shader_program *prog, - struct gl_linked_shader *linked_shader, + struct gl_program *gl_prog, struct gl_shader **shader_list, unsigned num_shaders) { - linked_shader->info.TessCtrl.VerticesOut = 0; - - if (linked_shader->Stage != MESA_SHADER_TESS_CTRL) + if (gl_prog->info.stage != MESA_SHADER_TESS_CTRL) return; + gl_prog->info.tess.tcs_vertices_out = 0; + /* From the GLSL 4.0 spec (chapter 4.3.8.2): * * "All tessellation control shader layout declarations in a program @@ -1680,16 +1694,16 @@ link_tcs_out_layout_qualifiers(struct gl_shader_program *prog, struct gl_shader *shader = shader_list[i]; if (shader->info.TessCtrl.VerticesOut != 0) { - if (linked_shader->info.TessCtrl.VerticesOut != 0 && - linked_shader->info.TessCtrl.VerticesOut != - shader->info.TessCtrl.VerticesOut) { + if (gl_prog->info.tess.tcs_vertices_out != 0 && + gl_prog->info.tess.tcs_vertices_out != + (unsigned) shader->info.TessCtrl.VerticesOut) { linker_error(prog, "tessellation control shader defined with " "conflicting output vertex count (%d and %d)\n", - linked_shader->info.TessCtrl.VerticesOut, + gl_prog->info.tess.tcs_vertices_out, shader->info.TessCtrl.VerticesOut); return; } - linked_shader->info.TessCtrl.VerticesOut = + gl_prog->info.tess.tcs_vertices_out = shader->info.TessCtrl.VerticesOut; } } @@ -1698,7 +1712,7 @@ link_tcs_out_layout_qualifiers(struct gl_shader_program *prog, * since we already know we're in the right type of shader program * for doing it. */ - if (linked_shader->info.TessCtrl.VerticesOut == 0) { + if (gl_prog->info.tess.tcs_vertices_out == 0) { linker_error(prog, "tessellation control shader didn't declare " "vertices out layout qualifier\n"); return; @@ -1714,18 +1728,19 @@ link_tcs_out_layout_qualifiers(struct gl_shader_program *prog, */ static void link_tes_in_layout_qualifiers(struct gl_shader_program *prog, - struct gl_linked_shader *linked_shader, + struct gl_program *gl_prog, struct gl_shader **shader_list, unsigned num_shaders) { - linked_shader->info.TessEval.PrimitiveMode = PRIM_UNKNOWN; - linked_shader->info.TessEval.Spacing = 0; - linked_shader->info.TessEval.VertexOrder = 0; - linked_shader->info.TessEval.PointMode = -1; - - if (linked_shader->Stage != MESA_SHADER_TESS_EVAL) + if (gl_prog->info.stage != MESA_SHADER_TESS_EVAL) return; + int point_mode = -1; + unsigned vertex_order = 0; + + gl_prog->info.tess.primitive_mode = PRIM_UNKNOWN; + gl_prog->info.tess.spacing = TESS_SPACING_UNSPECIFIED; + /* From the GLSL 4.0 spec (chapter 4.3.8.1): * * "At least one tessellation evaluation shader (compilation unit) in @@ -1744,49 +1759,45 @@ link_tes_in_layout_qualifiers(struct gl_shader_program *prog, struct gl_shader *shader = shader_list[i]; if (shader->info.TessEval.PrimitiveMode != PRIM_UNKNOWN) { - if (linked_shader->info.TessEval.PrimitiveMode != PRIM_UNKNOWN && - linked_shader->info.TessEval.PrimitiveMode != + if (gl_prog->info.tess.primitive_mode != PRIM_UNKNOWN && + gl_prog->info.tess.primitive_mode != shader->info.TessEval.PrimitiveMode) { linker_error(prog, "tessellation evaluation shader defined with " "conflicting input primitive modes.\n"); return; } - linked_shader->info.TessEval.PrimitiveMode = shader->info.TessEval.PrimitiveMode; + gl_prog->info.tess.primitive_mode = + shader->info.TessEval.PrimitiveMode; } if (shader->info.TessEval.Spacing != 0) { - if (linked_shader->info.TessEval.Spacing != 0 && - linked_shader->info.TessEval.Spacing != + if (gl_prog->info.tess.spacing != 0 && gl_prog->info.tess.spacing != shader->info.TessEval.Spacing) { linker_error(prog, "tessellation evaluation shader defined with " "conflicting vertex spacing.\n"); return; } - linked_shader->info.TessEval.Spacing = shader->info.TessEval.Spacing; + gl_prog->info.tess.spacing = shader->info.TessEval.Spacing; } if (shader->info.TessEval.VertexOrder != 0) { - if (linked_shader->info.TessEval.VertexOrder != 0 && - linked_shader->info.TessEval.VertexOrder != - shader->info.TessEval.VertexOrder) { + if (vertex_order != 0 && + vertex_order != shader->info.TessEval.VertexOrder) { linker_error(prog, "tessellation evaluation shader defined with " "conflicting ordering.\n"); return; } - linked_shader->info.TessEval.VertexOrder = - shader->info.TessEval.VertexOrder; + vertex_order = shader->info.TessEval.VertexOrder; } if (shader->info.TessEval.PointMode != -1) { - if (linked_shader->info.TessEval.PointMode != -1 && - linked_shader->info.TessEval.PointMode != - shader->info.TessEval.PointMode) { + if (point_mode != -1 && + point_mode != shader->info.TessEval.PointMode) { linker_error(prog, "tessellation evaluation shader defined with " "conflicting point modes.\n"); return; } - linked_shader->info.TessEval.PointMode = - shader->info.TessEval.PointMode; + point_mode = shader->info.TessEval.PointMode; } } @@ -1795,21 +1806,26 @@ link_tes_in_layout_qualifiers(struct gl_shader_program *prog, * since we already know we're in the right type of shader program * for doing it. */ - if (linked_shader->info.TessEval.PrimitiveMode == PRIM_UNKNOWN) { + if (gl_prog->info.tess.primitive_mode == PRIM_UNKNOWN) { linker_error(prog, "tessellation evaluation shader didn't declare input " "primitive modes.\n"); return; } - if (linked_shader->info.TessEval.Spacing == 0) - linked_shader->info.TessEval.Spacing = GL_EQUAL; + if (gl_prog->info.tess.spacing == TESS_SPACING_UNSPECIFIED) + gl_prog->info.tess.spacing = TESS_SPACING_EQUAL; + + if (vertex_order == 0 || vertex_order == GL_CCW) + gl_prog->info.tess.ccw = true; + else + gl_prog->info.tess.ccw = false; - if (linked_shader->info.TessEval.VertexOrder == 0) - linked_shader->info.TessEval.VertexOrder = GL_CCW; - if (linked_shader->info.TessEval.PointMode == -1) - linked_shader->info.TessEval.PointMode = GL_FALSE; + if (point_mode == -1 || point_mode == GL_FALSE) + gl_prog->info.tess.point_mode = false; + else + gl_prog->info.tess.point_mode = true; } @@ -1824,14 +1840,14 @@ link_fs_inout_layout_qualifiers(struct gl_shader_program *prog, struct gl_shader **shader_list, unsigned num_shaders) { - linked_shader->info.redeclares_gl_fragcoord = false; - linked_shader->info.uses_gl_fragcoord = false; - linked_shader->info.origin_upper_left = false; - linked_shader->info.pixel_center_integer = false; - linked_shader->info.BlendSupport = 0; + bool redeclares_gl_fragcoord = false; + bool uses_gl_fragcoord = false; + bool origin_upper_left = false; + bool pixel_center_integer = false; if (linked_shader->Stage != MESA_SHADER_FRAGMENT || - (prog->Version < 150 && !prog->ARB_fragment_coord_conventions_enable)) + (prog->data->Version < 150 && + !prog->ARB_fragment_coord_conventions_enable)) return; for (unsigned i = 0; i < num_shaders; i++) { @@ -1842,12 +1858,10 @@ link_fs_inout_layout_qualifiers(struct gl_shader_program *prog, * it must be redeclared in all the fragment shaders in that program * that have a static use gl_FragCoord." */ - if ((linked_shader->info.redeclares_gl_fragcoord - && !shader->info.redeclares_gl_fragcoord - && shader->info.uses_gl_fragcoord) - || (shader->info.redeclares_gl_fragcoord - && !linked_shader->info.redeclares_gl_fragcoord - && linked_shader->info.uses_gl_fragcoord)) { + if ((redeclares_gl_fragcoord && !shader->redeclares_gl_fragcoord && + shader->uses_gl_fragcoord) + || (shader->redeclares_gl_fragcoord && !redeclares_gl_fragcoord && + uses_gl_fragcoord)) { linker_error(prog, "fragment shader defined with conflicting " "layout qualifiers for gl_FragCoord\n"); } @@ -1857,12 +1871,9 @@ link_fs_inout_layout_qualifiers(struct gl_shader_program *prog, * "All redeclarations of gl_FragCoord in all fragment shaders in a * single program must have the same set of qualifiers." */ - if (linked_shader->info.redeclares_gl_fragcoord && - shader->info.redeclares_gl_fragcoord && - (shader->info.origin_upper_left != - linked_shader->info.origin_upper_left || - shader->info.pixel_center_integer != - linked_shader->info.pixel_center_integer)) { + if (redeclares_gl_fragcoord && shader->redeclares_gl_fragcoord && + (shader->origin_upper_left != origin_upper_left || + shader->pixel_center_integer != pixel_center_integer)) { linker_error(prog, "fragment shader defined with conflicting " "layout qualifiers for gl_FragCoord\n"); } @@ -1872,22 +1883,20 @@ link_fs_inout_layout_qualifiers(struct gl_shader_program *prog, * are multiple redeclarations, all the fields except uses_gl_fragcoord * are already known to be the same. */ - if (shader->info.redeclares_gl_fragcoord || - shader->info.uses_gl_fragcoord) { - linked_shader->info.redeclares_gl_fragcoord = - shader->info.redeclares_gl_fragcoord; - linked_shader->info.uses_gl_fragcoord = - linked_shader->info.uses_gl_fragcoord || - shader->info.uses_gl_fragcoord; - linked_shader->info.origin_upper_left = - shader->info.origin_upper_left; - linked_shader->info.pixel_center_integer = - shader->info.pixel_center_integer; + if (shader->redeclares_gl_fragcoord || shader->uses_gl_fragcoord) { + redeclares_gl_fragcoord = shader->redeclares_gl_fragcoord; + uses_gl_fragcoord |= shader->uses_gl_fragcoord; + origin_upper_left = shader->origin_upper_left; + pixel_center_integer = shader->pixel_center_integer; } - linked_shader->info.EarlyFragmentTests |= - shader->info.EarlyFragmentTests; - linked_shader->info.BlendSupport |= shader->info.BlendSupport; + linked_shader->Program->info.fs.early_fragment_tests |= + shader->EarlyFragmentTests || shader->PostDepthCoverage; + linked_shader->Program->info.fs.inner_coverage |= shader->InnerCoverage; + linked_shader->Program->info.fs.post_depth_coverage |= + shader->PostDepthCoverage; + + linked_shader->Program->sh.fs.BlendSupport |= shader->BlendSupport; } } @@ -1898,21 +1907,23 @@ link_fs_inout_layout_qualifiers(struct gl_shader_program *prog, */ static void link_gs_inout_layout_qualifiers(struct gl_shader_program *prog, - struct gl_linked_shader *linked_shader, + struct gl_program *gl_prog, struct gl_shader **shader_list, unsigned num_shaders) { - linked_shader->info.Geom.VerticesOut = -1; - linked_shader->info.Geom.Invocations = 0; - linked_shader->info.Geom.InputType = PRIM_UNKNOWN; - linked_shader->info.Geom.OutputType = PRIM_UNKNOWN; - /* No in/out qualifiers defined for anything but GLSL 1.50+ * geometry shaders so far. */ - if (linked_shader->Stage != MESA_SHADER_GEOMETRY || prog->Version < 150) + if (gl_prog->info.stage != MESA_SHADER_GEOMETRY || + prog->data->Version < 150) return; + int vertices_out = -1; + + gl_prog->info.gs.invocations = 0; + gl_prog->info.gs.input_primitive = PRIM_UNKNOWN; + gl_prog->info.gs.output_primitive = PRIM_UNKNOWN; + /* From the GLSL 1.50 spec, page 46: * * "All geometry shader output layout declarations in a program @@ -1927,51 +1938,49 @@ link_gs_inout_layout_qualifiers(struct gl_shader_program *prog, struct gl_shader *shader = shader_list[i]; if (shader->info.Geom.InputType != PRIM_UNKNOWN) { - if (linked_shader->info.Geom.InputType != PRIM_UNKNOWN && - linked_shader->info.Geom.InputType != + if (gl_prog->info.gs.input_primitive != PRIM_UNKNOWN && + gl_prog->info.gs.input_primitive != shader->info.Geom.InputType) { linker_error(prog, "geometry shader defined with conflicting " "input types\n"); return; } - linked_shader->info.Geom.InputType = shader->info.Geom.InputType; + gl_prog->info.gs.input_primitive = shader->info.Geom.InputType; } if (shader->info.Geom.OutputType != PRIM_UNKNOWN) { - if (linked_shader->info.Geom.OutputType != PRIM_UNKNOWN && - linked_shader->info.Geom.OutputType != + if (gl_prog->info.gs.output_primitive != PRIM_UNKNOWN && + gl_prog->info.gs.output_primitive != shader->info.Geom.OutputType) { linker_error(prog, "geometry shader defined with conflicting " "output types\n"); return; } - linked_shader->info.Geom.OutputType = shader->info.Geom.OutputType; + gl_prog->info.gs.output_primitive = shader->info.Geom.OutputType; } if (shader->info.Geom.VerticesOut != -1) { - if (linked_shader->info.Geom.VerticesOut != -1 && - linked_shader->info.Geom.VerticesOut != - shader->info.Geom.VerticesOut) { + if (vertices_out != -1 && + vertices_out != shader->info.Geom.VerticesOut) { linker_error(prog, "geometry shader defined with conflicting " "output vertex count (%d and %d)\n", - linked_shader->info.Geom.VerticesOut, - shader->info.Geom.VerticesOut); + vertices_out, shader->info.Geom.VerticesOut); return; } - linked_shader->info.Geom.VerticesOut = shader->info.Geom.VerticesOut; + vertices_out = shader->info.Geom.VerticesOut; } if (shader->info.Geom.Invocations != 0) { - if (linked_shader->info.Geom.Invocations != 0 && - linked_shader->info.Geom.Invocations != - shader->info.Geom.Invocations) { + if (gl_prog->info.gs.invocations != 0 && + gl_prog->info.gs.invocations != + (unsigned) shader->info.Geom.Invocations) { linker_error(prog, "geometry shader defined with conflicting " "invocation count (%d and %d)\n", - linked_shader->info.Geom.Invocations, + gl_prog->info.gs.invocations, shader->info.Geom.Invocations); return; } - linked_shader->info.Geom.Invocations = shader->info.Geom.Invocations; + gl_prog->info.gs.invocations = shader->info.Geom.Invocations; } } @@ -1979,26 +1988,28 @@ link_gs_inout_layout_qualifiers(struct gl_shader_program *prog, * since we already know we're in the right type of shader program * for doing it. */ - if (linked_shader->info.Geom.InputType == PRIM_UNKNOWN) { + if (gl_prog->info.gs.input_primitive == PRIM_UNKNOWN) { linker_error(prog, "geometry shader didn't declare primitive input type\n"); return; } - if (linked_shader->info.Geom.OutputType == PRIM_UNKNOWN) { + if (gl_prog->info.gs.output_primitive == PRIM_UNKNOWN) { linker_error(prog, "geometry shader didn't declare primitive output type\n"); return; } - if (linked_shader->info.Geom.VerticesOut == -1) { + if (vertices_out == -1) { linker_error(prog, "geometry shader didn't declare max_vertices\n"); return; + } else { + gl_prog->info.gs.vertices_out = vertices_out; } - if (linked_shader->info.Geom.Invocations == 0) - linked_shader->info.Geom.Invocations = 1; + if (gl_prog->info.gs.invocations == 0) + gl_prog->info.gs.invocations = 1; } @@ -2009,21 +2020,21 @@ link_gs_inout_layout_qualifiers(struct gl_shader_program *prog, */ static void link_cs_input_layout_qualifiers(struct gl_shader_program *prog, - struct gl_linked_shader *linked_shader, + struct gl_program *gl_prog, struct gl_shader **shader_list, unsigned num_shaders) { - for (int i = 0; i < 3; i++) - linked_shader->info.Comp.LocalSize[i] = 0; - - linked_shader->info.Comp.LocalSizeVariable = false; - /* This function is called for all shader stages, but it only has an effect * for compute shaders. */ - if (linked_shader->Stage != MESA_SHADER_COMPUTE) + if (gl_prog->info.stage != MESA_SHADER_COMPUTE) return; + for (int i = 0; i < 3; i++) + gl_prog->info.cs.local_size[i] = 0; + + gl_prog->info.cs.local_size_variable = false; + /* From the ARB_compute_shader spec, in the section describing local size * declarations: * @@ -2038,9 +2049,9 @@ link_cs_input_layout_qualifiers(struct gl_shader_program *prog, struct gl_shader *shader = shader_list[sh]; if (shader->info.Comp.LocalSize[0] != 0) { - if (linked_shader->info.Comp.LocalSize[0] != 0) { + if (gl_prog->info.cs.local_size[0] != 0) { for (int i = 0; i < 3; i++) { - if (linked_shader->info.Comp.LocalSize[i] != + if (gl_prog->info.cs.local_size[i] != shader->info.Comp.LocalSize[i]) { linker_error(prog, "compute shader defined with conflicting " "local sizes\n"); @@ -2049,11 +2060,11 @@ link_cs_input_layout_qualifiers(struct gl_shader_program *prog, } } for (int i = 0; i < 3; i++) { - linked_shader->info.Comp.LocalSize[i] = + gl_prog->info.cs.local_size[i] = shader->info.Comp.LocalSize[i]; } } else if (shader->info.Comp.LocalSizeVariable) { - if (linked_shader->info.Comp.LocalSize[0] != 0) { + if (gl_prog->info.cs.local_size[0] != 0) { /* The ARB_compute_variable_group_size spec says: * * If one compute shader attached to a program declares a @@ -2065,7 +2076,7 @@ link_cs_input_layout_qualifiers(struct gl_shader_program *prog, "variable local group size\n"); return; } - linked_shader->info.Comp.LocalSizeVariable = true; + gl_prog->info.cs.local_size_variable = true; } } @@ -2073,17 +2084,12 @@ link_cs_input_layout_qualifiers(struct gl_shader_program *prog, * since we already know we're in the right type of shader program * for doing it. */ - if (linked_shader->info.Comp.LocalSize[0] == 0 && - !linked_shader->info.Comp.LocalSizeVariable) { + if (gl_prog->info.cs.local_size[0] == 0 && + !gl_prog->info.cs.local_size_variable) { linker_error(prog, "compute shader must contain a fixed or a variable " "local group size\n"); return; } - for (int i = 0; i < 3; i++) - prog->Comp.LocalSize[i] = linked_shader->info.Comp.LocalSize[i]; - - prog->Comp.LocalSizeVariable = - linked_shader->info.Comp.LocalSizeVariable; } @@ -2187,19 +2193,23 @@ link_intrastage_shaders(void *mem_ctx, return NULL; } - gl_linked_shader *linked = ctx->Driver.NewShader(shader_list[0]->Stage); + gl_linked_shader *linked = rzalloc(NULL, struct gl_linked_shader); + linked->Stage = shader_list[0]->Stage; /* Create program and attach it to the linked shader */ struct gl_program *gl_prog = ctx->Driver.NewProgram(ctx, _mesa_shader_stage_to_program(shader_list[0]->Stage), - prog->Name); + prog->Name, false); if (!gl_prog) { - prog->data->LinkStatus = false; + prog->data->LinkStatus = linking_failure; _mesa_delete_linked_shader(ctx, linked); return NULL; } + if (!prog->data->cache_fallback) + _mesa_reference_shader_program_data(ctx, &gl_prog->sh.data, prog->data); + /* Don't use _mesa_reference_program() just take ownership */ linked->Program = gl_prog; @@ -2207,10 +2217,10 @@ link_intrastage_shaders(void *mem_ctx, clone_ir_list(mem_ctx, linked->ir, main->ir); link_fs_inout_layout_qualifiers(prog, linked, shader_list, num_shaders); - link_tcs_out_layout_qualifiers(prog, linked, shader_list, num_shaders); - link_tes_in_layout_qualifiers(prog, linked, shader_list, num_shaders); - link_gs_inout_layout_qualifiers(prog, linked, shader_list, num_shaders); - link_cs_input_layout_qualifiers(prog, linked, shader_list, num_shaders); + link_tcs_out_layout_qualifiers(prog, gl_prog, shader_list, num_shaders); + link_tes_in_layout_qualifiers(prog, gl_prog, shader_list, num_shaders); + link_gs_inout_layout_qualifiers(prog, gl_prog, shader_list, num_shaders); + link_cs_input_layout_qualifiers(prog, gl_prog, shader_list, num_shaders); link_xfb_stride_layout_qualifiers(ctx, prog, linked, shader_list, num_shaders); @@ -2252,32 +2262,34 @@ link_intrastage_shaders(void *mem_ctx, v.run(linked->ir); v.fixup_unnamed_interface_types(); - /* Link up uniform blocks defined within this stage. */ - link_uniform_blocks(mem_ctx, ctx, prog, linked, &ubo_blocks, - &num_ubo_blocks, &ssbo_blocks, &num_ssbo_blocks); + if (!prog->data->cache_fallback) { + /* Link up uniform blocks defined within this stage. */ + link_uniform_blocks(mem_ctx, ctx, prog, linked, &ubo_blocks, + &num_ubo_blocks, &ssbo_blocks, &num_ssbo_blocks); - if (!prog->data->LinkStatus) { - _mesa_delete_linked_shader(ctx, linked); - return NULL; - } - - /* Copy ubo blocks to linked shader list */ - linked->UniformBlocks = - ralloc_array(linked, gl_uniform_block *, num_ubo_blocks); - ralloc_steal(linked, ubo_blocks); - for (unsigned i = 0; i < num_ubo_blocks; i++) { - linked->UniformBlocks[i] = &ubo_blocks[i]; - } - linked->NumUniformBlocks = num_ubo_blocks; + if (!prog->data->LinkStatus) { + _mesa_delete_linked_shader(ctx, linked); + return NULL; + } - /* Copy ssbo blocks to linked shader list */ - linked->ShaderStorageBlocks = - ralloc_array(linked, gl_uniform_block *, num_ssbo_blocks); - ralloc_steal(linked, ssbo_blocks); - for (unsigned i = 0; i < num_ssbo_blocks; i++) { - linked->ShaderStorageBlocks[i] = &ssbo_blocks[i]; + /* Copy ubo blocks to linked shader list */ + linked->Program->sh.UniformBlocks = + ralloc_array(linked, gl_uniform_block *, num_ubo_blocks); + ralloc_steal(linked, ubo_blocks); + for (unsigned i = 0; i < num_ubo_blocks; i++) { + linked->Program->sh.UniformBlocks[i] = &ubo_blocks[i]; + } + linked->Program->info.num_ubos = num_ubo_blocks; + + /* Copy ssbo blocks to linked shader list */ + linked->Program->sh.ShaderStorageBlocks = + ralloc_array(linked, gl_uniform_block *, num_ssbo_blocks); + ralloc_steal(linked, ssbo_blocks); + for (unsigned i = 0; i < num_ssbo_blocks; i++) { + linked->Program->sh.ShaderStorageBlocks[i] = &ssbo_blocks[i]; + } + linked->Program->info.num_ssbos = num_ssbo_blocks; } - linked->NumShaderStorageBlocks = num_ssbo_blocks; /* At this point linked should contain all of the linked IR, so * validate it to make sure nothing went wrong. @@ -2286,7 +2298,8 @@ link_intrastage_shaders(void *mem_ctx, /* Set the size of geometry shader input arrays */ if (linked->Stage == MESA_SHADER_GEOMETRY) { - unsigned num_vertices = vertices_per_prim(linked->info.Geom.InputType); + unsigned num_vertices = + vertices_per_prim(gl_prog->info.gs.input_primitive); array_resize_visitor input_resize_visitor(num_vertices, prog, MESA_SHADER_GEOMETRY); foreach_in_list(ir_instruction, ir, linked->ir) { @@ -2420,7 +2433,7 @@ resize_tes_inputs(struct gl_context *ctx, * known until draw time. */ const int num_vertices = tcs - ? tcs->info.TessCtrl.VerticesOut + ? tcs->Program->info.tess.tcs_vertices_out : ctx->Const.MaxPatchVertices; array_resize_visitor input_resize_visitor(num_vertices, prog, @@ -2806,7 +2819,7 @@ assign_attribute_or_color_locations(void *mem_ctx, } } } else if (target_index == MESA_SHADER_FRAGMENT || - (prog->IsES && prog->Version >= 300)) { + (prog->IsES && prog->data->Version >= 300)) { linker_error(prog, "overlapping location is assigned " "to %s `%s' %d %d %d\n", string, var->name, used_locations, use_mask, attr); @@ -3056,7 +3069,8 @@ check_resources(struct gl_context *ctx, struct gl_shader_program *prog) if (sh == NULL) continue; - if (sh->num_samplers > ctx->Const.Program[i].MaxTextureImageUnits) { + if (sh->Program->info.num_textures > + ctx->Const.Program[i].MaxTextureImageUnits) { linker_error(prog, "Too many %s shader texture samplers\n", _mesa_shader_stage_to_string(i)); } @@ -3089,23 +3103,23 @@ check_resources(struct gl_context *ctx, struct gl_shader_program *prog) } } - total_shader_storage_blocks += sh->NumShaderStorageBlocks; - total_uniform_blocks += sh->NumUniformBlocks; + total_shader_storage_blocks += sh->Program->info.num_ssbos; + total_uniform_blocks += sh->Program->info.num_ubos; const unsigned max_uniform_blocks = ctx->Const.Program[i].MaxUniformBlocks; - if (max_uniform_blocks < sh->NumUniformBlocks) { + if (max_uniform_blocks < sh->Program->info.num_ubos) { linker_error(prog, "Too many %s uniform blocks (%d/%d)\n", - _mesa_shader_stage_to_string(i), sh->NumUniformBlocks, - max_uniform_blocks); + _mesa_shader_stage_to_string(i), + sh->Program->info.num_ubos, max_uniform_blocks); } const unsigned max_shader_storage_blocks = ctx->Const.Program[i].MaxShaderStorageBlocks; - if (max_shader_storage_blocks < sh->NumShaderStorageBlocks) { + if (max_shader_storage_blocks < sh->Program->info.num_ssbos) { linker_error(prog, "Too many %s shader storage blocks (%d/%d)\n", _mesa_shader_stage_to_string(i), - sh->NumShaderStorageBlocks, max_shader_storage_blocks); + sh->Program->info.num_ssbos, max_shader_storage_blocks); } } @@ -3147,24 +3161,24 @@ link_calculate_subroutine_compat(struct gl_shader_program *prog) unsigned mask = prog->data->linked_stages; while (mask) { const int i = u_bit_scan(&mask); - struct gl_linked_shader *sh = prog->_LinkedShaders[i]; + struct gl_program *p = prog->_LinkedShaders[i]->Program; - for (unsigned j = 0; j < sh->NumSubroutineUniformRemapTable; j++) { - if (sh->SubroutineUniformRemapTable[j] == INACTIVE_UNIFORM_EXPLICIT_LOCATION) + for (unsigned j = 0; j < p->sh.NumSubroutineUniformRemapTable; j++) { + if (p->sh.SubroutineUniformRemapTable[j] == INACTIVE_UNIFORM_EXPLICIT_LOCATION) continue; - struct gl_uniform_storage *uni = sh->SubroutineUniformRemapTable[j]; + struct gl_uniform_storage *uni = p->sh.SubroutineUniformRemapTable[j]; if (!uni) continue; int count = 0; - if (sh->NumSubroutineFunctions == 0) { + if (p->sh.NumSubroutineFunctions == 0) { linker_error(prog, "subroutine uniform %s defined but no valid functions found\n", uni->type->name); continue; } - for (unsigned f = 0; f < sh->NumSubroutineFunctions; f++) { - struct gl_subroutine_function *fn = &sh->SubroutineFunctions[f]; + for (unsigned f = 0; f < p->sh.NumSubroutineFunctions; f++) { + struct gl_subroutine_function *fn = &p->sh.SubroutineFunctions[f]; for (int k = 0; k < fn->num_compat_types; k++) { if (fn->types[k] == uni->type) { count++; @@ -3183,11 +3197,12 @@ check_subroutine_resources(struct gl_shader_program *prog) unsigned mask = prog->data->linked_stages; while (mask) { const int i = u_bit_scan(&mask); - struct gl_linked_shader *sh = prog->_LinkedShaders[i]; + struct gl_program *p = prog->_LinkedShaders[i]->Program; - if (sh->NumSubroutineUniformRemapTable > MAX_SUBROUTINE_UNIFORM_LOCATIONS) + if (p->sh.NumSubroutineUniformRemapTable > MAX_SUBROUTINE_UNIFORM_LOCATIONS) { linker_error(prog, "Too many %s shader subroutine uniforms\n", _mesa_shader_stage_to_string(i)); + } } } /** @@ -3207,13 +3222,14 @@ check_image_resources(struct gl_context *ctx, struct gl_shader_program *prog) struct gl_linked_shader *sh = prog->_LinkedShaders[i]; if (sh) { - if (sh->NumImages > ctx->Const.Program[i].MaxImageUniforms) + if (sh->Program->info.num_images > ctx->Const.Program[i].MaxImageUniforms) linker_error(prog, "Too many %s shader image uniforms (%u > %u)\n", - _mesa_shader_stage_to_string(i), sh->NumImages, + _mesa_shader_stage_to_string(i), + sh->Program->info.num_images, ctx->Const.Program[i].MaxImageUniforms); - total_image_units += sh->NumImages; - total_shader_storage_blocks += sh->NumShaderStorageBlocks; + total_image_units += sh->Program->info.num_images; + total_shader_storage_blocks += sh->Program->info.num_ssbos; if (i == MESA_SHADER_FRAGMENT) { foreach_in_list(ir_instruction, node, sh->ir) { @@ -3308,36 +3324,36 @@ reserve_explicit_locations(struct gl_shader_program *prog, static bool reserve_subroutine_explicit_locations(struct gl_shader_program *prog, - struct gl_linked_shader *sh, + struct gl_program *p, ir_variable *var) { unsigned slots = var->type->uniform_locations(); unsigned max_loc = var->data.location + slots - 1; /* Resize remap table if locations do not fit in the current one. */ - if (max_loc + 1 > sh->NumSubroutineUniformRemapTable) { - sh->SubroutineUniformRemapTable = - reralloc(sh, sh->SubroutineUniformRemapTable, + if (max_loc + 1 > p->sh.NumSubroutineUniformRemapTable) { + p->sh.SubroutineUniformRemapTable = + reralloc(p, p->sh.SubroutineUniformRemapTable, gl_uniform_storage *, max_loc + 1); - if (!sh->SubroutineUniformRemapTable) { + if (!p->sh.SubroutineUniformRemapTable) { linker_error(prog, "Out of memory during linking.\n"); return false; } /* Initialize allocated space. */ - for (unsigned i = sh->NumSubroutineUniformRemapTable; i < max_loc + 1; i++) - sh->SubroutineUniformRemapTable[i] = NULL; + for (unsigned i = p->sh.NumSubroutineUniformRemapTable; i < max_loc + 1; i++) + p->sh.SubroutineUniformRemapTable[i] = NULL; - sh->NumSubroutineUniformRemapTable = max_loc + 1; + p->sh.NumSubroutineUniformRemapTable = max_loc + 1; } for (unsigned i = 0; i < slots; i++) { unsigned loc = var->data.location + i; /* Check if location is already used. */ - if (sh->SubroutineUniformRemapTable[loc] == INACTIVE_UNIFORM_EXPLICIT_LOCATION) { + if (p->sh.SubroutineUniformRemapTable[loc] == INACTIVE_UNIFORM_EXPLICIT_LOCATION) { /* ARB_explicit_uniform_location specification states: * "No two subroutine uniform variables can have the same location @@ -3354,7 +3370,7 @@ reserve_subroutine_explicit_locations(struct gl_shader_program *prog, /* Initialize location as inactive before optimization * rounds and location assignment. */ - sh->SubroutineUniformRemapTable[loc] = INACTIVE_UNIFORM_EXPLICIT_LOCATION; + p->sh.SubroutineUniformRemapTable[loc] = INACTIVE_UNIFORM_EXPLICIT_LOCATION; } return true; @@ -3364,12 +3380,14 @@ reserve_subroutine_explicit_locations(struct gl_shader_program *prog, * any optimizations happen to handle also inactive uniforms and * inactive array elements that may get trimmed away. */ -static unsigned +static void check_explicit_uniform_locations(struct gl_context *ctx, struct gl_shader_program *prog) { + prog->NumExplicitUniformLocations = 0; + if (!ctx->Extensions.ARB_explicit_uniform_location) - return 0; + return; /* This map is used to detect if overlapping explicit locations * occur with the same uniform (from different stage) or a different one. @@ -3378,16 +3396,16 @@ check_explicit_uniform_locations(struct gl_context *ctx, if (!uniform_map) { linker_error(prog, "Out of memory during linking.\n"); - return 0; + return; } unsigned entries_total = 0; unsigned mask = prog->data->linked_stages; while (mask) { const int i = u_bit_scan(&mask); - struct gl_linked_shader *sh = prog->_LinkedShaders[i]; + struct gl_program *p = prog->_LinkedShaders[i]->Program; - foreach_in_list(ir_instruction, node, sh->ir) { + foreach_in_list(ir_instruction, node, prog->_LinkedShaders[i]->ir) { ir_variable *var = node->as_variable(); if (!var || var->data.mode != ir_var_uniform) continue; @@ -3395,7 +3413,7 @@ check_explicit_uniform_locations(struct gl_context *ctx, if (var->data.explicit_location) { bool ret = false; if (var->type->without_array()->is_subroutine()) - ret = reserve_subroutine_explicit_locations(prog, sh, var); + ret = reserve_subroutine_explicit_locations(prog, p, var); else { int slots = reserve_explicit_locations(prog, uniform_map, var); @@ -3406,7 +3424,7 @@ check_explicit_uniform_locations(struct gl_context *ctx, } if (!ret) { delete uniform_map; - return 0; + return; } } } @@ -3431,7 +3449,7 @@ check_explicit_uniform_locations(struct gl_context *ctx, } delete uniform_map; - return entries_total; + prog->NumExplicitUniformLocations = entries_total; } static bool @@ -3520,25 +3538,25 @@ add_program_resource(struct gl_shader_program *prog, if (_mesa_set_search(resource_set, data)) return true; - prog->ProgramResourceList = + prog->data->ProgramResourceList = reralloc(prog, - prog->ProgramResourceList, + prog->data->ProgramResourceList, gl_program_resource, - prog->NumProgramResourceList + 1); + prog->data->NumProgramResourceList + 1); - if (!prog->ProgramResourceList) { + if (!prog->data->ProgramResourceList) { linker_error(prog, "Out of memory during linking.\n"); return false; } struct gl_program_resource *res = - &prog->ProgramResourceList[prog->NumProgramResourceList]; + &prog->data->ProgramResourceList[prog->data->NumProgramResourceList]; res->Type = type; res->Data = data; res->StageReferences = stages; - prog->NumProgramResourceList++; + prog->data->NumProgramResourceList++; _mesa_set_add(resource_set, data); @@ -3684,8 +3702,7 @@ create_shader_variable(struct gl_shader_program *shProg, * qualifier, except for vertex shader inputs and fragment shader * outputs." */ - if (in->type->base_type == GLSL_TYPE_ATOMIC_UINT || - is_gl_identifier(in->name) || + if (in->type->is_atomic_uint() || is_gl_identifier(in->name) || !(in->data.explicit_location || use_implicit_location)) { out->location = -1; } else { @@ -3706,17 +3723,6 @@ create_shader_variable(struct gl_shader_program *shProg, return out; } -static const glsl_type * -resize_to_max_patch_vertices(const struct gl_context *ctx, - const glsl_type *type) -{ - if (!type) - return NULL; - - return glsl_type::get_array_instance(type->fields.array, - ctx->Const.MaxPatchVertices); -} - static bool add_shader_variable(const struct gl_context *ctx, struct gl_shader_program *shProg, @@ -3727,9 +3733,43 @@ add_shader_variable(const struct gl_context *ctx, bool use_implicit_location, int location, const glsl_type *outermost_struct_type = NULL) { - const bool is_vertex_input = - programInterface == GL_PROGRAM_INPUT && - stage_mask == MESA_SHADER_VERTEX; + const glsl_type *interface_type = var->get_interface_type(); + + if (outermost_struct_type == NULL) { + if (var->data.from_named_ifc_block) { + const char *interface_name = interface_type->name; + + if (interface_type->is_array()) { + /* Issue #16 of the ARB_program_interface_query spec says: + * + * "* If a variable is a member of an interface block without an + * instance name, it is enumerated using just the variable name. + * + * * If a variable is a member of an interface block with an + * instance name, it is enumerated as "BlockName.Member", where + * "BlockName" is the name of the interface block (not the + * instance name) and "Member" is the name of the variable." + * + * In particular, it indicates that it should be "BlockName", + * not "BlockName[array length]". The conformance suite and + * dEQP both require this behavior. + * + * Here, we unwrap the extra array level added by named interface + * block array lowering so we have the correct variable type. We + * also unwrap the interface type when constructing the name. + * + * We leave interface_type the same so that ES 3.x SSO pipeline + * validation can enforce the rules requiring array length to + * match on interface blocks. + */ + type = type->fields.array; + + interface_name = interface_type->fields.array->name; + } + + name = ralloc_asprintf(shProg, "%s.%s", interface_name, name); + } + } switch (type->base_type) { case GLSL_TYPE_STRUCT: { @@ -3756,51 +3796,12 @@ add_shader_variable(const struct gl_context *ctx, outermost_struct_type)) return false; - field_location += - field->type->count_attribute_slots(is_vertex_input); + field_location += field->type->count_attribute_slots(false); } return true; } default: { - const glsl_type *interface_type = var->get_interface_type(); - - /* Unsized (non-patch) TCS output/TES input arrays are implicitly - * sized to gl_MaxPatchVertices. Internally, we shrink them to a - * smaller size. - * - * This can cause trouble with SSO programs. Since the TCS declares - * the number of output vertices, we can always shrink TCS output - * arrays. However, the TES might not be linked with a TCS, in - * which case it won't know the size of the patch. In other words, - * the TCS and TES may disagree on the (smaller) array sizes. This - * can result in the resource names differing across stages, causing - * SSO validation failures and other cascading issues. - * - * Expanding the array size to the full gl_MaxPatchVertices fixes - * these issues. It's also what program interface queries expect, - * as that is the official size of the array. - */ - if (var->data.tess_varying_implicit_sized_array) { - type = resize_to_max_patch_vertices(ctx, type); - interface_type = resize_to_max_patch_vertices(ctx, interface_type); - } - - /* Issue #16 of the ARB_program_interface_query spec says: - * - * "* If a variable is a member of an interface block without an - * instance name, it is enumerated using just the variable name. - * - * * If a variable is a member of an interface block with an instance - * name, it is enumerated as "BlockName.Member", where "BlockName" is - * the name of the interface block (not the instance name) and - * "Member" is the name of the variable." - */ - const char *prefixed_name = (var->data.from_named_ifc_block && - !is_gl_identifier(var->name)) - ? ralloc_asprintf(shProg, "%s.%s", interface_type->name, name) - : name; - /* The ARB_program_interface_query spec says: * * "For an active variable declared as a single instance of a basic @@ -3808,8 +3809,7 @@ add_shader_variable(const struct gl_context *ctx, * from the shader source." */ gl_shader_variable *sha_v = - create_shader_variable(shProg, var, prefixed_name, type, - interface_type, + create_shader_variable(shProg, var, name, type, interface_type, use_implicit_location, location, outermost_struct_type); if (!sha_v) @@ -4167,10 +4167,10 @@ build_program_resource_list(struct gl_context *ctx, struct gl_shader_program *shProg) { /* Rebuild resource list. */ - if (shProg->ProgramResourceList) { - ralloc_free(shProg->ProgramResourceList); - shProg->ProgramResourceList = NULL; - shProg->NumProgramResourceList = 0; + if (shProg->data->ProgramResourceList) { + ralloc_free(shProg->data->ProgramResourceList); + shProg->data->ProgramResourceList = NULL; + shProg->data->NumProgramResourceList = 0; } int input_stage = MESA_SHADER_STAGES, output_stage = 0; @@ -4218,26 +4218,29 @@ build_program_resource_list(struct gl_context *ctx, output_stage, GL_PROGRAM_OUTPUT)) return; - /* Add transform feedback varyings. */ - if (shProg->LinkedTransformFeedback.NumVarying > 0) { - for (int i = 0; i < shProg->LinkedTransformFeedback.NumVarying; i++) { - if (!add_program_resource(shProg, resource_set, - GL_TRANSFORM_FEEDBACK_VARYING, - &shProg->LinkedTransformFeedback.Varyings[i], - 0)) - return; + if (shProg->last_vert_prog) { + struct gl_transform_feedback_info *linked_xfb = + shProg->last_vert_prog->sh.LinkedTransformFeedback; + + /* Add transform feedback varyings. */ + if (linked_xfb->NumVarying > 0) { + for (int i = 0; i < linked_xfb->NumVarying; i++) { + if (!add_program_resource(shProg, resource_set, + GL_TRANSFORM_FEEDBACK_VARYING, + &linked_xfb->Varyings[i], 0)) + return; + } } - } - /* Add transform feedback buffers. */ - for (unsigned i = 0; i < ctx->Const.MaxTransformFeedbackBuffers; i++) { - if ((shProg->LinkedTransformFeedback.ActiveBuffers >> i) & 1) { - shProg->LinkedTransformFeedback.Buffers[i].Binding = i; - if (!add_program_resource(shProg, resource_set, - GL_TRANSFORM_FEEDBACK_BUFFER, - &shProg->LinkedTransformFeedback.Buffers[i], - 0)) - return; + /* Add transform feedback buffers. */ + for (unsigned i = 0; i < ctx->Const.MaxTransformFeedbackBuffers; i++) { + if ((linked_xfb->ActiveBuffers >> i) & 1) { + linked_xfb->Buffers[i].Binding = i; + if (!add_program_resource(shProg, resource_set, + GL_TRANSFORM_FEEDBACK_BUFFER, + &linked_xfb->Buffers[i], 0)) + return; + } } } @@ -4318,12 +4321,12 @@ build_program_resource_list(struct gl_context *ctx, unsigned mask = shProg->data->linked_stages; while (mask) { const int i = u_bit_scan(&mask); - struct gl_linked_shader *sh = shProg->_LinkedShaders[i]; + struct gl_program *p = shProg->_LinkedShaders[i]->Program; GLuint type = _mesa_shader_stage_to_subroutine((gl_shader_stage)i); - for (unsigned j = 0; j < sh->NumSubroutineFunctions; j++) { + for (unsigned j = 0; j < p->sh.NumSubroutineFunctions; j++) { if (!add_program_resource(shProg, resource_set, - type, &sh->SubroutineFunctions[j], 0)) + type, &p->sh.SubroutineFunctions[j], 0)) return; } } @@ -4355,10 +4358,12 @@ validate_sampler_array_indexing(struct gl_context *ctx, "expressions is forbidden in GLSL %s %u"; /* Backend has indicated that it has no dynamic indexing support. */ if (no_dynamic_indexing) { - linker_error(prog, msg, prog->IsES ? "ES" : "", prog->Version); + linker_error(prog, msg, prog->IsES ? "ES" : "", + prog->data->Version); return false; } else { - linker_warning(prog, msg, prog->IsES ? "ES" : "", prog->Version); + linker_warning(prog, msg, prog->IsES ? "ES" : "", + prog->data->Version); } } } @@ -4371,33 +4376,33 @@ link_assign_subroutine_types(struct gl_shader_program *prog) unsigned mask = prog->data->linked_stages; while (mask) { const int i = u_bit_scan(&mask); - gl_linked_shader *sh = prog->_LinkedShaders[i]; + gl_program *p = prog->_LinkedShaders[i]->Program; - sh->MaxSubroutineFunctionIndex = 0; - foreach_in_list(ir_instruction, node, sh->ir) { + p->sh.MaxSubroutineFunctionIndex = 0; + foreach_in_list(ir_instruction, node, prog->_LinkedShaders[i]->ir) { ir_function *fn = node->as_function(); if (!fn) continue; if (fn->is_subroutine) - sh->NumSubroutineUniformTypes++; + p->sh.NumSubroutineUniformTypes++; if (!fn->num_subroutine_types) continue; /* these should have been calculated earlier. */ assert(fn->subroutine_index != -1); - if (sh->NumSubroutineFunctions + 1 > MAX_SUBROUTINES) { + if (p->sh.NumSubroutineFunctions + 1 > MAX_SUBROUTINES) { linker_error(prog, "Too many subroutine functions declared.\n"); return; } - sh->SubroutineFunctions = reralloc(sh, sh->SubroutineFunctions, + p->sh.SubroutineFunctions = reralloc(p, p->sh.SubroutineFunctions, struct gl_subroutine_function, - sh->NumSubroutineFunctions + 1); - sh->SubroutineFunctions[sh->NumSubroutineFunctions].name = ralloc_strdup(sh, fn->name); - sh->SubroutineFunctions[sh->NumSubroutineFunctions].num_compat_types = fn->num_subroutine_types; - sh->SubroutineFunctions[sh->NumSubroutineFunctions].types = - ralloc_array(sh, const struct glsl_type *, + p->sh.NumSubroutineFunctions + 1); + p->sh.SubroutineFunctions[p->sh.NumSubroutineFunctions].name = ralloc_strdup(p, fn->name); + p->sh.SubroutineFunctions[p->sh.NumSubroutineFunctions].num_compat_types = fn->num_subroutine_types; + p->sh.SubroutineFunctions[p->sh.NumSubroutineFunctions].types = + ralloc_array(p, const struct glsl_type *, fn->num_subroutine_types); /* From Section 4.4.4(Subroutine Function Layout Qualifiers) of the @@ -4407,23 +4412,23 @@ link_assign_subroutine_types(struct gl_shader_program *prog) * given a unique index, otherwise a compile or link error will be * generated." */ - for (unsigned j = 0; j < sh->NumSubroutineFunctions; j++) { - if (sh->SubroutineFunctions[j].index != -1 && - sh->SubroutineFunctions[j].index == fn->subroutine_index) { + for (unsigned j = 0; j < p->sh.NumSubroutineFunctions; j++) { + if (p->sh.SubroutineFunctions[j].index != -1 && + p->sh.SubroutineFunctions[j].index == fn->subroutine_index) { linker_error(prog, "each subroutine index qualifier in the " "shader must be unique\n"); return; } } - sh->SubroutineFunctions[sh->NumSubroutineFunctions].index = + p->sh.SubroutineFunctions[p->sh.NumSubroutineFunctions].index = fn->subroutine_index; - if (fn->subroutine_index > (int)sh->MaxSubroutineFunctionIndex) - sh->MaxSubroutineFunctionIndex = fn->subroutine_index; + if (fn->subroutine_index > (int)p->sh.MaxSubroutineFunctionIndex) + p->sh.MaxSubroutineFunctionIndex = fn->subroutine_index; for (int j = 0; j < fn->num_subroutine_types; j++) - sh->SubroutineFunctions[sh->NumSubroutineFunctions].types[j] = fn->subroutine_types[j]; - sh->NumSubroutineFunctions++; + p->sh.SubroutineFunctions[p->sh.NumSubroutineFunctions].types[j] = fn->subroutine_types[j]; + p->sh.NumSubroutineFunctions++; } } } @@ -4499,17 +4504,28 @@ disable_varying_optimizations_for_sso(struct gl_shader_program *prog) } } +static void +link_and_validate_uniforms(struct gl_context *ctx, + struct gl_shader_program *prog) +{ + update_array_sizes(prog); + link_assign_uniform_locations(prog, ctx); + + if (!prog->data->cache_fallback) { + link_assign_atomic_counter_resources(ctx, prog); + link_calculate_subroutine_compat(prog); + check_resources(ctx, prog); + check_subroutine_resources(prog); + check_image_resources(ctx, prog); + link_check_atomic_counter_resources(ctx, prog); + } +} + static bool link_varyings_and_uniforms(unsigned first, unsigned last, - unsigned num_explicit_uniform_locs, struct gl_context *ctx, struct gl_shader_program *prog, void *mem_ctx) { - bool has_xfb_qualifiers = false; - unsigned num_tfeedback_decls = 0; - char **varying_names = NULL; - tfeedback_decl *tfeedback_decls = NULL; - /* Mark all generic shader inputs and outputs as unpaired. */ for (unsigned i = MESA_SHADER_VERTEX; i <= MESA_SHADER_FRAGMENT; i++) { if (prog->_LinkedShaders[i] != NULL) { @@ -4537,160 +4553,19 @@ link_varyings_and_uniforms(unsigned first, unsigned last, return false; } - /* From the ARB_enhanced_layouts spec: - * - * "If the shader used to record output variables for transform feedback - * varyings uses the "xfb_buffer", "xfb_offset", or "xfb_stride" layout - * qualifiers, the values specified by TransformFeedbackVaryings are - * ignored, and the set of variables captured for transform feedback is - * instead derived from the specified layout qualifiers." - */ - for (int i = MESA_SHADER_FRAGMENT - 1; i >= 0; i--) { - /* Find last stage before fragment shader */ - if (prog->_LinkedShaders[i]) { - has_xfb_qualifiers = - process_xfb_layout_qualifiers(mem_ctx, prog->_LinkedShaders[i], - &num_tfeedback_decls, - &varying_names); - break; - } - } - - if (!has_xfb_qualifiers) { - num_tfeedback_decls = prog->TransformFeedback.NumVarying; - varying_names = prog->TransformFeedback.VaryingNames; - } - - if (num_tfeedback_decls != 0) { - /* From GL_EXT_transform_feedback: - * A program will fail to link if: - * - * * the specified by TransformFeedbackVaryingsEXT is - * non-zero, but the program object has no vertex or geometry - * shader; - */ - if (first >= MESA_SHADER_FRAGMENT) { - linker_error(prog, "Transform feedback varyings specified, but " - "no vertex, tessellation, or geometry shader is " - "present.\n"); - return false; - } - - tfeedback_decls = rzalloc_array(mem_ctx, tfeedback_decl, - num_tfeedback_decls); - if (!parse_tfeedback_decls(ctx, prog, mem_ctx, num_tfeedback_decls, - varying_names, tfeedback_decls)) - return false; - } - - /* If there is no fragment shader we need to set transform feedback. - * - * For SSO we also need to assign output locations. We assign them here - * because we need to do it for both single stage programs and multi stage - * programs. - */ - if (last < MESA_SHADER_FRAGMENT && - (num_tfeedback_decls != 0 || prog->SeparateShader)) { - const uint64_t reserved_out_slots = - reserved_varying_slot(prog->_LinkedShaders[last], ir_var_shader_out); - if (!assign_varying_locations(ctx, mem_ctx, prog, - prog->_LinkedShaders[last], NULL, - num_tfeedback_decls, tfeedback_decls, - reserved_out_slots)) - return false; - } - - if (last <= MESA_SHADER_FRAGMENT) { - /* Remove unused varyings from the first/last stage unless SSO */ - remove_unused_shader_inputs_and_outputs(prog->SeparateShader, - prog->_LinkedShaders[first], - ir_var_shader_in); - remove_unused_shader_inputs_and_outputs(prog->SeparateShader, - prog->_LinkedShaders[last], - ir_var_shader_out); - - /* If the program is made up of only a single stage */ - if (first == last) { - gl_linked_shader *const sh = prog->_LinkedShaders[last]; - - do_dead_builtin_varyings(ctx, NULL, sh, 0, NULL); - do_dead_builtin_varyings(ctx, sh, NULL, num_tfeedback_decls, - tfeedback_decls); - - if (prog->SeparateShader) { - const uint64_t reserved_slots = - reserved_varying_slot(sh, ir_var_shader_in); - - /* Assign input locations for SSO, output locations are already - * assigned. - */ - if (!assign_varying_locations(ctx, mem_ctx, prog, - NULL /* producer */, - sh /* consumer */, - 0 /* num_tfeedback_decls */, - NULL /* tfeedback_decls */, - reserved_slots)) - return false; - } - } else { - /* Linking the stages in the opposite order (from fragment to vertex) - * ensures that inter-shader outputs written to in an earlier stage - * are eliminated if they are (transitively) not used in a later - * stage. - */ - int next = last; - for (int i = next - 1; i >= 0; i--) { - if (prog->_LinkedShaders[i] == NULL && i != 0) - continue; - - gl_linked_shader *const sh_i = prog->_LinkedShaders[i]; - gl_linked_shader *const sh_next = prog->_LinkedShaders[next]; - - const uint64_t reserved_out_slots = - reserved_varying_slot(sh_i, ir_var_shader_out); - const uint64_t reserved_in_slots = - reserved_varying_slot(sh_next, ir_var_shader_in); - - do_dead_builtin_varyings(ctx, sh_i, sh_next, - next == MESA_SHADER_FRAGMENT ? num_tfeedback_decls : 0, - tfeedback_decls); - - if (!assign_varying_locations(ctx, mem_ctx, prog, sh_i, sh_next, - next == MESA_SHADER_FRAGMENT ? num_tfeedback_decls : 0, - tfeedback_decls, - reserved_out_slots | reserved_in_slots)) - return false; - - /* This must be done after all dead varyings are eliminated. */ - if (sh_i != NULL) { - unsigned slots_used = _mesa_bitcount_64(reserved_out_slots); - if (!check_against_output_limit(ctx, prog, sh_i, slots_used)) { - return false; - } - } - - unsigned slots_used = _mesa_bitcount_64(reserved_in_slots); - if (!check_against_input_limit(ctx, prog, sh_next, slots_used)) - return false; + prog->last_vert_prog = NULL; + for (int i = MESA_SHADER_GEOMETRY; i >= MESA_SHADER_VERTEX; i--) { + if (prog->_LinkedShaders[i] == NULL) + continue; - next = i; - } - } + prog->last_vert_prog = prog->_LinkedShaders[i]->Program; + break; } - if (!store_tfeedback_info(ctx, prog, num_tfeedback_decls, tfeedback_decls, - has_xfb_qualifiers)) + if (!link_varyings(prog, first, last, ctx, mem_ctx)) return false; - update_array_sizes(prog); - link_assign_uniform_locations(prog, ctx, num_explicit_uniform_locs); - link_assign_atomic_counter_resources(ctx, prog); - - link_calculate_subroutine_compat(prog); - check_resources(ctx, prog); - check_subroutine_resources(prog); - check_image_resources(ctx, prog); - link_check_atomic_counter_resources(ctx, prog); + link_and_validate_uniforms(ctx, prog); if (!prog->data->LinkStatus) return false; @@ -4717,12 +4592,29 @@ link_varyings_and_uniforms(unsigned first, unsigned last, return true; } +static void +linker_optimisation_loop(struct gl_context *ctx, exec_list *ir, + unsigned stage) +{ + if (ctx->Const.GLSLOptimizeConservatively) { + /* Run it just once. */ + do_common_optimization(ir, true, false, + &ctx->Const.ShaderCompilerOptions[stage], + ctx->Const.NativeIntegers); + } else { + /* Repeat it until it stops making changes. */ + while (do_common_optimization(ir, true, false, + &ctx->Const.ShaderCompilerOptions[stage], + ctx->Const.NativeIntegers)) + ; + } +} + void link_shaders(struct gl_context *ctx, struct gl_shader_program *prog) { - prog->data->LinkStatus = true; /* All error paths will set this to false */ + prog->data->LinkStatus = linking_success; /* All error paths will set this to false */ prog->data->Validated = false; - prog->_Used = false; /* Section 7.3 (Program Objects) of the OpenGL 4.5 Core Profile spec says: * @@ -4743,7 +4635,19 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog) return; } - unsigned int num_explicit_uniform_locs = 0; +#ifdef ENABLE_SHADER_CACHE + /* If transform feedback used on the program then compile all shaders. */ + bool skip_cache = false; + if (prog->TransformFeedback.NumVarying > 0) { + for (unsigned i = 0; i < prog->NumShaders; i++) { + _mesa_glsl_compile_shader(ctx, prog->Shaders[i], false, false, true); + } + skip_cache = true; + } + + if (!skip_cache && shader_cache_read_program_metadata(ctx, prog)) + return; +#endif void *mem_ctx = ralloc_context(NULL); // temporary linker context @@ -4772,7 +4676,7 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog) goto done; } - if (prog->Shaders[i]->info.ARB_fragment_coord_conventions_enable) { + if (prog->Shaders[i]->ARB_fragment_coord_conventions_enable) { prog->ARB_fragment_coord_conventions_enable = true; } @@ -4790,7 +4694,7 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog) goto done; } - prog->Version = max_version; + prog->data->Version = max_version; prog->IsES = prog->Shaders[0]->IsES; /* Some shaders have to be linked with some other shaders present. @@ -4815,7 +4719,15 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog) goto done; } - /* The spec is self-contradictory here. It allows linking without a tess + /* Section 7.3 of the OpenGL ES 3.2 specification says: + * + * "Linking can fail for [...] any of the following reasons: + * + * * program contains an object to form a tessellation control + * shader [...] and [...] the program is not separable and + * contains no object to form a tessellation evaluation shader" + * + * The OpenGL spec is contradictory. It allows linking without a tess * eval shader, but that can only be used with transform feedback and * rasterization disabled. However, transform feedback isn't allowed * with GL_PATCHES, so it can't be used. @@ -4837,6 +4749,16 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog) "tessellation evaluation shader\n"); goto done; } + + if (prog->IsES) { + if (num_shaders[MESA_SHADER_TESS_EVAL] > 0 && + num_shaders[MESA_SHADER_TESS_CTRL] == 0) { + linker_error(prog, "GLSL ES requires non-separable programs " + "containing a tessellation evaluation shader to also " + "be linked with a tessellation control shader\n"); + goto done; + } + } } /* Compute shaders have additional restrictions. */ @@ -4888,20 +4810,6 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog) } } - if (num_shaders[MESA_SHADER_GEOMETRY] > 0) { - prog->LastClipDistanceArraySize = prog->Geom.ClipDistanceArraySize; - prog->LastCullDistanceArraySize = prog->Geom.CullDistanceArraySize; - } else if (num_shaders[MESA_SHADER_TESS_EVAL] > 0) { - prog->LastClipDistanceArraySize = prog->TessEval.ClipDistanceArraySize; - prog->LastCullDistanceArraySize = prog->TessEval.CullDistanceArraySize; - } else if (num_shaders[MESA_SHADER_VERTEX] > 0) { - prog->LastClipDistanceArraySize = prog->Vert.ClipDistanceArraySize; - prog->LastCullDistanceArraySize = prog->Vert.CullDistanceArraySize; - } else { - prog->LastClipDistanceArraySize = 0; /* Not used */ - prog->LastCullDistanceArraySize = 0; /* Not used */ - } - /* Here begins the inter-stage linking phase. Some initial validation is * performed, then locations are assigned for uniforms, attributes, and * varyings. @@ -4924,8 +4832,10 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog) last = i; } - num_explicit_uniform_locs = check_explicit_uniform_locations(ctx, prog); - link_assign_subroutine_types(prog); + if (!prog->data->cache_fallback) { + check_explicit_uniform_locations(ctx, prog); + link_assign_subroutine_types(prog); + } if (!prog->data->LinkStatus) goto done; @@ -4980,13 +4890,15 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog) if (prog->SeparateShader) disable_varying_optimizations_for_sso(prog); - /* Process UBOs */ - if (!interstage_cross_validate_uniform_blocks(prog, false)) - goto done; + if (!prog->data->cache_fallback) { + /* Process UBOs */ + if (!interstage_cross_validate_uniform_blocks(prog, false)) + goto done; - /* Process SSBOs */ - if (!interstage_cross_validate_uniform_blocks(prog, true)) - goto done; + /* Process SSBOs */ + if (!interstage_cross_validate_uniform_blocks(prog, true)) + goto done; + } /* Do common optimization before assigning storage for attributes, * uniforms, and varyings. Later optimization could possibly make @@ -5008,12 +4920,15 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog) lower_tess_level(prog->_LinkedShaders[i]); } - while (do_common_optimization(prog->_LinkedShaders[i]->ir, true, false, - &ctx->Const.ShaderCompilerOptions[i], - ctx->Const.NativeIntegers)) - ; + /* Call opts before lowering const arrays to uniforms so we can const + * propagate any elements accessed directly. + */ + linker_optimisation_loop(ctx, prog->_LinkedShaders[i]->ir, i); + + /* Call opts after lowering const arrays to copy propagate things. */ + if (lower_const_arrays_to_uniforms(prog->_LinkedShaders[i]->ir, i)) + linker_optimisation_loop(ctx, prog->_LinkedShaders[i]->ir, i); - lower_const_arrays_to_uniforms(prog->_LinkedShaders[i]->ir, i); propagate_invariance(prog->_LinkedShaders[i]->ir); } @@ -5021,8 +4936,8 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog) * with loop induction variable. This check emits a warning or error * depending if backend can handle dynamic indexing. */ - if ((!prog->IsES && prog->Version < 130) || - (prog->IsES && prog->Version < 300)) { + if ((!prog->IsES && prog->data->Version < 130) || + (prog->IsES && prog->data->Version < 300)) { if (!validate_sampler_array_indexing(ctx, prog)) goto done; } @@ -5032,8 +4947,7 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog) store_fragdepth_layout(prog); - if(!link_varyings_and_uniforms(first, last, num_explicit_uniform_locs, ctx, - prog, mem_ctx)) + if(!link_varyings_and_uniforms(first, last, ctx, prog, mem_ctx)) goto done; /* OpenGL ES < 3.1 requires that a vertex shader and a fragment shader both