mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-03-06 03:30:30 +01:00
zink: Rework sparse texture lowering
Instead of the previous fragile attempt to handle sparse_resident_and by crawling deref chains, we now insert an is_sparse_resident_zink intrinsic immediately after the tex or sparse_load intrinsic and define Zink's sparse resident codes to always be 0/1. Then sparse_resident_and becomes iand and is_sparse_texels_resident becomes != 0 and everything is well-defined and robust. Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/28123>
This commit is contained in:
parent
8a5120003c
commit
b68f2e747c
3 changed files with 51 additions and 87 deletions
|
|
@ -402,6 +402,13 @@ intrinsic("is_sparse_texels_resident", dest_comp=1, src_comp=[1], bit_sizes=[1,3
|
|||
intrinsic("sparse_residency_code_and", dest_comp=1, src_comp=[1, 1], bit_sizes=[32],
|
||||
flags=[CAN_ELIMINATE, CAN_REORDER])
|
||||
|
||||
# Unlike is_sparse_texels_resident, this intrinsic is required to consume
|
||||
# the destination of the nir_tex_instr or sparse_load intrinsic directly.
|
||||
# As such it is allowed to ignore the .e component where we usually store
|
||||
# sparse information.
|
||||
intrinsic("is_sparse_resident_zink", dest_comp=1, src_comp=[0], bit_sizes=[1],
|
||||
flags=[CAN_ELIMINATE, CAN_REORDER])
|
||||
|
||||
# a barrier is an intrinsic with no inputs/outputs but which can't be moved
|
||||
# around/optimized in general
|
||||
def barrier(name):
|
||||
|
|
|
|||
|
|
@ -3140,11 +3140,7 @@ emit_is_sparse_texels_resident(struct ntv_context *ctx, nir_intrinsic_instr *int
|
|||
|
||||
SpvId type = get_def_type(ctx, &intr->def, nir_type_uint);
|
||||
|
||||
/* this will always be stored with the ssa index of the parent instr */
|
||||
nir_def *ssa = intr->src[0].ssa;
|
||||
assert(ssa->parent_instr->type == nir_instr_type_alu);
|
||||
nir_alu_instr *alu = nir_instr_as_alu(ssa->parent_instr);
|
||||
unsigned index = alu->src[0].src.ssa->index;
|
||||
unsigned index = intr->src[0].ssa->index;
|
||||
assert(index < ctx->num_defs);
|
||||
assert(ctx->resident_defs[index] != 0);
|
||||
SpvId resident = ctx->resident_defs[index];
|
||||
|
|
@ -3480,7 +3476,7 @@ emit_intrinsic(struct ntv_context *ctx, nir_intrinsic_instr *intr)
|
|||
emit_vote(ctx, intr);
|
||||
break;
|
||||
|
||||
case nir_intrinsic_is_sparse_texels_resident:
|
||||
case nir_intrinsic_is_sparse_resident_zink:
|
||||
emit_is_sparse_texels_resident(ctx, intr);
|
||||
break;
|
||||
|
||||
|
|
|
|||
|
|
@ -3546,98 +3546,60 @@ invert_point_coord(nir_shader *nir)
|
|||
}
|
||||
|
||||
static bool
|
||||
is_residency_code(nir_def *src)
|
||||
lower_sparse_instr(nir_builder *b, nir_instr *instr, void *data)
|
||||
{
|
||||
nir_instr *parent = src->parent_instr;
|
||||
while (1) {
|
||||
if (parent->type == nir_instr_type_intrinsic) {
|
||||
ASSERTED nir_intrinsic_instr *intr = nir_instr_as_intrinsic(parent);
|
||||
assert(intr->intrinsic == nir_intrinsic_is_sparse_texels_resident);
|
||||
b->cursor = nir_after_instr(instr);
|
||||
|
||||
switch (instr->type) {
|
||||
case nir_instr_type_tex: {
|
||||
nir_tex_instr *tex = nir_instr_as_tex(instr);
|
||||
if (!tex->is_sparse)
|
||||
return false;
|
||||
|
||||
nir_def *res = nir_b2i32(b, nir_is_sparse_resident_zink(b, &tex->def));
|
||||
nir_def *vec = nir_vector_insert_imm(b, &tex->def, res,
|
||||
tex->def.num_components - 1);
|
||||
nir_def_rewrite_uses_after(&tex->def, vec, vec->parent_instr);
|
||||
return true;
|
||||
}
|
||||
|
||||
case nir_instr_type_intrinsic: {
|
||||
nir_intrinsic_instr *intrin = nir_instr_as_intrinsic(instr);
|
||||
switch (intrin->intrinsic) {
|
||||
case nir_intrinsic_image_deref_sparse_load: {
|
||||
nir_def *res = nir_b2i32(b, nir_is_sparse_resident_zink(b, &intrin->def));
|
||||
nir_def *vec = nir_vector_insert_imm(b, &intrin->def, res, 4);
|
||||
nir_def_rewrite_uses_after(&intrin->def, vec, vec->parent_instr);
|
||||
return true;
|
||||
}
|
||||
|
||||
case nir_intrinsic_sparse_residency_code_and: {
|
||||
nir_def *res = nir_iand(b, intrin->src[0].ssa, intrin->src[1].ssa);
|
||||
nir_def_rewrite_uses(&intrin->def, res);
|
||||
return true;
|
||||
}
|
||||
|
||||
case nir_intrinsic_is_sparse_texels_resident: {
|
||||
nir_def *res = nir_i2b(b, intrin->src[0].ssa);
|
||||
nir_def_rewrite_uses(&intrin->def, res);
|
||||
return true;
|
||||
}
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
if (parent->type == nir_instr_type_tex)
|
||||
return true;
|
||||
assert(parent->type == nir_instr_type_alu);
|
||||
nir_alu_instr *alu = nir_instr_as_alu(parent);
|
||||
parent = alu->src[0].src.ssa->parent_instr;
|
||||
}
|
||||
}
|
||||
|
||||
static bool
|
||||
lower_sparse_and_instr(nir_builder *b, nir_intrinsic_instr *instr, void *data)
|
||||
{
|
||||
if (instr->intrinsic != nir_intrinsic_sparse_residency_code_and)
|
||||
default:
|
||||
return false;
|
||||
|
||||
b->cursor = nir_before_instr(&instr->instr);
|
||||
nir_def *src0;
|
||||
if (is_residency_code(instr->src[0].ssa))
|
||||
src0 = nir_is_sparse_texels_resident(b, 1, instr->src[0].ssa);
|
||||
else
|
||||
src0 = instr->src[0].ssa;
|
||||
nir_def *src1;
|
||||
if (is_residency_code(instr->src[1].ssa))
|
||||
src1 = nir_is_sparse_texels_resident(b, 1, instr->src[1].ssa);
|
||||
else
|
||||
src1 = instr->src[1].ssa;
|
||||
nir_def *def = nir_iand(b, src0, src1);
|
||||
nir_def_rewrite_uses_after(&instr->def, def, &instr->instr);
|
||||
nir_instr_remove(&instr->instr);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
lower_sparse_and(nir_shader *shader)
|
||||
{
|
||||
return nir_shader_intrinsics_pass(shader, lower_sparse_and_instr,
|
||||
nir_metadata_dominance, NULL);
|
||||
}
|
||||
|
||||
static bool
|
||||
lower_sparse_instr(nir_builder *b, nir_intrinsic_instr *instr, void *data)
|
||||
{
|
||||
if (instr->intrinsic != nir_intrinsic_is_sparse_texels_resident)
|
||||
return false;
|
||||
|
||||
/* vulkan vec can only be a vec4, but this is (maybe) vec5,
|
||||
* so just rewrite as the first component since ntv is going to use a different
|
||||
* method for storing the residency value anyway
|
||||
*/
|
||||
b->cursor = nir_before_instr(&instr->instr);
|
||||
nir_instr *parent = instr->src[0].ssa->parent_instr;
|
||||
if (is_residency_code(instr->src[0].ssa)) {
|
||||
assert(parent->type == nir_instr_type_alu);
|
||||
nir_alu_instr *alu = nir_instr_as_alu(parent);
|
||||
nir_def_rewrite_uses_after(instr->src[0].ssa, nir_channel(b, alu->src[0].src.ssa, 0), parent);
|
||||
nir_instr_remove(parent);
|
||||
} else {
|
||||
nir_def *src;
|
||||
if (parent->type == nir_instr_type_intrinsic) {
|
||||
nir_intrinsic_instr *intr = nir_instr_as_intrinsic(parent);
|
||||
assert(intr->intrinsic == nir_intrinsic_is_sparse_texels_resident);
|
||||
src = intr->src[0].ssa;
|
||||
} else {
|
||||
assert(parent->type == nir_instr_type_alu);
|
||||
nir_alu_instr *alu = nir_instr_as_alu(parent);
|
||||
src = alu->src[0].src.ssa;
|
||||
}
|
||||
if (instr->def.bit_size != 32) {
|
||||
if (instr->def.bit_size == 1)
|
||||
src = nir_ieq_imm(b, src, 1);
|
||||
else
|
||||
src = nir_u2uN(b, src, instr->def.bit_size);
|
||||
}
|
||||
nir_def_rewrite_uses(&instr->def, src);
|
||||
nir_instr_remove(&instr->instr);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
lower_sparse(nir_shader *shader)
|
||||
{
|
||||
return nir_shader_intrinsics_pass(shader, lower_sparse_instr,
|
||||
nir_metadata_dominance, NULL);
|
||||
return nir_shader_instructions_pass(shader, lower_sparse_instr,
|
||||
nir_metadata_dominance, NULL);
|
||||
}
|
||||
|
||||
static bool
|
||||
|
|
@ -5572,7 +5534,6 @@ zink_shader_create(struct zink_screen *screen, struct nir_shader *nir)
|
|||
|
||||
NIR_PASS_V(nir, lower_basevertex);
|
||||
NIR_PASS_V(nir, lower_baseinstance);
|
||||
NIR_PASS_V(nir, lower_sparse_and);
|
||||
NIR_PASS_V(nir, split_bitfields);
|
||||
if (!screen->info.feats.features.shaderStorageImageMultisample)
|
||||
NIR_PASS_V(nir, strip_tex_ms);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue