diff --git a/examples/imgui_impl_vulkan.cpp b/examples/imgui_impl_vulkan.cpp index 2a728ea6..434459a2 100644 --- a/examples/imgui_impl_vulkan.cpp +++ b/examples/imgui_impl_vulkan.cpp @@ -32,28 +32,32 @@ static VkPipelineCache g_PipelineCache = VK_NULL_HANDLE; static VkDescriptorPool g_DescriptorPool = VK_NULL_HANDLE; static void (*g_CheckVkResult)(VkResult err) = NULL; -static VkCommandBuffer g_CommandBuffer = VK_NULL_HANDLE; static VkDeviceSize g_BufferMemoryAlignment = 256; static VkPipelineCreateFlags g_PipelineCreateFlags = 0; -static int g_FrameIndex = 0; static VkDescriptorSetLayout g_DescriptorSetLayout = VK_NULL_HANDLE; static VkPipelineLayout g_PipelineLayout = VK_NULL_HANDLE; static VkDescriptorSet g_DescriptorSet = VK_NULL_HANDLE; static VkPipeline g_Pipeline = VK_NULL_HANDLE; +// Frame data +struct FrameDataForRender +{ + VkDeviceMemory VertexBufferMemory; + VkDeviceMemory IndexBufferMemory; + VkDeviceSize VertexBufferSize; + VkDeviceSize IndexBufferSize; + VkBuffer VertexBuffer; + VkBuffer IndexBuffer; +}; +static int g_FrameIndex = 0; +static FrameDataForRender g_FramesDataBuffers[IMGUI_VK_QUEUED_FRAMES]; + +// Font data static VkSampler g_FontSampler = VK_NULL_HANDLE; static VkDeviceMemory g_FontMemory = VK_NULL_HANDLE; static VkImage g_FontImage = VK_NULL_HANDLE; static VkImageView g_FontView = VK_NULL_HANDLE; - -static VkDeviceMemory g_VertexBufferMemory[IMGUI_VK_QUEUED_FRAMES] = {}; -static VkDeviceMemory g_IndexBufferMemory[IMGUI_VK_QUEUED_FRAMES] = {}; -static VkDeviceSize g_VertexBufferSize[IMGUI_VK_QUEUED_FRAMES] = {}; -static VkDeviceSize g_IndexBufferSize[IMGUI_VK_QUEUED_FRAMES] = {}; -static VkBuffer g_VertexBuffer[IMGUI_VK_QUEUED_FRAMES] = {}; -static VkBuffer g_IndexBuffer[IMGUI_VK_QUEUED_FRAMES] = {}; - static VkDeviceMemory g_UploadBufferMemory = VK_NULL_HANDLE; static VkBuffer g_UploadBuffer = VK_NULL_HANDLE; @@ -61,6 +65,8 @@ static VkBuffer g_UploadBuffer = VK_NULL_HANDLE; static void ImGui_ImplVulkan_InitPlatformInterface(); static void ImGui_ImplVulkan_ShutdownPlatformInterface(); +// glsl_shader.vert, compiled with: +// # glslangValidator -V -x -o glsl_shader.vert.u32 glsl_shader.vert static uint32_t __glsl_shader_vert_spv[] = { 0x07230203,0x00010000,0x00080001,0x0000002e,0x00000000,0x00020011,0x00000001,0x0006000b, @@ -106,6 +112,8 @@ static uint32_t __glsl_shader_vert_spv[] = 0x0000002d,0x0000002c,0x000100fd,0x00010038 }; +// glsl_shader.frag, compiled with: +// # glslangValidator -V -x -o glsl_shader.frag.u32 glsl_shader.frag static uint32_t __glsl_shader_frag_spv[] = { 0x07230203,0x00010000,0x00080001,0x0000001e,0x00000000,0x00020011,0x00000001,0x0006000b, @@ -151,81 +159,63 @@ static void ImGui_ImplVulkan_VkResult(VkResult err) g_CheckVkResult(err); } +static void CreateOrResizeBuffer(VkBuffer& buffer, VkDeviceMemory& buffer_memory, VkDeviceSize& p_buffer_size, size_t new_size, VkBufferUsageFlagBits usage) +{ + VkResult err; + if (buffer != NULL) + vkDestroyBuffer(g_Device, buffer, g_Allocator); + if (buffer_memory) + vkFreeMemory(g_Device, buffer_memory, g_Allocator); + + VkDeviceSize vertex_buffer_size_aligned = ((new_size - 1) / g_BufferMemoryAlignment + 1) * g_BufferMemoryAlignment; + VkBufferCreateInfo buffer_info = {}; + buffer_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; + buffer_info.size = vertex_buffer_size_aligned; + buffer_info.usage = usage; + buffer_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + err = vkCreateBuffer(g_Device, &buffer_info, g_Allocator, &buffer); + ImGui_ImplVulkan_VkResult(err); + + VkMemoryRequirements req; + vkGetBufferMemoryRequirements(g_Device, buffer, &req); + g_BufferMemoryAlignment = (g_BufferMemoryAlignment > req.alignment) ? g_BufferMemoryAlignment : req.alignment; + VkMemoryAllocateInfo alloc_info = {}; + alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; + alloc_info.allocationSize = req.size; + alloc_info.memoryTypeIndex = ImGui_ImplVulkan_MemoryType(VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, req.memoryTypeBits); + err = vkAllocateMemory(g_Device, &alloc_info, g_Allocator, &buffer_memory); + ImGui_ImplVulkan_VkResult(err); + + err = vkBindBufferMemory(g_Device, buffer, buffer_memory, 0); + ImGui_ImplVulkan_VkResult(err); + p_buffer_size = new_size; +} + // This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure) -void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data) +void ImGui_ImplVulkan_RenderDrawData(VkCommandBuffer command_buffer, ImDrawData* draw_data) { VkResult err; ImGuiIO& io = ImGui::GetIO(); if (draw_data->TotalVtxCount == 0) return; - // Create the Vertex Buffer: - size_t vertex_size = draw_data->TotalVtxCount * sizeof(ImDrawVert); - if (!g_VertexBuffer[g_FrameIndex] || g_VertexBufferSize[g_FrameIndex] < vertex_size) - { - if (g_VertexBuffer[g_FrameIndex]) - vkDestroyBuffer(g_Device, g_VertexBuffer[g_FrameIndex], g_Allocator); - if (g_VertexBufferMemory[g_FrameIndex]) - vkFreeMemory(g_Device, g_VertexBufferMemory[g_FrameIndex], g_Allocator); - VkDeviceSize vertex_buffer_size = ((vertex_size-1) / g_BufferMemoryAlignment+1) * g_BufferMemoryAlignment; - VkBufferCreateInfo buffer_info = {}; - buffer_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; - buffer_info.size = vertex_buffer_size; - buffer_info.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT; - buffer_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - err = vkCreateBuffer(g_Device, &buffer_info, g_Allocator, &g_VertexBuffer[g_FrameIndex]); - ImGui_ImplVulkan_VkResult(err); - VkMemoryRequirements req; - vkGetBufferMemoryRequirements(g_Device, g_VertexBuffer[g_FrameIndex], &req); - g_BufferMemoryAlignment = (g_BufferMemoryAlignment > req.alignment) ? g_BufferMemoryAlignment : req.alignment; - VkMemoryAllocateInfo alloc_info = {}; - alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - alloc_info.allocationSize = req.size; - alloc_info.memoryTypeIndex = ImGui_ImplVulkan_MemoryType(VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, req.memoryTypeBits); - err = vkAllocateMemory(g_Device, &alloc_info, g_Allocator, &g_VertexBufferMemory[g_FrameIndex]); - ImGui_ImplVulkan_VkResult(err); - err = vkBindBufferMemory(g_Device, g_VertexBuffer[g_FrameIndex], g_VertexBufferMemory[g_FrameIndex], 0); - ImGui_ImplVulkan_VkResult(err); - g_VertexBufferSize[g_FrameIndex] = vertex_buffer_size; - } + FrameDataForRender* fd = &g_FramesDataBuffers[g_FrameIndex]; - // Create the Index Buffer: + // Create the Vertex and Index buffers: + size_t vertex_size = draw_data->TotalVtxCount * sizeof(ImDrawVert); size_t index_size = draw_data->TotalIdxCount * sizeof(ImDrawIdx); - if (!g_IndexBuffer[g_FrameIndex] || g_IndexBufferSize[g_FrameIndex] < index_size) - { - if (g_IndexBuffer[g_FrameIndex]) - vkDestroyBuffer(g_Device, g_IndexBuffer[g_FrameIndex], g_Allocator); - if (g_IndexBufferMemory[g_FrameIndex]) - vkFreeMemory(g_Device, g_IndexBufferMemory[g_FrameIndex], g_Allocator); - VkDeviceSize index_buffer_size = ((index_size-1) / g_BufferMemoryAlignment+1) * g_BufferMemoryAlignment; - VkBufferCreateInfo buffer_info = {}; - buffer_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; - buffer_info.size = index_buffer_size; - buffer_info.usage = VK_BUFFER_USAGE_INDEX_BUFFER_BIT; - buffer_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - err = vkCreateBuffer(g_Device, &buffer_info, g_Allocator, &g_IndexBuffer[g_FrameIndex]); - ImGui_ImplVulkan_VkResult(err); - VkMemoryRequirements req; - vkGetBufferMemoryRequirements(g_Device, g_IndexBuffer[g_FrameIndex], &req); - g_BufferMemoryAlignment = (g_BufferMemoryAlignment > req.alignment) ? g_BufferMemoryAlignment : req.alignment; - VkMemoryAllocateInfo alloc_info = {}; - alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - alloc_info.allocationSize = req.size; - alloc_info.memoryTypeIndex = ImGui_ImplVulkan_MemoryType(VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, req.memoryTypeBits); - err = vkAllocateMemory(g_Device, &alloc_info, g_Allocator, &g_IndexBufferMemory[g_FrameIndex]); - ImGui_ImplVulkan_VkResult(err); - err = vkBindBufferMemory(g_Device, g_IndexBuffer[g_FrameIndex], g_IndexBufferMemory[g_FrameIndex], 0); - ImGui_ImplVulkan_VkResult(err); - g_IndexBufferSize[g_FrameIndex] = index_buffer_size; - } + if (!fd->VertexBuffer || fd->VertexBufferSize < vertex_size) + CreateOrResizeBuffer(fd->VertexBuffer, fd->VertexBufferMemory, fd->VertexBufferSize, vertex_size, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT); + if (!fd->IndexBuffer || fd->IndexBufferSize < index_size) + CreateOrResizeBuffer(fd->IndexBuffer, fd->IndexBufferMemory, fd->IndexBufferSize, index_size, VK_BUFFER_USAGE_INDEX_BUFFER_BIT); // Upload Vertex and index Data: { ImDrawVert* vtx_dst; ImDrawIdx* idx_dst; - err = vkMapMemory(g_Device, g_VertexBufferMemory[g_FrameIndex], 0, vertex_size, 0, (void**)(&vtx_dst)); + err = vkMapMemory(g_Device, fd->VertexBufferMemory, 0, vertex_size, 0, (void**)(&vtx_dst)); ImGui_ImplVulkan_VkResult(err); - err = vkMapMemory(g_Device, g_IndexBufferMemory[g_FrameIndex], 0, index_size, 0, (void**)(&idx_dst)); + err = vkMapMemory(g_Device, fd->IndexBufferMemory, 0, index_size, 0, (void**)(&idx_dst)); ImGui_ImplVulkan_VkResult(err); for (int n = 0; n < draw_data->CmdListsCount; n++) { @@ -237,30 +227,30 @@ void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data) } VkMappedMemoryRange range[2] = {}; range[0].sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE; - range[0].memory = g_VertexBufferMemory[g_FrameIndex]; + range[0].memory = fd->VertexBufferMemory; range[0].size = VK_WHOLE_SIZE; range[1].sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE; - range[1].memory = g_IndexBufferMemory[g_FrameIndex]; + range[1].memory = fd->IndexBufferMemory; range[1].size = VK_WHOLE_SIZE; err = vkFlushMappedMemoryRanges(g_Device, 2, range); ImGui_ImplVulkan_VkResult(err); - vkUnmapMemory(g_Device, g_VertexBufferMemory[g_FrameIndex]); - vkUnmapMemory(g_Device, g_IndexBufferMemory[g_FrameIndex]); + vkUnmapMemory(g_Device, fd->VertexBufferMemory); + vkUnmapMemory(g_Device, fd->IndexBufferMemory); } // Bind pipeline and descriptor sets: { - vkCmdBindPipeline(g_CommandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, g_Pipeline); - VkDescriptorSet desc_set[1] = {g_DescriptorSet}; - vkCmdBindDescriptorSets(g_CommandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, g_PipelineLayout, 0, 1, desc_set, 0, NULL); + vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, g_Pipeline); + VkDescriptorSet desc_set[1] = { g_DescriptorSet }; + vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, g_PipelineLayout, 0, 1, desc_set, 0, NULL); } // Bind Vertex And Index Buffer: { - VkBuffer vertex_buffers[1] = {g_VertexBuffer[g_FrameIndex]}; - VkDeviceSize vertex_offset[1] = {0}; - vkCmdBindVertexBuffers(g_CommandBuffer, 0, 1, vertex_buffers, vertex_offset); - vkCmdBindIndexBuffer(g_CommandBuffer, g_IndexBuffer[g_FrameIndex], 0, VK_INDEX_TYPE_UINT16); + VkBuffer vertex_buffers[1] = { fd->VertexBuffer }; + VkDeviceSize vertex_offset[1] = { 0 }; + vkCmdBindVertexBuffers(command_buffer, 0, 1, vertex_buffers, vertex_offset); + vkCmdBindIndexBuffer(command_buffer, fd->IndexBuffer, 0, VK_INDEX_TYPE_UINT16); } // Setup viewport: @@ -272,7 +262,7 @@ void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data) viewport.height = io.DisplaySize.y; viewport.minDepth = 0.0f; viewport.maxDepth = 1.0f; - vkCmdSetViewport(g_CommandBuffer, 0, 1, &viewport); + vkCmdSetViewport(command_buffer, 0, 1, &viewport); } // Setup scale and translation: @@ -284,8 +274,8 @@ void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data) float translate[2]; translate[0] = -1.0f - io.DisplayPos.x * scale[0]; translate[1] = -1.0f - io.DisplayPos.y * scale[1]; - vkCmdPushConstants(g_CommandBuffer, g_PipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, sizeof(float) * 0, sizeof(float) * 2, scale); - vkCmdPushConstants(g_CommandBuffer, g_PipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, sizeof(float) * 2, sizeof(float) * 2, translate); + vkCmdPushConstants(command_buffer, g_PipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, sizeof(float) * 0, sizeof(float) * 2, scale); + vkCmdPushConstants(command_buffer, g_PipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, sizeof(float) * 2, sizeof(float) * 2, translate); } // Render the command lists: @@ -310,10 +300,10 @@ void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data) scissor.offset.y = (int32_t)(pcmd->ClipRect.y - io.DisplayPos.y) > 0 ? (int32_t)(pcmd->ClipRect.y - io.DisplayPos.y) : 0; scissor.extent.width = (uint32_t)(pcmd->ClipRect.z - pcmd->ClipRect.x); scissor.extent.height = (uint32_t)(pcmd->ClipRect.w - pcmd->ClipRect.y + 1); // FIXME: Why +1 here? - vkCmdSetScissor(g_CommandBuffer, 0, 1, &scissor); + vkCmdSetScissor(command_buffer, 0, 1, &scissor); // Draw - vkCmdDrawIndexed(g_CommandBuffer, pcmd->ElemCount, 1, idx_offset, vtx_offset, 0); + vkCmdDrawIndexed(command_buffer, pcmd->ElemCount, 1, idx_offset, vtx_offset, 0); } idx_offset += pcmd->ElemCount; } @@ -540,11 +530,12 @@ bool ImGui_ImplVulkan_CreateDeviceObjects() if (!g_PipelineLayout) { + // Constants: we are using 'vec2 offset' and 'vec2 scale' instead of a full 3d projection matrix VkPushConstantRange push_constants[1] = {}; push_constants[0].stageFlags = VK_SHADER_STAGE_VERTEX_BIT; push_constants[0].offset = sizeof(float) * 0; push_constants[0].size = sizeof(float) * 4; - VkDescriptorSetLayout set_layout[1] = {g_DescriptorSetLayout}; + VkDescriptorSetLayout set_layout[1] = { g_DescriptorSetLayout }; VkPipelineLayoutCreateInfo layout_info = {}; layout_info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; layout_info.setLayoutCount = 1; @@ -573,15 +564,15 @@ bool ImGui_ImplVulkan_CreateDeviceObjects() attribute_desc[0].location = 0; attribute_desc[0].binding = binding_desc[0].binding; attribute_desc[0].format = VK_FORMAT_R32G32_SFLOAT; - attribute_desc[0].offset = (size_t)(&((ImDrawVert*)0)->pos); + attribute_desc[0].offset = IM_OFFSETOF(ImDrawVert, pos); attribute_desc[1].location = 1; attribute_desc[1].binding = binding_desc[0].binding; attribute_desc[1].format = VK_FORMAT_R32G32_SFLOAT; - attribute_desc[1].offset = (size_t)(&((ImDrawVert*)0)->uv); + attribute_desc[1].offset = IM_OFFSETOF(ImDrawVert, uv); attribute_desc[2].location = 2; attribute_desc[2].binding = binding_desc[0].binding; attribute_desc[2].format = VK_FORMAT_R8G8B8A8_UNORM; - attribute_desc[2].offset = (size_t)(&((ImDrawVert*)0)->col); + attribute_desc[2].offset = IM_OFFSETOF(ImDrawVert, col); VkPipelineVertexInputStateCreateInfo vertex_info = {}; vertex_info.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; @@ -678,10 +669,11 @@ void ImGui_ImplVulkan_InvalidateDeviceObjects() for (int i = 0; i < IMGUI_VK_QUEUED_FRAMES; i++) { - if (g_VertexBuffer[i]) { vkDestroyBuffer(g_Device, g_VertexBuffer[i], g_Allocator); g_VertexBuffer[i] = VK_NULL_HANDLE; } - if (g_VertexBufferMemory[i]) { vkFreeMemory(g_Device, g_VertexBufferMemory[i], g_Allocator); g_VertexBufferMemory[i] = VK_NULL_HANDLE; } - if (g_IndexBuffer[i]) { vkDestroyBuffer(g_Device, g_IndexBuffer[i], g_Allocator); g_IndexBuffer[i] = VK_NULL_HANDLE; } - if (g_IndexBufferMemory[i]) { vkFreeMemory(g_Device, g_IndexBufferMemory[i], g_Allocator); g_IndexBufferMemory[i] = VK_NULL_HANDLE; } + FrameDataForRender* fd = &g_FramesDataBuffers[i]; + if (fd->VertexBuffer) { vkDestroyBuffer (g_Device, fd->VertexBuffer, g_Allocator); fd->VertexBuffer = VK_NULL_HANDLE; } + if (fd->VertexBufferMemory) { vkFreeMemory (g_Device, fd->VertexBufferMemory, g_Allocator); fd->VertexBufferMemory = VK_NULL_HANDLE; } + if (fd->IndexBuffer) { vkDestroyBuffer (g_Device, fd->IndexBuffer, g_Allocator); fd->IndexBuffer = VK_NULL_HANDLE; } + if (fd->IndexBufferMemory) { vkFreeMemory (g_Device, fd->IndexBufferMemory, g_Allocator); fd->IndexBufferMemory = VK_NULL_HANDLE; } } if (g_FontView) { vkDestroyImageView(g_Device, g_FontView, g_Allocator); g_FontView = VK_NULL_HANDLE; } @@ -723,10 +715,8 @@ void ImGui_ImplVulkan_NewFrame() void ImGui_ImplVulkan_Render(VkCommandBuffer command_buffer) { - g_CommandBuffer = command_buffer; ImGui::Render(); - ImGui_ImplVulkan_RenderDrawData(ImGui::GetDrawData()); - g_CommandBuffer = VK_NULL_HANDLE; + ImGui_ImplVulkan_RenderDrawData(command_buffer, ImGui::GetDrawData()); g_FrameIndex = (g_FrameIndex + 1) % IMGUI_VK_QUEUED_FRAMES; } diff --git a/examples/imgui_impl_vulkan.h b/examples/imgui_impl_vulkan.h index 188f0e11..044795a2 100644 --- a/examples/imgui_impl_vulkan.h +++ b/examples/imgui_impl_vulkan.h @@ -28,6 +28,7 @@ IMGUI_API bool ImGui_ImplVulkan_Init(ImGui_ImplVulkan_InitInfo *init_data IMGUI_API void ImGui_ImplVulkan_Shutdown(); IMGUI_API void ImGui_ImplVulkan_NewFrame(); IMGUI_API void ImGui_ImplVulkan_Render(VkCommandBuffer command_buffer); +IMGUI_API void ImGui_ImplVulkan_RenderDrawData(VkCommandBuffer command_buffer, ImDrawData* draw_data); // Called by Init/NewFrame/Shutdown IMGUI_API void ImGui_ImplVulkan_InvalidateFontUploadObjects(); diff --git a/examples/sdl_vulkan_example/main.cpp b/examples/sdl_vulkan_example/main.cpp index 42d6c349..8d24b6bf 100644 --- a/examples/sdl_vulkan_example/main.cpp +++ b/examples/sdl_vulkan_example/main.cpp @@ -34,18 +34,22 @@ static VkPipelineCache g_PipelineCache = VK_NULL_HANDLE; static VkDescriptorPool g_DescriptorPool = VK_NULL_HANDLE; static int fb_width, fb_height; -static uint32_t g_BackbufferIndices[IMGUI_VK_QUEUED_FRAMES]; // keep track of recently rendered swapchain frame indices static uint32_t g_BackBufferCount = 0; static VkImage g_BackBuffer[IMGUI_MAX_POSSIBLE_BACK_BUFFERS] = {}; static VkImageView g_BackBufferView[IMGUI_MAX_POSSIBLE_BACK_BUFFERS] = {}; static VkFramebuffer g_Framebuffer[IMGUI_MAX_POSSIBLE_BACK_BUFFERS] = {}; +struct FrameData +{ + uint32_t BackbufferIndex; // keep track of recently rendered swapchain frame indices + VkCommandPool CommandPool; + VkCommandBuffer CommandBuffer; + VkFence Fence; + VkSemaphore PresentCompleteSemaphore; + VkSemaphore RenderCompleteSemaphore; +}; static uint32_t g_FrameIndex = 0; -static VkCommandPool g_CommandPool[IMGUI_VK_QUEUED_FRAMES]; -static VkCommandBuffer g_CommandBuffer[IMGUI_VK_QUEUED_FRAMES]; -static VkFence g_Fence[IMGUI_VK_QUEUED_FRAMES]; -static VkSemaphore g_PresentCompleteSemaphore[IMGUI_VK_QUEUED_FRAMES]; -static VkSemaphore g_RenderCompleteSemaphore[IMGUI_VK_QUEUED_FRAMES]; +static FrameData g_Frames[IMGUI_VK_QUEUED_FRAMES] = {}; static VkClearValue g_ClearValue = {}; @@ -295,6 +299,7 @@ static void setup_vulkan(SDL_Window* window, const char** extensions, uint32_t e } } + // Get Surface Format { const VkFormat requestSurfaceImageFormat[] = { VK_FORMAT_B8G8R8A8_UNORM, VK_FORMAT_R8G8B8A8_UNORM, VK_FORMAT_B8G8R8_UNORM, VK_FORMAT_R8G8B8_UNORM }; @@ -347,43 +352,44 @@ static void setup_vulkan(SDL_Window* window, const char** extensions, uint32_t e // Create Command Buffers for (int i = 0; i < IMGUI_VK_QUEUED_FRAMES; i++) { + FrameData* fd = &g_Frames[i]; { VkCommandPoolCreateInfo info = {}; info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; info.queueFamilyIndex = g_QueueFamily; - err = vkCreateCommandPool(g_Device, &info, g_Allocator, &g_CommandPool[i]); + err = vkCreateCommandPool(g_Device, &info, g_Allocator, &fd->CommandPool); check_vk_result(err); } { VkCommandBufferAllocateInfo info = {}; info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; - info.commandPool = g_CommandPool[i]; + info.commandPool = fd->CommandPool; info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; info.commandBufferCount = 1; - err = vkAllocateCommandBuffers(g_Device, &info, &g_CommandBuffer[i]); + err = vkAllocateCommandBuffers(g_Device, &info, &fd->CommandBuffer); check_vk_result(err); } { VkFenceCreateInfo info = {}; info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; info.flags = VK_FENCE_CREATE_SIGNALED_BIT; - err = vkCreateFence(g_Device, &info, g_Allocator, &g_Fence[i]); + err = vkCreateFence(g_Device, &info, g_Allocator, &fd->Fence); check_vk_result(err); } { VkSemaphoreCreateInfo info = {}; info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; - err = vkCreateSemaphore(g_Device, &info, g_Allocator, &g_PresentCompleteSemaphore[i]); + err = vkCreateSemaphore(g_Device, &info, g_Allocator, &fd->PresentCompleteSemaphore); check_vk_result(err); - err = vkCreateSemaphore(g_Device, &info, g_Allocator, &g_RenderCompleteSemaphore[i]); + err = vkCreateSemaphore(g_Device, &info, g_Allocator, &fd->RenderCompleteSemaphore); check_vk_result(err); } } // Create Descriptor Pool { - VkDescriptorPoolSize pool_size[11] = + VkDescriptorPoolSize pool_sizes[] = { { VK_DESCRIPTOR_TYPE_SAMPLER, 1000 }, { VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1000 }, @@ -400,9 +406,9 @@ static void setup_vulkan(SDL_Window* window, const char** extensions, uint32_t e VkDescriptorPoolCreateInfo pool_info = {}; pool_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; pool_info.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT; - pool_info.maxSets = 1000 * 11; - pool_info.poolSizeCount = 11; - pool_info.pPoolSizes = pool_size; + pool_info.maxSets = 1000 * IM_ARRAYSIZE(pool_sizes); + pool_info.poolSizeCount = (uint32_t)IM_ARRAYSIZE(pool_sizes); + pool_info.pPoolSizes = pool_sizes; err = vkCreateDescriptorPool(g_Device, &pool_info, g_Allocator, &g_DescriptorPool); check_vk_result(err); } @@ -413,11 +419,12 @@ static void cleanup_vulkan() vkDestroyDescriptorPool(g_Device, g_DescriptorPool, g_Allocator); for (int i = 0; i < IMGUI_VK_QUEUED_FRAMES; i++) { - vkDestroyFence(g_Device, g_Fence[i], g_Allocator); - vkFreeCommandBuffers(g_Device, g_CommandPool[i], 1, &g_CommandBuffer[i]); - vkDestroyCommandPool(g_Device, g_CommandPool[i], g_Allocator); - vkDestroySemaphore(g_Device, g_PresentCompleteSemaphore[i], g_Allocator); - vkDestroySemaphore(g_Device, g_RenderCompleteSemaphore[i], g_Allocator); + FrameData* fd = &g_Frames[i]; + vkDestroyFence(g_Device, fd->Fence, g_Allocator); + vkFreeCommandBuffers(g_Device, fd->CommandPool, 1, &fd->CommandBuffer); + vkDestroyCommandPool(g_Device, fd->CommandPool, g_Allocator); + vkDestroySemaphore(g_Device, fd->PresentCompleteSemaphore, g_Allocator); + vkDestroySemaphore(g_Device, fd->RenderCompleteSemaphore, g_Allocator); } for (uint32_t i = 0; i < g_BackBufferCount; i++) { @@ -440,61 +447,63 @@ static void cleanup_vulkan() static void frame_begin() { + FrameData* fd = &g_Frames[g_FrameIndex]; VkResult err; for (;;) { - err = vkWaitForFences(g_Device, 1, &g_Fence[g_FrameIndex], VK_TRUE, 100); + err = vkWaitForFences(g_Device, 1, &fd->Fence, VK_TRUE, 100); if (err == VK_SUCCESS) break; if (err == VK_TIMEOUT) continue; check_vk_result(err); } { - err = vkAcquireNextImageKHR(g_Device, g_Swapchain, UINT64_MAX, g_PresentCompleteSemaphore[g_FrameIndex], VK_NULL_HANDLE, &g_BackbufferIndices[g_FrameIndex]); + err = vkAcquireNextImageKHR(g_Device, g_Swapchain, UINT64_MAX, fd->PresentCompleteSemaphore, VK_NULL_HANDLE, &fd->BackbufferIndex); check_vk_result(err); } { - err = vkResetCommandPool(g_Device, g_CommandPool[g_FrameIndex], 0); + err = vkResetCommandPool(g_Device, fd->CommandPool, 0); check_vk_result(err); VkCommandBufferBeginInfo info = {}; info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; info.flags |= VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; - err = vkBeginCommandBuffer(g_CommandBuffer[g_FrameIndex], &info); + err = vkBeginCommandBuffer(fd->CommandBuffer, &info); check_vk_result(err); } { VkRenderPassBeginInfo info = {}; info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; info.renderPass = g_RenderPass; - info.framebuffer = g_Framebuffer[g_BackbufferIndices[g_FrameIndex]]; + info.framebuffer = g_Framebuffer[fd->BackbufferIndex]; info.renderArea.extent.width = fb_width; info.renderArea.extent.height = fb_height; info.clearValueCount = 1; info.pClearValues = &g_ClearValue; - vkCmdBeginRenderPass(g_CommandBuffer[g_FrameIndex], &info, VK_SUBPASS_CONTENTS_INLINE); + vkCmdBeginRenderPass(fd->CommandBuffer, &info, VK_SUBPASS_CONTENTS_INLINE); } } static void frame_end() { + FrameData* fd = &g_Frames[g_FrameIndex]; VkResult err; - vkCmdEndRenderPass(g_CommandBuffer[g_FrameIndex]); + vkCmdEndRenderPass(fd->CommandBuffer); { VkPipelineStageFlags wait_stage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; VkSubmitInfo info = {}; info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; info.waitSemaphoreCount = 1; - info.pWaitSemaphores = &g_PresentCompleteSemaphore[g_FrameIndex]; + info.pWaitSemaphores = &fd->PresentCompleteSemaphore; info.pWaitDstStageMask = &wait_stage; info.commandBufferCount = 1; - info.pCommandBuffers = &g_CommandBuffer[g_FrameIndex]; + info.pCommandBuffers = &fd->CommandBuffer; info.signalSemaphoreCount = 1; - info.pSignalSemaphores = &g_RenderCompleteSemaphore[g_FrameIndex]; + info.pSignalSemaphores = &fd->RenderCompleteSemaphore; - err = vkEndCommandBuffer(g_CommandBuffer[g_FrameIndex]); + err = vkEndCommandBuffer(fd->CommandBuffer); check_vk_result(err); - err = vkResetFences(g_Device, 1, &g_Fence[g_FrameIndex]); + err = vkResetFences(g_Device, 1, &fd->Fence); check_vk_result(err); - err = vkQueueSubmit(g_Queue, 1, &info, g_Fence[g_FrameIndex]); + err = vkQueueSubmit(g_Queue, 1, &info, fd->Fence); check_vk_result(err); } } @@ -509,15 +518,14 @@ static void frame_present() uint32_t PresentIndex = g_FrameIndex; #endif // IMGUI_UNLIMITED_FRAME_RATE - VkSwapchainKHR swapchains[1] = { g_Swapchain }; - uint32_t indices[1] = { g_BackbufferIndices[PresentIndex] }; + FrameData* fd = &g_Frames[PresentIndex]; VkPresentInfoKHR info = {}; info.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; info.waitSemaphoreCount = 1; - info.pWaitSemaphores = &g_RenderCompleteSemaphore[PresentIndex]; + info.pWaitSemaphores = &fd->RenderCompleteSemaphore; info.swapchainCount = 1; - info.pSwapchains = swapchains; - info.pImageIndices = indices; + info.pSwapchains = &g_Swapchain; + info.pImageIndices = &fd->BackbufferIndex; err = vkQueuePresentKHR(g_Queue, &info); check_vk_result(err); @@ -584,22 +592,26 @@ int main(int, char**) // Upload Fonts { + // Use any command queue + VkCommandPool command_pool = g_Frames[g_FrameIndex].CommandPool; + VkCommandBuffer command_buffer = g_Frames[g_FrameIndex].CommandBuffer; + VkResult err; - err = vkResetCommandPool(g_Device, g_CommandPool[g_FrameIndex], 0); + err = vkResetCommandPool(g_Device, command_pool, 0); check_vk_result(err); VkCommandBufferBeginInfo begin_info = {}; begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; begin_info.flags |= VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; - err = vkBeginCommandBuffer(g_CommandBuffer[g_FrameIndex], &begin_info); + err = vkBeginCommandBuffer(command_buffer, &begin_info); check_vk_result(err); - ImGui_ImplVulkan_CreateFontsTexture(g_CommandBuffer[g_FrameIndex]); + ImGui_ImplVulkan_CreateFontsTexture(command_buffer); VkSubmitInfo end_info = {}; end_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; end_info.commandBufferCount = 1; - end_info.pCommandBuffers = &g_CommandBuffer[g_FrameIndex]; - err = vkEndCommandBuffer(g_CommandBuffer[g_FrameIndex]); + end_info.pCommandBuffers = &command_buffer; + err = vkEndCommandBuffer(command_buffer); check_vk_result(err); err = vkQueueSubmit(g_Queue, 1, &end_info, VK_NULL_HANDLE); check_vk_result(err); @@ -620,7 +632,7 @@ int main(int, char**) ImGui_ImplVulkan_NewFrame(); ImGui_ImplSDL2_NewFrame(window); frame_begin(); - ImGui_ImplVulkan_Render(g_CommandBuffer[g_FrameIndex]); + ImGui_ImplVulkan_Render(g_Frames[g_FrameIndex].CommandBuffer); frame_end(); g_FrameIndex = (g_FrameIndex + 1) % IMGUI_VK_QUEUED_FRAMES; #endif // IMGUI_UNLIMITED_FRAME_RATE @@ -685,7 +697,7 @@ int main(int, char**) // Rendering memcpy(&g_ClearValue.color.float32[0], &clear_color, 4 * sizeof(float)); frame_begin(); - ImGui_ImplVulkan_Render(g_CommandBuffer[g_FrameIndex]); + ImGui_ImplVulkan_Render(g_Frames[g_FrameIndex].CommandBuffer); frame_end(); frame_present(); } diff --git a/examples/vulkan_example/main.cpp b/examples/vulkan_example/main.cpp index 2e6c8bbd..a25592de 100644 --- a/examples/vulkan_example/main.cpp +++ b/examples/vulkan_example/main.cpp @@ -37,18 +37,22 @@ static VkPipelineCache g_PipelineCache = VK_NULL_HANDLE; static VkDescriptorPool g_DescriptorPool = VK_NULL_HANDLE; static int fb_width, fb_height; -static uint32_t g_BackbufferIndices[IMGUI_VK_QUEUED_FRAMES]; // keep track of recently rendered swapchain frame indices static uint32_t g_BackBufferCount = 0; static VkImage g_BackBuffer[IMGUI_MAX_POSSIBLE_BACK_BUFFERS] = {}; static VkImageView g_BackBufferView[IMGUI_MAX_POSSIBLE_BACK_BUFFERS] = {}; static VkFramebuffer g_Framebuffer[IMGUI_MAX_POSSIBLE_BACK_BUFFERS] = {}; +struct FrameData +{ + uint32_t BackbufferIndex; // keep track of recently rendered swapchain frame indices + VkCommandPool CommandPool; + VkCommandBuffer CommandBuffer; + VkFence Fence; + VkSemaphore PresentCompleteSemaphore; + VkSemaphore RenderCompleteSemaphore; +}; static uint32_t g_FrameIndex = 0; -static VkCommandPool g_CommandPool[IMGUI_VK_QUEUED_FRAMES]; -static VkCommandBuffer g_CommandBuffer[IMGUI_VK_QUEUED_FRAMES]; -static VkFence g_Fence[IMGUI_VK_QUEUED_FRAMES]; -static VkSemaphore g_PresentCompleteSemaphore[IMGUI_VK_QUEUED_FRAMES]; -static VkSemaphore g_RenderCompleteSemaphore[IMGUI_VK_QUEUED_FRAMES]; +static FrameData g_Frames[IMGUI_VK_QUEUED_FRAMES] = {}; static VkClearValue g_ClearValue = {}; @@ -353,43 +357,44 @@ static void setup_vulkan(GLFWwindow* window, const char** extensions, uint32_t e // Create Command Buffers for (int i = 0; i < IMGUI_VK_QUEUED_FRAMES; i++) { + FrameData* fd = &g_Frames[i]; { VkCommandPoolCreateInfo info = {}; info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; info.queueFamilyIndex = g_QueueFamily; - err = vkCreateCommandPool(g_Device, &info, g_Allocator, &g_CommandPool[i]); + err = vkCreateCommandPool(g_Device, &info, g_Allocator, &fd->CommandPool); check_vk_result(err); } { VkCommandBufferAllocateInfo info = {}; info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; - info.commandPool = g_CommandPool[i]; + info.commandPool = fd->CommandPool; info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; info.commandBufferCount = 1; - err = vkAllocateCommandBuffers(g_Device, &info, &g_CommandBuffer[i]); + err = vkAllocateCommandBuffers(g_Device, &info, &fd->CommandBuffer); check_vk_result(err); } { VkFenceCreateInfo info = {}; info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; info.flags = VK_FENCE_CREATE_SIGNALED_BIT; - err = vkCreateFence(g_Device, &info, g_Allocator, &g_Fence[i]); + err = vkCreateFence(g_Device, &info, g_Allocator, &fd->Fence); check_vk_result(err); } { VkSemaphoreCreateInfo info = {}; info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; - err = vkCreateSemaphore(g_Device, &info, g_Allocator, &g_PresentCompleteSemaphore[i]); + err = vkCreateSemaphore(g_Device, &info, g_Allocator, &fd->PresentCompleteSemaphore); check_vk_result(err); - err = vkCreateSemaphore(g_Device, &info, g_Allocator, &g_RenderCompleteSemaphore[i]); + err = vkCreateSemaphore(g_Device, &info, g_Allocator, &fd->RenderCompleteSemaphore); check_vk_result(err); } } // Create Descriptor Pool { - VkDescriptorPoolSize pool_size[11] = + VkDescriptorPoolSize pool_sizes[] = { { VK_DESCRIPTOR_TYPE_SAMPLER, 1000 }, { VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1000 }, @@ -406,9 +411,9 @@ static void setup_vulkan(GLFWwindow* window, const char** extensions, uint32_t e VkDescriptorPoolCreateInfo pool_info = {}; pool_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; pool_info.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT; - pool_info.maxSets = 1000 * 11; - pool_info.poolSizeCount = 11; - pool_info.pPoolSizes = pool_size; + pool_info.maxSets = 1000 * IM_ARRAYSIZE(pool_sizes); + pool_info.poolSizeCount = (uint32_t)IM_ARRAYSIZE(pool_sizes); + pool_info.pPoolSizes = pool_sizes; err = vkCreateDescriptorPool(g_Device, &pool_info, g_Allocator, &g_DescriptorPool); check_vk_result(err); } @@ -419,11 +424,12 @@ static void cleanup_vulkan() vkDestroyDescriptorPool(g_Device, g_DescriptorPool, g_Allocator); for (int i = 0; i < IMGUI_VK_QUEUED_FRAMES; i++) { - vkDestroyFence(g_Device, g_Fence[i], g_Allocator); - vkFreeCommandBuffers(g_Device, g_CommandPool[i], 1, &g_CommandBuffer[i]); - vkDestroyCommandPool(g_Device, g_CommandPool[i], g_Allocator); - vkDestroySemaphore(g_Device, g_PresentCompleteSemaphore[i], g_Allocator); - vkDestroySemaphore(g_Device, g_RenderCompleteSemaphore[i], g_Allocator); + FrameData* fd = &g_Frames[i]; + vkDestroyFence(g_Device, fd->Fence, g_Allocator); + vkFreeCommandBuffers(g_Device, fd->CommandPool, 1, &fd->CommandBuffer); + vkDestroyCommandPool(g_Device, fd->CommandPool, g_Allocator); + vkDestroySemaphore(g_Device, fd->PresentCompleteSemaphore, g_Allocator); + vkDestroySemaphore(g_Device, fd->RenderCompleteSemaphore, g_Allocator); } for (uint32_t i = 0; i < g_BackBufferCount; i++) { @@ -446,61 +452,63 @@ static void cleanup_vulkan() static void frame_begin() { + FrameData* fd = &g_Frames[g_FrameIndex]; VkResult err; for (;;) { - err = vkWaitForFences(g_Device, 1, &g_Fence[g_FrameIndex], VK_TRUE, 100); + err = vkWaitForFences(g_Device, 1, &fd->Fence, VK_TRUE, 100); if (err == VK_SUCCESS) break; if (err == VK_TIMEOUT) continue; check_vk_result(err); } { - err = vkAcquireNextImageKHR(g_Device, g_Swapchain, UINT64_MAX, g_PresentCompleteSemaphore[g_FrameIndex], VK_NULL_HANDLE, &g_BackbufferIndices[g_FrameIndex]); + err = vkAcquireNextImageKHR(g_Device, g_Swapchain, UINT64_MAX, fd->PresentCompleteSemaphore, VK_NULL_HANDLE, &fd->BackbufferIndex); check_vk_result(err); } { - err = vkResetCommandPool(g_Device, g_CommandPool[g_FrameIndex], 0); + err = vkResetCommandPool(g_Device, fd->CommandPool, 0); check_vk_result(err); VkCommandBufferBeginInfo info = {}; info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; info.flags |= VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; - err = vkBeginCommandBuffer(g_CommandBuffer[g_FrameIndex], &info); + err = vkBeginCommandBuffer(fd->CommandBuffer, &info); check_vk_result(err); } { VkRenderPassBeginInfo info = {}; info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; info.renderPass = g_RenderPass; - info.framebuffer = g_Framebuffer[g_BackbufferIndices[g_FrameIndex]]; + info.framebuffer = g_Framebuffer[fd->BackbufferIndex]; info.renderArea.extent.width = fb_width; info.renderArea.extent.height = fb_height; info.clearValueCount = 1; info.pClearValues = &g_ClearValue; - vkCmdBeginRenderPass(g_CommandBuffer[g_FrameIndex], &info, VK_SUBPASS_CONTENTS_INLINE); + vkCmdBeginRenderPass(fd->CommandBuffer, &info, VK_SUBPASS_CONTENTS_INLINE); } } static void frame_end() { + FrameData* fd = &g_Frames[g_FrameIndex]; VkResult err; - vkCmdEndRenderPass(g_CommandBuffer[g_FrameIndex]); + vkCmdEndRenderPass(fd->CommandBuffer); { VkPipelineStageFlags wait_stage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; VkSubmitInfo info = {}; info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; info.waitSemaphoreCount = 1; - info.pWaitSemaphores = &g_PresentCompleteSemaphore[g_FrameIndex]; + info.pWaitSemaphores = &fd->PresentCompleteSemaphore; info.pWaitDstStageMask = &wait_stage; info.commandBufferCount = 1; - info.pCommandBuffers = &g_CommandBuffer[g_FrameIndex]; + info.pCommandBuffers = &fd->CommandBuffer; info.signalSemaphoreCount = 1; - info.pSignalSemaphores = &g_RenderCompleteSemaphore[g_FrameIndex]; + info.pSignalSemaphores = &fd->RenderCompleteSemaphore; - err = vkEndCommandBuffer(g_CommandBuffer[g_FrameIndex]); + err = vkEndCommandBuffer(fd->CommandBuffer); check_vk_result(err); - err = vkResetFences(g_Device, 1, &g_Fence[g_FrameIndex]); + err = vkResetFences(g_Device, 1, &fd->Fence); check_vk_result(err); - err = vkQueueSubmit(g_Queue, 1, &info, g_Fence[g_FrameIndex]); + err = vkQueueSubmit(g_Queue, 1, &info, fd->Fence); check_vk_result(err); } } @@ -515,15 +523,14 @@ static void frame_present() uint32_t PresentIndex = g_FrameIndex; #endif // IMGUI_UNLIMITED_FRAME_RATE - VkSwapchainKHR swapchains[1] = { g_Swapchain }; - uint32_t indices[1] = { g_BackbufferIndices[PresentIndex] }; + FrameData* fd = &g_Frames[PresentIndex]; VkPresentInfoKHR info = {}; info.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; info.waitSemaphoreCount = 1; - info.pWaitSemaphores = &g_RenderCompleteSemaphore[PresentIndex]; + info.pWaitSemaphores = &fd->RenderCompleteSemaphore; info.swapchainCount = 1; - info.pSwapchains = swapchains; - info.pImageIndices = indices; + info.pSwapchains = &g_Swapchain; + info.pImageIndices = &fd->BackbufferIndex; err = vkQueuePresentKHR(g_Queue, &info); check_vk_result(err); @@ -595,22 +602,26 @@ int main(int, char**) // Upload Fonts { + // Use any command queue + VkCommandPool command_pool = g_Frames[g_FrameIndex].CommandPool; + VkCommandBuffer command_buffer = g_Frames[g_FrameIndex].CommandBuffer; + VkResult err; - err = vkResetCommandPool(g_Device, g_CommandPool[g_FrameIndex], 0); + err = vkResetCommandPool(g_Device, command_pool, 0); check_vk_result(err); VkCommandBufferBeginInfo begin_info = {}; begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; begin_info.flags |= VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; - err = vkBeginCommandBuffer(g_CommandBuffer[g_FrameIndex], &begin_info); + err = vkBeginCommandBuffer(command_buffer, &begin_info); check_vk_result(err); - ImGui_ImplVulkan_CreateFontsTexture(g_CommandBuffer[g_FrameIndex]); + ImGui_ImplVulkan_CreateFontsTexture(command_buffer); VkSubmitInfo end_info = {}; end_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; end_info.commandBufferCount = 1; - end_info.pCommandBuffers = &g_CommandBuffer[g_FrameIndex]; - err = vkEndCommandBuffer(g_CommandBuffer[g_FrameIndex]); + end_info.pCommandBuffers = &command_buffer; + err = vkEndCommandBuffer(command_buffer); check_vk_result(err); err = vkQueueSubmit(g_Queue, 1, &end_info, VK_NULL_HANDLE); check_vk_result(err); @@ -631,7 +642,7 @@ int main(int, char**) ImGui_ImplVulkan_NewFrame(); ImGui_ImplGlfw_NewFrame(); frame_begin(); - ImGui_ImplVulkan_Render(g_CommandBuffer[g_FrameIndex]); + ImGui_ImplVulkan_Render(g_Frames[g_FrameIndex].CommandBuffer); frame_end(); g_FrameIndex = (g_FrameIndex + 1) % IMGUI_VK_QUEUED_FRAMES; #endif // IMGUI_UNLIMITED_FRAME_RATE @@ -687,7 +698,7 @@ int main(int, char**) // Rendering memcpy(&g_ClearValue.color.float32[0], &clear_color, 4 * sizeof(float)); frame_begin(); - ImGui_ImplVulkan_Render(g_CommandBuffer[g_FrameIndex]); + ImGui_ImplVulkan_Render(g_Frames[g_FrameIndex].CommandBuffer); frame_end(); frame_present();