1bf215546Sopenharmony_ci/*
2bf215546Sopenharmony_ci * Copyright © 2020 Google, Inc.
3bf215546Sopenharmony_ci * SPDX-License-Identifier: MIT
4bf215546Sopenharmony_ci */
5bf215546Sopenharmony_ci
6bf215546Sopenharmony_ci#include "tu_drm.h"
7bf215546Sopenharmony_ci
8bf215546Sopenharmony_ci#include <errno.h>
9bf215546Sopenharmony_ci#include <fcntl.h>
10bf215546Sopenharmony_ci#include <sys/ioctl.h>
11bf215546Sopenharmony_ci#include <sys/mman.h>
12bf215546Sopenharmony_ci
13bf215546Sopenharmony_ci#include "msm_kgsl.h"
14bf215546Sopenharmony_ci#include "vk_util.h"
15bf215546Sopenharmony_ci
16bf215546Sopenharmony_ci#include "util/debug.h"
17bf215546Sopenharmony_ci
18bf215546Sopenharmony_ci#include "tu_cmd_buffer.h"
19bf215546Sopenharmony_ci#include "tu_cs.h"
20bf215546Sopenharmony_ci#include "tu_device.h"
21bf215546Sopenharmony_ci#include "tu_dynamic_rendering.h"
22bf215546Sopenharmony_ci
23bf215546Sopenharmony_cistruct tu_syncobj {
24bf215546Sopenharmony_ci   struct vk_object_base base;
25bf215546Sopenharmony_ci   uint32_t timestamp;
26bf215546Sopenharmony_ci   bool timestamp_valid;
27bf215546Sopenharmony_ci};
28bf215546Sopenharmony_ci
29bf215546Sopenharmony_cistatic int
30bf215546Sopenharmony_cisafe_ioctl(int fd, unsigned long request, void *arg)
31bf215546Sopenharmony_ci{
32bf215546Sopenharmony_ci   int ret;
33bf215546Sopenharmony_ci
34bf215546Sopenharmony_ci   do {
35bf215546Sopenharmony_ci      ret = ioctl(fd, request, arg);
36bf215546Sopenharmony_ci   } while (ret == -1 && (errno == EINTR || errno == EAGAIN));
37bf215546Sopenharmony_ci
38bf215546Sopenharmony_ci   return ret;
39bf215546Sopenharmony_ci}
40bf215546Sopenharmony_ci
41bf215546Sopenharmony_ciint
42bf215546Sopenharmony_citu_drm_submitqueue_new(const struct tu_device *dev,
43bf215546Sopenharmony_ci                       int priority,
44bf215546Sopenharmony_ci                       uint32_t *queue_id)
45bf215546Sopenharmony_ci{
46bf215546Sopenharmony_ci   struct kgsl_drawctxt_create req = {
47bf215546Sopenharmony_ci      .flags = KGSL_CONTEXT_SAVE_GMEM |
48bf215546Sopenharmony_ci              KGSL_CONTEXT_NO_GMEM_ALLOC |
49bf215546Sopenharmony_ci              KGSL_CONTEXT_PREAMBLE,
50bf215546Sopenharmony_ci   };
51bf215546Sopenharmony_ci
52bf215546Sopenharmony_ci   int ret = safe_ioctl(dev->physical_device->local_fd, IOCTL_KGSL_DRAWCTXT_CREATE, &req);
53bf215546Sopenharmony_ci   if (ret)
54bf215546Sopenharmony_ci      return ret;
55bf215546Sopenharmony_ci
56bf215546Sopenharmony_ci   *queue_id = req.drawctxt_id;
57bf215546Sopenharmony_ci
58bf215546Sopenharmony_ci   return 0;
59bf215546Sopenharmony_ci}
60bf215546Sopenharmony_ci
61bf215546Sopenharmony_civoid
62bf215546Sopenharmony_citu_drm_submitqueue_close(const struct tu_device *dev, uint32_t queue_id)
63bf215546Sopenharmony_ci{
64bf215546Sopenharmony_ci   struct kgsl_drawctxt_destroy req = {
65bf215546Sopenharmony_ci      .drawctxt_id = queue_id,
66bf215546Sopenharmony_ci   };
67bf215546Sopenharmony_ci
68bf215546Sopenharmony_ci   safe_ioctl(dev->physical_device->local_fd, IOCTL_KGSL_DRAWCTXT_DESTROY, &req);
69bf215546Sopenharmony_ci}
70bf215546Sopenharmony_ci
71bf215546Sopenharmony_ciVkResult
72bf215546Sopenharmony_citu_bo_init_new(struct tu_device *dev, struct tu_bo **out_bo, uint64_t size,
73bf215546Sopenharmony_ci               enum tu_bo_alloc_flags flags)
74bf215546Sopenharmony_ci{
75bf215546Sopenharmony_ci   struct kgsl_gpumem_alloc_id req = {
76bf215546Sopenharmony_ci      .size = size,
77bf215546Sopenharmony_ci   };
78bf215546Sopenharmony_ci
79bf215546Sopenharmony_ci   if (flags & TU_BO_ALLOC_GPU_READ_ONLY)
80bf215546Sopenharmony_ci      req.flags |= KGSL_MEMFLAGS_GPUREADONLY;
81bf215546Sopenharmony_ci
82bf215546Sopenharmony_ci   int ret;
83bf215546Sopenharmony_ci
84bf215546Sopenharmony_ci   ret = safe_ioctl(dev->physical_device->local_fd,
85bf215546Sopenharmony_ci                    IOCTL_KGSL_GPUMEM_ALLOC_ID, &req);
86bf215546Sopenharmony_ci   if (ret) {
87bf215546Sopenharmony_ci      return vk_errorf(dev, VK_ERROR_OUT_OF_DEVICE_MEMORY,
88bf215546Sopenharmony_ci                       "GPUMEM_ALLOC_ID failed (%s)", strerror(errno));
89bf215546Sopenharmony_ci   }
90bf215546Sopenharmony_ci
91bf215546Sopenharmony_ci   struct tu_bo* bo = tu_device_lookup_bo(dev, req.id);
92bf215546Sopenharmony_ci   assert(bo && bo->gem_handle == 0);
93bf215546Sopenharmony_ci
94bf215546Sopenharmony_ci   *bo = (struct tu_bo) {
95bf215546Sopenharmony_ci      .gem_handle = req.id,
96bf215546Sopenharmony_ci      .size = req.mmapsize,
97bf215546Sopenharmony_ci      .iova = req.gpuaddr,
98bf215546Sopenharmony_ci      .refcnt = 1,
99bf215546Sopenharmony_ci   };
100bf215546Sopenharmony_ci
101bf215546Sopenharmony_ci   *out_bo = bo;
102bf215546Sopenharmony_ci
103bf215546Sopenharmony_ci   return VK_SUCCESS;
104bf215546Sopenharmony_ci}
105bf215546Sopenharmony_ci
106bf215546Sopenharmony_ciVkResult
107bf215546Sopenharmony_citu_bo_init_dmabuf(struct tu_device *dev,
108bf215546Sopenharmony_ci                  struct tu_bo **out_bo,
109bf215546Sopenharmony_ci                  uint64_t size,
110bf215546Sopenharmony_ci                  int fd)
111bf215546Sopenharmony_ci{
112bf215546Sopenharmony_ci   struct kgsl_gpuobj_import_dma_buf import_dmabuf = {
113bf215546Sopenharmony_ci      .fd = fd,
114bf215546Sopenharmony_ci   };
115bf215546Sopenharmony_ci   struct kgsl_gpuobj_import req = {
116bf215546Sopenharmony_ci      .priv = (uintptr_t)&import_dmabuf,
117bf215546Sopenharmony_ci      .priv_len = sizeof(import_dmabuf),
118bf215546Sopenharmony_ci      .flags = 0,
119bf215546Sopenharmony_ci      .type = KGSL_USER_MEM_TYPE_DMABUF,
120bf215546Sopenharmony_ci   };
121bf215546Sopenharmony_ci   int ret;
122bf215546Sopenharmony_ci
123bf215546Sopenharmony_ci   ret = safe_ioctl(dev->physical_device->local_fd,
124bf215546Sopenharmony_ci                    IOCTL_KGSL_GPUOBJ_IMPORT, &req);
125bf215546Sopenharmony_ci   if (ret)
126bf215546Sopenharmony_ci      return vk_errorf(dev, VK_ERROR_OUT_OF_DEVICE_MEMORY,
127bf215546Sopenharmony_ci                       "Failed to import dma-buf (%s)\n", strerror(errno));
128bf215546Sopenharmony_ci
129bf215546Sopenharmony_ci   struct kgsl_gpuobj_info info_req = {
130bf215546Sopenharmony_ci      .id = req.id,
131bf215546Sopenharmony_ci   };
132bf215546Sopenharmony_ci
133bf215546Sopenharmony_ci   ret = safe_ioctl(dev->physical_device->local_fd,
134bf215546Sopenharmony_ci                    IOCTL_KGSL_GPUOBJ_INFO, &info_req);
135bf215546Sopenharmony_ci   if (ret)
136bf215546Sopenharmony_ci      return vk_errorf(dev, VK_ERROR_OUT_OF_DEVICE_MEMORY,
137bf215546Sopenharmony_ci                       "Failed to get dma-buf info (%s)\n", strerror(errno));
138bf215546Sopenharmony_ci
139bf215546Sopenharmony_ci   struct tu_bo* bo = tu_device_lookup_bo(dev, req.id);
140bf215546Sopenharmony_ci   assert(bo && bo->gem_handle == 0);
141bf215546Sopenharmony_ci
142bf215546Sopenharmony_ci   *bo = (struct tu_bo) {
143bf215546Sopenharmony_ci      .gem_handle = req.id,
144bf215546Sopenharmony_ci      .size = info_req.size,
145bf215546Sopenharmony_ci      .iova = info_req.gpuaddr,
146bf215546Sopenharmony_ci      .refcnt = 1,
147bf215546Sopenharmony_ci   };
148bf215546Sopenharmony_ci
149bf215546Sopenharmony_ci   *out_bo = bo;
150bf215546Sopenharmony_ci
151bf215546Sopenharmony_ci   return VK_SUCCESS;
152bf215546Sopenharmony_ci}
153bf215546Sopenharmony_ci
154bf215546Sopenharmony_ciint
155bf215546Sopenharmony_citu_bo_export_dmabuf(struct tu_device *dev, struct tu_bo *bo)
156bf215546Sopenharmony_ci{
157bf215546Sopenharmony_ci   tu_stub();
158bf215546Sopenharmony_ci
159bf215546Sopenharmony_ci   return -1;
160bf215546Sopenharmony_ci}
161bf215546Sopenharmony_ci
162bf215546Sopenharmony_ciVkResult
163bf215546Sopenharmony_citu_bo_map(struct tu_device *dev, struct tu_bo *bo)
164bf215546Sopenharmony_ci{
165bf215546Sopenharmony_ci   if (bo->map)
166bf215546Sopenharmony_ci      return VK_SUCCESS;
167bf215546Sopenharmony_ci
168bf215546Sopenharmony_ci   uint64_t offset = bo->gem_handle << 12;
169bf215546Sopenharmony_ci   void *map = mmap(0, bo->size, PROT_READ | PROT_WRITE, MAP_SHARED,
170bf215546Sopenharmony_ci                    dev->physical_device->local_fd, offset);
171bf215546Sopenharmony_ci   if (map == MAP_FAILED)
172bf215546Sopenharmony_ci      return vk_error(dev, VK_ERROR_MEMORY_MAP_FAILED);
173bf215546Sopenharmony_ci
174bf215546Sopenharmony_ci   bo->map = map;
175bf215546Sopenharmony_ci
176bf215546Sopenharmony_ci   return VK_SUCCESS;
177bf215546Sopenharmony_ci}
178bf215546Sopenharmony_ci
179bf215546Sopenharmony_civoid
180bf215546Sopenharmony_citu_bo_finish(struct tu_device *dev, struct tu_bo *bo)
181bf215546Sopenharmony_ci{
182bf215546Sopenharmony_ci   assert(bo->gem_handle);
183bf215546Sopenharmony_ci
184bf215546Sopenharmony_ci   if (!p_atomic_dec_zero(&bo->refcnt))
185bf215546Sopenharmony_ci      return;
186bf215546Sopenharmony_ci
187bf215546Sopenharmony_ci   if (bo->map)
188bf215546Sopenharmony_ci      munmap(bo->map, bo->size);
189bf215546Sopenharmony_ci
190bf215546Sopenharmony_ci   struct kgsl_gpumem_free_id req = {
191bf215546Sopenharmony_ci      .id = bo->gem_handle
192bf215546Sopenharmony_ci   };
193bf215546Sopenharmony_ci
194bf215546Sopenharmony_ci   /* Tell sparse array that entry is free */
195bf215546Sopenharmony_ci   memset(bo, 0, sizeof(*bo));
196bf215546Sopenharmony_ci
197bf215546Sopenharmony_ci   safe_ioctl(dev->physical_device->local_fd, IOCTL_KGSL_GPUMEM_FREE_ID, &req);
198bf215546Sopenharmony_ci}
199bf215546Sopenharmony_ci
200bf215546Sopenharmony_cistatic VkResult
201bf215546Sopenharmony_ciget_kgsl_prop(int fd, unsigned int type, void *value, size_t size)
202bf215546Sopenharmony_ci{
203bf215546Sopenharmony_ci   struct kgsl_device_getproperty getprop = {
204bf215546Sopenharmony_ci      .type = type,
205bf215546Sopenharmony_ci      .value = value,
206bf215546Sopenharmony_ci      .sizebytes = size,
207bf215546Sopenharmony_ci   };
208bf215546Sopenharmony_ci
209bf215546Sopenharmony_ci   return safe_ioctl(fd, IOCTL_KGSL_DEVICE_GETPROPERTY, &getprop);
210bf215546Sopenharmony_ci}
211bf215546Sopenharmony_ci
212bf215546Sopenharmony_ciVkResult
213bf215546Sopenharmony_citu_enumerate_devices(struct tu_instance *instance)
214bf215546Sopenharmony_ci{
215bf215546Sopenharmony_ci   static const char path[] = "/dev/kgsl-3d0";
216bf215546Sopenharmony_ci   int fd;
217bf215546Sopenharmony_ci
218bf215546Sopenharmony_ci   struct tu_physical_device *device = &instance->physical_devices[0];
219bf215546Sopenharmony_ci
220bf215546Sopenharmony_ci   if (instance->vk.enabled_extensions.KHR_display)
221bf215546Sopenharmony_ci      return vk_errorf(instance, VK_ERROR_INCOMPATIBLE_DRIVER,
222bf215546Sopenharmony_ci                       "I can't KHR_display");
223bf215546Sopenharmony_ci
224bf215546Sopenharmony_ci   fd = open(path, O_RDWR | O_CLOEXEC);
225bf215546Sopenharmony_ci   if (fd < 0) {
226bf215546Sopenharmony_ci      instance->physical_device_count = 0;
227bf215546Sopenharmony_ci      return vk_errorf(instance, VK_ERROR_INCOMPATIBLE_DRIVER,
228bf215546Sopenharmony_ci                       "failed to open device %s", path);
229bf215546Sopenharmony_ci   }
230bf215546Sopenharmony_ci
231bf215546Sopenharmony_ci   struct kgsl_devinfo info;
232bf215546Sopenharmony_ci   if (get_kgsl_prop(fd, KGSL_PROP_DEVICE_INFO, &info, sizeof(info)))
233bf215546Sopenharmony_ci      goto fail;
234bf215546Sopenharmony_ci
235bf215546Sopenharmony_ci   uint64_t gmem_iova;
236bf215546Sopenharmony_ci   if (get_kgsl_prop(fd, KGSL_PROP_UCHE_GMEM_VADDR, &gmem_iova, sizeof(gmem_iova)))
237bf215546Sopenharmony_ci      goto fail;
238bf215546Sopenharmony_ci
239bf215546Sopenharmony_ci   /* kgsl version check? */
240bf215546Sopenharmony_ci
241bf215546Sopenharmony_ci   if (instance->debug_flags & TU_DEBUG_STARTUP)
242bf215546Sopenharmony_ci      mesa_logi("Found compatible device '%s'.", path);
243bf215546Sopenharmony_ci
244bf215546Sopenharmony_ci   device->instance = instance;
245bf215546Sopenharmony_ci   device->master_fd = -1;
246bf215546Sopenharmony_ci   device->local_fd = fd;
247bf215546Sopenharmony_ci
248bf215546Sopenharmony_ci   device->dev_id.gpu_id =
249bf215546Sopenharmony_ci      ((info.chip_id >> 24) & 0xff) * 100 +
250bf215546Sopenharmony_ci      ((info.chip_id >> 16) & 0xff) * 10 +
251bf215546Sopenharmony_ci      ((info.chip_id >>  8) & 0xff);
252bf215546Sopenharmony_ci   device->dev_id.chip_id = info.chip_id;
253bf215546Sopenharmony_ci   device->gmem_size = env_var_as_unsigned("TU_GMEM", info.gmem_sizebytes);
254bf215546Sopenharmony_ci   device->gmem_base = gmem_iova;
255bf215546Sopenharmony_ci
256bf215546Sopenharmony_ci   device->heap.size = tu_get_system_heap_size();
257bf215546Sopenharmony_ci   device->heap.used = 0u;
258bf215546Sopenharmony_ci   device->heap.flags = VK_MEMORY_HEAP_DEVICE_LOCAL_BIT;
259bf215546Sopenharmony_ci
260bf215546Sopenharmony_ci   if (tu_physical_device_init(device, instance) != VK_SUCCESS)
261bf215546Sopenharmony_ci      goto fail;
262bf215546Sopenharmony_ci
263bf215546Sopenharmony_ci   instance->physical_device_count = 1;
264bf215546Sopenharmony_ci
265bf215546Sopenharmony_ci   return VK_SUCCESS;
266bf215546Sopenharmony_ci
267bf215546Sopenharmony_cifail:
268bf215546Sopenharmony_ci   close(fd);
269bf215546Sopenharmony_ci   return VK_ERROR_INITIALIZATION_FAILED;
270bf215546Sopenharmony_ci}
271bf215546Sopenharmony_ci
272bf215546Sopenharmony_cistatic int
273bf215546Sopenharmony_citimestamp_to_fd(struct tu_queue *queue, uint32_t timestamp)
274bf215546Sopenharmony_ci{
275bf215546Sopenharmony_ci   int fd;
276bf215546Sopenharmony_ci   struct kgsl_timestamp_event event = {
277bf215546Sopenharmony_ci      .type = KGSL_TIMESTAMP_EVENT_FENCE,
278bf215546Sopenharmony_ci      .context_id = queue->msm_queue_id,
279bf215546Sopenharmony_ci      .timestamp = timestamp,
280bf215546Sopenharmony_ci      .priv = &fd,
281bf215546Sopenharmony_ci      .len = sizeof(fd),
282bf215546Sopenharmony_ci   };
283bf215546Sopenharmony_ci
284bf215546Sopenharmony_ci   int ret = safe_ioctl(queue->device->fd, IOCTL_KGSL_TIMESTAMP_EVENT, &event);
285bf215546Sopenharmony_ci   if (ret)
286bf215546Sopenharmony_ci      return -1;
287bf215546Sopenharmony_ci
288bf215546Sopenharmony_ci   return fd;
289bf215546Sopenharmony_ci}
290bf215546Sopenharmony_ci
291bf215546Sopenharmony_ci/* return true if timestamp a is greater (more recent) then b
292bf215546Sopenharmony_ci * this relies on timestamps never having a difference > (1<<31)
293bf215546Sopenharmony_ci */
294bf215546Sopenharmony_cistatic inline bool
295bf215546Sopenharmony_citimestamp_cmp(uint32_t a, uint32_t b)
296bf215546Sopenharmony_ci{
297bf215546Sopenharmony_ci   return (int32_t) (a - b) >= 0;
298bf215546Sopenharmony_ci}
299bf215546Sopenharmony_ci
300bf215546Sopenharmony_cistatic uint32_t
301bf215546Sopenharmony_cimax_ts(uint32_t a, uint32_t b)
302bf215546Sopenharmony_ci{
303bf215546Sopenharmony_ci   return timestamp_cmp(a, b) ? a : b;
304bf215546Sopenharmony_ci}
305bf215546Sopenharmony_ci
306bf215546Sopenharmony_cistatic uint32_t
307bf215546Sopenharmony_cimin_ts(uint32_t a, uint32_t b)
308bf215546Sopenharmony_ci{
309bf215546Sopenharmony_ci   return timestamp_cmp(a, b) ? b : a;
310bf215546Sopenharmony_ci}
311bf215546Sopenharmony_ci
312bf215546Sopenharmony_cistatic struct tu_syncobj
313bf215546Sopenharmony_cisync_merge(const VkSemaphore *syncobjs, uint32_t count, bool wait_all, bool reset)
314bf215546Sopenharmony_ci{
315bf215546Sopenharmony_ci   struct tu_syncobj ret;
316bf215546Sopenharmony_ci
317bf215546Sopenharmony_ci   ret.timestamp_valid = false;
318bf215546Sopenharmony_ci
319bf215546Sopenharmony_ci   for (uint32_t i = 0; i < count; ++i) {
320bf215546Sopenharmony_ci      TU_FROM_HANDLE(tu_syncobj, sync, syncobjs[i]);
321bf215546Sopenharmony_ci
322bf215546Sopenharmony_ci      /* TODO: this means the fence is unsignaled and will never become signaled */
323bf215546Sopenharmony_ci      if (!sync->timestamp_valid)
324bf215546Sopenharmony_ci         continue;
325bf215546Sopenharmony_ci
326bf215546Sopenharmony_ci      if (!ret.timestamp_valid)
327bf215546Sopenharmony_ci         ret.timestamp = sync->timestamp;
328bf215546Sopenharmony_ci      else if (wait_all)
329bf215546Sopenharmony_ci         ret.timestamp = max_ts(ret.timestamp, sync->timestamp);
330bf215546Sopenharmony_ci      else
331bf215546Sopenharmony_ci         ret.timestamp = min_ts(ret.timestamp, sync->timestamp);
332bf215546Sopenharmony_ci
333bf215546Sopenharmony_ci      ret.timestamp_valid = true;
334bf215546Sopenharmony_ci      if (reset)
335bf215546Sopenharmony_ci         sync->timestamp_valid = false;
336bf215546Sopenharmony_ci
337bf215546Sopenharmony_ci   }
338bf215546Sopenharmony_ci   return ret;
339bf215546Sopenharmony_ci}
340bf215546Sopenharmony_ci
341bf215546Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL
342bf215546Sopenharmony_citu_QueueSubmit2(VkQueue _queue,
343bf215546Sopenharmony_ci                uint32_t submitCount,
344bf215546Sopenharmony_ci                const VkSubmitInfo2 *pSubmits,
345bf215546Sopenharmony_ci                VkFence _fence)
346bf215546Sopenharmony_ci{
347bf215546Sopenharmony_ci   TU_FROM_HANDLE(tu_queue, queue, _queue);
348bf215546Sopenharmony_ci   TU_FROM_HANDLE(tu_syncobj, fence, _fence);
349bf215546Sopenharmony_ci   VkResult result = VK_SUCCESS;
350bf215546Sopenharmony_ci
351bf215546Sopenharmony_ci   if (unlikely(queue->device->physical_device->instance->debug_flags &
352bf215546Sopenharmony_ci                 TU_DEBUG_LOG_SKIP_GMEM_OPS)) {
353bf215546Sopenharmony_ci      tu_dbg_log_gmem_load_store_skips(queue->device);
354bf215546Sopenharmony_ci   }
355bf215546Sopenharmony_ci
356bf215546Sopenharmony_ci   struct tu_cmd_buffer **submit_cmd_buffers[submitCount];
357bf215546Sopenharmony_ci   uint32_t submit_cmd_buffer_count[submitCount];
358bf215546Sopenharmony_ci
359bf215546Sopenharmony_ci   uint32_t max_entry_count = 0;
360bf215546Sopenharmony_ci   for (uint32_t i = 0; i < submitCount; ++i) {
361bf215546Sopenharmony_ci      const VkSubmitInfo2 *submit = pSubmits + i;
362bf215546Sopenharmony_ci
363bf215546Sopenharmony_ci      const VkPerformanceQuerySubmitInfoKHR *perf_info =
364bf215546Sopenharmony_ci         vk_find_struct_const(pSubmits[i].pNext,
365bf215546Sopenharmony_ci                              PERFORMANCE_QUERY_SUBMIT_INFO_KHR);
366bf215546Sopenharmony_ci
367bf215546Sopenharmony_ci      struct tu_cmd_buffer *old_cmd_buffers[submit->commandBufferInfoCount];
368bf215546Sopenharmony_ci      uint32_t cmdbuf_count = submit->commandBufferInfoCount;
369bf215546Sopenharmony_ci      for (uint32_t j = 0; j < cmdbuf_count; ++j) {
370bf215546Sopenharmony_ci         TU_FROM_HANDLE(tu_cmd_buffer, cmdbuf, submit->pCommandBufferInfos[j].commandBuffer);
371bf215546Sopenharmony_ci         old_cmd_buffers[j] = cmdbuf;
372bf215546Sopenharmony_ci      }
373bf215546Sopenharmony_ci
374bf215546Sopenharmony_ci      struct tu_cmd_buffer **cmd_buffers = old_cmd_buffers;
375bf215546Sopenharmony_ci      tu_insert_dynamic_cmdbufs(queue->device, &cmd_buffers, &cmdbuf_count);
376bf215546Sopenharmony_ci      if (cmd_buffers == old_cmd_buffers) {
377bf215546Sopenharmony_ci         cmd_buffers =
378bf215546Sopenharmony_ci            vk_alloc(&queue->device->vk.alloc,
379bf215546Sopenharmony_ci                     sizeof(*cmd_buffers) * cmdbuf_count, 8,
380bf215546Sopenharmony_ci                     VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
381bf215546Sopenharmony_ci         memcpy(cmd_buffers, old_cmd_buffers,
382bf215546Sopenharmony_ci                sizeof(*cmd_buffers) * cmdbuf_count);
383bf215546Sopenharmony_ci      }
384bf215546Sopenharmony_ci      submit_cmd_buffers[i] = cmd_buffers;
385bf215546Sopenharmony_ci      submit_cmd_buffer_count[i] = cmdbuf_count;
386bf215546Sopenharmony_ci
387bf215546Sopenharmony_ci      uint32_t entry_count = 0;
388bf215546Sopenharmony_ci      for (uint32_t j = 0; j < cmdbuf_count; ++j) {
389bf215546Sopenharmony_ci         entry_count += cmd_buffers[i]->cs.entry_count;
390bf215546Sopenharmony_ci         if (perf_info)
391bf215546Sopenharmony_ci            entry_count++;
392bf215546Sopenharmony_ci      }
393bf215546Sopenharmony_ci
394bf215546Sopenharmony_ci      if (tu_autotune_submit_requires_fence(cmd_buffers, cmdbuf_count))
395bf215546Sopenharmony_ci         entry_count++;
396bf215546Sopenharmony_ci
397bf215546Sopenharmony_ci      max_entry_count = MAX2(max_entry_count, entry_count);
398bf215546Sopenharmony_ci   }
399bf215546Sopenharmony_ci
400bf215546Sopenharmony_ci   struct kgsl_command_object *cmds =
401bf215546Sopenharmony_ci      vk_alloc(&queue->device->vk.alloc,
402bf215546Sopenharmony_ci               sizeof(cmds[0]) * max_entry_count, 8,
403bf215546Sopenharmony_ci               VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
404bf215546Sopenharmony_ci   if (cmds == NULL)
405bf215546Sopenharmony_ci      return vk_error(queue, VK_ERROR_OUT_OF_HOST_MEMORY);
406bf215546Sopenharmony_ci
407bf215546Sopenharmony_ci   for (uint32_t i = 0; i < submitCount; ++i) {
408bf215546Sopenharmony_ci      const VkSubmitInfo2 *submit = pSubmits + i;
409bf215546Sopenharmony_ci      uint32_t entry_idx = 0;
410bf215546Sopenharmony_ci      const VkPerformanceQuerySubmitInfoKHR *perf_info =
411bf215546Sopenharmony_ci         vk_find_struct_const(pSubmits[i].pNext,
412bf215546Sopenharmony_ci                              PERFORMANCE_QUERY_SUBMIT_INFO_KHR);
413bf215546Sopenharmony_ci
414bf215546Sopenharmony_ci
415bf215546Sopenharmony_ci      struct tu_cmd_buffer **cmd_buffers = submit_cmd_buffers[i];
416bf215546Sopenharmony_ci      uint32_t cmdbuf_count = submit_cmd_buffer_count[i];
417bf215546Sopenharmony_ci      for (uint32_t j = 0; j < cmdbuf_count; j++) {
418bf215546Sopenharmony_ci         struct tu_cmd_buffer *cmdbuf = cmd_buffers[j];
419bf215546Sopenharmony_ci         struct tu_cs *cs = &cmdbuf->cs;
420bf215546Sopenharmony_ci
421bf215546Sopenharmony_ci         if (perf_info) {
422bf215546Sopenharmony_ci            struct tu_cs_entry *perf_cs_entry =
423bf215546Sopenharmony_ci               &cmdbuf->device->perfcntrs_pass_cs_entries[perf_info->counterPassIndex];
424bf215546Sopenharmony_ci
425bf215546Sopenharmony_ci            cmds[entry_idx++] = (struct kgsl_command_object) {
426bf215546Sopenharmony_ci               .offset = perf_cs_entry->offset,
427bf215546Sopenharmony_ci               .gpuaddr = perf_cs_entry->bo->iova,
428bf215546Sopenharmony_ci               .size = perf_cs_entry->size,
429bf215546Sopenharmony_ci               .flags = KGSL_CMDLIST_IB,
430bf215546Sopenharmony_ci               .id = perf_cs_entry->bo->gem_handle,
431bf215546Sopenharmony_ci            };
432bf215546Sopenharmony_ci         }
433bf215546Sopenharmony_ci
434bf215546Sopenharmony_ci         for (unsigned k = 0; k < cs->entry_count; k++) {
435bf215546Sopenharmony_ci            cmds[entry_idx++] = (struct kgsl_command_object) {
436bf215546Sopenharmony_ci               .offset = cs->entries[k].offset,
437bf215546Sopenharmony_ci               .gpuaddr = cs->entries[k].bo->iova,
438bf215546Sopenharmony_ci               .size = cs->entries[k].size,
439bf215546Sopenharmony_ci               .flags = KGSL_CMDLIST_IB,
440bf215546Sopenharmony_ci               .id = cs->entries[k].bo->gem_handle,
441bf215546Sopenharmony_ci            };
442bf215546Sopenharmony_ci         }
443bf215546Sopenharmony_ci      }
444bf215546Sopenharmony_ci
445bf215546Sopenharmony_ci      if (tu_autotune_submit_requires_fence(cmd_buffers, cmdbuf_count)) {
446bf215546Sopenharmony_ci         struct tu_cs *autotune_cs =
447bf215546Sopenharmony_ci            tu_autotune_on_submit(queue->device,
448bf215546Sopenharmony_ci                                  &queue->device->autotune,
449bf215546Sopenharmony_ci                                  cmd_buffers,
450bf215546Sopenharmony_ci                                  cmdbuf_count);
451bf215546Sopenharmony_ci         cmds[entry_idx++] = (struct kgsl_command_object) {
452bf215546Sopenharmony_ci            .offset = autotune_cs->entries[0].offset,
453bf215546Sopenharmony_ci            .gpuaddr = autotune_cs->entries[0].bo->iova,
454bf215546Sopenharmony_ci            .size = autotune_cs->entries[0].size,
455bf215546Sopenharmony_ci            .flags = KGSL_CMDLIST_IB,
456bf215546Sopenharmony_ci            .id = autotune_cs->entries[0].bo->gem_handle,
457bf215546Sopenharmony_ci         };
458bf215546Sopenharmony_ci      }
459bf215546Sopenharmony_ci
460bf215546Sopenharmony_ci      VkSemaphore wait_semaphores[submit->waitSemaphoreInfoCount];
461bf215546Sopenharmony_ci      for (uint32_t j = 0; j < submit->waitSemaphoreInfoCount; j++) {
462bf215546Sopenharmony_ci         wait_semaphores[j] = submit->pWaitSemaphoreInfos[j].semaphore;
463bf215546Sopenharmony_ci      }
464bf215546Sopenharmony_ci
465bf215546Sopenharmony_ci      struct tu_syncobj s = sync_merge(wait_semaphores,
466bf215546Sopenharmony_ci                                       submit->waitSemaphoreInfoCount,
467bf215546Sopenharmony_ci                                       true, true);
468bf215546Sopenharmony_ci
469bf215546Sopenharmony_ci      struct kgsl_cmd_syncpoint_timestamp ts = {
470bf215546Sopenharmony_ci         .context_id = queue->msm_queue_id,
471bf215546Sopenharmony_ci         .timestamp = s.timestamp,
472bf215546Sopenharmony_ci      };
473bf215546Sopenharmony_ci      struct kgsl_command_syncpoint sync = {
474bf215546Sopenharmony_ci         .type = KGSL_CMD_SYNCPOINT_TYPE_TIMESTAMP,
475bf215546Sopenharmony_ci         .size = sizeof(ts),
476bf215546Sopenharmony_ci         .priv = (uintptr_t) &ts,
477bf215546Sopenharmony_ci      };
478bf215546Sopenharmony_ci
479bf215546Sopenharmony_ci      struct kgsl_gpu_command req = {
480bf215546Sopenharmony_ci         .flags = KGSL_CMDBATCH_SUBMIT_IB_LIST,
481bf215546Sopenharmony_ci         .context_id = queue->msm_queue_id,
482bf215546Sopenharmony_ci         .cmdlist = (uint64_t) (uintptr_t) cmds,
483bf215546Sopenharmony_ci         .numcmds = entry_idx,
484bf215546Sopenharmony_ci         .cmdsize = sizeof(struct kgsl_command_object),
485bf215546Sopenharmony_ci         .synclist = (uintptr_t) &sync,
486bf215546Sopenharmony_ci         .syncsize = sizeof(struct kgsl_command_syncpoint),
487bf215546Sopenharmony_ci         .numsyncs = s.timestamp_valid ? 1 : 0,
488bf215546Sopenharmony_ci      };
489bf215546Sopenharmony_ci
490bf215546Sopenharmony_ci      int ret = safe_ioctl(queue->device->physical_device->local_fd,
491bf215546Sopenharmony_ci                           IOCTL_KGSL_GPU_COMMAND, &req);
492bf215546Sopenharmony_ci      if (ret) {
493bf215546Sopenharmony_ci         result = vk_device_set_lost(&queue->device->vk,
494bf215546Sopenharmony_ci                                     "submit failed: %s\n", strerror(errno));
495bf215546Sopenharmony_ci         goto fail;
496bf215546Sopenharmony_ci      }
497bf215546Sopenharmony_ci
498bf215546Sopenharmony_ci      for (uint32_t i = 0; i < submit->signalSemaphoreInfoCount; i++) {
499bf215546Sopenharmony_ci         TU_FROM_HANDLE(tu_syncobj, sem, submit->pSignalSemaphoreInfos[i].semaphore);
500bf215546Sopenharmony_ci         sem->timestamp = req.timestamp;
501bf215546Sopenharmony_ci         sem->timestamp_valid = true;
502bf215546Sopenharmony_ci      }
503bf215546Sopenharmony_ci
504bf215546Sopenharmony_ci      /* no need to merge fences as queue execution is serialized */
505bf215546Sopenharmony_ci      if (i == submitCount - 1) {
506bf215546Sopenharmony_ci         int fd = timestamp_to_fd(queue, req.timestamp);
507bf215546Sopenharmony_ci         if (fd < 0) {
508bf215546Sopenharmony_ci            result = vk_device_set_lost(&queue->device->vk,
509bf215546Sopenharmony_ci                                        "Failed to create sync file for timestamp: %s\n",
510bf215546Sopenharmony_ci                                        strerror(errno));
511bf215546Sopenharmony_ci            goto fail;
512bf215546Sopenharmony_ci         }
513bf215546Sopenharmony_ci
514bf215546Sopenharmony_ci         if (queue->fence >= 0)
515bf215546Sopenharmony_ci            close(queue->fence);
516bf215546Sopenharmony_ci         queue->fence = fd;
517bf215546Sopenharmony_ci
518bf215546Sopenharmony_ci         if (fence) {
519bf215546Sopenharmony_ci            fence->timestamp = req.timestamp;
520bf215546Sopenharmony_ci            fence->timestamp_valid = true;
521bf215546Sopenharmony_ci         }
522bf215546Sopenharmony_ci      }
523bf215546Sopenharmony_ci   }
524bf215546Sopenharmony_cifail:
525bf215546Sopenharmony_ci   vk_free(&queue->device->vk.alloc, cmds);
526bf215546Sopenharmony_ci
527bf215546Sopenharmony_ci   return result;
528bf215546Sopenharmony_ci}
529bf215546Sopenharmony_ci
530bf215546Sopenharmony_cistatic VkResult
531bf215546Sopenharmony_cisync_create(VkDevice _device,
532bf215546Sopenharmony_ci            bool signaled,
533bf215546Sopenharmony_ci            bool fence,
534bf215546Sopenharmony_ci            const VkAllocationCallbacks *pAllocator,
535bf215546Sopenharmony_ci            void **p_sync)
536bf215546Sopenharmony_ci{
537bf215546Sopenharmony_ci   TU_FROM_HANDLE(tu_device, device, _device);
538bf215546Sopenharmony_ci
539bf215546Sopenharmony_ci   struct tu_syncobj *sync =
540bf215546Sopenharmony_ci         vk_object_alloc(&device->vk, pAllocator, sizeof(*sync),
541bf215546Sopenharmony_ci                         fence ? VK_OBJECT_TYPE_FENCE : VK_OBJECT_TYPE_SEMAPHORE);
542bf215546Sopenharmony_ci   if (!sync)
543bf215546Sopenharmony_ci      return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
544bf215546Sopenharmony_ci
545bf215546Sopenharmony_ci   if (signaled)
546bf215546Sopenharmony_ci      tu_finishme("CREATE FENCE SIGNALED");
547bf215546Sopenharmony_ci
548bf215546Sopenharmony_ci   sync->timestamp_valid = false;
549bf215546Sopenharmony_ci   *p_sync = sync;
550bf215546Sopenharmony_ci
551bf215546Sopenharmony_ci   return VK_SUCCESS;
552bf215546Sopenharmony_ci}
553bf215546Sopenharmony_ci
554bf215546Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL
555bf215546Sopenharmony_citu_ImportSemaphoreFdKHR(VkDevice _device,
556bf215546Sopenharmony_ci                        const VkImportSemaphoreFdInfoKHR *pImportSemaphoreFdInfo)
557bf215546Sopenharmony_ci{
558bf215546Sopenharmony_ci   tu_finishme("ImportSemaphoreFdKHR");
559bf215546Sopenharmony_ci   return VK_SUCCESS;
560bf215546Sopenharmony_ci}
561bf215546Sopenharmony_ci
562bf215546Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL
563bf215546Sopenharmony_citu_GetSemaphoreFdKHR(VkDevice _device,
564bf215546Sopenharmony_ci                     const VkSemaphoreGetFdInfoKHR *pGetFdInfo,
565bf215546Sopenharmony_ci                     int *pFd)
566bf215546Sopenharmony_ci{
567bf215546Sopenharmony_ci   tu_finishme("GetSemaphoreFdKHR");
568bf215546Sopenharmony_ci   return VK_SUCCESS;
569bf215546Sopenharmony_ci}
570bf215546Sopenharmony_ci
571bf215546Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL
572bf215546Sopenharmony_citu_CreateSemaphore(VkDevice device,
573bf215546Sopenharmony_ci                   const VkSemaphoreCreateInfo *pCreateInfo,
574bf215546Sopenharmony_ci                   const VkAllocationCallbacks *pAllocator,
575bf215546Sopenharmony_ci                   VkSemaphore *pSemaphore)
576bf215546Sopenharmony_ci{
577bf215546Sopenharmony_ci   return sync_create(device, false, false, pAllocator, (void**) pSemaphore);
578bf215546Sopenharmony_ci}
579bf215546Sopenharmony_ci
580bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL
581bf215546Sopenharmony_citu_DestroySemaphore(VkDevice _device,
582bf215546Sopenharmony_ci                    VkSemaphore semaphore,
583bf215546Sopenharmony_ci                    const VkAllocationCallbacks *pAllocator)
584bf215546Sopenharmony_ci{
585bf215546Sopenharmony_ci   TU_FROM_HANDLE(tu_device, device, _device);
586bf215546Sopenharmony_ci   TU_FROM_HANDLE(tu_syncobj, sync, semaphore);
587bf215546Sopenharmony_ci
588bf215546Sopenharmony_ci   if (!sync)
589bf215546Sopenharmony_ci      return;
590bf215546Sopenharmony_ci
591bf215546Sopenharmony_ci   vk_object_free(&device->vk, pAllocator, sync);
592bf215546Sopenharmony_ci}
593bf215546Sopenharmony_ci
594bf215546Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL
595bf215546Sopenharmony_citu_ImportFenceFdKHR(VkDevice _device,
596bf215546Sopenharmony_ci                    const VkImportFenceFdInfoKHR *pImportFenceFdInfo)
597bf215546Sopenharmony_ci{
598bf215546Sopenharmony_ci   tu_stub();
599bf215546Sopenharmony_ci
600bf215546Sopenharmony_ci   return VK_SUCCESS;
601bf215546Sopenharmony_ci}
602bf215546Sopenharmony_ci
603bf215546Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL
604bf215546Sopenharmony_citu_GetFenceFdKHR(VkDevice _device,
605bf215546Sopenharmony_ci                 const VkFenceGetFdInfoKHR *pGetFdInfo,
606bf215546Sopenharmony_ci                 int *pFd)
607bf215546Sopenharmony_ci{
608bf215546Sopenharmony_ci   tu_stub();
609bf215546Sopenharmony_ci
610bf215546Sopenharmony_ci   return VK_SUCCESS;
611bf215546Sopenharmony_ci}
612bf215546Sopenharmony_ci
613bf215546Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL
614bf215546Sopenharmony_citu_CreateFence(VkDevice device,
615bf215546Sopenharmony_ci               const VkFenceCreateInfo *info,
616bf215546Sopenharmony_ci               const VkAllocationCallbacks *pAllocator,
617bf215546Sopenharmony_ci               VkFence *pFence)
618bf215546Sopenharmony_ci{
619bf215546Sopenharmony_ci   return sync_create(device, info->flags & VK_FENCE_CREATE_SIGNALED_BIT, true,
620bf215546Sopenharmony_ci                      pAllocator, (void**) pFence);
621bf215546Sopenharmony_ci}
622bf215546Sopenharmony_ci
623bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL
624bf215546Sopenharmony_citu_DestroyFence(VkDevice _device, VkFence fence, const VkAllocationCallbacks *pAllocator)
625bf215546Sopenharmony_ci{
626bf215546Sopenharmony_ci   TU_FROM_HANDLE(tu_device, device, _device);
627bf215546Sopenharmony_ci   TU_FROM_HANDLE(tu_syncobj, sync, fence);
628bf215546Sopenharmony_ci
629bf215546Sopenharmony_ci   if (!sync)
630bf215546Sopenharmony_ci      return;
631bf215546Sopenharmony_ci
632bf215546Sopenharmony_ci   vk_object_free(&device->vk, pAllocator, sync);
633bf215546Sopenharmony_ci}
634bf215546Sopenharmony_ci
635bf215546Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL
636bf215546Sopenharmony_citu_WaitForFences(VkDevice _device,
637bf215546Sopenharmony_ci                 uint32_t count,
638bf215546Sopenharmony_ci                 const VkFence *pFences,
639bf215546Sopenharmony_ci                 VkBool32 waitAll,
640bf215546Sopenharmony_ci                 uint64_t timeout)
641bf215546Sopenharmony_ci{
642bf215546Sopenharmony_ci   TU_FROM_HANDLE(tu_device, device, _device);
643bf215546Sopenharmony_ci   struct tu_syncobj s = sync_merge((const VkSemaphore*) pFences, count, waitAll, false);
644bf215546Sopenharmony_ci
645bf215546Sopenharmony_ci   if (!s.timestamp_valid)
646bf215546Sopenharmony_ci      return VK_SUCCESS;
647bf215546Sopenharmony_ci
648bf215546Sopenharmony_ci   int ret = ioctl(device->fd, IOCTL_KGSL_DEVICE_WAITTIMESTAMP_CTXTID,
649bf215546Sopenharmony_ci                   &(struct kgsl_device_waittimestamp_ctxtid) {
650bf215546Sopenharmony_ci      .context_id = device->queues[0]->msm_queue_id,
651bf215546Sopenharmony_ci      .timestamp = s.timestamp,
652bf215546Sopenharmony_ci      .timeout = timeout / 1000000,
653bf215546Sopenharmony_ci   });
654bf215546Sopenharmony_ci   if (ret) {
655bf215546Sopenharmony_ci      assert(errno == ETIME);
656bf215546Sopenharmony_ci      return VK_TIMEOUT;
657bf215546Sopenharmony_ci   }
658bf215546Sopenharmony_ci
659bf215546Sopenharmony_ci   return VK_SUCCESS;
660bf215546Sopenharmony_ci}
661bf215546Sopenharmony_ci
662bf215546Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL
663bf215546Sopenharmony_citu_ResetFences(VkDevice _device, uint32_t count, const VkFence *pFences)
664bf215546Sopenharmony_ci{
665bf215546Sopenharmony_ci   for (uint32_t i = 0; i < count; i++) {
666bf215546Sopenharmony_ci      TU_FROM_HANDLE(tu_syncobj, sync, pFences[i]);
667bf215546Sopenharmony_ci      sync->timestamp_valid = false;
668bf215546Sopenharmony_ci   }
669bf215546Sopenharmony_ci   return VK_SUCCESS;
670bf215546Sopenharmony_ci}
671bf215546Sopenharmony_ci
672bf215546Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL
673bf215546Sopenharmony_citu_GetFenceStatus(VkDevice _device, VkFence _fence)
674bf215546Sopenharmony_ci{
675bf215546Sopenharmony_ci   TU_FROM_HANDLE(tu_device, device, _device);
676bf215546Sopenharmony_ci   TU_FROM_HANDLE(tu_syncobj, sync, _fence);
677bf215546Sopenharmony_ci
678bf215546Sopenharmony_ci   if (!sync->timestamp_valid)
679bf215546Sopenharmony_ci      return VK_NOT_READY;
680bf215546Sopenharmony_ci
681bf215546Sopenharmony_ci   int ret = ioctl(device->fd, IOCTL_KGSL_DEVICE_WAITTIMESTAMP_CTXTID,
682bf215546Sopenharmony_ci               &(struct kgsl_device_waittimestamp_ctxtid) {
683bf215546Sopenharmony_ci      .context_id = device->queues[0]->msm_queue_id,
684bf215546Sopenharmony_ci      .timestamp = sync->timestamp,
685bf215546Sopenharmony_ci      .timeout = 0,
686bf215546Sopenharmony_ci   });
687bf215546Sopenharmony_ci   if (ret) {
688bf215546Sopenharmony_ci      assert(errno == ETIME);
689bf215546Sopenharmony_ci      return VK_NOT_READY;
690bf215546Sopenharmony_ci   }
691bf215546Sopenharmony_ci
692bf215546Sopenharmony_ci   return VK_SUCCESS;
693bf215546Sopenharmony_ci}
694bf215546Sopenharmony_ci
695bf215546Sopenharmony_ciint
696bf215546Sopenharmony_citu_syncobj_to_fd(struct tu_device *device, struct vk_sync *sync)
697bf215546Sopenharmony_ci{
698bf215546Sopenharmony_ci   tu_finishme("tu_syncobj_to_fd");
699bf215546Sopenharmony_ci   return -1;
700bf215546Sopenharmony_ci}
701bf215546Sopenharmony_ci
702bf215546Sopenharmony_ciVkResult
703bf215546Sopenharmony_citu_device_wait_u_trace(struct tu_device *dev, struct tu_u_trace_syncobj *syncobj)
704bf215546Sopenharmony_ci{
705bf215546Sopenharmony_ci   tu_finishme("tu_device_wait_u_trace");
706bf215546Sopenharmony_ci   return VK_SUCCESS;
707bf215546Sopenharmony_ci}
708bf215546Sopenharmony_ci
709bf215546Sopenharmony_ciint
710bf215546Sopenharmony_citu_device_get_gpu_timestamp(struct tu_device *dev, uint64_t *ts)
711bf215546Sopenharmony_ci{
712bf215546Sopenharmony_ci   tu_finishme("tu_device_get_gpu_timestamp");
713bf215546Sopenharmony_ci   return 0;
714bf215546Sopenharmony_ci}
715bf215546Sopenharmony_ci
716bf215546Sopenharmony_ciint
717bf215546Sopenharmony_citu_device_get_suspend_count(struct tu_device *dev, uint64_t *suspend_count)
718bf215546Sopenharmony_ci{
719bf215546Sopenharmony_ci   /* kgsl doesn't have a way to get it */
720bf215546Sopenharmony_ci   *suspend_count = 0;
721bf215546Sopenharmony_ci   return 0;
722bf215546Sopenharmony_ci}
723bf215546Sopenharmony_ci
724bf215546Sopenharmony_ciVkResult
725bf215546Sopenharmony_citu_device_check_status(struct vk_device *vk_device)
726bf215546Sopenharmony_ci{
727bf215546Sopenharmony_ci   struct tu_device *device = container_of(vk_device, struct tu_device, vk);
728bf215546Sopenharmony_ci
729bf215546Sopenharmony_ci   for (unsigned i = 0; i < TU_MAX_QUEUE_FAMILIES; i++) {
730bf215546Sopenharmony_ci      for (unsigned q = 0; q < device->queue_count[i]; q++) {
731bf215546Sopenharmony_ci         /* KGSL's KGSL_PROP_GPU_RESET_STAT takes the u32 msm_queue_id and returns a
732bf215546Sopenharmony_ci         * KGSL_CTX_STAT_* for the worst reset that happened since the last time it
733bf215546Sopenharmony_ci         * was queried on that queue.
734bf215546Sopenharmony_ci         */
735bf215546Sopenharmony_ci         uint32_t value = device->queues[i][q].msm_queue_id;
736bf215546Sopenharmony_ci         VkResult status = get_kgsl_prop(device->fd, KGSL_PROP_GPU_RESET_STAT,
737bf215546Sopenharmony_ci                                       &value, sizeof(value));
738bf215546Sopenharmony_ci         if (status != VK_SUCCESS)
739bf215546Sopenharmony_ci            return vk_device_set_lost(&device->vk, "Failed to get GPU reset status");
740bf215546Sopenharmony_ci
741bf215546Sopenharmony_ci         if (value != KGSL_CTX_STAT_NO_ERROR &&
742bf215546Sopenharmony_ci            value != KGSL_CTX_STAT_INNOCENT_CONTEXT_RESET_EXT) {
743bf215546Sopenharmony_ci            return vk_device_set_lost(&device->vk, "GPU faulted or hung");
744bf215546Sopenharmony_ci         }
745bf215546Sopenharmony_ci      }
746bf215546Sopenharmony_ci   }
747bf215546Sopenharmony_ci
748bf215546Sopenharmony_ci   return VK_SUCCESS;
749bf215546Sopenharmony_ci}
750bf215546Sopenharmony_ci
751bf215546Sopenharmony_ci#ifdef ANDROID
752bf215546Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL
753bf215546Sopenharmony_citu_QueueSignalReleaseImageANDROID(VkQueue _queue,
754bf215546Sopenharmony_ci                                  uint32_t waitSemaphoreCount,
755bf215546Sopenharmony_ci                                  const VkSemaphore *pWaitSemaphores,
756bf215546Sopenharmony_ci                                  VkImage image,
757bf215546Sopenharmony_ci                                  int *pNativeFenceFd)
758bf215546Sopenharmony_ci{
759bf215546Sopenharmony_ci   TU_FROM_HANDLE(tu_queue, queue, _queue);
760bf215546Sopenharmony_ci   if (!pNativeFenceFd)
761bf215546Sopenharmony_ci      return VK_SUCCESS;
762bf215546Sopenharmony_ci
763bf215546Sopenharmony_ci   struct tu_syncobj s = sync_merge(pWaitSemaphores, waitSemaphoreCount, true, true);
764bf215546Sopenharmony_ci
765bf215546Sopenharmony_ci   if (!s.timestamp_valid) {
766bf215546Sopenharmony_ci      *pNativeFenceFd = -1;
767bf215546Sopenharmony_ci      return VK_SUCCESS;
768bf215546Sopenharmony_ci   }
769bf215546Sopenharmony_ci
770bf215546Sopenharmony_ci   *pNativeFenceFd = timestamp_to_fd(queue, s.timestamp);
771bf215546Sopenharmony_ci
772bf215546Sopenharmony_ci   return VK_SUCCESS;
773bf215546Sopenharmony_ci}
774bf215546Sopenharmony_ci#endif
775