mesa: Add support for ARB_shader_atomic_counters.
authorFrancisco Jerez <currojerez@riseup.net>
Tue, 8 Oct 2013 01:53:40 +0000 (18:53 -0700)
committerFrancisco Jerez <currojerez@riseup.net>
Tue, 29 Oct 2013 19:40:55 +0000 (12:40 -0700)
This patch implements the common support code required for the
ARB_shader_atomic_counters extension.  It defines the necessary data
structures for tracking atomic counter buffer objects (from now on
"ABOs") associated with some specific context or shader program, it
implements support for binding buffers to an ABO binding point and
querying the existing atomic counters and buffers declared by GLSL
shaders.

v2: Fix extension checks.  Drop unused MAX_ATOMIC_BUFFERS constant.

Acked-by: Paul Berry <stereotype441@gmail.com>
Reviewed-by: Ian Romanick <ian.d.romanick@intel.com>
12 files changed:
src/glsl/ir_uniform.h
src/glsl/link_uniforms.cpp
src/mesa/main/bufferobj.c
src/mesa/main/config.h
src/mesa/main/context.c
src/mesa/main/extensions.c
src/mesa/main/get.c
src/mesa/main/get_hash_params.py
src/mesa/main/mtypes.h
src/mesa/main/shaderapi.c
src/mesa/main/uniform_query.cpp
src/mesa/main/uniforms.c

index 8198c4819833fd5edcd70470836a751b20071e58..13faab7c0a14d460b839ef07946ec0d1b84a7541 100644 (file)
@@ -166,6 +166,13 @@ struct gl_uniform_storage {
    bool row_major;
 
    /** @} */
+
+   /**
+    * Index within gl_shader_program::AtomicBuffers[] of the atomic
+    * counter buffer this uniform is stored in, or -1 if this is not
+    * an atomic counter.
+    */
+   int atomic_buffer_index;
 };
 
 #ifdef __cplusplus
index ea71b3063ca03252bf6ca75580e5712f6c186cdd..0a15739c2659f3581ae841648297aa2908be2fb3 100644 (file)
@@ -513,6 +513,7 @@ private:
       this->uniforms[id].num_driver_storage = 0;
       this->uniforms[id].driver_storage = NULL;
       this->uniforms[id].storage = this->values;
+      this->uniforms[id].atomic_buffer_index = -1;
       if (this->ubo_block_index != -1) {
         this->uniforms[id].block_index = this->ubo_block_index;
 
index 312ffb788889bab9fd27d6f89f5df3af50af7a8e..1f5506157ca0379397b9a9b8a2624bd3280f08ca 100644 (file)
@@ -102,6 +102,11 @@ get_buffer_target(struct gl_context *ctx, GLenum target)
          return &ctx->UniformBuffer;
       }
       break;
+   case GL_ATOMIC_COUNTER_BUFFER:
+      if (ctx->Extensions.ARB_shader_atomic_counters) {
+         return &ctx->AtomicBuffer;
+      }
+      break;
    default:
       return NULL;
    }
@@ -2119,6 +2124,51 @@ bind_buffer_base_uniform_buffer(struct gl_context *ctx,
       set_ubo_binding(ctx, index, bufObj, 0, 0, GL_TRUE);
 }
 
+static void
+set_atomic_buffer_binding(struct gl_context *ctx,
+                          unsigned index,
+                          struct gl_buffer_object *bufObj,
+                          GLintptr offset,
+                          GLsizeiptr size,
+                          const char *name)
+{
+   struct gl_atomic_buffer_binding *binding;
+
+   if (index >= ctx->Const.MaxAtomicBufferBindings) {
+      _mesa_error(ctx, GL_INVALID_VALUE, "%s(index=%d)", name, index);
+      return;
+   }
+
+   if (offset & (ATOMIC_COUNTER_SIZE - 1)) {
+      _mesa_error(ctx, GL_INVALID_VALUE,
+                  "%s(offset misalgned %d/%d)", name, (int) offset,
+                  ATOMIC_COUNTER_SIZE);
+      return;
+   }
+
+   _mesa_reference_buffer_object(ctx, &ctx->AtomicBuffer, bufObj);
+
+   binding = &ctx->AtomicBufferBindings[index];
+   if (binding->BufferObject == bufObj &&
+       binding->Offset == offset &&
+       binding->Size == size) {
+      return;
+   }
+
+   FLUSH_VERTICES(ctx, 0);
+   ctx->NewDriverState |= ctx->DriverFlags.NewAtomicBuffer;
+
+   _mesa_reference_buffer_object(ctx, &binding->BufferObject, bufObj);
+
+   if (bufObj == ctx->Shared->NullBufferObj) {
+      binding->Offset = -1;
+      binding->Size = -1;
+   } else {
+      binding->Offset = offset;
+      binding->Size = size;
+   }
+}
+
 void GLAPIENTRY
 _mesa_BindBufferRange(GLenum target, GLuint index,
                       GLuint buffer, GLintptr offset, GLsizeiptr size)
