@@ -486,6 +486,38 @@ static bool is_tensor_like_descriptor_type(VkDescriptorType descriptor_type) {
486486 descriptor_type == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER ;
487487}
488488
489+ static VkResult submit_and_wait_with_fence (
490+ VkDevice device,
491+ VkQueue queue,
492+ const VkSubmitInfo* submit_info) {
493+ VkFence fence = VK_NULL_HANDLE ;
494+
495+ const VkFenceCreateInfo fence_info = {
496+ .sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO ,
497+ .pNext = nullptr ,
498+ .flags = 0 ,
499+ };
500+
501+ VkResult result = vkCreateFence (device, &fence_info, nullptr , &fence);
502+ if (result != VK_SUCCESS ) {
503+ ET_LOG (Error, " Failed to create Vulkan fence, error %d" , result);
504+ return result;
505+ }
506+
507+ result = vkQueueSubmit (queue, 1 , submit_info, fence);
508+ if (result != VK_SUCCESS ) {
509+ ET_LOG (Error, " Vulkan queue submit failed, error %d" , result);
510+ vkDestroyFence (device, fence, nullptr );
511+ return result;
512+ }
513+
514+ result = vkWaitForFences (
515+ device, 1 , &fence, VK_TRUE , std::numeric_limits<uint64_t >::max ());
516+
517+ vkDestroyFence (device, fence, nullptr );
518+ return result;
519+ }
520+
489521static void record_image_layout_transition (
490522 VkCommandBuffer command_buffer,
491523 VkImage image,
@@ -1278,10 +1310,11 @@ VkResult transition_image_layout(
12781310 .signalSemaphoreCount = 0 ,
12791311 .pSignalSemaphores = nullptr ,
12801312 };
1281- result = vkQueueSubmit (queue, 1 , &submit_info, VK_NULL_HANDLE );
1282- if (result == VK_SUCCESS ) {
1283- result = vkQueueWaitIdle (queue);
1284- }
1313+
1314+ // creates a temporary one-time command buffer, submits it once, waits, and
1315+ // frees it immediately.
1316+ result = submit_and_wait_with_fence (device, queue, &submit_info);
1317+
12851318 vkFreeCommandBuffers (device, command_pool, 1 , &command_buffer);
12861319 return result;
12871320}
@@ -3078,19 +3111,33 @@ bool VgfRepr::process_vgf(
30783111 {
30793112 VGF_PROFILE_SCOPE (event_tracer, " VGF_INIT_ALLOCATE_COMMAND_BUFFER" );
30803113
3081- // Allocate command buffer
30823114 VkCommandBufferAllocateInfo buffer_allocate_info{
30833115 .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO ,
30843116 .pNext = nullptr ,
30853117 .commandPool = vk_command_pool,
30863118 .level = VK_COMMAND_BUFFER_LEVEL_PRIMARY ,
30873119 .commandBufferCount = 1 };
3120+
30883121 result = vkAllocateCommandBuffers (
30893122 vk_device, &buffer_allocate_info, &vk_execute_cmd);
30903123 if (result != VK_SUCCESS ) {
30913124 ET_LOG (Error, " Failed to allocate command buffers" );
30923125 return false ;
30933126 }
3127+
3128+ const VkFenceCreateInfo fence_info{
3129+ .sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO ,
3130+ .pNext = nullptr ,
3131+ .flags = VK_FENCE_CREATE_SIGNALED_BIT ,
3132+ };
3133+
3134+ result = vkCreateFence (vk_device, &fence_info, nullptr , &vk_execute_fence);
3135+ if (result != VK_SUCCESS ) {
3136+ ET_LOG (Error, " Failed to create VGF execute fence, error %d" , result);
3137+ vkFreeCommandBuffers (vk_device, vk_command_pool, 1 , &vk_execute_cmd);
3138+ vk_execute_cmd = VK_NULL_HANDLE ;
3139+ return false ;
3140+ }
30943141 }
30953142
30963143 {
@@ -3392,31 +3439,51 @@ bool VgfRepr::process_vgf(
33923439bool VgfRepr::execute_vgf (executorch::runtime::EventTracer* event_tracer) {
33933440 ET_LOG (Info, " Executing vgf" );
33943441
3395- VkSubmitInfo submit{VK_STRUCTURE_TYPE_SUBMIT_INFO };
3396- submit.commandBufferCount = 1 ;
3397- submit.pCommandBuffers = &vk_execute_cmd;
3442+ VkSubmitInfo submit{
3443+ .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO ,
3444+ .pNext = nullptr ,
3445+ .waitSemaphoreCount = 0 ,
3446+ .pWaitSemaphores = nullptr ,
3447+ .pWaitDstStageMask = nullptr ,
3448+ .commandBufferCount = 1 ,
3449+ .pCommandBuffers = &vk_execute_cmd,
3450+ .signalSemaphoreCount = 0 ,
3451+ .pSignalSemaphores = nullptr ,
3452+ };
33983453
33993454 VkResult result;
34003455
34013456 {
3402- VGF_PROFILE_SCOPE (event_tracer, " VGF_QUEUE_SUBMIT " );
3457+ VGF_PROFILE_SCOPE (event_tracer, " VGF_QUEUE_SUBMIT_AND_WAIT_FENCE " );
34033458
3404- result = vkQueueSubmit (vk_queue, 1 , &submit, VK_NULL_HANDLE );
3405- }
3459+ if (vk_execute_fence == VK_NULL_HANDLE ) {
3460+ ET_LOG (Error, " VGF execute fence is not initialized" );
3461+ return false ;
3462+ }
34063463
3407- if (result != VK_SUCCESS ) {
3408- ET_LOG (Error, " VGF/VkCommandBuffer command submission failed" );
3409- return false ;
3410- }
3464+ result = vkResetFences (vk_device, 1 , &vk_execute_fence);
3465+ if (result != VK_SUCCESS ) {
3466+ ET_LOG (Error, " VGF/VkFence reset failed, error %d" , result);
3467+ return false ;
3468+ }
34113469
3412- {
3413- VGF_PROFILE_SCOPE (event_tracer, " VGF_QUEUE_WAIT_IDLE" );
3470+ result = vkQueueSubmit (vk_queue, 1 , &submit, vk_execute_fence);
3471+ if (result != VK_SUCCESS ) {
3472+ ET_LOG (Error, " VGF/VkFence wait failed, error %d" , result);
3473+ return false ;
3474+ }
34143475
3415- result = vkQueueWaitIdle (vk_queue);
3476+ result = vkWaitForFences (
3477+ vk_device,
3478+ 1 ,
3479+ &vk_execute_fence,
3480+ VK_TRUE ,
3481+ std::numeric_limits<uint64_t >::max ());
34163482 }
34173483
34183484 if (result != VK_SUCCESS ) {
3419- ET_LOG (Error, " VGF/VkQueue wait idle failed" );
3485+ ET_LOG (
3486+ Error, " VGF/VkCommandBuffer command submission or fence wait failed" );
34203487 return false ;
34213488 }
34223489
@@ -3431,6 +3498,11 @@ void VgfRepr::free_vgf() {
34313498 vk_timestamp_query_pool = VK_NULL_HANDLE ;
34323499 }
34333500
3501+ if (vk_execute_fence != VK_NULL_HANDLE ) {
3502+ vkDestroyFence (vk_device, vk_execute_fence, nullptr );
3503+ vk_execute_fence = VK_NULL_HANDLE ;
3504+ }
3505+
34343506 vkFreeCommandBuffers (vk_device, vk_command_pool, 1 , &vk_execute_cmd);
34353507 vector<VkDeviceMemory> owned_memory;
34363508 auto remember_owned_memory = [&](VkDeviceMemory memory) {
0 commit comments