--- src/glsl/link_uniforms.cpp | 13 +++++++++++- src/glsl/linker.cpp | 50 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+), 1 deletion(-)
diff --git a/src/glsl/link_uniforms.cpp b/src/glsl/link_uniforms.cpp index 0a15739..c75a38c 100644 --- a/src/glsl/link_uniforms.cpp +++ b/src/glsl/link_uniforms.cpp @@ -240,7 +240,8 @@ class count_uniform_size : public program_resource_visitor { public: count_uniform_size(struct string_to_uint_map *map) : num_active_uniforms(0), num_values(0), num_shader_samplers(0), - num_shader_uniform_components(0), is_ubo_var(false), map(map) + num_shader_images(0), num_shader_uniform_components(0), + is_ubo_var(false), map(map) { /* empty */ } @@ -248,6 +249,7 @@ public: void start_shader() { this->num_shader_samplers = 0; + this->num_shader_images = 0; this->num_shader_uniform_components = 0; } @@ -277,6 +279,11 @@ public: unsigned num_shader_samplers; /** + * Number of images used + */ + unsigned num_shader_images; + + /** * Number of uniforms used in the current shader */ unsigned num_shader_uniform_components; @@ -303,6 +310,9 @@ private: if (type->contains_sampler()) { this->num_shader_samplers += type->is_array() ? type->array_size() : 1; + } else if (type->contains_image()) { + this->num_shader_images += values; + this->num_shader_uniform_components += values; } else { /* Accumulate the total number of uniform slots used by this shader. * Note that samplers do not count against this limit because they @@ -782,6 +792,7 @@ link_assign_uniform_locations(struct gl_shader_program *prog) } sh->num_samplers = uniform_size.num_shader_samplers; + sh->NumImages = uniform_size.num_shader_images; sh->num_uniform_components = uniform_size.num_shader_uniform_components; sh->num_combined_uniform_components = sh->num_uniform_components; diff --git a/src/glsl/linker.cpp b/src/glsl/linker.cpp index fac186a..86a0cae 100644 --- a/src/glsl/linker.cpp +++ b/src/glsl/linker.cpp @@ -1980,6 +1980,55 @@ 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) +{ + STATIC_ASSERT(MESA_SHADER_TYPES == 3); + static const char *const shader_names[MESA_SHADER_TYPES] = { + "vertex", "geometry", "fragment" + }; + const unsigned max_images[MESA_SHADER_TYPES] = { + ctx->Const.VertexProgram.MaxImageUniforms, + ctx->Const.GeometryProgram.MaxImageUniforms, + ctx->Const.FragmentProgram.MaxImageUniforms + }; + 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_TYPES; i++) { + struct gl_shader *sh = prog->_LinkedShaders[i]; + + if (sh) { + if (sh->NumImages > max_images[i]) + linker_error(prog, "Too many %s shader image uniforms", + shader_names[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->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) { @@ -2367,6 +2416,7 @@ 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) -- 1.8.3.4 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev