brw: add support for 64bit storage images load/store

Signed-off-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/32676>
This commit is contained in:
Lionel Landwerlin 2024-12-14 02:11:37 +02:00 committed by Marge Bot
parent 3bd4c5a166
commit b25e050ec7
2 changed files with 38 additions and 14 deletions

View file

@ -191,6 +191,7 @@ struct brw_nir_lower_storage_image_opts {
bool lower_loads;
bool lower_stores;
bool lower_stores_64bit;
};
bool brw_nir_lower_storage_image(nir_shader *nir,

View file

@ -63,6 +63,10 @@ convert_color_for_load(nir_builder *b, const struct intel_device_info *devinfo,
assert(lower_fmt == ISL_FORMAT_R32_UINT);
color = nir_format_unpack_11f11f10f(b, color);
goto expand_vec;
} else if (image_fmt == ISL_FORMAT_R64_PASSTHRU) {
assert(lower_fmt == ISL_FORMAT_R32G32_UINT);
color = nir_pack_64_2x32(b, nir_channels(b, color, 0x3));
goto expand_vec;
}
struct format_info image = get_format_info(image_fmt);
@ -130,13 +134,14 @@ expand_vec:
comps[i] = nir_channel(b, color, i);
for (unsigned i = color->num_components; i < 3; i++)
comps[i] = nir_imm_int(b, 0);
comps[i] = nir_imm_intN_t(b, 0, color->bit_size);
if (color->num_components < 4) {
if (isl_format_has_int_channel(image_fmt))
comps[3] = nir_imm_int(b, 1);
if (isl_format_has_int_channel(image_fmt) ||
image_fmt == ISL_FORMAT_R64_PASSTHRU)
comps[3] = nir_imm_intN_t(b, 1, color->bit_size);
else
comps[3] = nir_imm_float(b, 1);
comps[3] = nir_imm_floatN_t(b, 1, color->bit_size);
}
return nir_vec(b, comps, dest_components);
@ -163,6 +168,12 @@ lower_image_load_instr(nir_builder *b,
const unsigned dest_components =
sparse ? (intrin->num_components - 1) : intrin->num_components;
if (intrin->def.bit_size == 64 &&
isl_format_get_layout(lower_fmt)->channels.r.bits == 32) {
intrin->def.num_components = 2;
intrin->def.bit_size = 32;
}
/* Use an undef to hold the uses of the load while we do the color
* conversion.
*/
@ -189,7 +200,9 @@ lower_image_load_instr(nir_builder *b,
for (unsigned i = 0; i < dest_components; i++)
sparse_color[i] = nir_channel(b, color, i);
sparse_color[dest_components] =
nir_channel(b, &intrin->def, intrin->num_components - 1);
nir_u2uN(b,
nir_channel(b, &intrin->def, intrin->num_components - 1),
color->bit_size);
color = nir_vec(b, sparse_color, dest_components + 1);
}
@ -215,6 +228,9 @@ convert_color_for_store(nir_builder *b, const struct intel_device_info *devinfo,
if (image_fmt == ISL_FORMAT_R11G11B10_FLOAT) {
assert(lower_fmt == ISL_FORMAT_R32_UINT);
return nir_format_pack_11f11f10f(b, color);
} else if (image_fmt == ISL_FORMAT_R64_PASSTHRU) {
assert(lower_fmt == ISL_FORMAT_R32G32_UINT);
return nir_unpack_64_2x32(b, color);
}
switch (image.fmtl->channels.r.type) {
@ -268,19 +284,28 @@ convert_color_for_store(nir_builder *b, const struct intel_device_info *devinfo,
static bool
lower_image_store_instr(nir_builder *b,
const struct intel_device_info *devinfo,
const struct brw_nir_lower_storage_image_opts *opts,
nir_intrinsic_instr *intrin)
{
const struct intel_device_info *devinfo = opts->devinfo;
nir_deref_instr *deref = nir_src_as_deref(intrin->src[0]);
nir_variable *var = nir_deref_instr_get_variable(deref);
/* For write-only surfaces, we trust that the hardware can just do the
* conversion for us.
*/
if (var->data.access & ACCESS_NON_READABLE)
if (var->data.image.format == PIPE_FORMAT_NONE)
return false;
if (var->data.image.format == PIPE_FORMAT_NONE)
const struct util_format_description *fmt_desc =
util_format_description(var->data.image.format);
const bool is_r64_fmt =
fmt_desc->block.bits == 64 && fmt_desc->nr_channels == 1;
if ((!opts->lower_stores && !is_r64_fmt) ||
(!opts->lower_stores_64bit && is_r64_fmt))
return false;
/* For write-only surfaces non-64bit bpc, we trust that the hardware can
* just do the conversion for us.
*/
if ((var->data.access & ACCESS_NON_READABLE) && !is_r64_fmt)
return false;
const enum isl_format image_fmt =
@ -324,9 +349,7 @@ brw_nir_lower_storage_image_instr(nir_builder *b,
return false;
case nir_intrinsic_image_deref_store:
if (opts->lower_stores)
return lower_image_store_instr(b, opts->devinfo, intrin);
return false;
return lower_image_store_instr(b, opts, intrin);
default:
/* Nothing to do */