mesa/main: Fix UBO/SSBO ACTIVE_VARIABLES query (ARB_gl_spirv)

When querying MAX_NUM_ACTIVE_VARIABLES, NUM_ACTIVE_VARIABLES and
ACTIVE_VARIABLES over SSBO and UBO interfaces, we filter the variables
which are active using the variable's name and looking for it in the
program resource list. If it is in the program resource list, the
variable will be considered active.

However due to ARB_gl_spirv where name reflection information is not
mandatory, we can use the UBO/SSBO binding and variable offset to
filter which variables which are active.

v2: use RESOURCE_UBO/UNI macros instead of direct castings, update
    comment (Alejandro)

v3: Change signature of _mesa_program_resource_find_active_variable
    to simplify calling it. Also, squash the fix for find_binding_offset
    for arrays of blocks (Arcady)

Signed-off-by: Antia Puentes <apuentes@igalia.com>
Signed-off-by: Alejandro Piñeiro <apinheiro@igalia.com>
Signed-off-by: Arcady Goldmints-Orlov <agoldmints@igalia.com>

Reviewed-by: Caio Marcelo de Oliveira Filho <caio.oliveira@intel.com>
This commit is contained in:
Antia Puentes 2018-12-18 11:55:04 +01:00 committed by Alejandro Piñeiro
parent 161de77e0f
commit 0baa553fab
3 changed files with 149 additions and 15 deletions

View File

@ -164,10 +164,12 @@ _mesa_GetProgramInterfaceiv(GLuint program, GLenum programInterface,
shProg->data->ProgramResourceList[i].Data;
GLint block_params = 0;
for (unsigned j = 0; j < block->NumUniforms; j++) {
const char *iname = block->Uniforms[j].IndexName;
struct gl_program_resource *uni =
_mesa_program_resource_find_name(shProg, GL_BUFFER_VARIABLE,
iname, NULL);
_mesa_program_resource_find_active_variable(
shProg,
GL_BUFFER_VARIABLE,
block,
j);
if (!uni)
continue;
block_params++;

View File

@ -638,6 +638,119 @@ _mesa_program_resource_find_name(struct gl_shader_program *shProg,
return NULL;
}
/* Find an uniform or buffer variable program resource with an specific offset
* inside a block with an specific binding.
*
* Valid interfaces are GL_BUFFER_VARIABLE and GL_UNIFORM.
*/
static struct gl_program_resource *
program_resource_find_binding_offset(struct gl_shader_program *shProg,
GLenum programInterface,
const GLuint binding,
const GLint offset)
{
/* First we need to get the BLOCK_INDEX from the BUFFER_BINDING */
GLenum blockInterface;
switch (programInterface) {
case GL_BUFFER_VARIABLE:
blockInterface = GL_SHADER_STORAGE_BLOCK;
break;
case GL_UNIFORM:
blockInterface = GL_UNIFORM_BLOCK;
break;
default:
assert("Invalid program interface");
return NULL;
}
int block_index = -1;
int starting_index = -1;
struct gl_program_resource *res = shProg->data->ProgramResourceList;
/* Blocks are added to the resource list in the same order that they are
* added to UniformBlocks/ShaderStorageBlocks. Furthermore, all the blocks
* of each type (UBO/SSBO) are contiguous, so we can infer block_index from
* the resource list.
*/
for (unsigned i = 0; i < shProg->data->NumProgramResourceList; i++, res++) {
if (res->Type != blockInterface)
continue;
/* Store the first index where a resource of the specific interface is. */
if (starting_index == -1)
starting_index = i;
const struct gl_uniform_block *block = RESOURCE_UBO(res);
if (block->Binding == binding) {
/* For arrays, or arrays of arrays of blocks, we want the resource
* for the block with base index. Most properties for members of each
* block are inherited from the block with the base index, including
* a uniform being active or not.
*/
block_index = i - starting_index - block->linearized_array_index;
break;
}
}
if (block_index == -1)
return NULL;
/* We now look for the resource corresponding to the uniform or buffer
* variable using the BLOCK_INDEX and OFFSET.
*/
res = shProg->data->ProgramResourceList;
for (unsigned i = 0; i < shProg->data->NumProgramResourceList; i++, res++) {
if (res->Type != programInterface)
continue;
const struct gl_uniform_storage *uniform = RESOURCE_UNI(res);
if (uniform->block_index == block_index && uniform->offset == offset) {
return res;
}
}
return NULL;
}
/* Checks if an uniform or buffer variable is in the active program resource
* list.
*
* It takes into accout that for variables coming from SPIR-V binaries their
* names could not be available (ARB_gl_spirv). In that case, it will use the
* the offset and the block binding to locate the resource.
*
* Valid interfaces are GL_BUFFER_VARIABLE and GL_UNIFORM.
*/
struct gl_program_resource *
_mesa_program_resource_find_active_variable(struct gl_shader_program *shProg,
GLenum programInterface,
const gl_uniform_block *block,
unsigned index)
{
struct gl_program_resource *res;
struct gl_uniform_buffer_variable uni = block->Uniforms[index];
assert(programInterface == GL_UNIFORM ||
programInterface == GL_BUFFER_VARIABLE);
if (uni.IndexName) {
res = _mesa_program_resource_find_name(shProg, programInterface, uni.IndexName,
NULL);
} else {
/* As the resource has no associated name (ARB_gl_spirv),
* we can use the UBO/SSBO binding and offset to find it.
*/
res = program_resource_find_binding_offset(shProg, programInterface,
block->Binding, uni.Offset);
}
return res;
}
static GLuint
calc_resource_index(struct gl_shader_program *shProg,
struct gl_program_resource *res)
@ -1039,10 +1152,13 @@ get_buffer_property(struct gl_shader_program *shProg,
case GL_NUM_ACTIVE_VARIABLES:
*val = 0;
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,
NULL);
_mesa_program_resource_find_active_variable(
shProg,
GL_UNIFORM,
RESOURCE_UBO(res),
i);
if (!uni)
continue;
(*val)++;
@ -1051,10 +1167,13 @@ get_buffer_property(struct gl_shader_program *shProg,
case GL_ACTIVE_VARIABLES: {
unsigned num_values = 0;
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,
NULL);
_mesa_program_resource_find_active_variable(
shProg,
GL_UNIFORM,
RESOURCE_UBO(res),
i);
if (!uni)
continue;
*val++ =
@ -1075,10 +1194,13 @@ get_buffer_property(struct gl_shader_program *shProg,
case GL_NUM_ACTIVE_VARIABLES:
*val = 0;
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_BUFFER_VARIABLE,
iname, NULL);
_mesa_program_resource_find_active_variable(
shProg,
GL_BUFFER_VARIABLE,
RESOURCE_UBO(res),
i);
if (!uni)
continue;
(*val)++;
@ -1087,10 +1209,13 @@ get_buffer_property(struct gl_shader_program *shProg,
case GL_ACTIVE_VARIABLES: {
unsigned num_values = 0;
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_BUFFER_VARIABLE,
iname, NULL);
_mesa_program_resource_find_active_variable(
shProg,
GL_BUFFER_VARIABLE,
RESOURCE_UBO(res),
i);
if (!uni)
continue;
*val++ =

View File

@ -29,6 +29,7 @@
#include "glheader.h"
#include "main/mtypes.h"
#include "compiler/shader_enums.h"
#ifdef __cplusplus
@ -296,6 +297,12 @@ extern struct gl_program_resource *
_mesa_program_resource_find_index(struct gl_shader_program *shProg,
GLenum programInterface, GLuint index);
extern struct gl_program_resource *
_mesa_program_resource_find_active_variable(struct gl_shader_program *shProg,
GLenum programInterface,
const struct gl_uniform_block *block,
unsigned index);
extern bool
_mesa_get_program_resource_name(struct gl_shader_program *shProg,
GLenum programInterface, GLuint index,