On 04/13/2015 05:14 PM, Martin Peres wrote:
On 01/04/15 15:14, Tapani Pälli wrote:
Patch adds required helper functions to shaderapi.h and
the actual implementation.

The property query functionality can be tested with tests for
following functions that are refactored by later patches:

    GetActiveAtomicCounterBufferiv
    GetActiveUniformBlockiv
    GetActiveUniformsiv

v2: code cleanup (Ilia Mirkin)
     add bufSize < 0 check and error out
     fix is_resource_referenced to return bool
     check for propCount and bufSize, fixes in buffer_prop

Signed-off-by: Tapani Pälli <tapani.pa...@intel.com>
---
  src/mesa/main/program_resource.c |  22 ++++
  src/mesa/main/shader_query.cpp   | 266
+++++++++++++++++++++++++++++++++++++++
  src/mesa/main/shaderapi.h        |  12 ++
  3 files changed, 300 insertions(+)

diff --git a/src/mesa/main/program_resource.c
b/src/mesa/main/program_resource.c
index e381035..b095227 100644
--- a/src/mesa/main/program_resource.c
+++ b/src/mesa/main/program_resource.c
@@ -276,6 +276,28 @@ _mesa_GetProgramResourceiv(GLuint program, GLenum
programInterface,
                             const GLenum *props, GLsizei bufSize,
                             GLsizei *length, GLint *params)
  {
+   GET_CURRENT_CONTEXT(ctx);
+   struct gl_shader_program *shProg =
+      _mesa_lookup_shader_program_err(ctx, program,
"glGetProgramResourceiv");
+
+   if (!shProg || !params)
+      return;
+
+   /* The error INVALID_VALUE is generated if <propCount> is zero.
+    * Note that we check < 0 here because it makes sense to bail early.
+    */
+   if (propCount <= 0) {
+      _mesa_error(ctx, GL_INVALID_VALUE,
+                  "glGetProgramResourceiv(propCount <= 0)");
+      return;
+   }
+
+   /* No need to write any properties, user requested none. */
+   if (bufSize == 0)
+      return;
+
+   _mesa_get_program_resourceiv(shProg, programInterface, index,
+                                propCount, props, bufSize, length,
params);
  }
  /**
diff --git a/src/mesa/main/shader_query.cpp
b/src/mesa/main/shader_query.cpp
index 8b2281d..ef5e6a2 100644
--- a/src/mesa/main/shader_query.cpp
+++ b/src/mesa/main/shader_query.cpp
@@ -839,3 +839,269 @@ _mesa_program_resource_location_index(struct
gl_shader_program *shProg,
     return RESOURCE_VAR(res)->data.index;
  }
+
+static uint8_t
+stage_from_enum(GLenum ref)
+{
+   switch (ref) {
+   case GL_REFERENCED_BY_VERTEX_SHADER:
+      return MESA_SHADER_VERTEX;
+   case GL_REFERENCED_BY_GEOMETRY_SHADER:
+      return MESA_SHADER_GEOMETRY;
+   case GL_REFERENCED_BY_FRAGMENT_SHADER:
+      return MESA_SHADER_FRAGMENT;
+   default:
+      assert(!"shader stage not supported");
+      return MESA_SHADER_STAGES;
+   }
+}
+
+/**
+ * Check if resource is referenced by given 'referenced by' stage enum.
+ * ATC and UBO resources hold stage references of their own.
+ */
+static bool
+is_resource_referenced(struct gl_shader_program *shProg,
+                       struct gl_program_resource *res,
+                       GLuint index, uint8_t stage)
+{
+   if (res->Type == GL_ATOMIC_COUNTER_BUFFER)
+      return RESOURCE_ATC(res)->StageReferences[stage];
+
+   if (res->Type == GL_UNIFORM_BLOCK)
+      return shProg->UniformBlockStageIndex[stage][index] != -1;
+
+   return res->StageReferences & (1 << stage);
+}
+
+static unsigned
+get_buffer_property(struct gl_shader_program *shProg,
+                    struct gl_program_resource *res, const GLenum prop,
+                    GLint *val, const char *caller)
+{
+   GET_CURRENT_CONTEXT(ctx);
Same comment as the previous patch.
+   if (res->Type != GL_UNIFORM_BLOCK &&
+       res->Type != GL_ATOMIC_COUNTER_BUFFER)
+      goto invalid_operation;
+
+   if (res->Type == GL_UNIFORM_BLOCK) {
+      switch (prop) {
+      case GL_BUFFER_BINDING:
+         *val = RESOURCE_UBO(res)->Binding;
+         return 1;
+      case GL_BUFFER_DATA_SIZE:
+         *val = RESOURCE_UBO(res)->UniformBufferSize;
+         return 1;
+      case GL_NUM_ACTIVE_VARIABLES:
+         *val = RESOURCE_UBO(res)->NumUniforms;
+         return 1;
+      case GL_ACTIVE_VARIABLES:
+         for (unsigned i = 0; i < RESOURCE_UBO(res)->NumUniforms; i++) {
+            const char *iname =
RESOURCE_UBO(res)->Uniforms[i].IndexName;
+            struct gl_program_resource *uni =
+               _mesa_program_resource_find_name(shProg, GL_UNIFORM,
iname);
+            *val++ =
+               _mesa_program_resource_index(shProg, uni);
+         }
+         return RESOURCE_UBO(res)->NumUniforms;
+      }
+   } else if (res->Type == GL_ATOMIC_COUNTER_BUFFER) {
+      switch (prop) {
+      case GL_BUFFER_BINDING:
+         *val = RESOURCE_ATC(res)->Binding;
+         return 1;
+      case GL_BUFFER_DATA_SIZE:
+         *val = RESOURCE_ATC(res)->MinimumSize;
+         return 1;
+      case GL_NUM_ACTIVE_VARIABLES:
+         *val = RESOURCE_ATC(res)->NumUniforms;
+         return 1;
+      case GL_ACTIVE_VARIABLES:
+         for (unsigned i = 0; i < RESOURCE_ATC(res)->NumUniforms; i++)
+            *val++ = RESOURCE_ATC(res)->Uniforms[i];
+         return RESOURCE_ATC(res)->NumUniforms;
+      }
+   }
+   assert(!"support for property type not implemented");
+
+invalid_operation:
+   _mesa_error(ctx, GL_INVALID_OPERATION, "%s(%s prop %s)", caller,
+               _mesa_lookup_enum_by_nr(res->Type),
+               _mesa_lookup_enum_by_nr(prop));
+
+   return 0;
+}
+
+unsigned
+_mesa_program_resource_prop(struct gl_shader_program *shProg,
+                            struct gl_program_resource *res, GLuint
index,
+                            const GLenum prop, GLint *val, const char
*caller)
+{
+   GET_CURRENT_CONTEXT(ctx);
+
+#define VALIDATE_TYPE(type)\
+   if (res->Type != type)\
+      goto invalid_operation;
+
+   switch(prop) {
+   case GL_NAME_LENGTH:
+      if (res->Type == GL_ATOMIC_COUNTER_BUFFER)
+         goto invalid_operation;
+      /* Base name +3 if array '[0]' + terminator. */
+      *val = strlen(_mesa_program_resource_name(res)) +
+         (_mesa_program_resource_array_size(res) > 0 ? 3 : 0) + 1;
+      return 1;
+   case GL_TYPE:
+      switch (res->Type) {
+      case GL_UNIFORM:
+         *val = RESOURCE_UNI(res)->type->gl_type;
+         return 1;
+      case GL_PROGRAM_INPUT:
+      case GL_PROGRAM_OUTPUT:
+         *val = RESOURCE_VAR(res)->type->gl_type;
+         return 1;
+      case GL_TRANSFORM_FEEDBACK_VARYING:
+         *val = RESOURCE_XFB(res)->Type;
+         return 1;
+      default:
+         goto invalid_operation;
+      }
+   case GL_ARRAY_SIZE:
+      switch (res->Type) {
+      case GL_UNIFORM:
+            *val = MAX2(RESOURCE_UNI(res)->array_elements, 1);
+            return 1;
+      case GL_PROGRAM_INPUT:
+      case GL_PROGRAM_OUTPUT:
+         *val = MAX2(RESOURCE_VAR(res)->type->length, 1);
+         return 1;
+      case GL_TRANSFORM_FEEDBACK_VARYING:
+         *val = MAX2(RESOURCE_XFB(res)->Size, 1);
+         return 1;
+      default:
+         goto invalid_operation;
+      }
+   case GL_OFFSET:
+      VALIDATE_TYPE(GL_UNIFORM);
+      *val = RESOURCE_UNI(res)->offset;
+      return 1;
+   case GL_BLOCK_INDEX:
+      VALIDATE_TYPE(GL_UNIFORM);
+      *val = RESOURCE_UNI(res)->block_index;
+      return 1;
+   case GL_ARRAY_STRIDE:
+      VALIDATE_TYPE(GL_UNIFORM);
+      *val = RESOURCE_UNI(res)->array_stride;
+      return 1;
+   case GL_MATRIX_STRIDE:
+      VALIDATE_TYPE(GL_UNIFORM);
+      *val = RESOURCE_UNI(res)->matrix_stride;
+      return 1;
+   case GL_IS_ROW_MAJOR:
+      VALIDATE_TYPE(GL_UNIFORM);
+      *val = RESOURCE_UNI(res)->row_major;
+      return 1;
+   case GL_ATOMIC_COUNTER_BUFFER_INDEX:
+      VALIDATE_TYPE(GL_UNIFORM);
+      *val = RESOURCE_UNI(res)->atomic_buffer_index;
+      return 1;
+   case GL_BUFFER_BINDING:
+   case GL_BUFFER_DATA_SIZE:
+   case GL_NUM_ACTIVE_VARIABLES:
+   case GL_ACTIVE_VARIABLES:
+      return get_buffer_property(shProg, res, prop, val, caller);
+   case GL_REFERENCED_BY_VERTEX_SHADER:
+   case GL_REFERENCED_BY_GEOMETRY_SHADER:
+   case GL_REFERENCED_BY_FRAGMENT_SHADER:
+      switch (res->Type) {
+      case GL_UNIFORM:
+      case GL_PROGRAM_INPUT:
+      case GL_PROGRAM_OUTPUT:
+      case GL_UNIFORM_BLOCK:
+      case GL_ATOMIC_COUNTER_BUFFER:
+         *val = is_resource_referenced(shProg, res, index,
+                                       stage_from_enum(prop));
+         return 1;
+      default:
+         goto invalid_operation;
+      }
+   case GL_LOCATION:
+      switch (res->Type) {
+      case GL_UNIFORM:
+      case GL_PROGRAM_INPUT:
+      case GL_PROGRAM_OUTPUT:
+         *val = program_resource_location(shProg, res,
+
_mesa_program_resource_name(res));
+         return 1;
+      default:
+         goto invalid_operation;
+      }
+   case GL_LOCATION_INDEX:
+      if (res->Type != GL_PROGRAM_OUTPUT)
+         goto invalid_operation;
+      *val = RESOURCE_VAR(res)->data.index;
+      return 1;
+
+   /* GL_ARB_tessellation_shader */
+   case GL_IS_PER_PATCH:
+   case GL_REFERENCED_BY_TESS_CONTROL_SHADER:
+   case GL_REFERENCED_BY_TESS_EVALUATION_SHADER:
+   /* GL_ARB_compute_shader */
+   case GL_REFERENCED_BY_COMPUTE_SHADER:
+   default:
+      _mesa_error(ctx, GL_INVALID_ENUM, "%s(%s prop %s)", caller,
+                  _mesa_lookup_enum_by_nr(res->Type),
+                  _mesa_lookup_enum_by_nr(prop));
+      return 0;
+   }
+
+#undef VALIDATE_TYPE
+
+invalid_operation:
+   _mesa_error(ctx, GL_INVALID_OPERATION, "%s(%s prop %s)", caller,
+               _mesa_lookup_enum_by_nr(res->Type),
+               _mesa_lookup_enum_by_nr(prop));
+   return 0;
+}
+
+extern void
+_mesa_get_program_resourceiv(struct gl_shader_program *shProg,
+                             GLenum interface, GLuint index, GLsizei
propCount,
+                             const GLenum *props, GLsizei bufSize,
+                             GLsizei *length, GLint *params)
+{
+   GET_CURRENT_CONTEXT(ctx);
+   GLint *val = (GLint *) params;
+   const GLenum *prop = props;
+   GLsizei amount = 0;
+
+   struct gl_program_resource *res =
+      _mesa_program_resource_find_index(shProg, interface, index);
+
+   /* No such resource found or bufSize negative. */
+   if (!res || bufSize < 0) {
+      _mesa_error(ctx, GL_INVALID_VALUE,
+                  "glGetProgramResourceiv(%s index %d bufSize %d)",
+                  _mesa_lookup_enum_by_nr(interface), index, bufSize);
+      return;
+   }
+
+   /* Write propCount values until error occurs or bufSize reached. */
+   for (int i = 0; i < propCount && i < bufSize; i++, val++, prop++) {
+      int props_written =
+         _mesa_program_resource_prop(shProg, res, index, *prop, val,
+                                     "glGetProgramResourceiv");
+      if (props_written) {
+         amount += props_written;
Not sure this test matters since you should abort the call anyway. How
about just returning?

As discussed IRL, this is what happens here. There can be > 1 props written. I'll squash this a bit with just returning when error happened to get rid of if/else.


+      } else {
+         /* Error happened. */
+         return;
+      }
+   }
+
+   /* If <length> is not NULL, the actual number of integer values
+    * written to <params> will be written to <length>.
+    */
+   if (length)
+      *length = amount;
+}
diff --git a/src/mesa/main/shaderapi.h b/src/mesa/main/shaderapi.h
index 5046018..0cd2fad 100644
--- a/src/mesa/main/shaderapi.h
+++ b/src/mesa/main/shaderapi.h
@@ -252,6 +252,18 @@ extern GLint
  _mesa_program_resource_location_index(struct gl_shader_program *shProg,
                                        GLenum interface, const char
*name);
+extern unsigned
+_mesa_program_resource_prop(struct gl_shader_program *shProg,
+                            struct gl_program_resource *res, GLuint
index,
+                            const GLenum prop, GLint *val, const char
*caller);
+
+extern void
+_mesa_get_program_resourceiv(struct gl_shader_program *shProg,
+                             GLenum interface, GLuint index,
+                             GLsizei propCount, const GLenum *props,
+                             GLsizei bufSize, GLsizei *length,
+                             GLint *params);
+
  #ifdef __cplusplus
  }
  #endif

Other than that:

Reviewed-by: Martin Peres <martin.pe...@linux.intel.com>
_______________________________________________
mesa-dev mailing list
mesa-dev@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/mesa-dev

Reply via email to