mirror of
https://github.com/ocornut/imgui.git
synced 2026-01-09 23:54:20 +00:00
Fix VUID 03868
- Remove ImGui_ImplVulkanH_FrameSemaphores structure - Integrate ImageAcquiredSemaphore VkSemaphore into ImGui_ImplVulkanH_Frame struct, as it is a current-frame specific feature - Make RenderSemaphores independent, indexed by the current SwapchainImageIndex (this avoids the validation error) - This fix does NOT require the use of any new extensions More info on the issue with examples: https://docs.vulkan.org/guide/latest/swapchain_semaphore_reuse.html
This commit is contained in:
parent
34debc733f
commit
ccd613afa8
2 changed files with 43 additions and 53 deletions
|
|
@ -116,7 +116,6 @@ void ImGui_ImplVulkan_DestroyDeviceObjects();
|
||||||
void ImGui_ImplVulkan_DestroyFrameRenderBuffers(VkDevice device, ImGui_ImplVulkan_FrameRenderBuffers* buffers, const VkAllocationCallbacks* allocator);
|
void ImGui_ImplVulkan_DestroyFrameRenderBuffers(VkDevice device, ImGui_ImplVulkan_FrameRenderBuffers* buffers, const VkAllocationCallbacks* allocator);
|
||||||
void ImGui_ImplVulkan_DestroyWindowRenderBuffers(VkDevice device, ImGui_ImplVulkan_WindowRenderBuffers* buffers, const VkAllocationCallbacks* allocator);
|
void ImGui_ImplVulkan_DestroyWindowRenderBuffers(VkDevice device, ImGui_ImplVulkan_WindowRenderBuffers* buffers, const VkAllocationCallbacks* allocator);
|
||||||
void ImGui_ImplVulkanH_DestroyFrame(VkDevice device, ImGui_ImplVulkanH_Frame* fd, const VkAllocationCallbacks* allocator);
|
void ImGui_ImplVulkanH_DestroyFrame(VkDevice device, ImGui_ImplVulkanH_Frame* fd, const VkAllocationCallbacks* allocator);
|
||||||
void ImGui_ImplVulkanH_DestroyFrameSemaphores(VkDevice device, ImGui_ImplVulkanH_FrameSemaphores* fsd, const VkAllocationCallbacks* allocator);
|
|
||||||
void ImGui_ImplVulkanH_DestroyAllViewportsRenderBuffers(VkDevice device, const VkAllocationCallbacks* allocator);
|
void ImGui_ImplVulkanH_DestroyAllViewportsRenderBuffers(VkDevice device, const VkAllocationCallbacks* allocator);
|
||||||
void ImGui_ImplVulkanH_CreateWindowSwapChain(VkPhysicalDevice physical_device, VkDevice device, ImGui_ImplVulkanH_Window* wd, const VkAllocationCallbacks* allocator, int w, int h, uint32_t min_image_count);
|
void ImGui_ImplVulkanH_CreateWindowSwapChain(VkPhysicalDevice physical_device, VkDevice device, ImGui_ImplVulkanH_Window* wd, const VkAllocationCallbacks* allocator, int w, int h, uint32_t min_image_count);
|
||||||
void ImGui_ImplVulkanH_CreateWindowCommandBuffers(VkPhysicalDevice physical_device, VkDevice device, ImGui_ImplVulkanH_Window* wd, uint32_t queue_family, const VkAllocationCallbacks* allocator);
|
void ImGui_ImplVulkanH_CreateWindowCommandBuffers(VkPhysicalDevice physical_device, VkDevice device, ImGui_ImplVulkanH_Window* wd, uint32_t queue_family, const VkAllocationCallbacks* allocator);
|
||||||
|
|
@ -1570,20 +1569,19 @@ void ImGui_ImplVulkanH_CreateWindowCommandBuffers(VkPhysicalDevice physical_devi
|
||||||
VkFenceCreateInfo info = {};
|
VkFenceCreateInfo info = {};
|
||||||
info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
|
info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
|
||||||
info.flags = VK_FENCE_CREATE_SIGNALED_BIT;
|
info.flags = VK_FENCE_CREATE_SIGNALED_BIT;
|
||||||
err = vkCreateFence(device, &info, allocator, &fd->Fence);
|
err = vkCreateFence(device, &info, allocator, &fd->RenderFence);
|
||||||
check_vk_result(err);
|
check_vk_result(err);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
for (uint32_t i = 0; i < wd->SemaphoreCount; i++)
|
|
||||||
{
|
|
||||||
ImGui_ImplVulkanH_FrameSemaphores* fsd = &wd->FrameSemaphores[i];
|
|
||||||
{
|
{
|
||||||
VkSemaphoreCreateInfo info = {};
|
VkSemaphoreCreateInfo info = {};
|
||||||
info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
|
info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
|
||||||
err = vkCreateSemaphore(device, &info, allocator, &fsd->ImageAcquiredSemaphore);
|
err = vkCreateSemaphore(device, &info, allocator, &fd->ImageAcquiredSemaphore);
|
||||||
check_vk_result(err);
|
check_vk_result(err);
|
||||||
err = vkCreateSemaphore(device, &info, allocator, &fsd->RenderCompleteSemaphore);
|
}
|
||||||
|
{
|
||||||
|
VkSemaphoreCreateInfo info = {};
|
||||||
|
info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
|
||||||
|
err = vkCreateSemaphore(device, &info, allocator, &wd->RenderSemaphores[i]);
|
||||||
check_vk_result(err);
|
check_vk_result(err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1613,11 +1611,14 @@ void ImGui_ImplVulkanH_CreateWindowSwapChain(VkPhysicalDevice physical_device, V
|
||||||
// We don't use ImGui_ImplVulkanH_DestroyWindow() because we want to preserve the old swapchain to create the new one.
|
// We don't use ImGui_ImplVulkanH_DestroyWindow() because we want to preserve the old swapchain to create the new one.
|
||||||
// Destroy old Framebuffer
|
// Destroy old Framebuffer
|
||||||
for (uint32_t i = 0; i < wd->ImageCount; i++)
|
for (uint32_t i = 0; i < wd->ImageCount; i++)
|
||||||
|
{
|
||||||
ImGui_ImplVulkanH_DestroyFrame(device, &wd->Frames[i], allocator);
|
ImGui_ImplVulkanH_DestroyFrame(device, &wd->Frames[i], allocator);
|
||||||
for (uint32_t i = 0; i < wd->SemaphoreCount; i++)
|
vkDestroySemaphore(device, wd->RenderSemaphores[i], allocator);
|
||||||
ImGui_ImplVulkanH_DestroyFrameSemaphores(device, &wd->FrameSemaphores[i], allocator);
|
wd->RenderSemaphores[i] = VK_NULL_HANDLE;
|
||||||
|
}
|
||||||
|
|
||||||
wd->Frames.clear();
|
wd->Frames.clear();
|
||||||
wd->FrameSemaphores.clear();
|
wd->RenderSemaphores.clear();
|
||||||
wd->ImageCount = 0;
|
wd->ImageCount = 0;
|
||||||
if (wd->RenderPass)
|
if (wd->RenderPass)
|
||||||
vkDestroyRenderPass(device, wd->RenderPass, allocator);
|
vkDestroyRenderPass(device, wd->RenderPass, allocator);
|
||||||
|
|
@ -1670,11 +1671,10 @@ void ImGui_ImplVulkanH_CreateWindowSwapChain(VkPhysicalDevice physical_device, V
|
||||||
err = vkGetSwapchainImagesKHR(device, wd->Swapchain, &wd->ImageCount, backbuffers);
|
err = vkGetSwapchainImagesKHR(device, wd->Swapchain, &wd->ImageCount, backbuffers);
|
||||||
check_vk_result(err);
|
check_vk_result(err);
|
||||||
|
|
||||||
wd->SemaphoreCount = wd->ImageCount + 1;
|
|
||||||
wd->Frames.resize(wd->ImageCount);
|
wd->Frames.resize(wd->ImageCount);
|
||||||
wd->FrameSemaphores.resize(wd->SemaphoreCount);
|
wd->RenderSemaphores.resize(wd->ImageCount);
|
||||||
memset(wd->Frames.Data, 0, wd->Frames.size_in_bytes());
|
memset(wd->Frames.Data, 0, wd->Frames.size_in_bytes());
|
||||||
memset(wd->FrameSemaphores.Data, 0, wd->FrameSemaphores.size_in_bytes());
|
memset(wd->RenderSemaphores.Data, 0, wd->RenderSemaphores.size_in_bytes());
|
||||||
for (uint32_t i = 0; i < wd->ImageCount; i++)
|
for (uint32_t i = 0; i < wd->ImageCount; i++)
|
||||||
wd->Frames[i].Backbuffer = backbuffers[i];
|
wd->Frames[i].Backbuffer = backbuffers[i];
|
||||||
}
|
}
|
||||||
|
|
@ -1858,11 +1858,14 @@ void ImGui_ImplVulkanH_DestroyWindow(VkInstance instance, VkDevice device, ImGui
|
||||||
//vkQueueWaitIdle(bd->Queue);
|
//vkQueueWaitIdle(bd->Queue);
|
||||||
|
|
||||||
for (uint32_t i = 0; i < wd->ImageCount; i++)
|
for (uint32_t i = 0; i < wd->ImageCount; i++)
|
||||||
|
{
|
||||||
ImGui_ImplVulkanH_DestroyFrame(device, &wd->Frames[i], allocator);
|
ImGui_ImplVulkanH_DestroyFrame(device, &wd->Frames[i], allocator);
|
||||||
for (uint32_t i = 0; i < wd->SemaphoreCount; i++)
|
vkDestroySemaphore(device, wd->RenderSemaphores[i], allocator);
|
||||||
ImGui_ImplVulkanH_DestroyFrameSemaphores(device, &wd->FrameSemaphores[i], allocator);
|
wd->RenderSemaphores[i] = VK_NULL_HANDLE;
|
||||||
|
}
|
||||||
|
|
||||||
wd->Frames.clear();
|
wd->Frames.clear();
|
||||||
wd->FrameSemaphores.clear();
|
wd->RenderSemaphores.clear();
|
||||||
vkDestroyRenderPass(device, wd->RenderPass, allocator);
|
vkDestroyRenderPass(device, wd->RenderPass, allocator);
|
||||||
vkDestroySwapchainKHR(device, wd->Swapchain, allocator);
|
vkDestroySwapchainKHR(device, wd->Swapchain, allocator);
|
||||||
vkDestroySurfaceKHR(instance, wd->Surface, allocator);
|
vkDestroySurfaceKHR(instance, wd->Surface, allocator);
|
||||||
|
|
@ -1872,10 +1875,12 @@ void ImGui_ImplVulkanH_DestroyWindow(VkInstance instance, VkDevice device, ImGui
|
||||||
|
|
||||||
void ImGui_ImplVulkanH_DestroyFrame(VkDevice device, ImGui_ImplVulkanH_Frame* fd, const VkAllocationCallbacks* allocator)
|
void ImGui_ImplVulkanH_DestroyFrame(VkDevice device, ImGui_ImplVulkanH_Frame* fd, const VkAllocationCallbacks* allocator)
|
||||||
{
|
{
|
||||||
vkDestroyFence(device, fd->Fence, allocator);
|
vkDestroySemaphore(device, fd->ImageAcquiredSemaphore, allocator);
|
||||||
|
vkDestroyFence(device, fd->RenderFence, allocator);
|
||||||
vkFreeCommandBuffers(device, fd->CommandPool, 1, &fd->CommandBuffer);
|
vkFreeCommandBuffers(device, fd->CommandPool, 1, &fd->CommandBuffer);
|
||||||
vkDestroyCommandPool(device, fd->CommandPool, allocator);
|
vkDestroyCommandPool(device, fd->CommandPool, allocator);
|
||||||
fd->Fence = VK_NULL_HANDLE;
|
fd->ImageAcquiredSemaphore = VK_NULL_HANDLE;
|
||||||
|
fd->RenderFence = VK_NULL_HANDLE;
|
||||||
fd->CommandBuffer = VK_NULL_HANDLE;
|
fd->CommandBuffer = VK_NULL_HANDLE;
|
||||||
fd->CommandPool = VK_NULL_HANDLE;
|
fd->CommandPool = VK_NULL_HANDLE;
|
||||||
|
|
||||||
|
|
@ -1883,13 +1888,6 @@ void ImGui_ImplVulkanH_DestroyFrame(VkDevice device, ImGui_ImplVulkanH_Frame* fd
|
||||||
vkDestroyFramebuffer(device, fd->Framebuffer, allocator);
|
vkDestroyFramebuffer(device, fd->Framebuffer, allocator);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImGui_ImplVulkanH_DestroyFrameSemaphores(VkDevice device, ImGui_ImplVulkanH_FrameSemaphores* fsd, const VkAllocationCallbacks* allocator)
|
|
||||||
{
|
|
||||||
vkDestroySemaphore(device, fsd->ImageAcquiredSemaphore, allocator);
|
|
||||||
vkDestroySemaphore(device, fsd->RenderCompleteSemaphore, allocator);
|
|
||||||
fsd->ImageAcquiredSemaphore = fsd->RenderCompleteSemaphore = VK_NULL_HANDLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ImGui_ImplVulkanH_DestroyAllViewportsRenderBuffers(VkDevice device, const VkAllocationCallbacks* allocator)
|
void ImGui_ImplVulkanH_DestroyAllViewportsRenderBuffers(VkDevice device, const VkAllocationCallbacks* allocator)
|
||||||
{
|
{
|
||||||
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
|
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
|
||||||
|
|
@ -1996,11 +1994,11 @@ static void ImGui_ImplVulkan_RenderWindow(ImGuiViewport* viewport, void*)
|
||||||
vd->SwapChainNeedRebuild = vd->SwapChainSuboptimal = false;
|
vd->SwapChainNeedRebuild = vd->SwapChainSuboptimal = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui_ImplVulkanH_Frame* fd = nullptr;
|
ImGui_ImplVulkanH_Frame* fd = &wd->Frames[wd->CurrentFrameIndex];
|
||||||
ImGui_ImplVulkanH_FrameSemaphores* fsd = &wd->FrameSemaphores[wd->SemaphoreIndex];
|
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
err = vkAcquireNextImageKHR(v->Device, wd->Swapchain, UINT64_MAX, fsd->ImageAcquiredSemaphore, VK_NULL_HANDLE, &wd->FrameIndex);
|
err = vkAcquireNextImageKHR(v->Device, wd->Swapchain, UINT64_MAX, fd->ImageAcquiredSemaphore, VK_NULL_HANDLE, &wd->SwapchainImageIndex);
|
||||||
|
|
||||||
if (err == VK_ERROR_OUT_OF_DATE_KHR)
|
if (err == VK_ERROR_OUT_OF_DATE_KHR)
|
||||||
{
|
{
|
||||||
vd->SwapChainNeedRebuild = true; // Since we are not going to swap this frame anyway, it's ok that recreation happens on next frame.
|
vd->SwapChainNeedRebuild = true; // Since we are not going to swap this frame anyway, it's ok that recreation happens on next frame.
|
||||||
|
|
@ -2010,11 +2008,10 @@ static void ImGui_ImplVulkan_RenderWindow(ImGuiViewport* viewport, void*)
|
||||||
vd->SwapChainSuboptimal = true;
|
vd->SwapChainSuboptimal = true;
|
||||||
else
|
else
|
||||||
check_vk_result(err);
|
check_vk_result(err);
|
||||||
fd = &wd->Frames[wd->FrameIndex];
|
|
||||||
}
|
}
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
err = vkWaitForFences(v->Device, 1, &fd->Fence, VK_TRUE, 100);
|
err = vkWaitForFences(v->Device, 1, &fd->RenderFence, VK_TRUE, 100);
|
||||||
if (err == VK_SUCCESS) break;
|
if (err == VK_SUCCESS) break;
|
||||||
if (err == VK_TIMEOUT) continue;
|
if (err == VK_TIMEOUT) continue;
|
||||||
check_vk_result(err);
|
check_vk_result(err);
|
||||||
|
|
@ -2112,18 +2109,18 @@ static void ImGui_ImplVulkan_RenderWindow(ImGuiViewport* viewport, void*)
|
||||||
VkSubmitInfo info = {};
|
VkSubmitInfo info = {};
|
||||||
info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
|
info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
|
||||||
info.waitSemaphoreCount = 1;
|
info.waitSemaphoreCount = 1;
|
||||||
info.pWaitSemaphores = &fsd->ImageAcquiredSemaphore;
|
info.pWaitSemaphores = &fd->ImageAcquiredSemaphore;
|
||||||
info.pWaitDstStageMask = &wait_stage;
|
info.pWaitDstStageMask = &wait_stage;
|
||||||
info.commandBufferCount = 1;
|
info.commandBufferCount = 1;
|
||||||
info.pCommandBuffers = &fd->CommandBuffer;
|
info.pCommandBuffers = &fd->CommandBuffer;
|
||||||
info.signalSemaphoreCount = 1;
|
info.signalSemaphoreCount = 1;
|
||||||
info.pSignalSemaphores = &fsd->RenderCompleteSemaphore;
|
info.pSignalSemaphores = &wd->RenderSemaphores[wd->SwapchainImageIndex];
|
||||||
|
|
||||||
err = vkEndCommandBuffer(fd->CommandBuffer);
|
err = vkEndCommandBuffer(fd->CommandBuffer);
|
||||||
check_vk_result(err);
|
check_vk_result(err);
|
||||||
err = vkResetFences(v->Device, 1, &fd->Fence);
|
err = vkResetFences(v->Device, 1, &fd->RenderFence);
|
||||||
check_vk_result(err);
|
check_vk_result(err);
|
||||||
err = vkQueueSubmit(v->Queue, 1, &info, fd->Fence);
|
err = vkQueueSubmit(v->Queue, 1, &info, fd->RenderFence);
|
||||||
check_vk_result(err);
|
check_vk_result(err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -2140,16 +2137,15 @@ static void ImGui_ImplVulkan_SwapBuffers(ImGuiViewport* viewport, void*)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
VkResult err;
|
VkResult err;
|
||||||
uint32_t present_index = wd->FrameIndex;
|
ImGui_ImplVulkanH_Frame* fd = &wd->Frames[wd->CurrentFrameIndex];
|
||||||
|
|
||||||
ImGui_ImplVulkanH_FrameSemaphores* fsd = &wd->FrameSemaphores[wd->SemaphoreIndex];
|
|
||||||
VkPresentInfoKHR info = {};
|
VkPresentInfoKHR info = {};
|
||||||
info.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
|
info.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
|
||||||
info.waitSemaphoreCount = 1;
|
info.waitSemaphoreCount = 1;
|
||||||
info.pWaitSemaphores = &fsd->RenderCompleteSemaphore;
|
info.pWaitSemaphores = &wd->RenderSemaphores[wd->SwapchainImageIndex];
|
||||||
info.swapchainCount = 1;
|
info.swapchainCount = 1;
|
||||||
info.pSwapchains = &wd->Swapchain;
|
info.pSwapchains = &wd->Swapchain;
|
||||||
info.pImageIndices = &present_index;
|
info.pImageIndices = &wd->SwapchainImageIndex;
|
||||||
err = vkQueuePresentKHR(v->Queue, &info);
|
err = vkQueuePresentKHR(v->Queue, &info);
|
||||||
if (err == VK_ERROR_OUT_OF_DATE_KHR)
|
if (err == VK_ERROR_OUT_OF_DATE_KHR)
|
||||||
{
|
{
|
||||||
|
|
@ -2160,7 +2156,7 @@ static void ImGui_ImplVulkan_SwapBuffers(ImGuiViewport* viewport, void*)
|
||||||
vd->SwapChainSuboptimal = true;
|
vd->SwapChainSuboptimal = true;
|
||||||
else
|
else
|
||||||
check_vk_result(err);
|
check_vk_result(err);
|
||||||
wd->SemaphoreIndex = (wd->SemaphoreIndex + 1) % wd->SemaphoreCount; // Now we can use the next set of semaphores
|
wd->CurrentFrameIndex = (wd->CurrentFrameIndex + 1) % wd->ImageCount; // Now we can use the next set of frame data
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImGui_ImplVulkan_InitMultiViewportSupport()
|
void ImGui_ImplVulkan_InitMultiViewportSupport()
|
||||||
|
|
|
||||||
|
|
@ -179,18 +179,13 @@ struct ImGui_ImplVulkanH_Frame
|
||||||
{
|
{
|
||||||
VkCommandPool CommandPool;
|
VkCommandPool CommandPool;
|
||||||
VkCommandBuffer CommandBuffer;
|
VkCommandBuffer CommandBuffer;
|
||||||
VkFence Fence;
|
VkSemaphore ImageAcquiredSemaphore;
|
||||||
|
VkFence RenderFence;
|
||||||
VkImage Backbuffer;
|
VkImage Backbuffer;
|
||||||
VkImageView BackbufferView;
|
VkImageView BackbufferView;
|
||||||
VkFramebuffer Framebuffer;
|
VkFramebuffer Framebuffer;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ImGui_ImplVulkanH_FrameSemaphores
|
|
||||||
{
|
|
||||||
VkSemaphore ImageAcquiredSemaphore;
|
|
||||||
VkSemaphore RenderCompleteSemaphore;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Helper structure to hold the data needed by one rendering context into one OS window
|
// Helper structure to hold the data needed by one rendering context into one OS window
|
||||||
// (Used by example's main.cpp. Used by multi-viewport features. Probably NOT used by your own engine/app.)
|
// (Used by example's main.cpp. Used by multi-viewport features. Probably NOT used by your own engine/app.)
|
||||||
struct ImGui_ImplVulkanH_Window
|
struct ImGui_ImplVulkanH_Window
|
||||||
|
|
@ -205,12 +200,11 @@ struct ImGui_ImplVulkanH_Window
|
||||||
bool UseDynamicRendering;
|
bool UseDynamicRendering;
|
||||||
bool ClearEnable;
|
bool ClearEnable;
|
||||||
VkClearValue ClearValue;
|
VkClearValue ClearValue;
|
||||||
uint32_t FrameIndex; // Current frame being rendered to (0 <= FrameIndex < FrameInFlightCount)
|
uint32_t SwapchainImageIndex; // Current swapchain image index being rendered to (0 <= SwapchainImageIndex < ImageCount)
|
||||||
uint32_t ImageCount; // Number of simultaneous in-flight frames (returned by vkGetSwapchainImagesKHR, usually derived from min_image_count)
|
uint32_t ImageCount; // Number of simultaneous in-flight frames (returned by vkGetSwapchainImagesKHR, usually derived from min_image_count)
|
||||||
uint32_t SemaphoreCount; // Number of simultaneous in-flight frames + 1, to be able to use it in vkAcquireNextImageKHR
|
uint32_t CurrentFrameIndex; // Current frame-in-flight index
|
||||||
uint32_t SemaphoreIndex; // Current set of swapchain wait semaphores we're using (needs to be distinct from per frame data)
|
|
||||||
ImVector<ImGui_ImplVulkanH_Frame> Frames;
|
ImVector<ImGui_ImplVulkanH_Frame> Frames;
|
||||||
ImVector<ImGui_ImplVulkanH_FrameSemaphores> FrameSemaphores;
|
ImVector<VkSemaphore> RenderSemaphores; // Semaphores to signal when rendering is done for each frame, indexed by SwapchainImageIndex to be sure the semaphore is safe to use again for that swapchain image.
|
||||||
|
|
||||||
ImGui_ImplVulkanH_Window()
|
ImGui_ImplVulkanH_Window()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue