diff --git a/src/gallium/drivers/panfrost/pan_cmdstream.c b/src/gallium/drivers/panfrost/pan_cmdstream.c index 7e7062ec74f..5359f8080f9 100644 --- a/src/gallium/drivers/panfrost/pan_cmdstream.c +++ b/src/gallium/drivers/panfrost/pan_cmdstream.c @@ -27,6 +27,8 @@ #include "util/u_prim.h" #include "util/u_vbuf.h" #include "util/u_helpers.h" +#include "util/u_draw.h" +#include "indices/u_primconvert.h" #include "panfrost-quirks.h" @@ -37,6 +39,8 @@ #include "pan_job.h" #include "pan_shader.h" #include "pan_texture.h" +#include "pan_util.h" +#include "pan_indirect_draw.h" /* Statically assert that PIPE_* enums match the hardware enums. * (As long as they match, we don't need to translate them.) @@ -2453,3 +2457,664 @@ panfrost_emit_fragment_job(struct panfrost_batch *batch, return transfer.gpu; } + +#define DEFINE_CASE(c) case PIPE_PRIM_##c: return MALI_DRAW_MODE_##c; + +static uint8_t +pan_draw_mode(enum pipe_prim_type mode) +{ + switch (mode) { + DEFINE_CASE(POINTS); + DEFINE_CASE(LINES); + DEFINE_CASE(LINE_LOOP); + DEFINE_CASE(LINE_STRIP); + DEFINE_CASE(TRIANGLES); + DEFINE_CASE(TRIANGLE_STRIP); + DEFINE_CASE(TRIANGLE_FAN); + DEFINE_CASE(QUADS); + DEFINE_CASE(QUAD_STRIP); + DEFINE_CASE(POLYGON); + + default: + unreachable("Invalid draw mode"); + } +} + +#undef DEFINE_CASE + +/* Count generated primitives (when there is no geom/tess shaders) for + * transform feedback */ + +static void +panfrost_statistics_record( + struct panfrost_context *ctx, + const struct pipe_draw_info *info, + const struct pipe_draw_start_count_bias *draw) +{ + if (!ctx->active_queries) + return; + + uint32_t prims = u_prims_for_vertices(info->mode, draw->count); + ctx->prims_generated += prims; + + if (!ctx->streamout.num_targets) + return; + + ctx->tf_prims_generated += prims; +} + +static void +panfrost_update_streamout_offsets(struct panfrost_context *ctx) +{ + for (unsigned i = 0; i < ctx->streamout.num_targets; ++i) { + unsigned count; + + count = u_stream_outputs_for_vertices(ctx->active_prim, + ctx->vertex_count); + pan_so_target(ctx->streamout.targets[i])->offset += count; + } +} + +static inline void +pan_emit_draw_descs(struct panfrost_batch *batch, + struct MALI_DRAW *d, enum pipe_shader_type st) +{ + d->offset_start = batch->ctx->offset_start; + d->instance_size = batch->ctx->instance_count > 1 ? + batch->ctx->padded_count : 1; + + d->uniform_buffers = batch->uniform_buffers[st]; + d->push_uniforms = batch->push_uniforms[st]; + d->textures = batch->textures[st]; + d->samplers = batch->samplers[st]; +} + +static inline enum mali_index_type +panfrost_translate_index_size(unsigned size) +{ + STATIC_ASSERT(MALI_INDEX_TYPE_NONE == 0); + STATIC_ASSERT(MALI_INDEX_TYPE_UINT8 == 1); + STATIC_ASSERT(MALI_INDEX_TYPE_UINT16 == 2); + + return (size == 4) ? MALI_INDEX_TYPE_UINT32 : size; +} + +static void +panfrost_draw_emit_vertex(struct panfrost_batch *batch, + const struct pipe_draw_info *info, + void *invocation_template, + mali_ptr vs_vary, mali_ptr varyings, + mali_ptr attribs, mali_ptr attrib_bufs, + void *job) +{ + struct panfrost_context *ctx = batch->ctx; + struct panfrost_device *device = pan_device(ctx->base.screen); + + void *section = + pan_section_ptr(job, COMPUTE_JOB, INVOCATION); + memcpy(section, invocation_template, MALI_INVOCATION_LENGTH); + + pan_section_pack(job, COMPUTE_JOB, PARAMETERS, cfg) { + cfg.job_task_split = 5; + } + + pan_section_pack(job, COMPUTE_JOB, DRAW, cfg) { + cfg.draw_descriptor_is_64b = true; + if (!pan_is_bifrost(device)) + cfg.texture_descriptor_is_64b = true; + cfg.state = batch->rsd[PIPE_SHADER_VERTEX]; + cfg.attributes = attribs; + cfg.attribute_buffers = attrib_bufs; + cfg.varyings = vs_vary; + cfg.varying_buffers = vs_vary ? varyings : 0; + cfg.thread_storage = batch->tls.gpu; + pan_emit_draw_descs(batch, &cfg, PIPE_SHADER_VERTEX); + } + + pan_section_pack(job, COMPUTE_JOB, DRAW_PADDING, cfg); +} + +static void +panfrost_emit_primitive_size(struct panfrost_context *ctx, + bool points, mali_ptr size_array, + void *prim_size) +{ + struct panfrost_rasterizer *rast = ctx->rasterizer; + + pan_pack(prim_size, PRIMITIVE_SIZE, cfg) { + if (panfrost_writes_point_size(ctx)) { + cfg.size_array = size_array; + } else { + cfg.constant = points ? + rast->base.point_size : + rast->base.line_width; + } + } +} + +static bool +panfrost_is_implicit_prim_restart(const struct pipe_draw_info *info) +{ + unsigned implicit_index = (1 << (info->index_size * 8)) - 1; + bool implicit = info->restart_index == implicit_index; + return info->primitive_restart && implicit; +} + +static inline void +panfrost_update_state_tex(struct panfrost_batch *batch, + enum pipe_shader_type st) +{ + struct panfrost_context *ctx = batch->ctx; + struct panfrost_shader_state *ss = panfrost_get_shader_state(ctx, st); + + unsigned dirty_3d = ctx->dirty; + unsigned dirty = ctx->dirty_shader[st]; + + if (dirty & PAN_DIRTY_STAGE_TEXTURE) { + batch->textures[st] = + panfrost_emit_texture_descriptors(batch, st); + } + + if (dirty & PAN_DIRTY_STAGE_SAMPLER) { + batch->samplers[st] = + panfrost_emit_sampler_descriptors(batch, st); + } + + if ((dirty & ss->dirty_shader) || (dirty_3d & ss->dirty_3d)) { + batch->uniform_buffers[st] = panfrost_emit_const_buf(batch, st, + &batch->push_uniforms[st]); + } +} + +static inline void +panfrost_update_state_3d(struct panfrost_batch *batch) +{ + unsigned dirty = batch->ctx->dirty; + + if (dirty & (PAN_DIRTY_VIEWPORT | PAN_DIRTY_SCISSOR)) + batch->viewport = panfrost_emit_viewport(batch); + + if (dirty & PAN_DIRTY_TLS_SIZE) + panfrost_batch_adjust_stack_size(batch); +} + +static void +panfrost_update_state_vs(struct panfrost_batch *batch) +{ + enum pipe_shader_type st = PIPE_SHADER_VERTEX; + unsigned dirty = batch->ctx->dirty_shader[st]; + + if (dirty & PAN_DIRTY_STAGE_RENDERER) + batch->rsd[st] = panfrost_emit_compute_shader_meta(batch, st); + + panfrost_update_state_tex(batch, st); +} + +static void +panfrost_update_state_fs(struct panfrost_batch *batch) +{ + enum pipe_shader_type st = PIPE_SHADER_FRAGMENT; + unsigned dirty = batch->ctx->dirty_shader[st]; + + if (dirty & PAN_DIRTY_STAGE_RENDERER) + batch->rsd[st] = panfrost_emit_frag_shader_meta(batch); + + if (dirty & PAN_DIRTY_STAGE_IMAGE) { + batch->attribs[st] = panfrost_emit_image_attribs(batch, + &batch->attrib_bufs[st], st); + } + + panfrost_update_state_tex(batch, st); +} + +static void +panfrost_draw_emit_tiler(struct panfrost_batch *batch, + const struct pipe_draw_info *info, + const struct pipe_draw_start_count_bias *draw, + void *invocation_template, + mali_ptr indices, mali_ptr fs_vary, mali_ptr varyings, + mali_ptr pos, mali_ptr psiz, void *job) +{ + struct panfrost_context *ctx = batch->ctx; + struct pipe_rasterizer_state *rast = &ctx->rasterizer->base; + struct panfrost_device *device = pan_device(ctx->base.screen); + + void *section = pan_is_bifrost(device) ? + pan_section_ptr(job, BIFROST_TILER_JOB, INVOCATION) : + pan_section_ptr(job, MIDGARD_TILER_JOB, INVOCATION); + memcpy(section, invocation_template, MALI_INVOCATION_LENGTH); + + section = pan_is_bifrost(device) ? + pan_section_ptr(job, BIFROST_TILER_JOB, PRIMITIVE) : + pan_section_ptr(job, MIDGARD_TILER_JOB, PRIMITIVE); + pan_pack(section, PRIMITIVE, cfg) { + cfg.draw_mode = pan_draw_mode(info->mode); + if (panfrost_writes_point_size(ctx)) + cfg.point_size_array_format = MALI_POINT_SIZE_ARRAY_FORMAT_FP16; + + /* For line primitives, PRIMITIVE.first_provoking_vertex must + * be set to true and the provoking vertex is selected with + * DRAW.flat_shading_vertex. + */ + if (info->mode == PIPE_PRIM_LINES || + info->mode == PIPE_PRIM_LINE_LOOP || + info->mode == PIPE_PRIM_LINE_STRIP) + cfg.first_provoking_vertex = true; + else + cfg.first_provoking_vertex = rast->flatshade_first; + + if (panfrost_is_implicit_prim_restart(info)) { + cfg.primitive_restart = MALI_PRIMITIVE_RESTART_IMPLICIT; + } else if (info->primitive_restart) { + cfg.primitive_restart = MALI_PRIMITIVE_RESTART_EXPLICIT; + cfg.primitive_restart_index = info->restart_index; + } + + cfg.job_task_split = 6; + + cfg.index_count = ctx->indirect_draw ? 1 : draw->count; + cfg.index_type = panfrost_translate_index_size(info->index_size); + + if (cfg.index_type) { + cfg.indices = indices; + cfg.base_vertex_offset = draw->index_bias - ctx->offset_start; + } + } + + bool points = info->mode == PIPE_PRIM_POINTS; + void *prim_size = pan_is_bifrost(device) ? + pan_section_ptr(job, BIFROST_TILER_JOB, PRIMITIVE_SIZE) : + pan_section_ptr(job, MIDGARD_TILER_JOB, PRIMITIVE_SIZE); + + if (pan_is_bifrost(device)) { + panfrost_emit_primitive_size(ctx, points, psiz, prim_size); + pan_section_pack(job, BIFROST_TILER_JOB, TILER, cfg) { + cfg.address = panfrost_batch_get_bifrost_tiler(batch, ~0); + } + pan_section_pack(job, BIFROST_TILER_JOB, PADDING, padding) {} + } + + section = pan_is_bifrost(device) ? + pan_section_ptr(job, BIFROST_TILER_JOB, DRAW) : + pan_section_ptr(job, MIDGARD_TILER_JOB, DRAW); + pan_pack(section, DRAW, cfg) { + cfg.four_components_per_vertex = true; + cfg.draw_descriptor_is_64b = true; + if (!pan_is_bifrost(device)) + cfg.texture_descriptor_is_64b = true; + cfg.front_face_ccw = rast->front_ccw; + cfg.cull_front_face = rast->cull_face & PIPE_FACE_FRONT; + cfg.cull_back_face = rast->cull_face & PIPE_FACE_BACK; + cfg.position = pos; + cfg.state = batch->rsd[PIPE_SHADER_FRAGMENT]; + cfg.attributes = batch->attribs[PIPE_SHADER_FRAGMENT]; + cfg.attribute_buffers = batch->attrib_bufs[PIPE_SHADER_FRAGMENT]; + cfg.viewport = batch->viewport; + cfg.varyings = fs_vary; + cfg.varying_buffers = fs_vary ? varyings : 0; + cfg.thread_storage = batch->tls.gpu; + + /* For all primitives but lines DRAW.flat_shading_vertex must + * be set to 0 and the provoking vertex is selected with the + * PRIMITIVE.first_provoking_vertex field. + */ + if (info->mode == PIPE_PRIM_LINES || + info->mode == PIPE_PRIM_LINE_LOOP || + info->mode == PIPE_PRIM_LINE_STRIP) { + /* The logic is inverted on bifrost. */ + cfg.flat_shading_vertex = + pan_is_bifrost(device) ? + rast->flatshade_first : !rast->flatshade_first; + } + + pan_emit_draw_descs(batch, &cfg, PIPE_SHADER_FRAGMENT); + + if (ctx->occlusion_query && ctx->active_queries) { + if (ctx->occlusion_query->type == PIPE_QUERY_OCCLUSION_COUNTER) + cfg.occlusion_query = MALI_OCCLUSION_MODE_COUNTER; + else + cfg.occlusion_query = MALI_OCCLUSION_MODE_PREDICATE; + + struct panfrost_resource *rsrc = pan_resource(ctx->occlusion_query->rsrc); + cfg.occlusion = rsrc->image.data.bo->ptr.gpu; + panfrost_batch_write_rsrc(ctx->batch, rsrc, + PIPE_SHADER_FRAGMENT); + } + } + + if (!pan_is_bifrost(device)) + panfrost_emit_primitive_size(ctx, points, psiz, prim_size); + else + pan_section_pack(job, BIFROST_TILER_JOB, DRAW_PADDING, cfg); +} + +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) +{ + if (!draw->count || !info->instance_count) + return; + + struct panfrost_context *ctx = batch->ctx; + struct panfrost_device *device = pan_device(ctx->base.screen); + + /* Fallback for unsupported modes */ + if (!(ctx->draw_modes & BITFIELD_BIT(info->mode))) { + if (draw->count < 4) { + /* Degenerate case? */ + return; + } + + util_primconvert_save_rasterizer_state(ctx->primconvert, &ctx->rasterizer->base); + util_primconvert_draw_vbo(ctx->primconvert, info, drawid_offset, NULL, draw, 1); + return; + } + + /* Take into account a negative bias */ + ctx->indirect_draw = false; + ctx->vertex_count = draw->count + (info->index_size ? abs(draw->index_bias) : 0); + ctx->instance_count = info->instance_count; + ctx->base_vertex = info->index_size ? draw->index_bias : 0; + ctx->base_instance = info->start_instance; + ctx->active_prim = info->mode; + ctx->drawid = drawid_offset; + + struct panfrost_ptr tiler = + pan_is_bifrost(device) ? + pan_pool_alloc_desc(&batch->pool.base, BIFROST_TILER_JOB) : + pan_pool_alloc_desc(&batch->pool.base, MIDGARD_TILER_JOB); + struct panfrost_ptr vertex = + pan_pool_alloc_desc(&batch->pool.base, COMPUTE_JOB); + + unsigned vertex_count = ctx->vertex_count; + + unsigned min_index = 0, max_index = 0; + mali_ptr indices = 0; + + if (info->index_size) { + indices = panfrost_get_index_buffer_bounded(batch, info, draw, + &min_index, + &max_index); + + /* Use the corresponding values */ + vertex_count = max_index - min_index + 1; + ctx->offset_start = min_index + draw->index_bias; + } else { + ctx->offset_start = draw->start; + } + + if (info->instance_count > 1) + ctx->padded_count = panfrost_padded_vertex_count(vertex_count); + else + ctx->padded_count = vertex_count; + + panfrost_statistics_record(ctx, info, draw); + + struct mali_invocation_packed invocation; + if (info->instance_count > 1) { + panfrost_pack_work_groups_compute(&invocation, + 1, vertex_count, info->instance_count, + 1, 1, 1, true, false); + } else { + pan_pack(&invocation, INVOCATION, cfg) { + cfg.invocations = MALI_POSITIVE(vertex_count); + cfg.size_y_shift = 0; + cfg.size_z_shift = 0; + cfg.workgroups_x_shift = 0; + cfg.workgroups_y_shift = 0; + cfg.workgroups_z_shift = 32; + cfg.thread_group_split = MALI_SPLIT_MIN_EFFICIENT; + } + } + + /* Emit all sort of descriptors. */ + mali_ptr varyings = 0, vs_vary = 0, fs_vary = 0, pos = 0, psiz = 0; + + panfrost_emit_varying_descriptor(batch, + ctx->padded_count * + ctx->instance_count, + &vs_vary, &fs_vary, &varyings, + NULL, &pos, &psiz, + info->mode == PIPE_PRIM_POINTS); + + mali_ptr attribs, attrib_bufs; + attribs = panfrost_emit_vertex_data(batch, &attrib_bufs); + + panfrost_update_state_3d(batch); + panfrost_update_state_vs(batch); + panfrost_update_state_fs(batch); + panfrost_clean_state_3d(ctx); + + /* Fire off the draw itself */ + panfrost_draw_emit_vertex(batch, info, &invocation, + vs_vary, varyings, attribs, attrib_bufs, vertex.cpu); + panfrost_draw_emit_tiler(batch, info, draw, &invocation, indices, + fs_vary, varyings, pos, psiz, tiler.cpu); + panfrost_emit_vertex_tiler_jobs(batch, &vertex, &tiler); + + /* Increment transform feedback offsets */ + panfrost_update_streamout_offsets(ctx); +} + +static void +panfrost_indirect_draw(struct panfrost_batch *batch, + const struct pipe_draw_info *info, + unsigned drawid_offset, + const struct pipe_draw_indirect_info *indirect, + const struct pipe_draw_start_count_bias *draw) +{ + /* Indirect draw count and multi-draw not supported. */ + assert(indirect->draw_count == 1 && !indirect->indirect_draw_count); + + struct panfrost_context *ctx = batch->ctx; + struct panfrost_device *dev = pan_device(ctx->base.screen); + + /* TODO: update statistics (see panfrost_statistics_record()) */ + /* TODO: Increment transform feedback offsets */ + assert(ctx->streamout.num_targets == 0); + + assert(ctx->draw_modes & (1 << info->mode)); + ctx->active_prim = info->mode; + ctx->drawid = drawid_offset; + ctx->indirect_draw = true; + + struct panfrost_ptr tiler = + pan_pool_alloc_aligned(&batch->pool.base, + pan_is_bifrost(dev) ? + MALI_BIFROST_TILER_JOB_LENGTH : + MALI_MIDGARD_TILER_JOB_LENGTH, + 64); + struct panfrost_ptr vertex = + pan_pool_alloc_aligned(&batch->pool.base, + 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); + struct panfrost_resource *rsrc = pan_resource(info->index.resource); + index_buf = rsrc->image.data.bo; + panfrost_batch_read_rsrc(batch, rsrc, PIPE_SHADER_VERTEX); + } + + 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; + + /* Set the {first,base}_vertex sysvals to NULL. Will be updated if the + * vertex shader uses gl_VertexID or gl_BaseVertex. + */ + ctx->first_vertex_sysval_ptr = 0; + ctx->base_vertex_sysval_ptr = 0; + ctx->base_instance_sysval_ptr = 0; + + panfrost_update_state_3d(batch); + panfrost_update_state_vs(batch); + panfrost_update_state_fs(batch); + panfrost_clean_state_3d(ctx); + + bool point_coord_replace = (info->mode == PIPE_PRIM_POINTS); + + panfrost_emit_varying_descriptor(batch, 0, + &vs_vary, &fs_vary, &varyings, + &varying_buf_count, &pos, &psiz, + point_coord_replace); + + 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, vs_vary, varyings, + attribs, attrib_bufs, vertex.cpu); + panfrost_draw_emit_tiler(batch, info, draw, &invocation, + 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, + PIPE_SHADER_VERTEX); + } + + 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_read_rsrc(batch, draw_buf, PIPE_SHADER_VERTEX); + + struct pan_indirect_draw_info draw_info = { + .last_indirect_draw = batch->indirect_draw_job_id, + .draw_buf = draw_buf->image.data.bo->ptr.gpu + indirect->offset, + .index_buf = index_buf ? index_buf->ptr.gpu : 0, + .first_vertex_sysval = ctx->first_vertex_sysval_ptr, + .base_vertex_sysval = ctx->base_vertex_sysval_ptr, + .base_instance_sysval = ctx->base_instance_sysval_ptr, + .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.base, + &batch->scoreboard, + &draw_info, + &batch->indirect_draw_ctx); + + panfrost_emit_vertex_tiler_jobs(batch, &vertex, &tiler); +} + +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); + struct panfrost_device *dev = pan_device(pipe->screen); + + if (!panfrost_render_condition_check(ctx)) + return; + + /* Emulate indirect draws when debugging */ + if (dev->debug & PAN_DBG_NOINDIRECT && indirect && indirect->buffer) { + assert(num_draws == 1); + util_draw_indirect(pipe, info, indirect); + return; + } + + /* Do some common setup */ + struct panfrost_batch *batch = panfrost_get_batch_for_fbo(ctx); + + /* Don't add too many jobs to a single batch. Hardware has a hard limit + * of 65536 jobs, but we choose a smaller soft limit (arbitrary) to + * avoid the risk of timeouts. This might not be a good idea. */ + if (unlikely(batch->scoreboard.job_index > 10000)) + batch = panfrost_get_fresh_batch_for_fbo(ctx); + + unsigned zs_draws = ctx->depth_stencil->draws; + batch->draws |= zs_draws; + batch->resolve |= zs_draws; + + /* Mark everything dirty when debugging */ + if (unlikely(dev->debug & PAN_DBG_DIRTY)) + panfrost_dirty_state_all(ctx); + + /* Conservatively assume draw parameters always change */ + ctx->dirty |= PAN_DIRTY_PARAMS | PAN_DIRTY_DRAWID; + + if (indirect) { + assert(num_draws == 1); + + if (indirect->count_from_stream_output) { + struct pipe_draw_start_count_bias tmp_draw = *draws; + struct panfrost_streamout_target *so = + pan_so_target(indirect->count_from_stream_output); + + tmp_draw.start = 0; + tmp_draw.count = so->offset; + tmp_draw.index_bias = 0; + panfrost_direct_draw(batch, info, drawid_offset, &tmp_draw); + return; + } + + panfrost_indirect_draw(batch, info, drawid_offset, indirect, &draws[0]); + return; + } + + 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]); + + if (tmp_info.increment_draw_id) { + ctx->dirty |= PAN_DIRTY_DRAWID; + drawid++; + } + } + +} + +void +panfrost_cmdstream_context_init(struct pipe_context *pipe) +{ + pipe->draw_vbo = panfrost_draw_vbo; +} diff --git a/src/gallium/drivers/panfrost/pan_context.c b/src/gallium/drivers/panfrost/pan_context.c index 95f3f7ee222..2694678fbe5 100644 --- a/src/gallium/drivers/panfrost/pan_context.c +++ b/src/gallium/drivers/panfrost/pan_context.c @@ -44,7 +44,6 @@ #include "util/format/u_format.h" #include "util/u_prim.h" #include "util/u_prim_restart.h" -#include "util/u_draw.h" #include "indices/u_primconvert.h" #include "tgsi/tgsi_parse.h" #include "tgsi/tgsi_from_mesa.h" @@ -53,7 +52,6 @@ #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" @@ -130,662 +128,6 @@ panfrost_set_frontend_noop(struct pipe_context *pipe, bool enable) ctx->is_noop = enable; } -#define DEFINE_CASE(c) case PIPE_PRIM_##c: return MALI_DRAW_MODE_##c; - -static uint8_t -pan_draw_mode(enum pipe_prim_type mode) -{ - switch (mode) { - DEFINE_CASE(POINTS); - DEFINE_CASE(LINES); - DEFINE_CASE(LINE_LOOP); - DEFINE_CASE(LINE_STRIP); - DEFINE_CASE(TRIANGLES); - DEFINE_CASE(TRIANGLE_STRIP); - DEFINE_CASE(TRIANGLE_FAN); - DEFINE_CASE(QUADS); - DEFINE_CASE(QUAD_STRIP); - DEFINE_CASE(POLYGON); - - default: - unreachable("Invalid draw mode"); - } -} - -#undef DEFINE_CASE - -/* Count generated primitives (when there is no geom/tess shaders) for - * transform feedback */ - -static void -panfrost_statistics_record( - struct panfrost_context *ctx, - const struct pipe_draw_info *info, - const struct pipe_draw_start_count_bias *draw) -{ - if (!ctx->active_queries) - return; - - uint32_t prims = u_prims_for_vertices(info->mode, draw->count); - ctx->prims_generated += prims; - - if (!ctx->streamout.num_targets) - return; - - ctx->tf_prims_generated += prims; -} - -static void -panfrost_update_streamout_offsets(struct panfrost_context *ctx) -{ - for (unsigned i = 0; i < ctx->streamout.num_targets; ++i) { - unsigned count; - - count = u_stream_outputs_for_vertices(ctx->active_prim, - ctx->vertex_count); - pan_so_target(ctx->streamout.targets[i])->offset += count; - } -} - -static inline void -pan_emit_draw_descs(struct panfrost_batch *batch, - struct MALI_DRAW *d, enum pipe_shader_type st) -{ - d->offset_start = batch->ctx->offset_start; - d->instance_size = batch->ctx->instance_count > 1 ? - batch->ctx->padded_count : 1; - - d->uniform_buffers = batch->uniform_buffers[st]; - d->push_uniforms = batch->push_uniforms[st]; - d->textures = batch->textures[st]; - d->samplers = batch->samplers[st]; -} - -static inline enum mali_index_type -panfrost_translate_index_size(unsigned size) -{ - STATIC_ASSERT(MALI_INDEX_TYPE_NONE == 0); - STATIC_ASSERT(MALI_INDEX_TYPE_UINT8 == 1); - STATIC_ASSERT(MALI_INDEX_TYPE_UINT16 == 2); - - return (size == 4) ? MALI_INDEX_TYPE_UINT32 : size; -} - -static void -panfrost_draw_emit_vertex(struct panfrost_batch *batch, - const struct pipe_draw_info *info, - void *invocation_template, - mali_ptr vs_vary, mali_ptr varyings, - mali_ptr attribs, mali_ptr attrib_bufs, - void *job) -{ - struct panfrost_context *ctx = batch->ctx; - struct panfrost_device *device = pan_device(ctx->base.screen); - - void *section = - pan_section_ptr(job, COMPUTE_JOB, INVOCATION); - memcpy(section, invocation_template, MALI_INVOCATION_LENGTH); - - pan_section_pack(job, COMPUTE_JOB, PARAMETERS, cfg) { - cfg.job_task_split = 5; - } - - pan_section_pack(job, COMPUTE_JOB, DRAW, cfg) { - cfg.draw_descriptor_is_64b = true; - if (!pan_is_bifrost(device)) - cfg.texture_descriptor_is_64b = true; - cfg.state = batch->rsd[PIPE_SHADER_VERTEX]; - cfg.attributes = attribs; - cfg.attribute_buffers = attrib_bufs; - cfg.varyings = vs_vary; - cfg.varying_buffers = vs_vary ? varyings : 0; - cfg.thread_storage = batch->tls.gpu; - pan_emit_draw_descs(batch, &cfg, PIPE_SHADER_VERTEX); - } - - pan_section_pack(job, COMPUTE_JOB, DRAW_PADDING, cfg); -} - -static void -panfrost_emit_primitive_size(struct panfrost_context *ctx, - bool points, mali_ptr size_array, - void *prim_size) -{ - struct panfrost_rasterizer *rast = ctx->rasterizer; - - pan_pack(prim_size, PRIMITIVE_SIZE, cfg) { - if (panfrost_writes_point_size(ctx)) { - cfg.size_array = size_array; - } else { - cfg.constant = points ? - rast->base.point_size : - rast->base.line_width; - } - } -} - -static bool -panfrost_is_implicit_prim_restart(const struct pipe_draw_info *info) -{ - unsigned implicit_index = (1 << (info->index_size * 8)) - 1; - bool implicit = info->restart_index == implicit_index; - return info->primitive_restart && implicit; -} - -static inline void -panfrost_update_state_tex(struct panfrost_batch *batch, - enum pipe_shader_type st) -{ - struct panfrost_context *ctx = batch->ctx; - struct panfrost_shader_state *ss = panfrost_get_shader_state(ctx, st); - - unsigned dirty_3d = ctx->dirty; - unsigned dirty = ctx->dirty_shader[st]; - - if (dirty & PAN_DIRTY_STAGE_TEXTURE) { - batch->textures[st] = - panfrost_emit_texture_descriptors(batch, st); - } - - if (dirty & PAN_DIRTY_STAGE_SAMPLER) { - batch->samplers[st] = - panfrost_emit_sampler_descriptors(batch, st); - } - - if ((dirty & ss->dirty_shader) || (dirty_3d & ss->dirty_3d)) { - batch->uniform_buffers[st] = panfrost_emit_const_buf(batch, st, - &batch->push_uniforms[st]); - } -} - -static inline void -panfrost_update_state_3d(struct panfrost_batch *batch) -{ - unsigned dirty = batch->ctx->dirty; - - if (dirty & (PAN_DIRTY_VIEWPORT | PAN_DIRTY_SCISSOR)) - batch->viewport = panfrost_emit_viewport(batch); - - if (dirty & PAN_DIRTY_TLS_SIZE) - panfrost_batch_adjust_stack_size(batch); -} - -static void -panfrost_update_state_vs(struct panfrost_batch *batch) -{ - enum pipe_shader_type st = PIPE_SHADER_VERTEX; - unsigned dirty = batch->ctx->dirty_shader[st]; - - if (dirty & PAN_DIRTY_STAGE_RENDERER) - batch->rsd[st] = panfrost_emit_compute_shader_meta(batch, st); - - panfrost_update_state_tex(batch, st); -} - -static void -panfrost_update_state_fs(struct panfrost_batch *batch) -{ - enum pipe_shader_type st = PIPE_SHADER_FRAGMENT; - unsigned dirty = batch->ctx->dirty_shader[st]; - - if (dirty & PAN_DIRTY_STAGE_RENDERER) - batch->rsd[st] = panfrost_emit_frag_shader_meta(batch); - - if (dirty & PAN_DIRTY_STAGE_IMAGE) { - batch->attribs[st] = panfrost_emit_image_attribs(batch, - &batch->attrib_bufs[st], st); - } - - panfrost_update_state_tex(batch, st); -} - -static void -panfrost_draw_emit_tiler(struct panfrost_batch *batch, - const struct pipe_draw_info *info, - const struct pipe_draw_start_count_bias *draw, - void *invocation_template, - mali_ptr indices, mali_ptr fs_vary, mali_ptr varyings, - mali_ptr pos, mali_ptr psiz, void *job) -{ - struct panfrost_context *ctx = batch->ctx; - struct pipe_rasterizer_state *rast = &ctx->rasterizer->base; - struct panfrost_device *device = pan_device(ctx->base.screen); - - void *section = pan_is_bifrost(device) ? - pan_section_ptr(job, BIFROST_TILER_JOB, INVOCATION) : - pan_section_ptr(job, MIDGARD_TILER_JOB, INVOCATION); - memcpy(section, invocation_template, MALI_INVOCATION_LENGTH); - - section = pan_is_bifrost(device) ? - pan_section_ptr(job, BIFROST_TILER_JOB, PRIMITIVE) : - pan_section_ptr(job, MIDGARD_TILER_JOB, PRIMITIVE); - pan_pack(section, PRIMITIVE, cfg) { - cfg.draw_mode = pan_draw_mode(info->mode); - if (panfrost_writes_point_size(ctx)) - cfg.point_size_array_format = MALI_POINT_SIZE_ARRAY_FORMAT_FP16; - - /* For line primitives, PRIMITIVE.first_provoking_vertex must - * be set to true and the provoking vertex is selected with - * DRAW.flat_shading_vertex. - */ - if (info->mode == PIPE_PRIM_LINES || - info->mode == PIPE_PRIM_LINE_LOOP || - info->mode == PIPE_PRIM_LINE_STRIP) - cfg.first_provoking_vertex = true; - else - cfg.first_provoking_vertex = rast->flatshade_first; - - if (panfrost_is_implicit_prim_restart(info)) { - cfg.primitive_restart = MALI_PRIMITIVE_RESTART_IMPLICIT; - } else if (info->primitive_restart) { - cfg.primitive_restart = MALI_PRIMITIVE_RESTART_EXPLICIT; - cfg.primitive_restart_index = info->restart_index; - } - - cfg.job_task_split = 6; - - cfg.index_count = ctx->indirect_draw ? 1 : draw->count; - cfg.index_type = panfrost_translate_index_size(info->index_size); - - if (cfg.index_type) { - cfg.indices = indices; - cfg.base_vertex_offset = draw->index_bias - ctx->offset_start; - } - } - - bool points = info->mode == PIPE_PRIM_POINTS; - void *prim_size = pan_is_bifrost(device) ? - pan_section_ptr(job, BIFROST_TILER_JOB, PRIMITIVE_SIZE) : - pan_section_ptr(job, MIDGARD_TILER_JOB, PRIMITIVE_SIZE); - - if (pan_is_bifrost(device)) { - panfrost_emit_primitive_size(ctx, points, psiz, prim_size); - pan_section_pack(job, BIFROST_TILER_JOB, TILER, cfg) { - cfg.address = panfrost_batch_get_bifrost_tiler(batch, ~0); - } - pan_section_pack(job, BIFROST_TILER_JOB, PADDING, padding) {} - } - - section = pan_is_bifrost(device) ? - pan_section_ptr(job, BIFROST_TILER_JOB, DRAW) : - pan_section_ptr(job, MIDGARD_TILER_JOB, DRAW); - pan_pack(section, DRAW, cfg) { - cfg.four_components_per_vertex = true; - cfg.draw_descriptor_is_64b = true; - if (!pan_is_bifrost(device)) - cfg.texture_descriptor_is_64b = true; - cfg.front_face_ccw = rast->front_ccw; - cfg.cull_front_face = rast->cull_face & PIPE_FACE_FRONT; - cfg.cull_back_face = rast->cull_face & PIPE_FACE_BACK; - cfg.position = pos; - cfg.state = batch->rsd[PIPE_SHADER_FRAGMENT]; - cfg.attributes = batch->attribs[PIPE_SHADER_FRAGMENT]; - cfg.attribute_buffers = batch->attrib_bufs[PIPE_SHADER_FRAGMENT]; - cfg.viewport = batch->viewport; - cfg.varyings = fs_vary; - cfg.varying_buffers = fs_vary ? varyings : 0; - cfg.thread_storage = batch->tls.gpu; - - /* For all primitives but lines DRAW.flat_shading_vertex must - * be set to 0 and the provoking vertex is selected with the - * PRIMITIVE.first_provoking_vertex field. - */ - if (info->mode == PIPE_PRIM_LINES || - info->mode == PIPE_PRIM_LINE_LOOP || - info->mode == PIPE_PRIM_LINE_STRIP) { - /* The logic is inverted on bifrost. */ - cfg.flat_shading_vertex = - pan_is_bifrost(device) ? - rast->flatshade_first : !rast->flatshade_first; - } - - pan_emit_draw_descs(batch, &cfg, PIPE_SHADER_FRAGMENT); - - if (ctx->occlusion_query && ctx->active_queries) { - if (ctx->occlusion_query->type == PIPE_QUERY_OCCLUSION_COUNTER) - cfg.occlusion_query = MALI_OCCLUSION_MODE_COUNTER; - else - cfg.occlusion_query = MALI_OCCLUSION_MODE_PREDICATE; - - struct panfrost_resource *rsrc = pan_resource(ctx->occlusion_query->rsrc); - cfg.occlusion = rsrc->image.data.bo->ptr.gpu; - panfrost_batch_write_rsrc(ctx->batch, rsrc, - PIPE_SHADER_FRAGMENT); - } - } - - if (!pan_is_bifrost(device)) - panfrost_emit_primitive_size(ctx, points, psiz, prim_size); - else - pan_section_pack(job, BIFROST_TILER_JOB, DRAW_PADDING, cfg); -} - -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) -{ - if (!draw->count || !info->instance_count) - return; - - struct panfrost_context *ctx = batch->ctx; - struct panfrost_device *device = pan_device(ctx->base.screen); - - /* Fallback for unsupported modes */ - if (!(ctx->draw_modes & BITFIELD_BIT(info->mode))) { - if (draw->count < 4) { - /* Degenerate case? */ - return; - } - - util_primconvert_save_rasterizer_state(ctx->primconvert, &ctx->rasterizer->base); - util_primconvert_draw_vbo(ctx->primconvert, info, drawid_offset, NULL, draw, 1); - return; - } - - /* Take into account a negative bias */ - ctx->indirect_draw = false; - ctx->vertex_count = draw->count + (info->index_size ? abs(draw->index_bias) : 0); - ctx->instance_count = info->instance_count; - ctx->base_vertex = info->index_size ? draw->index_bias : 0; - ctx->base_instance = info->start_instance; - ctx->active_prim = info->mode; - ctx->drawid = drawid_offset; - - struct panfrost_ptr tiler = - pan_is_bifrost(device) ? - pan_pool_alloc_desc(&batch->pool.base, BIFROST_TILER_JOB) : - pan_pool_alloc_desc(&batch->pool.base, MIDGARD_TILER_JOB); - struct panfrost_ptr vertex = - pan_pool_alloc_desc(&batch->pool.base, COMPUTE_JOB); - - unsigned vertex_count = ctx->vertex_count; - - unsigned min_index = 0, max_index = 0; - mali_ptr indices = 0; - - if (info->index_size) { - indices = panfrost_get_index_buffer_bounded(batch, info, draw, - &min_index, - &max_index); - - /* Use the corresponding values */ - vertex_count = max_index - min_index + 1; - ctx->offset_start = min_index + draw->index_bias; - } else { - ctx->offset_start = draw->start; - } - - if (info->instance_count > 1) - ctx->padded_count = panfrost_padded_vertex_count(vertex_count); - else - ctx->padded_count = vertex_count; - - panfrost_statistics_record(ctx, info, draw); - - struct mali_invocation_packed invocation; - if (info->instance_count > 1) { - panfrost_pack_work_groups_compute(&invocation, - 1, vertex_count, info->instance_count, - 1, 1, 1, true, false); - } else { - pan_pack(&invocation, INVOCATION, cfg) { - cfg.invocations = MALI_POSITIVE(vertex_count); - cfg.size_y_shift = 0; - cfg.size_z_shift = 0; - cfg.workgroups_x_shift = 0; - cfg.workgroups_y_shift = 0; - cfg.workgroups_z_shift = 32; - cfg.thread_group_split = MALI_SPLIT_MIN_EFFICIENT; - } - } - - /* Emit all sort of descriptors. */ - mali_ptr varyings = 0, vs_vary = 0, fs_vary = 0, pos = 0, psiz = 0; - - panfrost_emit_varying_descriptor(batch, - ctx->padded_count * - ctx->instance_count, - &vs_vary, &fs_vary, &varyings, - NULL, &pos, &psiz, - info->mode == PIPE_PRIM_POINTS); - - mali_ptr attribs, attrib_bufs; - attribs = panfrost_emit_vertex_data(batch, &attrib_bufs); - - panfrost_update_state_3d(batch); - panfrost_update_state_vs(batch); - panfrost_update_state_fs(batch); - panfrost_clean_state_3d(ctx); - - /* Fire off the draw itself */ - panfrost_draw_emit_vertex(batch, info, &invocation, - vs_vary, varyings, attribs, attrib_bufs, vertex.cpu); - panfrost_draw_emit_tiler(batch, info, draw, &invocation, indices, - fs_vary, varyings, pos, psiz, tiler.cpu); - panfrost_emit_vertex_tiler_jobs(batch, &vertex, &tiler); - - /* Increment transform feedback offsets */ - panfrost_update_streamout_offsets(ctx); -} - -static void -panfrost_indirect_draw(struct panfrost_batch *batch, - const struct pipe_draw_info *info, - unsigned drawid_offset, - const struct pipe_draw_indirect_info *indirect, - const struct pipe_draw_start_count_bias *draw) -{ - /* Indirect draw count and multi-draw not supported. */ - assert(indirect->draw_count == 1 && !indirect->indirect_draw_count); - - struct panfrost_context *ctx = batch->ctx; - struct panfrost_device *dev = pan_device(ctx->base.screen); - - /* TODO: update statistics (see panfrost_statistics_record()) */ - /* TODO: Increment transform feedback offsets */ - assert(ctx->streamout.num_targets == 0); - - assert(ctx->draw_modes & (1 << info->mode)); - ctx->active_prim = info->mode; - ctx->drawid = drawid_offset; - ctx->indirect_draw = true; - - struct panfrost_ptr tiler = - pan_pool_alloc_aligned(&batch->pool.base, - pan_is_bifrost(dev) ? - MALI_BIFROST_TILER_JOB_LENGTH : - MALI_MIDGARD_TILER_JOB_LENGTH, - 64); - struct panfrost_ptr vertex = - pan_pool_alloc_aligned(&batch->pool.base, - 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); - struct panfrost_resource *rsrc = pan_resource(info->index.resource); - index_buf = rsrc->image.data.bo; - panfrost_batch_read_rsrc(batch, rsrc, PIPE_SHADER_VERTEX); - } - - 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; - - /* Set the {first,base}_vertex sysvals to NULL. Will be updated if the - * vertex shader uses gl_VertexID or gl_BaseVertex. - */ - ctx->first_vertex_sysval_ptr = 0; - ctx->base_vertex_sysval_ptr = 0; - ctx->base_instance_sysval_ptr = 0; - - panfrost_update_state_3d(batch); - panfrost_update_state_vs(batch); - panfrost_update_state_fs(batch); - panfrost_clean_state_3d(ctx); - - bool point_coord_replace = (info->mode == PIPE_PRIM_POINTS); - - panfrost_emit_varying_descriptor(batch, 0, - &vs_vary, &fs_vary, &varyings, - &varying_buf_count, &pos, &psiz, - point_coord_replace); - - 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, vs_vary, varyings, - attribs, attrib_bufs, vertex.cpu); - panfrost_draw_emit_tiler(batch, info, draw, &invocation, - 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, - PIPE_SHADER_VERTEX); - } - - 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_read_rsrc(batch, draw_buf, PIPE_SHADER_VERTEX); - - struct pan_indirect_draw_info draw_info = { - .last_indirect_draw = batch->indirect_draw_job_id, - .draw_buf = draw_buf->image.data.bo->ptr.gpu + indirect->offset, - .index_buf = index_buf ? index_buf->ptr.gpu : 0, - .first_vertex_sysval = ctx->first_vertex_sysval_ptr, - .base_vertex_sysval = ctx->base_vertex_sysval_ptr, - .base_instance_sysval = ctx->base_instance_sysval_ptr, - .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.base, - &batch->scoreboard, - &draw_info, - &batch->indirect_draw_ctx); - - panfrost_emit_vertex_tiler_jobs(batch, &vertex, &tiler); -} - -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); - struct panfrost_device *dev = pan_device(pipe->screen); - - if (!panfrost_render_condition_check(ctx)) - return; - - /* Emulate indirect draws when debugging */ - if (dev->debug & PAN_DBG_NOINDIRECT && indirect && indirect->buffer) { - assert(num_draws == 1); - util_draw_indirect(pipe, info, indirect); - return; - } - - /* Do some common setup */ - struct panfrost_batch *batch = panfrost_get_batch_for_fbo(ctx); - - /* Don't add too many jobs to a single batch. Hardware has a hard limit - * of 65536 jobs, but we choose a smaller soft limit (arbitrary) to - * avoid the risk of timeouts. This might not be a good idea. */ - if (unlikely(batch->scoreboard.job_index > 10000)) - batch = panfrost_get_fresh_batch_for_fbo(ctx); - - unsigned zs_draws = ctx->depth_stencil->draws; - batch->draws |= zs_draws; - batch->resolve |= zs_draws; - - /* Mark everything dirty when debugging */ - if (unlikely(dev->debug & PAN_DBG_DIRTY)) - panfrost_dirty_state_all(ctx); - - /* Conservatively assume draw parameters always change */ - ctx->dirty |= PAN_DIRTY_PARAMS | PAN_DIRTY_DRAWID; - - if (indirect) { - assert(num_draws == 1); - - if (indirect->count_from_stream_output) { - struct pipe_draw_start_count_bias tmp_draw = *draws; - struct panfrost_streamout_target *so = - pan_so_target(indirect->count_from_stream_output); - - tmp_draw.start = 0; - tmp_draw.count = so->offset; - tmp_draw.index_bias = 0; - panfrost_direct_draw(batch, info, drawid_offset, &tmp_draw); - return; - } - - panfrost_indirect_draw(batch, info, drawid_offset, indirect, &draws[0]); - return; - } - - 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]); - - if (tmp_info.increment_draw_id) { - ctx->dirty |= PAN_DIRTY_DRAWID; - drawid++; - } - } - -} - -/* CSO state */ static void panfrost_generic_cso_delete(struct pipe_context *pctx, void *hwcso) @@ -1945,7 +1287,6 @@ panfrost_create_context(struct pipe_screen *screen, void *priv, unsigned flags) gallium->flush = panfrost_flush; gallium->clear = panfrost_clear; - gallium->draw_vbo = panfrost_draw_vbo; gallium->texture_barrier = panfrost_texture_barrier; gallium->set_frontend_noop = panfrost_set_frontend_noop; @@ -2005,6 +1346,7 @@ panfrost_create_context(struct pipe_screen *screen, void *priv, unsigned flags) gallium->stream_output_target_destroy = panfrost_stream_output_target_destroy; gallium->set_stream_output_targets = panfrost_set_stream_output_targets; + panfrost_cmdstream_context_init(gallium); panfrost_resource_context_init(gallium); panfrost_blend_context_init(gallium); panfrost_compute_context_init(gallium); diff --git a/src/gallium/drivers/panfrost/pan_context.h b/src/gallium/drivers/panfrost/pan_context.h index 0b460a10785..ff50f3c3897 100644 --- a/src/gallium/drivers/panfrost/pan_context.h +++ b/src/gallium/drivers/panfrost/pan_context.h @@ -437,4 +437,7 @@ panfrost_clean_state_3d(struct panfrost_context *ctx) } } +void +panfrost_cmdstream_context_init(struct pipe_context *pipe); + #endif