+ for (unsigned i = 0; i < num_dependencies; i++) {
+ struct amdgpu_fence *fence =
+ (struct amdgpu_fence*)cs->compute_fence_dependencies.list[i];
+
+ assert(util_queue_fence_is_signalled(&fence->submitted));
+ amdgpu_cs_chunk_fence_to_dep(&fence->fence, &dep_chunk[i]);
+ }
+
+ chunks[num_chunks].chunk_id = AMDGPU_CHUNK_ID_DEPENDENCIES;
+ chunks[num_chunks].length_dw = sizeof(dep_chunk[0]) / 4 * num_dependencies;
+ chunks[num_chunks].chunk_data = (uintptr_t)dep_chunk;
+ num_chunks++;
+ }
+
+ /* Add compute start fence dependencies. */
+ unsigned num_start_dependencies = cs->compute_start_fence_dependencies.num;
+ if (num_start_dependencies) {
+ struct drm_amdgpu_cs_chunk_dep *dep_chunk =
+ alloca(num_start_dependencies * sizeof(*dep_chunk));
+
+ for (unsigned i = 0; i < num_start_dependencies; i++) {
+ struct amdgpu_fence *fence =
+ (struct amdgpu_fence*)cs->compute_start_fence_dependencies.list[i];
+
+ assert(util_queue_fence_is_signalled(&fence->submitted));
+ amdgpu_cs_chunk_fence_to_dep(&fence->fence, &dep_chunk[i]);
+ }
+
+ chunks[num_chunks].chunk_id = AMDGPU_CHUNK_ID_SCHEDULED_DEPENDENCIES;
+ chunks[num_chunks].length_dw = sizeof(dep_chunk[0]) / 4 * num_start_dependencies;
+ chunks[num_chunks].chunk_data = (uintptr_t)dep_chunk;
+ num_chunks++;
+ }
+
+ /* Convert from dwords to bytes. */
+ cs->ib[IB_PARALLEL_COMPUTE].ib_bytes *= 4;
+ chunks[num_chunks].chunk_id = AMDGPU_CHUNK_ID_IB;
+ chunks[num_chunks].length_dw = sizeof(struct drm_amdgpu_cs_chunk_ib) / 4;
+ chunks[num_chunks].chunk_data = (uintptr_t)&cs->ib[IB_PARALLEL_COMPUTE];
+ num_chunks++;
+
+ r = amdgpu_cs_submit_raw2(ws->dev, acs->ctx->ctx, bo_list,
+ num_chunks, chunks, NULL);
+ if (r)
+ goto finalize;
+
+ /* Back off the compute chunks. */
+ num_chunks = old_num_chunks;
+ }
+
+ /* Syncobj signals. */
+ unsigned num_syncobj_to_signal = cs->syncobj_to_signal.num;
+ if (num_syncobj_to_signal) {
+ struct drm_amdgpu_cs_chunk_sem *sem_chunk =
+ alloca(num_syncobj_to_signal * sizeof(sem_chunk[0]));
+
+ for (unsigned i = 0; i < num_syncobj_to_signal; i++) {
+ struct amdgpu_fence *fence =
+ (struct amdgpu_fence*)cs->syncobj_to_signal.list[i];
+
+ assert(amdgpu_fence_is_syncobj(fence));
+ sem_chunk[i].handle = fence->syncobj;
+ }
+
+ chunks[num_chunks].chunk_id = AMDGPU_CHUNK_ID_SYNCOBJ_OUT;
+ chunks[num_chunks].length_dw = sizeof(sem_chunk[0]) / 4
+ * num_syncobj_to_signal;
+ chunks[num_chunks].chunk_data = (uintptr_t)sem_chunk;
+ num_chunks++;
+ }
+
+ /* Fence */
+ if (has_user_fence) {
+ chunks[num_chunks].chunk_id = AMDGPU_CHUNK_ID_FENCE;
+ chunks[num_chunks].length_dw = sizeof(struct drm_amdgpu_cs_chunk_fence) / 4;
+ chunks[num_chunks].chunk_data = (uintptr_t)&acs->fence_chunk;
+ num_chunks++;
+ }
+
+ /* IB */
+ cs->ib[IB_MAIN].ib_bytes *= 4; /* Convert from dwords to bytes. */
+ chunks[num_chunks].chunk_id = AMDGPU_CHUNK_ID_IB;
+ chunks[num_chunks].length_dw = sizeof(struct drm_amdgpu_cs_chunk_ib) / 4;
+ chunks[num_chunks].chunk_data = (uintptr_t)&cs->ib[IB_MAIN];
+ num_chunks++;
+
+ if (ws->secure && cs->secure)
+ cs->ib[IB_MAIN].flags |= AMDGPU_IB_FLAGS_SECURE;
+ else
+ cs->ib[IB_MAIN].flags &= ~AMDGPU_IB_FLAGS_SECURE;
+
+ assert(num_chunks <= ARRAY_SIZE(chunks));
+
+ r = amdgpu_cs_submit_raw2(ws->dev, acs->ctx->ctx, bo_list,
+ num_chunks, chunks, &seq_no);
+ }
+finalize: