X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fgallium%2Fdrivers%2Ffreedreno%2Ffreedreno_draw.c;h=a5dae976607af1c3137a957582b19ac2db14f2d8;hb=00f9d4b1fdbfd9bf00c4eb2160ae85057369e8a1;hp=a4724221b12522e458c8ef8f8aeb526c48c4e2a5;hpb=8bf2b5db786b8608ddd7c83fffa695ae011bf6b3;p=mesa.git diff --git a/src/gallium/drivers/freedreno/freedreno_draw.c b/src/gallium/drivers/freedreno/freedreno_draw.c index a4724221b12..a5dae976607 100644 --- a/src/gallium/drivers/freedreno/freedreno_draw.c +++ b/src/gallium/drivers/freedreno/freedreno_draw.c @@ -47,7 +47,7 @@ resource_read(struct fd_batch *batch, struct pipe_resource *prsc) { if (!prsc) return; - fd_batch_resource_used(batch, fd_resource(prsc), false); + fd_batch_resource_read(batch, fd_resource(prsc)); } static void @@ -55,70 +55,15 @@ resource_written(struct fd_batch *batch, struct pipe_resource *prsc) { if (!prsc) return; - fd_batch_resource_used(batch, fd_resource(prsc), true); + fd_batch_resource_write(batch, fd_resource(prsc)); } static void -fd_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info) +batch_draw_tracking(struct fd_batch *batch, const struct pipe_draw_info *info) { - struct fd_context *ctx = fd_context(pctx); - struct fd_batch *batch = fd_context_batch(ctx); + struct fd_context *ctx = batch->ctx; struct pipe_framebuffer_state *pfb = &batch->framebuffer; - unsigned i, prims, buffers = 0, restore_buffers = 0; - - /* for debugging problems with indirect draw, it is convenient - * to be able to emulate it, to determine if game is feeding us - * bogus data: - */ - if (info->indirect && (fd_mesa_debug & FD_DBG_NOINDR)) { - util_draw_indirect(pctx, info); - return; - } - - if (!info->count_from_stream_output && !info->indirect && - !info->primitive_restart && - !u_trim_pipe_prim(info->mode, (unsigned*)&info->count)) - return; - - /* TODO: push down the region versions into the tiles */ - if (!fd_render_condition_check(pctx)) - return; - - /* emulate unsupported primitives: */ - if (!fd_supported_prim(ctx, info->mode)) { - if (ctx->streamout.num_targets > 0) - debug_error("stream-out with emulated prims"); - util_primconvert_save_rasterizer_state(ctx->primconvert, ctx->rasterizer); - util_primconvert_draw_vbo(ctx->primconvert, info); - return; - } - - fd_fence_ref(&ctx->last_fence, NULL); - - /* Upload a user index buffer. */ - struct pipe_resource *indexbuf = NULL; - unsigned index_offset = 0; - struct pipe_draw_info new_info; - if (info->index_size) { - if (info->has_user_indices) { - if (!util_upload_index_buffer(pctx, info, &indexbuf, &index_offset, 4)) - return; - new_info = *info; - new_info.index.resource = indexbuf; - new_info.has_user_indices = false; - info = &new_info; - } else { - indexbuf = info->index.resource; - } - } - - if (ctx->in_blit) { - fd_batch_reset(batch); - fd_context_all_dirty(ctx); - } - - batch->blit = ctx->in_blit; - batch->back_blit = ctx->in_shadow; + unsigned buffers = 0, restore_buffers = 0; /* NOTE: needs to be before resource_written(batch->query_buf), otherwise * query_buf may not be created yet. @@ -129,7 +74,7 @@ fd_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info) * Figure out the buffers/features we need: */ - mtx_lock(&ctx->screen->lock); + fd_screen_lock(ctx->screen); if (ctx->dirty & (FD_DIRTY_FRAMEBUFFER | FD_DIRTY_ZSA)) { if (fd_depth_enabled(ctx)) { @@ -162,7 +107,7 @@ fd_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info) if (fd_logicop_enabled(ctx)) batch->gmem_reason |= FD_GMEM_LOGICOP_ENABLED; - for (i = 0; i < pfb->nr_cbufs; i++) { + for (unsigned i = 0; i < pfb->nr_cbufs; i++) { struct pipe_resource *surf; if (!pfb->cbufs[i]) @@ -185,16 +130,19 @@ fd_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info) resource_written(batch, pfb->cbufs[i]->texture); } - /* Mark SSBOs as being written.. we don't actually know which ones are - * read vs written, so just assume the worst - */ + /* Mark SSBOs */ if (ctx->dirty_shader[PIPE_SHADER_FRAGMENT] & FD_DIRTY_SHADER_SSBO) { - foreach_bit(i, ctx->shaderbuf[PIPE_SHADER_FRAGMENT].enabled_mask) - resource_written(batch, ctx->shaderbuf[PIPE_SHADER_FRAGMENT].sb[i].buffer); + const struct fd_shaderbuf_stateobj *so = &ctx->shaderbuf[PIPE_SHADER_FRAGMENT]; + + foreach_bit (i, so->enabled_mask & so->writable_mask) + resource_written(batch, so->sb[i].buffer); + + foreach_bit (i, so->enabled_mask & ~so->writable_mask) + resource_read(batch, so->sb[i].buffer); } if (ctx->dirty_shader[PIPE_SHADER_FRAGMENT] & FD_DIRTY_SHADER_IMAGE) { - foreach_bit(i, ctx->shaderimg[PIPE_SHADER_FRAGMENT].enabled_mask) { + foreach_bit (i, ctx->shaderimg[PIPE_SHADER_FRAGMENT].enabled_mask) { struct pipe_image_view *img = &ctx->shaderimg[PIPE_SHADER_FRAGMENT].si[i]; if (img->access & PIPE_IMAGE_ACCESS_WRITE) @@ -205,25 +153,26 @@ fd_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info) } if (ctx->dirty_shader[PIPE_SHADER_VERTEX] & FD_DIRTY_SHADER_CONST) { - foreach_bit(i, ctx->constbuf[PIPE_SHADER_VERTEX].enabled_mask) + foreach_bit (i, ctx->constbuf[PIPE_SHADER_VERTEX].enabled_mask) resource_read(batch, ctx->constbuf[PIPE_SHADER_VERTEX].cb[i].buffer); } if (ctx->dirty_shader[PIPE_SHADER_FRAGMENT] & FD_DIRTY_SHADER_CONST) { - foreach_bit(i, ctx->constbuf[PIPE_SHADER_FRAGMENT].enabled_mask) + foreach_bit (i, ctx->constbuf[PIPE_SHADER_FRAGMENT].enabled_mask) resource_read(batch, ctx->constbuf[PIPE_SHADER_FRAGMENT].cb[i].buffer); } /* Mark VBOs as being read */ if (ctx->dirty & FD_DIRTY_VTXBUF) { - foreach_bit(i, ctx->vtx.vertexbuf.enabled_mask) { + foreach_bit (i, ctx->vtx.vertexbuf.enabled_mask) { assert(!ctx->vtx.vertexbuf.vb[i].is_user_buffer); resource_read(batch, ctx->vtx.vertexbuf.vb[i].buffer.resource); } } /* Mark index buffer as being read */ - resource_read(batch, indexbuf); + if (info->index_size) + resource_read(batch, info->index.resource); /* Mark indirect draw buffer as being read */ if (info->indirect) @@ -231,18 +180,18 @@ fd_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info) /* Mark textures as being read */ if (ctx->dirty_shader[PIPE_SHADER_VERTEX] & FD_DIRTY_SHADER_TEX) { - foreach_bit(i, ctx->tex[PIPE_SHADER_VERTEX].valid_textures) + foreach_bit (i, ctx->tex[PIPE_SHADER_VERTEX].valid_textures) resource_read(batch, ctx->tex[PIPE_SHADER_VERTEX].textures[i]->texture); } if (ctx->dirty_shader[PIPE_SHADER_FRAGMENT] & FD_DIRTY_SHADER_TEX) { - foreach_bit(i, ctx->tex[PIPE_SHADER_FRAGMENT].valid_textures) + foreach_bit (i, ctx->tex[PIPE_SHADER_FRAGMENT].valid_textures) resource_read(batch, ctx->tex[PIPE_SHADER_FRAGMENT].textures[i]->texture); } /* Mark streamout buffers as being written.. */ if (ctx->dirty & FD_DIRTY_STREAMOUT) { - for (i = 0; i < ctx->streamout.num_targets; i++) + for (unsigned i = 0; i < ctx->streamout.num_targets; i++) if (ctx->streamout.targets[i]) resource_written(batch, ctx->streamout.targets[i]->buffer); } @@ -252,14 +201,92 @@ fd_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info) list_for_each_entry(struct fd_acc_query, aq, &ctx->acc_active_queries, node) resource_written(batch, aq->prsc); - mtx_unlock(&ctx->screen->lock); + fd_screen_unlock(ctx->screen); + + /* any buffers that haven't been cleared yet, we need to restore: */ + batch->restore |= restore_buffers & (FD_BUFFER_ALL & ~batch->invalidated); + /* and any buffers used, need to be resolved: */ + batch->resolve |= buffers; +} + +static void +fd_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info) +{ + struct fd_context *ctx = fd_context(pctx); + + /* for debugging problems with indirect draw, it is convenient + * to be able to emulate it, to determine if game is feeding us + * bogus data: + */ + if (info->indirect && (fd_mesa_debug & FD_DBG_NOINDR)) { + util_draw_indirect(pctx, info); + return; + } + + if (!info->count_from_stream_output && !info->indirect && + !info->primitive_restart && + !u_trim_pipe_prim(info->mode, (unsigned*)&info->count)) + return; + + /* TODO: push down the region versions into the tiles */ + if (!fd_render_condition_check(pctx)) + return; + + /* emulate unsupported primitives: */ + if (!fd_supported_prim(ctx, info->mode)) { + if (ctx->streamout.num_targets > 0) + debug_error("stream-out with emulated prims"); + util_primconvert_save_rasterizer_state(ctx->primconvert, ctx->rasterizer); + util_primconvert_draw_vbo(ctx->primconvert, info); + return; + } + + /* Upload a user index buffer. */ + struct pipe_resource *indexbuf = NULL; + unsigned index_offset = 0; + struct pipe_draw_info new_info; + if (info->index_size) { + if (info->has_user_indices) { + if (!util_upload_index_buffer(pctx, info, &indexbuf, &index_offset, 4)) + return; + new_info = *info; + new_info.index.resource = indexbuf; + new_info.has_user_indices = false; + info = &new_info; + } else { + indexbuf = info->index.resource; + } + } + + struct fd_batch *batch = NULL; + fd_batch_reference(&batch, fd_context_batch(ctx)); + if (ctx->in_discard_blit) { + fd_batch_reset(batch); + fd_context_all_dirty(ctx); + } + + batch_draw_tracking(batch, info); + + if (unlikely(ctx->batch != batch)) { + /* The current batch was flushed in batch_draw_tracking() + * so start anew. We know this won't happen a second time + * since we are dealing with a fresh batch: + */ + fd_batch_reference(&batch, fd_context_batch(ctx)); + batch_draw_tracking(batch, info); + assert(ctx->batch == batch); + } + + batch->blit = ctx->in_discard_blit; + batch->back_blit = ctx->in_shadow; batch->num_draws++; /* Counting prims in sw doesn't work for GS and tesselation. For older * gens we don't have those stages and don't have the hw counters enabled, * so keep the count accurate for non-patch geometry. */ + unsigned prims; if (info->mode != PIPE_PRIM_PATCHES) prims = u_reduced_prims_for_vertices(info->mode, info->count); else @@ -277,12 +304,14 @@ fd_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info) ctx->stats.prims_emitted += prims; ctx->stats.prims_generated += prims; - /* any buffers that haven't been cleared yet, we need to restore: */ - batch->restore |= restore_buffers & (FD_BUFFER_ALL & ~batch->invalidated); - /* and any buffers used, need to be resolved: */ - batch->resolve |= buffers; + /* Clearing last_fence must come after the batch dependency tracking + * (resource_read()/resource_written()), as that can trigger a flush, + * re-populating last_fence + */ + fd_fence_ref(&ctx->last_fence, NULL); - DBG("%p: %x %ux%u num_draws=%u (%s/%s)", batch, buffers, + struct pipe_framebuffer_state *pfb = &batch->framebuffer; + DBG("%p: %ux%u num_draws=%u (%s/%s)", batch, pfb->width, pfb->height, batch->num_draws, util_format_short_name(pipe_surface_format(pfb->cbufs[0])), util_format_short_name(pipe_surface_format(pfb->zsbuf))); @@ -292,38 +321,25 @@ fd_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info) batch->num_vertices += info->count * info->instance_count; - for (i = 0; i < ctx->streamout.num_targets; i++) + for (unsigned i = 0; i < ctx->streamout.num_targets; i++) ctx->streamout.offsets[i] += info->count; if (fd_mesa_debug & FD_DBG_DDRAW) fd_context_all_dirty(ctx); fd_batch_check_size(batch); + fd_batch_reference(&batch, NULL); if (info == &new_info) pipe_resource_reference(&indexbuf, NULL); } static void -fd_clear(struct pipe_context *pctx, unsigned buffers, - const union pipe_color_union *color, double depth, unsigned stencil) +batch_clear_tracking(struct fd_batch *batch, unsigned buffers) { - struct fd_context *ctx = fd_context(pctx); - struct fd_batch *batch = fd_context_batch(ctx); + struct fd_context *ctx = batch->ctx; struct pipe_framebuffer_state *pfb = &batch->framebuffer; unsigned cleared_buffers; - int i; - - /* TODO: push down the region versions into the tiles */ - if (!fd_render_condition_check(pctx)) - return; - - fd_fence_ref(&ctx->last_fence, NULL); - - if (ctx->in_blit) { - fd_batch_reset(batch); - fd_context_all_dirty(ctx); - } /* pctx->clear() is only for full-surface clears, so scissor is * equivalent to having GL_SCISSOR_TEST disabled: @@ -347,10 +363,10 @@ fd_clear(struct pipe_context *pctx, unsigned buffers, batch->resolve |= buffers; batch->needs_flush = true; - mtx_lock(&ctx->screen->lock); + fd_screen_lock(ctx->screen); if (buffers & PIPE_CLEAR_COLOR) - for (i = 0; i < pfb->nr_cbufs; i++) + for (unsigned i = 0; i < pfb->nr_cbufs; i++) if (buffers & (PIPE_CLEAR_COLOR0 << i)) resource_written(batch, pfb->cbufs[i]->texture); @@ -364,8 +380,48 @@ fd_clear(struct pipe_context *pctx, unsigned buffers, list_for_each_entry(struct fd_acc_query, aq, &ctx->acc_active_queries, node) resource_written(batch, aq->prsc); - mtx_unlock(&ctx->screen->lock); + fd_screen_unlock(ctx->screen); +} +static void +fd_clear(struct pipe_context *pctx, unsigned buffers, + const struct pipe_scissor_state *scissor_state, + const union pipe_color_union *color, double depth, + unsigned stencil) +{ + struct fd_context *ctx = fd_context(pctx); + + /* TODO: push down the region versions into the tiles */ + if (!fd_render_condition_check(pctx)) + return; + + struct fd_batch *batch = NULL; + fd_batch_reference(&batch, fd_context_batch(ctx)); + + if (ctx->in_discard_blit) { + fd_batch_reset(batch); + fd_context_all_dirty(ctx); + } + + batch_clear_tracking(batch, buffers); + + if (unlikely(ctx->batch != batch)) { + /* The current batch was flushed in batch_clear_tracking() + * so start anew. We know this won't happen a second time + * since we are dealing with a fresh batch: + */ + fd_batch_reference(&batch, fd_context_batch(ctx)); + batch_clear_tracking(batch, buffers); + assert(ctx->batch == batch); + } + + /* Clearing last_fence must come after the batch dependency tracking + * (resource_read()/resource_written()), as that can trigger a flush, + * re-populating last_fence + */ + fd_fence_ref(&ctx->last_fence, NULL); + + struct pipe_framebuffer_state *pfb = &batch->framebuffer; DBG("%p: %x %ux%u depth=%f, stencil=%u (%s/%s)", batch, buffers, pfb->width, pfb->height, depth, stencil, util_format_short_name(pipe_surface_format(pfb->cbufs[0])), @@ -392,6 +448,7 @@ fd_clear(struct pipe_context *pctx, unsigned buffers, } fd_batch_check_size(batch); + fd_batch_reference(&batch, NULL); } static void @@ -417,21 +474,22 @@ static void fd_launch_grid(struct pipe_context *pctx, const struct pipe_grid_info *info) { struct fd_context *ctx = fd_context(pctx); + const struct fd_shaderbuf_stateobj *so = &ctx->shaderbuf[PIPE_SHADER_COMPUTE]; struct fd_batch *batch, *save_batch = NULL; - unsigned i; batch = fd_bc_alloc_batch(&ctx->screen->batch_cache, ctx, true); fd_batch_reference(&save_batch, ctx->batch); fd_batch_reference(&ctx->batch, batch); fd_context_all_dirty(ctx); - mtx_lock(&ctx->screen->lock); + fd_screen_lock(ctx->screen); - /* Mark SSBOs as being written.. we don't actually know which ones are - * read vs written, so just assume the worst - */ - foreach_bit(i, ctx->shaderbuf[PIPE_SHADER_COMPUTE].enabled_mask) - resource_written(batch, ctx->shaderbuf[PIPE_SHADER_COMPUTE].sb[i].buffer); + /* Mark SSBOs */ + foreach_bit (i, so->enabled_mask & so->writable_mask) + resource_written(batch, so->sb[i].buffer); + + foreach_bit (i, so->enabled_mask & ~so->writable_mask) + resource_read(batch, so->sb[i].buffer); foreach_bit(i, ctx->shaderimg[PIPE_SHADER_COMPUTE].enabled_mask) { struct pipe_image_view *img = @@ -459,12 +517,12 @@ fd_launch_grid(struct pipe_context *pctx, const struct pipe_grid_info *info) if (info->indirect) resource_read(batch, info->indirect); - mtx_unlock(&ctx->screen->lock); + fd_screen_unlock(ctx->screen); batch->needs_flush = true; ctx->launch_grid(ctx, info); - fd_batch_flush(batch, false); + fd_batch_flush(batch); fd_batch_reference(&ctx->batch, save_batch); fd_context_all_dirty(ctx);