mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-04-16 12:50:38 +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 "util/u_dynarray.h"
|
||||
#include "util/u_math.h"
|
||||
#include "util/u_range_remap.h"
|
||||
#include "main/consts_exts.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.
|
||||
*/
|
||||
assert(!prog->data->spirv ||
|
||||
(prog->data->spirv && !prog->UniformRemapTable));
|
||||
if (!prog->UniformRemapTable) {
|
||||
prog->UniformRemapTable = rzalloc_array(prog,
|
||||
struct gl_uniform_storage *,
|
||||
prog->NumUniformRemapTable);
|
||||
}
|
||||
(prog->data->spirv && list_is_empty(prog->UniformRemapTable)));
|
||||
|
||||
union gl_constant_value *data =
|
||||
rzalloc_array(prog->data,
|
||||
union gl_constant_value, prog->data->NumUniformDataSlots);
|
||||
if (!prog->UniformRemapTable || !data) {
|
||||
if (!data) {
|
||||
linker_error(prog, "Out of memory during linking.\n");
|
||||
return;
|
||||
}
|
||||
|
|
@ -321,19 +317,17 @@ setup_uniform_remap_tables(const struct gl_constants *consts,
|
|||
unsigned num_slots = glsl_get_component_slots(uniform->type);
|
||||
|
||||
uniform->storage = &data[data_pos];
|
||||
data_pos += num_slots * entries;
|
||||
|
||||
/* 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;
|
||||
|
||||
data_pos += num_slots;
|
||||
}
|
||||
/* Set remap table entry to the correct gl_uniform_storage. */
|
||||
util_range_insert_remap(uniform->remap_location,
|
||||
uniform->remap_location + entries - 1,
|
||||
prog->UniformRemapTable, uniform);
|
||||
}
|
||||
|
||||
/* Reserve locations for rest of the uniforms. */
|
||||
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++) {
|
||||
struct gl_uniform_storage *uniform = &prog->data->UniformStorage[i];
|
||||
|
|
@ -365,35 +359,24 @@ setup_uniform_remap_tables(const struct gl_constants *consts,
|
|||
|
||||
unsigned location =
|
||||
link_util_find_empty_block(prog, &prog->data->UniformStorage[i]);
|
||||
|
||||
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 */
|
||||
prog->UniformRemapTable =
|
||||
reralloc(prog,
|
||||
prog->UniformRemapTable,
|
||||
struct gl_uniform_storage *,
|
||||
prog->NumUniformRemapTable + entries);
|
||||
prog->NumUniformRemapTable += entries;
|
||||
unsigned num_slots = glsl_get_component_slots(uniform->type);
|
||||
if (uniform->block_index == -1) {
|
||||
uniform->storage = &data[data_pos];
|
||||
data_pos += num_slots * entries;
|
||||
}
|
||||
|
||||
/* set the base location in remap table for the uniform */
|
||||
uniform->remap_location = location;
|
||||
|
||||
unsigned num_slots = glsl_get_component_slots(uniform->type);
|
||||
|
||||
if (uniform->block_index == -1)
|
||||
uniform->storage = &data[data_pos];
|
||||
|
||||
/* 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;
|
||||
}
|
||||
/* Set remap table entry to the correct gl_uniform_storage. */
|
||||
util_range_insert_remap(uniform->remap_location,
|
||||
uniform->remap_location + entries - 1,
|
||||
prog->UniformRemapTable, uniform);
|
||||
}
|
||||
|
||||
/* Verify that total amount of entries for explicit and implicit locations
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@
|
|||
#include "main/context.h"
|
||||
#include "main/shaderobj.h"
|
||||
#include "util/glheader.h"
|
||||
#include "util/u_range_remap.h"
|
||||
#include "util/perf/cpu_trace.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
|
||||
* for a variable, checks for overlaps between other uniforms using explicit
|
||||
* locations.
|
||||
* If return_zero bool is true zero will be returned if the uniform was
|
||||
* already processed for a different stage.
|
||||
*/
|
||||
static int
|
||||
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);
|
||||
unsigned max_loc = var->data.location + slots - 1;
|
||||
unsigned return_value = slots;
|
||||
if (glsl_type_is_struct_or_ifc(type) ||
|
||||
(glsl_type_is_array(type) &&
|
||||
(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. */
|
||||
if (max_loc + 1 > prog->NumUniformRemapTable) {
|
||||
prog->UniformRemapTable =
|
||||
reralloc(prog, prog->UniformRemapTable,
|
||||
struct gl_uniform_storage *,
|
||||
max_loc + 1);
|
||||
unsigned length = glsl_get_length(type);
|
||||
if (glsl_type_is_unsized_array(type))
|
||||
length = 1;
|
||||
|
||||
if (!prog->UniformRemapTable) {
|
||||
linker_error(prog, "Out of memory during linking.\n");
|
||||
return -1;
|
||||
}
|
||||
int location_count = 0;
|
||||
for (unsigned i = 0; i < length; i++) {
|
||||
const struct glsl_type *field_type;
|
||||
size_t new_length = name_length;
|
||||
|
||||
/* Initialize allocated space. */
|
||||
for (unsigned i = prog->NumUniformRemapTable; i < max_loc + 1; i++)
|
||||
prog->UniformRemapTable[i] = NULL;
|
||||
if (glsl_type_is_struct_or_ifc(type)) {
|
||||
field_type = glsl_get_struct_field(type, i);
|
||||
|
||||
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++) {
|
||||
unsigned loc = var->data.location + 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;
|
||||
/* Append the subscript to the current variable name */
|
||||
if (var_name)
|
||||
ralloc_asprintf_rewrite_tail(var_name, &new_length, "[%u]", i);
|
||||
}
|
||||
|
||||
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:
|
||||
*
|
||||
* "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,
|
||||
"location qualifier for uniform %s overlaps "
|
||||
"previously used location\n",
|
||||
var->name);
|
||||
*var_name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Initialize location as inactive before optimization
|
||||
* rounds and location assignment.
|
||||
*/
|
||||
prog->UniformRemapTable[loc] = INACTIVE_UNIFORM_EXPLICIT_LOCATION;
|
||||
prog->NumUniformRemapTable += slots;
|
||||
}
|
||||
|
||||
/* 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. */
|
||||
string_to_uint_map_put(map, var->data.location, var->name);
|
||||
string_to_uint_map_put(map, location, *var_name);
|
||||
|
||||
return return_value;
|
||||
}
|
||||
|
|
@ -2895,13 +2940,16 @@ reserve_subroutine_explicit_locations(struct gl_shader_program *prog,
|
|||
* inactive array elements that may get trimmed away.
|
||||
*/
|
||||
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)
|
||||
{
|
||||
prog->NumExplicitUniformLocations = 0;
|
||||
|
||||
if (!exts->ARB_explicit_uniform_location)
|
||||
if (!exts->ARB_explicit_uniform_location) {
|
||||
link_util_update_empty_uniform_locations(consts, prog);
|
||||
return;
|
||||
}
|
||||
|
||||
/* This map is used to detect if overlapping explicit locations
|
||||
* 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)))
|
||||
ret = reserve_subroutine_explicit_locations(prog, p, var);
|
||||
else {
|
||||
char *name_tmp = ralloc_strdup(NULL, var->name);
|
||||
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) {
|
||||
ret = true;
|
||||
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);
|
||||
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)
|
||||
goto done;
|
||||
|
||||
check_explicit_uniform_locations(exts, prog);
|
||||
check_explicit_uniform_locations(consts, exts, prog);
|
||||
|
||||
link_assign_subroutine_types(prog);
|
||||
verify_subroutine_associated_funcs(prog);
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@
|
|||
#include "linker_util.h"
|
||||
#include "util/bitscan.h"
|
||||
#include "util/set.h"
|
||||
#include "util/u_range_remap.h"
|
||||
#include "main/consts_exts.h"
|
||||
|
||||
void
|
||||
|
|
@ -249,24 +250,41 @@ link_util_find_empty_block(struct gl_shader_program *prog,
|
|||
}
|
||||
|
||||
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;
|
||||
|
||||
for (unsigned i = 0; i < prog->NumUniformRemapTable; i++) {
|
||||
/* We found empty space in UniformRemapTable. */
|
||||
if (prog->UniformRemapTable[i] == NULL) {
|
||||
int prev_end = -1;
|
||||
list_for_each_entry_safe(struct range_entry, e, prog->UniformRemapTable, node) {
|
||||
unsigned next_slot = prev_end + 1;
|
||||
if (e->start > next_slot) {
|
||||
/* We've found the beginning of a new continous block of empty slots */
|
||||
if (!current_block || current_block->start + current_block->slots != i) {
|
||||
current_block = rzalloc(prog, struct empty_uniform_block);
|
||||
current_block->start = i;
|
||||
ir_exec_list_push_tail(&prog->EmptyUniformLocations,
|
||||
struct empty_uniform_block *current_block =
|
||||
rzalloc(prog, struct empty_uniform_block);
|
||||
current_block->start = next_slot;
|
||||
current_block->slots = e->start - next_slot;
|
||||
ir_exec_list_push_tail(&prog->EmptyUniformLocations,
|
||||
¤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);
|
||||
|
||||
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
|
||||
link_util_check_subroutine_resources(struct gl_shader_program *prog);
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@
|
|||
#include "program/program.h"
|
||||
#include "string_to_uint_map.h"
|
||||
#include "util/bitscan.h"
|
||||
#include "util/u_range_remap.h"
|
||||
|
||||
|
||||
static void
|
||||
|
|
@ -573,6 +574,33 @@ enum uniform_remap_type
|
|||
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
|
||||
write_uniform_remap_table(struct blob *metadata,
|
||||
unsigned num_entries,
|
||||
|
|
@ -618,9 +646,9 @@ static void
|
|||
write_uniform_remap_tables(struct blob *metadata,
|
||||
struct gl_shader_program *prog)
|
||||
{
|
||||
write_uniform_remap_table(metadata, prog->NumUniformRemapTable,
|
||||
prog->data->UniformStorage,
|
||||
prog->UniformRemapTable);
|
||||
write_uniform_remap_list(metadata, prog->NumUniformRemapTable,
|
||||
prog->data->UniformStorage,
|
||||
prog->UniformRemapTable);
|
||||
|
||||
for (unsigned i = 0; i < MESA_SHADER_MESH_STAGES; 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 **
|
||||
read_uniform_remap_table(struct blob_reader *metadata,
|
||||
struct gl_shader_program *prog,
|
||||
|
|
@ -673,9 +733,9 @@ static void
|
|||
read_uniform_remap_tables(struct blob_reader *metadata,
|
||||
struct gl_shader_program *prog)
|
||||
{
|
||||
prog->UniformRemapTable =
|
||||
read_uniform_remap_table(metadata, prog, &prog->NumUniformRemapTable,
|
||||
prog->data->UniformStorage);
|
||||
read_uniform_remap_list(metadata, prog, &prog->NumUniformRemapTable,
|
||||
prog->UniformRemapTable,
|
||||
prog->data->UniformStorage);
|
||||
|
||||
for (unsigned i = 0; i < MESA_SHADER_MESH_STAGES; 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) {
|
||||
res->Data = &prog->data->UniformStorage[blob_read_uint32(metadata)];
|
||||
} else {
|
||||
res->Data = prog->UniformRemapTable[blob_read_uint32(metadata)];
|
||||
res->Data = util_range_remap(blob_read_uint32(metadata),
|
||||
prog->UniformRemapTable)->ptr;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@
|
|||
#include <string.h>
|
||||
#include "util/ralloc.h"
|
||||
#include "util/strtod.h"
|
||||
#include "util/u_range_remap.h"
|
||||
#include "main/mtypes.h"
|
||||
#include "string_to_uint_map.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->UniformStorage = NULL;
|
||||
shProg->NumUniformRemapTable = 0;
|
||||
shProg->UniformRemapTable = NULL;
|
||||
shProg->UniformRemapTable =
|
||||
util_reset_range_remap(shProg->UniformRemapTable);
|
||||
|
||||
ralloc_free(shProg->data->InfoLog);
|
||||
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].MaxOutputComponents = 0; /* not used */
|
||||
|
||||
ctx->Const.MaxUniformBlockSize = 16384;
|
||||
|
||||
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->FragDataIndexBindings = new string_to_uint_map;
|
||||
|
||||
whole_program->UniformRemapTable = util_create_range_remap();
|
||||
ir_exec_list_make_empty(&whole_program->EmptyUniformLocations);
|
||||
|
||||
return whole_program;
|
||||
|
|
@ -327,6 +332,7 @@ standalone_destroy_shader_program(struct gl_shader_program *whole_program)
|
|||
delete whole_program->FragDataBindings;
|
||||
delete whole_program->FragDataIndexBindings;
|
||||
|
||||
ralloc_free(whole_program->UniformRemapTable);
|
||||
ralloc_free(whole_program);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -440,7 +440,7 @@ struct gl_shader_program
|
|||
* in the UniformRemapTable, all pointing to the same UniformStorage entry.
|
||||
*/
|
||||
unsigned NumUniformRemapTable;
|
||||
struct gl_uniform_storage **UniformRemapTable;
|
||||
struct list_head *UniformRemapTable;
|
||||
|
||||
/**
|
||||
* Sometimes there are empty slots left over in UniformRemapTable after we
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@
|
|||
#include "program/prog_parameter.h"
|
||||
#include "util/ralloc.h"
|
||||
#include "util/u_atomic.h"
|
||||
#include "util/u_range_remap.h"
|
||||
|
||||
/**********************************************************************/
|
||||
/*** Shader object functions ***/
|
||||
|
|
@ -291,8 +292,6 @@ init_shader_program(struct gl_shader_program *prog)
|
|||
prog->FragDataIndexBindings = string_to_uint_map_ctor();
|
||||
|
||||
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) {
|
||||
ralloc_free(shProg->UniformRemapTable);
|
||||
shProg->NumUniformRemapTable = 0;
|
||||
shProg->UniformRemapTable = NULL;
|
||||
}
|
||||
shProg->UniformRemapTable =
|
||||
util_reset_range_remap(shProg->UniformRemapTable);
|
||||
ir_exec_list_make_empty(&shProg->EmptyUniformLocations);
|
||||
|
||||
if (shProg->data)
|
||||
_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);
|
||||
|
||||
if (shProg->UniformRemapTable) {
|
||||
ralloc_free(shProg->UniformRemapTable);
|
||||
shProg->UniformRemapTable = NULL;
|
||||
}
|
||||
|
||||
if (shProg->AttributeBindings) {
|
||||
string_to_uint_map_dtor(shProg->AttributeBindings);
|
||||
shProg->AttributeBindings = NULL;
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@
|
|||
#include "compiler/glsl/ir.h"
|
||||
#include "compiler/glsl/glsl_parser_extras.h"
|
||||
#include "util/bitscan.h"
|
||||
#include "util/u_range_remap.h"
|
||||
|
||||
#include "state_tracker/st_context.h"
|
||||
|
||||
|
|
@ -200,11 +201,17 @@ validate_uniform_parameters(GLint location, GLsizei count,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/* Check that the given location is in bounds of uniform remap table.
|
||||
* Unlinked programs will have NumUniformRemapTable == 0, so we can take
|
||||
* the shProg->data->LinkStatus check out of the main path.
|
||||
*/
|
||||
if (unlikely(location >= (GLint) shProg->NumUniformRemapTable)) {
|
||||
if (location == -1) {
|
||||
if (!shProg->data->LinkStatus)
|
||||
_mesa_error(ctx, GL_INVALID_OPERATION, "%s(program not linked)",
|
||||
caller);
|
||||
|
||||
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)
|
||||
_mesa_error(ctx, GL_INVALID_OPERATION, "%s(program not linked)",
|
||||
caller);
|
||||
|
|
@ -215,14 +222,6 @@ validate_uniform_parameters(GLint location, GLsizei count,
|
|||
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:
|
||||
*
|
||||
* "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
|
||||
* 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)",
|
||||
caller, location);
|
||||
return NULL;
|
||||
|
|
@ -253,12 +259,9 @@ validate_uniform_parameters(GLint location, GLsizei count,
|
|||
* no error is generated."
|
||||
*
|
||||
*/
|
||||
if (shProg->UniformRemapTable[location] ==
|
||||
INACTIVE_UNIFORM_EXPLICIT_LOCATION)
|
||||
if (uni == INACTIVE_UNIFORM_EXPLICIT_LOCATION)
|
||||
return NULL;
|
||||
|
||||
struct gl_uniform_storage *const uni = shProg->UniformRemapTable[location];
|
||||
|
||||
/* Even though no location is assigned to a built-in uniform and this
|
||||
* function should already have returned NULL, this test makes it explicit
|
||||
* 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)
|
||||
return;
|
||||
|
||||
if (location >= (int)shProg->NumUniformRemapTable)
|
||||
return;
|
||||
struct range_entry *e =
|
||||
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)
|
||||
return;
|
||||
|
||||
|
|
@ -2019,7 +2022,10 @@ _mesa_uniform_handle(GLint location, GLsizei count, const GLvoid *values,
|
|||
if (location == -1)
|
||||
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)
|
||||
return;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue