virtual void visit_field(const glsl_type *type, const char *name, bool row_major) { assert(!type->is_record()); assert(!(type->is_array() && type->fields.array->is_record())); assert(!type->is_interface()); assert(!(type->is_array() && type->fields.array->is_interface())); (void) row_major; /* Count the number of samplers regardless of whether the uniform is * already in the hash table. The hash table prevents adding the same * uniform for multiple shader targets, but in this case we want to * count it for each shader target. */ const unsigned values = values_for_type(type); if (type->contains_sampler()) { this->num_shader_samplers += type->is_array() ? type->array_size() : 1; } else { /* Accumulate the total number of uniform slots used by this shader. * Note that samplers do not count against this limit because they * don't use any storage on current hardware. */ if (!is_ubo_var) this->num_shader_uniform_components += values; } /* If the uniform is already in the map, there's nothing more to do. */ unsigned id; if (this->map->get(id, name)) return; this->map->put(this->num_active_uniforms, name); /* Each leaf uniform occupies one entry in the list of active * uniforms. */ this->num_active_uniforms++; this->num_values += values; }
virtual void visit_field(const glsl_type *type, const char *name, bool row_major) { assert(!type->is_record()); assert(!(type->is_array() && type->fields.array->is_record())); assert(!type->is_interface()); assert(!(type->is_array() && type->fields.array->is_interface())); (void) row_major; unsigned id; bool found = this->map->get(id, name); assert(found); if (!found) return; /* If there is already storage associated with this uniform, it means * that it was set while processing an earlier shader stage. For * example, we may be processing the uniform in the fragment shader, but * the uniform was already processed in the vertex shader. */ if (this->uniforms[id].storage != NULL) { /* If the uniform already has storage set from another shader stage, * mark the samplers used for this shader stage. */ if (type->contains_sampler()) { const unsigned count = MAX2(1, this->uniforms[id].array_elements); const unsigned shadow = (type->is_array()) ? type->fields.array->sampler_shadow : type->sampler_shadow; for (unsigned i = 0; i < count; i++) { const unsigned s = this->uniforms[id].sampler + i; this->shader_samplers_used |= 1U << s; this->shader_shadow_samplers |= shadow << s; } } return; } const glsl_type *base_type; if (type->is_array()) { this->uniforms[id].array_elements = type->length; base_type = type->fields.array; } else { this->uniforms[id].array_elements = 0; base_type = type; } if (base_type->is_sampler()) { this->uniforms[id].sampler = this->next_sampler; /* Increment the sampler by 1 for non-arrays and by the number of * array elements for arrays. */ this->next_sampler += MAX2(1, this->uniforms[id].array_elements); const gl_texture_index target = base_type->sampler_index(); const unsigned shadow = base_type->sampler_shadow; for (unsigned i = this->uniforms[id].sampler ; i < MIN2(this->next_sampler, MAX_SAMPLERS) ; i++) { this->targets[i] = target; this->shader_samplers_used |= 1U << i; this->shader_shadow_samplers |= shadow << i; } } else { this->uniforms[id].sampler = ~0; } this->uniforms[id].name = ralloc_strdup(this->uniforms, name); this->uniforms[id].type = base_type; this->uniforms[id].initialized = 0; this->uniforms[id].num_driver_storage = 0; this->uniforms[id].driver_storage = NULL; this->uniforms[id].storage = this->values; if (this->ubo_block_index != -1) { this->uniforms[id].block_index = this->ubo_block_index; unsigned alignment = type->std140_base_alignment(ubo_row_major); this->ubo_byte_offset = glsl_align(this->ubo_byte_offset, alignment); this->uniforms[id].offset = this->ubo_byte_offset; this->ubo_byte_offset += type->std140_size(ubo_row_major); if (type->is_array()) { this->uniforms[id].array_stride = glsl_align(type->fields.array->std140_size(ubo_row_major), 16); } else { this->uniforms[id].array_stride = 0; } if (type->is_matrix() || (type->is_array() && type->fields.array->is_matrix())) { this->uniforms[id].matrix_stride = 16; this->uniforms[id].row_major = ubo_row_major; } else { this->uniforms[id].matrix_stride = 0; this->uniforms[id].row_major = false; } } else { this->uniforms[id].block_index = -1; this->uniforms[id].offset = -1; this->uniforms[id].array_stride = -1; this->uniforms[id].matrix_stride = -1; this->uniforms[id].row_major = false; } this->values += values_for_type(type); }
virtual void visit_field(const glsl_type *type, const char *name, bool row_major, const glsl_type *record_type, bool last_field) { assert(!type->without_array()->is_record()); assert(!type->without_array()->is_interface()); unsigned id; bool found = this->map->get(id, name); assert(found); if (!found) return; const glsl_type *base_type; if (type->is_array()) { this->uniforms[id].array_elements = type->length; base_type = type->fields.array; } else { this->uniforms[id].array_elements = 0; base_type = type; } /* This assigns uniform indices to sampler and image uniforms. */ handle_samplers(base_type, &this->uniforms[id]); handle_images(base_type, &this->uniforms[id]); /* If there is already storage associated with this uniform, it means * that it was set while processing an earlier shader stage. For * example, we may be processing the uniform in the fragment shader, but * the uniform was already processed in the vertex shader. */ if (this->uniforms[id].storage != NULL) { return; } /* Assign explicit locations. */ if (current_var->data.explicit_location) { /* Set sequential locations for struct fields. */ if (record_type != NULL) { const unsigned entries = MAX2(1, this->uniforms[id].array_elements); this->uniforms[id].remap_location = current_var->data.location + field_counter; field_counter += entries; } else { this->uniforms[id].remap_location = current_var->data.location; } } else { /* Initialize to to indicate that no location is set */ this->uniforms[id].remap_location = UNMAPPED_UNIFORM_LOC; } this->uniforms[id].name = ralloc_strdup(this->uniforms, name); this->uniforms[id].type = base_type; this->uniforms[id].initialized = 0; this->uniforms[id].num_driver_storage = 0; this->uniforms[id].driver_storage = NULL; this->uniforms[id].storage = this->values; this->uniforms[id].atomic_buffer_index = -1; if (this->ubo_block_index != -1) { this->uniforms[id].block_index = this->ubo_block_index; const unsigned alignment = record_type ? record_type->std140_base_alignment(row_major) : type->std140_base_alignment(row_major); this->ubo_byte_offset = glsl_align(this->ubo_byte_offset, alignment); this->uniforms[id].offset = this->ubo_byte_offset; this->ubo_byte_offset += type->std140_size(row_major); if (last_field) this->ubo_byte_offset = glsl_align(this->ubo_byte_offset, 16); if (type->is_array()) { this->uniforms[id].array_stride = glsl_align(type->fields.array->std140_size(row_major), 16); } else { this->uniforms[id].array_stride = 0; } if (type->without_array()->is_matrix()) { this->uniforms[id].matrix_stride = 16; this->uniforms[id].row_major = row_major; } else { this->uniforms[id].matrix_stride = 0; this->uniforms[id].row_major = false; } } else { this->uniforms[id].block_index = -1; this->uniforms[id].offset = -1; this->uniforms[id].array_stride = -1; this->uniforms[id].matrix_stride = -1; this->uniforms[id].row_major = false; } this->values += values_for_type(type); }
virtual void visit_field(const glsl_type *type, const char *name, bool row_major) { assert(!type->is_record()); assert(!(type->is_array() && type->fields.array->is_record())); assert(!type->is_interface()); assert(!(type->is_array() && type->fields.array->is_interface())); (void) row_major; unsigned id; bool found = this->map->get(id, name); assert(found); if (!found) return; const glsl_type *base_type; if (type->is_array()) { this->uniforms[id].array_elements = type->length; base_type = type->fields.array; } else { this->uniforms[id].array_elements = 0; base_type = type; } /* This assigns sampler uniforms to sampler units. */ handle_samplers(base_type, &this->uniforms[id]); /* If there is already storage associated with this uniform, it means * that it was set while processing an earlier shader stage. For * example, we may be processing the uniform in the fragment shader, but * the uniform was already processed in the vertex shader. */ if (this->uniforms[id].storage != NULL) { return; } this->uniforms[id].name = ralloc_strdup(this->uniforms, name); this->uniforms[id].type = base_type; this->uniforms[id].initialized = 0; this->uniforms[id].num_driver_storage = 0; this->uniforms[id].driver_storage = NULL; this->uniforms[id].storage = this->values; if (this->ubo_block_index != -1) { this->uniforms[id].block_index = this->ubo_block_index; unsigned alignment = type->std140_base_alignment(ubo_row_major); this->ubo_byte_offset = glsl_align(this->ubo_byte_offset, alignment); this->uniforms[id].offset = this->ubo_byte_offset; this->ubo_byte_offset += type->std140_size(ubo_row_major); if (type->is_array()) { this->uniforms[id].array_stride = glsl_align(type->fields.array->std140_size(ubo_row_major), 16); } else { this->uniforms[id].array_stride = 0; } if (type->is_matrix() || (type->is_array() && type->fields.array->is_matrix())) { this->uniforms[id].matrix_stride = 16; this->uniforms[id].row_major = ubo_row_major; } else { this->uniforms[id].matrix_stride = 0; this->uniforms[id].row_major = false; } } else { this->uniforms[id].block_index = -1; this->uniforms[id].offset = -1; this->uniforms[id].array_stride = -1; this->uniforms[id].matrix_stride = -1; this->uniforms[id].row_major = false; } this->values += values_for_type(type); }
virtual void visit_field(const glsl_type *type, const char *name, bool row_major, const glsl_type *record_type, bool /* last_field */) { assert(!type->without_array()->is_record()); assert(!type->without_array()->is_interface()); unsigned id; bool found = this->map->get(id, name); assert(found); if (!found) return; const glsl_type *base_type; if (type->is_array()) { this->uniforms[id].array_elements = type->length; base_type = type->fields.array; } else { this->uniforms[id].array_elements = 0; base_type = type; } /* 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 * an earlier shader stage. For example, we may be processing the * uniform in the fragment shader, but the uniform was already processed * in the vertex shader. */ if (this->uniforms[id].storage != NULL || this->uniforms[id].builtin) { return; } /* Assign explicit locations. */ if (current_var->data.explicit_location) { /* Set sequential locations for struct fields. */ if (record_type != NULL) { const unsigned entries = MAX2(1, this->uniforms[id].array_elements); this->uniforms[id].remap_location = current_var->data.location + field_counter; field_counter += entries; } else { this->uniforms[id].remap_location = current_var->data.location; } } else { /* Initialize to to indicate that no location is set */ this->uniforms[id].remap_location = UNMAPPED_UNIFORM_LOC; } this->uniforms[id].name = ralloc_strdup(this->uniforms, name); this->uniforms[id].type = base_type; this->uniforms[id].initialized = 0; this->uniforms[id].num_driver_storage = 0; this->uniforms[id].driver_storage = NULL; this->uniforms[id].atomic_buffer_index = -1; this->uniforms[id].hidden = current_var->data.how_declared == ir_var_hidden; this->uniforms[id].builtin = is_gl_identifier(name); /* Do not assign storage if the uniform is builtin */ if (!this->uniforms[id].builtin) this->uniforms[id].storage = this->values; if (this->ubo_block_index != -1) { this->uniforms[id].block_index = this->ubo_block_index; const unsigned alignment = type->std140_base_alignment(row_major); this->ubo_byte_offset = glsl_align(this->ubo_byte_offset, alignment); this->uniforms[id].offset = this->ubo_byte_offset; this->ubo_byte_offset += type->std140_size(row_major); if (type->is_array()) { this->uniforms[id].array_stride = glsl_align(type->fields.array->std140_size(row_major), 16); } else { this->uniforms[id].array_stride = 0; } if (type->without_array()->is_matrix()) { const glsl_type *matrix = type->without_array(); const unsigned N = matrix->base_type == GLSL_TYPE_DOUBLE ? 8 : 4; const unsigned items = row_major ? matrix->matrix_columns : matrix->vector_elements; assert(items <= 4); this->uniforms[id].matrix_stride = glsl_align(items * N, 16); this->uniforms[id].row_major = row_major; } else { this->uniforms[id].matrix_stride = 0; this->uniforms[id].row_major = false; } } else { this->uniforms[id].block_index = -1; this->uniforms[id].offset = -1; this->uniforms[id].array_stride = -1; this->uniforms[id].matrix_stride = -1; this->uniforms[id].row_major = false; } this->values += values_for_type(type); }