From cd18ba1c7aba66f2dd7cdbe2cf3b4a803c241d10 Mon Sep 17 00:00:00 2001 From: Paul Berry Date: Tue, 7 Jan 2014 08:56:57 -0800 Subject: glsl/linker: Refactor in preparation for adding more shader stages. Rather than maintain separately named arrays and counts for vertex, geometry, and fragment shaders, just maintain these as arrays indexed by the gl_shader_type enum. v2: When there is neither a vertex nor a geometry shader, set prog->LastClipDistanceArraySize = 0, and clarify that the values is not used. Reviewed-by: Chris Forbes Reviewed-by: Brian Paul --- src/glsl/linker.cpp | 116 +++++++++++++++++++--------------------------------- 1 file changed, 41 insertions(+), 75 deletions(-) diff --git a/src/glsl/linker.cpp b/src/glsl/linker.cpp index 38a6560d1b5..93b4754970c 100644 --- a/src/glsl/linker.cpp +++ b/src/glsl/linker.cpp @@ -1996,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; @@ -2024,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 @@ -2054,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; @@ -2069,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 @@ -2375,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; -- cgit v1.2.3