panfrost: Hook up indirect draw support

Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>
Reviewed-by: Alyssa Rosenzweig <alyssa@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/8700>
This commit is contained in:
Boris Brezillon 2021-01-25 12:00:56 +01:00 committed by Marge Bot
parent 54526d8eca
commit d760a995e3
4 changed files with 147 additions and 4 deletions

View File

@ -2237,11 +2237,14 @@ panfrost_emit_vertex_tiler_jobs(struct panfrost_batch *batch,
unsigned vertex = panfrost_add_job(&batch->pool, &batch->scoreboard,
MALI_JOB_TYPE_VERTEX, false, false,
0, 0, vertex_job, false);
ctx->indirect_draw ?
batch->indirect_draw_job_id : 0,
0, vertex_job, false);
if (ctx->rasterizer->base.rasterizer_discard)
return;
panfrost_add_job(&batch->pool, &batch->scoreboard, MALI_JOB_TYPE_TILER,
false, false, vertex, 0, tiler_job, false);
panfrost_add_job(&batch->pool, &batch->scoreboard,
MALI_JOB_TYPE_TILER, false, false,
vertex, 0, tiler_job, false);
}

View File

@ -52,6 +52,7 @@
#include "midgard_pack.h"
#include "pan_screen.h"
#include "pan_cmdstream.h"
#include "pan_indirect_draw.h"
#include "pan_util.h"
#include "decode.h"
#include "util/pan_lower_framebuffer.h"
@ -596,7 +597,137 @@ panfrost_indirect_draw(struct panfrost_context *ctx,
return;
}
assert(0);
/* Indirect draw count and multi-draw not supported. */
assert(indirect->draw_count == 1 && !indirect->indirect_draw_count);
/* TODO: update statistics (see panfrost_statistics_record()) */
/* TODO: Increment transform feedback offsets */
assert(ctx->streamout.num_targets == 0);
struct panfrost_device *dev = pan_device(ctx->base.screen);
assert(ctx->draw_modes & (1 << info->mode));
ctx->active_prim = info->mode;
ctx->indirect_draw = true;
struct panfrost_batch *batch = panfrost_get_batch_for_fbo(ctx);
/* Don't add too many jobs to a single batch */
if (batch->scoreboard.job_index + (indirect->draw_count * 3) > 10000)
batch = panfrost_get_fresh_batch_for_fbo(ctx);
panfrost_batch_set_requirements(batch);
mali_ptr shared_mem = panfrost_batch_reserve_framebuffer(batch);
struct panfrost_ptr tiler =
panfrost_pool_alloc_aligned(&batch->pool,
pan_is_bifrost(dev) ?
MALI_BIFROST_TILER_JOB_LENGTH :
MALI_MIDGARD_TILER_JOB_LENGTH,
64);
struct panfrost_ptr vertex =
panfrost_pool_alloc_aligned(&batch->pool,
MALI_COMPUTE_JOB_LENGTH,
64);
struct panfrost_shader_state *vs =
panfrost_get_shader_state(ctx, PIPE_SHADER_VERTEX);
struct panfrost_bo *index_buf = NULL;
if (info->index_size) {
assert(!info->has_user_indices);
index_buf = pan_resource(info->index.resource)->bo;
panfrost_batch_add_bo(batch,
index_buf,
PAN_BO_ACCESS_SHARED | PAN_BO_ACCESS_READ |
PAN_BO_ACCESS_VERTEX_TILER);
}
mali_ptr varyings = 0, vs_vary = 0, fs_vary = 0, pos = 0, psiz = 0;
unsigned varying_buf_count;
/* We want to create templates, set all count fields to 0 to reflect
* that.
*/
ctx->instance_count = ctx->vertex_count = ctx->padded_count = 0;
ctx->offset_start = 0;
panfrost_emit_varying_descriptor(batch, 0,
&vs_vary, &fs_vary, &varyings,
&varying_buf_count, &pos, &psiz);
mali_ptr attribs, attrib_bufs;
attribs = panfrost_emit_vertex_data(batch, &attrib_bufs);
/* Zero-ed invocation, the compute job will update it. */
static struct mali_invocation_packed invocation;
/* Fire off the draw itself */
panfrost_draw_emit_vertex(batch, info, &invocation, shared_mem,
vs_vary, varyings, attribs, attrib_bufs,
vertex.cpu);
panfrost_draw_emit_tiler(batch, info, NULL, &invocation, shared_mem,
index_buf ? index_buf->ptr.gpu : 0,
fs_vary, varyings, pos, psiz, tiler.cpu);
/* Add the varying heap BO to the batch if we're allocating varyings. */
if (varyings) {
panfrost_batch_add_bo(batch,
dev->indirect_draw_shaders.varying_heap,
PAN_BO_ACCESS_SHARED | PAN_BO_ACCESS_RW |
PAN_BO_ACCESS_VERTEX_TILER);
}
assert(indirect->buffer);
struct panfrost_resource *draw_buf = pan_resource(indirect->buffer);
/* Don't count images: those attributes don't need to be patched. */
unsigned attrib_count =
vs->info.attribute_count -
util_bitcount(ctx->image_mask[PIPE_SHADER_VERTEX]);
panfrost_batch_add_bo(batch, draw_buf->bo,
PAN_BO_ACCESS_SHARED | PAN_BO_ACCESS_READ |
PAN_BO_ACCESS_VERTEX_TILER);
struct pan_indirect_draw_info draw_info = {
.last_indirect_draw = batch->indirect_draw_job_id,
.draw_buf = draw_buf->bo->ptr.gpu + indirect->offset,
.index_buf = index_buf ? index_buf->ptr.gpu : 0,
.vertex_job = vertex.gpu,
.tiler_job = tiler.gpu,
.attrib_bufs = attrib_bufs,
.attribs = attribs,
.attrib_count = attrib_count,
.varying_bufs = varyings,
.index_size = info->index_size,
};
if (panfrost_writes_point_size(ctx))
draw_info.flags |= PAN_INDIRECT_DRAW_UPDATE_PRIM_SIZE;
if (vs->info.vs.writes_point_size)
draw_info.flags |= PAN_INDIRECT_DRAW_HAS_PSIZ;
if (info->primitive_restart) {
draw_info.restart_index = info->restart_index;
draw_info.flags |= PAN_INDIRECT_DRAW_PRIMITIVE_RESTART;
}
batch->indirect_draw_job_id =
panfrost_emit_indirect_draw(&batch->pool,
&batch->scoreboard,
&draw_info,
&batch->indirect_draw_ctx);
panfrost_emit_vertex_tiler_jobs(batch, &vertex, &tiler);
/* Adjust the batch stack size based on the new shader stack sizes. */
panfrost_batch_adjust_stack_size(batch);
}
static void

View File

@ -125,6 +125,10 @@ struct panfrost_batch {
/* Batch dependencies */
struct util_dynarray dependencies;
/* Indirect draw data */
struct panfrost_ptr indirect_draw_ctx;
unsigned indirect_draw_job_id;
};
/* Functions for managing the above */

View File

@ -301,6 +301,9 @@ panfrost_get_param(struct pipe_screen *screen, enum pipe_cap param)
case PIPE_CAP_SHAREABLE_SHADERS:
return 0;
case PIPE_CAP_DRAW_INDIRECT:
return is_deqp;
default:
return u_pipe_screen_get_param_defaults(screen, param);
}
@ -686,6 +689,7 @@ panfrost_destroy_screen(struct pipe_screen *pscreen)
{
struct panfrost_device *dev = pan_device(pscreen);
panfrost_cleanup_indirect_draw_shaders(dev);
pan_blend_shaders_cleanup(dev);
if (dev->ro)
@ -860,6 +864,7 @@ panfrost_create_screen(int fd, struct renderonly *ro)
panfrost_resource_screen_init(&screen->base);
panfrost_init_blit_shaders(dev);
pan_blend_shaders_init(dev);
panfrost_init_indirect_draw_shaders(dev);
return &screen->base;
}