1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright (C) 2016 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 "util/hash_table.h" 28bf215546Sopenharmony_ci#include "util/list.h" 29bf215546Sopenharmony_ci#include "util/set.h" 30bf215546Sopenharmony_ci#include "util/u_string.h" 31bf215546Sopenharmony_ci 32bf215546Sopenharmony_ci#include "freedreno_batch.h" 33bf215546Sopenharmony_ci#include "freedreno_context.h" 34bf215546Sopenharmony_ci#include "freedreno_fence.h" 35bf215546Sopenharmony_ci#include "freedreno_query_hw.h" 36bf215546Sopenharmony_ci#include "freedreno_resource.h" 37bf215546Sopenharmony_ci 38bf215546Sopenharmony_cistatic struct fd_ringbuffer * 39bf215546Sopenharmony_cialloc_ring(struct fd_batch *batch, unsigned sz, enum fd_ringbuffer_flags flags) 40bf215546Sopenharmony_ci{ 41bf215546Sopenharmony_ci struct fd_context *ctx = batch->ctx; 42bf215546Sopenharmony_ci 43bf215546Sopenharmony_ci /* if kernel is too old to support unlimited # of cmd buffers, we 44bf215546Sopenharmony_ci * have no option but to allocate large worst-case sizes so that 45bf215546Sopenharmony_ci * we don't need to grow the ringbuffer. Performance is likely to 46bf215546Sopenharmony_ci * suffer, but there is no good alternative. 47bf215546Sopenharmony_ci * 48bf215546Sopenharmony_ci * Otherwise if supported, allocate a growable ring with initial 49bf215546Sopenharmony_ci * size of zero. 50bf215546Sopenharmony_ci */ 51bf215546Sopenharmony_ci if ((fd_device_version(ctx->screen->dev) >= FD_VERSION_UNLIMITED_CMDS) && 52bf215546Sopenharmony_ci !FD_DBG(NOGROW)) { 53bf215546Sopenharmony_ci flags |= FD_RINGBUFFER_GROWABLE; 54bf215546Sopenharmony_ci sz = 0; 55bf215546Sopenharmony_ci } 56bf215546Sopenharmony_ci 57bf215546Sopenharmony_ci return fd_submit_new_ringbuffer(batch->submit, sz, flags); 58bf215546Sopenharmony_ci} 59bf215546Sopenharmony_ci 60bf215546Sopenharmony_cistatic void 61bf215546Sopenharmony_cibatch_init(struct fd_batch *batch) 62bf215546Sopenharmony_ci{ 63bf215546Sopenharmony_ci struct fd_context *ctx = batch->ctx; 64bf215546Sopenharmony_ci 65bf215546Sopenharmony_ci batch->submit = fd_submit_new(ctx->pipe); 66bf215546Sopenharmony_ci if (batch->nondraw) { 67bf215546Sopenharmony_ci batch->gmem = alloc_ring(batch, 0x1000, FD_RINGBUFFER_PRIMARY); 68bf215546Sopenharmony_ci batch->draw = alloc_ring(batch, 0x100000, 0); 69bf215546Sopenharmony_ci } else { 70bf215546Sopenharmony_ci batch->gmem = alloc_ring(batch, 0x100000, FD_RINGBUFFER_PRIMARY); 71bf215546Sopenharmony_ci batch->draw = alloc_ring(batch, 0x100000, 0); 72bf215546Sopenharmony_ci 73bf215546Sopenharmony_ci /* a6xx+ re-uses draw rb for both draw and binning pass: */ 74bf215546Sopenharmony_ci if (ctx->screen->gen < 6) { 75bf215546Sopenharmony_ci batch->binning = alloc_ring(batch, 0x100000, 0); 76bf215546Sopenharmony_ci } 77bf215546Sopenharmony_ci } 78bf215546Sopenharmony_ci 79bf215546Sopenharmony_ci batch->in_fence_fd = -1; 80bf215546Sopenharmony_ci batch->fence = NULL; 81bf215546Sopenharmony_ci 82bf215546Sopenharmony_ci /* Work around problems on earlier gens with submit merging, etc, 83bf215546Sopenharmony_ci * by always creating a fence to request that the submit is flushed 84bf215546Sopenharmony_ci * immediately: 85bf215546Sopenharmony_ci */ 86bf215546Sopenharmony_ci if (ctx->screen->gen < 6) 87bf215546Sopenharmony_ci batch->fence = fd_fence_create(batch); 88bf215546Sopenharmony_ci 89bf215546Sopenharmony_ci batch->cleared = 0; 90bf215546Sopenharmony_ci batch->fast_cleared = 0; 91bf215546Sopenharmony_ci batch->invalidated = 0; 92bf215546Sopenharmony_ci batch->restore = batch->resolve = 0; 93bf215546Sopenharmony_ci batch->needs_flush = false; 94bf215546Sopenharmony_ci batch->flushed = false; 95bf215546Sopenharmony_ci batch->gmem_reason = 0; 96bf215546Sopenharmony_ci batch->num_draws = 0; 97bf215546Sopenharmony_ci batch->num_vertices = 0; 98bf215546Sopenharmony_ci batch->num_bins_per_pipe = 0; 99bf215546Sopenharmony_ci batch->prim_strm_bits = 0; 100bf215546Sopenharmony_ci batch->draw_strm_bits = 0; 101bf215546Sopenharmony_ci 102bf215546Sopenharmony_ci fd_reset_wfi(batch); 103bf215546Sopenharmony_ci 104bf215546Sopenharmony_ci util_dynarray_init(&batch->draw_patches, NULL); 105bf215546Sopenharmony_ci util_dynarray_init(&batch->fb_read_patches, NULL); 106bf215546Sopenharmony_ci 107bf215546Sopenharmony_ci if (is_a2xx(ctx->screen)) { 108bf215546Sopenharmony_ci util_dynarray_init(&batch->shader_patches, NULL); 109bf215546Sopenharmony_ci util_dynarray_init(&batch->gmem_patches, NULL); 110bf215546Sopenharmony_ci } 111bf215546Sopenharmony_ci 112bf215546Sopenharmony_ci if (is_a3xx(ctx->screen)) 113bf215546Sopenharmony_ci util_dynarray_init(&batch->rbrc_patches, NULL); 114bf215546Sopenharmony_ci 115bf215546Sopenharmony_ci assert(batch->resources->entries == 0); 116bf215546Sopenharmony_ci 117bf215546Sopenharmony_ci util_dynarray_init(&batch->samples, NULL); 118bf215546Sopenharmony_ci 119bf215546Sopenharmony_ci u_trace_init(&batch->trace, &ctx->trace_context); 120bf215546Sopenharmony_ci batch->last_timestamp_cmd = NULL; 121bf215546Sopenharmony_ci} 122bf215546Sopenharmony_ci 123bf215546Sopenharmony_cistruct fd_batch * 124bf215546Sopenharmony_cifd_batch_create(struct fd_context *ctx, bool nondraw) 125bf215546Sopenharmony_ci{ 126bf215546Sopenharmony_ci struct fd_batch *batch = CALLOC_STRUCT(fd_batch); 127bf215546Sopenharmony_ci 128bf215546Sopenharmony_ci if (!batch) 129bf215546Sopenharmony_ci return NULL; 130bf215546Sopenharmony_ci 131bf215546Sopenharmony_ci DBG("%p", batch); 132bf215546Sopenharmony_ci 133bf215546Sopenharmony_ci pipe_reference_init(&batch->reference, 1); 134bf215546Sopenharmony_ci batch->ctx = ctx; 135bf215546Sopenharmony_ci batch->nondraw = nondraw; 136bf215546Sopenharmony_ci 137bf215546Sopenharmony_ci simple_mtx_init(&batch->submit_lock, mtx_plain); 138bf215546Sopenharmony_ci 139bf215546Sopenharmony_ci batch->resources = 140bf215546Sopenharmony_ci _mesa_set_create(NULL, _mesa_hash_pointer, _mesa_key_pointer_equal); 141bf215546Sopenharmony_ci 142bf215546Sopenharmony_ci batch_init(batch); 143bf215546Sopenharmony_ci 144bf215546Sopenharmony_ci return batch; 145bf215546Sopenharmony_ci} 146bf215546Sopenharmony_ci 147bf215546Sopenharmony_cistatic void 148bf215546Sopenharmony_cicleanup_submit(struct fd_batch *batch) 149bf215546Sopenharmony_ci{ 150bf215546Sopenharmony_ci if (!batch->submit) 151bf215546Sopenharmony_ci return; 152bf215546Sopenharmony_ci 153bf215546Sopenharmony_ci fd_ringbuffer_del(batch->draw); 154bf215546Sopenharmony_ci fd_ringbuffer_del(batch->gmem); 155bf215546Sopenharmony_ci 156bf215546Sopenharmony_ci if (batch->binning) { 157bf215546Sopenharmony_ci fd_ringbuffer_del(batch->binning); 158bf215546Sopenharmony_ci batch->binning = NULL; 159bf215546Sopenharmony_ci } 160bf215546Sopenharmony_ci 161bf215546Sopenharmony_ci if (batch->prologue) { 162bf215546Sopenharmony_ci fd_ringbuffer_del(batch->prologue); 163bf215546Sopenharmony_ci batch->prologue = NULL; 164bf215546Sopenharmony_ci } 165bf215546Sopenharmony_ci 166bf215546Sopenharmony_ci if (batch->epilogue) { 167bf215546Sopenharmony_ci fd_ringbuffer_del(batch->epilogue); 168bf215546Sopenharmony_ci batch->epilogue = NULL; 169bf215546Sopenharmony_ci } 170bf215546Sopenharmony_ci 171bf215546Sopenharmony_ci if (batch->tile_setup) { 172bf215546Sopenharmony_ci fd_ringbuffer_del(batch->tile_setup); 173bf215546Sopenharmony_ci batch->tile_setup = NULL; 174bf215546Sopenharmony_ci } 175bf215546Sopenharmony_ci 176bf215546Sopenharmony_ci if (batch->tile_fini) { 177bf215546Sopenharmony_ci fd_ringbuffer_del(batch->tile_fini); 178bf215546Sopenharmony_ci batch->tile_fini = NULL; 179bf215546Sopenharmony_ci } 180bf215546Sopenharmony_ci 181bf215546Sopenharmony_ci fd_submit_del(batch->submit); 182bf215546Sopenharmony_ci batch->submit = NULL; 183bf215546Sopenharmony_ci} 184bf215546Sopenharmony_ci 185bf215546Sopenharmony_cistatic void 186bf215546Sopenharmony_cibatch_fini(struct fd_batch *batch) 187bf215546Sopenharmony_ci{ 188bf215546Sopenharmony_ci DBG("%p", batch); 189bf215546Sopenharmony_ci 190bf215546Sopenharmony_ci pipe_resource_reference(&batch->query_buf, NULL); 191bf215546Sopenharmony_ci 192bf215546Sopenharmony_ci if (batch->in_fence_fd != -1) 193bf215546Sopenharmony_ci close(batch->in_fence_fd); 194bf215546Sopenharmony_ci 195bf215546Sopenharmony_ci /* in case batch wasn't flushed but fence was created: */ 196bf215546Sopenharmony_ci if (batch->fence) 197bf215546Sopenharmony_ci fd_fence_set_batch(batch->fence, NULL); 198bf215546Sopenharmony_ci 199bf215546Sopenharmony_ci fd_fence_ref(&batch->fence, NULL); 200bf215546Sopenharmony_ci 201bf215546Sopenharmony_ci cleanup_submit(batch); 202bf215546Sopenharmony_ci 203bf215546Sopenharmony_ci util_dynarray_fini(&batch->draw_patches); 204bf215546Sopenharmony_ci util_dynarray_fini(&batch->fb_read_patches); 205bf215546Sopenharmony_ci 206bf215546Sopenharmony_ci if (is_a2xx(batch->ctx->screen)) { 207bf215546Sopenharmony_ci util_dynarray_fini(&batch->shader_patches); 208bf215546Sopenharmony_ci util_dynarray_fini(&batch->gmem_patches); 209bf215546Sopenharmony_ci } 210bf215546Sopenharmony_ci 211bf215546Sopenharmony_ci if (is_a3xx(batch->ctx->screen)) 212bf215546Sopenharmony_ci util_dynarray_fini(&batch->rbrc_patches); 213bf215546Sopenharmony_ci 214bf215546Sopenharmony_ci while (batch->samples.size > 0) { 215bf215546Sopenharmony_ci struct fd_hw_sample *samp = 216bf215546Sopenharmony_ci util_dynarray_pop(&batch->samples, struct fd_hw_sample *); 217bf215546Sopenharmony_ci fd_hw_sample_reference(batch->ctx, &samp, NULL); 218bf215546Sopenharmony_ci } 219bf215546Sopenharmony_ci util_dynarray_fini(&batch->samples); 220bf215546Sopenharmony_ci 221bf215546Sopenharmony_ci u_trace_fini(&batch->trace); 222bf215546Sopenharmony_ci} 223bf215546Sopenharmony_ci 224bf215546Sopenharmony_cistatic void 225bf215546Sopenharmony_cibatch_flush_dependencies(struct fd_batch *batch) assert_dt 226bf215546Sopenharmony_ci{ 227bf215546Sopenharmony_ci struct fd_batch_cache *cache = &batch->ctx->screen->batch_cache; 228bf215546Sopenharmony_ci struct fd_batch *dep; 229bf215546Sopenharmony_ci 230bf215546Sopenharmony_ci foreach_batch (dep, cache, batch->dependents_mask) { 231bf215546Sopenharmony_ci fd_batch_flush(dep); 232bf215546Sopenharmony_ci fd_batch_reference(&dep, NULL); 233bf215546Sopenharmony_ci } 234bf215546Sopenharmony_ci 235bf215546Sopenharmony_ci batch->dependents_mask = 0; 236bf215546Sopenharmony_ci} 237bf215546Sopenharmony_ci 238bf215546Sopenharmony_cistatic void 239bf215546Sopenharmony_cibatch_reset_dependencies(struct fd_batch *batch) 240bf215546Sopenharmony_ci{ 241bf215546Sopenharmony_ci struct fd_batch_cache *cache = &batch->ctx->screen->batch_cache; 242bf215546Sopenharmony_ci struct fd_batch *dep; 243bf215546Sopenharmony_ci 244bf215546Sopenharmony_ci foreach_batch (dep, cache, batch->dependents_mask) { 245bf215546Sopenharmony_ci fd_batch_reference(&dep, NULL); 246bf215546Sopenharmony_ci } 247bf215546Sopenharmony_ci 248bf215546Sopenharmony_ci batch->dependents_mask = 0; 249bf215546Sopenharmony_ci} 250bf215546Sopenharmony_ci 251bf215546Sopenharmony_cistatic void 252bf215546Sopenharmony_cibatch_reset_resources(struct fd_batch *batch) 253bf215546Sopenharmony_ci{ 254bf215546Sopenharmony_ci fd_screen_assert_locked(batch->ctx->screen); 255bf215546Sopenharmony_ci 256bf215546Sopenharmony_ci set_foreach (batch->resources, entry) { 257bf215546Sopenharmony_ci struct fd_resource *rsc = (struct fd_resource *)entry->key; 258bf215546Sopenharmony_ci _mesa_set_remove(batch->resources, entry); 259bf215546Sopenharmony_ci assert(rsc->track->batch_mask & (1 << batch->idx)); 260bf215546Sopenharmony_ci rsc->track->batch_mask &= ~(1 << batch->idx); 261bf215546Sopenharmony_ci if (rsc->track->write_batch == batch) 262bf215546Sopenharmony_ci fd_batch_reference_locked(&rsc->track->write_batch, NULL); 263bf215546Sopenharmony_ci } 264bf215546Sopenharmony_ci} 265bf215546Sopenharmony_ci 266bf215546Sopenharmony_cistatic void 267bf215546Sopenharmony_cibatch_reset(struct fd_batch *batch) assert_dt 268bf215546Sopenharmony_ci{ 269bf215546Sopenharmony_ci DBG("%p", batch); 270bf215546Sopenharmony_ci 271bf215546Sopenharmony_ci batch_reset_dependencies(batch); 272bf215546Sopenharmony_ci 273bf215546Sopenharmony_ci fd_screen_lock(batch->ctx->screen); 274bf215546Sopenharmony_ci batch_reset_resources(batch); 275bf215546Sopenharmony_ci fd_screen_unlock(batch->ctx->screen); 276bf215546Sopenharmony_ci 277bf215546Sopenharmony_ci batch_fini(batch); 278bf215546Sopenharmony_ci batch_init(batch); 279bf215546Sopenharmony_ci} 280bf215546Sopenharmony_ci 281bf215546Sopenharmony_civoid 282bf215546Sopenharmony_cifd_batch_reset(struct fd_batch *batch) 283bf215546Sopenharmony_ci{ 284bf215546Sopenharmony_ci if (batch->needs_flush) 285bf215546Sopenharmony_ci batch_reset(batch); 286bf215546Sopenharmony_ci} 287bf215546Sopenharmony_ci 288bf215546Sopenharmony_civoid 289bf215546Sopenharmony_ci__fd_batch_destroy(struct fd_batch *batch) 290bf215546Sopenharmony_ci{ 291bf215546Sopenharmony_ci struct fd_context *ctx = batch->ctx; 292bf215546Sopenharmony_ci 293bf215546Sopenharmony_ci DBG("%p", batch); 294bf215546Sopenharmony_ci 295bf215546Sopenharmony_ci fd_screen_assert_locked(batch->ctx->screen); 296bf215546Sopenharmony_ci 297bf215546Sopenharmony_ci fd_bc_invalidate_batch(batch, true); 298bf215546Sopenharmony_ci 299bf215546Sopenharmony_ci batch_reset_resources(batch); 300bf215546Sopenharmony_ci assert(batch->resources->entries == 0); 301bf215546Sopenharmony_ci _mesa_set_destroy(batch->resources, NULL); 302bf215546Sopenharmony_ci 303bf215546Sopenharmony_ci fd_screen_unlock(ctx->screen); 304bf215546Sopenharmony_ci batch_reset_dependencies(batch); 305bf215546Sopenharmony_ci assert(batch->dependents_mask == 0); 306bf215546Sopenharmony_ci 307bf215546Sopenharmony_ci util_copy_framebuffer_state(&batch->framebuffer, NULL); 308bf215546Sopenharmony_ci batch_fini(batch); 309bf215546Sopenharmony_ci 310bf215546Sopenharmony_ci simple_mtx_destroy(&batch->submit_lock); 311bf215546Sopenharmony_ci 312bf215546Sopenharmony_ci free(batch->key); 313bf215546Sopenharmony_ci free(batch); 314bf215546Sopenharmony_ci fd_screen_lock(ctx->screen); 315bf215546Sopenharmony_ci} 316bf215546Sopenharmony_ci 317bf215546Sopenharmony_civoid 318bf215546Sopenharmony_ci__fd_batch_describe(char *buf, const struct fd_batch *batch) 319bf215546Sopenharmony_ci{ 320bf215546Sopenharmony_ci sprintf(buf, "fd_batch<%u>", batch->seqno); 321bf215546Sopenharmony_ci} 322bf215546Sopenharmony_ci 323bf215546Sopenharmony_ci/* Get per-batch prologue */ 324bf215546Sopenharmony_cistruct fd_ringbuffer * 325bf215546Sopenharmony_cifd_batch_get_prologue(struct fd_batch *batch) 326bf215546Sopenharmony_ci{ 327bf215546Sopenharmony_ci if (!batch->prologue) 328bf215546Sopenharmony_ci batch->prologue = alloc_ring(batch, 0x1000, 0); 329bf215546Sopenharmony_ci return batch->prologue; 330bf215546Sopenharmony_ci} 331bf215546Sopenharmony_ci 332bf215546Sopenharmony_ci/* Only called from fd_batch_flush() */ 333bf215546Sopenharmony_cistatic void 334bf215546Sopenharmony_cibatch_flush(struct fd_batch *batch) assert_dt 335bf215546Sopenharmony_ci{ 336bf215546Sopenharmony_ci DBG("%p: needs_flush=%d", batch, batch->needs_flush); 337bf215546Sopenharmony_ci 338bf215546Sopenharmony_ci if (!fd_batch_lock_submit(batch)) 339bf215546Sopenharmony_ci return; 340bf215546Sopenharmony_ci 341bf215546Sopenharmony_ci batch->needs_flush = false; 342bf215546Sopenharmony_ci 343bf215546Sopenharmony_ci /* close out the draw cmds by making sure any active queries are 344bf215546Sopenharmony_ci * paused: 345bf215546Sopenharmony_ci */ 346bf215546Sopenharmony_ci fd_batch_finish_queries(batch); 347bf215546Sopenharmony_ci 348bf215546Sopenharmony_ci batch_flush_dependencies(batch); 349bf215546Sopenharmony_ci 350bf215546Sopenharmony_ci fd_screen_lock(batch->ctx->screen); 351bf215546Sopenharmony_ci batch_reset_resources(batch); 352bf215546Sopenharmony_ci /* NOTE: remove=false removes the batch from the hashtable, so future 353bf215546Sopenharmony_ci * lookups won't cache-hit a flushed batch, but leaves the weak reference 354bf215546Sopenharmony_ci * to the batch to avoid having multiple batches with same batch->idx, as 355bf215546Sopenharmony_ci * that causes all sorts of hilarity. 356bf215546Sopenharmony_ci */ 357bf215546Sopenharmony_ci fd_bc_invalidate_batch(batch, false); 358bf215546Sopenharmony_ci batch->flushed = true; 359bf215546Sopenharmony_ci 360bf215546Sopenharmony_ci if (batch == batch->ctx->batch) 361bf215546Sopenharmony_ci fd_batch_reference_locked(&batch->ctx->batch, NULL); 362bf215546Sopenharmony_ci 363bf215546Sopenharmony_ci fd_screen_unlock(batch->ctx->screen); 364bf215546Sopenharmony_ci 365bf215546Sopenharmony_ci if (batch->fence) 366bf215546Sopenharmony_ci fd_fence_ref(&batch->ctx->last_fence, batch->fence); 367bf215546Sopenharmony_ci 368bf215546Sopenharmony_ci fd_gmem_render_tiles(batch); 369bf215546Sopenharmony_ci 370bf215546Sopenharmony_ci assert(batch->reference.count > 0); 371bf215546Sopenharmony_ci 372bf215546Sopenharmony_ci cleanup_submit(batch); 373bf215546Sopenharmony_ci fd_batch_unlock_submit(batch); 374bf215546Sopenharmony_ci} 375bf215546Sopenharmony_ci 376bf215546Sopenharmony_ci/* NOTE: could drop the last ref to batch 377bf215546Sopenharmony_ci */ 378bf215546Sopenharmony_civoid 379bf215546Sopenharmony_cifd_batch_flush(struct fd_batch *batch) 380bf215546Sopenharmony_ci{ 381bf215546Sopenharmony_ci struct fd_batch *tmp = NULL; 382bf215546Sopenharmony_ci 383bf215546Sopenharmony_ci /* NOTE: we need to hold an extra ref across the body of flush, 384bf215546Sopenharmony_ci * since the last ref to this batch could be dropped when cleaning 385bf215546Sopenharmony_ci * up used_resources 386bf215546Sopenharmony_ci */ 387bf215546Sopenharmony_ci fd_batch_reference(&tmp, batch); 388bf215546Sopenharmony_ci batch_flush(tmp); 389bf215546Sopenharmony_ci fd_batch_reference(&tmp, NULL); 390bf215546Sopenharmony_ci} 391bf215546Sopenharmony_ci 392bf215546Sopenharmony_ci/* find a batches dependents mask, including recursive dependencies: */ 393bf215546Sopenharmony_cistatic uint32_t 394bf215546Sopenharmony_cirecursive_dependents_mask(struct fd_batch *batch) 395bf215546Sopenharmony_ci{ 396bf215546Sopenharmony_ci struct fd_batch_cache *cache = &batch->ctx->screen->batch_cache; 397bf215546Sopenharmony_ci struct fd_batch *dep; 398bf215546Sopenharmony_ci uint32_t dependents_mask = batch->dependents_mask; 399bf215546Sopenharmony_ci 400bf215546Sopenharmony_ci foreach_batch (dep, cache, batch->dependents_mask) 401bf215546Sopenharmony_ci dependents_mask |= recursive_dependents_mask(dep); 402bf215546Sopenharmony_ci 403bf215546Sopenharmony_ci return dependents_mask; 404bf215546Sopenharmony_ci} 405bf215546Sopenharmony_ci 406bf215546Sopenharmony_civoid 407bf215546Sopenharmony_cifd_batch_add_dep(struct fd_batch *batch, struct fd_batch *dep) 408bf215546Sopenharmony_ci{ 409bf215546Sopenharmony_ci fd_screen_assert_locked(batch->ctx->screen); 410bf215546Sopenharmony_ci 411bf215546Sopenharmony_ci if (batch->dependents_mask & (1 << dep->idx)) 412bf215546Sopenharmony_ci return; 413bf215546Sopenharmony_ci 414bf215546Sopenharmony_ci /* a loop should not be possible */ 415bf215546Sopenharmony_ci assert(!((1 << batch->idx) & recursive_dependents_mask(dep))); 416bf215546Sopenharmony_ci 417bf215546Sopenharmony_ci struct fd_batch *other = NULL; 418bf215546Sopenharmony_ci fd_batch_reference_locked(&other, dep); 419bf215546Sopenharmony_ci batch->dependents_mask |= (1 << dep->idx); 420bf215546Sopenharmony_ci DBG("%p: added dependency on %p", batch, dep); 421bf215546Sopenharmony_ci} 422bf215546Sopenharmony_ci 423bf215546Sopenharmony_cistatic void 424bf215546Sopenharmony_ciflush_write_batch(struct fd_resource *rsc) assert_dt 425bf215546Sopenharmony_ci{ 426bf215546Sopenharmony_ci struct fd_batch *b = NULL; 427bf215546Sopenharmony_ci fd_batch_reference_locked(&b, rsc->track->write_batch); 428bf215546Sopenharmony_ci 429bf215546Sopenharmony_ci fd_screen_unlock(b->ctx->screen); 430bf215546Sopenharmony_ci fd_batch_flush(b); 431bf215546Sopenharmony_ci fd_screen_lock(b->ctx->screen); 432bf215546Sopenharmony_ci 433bf215546Sopenharmony_ci fd_batch_reference_locked(&b, NULL); 434bf215546Sopenharmony_ci} 435bf215546Sopenharmony_ci 436bf215546Sopenharmony_cistatic void 437bf215546Sopenharmony_cifd_batch_add_resource(struct fd_batch *batch, struct fd_resource *rsc) 438bf215546Sopenharmony_ci{ 439bf215546Sopenharmony_ci 440bf215546Sopenharmony_ci if (likely(fd_batch_references_resource(batch, rsc))) { 441bf215546Sopenharmony_ci assert(_mesa_set_search_pre_hashed(batch->resources, rsc->hash, rsc)); 442bf215546Sopenharmony_ci return; 443bf215546Sopenharmony_ci } 444bf215546Sopenharmony_ci 445bf215546Sopenharmony_ci assert(!_mesa_set_search(batch->resources, rsc)); 446bf215546Sopenharmony_ci 447bf215546Sopenharmony_ci _mesa_set_add_pre_hashed(batch->resources, rsc->hash, rsc); 448bf215546Sopenharmony_ci rsc->track->batch_mask |= (1 << batch->idx); 449bf215546Sopenharmony_ci} 450bf215546Sopenharmony_ci 451bf215546Sopenharmony_civoid 452bf215546Sopenharmony_cifd_batch_resource_write(struct fd_batch *batch, struct fd_resource *rsc) 453bf215546Sopenharmony_ci{ 454bf215546Sopenharmony_ci fd_screen_assert_locked(batch->ctx->screen); 455bf215546Sopenharmony_ci 456bf215546Sopenharmony_ci DBG("%p: write %p", batch, rsc); 457bf215546Sopenharmony_ci 458bf215546Sopenharmony_ci /* Must do this before the early out, so we unset a previous resource 459bf215546Sopenharmony_ci * invalidate (which may have left the write_batch state in place). 460bf215546Sopenharmony_ci */ 461bf215546Sopenharmony_ci rsc->valid = true; 462bf215546Sopenharmony_ci 463bf215546Sopenharmony_ci if (rsc->track->write_batch == batch) 464bf215546Sopenharmony_ci return; 465bf215546Sopenharmony_ci 466bf215546Sopenharmony_ci fd_batch_write_prep(batch, rsc); 467bf215546Sopenharmony_ci 468bf215546Sopenharmony_ci if (rsc->stencil) 469bf215546Sopenharmony_ci fd_batch_resource_write(batch, rsc->stencil); 470bf215546Sopenharmony_ci 471bf215546Sopenharmony_ci /* note, invalidate write batch, to avoid further writes to rsc 472bf215546Sopenharmony_ci * resulting in a write-after-read hazard. 473bf215546Sopenharmony_ci */ 474bf215546Sopenharmony_ci /* if we are pending read or write by any other batch: */ 475bf215546Sopenharmony_ci if (unlikely(rsc->track->batch_mask & ~(1 << batch->idx))) { 476bf215546Sopenharmony_ci struct fd_batch_cache *cache = &batch->ctx->screen->batch_cache; 477bf215546Sopenharmony_ci struct fd_batch *dep; 478bf215546Sopenharmony_ci 479bf215546Sopenharmony_ci if (rsc->track->write_batch) 480bf215546Sopenharmony_ci flush_write_batch(rsc); 481bf215546Sopenharmony_ci 482bf215546Sopenharmony_ci foreach_batch (dep, cache, rsc->track->batch_mask) { 483bf215546Sopenharmony_ci struct fd_batch *b = NULL; 484bf215546Sopenharmony_ci if (dep == batch) 485bf215546Sopenharmony_ci continue; 486bf215546Sopenharmony_ci /* note that batch_add_dep could flush and unref dep, so 487bf215546Sopenharmony_ci * we need to hold a reference to keep it live for the 488bf215546Sopenharmony_ci * fd_bc_invalidate_batch() 489bf215546Sopenharmony_ci */ 490bf215546Sopenharmony_ci fd_batch_reference(&b, dep); 491bf215546Sopenharmony_ci fd_batch_add_dep(batch, b); 492bf215546Sopenharmony_ci fd_bc_invalidate_batch(b, false); 493bf215546Sopenharmony_ci fd_batch_reference_locked(&b, NULL); 494bf215546Sopenharmony_ci } 495bf215546Sopenharmony_ci } 496bf215546Sopenharmony_ci fd_batch_reference_locked(&rsc->track->write_batch, batch); 497bf215546Sopenharmony_ci 498bf215546Sopenharmony_ci fd_batch_add_resource(batch, rsc); 499bf215546Sopenharmony_ci} 500bf215546Sopenharmony_ci 501bf215546Sopenharmony_civoid 502bf215546Sopenharmony_cifd_batch_resource_read_slowpath(struct fd_batch *batch, struct fd_resource *rsc) 503bf215546Sopenharmony_ci{ 504bf215546Sopenharmony_ci fd_screen_assert_locked(batch->ctx->screen); 505bf215546Sopenharmony_ci 506bf215546Sopenharmony_ci if (rsc->stencil) 507bf215546Sopenharmony_ci fd_batch_resource_read(batch, rsc->stencil); 508bf215546Sopenharmony_ci 509bf215546Sopenharmony_ci DBG("%p: read %p", batch, rsc); 510bf215546Sopenharmony_ci 511bf215546Sopenharmony_ci /* If reading a resource pending a write, go ahead and flush the 512bf215546Sopenharmony_ci * writer. This avoids situations where we end up having to 513bf215546Sopenharmony_ci * flush the current batch in _resource_used() 514bf215546Sopenharmony_ci */ 515bf215546Sopenharmony_ci if (unlikely(rsc->track->write_batch && rsc->track->write_batch != batch)) 516bf215546Sopenharmony_ci flush_write_batch(rsc); 517bf215546Sopenharmony_ci 518bf215546Sopenharmony_ci fd_batch_add_resource(batch, rsc); 519bf215546Sopenharmony_ci} 520bf215546Sopenharmony_ci 521bf215546Sopenharmony_civoid 522bf215546Sopenharmony_cifd_batch_check_size(struct fd_batch *batch) 523bf215546Sopenharmony_ci{ 524bf215546Sopenharmony_ci if (FD_DBG(FLUSH)) { 525bf215546Sopenharmony_ci fd_batch_flush(batch); 526bf215546Sopenharmony_ci return; 527bf215546Sopenharmony_ci } 528bf215546Sopenharmony_ci 529bf215546Sopenharmony_ci /* Place a reasonable upper bound on prim/draw stream buffer size: */ 530bf215546Sopenharmony_ci const unsigned limit_bits = 8 * 8 * 1024 * 1024; 531bf215546Sopenharmony_ci if ((batch->prim_strm_bits > limit_bits) || 532bf215546Sopenharmony_ci (batch->draw_strm_bits > limit_bits)) { 533bf215546Sopenharmony_ci fd_batch_flush(batch); 534bf215546Sopenharmony_ci return; 535bf215546Sopenharmony_ci } 536bf215546Sopenharmony_ci 537bf215546Sopenharmony_ci if (!fd_ringbuffer_check_size(batch->draw)) 538bf215546Sopenharmony_ci fd_batch_flush(batch); 539bf215546Sopenharmony_ci} 540bf215546Sopenharmony_ci 541bf215546Sopenharmony_ci/* emit a WAIT_FOR_IDLE only if needed, ie. if there has not already 542bf215546Sopenharmony_ci * been one since last draw: 543bf215546Sopenharmony_ci */ 544bf215546Sopenharmony_civoid 545bf215546Sopenharmony_cifd_wfi(struct fd_batch *batch, struct fd_ringbuffer *ring) 546bf215546Sopenharmony_ci{ 547bf215546Sopenharmony_ci if (batch->needs_wfi) { 548bf215546Sopenharmony_ci if (batch->ctx->screen->gen >= 5) 549bf215546Sopenharmony_ci OUT_WFI5(ring); 550bf215546Sopenharmony_ci else 551bf215546Sopenharmony_ci OUT_WFI(ring); 552bf215546Sopenharmony_ci batch->needs_wfi = false; 553bf215546Sopenharmony_ci } 554bf215546Sopenharmony_ci} 555