nir: Implement __intrinsic_store_ssbo

v2 (Connor):
 - Make the STORE() macro take arguments for the extra sources (and their
   size) and any extra indices required.

Reviewed-by: Kristian Høgsberg <krh@bitplanet.net>
This commit is contained in:
Iago Toral Quiroga 2015-07-09 10:26:42 +02:00 committed by Samuel Iglesias Gonsalvez
parent f17c6b9066
commit 9bb7d9ecf8
2 changed files with 48 additions and 8 deletions

View File

@ -649,6 +649,8 @@ nir_visitor::visit(ir_call *ir)
op = nir_intrinsic_image_size;
} else if (strcmp(ir->callee_name(), "__intrinsic_image_samples") == 0) {
op = nir_intrinsic_image_samples;
} else if (strcmp(ir->callee_name(), "__intrinsic_store_ssbo") == 0) {
op = nir_intrinsic_store_ssbo;
} else {
unreachable("not reached");
}
@ -747,6 +749,40 @@ nir_visitor::visit(ir_call *ir)
}
case nir_intrinsic_memory_barrier:
break;
case nir_intrinsic_store_ssbo: {
exec_node *param = ir->actual_parameters.get_head();
ir_rvalue *block = ((ir_instruction *)param)->as_rvalue();
param = param->get_next();
ir_rvalue *offset = ((ir_instruction *)param)->as_rvalue();
param = param->get_next();
ir_rvalue *val = ((ir_instruction *)param)->as_rvalue();
param = param->get_next();
ir_constant *write_mask = ((ir_instruction *)param)->as_constant();
assert(write_mask);
/* Check if we need the indirect version */
ir_constant *const_offset = offset->as_constant();
if (!const_offset) {
op = nir_intrinsic_store_ssbo_indirect;
ralloc_free(instr);
instr = nir_intrinsic_instr_create(shader, op);
instr->src[2] = evaluate_rvalue(offset);
instr->const_index[0] = 0;
} else {
instr->const_index[0] = const_offset->value.u[0];
}
instr->const_index[1] = write_mask->value.u[0];
instr->src[0] = evaluate_rvalue(val);
instr->num_components = val->type->vector_elements;
instr->src[1] = evaluate_rvalue(block);
break;
}
default:
unreachable("not reached");
}

View File

@ -205,15 +205,19 @@ LOAD(input, 0, 1, NIR_INTRINSIC_CAN_ELIMINATE | NIR_INTRINSIC_CAN_REORDER)
/*
* Stores work the same way as loads, except now the first register input is
* the value or array to store and the optional second input is the indirect
* offset.
* offset. SSBO stores are similar, but they accept an extra source for the
* block index and an extra index with the writemask to use.
*/
#define STORE(name, num_indices, flags) \
INTRINSIC(store_##name, 1, ARR(0), false, 0, 0, num_indices, flags) \
INTRINSIC(store_##name##_indirect, 2, ARR(0, 1), false, 0, 0, \
num_indices, flags) \
#define STORE(name, extra_srcs, extra_srcs_size, extra_indices, flags) \
INTRINSIC(store_##name, 1 + extra_srcs, \
ARR(0, extra_srcs_size, extra_srcs_size, extra_srcs_size), \
false, 0, 0, 1 + extra_indices, flags) \
INTRINSIC(store_##name##_indirect, 2 + extra_srcs, \
ARR(0, 1, extra_srcs_size, extra_srcs_size), \
false, 0, 0, 1 + extra_indices, flags)
STORE(output, 1, 0)
/* STORE(ssbo, 2, 0) */
STORE(output, 0, 0, 0, 0)
STORE(ssbo, 1, 1, 1, 0)
LAST_INTRINSIC(store_output_indirect)
LAST_INTRINSIC(store_ssbo_indirect)