asahi: offset buffer images in software
this is needed for honeykrisp to implement uniformTexelBufferOffsetSingleTexelAlignment. Signed-off-by: Alyssa Rosenzweig <alyssa@rosenzweig.io> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/30382>
This commit is contained in:

committed by
Marge Bot

parent
735c63c75e
commit
76e3bd56f6
@@ -259,6 +259,7 @@
|
||||
<field name="Tile height (sw)" size="3" start="158" type="uint" modifier="log2" default="1"/>
|
||||
<field name="Layer stride (sw)" size="27" start="161" type="uint" modifier="shr(7)"/>
|
||||
<field name="Sample count log2 (sw)" size="2" start="188" type="uint"/>
|
||||
<field name="Buffer offset (sw)" size="32" start="128" type="uint"/>
|
||||
</struct>
|
||||
|
||||
<struct name="Texture" size="24">
|
||||
@@ -301,8 +302,9 @@
|
||||
<field name="Depth (linear)" size="11" start="128" type="uint" modifier="minus(1)" default="1"/>
|
||||
<field name="Layer stride (linear)" size="27" start="139" type="uint" modifier="shr(7)"/>
|
||||
|
||||
<!-- Buffer texture size -->
|
||||
<field name="Software-defined" size="64" start="128" type="hex"/>
|
||||
<!-- Buffer texture metadata -->
|
||||
<field name="Buffer size (sw)" size="32" start="128" type="uint"/>
|
||||
<field name="Buffer offset (sw)" size="32" start="160" type="uint"/>
|
||||
</struct>
|
||||
|
||||
<enum name="Wrap">
|
||||
|
@@ -134,15 +134,18 @@ static bool
|
||||
lower_buffer_texture(nir_builder *b, nir_tex_instr *tex)
|
||||
{
|
||||
nir_def *coord = nir_steal_tex_src(tex, nir_tex_src_coord);
|
||||
nir_def *size = nir_get_texture_size(b, tex);
|
||||
nir_def *oob = nir_uge(b, coord, size);
|
||||
|
||||
/* Apply the buffer offset after calculating oob but before remapping */
|
||||
nir_def *desc = texture_descriptor_ptr(b, tex);
|
||||
coord = libagx_buffer_texture_offset(b, desc, coord);
|
||||
|
||||
/* Map out-of-bounds indices to out-of-bounds coordinates for robustness2
|
||||
* semantics from the hardware.
|
||||
*/
|
||||
nir_def *size = nir_get_texture_size(b, tex);
|
||||
nir_def *oob = nir_uge(b, coord, size);
|
||||
coord = nir_bcsel(b, oob, nir_imm_int(b, -1), coord);
|
||||
|
||||
nir_def *desc = texture_descriptor_ptr(b, tex);
|
||||
bool is_float = nir_alu_type_get_base_type(tex->dest_type) == nir_type_float;
|
||||
|
||||
/* Lower RGB32 reads if the format requires. If we are out-of-bounds, we use
|
||||
@@ -502,6 +505,15 @@ lower_buffer_image(nir_builder *b, nir_intrinsic_instr *intr)
|
||||
nir_def *coord_vector = intr->src[1].ssa;
|
||||
nir_def *coord = nir_channel(b, coord_vector, 0);
|
||||
|
||||
/* If we're not bindless, assume we don't need an offset (GL driver) */
|
||||
if (intr->intrinsic == nir_intrinsic_bindless_image_load) {
|
||||
nir_def *desc = nir_load_from_texture_handle_agx(b, intr->src[0].ssa);
|
||||
coord = libagx_buffer_texture_offset(b, desc, coord);
|
||||
} else if (intr->intrinsic == nir_intrinsic_bindless_image_store) {
|
||||
nir_def *desc = nir_load_from_texture_handle_agx(b, intr->src[0].ssa);
|
||||
coord = libagx_buffer_image_offset(b, desc, coord);
|
||||
}
|
||||
|
||||
/* Lower the buffer load/store to a 2D image load/store, matching the 2D
|
||||
* texture/PBE descriptor the driver supplies for buffer images.
|
||||
*/
|
||||
@@ -667,14 +679,17 @@ lower_robustness(nir_builder *b, nir_intrinsic_instr *intr, UNUSED void *data)
|
||||
}
|
||||
|
||||
/* Replace the last coordinate component with a large coordinate for
|
||||
* out-of-bounds. We pick 65535 as it fits in 16-bit, and it is not signed as
|
||||
* 32-bit so we won't get in-bounds coordinates for arrays due to two's
|
||||
* complement wraparound. This ensures the resulting hardware coordinate is
|
||||
* definitely out-of-bounds, giving hardware-level robustness2 behaviour.
|
||||
* out-of-bounds. We pick 0xFFF0 as it fits in 16-bit, and it is not signed
|
||||
* as 32-bit so we won't get in-bounds coordinates for arrays due to two's
|
||||
* complement wraparound. Additionally it still meets this requirement after
|
||||
* adding 0xF, the maximum tail offset.
|
||||
*
|
||||
* This ensures the resulting hardware coordinate is definitely
|
||||
* out-of-bounds, giving hardware-level robustness2 behaviour.
|
||||
*/
|
||||
unsigned c = size_components - 1;
|
||||
nir_def *r =
|
||||
nir_bcsel(b, oob, nir_imm_int(b, 65535), nir_channel(b, coord, c));
|
||||
nir_bcsel(b, oob, nir_imm_int(b, 0xFFF0), nir_channel(b, coord, c));
|
||||
|
||||
nir_src_rewrite(&intr->src[1], nir_vector_insert_imm(b, coord, r, c));
|
||||
return true;
|
||||
|
@@ -24,7 +24,7 @@ libagx_txs(constant struct agx_texture_packed *ptr, uint16_t lod,
|
||||
* Instead, we stash it in the software-defined section.
|
||||
*/
|
||||
if (is_buffer)
|
||||
return d.software_defined;
|
||||
return d.buffer_size_sw;
|
||||
|
||||
/* Load standard dimensions */
|
||||
uint3 size = (uint3)(d.width, d.height, d.depth);
|
||||
@@ -108,7 +108,10 @@ libagx_lower_txf_robustness(constant struct agx_texture_packed *ptr,
|
||||
valid &= layer < (linear ? d.depth_linear : d.depth);
|
||||
}
|
||||
|
||||
return valid ? x : 0xFFFF;
|
||||
/* The maximum tail offset is 0xF so by returning 0xFFF0 for out-of-bounds we
|
||||
* stay under 0xFFFF and keep robustness after offsetting.
|
||||
*/
|
||||
return valid ? x : 0xFFF0;
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
@@ -196,7 +199,9 @@ libagx_buffer_texel_address(constant const struct agx_pbe_packed *ptr,
|
||||
uint4 coord, uint bytes_per_pixel_B)
|
||||
{
|
||||
agx_unpack(NULL, ptr, PBE, d);
|
||||
return d.buffer + (uint64_t)(coord.x * bytes_per_pixel_B);
|
||||
|
||||
uint32_t x_el = d.buffer_offset_sw + coord.x;
|
||||
return d.buffer + (uint64_t)(x_el * bytes_per_pixel_B);
|
||||
}
|
||||
|
||||
/* Buffer texture lowerings */
|
||||
@@ -216,3 +221,19 @@ libagx_texture_load_rgb32(constant struct agx_texture_packed *ptr, uint coord,
|
||||
|
||||
return (uint4)(*data, is_float ? as_uint(1.0f) : 1);
|
||||
}
|
||||
|
||||
uint
|
||||
libagx_buffer_texture_offset(constant struct agx_texture_packed *ptr, uint x)
|
||||
{
|
||||
agx_unpack(NULL, ptr, TEXTURE, d);
|
||||
|
||||
return x + d.buffer_offset_sw;
|
||||
}
|
||||
|
||||
uint
|
||||
libagx_buffer_image_offset(constant struct agx_pbe_packed *ptr, uint x)
|
||||
{
|
||||
agx_unpack(NULL, ptr, PBE, d);
|
||||
|
||||
return x + d.buffer_offset_sw;
|
||||
}
|
||||
|
@@ -722,9 +722,8 @@ agx_pack_texture(void *out, struct agx_resource *rsrc,
|
||||
cfg.width = AGX_TEXTURE_BUFFER_WIDTH;
|
||||
cfg.height = DIV_ROUND_UP(size_el, cfg.width);
|
||||
cfg.first_level = cfg.last_level = 0;
|
||||
|
||||
/* Stash the actual size in the software-defined section for txs */
|
||||
cfg.software_defined = size_el;
|
||||
cfg.buffer_size_sw = size_el;
|
||||
cfg.buffer_offset_sw = 0;
|
||||
} else {
|
||||
cfg.width = rsrc->base.width0;
|
||||
cfg.height = rsrc->base.height0;
|
||||
|
Reference in New Issue
Block a user