1bf215546Sopenharmony_ci#include "zink_batch.h"
2bf215546Sopenharmony_ci
3bf215546Sopenharmony_ci#include "zink_context.h"
4bf215546Sopenharmony_ci#include "zink_kopper.h"
5bf215546Sopenharmony_ci#include "zink_fence.h"
6bf215546Sopenharmony_ci#include "zink_framebuffer.h"
7bf215546Sopenharmony_ci#include "zink_query.h"
8bf215546Sopenharmony_ci#include "zink_program.h"
9bf215546Sopenharmony_ci#include "zink_render_pass.h"
10bf215546Sopenharmony_ci#include "zink_resource.h"
11bf215546Sopenharmony_ci#include "zink_screen.h"
12bf215546Sopenharmony_ci#include "zink_surface.h"
13bf215546Sopenharmony_ci
14bf215546Sopenharmony_ci#include "util/hash_table.h"
15bf215546Sopenharmony_ci#include "util/u_debug.h"
16bf215546Sopenharmony_ci#include "util/set.h"
17bf215546Sopenharmony_ci
18bf215546Sopenharmony_ci#ifdef VK_USE_PLATFORM_METAL_EXT
19bf215546Sopenharmony_ci#include "QuartzCore/CAMetalLayer.h"
20bf215546Sopenharmony_ci#endif
21bf215546Sopenharmony_ci#include "wsi_common.h"
22bf215546Sopenharmony_ci
23bf215546Sopenharmony_civoid
24bf215546Sopenharmony_cidebug_describe_zink_batch_state(char *buf, const struct zink_batch_state *ptr)
25bf215546Sopenharmony_ci{
26bf215546Sopenharmony_ci   sprintf(buf, "zink_batch_state");
27bf215546Sopenharmony_ci}
28bf215546Sopenharmony_ci
29bf215546Sopenharmony_civoid
30bf215546Sopenharmony_cizink_reset_batch_state(struct zink_context *ctx, struct zink_batch_state *bs)
31bf215546Sopenharmony_ci{
32bf215546Sopenharmony_ci   struct zink_screen *screen = zink_screen(ctx->base.screen);
33bf215546Sopenharmony_ci
34bf215546Sopenharmony_ci   VkResult result = VKSCR(ResetCommandPool)(screen->dev, bs->cmdpool, 0);
35bf215546Sopenharmony_ci   if (result != VK_SUCCESS)
36bf215546Sopenharmony_ci      mesa_loge("ZINK: vkResetCommandPool failed (%s)", vk_Result_to_str(result));
37bf215546Sopenharmony_ci
38bf215546Sopenharmony_ci   /* unref all used resources */
39bf215546Sopenharmony_ci   set_foreach_remove(bs->resources, entry) {
40bf215546Sopenharmony_ci      struct zink_resource_object *obj = (struct zink_resource_object *)entry->key;
41bf215546Sopenharmony_ci      if (!zink_resource_object_usage_unset(obj, bs)) {
42bf215546Sopenharmony_ci         obj->unordered_read = obj->unordered_write = false;
43bf215546Sopenharmony_ci         obj->access = 0;
44bf215546Sopenharmony_ci         obj->access_stage = 0;
45bf215546Sopenharmony_ci      }
46bf215546Sopenharmony_ci      util_dynarray_append(&bs->unref_resources, struct zink_resource_object*, obj);
47bf215546Sopenharmony_ci   }
48bf215546Sopenharmony_ci
49bf215546Sopenharmony_ci   for (unsigned i = 0; i < 2; i++) {
50bf215546Sopenharmony_ci      while (util_dynarray_contains(&bs->bindless_releases[i], uint32_t)) {
51bf215546Sopenharmony_ci         uint32_t handle = util_dynarray_pop(&bs->bindless_releases[i], uint32_t);
52bf215546Sopenharmony_ci         bool is_buffer = ZINK_BINDLESS_IS_BUFFER(handle);
53bf215546Sopenharmony_ci         struct util_idalloc *ids = i ? &ctx->di.bindless[is_buffer].img_slots : &ctx->di.bindless[is_buffer].tex_slots;
54bf215546Sopenharmony_ci         util_idalloc_free(ids, is_buffer ? handle - ZINK_MAX_BINDLESS_HANDLES : handle);
55bf215546Sopenharmony_ci      }
56bf215546Sopenharmony_ci   }
57bf215546Sopenharmony_ci
58bf215546Sopenharmony_ci   set_foreach_remove(bs->active_queries, entry) {
59bf215546Sopenharmony_ci      struct zink_query *query = (void*)entry->key;
60bf215546Sopenharmony_ci      zink_prune_query(screen, bs, query);
61bf215546Sopenharmony_ci   }
62bf215546Sopenharmony_ci
63bf215546Sopenharmony_ci   set_foreach_remove(bs->surfaces, entry) {
64bf215546Sopenharmony_ci      struct zink_surface *surf = (struct zink_surface *)entry->key;
65bf215546Sopenharmony_ci      zink_batch_usage_unset(&surf->batch_uses, bs);
66bf215546Sopenharmony_ci      zink_surface_reference(screen, &surf, NULL);
67bf215546Sopenharmony_ci   }
68bf215546Sopenharmony_ci   set_foreach_remove(bs->bufferviews, entry) {
69bf215546Sopenharmony_ci      struct zink_buffer_view *buffer_view = (struct zink_buffer_view *)entry->key;
70bf215546Sopenharmony_ci      zink_batch_usage_unset(&buffer_view->batch_uses, bs);
71bf215546Sopenharmony_ci      zink_buffer_view_reference(screen, &buffer_view, NULL);
72bf215546Sopenharmony_ci   }
73bf215546Sopenharmony_ci
74bf215546Sopenharmony_ci   util_dynarray_foreach(&bs->dead_framebuffers, struct zink_framebuffer*, fb) {
75bf215546Sopenharmony_ci      zink_framebuffer_reference(screen, fb, NULL);
76bf215546Sopenharmony_ci   }
77bf215546Sopenharmony_ci   util_dynarray_clear(&bs->dead_framebuffers);
78bf215546Sopenharmony_ci   util_dynarray_foreach(&bs->zombie_samplers, VkSampler, samp) {
79bf215546Sopenharmony_ci      VKSCR(DestroySampler)(screen->dev, *samp, NULL);
80bf215546Sopenharmony_ci   }
81bf215546Sopenharmony_ci   util_dynarray_clear(&bs->zombie_samplers);
82bf215546Sopenharmony_ci   util_dynarray_clear(&bs->persistent_resources);
83bf215546Sopenharmony_ci
84bf215546Sopenharmony_ci   screen->batch_descriptor_reset(screen, bs);
85bf215546Sopenharmony_ci
86bf215546Sopenharmony_ci   set_foreach_remove(bs->programs, entry) {
87bf215546Sopenharmony_ci      struct zink_program *pg = (struct zink_program*)entry->key;
88bf215546Sopenharmony_ci      zink_batch_usage_unset(&pg->batch_uses, bs);
89bf215546Sopenharmony_ci      zink_program_reference(ctx, &pg, NULL);
90bf215546Sopenharmony_ci   }
91bf215546Sopenharmony_ci
92bf215546Sopenharmony_ci   bs->resource_size = 0;
93bf215546Sopenharmony_ci   bs->signal_semaphore = VK_NULL_HANDLE;
94bf215546Sopenharmony_ci   while (util_dynarray_contains(&bs->wait_semaphores, VkSemaphore))
95bf215546Sopenharmony_ci      VKSCR(DestroySemaphore)(screen->dev, util_dynarray_pop(&bs->wait_semaphores, VkSemaphore), NULL);
96bf215546Sopenharmony_ci   util_dynarray_clear(&bs->wait_semaphore_stages);
97bf215546Sopenharmony_ci
98bf215546Sopenharmony_ci   bs->present = VK_NULL_HANDLE;
99bf215546Sopenharmony_ci   while (util_dynarray_contains(&bs->acquires, VkSemaphore))
100bf215546Sopenharmony_ci      VKSCR(DestroySemaphore)(screen->dev, util_dynarray_pop(&bs->acquires, VkSemaphore), NULL);
101bf215546Sopenharmony_ci   bs->swapchain = NULL;
102bf215546Sopenharmony_ci
103bf215546Sopenharmony_ci   while (util_dynarray_contains(&bs->dead_swapchains, VkImageView))
104bf215546Sopenharmony_ci      VKSCR(DestroyImageView)(screen->dev, util_dynarray_pop(&bs->dead_swapchains, VkImageView), NULL);
105bf215546Sopenharmony_ci
106bf215546Sopenharmony_ci   /* only reset submitted here so that tc fence desync can pick up the 'completed' flag
107bf215546Sopenharmony_ci    * before the state is reused
108bf215546Sopenharmony_ci    */
109bf215546Sopenharmony_ci   bs->fence.submitted = false;
110bf215546Sopenharmony_ci   bs->has_barriers = false;
111bf215546Sopenharmony_ci   if (bs->fence.batch_id)
112bf215546Sopenharmony_ci      zink_screen_update_last_finished(screen, bs->fence.batch_id);
113bf215546Sopenharmony_ci   bs->submit_count++;
114bf215546Sopenharmony_ci   bs->fence.batch_id = 0;
115bf215546Sopenharmony_ci   bs->usage.usage = 0;
116bf215546Sopenharmony_ci   bs->next = NULL;
117bf215546Sopenharmony_ci}
118bf215546Sopenharmony_ci
119bf215546Sopenharmony_cistatic void
120bf215546Sopenharmony_ciunref_resources(struct zink_screen *screen, struct zink_batch_state *bs)
121bf215546Sopenharmony_ci{
122bf215546Sopenharmony_ci   while (util_dynarray_contains(&bs->unref_resources, struct zink_resource_object*)) {
123bf215546Sopenharmony_ci      struct zink_resource_object *obj = util_dynarray_pop(&bs->unref_resources, struct zink_resource_object*);
124bf215546Sopenharmony_ci      zink_resource_object_reference(screen, &obj, NULL);
125bf215546Sopenharmony_ci   }
126bf215546Sopenharmony_ci}
127bf215546Sopenharmony_ci
128bf215546Sopenharmony_civoid
129bf215546Sopenharmony_cizink_clear_batch_state(struct zink_context *ctx, struct zink_batch_state *bs)
130bf215546Sopenharmony_ci{
131bf215546Sopenharmony_ci   bs->fence.completed = true;
132bf215546Sopenharmony_ci   zink_reset_batch_state(ctx, bs);
133bf215546Sopenharmony_ci   unref_resources(zink_screen(ctx->base.screen), bs);
134bf215546Sopenharmony_ci}
135bf215546Sopenharmony_ci
136bf215546Sopenharmony_cistatic void
137bf215546Sopenharmony_cipop_batch_state(struct zink_context *ctx)
138bf215546Sopenharmony_ci{
139bf215546Sopenharmony_ci   const struct zink_batch_state *bs = ctx->batch_states;
140bf215546Sopenharmony_ci   ctx->batch_states = bs->next;
141bf215546Sopenharmony_ci   ctx->batch_states_count--;
142bf215546Sopenharmony_ci   if (ctx->last_fence == &bs->fence)
143bf215546Sopenharmony_ci      ctx->last_fence = NULL;
144bf215546Sopenharmony_ci}
145bf215546Sopenharmony_ci
146bf215546Sopenharmony_civoid
147bf215546Sopenharmony_cizink_batch_reset_all(struct zink_context *ctx)
148bf215546Sopenharmony_ci{
149bf215546Sopenharmony_ci   while (ctx->batch_states) {
150bf215546Sopenharmony_ci      struct zink_batch_state *bs = ctx->batch_states;
151bf215546Sopenharmony_ci      bs->fence.completed = true;
152bf215546Sopenharmony_ci      pop_batch_state(ctx);
153bf215546Sopenharmony_ci      zink_reset_batch_state(ctx, bs);
154bf215546Sopenharmony_ci      util_dynarray_append(&ctx->free_batch_states, struct zink_batch_state *, bs);
155bf215546Sopenharmony_ci   }
156bf215546Sopenharmony_ci}
157bf215546Sopenharmony_ci
158bf215546Sopenharmony_civoid
159bf215546Sopenharmony_cizink_batch_state_destroy(struct zink_screen *screen, struct zink_batch_state *bs)
160bf215546Sopenharmony_ci{
161bf215546Sopenharmony_ci   if (!bs)
162bf215546Sopenharmony_ci      return;
163bf215546Sopenharmony_ci
164bf215546Sopenharmony_ci   util_queue_fence_destroy(&bs->flush_completed);
165bf215546Sopenharmony_ci
166bf215546Sopenharmony_ci   cnd_destroy(&bs->usage.flush);
167bf215546Sopenharmony_ci   mtx_destroy(&bs->usage.mtx);
168bf215546Sopenharmony_ci
169bf215546Sopenharmony_ci   if (bs->cmdbuf)
170bf215546Sopenharmony_ci      VKSCR(FreeCommandBuffers)(screen->dev, bs->cmdpool, 1, &bs->cmdbuf);
171bf215546Sopenharmony_ci   if (bs->barrier_cmdbuf)
172bf215546Sopenharmony_ci      VKSCR(FreeCommandBuffers)(screen->dev, bs->cmdpool, 1, &bs->barrier_cmdbuf);
173bf215546Sopenharmony_ci   if (bs->cmdpool)
174bf215546Sopenharmony_ci      VKSCR(DestroyCommandPool)(screen->dev, bs->cmdpool, NULL);
175bf215546Sopenharmony_ci
176bf215546Sopenharmony_ci   util_dynarray_fini(&bs->zombie_samplers);
177bf215546Sopenharmony_ci   util_dynarray_fini(&bs->dead_framebuffers);
178bf215546Sopenharmony_ci   util_dynarray_fini(&bs->unref_resources);
179bf215546Sopenharmony_ci   util_dynarray_fini(&bs->bindless_releases[0]);
180bf215546Sopenharmony_ci   util_dynarray_fini(&bs->bindless_releases[1]);
181bf215546Sopenharmony_ci   util_dynarray_fini(&bs->acquires);
182bf215546Sopenharmony_ci   util_dynarray_fini(&bs->acquire_flags);
183bf215546Sopenharmony_ci   util_dynarray_fini(&bs->dead_swapchains);
184bf215546Sopenharmony_ci   _mesa_set_destroy(bs->surfaces, NULL);
185bf215546Sopenharmony_ci   _mesa_set_destroy(bs->bufferviews, NULL);
186bf215546Sopenharmony_ci   _mesa_set_destroy(bs->programs, NULL);
187bf215546Sopenharmony_ci   _mesa_set_destroy(bs->active_queries, NULL);
188bf215546Sopenharmony_ci   screen->batch_descriptor_deinit(screen, bs);
189bf215546Sopenharmony_ci   ralloc_free(bs);
190bf215546Sopenharmony_ci}
191bf215546Sopenharmony_ci
192bf215546Sopenharmony_cistatic struct zink_batch_state *
193bf215546Sopenharmony_cicreate_batch_state(struct zink_context *ctx)
194bf215546Sopenharmony_ci{
195bf215546Sopenharmony_ci   struct zink_screen *screen = zink_screen(ctx->base.screen);
196bf215546Sopenharmony_ci   struct zink_batch_state *bs = rzalloc(NULL, struct zink_batch_state);
197bf215546Sopenharmony_ci   VkCommandPoolCreateInfo cpci = {0};
198bf215546Sopenharmony_ci   cpci.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
199bf215546Sopenharmony_ci   cpci.queueFamilyIndex = screen->gfx_queue;
200bf215546Sopenharmony_ci   VkResult result = VKSCR(CreateCommandPool)(screen->dev, &cpci, NULL, &bs->cmdpool);
201bf215546Sopenharmony_ci   if (result != VK_SUCCESS) {
202bf215546Sopenharmony_ci      mesa_loge("ZINK: vkCreateCommandPool failed (%s)", vk_Result_to_str(result));
203bf215546Sopenharmony_ci      goto fail;
204bf215546Sopenharmony_ci   }
205bf215546Sopenharmony_ci
206bf215546Sopenharmony_ci   VkCommandBufferAllocateInfo cbai = {0};
207bf215546Sopenharmony_ci   cbai.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
208bf215546Sopenharmony_ci   cbai.commandPool = bs->cmdpool;
209bf215546Sopenharmony_ci   cbai.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
210bf215546Sopenharmony_ci   cbai.commandBufferCount = 1;
211bf215546Sopenharmony_ci
212bf215546Sopenharmony_ci   result = VKSCR(AllocateCommandBuffers)(screen->dev, &cbai, &bs->cmdbuf);
213bf215546Sopenharmony_ci   if (result != VK_SUCCESS) {
214bf215546Sopenharmony_ci      mesa_loge("ZINK: vkAllocateCommandBuffers failed (%s)", vk_Result_to_str(result));
215bf215546Sopenharmony_ci      goto fail;
216bf215546Sopenharmony_ci   }
217bf215546Sopenharmony_ci
218bf215546Sopenharmony_ci   result = VKSCR(AllocateCommandBuffers)(screen->dev, &cbai, &bs->barrier_cmdbuf);
219bf215546Sopenharmony_ci   if (result != VK_SUCCESS) {
220bf215546Sopenharmony_ci      mesa_loge("ZINK: vkAllocateCommandBuffers failed (%s)", vk_Result_to_str(result));
221bf215546Sopenharmony_ci      goto fail;
222bf215546Sopenharmony_ci   }
223bf215546Sopenharmony_ci
224bf215546Sopenharmony_ci#define SET_CREATE_OR_FAIL(ptr) \
225bf215546Sopenharmony_ci   ptr = _mesa_pointer_set_create(bs); \
226bf215546Sopenharmony_ci   if (!ptr) \
227bf215546Sopenharmony_ci      goto fail
228bf215546Sopenharmony_ci
229bf215546Sopenharmony_ci   bs->ctx = ctx;
230bf215546Sopenharmony_ci
231bf215546Sopenharmony_ci   SET_CREATE_OR_FAIL(bs->resources);
232bf215546Sopenharmony_ci   SET_CREATE_OR_FAIL(bs->surfaces);
233bf215546Sopenharmony_ci   SET_CREATE_OR_FAIL(bs->bufferviews);
234bf215546Sopenharmony_ci   SET_CREATE_OR_FAIL(bs->programs);
235bf215546Sopenharmony_ci   SET_CREATE_OR_FAIL(bs->active_queries);
236bf215546Sopenharmony_ci   util_dynarray_init(&bs->wait_semaphores, NULL);
237bf215546Sopenharmony_ci   util_dynarray_init(&bs->wait_semaphore_stages, NULL);
238bf215546Sopenharmony_ci   util_dynarray_init(&bs->zombie_samplers, NULL);
239bf215546Sopenharmony_ci   util_dynarray_init(&bs->dead_framebuffers, NULL);
240bf215546Sopenharmony_ci   util_dynarray_init(&bs->persistent_resources, NULL);
241bf215546Sopenharmony_ci   util_dynarray_init(&bs->unref_resources, NULL);
242bf215546Sopenharmony_ci   util_dynarray_init(&bs->acquires, NULL);
243bf215546Sopenharmony_ci   util_dynarray_init(&bs->acquire_flags, NULL);
244bf215546Sopenharmony_ci   util_dynarray_init(&bs->dead_swapchains, NULL);
245bf215546Sopenharmony_ci   util_dynarray_init(&bs->bindless_releases[0], NULL);
246bf215546Sopenharmony_ci   util_dynarray_init(&bs->bindless_releases[1], NULL);
247bf215546Sopenharmony_ci
248bf215546Sopenharmony_ci   cnd_init(&bs->usage.flush);
249bf215546Sopenharmony_ci   mtx_init(&bs->usage.mtx, mtx_plain);
250bf215546Sopenharmony_ci
251bf215546Sopenharmony_ci   if (!screen->batch_descriptor_init(screen, bs))
252bf215546Sopenharmony_ci      goto fail;
253bf215546Sopenharmony_ci
254bf215546Sopenharmony_ci   util_queue_fence_init(&bs->flush_completed);
255bf215546Sopenharmony_ci
256bf215546Sopenharmony_ci   return bs;
257bf215546Sopenharmony_cifail:
258bf215546Sopenharmony_ci   zink_batch_state_destroy(screen, bs);
259bf215546Sopenharmony_ci   return NULL;
260bf215546Sopenharmony_ci}
261bf215546Sopenharmony_ci
262bf215546Sopenharmony_cistatic inline bool
263bf215546Sopenharmony_cifind_unused_state(struct zink_batch_state *bs)
264bf215546Sopenharmony_ci{
265bf215546Sopenharmony_ci   struct zink_fence *fence = &bs->fence;
266bf215546Sopenharmony_ci   /* we can't reset these from fence_finish because threads */
267bf215546Sopenharmony_ci   bool completed = p_atomic_read(&fence->completed);
268bf215546Sopenharmony_ci   bool submitted = p_atomic_read(&fence->submitted);
269bf215546Sopenharmony_ci   return submitted && completed;
270bf215546Sopenharmony_ci}
271bf215546Sopenharmony_ci
272bf215546Sopenharmony_cistatic struct zink_batch_state *
273bf215546Sopenharmony_ciget_batch_state(struct zink_context *ctx, struct zink_batch *batch)
274bf215546Sopenharmony_ci{
275bf215546Sopenharmony_ci   struct zink_screen *screen = zink_screen(ctx->base.screen);
276bf215546Sopenharmony_ci   struct zink_batch_state *bs = NULL;
277bf215546Sopenharmony_ci
278bf215546Sopenharmony_ci   if (util_dynarray_num_elements(&ctx->free_batch_states, struct zink_batch_state*))
279bf215546Sopenharmony_ci      bs = util_dynarray_pop(&ctx->free_batch_states, struct zink_batch_state*);
280bf215546Sopenharmony_ci   if (!bs && ctx->batch_states) {
281bf215546Sopenharmony_ci      /* states are stored sequentially, so if the first one doesn't work, none of them will */
282bf215546Sopenharmony_ci      if (zink_screen_check_last_finished(screen, ctx->batch_states->fence.batch_id) ||
283bf215546Sopenharmony_ci          find_unused_state(ctx->batch_states)) {
284bf215546Sopenharmony_ci         bs = ctx->batch_states;
285bf215546Sopenharmony_ci         pop_batch_state(ctx);
286bf215546Sopenharmony_ci      }
287bf215546Sopenharmony_ci   }
288bf215546Sopenharmony_ci   if (bs) {
289bf215546Sopenharmony_ci      zink_reset_batch_state(ctx, bs);
290bf215546Sopenharmony_ci   } else {
291bf215546Sopenharmony_ci      if (!batch->state) {
292bf215546Sopenharmony_ci         /* this is batch init, so create a few more states for later use */
293bf215546Sopenharmony_ci         for (int i = 0; i < 3; i++) {
294bf215546Sopenharmony_ci            struct zink_batch_state *state = create_batch_state(ctx);
295bf215546Sopenharmony_ci            util_dynarray_append(&ctx->free_batch_states, struct zink_batch_state *, state);
296bf215546Sopenharmony_ci         }
297bf215546Sopenharmony_ci      }
298bf215546Sopenharmony_ci      bs = create_batch_state(ctx);
299bf215546Sopenharmony_ci   }
300bf215546Sopenharmony_ci   return bs;
301bf215546Sopenharmony_ci}
302bf215546Sopenharmony_ci
303bf215546Sopenharmony_civoid
304bf215546Sopenharmony_cizink_reset_batch(struct zink_context *ctx, struct zink_batch *batch)
305bf215546Sopenharmony_ci{
306bf215546Sopenharmony_ci   batch->state = get_batch_state(ctx, batch);
307bf215546Sopenharmony_ci   assert(batch->state);
308bf215546Sopenharmony_ci
309bf215546Sopenharmony_ci   batch->has_work = false;
310bf215546Sopenharmony_ci}
311bf215546Sopenharmony_ci
312bf215546Sopenharmony_civoid
313bf215546Sopenharmony_cizink_start_batch(struct zink_context *ctx, struct zink_batch *batch)
314bf215546Sopenharmony_ci{
315bf215546Sopenharmony_ci   zink_reset_batch(ctx, batch);
316bf215546Sopenharmony_ci
317bf215546Sopenharmony_ci   batch->state->usage.unflushed = true;
318bf215546Sopenharmony_ci
319bf215546Sopenharmony_ci   VkCommandBufferBeginInfo cbbi = {0};
320bf215546Sopenharmony_ci   cbbi.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
321bf215546Sopenharmony_ci   cbbi.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
322bf215546Sopenharmony_ci
323bf215546Sopenharmony_ci   VkResult result = VKCTX(BeginCommandBuffer)(batch->state->cmdbuf, &cbbi);
324bf215546Sopenharmony_ci   if (result != VK_SUCCESS)
325bf215546Sopenharmony_ci      mesa_loge("ZINK: vkBeginCommandBuffer failed (%s)", vk_Result_to_str(result));
326bf215546Sopenharmony_ci
327bf215546Sopenharmony_ci   result = VKCTX(BeginCommandBuffer)(batch->state->barrier_cmdbuf, &cbbi);
328bf215546Sopenharmony_ci   if (result != VK_SUCCESS)
329bf215546Sopenharmony_ci      mesa_loge("ZINK: vkBeginCommandBuffer failed (%s)", vk_Result_to_str(result));
330bf215546Sopenharmony_ci
331bf215546Sopenharmony_ci   batch->state->fence.completed = false;
332bf215546Sopenharmony_ci   if (ctx->last_fence) {
333bf215546Sopenharmony_ci      struct zink_batch_state *last_state = zink_batch_state(ctx->last_fence);
334bf215546Sopenharmony_ci      batch->last_batch_usage = &last_state->usage;
335bf215546Sopenharmony_ci   }
336bf215546Sopenharmony_ci
337bf215546Sopenharmony_ci   if (!ctx->queries_disabled)
338bf215546Sopenharmony_ci      zink_resume_queries(ctx, batch);
339bf215546Sopenharmony_ci}
340bf215546Sopenharmony_ci
341bf215546Sopenharmony_cistatic void
342bf215546Sopenharmony_cipost_submit(void *data, void *gdata, int thread_index)
343bf215546Sopenharmony_ci{
344bf215546Sopenharmony_ci   struct zink_batch_state *bs = data;
345bf215546Sopenharmony_ci   struct zink_screen *screen = zink_screen(bs->ctx->base.screen);
346bf215546Sopenharmony_ci
347bf215546Sopenharmony_ci   if (bs->is_device_lost) {
348bf215546Sopenharmony_ci      if (bs->ctx->reset.reset)
349bf215546Sopenharmony_ci         bs->ctx->reset.reset(bs->ctx->reset.data, PIPE_GUILTY_CONTEXT_RESET);
350bf215546Sopenharmony_ci      else if (screen->abort_on_hang && !screen->robust_ctx_count)
351bf215546Sopenharmony_ci         /* if nothing can save us, abort */
352bf215546Sopenharmony_ci         abort();
353bf215546Sopenharmony_ci      screen->device_lost = true;
354bf215546Sopenharmony_ci   } else if (bs->ctx->batch_states_count > 5000) {
355bf215546Sopenharmony_ci      zink_screen_timeline_wait(screen, bs->fence.batch_id - 2500, PIPE_TIMEOUT_INFINITE);
356bf215546Sopenharmony_ci   }
357bf215546Sopenharmony_ci}
358bf215546Sopenharmony_ci
359bf215546Sopenharmony_cistatic void
360bf215546Sopenharmony_cisubmit_queue(void *data, void *gdata, int thread_index)
361bf215546Sopenharmony_ci{
362bf215546Sopenharmony_ci   struct zink_batch_state *bs = data;
363bf215546Sopenharmony_ci   struct zink_context *ctx = bs->ctx;
364bf215546Sopenharmony_ci   struct zink_screen *screen = zink_screen(ctx->base.screen);
365bf215546Sopenharmony_ci   VkSubmitInfo si[2] = {0};
366bf215546Sopenharmony_ci   int num_si = 2;
367bf215546Sopenharmony_ci   while (!bs->fence.batch_id)
368bf215546Sopenharmony_ci      bs->fence.batch_id = (uint32_t)p_atomic_inc_return(&screen->curr_batch);
369bf215546Sopenharmony_ci   bs->usage.usage = bs->fence.batch_id;
370bf215546Sopenharmony_ci   bs->usage.unflushed = false;
371bf215546Sopenharmony_ci
372bf215546Sopenharmony_ci   uint64_t batch_id = bs->fence.batch_id;
373bf215546Sopenharmony_ci   /* first submit is just for acquire waits since they have a separate array */
374bf215546Sopenharmony_ci   si[0].sType = si[1].sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
375bf215546Sopenharmony_ci   si[0].waitSemaphoreCount = util_dynarray_num_elements(&bs->acquires, VkSemaphore);
376bf215546Sopenharmony_ci   si[0].pWaitSemaphores = bs->acquires.data;
377bf215546Sopenharmony_ci   while (util_dynarray_num_elements(&bs->acquire_flags, VkPipelineStageFlags) < si[0].waitSemaphoreCount) {
378bf215546Sopenharmony_ci      VkPipelineStageFlags mask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
379bf215546Sopenharmony_ci      util_dynarray_append(&bs->acquire_flags, VkPipelineStageFlags, mask);
380bf215546Sopenharmony_ci   }
381bf215546Sopenharmony_ci   assert(util_dynarray_num_elements(&bs->acquires, VkSemaphore) <= util_dynarray_num_elements(&bs->acquire_flags, VkPipelineStageFlags));
382bf215546Sopenharmony_ci   si[0].pWaitDstStageMask = bs->acquire_flags.data;
383bf215546Sopenharmony_ci
384bf215546Sopenharmony_ci   if (si[0].waitSemaphoreCount == 0)
385bf215546Sopenharmony_ci     num_si--;
386bf215546Sopenharmony_ci
387bf215546Sopenharmony_ci   /* then the real submit */
388bf215546Sopenharmony_ci   si[1].waitSemaphoreCount = util_dynarray_num_elements(&bs->wait_semaphores, VkSemaphore);
389bf215546Sopenharmony_ci   si[1].pWaitSemaphores = bs->wait_semaphores.data;
390bf215546Sopenharmony_ci   si[1].pWaitDstStageMask = bs->wait_semaphore_stages.data;
391bf215546Sopenharmony_ci   si[1].commandBufferCount = bs->has_barriers ? 2 : 1;
392bf215546Sopenharmony_ci   VkCommandBuffer cmdbufs[2] = {
393bf215546Sopenharmony_ci      bs->barrier_cmdbuf,
394bf215546Sopenharmony_ci      bs->cmdbuf,
395bf215546Sopenharmony_ci   };
396bf215546Sopenharmony_ci   si[1].pCommandBuffers = bs->has_barriers ? cmdbufs : &cmdbufs[1];
397bf215546Sopenharmony_ci
398bf215546Sopenharmony_ci   VkSemaphore signals[3];
399bf215546Sopenharmony_ci   si[1].signalSemaphoreCount = !!bs->signal_semaphore;
400bf215546Sopenharmony_ci   signals[0] = bs->signal_semaphore;
401bf215546Sopenharmony_ci   si[1].pSignalSemaphores = signals;
402bf215546Sopenharmony_ci   VkTimelineSemaphoreSubmitInfo tsi = {0};
403bf215546Sopenharmony_ci   uint64_t signal_values[2] = {0};
404bf215546Sopenharmony_ci   tsi.sType = VK_STRUCTURE_TYPE_TIMELINE_SEMAPHORE_SUBMIT_INFO;
405bf215546Sopenharmony_ci   si[1].pNext = &tsi;
406bf215546Sopenharmony_ci   tsi.pSignalSemaphoreValues = signal_values;
407bf215546Sopenharmony_ci   signal_values[si[1].signalSemaphoreCount] = batch_id;
408bf215546Sopenharmony_ci   signals[si[1].signalSemaphoreCount++] = screen->sem;
409bf215546Sopenharmony_ci   tsi.signalSemaphoreValueCount = si[1].signalSemaphoreCount;
410bf215546Sopenharmony_ci
411bf215546Sopenharmony_ci   if (bs->present)
412bf215546Sopenharmony_ci      signals[si[1].signalSemaphoreCount++] = bs->present;
413bf215546Sopenharmony_ci   tsi.signalSemaphoreValueCount = si[1].signalSemaphoreCount;
414bf215546Sopenharmony_ci
415bf215546Sopenharmony_ci   VkResult result = VKSCR(EndCommandBuffer)(bs->cmdbuf);
416bf215546Sopenharmony_ci   if (result != VK_SUCCESS) {
417bf215546Sopenharmony_ci      mesa_loge("ZINK: vkEndCommandBuffer failed (%s)", vk_Result_to_str(result));
418bf215546Sopenharmony_ci      bs->is_device_lost = true;
419bf215546Sopenharmony_ci      goto end;
420bf215546Sopenharmony_ci   }
421bf215546Sopenharmony_ci   if (bs->has_barriers) {
422bf215546Sopenharmony_ci      result = VKSCR(EndCommandBuffer)(bs->barrier_cmdbuf);
423bf215546Sopenharmony_ci      if (result != VK_SUCCESS) {
424bf215546Sopenharmony_ci         mesa_loge("ZINK: vkEndCommandBuffer failed (%s)", vk_Result_to_str(result));
425bf215546Sopenharmony_ci         bs->is_device_lost = true;
426bf215546Sopenharmony_ci         goto end;
427bf215546Sopenharmony_ci      }
428bf215546Sopenharmony_ci   }
429bf215546Sopenharmony_ci
430bf215546Sopenharmony_ci   while (util_dynarray_contains(&bs->persistent_resources, struct zink_resource_object*)) {
431bf215546Sopenharmony_ci      struct zink_resource_object *obj = util_dynarray_pop(&bs->persistent_resources, struct zink_resource_object*);
432bf215546Sopenharmony_ci       VkMappedMemoryRange range = zink_resource_init_mem_range(screen, obj, 0, obj->size);
433bf215546Sopenharmony_ci
434bf215546Sopenharmony_ci       result = VKSCR(FlushMappedMemoryRanges)(screen->dev, 1, &range);
435bf215546Sopenharmony_ci       if (result != VK_SUCCESS) {
436bf215546Sopenharmony_ci          mesa_loge("ZINK: vkFlushMappedMemoryRanges failed (%s)", vk_Result_to_str(result));
437bf215546Sopenharmony_ci       }
438bf215546Sopenharmony_ci   }
439bf215546Sopenharmony_ci
440bf215546Sopenharmony_ci   simple_mtx_lock(&screen->queue_lock);
441bf215546Sopenharmony_ci   result = VKSCR(QueueSubmit)(screen->queue, num_si, num_si == 2 ? si : &si[1], VK_NULL_HANDLE);
442bf215546Sopenharmony_ci   if (result != VK_SUCCESS) {
443bf215546Sopenharmony_ci      mesa_loge("ZINK: vkQueueSubmit failed (%s)", vk_Result_to_str(result));
444bf215546Sopenharmony_ci      bs->is_device_lost = true;
445bf215546Sopenharmony_ci   }
446bf215546Sopenharmony_ci   simple_mtx_unlock(&screen->queue_lock);
447bf215546Sopenharmony_ci   bs->submit_count++;
448bf215546Sopenharmony_ciend:
449bf215546Sopenharmony_ci   cnd_broadcast(&bs->usage.flush);
450bf215546Sopenharmony_ci
451bf215546Sopenharmony_ci   p_atomic_set(&bs->fence.submitted, true);
452bf215546Sopenharmony_ci   unref_resources(screen, bs);
453bf215546Sopenharmony_ci}
454bf215546Sopenharmony_ci
455bf215546Sopenharmony_civoid
456bf215546Sopenharmony_cizink_end_batch(struct zink_context *ctx, struct zink_batch *batch)
457bf215546Sopenharmony_ci{
458bf215546Sopenharmony_ci   if (!ctx->queries_disabled)
459bf215546Sopenharmony_ci      zink_suspend_queries(ctx, batch);
460bf215546Sopenharmony_ci
461bf215546Sopenharmony_ci   tc_driver_internal_flush_notify(ctx->tc);
462bf215546Sopenharmony_ci
463bf215546Sopenharmony_ci   struct zink_screen *screen = zink_screen(ctx->base.screen);
464bf215546Sopenharmony_ci   struct zink_batch_state *bs;
465bf215546Sopenharmony_ci
466bf215546Sopenharmony_ci   if (ctx->oom_flush || ctx->batch_states_count > 10) {
467bf215546Sopenharmony_ci      assert(!ctx->batch_states_count || ctx->batch_states);
468bf215546Sopenharmony_ci      while (ctx->batch_states) {
469bf215546Sopenharmony_ci         bs = ctx->batch_states;
470bf215546Sopenharmony_ci         struct zink_fence *fence = &bs->fence;
471bf215546Sopenharmony_ci         /* once an incomplete state is reached, no more will be complete */
472bf215546Sopenharmony_ci         if (!zink_check_batch_completion(ctx, fence->batch_id))
473bf215546Sopenharmony_ci            break;
474bf215546Sopenharmony_ci
475bf215546Sopenharmony_ci         pop_batch_state(ctx);
476bf215546Sopenharmony_ci         zink_reset_batch_state(ctx, bs);
477bf215546Sopenharmony_ci         util_dynarray_append(&ctx->free_batch_states, struct zink_batch_state *, bs);
478bf215546Sopenharmony_ci      }
479bf215546Sopenharmony_ci      if (ctx->batch_states_count > 50)
480bf215546Sopenharmony_ci         ctx->oom_flush = true;
481bf215546Sopenharmony_ci   }
482bf215546Sopenharmony_ci
483bf215546Sopenharmony_ci   bs = batch->state;
484bf215546Sopenharmony_ci   if (ctx->last_fence)
485bf215546Sopenharmony_ci      zink_batch_state(ctx->last_fence)->next = bs;
486bf215546Sopenharmony_ci   else {
487bf215546Sopenharmony_ci      assert(!ctx->batch_states);
488bf215546Sopenharmony_ci      ctx->batch_states = bs;
489bf215546Sopenharmony_ci   }
490bf215546Sopenharmony_ci   ctx->last_fence = &bs->fence;
491bf215546Sopenharmony_ci   ctx->batch_states_count++;
492bf215546Sopenharmony_ci   batch->work_count = 0;
493bf215546Sopenharmony_ci
494bf215546Sopenharmony_ci   if (batch->swapchain) {
495bf215546Sopenharmony_ci      if (zink_kopper_acquired(batch->swapchain->obj->dt, batch->swapchain->obj->dt_idx) && !batch->swapchain->obj->present) {
496bf215546Sopenharmony_ci         batch->state->present = zink_kopper_present(screen, batch->swapchain);
497bf215546Sopenharmony_ci         batch->state->swapchain = batch->swapchain;
498bf215546Sopenharmony_ci      }
499bf215546Sopenharmony_ci      batch->swapchain = NULL;
500bf215546Sopenharmony_ci   }
501bf215546Sopenharmony_ci
502bf215546Sopenharmony_ci   if (screen->device_lost)
503bf215546Sopenharmony_ci      return;
504bf215546Sopenharmony_ci
505bf215546Sopenharmony_ci   if (screen->threaded) {
506bf215546Sopenharmony_ci      util_queue_add_job(&screen->flush_queue, bs, &bs->flush_completed,
507bf215546Sopenharmony_ci                         submit_queue, post_submit, 0);
508bf215546Sopenharmony_ci   } else {
509bf215546Sopenharmony_ci      submit_queue(bs, NULL, 0);
510bf215546Sopenharmony_ci      post_submit(bs, NULL, 0);
511bf215546Sopenharmony_ci   }
512bf215546Sopenharmony_ci}
513bf215546Sopenharmony_ci
514bf215546Sopenharmony_civoid
515bf215546Sopenharmony_cizink_batch_resource_usage_set(struct zink_batch *batch, struct zink_resource *res, bool write)
516bf215546Sopenharmony_ci{
517bf215546Sopenharmony_ci   if (res->obj->dt) {
518bf215546Sopenharmony_ci      VkSemaphore acquire = zink_kopper_acquire_submit(zink_screen(batch->state->ctx->base.screen), res);
519bf215546Sopenharmony_ci      if (acquire)
520bf215546Sopenharmony_ci         util_dynarray_append(&batch->state->acquires, VkSemaphore, acquire);
521bf215546Sopenharmony_ci   }
522bf215546Sopenharmony_ci   if (write && !res->obj->is_buffer) {
523bf215546Sopenharmony_ci      if (!res->valid && res->fb_binds)
524bf215546Sopenharmony_ci         batch->state->ctx->rp_loadop_changed = true;
525bf215546Sopenharmony_ci      res->valid = true;
526bf215546Sopenharmony_ci   }
527bf215546Sopenharmony_ci   zink_resource_usage_set(res, batch->state, write);
528bf215546Sopenharmony_ci   /* multiple array entries are fine */
529bf215546Sopenharmony_ci   if (!res->obj->coherent && res->obj->persistent_maps)
530bf215546Sopenharmony_ci      util_dynarray_append(&batch->state->persistent_resources, struct zink_resource_object*, res->obj);
531bf215546Sopenharmony_ci
532bf215546Sopenharmony_ci   batch->has_work = true;
533bf215546Sopenharmony_ci}
534bf215546Sopenharmony_ci
535bf215546Sopenharmony_civoid
536bf215546Sopenharmony_cizink_batch_reference_resource_rw(struct zink_batch *batch, struct zink_resource *res, bool write)
537bf215546Sopenharmony_ci{
538bf215546Sopenharmony_ci   /* if the resource already has usage of any sort set for this batch, */
539bf215546Sopenharmony_ci   if (!zink_resource_usage_matches(res, batch->state) ||
540bf215546Sopenharmony_ci       /* or if it's bound somewhere */
541bf215546Sopenharmony_ci       !zink_resource_has_binds(res))
542bf215546Sopenharmony_ci      /* then it already has a batch ref and doesn't need one here */
543bf215546Sopenharmony_ci      zink_batch_reference_resource(batch, res);
544bf215546Sopenharmony_ci   zink_batch_resource_usage_set(batch, res, write);
545bf215546Sopenharmony_ci}
546bf215546Sopenharmony_ci
547bf215546Sopenharmony_civoid
548bf215546Sopenharmony_cizink_batch_add_wait_semaphore(struct zink_batch *batch, VkSemaphore sem)
549bf215546Sopenharmony_ci{
550bf215546Sopenharmony_ci   util_dynarray_append(&batch->state->acquires, VkSemaphore, sem);
551bf215546Sopenharmony_ci}
552bf215546Sopenharmony_ci
553bf215546Sopenharmony_cibool
554bf215546Sopenharmony_cibatch_ptr_add_usage(struct zink_batch *batch, struct set *s, void *ptr)
555bf215546Sopenharmony_ci{
556bf215546Sopenharmony_ci   bool found = false;
557bf215546Sopenharmony_ci   _mesa_set_search_or_add(s, ptr, &found);
558bf215546Sopenharmony_ci   return !found;
559bf215546Sopenharmony_ci}
560bf215546Sopenharmony_ci
561bf215546Sopenharmony_ciALWAYS_INLINE static void
562bf215546Sopenharmony_cicheck_oom_flush(struct zink_context *ctx, const struct zink_batch *batch)
563bf215546Sopenharmony_ci{
564bf215546Sopenharmony_ci   const VkDeviceSize resource_size = batch->state->resource_size;
565bf215546Sopenharmony_ci   if (resource_size >= zink_screen(ctx->base.screen)->clamp_video_mem) {
566bf215546Sopenharmony_ci       ctx->oom_flush = true;
567bf215546Sopenharmony_ci       ctx->oom_stall = true;
568bf215546Sopenharmony_ci    }
569bf215546Sopenharmony_ci}
570bf215546Sopenharmony_ci
571bf215546Sopenharmony_civoid
572bf215546Sopenharmony_cizink_batch_reference_resource(struct zink_batch *batch, struct zink_resource *res)
573bf215546Sopenharmony_ci{
574bf215546Sopenharmony_ci   if (!batch_ptr_add_usage(batch, batch->state->resources, res->obj))
575bf215546Sopenharmony_ci      return;
576bf215546Sopenharmony_ci   pipe_reference(NULL, &res->obj->reference);
577bf215546Sopenharmony_ci   batch->state->resource_size += res->obj->size;
578bf215546Sopenharmony_ci   check_oom_flush(batch->state->ctx, batch);
579bf215546Sopenharmony_ci   batch->has_work = true;
580bf215546Sopenharmony_ci}
581bf215546Sopenharmony_ci
582bf215546Sopenharmony_civoid
583bf215546Sopenharmony_cizink_batch_reference_resource_move(struct zink_batch *batch, struct zink_resource *res)
584bf215546Sopenharmony_ci{
585bf215546Sopenharmony_ci   if (!batch_ptr_add_usage(batch, batch->state->resources, res->obj))
586bf215546Sopenharmony_ci      return;
587bf215546Sopenharmony_ci   batch->state->resource_size += res->obj->size;
588bf215546Sopenharmony_ci   check_oom_flush(batch->state->ctx, batch);
589bf215546Sopenharmony_ci   batch->has_work = true;
590bf215546Sopenharmony_ci}
591bf215546Sopenharmony_ci
592bf215546Sopenharmony_civoid
593bf215546Sopenharmony_cizink_batch_reference_bufferview(struct zink_batch *batch, struct zink_buffer_view *buffer_view)
594bf215546Sopenharmony_ci{
595bf215546Sopenharmony_ci   if (!batch_ptr_add_usage(batch, batch->state->bufferviews, buffer_view))
596bf215546Sopenharmony_ci      return;
597bf215546Sopenharmony_ci   pipe_reference(NULL, &buffer_view->reference);
598bf215546Sopenharmony_ci   batch->has_work = true;
599bf215546Sopenharmony_ci}
600bf215546Sopenharmony_ci
601bf215546Sopenharmony_civoid
602bf215546Sopenharmony_cizink_batch_reference_surface(struct zink_batch *batch, struct zink_surface *surface)
603bf215546Sopenharmony_ci{
604bf215546Sopenharmony_ci   if (!batch_ptr_add_usage(batch, batch->state->surfaces, surface))
605bf215546Sopenharmony_ci      return;
606bf215546Sopenharmony_ci   struct pipe_surface *surf = NULL;
607bf215546Sopenharmony_ci   pipe_surface_reference(&surf, &surface->base);
608bf215546Sopenharmony_ci   batch->has_work = true;
609bf215546Sopenharmony_ci}
610bf215546Sopenharmony_ci
611bf215546Sopenharmony_civoid
612bf215546Sopenharmony_cizink_batch_reference_sampler_view(struct zink_batch *batch,
613bf215546Sopenharmony_ci                                  struct zink_sampler_view *sv)
614bf215546Sopenharmony_ci{
615bf215546Sopenharmony_ci   if (sv->base.target == PIPE_BUFFER)
616bf215546Sopenharmony_ci      zink_batch_reference_bufferview(batch, sv->buffer_view);
617bf215546Sopenharmony_ci   else {
618bf215546Sopenharmony_ci      zink_batch_reference_surface(batch, sv->image_view);
619bf215546Sopenharmony_ci      if (sv->cube_array)
620bf215546Sopenharmony_ci         zink_batch_reference_surface(batch, sv->cube_array);
621bf215546Sopenharmony_ci   }
622bf215546Sopenharmony_ci}
623bf215546Sopenharmony_ci
624bf215546Sopenharmony_civoid
625bf215546Sopenharmony_cizink_batch_reference_program(struct zink_batch *batch,
626bf215546Sopenharmony_ci                             struct zink_program *pg)
627bf215546Sopenharmony_ci{
628bf215546Sopenharmony_ci   if (zink_batch_usage_matches(pg->batch_uses, batch->state) ||
629bf215546Sopenharmony_ci       !batch_ptr_add_usage(batch, batch->state->programs, pg))
630bf215546Sopenharmony_ci      return;
631bf215546Sopenharmony_ci   pipe_reference(NULL, &pg->reference);
632bf215546Sopenharmony_ci   zink_batch_usage_set(&pg->batch_uses, batch->state);
633bf215546Sopenharmony_ci   batch->has_work = true;
634bf215546Sopenharmony_ci}
635bf215546Sopenharmony_ci
636bf215546Sopenharmony_civoid
637bf215546Sopenharmony_cizink_batch_reference_image_view(struct zink_batch *batch,
638bf215546Sopenharmony_ci                                struct zink_image_view *image_view)
639bf215546Sopenharmony_ci{
640bf215546Sopenharmony_ci   if (image_view->base.resource->target == PIPE_BUFFER)
641bf215546Sopenharmony_ci      zink_batch_reference_bufferview(batch, image_view->buffer_view);
642bf215546Sopenharmony_ci   else
643bf215546Sopenharmony_ci      zink_batch_reference_surface(batch, image_view->surface);
644bf215546Sopenharmony_ci}
645bf215546Sopenharmony_ci
646bf215546Sopenharmony_cibool
647bf215546Sopenharmony_cizink_screen_usage_check_completion(struct zink_screen *screen, const struct zink_batch_usage *u)
648bf215546Sopenharmony_ci{
649bf215546Sopenharmony_ci   if (!zink_batch_usage_exists(u))
650bf215546Sopenharmony_ci      return true;
651bf215546Sopenharmony_ci   if (zink_batch_usage_is_unflushed(u))
652bf215546Sopenharmony_ci      return false;
653bf215546Sopenharmony_ci
654bf215546Sopenharmony_ci   return zink_screen_timeline_wait(screen, u->usage, 0);
655bf215546Sopenharmony_ci}
656bf215546Sopenharmony_ci
657bf215546Sopenharmony_cibool
658bf215546Sopenharmony_cizink_batch_usage_check_completion(struct zink_context *ctx, const struct zink_batch_usage *u)
659bf215546Sopenharmony_ci{
660bf215546Sopenharmony_ci   if (!zink_batch_usage_exists(u))
661bf215546Sopenharmony_ci      return true;
662bf215546Sopenharmony_ci   if (zink_batch_usage_is_unflushed(u))
663bf215546Sopenharmony_ci      return false;
664bf215546Sopenharmony_ci   return zink_check_batch_completion(ctx, u->usage);
665bf215546Sopenharmony_ci}
666bf215546Sopenharmony_ci
667bf215546Sopenharmony_civoid
668bf215546Sopenharmony_cizink_batch_usage_wait(struct zink_context *ctx, struct zink_batch_usage *u)
669bf215546Sopenharmony_ci{
670bf215546Sopenharmony_ci   if (!zink_batch_usage_exists(u))
671bf215546Sopenharmony_ci      return;
672bf215546Sopenharmony_ci   if (zink_batch_usage_is_unflushed(u)) {
673bf215546Sopenharmony_ci      if (likely(u == &ctx->batch.state->usage))
674bf215546Sopenharmony_ci         ctx->base.flush(&ctx->base, NULL, PIPE_FLUSH_HINT_FINISH);
675bf215546Sopenharmony_ci      else { //multi-context
676bf215546Sopenharmony_ci         mtx_lock(&u->mtx);
677bf215546Sopenharmony_ci         cnd_wait(&u->flush, &u->mtx);
678bf215546Sopenharmony_ci         mtx_unlock(&u->mtx);
679bf215546Sopenharmony_ci      }
680bf215546Sopenharmony_ci   }
681bf215546Sopenharmony_ci   zink_wait_on_batch(ctx, u->usage);
682bf215546Sopenharmony_ci}
683