diff options
-rw-r--r-- | src/glsl/link_uniform_block_active_visitor.cpp | 39 | ||||
-rw-r--r-- | src/glsl/link_uniform_block_active_visitor.h | 1 | ||||
-rw-r--r-- | src/glsl/opt_dead_code.cpp | 29 |
3 files changed, 65 insertions, 4 deletions
diff --git a/src/glsl/link_uniform_block_active_visitor.cpp b/src/glsl/link_uniform_block_active_visitor.cpp index 854309f9baa..9da6a4bba48 100644 --- a/src/glsl/link_uniform_block_active_visitor.cpp +++ b/src/glsl/link_uniform_block_active_visitor.cpp @@ -73,6 +73,45 @@ process_block(void *mem_ctx, struct hash_table *ht, ir_variable *var) } ir_visitor_status +link_uniform_block_active_visitor::visit(ir_variable *var) +{ + if (!var->is_in_uniform_block()) + return visit_continue; + + const glsl_type *const block_type = var->is_interface_instance() + ? var->type : var->get_interface_type(); + + /* 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 (block_type->interface_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", + var->get_interface_type()->name); + this->success = false; + return visit_stop; + } + + assert(b->num_array_elements == 0); + assert(b->array_elements == NULL); + assert(b->type != NULL); + + return visit_continue; +} + +ir_visitor_status link_uniform_block_active_visitor::visit_enter(ir_dereference_array *ir) { ir_dereference_variable *const d = ir->array->as_dereference_variable(); diff --git a/src/glsl/link_uniform_block_active_visitor.h b/src/glsl/link_uniform_block_active_visitor.h index 64de8268007..e5ea501553c 100644 --- a/src/glsl/link_uniform_block_active_visitor.h +++ b/src/glsl/link_uniform_block_active_visitor.h @@ -51,6 +51,7 @@ public: 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; diff --git a/src/glsl/opt_dead_code.cpp b/src/glsl/opt_dead_code.cpp index 3df01b4137d..f45bf5dfdf8 100644 --- a/src/glsl/opt_dead_code.cpp +++ b/src/glsl/opt_dead_code.cpp @@ -99,10 +99,31 @@ do_dead_code(exec_list *instructions, bool uniform_locations_assigned) * stage. Also, once uniform locations have been assigned, the * declaration cannot be deleted. */ - if (entry->var->data.mode == ir_var_uniform && - (uniform_locations_assigned || - entry->var->constant_value)) - continue; + if (entry->var->data.mode == ir_var_uniform) { + if (uniform_locations_assigned || entry->var->constant_value) + 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 the variable is in a uniform block with one of those + * layouts, do not eliminate it. + */ + if (entry->var->is_in_uniform_block()) { + const glsl_type *const block_type = + entry->var->is_interface_instance() + ? entry->var->type : entry->var->get_interface_type(); + + if (block_type->interface_packing != GLSL_INTERFACE_PACKING_PACKED) + continue; + } + } entry->var->remove(); progress = true; |