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:
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 */
|
||||
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
@@ -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 */
|
||||
|
||||
|
||||
Reference in New Issue
Block a user