nir: Look into uniform structs for samplers when counting num_textures.
authorEric Anholt <eric@anholt.net>
Fri, 30 Mar 2018 23:04:34 +0000 (16:04 -0700)
committerEric Anholt <eric@anholt.net>
Wed, 6 Jun 2018 20:46:55 +0000 (13:46 -0700)
mesa/st decides whether to update samplers after a program change based on
whether num_textures is nonzero.  By not counting samplers in a uniform
struct, we would segfault in
KHR-GLES3.shaders.struct.uniform.sampler_vertex if it was run in the same
context after a non-vertex-shader-uniform testcase (as is the case during
a full conformance run).

v2: Implement using two separate pure functions instead of updating
    pointers.

Reviewed-by: Jason Ekstrand <jason@jlekstrand.net>
src/compiler/nir/nir_gather_info.c

index dba9f19..3534b69 100644 (file)
@@ -352,24 +352,56 @@ gather_info_block(nir_block *block, nir_shader *shader)
    }
 }
 
+static unsigned
+glsl_type_get_sampler_count(const struct glsl_type *type)
+{
+   if (glsl_type_is_array(type)) {
+      return (glsl_get_aoa_size(type) *
+              glsl_type_get_sampler_count(glsl_without_array(type)));
+   }
+
+   if (glsl_type_is_struct(type)) {
+      unsigned count = 0;
+      for (int i = 0; i < glsl_get_length(type); i++)
+         count += glsl_type_get_sampler_count(glsl_get_struct_field(type, i));
+      return count;
+   }
+
+   if (glsl_type_is_sampler(type))
+      return 1;
+
+   return 0;
+}
+
+static unsigned
+glsl_type_get_image_count(const struct glsl_type *type)
+{
+   if (glsl_type_is_array(type)) {
+      return (glsl_get_aoa_size(type) *
+              glsl_type_get_image_count(glsl_without_array(type)));
+   }
+
+   if (glsl_type_is_struct(type)) {
+      unsigned count = 0;
+      for (int i = 0; i < glsl_get_length(type); i++)
+         count += glsl_type_get_image_count(glsl_get_struct_field(type, i));
+      return count;
+   }
+
+   if (glsl_type_is_image(type))
+      return 1;
+
+   return 0;
+}
+
 void
 nir_shader_gather_info(nir_shader *shader, nir_function_impl *entrypoint)
 {
    shader->info.num_textures = 0;
    shader->info.num_images = 0;
    nir_foreach_variable(var, &shader->uniforms) {
-      const struct glsl_type *type = var->type;
-      unsigned count = 1;
-      if (glsl_type_is_array(type)) {
-         count = glsl_get_aoa_size(type);
-         type = glsl_without_array(type);
-      }
-
-      if (glsl_type_is_image(type)) {
-         shader->info.num_images += count;
-      } else if (glsl_type_is_sampler(type)) {
-         shader->info.num_textures += count;
-      }
+      shader->info.num_textures += glsl_type_get_sampler_count(var->type);
+      shader->info.num_images += glsl_type_get_image_count(var->type);
    }
 
    shader->info.inputs_read = 0;