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)
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:
}
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:
}
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)
{
- nir_builder *b = &state->builder;
+ 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];
+ }
- 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);
+ 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_array->deref_array_type == nir_deref_array_type_indirect) {
/* From VK_KHR_sampler_ycbcr_conversion:
*
* If sampler Y’CBCR conversion is enabled, the combined image
*/
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));
- } else {
- *const_index += MIN2(deref_array->base_offset, array_size - 1);
}
}
-}
-
-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);
+ 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 {
+ nir_tex_instr_remove_src(tex, deref_src_idx);
+ }
}
static uint32_t
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);
- tex->sampler_index += plane;
- }
+ 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