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 <chrisf@ijw.co.nz>
Reviewed-by: Brian Paul <brianp@vmware.com>
diff --git a/src/glsl/linker.cpp b/src/glsl/linker.cpp
index 38a6560..93b4754 100644
--- a/src/glsl/linker.cpp
+++ b/src/glsl/linker.cpp
@@ -1996,19 +1996,14 @@
/* 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;
+ struct gl_shader **shader_list[MESA_SHADER_STAGES];
+ unsigned num_shaders[MESA_SHADER_STAGES];
- 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 *));
+ 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 @@
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 @@
/* 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 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);
+ 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]);
- if (!prog->LinkStatus)
- goto done;
+ if (!prog->LinkStatus)
+ goto done;
- validate_vertex_shader_executable(prog, sh);
- if (!prog->LinkStatus)
- goto done;
- prog->LastClipDistanceArraySize = prog->Vert.ClipDistanceArraySize;
+ 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_VERTEX],
- sh);
+ _mesa_reference_shader(ctx, &prog->_LinkedShaders[stage], 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;
-
- validate_fragment_shader_executable(prog, sh);
- if (!prog->LinkStatus)
- goto done;
-
- _mesa_reference_shader(ctx, &prog->_LinkedShaders[MESA_SHADER_FRAGMENT],
- 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 @@
/* 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;