1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright (C) 2012 Rob Clark <robclark@freedesktop.org> 3bf215546Sopenharmony_ci * 4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation 7bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 9bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions: 10bf215546Sopenharmony_ci * 11bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next 12bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the 13bf215546Sopenharmony_ci * Software. 14bf215546Sopenharmony_ci * 15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20bf215546Sopenharmony_ci * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21bf215546Sopenharmony_ci * SOFTWARE. 22bf215546Sopenharmony_ci * 23bf215546Sopenharmony_ci * Authors: 24bf215546Sopenharmony_ci * Rob Clark <robclark@freedesktop.org> 25bf215546Sopenharmony_ci */ 26bf215546Sopenharmony_ci 27bf215546Sopenharmony_ci#include "pipe/p_state.h" 28bf215546Sopenharmony_ci#include "util/format/u_format.h" 29bf215546Sopenharmony_ci#include "util/u_draw.h" 30bf215546Sopenharmony_ci#include "util/u_helpers.h" 31bf215546Sopenharmony_ci#include "util/u_memory.h" 32bf215546Sopenharmony_ci#include "util/u_prim.h" 33bf215546Sopenharmony_ci#include "util/u_string.h" 34bf215546Sopenharmony_ci 35bf215546Sopenharmony_ci#include "freedreno_blitter.h" 36bf215546Sopenharmony_ci#include "freedreno_context.h" 37bf215546Sopenharmony_ci#include "freedreno_draw.h" 38bf215546Sopenharmony_ci#include "freedreno_fence.h" 39bf215546Sopenharmony_ci#include "freedreno_query_acc.h" 40bf215546Sopenharmony_ci#include "freedreno_query_hw.h" 41bf215546Sopenharmony_ci#include "freedreno_resource.h" 42bf215546Sopenharmony_ci#include "freedreno_state.h" 43bf215546Sopenharmony_ci#include "freedreno_util.h" 44bf215546Sopenharmony_ci 45bf215546Sopenharmony_cistatic void 46bf215546Sopenharmony_ciresource_read(struct fd_batch *batch, struct pipe_resource *prsc) assert_dt 47bf215546Sopenharmony_ci{ 48bf215546Sopenharmony_ci if (!prsc) 49bf215546Sopenharmony_ci return; 50bf215546Sopenharmony_ci fd_batch_resource_read(batch, fd_resource(prsc)); 51bf215546Sopenharmony_ci} 52bf215546Sopenharmony_ci 53bf215546Sopenharmony_cistatic void 54bf215546Sopenharmony_ciresource_written(struct fd_batch *batch, struct pipe_resource *prsc) assert_dt 55bf215546Sopenharmony_ci{ 56bf215546Sopenharmony_ci if (!prsc) 57bf215546Sopenharmony_ci return; 58bf215546Sopenharmony_ci fd_batch_resource_write(batch, fd_resource(prsc)); 59bf215546Sopenharmony_ci} 60bf215546Sopenharmony_ci 61bf215546Sopenharmony_cistatic void 62bf215546Sopenharmony_cibatch_draw_tracking_for_dirty_bits(struct fd_batch *batch) assert_dt 63bf215546Sopenharmony_ci{ 64bf215546Sopenharmony_ci struct fd_context *ctx = batch->ctx; 65bf215546Sopenharmony_ci struct pipe_framebuffer_state *pfb = &batch->framebuffer; 66bf215546Sopenharmony_ci unsigned buffers = 0, restore_buffers = 0; 67bf215546Sopenharmony_ci 68bf215546Sopenharmony_ci if (ctx->dirty & (FD_DIRTY_FRAMEBUFFER | FD_DIRTY_ZSA)) { 69bf215546Sopenharmony_ci if (fd_depth_enabled(ctx)) { 70bf215546Sopenharmony_ci if (fd_resource(pfb->zsbuf->texture)->valid) { 71bf215546Sopenharmony_ci restore_buffers |= FD_BUFFER_DEPTH; 72bf215546Sopenharmony_ci /* storing packed d/s depth also stores stencil, so we need 73bf215546Sopenharmony_ci * the stencil restored too to avoid invalidating it. 74bf215546Sopenharmony_ci */ 75bf215546Sopenharmony_ci if (pfb->zsbuf->texture->format == PIPE_FORMAT_Z24_UNORM_S8_UINT) 76bf215546Sopenharmony_ci restore_buffers |= FD_BUFFER_STENCIL; 77bf215546Sopenharmony_ci } else { 78bf215546Sopenharmony_ci batch->invalidated |= FD_BUFFER_DEPTH; 79bf215546Sopenharmony_ci } 80bf215546Sopenharmony_ci batch->gmem_reason |= FD_GMEM_DEPTH_ENABLED; 81bf215546Sopenharmony_ci if (fd_depth_write_enabled(ctx)) { 82bf215546Sopenharmony_ci buffers |= FD_BUFFER_DEPTH; 83bf215546Sopenharmony_ci resource_written(batch, pfb->zsbuf->texture); 84bf215546Sopenharmony_ci } else { 85bf215546Sopenharmony_ci resource_read(batch, pfb->zsbuf->texture); 86bf215546Sopenharmony_ci } 87bf215546Sopenharmony_ci } 88bf215546Sopenharmony_ci 89bf215546Sopenharmony_ci if (fd_stencil_enabled(ctx)) { 90bf215546Sopenharmony_ci if (fd_resource(pfb->zsbuf->texture)->valid) { 91bf215546Sopenharmony_ci restore_buffers |= FD_BUFFER_STENCIL; 92bf215546Sopenharmony_ci /* storing packed d/s stencil also stores depth, so we need 93bf215546Sopenharmony_ci * the depth restored too to avoid invalidating it. 94bf215546Sopenharmony_ci */ 95bf215546Sopenharmony_ci if (pfb->zsbuf->texture->format == PIPE_FORMAT_Z24_UNORM_S8_UINT) 96bf215546Sopenharmony_ci restore_buffers |= FD_BUFFER_DEPTH; 97bf215546Sopenharmony_ci } else { 98bf215546Sopenharmony_ci batch->invalidated |= FD_BUFFER_STENCIL; 99bf215546Sopenharmony_ci } 100bf215546Sopenharmony_ci batch->gmem_reason |= FD_GMEM_STENCIL_ENABLED; 101bf215546Sopenharmony_ci buffers |= FD_BUFFER_STENCIL; 102bf215546Sopenharmony_ci resource_written(batch, pfb->zsbuf->texture); 103bf215546Sopenharmony_ci } 104bf215546Sopenharmony_ci } 105bf215546Sopenharmony_ci 106bf215546Sopenharmony_ci if (ctx->dirty & FD_DIRTY_FRAMEBUFFER) { 107bf215546Sopenharmony_ci for (unsigned i = 0; i < pfb->nr_cbufs; i++) { 108bf215546Sopenharmony_ci struct pipe_resource *surf; 109bf215546Sopenharmony_ci 110bf215546Sopenharmony_ci if (!pfb->cbufs[i]) 111bf215546Sopenharmony_ci continue; 112bf215546Sopenharmony_ci 113bf215546Sopenharmony_ci surf = pfb->cbufs[i]->texture; 114bf215546Sopenharmony_ci 115bf215546Sopenharmony_ci if (fd_resource(surf)->valid) { 116bf215546Sopenharmony_ci restore_buffers |= PIPE_CLEAR_COLOR0 << i; 117bf215546Sopenharmony_ci } else { 118bf215546Sopenharmony_ci batch->invalidated |= PIPE_CLEAR_COLOR0 << i; 119bf215546Sopenharmony_ci } 120bf215546Sopenharmony_ci 121bf215546Sopenharmony_ci buffers |= PIPE_CLEAR_COLOR0 << i; 122bf215546Sopenharmony_ci 123bf215546Sopenharmony_ci if (ctx->dirty & FD_DIRTY_FRAMEBUFFER) 124bf215546Sopenharmony_ci resource_written(batch, pfb->cbufs[i]->texture); 125bf215546Sopenharmony_ci } 126bf215546Sopenharmony_ci } 127bf215546Sopenharmony_ci 128bf215546Sopenharmony_ci if (ctx->dirty & FD_DIRTY_BLEND) { 129bf215546Sopenharmony_ci if (ctx->blend->logicop_enable) 130bf215546Sopenharmony_ci batch->gmem_reason |= FD_GMEM_LOGICOP_ENABLED; 131bf215546Sopenharmony_ci for (unsigned i = 0; i < pfb->nr_cbufs; i++) { 132bf215546Sopenharmony_ci if (ctx->blend->rt[i].blend_enable) 133bf215546Sopenharmony_ci batch->gmem_reason |= FD_GMEM_BLEND_ENABLED; 134bf215546Sopenharmony_ci } 135bf215546Sopenharmony_ci } 136bf215546Sopenharmony_ci 137bf215546Sopenharmony_ci /* Mark SSBOs */ 138bf215546Sopenharmony_ci if (ctx->dirty_shader[PIPE_SHADER_FRAGMENT] & FD_DIRTY_SHADER_SSBO) { 139bf215546Sopenharmony_ci const struct fd_shaderbuf_stateobj *so = 140bf215546Sopenharmony_ci &ctx->shaderbuf[PIPE_SHADER_FRAGMENT]; 141bf215546Sopenharmony_ci 142bf215546Sopenharmony_ci u_foreach_bit (i, so->enabled_mask & so->writable_mask) 143bf215546Sopenharmony_ci resource_written(batch, so->sb[i].buffer); 144bf215546Sopenharmony_ci 145bf215546Sopenharmony_ci u_foreach_bit (i, so->enabled_mask & ~so->writable_mask) 146bf215546Sopenharmony_ci resource_read(batch, so->sb[i].buffer); 147bf215546Sopenharmony_ci } 148bf215546Sopenharmony_ci 149bf215546Sopenharmony_ci if (ctx->dirty_shader[PIPE_SHADER_FRAGMENT] & FD_DIRTY_SHADER_IMAGE) { 150bf215546Sopenharmony_ci u_foreach_bit (i, ctx->shaderimg[PIPE_SHADER_FRAGMENT].enabled_mask) { 151bf215546Sopenharmony_ci struct pipe_image_view *img = 152bf215546Sopenharmony_ci &ctx->shaderimg[PIPE_SHADER_FRAGMENT].si[i]; 153bf215546Sopenharmony_ci if (img->access & PIPE_IMAGE_ACCESS_WRITE) 154bf215546Sopenharmony_ci resource_written(batch, img->resource); 155bf215546Sopenharmony_ci else 156bf215546Sopenharmony_ci resource_read(batch, img->resource); 157bf215546Sopenharmony_ci } 158bf215546Sopenharmony_ci } 159bf215546Sopenharmony_ci 160bf215546Sopenharmony_ci u_foreach_bit (s, ctx->bound_shader_stages) { 161bf215546Sopenharmony_ci /* Mark constbuf as being read: */ 162bf215546Sopenharmony_ci if (ctx->dirty_shader[s] & FD_DIRTY_SHADER_CONST) { 163bf215546Sopenharmony_ci u_foreach_bit (i, ctx->constbuf[s].enabled_mask) 164bf215546Sopenharmony_ci resource_read(batch, ctx->constbuf[s].cb[i].buffer); 165bf215546Sopenharmony_ci } 166bf215546Sopenharmony_ci 167bf215546Sopenharmony_ci /* Mark textures as being read */ 168bf215546Sopenharmony_ci if (ctx->dirty_shader[s] & FD_DIRTY_SHADER_TEX) { 169bf215546Sopenharmony_ci u_foreach_bit (i, ctx->tex[s].valid_textures) 170bf215546Sopenharmony_ci resource_read(batch, ctx->tex[s].textures[i]->texture); 171bf215546Sopenharmony_ci } 172bf215546Sopenharmony_ci } 173bf215546Sopenharmony_ci 174bf215546Sopenharmony_ci /* Mark VBOs as being read */ 175bf215546Sopenharmony_ci if (ctx->dirty & FD_DIRTY_VTXBUF) { 176bf215546Sopenharmony_ci u_foreach_bit (i, ctx->vtx.vertexbuf.enabled_mask) { 177bf215546Sopenharmony_ci assert(!ctx->vtx.vertexbuf.vb[i].is_user_buffer); 178bf215546Sopenharmony_ci resource_read(batch, ctx->vtx.vertexbuf.vb[i].buffer.resource); 179bf215546Sopenharmony_ci } 180bf215546Sopenharmony_ci } 181bf215546Sopenharmony_ci 182bf215546Sopenharmony_ci /* Mark streamout buffers as being written.. */ 183bf215546Sopenharmony_ci if (ctx->dirty & FD_DIRTY_STREAMOUT) { 184bf215546Sopenharmony_ci for (unsigned i = 0; i < ctx->streamout.num_targets; i++) 185bf215546Sopenharmony_ci if (ctx->streamout.targets[i]) 186bf215546Sopenharmony_ci resource_written(batch, ctx->streamout.targets[i]->buffer); 187bf215546Sopenharmony_ci } 188bf215546Sopenharmony_ci 189bf215546Sopenharmony_ci /* any buffers that haven't been cleared yet, we need to restore: */ 190bf215546Sopenharmony_ci batch->restore |= restore_buffers & (FD_BUFFER_ALL & ~batch->invalidated); 191bf215546Sopenharmony_ci /* and any buffers used, need to be resolved: */ 192bf215546Sopenharmony_ci batch->resolve |= buffers; 193bf215546Sopenharmony_ci} 194bf215546Sopenharmony_ci 195bf215546Sopenharmony_cistatic void 196bf215546Sopenharmony_cibatch_draw_tracking(struct fd_batch *batch, const struct pipe_draw_info *info, 197bf215546Sopenharmony_ci const struct pipe_draw_indirect_info *indirect) assert_dt 198bf215546Sopenharmony_ci{ 199bf215546Sopenharmony_ci struct fd_context *ctx = batch->ctx; 200bf215546Sopenharmony_ci 201bf215546Sopenharmony_ci /* NOTE: needs to be before resource_written(batch->query_buf), otherwise 202bf215546Sopenharmony_ci * query_buf may not be created yet. 203bf215546Sopenharmony_ci */ 204bf215546Sopenharmony_ci fd_batch_update_queries(batch); 205bf215546Sopenharmony_ci 206bf215546Sopenharmony_ci /* 207bf215546Sopenharmony_ci * Figure out the buffers/features we need: 208bf215546Sopenharmony_ci */ 209bf215546Sopenharmony_ci 210bf215546Sopenharmony_ci fd_screen_lock(ctx->screen); 211bf215546Sopenharmony_ci 212bf215546Sopenharmony_ci if (ctx->dirty & FD_DIRTY_RESOURCE) 213bf215546Sopenharmony_ci batch_draw_tracking_for_dirty_bits(batch); 214bf215546Sopenharmony_ci 215bf215546Sopenharmony_ci /* Mark index buffer as being read */ 216bf215546Sopenharmony_ci if (info->index_size) 217bf215546Sopenharmony_ci resource_read(batch, info->index.resource); 218bf215546Sopenharmony_ci 219bf215546Sopenharmony_ci /* Mark indirect draw buffer as being read */ 220bf215546Sopenharmony_ci if (indirect) { 221bf215546Sopenharmony_ci if (indirect->buffer) 222bf215546Sopenharmony_ci resource_read(batch, indirect->buffer); 223bf215546Sopenharmony_ci if (indirect->count_from_stream_output) 224bf215546Sopenharmony_ci resource_read( 225bf215546Sopenharmony_ci batch, fd_stream_output_target(indirect->count_from_stream_output) 226bf215546Sopenharmony_ci ->offset_buf); 227bf215546Sopenharmony_ci } 228bf215546Sopenharmony_ci 229bf215546Sopenharmony_ci resource_written(batch, batch->query_buf); 230bf215546Sopenharmony_ci 231bf215546Sopenharmony_ci list_for_each_entry (struct fd_acc_query, aq, &ctx->acc_active_queries, node) 232bf215546Sopenharmony_ci resource_written(batch, aq->prsc); 233bf215546Sopenharmony_ci 234bf215546Sopenharmony_ci fd_screen_unlock(ctx->screen); 235bf215546Sopenharmony_ci} 236bf215546Sopenharmony_ci 237bf215546Sopenharmony_cistatic void 238bf215546Sopenharmony_ciupdate_draw_stats(struct fd_context *ctx, const struct pipe_draw_info *info, 239bf215546Sopenharmony_ci const struct pipe_draw_start_count_bias *draws, 240bf215546Sopenharmony_ci unsigned num_draws) assert_dt 241bf215546Sopenharmony_ci{ 242bf215546Sopenharmony_ci ctx->stats.draw_calls++; 243bf215546Sopenharmony_ci 244bf215546Sopenharmony_ci if (ctx->screen->gen < 6) { 245bf215546Sopenharmony_ci /* Counting prims in sw doesn't work for GS and tesselation. For older 246bf215546Sopenharmony_ci * gens we don't have those stages and don't have the hw counters enabled, 247bf215546Sopenharmony_ci * so keep the count accurate for non-patch geometry. 248bf215546Sopenharmony_ci */ 249bf215546Sopenharmony_ci unsigned prims = 0; 250bf215546Sopenharmony_ci if ((info->mode != PIPE_PRIM_PATCHES) && (info->mode != PIPE_PRIM_MAX)) { 251bf215546Sopenharmony_ci for (unsigned i = 0; i < num_draws; i++) { 252bf215546Sopenharmony_ci prims += u_reduced_prims_for_vertices(info->mode, draws[i].count); 253bf215546Sopenharmony_ci } 254bf215546Sopenharmony_ci } 255bf215546Sopenharmony_ci 256bf215546Sopenharmony_ci ctx->stats.prims_generated += prims; 257bf215546Sopenharmony_ci 258bf215546Sopenharmony_ci if (ctx->streamout.num_targets > 0) { 259bf215546Sopenharmony_ci /* Clip the prims we're writing to the size of the SO buffers. */ 260bf215546Sopenharmony_ci enum pipe_prim_type tf_prim = u_decomposed_prim(info->mode); 261bf215546Sopenharmony_ci unsigned verts_written = u_vertices_for_prims(tf_prim, prims); 262bf215546Sopenharmony_ci unsigned remaining_vert_space = 263bf215546Sopenharmony_ci ctx->streamout.max_tf_vtx - ctx->streamout.verts_written; 264bf215546Sopenharmony_ci if (verts_written > remaining_vert_space) { 265bf215546Sopenharmony_ci verts_written = remaining_vert_space; 266bf215546Sopenharmony_ci u_trim_pipe_prim(tf_prim, &remaining_vert_space); 267bf215546Sopenharmony_ci } 268bf215546Sopenharmony_ci ctx->streamout.verts_written += verts_written; 269bf215546Sopenharmony_ci 270bf215546Sopenharmony_ci ctx->stats.prims_emitted += 271bf215546Sopenharmony_ci u_reduced_prims_for_vertices(tf_prim, verts_written); 272bf215546Sopenharmony_ci } 273bf215546Sopenharmony_ci } 274bf215546Sopenharmony_ci} 275bf215546Sopenharmony_ci 276bf215546Sopenharmony_cistatic void 277bf215546Sopenharmony_cifd_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info, 278bf215546Sopenharmony_ci unsigned drawid_offset, 279bf215546Sopenharmony_ci const struct pipe_draw_indirect_info *indirect, 280bf215546Sopenharmony_ci const struct pipe_draw_start_count_bias *draws, unsigned num_draws) in_dt 281bf215546Sopenharmony_ci{ 282bf215546Sopenharmony_ci struct fd_context *ctx = fd_context(pctx); 283bf215546Sopenharmony_ci 284bf215546Sopenharmony_ci /* for debugging problems with indirect draw, it is convenient 285bf215546Sopenharmony_ci * to be able to emulate it, to determine if game is feeding us 286bf215546Sopenharmony_ci * bogus data: 287bf215546Sopenharmony_ci */ 288bf215546Sopenharmony_ci if (indirect && indirect->buffer && FD_DBG(NOINDR)) { 289bf215546Sopenharmony_ci /* num_draws is only applicable for direct draws: */ 290bf215546Sopenharmony_ci assert(num_draws == 1); 291bf215546Sopenharmony_ci util_draw_indirect(pctx, info, indirect); 292bf215546Sopenharmony_ci return; 293bf215546Sopenharmony_ci } 294bf215546Sopenharmony_ci 295bf215546Sopenharmony_ci /* TODO: push down the region versions into the tiles */ 296bf215546Sopenharmony_ci if (!fd_render_condition_check(pctx)) 297bf215546Sopenharmony_ci return; 298bf215546Sopenharmony_ci 299bf215546Sopenharmony_ci /* Upload a user index buffer. */ 300bf215546Sopenharmony_ci struct pipe_resource *indexbuf = NULL; 301bf215546Sopenharmony_ci unsigned index_offset = 0; 302bf215546Sopenharmony_ci struct pipe_draw_info new_info; 303bf215546Sopenharmony_ci if (info->index_size) { 304bf215546Sopenharmony_ci if (info->has_user_indices) { 305bf215546Sopenharmony_ci if (num_draws > 1) { 306bf215546Sopenharmony_ci util_draw_multi(pctx, info, drawid_offset, indirect, draws, num_draws); 307bf215546Sopenharmony_ci return; 308bf215546Sopenharmony_ci } 309bf215546Sopenharmony_ci if (!util_upload_index_buffer(pctx, info, &draws[0], &indexbuf, 310bf215546Sopenharmony_ci &index_offset, 4)) 311bf215546Sopenharmony_ci return; 312bf215546Sopenharmony_ci new_info = *info; 313bf215546Sopenharmony_ci new_info.index.resource = indexbuf; 314bf215546Sopenharmony_ci new_info.has_user_indices = false; 315bf215546Sopenharmony_ci info = &new_info; 316bf215546Sopenharmony_ci } else { 317bf215546Sopenharmony_ci indexbuf = info->index.resource; 318bf215546Sopenharmony_ci } 319bf215546Sopenharmony_ci } 320bf215546Sopenharmony_ci 321bf215546Sopenharmony_ci if ((ctx->streamout.num_targets > 0) && (num_draws > 1)) { 322bf215546Sopenharmony_ci util_draw_multi(pctx, info, drawid_offset, indirect, draws, num_draws); 323bf215546Sopenharmony_ci return; 324bf215546Sopenharmony_ci } 325bf215546Sopenharmony_ci 326bf215546Sopenharmony_ci struct fd_batch *batch = fd_context_batch(ctx); 327bf215546Sopenharmony_ci 328bf215546Sopenharmony_ci batch_draw_tracking(batch, info, indirect); 329bf215546Sopenharmony_ci 330bf215546Sopenharmony_ci while (unlikely(!fd_batch_lock_submit(batch))) { 331bf215546Sopenharmony_ci /* The current batch was flushed in batch_draw_tracking() 332bf215546Sopenharmony_ci * so start anew. We know this won't happen a second time 333bf215546Sopenharmony_ci * since we are dealing with a fresh batch: 334bf215546Sopenharmony_ci */ 335bf215546Sopenharmony_ci fd_batch_reference(&batch, NULL); 336bf215546Sopenharmony_ci batch = fd_context_batch(ctx); 337bf215546Sopenharmony_ci batch_draw_tracking(batch, info, indirect); 338bf215546Sopenharmony_ci assert(ctx->batch == batch); 339bf215546Sopenharmony_ci } 340bf215546Sopenharmony_ci 341bf215546Sopenharmony_ci batch->num_draws++; 342bf215546Sopenharmony_ci 343bf215546Sopenharmony_ci /* Marking the batch as needing flush must come after the batch 344bf215546Sopenharmony_ci * dependency tracking (resource_read()/resource_write()), as that 345bf215546Sopenharmony_ci * can trigger a flush 346bf215546Sopenharmony_ci */ 347bf215546Sopenharmony_ci fd_batch_needs_flush(batch); 348bf215546Sopenharmony_ci 349bf215546Sopenharmony_ci struct pipe_framebuffer_state *pfb = &batch->framebuffer; 350bf215546Sopenharmony_ci DBG("%p: %ux%u num_draws=%u (%s/%s)", batch, pfb->width, pfb->height, 351bf215546Sopenharmony_ci batch->num_draws, 352bf215546Sopenharmony_ci util_format_short_name(pipe_surface_format(pfb->cbufs[0])), 353bf215546Sopenharmony_ci util_format_short_name(pipe_surface_format(pfb->zsbuf))); 354bf215546Sopenharmony_ci 355bf215546Sopenharmony_ci batch->cost += ctx->draw_cost; 356bf215546Sopenharmony_ci 357bf215546Sopenharmony_ci for (unsigned i = 0; i < num_draws; i++) { 358bf215546Sopenharmony_ci ctx->draw_vbo(ctx, info, drawid_offset, indirect, &draws[i], index_offset); 359bf215546Sopenharmony_ci 360bf215546Sopenharmony_ci batch->num_vertices += draws[i].count * info->instance_count; 361bf215546Sopenharmony_ci } 362bf215546Sopenharmony_ci 363bf215546Sopenharmony_ci if (unlikely(ctx->stats_users > 0)) 364bf215546Sopenharmony_ci update_draw_stats(ctx, info, draws, num_draws); 365bf215546Sopenharmony_ci 366bf215546Sopenharmony_ci for (unsigned i = 0; i < ctx->streamout.num_targets; i++) { 367bf215546Sopenharmony_ci assert(num_draws == 1); 368bf215546Sopenharmony_ci ctx->streamout.offsets[i] += draws[0].count; 369bf215546Sopenharmony_ci } 370bf215546Sopenharmony_ci 371bf215546Sopenharmony_ci if (FD_DBG(DDRAW)) 372bf215546Sopenharmony_ci fd_context_all_dirty(ctx); 373bf215546Sopenharmony_ci 374bf215546Sopenharmony_ci assert(!batch->flushed); 375bf215546Sopenharmony_ci 376bf215546Sopenharmony_ci fd_batch_unlock_submit(batch); 377bf215546Sopenharmony_ci fd_batch_check_size(batch); 378bf215546Sopenharmony_ci fd_batch_reference(&batch, NULL); 379bf215546Sopenharmony_ci 380bf215546Sopenharmony_ci if (info == &new_info) 381bf215546Sopenharmony_ci pipe_resource_reference(&indexbuf, NULL); 382bf215546Sopenharmony_ci} 383bf215546Sopenharmony_ci 384bf215546Sopenharmony_cistatic void 385bf215546Sopenharmony_cibatch_clear_tracking(struct fd_batch *batch, unsigned buffers) assert_dt 386bf215546Sopenharmony_ci{ 387bf215546Sopenharmony_ci struct fd_context *ctx = batch->ctx; 388bf215546Sopenharmony_ci struct pipe_framebuffer_state *pfb = &batch->framebuffer; 389bf215546Sopenharmony_ci unsigned cleared_buffers; 390bf215546Sopenharmony_ci 391bf215546Sopenharmony_ci /* pctx->clear() is only for full-surface clears, so scissor is 392bf215546Sopenharmony_ci * equivalent to having GL_SCISSOR_TEST disabled: 393bf215546Sopenharmony_ci */ 394bf215546Sopenharmony_ci batch->max_scissor.minx = 0; 395bf215546Sopenharmony_ci batch->max_scissor.miny = 0; 396bf215546Sopenharmony_ci batch->max_scissor.maxx = pfb->width; 397bf215546Sopenharmony_ci batch->max_scissor.maxy = pfb->height; 398bf215546Sopenharmony_ci 399bf215546Sopenharmony_ci /* for bookkeeping about which buffers have been cleared (and thus 400bf215546Sopenharmony_ci * can fully or partially skip mem2gmem) we need to ignore buffers 401bf215546Sopenharmony_ci * that have already had a draw, in case apps do silly things like 402bf215546Sopenharmony_ci * clear after draw (ie. if you only clear the color buffer, but 403bf215546Sopenharmony_ci * something like alpha-test causes side effects from the draw in 404bf215546Sopenharmony_ci * the depth buffer, etc) 405bf215546Sopenharmony_ci */ 406bf215546Sopenharmony_ci cleared_buffers = buffers & (FD_BUFFER_ALL & ~batch->restore); 407bf215546Sopenharmony_ci batch->cleared |= buffers; 408bf215546Sopenharmony_ci batch->invalidated |= cleared_buffers; 409bf215546Sopenharmony_ci 410bf215546Sopenharmony_ci batch->resolve |= buffers; 411bf215546Sopenharmony_ci 412bf215546Sopenharmony_ci fd_screen_lock(ctx->screen); 413bf215546Sopenharmony_ci 414bf215546Sopenharmony_ci if (buffers & PIPE_CLEAR_COLOR) 415bf215546Sopenharmony_ci for (unsigned i = 0; i < pfb->nr_cbufs; i++) 416bf215546Sopenharmony_ci if (buffers & (PIPE_CLEAR_COLOR0 << i)) 417bf215546Sopenharmony_ci resource_written(batch, pfb->cbufs[i]->texture); 418bf215546Sopenharmony_ci 419bf215546Sopenharmony_ci if (buffers & (PIPE_CLEAR_DEPTH | PIPE_CLEAR_STENCIL)) { 420bf215546Sopenharmony_ci resource_written(batch, pfb->zsbuf->texture); 421bf215546Sopenharmony_ci batch->gmem_reason |= FD_GMEM_CLEARS_DEPTH_STENCIL; 422bf215546Sopenharmony_ci } 423bf215546Sopenharmony_ci 424bf215546Sopenharmony_ci resource_written(batch, batch->query_buf); 425bf215546Sopenharmony_ci 426bf215546Sopenharmony_ci list_for_each_entry (struct fd_acc_query, aq, &ctx->acc_active_queries, node) 427bf215546Sopenharmony_ci resource_written(batch, aq->prsc); 428bf215546Sopenharmony_ci 429bf215546Sopenharmony_ci fd_screen_unlock(ctx->screen); 430bf215546Sopenharmony_ci} 431bf215546Sopenharmony_ci 432bf215546Sopenharmony_cistatic void 433bf215546Sopenharmony_cifd_clear(struct pipe_context *pctx, unsigned buffers, 434bf215546Sopenharmony_ci const struct pipe_scissor_state *scissor_state, 435bf215546Sopenharmony_ci const union pipe_color_union *color, double depth, 436bf215546Sopenharmony_ci unsigned stencil) in_dt 437bf215546Sopenharmony_ci{ 438bf215546Sopenharmony_ci struct fd_context *ctx = fd_context(pctx); 439bf215546Sopenharmony_ci 440bf215546Sopenharmony_ci /* TODO: push down the region versions into the tiles */ 441bf215546Sopenharmony_ci if (!fd_render_condition_check(pctx)) 442bf215546Sopenharmony_ci return; 443bf215546Sopenharmony_ci 444bf215546Sopenharmony_ci struct fd_batch *batch = fd_context_batch(ctx); 445bf215546Sopenharmony_ci 446bf215546Sopenharmony_ci batch_clear_tracking(batch, buffers); 447bf215546Sopenharmony_ci 448bf215546Sopenharmony_ci while (unlikely(!fd_batch_lock_submit(batch))) { 449bf215546Sopenharmony_ci /* The current batch was flushed in batch_clear_tracking() 450bf215546Sopenharmony_ci * so start anew. We know this won't happen a second time 451bf215546Sopenharmony_ci * since we are dealing with a fresh batch: 452bf215546Sopenharmony_ci */ 453bf215546Sopenharmony_ci fd_batch_reference(&batch, NULL); 454bf215546Sopenharmony_ci batch = fd_context_batch(ctx); 455bf215546Sopenharmony_ci batch_clear_tracking(batch, buffers); 456bf215546Sopenharmony_ci assert(ctx->batch == batch); 457bf215546Sopenharmony_ci } 458bf215546Sopenharmony_ci 459bf215546Sopenharmony_ci /* Marking the batch as needing flush must come after the batch 460bf215546Sopenharmony_ci * dependency tracking (resource_read()/resource_write()), as that 461bf215546Sopenharmony_ci * can trigger a flush 462bf215546Sopenharmony_ci */ 463bf215546Sopenharmony_ci fd_batch_needs_flush(batch); 464bf215546Sopenharmony_ci 465bf215546Sopenharmony_ci struct pipe_framebuffer_state *pfb = &batch->framebuffer; 466bf215546Sopenharmony_ci DBG("%p: %x %ux%u depth=%f, stencil=%u (%s/%s)", batch, buffers, pfb->width, 467bf215546Sopenharmony_ci pfb->height, depth, stencil, 468bf215546Sopenharmony_ci util_format_short_name(pipe_surface_format(pfb->cbufs[0])), 469bf215546Sopenharmony_ci util_format_short_name(pipe_surface_format(pfb->zsbuf))); 470bf215546Sopenharmony_ci 471bf215546Sopenharmony_ci /* if per-gen backend doesn't implement ctx->clear() generic 472bf215546Sopenharmony_ci * blitter clear: 473bf215546Sopenharmony_ci */ 474bf215546Sopenharmony_ci bool fallback = true; 475bf215546Sopenharmony_ci 476bf215546Sopenharmony_ci if (ctx->clear) { 477bf215546Sopenharmony_ci fd_batch_update_queries(batch); 478bf215546Sopenharmony_ci 479bf215546Sopenharmony_ci if (ctx->clear(ctx, buffers, color, depth, stencil)) { 480bf215546Sopenharmony_ci if (FD_DBG(DCLEAR)) 481bf215546Sopenharmony_ci fd_context_all_dirty(ctx); 482bf215546Sopenharmony_ci 483bf215546Sopenharmony_ci fallback = false; 484bf215546Sopenharmony_ci } 485bf215546Sopenharmony_ci } 486bf215546Sopenharmony_ci 487bf215546Sopenharmony_ci assert(!batch->flushed); 488bf215546Sopenharmony_ci 489bf215546Sopenharmony_ci fd_batch_unlock_submit(batch); 490bf215546Sopenharmony_ci 491bf215546Sopenharmony_ci if (fallback) { 492bf215546Sopenharmony_ci fd_blitter_clear(pctx, buffers, color, depth, stencil); 493bf215546Sopenharmony_ci } 494bf215546Sopenharmony_ci 495bf215546Sopenharmony_ci fd_batch_check_size(batch); 496bf215546Sopenharmony_ci 497bf215546Sopenharmony_ci fd_batch_reference(&batch, NULL); 498bf215546Sopenharmony_ci} 499bf215546Sopenharmony_ci 500bf215546Sopenharmony_cistatic void 501bf215546Sopenharmony_cifd_clear_render_target(struct pipe_context *pctx, struct pipe_surface *ps, 502bf215546Sopenharmony_ci const union pipe_color_union *color, unsigned x, 503bf215546Sopenharmony_ci unsigned y, unsigned w, unsigned h, 504bf215546Sopenharmony_ci bool render_condition_enabled) 505bf215546Sopenharmony_ci{ 506bf215546Sopenharmony_ci DBG("TODO: x=%u, y=%u, w=%u, h=%u", x, y, w, h); 507bf215546Sopenharmony_ci} 508bf215546Sopenharmony_ci 509bf215546Sopenharmony_cistatic void 510bf215546Sopenharmony_cifd_clear_depth_stencil(struct pipe_context *pctx, struct pipe_surface *ps, 511bf215546Sopenharmony_ci unsigned buffers, double depth, unsigned stencil, 512bf215546Sopenharmony_ci unsigned x, unsigned y, unsigned w, unsigned h, 513bf215546Sopenharmony_ci bool render_condition_enabled) 514bf215546Sopenharmony_ci{ 515bf215546Sopenharmony_ci DBG("TODO: buffers=%u, depth=%f, stencil=%u, x=%u, y=%u, w=%u, h=%u", 516bf215546Sopenharmony_ci buffers, depth, stencil, x, y, w, h); 517bf215546Sopenharmony_ci} 518bf215546Sopenharmony_ci 519bf215546Sopenharmony_cistatic void 520bf215546Sopenharmony_cifd_launch_grid(struct pipe_context *pctx, 521bf215546Sopenharmony_ci const struct pipe_grid_info *info) in_dt 522bf215546Sopenharmony_ci{ 523bf215546Sopenharmony_ci struct fd_context *ctx = fd_context(pctx); 524bf215546Sopenharmony_ci const struct fd_shaderbuf_stateobj *so = 525bf215546Sopenharmony_ci &ctx->shaderbuf[PIPE_SHADER_COMPUTE]; 526bf215546Sopenharmony_ci struct fd_batch *batch, *save_batch = NULL; 527bf215546Sopenharmony_ci 528bf215546Sopenharmony_ci batch = fd_bc_alloc_batch(ctx, true); 529bf215546Sopenharmony_ci fd_batch_reference(&save_batch, ctx->batch); 530bf215546Sopenharmony_ci fd_batch_reference(&ctx->batch, batch); 531bf215546Sopenharmony_ci fd_context_all_dirty(ctx); 532bf215546Sopenharmony_ci 533bf215546Sopenharmony_ci fd_screen_lock(ctx->screen); 534bf215546Sopenharmony_ci 535bf215546Sopenharmony_ci /* Mark SSBOs */ 536bf215546Sopenharmony_ci u_foreach_bit (i, so->enabled_mask & so->writable_mask) 537bf215546Sopenharmony_ci resource_written(batch, so->sb[i].buffer); 538bf215546Sopenharmony_ci 539bf215546Sopenharmony_ci u_foreach_bit (i, so->enabled_mask & ~so->writable_mask) 540bf215546Sopenharmony_ci resource_read(batch, so->sb[i].buffer); 541bf215546Sopenharmony_ci 542bf215546Sopenharmony_ci u_foreach_bit (i, ctx->shaderimg[PIPE_SHADER_COMPUTE].enabled_mask) { 543bf215546Sopenharmony_ci struct pipe_image_view *img = &ctx->shaderimg[PIPE_SHADER_COMPUTE].si[i]; 544bf215546Sopenharmony_ci if (img->access & PIPE_IMAGE_ACCESS_WRITE) 545bf215546Sopenharmony_ci resource_written(batch, img->resource); 546bf215546Sopenharmony_ci else 547bf215546Sopenharmony_ci resource_read(batch, img->resource); 548bf215546Sopenharmony_ci } 549bf215546Sopenharmony_ci 550bf215546Sopenharmony_ci /* UBO's are read */ 551bf215546Sopenharmony_ci u_foreach_bit (i, ctx->constbuf[PIPE_SHADER_COMPUTE].enabled_mask) 552bf215546Sopenharmony_ci resource_read(batch, ctx->constbuf[PIPE_SHADER_COMPUTE].cb[i].buffer); 553bf215546Sopenharmony_ci 554bf215546Sopenharmony_ci /* Mark textures as being read */ 555bf215546Sopenharmony_ci u_foreach_bit (i, ctx->tex[PIPE_SHADER_COMPUTE].valid_textures) 556bf215546Sopenharmony_ci resource_read(batch, ctx->tex[PIPE_SHADER_COMPUTE].textures[i]->texture); 557bf215546Sopenharmony_ci 558bf215546Sopenharmony_ci /* For global buffers, we don't really know if read or written, so assume 559bf215546Sopenharmony_ci * the worst: 560bf215546Sopenharmony_ci */ 561bf215546Sopenharmony_ci u_foreach_bit (i, ctx->global_bindings.enabled_mask) 562bf215546Sopenharmony_ci resource_written(batch, ctx->global_bindings.buf[i]); 563bf215546Sopenharmony_ci 564bf215546Sopenharmony_ci if (info->indirect) 565bf215546Sopenharmony_ci resource_read(batch, info->indirect); 566bf215546Sopenharmony_ci 567bf215546Sopenharmony_ci fd_screen_unlock(ctx->screen); 568bf215546Sopenharmony_ci 569bf215546Sopenharmony_ci DBG("%p: work_dim=%u, block=%ux%ux%u, grid=%ux%ux%u", 570bf215546Sopenharmony_ci batch, info->work_dim, 571bf215546Sopenharmony_ci info->block[0], info->block[1], info->block[2], 572bf215546Sopenharmony_ci info->grid[0], info->grid[1], info->grid[2]); 573bf215546Sopenharmony_ci 574bf215546Sopenharmony_ci fd_batch_needs_flush(batch); 575bf215546Sopenharmony_ci ctx->launch_grid(ctx, info); 576bf215546Sopenharmony_ci 577bf215546Sopenharmony_ci fd_batch_flush(batch); 578bf215546Sopenharmony_ci 579bf215546Sopenharmony_ci fd_batch_reference(&ctx->batch, save_batch); 580bf215546Sopenharmony_ci fd_context_all_dirty(ctx); 581bf215546Sopenharmony_ci fd_batch_reference(&save_batch, NULL); 582bf215546Sopenharmony_ci fd_batch_reference(&batch, NULL); 583bf215546Sopenharmony_ci} 584bf215546Sopenharmony_ci 585bf215546Sopenharmony_civoid 586bf215546Sopenharmony_cifd_draw_init(struct pipe_context *pctx) 587bf215546Sopenharmony_ci{ 588bf215546Sopenharmony_ci pctx->draw_vbo = fd_draw_vbo; 589bf215546Sopenharmony_ci pctx->clear = fd_clear; 590bf215546Sopenharmony_ci pctx->clear_render_target = fd_clear_render_target; 591bf215546Sopenharmony_ci pctx->clear_depth_stencil = fd_clear_depth_stencil; 592bf215546Sopenharmony_ci 593bf215546Sopenharmony_ci if (has_compute(fd_screen(pctx->screen))) { 594bf215546Sopenharmony_ci pctx->launch_grid = fd_launch_grid; 595bf215546Sopenharmony_ci } 596bf215546Sopenharmony_ci} 597