mesa: glGetProgramInterfaceiv
authorTapani Pälli <tapani.palli@intel.com>
Fri, 6 Mar 2015 13:05:51 +0000 (15:05 +0200)
committerTapani Pälli <tapani.palli@intel.com>
Thu, 16 Apr 2015 04:55:56 +0000 (07:55 +0300)
Patch adds required helper functions to shaderapi.h and
the actual implementation.

v2: code cleanup (Ilia Mirkin)
    fix array size fo xfb varyings
    validate programInterface and throw error

v3: put GL_MAX_NUM_COMPATIBLE_SUBROUTINES where
    it belongs

corresponding Piglit test:
   arb_program_interface_query-getprograminterfaceiv

Signed-off-by: Tapani Pälli <tapani.palli@intel.com>
Reviewed-by: Martin Peres <martin.peres@linux.intel.com>
src/mesa/main/program_resource.c
src/mesa/main/shader_query.cpp
src/mesa/main/shaderapi.h

index b3b93aa6cc8dd53aac7b071b32916deef5b7de57..ae28a26d3e44e77ee0c006a6fb69926a8d01d305 100644 (file)
  *
  */
 
+#include "main/enums.h"
+#include "main/macros.h"
+#include "main/mtypes.h"
+#include "main/shaderapi.h"
+#include "main/shaderobj.h"
 #include "program_resource.h"
 
+static bool
+supported_interface_enum(GLenum iface)
+{
+   switch (iface) {
+   case GL_UNIFORM:
+   case GL_UNIFORM_BLOCK:
+   case GL_PROGRAM_INPUT:
+   case GL_PROGRAM_OUTPUT:
+   case GL_TRANSFORM_FEEDBACK_VARYING:
+   case GL_ATOMIC_COUNTER_BUFFER:
+      return true;
+   case GL_VERTEX_SUBROUTINE:
+   case GL_TESS_CONTROL_SUBROUTINE:
+   case GL_TESS_EVALUATION_SUBROUTINE:
+   case GL_GEOMETRY_SUBROUTINE:
+   case GL_FRAGMENT_SUBROUTINE:
+   case GL_COMPUTE_SUBROUTINE:
+   case GL_VERTEX_SUBROUTINE_UNIFORM:
+   case GL_TESS_CONTROL_SUBROUTINE_UNIFORM:
+   case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM:
+   case GL_GEOMETRY_SUBROUTINE_UNIFORM:
+   case GL_FRAGMENT_SUBROUTINE_UNIFORM:
+   case GL_COMPUTE_SUBROUTINE_UNIFORM:
+   case GL_BUFFER_VARIABLE:
+   case GL_SHADER_STORAGE_BLOCK:
+   default:
+      return false;
+   }
+}
+
 void GLAPIENTRY
 _mesa_GetProgramInterfaceiv(GLuint program, GLenum programInterface,
                             GLenum pname, GLint *params)
 {
+   GET_CURRENT_CONTEXT(ctx);
+   unsigned i;
+   struct gl_shader_program *shProg =
+      _mesa_lookup_shader_program_err(ctx, program,
+                                      "glGetProgramInterfaceiv");
+   if (!shProg)
+      return;
+
+   if (!params) {
+      _mesa_error(ctx, GL_INVALID_OPERATION,
+                  "glGetProgramInterfaceiv(params NULL)");
+      return;
+   }
+
+   /* Validate interface. */
+   if (!supported_interface_enum(programInterface)) {
+      _mesa_error(ctx, GL_INVALID_OPERATION, "glGetProgramInterfaceiv(%s)",
+                  _mesa_lookup_enum_by_nr(programInterface));
+      return;
+   }
+
+   /* Validate pname against interface. */
+   switch(pname) {
+   case GL_ACTIVE_RESOURCES:
+      for (i = 0, *params = 0; i < shProg->NumProgramResourceList; i++)
+         if (shProg->ProgramResourceList[i].Type == programInterface)
+            (*params)++;
+      break;
+   case GL_MAX_NAME_LENGTH:
+      if (programInterface == GL_ATOMIC_COUNTER_BUFFER) {
+         _mesa_error(ctx, GL_INVALID_OPERATION,
+                     "glGetProgramInterfaceiv(%s pname %s)",
+                     _mesa_lookup_enum_by_nr(programInterface),
+                     _mesa_lookup_enum_by_nr(pname));
+         return;
+      }
+      /* Name length consists of base name, 3 additional chars '[0]' if
+       * resource is an array and finally 1 char for string terminator.
+       */
+      for (i = 0, *params = 0; i < shProg->NumProgramResourceList; i++) {
+         if (shProg->ProgramResourceList[i].Type != programInterface)
+            continue;
+         const char *name =
+            _mesa_program_resource_name(&shProg->ProgramResourceList[i]);
+         unsigned array_size =
+            _mesa_program_resource_array_size(&shProg->ProgramResourceList[i]);
+         *params = MAX2(*params, strlen(name) + (array_size ? 3 : 0) + 1);
+      }
+      break;
+   case GL_MAX_NUM_ACTIVE_VARIABLES:
+      switch (programInterface) {
+      case GL_UNIFORM_BLOCK:
+         for (i = 0, *params = 0; i < shProg->NumProgramResourceList; i++) {
+            if (shProg->ProgramResourceList[i].Type == programInterface) {
+               struct gl_uniform_block *block =
+                  (struct gl_uniform_block *)
+                  shProg->ProgramResourceList[i].Data;
+               *params = MAX2(*params, block->NumUniforms);
+            }
+         }
+         break;
+      case GL_ATOMIC_COUNTER_BUFFER:
+         for (i = 0, *params = 0; i < shProg->NumProgramResourceList; i++) {
+            if (shProg->ProgramResourceList[i].Type == programInterface) {
+               struct gl_active_atomic_buffer *buffer =
+                  (struct gl_active_atomic_buffer *)
+                  shProg->ProgramResourceList[i].Data;
+               *params = MAX2(*params, buffer->NumUniforms);
+            }
+         }
+         break;
+      default:
+        _mesa_error(ctx, GL_INVALID_OPERATION,
+                    "glGetProgramInterfaceiv(%s pname %s)",
+                    _mesa_lookup_enum_by_nr(programInterface),
+                    _mesa_lookup_enum_by_nr(pname));
+      };
+      break;
+   case GL_MAX_NUM_COMPATIBLE_SUBROUTINES:
+   default:
+      _mesa_error(ctx, GL_INVALID_OPERATION,
+                  "glGetProgramInterfaceiv(pname %s)",
+                  _mesa_lookup_enum_by_nr(pname));
+   }
 }
 
 GLuint GLAPIENTRY
