panfrost: refactor draw logic to support native draw indirect

Split the draw logic into multiple methods depending on whether
the draw is single direct, multiple direct or indirect. Indirect
draws are emulated for now by reading back the indirect buffer info,
but we can implement optimized version later for JM and CSF.

Signed-off-by: Antonino Maniscalco <antonino.maniscalco@collabora.com>
Reviewed-by: Boris Brezillon <boris.brezillon@collabora.com>
Reviewed-by: Louis-Francis Ratté-Boulianne <lfrb@collabora.com>
Reviewed-by: Mary Guillemard <mary.guillemard@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/30583>
This commit is contained in:
antonino
2024-08-20 22:40:12 -04:00
committed by Marge Bot
parent d8b6a59896
commit 3b871856d1
6 changed files with 119 additions and 23 deletions
+92 -23
View File
@@ -2912,9 +2912,10 @@ panfrost_draw_get_vertex_count(struct panfrost_batch *batch,
}
static void
panfrost_direct_draw(struct panfrost_batch *batch,
const struct pipe_draw_info *info, unsigned drawid_offset,
const struct pipe_draw_start_count_bias *draw)
panfrost_single_draw_direct(struct panfrost_batch *batch,
const struct pipe_draw_info *info,
unsigned drawid_offset,
const struct pipe_draw_start_count_bias *draw)
{
if (!draw->count || !info->instance_count)
return;
@@ -2995,29 +2996,12 @@ panfrost_compatible_batch_state(struct panfrost_batch *batch,
return pan_tristate_set(&batch->first_provoking_vertex, first);
}
static void
panfrost_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info,
unsigned drawid_offset,
const struct pipe_draw_indirect_info *indirect,
const struct pipe_draw_start_count_bias *draws,
unsigned num_draws)
static struct panfrost_batch *
prepare_draw(struct pipe_context *pipe, const struct pipe_draw_info *info)
{
struct panfrost_context *ctx = pan_context(pipe);
struct panfrost_device *dev = pan_device(pipe->screen);
if (!panfrost_render_condition_check(ctx))
return;
ctx->draw_calls++;
/* Emulate indirect draws on JM */
if (indirect && indirect->buffer) {
assert(num_draws == 1);
util_draw_indirect(pipe, info, drawid_offset, indirect);
perf_debug(ctx, "Emulating indirect draw on the CPU");
return;
}
/* Do some common setup */
struct panfrost_batch *batch = panfrost_get_batch_for_fbo(ctx);
@@ -3053,11 +3037,74 @@ panfrost_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info,
/* Conservatively assume draw parameters always change */
ctx->dirty |= PAN_DIRTY_PARAMS | PAN_DIRTY_DRAWID;
return batch;
}
static void
panfrost_draw_indirect(struct pipe_context *pipe,
const struct pipe_draw_info *info,
unsigned drawid_offset,
const struct pipe_draw_indirect_info *indirect)
{
struct panfrost_context *ctx = pan_context(pipe);
if (!PAN_GPU_SUPPORTS_DRAW_INDIRECT || ctx->active_queries ||
ctx->streamout.num_targets) {
util_draw_indirect(pipe, info, drawid_offset, indirect);
perf_debug(ctx, "Emulating indirect draw on the CPU");
return;
}
struct panfrost_batch *batch = prepare_draw(pipe, info);
struct pipe_draw_info tmp_info = *info;
panfrost_batch_read_rsrc(batch, pan_resource(indirect->buffer),
PIPE_SHADER_VERTEX);
panfrost_update_active_prim(ctx, &tmp_info);
ctx->drawid = drawid_offset;
batch->indices = 0;
if (info->index_size) {
struct panfrost_resource *index_buffer =
pan_resource(info->index.resource);
panfrost_batch_read_rsrc(batch, index_buffer, PIPE_SHADER_VERTEX);
batch->indices = index_buffer->image.data.base;
}
panfrost_update_state_3d(batch);
panfrost_update_shader_state(batch, PIPE_SHADER_VERTEX);
panfrost_update_shader_state(batch, PIPE_SHADER_FRAGMENT);
panfrost_clean_state_3d(ctx);
/* Increment transform feedback offsets */
panfrost_update_streamout_offsets(ctx);
/* Any side effects must be handled by the XFB shader, so we only need
* to run vertex shaders if we need rasterization.
*/
if (panfrost_batch_skip_rasterization(batch))
return;
JOBX(launch_draw_indirect)(batch, &tmp_info, drawid_offset, indirect);
batch->draw_count++;
}
static void
panfrost_multi_draw_direct(struct pipe_context *pipe,
const struct pipe_draw_info *info,
unsigned drawid_offset,
const struct pipe_draw_start_count_bias *draws,
unsigned num_draws)
{
struct panfrost_context *ctx = pan_context(pipe);
struct panfrost_batch *batch = prepare_draw(pipe, info);
struct pipe_draw_info tmp_info = *info;
unsigned drawid = drawid_offset;
for (unsigned i = 0; i < num_draws; i++) {
panfrost_direct_draw(batch, &tmp_info, drawid, &draws[i]);
panfrost_single_draw_direct(batch, &tmp_info, drawid, &draws[i]);
if (tmp_info.increment_draw_id) {
ctx->dirty |= PAN_DIRTY_DRAWID;
@@ -3066,6 +3113,28 @@ panfrost_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info,
}
}
static void
panfrost_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info,
unsigned drawid_offset,
const struct pipe_draw_indirect_info *indirect,
const struct pipe_draw_start_count_bias *draws,
unsigned num_draws)
{
struct panfrost_context *ctx = pan_context(pipe);
if (!panfrost_render_condition_check(ctx))
return;
ctx->draw_calls++;
if (indirect && indirect->buffer) {
assert(num_draws == 1);
panfrost_draw_indirect(pipe, info, drawid_offset, indirect);
} else {
panfrost_multi_draw_direct(pipe, info, drawid_offset, draws, num_draws);
}
}
/* Launch grid is the compute equivalent of draw_vbo, so in this routine, we
* construct the COMPUTE job and some of its payload.
*/
@@ -41,6 +41,7 @@
#include "util/u_prim.h"
#define PAN_GPU_SUPPORTS_DISPATCH_INDIRECT (PAN_ARCH == 7 || PAN_ARCH >= 10)
#define PAN_GPU_SUPPORTS_DRAW_INDIRECT 0
struct panfrost_rasterizer {
struct pipe_rasterizer_state base;
+9
View File
@@ -942,6 +942,15 @@ GENX(csf_launch_draw)(struct panfrost_batch *batch,
cs_shader_res_sel(2, 2, 2, 0), cs_undef());
}
void
GENX(csf_launch_draw_indirect)(struct panfrost_batch *batch,
const struct pipe_draw_info *info,
unsigned drawid_offset,
const struct pipe_draw_indirect_info *indirect)
{
unreachable("draw indirect not implemented yet for CSF");
}
#define POSITION_FIFO_SIZE (64 * 1024)
int
+4
View File
@@ -91,6 +91,10 @@ void GENX(csf_launch_draw)(struct panfrost_batch *batch,
unsigned drawid_offset,
const struct pipe_draw_start_count_bias *draw,
unsigned vertex_count);
void GENX(csf_launch_draw_indirect)(struct panfrost_batch *batch,
const struct pipe_draw_info *info,
unsigned drawid_offset,
const struct pipe_draw_indirect_info *indirect);
#endif /* PAN_ARCH >= 10 */
+9
View File
@@ -969,3 +969,12 @@ GENX(jm_launch_draw)(struct panfrost_batch *batch,
}
#endif
}
void
GENX(jm_launch_draw_indirect)(struct panfrost_batch *batch,
const struct pipe_draw_info *info,
unsigned drawid_offset,
const struct pipe_draw_indirect_info *indirect)
{
unreachable("draw indirect not implemented for jm");
}
+4
View File
@@ -84,6 +84,10 @@ void GENX(jm_launch_draw)(struct panfrost_batch *batch,
unsigned drawid_offset,
const struct pipe_draw_start_count_bias *draw,
unsigned vertex_count);
void GENX(jm_launch_draw_indirect)(struct panfrost_batch *batch,
const struct pipe_draw_info *info,
unsigned drawid_offset,
const struct pipe_draw_indirect_info *indirect);
#endif /* PAN_ARCH < 10 */