diff options
Diffstat (limited to 'mesalib/src/glsl/linker.cpp')
-rw-r--r-- | mesalib/src/glsl/linker.cpp | 120 |
1 files changed, 45 insertions, 75 deletions
diff --git a/mesalib/src/glsl/linker.cpp b/mesalib/src/glsl/linker.cpp index 85a4d3883..93b475497 100644 --- a/mesalib/src/glsl/linker.cpp +++ b/mesalib/src/glsl/linker.cpp @@ -609,6 +609,10 @@ cross_validate_globals(struct gl_shader_program *prog, if (var->type->length != 0) { existing->type = var->type; } + } else if (var->type->is_record() + && existing->type->is_record() + && existing->type->record_compare(var->type)) { + existing->type = var->type; } else { linker_error(prog, "%s `%s' declared as type " "`%s' and type `%s'\n", @@ -1992,19 +1996,14 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog) /* Separate the shaders into groups based on their type. */ - struct gl_shader **vert_shader_list; - unsigned num_vert_shaders = 0; - struct gl_shader **frag_shader_list; - unsigned num_frag_shaders = 0; - struct gl_shader **geom_shader_list; - unsigned num_geom_shaders = 0; - - vert_shader_list = (struct gl_shader **) - calloc(prog->NumShaders, sizeof(struct gl_shader *)); - frag_shader_list = (struct gl_shader **) - calloc(prog->NumShaders, sizeof(struct gl_shader *)); - geom_shader_list = (struct gl_shader **) - calloc(prog->NumShaders, sizeof(struct gl_shader *)); + struct gl_shader **shader_list[MESA_SHADER_STAGES]; + unsigned num_shaders[MESA_SHADER_STAGES]; + + for (int i = 0; i < MESA_SHADER_STAGES; i++) { + shader_list[i] = (struct gl_shader **) + calloc(prog->NumShaders, sizeof(struct gl_shader *)); + num_shaders[i] = 0; + } unsigned min_version = UINT_MAX; unsigned max_version = 0; @@ -2020,20 +2019,9 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog) goto done; } - switch (prog->Shaders[i]->Stage) { - case MESA_SHADER_VERTEX: - vert_shader_list[num_vert_shaders] = prog->Shaders[i]; - num_vert_shaders++; - break; - case MESA_SHADER_FRAGMENT: - frag_shader_list[num_frag_shaders] = prog->Shaders[i]; - num_frag_shaders++; - break; - case MESA_SHADER_GEOMETRY: - geom_shader_list[num_geom_shaders] = prog->Shaders[i]; - num_geom_shaders++; - break; - } + gl_shader_stage shader_type = prog->Shaders[i]->Stage; + shader_list[shader_type][num_shaders[shader_type]] = prog->Shaders[i]; + num_shaders[shader_type]++; } /* In desktop GLSL, different shader versions may be linked together. In @@ -2050,7 +2038,8 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog) /* Geometry shaders have to be linked with vertex shaders. */ - if (num_geom_shaders > 0 && num_vert_shaders == 0) { + if (num_shaders[MESA_SHADER_GEOMETRY] > 0 && + num_shaders[MESA_SHADER_VERTEX] == 0) { linker_error(prog, "Geometry shader must be linked with " "vertex shader\n"); goto done; @@ -2065,55 +2054,39 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog) /* Link all shaders for a particular stage and validate the result. */ - if (num_vert_shaders > 0) { - gl_shader *const sh = - link_intrastage_shaders(mem_ctx, ctx, prog, vert_shader_list, - num_vert_shaders); - - if (!prog->LinkStatus) - goto done; - - validate_vertex_shader_executable(prog, sh); - if (!prog->LinkStatus) - goto done; - prog->LastClipDistanceArraySize = prog->Vert.ClipDistanceArraySize; + for (int stage = 0; stage < MESA_SHADER_STAGES; stage++) { + if (num_shaders[stage] > 0) { + gl_shader *const sh = + link_intrastage_shaders(mem_ctx, ctx, prog, shader_list[stage], + num_shaders[stage]); - _mesa_reference_shader(ctx, &prog->_LinkedShaders[MESA_SHADER_VERTEX], - sh); - } - - if (num_frag_shaders > 0) { - gl_shader *const sh = - link_intrastage_shaders(mem_ctx, ctx, prog, frag_shader_list, - num_frag_shaders); - - if (!prog->LinkStatus) - goto done; + if (!prog->LinkStatus) + goto done; - validate_fragment_shader_executable(prog, sh); - if (!prog->LinkStatus) - goto done; + switch (stage) { + case MESA_SHADER_VERTEX: + validate_vertex_shader_executable(prog, sh); + break; + case MESA_SHADER_GEOMETRY: + validate_geometry_shader_executable(prog, sh); + break; + case MESA_SHADER_FRAGMENT: + validate_fragment_shader_executable(prog, sh); + break; + } + if (!prog->LinkStatus) + goto done; - _mesa_reference_shader(ctx, &prog->_LinkedShaders[MESA_SHADER_FRAGMENT], - sh); + _mesa_reference_shader(ctx, &prog->_LinkedShaders[stage], sh); + } } - if (num_geom_shaders > 0) { - gl_shader *const sh = - link_intrastage_shaders(mem_ctx, ctx, prog, geom_shader_list, - num_geom_shaders); - - if (!prog->LinkStatus) - goto done; - - validate_geometry_shader_executable(prog, sh); - if (!prog->LinkStatus) - goto done; + if (num_shaders[MESA_SHADER_GEOMETRY] > 0) prog->LastClipDistanceArraySize = prog->Geom.ClipDistanceArraySize; - - _mesa_reference_shader(ctx, &prog->_LinkedShaders[MESA_SHADER_GEOMETRY], - sh); - } + else if (num_shaders[MESA_SHADER_VERTEX] > 0) + prog->LastClipDistanceArraySize = prog->Vert.ClipDistanceArraySize; + else + prog->LastClipDistanceArraySize = 0; /* Not used */ /* Here begins the inter-stage linking phase. Some initial validation is * performed, then locations are assigned for uniforms, attributes, and @@ -2371,11 +2344,8 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog) /* FINISHME: Assign fragment shader output locations. */ done: - free(vert_shader_list); - free(frag_shader_list); - free(geom_shader_list); - for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) { + free(shader_list[i]); if (prog->_LinkedShaders[i] == NULL) continue; |