index df9081b734d29624b00a9113c0b8d3186a7349dc..4e0247ea817dd1b24e269c7ecbdcfdc5b0247e8d 100644 (file)
 #include "shaderobj.h"
 #include "program/hash_table.h"
 #include "../glsl/program.h"
+#include "uniforms.h"
+#include "main/enums.h"
 
 extern "C" {
 #include "shaderapi.h"
 }
 
+/**
+ * Declare convenience functions to return resource data in a given type.
+ * Warning! this is not type safe so be *very* careful when using these.
+ */
+#define DECL_RESOURCE_FUNC(name, type) \
+const type * RESOURCE_ ## name (gl_program_resource *res) { \
+   assert(res->Data); \
+   return (type *) res->Data; \
+}
+
+DECL_RESOURCE_FUNC(VAR, ir_variable);
+DECL_RESOURCE_FUNC(UBO, gl_uniform_block);
+DECL_RESOURCE_FUNC(UNI, gl_uniform_storage);
+DECL_RESOURCE_FUNC(ATC, gl_active_atomic_buffer);
+DECL_RESOURCE_FUNC(XFB, gl_transform_feedback_varying_info);
+
 void GLAPIENTRY
 _mesa_BindAttribLocation(GLhandleARB program, GLuint index,
                             const GLcharARB *name)
@@ -498,3 +516,44 @@ _mesa_GetFragDataLocation(GLuint program, const GLchar *name)
 
    return -1;
 }
+
+const char*
+_mesa_program_resource_name(struct gl_program_resource *res)
+{
+   switch (res->Type) {
+   case GL_UNIFORM_BLOCK:
+      return RESOURCE_UBO(res)->Name;
+   case GL_TRANSFORM_FEEDBACK_VARYING:
+      return RESOURCE_XFB(res)->Name;
+   case GL_PROGRAM_INPUT:
+   case GL_PROGRAM_OUTPUT:
+      return RESOURCE_VAR(res)->name;
+   case GL_UNIFORM:
+      return RESOURCE_UNI(res)->name;
+   default:
+      assert(!"support for resource type not implemented");
+   }
+   return NULL;
+}
+
+
+unsigned
+_mesa_program_resource_array_size(struct gl_program_resource *res)
+{
+   switch (res->Type) {
+   case GL_TRANSFORM_FEEDBACK_VARYING:
+      return RESOURCE_XFB(res)->Size > 1 ?
+             RESOURCE_XFB(res)->Size : 0;
+   case GL_PROGRAM_INPUT:
+   case GL_PROGRAM_OUTPUT:
+      return RESOURCE_VAR(res)->data.max_array_access;
+   case GL_UNIFORM:
+      return RESOURCE_UNI(res)->array_elements;
+   case GL_ATOMIC_COUNTER_BUFFER:
+   case GL_UNIFORM_BLOCK:
+      return 0;
+   default:
+      assert(!"support for resource type not implemented");
+   }
+   return 0;
+}
index 047d2562dd1a3ebfe863afb3a7369b9573fb0673..6db52f798b83c32fe4e68af2d91598cf9e56267b 100644 (file)
@@ -219,6 +219,13 @@ extern GLuint GLAPIENTRY
 _mesa_CreateShaderProgramv(GLenum type, GLsizei count,
                            const GLchar* const *strings);
 
+/* GL_ARB_program_resource_query */
+extern const char*
+_mesa_program_resource_name(struct gl_program_resource *res);
+
+extern unsigned
+_mesa_program_resource_array_size(struct gl_program_resource *res);
+
 #ifdef __cplusplus
 }
 #endif