anv/pipeline: Convert apply_pipeline_layout to deref instructions

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-22 23:25:07 -07:00
parent 43bb707fa4
commit 032b845edf
2 changed files with 78 additions and 74 deletions

View File

@@ -53,6 +53,24 @@ add_var_binding(struct apply_pipeline_layout_state *state, nir_variable *var)
add_binding(state, var->data.descriptor_set, var->data.binding);
}
static void
add_deref_src_binding(struct apply_pipeline_layout_state *state, nir_src src)
{
nir_deref_instr *deref = nir_src_as_deref(src);
add_var_binding(state, nir_deref_instr_get_variable(deref));
}
static void
add_tex_src_binding(struct apply_pipeline_layout_state *state,
nir_tex_instr *tex, nir_tex_src_type deref_src_type)
{
int deref_src_idx = nir_tex_instr_src_index(tex, deref_src_type);
if (deref_src_idx < 0)
return;
add_deref_src_binding(state, tex->src[deref_src_idx].src);
}
static void
get_used_bindings_block(nir_block *block,
struct apply_pipeline_layout_state *state)
@@ -67,19 +85,19 @@ get_used_bindings_block(nir_block *block,
nir_intrinsic_binding(intrin));
break;
case nir_intrinsic_image_var_load:
case nir_intrinsic_image_var_store:
case nir_intrinsic_image_var_atomic_add:
case nir_intrinsic_image_var_atomic_min:
case nir_intrinsic_image_var_atomic_max:
case nir_intrinsic_image_var_atomic_and:
case nir_intrinsic_image_var_atomic_or:
case nir_intrinsic_image_var_atomic_xor:
case nir_intrinsic_image_var_atomic_exchange:
case nir_intrinsic_image_var_atomic_comp_swap:
case nir_intrinsic_image_var_size:
case nir_intrinsic_image_var_samples:
add_var_binding(state, intrin->variables[0]->var);
case nir_intrinsic_image_deref_load:
case nir_intrinsic_image_deref_store:
case nir_intrinsic_image_deref_atomic_add:
case nir_intrinsic_image_deref_atomic_min:
case nir_intrinsic_image_deref_atomic_max:
case nir_intrinsic_image_deref_atomic_and:
case nir_intrinsic_image_deref_atomic_or:
case nir_intrinsic_image_deref_atomic_xor:
case nir_intrinsic_image_deref_atomic_exchange:
case nir_intrinsic_image_deref_atomic_comp_swap:
case nir_intrinsic_image_deref_size:
case nir_intrinsic_image_deref_samples:
add_deref_src_binding(state, intrin->src[0]);
break;
default:
@@ -89,10 +107,8 @@ get_used_bindings_block(nir_block *block,
}
case nir_instr_type_tex: {
nir_tex_instr *tex = nir_instr_as_tex(instr);
assert(tex->texture);
add_var_binding(state, tex->texture->var);
if (tex->sampler)
add_var_binding(state, tex->sampler->var);
add_tex_src_binding(state, tex, nir_tex_src_texture_deref);
add_tex_src_binding(state, tex, nir_tex_src_sampler_deref);
break;
}
default:
@@ -157,18 +173,42 @@ lower_res_reindex_intrinsic(nir_intrinsic_instr *intrin,
}
static void
lower_tex_deref(nir_tex_instr *tex, nir_deref_var *deref,
unsigned *const_index, unsigned array_size,
nir_tex_src_type src_type,
lower_tex_deref(nir_tex_instr *tex, nir_tex_src_type deref_src_type,
unsigned *base_index,
struct apply_pipeline_layout_state *state)
{
int deref_src_idx = nir_tex_instr_src_index(tex, deref_src_type);
if (deref_src_idx < 0)
return;
nir_deref_instr *deref = nir_src_as_deref(tex->src[deref_src_idx].src);
nir_variable *var = nir_deref_instr_get_variable(deref);
unsigned set = var->data.descriptor_set;
unsigned binding = var->data.binding;
unsigned array_size =
state->layout->set[set].layout->binding[binding].array_size;
nir_tex_src_type offset_src_type;
if (deref_src_type == nir_tex_src_texture_deref) {
offset_src_type = nir_tex_src_texture_offset;
*base_index = state->set[set].surface_offsets[binding];
} else {
assert(deref_src_type == nir_tex_src_sampler_deref);
offset_src_type = nir_tex_src_sampler_offset;
*base_index = state->set[set].sampler_offsets[binding];
}
nir_ssa_def *index = NULL;
if (deref->deref_type != nir_deref_type_var) {
assert(deref->deref_type == nir_deref_type_array);
nir_const_value *const_index = nir_src_as_const_value(deref->arr.index);
if (const_index) {
*base_index += MIN2(const_index->u32[0], array_size - 1);
} else {
nir_builder *b = &state->builder;
if (deref->deref.child) {
assert(deref->deref.child->deref_type == nir_deref_type_array);
nir_deref_array *deref_array = nir_deref_as_array(deref->deref.child);
if (deref_array->deref_array_type == nir_deref_array_type_indirect) {
/* From VK_KHR_sampler_ycbcr_conversion:
*
* If sampler YCBCR conversion is enabled, the combined image
@@ -178,32 +218,20 @@ lower_tex_deref(nir_tex_instr *tex, nir_deref_var *deref,
*/
assert(nir_tex_instr_src_index(tex, nir_tex_src_plane) == -1);
nir_ssa_def *index =
nir_iadd(b, nir_imm_int(b, deref_array->base_offset),
nir_ssa_for_src(b, deref_array->indirect, 1));
index = nir_ssa_for_src(b, deref->arr.index, 1);
if (state->add_bounds_checks)
index = nir_umin(b, index, nir_imm_int(b, array_size - 1));
}
}
nir_tex_instr_add_src(tex, src_type, nir_src_for_ssa(index));
if (index) {
nir_instr_rewrite_src(&tex->instr, &tex->src[deref_src_idx].src,
nir_src_for_ssa(index));
tex->src[deref_src_idx].src_type = offset_src_type;
} else {
*const_index += MIN2(deref_array->base_offset, array_size - 1);
nir_tex_instr_remove_src(tex, deref_src_idx);
}
}
}
static void
cleanup_tex_deref(nir_tex_instr *tex, nir_deref_var *deref)
{
if (deref->deref.child == NULL)
return;
nir_deref_array *deref_array = nir_deref_as_array(deref->deref.child);
if (deref_array->deref_array_type != nir_deref_array_type_indirect)
return;
nir_instr_rewrite_src(&tex->instr, &deref_array->indirect, NIR_SRC_INIT);
}
static uint32_t
@@ -224,43 +252,22 @@ tex_instr_get_and_remove_plane_src(nir_tex_instr *tex)
static void
lower_tex(nir_tex_instr *tex, struct apply_pipeline_layout_state *state)
{
/* No one should have come by and lowered it already */
assert(tex->texture);
state->builder.cursor = nir_before_instr(&tex->instr);
unsigned set = tex->texture->var->data.descriptor_set;
unsigned binding = tex->texture->var->data.binding;
unsigned array_size =
state->layout->set[set].layout->binding[binding].array_size;
unsigned plane = tex_instr_get_and_remove_plane_src(tex);
tex->texture_index = state->set[set].surface_offsets[binding];
lower_tex_deref(tex, tex->texture, &tex->texture_index, array_size,
nir_tex_src_texture_offset, state);
lower_tex_deref(tex, nir_tex_src_texture_deref,
&tex->texture_index, state);
tex->texture_index += plane;
if (tex->sampler) {
unsigned set = tex->sampler->var->data.descriptor_set;
unsigned binding = tex->sampler->var->data.binding;
unsigned array_size =
state->layout->set[set].layout->binding[binding].array_size;
tex->sampler_index = state->set[set].sampler_offsets[binding];
lower_tex_deref(tex, tex->sampler, &tex->sampler_index, array_size,
nir_tex_src_sampler_offset, state);
lower_tex_deref(tex, nir_tex_src_sampler_deref,
&tex->sampler_index, state);
tex->sampler_index += plane;
}
/* The backend only ever uses this to mark used surfaces. We don't care
* about that little optimization so it just needs to be non-zero.
*/
tex->texture_array_size = 1;
cleanup_tex_deref(tex, tex->texture);
if (tex->sampler)
cleanup_tex_deref(tex, tex->sampler);
tex->texture = NULL;
tex->sampler = NULL;
}
static void

View File

@@ -420,9 +420,6 @@ anv_pipeline_compile(struct anv_pipeline *pipeline,
NIR_PASS_V(nir, anv_nir_lower_ycbcr_textures, layout);
NIR_PASS_V(nir, nir_lower_deref_instrs,
nir_lower_texture_derefs | nir_lower_image_derefs);
NIR_PASS_V(nir, anv_nir_lower_push_constants);
if (stage != MESA_SHADER_COMPUTE)