mirror of
				https://github.com/Drezil/imgui.git
				synced 2025-10-31 13:11:05 +01:00 
			
		
		
		
	Examples: Vulkan: Various tweak. Misc refactor into per-frame data. Duplicate buffer creation code moved to CreateOrResizeBuffer().
This commit is contained in:
		| @@ -32,28 +32,32 @@ static VkPipelineCache              g_PipelineCache = VK_NULL_HANDLE; | |||||||
| static VkDescriptorPool             g_DescriptorPool = VK_NULL_HANDLE; | static VkDescriptorPool             g_DescriptorPool = VK_NULL_HANDLE; | ||||||
| static void                         (*g_CheckVkResult)(VkResult err) = NULL; | static void                         (*g_CheckVkResult)(VkResult err) = NULL; | ||||||
|  |  | ||||||
| static VkCommandBuffer        g_CommandBuffer = VK_NULL_HANDLE; |  | ||||||
| static VkDeviceSize           g_BufferMemoryAlignment = 256; | static VkDeviceSize           g_BufferMemoryAlignment = 256; | ||||||
| static VkPipelineCreateFlags  g_PipelineCreateFlags = 0; | static VkPipelineCreateFlags  g_PipelineCreateFlags = 0; | ||||||
| static int                    g_FrameIndex = 0; |  | ||||||
|  |  | ||||||
| static VkDescriptorSetLayout  g_DescriptorSetLayout = VK_NULL_HANDLE; | static VkDescriptorSetLayout  g_DescriptorSetLayout = VK_NULL_HANDLE; | ||||||
| static VkPipelineLayout       g_PipelineLayout = VK_NULL_HANDLE; | static VkPipelineLayout       g_PipelineLayout = VK_NULL_HANDLE; | ||||||
| static VkDescriptorSet        g_DescriptorSet = VK_NULL_HANDLE; | static VkDescriptorSet        g_DescriptorSet = VK_NULL_HANDLE; | ||||||
| static VkPipeline             g_Pipeline = 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 VkSampler              g_FontSampler = VK_NULL_HANDLE; | ||||||
| static VkDeviceMemory         g_FontMemory = VK_NULL_HANDLE; | static VkDeviceMemory         g_FontMemory = VK_NULL_HANDLE; | ||||||
| static VkImage                g_FontImage = VK_NULL_HANDLE; | static VkImage                g_FontImage = VK_NULL_HANDLE; | ||||||
| static VkImageView            g_FontView = 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 VkDeviceMemory         g_UploadBufferMemory = VK_NULL_HANDLE; | ||||||
| static VkBuffer               g_UploadBuffer = 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_InitPlatformInterface(); | ||||||
| static void ImGui_ImplVulkan_ShutdownPlatformInterface(); | 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[] = | static uint32_t __glsl_shader_vert_spv[] = | ||||||
| { | { | ||||||
|     0x07230203,0x00010000,0x00080001,0x0000002e,0x00000000,0x00020011,0x00000001,0x0006000b, |     0x07230203,0x00010000,0x00080001,0x0000002e,0x00000000,0x00020011,0x00000001,0x0006000b, | ||||||
| @@ -106,6 +112,8 @@ static uint32_t __glsl_shader_vert_spv[] = | |||||||
|     0x0000002d,0x0000002c,0x000100fd,0x00010038 |     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[] = | static uint32_t __glsl_shader_frag_spv[] = | ||||||
| { | { | ||||||
|     0x07230203,0x00010000,0x00080001,0x0000001e,0x00000000,0x00020011,0x00000001,0x0006000b, |     0x07230203,0x00010000,0x00080001,0x0000001e,0x00000000,0x00020011,0x00000001,0x0006000b, | ||||||
| @@ -151,81 +159,63 @@ static void ImGui_ImplVulkan_VkResult(VkResult err) | |||||||
|         g_CheckVkResult(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) | // 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; |     VkResult err; | ||||||
|     ImGuiIO& io = ImGui::GetIO(); |     ImGuiIO& io = ImGui::GetIO(); | ||||||
|     if (draw_data->TotalVtxCount == 0) |     if (draw_data->TotalVtxCount == 0) | ||||||
|         return; |         return; | ||||||
|  |  | ||||||
|     // Create the Vertex Buffer: |     FrameDataForRender* fd = &g_FramesDataBuffers[g_FrameIndex]; | ||||||
|     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; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     // 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); |     size_t index_size = draw_data->TotalIdxCount * sizeof(ImDrawIdx); | ||||||
|     if (!g_IndexBuffer[g_FrameIndex] || g_IndexBufferSize[g_FrameIndex] < index_size) |     if (!fd->VertexBuffer || fd->VertexBufferSize < vertex_size) | ||||||
|     { |         CreateOrResizeBuffer(fd->VertexBuffer, fd->VertexBufferMemory, fd->VertexBufferSize, vertex_size, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT); | ||||||
|         if (g_IndexBuffer[g_FrameIndex]) |     if (!fd->IndexBuffer || fd->IndexBufferSize < index_size) | ||||||
|             vkDestroyBuffer(g_Device, g_IndexBuffer[g_FrameIndex], g_Allocator); |         CreateOrResizeBuffer(fd->IndexBuffer, fd->IndexBufferMemory, fd->IndexBufferSize, index_size, VK_BUFFER_USAGE_INDEX_BUFFER_BIT); | ||||||
|         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; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     // Upload Vertex and index Data: |     // Upload Vertex and index Data: | ||||||
|     { |     { | ||||||
|         ImDrawVert* vtx_dst; |         ImDrawVert* vtx_dst; | ||||||
|         ImDrawIdx* idx_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); |         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); |         ImGui_ImplVulkan_VkResult(err); | ||||||
|         for (int n = 0; n < draw_data->CmdListsCount; n++) |         for (int n = 0; n < draw_data->CmdListsCount; n++) | ||||||
|         { |         { | ||||||
| @@ -237,30 +227,30 @@ void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data) | |||||||
|         } |         } | ||||||
|         VkMappedMemoryRange range[2] = {}; |         VkMappedMemoryRange range[2] = {}; | ||||||
|         range[0].sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE; |         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[0].size = VK_WHOLE_SIZE; | ||||||
|         range[1].sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE; |         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; |         range[1].size = VK_WHOLE_SIZE; | ||||||
|         err = vkFlushMappedMemoryRanges(g_Device, 2, range); |         err = vkFlushMappedMemoryRanges(g_Device, 2, range); | ||||||
|         ImGui_ImplVulkan_VkResult(err); |         ImGui_ImplVulkan_VkResult(err); | ||||||
|         vkUnmapMemory(g_Device, g_VertexBufferMemory[g_FrameIndex]); |         vkUnmapMemory(g_Device, fd->VertexBufferMemory); | ||||||
|         vkUnmapMemory(g_Device, g_IndexBufferMemory[g_FrameIndex]); |         vkUnmapMemory(g_Device, fd->IndexBufferMemory); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     // Bind pipeline and descriptor sets: |     // Bind pipeline and descriptor sets: | ||||||
|     { |     { | ||||||
|         vkCmdBindPipeline(g_CommandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, g_Pipeline); |         vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, g_Pipeline); | ||||||
|         VkDescriptorSet desc_set[1] = {g_DescriptorSet}; |         VkDescriptorSet desc_set[1] = { g_DescriptorSet }; | ||||||
|         vkCmdBindDescriptorSets(g_CommandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, g_PipelineLayout, 0, 1, desc_set, 0, NULL); |         vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, g_PipelineLayout, 0, 1, desc_set, 0, NULL); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     // Bind Vertex And Index Buffer: |     // Bind Vertex And Index Buffer: | ||||||
|     { |     { | ||||||
|         VkBuffer vertex_buffers[1] = {g_VertexBuffer[g_FrameIndex]}; |         VkBuffer vertex_buffers[1] = { fd->VertexBuffer }; | ||||||
|         VkDeviceSize vertex_offset[1] = {0}; |         VkDeviceSize vertex_offset[1] = { 0 }; | ||||||
|         vkCmdBindVertexBuffers(g_CommandBuffer, 0, 1, vertex_buffers, vertex_offset); |         vkCmdBindVertexBuffers(command_buffer, 0, 1, vertex_buffers, vertex_offset); | ||||||
|         vkCmdBindIndexBuffer(g_CommandBuffer, g_IndexBuffer[g_FrameIndex], 0, VK_INDEX_TYPE_UINT16); |         vkCmdBindIndexBuffer(command_buffer, fd->IndexBuffer, 0, VK_INDEX_TYPE_UINT16); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     // Setup viewport: |     // Setup viewport: | ||||||
| @@ -272,7 +262,7 @@ void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data) | |||||||
|         viewport.height = io.DisplaySize.y; |         viewport.height = io.DisplaySize.y; | ||||||
|         viewport.minDepth = 0.0f; |         viewport.minDepth = 0.0f; | ||||||
|         viewport.maxDepth = 1.0f; |         viewport.maxDepth = 1.0f; | ||||||
|         vkCmdSetViewport(g_CommandBuffer, 0, 1, &viewport); |         vkCmdSetViewport(command_buffer, 0, 1, &viewport); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     // Setup scale and translation: |     // Setup scale and translation: | ||||||
| @@ -284,8 +274,8 @@ void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data) | |||||||
|         float translate[2]; |         float translate[2]; | ||||||
|         translate[0] = -1.0f - io.DisplayPos.x * scale[0]; |         translate[0] = -1.0f - io.DisplayPos.x * scale[0]; | ||||||
|         translate[1] = -1.0f - io.DisplayPos.y * scale[1]; |         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(command_buffer, 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) * 2, sizeof(float) * 2, translate); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     // Render the command lists: |     // 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.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.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? |                 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 |                 // 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; |             idx_offset += pcmd->ElemCount; | ||||||
|         } |         } | ||||||
| @@ -540,11 +530,12 @@ bool ImGui_ImplVulkan_CreateDeviceObjects() | |||||||
|  |  | ||||||
|     if (!g_PipelineLayout) |     if (!g_PipelineLayout) | ||||||
|     { |     { | ||||||
|  |         // Constants: we are using 'vec2 offset' and 'vec2 scale' instead of a full 3d projection matrix | ||||||
|         VkPushConstantRange push_constants[1] = {}; |         VkPushConstantRange push_constants[1] = {}; | ||||||
|         push_constants[0].stageFlags = VK_SHADER_STAGE_VERTEX_BIT; |         push_constants[0].stageFlags = VK_SHADER_STAGE_VERTEX_BIT; | ||||||
|         push_constants[0].offset = sizeof(float) * 0; |         push_constants[0].offset = sizeof(float) * 0; | ||||||
|         push_constants[0].size = sizeof(float) * 4; |         push_constants[0].size = sizeof(float) * 4; | ||||||
|         VkDescriptorSetLayout set_layout[1] = {g_DescriptorSetLayout}; |         VkDescriptorSetLayout set_layout[1] = { g_DescriptorSetLayout }; | ||||||
|         VkPipelineLayoutCreateInfo layout_info = {}; |         VkPipelineLayoutCreateInfo layout_info = {}; | ||||||
|         layout_info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; |         layout_info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; | ||||||
|         layout_info.setLayoutCount = 1; |         layout_info.setLayoutCount = 1; | ||||||
| @@ -573,15 +564,15 @@ bool ImGui_ImplVulkan_CreateDeviceObjects() | |||||||
|     attribute_desc[0].location = 0; |     attribute_desc[0].location = 0; | ||||||
|     attribute_desc[0].binding = binding_desc[0].binding; |     attribute_desc[0].binding = binding_desc[0].binding; | ||||||
|     attribute_desc[0].format = VK_FORMAT_R32G32_SFLOAT; |     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].location = 1; | ||||||
|     attribute_desc[1].binding = binding_desc[0].binding; |     attribute_desc[1].binding = binding_desc[0].binding; | ||||||
|     attribute_desc[1].format = VK_FORMAT_R32G32_SFLOAT; |     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].location = 2; | ||||||
|     attribute_desc[2].binding = binding_desc[0].binding; |     attribute_desc[2].binding = binding_desc[0].binding; | ||||||
|     attribute_desc[2].format = VK_FORMAT_R8G8B8A8_UNORM; |     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 = {}; |     VkPipelineVertexInputStateCreateInfo vertex_info = {}; | ||||||
|     vertex_info.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_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++) |     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; } |         FrameDataForRender* fd = &g_FramesDataBuffers[i]; | ||||||
|         if (g_VertexBufferMemory[i])    { vkFreeMemory(g_Device, g_VertexBufferMemory[i], g_Allocator); g_VertexBufferMemory[i] = VK_NULL_HANDLE; } |         if (fd->VertexBuffer)       { vkDestroyBuffer   (g_Device, fd->VertexBuffer,        g_Allocator); fd->VertexBuffer = VK_NULL_HANDLE; } | ||||||
|         if (g_IndexBuffer[i])           { vkDestroyBuffer(g_Device, g_IndexBuffer[i], g_Allocator); g_IndexBuffer[i] = VK_NULL_HANDLE; } |         if (fd->VertexBufferMemory) { vkFreeMemory      (g_Device, fd->VertexBufferMemory,  g_Allocator); fd->VertexBufferMemory = VK_NULL_HANDLE; } | ||||||
|         if (g_IndexBufferMemory[i])     { vkFreeMemory(g_Device, g_IndexBufferMemory[i], g_Allocator); g_IndexBufferMemory[i] = 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; } |     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) | void ImGui_ImplVulkan_Render(VkCommandBuffer command_buffer) | ||||||
| { | { | ||||||
|     g_CommandBuffer = command_buffer; |  | ||||||
|     ImGui::Render(); |     ImGui::Render(); | ||||||
|     ImGui_ImplVulkan_RenderDrawData(ImGui::GetDrawData()); |     ImGui_ImplVulkan_RenderDrawData(command_buffer, ImGui::GetDrawData()); | ||||||
|     g_CommandBuffer = VK_NULL_HANDLE; |  | ||||||
|     g_FrameIndex = (g_FrameIndex + 1) % IMGUI_VK_QUEUED_FRAMES; |     g_FrameIndex = (g_FrameIndex + 1) % IMGUI_VK_QUEUED_FRAMES; | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -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_Shutdown(); | ||||||
| IMGUI_API void        ImGui_ImplVulkan_NewFrame(); | IMGUI_API void        ImGui_ImplVulkan_NewFrame(); | ||||||
| IMGUI_API void        ImGui_ImplVulkan_Render(VkCommandBuffer command_buffer); | 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 | // Called by Init/NewFrame/Shutdown | ||||||
| IMGUI_API void        ImGui_ImplVulkan_InvalidateFontUploadObjects(); | IMGUI_API void        ImGui_ImplVulkan_InvalidateFontUploadObjects(); | ||||||
|   | |||||||
| @@ -34,18 +34,22 @@ static VkPipelineCache          g_PipelineCache = VK_NULL_HANDLE; | |||||||
| static VkDescriptorPool         g_DescriptorPool = VK_NULL_HANDLE; | static VkDescriptorPool         g_DescriptorPool = VK_NULL_HANDLE; | ||||||
|  |  | ||||||
| static int                      fb_width, fb_height; | 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 uint32_t                 g_BackBufferCount = 0; | ||||||
| static VkImage                  g_BackBuffer[IMGUI_MAX_POSSIBLE_BACK_BUFFERS] = {}; | static VkImage                  g_BackBuffer[IMGUI_MAX_POSSIBLE_BACK_BUFFERS] = {}; | ||||||
| static VkImageView              g_BackBufferView[IMGUI_MAX_POSSIBLE_BACK_BUFFERS] = {}; | static VkImageView              g_BackBufferView[IMGUI_MAX_POSSIBLE_BACK_BUFFERS] = {}; | ||||||
| static VkFramebuffer            g_Framebuffer[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 uint32_t                 g_FrameIndex = 0; | ||||||
| static VkCommandPool            g_CommandPool[IMGUI_VK_QUEUED_FRAMES]; | static FrameData                g_Frames[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 VkClearValue             g_ClearValue = {}; | static VkClearValue             g_ClearValue = {}; | ||||||
|  |  | ||||||
| @@ -295,6 +299,7 @@ static void setup_vulkan(SDL_Window* window, const char** extensions, uint32_t e | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |  | ||||||
|     // Get Surface Format |     // Get Surface Format | ||||||
|     { |     { | ||||||
|         const VkFormat requestSurfaceImageFormat[] = { VK_FORMAT_B8G8R8A8_UNORM, VK_FORMAT_R8G8B8A8_UNORM, VK_FORMAT_B8G8R8_UNORM, VK_FORMAT_R8G8B8_UNORM }; |         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 |     // Create Command Buffers | ||||||
|     for (int i = 0; i < IMGUI_VK_QUEUED_FRAMES; i++) |     for (int i = 0; i < IMGUI_VK_QUEUED_FRAMES; i++) | ||||||
|     { |     { | ||||||
|  |         FrameData* fd = &g_Frames[i]; | ||||||
|         { |         { | ||||||
|             VkCommandPoolCreateInfo info = {}; |             VkCommandPoolCreateInfo info = {}; | ||||||
|             info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; |             info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; | ||||||
|             info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; |             info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; | ||||||
|             info.queueFamilyIndex = g_QueueFamily; |             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); |             check_vk_result(err); | ||||||
|         } |         } | ||||||
|         { |         { | ||||||
|             VkCommandBufferAllocateInfo info = {}; |             VkCommandBufferAllocateInfo info = {}; | ||||||
|             info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_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.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; | ||||||
|             info.commandBufferCount = 1; |             info.commandBufferCount = 1; | ||||||
|             err = vkAllocateCommandBuffers(g_Device, &info, &g_CommandBuffer[i]); |             err = vkAllocateCommandBuffers(g_Device, &info, &fd->CommandBuffer); | ||||||
|             check_vk_result(err); |             check_vk_result(err); | ||||||
|         } |         } | ||||||
|         { |         { | ||||||
|             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(g_Device, &info, g_Allocator, &g_Fence[i]); |             err = vkCreateFence(g_Device, &info, g_Allocator, &fd->Fence); | ||||||
|             check_vk_result(err); |             check_vk_result(err); | ||||||
|         } |         } | ||||||
|         { |         { | ||||||
|             VkSemaphoreCreateInfo info = {}; |             VkSemaphoreCreateInfo info = {}; | ||||||
|             info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_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); |             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); |             check_vk_result(err); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     // Create Descriptor Pool |     // Create Descriptor Pool | ||||||
|     { |     { | ||||||
|         VkDescriptorPoolSize pool_size[11] = |         VkDescriptorPoolSize pool_sizes[] = | ||||||
|         { |         { | ||||||
|             { VK_DESCRIPTOR_TYPE_SAMPLER, 1000 }, |             { VK_DESCRIPTOR_TYPE_SAMPLER, 1000 }, | ||||||
|             { VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_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 = {}; |         VkDescriptorPoolCreateInfo pool_info = {}; | ||||||
|         pool_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; |         pool_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; | ||||||
|         pool_info.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT; |         pool_info.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT; | ||||||
|         pool_info.maxSets = 1000 * 11; |         pool_info.maxSets = 1000 * IM_ARRAYSIZE(pool_sizes); | ||||||
|         pool_info.poolSizeCount = 11; |         pool_info.poolSizeCount = (uint32_t)IM_ARRAYSIZE(pool_sizes); | ||||||
|         pool_info.pPoolSizes = pool_size; |         pool_info.pPoolSizes = pool_sizes; | ||||||
|         err = vkCreateDescriptorPool(g_Device, &pool_info, g_Allocator, &g_DescriptorPool); |         err = vkCreateDescriptorPool(g_Device, &pool_info, g_Allocator, &g_DescriptorPool); | ||||||
|         check_vk_result(err); |         check_vk_result(err); | ||||||
|     } |     } | ||||||
| @@ -413,11 +419,12 @@ static void cleanup_vulkan() | |||||||
|     vkDestroyDescriptorPool(g_Device, g_DescriptorPool, g_Allocator); |     vkDestroyDescriptorPool(g_Device, g_DescriptorPool, g_Allocator); | ||||||
|     for (int i = 0; i < IMGUI_VK_QUEUED_FRAMES; i++) |     for (int i = 0; i < IMGUI_VK_QUEUED_FRAMES; i++) | ||||||
|     { |     { | ||||||
|         vkDestroyFence(g_Device, g_Fence[i], g_Allocator); |         FrameData* fd = &g_Frames[i]; | ||||||
|         vkFreeCommandBuffers(g_Device, g_CommandPool[i], 1, &g_CommandBuffer[i]); |         vkDestroyFence(g_Device, fd->Fence, g_Allocator); | ||||||
|         vkDestroyCommandPool(g_Device, g_CommandPool[i], g_Allocator); |         vkFreeCommandBuffers(g_Device, fd->CommandPool, 1, &fd->CommandBuffer); | ||||||
|         vkDestroySemaphore(g_Device, g_PresentCompleteSemaphore[i], g_Allocator); |         vkDestroyCommandPool(g_Device, fd->CommandPool, g_Allocator); | ||||||
|         vkDestroySemaphore(g_Device, g_RenderCompleteSemaphore[i], 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++) |     for (uint32_t i = 0; i < g_BackBufferCount; i++) | ||||||
|     { |     { | ||||||
| @@ -440,61 +447,63 @@ static void cleanup_vulkan() | |||||||
|  |  | ||||||
| static void frame_begin() | static void frame_begin() | ||||||
| { | { | ||||||
|  |     FrameData* fd = &g_Frames[g_FrameIndex]; | ||||||
|     VkResult err; |     VkResult err; | ||||||
|     for (;;) |     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_SUCCESS) break; | ||||||
|         if (err == VK_TIMEOUT) continue; |         if (err == VK_TIMEOUT) continue; | ||||||
|         check_vk_result(err); |         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); |         check_vk_result(err); | ||||||
|     } |     } | ||||||
|     { |     { | ||||||
|         err = vkResetCommandPool(g_Device, g_CommandPool[g_FrameIndex], 0); |         err = vkResetCommandPool(g_Device, fd->CommandPool, 0); | ||||||
|         check_vk_result(err); |         check_vk_result(err); | ||||||
|         VkCommandBufferBeginInfo info = {}; |         VkCommandBufferBeginInfo info = {}; | ||||||
|         info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; |         info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; | ||||||
|         info.flags |= VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; |         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); |         check_vk_result(err); | ||||||
|     } |     } | ||||||
|     { |     { | ||||||
|         VkRenderPassBeginInfo info = {}; |         VkRenderPassBeginInfo info = {}; | ||||||
|         info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; |         info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; | ||||||
|         info.renderPass = g_RenderPass; |         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.width = fb_width; | ||||||
|         info.renderArea.extent.height = fb_height; |         info.renderArea.extent.height = fb_height; | ||||||
|         info.clearValueCount = 1; |         info.clearValueCount = 1; | ||||||
|         info.pClearValues = &g_ClearValue; |         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() | static void frame_end() | ||||||
| { | { | ||||||
|  |     FrameData* fd = &g_Frames[g_FrameIndex]; | ||||||
|     VkResult err; |     VkResult err; | ||||||
|     vkCmdEndRenderPass(g_CommandBuffer[g_FrameIndex]); |     vkCmdEndRenderPass(fd->CommandBuffer); | ||||||
|     { |     { | ||||||
|         VkPipelineStageFlags wait_stage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; |         VkPipelineStageFlags wait_stage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; | ||||||
|         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 = &g_PresentCompleteSemaphore[g_FrameIndex]; |         info.pWaitSemaphores = &fd->PresentCompleteSemaphore; | ||||||
|         info.pWaitDstStageMask = &wait_stage; |         info.pWaitDstStageMask = &wait_stage; | ||||||
|         info.commandBufferCount = 1; |         info.commandBufferCount = 1; | ||||||
|         info.pCommandBuffers = &g_CommandBuffer[g_FrameIndex]; |         info.pCommandBuffers = &fd->CommandBuffer; | ||||||
|         info.signalSemaphoreCount = 1; |         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); |         check_vk_result(err); | ||||||
|         err = vkResetFences(g_Device, 1, &g_Fence[g_FrameIndex]); |         err = vkResetFences(g_Device, 1, &fd->Fence); | ||||||
|         check_vk_result(err); |         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); |         check_vk_result(err); | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @@ -509,15 +518,14 @@ static void frame_present() | |||||||
|     uint32_t PresentIndex = g_FrameIndex; |     uint32_t PresentIndex = g_FrameIndex; | ||||||
| #endif // IMGUI_UNLIMITED_FRAME_RATE | #endif // IMGUI_UNLIMITED_FRAME_RATE | ||||||
|  |  | ||||||
|     VkSwapchainKHR swapchains[1] = { g_Swapchain }; |     FrameData* fd = &g_Frames[PresentIndex]; | ||||||
|     uint32_t indices[1] = { g_BackbufferIndices[PresentIndex] }; |  | ||||||
|     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 = &g_RenderCompleteSemaphore[PresentIndex]; |     info.pWaitSemaphores = &fd->RenderCompleteSemaphore; | ||||||
|     info.swapchainCount = 1; |     info.swapchainCount = 1; | ||||||
|     info.pSwapchains = swapchains; |     info.pSwapchains = &g_Swapchain; | ||||||
|     info.pImageIndices = indices; |     info.pImageIndices = &fd->BackbufferIndex; | ||||||
|     err = vkQueuePresentKHR(g_Queue, &info); |     err = vkQueuePresentKHR(g_Queue, &info); | ||||||
|     check_vk_result(err); |     check_vk_result(err); | ||||||
|  |  | ||||||
| @@ -584,22 +592,26 @@ int main(int, char**) | |||||||
|  |  | ||||||
|     // Upload Fonts |     // Upload Fonts | ||||||
|     { |     { | ||||||
|  |         // Use any command queue | ||||||
|  |         VkCommandPool command_pool = g_Frames[g_FrameIndex].CommandPool; | ||||||
|  |         VkCommandBuffer command_buffer = g_Frames[g_FrameIndex].CommandBuffer; | ||||||
|  |  | ||||||
|         VkResult err; |         VkResult err; | ||||||
|         err = vkResetCommandPool(g_Device, g_CommandPool[g_FrameIndex], 0); |         err = vkResetCommandPool(g_Device, command_pool, 0); | ||||||
|         check_vk_result(err); |         check_vk_result(err); | ||||||
|         VkCommandBufferBeginInfo begin_info = {}; |         VkCommandBufferBeginInfo begin_info = {}; | ||||||
|         begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; |         begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; | ||||||
|         begin_info.flags |= VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; |         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); |         check_vk_result(err); | ||||||
|  |  | ||||||
|         ImGui_ImplVulkan_CreateFontsTexture(g_CommandBuffer[g_FrameIndex]); |         ImGui_ImplVulkan_CreateFontsTexture(command_buffer); | ||||||
|  |  | ||||||
|         VkSubmitInfo end_info = {}; |         VkSubmitInfo end_info = {}; | ||||||
|         end_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; |         end_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; | ||||||
|         end_info.commandBufferCount = 1; |         end_info.commandBufferCount = 1; | ||||||
|         end_info.pCommandBuffers = &g_CommandBuffer[g_FrameIndex]; |         end_info.pCommandBuffers = &command_buffer; | ||||||
|         err = vkEndCommandBuffer(g_CommandBuffer[g_FrameIndex]); |         err = vkEndCommandBuffer(command_buffer); | ||||||
|         check_vk_result(err); |         check_vk_result(err); | ||||||
|         err = vkQueueSubmit(g_Queue, 1, &end_info, VK_NULL_HANDLE); |         err = vkQueueSubmit(g_Queue, 1, &end_info, VK_NULL_HANDLE); | ||||||
|         check_vk_result(err); |         check_vk_result(err); | ||||||
| @@ -620,7 +632,7 @@ int main(int, char**) | |||||||
|     ImGui_ImplVulkan_NewFrame(); |     ImGui_ImplVulkan_NewFrame(); | ||||||
|     ImGui_ImplSDL2_NewFrame(window); |     ImGui_ImplSDL2_NewFrame(window); | ||||||
|     frame_begin(); |     frame_begin(); | ||||||
|     ImGui_ImplVulkan_Render(g_CommandBuffer[g_FrameIndex]); |     ImGui_ImplVulkan_Render(g_Frames[g_FrameIndex].CommandBuffer); | ||||||
|     frame_end(); |     frame_end(); | ||||||
|     g_FrameIndex = (g_FrameIndex + 1) % IMGUI_VK_QUEUED_FRAMES; |     g_FrameIndex = (g_FrameIndex + 1) % IMGUI_VK_QUEUED_FRAMES; | ||||||
| #endif // IMGUI_UNLIMITED_FRAME_RATE | #endif // IMGUI_UNLIMITED_FRAME_RATE | ||||||
| @@ -685,7 +697,7 @@ int main(int, char**) | |||||||
|         // Rendering |         // Rendering | ||||||
|         memcpy(&g_ClearValue.color.float32[0], &clear_color, 4 * sizeof(float)); |         memcpy(&g_ClearValue.color.float32[0], &clear_color, 4 * sizeof(float)); | ||||||
|         frame_begin(); |         frame_begin(); | ||||||
|         ImGui_ImplVulkan_Render(g_CommandBuffer[g_FrameIndex]); |         ImGui_ImplVulkan_Render(g_Frames[g_FrameIndex].CommandBuffer); | ||||||
|         frame_end(); |         frame_end(); | ||||||
|         frame_present(); |         frame_present(); | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -37,18 +37,22 @@ static VkPipelineCache          g_PipelineCache = VK_NULL_HANDLE; | |||||||
| static VkDescriptorPool         g_DescriptorPool = VK_NULL_HANDLE; | static VkDescriptorPool         g_DescriptorPool = VK_NULL_HANDLE; | ||||||
|  |  | ||||||
| static int                      fb_width, fb_height; | 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 uint32_t                 g_BackBufferCount = 0; | ||||||
| static VkImage                  g_BackBuffer[IMGUI_MAX_POSSIBLE_BACK_BUFFERS] = {}; | static VkImage                  g_BackBuffer[IMGUI_MAX_POSSIBLE_BACK_BUFFERS] = {}; | ||||||
| static VkImageView              g_BackBufferView[IMGUI_MAX_POSSIBLE_BACK_BUFFERS] = {}; | static VkImageView              g_BackBufferView[IMGUI_MAX_POSSIBLE_BACK_BUFFERS] = {}; | ||||||
| static VkFramebuffer            g_Framebuffer[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 uint32_t                 g_FrameIndex = 0; | ||||||
| static VkCommandPool            g_CommandPool[IMGUI_VK_QUEUED_FRAMES]; | static FrameData                g_Frames[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 VkClearValue             g_ClearValue = {}; | static VkClearValue             g_ClearValue = {}; | ||||||
|  |  | ||||||
| @@ -353,43 +357,44 @@ static void setup_vulkan(GLFWwindow* window, const char** extensions, uint32_t e | |||||||
|     // Create Command Buffers |     // Create Command Buffers | ||||||
|     for (int i = 0; i < IMGUI_VK_QUEUED_FRAMES; i++) |     for (int i = 0; i < IMGUI_VK_QUEUED_FRAMES; i++) | ||||||
|     { |     { | ||||||
|  |         FrameData* fd = &g_Frames[i]; | ||||||
|         { |         { | ||||||
|             VkCommandPoolCreateInfo info = {}; |             VkCommandPoolCreateInfo info = {}; | ||||||
|             info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; |             info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; | ||||||
|             info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; |             info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; | ||||||
|             info.queueFamilyIndex = g_QueueFamily; |             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); |             check_vk_result(err); | ||||||
|         } |         } | ||||||
|         { |         { | ||||||
|             VkCommandBufferAllocateInfo info = {}; |             VkCommandBufferAllocateInfo info = {}; | ||||||
|             info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_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.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; | ||||||
|             info.commandBufferCount = 1; |             info.commandBufferCount = 1; | ||||||
|             err = vkAllocateCommandBuffers(g_Device, &info, &g_CommandBuffer[i]); |             err = vkAllocateCommandBuffers(g_Device, &info, &fd->CommandBuffer); | ||||||
|             check_vk_result(err); |             check_vk_result(err); | ||||||
|         } |         } | ||||||
|         { |         { | ||||||
|             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(g_Device, &info, g_Allocator, &g_Fence[i]); |             err = vkCreateFence(g_Device, &info, g_Allocator, &fd->Fence); | ||||||
|             check_vk_result(err); |             check_vk_result(err); | ||||||
|         } |         } | ||||||
|         { |         { | ||||||
|             VkSemaphoreCreateInfo info = {}; |             VkSemaphoreCreateInfo info = {}; | ||||||
|             info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_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); |             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); |             check_vk_result(err); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     // Create Descriptor Pool |     // Create Descriptor Pool | ||||||
|     { |     { | ||||||
|         VkDescriptorPoolSize pool_size[11] = |         VkDescriptorPoolSize pool_sizes[] = | ||||||
|         { |         { | ||||||
|             { VK_DESCRIPTOR_TYPE_SAMPLER, 1000 }, |             { VK_DESCRIPTOR_TYPE_SAMPLER, 1000 }, | ||||||
|             { VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_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 = {}; |         VkDescriptorPoolCreateInfo pool_info = {}; | ||||||
|         pool_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; |         pool_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; | ||||||
|         pool_info.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT; |         pool_info.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT; | ||||||
|         pool_info.maxSets = 1000 * 11; |         pool_info.maxSets = 1000 * IM_ARRAYSIZE(pool_sizes); | ||||||
|         pool_info.poolSizeCount = 11; |         pool_info.poolSizeCount = (uint32_t)IM_ARRAYSIZE(pool_sizes); | ||||||
|         pool_info.pPoolSizes = pool_size; |         pool_info.pPoolSizes = pool_sizes; | ||||||
|         err = vkCreateDescriptorPool(g_Device, &pool_info, g_Allocator, &g_DescriptorPool); |         err = vkCreateDescriptorPool(g_Device, &pool_info, g_Allocator, &g_DescriptorPool); | ||||||
|         check_vk_result(err); |         check_vk_result(err); | ||||||
|     } |     } | ||||||
| @@ -419,11 +424,12 @@ static void cleanup_vulkan() | |||||||
|     vkDestroyDescriptorPool(g_Device, g_DescriptorPool, g_Allocator); |     vkDestroyDescriptorPool(g_Device, g_DescriptorPool, g_Allocator); | ||||||
|     for (int i = 0; i < IMGUI_VK_QUEUED_FRAMES; i++) |     for (int i = 0; i < IMGUI_VK_QUEUED_FRAMES; i++) | ||||||
|     { |     { | ||||||
|         vkDestroyFence(g_Device, g_Fence[i], g_Allocator); |         FrameData* fd = &g_Frames[i]; | ||||||
|         vkFreeCommandBuffers(g_Device, g_CommandPool[i], 1, &g_CommandBuffer[i]); |         vkDestroyFence(g_Device, fd->Fence, g_Allocator); | ||||||
|         vkDestroyCommandPool(g_Device, g_CommandPool[i], g_Allocator); |         vkFreeCommandBuffers(g_Device, fd->CommandPool, 1, &fd->CommandBuffer); | ||||||
|         vkDestroySemaphore(g_Device, g_PresentCompleteSemaphore[i], g_Allocator); |         vkDestroyCommandPool(g_Device, fd->CommandPool, g_Allocator); | ||||||
|         vkDestroySemaphore(g_Device, g_RenderCompleteSemaphore[i], 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++) |     for (uint32_t i = 0; i < g_BackBufferCount; i++) | ||||||
|     { |     { | ||||||
| @@ -446,61 +452,63 @@ static void cleanup_vulkan() | |||||||
|  |  | ||||||
| static void frame_begin() | static void frame_begin() | ||||||
| { | { | ||||||
|  |     FrameData* fd = &g_Frames[g_FrameIndex]; | ||||||
|     VkResult err; |     VkResult err; | ||||||
|     for (;;) |     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_SUCCESS) break; | ||||||
|         if (err == VK_TIMEOUT) continue; |         if (err == VK_TIMEOUT) continue; | ||||||
|         check_vk_result(err); |         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); |         check_vk_result(err); | ||||||
|     } |     } | ||||||
|     { |     { | ||||||
|         err = vkResetCommandPool(g_Device, g_CommandPool[g_FrameIndex], 0); |         err = vkResetCommandPool(g_Device, fd->CommandPool, 0); | ||||||
|         check_vk_result(err); |         check_vk_result(err); | ||||||
|         VkCommandBufferBeginInfo info = {}; |         VkCommandBufferBeginInfo info = {}; | ||||||
|         info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; |         info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; | ||||||
|         info.flags |= VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; |         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); |         check_vk_result(err); | ||||||
|     } |     } | ||||||
|     { |     { | ||||||
|         VkRenderPassBeginInfo info = {}; |         VkRenderPassBeginInfo info = {}; | ||||||
|         info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; |         info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; | ||||||
|         info.renderPass = g_RenderPass; |         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.width = fb_width; | ||||||
|         info.renderArea.extent.height = fb_height; |         info.renderArea.extent.height = fb_height; | ||||||
|         info.clearValueCount = 1; |         info.clearValueCount = 1; | ||||||
|         info.pClearValues = &g_ClearValue; |         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() | static void frame_end() | ||||||
| { | { | ||||||
|  |     FrameData* fd = &g_Frames[g_FrameIndex]; | ||||||
|     VkResult err; |     VkResult err; | ||||||
|     vkCmdEndRenderPass(g_CommandBuffer[g_FrameIndex]); |     vkCmdEndRenderPass(fd->CommandBuffer); | ||||||
|     { |     { | ||||||
|         VkPipelineStageFlags wait_stage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; |         VkPipelineStageFlags wait_stage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; | ||||||
|         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 = &g_PresentCompleteSemaphore[g_FrameIndex]; |         info.pWaitSemaphores = &fd->PresentCompleteSemaphore; | ||||||
|         info.pWaitDstStageMask = &wait_stage; |         info.pWaitDstStageMask = &wait_stage; | ||||||
|         info.commandBufferCount = 1; |         info.commandBufferCount = 1; | ||||||
|         info.pCommandBuffers = &g_CommandBuffer[g_FrameIndex]; |         info.pCommandBuffers = &fd->CommandBuffer; | ||||||
|         info.signalSemaphoreCount = 1; |         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); |         check_vk_result(err); | ||||||
|         err = vkResetFences(g_Device, 1, &g_Fence[g_FrameIndex]); |         err = vkResetFences(g_Device, 1, &fd->Fence); | ||||||
|         check_vk_result(err); |         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); |         check_vk_result(err); | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @@ -515,15 +523,14 @@ static void frame_present() | |||||||
|     uint32_t PresentIndex = g_FrameIndex; |     uint32_t PresentIndex = g_FrameIndex; | ||||||
| #endif // IMGUI_UNLIMITED_FRAME_RATE | #endif // IMGUI_UNLIMITED_FRAME_RATE | ||||||
|  |  | ||||||
|     VkSwapchainKHR swapchains[1] = { g_Swapchain }; |     FrameData* fd = &g_Frames[PresentIndex]; | ||||||
|     uint32_t indices[1] = { g_BackbufferIndices[PresentIndex] }; |  | ||||||
|     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 = &g_RenderCompleteSemaphore[PresentIndex]; |     info.pWaitSemaphores = &fd->RenderCompleteSemaphore; | ||||||
|     info.swapchainCount = 1; |     info.swapchainCount = 1; | ||||||
|     info.pSwapchains = swapchains; |     info.pSwapchains = &g_Swapchain; | ||||||
|     info.pImageIndices = indices; |     info.pImageIndices = &fd->BackbufferIndex; | ||||||
|     err = vkQueuePresentKHR(g_Queue, &info); |     err = vkQueuePresentKHR(g_Queue, &info); | ||||||
|     check_vk_result(err); |     check_vk_result(err); | ||||||
|  |  | ||||||
| @@ -595,22 +602,26 @@ int main(int, char**) | |||||||
|  |  | ||||||
|     // Upload Fonts |     // Upload Fonts | ||||||
|     { |     { | ||||||
|  |         // Use any command queue | ||||||
|  |         VkCommandPool command_pool = g_Frames[g_FrameIndex].CommandPool; | ||||||
|  |         VkCommandBuffer command_buffer = g_Frames[g_FrameIndex].CommandBuffer; | ||||||
|  |  | ||||||
|         VkResult err; |         VkResult err; | ||||||
|         err = vkResetCommandPool(g_Device, g_CommandPool[g_FrameIndex], 0); |         err = vkResetCommandPool(g_Device, command_pool, 0); | ||||||
|         check_vk_result(err); |         check_vk_result(err); | ||||||
|         VkCommandBufferBeginInfo begin_info = {}; |         VkCommandBufferBeginInfo begin_info = {}; | ||||||
|         begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; |         begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; | ||||||
|         begin_info.flags |= VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; |         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); |         check_vk_result(err); | ||||||
|  |  | ||||||
|         ImGui_ImplVulkan_CreateFontsTexture(g_CommandBuffer[g_FrameIndex]); |         ImGui_ImplVulkan_CreateFontsTexture(command_buffer); | ||||||
|  |  | ||||||
|         VkSubmitInfo end_info = {}; |         VkSubmitInfo end_info = {}; | ||||||
|         end_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; |         end_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; | ||||||
|         end_info.commandBufferCount = 1; |         end_info.commandBufferCount = 1; | ||||||
|         end_info.pCommandBuffers = &g_CommandBuffer[g_FrameIndex]; |         end_info.pCommandBuffers = &command_buffer; | ||||||
|         err = vkEndCommandBuffer(g_CommandBuffer[g_FrameIndex]); |         err = vkEndCommandBuffer(command_buffer); | ||||||
|         check_vk_result(err); |         check_vk_result(err); | ||||||
|         err = vkQueueSubmit(g_Queue, 1, &end_info, VK_NULL_HANDLE); |         err = vkQueueSubmit(g_Queue, 1, &end_info, VK_NULL_HANDLE); | ||||||
|         check_vk_result(err); |         check_vk_result(err); | ||||||
| @@ -631,7 +642,7 @@ int main(int, char**) | |||||||
|     ImGui_ImplVulkan_NewFrame(); |     ImGui_ImplVulkan_NewFrame(); | ||||||
|     ImGui_ImplGlfw_NewFrame(); |     ImGui_ImplGlfw_NewFrame(); | ||||||
|     frame_begin(); |     frame_begin(); | ||||||
|     ImGui_ImplVulkan_Render(g_CommandBuffer[g_FrameIndex]); |     ImGui_ImplVulkan_Render(g_Frames[g_FrameIndex].CommandBuffer); | ||||||
|     frame_end(); |     frame_end(); | ||||||
|     g_FrameIndex = (g_FrameIndex + 1) % IMGUI_VK_QUEUED_FRAMES; |     g_FrameIndex = (g_FrameIndex + 1) % IMGUI_VK_QUEUED_FRAMES; | ||||||
| #endif // IMGUI_UNLIMITED_FRAME_RATE | #endif // IMGUI_UNLIMITED_FRAME_RATE | ||||||
| @@ -687,7 +698,7 @@ int main(int, char**) | |||||||
|         // Rendering |         // Rendering | ||||||
|         memcpy(&g_ClearValue.color.float32[0], &clear_color, 4 * sizeof(float)); |         memcpy(&g_ClearValue.color.float32[0], &clear_color, 4 * sizeof(float)); | ||||||
|         frame_begin(); |         frame_begin(); | ||||||
|         ImGui_ImplVulkan_Render(g_CommandBuffer[g_FrameIndex]); |         ImGui_ImplVulkan_Render(g_Frames[g_FrameIndex].CommandBuffer); | ||||||
|         frame_end(); |         frame_end(); | ||||||
|         frame_present(); |         frame_present(); | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user