libagx: don't key unroll to index size

Probably a premature optimization, it's annoying for precomp and for DGC.

Signed-off-by: Alyssa Rosenzweig <alyssa@rosenzweig.io>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/32081>
This commit is contained in:
Alyssa Rosenzweig
2024-11-08 22:00:21 -04:00
committed by Marge Bot
parent 6030b204d5
commit 2963cd900f
6 changed files with 93 additions and 93 deletions
+1 -8
View File
@@ -1548,14 +1548,7 @@ agx_nir_unroll_restart(nir_builder *b, const void *data)
nir_def *lane = nir_channel(b, nir_load_local_invocation_id(b), 0);
nir_def *mode = nir_imm_int(b, key->prim);
if (key->index_size_B == 1)
libagx_unroll_restart_u8(b, ia, mode, draw, lane);
else if (key->index_size_B == 2)
libagx_unroll_restart_u16(b, ia, mode, draw, lane);
else if (key->index_size_B == 4)
libagx_unroll_restart_u32(b, ia, mode, draw, lane);
else
unreachable("invalid index size");
libagx_unroll_restart(b, ia, mode, draw, lane);
}
void
-1
View File
@@ -46,7 +46,6 @@ void agx_nir_gs_setup_indirect(struct nir_builder *b, const void *key);
struct agx_unroll_restart_key {
enum mesa_prim prim;
unsigned index_size_B;
};
void agx_nir_unroll_restart(struct nir_builder *b, const void *key);
+83 -80
View File
@@ -332,88 +332,91 @@ setup_unroll_for_draw(global struct agx_restart_unroll_params *p,
return (global uchar *)heap->heap + old_heap_bottom_B;
}
#define UNROLL(INDEX, suffix) \
kernel void libagx_unroll_restart_##suffix( \
global struct agx_restart_unroll_params *p, enum mesa_prim mode, \
uint draw, uint tid) \
{ \
/* For an indirect multidraw, we are dispatched maxDraws times and \
* terminate trailing invocations. \
*/ \
if (p->count && draw >= *(p->count)) \
return; \
\
constant uint *in_draw = \
(constant uint *)(p->draws + (draw * p->draw_stride)); \
\
uint count = in_draw[0]; \
\
local uintptr_t out_ptr, in_ptr; \
if (tid == 0) { \
out_ptr = (uintptr_t)setup_unroll_for_draw(p, in_draw, draw, mode, \
sizeof(INDEX)); \
\
/* Accessed thru local mem because NIR deref is too aggressive */ \
in_ptr = (uintptr_t)(libagx_index_buffer( \
p->index_buffer, p->index_buffer_size_el, in_draw[2], \
sizeof(INDEX), p->zero_sink)); \
} \
\
barrier(CLK_LOCAL_MEM_FENCE); \
global INDEX *out = (global INDEX *)out_ptr; \
\
local uint scratch[32]; \
\
uint out_prims = 0; \
INDEX restart_idx = p->restart_index; \
bool flatshade_first = p->flatshade_first; \
\
uint needle = 0; \
uint per_prim = mesa_vertices_per_prim(mode); \
while (needle < count) { \
/* Search for next restart or the end. Lanes load in parallel. */ \
uint next_restart = needle; \
for (;;) { \
uint idx = next_restart + tid; \
bool restart = \
idx >= count || libagx_load_index_buffer_internal( \
in_ptr, p->index_buffer_size_el, idx, \
sizeof(INDEX)) == restart_idx; \
\
uint next_offs = first_true_thread_in_workgroup(restart, scratch); \
\
next_restart += next_offs; \
if (next_offs < 1024) \
break; \
} \
\
/* Emit up to the next restart. Lanes output in parallel */ \
uint subcount = next_restart - needle; \
uint subprims = u_decomposed_prims_for_vertices(mode, subcount); \
uint out_prims_base = out_prims; \
for (uint i = tid; i < subprims; i += 1024) { \
for (uint vtx = 0; vtx < per_prim; ++vtx) { \
uint id = libagx_vertex_id_for_topology(mode, flatshade_first, \
i, vtx, subprims); \
uint offset = needle + id; \
\
out[((out_prims_base + i) * per_prim) + vtx] = \
libagx_load_index_buffer_internal( \
in_ptr, p->index_buffer_size_el, offset, sizeof(INDEX)); \
} \
} \
\
out_prims += subprims; \
needle = next_restart + 1; \
} \
\
if (tid == 0) \
p->out_draws[(5 * draw) + 0] = out_prims * per_prim; \
kernel void
libagx_unroll_restart(global struct agx_restart_unroll_params *p,
enum mesa_prim mode, uint draw, uint tid)
{
/* For an indirect multidraw, we are dispatched maxDraws times and
* terminate trailing invocations.
*/
if (p->count && draw >= *(p->count))
return;
constant uint *in_draw =
(constant uint *)(p->draws + (draw * p->draw_stride));
uint count = in_draw[0];
local uintptr_t out_ptr, in_ptr;
if (tid == 0) {
out_ptr = (uintptr_t)setup_unroll_for_draw(p, in_draw, draw, mode,
p->index_size_B);
/* Accessed thru local mem because NIR deref is too aggressive */
in_ptr = (uintptr_t)(libagx_index_buffer(
p->index_buffer, p->index_buffer_size_el, in_draw[2], p->index_size_B,
p->zero_sink));
}
UNROLL(uchar, u8)
UNROLL(ushort, u16)
UNROLL(uint, u32)
barrier(CLK_LOCAL_MEM_FENCE);
global uint32_t *out_32 = (global uint32_t *)out_ptr;
global uint16_t *out_16 = (global uint16_t *)out_ptr;
global uint8_t *out_8 = (global uint8_t *)out_ptr;
local uint scratch[32];
uint out_prims = 0;
uint32_t restart_idx = p->restart_index;
bool flatshade_first = p->flatshade_first;
uint needle = 0;
uint per_prim = mesa_vertices_per_prim(mode);
while (needle < count) {
/* Search for next restart or the end. Lanes load in parallel. */
uint next_restart = needle;
for (;;) {
uint idx = next_restart + tid;
bool restart = idx >= count || libagx_load_index_buffer_internal(
in_ptr, p->index_buffer_size_el, idx,
p->index_size_B) == restart_idx;
uint next_offs = first_true_thread_in_workgroup(restart, scratch);
next_restart += next_offs;
if (next_offs < 1024)
break;
}
/* Emit up to the next restart. Lanes output in parallel */
uint subcount = next_restart - needle;
uint subprims = u_decomposed_prims_for_vertices(mode, subcount);
uint out_prims_base = out_prims;
for (uint i = tid; i < subprims; i += 1024) {
for (uint vtx = 0; vtx < per_prim; ++vtx) {
uint id = libagx_vertex_id_for_topology(mode, flatshade_first, i,
vtx, subprims);
uint offset = needle + id;
uint x = ((out_prims_base + i) * per_prim) + vtx;
uint y = libagx_load_index_buffer_internal(
in_ptr, p->index_buffer_size_el, offset, p->index_size_B);
if (p->index_size_B == 4)
out_32[x] = y;
else if (p->index_size_B == 2)
out_16[x] = y;
else
out_8[x] = y;
}
}
out_prims += subprims;
needle = next_restart + 1;
}
if (tid == 0)
p->out_draws[(5 * draw) + 0] = out_prims * per_prim;
}
uint
libagx_setup_xfb_buffer(global struct agx_geometry_params *p, uint i)
+4 -1
View File
@@ -60,6 +60,9 @@ struct agx_restart_unroll_params {
/* Input index buffer size in elements */
uint32_t index_buffer_size_el;
/* Size of an index in bytes */
uint32_t index_size_B;
/* Stride for the draw descriptor array */
uint32_t draw_stride;
@@ -69,7 +72,7 @@ struct agx_restart_unroll_params {
*/
uint32_t flatshade_first;
} PACKED;
AGX_STATIC_ASSERT(sizeof(struct agx_restart_unroll_params) == 17 * 4);
AGX_STATIC_ASSERT(sizeof(struct agx_restart_unroll_params) == 18 * 4);
struct agx_gs_setup_indirect_params {
/* Index buffer if present. */
+4 -2
View File
@@ -1456,9 +1456,10 @@ hk_draw_without_restart(struct hk_cmd_buffer *cmd, struct hk_cs *cs,
/* Next, we unroll the index buffer used by the indirect draw */
struct agx_unroll_restart_key key = {
.prim = vk_conv_topology(dyn->ia.primitive_topology),
.index_size_B = agx_index_size_to_B(draw.index_size),
};
uint32_t index_size_B = agx_index_size_to_B(draw.index_size);
struct agx_restart_unroll_params ia = {
.heap = hk_geometry_state(cmd),
.index_buffer = draw.index.addr,
@@ -1467,10 +1468,11 @@ hk_draw_without_restart(struct hk_cmd_buffer *cmd, struct hk_cs *cs,
.out_draws = hk_pool_alloc(cmd, 5 * sizeof(uint32_t) * draw_count, 4).gpu,
.max_draws = 1 /* TODO: MDI */,
.restart_index = gfx->index.restart,
.index_buffer_size_el = draw.index.range / key.index_size_B,
.index_buffer_size_el = draw.index.range / index_size_B,
.flatshade_first =
dyn->rs.provoking_vertex == VK_PROVOKING_VERTEX_MODE_FIRST_VERTEX_EXT,
.zero_sink = dev->rodata.zero_sink,
.index_size_B = index_size_B,
};
struct hk_shader *s =
+1 -1
View File
@@ -4269,7 +4269,6 @@ agx_draw_without_restart(struct agx_batch *batch,
struct agx_unroll_restart_key key = {
.prim = info->mode,
.index_size_B = info->index_size,
};
/* Allocate output indirect draw descriptors. This is exact. */
@@ -4286,6 +4285,7 @@ agx_draw_without_restart(struct agx_batch *batch,
.index_buffer_size_el = ib_extent / info->index_size,
.flatshade_first = batch->ctx->rast->base.flatshade_first,
.draws = agx_indirect_buffer_ptr(batch, indirect),
.index_size_B = info->index_size,
};
/* Unroll the index buffer for each draw */