From cf4bd2e4123bff7797c02ea1f2ef6e583fdb09d0 Mon Sep 17 00:00:00 2001 From: Mark Collins Date: Mon, 31 Mar 2025 19:27:09 +0000 Subject: [PATCH] tu/kgsl: Revert "Remove zero CB queue submission fast path" This reverts commit 0342d34bdbb0a8bbdac78679d0497361628fa65c which introduced a regression in the Turnip's KGSL backend, causing various sync issues since KGSL doesn't advance the GPU timeline when a submit without cmdbufs is made. A comment explaining the issue was added to the code, and the fast path is reintroduced. Signed-off-by: Mark Collins Part-of: --- src/freedreno/vulkan/tu_knl_kgsl.cc | 45 +++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/src/freedreno/vulkan/tu_knl_kgsl.cc b/src/freedreno/vulkan/tu_knl_kgsl.cc index bdf515d4cce..c5bf255935c 100644 --- a/src/freedreno/vulkan/tu_knl_kgsl.cc +++ b/src/freedreno/vulkan/tu_knl_kgsl.cc @@ -1089,6 +1089,51 @@ kgsl_queue_submit(struct tu_queue *queue, void *_submit, uint64_t start_ts = tu_perfetto_begin_submit(); #endif + if (submit->commands.size == 0) { + /* This handles the case where we have a wait and no commands to submit. + * It is necessary to handle this case separately as the kernel will not + * advance the GPU timeline if a submit with no commands is made, even + * though it will return an incremented fence timestamp (which will + * never be signaled). + */ + const struct kgsl_syncobj *wait_semaphores[wait_count + 1]; + for (uint32_t i = 0; i < wait_count; i++) { + wait_semaphores[i] = &container_of(waits[i].sync, + struct vk_kgsl_syncobj, vk) + ->syncobj; + } + + struct kgsl_syncobj last_submit_sync; + if (queue->fence >= 0) + last_submit_sync = (struct kgsl_syncobj) { + .state = KGSL_SYNCOBJ_STATE_TS, + .queue = queue, + .timestamp = queue->fence, + }; + else + last_submit_sync = (struct kgsl_syncobj) { + .state = KGSL_SYNCOBJ_STATE_SIGNALED, + }; + + wait_semaphores[wait_count] = &last_submit_sync; + + struct kgsl_syncobj wait_sync = + kgsl_syncobj_merge(wait_semaphores, wait_count + 1); + assert(wait_sync.state != + KGSL_SYNCOBJ_STATE_UNSIGNALED); // Would wait forever + + for (uint32_t i = 0; i < signal_count; i++) { + struct kgsl_syncobj *signal_sync = + &container_of(signals[i].sync, struct vk_kgsl_syncobj, vk) + ->syncobj; + + kgsl_syncobj_reset(signal_sync); + *signal_sync = wait_sync; + } + + return VK_SUCCESS; + } + VkResult result = VK_SUCCESS; if (u_trace_submission_data) {