nir: Convert lower_io to deref instructions

This deletes support for _var intrinsics and legacy deref chains in
favor of deref instructions.  The internals are also reworked a bit to
use deref instructions directly.

Acked-by: Rob Clark <robdclark@gmail.com>
Acked-by: Bas Nieuwenhuizen <bas@basnieuwenhuizen.nl>
Acked-by: Dave Airlie <airlied@redhat.com>
Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
This commit is contained in:
Jason Ekstrand
2018-03-26 18:01:12 -07:00
parent 0d03c63e91
commit 47ffb893e6

View File

@@ -33,6 +33,7 @@
#include "nir.h" #include "nir.h"
#include "nir_builder.h" #include "nir_builder.h"
#include "nir_deref.h"
struct lower_io_state { struct lower_io_state {
void *dead_ctx; void *dead_ctx;
@@ -86,35 +87,35 @@ nir_is_per_vertex_io(const nir_variable *var, gl_shader_stage stage)
} }
static nir_ssa_def * static nir_ssa_def *
get_io_offset(nir_builder *b, nir_deref_var *deref, get_io_offset(nir_builder *b, nir_deref_instr *deref,
nir_ssa_def **vertex_index, nir_ssa_def **vertex_index,
int (*type_size)(const struct glsl_type *), int (*type_size)(const struct glsl_type *),
unsigned *component) unsigned *component)
{ {
nir_deref *tail = &deref->deref; nir_deref_path path;
nir_deref_path_init(&path, deref, NULL);
assert(path.path[0]->deref_type == nir_deref_type_var);
nir_deref_instr **p = &path.path[1];
/* For per-vertex input arrays (i.e. geometry shader inputs), keep the /* For per-vertex input arrays (i.e. geometry shader inputs), keep the
* outermost array index separate. Process the rest normally. * outermost array index separate. Process the rest normally.
*/ */
if (vertex_index != NULL) { if (vertex_index != NULL) {
tail = tail->child; assert((*p)->deref_type == nir_deref_type_array);
nir_deref_array *deref_array = nir_deref_as_array(tail); *vertex_index = nir_ssa_for_src(b, (*p)->arr.index, 1);
p++;
nir_ssa_def *vtx = nir_imm_int(b, deref_array->base_offset);
if (deref_array->deref_array_type == nir_deref_array_type_indirect) {
vtx = nir_iadd(b, vtx, nir_ssa_for_src(b, deref_array->indirect, 1));
}
*vertex_index = vtx;
} }
if (deref->var->data.compact) { if (path.path[0]->var->data.compact) {
assert(tail->child->deref_type == nir_deref_type_array); assert((*p)->deref_type == nir_deref_type_array);
assert(glsl_type_is_scalar(glsl_without_array(deref->var->type))); assert(glsl_type_is_scalar((*p)->type));
nir_deref_array *deref_array = nir_deref_as_array(tail->child);
/* We always lower indirect dereferences for "compact" array vars. */
assert(deref_array->deref_array_type == nir_deref_array_type_direct);
const unsigned total_offset = *component + deref_array->base_offset; /* We always lower indirect dereferences for "compact" array vars. */
nir_const_value *const_index = nir_src_as_const_value((*p)->arr.index);
assert(const_index);
const unsigned total_offset = *component + const_index->u32[0];
const unsigned slot_offset = total_offset / 4; const unsigned slot_offset = total_offset / 4;
*component = total_offset % 4; *component = total_offset % 4;
return nir_imm_int(b, type_size(glsl_vec4_type()) * slot_offset); return nir_imm_int(b, type_size(glsl_vec4_type()) * slot_offset);
@@ -123,35 +124,31 @@ get_io_offset(nir_builder *b, nir_deref_var *deref,
/* Just emit code and let constant-folding go to town */ /* Just emit code and let constant-folding go to town */
nir_ssa_def *offset = nir_imm_int(b, 0); nir_ssa_def *offset = nir_imm_int(b, 0);
while (tail->child != NULL) { for (; *p; p++) {
const struct glsl_type *parent_type = tail->type; if ((*p)->deref_type == nir_deref_type_array) {
tail = tail->child; unsigned size = type_size((*p)->type);
if (tail->deref_type == nir_deref_type_array) { nir_ssa_def *mul =
nir_deref_array *deref_array = nir_deref_as_array(tail); nir_imul(b, nir_imm_int(b, size),
unsigned size = type_size(tail->type); nir_ssa_for_src(b, (*p)->arr.index, 1));
offset = nir_iadd(b, offset, offset = nir_iadd(b, offset, mul);
nir_imm_int(b, size * deref_array->base_offset)); } else if ((*p)->deref_type == nir_deref_type_struct) {
/* p starts at path[1], so this is safe */
if (deref_array->deref_array_type == nir_deref_array_type_indirect) { nir_deref_instr *parent = *(p - 1);
nir_ssa_def *mul =
nir_imul(b, nir_imm_int(b, size),
nir_ssa_for_src(b, deref_array->indirect, 1));
offset = nir_iadd(b, offset, mul);
}
} else if (tail->deref_type == nir_deref_type_struct) {
nir_deref_struct *deref_struct = nir_deref_as_struct(tail);
unsigned field_offset = 0; unsigned field_offset = 0;
for (unsigned i = 0; i < deref_struct->index; i++) { for (unsigned i = 0; i < (*p)->strct.index; i++) {
field_offset += type_size(glsl_get_struct_field(parent_type, i)); field_offset += type_size(glsl_get_struct_field(parent->type, i));
} }
offset = nir_iadd(b, offset, nir_imm_int(b, field_offset)); offset = nir_iadd(b, offset, nir_imm_int(b, field_offset));
} else {
unreachable("Unsupported deref type");
} }
} }
nir_deref_path_finish(&path);
return offset; return offset;
} }
@@ -247,10 +244,7 @@ lower_store(nir_intrinsic_instr *intrin, struct lower_io_state *state,
nir_intrinsic_instr_create(state->builder.shader, op); nir_intrinsic_instr_create(state->builder.shader, op);
store->num_components = intrin->num_components; store->num_components = intrin->num_components;
if (intrin->intrinsic == nir_intrinsic_store_var) nir_src_copy(&store->src[0], &intrin->src[1], store);
nir_src_copy(&store->src[0], &intrin->src[0], store);
else
nir_src_copy(&store->src[0], &intrin->src[1], store);
nir_intrinsic_set_base(store, var->data.driver_location); nir_intrinsic_set_base(store, var->data.driver_location);
@@ -318,17 +312,14 @@ lower_interpolate_at(nir_intrinsic_instr *intrin, struct lower_io_state *state,
nir_intrinsic_op bary_op; nir_intrinsic_op bary_op;
switch (intrin->intrinsic) { switch (intrin->intrinsic) {
case nir_intrinsic_interp_var_at_centroid:
case nir_intrinsic_interp_deref_at_centroid: case nir_intrinsic_interp_deref_at_centroid:
bary_op = (state->options & nir_lower_io_force_sample_interpolation) ? bary_op = (state->options & nir_lower_io_force_sample_interpolation) ?
nir_intrinsic_load_barycentric_sample : nir_intrinsic_load_barycentric_sample :
nir_intrinsic_load_barycentric_centroid; nir_intrinsic_load_barycentric_centroid;
break; break;
case nir_intrinsic_interp_var_at_sample:
case nir_intrinsic_interp_deref_at_sample: case nir_intrinsic_interp_deref_at_sample:
bary_op = nir_intrinsic_load_barycentric_at_sample; bary_op = nir_intrinsic_load_barycentric_at_sample;
break; break;
case nir_intrinsic_interp_var_at_offset:
case nir_intrinsic_interp_deref_at_offset: case nir_intrinsic_interp_deref_at_offset:
bary_op = nir_intrinsic_load_barycentric_at_offset; bary_op = nir_intrinsic_load_barycentric_at_offset;
break; break;
@@ -342,10 +333,6 @@ lower_interpolate_at(nir_intrinsic_instr *intrin, struct lower_io_state *state,
nir_ssa_dest_init(&bary_setup->instr, &bary_setup->dest, 2, 32, NULL); nir_ssa_dest_init(&bary_setup->instr, &bary_setup->dest, 2, 32, NULL);
nir_intrinsic_set_interp_mode(bary_setup, var->data.interpolation); nir_intrinsic_set_interp_mode(bary_setup, var->data.interpolation);
if (intrin->intrinsic == nir_intrinsic_interp_var_at_sample ||
intrin->intrinsic == nir_intrinsic_interp_var_at_offset)
nir_src_copy(&bary_setup->src[0], &intrin->src[0], bary_setup);
if (intrin->intrinsic == nir_intrinsic_interp_deref_at_sample || if (intrin->intrinsic == nir_intrinsic_interp_deref_at_sample ||
intrin->intrinsic == nir_intrinsic_interp_deref_at_offset) intrin->intrinsic == nir_intrinsic_interp_deref_at_offset)
nir_src_copy(&bary_setup->src[0], &intrin->src[1], bary_setup); nir_src_copy(&bary_setup->src[0], &intrin->src[1], bary_setup);
@@ -381,9 +368,7 @@ nir_lower_io_block(nir_block *block,
nir_intrinsic_instr *intrin = nir_instr_as_intrinsic(instr); nir_intrinsic_instr *intrin = nir_instr_as_intrinsic(instr);
switch (intrin->intrinsic) { switch (intrin->intrinsic) {
case nir_intrinsic_load_var:
case nir_intrinsic_load_deref: case nir_intrinsic_load_deref:
case nir_intrinsic_store_var:
case nir_intrinsic_store_deref: case nir_intrinsic_store_deref:
case nir_intrinsic_deref_atomic_add: case nir_intrinsic_deref_atomic_add:
case nir_intrinsic_deref_atomic_imin: case nir_intrinsic_deref_atomic_imin:
@@ -397,9 +382,6 @@ nir_lower_io_block(nir_block *block,
case nir_intrinsic_deref_atomic_comp_swap: case nir_intrinsic_deref_atomic_comp_swap:
/* We can lower the io for this nir instrinsic */ /* We can lower the io for this nir instrinsic */
break; break;
case nir_intrinsic_interp_var_at_centroid:
case nir_intrinsic_interp_var_at_sample:
case nir_intrinsic_interp_var_at_offset:
case nir_intrinsic_interp_deref_at_centroid: case nir_intrinsic_interp_deref_at_centroid:
case nir_intrinsic_interp_deref_at_sample: case nir_intrinsic_interp_deref_at_sample:
case nir_intrinsic_interp_deref_at_offset: case nir_intrinsic_interp_deref_at_offset:
@@ -411,17 +393,9 @@ nir_lower_io_block(nir_block *block,
continue; continue;
} }
nir_deref_var *deref; nir_deref_instr *deref = nir_src_as_deref(intrin->src[0]);
nir_deref_instr *deref_instr = NULL;
if (nir_intrinsic_infos[intrin->intrinsic].num_variables > 0) {
assert(nir_intrinsic_infos[intrin->intrinsic].num_variables == 1);
deref = intrin->variables[0];
} else {
deref_instr = nir_src_as_deref(intrin->src[0]);
deref = nir_deref_instr_to_deref(deref_instr, state->dead_ctx);
}
nir_variable *var = deref->var; nir_variable *var = nir_deref_instr_get_variable(deref);
nir_variable_mode mode = var->data.mode; nir_variable_mode mode = var->data.mode;
if ((state->modes & mode) == 0) if ((state->modes & mode) == 0)
@@ -447,13 +421,11 @@ nir_lower_io_block(nir_block *block,
nir_intrinsic_instr *replacement; nir_intrinsic_instr *replacement;
switch (intrin->intrinsic) { switch (intrin->intrinsic) {
case nir_intrinsic_load_var:
case nir_intrinsic_load_deref: case nir_intrinsic_load_deref:
replacement = lower_load(intrin, state, vertex_index, var, offset, replacement = lower_load(intrin, state, vertex_index, var, offset,
component_offset); component_offset);
break; break;
case nir_intrinsic_store_var:
case nir_intrinsic_store_deref: case nir_intrinsic_store_deref:
replacement = lower_store(intrin, state, vertex_index, var, offset, replacement = lower_store(intrin, state, vertex_index, var, offset,
component_offset); component_offset);
@@ -473,9 +445,6 @@ nir_lower_io_block(nir_block *block,
replacement = lower_atomic(intrin, state, var, offset); replacement = lower_atomic(intrin, state, var, offset);
break; break;
case nir_intrinsic_interp_var_at_centroid:
case nir_intrinsic_interp_var_at_sample:
case nir_intrinsic_interp_var_at_offset:
case nir_intrinsic_interp_deref_at_centroid: case nir_intrinsic_interp_deref_at_centroid:
case nir_intrinsic_interp_deref_at_sample: case nir_intrinsic_interp_deref_at_sample:
case nir_intrinsic_interp_deref_at_offset: case nir_intrinsic_interp_deref_at_offset:
@@ -541,7 +510,7 @@ nir_lower_io(nir_shader *shader, nir_variable_mode modes,
{ {
bool progress = false; bool progress = false;
nir_assert_unlowered_derefs(shader, nir_lower_atomic_derefs); nir_assert_unlowered_derefs(shader, nir_lower_load_store_derefs | nir_lower_interp_derefs | nir_lower_atomic_derefs);
nir_foreach_function(function, shader) { nir_foreach_function(function, shader) {
if (function->impl) { if (function->impl) {