glsl: remove now unused GLSL IR block linker
This is now done in the NIR linker instead. Reviewed-by: Alejandro Piñeiro <apinheiro@igalia.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/26534>
This commit is contained in:

committed by
Marge Bot

parent
32f274768e
commit
72ad0db505
@@ -1,294 +0,0 @@
|
||||
/*
|
||||
* Copyright © 2013 Intel Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "link_uniform_block_active_visitor.h"
|
||||
#include "program.h"
|
||||
#include "linker_util.h"
|
||||
|
||||
static link_uniform_block_active *
|
||||
process_block(void *mem_ctx, struct hash_table *ht, ir_variable *var)
|
||||
{
|
||||
const hash_entry *const existing_block =
|
||||
_mesa_hash_table_search(ht, glsl_get_type_name(var->get_interface_type()));
|
||||
|
||||
const glsl_type *const block_type = var->is_interface_instance()
|
||||
? var->type : var->get_interface_type();
|
||||
|
||||
|
||||
/* If a block with this block-name has not previously been seen, add it.
|
||||
* If a block with this block-name has been seen, it must be identical to
|
||||
* the block currently being examined.
|
||||
*/
|
||||
if (existing_block == NULL) {
|
||||
link_uniform_block_active *const b =
|
||||
rzalloc(mem_ctx, struct link_uniform_block_active);
|
||||
|
||||
b->type = block_type;
|
||||
b->has_instance_name = var->is_interface_instance();
|
||||
b->is_shader_storage = var->data.mode == ir_var_shader_storage;
|
||||
|
||||
if (var->data.explicit_binding) {
|
||||
b->has_binding = true;
|
||||
b->binding = var->data.binding;
|
||||
} else {
|
||||
b->has_binding = false;
|
||||
b->binding = 0;
|
||||
}
|
||||
|
||||
_mesa_hash_table_insert(ht, glsl_get_type_name(var->get_interface_type()), (void *) b);
|
||||
return b;
|
||||
} else {
|
||||
link_uniform_block_active *const b =
|
||||
(link_uniform_block_active *) existing_block->data;
|
||||
|
||||
if (b->type != block_type
|
||||
|| b->has_instance_name != var->is_interface_instance())
|
||||
return NULL;
|
||||
else
|
||||
return b;
|
||||
}
|
||||
|
||||
assert(!"Should not get here.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* For arrays of arrays this function will give us a middle ground between
|
||||
* detecting inactive uniform blocks and structuring them in a way that makes
|
||||
* it easy to calculate the offset for indirect indexing.
|
||||
*
|
||||
* For example given the shader:
|
||||
*
|
||||
* uniform ArraysOfArraysBlock
|
||||
* {
|
||||
* vec4 a;
|
||||
* } i[3][4][5];
|
||||
*
|
||||
* void main()
|
||||
* {
|
||||
* vec4 b = i[0][1][1].a;
|
||||
* gl_Position = i[2][2][3].a + b;
|
||||
* }
|
||||
*
|
||||
* There are only 2 active blocks above but for the sake of indirect indexing
|
||||
* and not over complicating the code we will end up with a count of 8. Here
|
||||
* each dimension has 2 different indices counted so we end up with 2*2*2
|
||||
*/
|
||||
static struct uniform_block_array_elements **
|
||||
process_arrays(void *mem_ctx, ir_dereference_array *ir,
|
||||
struct link_uniform_block_active *block)
|
||||
{
|
||||
if (ir) {
|
||||
struct uniform_block_array_elements **ub_array_ptr =
|
||||
process_arrays(mem_ctx, ir->array->as_dereference_array(), block);
|
||||
if (*ub_array_ptr == NULL) {
|
||||
*ub_array_ptr = rzalloc(mem_ctx, struct uniform_block_array_elements);
|
||||
(*ub_array_ptr)->ir = ir;
|
||||
(*ub_array_ptr)->aoa_size =
|
||||
ir->array->type->arrays_of_arrays_size();
|
||||
}
|
||||
|
||||
struct uniform_block_array_elements *ub_array = *ub_array_ptr;
|
||||
ir_constant *c = ir->array_index->as_constant();
|
||||
if (c) {
|
||||
/* Index is a constant, so mark just that element used, if not
|
||||
* already.
|
||||
*/
|
||||
const unsigned idx = c->get_uint_component(0);
|
||||
|
||||
unsigned i;
|
||||
for (i = 0; i < ub_array->num_array_elements; i++) {
|
||||
if (ub_array->array_elements[i] == idx)
|
||||
break;
|
||||
}
|
||||
|
||||
assert(i <= ub_array->num_array_elements);
|
||||
|
||||
if (i == ub_array->num_array_elements) {
|
||||
ub_array->array_elements = reralloc(mem_ctx,
|
||||
ub_array->array_elements,
|
||||
unsigned,
|
||||
ub_array->num_array_elements + 1);
|
||||
|
||||
ub_array->array_elements[ub_array->num_array_elements] = idx;
|
||||
|
||||
ub_array->num_array_elements++;
|
||||
}
|
||||
} else {
|
||||
/* The array index is not a constant, so mark the entire array used. */
|
||||
assert(ir->array->type->is_array());
|
||||
if (ub_array->num_array_elements < ir->array->type->length) {
|
||||
ub_array->num_array_elements = ir->array->type->length;
|
||||
ub_array->array_elements = reralloc(mem_ctx,
|
||||
ub_array->array_elements,
|
||||
unsigned,
|
||||
ub_array->num_array_elements);
|
||||
|
||||
for (unsigned i = 0; i < ub_array->num_array_elements; i++) {
|
||||
ub_array->array_elements[i] = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return &ub_array->array;
|
||||
} else {
|
||||
return &block->array;
|
||||
}
|
||||
}
|
||||
|
||||
ir_visitor_status
|
||||
link_uniform_block_active_visitor::visit(ir_variable *var)
|
||||
{
|
||||
if (!var->is_in_buffer_block())
|
||||
return visit_continue;
|
||||
|
||||
/* Section 2.11.6 (Uniform Variables) of the OpenGL ES 3.0.3 spec says:
|
||||
*
|
||||
* "All members of a named uniform block declared with a shared or
|
||||
* std140 layout qualifier are considered active, even if they are not
|
||||
* referenced in any shader in the program. The uniform block itself is
|
||||
* also considered active, even if no member of the block is
|
||||
* referenced."
|
||||
*/
|
||||
if (var->get_interface_type_packing() == GLSL_INTERFACE_PACKING_PACKED)
|
||||
return visit_continue;
|
||||
|
||||
/* Process the block. Bail if there was an error. */
|
||||
link_uniform_block_active *const b =
|
||||
process_block(this->mem_ctx, this->ht, var);
|
||||
if (b == NULL) {
|
||||
linker_error(this->prog,
|
||||
"uniform block `%s' has mismatching definitions",
|
||||
glsl_get_type_name(var->get_interface_type()));
|
||||
this->success = false;
|
||||
return visit_stop;
|
||||
}
|
||||
|
||||
assert(b->array == NULL);
|
||||
assert(b->type != NULL);
|
||||
assert(!b->type->is_array() || b->has_instance_name);
|
||||
|
||||
/* For uniform block arrays declared with a shared or std140 layout
|
||||
* qualifier, mark all its instances as used.
|
||||
*/
|
||||
const glsl_type *type = b->type;
|
||||
struct uniform_block_array_elements **ub_array = &b->array;
|
||||
while (type->is_array()) {
|
||||
assert(b->type->length > 0);
|
||||
|
||||
*ub_array = rzalloc(this->mem_ctx, struct uniform_block_array_elements);
|
||||
(*ub_array)->num_array_elements = type->length;
|
||||
(*ub_array)->array_elements = reralloc(this->mem_ctx,
|
||||
(*ub_array)->array_elements,
|
||||
unsigned,
|
||||
(*ub_array)->num_array_elements);
|
||||
(*ub_array)->aoa_size = type->arrays_of_arrays_size();
|
||||
|
||||
for (unsigned i = 0; i < (*ub_array)->num_array_elements; i++) {
|
||||
(*ub_array)->array_elements[i] = i;
|
||||
}
|
||||
ub_array = &(*ub_array)->array;
|
||||
type = type->fields.array;
|
||||
}
|
||||
|
||||
return visit_continue;
|
||||
}
|
||||
|
||||
ir_visitor_status
|
||||
link_uniform_block_active_visitor::visit_enter(ir_dereference_array *ir)
|
||||
{
|
||||
/* cycle through arrays of arrays */
|
||||
ir_dereference_array *base_ir = ir;
|
||||
while (base_ir->array->ir_type == ir_type_dereference_array)
|
||||
base_ir = base_ir->array->as_dereference_array();
|
||||
|
||||
ir_dereference_variable *const d =
|
||||
base_ir->array->as_dereference_variable();
|
||||
ir_variable *const var = (d == NULL) ? NULL : d->var;
|
||||
|
||||
/* If the r-value being dereferenced is not a variable (e.g., a field of a
|
||||
* structure) or is not a uniform block instance, continue.
|
||||
*
|
||||
* WARNING: It is not enough for the variable to be part of uniform block.
|
||||
* It must represent the entire block. Arrays (or matrices) inside blocks
|
||||
* that lack an instance name are handled by the ir_dereference_variable
|
||||
* function.
|
||||
*/
|
||||
if (var == NULL
|
||||
|| !var->is_in_buffer_block()
|
||||
|| !var->is_interface_instance())
|
||||
return visit_continue;
|
||||
|
||||
/* Process the block. Bail if there was an error. */
|
||||
link_uniform_block_active *const b =
|
||||
process_block(this->mem_ctx, this->ht, var);
|
||||
if (b == NULL) {
|
||||
linker_error(prog,
|
||||
"uniform block `%s' has mismatching definitions",
|
||||
glsl_get_type_name(var->get_interface_type()));
|
||||
this->success = false;
|
||||
return visit_stop;
|
||||
}
|
||||
|
||||
/* Block arrays must be declared with an instance name.
|
||||
*/
|
||||
assert(b->has_instance_name);
|
||||
assert(b->type != NULL);
|
||||
|
||||
/* If the block array was declared with a shared or std140 layout
|
||||
* qualifier, all its instances have been already marked as used in
|
||||
* link_uniform_block_active_visitor::visit(ir_variable *).
|
||||
*/
|
||||
if (var->get_interface_type_packing() == GLSL_INTERFACE_PACKING_PACKED) {
|
||||
b->var = var;
|
||||
process_arrays(this->mem_ctx, ir, b);
|
||||
}
|
||||
|
||||
return visit_continue_with_parent;
|
||||
}
|
||||
|
||||
ir_visitor_status
|
||||
link_uniform_block_active_visitor::visit(ir_dereference_variable *ir)
|
||||
{
|
||||
ir_variable *var = ir->var;
|
||||
|
||||
if (!var->is_in_buffer_block())
|
||||
return visit_continue;
|
||||
|
||||
assert(!var->is_interface_instance() || !var->type->is_array());
|
||||
|
||||
/* Process the block. Bail if there was an error. */
|
||||
link_uniform_block_active *const b =
|
||||
process_block(this->mem_ctx, this->ht, var);
|
||||
if (b == NULL) {
|
||||
linker_error(this->prog,
|
||||
"uniform block `%s' has mismatching definitions",
|
||||
glsl_get_type_name(var->get_interface_type()));
|
||||
this->success = false;
|
||||
return visit_stop;
|
||||
}
|
||||
|
||||
assert(b->array == NULL);
|
||||
assert(b->type != NULL);
|
||||
|
||||
return visit_continue;
|
||||
}
|
@@ -1,82 +0,0 @@
|
||||
/*
|
||||
* Copyright © 2013 Intel Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef LINK_UNIFORM_BLOCK_ACTIVE_VISITOR_H
|
||||
#define LINK_UNIFORM_BLOCK_ACTIVE_VISITOR_H
|
||||
|
||||
#include "ir.h"
|
||||
#include "util/hash_table.h"
|
||||
|
||||
struct uniform_block_array_elements {
|
||||
unsigned *array_elements;
|
||||
unsigned num_array_elements;
|
||||
/**
|
||||
* Size of the array before array-trimming optimizations.
|
||||
*
|
||||
* Locations are only assigned to active array elements, but the location
|
||||
* values are calculated as if all elements are active. The total number
|
||||
* of elements in an array including the elements in arrays of arrays before
|
||||
* inactive elements are removed is needed to be perform that calculation.
|
||||
*/
|
||||
unsigned aoa_size;
|
||||
|
||||
ir_dereference_array *ir;
|
||||
|
||||
struct uniform_block_array_elements *array;
|
||||
};
|
||||
|
||||
struct link_uniform_block_active {
|
||||
const glsl_type *type;
|
||||
ir_variable *var;
|
||||
|
||||
struct uniform_block_array_elements *array;
|
||||
|
||||
unsigned binding;
|
||||
|
||||
bool has_instance_name;
|
||||
bool has_binding;
|
||||
bool is_shader_storage;
|
||||
};
|
||||
|
||||
class link_uniform_block_active_visitor : public ir_hierarchical_visitor {
|
||||
public:
|
||||
link_uniform_block_active_visitor(void *mem_ctx, struct hash_table *ht,
|
||||
struct gl_shader_program *prog)
|
||||
: success(true), prog(prog), ht(ht), mem_ctx(mem_ctx)
|
||||
{
|
||||
/* empty */
|
||||
}
|
||||
|
||||
virtual ir_visitor_status visit_enter(ir_dereference_array *);
|
||||
virtual ir_visitor_status visit(ir_dereference_variable *);
|
||||
virtual ir_visitor_status visit(ir_variable *);
|
||||
|
||||
bool success;
|
||||
|
||||
private:
|
||||
struct gl_shader_program *prog;
|
||||
struct hash_table *ht;
|
||||
void *mem_ctx;
|
||||
};
|
||||
|
||||
#endif /* LINK_UNIFORM_BLOCK_ACTIVE_VISITOR_H */
|
@@ -22,464 +22,7 @@
|
||||
*/
|
||||
|
||||
#include "ir.h"
|
||||
#include "linker.h"
|
||||
#include "ir_uniform.h"
|
||||
#include "link_uniform_block_active_visitor.h"
|
||||
#include "util/hash_table.h"
|
||||
#include "util/u_math.h"
|
||||
#include "program.h"
|
||||
#include "main/errors.h"
|
||||
#include "main/shader_types.h"
|
||||
#include "main/consts_exts.h"
|
||||
|
||||
namespace {
|
||||
|
||||
class ubo_visitor : public program_resource_visitor {
|
||||
public:
|
||||
ubo_visitor(void *mem_ctx, gl_uniform_buffer_variable *variables,
|
||||
unsigned num_variables, struct gl_shader_program *prog,
|
||||
bool use_std430_as_default)
|
||||
: index(0), offset(0), buffer_size(0), variables(variables),
|
||||
num_variables(num_variables), mem_ctx(mem_ctx),
|
||||
is_array_instance(false), prog(prog),
|
||||
use_std430_as_default(use_std430_as_default)
|
||||
{
|
||||
/* empty */
|
||||
}
|
||||
|
||||
void process(const glsl_type *type, const char *name)
|
||||
{
|
||||
this->offset = 0;
|
||||
this->buffer_size = 0;
|
||||
this->is_array_instance = strchr(name, ']') != NULL;
|
||||
this->program_resource_visitor::process(type, name,
|
||||
use_std430_as_default);
|
||||
}
|
||||
|
||||
unsigned index;
|
||||
unsigned offset;
|
||||
unsigned buffer_size;
|
||||
gl_uniform_buffer_variable *variables;
|
||||
unsigned num_variables;
|
||||
void *mem_ctx;
|
||||
bool is_array_instance;
|
||||
struct gl_shader_program *prog;
|
||||
|
||||
private:
|
||||
virtual void enter_record(const glsl_type *type, const char *,
|
||||
bool row_major,
|
||||
const enum glsl_interface_packing packing)
|
||||
{
|
||||
assert(type->is_struct());
|
||||
if (packing == GLSL_INTERFACE_PACKING_STD430)
|
||||
this->offset = align(
|
||||
this->offset, type->std430_base_alignment(row_major));
|
||||
else
|
||||
this->offset = align(
|
||||
this->offset, type->std140_base_alignment(row_major));
|
||||
}
|
||||
|
||||
virtual void leave_record(const glsl_type *type, const char *,
|
||||
bool row_major,
|
||||
const enum glsl_interface_packing packing)
|
||||
{
|
||||
assert(type->is_struct());
|
||||
|
||||
/* If this is the last field of a structure, apply rule #9. The
|
||||
* ARB_uniform_buffer_object spec says:
|
||||
*
|
||||
* The structure may have padding at the end; the base offset of the
|
||||
* member following the sub-structure is rounded up to the next
|
||||
* multiple of the base alignment of the structure.
|
||||
*/
|
||||
if (packing == GLSL_INTERFACE_PACKING_STD430)
|
||||
this->offset = align(
|
||||
this->offset, type->std430_base_alignment(row_major));
|
||||
else
|
||||
this->offset = align(
|
||||
this->offset, type->std140_base_alignment(row_major));
|
||||
}
|
||||
|
||||
virtual void set_buffer_offset(unsigned offset)
|
||||
{
|
||||
this->offset = offset;
|
||||
}
|
||||
|
||||
virtual void visit_field(const glsl_type *type, const char *name,
|
||||
bool row_major, const glsl_type *,
|
||||
const enum glsl_interface_packing packing,
|
||||
bool last_field)
|
||||
{
|
||||
assert(this->index < this->num_variables);
|
||||
|
||||
gl_uniform_buffer_variable *v = &this->variables[this->index++];
|
||||
|
||||
v->Name = ralloc_strdup(mem_ctx, name);
|
||||
v->Type = type;
|
||||
v->RowMajor = type->without_array()->is_matrix() && row_major;
|
||||
|
||||
if (this->is_array_instance) {
|
||||
v->IndexName = ralloc_strdup(mem_ctx, name);
|
||||
|
||||
char *open_bracket = strchr(v->IndexName, '[');
|
||||
assert(open_bracket != NULL);
|
||||
|
||||
char *close_bracket = strchr(open_bracket, '.') - 1;
|
||||
assert(close_bracket != NULL);
|
||||
|
||||
/* Length of the tail without the ']' but with the NUL.
|
||||
*/
|
||||
unsigned len = strlen(close_bracket + 1) + 1;
|
||||
|
||||
memmove(open_bracket, close_bracket + 1, len);
|
||||
} else {
|
||||
v->IndexName = v->Name;
|
||||
}
|
||||
|
||||
unsigned alignment = 0;
|
||||
unsigned size = 0;
|
||||
|
||||
/* The ARB_program_interface_query spec says:
|
||||
*
|
||||
* If the final member of an active shader storage block is array
|
||||
* with no declared size, the minimum buffer size is computed
|
||||
* assuming the array was declared as an array with one element.
|
||||
*
|
||||
* For that reason, we use the base type of the unsized array to
|
||||
* calculate its size. We don't need to check if the unsized array is
|
||||
* the last member of a shader storage block (that check was already
|
||||
* done by the parser).
|
||||
*/
|
||||
const glsl_type *type_for_size = type;
|
||||
if (type->is_unsized_array()) {
|
||||
if (!last_field) {
|
||||
linker_error(prog, "unsized array `%s' definition: "
|
||||
"only last member of a shader storage block "
|
||||
"can be defined as unsized array",
|
||||
name);
|
||||
}
|
||||
|
||||
type_for_size = type->without_array();
|
||||
}
|
||||
|
||||
if (packing == GLSL_INTERFACE_PACKING_STD430) {
|
||||
alignment = type->std430_base_alignment(v->RowMajor);
|
||||
size = type_for_size->std430_size(v->RowMajor);
|
||||
} else {
|
||||
alignment = type->std140_base_alignment(v->RowMajor);
|
||||
size = type_for_size->std140_size(v->RowMajor);
|
||||
}
|
||||
|
||||
this->offset = align(this->offset, alignment);
|
||||
v->Offset = this->offset;
|
||||
|
||||
this->offset += size;
|
||||
|
||||
/* The ARB_uniform_buffer_object spec says:
|
||||
*
|
||||
* For uniform blocks laid out according to [std140] rules, the
|
||||
* minimum buffer object size returned by the UNIFORM_BLOCK_DATA_SIZE
|
||||
* query is derived by taking the offset of the last basic machine
|
||||
* unit consumed by the last uniform of the uniform block (including
|
||||
* any end-of-array or end-of-structure padding), adding one, and
|
||||
* rounding up to the next multiple of the base alignment required
|
||||
* for a vec4.
|
||||
*/
|
||||
this->buffer_size = align(this->offset, 16);
|
||||
}
|
||||
|
||||
bool use_std430_as_default;
|
||||
};
|
||||
|
||||
class count_block_size : public program_resource_visitor {
|
||||
public:
|
||||
count_block_size() : num_active_uniforms(0)
|
||||
{
|
||||
/* empty */
|
||||
}
|
||||
|
||||
unsigned num_active_uniforms;
|
||||
|
||||
private:
|
||||
virtual void visit_field(const glsl_type * /* type */,
|
||||
const char * /* name */,
|
||||
bool /* row_major */,
|
||||
const glsl_type * /* record_type */,
|
||||
const enum glsl_interface_packing,
|
||||
bool /* last_field */)
|
||||
{
|
||||
this->num_active_uniforms++;
|
||||
}
|
||||
};
|
||||
|
||||
} /* anonymous namespace */
|
||||
|
||||
struct block {
|
||||
const glsl_type *type;
|
||||
bool has_instance_name;
|
||||
};
|
||||
|
||||
static void process_block_array_leaf(const char *name, gl_uniform_block *blocks,
|
||||
ubo_visitor *parcel,
|
||||
gl_uniform_buffer_variable *variables,
|
||||
const struct link_uniform_block_active *const b,
|
||||
unsigned *block_index,
|
||||
unsigned binding_offset,
|
||||
unsigned linearized_index,
|
||||
const struct gl_constants *consts,
|
||||
struct gl_shader_program *prog);
|
||||
|
||||
/**
|
||||
*
|
||||
* \param first_index Value of \c block_index for the first element of the
|
||||
* array.
|
||||
*/
|
||||
static void
|
||||
process_block_array(struct uniform_block_array_elements *ub_array, char **name,
|
||||
size_t name_length, gl_uniform_block *blocks,
|
||||
ubo_visitor *parcel, gl_uniform_buffer_variable *variables,
|
||||
const struct link_uniform_block_active *const b,
|
||||
unsigned *block_index, unsigned binding_offset,
|
||||
const struct gl_constants *consts,
|
||||
struct gl_shader_program *prog,
|
||||
unsigned first_index)
|
||||
{
|
||||
for (unsigned j = 0; j < ub_array->num_array_elements; j++) {
|
||||
size_t new_length = name_length;
|
||||
|
||||
unsigned int element_idx = ub_array->array_elements[j];
|
||||
/* Append the subscript to the current variable name */
|
||||
ralloc_asprintf_rewrite_tail(name, &new_length, "[%u]", element_idx);
|
||||
|
||||
if (ub_array->array) {
|
||||
unsigned binding_stride = binding_offset + (element_idx *
|
||||
ub_array->array->aoa_size);
|
||||
process_block_array(ub_array->array, name, new_length, blocks,
|
||||
parcel, variables, b, block_index,
|
||||
binding_stride, consts, prog, first_index);
|
||||
} else {
|
||||
process_block_array_leaf(*name, blocks,
|
||||
parcel, variables, b, block_index,
|
||||
binding_offset + element_idx,
|
||||
*block_index - first_index, consts, prog);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
process_block_array_leaf(const char *name,
|
||||
gl_uniform_block *blocks,
|
||||
ubo_visitor *parcel, gl_uniform_buffer_variable *variables,
|
||||
const struct link_uniform_block_active *const b,
|
||||
unsigned *block_index, unsigned binding_offset,
|
||||
unsigned linearized_index,
|
||||
const struct gl_constants *consts,
|
||||
struct gl_shader_program *prog)
|
||||
{
|
||||
unsigned i = *block_index;
|
||||
const glsl_type *type = b->type->without_array();
|
||||
|
||||
blocks[i].name.string = ralloc_strdup(blocks, name);
|
||||
resource_name_updated(&blocks[i].name);
|
||||
blocks[i].Uniforms = &variables[(*parcel).index];
|
||||
|
||||
/* The ARB_shading_language_420pack spec says:
|
||||
*
|
||||
* If the binding identifier is used with a uniform block instanced as
|
||||
* an array then the first element of the array takes the specified
|
||||
* block binding and each subsequent element takes the next consecutive
|
||||
* uniform block binding point.
|
||||
*/
|
||||
blocks[i].Binding = (b->has_binding) ? b->binding + binding_offset : 0;
|
||||
|
||||
blocks[i].UniformBufferSize = 0;
|
||||
blocks[i]._Packing = glsl_interface_packing(type->interface_packing);
|
||||
blocks[i]._RowMajor = type->get_interface_row_major();
|
||||
blocks[i].linearized_array_index = linearized_index;
|
||||
|
||||
parcel->process(type, b->has_instance_name ? blocks[i].name.string : "");
|
||||
|
||||
blocks[i].UniformBufferSize = parcel->buffer_size;
|
||||
|
||||
/* Check SSBO size is lower than maximum supported size for SSBO */
|
||||
if (b->is_shader_storage &&
|
||||
parcel->buffer_size > consts->MaxShaderStorageBlockSize) {
|
||||
linker_error(prog, "shader storage block `%s' has size %d, "
|
||||
"which is larger than the maximum allowed (%d)",
|
||||
glsl_get_type_name(b->type),
|
||||
parcel->buffer_size,
|
||||
consts->MaxShaderStorageBlockSize);
|
||||
}
|
||||
blocks[i].NumUniforms =
|
||||
(unsigned)(ptrdiff_t)(&variables[parcel->index] - blocks[i].Uniforms);
|
||||
|
||||
*block_index = *block_index + 1;
|
||||
}
|
||||
|
||||
/* This function resizes the array types of the block so that later we can use
|
||||
* this new size to correctly calculate the offest for indirect indexing.
|
||||
*/
|
||||
static const glsl_type *
|
||||
resize_block_array(const glsl_type *type,
|
||||
struct uniform_block_array_elements *ub_array)
|
||||
{
|
||||
if (type->is_array()) {
|
||||
struct uniform_block_array_elements *child_array =
|
||||
type->fields.array->is_array() ? ub_array->array : NULL;
|
||||
const glsl_type *new_child_type =
|
||||
resize_block_array(type->fields.array, child_array);
|
||||
|
||||
const glsl_type *new_type =
|
||||
glsl_type::get_array_instance(new_child_type,
|
||||
ub_array->num_array_elements);
|
||||
ub_array->ir->array->type = new_type;
|
||||
return new_type;
|
||||
} else {
|
||||
return type;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
create_buffer_blocks(void *mem_ctx, const struct gl_constants *consts,
|
||||
struct gl_shader_program *prog,
|
||||
struct gl_uniform_block **out_blks, unsigned num_blocks,
|
||||
struct hash_table *block_hash, unsigned num_variables,
|
||||
bool create_ubo_blocks)
|
||||
{
|
||||
if (num_blocks == 0) {
|
||||
assert(num_variables == 0);
|
||||
return;
|
||||
}
|
||||
|
||||
assert(num_variables != 0);
|
||||
|
||||
/* Allocate storage to hold all of the information related to uniform
|
||||
* blocks that can be queried through the API.
|
||||
*/
|
||||
struct gl_uniform_block *blocks =
|
||||
rzalloc_array(mem_ctx, gl_uniform_block, num_blocks);
|
||||
gl_uniform_buffer_variable *variables =
|
||||
ralloc_array(blocks, gl_uniform_buffer_variable, num_variables);
|
||||
|
||||
/* Add each variable from each uniform block to the API tracking
|
||||
* structures.
|
||||
*/
|
||||
ubo_visitor parcel(blocks, variables, num_variables, prog,
|
||||
consts->UseSTD430AsDefaultPacking);
|
||||
|
||||
unsigned i = 0;
|
||||
hash_table_foreach (block_hash, entry) {
|
||||
const struct link_uniform_block_active *const b =
|
||||
(const struct link_uniform_block_active *) entry->data;
|
||||
const glsl_type *block_type = b->type;
|
||||
|
||||
if ((create_ubo_blocks && !b->is_shader_storage) ||
|
||||
(!create_ubo_blocks && b->is_shader_storage)) {
|
||||
|
||||
if (b->array != NULL) {
|
||||
char *name = ralloc_strdup(NULL,
|
||||
glsl_get_type_name(block_type->without_array()));
|
||||
size_t name_length = strlen(name);
|
||||
|
||||
assert(b->has_instance_name);
|
||||
process_block_array(b->array, &name, name_length, blocks, &parcel,
|
||||
variables, b, &i, 0, consts, prog,
|
||||
i);
|
||||
ralloc_free(name);
|
||||
} else {
|
||||
process_block_array_leaf(glsl_get_type_name(block_type), blocks, &parcel,
|
||||
variables, b, &i, 0,
|
||||
0, consts, prog);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*out_blks = blocks;
|
||||
|
||||
assert(parcel.index == num_variables);
|
||||
}
|
||||
|
||||
void
|
||||
link_uniform_blocks(void *mem_ctx,
|
||||
const struct gl_constants *consts,
|
||||
struct gl_shader_program *prog,
|
||||
struct gl_linked_shader *shader,
|
||||
struct gl_uniform_block **ubo_blocks,
|
||||
unsigned *num_ubo_blocks,
|
||||
struct gl_uniform_block **ssbo_blocks,
|
||||
unsigned *num_ssbo_blocks)
|
||||
{
|
||||
/* This hash table will track all of the uniform blocks that have been
|
||||
* encountered. Since blocks with the same block-name must be the same,
|
||||
* the hash is organized by block-name.
|
||||
*/
|
||||
struct hash_table *block_hash =
|
||||
_mesa_hash_table_create(mem_ctx, _mesa_hash_string,
|
||||
_mesa_key_string_equal);
|
||||
|
||||
if (block_hash == NULL) {
|
||||
_mesa_error_no_memory(__func__);
|
||||
linker_error(prog, "out of memory\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Determine which uniform blocks are active. */
|
||||
link_uniform_block_active_visitor v(mem_ctx, block_hash, prog);
|
||||
visit_list_elements(&v, shader->ir);
|
||||
|
||||
/* Count the number of active uniform blocks. Count the total number of
|
||||
* active slots in those uniform blocks.
|
||||
*/
|
||||
unsigned num_ubo_variables = 0;
|
||||
unsigned num_ssbo_variables = 0;
|
||||
count_block_size block_size;
|
||||
|
||||
hash_table_foreach (block_hash, entry) {
|
||||
struct link_uniform_block_active *const b =
|
||||
(struct link_uniform_block_active *) entry->data;
|
||||
|
||||
assert((b->array != NULL) == b->type->is_array());
|
||||
|
||||
if (b->array != NULL &&
|
||||
(b->type->without_array()->interface_packing ==
|
||||
GLSL_INTERFACE_PACKING_PACKED)) {
|
||||
b->type = resize_block_array(b->type, b->array);
|
||||
b->var->type = b->type;
|
||||
b->var->data.max_array_access = b->type->length - 1;
|
||||
}
|
||||
|
||||
block_size.num_active_uniforms = 0;
|
||||
block_size.process(b->type->without_array(), "",
|
||||
consts->UseSTD430AsDefaultPacking);
|
||||
|
||||
if (b->array != NULL) {
|
||||
unsigned aoa_size = b->type->arrays_of_arrays_size();
|
||||
if (b->is_shader_storage) {
|
||||
*num_ssbo_blocks += aoa_size;
|
||||
num_ssbo_variables += aoa_size * block_size.num_active_uniforms;
|
||||
} else {
|
||||
*num_ubo_blocks += aoa_size;
|
||||
num_ubo_variables += aoa_size * block_size.num_active_uniforms;
|
||||
}
|
||||
} else {
|
||||
if (b->is_shader_storage) {
|
||||
(*num_ssbo_blocks)++;
|
||||
num_ssbo_variables += block_size.num_active_uniforms;
|
||||
} else {
|
||||
(*num_ubo_blocks)++;
|
||||
num_ubo_variables += block_size.num_active_uniforms;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
create_buffer_blocks(mem_ctx, consts, prog, ubo_blocks, *num_ubo_blocks,
|
||||
block_hash, num_ubo_variables, true);
|
||||
create_buffer_blocks(mem_ctx, consts, prog, ssbo_blocks, *num_ssbo_blocks,
|
||||
block_hash, num_ssbo_variables, false);
|
||||
|
||||
_mesa_hash_table_destroy(block_hash, NULL);
|
||||
}
|
||||
|
||||
static bool
|
||||
link_uniform_blocks_are_compatible(const gl_uniform_block *a,
|
||||
|
@@ -1,284 +0,0 @@
|
||||
/*
|
||||
* Copyright © 2011 Intel Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "ir.h"
|
||||
#include "linker.h"
|
||||
#include "ir_uniform.h"
|
||||
#include "glsl_symbol_table.h"
|
||||
#include "program.h"
|
||||
#include "string_to_uint_map.h"
|
||||
#include "ir_array_refcount.h"
|
||||
|
||||
#include "main/shader_types.h"
|
||||
#include "main/consts_exts.h"
|
||||
#include "util/strndup.h"
|
||||
#include "util/u_math.h"
|
||||
|
||||
/**
|
||||
* \file link_uniforms.cpp
|
||||
* Assign locations for GLSL uniforms.
|
||||
*
|
||||
* \author Ian Romanick <ian.d.romanick@intel.com>
|
||||
*/
|
||||
|
||||
void
|
||||
program_resource_visitor::process(const glsl_type *type, const char *name,
|
||||
bool use_std430_as_default)
|
||||
{
|
||||
assert(type->without_array()->is_struct()
|
||||
|| type->without_array()->is_interface());
|
||||
|
||||
unsigned record_array_count = 1;
|
||||
char *name_copy = ralloc_strdup(NULL, name);
|
||||
|
||||
enum glsl_interface_packing packing =
|
||||
type->get_internal_ifc_packing(use_std430_as_default);
|
||||
|
||||
recursion(type, &name_copy, strlen(name), false, NULL, packing, false,
|
||||
record_array_count, NULL);
|
||||
ralloc_free(name_copy);
|
||||
}
|
||||
|
||||
void
|
||||
program_resource_visitor::process(ir_variable *var, bool use_std430_as_default)
|
||||
{
|
||||
const glsl_type *t =
|
||||
var->data.from_named_ifc_block ? var->get_interface_type() : var->type;
|
||||
process(var, t, use_std430_as_default);
|
||||
}
|
||||
|
||||
void
|
||||
program_resource_visitor::process(ir_variable *var, const glsl_type *var_type,
|
||||
bool use_std430_as_default)
|
||||
{
|
||||
unsigned record_array_count = 1;
|
||||
const bool row_major =
|
||||
var->data.matrix_layout == GLSL_MATRIX_LAYOUT_ROW_MAJOR;
|
||||
|
||||
enum glsl_interface_packing packing = var->get_interface_type() ?
|
||||
var->get_interface_type()->
|
||||
get_internal_ifc_packing(use_std430_as_default) :
|
||||
var->type->get_internal_ifc_packing(use_std430_as_default);
|
||||
|
||||
const glsl_type *t = var_type;
|
||||
const glsl_type *t_without_array = t->without_array();
|
||||
|
||||
/* false is always passed for the row_major parameter to the other
|
||||
* processing functions because no information is available to do
|
||||
* otherwise. See the warning in linker.h.
|
||||
*/
|
||||
if (t_without_array->is_struct() ||
|
||||
(t->is_array() && t->fields.array->is_array())) {
|
||||
char *name = ralloc_strdup(NULL, var->name);
|
||||
recursion(var->type, &name, strlen(name), row_major, NULL, packing,
|
||||
false, record_array_count, NULL);
|
||||
ralloc_free(name);
|
||||
} else if (t_without_array->is_interface()) {
|
||||
char *name = ralloc_strdup(NULL, glsl_get_type_name(t_without_array));
|
||||
const glsl_struct_field *ifc_member = var->data.from_named_ifc_block ?
|
||||
&t_without_array->
|
||||
fields.structure[t_without_array->field_index(var->name)] : NULL;
|
||||
|
||||
recursion(t, &name, strlen(name), row_major, NULL, packing,
|
||||
false, record_array_count, ifc_member);
|
||||
ralloc_free(name);
|
||||
} else {
|
||||
this->set_record_array_count(record_array_count);
|
||||
this->visit_field(t, var->name, row_major, NULL, packing, false);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
program_resource_visitor::recursion(const glsl_type *t, char **name,
|
||||
size_t name_length, bool row_major,
|
||||
const glsl_type *record_type,
|
||||
const enum glsl_interface_packing packing,
|
||||
bool last_field,
|
||||
unsigned record_array_count,
|
||||
const glsl_struct_field *named_ifc_member)
|
||||
{
|
||||
/* Records need to have each field processed individually.
|
||||
*
|
||||
* Arrays of records need to have each array element processed
|
||||
* individually, then each field of the resulting array elements processed
|
||||
* individually.
|
||||
*/
|
||||
if (t->is_interface() && named_ifc_member) {
|
||||
ralloc_asprintf_rewrite_tail(name, &name_length, ".%s",
|
||||
named_ifc_member->name);
|
||||
recursion(named_ifc_member->type, name, name_length, row_major, NULL,
|
||||
packing, false, record_array_count, NULL);
|
||||
} else if (t->is_struct() || t->is_interface()) {
|
||||
if (record_type == NULL && t->is_struct())
|
||||
record_type = t;
|
||||
|
||||
if (t->is_struct())
|
||||
this->enter_record(t, *name, row_major, packing);
|
||||
|
||||
for (unsigned i = 0; i < t->length; i++) {
|
||||
const char *field = t->fields.structure[i].name;
|
||||
size_t new_length = name_length;
|
||||
|
||||
if (t->is_interface() && t->fields.structure[i].offset != -1)
|
||||
this->set_buffer_offset(t->fields.structure[i].offset);
|
||||
|
||||
/* Append '.field' to the current variable name. */
|
||||
if (name_length == 0) {
|
||||
ralloc_asprintf_rewrite_tail(name, &new_length, "%s", field);
|
||||
} else {
|
||||
ralloc_asprintf_rewrite_tail(name, &new_length, ".%s", field);
|
||||
}
|
||||
|
||||
/* The layout of structures at the top level of the block is set
|
||||
* during parsing. For matrices contained in multiple levels of
|
||||
* structures in the block, the inner structures have no layout.
|
||||
* These cases must potentially inherit the layout from the outer
|
||||
* levels.
|
||||
*/
|
||||
bool field_row_major = row_major;
|
||||
const enum glsl_matrix_layout matrix_layout =
|
||||
glsl_matrix_layout(t->fields.structure[i].matrix_layout);
|
||||
if (matrix_layout == GLSL_MATRIX_LAYOUT_ROW_MAJOR) {
|
||||
field_row_major = true;
|
||||
} else if (matrix_layout == GLSL_MATRIX_LAYOUT_COLUMN_MAJOR) {
|
||||
field_row_major = false;
|
||||
}
|
||||
|
||||
recursion(t->fields.structure[i].type, name, new_length,
|
||||
field_row_major,
|
||||
record_type,
|
||||
packing,
|
||||
(i + 1) == t->length, record_array_count, NULL);
|
||||
|
||||
/* Only the first leaf-field of the record gets called with the
|
||||
* record type pointer.
|
||||
*/
|
||||
record_type = NULL;
|
||||
}
|
||||
|
||||
if (t->is_struct()) {
|
||||
(*name)[name_length] = '\0';
|
||||
this->leave_record(t, *name, row_major, packing);
|
||||
}
|
||||
} else if (t->without_array()->is_struct() ||
|
||||
t->without_array()->is_interface() ||
|
||||
(t->is_array() && t->fields.array->is_array())) {
|
||||
if (record_type == NULL && t->fields.array->is_struct())
|
||||
record_type = t->fields.array;
|
||||
|
||||
unsigned length = t->length;
|
||||
|
||||
/* Shader storage block unsized arrays: add subscript [0] to variable
|
||||
* names.
|
||||
*/
|
||||
if (t->is_unsized_array())
|
||||
length = 1;
|
||||
|
||||
record_array_count *= length;
|
||||
|
||||
for (unsigned i = 0; i < length; i++) {
|
||||
size_t new_length = name_length;
|
||||
|
||||
/* Append the subscript to the current variable name */
|
||||
ralloc_asprintf_rewrite_tail(name, &new_length, "[%u]", i);
|
||||
|
||||
recursion(t->fields.array, name, new_length, row_major,
|
||||
record_type,
|
||||
packing,
|
||||
(i + 1) == t->length, record_array_count,
|
||||
named_ifc_member);
|
||||
|
||||
/* Only the first leaf-field of the record gets called with the
|
||||
* record type pointer.
|
||||
*/
|
||||
record_type = NULL;
|
||||
}
|
||||
} else {
|
||||
this->set_record_array_count(record_array_count);
|
||||
this->visit_field(t, *name, row_major, record_type, packing, last_field);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
program_resource_visitor::enter_record(const glsl_type *, const char *, bool,
|
||||
const enum glsl_interface_packing)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
program_resource_visitor::leave_record(const glsl_type *, const char *, bool,
|
||||
const enum glsl_interface_packing)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
program_resource_visitor::set_buffer_offset(unsigned)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
program_resource_visitor::set_record_array_count(unsigned)
|
||||
{
|
||||
}
|
||||
|
||||
unsigned
|
||||
link_calculate_matrix_stride(const glsl_type *matrix, bool row_major,
|
||||
enum glsl_interface_packing packing)
|
||||
{
|
||||
const unsigned N = matrix->is_double() ? 8 : 4;
|
||||
const unsigned items =
|
||||
row_major ? matrix->matrix_columns : matrix->vector_elements;
|
||||
|
||||
assert(items <= 4);
|
||||
|
||||
/* Matrix stride for std430 mat2xY matrices are not rounded up to
|
||||
* vec4 size.
|
||||
*
|
||||
* Section 7.6.2.2 "Standard Uniform Block Layout" of the OpenGL 4.3 spec
|
||||
* says:
|
||||
*
|
||||
* 2. If the member is a two- or four-component vector with components
|
||||
* consuming N basic machine units, the base alignment is 2N or 4N,
|
||||
* respectively.
|
||||
* ...
|
||||
* 4. If the member is an array of scalars or vectors, the base
|
||||
* alignment and array stride are set to match the base alignment of
|
||||
* a single array element, according to rules (1), (2), and (3), and
|
||||
* rounded up to the base alignment of a vec4.
|
||||
* ...
|
||||
* 7. If the member is a row-major matrix with C columns and R rows, the
|
||||
* matrix is stored identically to an array of R row vectors with C
|
||||
* components each, according to rule (4).
|
||||
* ...
|
||||
*
|
||||
* When using the std430 storage layout, shader storage blocks will be
|
||||
* laid out in buffer storage identically to uniform and shader storage
|
||||
* blocks using the std140 layout, except that the base alignment and
|
||||
* stride of arrays of scalars and vectors in rule 4 and of structures
|
||||
* in rule 9 are not rounded up a multiple of the base alignment of a
|
||||
* vec4.
|
||||
*/
|
||||
return packing == GLSL_INTERFACE_PACKING_STD430
|
||||
? (items < 3 ? items * N : align(items * N, 16))
|
||||
: align(items * N, 16);
|
||||
}
|
@@ -41,16 +41,6 @@ link_cross_validate_uniform_block(void *mem_ctx,
|
||||
unsigned int *num_linked_blocks,
|
||||
struct gl_uniform_block *new_block);
|
||||
|
||||
extern void
|
||||
link_uniform_blocks(void *mem_ctx,
|
||||
const struct gl_constants *consts,
|
||||
struct gl_shader_program *prog,
|
||||
struct gl_linked_shader *shader,
|
||||
struct gl_uniform_block **ubo_blocks,
|
||||
unsigned *num_ubo_blocks,
|
||||
struct gl_uniform_block **ssbo_blocks,
|
||||
unsigned *num_ssbo_blocks);
|
||||
|
||||
bool
|
||||
validate_intrastage_arrays(struct gl_shader_program *prog,
|
||||
ir_variable *const var,
|
||||
@@ -79,120 +69,4 @@ link_intrastage_shaders(void *mem_ctx,
|
||||
unsigned num_shaders,
|
||||
bool allow_missing_main);
|
||||
|
||||
extern unsigned
|
||||
link_calculate_matrix_stride(const glsl_type *matrix, bool row_major,
|
||||
enum glsl_interface_packing packing);
|
||||
|
||||
/**
|
||||
* Class for processing all of the leaf fields of a variable that corresponds
|
||||
* to a program resource.
|
||||
*
|
||||
* The leaf fields are all the parts of the variable that the application
|
||||
* could query using \c glGetProgramResourceIndex (or that could be returned
|
||||
* by \c glGetProgramResourceName).
|
||||
*
|
||||
* Classes my derive from this class to implement specific functionality.
|
||||
* This class only provides the mechanism to iterate over the leaves. Derived
|
||||
* classes must implement \c ::visit_field and may override \c ::process.
|
||||
*/
|
||||
class program_resource_visitor {
|
||||
public:
|
||||
/**
|
||||
* Begin processing a variable
|
||||
*
|
||||
* Classes that overload this function should call \c ::process from the
|
||||
* base class to start the recursive processing of the variable.
|
||||
*
|
||||
* \param var The variable that is to be processed
|
||||
*
|
||||
* Calls \c ::visit_field for each leaf of the variable.
|
||||
*
|
||||
* \warning
|
||||
* When processing a uniform block, this entry should only be used in cases
|
||||
* where the row / column ordering of matrices in the block does not
|
||||
* matter. For example, enumerating the names of members of the block, but
|
||||
* not for determining the offsets of members.
|
||||
*/
|
||||
void process(ir_variable *var, bool use_std430_as_default);
|
||||
|
||||
/**
|
||||
* Begin processing a variable
|
||||
*
|
||||
* Classes that overload this function should call \c ::process from the
|
||||
* base class to start the recursive processing of the variable.
|
||||
*
|
||||
* \param var The variable that is to be processed
|
||||
* \param var_type The glsl_type reference of the variable
|
||||
*
|
||||
* Calls \c ::visit_field for each leaf of the variable.
|
||||
*
|
||||
* \warning
|
||||
* When processing a uniform block, this entry should only be used in cases
|
||||
* where the row / column ordering of matrices in the block does not
|
||||
* matter. For example, enumerating the names of members of the block, but
|
||||
* not for determining the offsets of members.
|
||||
*/
|
||||
void process(ir_variable *var, const glsl_type *var_type,
|
||||
bool use_std430_as_default);
|
||||
|
||||
/**
|
||||
* Begin processing a variable of a structured type.
|
||||
*
|
||||
* This flavor of \c process should be used to handle structured types
|
||||
* (i.e., structures, interfaces, or arrays there of) that need special
|
||||
* name handling. A common usage is to handle cases where the block name
|
||||
* (instead of the instance name) is used for an interface block.
|
||||
*
|
||||
* \param type Type that is to be processed, associated with \c name
|
||||
* \param name Base name of the structured variable being processed
|
||||
*
|
||||
* \note
|
||||
* \c type must be \c GLSL_TYPE_RECORD, \c GLSL_TYPE_INTERFACE, or an array
|
||||
* there of.
|
||||
*/
|
||||
void process(const glsl_type *type, const char *name,
|
||||
bool use_std430_as_default);
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Method invoked for each leaf of the variable
|
||||
*
|
||||
* \param type Type of the field.
|
||||
* \param name Fully qualified name of the field.
|
||||
* \param row_major For a matrix type, is it stored row-major.
|
||||
* \param record_type Type of the record containing the field.
|
||||
* \param last_field Set if \c name is the last field of the structure
|
||||
* containing it. This will always be false for items
|
||||
* not contained in a structure or interface block.
|
||||
*/
|
||||
virtual void visit_field(const glsl_type *type, const char *name,
|
||||
bool row_major, const glsl_type *record_type,
|
||||
const enum glsl_interface_packing packing,
|
||||
bool last_field) = 0;
|
||||
|
||||
virtual void enter_record(const glsl_type *type, const char *name,
|
||||
bool row_major, const enum glsl_interface_packing packing);
|
||||
|
||||
virtual void leave_record(const glsl_type *type, const char *name,
|
||||
bool row_major, const enum glsl_interface_packing packing);
|
||||
|
||||
virtual void set_buffer_offset(unsigned offset);
|
||||
|
||||
virtual void set_record_array_count(unsigned record_array_count);
|
||||
|
||||
private:
|
||||
/**
|
||||
* \param name_length Length of the current name \b not including the
|
||||
* terminating \c NUL character.
|
||||
* \param last_field Set if \c name is the last field of the structure
|
||||
* containing it. This will always be false for items
|
||||
* not contained in a structure or interface block.
|
||||
*/
|
||||
void recursion(const glsl_type *t, char **name, size_t name_length,
|
||||
bool row_major, const glsl_type *record_type,
|
||||
const enum glsl_interface_packing packing,
|
||||
bool last_field, unsigned record_array_count,
|
||||
const glsl_struct_field *named_ifc_member);
|
||||
};
|
||||
|
||||
#endif /* GLSL_LINKER_H */
|
||||
|
@@ -190,9 +190,6 @@ files_libglsl = files(
|
||||
'linker_util.cpp',
|
||||
'link_functions.cpp',
|
||||
'link_interface_blocks.cpp',
|
||||
'link_uniforms.cpp',
|
||||
'link_uniform_block_active_visitor.cpp',
|
||||
'link_uniform_block_active_visitor.h',
|
||||
'link_uniform_blocks.cpp',
|
||||
'list.h',
|
||||
'lower_builtins.cpp',
|
||||
|
Reference in New Issue
Block a user