diff options
author | Francisco Jerez <[email protected]> | 2013-11-22 15:53:26 -0800 |
---|---|---|
committer | Francisco Jerez <[email protected]> | 2014-02-12 18:44:06 +0100 |
commit | e51158f2e77155bcfc6ba5f42d1cf9b9c9810930 (patch) | |
tree | 96c1fd97a3440751d5fecdf59a137581ec2bda04 | |
parent | e8dbe430aa77d6a775e087938bd19002f2a39e18 (diff) |
glsl/linker: Count and check image resources.
v2: Add comment about the reason why image variables take up space
from the default uniform block.
Reviewed-by: Paul Berry <[email protected]>
-rw-r--r-- | src/glsl/link_uniforms.cpp | 19 | ||||
-rw-r--r-- | src/glsl/linker.cpp | 41 |
2 files changed, 59 insertions, 1 deletions
diff --git a/src/glsl/link_uniforms.cpp b/src/glsl/link_uniforms.cpp index 1c97e195781..79f84046249 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,15 @@ 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; + + /* As drivers are likely to represent image uniforms as + * scalar indices, count them against the limit of uniform + * components in the default block. The spec allows image + * uniforms to use up no more than one scalar slot. + */ + 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 +798,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 bcd7394768f..72a3860f36b 100644 --- a/src/glsl/linker.cpp +++ b/src/glsl/linker.cpp @@ -2031,6 +2031,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,6 +2434,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) |