summaryrefslogtreecommitdiffstats
path: root/src/glsl/link_uniforms.cpp
diff options
context:
space:
mode:
authorDave Airlie <[email protected]>2015-04-20 10:27:36 +1000
committerDave Airlie <[email protected]>2015-07-23 17:25:43 +1000
commit60266863d80bb2af94fa5c189ccd23ee20607ea9 (patch)
tree9b7a90ddee9f98523508d95a201463f61ddb3126 /src/glsl/link_uniforms.cpp
parent44ea8b9b8edc5f59da546683fe64129a1c1be449 (diff)
glsl: add uniform and program resource support (v2)
This adds linker support for subroutine uniforms, they have some subtle differences from real uniforms, we also hide them and they are given internal uniform names. This also adds the subroutine locations and subroutine uniforms to the program resource tracking for later use. v1.1: drop is_subroutine_def v2: handle explicit location properly, ARB_explicit_location has a lot of language for subroutine shaders. Calculate a link time the number of compatible subroutines for a uniform, to make program resource easier later. Acked-by: Kenneth Graunke <[email protected]> Signed-off-by: Dave Airlie <[email protected]>
Diffstat (limited to 'src/glsl/link_uniforms.cpp')
-rw-r--r--src/glsl/link_uniforms.cpp103
1 files changed, 99 insertions, 4 deletions
diff --git a/src/glsl/link_uniforms.cpp b/src/glsl/link_uniforms.cpp
index e786ddcaa90..254086dc050 100644
--- a/src/glsl/link_uniforms.cpp
+++ b/src/glsl/link_uniforms.cpp
@@ -47,9 +47,10 @@
static unsigned
values_for_type(const glsl_type *type)
{
- if (type->is_sampler()) {
+ if (type->is_sampler() || type->is_subroutine()) {
return 1;
- } else if (type->is_array() && type->fields.array->is_sampler()) {
+ } else if (type->is_array() && (type->fields.array->is_sampler() ||
+ type->fields.array->is_subroutine())) {
return type->array_size();
} else {
return type->component_slots();
@@ -284,6 +285,7 @@ public:
count_uniform_size(struct string_to_uint_map *map)
: num_active_uniforms(0), num_values(0), num_shader_samplers(0),
num_shader_images(0), num_shader_uniform_components(0),
+ num_shader_subroutines(0),
is_ubo_var(false), map(map)
{
/* empty */
@@ -294,6 +296,7 @@ public:
this->num_shader_samplers = 0;
this->num_shader_images = 0;
this->num_shader_uniform_components = 0;
+ this->num_shader_subroutines = 0;
}
void process(ir_variable *var)
@@ -331,6 +334,11 @@ public:
*/
unsigned num_shader_uniform_components;
+ /**
+ * Number of subroutine uniforms used
+ */
+ unsigned num_shader_subroutines;
+
bool is_ubo_var;
private:
@@ -348,7 +356,9 @@ private:
* count it for each shader target.
*/
const unsigned values = values_for_type(type);
- if (type->contains_sampler()) {
+ if (type->contains_subroutine()) {
+ this->num_shader_subroutines += values;
+ } else if (type->contains_sampler()) {
this->num_shader_samplers += values;
} else if (type->contains_image()) {
this->num_shader_images += values;
@@ -421,6 +431,7 @@ public:
this->shader_shadow_samplers = 0;
this->next_sampler = 0;
this->next_image = 0;
+ this->next_subroutine = 0;
memset(this->targets, 0, sizeof(this->targets));
}
@@ -535,6 +546,24 @@ private:
}
}
+ void handle_subroutines(const glsl_type *base_type,
+ struct gl_uniform_storage *uniform)
+ {
+ if (base_type->is_subroutine()) {
+ uniform->subroutine[shader_type].index = this->next_subroutine;
+ uniform->subroutine[shader_type].active = true;
+
+ /* Increment the subroutine index by 1 for non-arrays and by the
+ * number of array elements for arrays.
+ */
+ this->next_subroutine += MAX2(1, uniform->array_elements);
+
+ } else {
+ uniform->subroutine[shader_type].index = ~0;
+ uniform->subroutine[shader_type].active = false;
+ }
+ }
+
virtual void visit_field(const glsl_type *type, const char *name,
bool row_major)
{
@@ -588,6 +617,7 @@ private:
/* This assigns uniform indices to sampler and image uniforms. */
handle_samplers(base_type, &this->uniforms[id]);
handle_images(base_type, &this->uniforms[id]);
+ handle_subroutines(base_type, &this->uniforms[id]);
/* If there is already storage associated with this uniform or if the
* uniform is set as builtin, it means that it was set while processing
@@ -672,6 +702,7 @@ private:
struct gl_uniform_storage *uniforms;
unsigned next_sampler;
unsigned next_image;
+ unsigned next_subroutine;
public:
union gl_constant_value *values;
@@ -954,8 +985,8 @@ link_assign_uniform_locations(struct gl_shader_program *prog,
sh->num_samplers = uniform_size.num_shader_samplers;
sh->NumImages = uniform_size.num_shader_images;
sh->num_uniform_components = uniform_size.num_shader_uniform_components;
-
sh->num_combined_uniform_components = sh->num_uniform_components;
+
for (unsigned i = 0; i < sh->NumUniformBlocks; i++) {
sh->num_combined_uniform_components +=
sh->UniformBlocks[i].UniformBufferSize / 4;
@@ -1008,6 +1039,9 @@ link_assign_uniform_locations(struct gl_shader_program *prog,
/* Reserve all the explicit locations of the active uniforms. */
for (unsigned i = 0; i < num_uniforms; i++) {
+ if (uniforms[i].type->is_subroutine())
+ continue;
+
if (uniforms[i].remap_location != UNMAPPED_UNIFORM_LOC) {
/* How many new entries for this uniform? */
const unsigned entries = MAX2(1, uniforms[i].array_elements);
@@ -1025,6 +1059,8 @@ link_assign_uniform_locations(struct gl_shader_program *prog,
/* Reserve locations for rest of the uniforms. */
for (unsigned i = 0; i < num_uniforms; i++) {
+ if (uniforms[i].type->is_subroutine())
+ continue;
/* Built-in uniforms should not get any location. */
if (uniforms[i].builtin)
continue;
@@ -1053,6 +1089,65 @@ link_assign_uniform_locations(struct gl_shader_program *prog,
prog->NumUniformRemapTable += entries;
}
+ /* Reserve all the explicit locations of the active subroutine uniforms. */
+ for (unsigned i = 0; i < num_uniforms; i++) {
+ if (!uniforms[i].type->is_subroutine())
+ continue;
+
+ if (uniforms[i].remap_location == UNMAPPED_UNIFORM_LOC)
+ continue;
+
+ for (unsigned j = 0; j < MESA_SHADER_STAGES; j++) {
+ struct gl_shader *sh = prog->_LinkedShaders[j];
+ if (!sh)
+ continue;
+
+ if (!uniforms[i].subroutine[j].active)
+ continue;
+
+ /* How many new entries for this uniform? */
+ const unsigned entries = MAX2(1, uniforms[i].array_elements);
+
+ /* Set remap table entries point to correct gl_uniform_storage. */
+ for (unsigned k = 0; k < entries; k++) {
+ unsigned element_loc = uniforms[i].remap_location + k;
+ assert(sh->SubroutineUniformRemapTable[element_loc] ==
+ INACTIVE_UNIFORM_EXPLICIT_LOCATION);
+ sh->SubroutineUniformRemapTable[element_loc] = &uniforms[i];
+ }
+ }
+ }
+
+ /* reserve subroutine locations */
+ for (unsigned i = 0; i < num_uniforms; i++) {
+
+ if (!uniforms[i].type->is_subroutine())
+ continue;
+ const unsigned entries = MAX2(1, uniforms[i].array_elements);
+
+ if (uniforms[i].remap_location != UNMAPPED_UNIFORM_LOC)
+ continue;
+ for (unsigned j = 0; j < MESA_SHADER_STAGES; j++) {
+ struct gl_shader *sh = prog->_LinkedShaders[j];
+ if (!sh)
+ continue;
+
+ if (!uniforms[i].subroutine[j].active)
+ continue;
+
+ sh->SubroutineUniformRemapTable =
+ reralloc(sh,
+ sh->SubroutineUniformRemapTable,
+ gl_uniform_storage *,
+ sh->NumSubroutineUniformRemapTable + entries);
+
+ for (unsigned k = 0; k < entries; k++)
+ sh->SubroutineUniformRemapTable[sh->NumSubroutineUniformRemapTable + k] = &uniforms[i];
+ uniforms[i].remap_location = sh->NumSubroutineUniformRemapTable;
+ sh->NumSubroutineUniformRemapTable += entries;
+ }
+ }
+
#ifndef NDEBUG
for (unsigned i = 0; i < num_uniforms; i++) {
assert(uniforms[i].storage != NULL || uniforms[i].builtin);