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>
This commit is contained in:
Paul Berry
2014-01-07 08:56:57 -08:00
parent 4a91675b26
commit cd18ba1c7a

View File

@@ -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;
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 **)
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) {
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, vert_shader_list,
num_vert_shaders);
link_intrastage_shaders(mem_ctx, ctx, prog, shader_list[stage],
num_shaders[stage]);
if (!prog->LinkStatus)
goto done;
switch (stage) {
case MESA_SHADER_VERTEX:
validate_vertex_shader_executable(prog, sh);
if (!prog->LinkStatus)
goto done;
prog->LastClipDistanceArraySize = prog->Vert.ClipDistanceArraySize;
_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;
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;
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;
prog->LastClipDistanceArraySize = prog->Geom.ClipDistanceArraySize;
_mesa_reference_shader(ctx, &prog->_LinkedShaders[MESA_SHADER_GEOMETRY],
sh);
_mesa_reference_shader(ctx, &prog->_LinkedShaders[stage], sh);
}
}
if (num_shaders[MESA_SHADER_GEOMETRY] > 0)
prog->LastClipDistanceArraySize = prog->Geom.ClipDistanceArraySize;
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;