aboutsummaryrefslogtreecommitdiff
path: root/mesalib/src/glsl/linker.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'mesalib/src/glsl/linker.cpp')
-rw-r--r--mesalib/src/glsl/linker.cpp120
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;