intel: Add and use isl_surf_from_mem()

Unify code which creates surfaces from buffers. The behavior is slightly
changed to use array layers to enable arrayed buffer clears (as needed).

Reviewed-by: Rohan Garg <rohan.garg@intel.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/33776>
This commit is contained in:
Nanley Chery
2025-03-02 10:44:35 -08:00
committed by Marge Bot
parent 9a21ac2730
commit fcdae4d4c0
5 changed files with 175 additions and 272 deletions
+23 -107
View File
@@ -3081,122 +3081,38 @@ blorp_copy(struct blorp_batch *batch,
do_blorp_blit(batch, &params, &key, &coords);
}
static enum isl_format
isl_format_for_size(unsigned size_B)
{
switch (size_B) {
case 1: return ISL_FORMAT_R8_UINT;
case 2: return ISL_FORMAT_R8G8_UINT;
case 4: return ISL_FORMAT_R8G8B8A8_UINT;
case 8: return ISL_FORMAT_R16G16B16A16_UINT;
case 16: return ISL_FORMAT_R32G32B32A32_UINT;
default:
unreachable("Not a power-of-two format size");
}
}
/**
* Returns the greatest common divisor of a and b that is a power of two.
*/
static uint64_t
gcd_pow2_u64(uint64_t a, uint64_t b)
{
assert(a > 0 || b > 0);
unsigned a_log2 = ffsll(a) - 1;
unsigned b_log2 = ffsll(b) - 1;
/* If either a or b is 0, then a_log2 or b_log2 till be UINT_MAX in which
* case, the MIN2() will take the other one. If both are 0 then we will
* hit the assert above.
*/
return 1 << MIN2(a_log2, b_log2);
}
static void
do_buffer_copy(struct blorp_batch *batch,
struct blorp_address *src,
struct blorp_address *dst,
int width, int height, int block_size)
{
/* The actual format we pick doesn't matter as blorp will throw it away.
* The only thing that actually matters is the size.
*/
enum isl_format format = isl_format_for_size(block_size);
UNUSED bool ok;
struct isl_surf surf;
ok = isl_surf_init(batch->blorp->isl_dev, &surf,
.dim = ISL_SURF_DIM_2D,
.format = format,
.width = width,
.height = height,
.depth = 1,
.levels = 1,
.array_len = 1,
.samples = 1,
.row_pitch_B = width * block_size,
.usage = ISL_SURF_USAGE_TEXTURE_BIT |
ISL_SURF_USAGE_RENDER_TARGET_BIT,
.tiling_flags = ISL_TILING_LINEAR_BIT);
assert(ok);
struct blorp_surf src_blorp_surf = {
.surf = &surf,
.addr = *src,
};
struct blorp_surf dst_blorp_surf = {
.surf = &surf,
.addr = *dst,
};
blorp_copy(batch, &src_blorp_surf, 0, 0, &dst_blorp_surf, 0, 0,
0, 0, 0, 0, width, height);
}
void
blorp_buffer_copy(struct blorp_batch *batch,
struct blorp_address src,
struct blorp_address dst,
uint64_t size)
{
const struct intel_device_info *devinfo = batch->blorp->isl_dev->info;
uint64_t copy_size = size;
struct isl_surf surf;
struct blorp_surf src_blorp_surf = {
.surf = &surf,
.addr = src,
};
/* This is maximum possible width/height our HW can handle */
uint64_t max_surface_dim = 1 << (devinfo->ver >= 7 ? 14 : 13);
struct blorp_surf dst_blorp_surf = {
.surf = &surf,
.addr = dst,
};
/* First, we compute the biggest format that can be used with the
* given offsets and size.
*/
int bs = 16;
bs = gcd_pow2_u64(bs, src.offset);
bs = gcd_pow2_u64(bs, dst.offset);
bs = gcd_pow2_u64(bs, size);
while (size != 0) {
isl_surf_from_mem(batch->blorp->isl_dev, &surf,
src_blorp_surf.addr.offset |
dst_blorp_surf.addr.offset, size, ISL_TILING_LINEAR);
/* First, we make a bunch of max-sized copies */
uint64_t max_copy_size = max_surface_dim * max_surface_dim * bs;
while (copy_size >= max_copy_size) {
do_buffer_copy(batch, &src, &dst, max_surface_dim, max_surface_dim, bs);
copy_size -= max_copy_size;
src.offset += max_copy_size;
dst.offset += max_copy_size;
}
for (int i = 0; i < surf.logical_level0_px.a; i++) {
blorp_copy(batch,
&src_blorp_surf, 0, i,
&dst_blorp_surf, 0, i, 0, 0, 0, 0,
surf.logical_level0_px.w,
surf.logical_level0_px.h);
}
/* Now make a max-width copy */
uint64_t height = copy_size / (max_surface_dim * bs);
assert(height < max_surface_dim);
if (height != 0) {
uint64_t rect_copy_size = height * max_surface_dim * bs;
do_buffer_copy(batch, &src, &dst, max_surface_dim, height, bs);
copy_size -= rect_copy_size;
src.offset += rect_copy_size;
dst.offset += rect_copy_size;
}
/* Finally, make a small copy to finish it off */
if (copy_size != 0) {
do_buffer_copy(batch, &src, &dst, copy_size / bs, 1, bs);
size -= surf.size_B;
src_blorp_surf.addr.offset += surf.size_B;
dst_blorp_surf.addr.offset += surf.size_B;
}
}