diff options
author | Dave Airlie <[email protected]> | 2015-04-20 10:27:36 +1000 |
---|---|---|
committer | Dave Airlie <[email protected]> | 2015-07-23 17:25:43 +1000 |
commit | 60266863d80bb2af94fa5c189ccd23ee20607ea9 (patch) | |
tree | 9b7a90ddee9f98523508d95a201463f61ddb3126 /src/glsl/link_uniforms.cpp | |
parent | 44ea8b9b8edc5f59da546683fe64129a1c1be449 (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.cpp | 103 |
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); |