@@ -2156,6 +2206,10 @@ _mesa_BindBufferRange(GLenum target, GLuint index,
    case GL_UNIFORM_BUFFER:
       bind_buffer_range_uniform_buffer(ctx, index, bufObj, offset, size);
       return;
+   case GL_ATOMIC_COUNTER_BUFFER:
+      set_atomic_buffer_binding(ctx, index, bufObj, offset, size,
+                                "glBindBufferRange");
+      return;
    default:
       _mesa_error(ctx, GL_INVALID_ENUM, "glBindBufferRange(target)");
       return;
@@ -2215,6 +2269,10 @@ _mesa_BindBufferBase(GLenum target, GLuint index, GLuint buffer)
    case GL_UNIFORM_BUFFER:
       bind_buffer_base_uniform_buffer(ctx, index, bufObj);
       return;
+   case GL_ATOMIC_COUNTER_BUFFER:
+      set_atomic_buffer_binding(ctx, index, bufObj, 0, 0,
+                                "glBindBufferBase");
+      return;
    default:
       _mesa_error(ctx, GL_INVALID_ENUM, "glBindBufferBase(target)");
       return;
index 0bcf27c345b8d1b4daf469712ebd3c64c6a5b19a..22bbfa0cf31baf6adfe1c4bb832fc81564afdffc 100644 (file)
 #define MAX_UNIFORM_BUFFERS            15 /* + 1 default uniform buffer */
 /* 6 is for vertex, hull, domain, geometry, fragment, and compute shader. */
 #define MAX_COMBINED_UNIFORM_BUFFERS   (MAX_UNIFORM_BUFFERS * 6)
+#define MAX_ATOMIC_COUNTERS            4096
+/* 6 is for vertex, hull, domain, geometry, fragment, and compute shader. */
+#define MAX_COMBINED_ATOMIC_BUFFERS    (MAX_UNIFORM_BUFFERS * 6)
+/* Size of an atomic counter in bytes according to ARB_shader_atomic_counters */
+#define ATOMIC_COUNTER_SIZE            4
 /*@}*/
 
 /**
index 0d1f71c7142450318da3d6ce7c8a090927efbf85..6cdeed19b0a0d1f27f8a54102e4957d49105c6a4 100644 (file)
@@ -537,6 +537,9 @@ init_program_limits(struct gl_context *ctx, GLenum type,
    prog->MaxCombinedUniformComponents = (prog->MaxUniformComponents +
                                          ctx->Const.MaxUniformBlockSize / 4 *
                                          prog->MaxUniformBlocks);
+
+   prog->MaxAtomicBuffers = 0;
+   prog->MaxAtomicCounters = 0;
 }
 
 
@@ -669,6 +672,12 @@ _mesa_init_constants(struct gl_context *ctx)
    ctx->Const.MaxColorTextureSamples = 1;
    ctx->Const.MaxDepthTextureSamples = 1;
    ctx->Const.MaxIntegerSamples = 1;
+
+   /* GL_ARB_shader_atomic_counters */
+   ctx->Const.MaxAtomicBufferBindings = MAX_COMBINED_ATOMIC_BUFFERS;
+   ctx->Const.MaxAtomicBufferSize = MAX_ATOMIC_COUNTERS * ATOMIC_COUNTER_SIZE;
+   ctx->Const.MaxCombinedAtomicBuffers = MAX_COMBINED_ATOMIC_BUFFERS;
+   ctx->Const.MaxCombinedAtomicCounters = MAX_ATOMIC_COUNTERS;
 }
 
 
index 00d65ccb04dc75010e198d3fd69e3f4da9b26252..285ec377cfdc0f7b735c133da4a03d7031506863 100644 (file)
@@ -120,6 +120,7 @@ static const struct extension extension_table[] = {
    { "GL_ARB_robustness",                          o(dummy_true),                              GL,             2010 },
    { "GL_ARB_sampler_objects",                     o(dummy_true),                              GL,             2009 },
    { "GL_ARB_seamless_cube_map",                   o(ARB_seamless_cube_map),                   GL,             2009 },
+   { "GL_ARB_shader_atomic_counters",              o(ARB_shader_atomic_counters),              GL,             2011 },
    { "GL_ARB_shader_bit_encoding",                 o(ARB_shader_bit_encoding),                 GL,             2010 },
    { "GL_ARB_shader_objects",                      o(dummy_true),                              GL,             2002 },
    { "GL_ARB_shader_stencil_export",               o(ARB_shader_stencil_export),               GL,             2009 },
index 89b3bf09ddb3168a6acdff9a1c4e57f0d4dacbc4..6e72ff5c298eace815408a2651a72b221112183d 100644 (file)
@@ -143,6 +143,7 @@ enum value_extra {
    EXTRA_FLUSH_CURRENT,
    EXTRA_GLSL_130,
    EXTRA_EXT_UBO_GS4,
+   EXTRA_EXT_ATOMICS_GS4,
 };
 
 #define NO_EXTRA NULL
@@ -331,6 +332,11 @@ static const int extra_MESA_texture_array_es3[] = {
    EXTRA_END
 };
 
+static const int extra_ARB_shader_atomic_counters_and_geometry_shader[] = {
+   EXTRA_EXT_ATOMICS_GS4,
+   EXTRA_END
+};
+
 EXTRA_EXT(ARB_texture_cube_map);
 EXTRA_EXT(MESA_texture_array);
 EXTRA_EXT(NV_fog_distance);
@@ -367,6 +373,7 @@ EXTRA_EXT(ARB_texture_cube_map_array);
 EXTRA_EXT(ARB_texture_buffer_range);
 EXTRA_EXT(ARB_texture_multisample);
 EXTRA_EXT(ARB_texture_gather);
+EXTRA_EXT(ARB_shader_atomic_counters);
 
 static const int
 extra_ARB_color_buffer_float_or_glcore[] = {
@@ -894,6 +901,10 @@ find_custom_value(struct gl_context *ctx, const struct value_desc *d, union valu
          _mesa_problem(ctx, "driver doesn't implement GetTimestamp");
       }
       break;
+   /* GL_ARB_shader_atomic_counters */
+   case GL_ATOMIC_COUNTER_BUFFER_BINDING:
+      v->value_int = ctx->AtomicBuffer->Name;
+      break;
    }
 }
 
@@ -999,6 +1010,11 @@ check_extra(struct gl_context *ctx, const char *func, const struct value_desc *d
          api_found = (ctx->Extensions.ARB_uniform_buffer_object &&
                       _mesa_has_geometry_shaders(ctx));
          break;
+      case EXTRA_EXT_ATOMICS_GS4:
+         api_check = GL_TRUE;
+         api_found = (ctx->Extensions.ARB_shader_atomic_counters &&
+                      _mesa_has_geometry_shaders(ctx));
+         break;
       case EXTRA_END:
         break;
       default: /* *e is a offset into the extension struct */
@@ -1692,6 +1708,30 @@ find_value_indexed(const char *func, GLenum pname, GLuint index, union value *v)
          goto invalid_enum;
       v->value_int = ctx->Multisample.SampleMaskValue;
       return TYPE_INT;
+
+   case GL_ATOMIC_COUNTER_BUFFER_BINDING:
+      if (!ctx->Extensions.ARB_shader_atomic_counters)
+         goto invalid_enum;
+      if (index >= ctx->Const.MaxAtomicBufferBindings)
+         goto invalid_value;
+      v->value_int = ctx->AtomicBufferBindings[index].BufferObject->Name;
+      return TYPE_INT;
+
+   case GL_ATOMIC_COUNTER_BUFFER_START:
+      if (!ctx->Extensions.ARB_shader_atomic_counters)
+         goto invalid_enum;
+      if (index >= ctx->Const.MaxAtomicBufferBindings)
+         goto invalid_value;
+      v->value_int64 = ctx->AtomicBufferBindings[index].Offset;
+      return TYPE_INT64;
+
+   case GL_ATOMIC_COUNTER_BUFFER_SIZE:
+      if (!ctx->Extensions.ARB_shader_atomic_counters)
+         goto invalid_enum;
+      if (index >= ctx->Const.MaxAtomicBufferBindings)
+         goto invalid_value;
+      v->value_int64 = ctx->AtomicBufferBindings[index].Size;
+      return TYPE_INT64;
    }
 
  invalid_enum:
index 9c54af094d771bbf265e6f3b927088b547c93ddc..9f79f340683821aba71243104b84579fc90e2450 100644 (file)
@@ -722,6 +722,18 @@ descriptor=[
   [ "MAX_PROGRAM_TEXTURE_GATHER_OFFSET", "CONTEXT_INT(Const.MaxProgramTextureGatherOffset), extra_ARB_texture_gather"],
   [ "MAX_PROGRAM_TEXTURE_GATHER_COMPONENTS_ARB", "CONTEXT_INT(Const.MaxProgramTextureGatherComponents), extra_ARB_texture_gather"],
 
+# GL_ARB_shader_atomic_counters
+  [ "ATOMIC_COUNTER_BUFFER_BINDING", "LOC_CUSTOM, TYPE_INT, 0, extra_ARB_shader_atomic_counters" ],
+  [ "MAX_ATOMIC_COUNTER_BUFFER_BINDINGS", "CONTEXT_INT(Const.MaxAtomicBufferBindings), extra_ARB_shader_atomic_counters" ],
+  [ "MAX_ATOMIC_COUNTER_BUFFER_SIZE", "CONTEXT_INT(Const.MaxAtomicBufferSize), extra_ARB_shader_atomic_counters" ],
+  [ "MAX_VERTEX_ATOMIC_COUNTER_BUFFERS", "CONTEXT_INT(Const.VertexProgram.MaxAtomicBuffers), extra_ARB_shader_atomic_counters" ],
+  [ "MAX_VERTEX_ATOMIC_COUNTERS", "CONTEXT_INT(Const.VertexProgram.MaxAtomicCounters), extra_ARB_shader_atomic_counters" ],
+  [ "MAX_FRAGMENT_ATOMIC_COUNTER_BUFFERS", "CONTEXT_INT(Const.FragmentProgram.MaxAtomicBuffers), extra_ARB_shader_atomic_counters" ],
+  [ "MAX_FRAGMENT_ATOMIC_COUNTERS", "CONTEXT_INT(Const.FragmentProgram.MaxAtomicCounters), extra_ARB_shader_atomic_counters" ],
+  [ "MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS", "CONTEXT_INT(Const.GeometryProgram.MaxAtomicBuffers), extra_ARB_shader_atomic_counters_and_geometry_shader" ],
+  [ "MAX_GEOMETRY_ATOMIC_COUNTERS", "CONTEXT_INT(Const.GeometryProgram.MaxAtomicCounters), extra_ARB_shader_atomic_counters_and_geometry_shader" ],
+  [ "MAX_COMBINED_ATOMIC_COUNTER_BUFFERS", "CONTEXT_INT(Const.MaxCombinedAtomicBuffers), extra_ARB_shader_atomic_counters" ],
+  [ "MAX_COMBINED_ATOMIC_COUNTERS", "CONTEXT_INT(Const.MaxCombinedAtomicCounters), extra_ARB_shader_atomic_counters" ],
 ]},
 
 # Enums restricted to OpenGL Core profile
index 824e33906fdf08befcbd6a32bb5df4261418eee5..a1a5eb4bf137b1f8a0622715c42dd213d4fd005c 100644 (file)
@@ -2375,6 +2375,25 @@ struct gl_uniform_block
    enum gl_uniform_block_packing _Packing;
 };
 
+/**
+ * Structure that represents a reference to an atomic buffer from some
+ * shader program.
+ */
+struct gl_active_atomic_buffer
+{
+   /** Uniform indices of the atomic counters declared within it. */
+   GLuint *Uniforms;
+   GLuint NumUniforms;
+
+   /** Binding point index associated with it. */
+   GLuint Binding;
+
+   /** Minimum reasonable size it is expected to have. */
+   GLuint MinimumSize;
+
+   /** Shader stages making use of it. */
+   GLboolean StageReferences[MESA_SHADER_TYPES];
+};
 
 /**
  * A GLSL program object.
@@ -2523,6 +2542,9 @@ struct gl_shader_program
     */
    struct string_to_uint_map *UniformHash;
 
+   struct gl_active_atomic_buffer *AtomicBuffers;
+   unsigned NumAtomicBuffers;
+
    GLboolean LinkStatus;   /**< GL_LINK_STATUS */
    GLboolean Validated;
    GLboolean _Used;        /**< Ever used for drawing? */
@@ -2960,6 +2982,9 @@ struct gl_program_constants
    GLuint MaxUniformBlocks;
    GLuint MaxCombinedUniformComponents;
    GLuint MaxTextureImageUnits;
+   /* GL_ARB_shader_atomic_counters */
+   GLuint MaxAtomicBuffers;
+   GLuint MaxAtomicCounters;
 };
 
 
@@ -3166,6 +3191,12 @@ struct gl_constants
    GLint MaxColorTextureSamples;
    GLint MaxDepthTextureSamples;
    GLint MaxIntegerSamples;
+
+   /** GL_ARB_shader_atomic_counters */
+   GLuint MaxAtomicBufferBindings;
+   GLuint MaxAtomicBufferSize;
+   GLuint MaxCombinedAtomicBuffers;
+   GLuint MaxCombinedAtomicCounters;
 };
 
 
@@ -3209,6 +3240,7 @@ struct gl_extensions
    GLboolean ARB_occlusion_query2;
    GLboolean ARB_point_sprite;
    GLboolean ARB_seamless_cube_map;
+   GLboolean ARB_shader_atomic_counters;
    GLboolean ARB_shader_bit_encoding;
    GLboolean ARB_shader_stencil_export;
    GLboolean ARB_shader_texture_lod;
@@ -3582,6 +3614,11 @@ struct gl_driver_flags
     * gl_shader_program::UniformBlocks
     */
    GLbitfield NewUniformBuffer;
+
+   /**
+    * gl_context::AtomicBufferBindings
+    */
+   GLbitfield NewAtomicBuffer;
 };
 
 struct gl_uniform_buffer_binding
@@ -3598,6 +3635,16 @@ struct gl_uniform_buffer_binding
    GLboolean AutomaticSize;
 };
 
+/**
+ * Binding point for an atomic counter buffer object.
+ */
+struct gl_atomic_buffer_binding
+{
+   struct gl_buffer_object *BufferObject;
+   GLintptr Offset;
+   GLsizeiptr Size;
+};
+
 /**
  * Mesa rendering context.
  *
@@ -3766,6 +3813,18 @@ struct gl_context
    struct gl_uniform_buffer_binding
       UniformBufferBindings[MAX_COMBINED_UNIFORM_BUFFERS];
 
+   /**
+    * Object currently associated with the GL_ATOMIC_COUNTER_BUFFER
+    * target.
+    */
+   struct gl_buffer_object *AtomicBuffer;
+
+   /**
+    * Array of atomic counter buffer binding points.
+    */
+   struct gl_atomic_buffer_binding
+      AtomicBufferBindings[MAX_COMBINED_ATOMIC_BUFFERS];
+
    /*@}*/
 
    struct gl_meta_state *Meta;  /**< for "meta" operations */
index f5c04b9f38f9e4551d261f50e62b180a268ea87d..4a6bd73d446f73626d8ef7bd8b40d0f04142da82 100644 (file)
@@ -648,6 +648,12 @@ get_programiv(struct gl_context *ctx, GLuint program, GLenum pname, GLint *param
    case GL_PROGRAM_BINARY_LENGTH:
       *params = 0;
       return;
+   case GL_ACTIVE_ATOMIC_COUNTER_BUFFERS:
+      if (!ctx->Extensions.ARB_shader_atomic_counters)
+         break;
+
+      *params = shProg->NumAtomicBuffers;
+      return;
    default:
       break;
    }
index 3c460042eeed5b42264d0ebc1273457792587050..88ad476acb94f9e163f98848f4de3e864c344006 100644 (file)
@@ -154,11 +154,21 @@ _mesa_GetActiveUniformsiv(GLuint program,
         params[i] = uni->row_major;
         break;
 
+      case GL_UNIFORM_ATOMIC_COUNTER_BUFFER_INDEX:
+         if (!ctx->Extensions.ARB_shader_atomic_counters)
+            goto invalid_enum;
+         params[i] = uni->atomic_buffer_index;
+         break;
+
       default:
-        _mesa_error(ctx, GL_INVALID_ENUM, "glGetActiveUniformsiv(pname)");
-        return;
+         goto invalid_enum;
       }
    }
+
+   return;
+
+ invalid_enum:
+   _mesa_error(ctx, GL_INVALID_ENUM, "glGetActiveUniformsiv(pname)");
 }
 
 static bool
index 07e7ea379989a1533a5d8a0618216ab5514e114d..2e847fe3147a065e4a6d9b7c96ebc54714ef1c3d 100644 (file)
@@ -535,7 +535,8 @@ _mesa_GetUniformLocation(GLhandleARB programObj, const GLcharARB *name)
     *      with a named uniform block, or if <name> starts with the reserved
     *      prefix "gl_"."
     */
-   if (shProg->UniformStorage[index].block_index != -1)
+   if (shProg->UniformStorage[index].block_index != -1 ||
+       shProg->UniformStorage[index].atomic_buffer_index != -1)
       return -1;
 
    return _mesa_uniform_merge_location_offset(shProg, index, offset);
@@ -849,4 +850,63 @@ void GLAPIENTRY
 _mesa_GetActiveAtomicCounterBufferiv(GLuint program, GLuint bufferIndex,
                                      GLenum pname, GLint *params)
 {
+   GET_CURRENT_CONTEXT(ctx);
+   struct gl_shader_program *shProg;
+   struct gl_active_atomic_buffer *ab;
+   int i;
+
+   if (!ctx->Extensions.ARB_shader_atomic_counters) {
+      _mesa_error(ctx, GL_INVALID_OPERATION,
+                  "glGetActiveAtomicCounterBufferiv");
+      return;
+   }
+
+   shProg = _mesa_lookup_shader_program_err(ctx, program,
+                                            "glGetActiveAtomicCounterBufferiv");
+   if (!shProg)
+      return;
+
+   if (bufferIndex >= shProg->NumAtomicBuffers) {
+      _mesa_error(ctx, GL_INVALID_VALUE,
+                  "glGetActiveAtomicCounterBufferiv(bufferIndex)");
+      return;
+   }
+
+   ab = &shProg->AtomicBuffers[bufferIndex];
+
+   switch (pname) {
+   case GL_ATOMIC_COUNTER_BUFFER_BINDING:
+      params[0] = ab->Binding;
+      return;
+   case GL_ATOMIC_COUNTER_BUFFER_DATA_SIZE:
+      params[0] = ab->MinimumSize;
+      return;
+   case GL_ATOMIC_COUNTER_BUFFER_ACTIVE_ATOMIC_COUNTERS:
+      params[0] = ab->NumUniforms;
+      return;
+   case GL_ATOMIC_COUNTER_BUFFER_ACTIVE_ATOMIC_COUNTER_INDICES:
+      for (i = 0; i < ab->NumUniforms; ++i)
+         params[i] = ab->Uniforms[i];
+      return;
+   case GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_VERTEX_SHADER:
+      params[0] = ab->StageReferences[MESA_SHADER_VERTEX];
+      return;
+   case GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_GEOMETRY_SHADER:
+      params[0] = ab->StageReferences[MESA_SHADER_GEOMETRY];
+      return;
+   case GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_FRAGMENT_SHADER:
+      params[0] = ab->StageReferences[MESA_SHADER_FRAGMENT];
+      return;
+   case GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_TESS_CONTROL_SHADER:
+      params[0] = GL_FALSE;
+      return;
+   case GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_TESS_EVALUATION_SHADER:
+      params[0] = GL_FALSE;
+      return;
+   default:
+      _mesa_error(ctx, GL_INVALID_ENUM,
+                  "glGetActiveAtomicCounterBufferiv(pname 0x%x (%s))",
+                  pname, _mesa_lookup_enum_by_nr(pname));
+      return;
+   }
 }