mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-04-28 17:20:37 +02:00
glsl: make use of u_range_remap for uniform remapping
This will allow ubo buffers to have arrays containing millions of elements without excessive memory use on a remap table. Before this change using the max sized array on radeonsi would result in 1.3GB of memory being used for a remap table in a single shader. There is also a small functional change here, previously if the shader used more than GL_MAX_UNIFORM_BLOCK_SIZE mesa would ignore and allow this as the original ARB_uniform_buffer_object spec stated: "If the amount of storage required for a uniform block exceeds this limit, a program may fail to link." However in OpenGL 4.3 the text was clarified and the "may" was removed so with this change we enforce the max limit. Closes: https://gitlab.freedesktop.org/mesa/mesa/-/issues/9953 Acked-by: Marek Olšák <marek.olsak@amd.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/36997>
This commit is contained in:
parent
bf946bccf2
commit
e052254066
9 changed files with 263 additions and 132 deletions
|
|
@ -27,6 +27,7 @@
|
||||||
#include "linker_util.h"
|
#include "linker_util.h"
|
||||||
#include "util/u_dynarray.h"
|
#include "util/u_dynarray.h"
|
||||||
#include "util/u_math.h"
|
#include "util/u_math.h"
|
||||||
|
#include "util/u_range_remap.h"
|
||||||
#include "main/consts_exts.h"
|
#include "main/consts_exts.h"
|
||||||
#include "main/shader_types.h"
|
#include "main/shader_types.h"
|
||||||
|
|
||||||
|
|
@ -280,17 +281,12 @@ setup_uniform_remap_tables(const struct gl_constants *consts,
|
||||||
* that we can keep track of unused uniforms with explicit locations.
|
* that we can keep track of unused uniforms with explicit locations.
|
||||||
*/
|
*/
|
||||||
assert(!prog->data->spirv ||
|
assert(!prog->data->spirv ||
|
||||||
(prog->data->spirv && !prog->UniformRemapTable));
|
(prog->data->spirv && list_is_empty(prog->UniformRemapTable)));
|
||||||
if (!prog->UniformRemapTable) {
|
|
||||||
prog->UniformRemapTable = rzalloc_array(prog,
|
|
||||||
struct gl_uniform_storage *,
|
|
||||||
prog->NumUniformRemapTable);
|
|
||||||
}
|
|
||||||
|
|
||||||
union gl_constant_value *data =
|
union gl_constant_value *data =
|
||||||
rzalloc_array(prog->data,
|
rzalloc_array(prog->data,
|
||||||
union gl_constant_value, prog->data->NumUniformDataSlots);
|
union gl_constant_value, prog->data->NumUniformDataSlots);
|
||||||
if (!prog->UniformRemapTable || !data) {
|
if (!data) {
|
||||||
linker_error(prog, "Out of memory during linking.\n");
|
linker_error(prog, "Out of memory during linking.\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -321,19 +317,17 @@ setup_uniform_remap_tables(const struct gl_constants *consts,
|
||||||
unsigned num_slots = glsl_get_component_slots(uniform->type);
|
unsigned num_slots = glsl_get_component_slots(uniform->type);
|
||||||
|
|
||||||
uniform->storage = &data[data_pos];
|
uniform->storage = &data[data_pos];
|
||||||
|
data_pos += num_slots * entries;
|
||||||
|
|
||||||
/* Set remap table entries point to correct gl_uniform_storage. */
|
/* Set remap table entry to the correct gl_uniform_storage. */
|
||||||
for (unsigned j = 0; j < entries; j++) {
|
util_range_insert_remap(uniform->remap_location,
|
||||||
unsigned element_loc = uniform->remap_location + j;
|
uniform->remap_location + entries - 1,
|
||||||
prog->UniformRemapTable[element_loc] = uniform;
|
prog->UniformRemapTable, uniform);
|
||||||
|
|
||||||
data_pos += num_slots;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Reserve locations for rest of the uniforms. */
|
/* Reserve locations for rest of the uniforms. */
|
||||||
if (prog->data->spirv)
|
if (prog->data->spirv)
|
||||||
link_util_update_empty_uniform_locations(prog);
|
link_util_update_empty_uniform_locations(consts, prog);
|
||||||
|
|
||||||
for (unsigned i = 0; i < prog->data->NumUniformStorage; i++) {
|
for (unsigned i = 0; i < prog->data->NumUniformStorage; i++) {
|
||||||
struct gl_uniform_storage *uniform = &prog->data->UniformStorage[i];
|
struct gl_uniform_storage *uniform = &prog->data->UniformStorage[i];
|
||||||
|
|
@ -365,35 +359,24 @@ setup_uniform_remap_tables(const struct gl_constants *consts,
|
||||||
|
|
||||||
unsigned location =
|
unsigned location =
|
||||||
link_util_find_empty_block(prog, &prog->data->UniformStorage[i]);
|
link_util_find_empty_block(prog, &prog->data->UniformStorage[i]);
|
||||||
|
|
||||||
if (location == -1) {
|
if (location == -1) {
|
||||||
location = prog->NumUniformRemapTable;
|
linker_error(prog, "Unable to find empty block for %u entries",
|
||||||
|
MAX2(1, prog->data->UniformStorage[i].array_elements));
|
||||||
|
}
|
||||||
|
|
||||||
/* resize remap table to fit new entries */
|
unsigned num_slots = glsl_get_component_slots(uniform->type);
|
||||||
prog->UniformRemapTable =
|
if (uniform->block_index == -1) {
|
||||||
reralloc(prog,
|
uniform->storage = &data[data_pos];
|
||||||
prog->UniformRemapTable,
|
data_pos += num_slots * entries;
|
||||||
struct gl_uniform_storage *,
|
|
||||||
prog->NumUniformRemapTable + entries);
|
|
||||||
prog->NumUniformRemapTable += entries;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* set the base location in remap table for the uniform */
|
/* set the base location in remap table for the uniform */
|
||||||
uniform->remap_location = location;
|
uniform->remap_location = location;
|
||||||
|
|
||||||
unsigned num_slots = glsl_get_component_slots(uniform->type);
|
/* Set remap table entry to the correct gl_uniform_storage. */
|
||||||
|
util_range_insert_remap(uniform->remap_location,
|
||||||
if (uniform->block_index == -1)
|
uniform->remap_location + entries - 1,
|
||||||
uniform->storage = &data[data_pos];
|
prog->UniformRemapTable, uniform);
|
||||||
|
|
||||||
/* Set remap table entries point to correct gl_uniform_storage. */
|
|
||||||
for (unsigned j = 0; j < entries; j++) {
|
|
||||||
unsigned element_loc = uniform->remap_location + j;
|
|
||||||
prog->UniformRemapTable[element_loc] = uniform;
|
|
||||||
|
|
||||||
if (uniform->block_index == -1)
|
|
||||||
data_pos += num_slots;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Verify that total amount of entries for explicit and implicit locations
|
/* Verify that total amount of entries for explicit and implicit locations
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,7 @@
|
||||||
#include "main/context.h"
|
#include "main/context.h"
|
||||||
#include "main/shaderobj.h"
|
#include "main/shaderobj.h"
|
||||||
#include "util/glheader.h"
|
#include "util/glheader.h"
|
||||||
|
#include "util/u_range_remap.h"
|
||||||
#include "util/perf/cpu_trace.h"
|
#include "util/perf/cpu_trace.h"
|
||||||
#include "pipe/p_screen.h"
|
#include "pipe/p_screen.h"
|
||||||
|
|
||||||
|
|
@ -2769,48 +2770,68 @@ link_intrastage_shaders(void *mem_ctx,
|
||||||
* Initializes explicit location slots to INACTIVE_UNIFORM_EXPLICIT_LOCATION
|
* Initializes explicit location slots to INACTIVE_UNIFORM_EXPLICIT_LOCATION
|
||||||
* for a variable, checks for overlaps between other uniforms using explicit
|
* for a variable, checks for overlaps between other uniforms using explicit
|
||||||
* locations.
|
* locations.
|
||||||
|
* If return_zero bool is true zero will be returned if the uniform was
|
||||||
|
* already processed for a different stage.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
reserve_explicit_locations(struct gl_shader_program *prog,
|
reserve_explicit_locations(struct gl_shader_program *prog,
|
||||||
struct string_to_uint_map *map, nir_variable *var)
|
struct string_to_uint_map *map,
|
||||||
|
const struct glsl_type *type,
|
||||||
|
int location, char **var_name,
|
||||||
|
size_t name_length, bool return_zero)
|
||||||
{
|
{
|
||||||
unsigned slots = glsl_type_uniform_locations(var->type);
|
if (glsl_type_is_struct_or_ifc(type) ||
|
||||||
unsigned max_loc = var->data.location + slots - 1;
|
(glsl_type_is_array(type) &&
|
||||||
unsigned return_value = slots;
|
(glsl_type_is_array(glsl_get_array_element(type)) ||
|
||||||
|
glsl_type_is_struct_or_ifc(glsl_get_array_element(type))))) {
|
||||||
|
|
||||||
/* Resize remap table if locations do not fit in the current one. */
|
unsigned length = glsl_get_length(type);
|
||||||
if (max_loc + 1 > prog->NumUniformRemapTable) {
|
if (glsl_type_is_unsized_array(type))
|
||||||
prog->UniformRemapTable =
|
length = 1;
|
||||||
reralloc(prog, prog->UniformRemapTable,
|
|
||||||
struct gl_uniform_storage *,
|
|
||||||
max_loc + 1);
|
|
||||||
|
|
||||||
if (!prog->UniformRemapTable) {
|
int location_count = 0;
|
||||||
linker_error(prog, "Out of memory during linking.\n");
|
for (unsigned i = 0; i < length; i++) {
|
||||||
return -1;
|
const struct glsl_type *field_type;
|
||||||
}
|
size_t new_length = name_length;
|
||||||
|
|
||||||
/* Initialize allocated space. */
|
if (glsl_type_is_struct_or_ifc(type)) {
|
||||||
for (unsigned i = prog->NumUniformRemapTable; i < max_loc + 1; i++)
|
field_type = glsl_get_struct_field(type, i);
|
||||||
prog->UniformRemapTable[i] = NULL;
|
|
||||||
|
|
||||||
prog->NumUniformRemapTable = max_loc + 1;
|
/* Append '.field' to the current variable name. */
|
||||||
}
|
if (var_name) {
|
||||||
|
ralloc_asprintf_rewrite_tail(var_name, &new_length, ".%s",
|
||||||
|
glsl_get_struct_elem_name(type, i));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
field_type = glsl_get_array_element(type);
|
||||||
|
|
||||||
for (unsigned i = 0; i < slots; i++) {
|
/* Append the subscript to the current variable name */
|
||||||
unsigned loc = var->data.location + i;
|
if (var_name)
|
||||||
|
ralloc_asprintf_rewrite_tail(var_name, &new_length, "[%u]", i);
|
||||||
/* Check if location is already used. */
|
|
||||||
if (prog->UniformRemapTable[loc] == INACTIVE_UNIFORM_EXPLICIT_LOCATION) {
|
|
||||||
|
|
||||||
/* Possibly same uniform from a different stage, this is ok. */
|
|
||||||
unsigned hash_loc;
|
|
||||||
if (string_to_uint_map_get(map, &hash_loc, var->name) &&
|
|
||||||
hash_loc == loc - i) {
|
|
||||||
return_value = 0;
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int entries = reserve_explicit_locations(prog, map, field_type,
|
||||||
|
location + location_count,
|
||||||
|
var_name, new_length, false);
|
||||||
|
if (entries == -1)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
location_count += entries;
|
||||||
|
}
|
||||||
|
|
||||||
|
return location_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned slots = glsl_type_uniform_locations(type);
|
||||||
|
unsigned max_loc = location + slots - 1;
|
||||||
|
unsigned return_value = slots;
|
||||||
|
|
||||||
|
struct range_entry *re =
|
||||||
|
util_range_remap(location, prog->UniformRemapTable);
|
||||||
|
if (!re) {
|
||||||
|
re = util_range_insert_remap(location, max_loc,
|
||||||
|
prog->UniformRemapTable, NULL);
|
||||||
|
if (!re) {
|
||||||
/* ARB_explicit_uniform_location specification states:
|
/* ARB_explicit_uniform_location specification states:
|
||||||
*
|
*
|
||||||
* "No two default-block uniform variables in the program can have
|
* "No two default-block uniform variables in the program can have
|
||||||
|
|
@ -2820,18 +2841,42 @@ reserve_explicit_locations(struct gl_shader_program *prog,
|
||||||
linker_error(prog,
|
linker_error(prog,
|
||||||
"location qualifier for uniform %s overlaps "
|
"location qualifier for uniform %s overlaps "
|
||||||
"previously used location\n",
|
"previously used location\n",
|
||||||
var->name);
|
*var_name);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Initialize location as inactive before optimization
|
prog->NumUniformRemapTable += slots;
|
||||||
* rounds and location assignment.
|
|
||||||
*/
|
|
||||||
prog->UniformRemapTable[loc] = INACTIVE_UNIFORM_EXPLICIT_LOCATION;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Check if location is already used. */
|
||||||
|
if (re->ptr == INACTIVE_UNIFORM_EXPLICIT_LOCATION) {
|
||||||
|
/* Possibly same uniform from a different stage, this is ok. */
|
||||||
|
unsigned hash_loc;
|
||||||
|
if (string_to_uint_map_get(map, &hash_loc, *var_name) &&
|
||||||
|
hash_loc == location) {
|
||||||
|
return return_zero ? 0 : return_value;
|
||||||
|
} else {
|
||||||
|
/* ARB_explicit_uniform_location specification states:
|
||||||
|
*
|
||||||
|
* "No two default-block uniform variables in the program can have
|
||||||
|
* the same location, even if they are unused, otherwise a compiler
|
||||||
|
* or linker error will be generated."
|
||||||
|
*/
|
||||||
|
linker_error(prog,
|
||||||
|
"location qualifier for uniform %s overlaps "
|
||||||
|
"previously used location\n",
|
||||||
|
*var_name);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Initialize location as inactive before optimization
|
||||||
|
* rounds and location assignment.
|
||||||
|
*/
|
||||||
|
re->ptr = INACTIVE_UNIFORM_EXPLICIT_LOCATION;
|
||||||
|
|
||||||
/* Note, base location used for arrays. */
|
/* Note, base location used for arrays. */
|
||||||
string_to_uint_map_put(map, var->data.location, var->name);
|
string_to_uint_map_put(map, location, *var_name);
|
||||||
|
|
||||||
return return_value;
|
return return_value;
|
||||||
}
|
}
|
||||||
|
|
@ -2895,13 +2940,16 @@ reserve_subroutine_explicit_locations(struct gl_shader_program *prog,
|
||||||
* inactive array elements that may get trimmed away.
|
* inactive array elements that may get trimmed away.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
check_explicit_uniform_locations(const struct gl_extensions *exts,
|
check_explicit_uniform_locations(const struct gl_constants *consts,
|
||||||
|
const struct gl_extensions *exts,
|
||||||
struct gl_shader_program *prog)
|
struct gl_shader_program *prog)
|
||||||
{
|
{
|
||||||
prog->NumExplicitUniformLocations = 0;
|
prog->NumExplicitUniformLocations = 0;
|
||||||
|
|
||||||
if (!exts->ARB_explicit_uniform_location)
|
if (!exts->ARB_explicit_uniform_location) {
|
||||||
|
link_util_update_empty_uniform_locations(consts, prog);
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* This map is used to detect if overlapping explicit locations
|
/* This map is used to detect if overlapping explicit locations
|
||||||
* occur with the same uniform (from different stage) or a different one.
|
* occur with the same uniform (from different stage) or a different one.
|
||||||
|
|
@ -2926,8 +2974,14 @@ check_explicit_uniform_locations(const struct gl_extensions *exts,
|
||||||
if (glsl_type_is_subroutine(glsl_without_array(var->type)))
|
if (glsl_type_is_subroutine(glsl_without_array(var->type)))
|
||||||
ret = reserve_subroutine_explicit_locations(prog, p, var);
|
ret = reserve_subroutine_explicit_locations(prog, p, var);
|
||||||
else {
|
else {
|
||||||
|
char *name_tmp = ralloc_strdup(NULL, var->name);
|
||||||
int slots = reserve_explicit_locations(prog, uniform_map,
|
int slots = reserve_explicit_locations(prog, uniform_map,
|
||||||
var);
|
var->type,
|
||||||
|
var->data.location,
|
||||||
|
&name_tmp,
|
||||||
|
strlen(name_tmp), true);
|
||||||
|
ralloc_free(name_tmp);
|
||||||
|
|
||||||
if (slots != -1) {
|
if (slots != -1) {
|
||||||
ret = true;
|
ret = true;
|
||||||
entries_total += slots;
|
entries_total += slots;
|
||||||
|
|
@ -2941,7 +2995,7 @@ check_explicit_uniform_locations(const struct gl_extensions *exts,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
link_util_update_empty_uniform_locations(prog);
|
link_util_update_empty_uniform_locations(consts, prog);
|
||||||
|
|
||||||
string_to_uint_map_dtor(uniform_map);
|
string_to_uint_map_dtor(uniform_map);
|
||||||
prog->NumExplicitUniformLocations = entries_total;
|
prog->NumExplicitUniformLocations = entries_total;
|
||||||
|
|
@ -3705,7 +3759,7 @@ gl_nir_link_glsl(struct gl_context *ctx, struct gl_shader_program *prog)
|
||||||
if (!prog->data->LinkStatus)
|
if (!prog->data->LinkStatus)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
check_explicit_uniform_locations(exts, prog);
|
check_explicit_uniform_locations(consts, exts, prog);
|
||||||
|
|
||||||
link_assign_subroutine_types(prog);
|
link_assign_subroutine_types(prog);
|
||||||
verify_subroutine_associated_funcs(prog);
|
verify_subroutine_associated_funcs(prog);
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@
|
||||||
#include "linker_util.h"
|
#include "linker_util.h"
|
||||||
#include "util/bitscan.h"
|
#include "util/bitscan.h"
|
||||||
#include "util/set.h"
|
#include "util/set.h"
|
||||||
|
#include "util/u_range_remap.h"
|
||||||
#include "main/consts_exts.h"
|
#include "main/consts_exts.h"
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -249,24 +250,41 @@ link_util_find_empty_block(struct gl_shader_program *prog,
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
link_util_update_empty_uniform_locations(struct gl_shader_program *prog)
|
link_util_update_empty_uniform_locations(const struct gl_constants *consts,
|
||||||
|
struct gl_shader_program *prog)
|
||||||
{
|
{
|
||||||
struct empty_uniform_block *current_block = NULL;
|
int prev_end = -1;
|
||||||
|
list_for_each_entry_safe(struct range_entry, e, prog->UniformRemapTable, node) {
|
||||||
for (unsigned i = 0; i < prog->NumUniformRemapTable; i++) {
|
unsigned next_slot = prev_end + 1;
|
||||||
/* We found empty space in UniformRemapTable. */
|
if (e->start > next_slot) {
|
||||||
if (prog->UniformRemapTable[i] == NULL) {
|
|
||||||
/* We've found the beginning of a new continous block of empty slots */
|
/* We've found the beginning of a new continous block of empty slots */
|
||||||
if (!current_block || current_block->start + current_block->slots != i) {
|
struct empty_uniform_block *current_block =
|
||||||
current_block = rzalloc(prog, struct empty_uniform_block);
|
rzalloc(prog, struct empty_uniform_block);
|
||||||
current_block->start = i;
|
current_block->start = next_slot;
|
||||||
ir_exec_list_push_tail(&prog->EmptyUniformLocations,
|
current_block->slots = e->start - next_slot;
|
||||||
|
ir_exec_list_push_tail(&prog->EmptyUniformLocations,
|
||||||
¤t_block->link);
|
¤t_block->link);
|
||||||
}
|
|
||||||
|
|
||||||
/* The current block continues, so we simply increment its slots */
|
|
||||||
current_block->slots++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
prev_end = e->end;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Add the remaining continous block of empty slots */
|
||||||
|
unsigned next_slot = prev_end + 1;
|
||||||
|
/* Some drivers assign a max assignable value greater than max block size
|
||||||
|
* so we work around this by taking the max of either to get the remaining
|
||||||
|
* empty slots.
|
||||||
|
*/
|
||||||
|
unsigned max_slot = MAX2(consts->MaxUniformBlockSize,
|
||||||
|
consts->MaxUserAssignableUniformLocations) - 1;
|
||||||
|
if (max_slot >= next_slot) {
|
||||||
|
struct empty_uniform_block *current_block =
|
||||||
|
rzalloc(prog, struct empty_uniform_block);
|
||||||
|
current_block->start = next_slot;
|
||||||
|
current_block->slots = max_slot + 1 - next_slot;
|
||||||
|
|
||||||
|
ir_exec_list_push_tail(&prog->EmptyUniformLocations,
|
||||||
|
¤t_block->link);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -116,7 +116,8 @@ link_util_find_empty_block(struct gl_shader_program *prog,
|
||||||
struct gl_uniform_storage *uniform);
|
struct gl_uniform_storage *uniform);
|
||||||
|
|
||||||
void
|
void
|
||||||
link_util_update_empty_uniform_locations(struct gl_shader_program *prog);
|
link_util_update_empty_uniform_locations(const struct gl_constants *consts,
|
||||||
|
struct gl_shader_program *prog);
|
||||||
|
|
||||||
void
|
void
|
||||||
link_util_check_subroutine_resources(struct gl_shader_program *prog);
|
link_util_check_subroutine_resources(struct gl_shader_program *prog);
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,7 @@
|
||||||
#include "program/program.h"
|
#include "program/program.h"
|
||||||
#include "string_to_uint_map.h"
|
#include "string_to_uint_map.h"
|
||||||
#include "util/bitscan.h"
|
#include "util/bitscan.h"
|
||||||
|
#include "util/u_range_remap.h"
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
@ -573,6 +574,33 @@ enum uniform_remap_type
|
||||||
remap_type_uniform_offsets_equal,
|
remap_type_uniform_offsets_equal,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
write_uniform_remap_list(struct blob *metadata,
|
||||||
|
unsigned num_uniform_remap_table,
|
||||||
|
gl_uniform_storage *uniform_storage,
|
||||||
|
struct list_head *uniform_remap_list)
|
||||||
|
{
|
||||||
|
blob_write_uint32(metadata, num_uniform_remap_table);
|
||||||
|
blob_write_uint32(metadata, list_length(uniform_remap_list));
|
||||||
|
|
||||||
|
list_for_each_entry_safe(struct range_entry, entry, uniform_remap_list, node) {
|
||||||
|
gl_uniform_storage *u = (gl_uniform_storage *)entry->ptr;
|
||||||
|
uint32_t offset = u - uniform_storage;
|
||||||
|
|
||||||
|
if (u == INACTIVE_UNIFORM_EXPLICIT_LOCATION) {
|
||||||
|
blob_write_uint32(metadata, remap_type_inactive_explicit_location);
|
||||||
|
} else if (u == NULL) {
|
||||||
|
blob_write_uint32(metadata, remap_type_null_ptr);
|
||||||
|
} else {
|
||||||
|
blob_write_uint32(metadata, remap_type_uniform_offset);
|
||||||
|
blob_write_uint32(metadata, offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
blob_write_uint32(metadata, entry->start);
|
||||||
|
blob_write_uint32(metadata, entry->end);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
write_uniform_remap_table(struct blob *metadata,
|
write_uniform_remap_table(struct blob *metadata,
|
||||||
unsigned num_entries,
|
unsigned num_entries,
|
||||||
|
|
@ -618,9 +646,9 @@ static void
|
||||||
write_uniform_remap_tables(struct blob *metadata,
|
write_uniform_remap_tables(struct blob *metadata,
|
||||||
struct gl_shader_program *prog)
|
struct gl_shader_program *prog)
|
||||||
{
|
{
|
||||||
write_uniform_remap_table(metadata, prog->NumUniformRemapTable,
|
write_uniform_remap_list(metadata, prog->NumUniformRemapTable,
|
||||||
prog->data->UniformStorage,
|
prog->data->UniformStorage,
|
||||||
prog->UniformRemapTable);
|
prog->UniformRemapTable);
|
||||||
|
|
||||||
for (unsigned i = 0; i < MESA_SHADER_MESH_STAGES; i++) {
|
for (unsigned i = 0; i < MESA_SHADER_MESH_STAGES; i++) {
|
||||||
struct gl_linked_shader *sh = prog->_LinkedShaders[i];
|
struct gl_linked_shader *sh = prog->_LinkedShaders[i];
|
||||||
|
|
@ -633,6 +661,38 @@ write_uniform_remap_tables(struct blob *metadata,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
read_uniform_remap_list(struct blob_reader *metadata,
|
||||||
|
struct gl_shader_program *prog,
|
||||||
|
unsigned *num_entries,
|
||||||
|
struct list_head *remap_list,
|
||||||
|
gl_uniform_storage *uniform_storage)
|
||||||
|
{
|
||||||
|
unsigned num = blob_read_uint32(metadata);
|
||||||
|
*num_entries = num;
|
||||||
|
|
||||||
|
unsigned num_list_entries = blob_read_uint32(metadata);
|
||||||
|
|
||||||
|
for (unsigned i = 0; i < num_list_entries; i++) {
|
||||||
|
gl_uniform_storage *uniform;
|
||||||
|
enum uniform_remap_type type =
|
||||||
|
(enum uniform_remap_type) blob_read_uint32(metadata);
|
||||||
|
|
||||||
|
if (type == remap_type_inactive_explicit_location) {
|
||||||
|
uniform = INACTIVE_UNIFORM_EXPLICIT_LOCATION;
|
||||||
|
} else if (type == remap_type_null_ptr) {
|
||||||
|
uniform = NULL;
|
||||||
|
} else {
|
||||||
|
uint32_t uni_offset = blob_read_uint32(metadata);
|
||||||
|
uniform = uniform_storage + uni_offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned start = blob_read_uint32(metadata);
|
||||||
|
unsigned end = blob_read_uint32(metadata);
|
||||||
|
util_range_insert_remap(start, end, remap_list, uniform);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static struct gl_uniform_storage **
|
static struct gl_uniform_storage **
|
||||||
read_uniform_remap_table(struct blob_reader *metadata,
|
read_uniform_remap_table(struct blob_reader *metadata,
|
||||||
struct gl_shader_program *prog,
|
struct gl_shader_program *prog,
|
||||||
|
|
@ -673,9 +733,9 @@ static void
|
||||||
read_uniform_remap_tables(struct blob_reader *metadata,
|
read_uniform_remap_tables(struct blob_reader *metadata,
|
||||||
struct gl_shader_program *prog)
|
struct gl_shader_program *prog)
|
||||||
{
|
{
|
||||||
prog->UniformRemapTable =
|
read_uniform_remap_list(metadata, prog, &prog->NumUniformRemapTable,
|
||||||
read_uniform_remap_table(metadata, prog, &prog->NumUniformRemapTable,
|
prog->UniformRemapTable,
|
||||||
prog->data->UniformStorage);
|
prog->data->UniformStorage);
|
||||||
|
|
||||||
for (unsigned i = 0; i < MESA_SHADER_MESH_STAGES; i++) {
|
for (unsigned i = 0; i < MESA_SHADER_MESH_STAGES; i++) {
|
||||||
struct gl_linked_shader *sh = prog->_LinkedShaders[i];
|
struct gl_linked_shader *sh = prog->_LinkedShaders[i];
|
||||||
|
|
@ -949,7 +1009,8 @@ read_program_resource_data(struct blob_reader *metadata,
|
||||||
if (type == uniform_not_remapped) {
|
if (type == uniform_not_remapped) {
|
||||||
res->Data = &prog->data->UniformStorage[blob_read_uint32(metadata)];
|
res->Data = &prog->data->UniformStorage[blob_read_uint32(metadata)];
|
||||||
} else {
|
} else {
|
||||||
res->Data = prog->UniformRemapTable[blob_read_uint32(metadata)];
|
res->Data = util_range_remap(blob_read_uint32(metadata),
|
||||||
|
prog->UniformRemapTable)->ptr;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,7 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "util/ralloc.h"
|
#include "util/ralloc.h"
|
||||||
#include "util/strtod.h"
|
#include "util/strtod.h"
|
||||||
|
#include "util/u_range_remap.h"
|
||||||
#include "main/mtypes.h"
|
#include "main/mtypes.h"
|
||||||
#include "string_to_uint_map.h"
|
#include "string_to_uint_map.h"
|
||||||
#include "pipe/p_screen.h"
|
#include "pipe/p_screen.h"
|
||||||
|
|
@ -161,7 +162,8 @@ _mesa_clear_shader_program_data(struct gl_context *ctx,
|
||||||
shProg->data->NumUniformStorage = 0;
|
shProg->data->NumUniformStorage = 0;
|
||||||
shProg->data->UniformStorage = NULL;
|
shProg->data->UniformStorage = NULL;
|
||||||
shProg->NumUniformRemapTable = 0;
|
shProg->NumUniformRemapTable = 0;
|
||||||
shProg->UniformRemapTable = NULL;
|
shProg->UniformRemapTable =
|
||||||
|
util_reset_range_remap(shProg->UniformRemapTable);
|
||||||
|
|
||||||
ralloc_free(shProg->data->InfoLog);
|
ralloc_free(shProg->data->InfoLog);
|
||||||
shProg->data->InfoLog = ralloc_strdup(shProg->data, "");
|
shProg->data->InfoLog = ralloc_strdup(shProg->data, "");
|
||||||
|
|
@ -284,6 +286,8 @@ void initialize_context_to_defaults(struct gl_context *ctx, gl_api api)
|
||||||
ctx->Const.Program[MESA_SHADER_COMPUTE].MaxInputComponents = 0; /* not used */
|
ctx->Const.Program[MESA_SHADER_COMPUTE].MaxInputComponents = 0; /* not used */
|
||||||
ctx->Const.Program[MESA_SHADER_COMPUTE].MaxOutputComponents = 0; /* not used */
|
ctx->Const.Program[MESA_SHADER_COMPUTE].MaxOutputComponents = 0; /* not used */
|
||||||
|
|
||||||
|
ctx->Const.MaxUniformBlockSize = 16384;
|
||||||
|
|
||||||
ctx->Driver.NewProgram = standalone_new_program;
|
ctx->Driver.NewProgram = standalone_new_program;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -303,6 +307,7 @@ standalone_create_shader_program(void)
|
||||||
whole_program->FragDataBindings = new string_to_uint_map;
|
whole_program->FragDataBindings = new string_to_uint_map;
|
||||||
whole_program->FragDataIndexBindings = new string_to_uint_map;
|
whole_program->FragDataIndexBindings = new string_to_uint_map;
|
||||||
|
|
||||||
|
whole_program->UniformRemapTable = util_create_range_remap();
|
||||||
ir_exec_list_make_empty(&whole_program->EmptyUniformLocations);
|
ir_exec_list_make_empty(&whole_program->EmptyUniformLocations);
|
||||||
|
|
||||||
return whole_program;
|
return whole_program;
|
||||||
|
|
@ -327,6 +332,7 @@ standalone_destroy_shader_program(struct gl_shader_program *whole_program)
|
||||||
delete whole_program->FragDataBindings;
|
delete whole_program->FragDataBindings;
|
||||||
delete whole_program->FragDataIndexBindings;
|
delete whole_program->FragDataIndexBindings;
|
||||||
|
|
||||||
|
ralloc_free(whole_program->UniformRemapTable);
|
||||||
ralloc_free(whole_program);
|
ralloc_free(whole_program);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -440,7 +440,7 @@ struct gl_shader_program
|
||||||
* in the UniformRemapTable, all pointing to the same UniformStorage entry.
|
* in the UniformRemapTable, all pointing to the same UniformStorage entry.
|
||||||
*/
|
*/
|
||||||
unsigned NumUniformRemapTable;
|
unsigned NumUniformRemapTable;
|
||||||
struct gl_uniform_storage **UniformRemapTable;
|
struct list_head *UniformRemapTable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sometimes there are empty slots left over in UniformRemapTable after we
|
* Sometimes there are empty slots left over in UniformRemapTable after we
|
||||||
|
|
|
||||||
|
|
@ -43,6 +43,7 @@
|
||||||
#include "program/prog_parameter.h"
|
#include "program/prog_parameter.h"
|
||||||
#include "util/ralloc.h"
|
#include "util/ralloc.h"
|
||||||
#include "util/u_atomic.h"
|
#include "util/u_atomic.h"
|
||||||
|
#include "util/u_range_remap.h"
|
||||||
|
|
||||||
/**********************************************************************/
|
/**********************************************************************/
|
||||||
/*** Shader object functions ***/
|
/*** Shader object functions ***/
|
||||||
|
|
@ -291,8 +292,6 @@ init_shader_program(struct gl_shader_program *prog)
|
||||||
prog->FragDataIndexBindings = string_to_uint_map_ctor();
|
prog->FragDataIndexBindings = string_to_uint_map_ctor();
|
||||||
|
|
||||||
prog->TransformFeedback.BufferMode = GL_INTERLEAVED_ATTRIBS;
|
prog->TransformFeedback.BufferMode = GL_INTERLEAVED_ATTRIBS;
|
||||||
|
|
||||||
ir_exec_list_make_empty(&prog->EmptyUniformLocations);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -330,11 +329,9 @@ _mesa_clear_shader_program_data(struct gl_context *ctx,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (shProg->UniformRemapTable) {
|
shProg->UniformRemapTable =
|
||||||
ralloc_free(shProg->UniformRemapTable);
|
util_reset_range_remap(shProg->UniformRemapTable);
|
||||||
shProg->NumUniformRemapTable = 0;
|
ir_exec_list_make_empty(&shProg->EmptyUniformLocations);
|
||||||
shProg->UniformRemapTable = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (shProg->data)
|
if (shProg->data)
|
||||||
_mesa_program_resource_hash_destroy(shProg);
|
_mesa_program_resource_hash_destroy(shProg);
|
||||||
|
|
@ -358,6 +355,11 @@ _mesa_free_shader_program_data(struct gl_context *ctx,
|
||||||
|
|
||||||
_mesa_clear_shader_program_data(ctx, shProg);
|
_mesa_clear_shader_program_data(ctx, shProg);
|
||||||
|
|
||||||
|
if (shProg->UniformRemapTable) {
|
||||||
|
ralloc_free(shProg->UniformRemapTable);
|
||||||
|
shProg->UniformRemapTable = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (shProg->AttributeBindings) {
|
if (shProg->AttributeBindings) {
|
||||||
string_to_uint_map_dtor(shProg->AttributeBindings);
|
string_to_uint_map_dtor(shProg->AttributeBindings);
|
||||||
shProg->AttributeBindings = NULL;
|
shProg->AttributeBindings = NULL;
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,7 @@
|
||||||
#include "compiler/glsl/ir.h"
|
#include "compiler/glsl/ir.h"
|
||||||
#include "compiler/glsl/glsl_parser_extras.h"
|
#include "compiler/glsl/glsl_parser_extras.h"
|
||||||
#include "util/bitscan.h"
|
#include "util/bitscan.h"
|
||||||
|
#include "util/u_range_remap.h"
|
||||||
|
|
||||||
#include "state_tracker/st_context.h"
|
#include "state_tracker/st_context.h"
|
||||||
|
|
||||||
|
|
@ -200,11 +201,17 @@ validate_uniform_parameters(GLint location, GLsizei count,
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check that the given location is in bounds of uniform remap table.
|
if (location == -1) {
|
||||||
* Unlinked programs will have NumUniformRemapTable == 0, so we can take
|
if (!shProg->data->LinkStatus)
|
||||||
* the shProg->data->LinkStatus check out of the main path.
|
_mesa_error(ctx, GL_INVALID_OPERATION, "%s(program not linked)",
|
||||||
*/
|
caller);
|
||||||
if (unlikely(location >= (GLint) shProg->NumUniformRemapTable)) {
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check that the given location is in bounds of uniform remap table */
|
||||||
|
if (unlikely(location >= 0 &&
|
||||||
|
(shProg->UniformRemapTable == NULL || list_is_empty(shProg->UniformRemapTable)))) {
|
||||||
if (!shProg->data->LinkStatus)
|
if (!shProg->data->LinkStatus)
|
||||||
_mesa_error(ctx, GL_INVALID_OPERATION, "%s(program not linked)",
|
_mesa_error(ctx, GL_INVALID_OPERATION, "%s(program not linked)",
|
||||||
caller);
|
caller);
|
||||||
|
|
@ -215,14 +222,6 @@ validate_uniform_parameters(GLint location, GLsizei count,
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (location == -1) {
|
|
||||||
if (!shProg->data->LinkStatus)
|
|
||||||
_mesa_error(ctx, GL_INVALID_OPERATION, "%s(program not linked)",
|
|
||||||
caller);
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Page 82 (page 96 of the PDF) of the OpenGL 2.1 spec says:
|
/* Page 82 (page 96 of the PDF) of the OpenGL 2.1 spec says:
|
||||||
*
|
*
|
||||||
* "If any of the following conditions occur, an INVALID_OPERATION
|
* "If any of the following conditions occur, an INVALID_OPERATION
|
||||||
|
|
@ -236,7 +235,14 @@ validate_uniform_parameters(GLint location, GLsizei count,
|
||||||
* - if count is greater than one, and the uniform declared in the
|
* - if count is greater than one, and the uniform declared in the
|
||||||
* shader is not an array variable,
|
* shader is not an array variable,
|
||||||
*/
|
*/
|
||||||
if (location < -1 || !shProg->UniformRemapTable[location]) {
|
struct gl_uniform_storage *uni = NULL;
|
||||||
|
if (location >= 0) {
|
||||||
|
struct range_entry *e =
|
||||||
|
util_range_remap(location, shProg->UniformRemapTable);
|
||||||
|
uni = e ? (struct gl_uniform_storage *)e->ptr : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!uni) {
|
||||||
_mesa_error(ctx, GL_INVALID_OPERATION, "%s(location=%d)",
|
_mesa_error(ctx, GL_INVALID_OPERATION, "%s(location=%d)",
|
||||||
caller, location);
|
caller, location);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
@ -253,12 +259,9 @@ validate_uniform_parameters(GLint location, GLsizei count,
|
||||||
* no error is generated."
|
* no error is generated."
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
if (shProg->UniformRemapTable[location] ==
|
if (uni == INACTIVE_UNIFORM_EXPLICIT_LOCATION)
|
||||||
INACTIVE_UNIFORM_EXPLICIT_LOCATION)
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
struct gl_uniform_storage *const uni = shProg->UniformRemapTable[location];
|
|
||||||
|
|
||||||
/* Even though no location is assigned to a built-in uniform and this
|
/* Even though no location is assigned to a built-in uniform and this
|
||||||
* function should already have returned NULL, this test makes it explicit
|
* function should already have returned NULL, this test makes it explicit
|
||||||
* that we are not allowing to update the value of a built-in.
|
* that we are not allowing to update the value of a built-in.
|
||||||
|
|
@ -1449,10 +1452,10 @@ _mesa_uniform(GLint location, GLsizei count, const GLvoid *values,
|
||||||
if (location == -1)
|
if (location == -1)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (location >= (int)shProg->NumUniformRemapTable)
|
struct range_entry *e =
|
||||||
return;
|
util_range_remap(location, shProg->UniformRemapTable);
|
||||||
|
uni = e ? (struct gl_uniform_storage *)e->ptr : NULL;
|
||||||
|
|
||||||
uni = shProg->UniformRemapTable[location];
|
|
||||||
if (!uni || uni == INACTIVE_UNIFORM_EXPLICIT_LOCATION)
|
if (!uni || uni == INACTIVE_UNIFORM_EXPLICIT_LOCATION)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
@ -2019,7 +2022,10 @@ _mesa_uniform_handle(GLint location, GLsizei count, const GLvoid *values,
|
||||||
if (location == -1)
|
if (location == -1)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
uni = shProg->UniformRemapTable[location];
|
struct range_entry *e =
|
||||||
|
util_range_remap(location, shProg->UniformRemapTable);
|
||||||
|
uni = e ? (struct gl_uniform_storage *)e->ptr : NULL;
|
||||||
|
|
||||||
if (!uni || uni == INACTIVE_UNIFORM_EXPLICIT_LOCATION)
|
if (!uni || uni == INACTIVE_UNIFORM_EXPLICIT_LOCATION)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue