freedreno/ir3: respect tex prefetch limits
Refactor a bit the limit checking in the bindless case, and add tex/samp limit checking for the non-bindless case, to ensure we do not try to prefetch textures which cannot be encoded in the # of bits available. Signed-off-by: Rob Clark <robdclark@chromium.org> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/5431>
This commit is contained in:
@@ -3446,10 +3446,16 @@ collect_tex_prefetches(struct ir3_context *ctx, struct ir3 *ir)
|
|||||||
fetch->dst = instr->regs[0]->num;
|
fetch->dst = instr->regs[0]->num;
|
||||||
fetch->src = instr->prefetch.input_offset;
|
fetch->src = instr->prefetch.input_offset;
|
||||||
|
|
||||||
|
/* These are the limits on a5xx/a6xx, we might need to
|
||||||
|
* revisit if SP_FS_PREFETCH[n] changes on later gens:
|
||||||
|
*/
|
||||||
|
assert(fetch->dst <= 0x3f);
|
||||||
|
assert(fetch->tex_id <= 0x1f);
|
||||||
|
assert(fetch->samp_id < 0xf);
|
||||||
|
|
||||||
ctx->so->total_in =
|
ctx->so->total_in =
|
||||||
MAX2(ctx->so->total_in, instr->prefetch.input_offset + 2);
|
MAX2(ctx->so->total_in, instr->prefetch.input_offset + 2);
|
||||||
|
|
||||||
/* Disable half precision until supported. */
|
|
||||||
fetch->half_precision = !!(instr->regs[0]->flags & IR3_REG_HALF);
|
fetch->half_precision = !!(instr->regs[0]->flags & IR3_REG_HALF);
|
||||||
|
|
||||||
/* Remove the prefetch placeholder instruction: */
|
/* Remove the prefetch placeholder instruction: */
|
||||||
|
@@ -110,6 +110,46 @@ has_src(nir_tex_instr *tex, nir_tex_src_type type)
|
|||||||
return nir_tex_instr_src_index(tex, type) > 0;
|
return nir_tex_instr_src_index(tex, type) > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
ok_bindless_src(nir_tex_instr *tex, nir_tex_src_type type)
|
||||||
|
{
|
||||||
|
int idx = nir_tex_instr_src_index(tex, type);
|
||||||
|
assert(idx >= 0);
|
||||||
|
nir_intrinsic_instr *bindless = ir3_bindless_resource(tex->src[idx].src);
|
||||||
|
|
||||||
|
/* TODO from SP_FS_BINDLESS_PREFETCH[n] it looks like this limit should
|
||||||
|
* be 1<<8 ?
|
||||||
|
*/
|
||||||
|
return nir_src_is_const(bindless->src[0]) &&
|
||||||
|
(nir_src_as_uint(bindless->src[0]) < (1 << 16));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check that we will be able to encode the tex/samp parameters
|
||||||
|
* successfully. These limits are based on the layout of
|
||||||
|
* SP_FS_PREFETCH[n] and SP_FS_BINDLESS_PREFETCH[n], so at some
|
||||||
|
* point (if those regs changes) they may become generation
|
||||||
|
* specific.
|
||||||
|
*/
|
||||||
|
static bool
|
||||||
|
ok_tex_samp(nir_tex_instr *tex)
|
||||||
|
{
|
||||||
|
if (has_src(tex, nir_tex_src_texture_handle)) {
|
||||||
|
/* bindless case: */
|
||||||
|
|
||||||
|
assert(has_src(tex, nir_tex_src_sampler_handle));
|
||||||
|
|
||||||
|
return ok_bindless_src(tex, nir_tex_src_texture_handle) &&
|
||||||
|
ok_bindless_src(tex, nir_tex_src_sampler_handle);
|
||||||
|
} else {
|
||||||
|
assert(!has_src(tex, nir_tex_src_texture_offset));
|
||||||
|
assert(!has_src(tex, nir_tex_src_sampler_offset));
|
||||||
|
|
||||||
|
return (tex->texture_index <= 0x1f) &&
|
||||||
|
(tex->sampler_index <= 0xf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
lower_tex_prefetch_block(nir_block *block)
|
lower_tex_prefetch_block(nir_block *block)
|
||||||
{
|
{
|
||||||
@@ -135,30 +175,14 @@ lower_tex_prefetch_block(nir_block *block)
|
|||||||
has_src(tex, nir_tex_src_sampler_offset))
|
has_src(tex, nir_tex_src_sampler_offset))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* Disallow indirect or large bindless handles */
|
|
||||||
int idx = nir_tex_instr_src_index(tex, nir_tex_src_texture_handle);
|
|
||||||
if (idx >= 0) {
|
|
||||||
nir_intrinsic_instr *bindless =
|
|
||||||
ir3_bindless_resource(tex->src[idx].src);
|
|
||||||
if (!nir_src_is_const(bindless->src[0]) ||
|
|
||||||
nir_src_as_uint(bindless->src[0]) >= (1 << 16))
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
idx = nir_tex_instr_src_index(tex, nir_tex_src_sampler_handle);
|
|
||||||
if (idx >= 0) {
|
|
||||||
nir_intrinsic_instr *bindless =
|
|
||||||
ir3_bindless_resource(tex->src[idx].src);
|
|
||||||
if (!nir_src_is_const(bindless->src[0]) ||
|
|
||||||
nir_src_as_uint(bindless->src[0]) >= (1 << 16))
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* only prefetch for simple 2d tex fetch case */
|
/* only prefetch for simple 2d tex fetch case */
|
||||||
if (tex->sampler_dim != GLSL_SAMPLER_DIM_2D || tex->is_array)
|
if (tex->sampler_dim != GLSL_SAMPLER_DIM_2D || tex->is_array)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
idx = nir_tex_instr_src_index(tex, nir_tex_src_coord);
|
if (!ok_tex_samp(tex))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
int idx = nir_tex_instr_src_index(tex, nir_tex_src_coord);
|
||||||
/* First source should be the sampling coordinate. */
|
/* First source should be the sampling coordinate. */
|
||||||
nir_tex_src *coord = &tex->src[idx];
|
nir_tex_src *coord = &tex->src[idx];
|
||||||
debug_assert(coord->src.is_ssa);
|
debug_assert(coord->src.is_ssa);
|
||||||
|
Reference in New Issue
Block a user