mesa: glGetProgramInterfaceiv

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>
This commit is contained in:
Tapani Pälli 2015-03-06 15:05:51 +02:00
parent c796ce4108
commit 4d3b98bc58
3 changed files with 185 additions and 0 deletions

View file

@ -23,12 +23,131 @@
*
*/
#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

View file

@ -34,11 +34,29 @@
#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;
}

View 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