program_resource: add subroutine support (v3.1)
This fleshes out the ARB_program_query support for the APIs that ARB_shader_subroutine introduces, leaving some TODOs for later addition. v2: reworked for lots of the ARB_program_interface_query entry points and tests v3: use common function to test for subroutine support v3.1: add tess, fix missing breaks Acked-by: Kenneth Graunke <kenneth@whitecape.org> Signed-off-by: Dave Airlie <airlied@redhat.com>
This commit is contained in:
@@ -28,10 +28,11 @@
|
|||||||
#include "main/mtypes.h"
|
#include "main/mtypes.h"
|
||||||
#include "main/shaderapi.h"
|
#include "main/shaderapi.h"
|
||||||
#include "main/shaderobj.h"
|
#include "main/shaderobj.h"
|
||||||
|
#include "main/context.h"
|
||||||
#include "program_resource.h"
|
#include "program_resource.h"
|
||||||
|
#include "ir_uniform.h"
|
||||||
static bool
|
static bool
|
||||||
supported_interface_enum(GLenum iface)
|
supported_interface_enum(struct gl_context *ctx, GLenum iface)
|
||||||
{
|
{
|
||||||
switch (iface) {
|
switch (iface) {
|
||||||
case GL_UNIFORM:
|
case GL_UNIFORM:
|
||||||
@@ -42,17 +43,21 @@ supported_interface_enum(GLenum iface)
|
|||||||
case GL_ATOMIC_COUNTER_BUFFER:
|
case GL_ATOMIC_COUNTER_BUFFER:
|
||||||
return true;
|
return true;
|
||||||
case GL_VERTEX_SUBROUTINE:
|
case GL_VERTEX_SUBROUTINE:
|
||||||
|
case GL_FRAGMENT_SUBROUTINE:
|
||||||
|
case GL_VERTEX_SUBROUTINE_UNIFORM:
|
||||||
|
case GL_FRAGMENT_SUBROUTINE_UNIFORM:
|
||||||
|
return _mesa_has_shader_subroutine(ctx);
|
||||||
|
case GL_GEOMETRY_SUBROUTINE:
|
||||||
|
case GL_GEOMETRY_SUBROUTINE_UNIFORM:
|
||||||
|
return _mesa_has_geometry_shaders(ctx) && _mesa_has_shader_subroutine(ctx);
|
||||||
|
case GL_COMPUTE_SUBROUTINE:
|
||||||
|
case GL_COMPUTE_SUBROUTINE_UNIFORM:
|
||||||
|
return _mesa_has_compute_shaders(ctx) && _mesa_has_shader_subroutine(ctx);
|
||||||
case GL_TESS_CONTROL_SUBROUTINE:
|
case GL_TESS_CONTROL_SUBROUTINE:
|
||||||
case GL_TESS_EVALUATION_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_CONTROL_SUBROUTINE_UNIFORM:
|
||||||
case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM:
|
case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM:
|
||||||
case GL_GEOMETRY_SUBROUTINE_UNIFORM:
|
return _mesa_has_tessellation(ctx) && _mesa_has_shader_subroutine(ctx);
|
||||||
case GL_FRAGMENT_SUBROUTINE_UNIFORM:
|
|
||||||
case GL_COMPUTE_SUBROUTINE_UNIFORM:
|
|
||||||
case GL_BUFFER_VARIABLE:
|
case GL_BUFFER_VARIABLE:
|
||||||
case GL_SHADER_STORAGE_BLOCK:
|
case GL_SHADER_STORAGE_BLOCK:
|
||||||
default:
|
default:
|
||||||
@@ -79,7 +84,7 @@ _mesa_GetProgramInterfaceiv(GLuint program, GLenum programInterface,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Validate interface. */
|
/* Validate interface. */
|
||||||
if (!supported_interface_enum(programInterface)) {
|
if (!supported_interface_enum(ctx, programInterface)) {
|
||||||
_mesa_error(ctx, GL_INVALID_OPERATION, "glGetProgramInterfaceiv(%s)",
|
_mesa_error(ctx, GL_INVALID_OPERATION, "glGetProgramInterfaceiv(%s)",
|
||||||
_mesa_enum_to_string(programInterface));
|
_mesa_enum_to_string(programInterface));
|
||||||
return;
|
return;
|
||||||
@@ -143,6 +148,31 @@ _mesa_GetProgramInterfaceiv(GLuint program, GLenum programInterface,
|
|||||||
};
|
};
|
||||||
break;
|
break;
|
||||||
case GL_MAX_NUM_COMPATIBLE_SUBROUTINES:
|
case GL_MAX_NUM_COMPATIBLE_SUBROUTINES:
|
||||||
|
switch (programInterface) {
|
||||||
|
case GL_VERTEX_SUBROUTINE_UNIFORM:
|
||||||
|
case GL_FRAGMENT_SUBROUTINE_UNIFORM:
|
||||||
|
case GL_GEOMETRY_SUBROUTINE_UNIFORM:
|
||||||
|
case GL_COMPUTE_SUBROUTINE_UNIFORM:
|
||||||
|
case GL_TESS_CONTROL_SUBROUTINE_UNIFORM:
|
||||||
|
case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM: {
|
||||||
|
for (i = 0, *params = 0; i < shProg->NumProgramResourceList; i++) {
|
||||||
|
if (shProg->ProgramResourceList[i].Type == programInterface) {
|
||||||
|
struct gl_uniform_storage *uni =
|
||||||
|
(struct gl_uniform_storage *)
|
||||||
|
shProg->ProgramResourceList[i].Data;
|
||||||
|
*params = MAX2(*params, uni->num_compatible_subroutines);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
_mesa_error(ctx, GL_INVALID_OPERATION,
|
||||||
|
"glGetProgramInterfaceiv(%s pname %s)",
|
||||||
|
_mesa_enum_to_string(programInterface),
|
||||||
|
_mesa_enum_to_string(pname));
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
_mesa_error(ctx, GL_INVALID_OPERATION,
|
_mesa_error(ctx, GL_INVALID_OPERATION,
|
||||||
"glGetProgramInterfaceiv(pname %s)",
|
"glGetProgramInterfaceiv(pname %s)",
|
||||||
@@ -206,6 +236,11 @@ _mesa_GetProgramResourceIndex(GLuint program, GLenum programInterface,
|
|||||||
if (!shProg || !name)
|
if (!shProg || !name)
|
||||||
return GL_INVALID_INDEX;
|
return GL_INVALID_INDEX;
|
||||||
|
|
||||||
|
if (!supported_interface_enum(ctx, programInterface)) {
|
||||||
|
_mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramResourceIndex(%s)",
|
||||||
|
_mesa_enum_to_string(programInterface));
|
||||||
|
return GL_INVALID_INDEX;
|
||||||
|
}
|
||||||
/*
|
/*
|
||||||
* For the interface TRANSFORM_FEEDBACK_VARYING, the value INVALID_INDEX
|
* For the interface TRANSFORM_FEEDBACK_VARYING, the value INVALID_INDEX
|
||||||
* should be returned when querying the index assigned to the special names
|
* should be returned when querying the index assigned to the special names
|
||||||
@@ -217,6 +252,18 @@ _mesa_GetProgramResourceIndex(GLuint program, GLenum programInterface,
|
|||||||
return GL_INVALID_INDEX;
|
return GL_INVALID_INDEX;
|
||||||
|
|
||||||
switch (programInterface) {
|
switch (programInterface) {
|
||||||
|
case GL_TESS_CONTROL_SUBROUTINE:
|
||||||
|
case GL_TESS_CONTROL_SUBROUTINE_UNIFORM:
|
||||||
|
case GL_TESS_EVALUATION_SUBROUTINE:
|
||||||
|
case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM:
|
||||||
|
case GL_COMPUTE_SUBROUTINE:
|
||||||
|
case GL_COMPUTE_SUBROUTINE_UNIFORM:
|
||||||
|
case GL_GEOMETRY_SUBROUTINE:
|
||||||
|
case GL_GEOMETRY_SUBROUTINE_UNIFORM:
|
||||||
|
case GL_VERTEX_SUBROUTINE:
|
||||||
|
case GL_FRAGMENT_SUBROUTINE:
|
||||||
|
case GL_VERTEX_SUBROUTINE_UNIFORM:
|
||||||
|
case GL_FRAGMENT_SUBROUTINE_UNIFORM:
|
||||||
case GL_PROGRAM_INPUT:
|
case GL_PROGRAM_INPUT:
|
||||||
case GL_PROGRAM_OUTPUT:
|
case GL_PROGRAM_OUTPUT:
|
||||||
case GL_UNIFORM:
|
case GL_UNIFORM:
|
||||||
@@ -260,7 +307,7 @@ _mesa_GetProgramResourceName(GLuint program, GLenum programInterface,
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
if (programInterface == GL_ATOMIC_COUNTER_BUFFER ||
|
if (programInterface == GL_ATOMIC_COUNTER_BUFFER ||
|
||||||
!supported_interface_enum(programInterface)) {
|
!supported_interface_enum(ctx, programInterface)) {
|
||||||
_mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramResourceName(%s)",
|
_mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramResourceName(%s)",
|
||||||
_mesa_enum_to_string(programInterface));
|
_mesa_enum_to_string(programInterface));
|
||||||
return;
|
return;
|
||||||
@@ -366,24 +413,33 @@ _mesa_GetProgramResourceLocation(GLuint program, GLenum programInterface,
|
|||||||
case GL_PROGRAM_OUTPUT:
|
case GL_PROGRAM_OUTPUT:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* For reference valid cases requiring additional extension support:
|
|
||||||
* GL_ARB_shader_subroutine
|
|
||||||
* GL_ARB_tessellation_shader
|
|
||||||
* GL_ARB_compute_shader
|
|
||||||
*/
|
|
||||||
case GL_VERTEX_SUBROUTINE_UNIFORM:
|
case GL_VERTEX_SUBROUTINE_UNIFORM:
|
||||||
|
case GL_FRAGMENT_SUBROUTINE_UNIFORM:
|
||||||
|
if (!_mesa_has_shader_subroutine(ctx))
|
||||||
|
goto fail;
|
||||||
|
break;
|
||||||
|
case GL_GEOMETRY_SUBROUTINE_UNIFORM:
|
||||||
|
if (!_mesa_has_geometry_shaders(ctx) || !_mesa_has_shader_subroutine(ctx))
|
||||||
|
goto fail;
|
||||||
|
break;
|
||||||
|
case GL_COMPUTE_SUBROUTINE_UNIFORM:
|
||||||
|
if (!_mesa_has_compute_shaders(ctx) || !_mesa_has_shader_subroutine(ctx))
|
||||||
|
goto fail;
|
||||||
|
break;
|
||||||
case GL_TESS_CONTROL_SUBROUTINE_UNIFORM:
|
case GL_TESS_CONTROL_SUBROUTINE_UNIFORM:
|
||||||
case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM:
|
case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM:
|
||||||
case GL_GEOMETRY_SUBROUTINE_UNIFORM:
|
if (!_mesa_has_tessellation(ctx) || !_mesa_has_shader_subroutine(ctx))
|
||||||
case GL_FRAGMENT_SUBROUTINE_UNIFORM:
|
goto fail;
|
||||||
case GL_COMPUTE_SUBROUTINE_UNIFORM:
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
_mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramResourceLocation(%s %s)",
|
goto fail;
|
||||||
_mesa_enum_to_string(programInterface), name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return _mesa_program_resource_location(shProg, programInterface, name);
|
return _mesa_program_resource_location(shProg, programInterface, name);
|
||||||
|
fail:
|
||||||
|
_mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramResourceLocation(%s %s)",
|
||||||
|
_mesa_enum_to_string(programInterface), name);
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -61,6 +61,7 @@ DECL_RESOURCE_FUNC(UBO, gl_uniform_block);
|
|||||||
DECL_RESOURCE_FUNC(UNI, gl_uniform_storage);
|
DECL_RESOURCE_FUNC(UNI, gl_uniform_storage);
|
||||||
DECL_RESOURCE_FUNC(ATC, gl_active_atomic_buffer);
|
DECL_RESOURCE_FUNC(ATC, gl_active_atomic_buffer);
|
||||||
DECL_RESOURCE_FUNC(XFB, gl_transform_feedback_varying_info);
|
DECL_RESOURCE_FUNC(XFB, gl_transform_feedback_varying_info);
|
||||||
|
DECL_RESOURCE_FUNC(SUB, gl_subroutine_function);
|
||||||
|
|
||||||
void GLAPIENTRY
|
void GLAPIENTRY
|
||||||
_mesa_BindAttribLocation(GLhandleARB program, GLuint index,
|
_mesa_BindAttribLocation(GLhandleARB program, GLuint index,
|
||||||
@@ -497,6 +498,20 @@ _mesa_program_resource_name(struct gl_program_resource *res)
|
|||||||
return RESOURCE_VAR(res)->name;
|
return RESOURCE_VAR(res)->name;
|
||||||
case GL_UNIFORM:
|
case GL_UNIFORM:
|
||||||
return RESOURCE_UNI(res)->name;
|
return RESOURCE_UNI(res)->name;
|
||||||
|
case GL_VERTEX_SUBROUTINE_UNIFORM:
|
||||||
|
case GL_GEOMETRY_SUBROUTINE_UNIFORM:
|
||||||
|
case GL_FRAGMENT_SUBROUTINE_UNIFORM:
|
||||||
|
case GL_COMPUTE_SUBROUTINE_UNIFORM:
|
||||||
|
case GL_TESS_CONTROL_SUBROUTINE_UNIFORM:
|
||||||
|
case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM:
|
||||||
|
return RESOURCE_UNI(res)->name + MESA_SUBROUTINE_PREFIX_LEN;
|
||||||
|
case GL_VERTEX_SUBROUTINE:
|
||||||
|
case GL_GEOMETRY_SUBROUTINE:
|
||||||
|
case GL_FRAGMENT_SUBROUTINE:
|
||||||
|
case GL_COMPUTE_SUBROUTINE:
|
||||||
|
case GL_TESS_CONTROL_SUBROUTINE:
|
||||||
|
case GL_TESS_EVALUATION_SUBROUTINE:
|
||||||
|
return RESOURCE_SUB(res)->name;
|
||||||
default:
|
default:
|
||||||
assert(!"support for resource type not implemented");
|
assert(!"support for resource type not implemented");
|
||||||
}
|
}
|
||||||
@@ -515,7 +530,19 @@ _mesa_program_resource_array_size(struct gl_program_resource *res)
|
|||||||
case GL_PROGRAM_OUTPUT:
|
case GL_PROGRAM_OUTPUT:
|
||||||
return RESOURCE_VAR(res)->data.max_array_access;
|
return RESOURCE_VAR(res)->data.max_array_access;
|
||||||
case GL_UNIFORM:
|
case GL_UNIFORM:
|
||||||
|
case GL_VERTEX_SUBROUTINE_UNIFORM:
|
||||||
|
case GL_GEOMETRY_SUBROUTINE_UNIFORM:
|
||||||
|
case GL_FRAGMENT_SUBROUTINE_UNIFORM:
|
||||||
|
case GL_COMPUTE_SUBROUTINE_UNIFORM:
|
||||||
|
case GL_TESS_CONTROL_SUBROUTINE_UNIFORM:
|
||||||
|
case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM:
|
||||||
return RESOURCE_UNI(res)->array_elements;
|
return RESOURCE_UNI(res)->array_elements;
|
||||||
|
case GL_VERTEX_SUBROUTINE:
|
||||||
|
case GL_GEOMETRY_SUBROUTINE:
|
||||||
|
case GL_FRAGMENT_SUBROUTINE:
|
||||||
|
case GL_COMPUTE_SUBROUTINE:
|
||||||
|
case GL_TESS_CONTROL_SUBROUTINE:
|
||||||
|
case GL_TESS_EVALUATION_SUBROUTINE:
|
||||||
case GL_ATOMIC_COUNTER_BUFFER:
|
case GL_ATOMIC_COUNTER_BUFFER:
|
||||||
case GL_UNIFORM_BLOCK:
|
case GL_UNIFORM_BLOCK:
|
||||||
return 0;
|
return 0;
|
||||||
@@ -571,6 +598,18 @@ _mesa_program_resource_find_name(struct gl_shader_program *shProg,
|
|||||||
case GL_TRANSFORM_FEEDBACK_VARYING:
|
case GL_TRANSFORM_FEEDBACK_VARYING:
|
||||||
case GL_UNIFORM_BLOCK:
|
case GL_UNIFORM_BLOCK:
|
||||||
case GL_UNIFORM:
|
case GL_UNIFORM:
|
||||||
|
case GL_VERTEX_SUBROUTINE_UNIFORM:
|
||||||
|
case GL_GEOMETRY_SUBROUTINE_UNIFORM:
|
||||||
|
case GL_FRAGMENT_SUBROUTINE_UNIFORM:
|
||||||
|
case GL_COMPUTE_SUBROUTINE_UNIFORM:
|
||||||
|
case GL_TESS_CONTROL_SUBROUTINE_UNIFORM:
|
||||||
|
case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM:
|
||||||
|
case GL_VERTEX_SUBROUTINE:
|
||||||
|
case GL_GEOMETRY_SUBROUTINE:
|
||||||
|
case GL_FRAGMENT_SUBROUTINE:
|
||||||
|
case GL_COMPUTE_SUBROUTINE:
|
||||||
|
case GL_TESS_CONTROL_SUBROUTINE:
|
||||||
|
case GL_TESS_EVALUATION_SUBROUTINE:
|
||||||
if (strncmp(rname, name, baselen) == 0) {
|
if (strncmp(rname, name, baselen) == 0) {
|
||||||
/* Basename match, check if array or struct. */
|
/* Basename match, check if array or struct. */
|
||||||
if (name[baselen] == '\0' ||
|
if (name[baselen] == '\0' ||
|
||||||
@@ -651,6 +690,18 @@ _mesa_program_resource_find_index(struct gl_shader_program *shProg,
|
|||||||
case GL_PROGRAM_INPUT:
|
case GL_PROGRAM_INPUT:
|
||||||
case GL_PROGRAM_OUTPUT:
|
case GL_PROGRAM_OUTPUT:
|
||||||
case GL_UNIFORM:
|
case GL_UNIFORM:
|
||||||
|
case GL_VERTEX_SUBROUTINE_UNIFORM:
|
||||||
|
case GL_GEOMETRY_SUBROUTINE_UNIFORM:
|
||||||
|
case GL_FRAGMENT_SUBROUTINE_UNIFORM:
|
||||||
|
case GL_COMPUTE_SUBROUTINE_UNIFORM:
|
||||||
|
case GL_TESS_CONTROL_SUBROUTINE_UNIFORM:
|
||||||
|
case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM:
|
||||||
|
case GL_VERTEX_SUBROUTINE:
|
||||||
|
case GL_GEOMETRY_SUBROUTINE:
|
||||||
|
case GL_FRAGMENT_SUBROUTINE:
|
||||||
|
case GL_COMPUTE_SUBROUTINE:
|
||||||
|
case GL_TESS_CONTROL_SUBROUTINE:
|
||||||
|
case GL_TESS_EVALUATION_SUBROUTINE:
|
||||||
if (++idx == (int) index)
|
if (++idx == (int) index)
|
||||||
return res;
|
return res;
|
||||||
break;
|
break;
|
||||||
@@ -740,6 +791,8 @@ program_resource_location(struct gl_shader_program *shProg,
|
|||||||
{
|
{
|
||||||
unsigned index, offset;
|
unsigned index, offset;
|
||||||
int array_index = -1;
|
int array_index = -1;
|
||||||
|
long offset_ret;
|
||||||
|
const GLchar *base_name_end;
|
||||||
|
|
||||||
if (res->Type == GL_PROGRAM_INPUT || res->Type == GL_PROGRAM_OUTPUT) {
|
if (res->Type == GL_PROGRAM_INPUT || res->Type == GL_PROGRAM_OUTPUT) {
|
||||||
array_index = array_index_of_resource(res, name);
|
array_index = array_index_of_resource(res, name);
|
||||||
@@ -780,6 +833,14 @@ program_resource_location(struct gl_shader_program *shProg,
|
|||||||
/* location in remap table + array element offset */
|
/* location in remap table + array element offset */
|
||||||
return RESOURCE_UNI(res)->remap_location + offset;
|
return RESOURCE_UNI(res)->remap_location + offset;
|
||||||
|
|
||||||
|
case GL_VERTEX_SUBROUTINE_UNIFORM:
|
||||||
|
case GL_GEOMETRY_SUBROUTINE_UNIFORM:
|
||||||
|
case GL_FRAGMENT_SUBROUTINE_UNIFORM:
|
||||||
|
case GL_COMPUTE_SUBROUTINE_UNIFORM:
|
||||||
|
case GL_TESS_CONTROL_SUBROUTINE_UNIFORM:
|
||||||
|
case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM:
|
||||||
|
offset_ret = parse_program_resource_name(name, &base_name_end);
|
||||||
|
return RESOURCE_UNI(res)->remap_location + ((offset_ret != -1) ? offset_ret : 0);
|
||||||
default:
|
default:
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -1048,6 +1109,46 @@ _mesa_program_resource_prop(struct gl_shader_program *shProg,
|
|||||||
goto invalid_operation;
|
goto invalid_operation;
|
||||||
*val = RESOURCE_VAR(res)->data.index;
|
*val = RESOURCE_VAR(res)->data.index;
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
case GL_NUM_COMPATIBLE_SUBROUTINES:
|
||||||
|
if (res->Type != GL_VERTEX_SUBROUTINE_UNIFORM &&
|
||||||
|
res->Type != GL_FRAGMENT_SUBROUTINE_UNIFORM &&
|
||||||
|
res->Type != GL_GEOMETRY_SUBROUTINE_UNIFORM &&
|
||||||
|
res->Type != GL_COMPUTE_SUBROUTINE_UNIFORM &&
|
||||||
|
res->Type != GL_TESS_CONTROL_SUBROUTINE_UNIFORM &&
|
||||||
|
res->Type != GL_TESS_EVALUATION_SUBROUTINE_UNIFORM)
|
||||||
|
goto invalid_operation;
|
||||||
|
*val = RESOURCE_UNI(res)->num_compatible_subroutines;
|
||||||
|
return 1;
|
||||||
|
case GL_COMPATIBLE_SUBROUTINES: {
|
||||||
|
const struct gl_uniform_storage *uni;
|
||||||
|
struct gl_shader *sh;
|
||||||
|
unsigned count, i;
|
||||||
|
int j;
|
||||||
|
|
||||||
|
if (res->Type != GL_VERTEX_SUBROUTINE_UNIFORM &&
|
||||||
|
res->Type != GL_FRAGMENT_SUBROUTINE_UNIFORM &&
|
||||||
|
res->Type != GL_GEOMETRY_SUBROUTINE_UNIFORM &&
|
||||||
|
res->Type != GL_COMPUTE_SUBROUTINE_UNIFORM &&
|
||||||
|
res->Type != GL_TESS_CONTROL_SUBROUTINE_UNIFORM &&
|
||||||
|
res->Type != GL_TESS_EVALUATION_SUBROUTINE_UNIFORM)
|
||||||
|
goto invalid_operation;
|
||||||
|
uni = RESOURCE_UNI(res);
|
||||||
|
|
||||||
|
sh = shProg->_LinkedShaders[_mesa_shader_stage_from_subroutine_uniform(res->Type)];
|
||||||
|
count = 0;
|
||||||
|
for (i = 0; i < sh->NumSubroutineFunctions; i++) {
|
||||||
|
struct gl_subroutine_function *fn = &sh->SubroutineFunctions[i];
|
||||||
|
for (j = 0; j < fn->num_compat_types; j++) {
|
||||||
|
if (fn->types[j] == uni->type) {
|
||||||
|
val[count++] = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
/* GL_ARB_tessellation_shader */
|
||||||
case GL_IS_PER_PATCH:
|
case GL_IS_PER_PATCH:
|
||||||
switch (res->Type) {
|
switch (res->Type) {
|
||||||
case GL_PROGRAM_INPUT:
|
case GL_PROGRAM_INPUT:
|
||||||
|
Reference in New Issue
Block a user