void handle_rvalue(ir_rvalue **rvalue);
ir_visitor_status visit_enter(ir_assignment *ir);
- void setup_for_load_or_store(ir_variable *var,
+ void setup_for_load_or_store(void *mem_ctx,
+ ir_variable *var,
ir_rvalue *deref,
ir_rvalue **offset,
unsigned *const_offset,
bool *row_major,
int *matrix_columns,
unsigned packing);
- ir_expression *ubo_load(const struct glsl_type *type,
+ ir_expression *ubo_load(void *mem_ctx, const struct glsl_type *type,
ir_rvalue *offset);
- ir_call *ssbo_load(const struct glsl_type *type,
+ ir_call *ssbo_load(void *mem_ctx, const struct glsl_type *type,
ir_rvalue *offset);
bool check_for_buffer_array_copy(ir_assignment *ir);
bool check_for_buffer_struct_copy(ir_assignment *ir);
void check_for_ssbo_store(ir_assignment *ir);
- void write_to_memory(ir_dereference *deref,
- ir_variable *var,
- ir_variable *write_var,
- unsigned write_mask);
- ir_call *ssbo_store(ir_rvalue *deref, ir_rvalue *offset,
+ void write_to_memory(void *mem_ctx, ir_dereference *deref, ir_variable *var,
+ ir_variable *write_var, unsigned write_mask);
+ ir_call *ssbo_store(void *mem_ctx, ir_rvalue *deref, ir_rvalue *offset,
unsigned write_mask);
enum {
ir_expression *process_ssbo_unsized_array_length(ir_rvalue **,
ir_dereference *,
ir_variable *);
- ir_expression *emit_ssbo_get_buffer_size();
+ ir_expression *emit_ssbo_get_buffer_size(void *mem_ctx);
unsigned calculate_unsized_array_stride(ir_dereference *deref,
unsigned packing);
ir_call *check_for_ssbo_atomic_intrinsic(ir_call *ir);
ir_visitor_status visit_enter(ir_call *ir);
- void *mem_ctx;
struct gl_shader *shader;
struct gl_uniform_buffer_variable *ubo_var;
ir_rvalue *uniform_block;
}
void
-lower_ubo_reference_visitor::setup_for_load_or_store(ir_variable *var,
+lower_ubo_reference_visitor::setup_for_load_or_store(void *mem_ctx,
+ ir_variable *var,
ir_rvalue *deref,
ir_rvalue **offset,
unsigned *const_offset,
assert(this->uniform_block);
- *offset = new(mem_ctx) ir_constant(0u);
- *const_offset = 0;
- *row_major = is_dereferenced_thing_row_major(deref);
- *matrix_columns = 1;
+ *const_offset = ubo_var->Offset;
- /* Calculate the offset to the start of the region of the UBO
- * dereferenced by *rvalue. This may be a variable offset if an
- * array dereference has a variable index.
- */
- while (deref) {
- switch (deref->ir_type) {
- case ir_type_dereference_variable: {
- *const_offset += ubo_var->Offset;
- deref = NULL;
- break;
- }
-
- case ir_type_dereference_array: {
- ir_dereference_array *deref_array = (ir_dereference_array *) deref;
- unsigned array_stride;
- if (deref_array->array->type->is_vector()) {
- /* We get this when storing or loading a component out of a vector
- * with a non-constant index. This happens for v[i] = f where v is
- * a vector (or m[i][j] = f where m is a matrix). If we don't
- * lower that here, it gets turned into v = vector_insert(v, i,
- * f), which loads the entire vector, modifies one component and
- * then write the entire thing back. That breaks if another
- * thread or SIMD channel is modifying the same vector.
- */
- array_stride = 4;
- if (deref_array->array->type->is_double())
- array_stride *= 2;
- } else if (deref_array->array->type->is_matrix() && *row_major) {
- /* When loading a vector out of a row major matrix, the
- * step between the columns (vectors) is the size of a
- * float, while the step between the rows (elements of a
- * vector) is handled below in emit_ubo_loads.
- */
- array_stride = 4;
- if (deref_array->array->type->is_double())
- array_stride *= 2;
- *matrix_columns = deref_array->array->type->matrix_columns;
- } else if (deref_array->type->without_array()->is_interface()) {
- /* We're processing an array dereference of an interface instance
- * array. The thing being dereferenced *must* be a variable
- * dereference because interfaces cannot be embedded in other
- * types. In terms of calculating the offsets for the lowering
- * pass, we don't care about the array index. All elements of an
- * interface instance array will have the same offsets relative to
- * the base of the block that backs them.
- */
- deref = deref_array->array->as_dereference();
- break;
- } else {
- /* Whether or not the field is row-major (because it might be a
- * bvec2 or something) does not affect the array itself. We need
- * to know whether an array element in its entirety is row-major.
- */
- const bool array_row_major =
- is_dereferenced_thing_row_major(deref_array);
-
- /* The array type will give the correct interface packing
- * information
- */
- if (packing == GLSL_INTERFACE_PACKING_STD430) {
- array_stride = deref_array->type->std430_array_stride(array_row_major);
- } else {
- array_stride = deref_array->type->std140_size(array_row_major);
- array_stride = glsl_align(array_stride, 16);
- }
- }
-
- ir_rvalue *array_index = deref_array->array_index;
- if (array_index->type->base_type == GLSL_TYPE_INT)
- array_index = i2u(array_index);
-
- ir_constant *const_index =
- array_index->constant_expression_value(NULL);
- if (const_index) {
- *const_offset += array_stride * const_index->value.u[0];
- } else {
- *offset = add(*offset,
- mul(array_index,
- new(mem_ctx) ir_constant(array_stride)));
- }
- deref = deref_array->array->as_dereference();
- break;
- }
-
- case ir_type_dereference_record: {
- ir_dereference_record *deref_record = (ir_dereference_record *) deref;
- const glsl_type *struct_type = deref_record->record->type;
- unsigned intra_struct_offset = 0;
-
- for (unsigned int i = 0; i < struct_type->length; i++) {
- const glsl_type *type = struct_type->fields.structure[i].type;
-
- ir_dereference_record *field_deref = new(mem_ctx)
- ir_dereference_record(deref_record->record,
- struct_type->fields.structure[i].name);
- const bool field_row_major =
- is_dereferenced_thing_row_major(field_deref);
-
- ralloc_free(field_deref);
-
- unsigned field_align = 0;
-
- if (packing == GLSL_INTERFACE_PACKING_STD430)
- field_align = type->std430_base_alignment(field_row_major);
- else
- field_align = type->std140_base_alignment(field_row_major);
-
- intra_struct_offset = glsl_align(intra_struct_offset, field_align);
-
- if (strcmp(struct_type->fields.structure[i].name,
- deref_record->field) == 0)
- break;
-
- if (packing == GLSL_INTERFACE_PACKING_STD430)
- intra_struct_offset += type->std430_size(field_row_major);
- else
- intra_struct_offset += type->std140_size(field_row_major);
-
- /* If the field just examined was itself a structure, apply rule
- * #9:
- *
- * "The structure may have padding at the end; the base offset
- * of the member following the sub-structure is rounded up to
- * the next multiple of the base alignment of the structure."
- */
- if (type->without_array()->is_record()) {
- intra_struct_offset = glsl_align(intra_struct_offset,
- field_align);
-
- }
- }
-
- *const_offset += intra_struct_offset;
- deref = deref_record->record->as_dereference();
- break;
- }
-
- case ir_type_swizzle: {
- ir_swizzle *deref_swizzle = (ir_swizzle *) deref;
-
- assert(deref_swizzle->mask.num_components == 1);
-
- *const_offset += deref_swizzle->mask.x * sizeof(int);
- deref = deref_swizzle->val->as_dereference();
- break;
- }
-
- default:
- assert(!"not reached");
- deref = NULL;
- break;
- }
- }
+ setup_buffer_access(mem_ctx, var, deref, offset, const_offset, row_major,
+ matrix_columns, packing);
}
void
if (!var || !var->is_in_buffer_block())
return;
- mem_ctx = ralloc_parent(shader->ir);
+ void *mem_ctx = ralloc_parent(shader->ir);
ir_rvalue *offset = NULL;
unsigned const_offset;
/* Compute the offset to the start if the dereference as well as other
* information we need to configure the write
*/
- setup_for_load_or_store(var, deref,
+ setup_for_load_or_store(mem_ctx, var, deref,
&offset, &const_offset,
&row_major, &matrix_columns,
packing);
}
ir_expression *
-lower_ubo_reference_visitor::ubo_load(const glsl_type *type,
+lower_ubo_reference_visitor::ubo_load(void *mem_ctx,
+ const glsl_type *type,
ir_rvalue *offset)
{
ir_rvalue *block_ref = this->uniform_block->clone(mem_ctx, NULL);
}
ir_call *
-lower_ubo_reference_visitor::ssbo_store(ir_rvalue *deref,
+lower_ubo_reference_visitor::ssbo_store(void *mem_ctx,
+ ir_rvalue *deref,
ir_rvalue *offset,
unsigned write_mask)
{
}
ir_call *
-lower_ubo_reference_visitor::ssbo_load(const struct glsl_type *type,
+lower_ubo_reference_visitor::ssbo_load(void *mem_ctx,
+ const struct glsl_type *type,
ir_rvalue *offset)
{
exec_list sig_params;
switch (this->buffer_access_type) {
case ubo_load_access:
base_ir->insert_before(assign(deref->clone(mem_ctx, NULL),
- ubo_load(type, offset),
+ ubo_load(mem_ctx, type, offset),
mask));
break;
case ssbo_load_access: {
- ir_call *load_ssbo = ssbo_load(type, offset);
+ ir_call *load_ssbo = ssbo_load(mem_ctx, type, offset);
base_ir->insert_before(load_ssbo);
ir_rvalue *value = load_ssbo->return_deref->as_rvalue()->clone(mem_ctx, NULL);
ir_assignment *assignment =
}
case ssbo_store_access:
if (channel >= 0) {
- base_ir->insert_after(ssbo_store(swizzle(deref, channel, 1),
+ base_ir->insert_after(ssbo_store(mem_ctx,
+ swizzle(deref, channel, 1),
offset, 1));
} else {
- base_ir->insert_after(ssbo_store(deref, offset, mask));
+ base_ir->insert_after(ssbo_store(mem_ctx, deref, offset, mask));
}
break;
default:
}
void
-lower_ubo_reference_visitor::write_to_memory(ir_dereference *deref,
+lower_ubo_reference_visitor::write_to_memory(void *mem_ctx,
+ ir_dereference *deref,
ir_variable *var,
ir_variable *write_var,
unsigned write_mask)
/* Compute the offset to the start if the dereference as well as other
* information we need to configure the write
*/
- setup_for_load_or_store(var, deref,
+ setup_for_load_or_store(mem_ctx, var, deref,
&offset, &const_offset,
&row_major, &matrix_columns,
packing);
}
ir_expression *
-lower_ubo_reference_visitor::emit_ssbo_get_buffer_size()
+lower_ubo_reference_visitor::emit_ssbo_get_buffer_size(void *mem_ctx)
{
ir_rvalue *block_ref = this->uniform_block->clone(mem_ctx, NULL);
return new(mem_ctx) ir_expression(ir_unop_get_buffer_size,
ir_dereference *deref,
ir_variable *var)
{
- mem_ctx = ralloc_parent(*rvalue);
+ void *mem_ctx = ralloc_parent(*rvalue);
ir_rvalue *base_offset = NULL;
unsigned const_offset;
/* Compute the offset to the start if the dereference as well as other
* information we need to calculate the length.
*/
- setup_for_load_or_store(var, deref,
+ setup_for_load_or_store(mem_ctx, var, deref,
&base_offset, &const_offset,
&row_major, &matrix_columns,
packing);
/* array.length() =
* max((buffer_object_size - offset_of_array) / stride_of_array, 0)
*/
- ir_expression *buffer_size = emit_ssbo_get_buffer_size();
+ ir_expression *buffer_size = emit_ssbo_get_buffer_size(mem_ctx);
ir_expression *offset_of_array = new(mem_ctx)
ir_expression(ir_binop_add, base_offset,
return;
ir_variable *var = ir->lhs->variable_referenced();
- if (!var || !var->is_in_buffer_block())
+ if (!var || !var->is_in_shader_storage_block())
return;
/* We have a write to a buffer variable, so declare a temporary and rewrite
* the assignment so that the temporary is the LHS.
*/
- mem_ctx = ralloc_parent(shader->ir);
+ void *mem_ctx = ralloc_parent(shader->ir);
const glsl_type *type = rvalue->type;
ir_variable *write_var = new(mem_ctx) ir_variable(type,
ir->lhs = new(mem_ctx) ir_dereference_variable(write_var);
/* Now we have to write the value assigned to the temporary back to memory */
- write_to_memory(deref, var, write_var, ir->write_mask);
+ write_to_memory(mem_ctx, deref, var, write_var, ir->write_mask);
progress = true;
}
return false;
assert(lhs_deref->type->length == rhs_deref->type->length);
- mem_ctx = ralloc_parent(shader->ir);
+ void *mem_ctx = ralloc_parent(shader->ir);
for (unsigned i = 0; i < lhs_deref->type->length; i++) {
ir_dereference *lhs_i =
return false;
assert(lhs_deref->type->record_compare(rhs_deref->type));
- mem_ctx = ralloc_parent(shader->ir);
+ void *mem_ctx = ralloc_parent(shader->ir);
for (unsigned i = 0; i < lhs_deref->type->length; i++) {
const char *field_name = lhs_deref->type->fields.structure[i].name;
/* Compute the offset to the start if the dereference and the
* block index
*/
- mem_ctx = ralloc_parent(shader->ir);
+ void *mem_ctx = ralloc_parent(shader->ir);
ir_rvalue *offset = NULL;
unsigned const_offset;
this->buffer_access_type = ssbo_atomic_access;
- setup_for_load_or_store(var, deref,
+ setup_for_load_or_store(mem_ctx, var, deref,
&offset, &const_offset,
&row_major, &matrix_columns,
packing);
sig->is_intrinsic = true;
char func_name[64];
- sprintf(func_name, "%s_internal", ir->callee_name());
+ sprintf(func_name, "%s_ssbo", ir->callee_name());
ir_function *f = new(mem_ctx) ir_function(func_name);
f->add_signature(sig);
ir_call *
lower_ubo_reference_visitor::check_for_ssbo_atomic_intrinsic(ir_call *ir)
{
+ exec_list& params = ir->actual_parameters;
+
+ if (params.length() < 2 || params.length() > 3)
+ return ir;
+
+ ir_rvalue *rvalue =
+ ((ir_instruction *) params.get_head())->as_rvalue();
+ if (!rvalue)
+ return ir;
+
+ ir_variable *var = rvalue->variable_referenced();
+ if (!var || !var->is_in_shader_storage_block())
+ return ir;
+
const char *callee = ir->callee_name();
- if (!strcmp("__intrinsic_ssbo_atomic_add", callee) ||
- !strcmp("__intrinsic_ssbo_atomic_min", callee) ||
- !strcmp("__intrinsic_ssbo_atomic_max", callee) ||
- !strcmp("__intrinsic_ssbo_atomic_and", callee) ||
- !strcmp("__intrinsic_ssbo_atomic_or", callee) ||
- !strcmp("__intrinsic_ssbo_atomic_xor", callee) ||
- !strcmp("__intrinsic_ssbo_atomic_exchange", callee) ||
- !strcmp("__intrinsic_ssbo_atomic_comp_swap", callee)) {
+ if (!strcmp("__intrinsic_atomic_add", callee) ||
+ !strcmp("__intrinsic_atomic_min", callee) ||
+ !strcmp("__intrinsic_atomic_max", callee) ||
+ !strcmp("__intrinsic_atomic_and", callee) ||
+ !strcmp("__intrinsic_atomic_or", callee) ||
+ !strcmp("__intrinsic_atomic_xor", callee) ||
+ !strcmp("__intrinsic_atomic_exchange", callee) ||
+ !strcmp("__intrinsic_atomic_comp_swap", callee)) {
return lower_ssbo_atomic_intrinsic(ir);
}