diff options
Diffstat (limited to 'mesalib/src/glsl/linker.cpp')
-rw-r--r-- | mesalib/src/glsl/linker.cpp | 68 |
1 files changed, 64 insertions, 4 deletions
diff --git a/mesalib/src/glsl/linker.cpp b/mesalib/src/glsl/linker.cpp index bcd739476..f6b266185 100644 --- a/mesalib/src/glsl/linker.cpp +++ b/mesalib/src/glsl/linker.cpp @@ -1206,6 +1206,7 @@ link_gs_inout_layout_qualifiers(struct gl_shader_program *prog, unsigned num_shaders) { linked_shader->Geom.VerticesOut = 0; + linked_shader->Geom.Invocations = 0; linked_shader->Geom.InputType = PRIM_UNKNOWN; linked_shader->Geom.OutputType = PRIM_UNKNOWN; @@ -1259,6 +1260,18 @@ link_gs_inout_layout_qualifiers(struct gl_shader_program *prog, } linked_shader->Geom.VerticesOut = shader->Geom.VerticesOut; } + + if (shader->Geom.Invocations != 0) { + if (linked_shader->Geom.Invocations != 0 && + linked_shader->Geom.Invocations != shader->Geom.Invocations) { + linker_error(prog, "geometry shader defined with conflicting " + "invocation count (%d and %d)\n", + linked_shader->Geom.Invocations, + shader->Geom.Invocations); + return; + } + linked_shader->Geom.Invocations = shader->Geom.Invocations; + } } /* Just do the intrastage -> interstage propagation right now, @@ -1285,6 +1298,11 @@ link_gs_inout_layout_qualifiers(struct gl_shader_program *prog, return; } prog->Geom.VerticesOut = linked_shader->Geom.VerticesOut; + + if (linked_shader->Geom.Invocations == 0) + linked_shader->Geom.Invocations = 1; + + prog->Geom.Invocations = linked_shader->Geom.Invocations; } @@ -2031,6 +2049,46 @@ check_resources(struct gl_context *ctx, struct gl_shader_program *prog) } } +/** + * Validate shader image resources. + */ +static void +check_image_resources(struct gl_context *ctx, struct gl_shader_program *prog) +{ + unsigned total_image_units = 0; + unsigned fragment_outputs = 0; + + if (!ctx->Extensions.ARB_shader_image_load_store) + return; + + for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) { + struct gl_shader *sh = prog->_LinkedShaders[i]; + + if (sh) { + if (sh->NumImages > ctx->Const.Program[i].MaxImageUniforms) + linker_error(prog, "Too many %s shader image uniforms", + _mesa_shader_stage_to_string(i)); + + total_image_units += sh->NumImages; + + if (i == MESA_SHADER_FRAGMENT) { + foreach_list(node, sh->ir) { + ir_variable *var = ((ir_instruction *)node)->as_variable(); + if (var && var->data.mode == ir_var_shader_out) + fragment_outputs += var->type->count_attribute_slots(); + } + } + } + } + + if (total_image_units > ctx->Const.MaxCombinedImageUniforms) + linker_error(prog, "Too many combined image uniforms"); + + if (total_image_units + fragment_outputs > + ctx->Const.MaxCombinedImageUnitsAndFragmentOutputs) + linker_error(prog, "Too many combined image uniforms and fragment outputs"); +} + void link_shaders(struct gl_context *ctx, struct gl_shader_program *prog) { @@ -2394,17 +2452,19 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog) store_fragdepth_layout(prog); check_resources(ctx, prog); + check_image_resources(ctx, prog); link_check_atomic_counter_resources(ctx, prog); if (!prog->LinkStatus) goto done; /* OpenGL ES requires that a vertex shader and a fragment shader both be - * present in a linked program. By checking prog->IsES, we also - * catch the GL_ARB_ES2_compatibility case. + * present in a linked program. GL_ARB_ES2_compatibility doesn't say + * anything about shader linking when one of the shaders (vertex or + * fragment shader) is absent. So, the extension shouldn't change the + * behavior specified in GLSL specification. */ - if (!prog->InternalSeparateShader && - (ctx->API == API_OPENGLES2 || prog->IsES)) { + if (!prog->InternalSeparateShader && ctx->API == API_OPENGLES2) { if (prog->_LinkedShaders[MESA_SHADER_VERTEX] == NULL) { linker_error(prog, "program lacks a vertex shader\n"); } else if (prog->_LinkedShaders[MESA_SHADER_FRAGMENT] == NULL) { |