+ struct amdgpu_cs_fence *sem = (struct amdgpu_cs_fence *)_sem;
+ FREE(sem);
+}
+
+static int radv_amdgpu_signal_sems(struct radv_amdgpu_ctx *ctx,
+ uint32_t ip_type,
+ uint32_t ring,
+ struct radv_winsys_sem_info *sem_info)
+{
+ for (unsigned i = 0; i < sem_info->signal.sem_count; i++) {
+ struct amdgpu_cs_fence *sem = (struct amdgpu_cs_fence *)(sem_info->signal.sem)[i];
+
+ if (sem->context)
+ return -EINVAL;
+
+ *sem = ctx->last_submission[ip_type][ring].fence;
+ }
+ return 0;
+}
+
+static struct drm_amdgpu_cs_chunk_sem *radv_amdgpu_cs_alloc_syncobj_chunk(struct radv_winsys_sem_counts *counts,
+ struct drm_amdgpu_cs_chunk *chunk, int chunk_id)
+{
+ struct drm_amdgpu_cs_chunk_sem *syncobj = malloc(sizeof(struct drm_amdgpu_cs_chunk_sem) * counts->syncobj_count);
+ if (!syncobj)
+ return NULL;
+
+ for (unsigned i = 0; i < counts->syncobj_count; i++) {
+ struct drm_amdgpu_cs_chunk_sem *sem = &syncobj[i];
+ sem->handle = counts->syncobj[i];
+ }
+
+ chunk->chunk_id = chunk_id;
+ chunk->length_dw = sizeof(struct drm_amdgpu_cs_chunk_sem) / 4 * counts->syncobj_count;
+ chunk->chunk_data = (uint64_t)(uintptr_t)syncobj;
+ return syncobj;
+}
+
+static int radv_amdgpu_cs_submit(struct radv_amdgpu_ctx *ctx,
+ struct radv_amdgpu_cs_request *request,
+ struct radv_winsys_sem_info *sem_info)
+{
+ int r;
+ int num_chunks;
+ int size;
+ bool user_fence;
+ struct drm_amdgpu_cs_chunk *chunks;
+ struct drm_amdgpu_cs_chunk_data *chunk_data;
+ struct drm_amdgpu_cs_chunk_dep *sem_dependencies = NULL;
+ struct drm_amdgpu_cs_chunk_sem *wait_syncobj = NULL, *signal_syncobj = NULL;
+ int i;
+ struct amdgpu_cs_fence *sem;
+
+ user_fence = (request->fence_info.handle != NULL);
+ size = request->number_of_ibs + (user_fence ? 2 : 1) + 3;
+
+ chunks = alloca(sizeof(struct drm_amdgpu_cs_chunk) * size);
+
+ size = request->number_of_ibs + (user_fence ? 1 : 0);
+
+ chunk_data = alloca(sizeof(struct drm_amdgpu_cs_chunk_data) * size);
+
+ num_chunks = request->number_of_ibs;
+ for (i = 0; i < request->number_of_ibs; i++) {
+ struct amdgpu_cs_ib_info *ib;
+ chunks[i].chunk_id = AMDGPU_CHUNK_ID_IB;
+ chunks[i].length_dw = sizeof(struct drm_amdgpu_cs_chunk_ib) / 4;
+ chunks[i].chunk_data = (uint64_t)(uintptr_t)&chunk_data[i];
+
+ ib = &request->ibs[i];
+
+ chunk_data[i].ib_data._pad = 0;
+ chunk_data[i].ib_data.va_start = ib->ib_mc_address;
+ chunk_data[i].ib_data.ib_bytes = ib->size * 4;
+ chunk_data[i].ib_data.ip_type = request->ip_type;
+ chunk_data[i].ib_data.ip_instance = request->ip_instance;
+ chunk_data[i].ib_data.ring = request->ring;
+ chunk_data[i].ib_data.flags = ib->flags;
+ }
+
+ if (user_fence) {
+ i = num_chunks++;
+
+ chunks[i].chunk_id = AMDGPU_CHUNK_ID_FENCE;
+ chunks[i].length_dw = sizeof(struct drm_amdgpu_cs_chunk_fence) / 4;
+ chunks[i].chunk_data = (uint64_t)(uintptr_t)&chunk_data[i];
+
+ amdgpu_cs_chunk_fence_info_to_data(&request->fence_info,
+ &chunk_data[i]);
+ }
+
+ if (sem_info->wait.syncobj_count && sem_info->cs_emit_wait) {
+ wait_syncobj = radv_amdgpu_cs_alloc_syncobj_chunk(&sem_info->wait,
+ &chunks[num_chunks],
+ AMDGPU_CHUNK_ID_SYNCOBJ_IN);
+ if (!wait_syncobj) {
+ r = -ENOMEM;
+ goto error_out;
+ }
+ num_chunks++;
+
+ if (sem_info->wait.sem_count == 0)
+ sem_info->cs_emit_wait = false;
+
+ }
+
+ if (sem_info->wait.sem_count && sem_info->cs_emit_wait) {
+ sem_dependencies = alloca(sizeof(struct drm_amdgpu_cs_chunk_dep) * sem_info->wait.sem_count);
+ int sem_count = 0;
+
+ for (unsigned j = 0; j < sem_info->wait.sem_count; j++) {
+ sem = (struct amdgpu_cs_fence *)sem_info->wait.sem[j];
+ if (!sem->context)
+ continue;
+ struct drm_amdgpu_cs_chunk_dep *dep = &sem_dependencies[sem_count++];
+
+ amdgpu_cs_chunk_fence_to_dep(sem, dep);
+
+ sem->context = NULL;
+ }
+ i = num_chunks++;
+
+ /* dependencies chunk */
+ chunks[i].chunk_id = AMDGPU_CHUNK_ID_DEPENDENCIES;
+ chunks[i].length_dw = sizeof(struct drm_amdgpu_cs_chunk_dep) / 4 * sem_count;
+ chunks[i].chunk_data = (uint64_t)(uintptr_t)sem_dependencies;
+
+ sem_info->cs_emit_wait = false;
+ }
+
+ if (sem_info->signal.syncobj_count && sem_info->cs_emit_signal) {
+ signal_syncobj = radv_amdgpu_cs_alloc_syncobj_chunk(&sem_info->signal,
+ &chunks[num_chunks],
+ AMDGPU_CHUNK_ID_SYNCOBJ_OUT);
+ if (!signal_syncobj) {
+ r = -ENOMEM;
+ goto error_out;
+ }
+ num_chunks++;
+ }
+
+ r = amdgpu_cs_submit_raw2(ctx->ws->dev,
+ ctx->ctx,
+ request->resources,
+ num_chunks,
+ chunks,
+ &request->seq_no);
+error_out:
+ free(wait_syncobj);
+ free(signal_syncobj);
+ return r;
+}
+
+static int radv_amdgpu_create_syncobj(struct radeon_winsys *_ws,
+ uint32_t *handle)
+{
+ struct radv_amdgpu_winsys *ws = radv_amdgpu_winsys(_ws);
+ return amdgpu_cs_create_syncobj(ws->dev, handle);
+}
+
+static void radv_amdgpu_destroy_syncobj(struct radeon_winsys *_ws,
+ uint32_t handle)
+{
+ struct radv_amdgpu_winsys *ws = radv_amdgpu_winsys(_ws);
+ amdgpu_cs_destroy_syncobj(ws->dev, handle);
+}
+
+static void radv_amdgpu_reset_syncobj(struct radeon_winsys *_ws,
+ uint32_t handle)
+{
+ struct radv_amdgpu_winsys *ws = radv_amdgpu_winsys(_ws);
+ amdgpu_cs_syncobj_reset(ws->dev, &handle, 1);
+}
+
+static void radv_amdgpu_signal_syncobj(struct radeon_winsys *_ws,
+ uint32_t handle)
+{
+ struct radv_amdgpu_winsys *ws = radv_amdgpu_winsys(_ws);
+ amdgpu_cs_syncobj_signal(ws->dev, &handle, 1);
+}
+
+static bool radv_amdgpu_wait_syncobj(struct radeon_winsys *_ws, const uint32_t *handles,
+ uint32_t handle_count, bool wait_all, uint64_t timeout)
+{
+ struct radv_amdgpu_winsys *ws = radv_amdgpu_winsys(_ws);
+ uint32_t tmp;
+
+ /* The timeouts are signed, while vulkan timeouts are unsigned. */
+ timeout = MIN2(timeout, INT64_MAX);
+
+ int ret = amdgpu_cs_syncobj_wait(ws->dev, (uint32_t*)handles, handle_count, timeout,
+ DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT |
+ (wait_all ? DRM_SYNCOBJ_WAIT_FLAGS_WAIT_ALL : 0),
+ &tmp);
+ if (ret == 0) {
+ return true;
+ } else if (ret == -ETIME) {
+ return false;
+ } else {
+ fprintf(stderr, "amdgpu: radv_amdgpu_wait_syncobj failed!\nerrno: %d\n", errno);
+ return false;
+ }
+}
+
+static int radv_amdgpu_export_syncobj(struct radeon_winsys *_ws,
+ uint32_t syncobj,
+ int *fd)
+{
+ struct radv_amdgpu_winsys *ws = radv_amdgpu_winsys(_ws);
+
+ return amdgpu_cs_export_syncobj(ws->dev, syncobj, fd);
+}
+
+static int radv_amdgpu_import_syncobj(struct radeon_winsys *_ws,
+ int fd,
+ uint32_t *syncobj)
+{
+ struct radv_amdgpu_winsys *ws = radv_amdgpu_winsys(_ws);
+
+ return amdgpu_cs_import_syncobj(ws->dev, fd, syncobj);
+}
+
+
+static int radv_amdgpu_export_syncobj_to_sync_file(struct radeon_winsys *_ws,
+ uint32_t syncobj,
+ int *fd)
+{
+ struct radv_amdgpu_winsys *ws = radv_amdgpu_winsys(_ws);
+
+ return amdgpu_cs_syncobj_export_sync_file(ws->dev, syncobj, fd);
+}
+
+static int radv_amdgpu_import_syncobj_from_sync_file(struct radeon_winsys *_ws,
+ uint32_t syncobj,
+ int fd)
+{
+ struct radv_amdgpu_winsys *ws = radv_amdgpu_winsys(_ws);
+
+ return amdgpu_cs_syncobj_import_sync_file(ws->dev, syncobj, fd);