From 4d3b98bc5801df27a7f9f2e3df28d66d83f883d9 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Tapani=20P=C3=A4lli?= Date: Fri, 6 Mar 2015 15:05:51 +0200 Subject: [PATCH] mesa: glGetProgramInterfaceiv MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit 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 Reviewed-by: Martin Peres --- src/mesa/main/program_resource.c | 119 +++++++++++++++++++++++++++++++ src/mesa/main/shader_query.cpp | 59 +++++++++++++++ src/mesa/main/shaderapi.h | 7 ++ 3 files changed, 185 insertions(+) diff --git a/src/mesa/main/program_resource.c b/src/mesa/main/program_resource.c index b3b93aa6cc8..ae28a26d3e4 100644 --- a/src/mesa/main/program_resource.c +++ b/src/mesa/main/program_resource.c @@ -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 diff --git a/src/mesa/main/shader_query.cpp b/src/mesa/main/shader_query.cpp index df9081b734d..4e0247ea817 100644 --- a/src/mesa/main/shader_query.cpp +++ b/src/mesa/main/shader_query.cpp @@ -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; +} diff --git a/src/mesa/main/shaderapi.h b/src/mesa/main/shaderapi.h index 047d2562dd1..6db52f798b8 100644 --- a/src/mesa/main/shaderapi.h +++ b/src/mesa/main/shaderapi.h @@ -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 -- 2.30.2