mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2025-12-27 19:10:14 +01:00
nak: Optimize bindless to cbuf textures on Volta+
Reviewed-by: Mel Henning <drawoc@darkrefraction.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/27755>
This commit is contained in:
parent
272e8ec461
commit
c1510ad72e
3 changed files with 117 additions and 23 deletions
|
|
@ -1745,6 +1745,18 @@ impl<'a> ShaderFromNir<'a> {
|
|||
let flags: nak_nir_tex_flags =
|
||||
unsafe { std::mem::transmute_copy(&tex.backend_flags) };
|
||||
|
||||
let tex_ref = match flags.ref_type() {
|
||||
NAK_NIR_TEX_REF_TYPE_BOUND => {
|
||||
TexRef::Bound(tex.texture_index.try_into().unwrap())
|
||||
}
|
||||
NAK_NIR_TEX_REF_TYPE_CBUF => TexRef::CBuf(TexCBufRef {
|
||||
idx: (tex.texture_index >> 16).try_into().unwrap(),
|
||||
offset: tex.texture_index as u16,
|
||||
}),
|
||||
NAK_NIR_TEX_REF_TYPE_BINDLESS => TexRef::Bindless,
|
||||
_ => panic!("Invalid tex ref type"),
|
||||
};
|
||||
|
||||
let mask = tex.def.components_read();
|
||||
let mut mask = u8::try_from(mask).unwrap();
|
||||
if flags.is_sparse() {
|
||||
|
|
@ -1774,7 +1786,7 @@ impl<'a> ShaderFromNir<'a> {
|
|||
assert!(fault.is_none());
|
||||
b.push_op(OpTxq {
|
||||
dsts: dsts,
|
||||
tex: TexRef::Bindless,
|
||||
tex: tex_ref,
|
||||
src: src,
|
||||
query: TexQuery::Dimension,
|
||||
mask: mask,
|
||||
|
|
@ -1784,7 +1796,7 @@ impl<'a> ShaderFromNir<'a> {
|
|||
assert!(fault.is_none());
|
||||
b.push_op(OpTxq {
|
||||
dsts: dsts,
|
||||
tex: TexRef::Bindless,
|
||||
tex: tex_ref,
|
||||
src: src,
|
||||
query: TexQuery::TextureType,
|
||||
mask: mask,
|
||||
|
|
@ -1816,7 +1828,7 @@ impl<'a> ShaderFromNir<'a> {
|
|||
b.push_op(OpTxd {
|
||||
dsts: dsts,
|
||||
fault,
|
||||
tex: TexRef::Bindless,
|
||||
tex: tex_ref,
|
||||
srcs: srcs,
|
||||
dim: dim,
|
||||
offset: offset_mode == Tld4OffsetMode::AddOffI,
|
||||
|
|
@ -1826,7 +1838,7 @@ impl<'a> ShaderFromNir<'a> {
|
|||
assert!(offset_mode == Tld4OffsetMode::None);
|
||||
b.push_op(OpTmml {
|
||||
dsts: dsts,
|
||||
tex: TexRef::Bindless,
|
||||
tex: tex_ref,
|
||||
srcs: srcs,
|
||||
dim: dim,
|
||||
mask: mask,
|
||||
|
|
@ -1836,7 +1848,7 @@ impl<'a> ShaderFromNir<'a> {
|
|||
b.push_op(OpTld {
|
||||
dsts: dsts,
|
||||
fault,
|
||||
tex: TexRef::Bindless,
|
||||
tex: tex_ref,
|
||||
srcs: srcs,
|
||||
dim: dim,
|
||||
lod_mode: lod_mode,
|
||||
|
|
@ -1848,7 +1860,7 @@ impl<'a> ShaderFromNir<'a> {
|
|||
b.push_op(OpTld4 {
|
||||
dsts: dsts,
|
||||
fault,
|
||||
tex: TexRef::Bindless,
|
||||
tex: tex_ref,
|
||||
srcs: srcs,
|
||||
dim: dim,
|
||||
comp: tex.component().try_into().unwrap(),
|
||||
|
|
@ -1861,7 +1873,7 @@ impl<'a> ShaderFromNir<'a> {
|
|||
b.push_op(OpTex {
|
||||
dsts: dsts,
|
||||
fault,
|
||||
tex: TexRef::Bindless,
|
||||
tex: tex_ref,
|
||||
srcs: srcs,
|
||||
dim: dim,
|
||||
lod_mode: lod_mode,
|
||||
|
|
|
|||
|
|
@ -9,6 +9,27 @@
|
|||
|
||||
#include "util/u_math.h"
|
||||
|
||||
static bool
|
||||
tex_handle_as_cbuf(nir_def *tex_h, uint32_t *cbuf_out)
|
||||
{
|
||||
if (tex_h->parent_instr->type != nir_instr_type_intrinsic)
|
||||
return false;
|
||||
|
||||
nir_intrinsic_instr *intrin = nir_instr_as_intrinsic(tex_h->parent_instr);
|
||||
if (intrin->intrinsic != nir_intrinsic_load_ubo)
|
||||
return false;
|
||||
|
||||
if (!nir_src_is_const(intrin->src[1]))
|
||||
return false;
|
||||
|
||||
uint32_t idx = nir_src_as_uint(intrin->src[0]);
|
||||
uint32_t offset = nir_src_as_uint(intrin->src[1]);
|
||||
assert(idx < (1 << 5) && offset < (1 << 16));
|
||||
*cbuf_out = (idx << 16) | offset;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static enum glsl_sampler_dim
|
||||
remap_sampler_dim(enum glsl_sampler_dim dim)
|
||||
{
|
||||
|
|
@ -51,6 +72,12 @@ lower_tex(nir_builder *b, nir_tex_instr *tex, const struct nak_compiler *nak)
|
|||
nir_iand_imm(b, samp_h, 0xfff00000));
|
||||
}
|
||||
|
||||
enum nak_nir_tex_ref_type ref_type = NAK_NIR_TEX_REF_TYPE_BINDLESS;
|
||||
if (nak->sm >= 70 && tex_handle_as_cbuf(tex_h, &tex->texture_index)) {
|
||||
ref_type = NAK_NIR_TEX_REF_TYPE_CBUF;
|
||||
tex_h = NULL;
|
||||
}
|
||||
|
||||
/* Array index is treated separately, so pull it off if we have one. */
|
||||
nir_def *arr_idx = NULL;
|
||||
unsigned coord_components = tex->coord_components;
|
||||
|
|
@ -149,7 +176,8 @@ lower_tex(nir_builder *b, nir_tex_instr *tex, const struct nak_compiler *nak)
|
|||
|
||||
if (nak->sm >= 50) {
|
||||
if (tex->op == nir_texop_txd) {
|
||||
PUSH(src0, tex_h);
|
||||
if (tex_h != NULL)
|
||||
PUSH(src0, tex_h);
|
||||
|
||||
for (uint32_t i = 0; i < coord_components; i++)
|
||||
PUSH(src0, nir_channel(b, coord, i));
|
||||
|
|
@ -181,7 +209,8 @@ lower_tex(nir_builder *b, nir_tex_instr *tex, const struct nak_compiler *nak)
|
|||
for (uint32_t i = 0; i < coord_components; i++)
|
||||
PUSH(src0, nir_channel(b, coord, i));
|
||||
|
||||
PUSH(src1, tex_h);
|
||||
if (tex_h != NULL)
|
||||
PUSH(src1, tex_h);
|
||||
if (ms_idx != NULL)
|
||||
PUSH(src1, ms_idx);
|
||||
if (lod != NULL)
|
||||
|
|
@ -199,6 +228,9 @@ lower_tex(nir_builder *b, nir_tex_instr *tex, const struct nak_compiler *nak)
|
|||
unreachable("Unsupported shader model");
|
||||
}
|
||||
|
||||
if (src1_comps == 0)
|
||||
PUSH(src1, nir_imm_int(b, 0));
|
||||
|
||||
nir_def *vec_srcs[2] = {
|
||||
nir_vec(b, src0, src0_comps),
|
||||
nir_vec(b, src1, src1_comps),
|
||||
|
|
@ -217,6 +249,7 @@ lower_tex(nir_builder *b, nir_tex_instr *tex, const struct nak_compiler *nak)
|
|||
tex->sampler_dim = remap_sampler_dim(tex->sampler_dim);
|
||||
|
||||
struct nak_nir_tex_flags flags = {
|
||||
.ref_type = ref_type,
|
||||
.lod_mode = lod_mode,
|
||||
.offset_mode = offset_mode,
|
||||
.has_z_cmpr = tex->is_shadow,
|
||||
|
|
@ -270,6 +303,12 @@ lower_txq(nir_builder *b, nir_tex_instr *tex, const struct nak_compiler *nak)
|
|||
}
|
||||
}
|
||||
|
||||
enum nak_nir_tex_ref_type ref_type = NAK_NIR_TEX_REF_TYPE_BINDLESS;
|
||||
if (nak->sm >= 70 && tex_handle_as_cbuf(tex_h, &tex->texture_index)) {
|
||||
ref_type = NAK_NIR_TEX_REF_TYPE_CBUF;
|
||||
tex_h = NULL;
|
||||
}
|
||||
|
||||
nir_def *txq_src;
|
||||
nir_component_mask_t mask;
|
||||
switch (tex->op) {
|
||||
|
|
@ -277,17 +316,18 @@ lower_txq(nir_builder *b, nir_tex_instr *tex, const struct nak_compiler *nak)
|
|||
tex->op = nir_texop_hdr_dim_nv;
|
||||
if (lod == NULL)
|
||||
lod = nir_imm_int(b, 0);
|
||||
txq_src = nir_vec2(b, tex_h, lod);
|
||||
txq_src = tex_h != NULL ? nir_vec2(b, tex_h, lod) : lod;
|
||||
mask = BITSET_MASK(tex->def.num_components);
|
||||
break;
|
||||
case nir_texop_query_levels:
|
||||
tex->op = nir_texop_hdr_dim_nv;
|
||||
txq_src = nir_vec2(b, tex_h, nir_imm_int(b, 0));
|
||||
lod = nir_imm_int(b, 0);
|
||||
txq_src = tex_h != NULL ? nir_vec2(b, tex_h, lod) : lod;
|
||||
mask = BITSET_BIT(3);
|
||||
break;
|
||||
case nir_texop_texture_samples:
|
||||
tex->op = nir_texop_tex_type_nv;
|
||||
txq_src = tex_h;
|
||||
txq_src = tex_h != NULL ? tex_h : nir_imm_int(b, 0);
|
||||
mask = BITSET_BIT(2);
|
||||
break;
|
||||
default:
|
||||
|
|
@ -303,6 +343,12 @@ lower_txq(nir_builder *b, nir_tex_instr *tex, const struct nak_compiler *nak)
|
|||
|
||||
tex->sampler_dim = remap_sampler_dim(tex->sampler_dim);
|
||||
|
||||
struct nak_nir_tex_flags flags = {
|
||||
.ref_type = ref_type,
|
||||
};
|
||||
STATIC_ASSERT(sizeof(flags) == sizeof(tex->backend_flags));
|
||||
memcpy(&tex->backend_flags, &flags, sizeof(flags));
|
||||
|
||||
b->cursor = nir_after_instr(&tex->instr);
|
||||
|
||||
/* Only pick off slected components */
|
||||
|
|
@ -485,31 +531,32 @@ lower_image_txq(nir_builder *b, nir_intrinsic_instr *intrin,
|
|||
|
||||
nir_def *img_h = intrin->src[0].ssa;
|
||||
|
||||
uint32_t texture_index = 0;
|
||||
enum nak_nir_tex_ref_type ref_type = NAK_NIR_TEX_REF_TYPE_BINDLESS;
|
||||
if (nak->sm >= 70 && tex_handle_as_cbuf(img_h, &texture_index)) {
|
||||
ref_type = NAK_NIR_TEX_REF_TYPE_CBUF;
|
||||
img_h = NULL;
|
||||
}
|
||||
|
||||
nir_tex_instr *txq = nir_tex_instr_create(b->shader, 1);
|
||||
txq->sampler_dim = remap_sampler_dim(nir_intrinsic_image_dim(intrin));
|
||||
txq->is_array = nir_intrinsic_image_array(intrin);
|
||||
txq->dest_type = nir_type_int32;
|
||||
|
||||
nir_def *txq_src;
|
||||
nir_component_mask_t mask;
|
||||
switch (intrin->intrinsic) {
|
||||
case nir_intrinsic_bindless_image_size: {
|
||||
nir_def *lod = intrin->src[1].ssa;
|
||||
|
||||
txq->op = nir_texop_hdr_dim_nv;
|
||||
txq->src[0] = (nir_tex_src) {
|
||||
.src_type = nir_tex_src_backend1,
|
||||
.src = nir_src_for_ssa(nir_vec2(b, img_h, lod)),
|
||||
};
|
||||
nir_def *lod = intrin->src[1].ssa;
|
||||
txq_src = img_h != NULL ? nir_vec2(b, img_h, lod) : lod;
|
||||
mask = BITSET_MASK(intrin->def.num_components);
|
||||
break;
|
||||
}
|
||||
|
||||
case nir_intrinsic_bindless_image_samples:
|
||||
txq->op = nir_texop_tex_type_nv;
|
||||
txq->src[0] = (nir_tex_src) {
|
||||
.src_type = nir_tex_src_backend1,
|
||||
.src = nir_src_for_ssa(img_h),
|
||||
};
|
||||
txq_src = img_h != NULL ? img_h : nir_imm_int(b, 0);
|
||||
mask = BITSET_BIT(2);
|
||||
break;
|
||||
|
||||
|
|
@ -517,6 +564,18 @@ lower_image_txq(nir_builder *b, nir_intrinsic_instr *intrin,
|
|||
unreachable("Invalid image query op");
|
||||
}
|
||||
|
||||
txq->src[0] = (nir_tex_src) {
|
||||
.src_type = nir_tex_src_backend1,
|
||||
.src = nir_src_for_ssa(txq_src),
|
||||
};
|
||||
txq->texture_index = texture_index;
|
||||
|
||||
struct nak_nir_tex_flags flags = {
|
||||
.ref_type = ref_type,
|
||||
};
|
||||
STATIC_ASSERT(sizeof(flags) == sizeof(txq->backend_flags));
|
||||
memcpy(&txq->backend_flags, &flags, sizeof(flags));
|
||||
|
||||
nir_def_init(&txq->instr, &txq->def, 4, 32);
|
||||
nir_builder_instr_insert(b, &txq->instr);
|
||||
|
||||
|
|
|
|||
|
|
@ -144,6 +144,23 @@ struct nak_io_addr_offset {
|
|||
struct nak_io_addr_offset
|
||||
nak_get_io_addr_offset(nir_def *addr, uint8_t imm_bits);
|
||||
|
||||
enum nak_nir_tex_ref_type {
|
||||
/** Indicates that this is a bindless texture */
|
||||
NAK_NIR_TEX_REF_TYPE_BINDLESS,
|
||||
|
||||
/** Indicates that this is a bound texture
|
||||
*
|
||||
* The binding index provided in texture_index.
|
||||
*/
|
||||
NAK_NIR_TEX_REF_TYPE_BOUND,
|
||||
|
||||
/** Indicates that this is a cbuf texture
|
||||
*
|
||||
* texture_index is (idx << 16) | offset.
|
||||
*/
|
||||
NAK_NIR_TEX_REF_TYPE_CBUF,
|
||||
};
|
||||
|
||||
enum nak_nir_lod_mode {
|
||||
NAK_NIR_LOD_MODE_AUTO = 0,
|
||||
NAK_NIR_LOD_MODE_ZERO,
|
||||
|
|
@ -159,13 +176,19 @@ enum nak_nir_offset_mode {
|
|||
NAK_NIR_OFFSET_MODE_PER_PX,
|
||||
};
|
||||
|
||||
PRAGMA_DIAGNOSTIC_PUSH
|
||||
PRAGMA_DIAGNOSTIC_ERROR(-Wpadded)
|
||||
struct nak_nir_tex_flags {
|
||||
enum nak_nir_tex_ref_type ref_type:2;
|
||||
enum nak_nir_lod_mode lod_mode:3;
|
||||
enum nak_nir_offset_mode offset_mode:2;
|
||||
bool has_z_cmpr:1;
|
||||
bool is_sparse:1;
|
||||
uint32_t pad:25;
|
||||
uint32_t pad:23;
|
||||
};
|
||||
PRAGMA_DIAGNOSTIC_POP
|
||||
static_assert(sizeof(struct nak_nir_tex_flags) == 4,
|
||||
"nak_nir_tex_flags has no holes");
|
||||
|
||||
bool nak_nir_lower_scan_reduce(nir_shader *shader);
|
||||
bool nak_nir_lower_tex(nir_shader *nir, const struct nak_compiler *nak);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue