diff options
| author | Jonathan Bradley <jcb@pikum.xyz> | 2025-06-10 11:23:44 -0400 |
|---|---|---|
| committer | Jonathan Bradley <jcb@pikum.xyz> | 2025-06-10 11:23:44 -0400 |
| commit | 2506c1af519ed14836986ecf2674636fa8b37947 (patch) | |
| tree | ed9270b9160582ef8fd1a7f0cb01e30921655e6f /src | |
| parent | 11454fb99a9dc1c959e58828f447d1fb2e9f3d9d (diff) | |
pke: vulkan dynamic rendering + update imgui
Diffstat (limited to 'src')
| -rw-r--r-- | src/window.cpp | 795 |
1 files changed, 397 insertions, 398 deletions
diff --git a/src/window.cpp b/src/window.cpp index dd871f6..4cab2b4 100644 --- a/src/window.cpp +++ b/src/window.cpp @@ -96,7 +96,6 @@ struct PKVK_Present { VkDescriptorSetLayout descriptor_set_layout; VkPipelineLayout pipeline_layout; VkPipeline pipeline; - VkRenderPass render_pass; VkDescriptorPool descriptor_pool; VkDescriptorSet *descriptor_sets; VkCommandBuffer *command_buffers; @@ -105,7 +104,6 @@ struct PKVK_Present { VkFence *fences_in_flight; VkImage *images; VkImageView *image_views; - VkFramebuffer *framebuffers; } pkvk_present; // TODO consider creating a depth pre-pass @@ -120,8 +118,6 @@ VkImageView *depthImageViews = nullptr; VkDeviceMemory depthImagesMemory; struct PKVK_3D { - VkRenderPass render_pass; - VkFramebuffer *framebuffers = nullptr; VkDeviceMemory images_memory; VkImageView *image_views = nullptr; VkImage *render_images = nullptr; @@ -131,8 +127,6 @@ struct PKVK_3D { } pkvk_3d; struct PKVK_2D { - VkRenderPass render_pass; - VkFramebuffer *framebuffers = nullptr; VkImage *images = nullptr; VkImageView *image_views = nullptr; VkDeviceMemory images_memory; @@ -197,6 +191,13 @@ static VKAPI_ATTR VkBool32 VKAPI_CALL DebugReport(VkDebugReportFlagsEXT flags, V return VK_FALSE; } +// 2025-06-10 TODO this should be called in more places or not called at all. +// It's possible we won't ever actually need to use this call if we never +// target a device that doesn't support depth+stencil (e.g. older android). +bool pkvk_is_depth_only_format(VkFormat format) { + return format == VK_FORMAT_D16_UNORM || format == VK_FORMAT_D32_SFLOAT; +} + unsigned int FindMemoryTypeIndex(uint32_t typeFilter, VkMemoryPropertyFlags memPropertyFlags) { for (uint32_t i = 0; i < vkPhysicalDeviceMemoryProperties.memoryTypeCount; i++) { if ((typeFilter & (1 << i)) && (vkPhysicalDeviceMemoryProperties.memoryTypes[i].propertyFlags & memPropertyFlags) == memPropertyFlags) { @@ -989,7 +990,6 @@ void InitVulkan() { VkDeviceCreateInfo vkDeviceCreateInfo; vkDeviceCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; - vkDeviceCreateInfo.pNext = nullptr; vkDeviceCreateInfo.flags = 0; vkDeviceCreateInfo.queueCreateInfoCount = 2; vkDeviceCreateInfo.pQueueCreateInfos = deviceQueueCreateInfos; @@ -1001,6 +1001,12 @@ void InitVulkan() { vkDeviceCreateInfo.ppEnabledExtensionNames = REQUIRED_EXTENSIONS.data(); vkDeviceCreateInfo.pEnabledFeatures = &requestedFeatures; + VkPhysicalDeviceDynamicRenderingFeatures dynamicRenderingFeatures{}; + vkDeviceCreateInfo.pNext = &dynamicRenderingFeatures; + dynamicRenderingFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DYNAMIC_RENDERING_FEATURES; + dynamicRenderingFeatures.pNext = NULL; + dynamicRenderingFeatures.dynamicRendering = VK_TRUE; + vkResult = vkCreateDevice(vkPhysicalDevice, &vkDeviceCreateInfo, vkAllocator, &vkDevice); if (vkResult != VK_SUCCESS) { printf("Failed to create VkInstance! : %d\n", vkResult); @@ -1018,9 +1024,9 @@ void InitVulkan() { // surface formats { const VkFormat acceptableDepthFormats[3] = { - VK_FORMAT_D32_SFLOAT, VK_FORMAT_D32_SFLOAT_S8_UINT, VK_FORMAT_D24_UNORM_S8_UINT, + VK_FORMAT_D32_SFLOAT, }; depthFormat = FindSupportedFormat(3, acceptableDepthFormats, VK_IMAGE_TILING_OPTIMAL, VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT); } @@ -1326,7 +1332,7 @@ void CreateSwapchain() { renderTargetImageCI.format = depthFormat; renderTargetImageCI.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; vkImageViewCreateInfo.format = depthFormat; - vkImageViewCreateInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; + vkImageViewCreateInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT; // depth images depthImages = pk_new<VkImage>(swapchainLength, MemBkt_Vulkan); @@ -1403,151 +1409,6 @@ void UpdateCamera() { ActiveCamera->stale = PkeCameraStaleFlags{0}; } -void CreateRenderPass() { - /* 2025-01-29 JCB - * I refactored this so that VkAttachmentDescription was an array and that - * wasn't totally necessary. It does have the advantage of 1:1-ing with the - * VkAttachmentReference, but it means you have to just know what each index - * is. Here's a legend since the code is no longer self-documenting. - * 0: render target (fragment) - * 1: color resolve (multisampling) - * 2: depth - * See also: CreateFramebuffers(): the same ordering can be observed. - */ - VkAttachmentDescription attachment_descriptions[3]; - memset(attachment_descriptions, 0, sizeof(VkAttachmentDescription) * 3); - VkAttachmentReference attachment_refs[3]; - memset(attachment_refs, 0, sizeof(VkAttachmentReference) * 3); - VkSubpassDependency subpass_dependencies[2]; - memset(subpass_dependencies, 0, sizeof(VkSubpassDependency) * 2); - - for (long i = 0; i < 3; ++i) { - attachment_refs[i].attachment = i; - } - for (long i = 0; i < 2; ++i) { - subpass_dependencies[i].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT; - } - - // color (fragment) - attachment_descriptions[0].flags = {}; - attachment_descriptions[0].format = vkSurfaceFormatKHR.format; - attachment_descriptions[0].samples = VK_SAMPLE_COUNT_1_BIT; - attachment_descriptions[0].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; - attachment_descriptions[0].storeOp = VK_ATTACHMENT_STORE_OP_STORE; - attachment_descriptions[0].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - attachment_descriptions[0].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - attachment_descriptions[0].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - attachment_descriptions[0].finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; - - // color (fragment) - attachment_refs[0].layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - - VkSubpassDescription subpass; - subpass.flags = {}; - subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; - subpass.inputAttachmentCount = 0; - subpass.pInputAttachments = nullptr; - subpass.colorAttachmentCount = 1; - subpass.pColorAttachments = &attachment_refs[0]; - subpass.pResolveAttachments = nullptr; - subpass.pDepthStencilAttachment = nullptr; - subpass.preserveAttachmentCount = 0; - subpass.pPreserveAttachments = nullptr; - - subpass_dependencies[0].srcSubpass = VK_SUBPASS_EXTERNAL; - subpass_dependencies[0].dstSubpass = 0U; - subpass_dependencies[0].srcStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; - subpass_dependencies[0].dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - subpass_dependencies[0].srcAccessMask = VK_ACCESS_MEMORY_READ_BIT; - subpass_dependencies[0].dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - - subpass_dependencies[1].srcSubpass = 0U; - subpass_dependencies[1].dstSubpass = VK_SUBPASS_EXTERNAL; - subpass_dependencies[1].srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - subpass_dependencies[1].dstStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; - subpass_dependencies[1].srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - subpass_dependencies[1].dstAccessMask = VK_ACCESS_MEMORY_READ_BIT; - - VkRenderPassCreateInfo renderPassInfo; - renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; - renderPassInfo.pNext = nullptr; - renderPassInfo.flags = {}; - renderPassInfo.attachmentCount = 1; - renderPassInfo.pAttachments = &attachment_descriptions[0]; - renderPassInfo.subpassCount = 1; - renderPassInfo.pSubpasses = &subpass; - renderPassInfo.dependencyCount = 2; - renderPassInfo.pDependencies = subpass_dependencies; - - if (vkCreateRenderPass(vkDevice, &renderPassInfo, vkAllocator, &pkvk_present.render_pass) != VK_SUCCESS) { - throw "failed to create present render pass!"; - } - - // color resolve - attachment_refs[1].layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - subpass.pResolveAttachments = &attachment_refs[1]; - - // color - attachment_descriptions[0].samples = global_sample_count; - attachment_descriptions[0].finalLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - // color resolve - attachment_descriptions[1] = attachment_descriptions[0]; - attachment_descriptions[1].samples = VK_SAMPLE_COUNT_1_BIT; - attachment_descriptions[1].loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - attachment_descriptions[1].storeOp = VK_ATTACHMENT_STORE_OP_STORE; - attachment_descriptions[1].finalLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - - subpass_dependencies[0].srcStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; - subpass_dependencies[0].dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - subpass_dependencies[0].srcAccessMask = VK_ACCESS_SHADER_READ_BIT; - subpass_dependencies[0].dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - - subpass_dependencies[1].srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - subpass_dependencies[1].dstStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; - subpass_dependencies[1].srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - subpass_dependencies[1].dstAccessMask = VK_ACCESS_SHADER_READ_BIT; - - renderPassInfo.attachmentCount = 2; - - if (vkCreateRenderPass(vkDevice, &renderPassInfo, vkAllocator, &pkvk_2d.render_pass) != VK_SUCCESS) { - throw "failed to create 2d render pass!"; - } - - // color - attachment_descriptions[0].samples = global_sample_count; - attachment_descriptions[0].finalLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - // depth - attachment_descriptions[2] = attachment_descriptions[0]; - attachment_descriptions[2].format = depthFormat; - attachment_descriptions[2].samples = global_sample_count; - attachment_descriptions[2].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; - attachment_descriptions[2].storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - attachment_descriptions[2].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - attachment_descriptions[2].stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE; - attachment_descriptions[2].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - attachment_descriptions[2].finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; - - // depth - attachment_refs[2].layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; - subpass.pDepthStencilAttachment = &attachment_refs[2]; - - subpass_dependencies[0].srcStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; - subpass_dependencies[0].dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - subpass_dependencies[0].srcAccessMask = VK_ACCESS_SHADER_READ_BIT; - subpass_dependencies[0].dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - - subpass_dependencies[1].srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - subpass_dependencies[1].dstStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; - subpass_dependencies[1].srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - subpass_dependencies[1].dstAccessMask = VK_ACCESS_SHADER_READ_BIT; - - renderPassInfo.attachmentCount = 3; - - if (vkCreateRenderPass(vkDevice, &renderPassInfo, vkAllocator, &pkvk_3d.render_pass) != VK_SUCCESS) { - throw "failed to create 3d render pass!"; - } -} - void CreatePresentDescriptorSetLayout() { VkDescriptorSetLayoutBinding imageSamplerLayoutBinding; imageSamplerLayoutBinding.binding = 0; @@ -1759,7 +1620,6 @@ void CreatePresentPipeline() { VkGraphicsPipelineCreateInfo pipelineInfo; pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; - pipelineInfo.pNext = nullptr; pipelineInfo.flags = {}; pipelineInfo.stageCount = 2; pipelineInfo.pStages = shaderStages; @@ -1775,11 +1635,19 @@ void CreatePresentPipeline() { pipelineInfo.pDynamicState = &dynamicState; pipelineInfo.layout = pkvk_present.pipeline_layout; - pipelineInfo.renderPass = pkvk_present.render_pass; + pipelineInfo.renderPass = VK_NULL_HANDLE; // dynamic rendering pipelineInfo.subpass = 0; pipelineInfo.basePipelineHandle = VK_NULL_HANDLE; pipelineInfo.basePipelineIndex = {}; + VkPipelineRenderingCreateInfo renderingInfo{}; + pipelineInfo.pNext = &renderingInfo; + renderingInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO; + renderingInfo.colorAttachmentCount = 1; + + VkFormat color_format = vkSurfaceFormatKHR.format; + renderingInfo.pColorAttachmentFormats = &color_format; + /* 2023-12-22 JCB * This happens just before needed because we want to let this * thread run while background threads load the assets. @@ -1798,66 +1666,6 @@ void CreatePresentPipeline() { vkDestroyShaderModule(vkDevice, vertShader, vkAllocator); } -void CreateFramebuffers() { - assert(pkvk_present.framebuffers == nullptr || pkvk_present.framebuffers == CAFE_BABE(VkFramebuffer)); - assert(pkvk_3d.framebuffers == nullptr || pkvk_3d.framebuffers == CAFE_BABE(VkFramebuffer)); - assert(pkvk_2d.framebuffers == nullptr || pkvk_2d.framebuffers == CAFE_BABE(VkFramebuffer)); - pkvk_present.framebuffers = pk_new<VkFramebuffer>(swapchainLength, MemBkt_Vulkan); - pkvk_3d.framebuffers = pk_new<VkFramebuffer>(swapchainLength, MemBkt_Vulkan); - pkvk_2d.framebuffers = pk_new<VkFramebuffer>(swapchainLength, MemBkt_Vulkan); - - VkFramebufferCreateInfo framebufferInfo; - framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; - framebufferInfo.pNext = nullptr; - framebufferInfo.flags = {}; - framebufferInfo.renderPass = pkvk_present.render_pass; - framebufferInfo.attachmentCount = 1; - framebufferInfo.pAttachments = nullptr; - framebufferInfo.width = Extent.width; - framebufferInfo.height = Extent.height; - framebufferInfo.layers = 1; - - for (long i = 0; i < swapchainLength; ++i) { - VkImageView attachments[] = { - pkvk_present.image_views[i] - }; - framebufferInfo.pAttachments = attachments; - auto result = vkCreateFramebuffer(vkDevice, &framebufferInfo, vkAllocator, &pkvk_present.framebuffers[i]); - if (result != VK_SUCCESS) { - throw "failed to create present framebuffer"; - } - } - - framebufferInfo.attachmentCount = 2; - framebufferInfo.renderPass = pkvk_2d.render_pass; - for (long i = 0; i < swapchainLength; ++i) { - VkImageView attachments[] = { - pkvk_2d.image_views[i], - pkvk_2d.image_views_color_resolve[i], - }; - framebufferInfo.pAttachments = attachments; - auto result = vkCreateFramebuffer(vkDevice, &framebufferInfo, vkAllocator, &pkvk_2d.framebuffers[i]); - if (result != VK_SUCCESS) { - throw "failed to create 2d overlay framebuffer"; - } - } - - framebufferInfo.attachmentCount = 3; - framebufferInfo.renderPass = pkvk_3d.render_pass; - for (long i = 0; i < swapchainLength; ++i) { - VkImageView attachments[] = { - pkvk_3d.image_views[i], - pkvk_3d.image_views_color_resolve[i], - depthImageViews[i], - }; - framebufferInfo.pAttachments = attachments; - auto result = vkCreateFramebuffer(vkDevice, &framebufferInfo, vkAllocator, &pkvk_3d.framebuffers[i]); - if (result != VK_SUCCESS) { - throw "failed to create render framebuffer"; - } - } -} - void CreateCommandPool() { VkCommandPoolCreateInfo poolInfo; poolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; @@ -2500,10 +2308,10 @@ void CreateGraphicsPipelines() { vkGraphicsPipelineCreateInfo[2].layout = pkePipelines.pipe_layouts.named.txtr; vkGraphicsPipelineCreateInfo[3].layout = pkePipelines.pipe_layouts.named.base; - vkGraphicsPipelineCreateInfo[0].renderPass = pkvk_3d.render_pass; - vkGraphicsPipelineCreateInfo[1].renderPass = pkvk_3d.render_pass; - vkGraphicsPipelineCreateInfo[2].renderPass = pkvk_2d.render_pass; - vkGraphicsPipelineCreateInfo[3].renderPass = pkvk_2d.render_pass; + vkGraphicsPipelineCreateInfo[0].renderPass = VK_NULL_HANDLE; // dynamic rendering + vkGraphicsPipelineCreateInfo[1].renderPass = VK_NULL_HANDLE; // dynamic rendering + vkGraphicsPipelineCreateInfo[2].renderPass = VK_NULL_HANDLE; // dynamic rendering + vkGraphicsPipelineCreateInfo[3].renderPass = VK_NULL_HANDLE; // dynamic rendering vkGraphicsPipelineCreateInfo[0].pVertexInputState = &vkPipelineVertexInputStateCreateInfo_txtr; vkGraphicsPipelineCreateInfo[1].pVertexInputState = &vkPipelineVertexInputStateCreateInfo_txtr; @@ -2528,12 +2336,34 @@ void CreateGraphicsPipelines() { vkPipelineShaderStageCreateInfo_ui_base[0].module = UploadShader(asset_handle_vert_ui_base); vkPipelineShaderStageCreateInfo_ui_base[1].module = UploadShader(asset_handle_frag_ui_base); + VkPipelineRenderingCreateInfo renderingInfo{}; + vkGraphicsPipelineCreateInfo[0].pNext = &renderingInfo; + vkGraphicsPipelineCreateInfo[1].pNext = &renderingInfo; + vkGraphicsPipelineCreateInfo[2].pNext = &renderingInfo; + vkGraphicsPipelineCreateInfo[3].pNext = &renderingInfo; + renderingInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO; + + std::array<VkFormat, 3> color_formats; + color_formats.at(0) = vkSurfaceFormatKHR.format; + color_formats.at(1) = depthFormat; + color_formats.at(2) = depthFormat; + renderingInfo.colorAttachmentCount = 1; + renderingInfo.pColorAttachmentFormats = color_formats.data(); + renderingInfo.depthAttachmentFormat = color_formats.at(1); + if (!pkvk_is_depth_only_format(depthFormat)) { + renderingInfo.stencilAttachmentFormat = color_formats.at(2); + } + vkResult = vkCreateGraphicsPipelines(vkDevice, VK_NULL_HANDLE, 1, &vkGraphicsPipelineCreateInfo[0], vkAllocator, &pkePipelines.pipelines.named.entity_standard); assert(vkResult == VK_SUCCESS); + vkResult = vkCreateGraphicsPipelines(vkDevice, VK_NULL_HANDLE, 1, &vkGraphicsPipelineCreateInfo[1], vkAllocator, &pkePipelines.pipelines.named.entity_wireframe); assert(vkResult == VK_SUCCESS); + + renderingInfo.depthAttachmentFormat = VK_FORMAT_UNDEFINED; vkResult = vkCreateGraphicsPipelines(vkDevice, VK_NULL_HANDLE, 1, &vkGraphicsPipelineCreateInfo[2], vkAllocator, &pkePipelines.pipelines.named.font_glyph); assert(vkResult == VK_SUCCESS); + vkResult = vkCreateGraphicsPipelines(vkDevice, VK_NULL_HANDLE, 1, &vkGraphicsPipelineCreateInfo[3], vkAllocator, &pkePipelines.pipelines.named.ui_base); assert(vkResult == VK_SUCCESS); assert(pkePipelines.pipelines.named.entity_standard != VK_NULL_HANDLE); @@ -3071,7 +2901,6 @@ void CreateImGui() { ImGui_ImplVulkan_InitInfo initInfo = {}; initInfo.Allocator = vkAllocator; initInfo.CheckVkResultFn = ImGuiCheckVkResult; - // initInfo.ColorAttachmentFormat = VkFormat::VK_FORMAT_B8G8R8A8_SRGB; initInfo.DescriptorPool = imGuiDescriptorPool; initInfo.Device = vkDevice; initInfo.ImageCount = swapchainLength; @@ -3082,9 +2911,17 @@ void CreateImGui() { initInfo.PipelineCache = {}; initInfo.Queue = pkvk_shared.queue.graphics; initInfo.QueueFamily = graphicsFamilyIndex; - initInfo.RenderPass = pkvk_present.render_pass; + initInfo.RenderPass = VK_NULL_HANDLE; // dynamic rendering initInfo.Subpass = 0; - initInfo.UseDynamicRendering = false; + initInfo.UseDynamicRendering = true; + + VkPipelineRenderingCreateInfo renderingInfo{}; + VkFormat color_format = vkSurfaceFormatKHR.format; + + renderingInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO; + renderingInfo.colorAttachmentCount = 1; + renderingInfo.pColorAttachmentFormats = &color_format; + initInfo.PipelineRenderingCreateInfo = renderingInfo; ImGui_ImplVulkan_Init(&initInfo); pke_window_did_init_imgui = true; @@ -3120,6 +2957,28 @@ void CreateImGui() { // ImGui_ImplVulkan_DestroyFontUploadObjects(); } +void pkvk_transition_image_layout(VkCommandBuffer command_buffer, + VkImage image, + VkPipelineStageFlags src_stage_mask, + VkPipelineStageFlags dst_stage_mask, + VkAccessFlags src_access_mask, + VkAccessFlags dst_access_mask, + VkImageLayout old_layout, + VkImageLayout new_layout, + VkImageSubresourceRange const &subresource_range) { + VkImageMemoryBarrier barrier{}; + barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; + barrier.srcAccessMask = src_access_mask; + barrier.dstAccessMask = dst_access_mask; + barrier.oldLayout = old_layout; + barrier.newLayout = new_layout; + barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + barrier.image = image; + barrier.subresourceRange = subresource_range; + vkCmdPipelineBarrier(command_buffer, src_stage_mask, dst_stage_mask, 0, 0, VK_NULL_HANDLE, 0, VK_NULL_HANDLE, 1, &barrier); +} + void RecordCommandBuffer(VkCommandBuffer commandBuffer, uint32_t imageIndex) { vkResetCommandBuffer(commandBuffer, 0); @@ -3136,23 +2995,9 @@ void RecordCommandBuffer(VkCommandBuffer commandBuffer, uint32_t imageIndex) { VkClearColorValue clearColorTransparent = {{0.0f, 0.0f, 0.0f, 0.0f}}; VkClearColorValue clearColorBlack = {{0.0f, 0.0f, 0.0f, 1.0f}}; - VkClearValue clearValues[3]; - clearValues[0].color = clearColorBlack; - clearValues[1].color = clearColorBlack; - clearValues[2].depthStencil.depth = 1.0; - clearValues[2].depthStencil.stencil = 0; - - VkRenderPassBeginInfo renderPassInfo; - renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; - renderPassInfo.renderPass = pkvk_3d.render_pass; - renderPassInfo.framebuffer = pkvk_3d.framebuffers[imageIndex]; - renderPassInfo.renderArea.offset = {0, 0}; - renderPassInfo.renderArea.extent = Extent; - renderPassInfo.clearValueCount = 3; - renderPassInfo.pClearValues = clearValues; - renderPassInfo.pNext = VK_NULL_HANDLE; - - vkCmdBeginRenderPass(commandBuffer, &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE); + VkClearValue clearTransparent = { .color = clearColorTransparent }; + VkClearValue clearBlack = { .color = clearColorBlack }; + VkClearValue clearDepth = { .depthStencil = { 1.f, 0 } }; VkViewport viewport; viewport.x = 0.0f; @@ -3166,162 +3011,344 @@ void RecordCommandBuffer(VkCommandBuffer commandBuffer, uint32_t imageIndex) { scissor.offset = {0, 0}; scissor.extent = Extent; - vkCmdSetViewport(commandBuffer, 0, 1, &viewport); - vkCmdSetScissor(commandBuffer, 0, 1, &scissor); - VkDeviceSize offsets[1] = {0U}; - using GrBindsIterFn = pk_tmpln_1<void, CompGrBinds*, void*>; - GrBindsIterFn gr_binds_iter_cb{}; - gr_binds_iter_cb.func = [commandBuffer, imageIndex](CompGrBinds *binder) { - VkDeviceSize offsets[1] = {0U}; - if (binder->grBindsHandle == GrBindsHandle_MAX) - return; - if (!binder->vkPipelineLayout) - return; - if (binder->instanceBD.bindingCount < 1) { - return; - } - vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, binder->graphicsPipeline); - vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, binder->vkPipelineLayout, 0, 1, &binder->vkDescriptorSets[imageIndex], 0, {}); - vkCmdBindVertexBuffers(commandBuffer, 0, 1, &UniformBuffers[imageIndex], offsets); - vkCmdBindIndexBuffer(commandBuffer, binder->indexBD.buffer, binder->indexBD.offsets[0], VK_INDEX_TYPE_UINT16); - - vkCmdBindVertexBuffers(commandBuffer, binder->vertexBD.firstBinding, binder->vertexBD.bindingCount, &binder->vertexBD.buffer, binder->vertexBD.offsets); - vkCmdBindVertexBuffers(commandBuffer, binder->normalsBD.firstBinding, binder->normalsBD.bindingCount, &binder->normalsBD.buffer, binder->normalsBD.offsets); - vkCmdBindVertexBuffers(commandBuffer, binder->uvBD.firstBinding, binder->uvBD.bindingCount, &binder->uvBD.buffer, binder->uvBD.offsets); - vkCmdBindVertexBuffers(commandBuffer, binder->instanceBD.firstBinding, binder->instanceBD.bindingCount, &binder->instanceBD.buffer, binder->instanceBD.offsets); - - vkCmdDrawIndexed(commandBuffer, binder->indexCount, binder->instanceCounter, 0, 0, 0); - - if (pkeSettings.isRenderingDebug) { - vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pkePipelines.pipelines.named.entity_wireframe); - vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pkePipelines.pipe_layouts.named.ubo_txtr, 0, 1, &pkeDebugHitbox.vkDescriptorSets[imageIndex], 0, {}); + VkImageSubresourceRange range{}; + range.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + range.baseMipLevel = 0; + range.levelCount = VK_REMAINING_MIP_LEVELS; + range.baseArrayLayer = 0; + range.layerCount = VK_REMAINING_ARRAY_LAYERS; + + VkImageSubresourceRange depth_range{range}; + depth_range.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT; + + // 0 : color + // 1 : color+resolve + // 2 : depth/stencil + std::array<VkRenderingAttachmentInfo,3> color_attachments; + for (long unsigned int i = 0; i < color_attachments.size(); ++i) { + color_attachments[i].sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO; + color_attachments[i].pNext = VK_NULL_HANDLE; + color_attachments[i].imageView = VK_NULL_HANDLE; + color_attachments[i].imageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + color_attachments[i].resolveMode = VK_RESOLVE_MODE_NONE; + color_attachments[i].resolveImageView = VK_NULL_HANDLE; + color_attachments[i].resolveImageLayout = VK_IMAGE_LAYOUT_UNDEFINED; + color_attachments[i].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; + color_attachments[i].storeOp = VK_ATTACHMENT_STORE_OP_STORE; + color_attachments[i].clearValue = clearBlack; + } + + VkRenderingInfo renderingInfo; + renderingInfo.sType = VK_STRUCTURE_TYPE_RENDERING_INFO; + renderingInfo.pNext = VK_NULL_HANDLE; + renderingInfo.flags = 0; + renderingInfo.renderArea.offset = {0, 0}; + renderingInfo.renderArea.extent = Extent; + renderingInfo.layerCount = 1; + renderingInfo.viewMask = 0; + + // 3d pass + { + // color + pkvk_transition_image_layout( + commandBuffer, pkvk_3d.render_images[imageIndex], + VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, + VK_ACCESS_SHADER_READ_BIT, + VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, + VK_IMAGE_LAYOUT_UNDEFINED, + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + range + ); + // color resolve + pkvk_transition_image_layout( + commandBuffer, pkvk_3d.images_color_resolve[imageIndex], + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, + VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, + VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, + VK_ACCESS_SHADER_READ_BIT, + VK_IMAGE_LAYOUT_UNDEFINED, + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, + range + ); + // depth + pkvk_transition_image_layout( + commandBuffer, depthImages[imageIndex], + VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, + VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, + VK_ACCESS_NONE, + VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, + VK_IMAGE_LAYOUT_UNDEFINED, + VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, + depth_range + ); + + color_attachments[1].imageView = pkvk_3d.image_views[imageIndex]; + color_attachments[1].clearValue = clearBlack; + color_attachments[1].resolveMode = VK_RESOLVE_MODE_AVERAGE_BIT; + color_attachments[1].resolveImageView = pkvk_3d.image_views_color_resolve[imageIndex]; + color_attachments[1].resolveImageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + + color_attachments[2].imageView = depthImageViews[imageIndex]; + color_attachments[2].imageLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + color_attachments[2].resolveMode = VK_RESOLVE_MODE_NONE; + color_attachments[2].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; + color_attachments[2].storeOp = VK_ATTACHMENT_STORE_OP_STORE; + color_attachments[2].clearValue = clearDepth; + + // skip [0], since we have a resolve on this pass + renderingInfo.colorAttachmentCount = 1; + renderingInfo.pColorAttachments = &color_attachments.at(1); + renderingInfo.pDepthAttachment = &color_attachments.at(2); + if (!pkvk_is_depth_only_format(depthFormat)) { + renderingInfo.pStencilAttachment = &color_attachments.at(2); + } + + vkCmdBeginRendering(commandBuffer, &renderingInfo); + + vkCmdSetViewport(commandBuffer, 0, 1, &viewport); + vkCmdSetScissor(commandBuffer, 0, 1, &scissor); + + using GrBindsIterFn = pk_tmpln_1<void, CompGrBinds*, void*>; + GrBindsIterFn gr_binds_iter_cb{}; + gr_binds_iter_cb.func = [commandBuffer, imageIndex](CompGrBinds *binder) { + VkDeviceSize offsets[1] = {0U}; + if (binder->grBindsHandle == GrBindsHandle_MAX) + return; + if (!binder->vkPipelineLayout) + return; + if (binder->instanceBD.bindingCount < 1) { + return; + } + vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, binder->graphicsPipeline); + vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, binder->vkPipelineLayout, 0, 1, &binder->vkDescriptorSets[imageIndex], 0, {}); + vkCmdBindVertexBuffers(commandBuffer, 0, 1, &UniformBuffers[imageIndex], offsets); + vkCmdBindIndexBuffer(commandBuffer, binder->indexBD.buffer, binder->indexBD.offsets[0], VK_INDEX_TYPE_UINT16); - vkCmdBindVertexBuffers(commandBuffer, binder->physVertBD.firstBinding, 1, &binder->physVertBD.buffer, binder->physVertBD.offsets); - vkCmdBindVertexBuffers(commandBuffer, binder->physNormBD.firstBinding, 1, &binder->physNormBD.buffer, binder->physVertBD.offsets); - vkCmdBindVertexBuffers(commandBuffer, binder->physUvBD.firstBinding, 1, &binder->physUvBD.buffer, binder->physVertBD.offsets); - vkCmdBindIndexBuffer(commandBuffer, binder->physIndxBD.buffer, binder->physIndxBD.offsets[0], VK_INDEX_TYPE_UINT16); + vkCmdBindVertexBuffers(commandBuffer, binder->vertexBD.firstBinding, binder->vertexBD.bindingCount, &binder->vertexBD.buffer, binder->vertexBD.offsets); + vkCmdBindVertexBuffers(commandBuffer, binder->normalsBD.firstBinding, binder->normalsBD.bindingCount, &binder->normalsBD.buffer, binder->normalsBD.offsets); + vkCmdBindVertexBuffers(commandBuffer, binder->uvBD.firstBinding, binder->uvBD.bindingCount, &binder->uvBD.buffer, binder->uvBD.offsets); + vkCmdBindVertexBuffers(commandBuffer, binder->instanceBD.firstBinding, binder->instanceBD.bindingCount, &binder->instanceBD.buffer, binder->instanceBD.offsets); - vkCmdDrawIndexed(commandBuffer, binder->physIndxBD.bindingCount, binder->instanceCounter, 0, 0, 0); - } - }; - pk_bkt_arr_iterate(ECS_GetGrBinds(), &GrBindsIterFn::invoke, &gr_binds_iter_cb); + vkCmdDrawIndexed(commandBuffer, binder->indexCount, binder->instanceCounter, 0, 0, 0); - if (pkeDebugHitbox.instanceBuffer != VK_NULL_HANDLE) { - vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pkePipelines.pipelines.named.entity_wireframe); - vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pkePipelines.pipe_layouts.named.ubo_txtr, 0, 1, &pkeDebugHitbox.vkDescriptorSets[imageIndex], 0, {}); - vkCmdBindVertexBuffers(commandBuffer, 0, 1, &UniformBuffers[imageIndex], offsets); + if (pkeSettings.isRenderingDebug) { + vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pkePipelines.pipelines.named.entity_wireframe); + vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pkePipelines.pipe_layouts.named.ubo_txtr, 0, 1, &pkeDebugHitbox.vkDescriptorSets[imageIndex], 0, {}); - // TODO don't hardcode firstBinding - vkCmdBindVertexBuffers(commandBuffer, 0, 1, &pkeDebugHitbox.vertexBuffer, offsets); - vkCmdBindVertexBuffers(commandBuffer, 1, 1, &pkeDebugHitbox.normalsBuffer, offsets); - vkCmdBindVertexBuffers(commandBuffer, 2, 1, &pkeDebugHitbox.uvBuffer, offsets); - vkCmdBindIndexBuffer(commandBuffer, pkeDebugHitbox.indexBuffer, offsets[0], VK_INDEX_TYPE_UINT16); + vkCmdBindVertexBuffers(commandBuffer, binder->physVertBD.firstBinding, 1, &binder->physVertBD.buffer, binder->physVertBD.offsets); + vkCmdBindVertexBuffers(commandBuffer, binder->physNormBD.firstBinding, 1, &binder->physNormBD.buffer, binder->physVertBD.offsets); + vkCmdBindVertexBuffers(commandBuffer, binder->physUvBD.firstBinding, 1, &binder->physUvBD.buffer, binder->physVertBD.offsets); + vkCmdBindIndexBuffer(commandBuffer, binder->physIndxBD.buffer, binder->physIndxBD.offsets[0], VK_INDEX_TYPE_UINT16); - vkCmdBindVertexBuffers(commandBuffer, 3, 1, &pkeDebugHitbox.instanceBuffer, offsets); - vkCmdDrawIndexed(commandBuffer, pkeDebugHitbox.indexCount, pkeDebugHitbox.instanceCount, 0, 0, pkeDebugHitbox.instanceStartingIndex); - } + vkCmdDrawIndexed(commandBuffer, binder->physIndxBD.bindingCount, binder->instanceCounter, 0, 0, 0); + } + }; + pk_bkt_arr_iterate(ECS_GetGrBinds(), &GrBindsIterFn::invoke, &gr_binds_iter_cb); - vkCmdEndRenderPass(commandBuffer); + if (pkeDebugHitbox.instanceBuffer != VK_NULL_HANDLE) { + vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pkePipelines.pipelines.named.entity_wireframe); + vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pkePipelines.pipe_layouts.named.ubo_txtr, 0, 1, &pkeDebugHitbox.vkDescriptorSets[imageIndex], 0, {}); + vkCmdBindVertexBuffers(commandBuffer, 0, 1, &UniformBuffers[imageIndex], offsets); - // 2d overlay pass - renderPassInfo.renderPass = pkvk_2d.render_pass; - renderPassInfo.framebuffer = pkvk_2d.framebuffers[imageIndex]; - renderPassInfo.clearValueCount = 1; - clearValues[0].color = clearColorTransparent; + // TODO don't hardcode firstBinding + vkCmdBindVertexBuffers(commandBuffer, 0, 1, &pkeDebugHitbox.vertexBuffer, offsets); + vkCmdBindVertexBuffers(commandBuffer, 1, 1, &pkeDebugHitbox.normalsBuffer, offsets); + vkCmdBindVertexBuffers(commandBuffer, 2, 1, &pkeDebugHitbox.uvBuffer, offsets); + vkCmdBindIndexBuffer(commandBuffer, pkeDebugHitbox.indexBuffer, offsets[0], VK_INDEX_TYPE_UINT16); - vkCmdBeginRenderPass(commandBuffer, &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE); - vkCmdSetViewport(commandBuffer, 0, 1, &viewport); - vkCmdSetScissor(commandBuffer, 0, 1, &scissor); + vkCmdBindVertexBuffers(commandBuffer, 3, 1, &pkeDebugHitbox.instanceBuffer, offsets); + vkCmdDrawIndexed(commandBuffer, pkeDebugHitbox.indexCount, pkeDebugHitbox.instanceCount, 0, 0, pkeDebugHitbox.instanceStartingIndex); + } - // 2d overlay grbinds - pke_ui_graphics_bindings *ui_gr = pke_ui_get_graphics_bindings(); - if (ui_gr != nullptr && ui_gr->instance_counter > 0) - { - vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pkePipelines.pipelines.named.ui_base); - vkCmdBindIndexBuffer(commandBuffer, ui_gr->bd_index.buffer, ui_gr->bd_index.offsets[0], VK_INDEX_TYPE_UINT16); - vkCmdBindVertexBuffers(commandBuffer, ui_gr->bd_vertex.firstBinding, ui_gr->bd_vertex.bindingCount, &ui_gr->bd_vertex.buffer, ui_gr->bd_vertex.offsets); - vkCmdBindVertexBuffers(commandBuffer, ui_gr->bd_uv.firstBinding, ui_gr->bd_uv.bindingCount, &ui_gr->bd_uv.buffer, ui_gr->bd_uv.offsets); - vkCmdBindVertexBuffers(commandBuffer, ui_gr->bd_instance.firstBinding, ui_gr->bd_instance.bindingCount, &ui_gr->bd_instance.buffer, ui_gr->bd_instance.offsets); - vkCmdDrawIndexed(commandBuffer, ui_gr->index_count, ui_gr->instance_counter, 0, 0, 0); - } - - // 2d - font glyphs - FontTypeIndex count; - FontType *fts = FontType_GetFonts(count); - for (FontTypeIndex i = FontTypeIndex{0}; i < count; ++i) + vkCmdEndRendering(commandBuffer); + } + + // 2d pass { - FontType *ft = &fts[(FontTypeIndex_T)i]; - if (ft->bindings.instance_counter == 0) - continue; - vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pkePipelines.pipelines.named.font_glyph); + // color + pkvk_transition_image_layout( + commandBuffer, pkvk_2d.images[imageIndex], + VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, + VK_ACCESS_SHADER_READ_BIT, + VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, + VK_IMAGE_LAYOUT_UNDEFINED, + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + range + ); + // color resolve + pkvk_transition_image_layout( + commandBuffer, pkvk_2d.images_color_resolve[imageIndex], + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, + VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, + VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, + VK_ACCESS_SHADER_READ_BIT, + VK_IMAGE_LAYOUT_UNDEFINED, + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, + range + ); + + color_attachments[1].imageView = pkvk_2d.image_views[imageIndex]; + color_attachments[1].clearValue = clearTransparent; + color_attachments[1].resolveMode = VK_RESOLVE_MODE_AVERAGE_BIT; // TODO verify + color_attachments[1].resolveImageView = pkvk_2d.image_views_color_resolve[imageIndex]; + color_attachments[1].resolveImageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + + // skip [0], since we have a resolve on this pass + renderingInfo.colorAttachmentCount = 1; + renderingInfo.pColorAttachments = &color_attachments.at(1); + renderingInfo.pDepthAttachment = VK_NULL_HANDLE; + renderingInfo.pStencilAttachment = VK_NULL_HANDLE; + + vkCmdBeginRendering(commandBuffer, &renderingInfo); + + vkCmdSetViewport(commandBuffer, 0, 1, &viewport); + vkCmdSetScissor(commandBuffer, 0, 1, &scissor); + + // 2d overlay grbinds + pke_ui_graphics_bindings *ui_gr = pke_ui_get_graphics_bindings(); + if (ui_gr != nullptr && ui_gr->instance_counter > 0) + { + vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pkePipelines.pipelines.named.ui_base); + vkCmdBindIndexBuffer(commandBuffer, ui_gr->bd_index.buffer, ui_gr->bd_index.offsets[0], VK_INDEX_TYPE_UINT16); + vkCmdBindVertexBuffers(commandBuffer, ui_gr->bd_vertex.firstBinding, ui_gr->bd_vertex.bindingCount, &ui_gr->bd_vertex.buffer, ui_gr->bd_vertex.offsets); + vkCmdBindVertexBuffers(commandBuffer, ui_gr->bd_uv.firstBinding, ui_gr->bd_uv.bindingCount, &ui_gr->bd_uv.buffer, ui_gr->bd_uv.offsets); + vkCmdBindVertexBuffers(commandBuffer, ui_gr->bd_instance.firstBinding, ui_gr->bd_instance.bindingCount, &ui_gr->bd_instance.buffer, ui_gr->bd_instance.offsets); + vkCmdDrawIndexed(commandBuffer, ui_gr->index_count, ui_gr->instance_counter, 0, 0, 0); + } + + // 2d - font glyphs + FontTypeIndex count; + FontType *fts = FontType_GetFonts(count); + for (FontTypeIndex i = FontTypeIndex{0}; i < count; ++i) + { + FontType *ft = &fts[(FontTypeIndex_T)i]; + if (ft->bindings.instance_counter == 0) + continue; + vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pkePipelines.pipelines.named.font_glyph); - vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pkePipelines.pipe_layouts.named.txtr, 0, 1, &ft->gr.vkDescriptorSet, 0, {}); - vkCmdBindIndexBuffer(commandBuffer, ft->bindings.bd_index.buffer, ft->bindings.bd_index.offsets[0], VK_INDEX_TYPE_UINT16); + vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pkePipelines.pipe_layouts.named.txtr, 0, 1, &ft->gr.vkDescriptorSet, 0, {}); + vkCmdBindIndexBuffer(commandBuffer, ft->bindings.bd_index.buffer, ft->bindings.bd_index.offsets[0], VK_INDEX_TYPE_UINT16); - vkCmdBindVertexBuffers(commandBuffer, ft->bindings.bd_vertex.firstBinding, ft->bindings.bd_vertex.bindingCount, &ft->bindings.bd_vertex.buffer, ft->bindings.bd_vertex.offsets); - vkCmdBindVertexBuffers(commandBuffer, ft->bindings.bd_uv.firstBinding, ft->bindings.bd_uv.bindingCount, &ft->bindings.bd_uv.buffer, ft->bindings.bd_uv.offsets); - vkCmdBindVertexBuffers(commandBuffer, ft->bindings.bd_atlas_size.firstBinding, ft->bindings.bd_atlas_size.bindingCount, &ft->bindings.bd_atlas_size.buffer, ft->bindings.bd_atlas_size.offsets); - vkCmdBindVertexBuffers(commandBuffer, ft->bindings.bd_instance.firstBinding, ft->bindings.bd_instance.bindingCount, &ft->bindings.bd_instance.buffer, ft->bindings.bd_instance.offsets); + vkCmdBindVertexBuffers(commandBuffer, ft->bindings.bd_vertex.firstBinding, ft->bindings.bd_vertex.bindingCount, &ft->bindings.bd_vertex.buffer, ft->bindings.bd_vertex.offsets); + vkCmdBindVertexBuffers(commandBuffer, ft->bindings.bd_uv.firstBinding, ft->bindings.bd_uv.bindingCount, &ft->bindings.bd_uv.buffer, ft->bindings.bd_uv.offsets); + vkCmdBindVertexBuffers(commandBuffer, ft->bindings.bd_atlas_size.firstBinding, ft->bindings.bd_atlas_size.bindingCount, &ft->bindings.bd_atlas_size.buffer, ft->bindings.bd_atlas_size.offsets); + vkCmdBindVertexBuffers(commandBuffer, ft->bindings.bd_instance.firstBinding, ft->bindings.bd_instance.bindingCount, &ft->bindings.bd_instance.buffer, ft->bindings.bd_instance.offsets); - vkCmdDrawIndexed(commandBuffer, ft->bindings.index_count, ft->bindings.instance_counter, 0, 0, 0); + vkCmdDrawIndexed(commandBuffer, ft->bindings.index_count, ft->bindings.instance_counter, 0, 0, 0); + } + + vkCmdEndRendering(commandBuffer); } - vkCmdEndRenderPass(commandBuffer); // present pass - renderPassInfo.renderPass = pkvk_present.render_pass; - renderPassInfo.framebuffer = pkvk_present.framebuffers[imageIndex]; - renderPassInfo.clearValueCount = 1; - clearValues[0].color = clearColorBlack; - - vkCmdBeginRenderPass(commandBuffer, &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE); - vkCmdSetViewport(commandBuffer, 0, 1, &viewport); - vkCmdSetScissor(commandBuffer, 0, 1, &scissor); - vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pkvk_present.pipeline); - - // reminder that present.vert is a triangle - - // 3d - vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pkvk_present.pipeline_layout, 0, 1, &pkvk_present.descriptor_sets[(imageIndex * 2)], 0, nullptr); - vkCmdDraw(commandBuffer, 3, 1, 0, 0); - - // 2d - vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pkvk_present.pipeline_layout, 0, 1, &pkvk_present.descriptor_sets[(imageIndex * 2) + 1], 0, nullptr); - vkCmdDraw(commandBuffer, 3, 1, 0, 0); - - // ImGui - bool any = false; - for (uint32_t i = 0; i < LoadedPkePlugins.next; ++i) { - if (LoadedPkePlugins[i].OnImGuiRender != nullptr) { - any = true; - break; - } - } - // TODO move this 'any' check to happen on plugin load and store in global? - if (any) { - ImGui_ImplVulkan_NewFrame(); - ImGui_ImplGlfw_NewFrame(); - ImGui::NewFrame(); + { + // present color + pkvk_transition_image_layout( + commandBuffer, pkvk_present.images[imageIndex], + VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, + VK_ACCESS_SHADER_READ_BIT, + VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, + VK_IMAGE_LAYOUT_UNDEFINED, + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, + range + ); + + // 3d color + pkvk_transition_image_layout( + commandBuffer, pkvk_3d.images_color_resolve[imageIndex], + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, + VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, + VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, + VK_ACCESS_SHADER_READ_BIT, + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + range + ); + + // 2d color + pkvk_transition_image_layout( + commandBuffer, pkvk_2d.images_color_resolve[imageIndex], + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, + VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, + VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, + VK_ACCESS_SHADER_READ_BIT, + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + range + ); + + color_attachments[0].imageView = pkvk_present.image_views[imageIndex]; + color_attachments[0].clearValue = clearBlack; + + renderingInfo.colorAttachmentCount = 1; + renderingInfo.pColorAttachments = &color_attachments.at(0); + renderingInfo.pDepthAttachment = VK_NULL_HANDLE; + renderingInfo.pStencilAttachment = VK_NULL_HANDLE; + + vkCmdBeginRendering(commandBuffer, &renderingInfo); + + vkCmdSetViewport(commandBuffer, 0, 1, &viewport); + vkCmdSetScissor(commandBuffer, 0, 1, &scissor); + + vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pkvk_present.pipeline); + + // reminder that present.vert is a triangle + + // 3d + vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pkvk_present.pipeline_layout, 0, 1, &pkvk_present.descriptor_sets[(imageIndex * 2)], 0, nullptr); + vkCmdDraw(commandBuffer, 3, 1, 0, 0); + + // 2d + vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pkvk_present.pipeline_layout, 0, 1, &pkvk_present.descriptor_sets[(imageIndex * 2) + 1], 0, nullptr); + vkCmdDraw(commandBuffer, 3, 1, 0, 0); + + // ImGui + bool any = false; for (uint32_t i = 0; i < LoadedPkePlugins.next; ++i) { if (LoadedPkePlugins[i].OnImGuiRender != nullptr) { - LoadedPkePlugins[i].OnImGuiRender(); + any = true; + break; } } - ImGui::Render(); - auto drawData = ImGui::GetDrawData(); - const bool isMinimized = drawData->DisplaySize.x <= 0.0f || drawData->DisplaySize.y <= 0.0f; - if (isMinimized) return; + // TODO move this 'any' check to happen on plugin load and store in global? + if (any) { + ImGui_ImplVulkan_NewFrame(); + ImGui_ImplGlfw_NewFrame(); + ImGui::NewFrame(); + for (uint32_t i = 0; i < LoadedPkePlugins.next; ++i) { + if (LoadedPkePlugins[i].OnImGuiRender != nullptr) { + LoadedPkePlugins[i].OnImGuiRender(); + } + } + ImGui::Render(); + auto drawData = ImGui::GetDrawData(); + const bool isMinimized = drawData->DisplaySize.x <= 0.0f || drawData->DisplaySize.y <= 0.0f; + if (isMinimized) return; - ImGui_ImplVulkan_RenderDrawData(drawData, commandBuffer); - } + ImGui_ImplVulkan_RenderDrawData(drawData, commandBuffer); + } - vkCmdEndRenderPass(commandBuffer); + vkCmdEndRendering(commandBuffer); - result = vkEndCommandBuffer(commandBuffer); - if (result != VK_SUCCESS) { - throw "failed to record command buffer!"; + // color + pkvk_transition_image_layout( + commandBuffer, pkvk_present.images[imageIndex], + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, + VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, + VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, + VK_ACCESS_NONE, + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, + VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, + range + ); } + + vkEndCommandBuffer(commandBuffer); } void DestroySyncObjects() { @@ -3374,27 +3401,6 @@ void DestroyPresentPipeline() { } void DestroySwapchain() { - if (pkvk_2d.framebuffers != nullptr && pkvk_2d.framebuffers != CAFE_BABE(VkFramebuffer)) { - for (long i = 0; i < swapchainLength; ++i) { - vkDestroyFramebuffer(vkDevice, pkvk_2d.framebuffers[i], vkAllocator); - } - pk_delete<VkFramebuffer>(pkvk_2d.framebuffers, swapchainLength, MemBkt_Vulkan); - pkvk_2d.framebuffers = CAFE_BABE(VkFramebuffer); - } - if (pkvk_3d.framebuffers != nullptr && pkvk_3d.framebuffers != CAFE_BABE(VkFramebuffer)) { - for (long i = 0; i < swapchainLength; ++i) { - vkDestroyFramebuffer(vkDevice, pkvk_3d.framebuffers[i], vkAllocator); - } - pk_delete<VkFramebuffer>(pkvk_3d.framebuffers, swapchainLength, MemBkt_Vulkan); - pkvk_3d.framebuffers = CAFE_BABE(VkFramebuffer); - } - if (pkvk_present.framebuffers != nullptr && pkvk_present.framebuffers != CAFE_BABE(VkFramebuffer)) { - for (long i = 0; i < swapchainLength; ++i) { - vkDestroyFramebuffer(vkDevice, pkvk_present.framebuffers[i], vkAllocator); - } - pk_delete<VkFramebuffer>(pkvk_present.framebuffers, swapchainLength, MemBkt_Vulkan); - pkvk_present.framebuffers = CAFE_BABE(VkFramebuffer); - } if (depthImageViews != nullptr && depthImageViews != CAFE_BABE(VkImageView)) { for (long i = 0; i < swapchainLength; ++i) { vkDestroyImageView(vkDevice, depthImageViews[i], vkAllocator); @@ -3520,7 +3526,6 @@ void RecreateSwapchain() { } UpdatePresentDescriptorSets(); UpdateCamera(); - CreateFramebuffers(); if (prevSwapchainLength != swapchainLength) { DestroyDebugDescriptors(); DestroyUniformBuffers(); @@ -3556,12 +3561,10 @@ void CreateWindow(PKEWindowProperties wp) { InitVulkan(); glfwSetFramebufferSizeCallback(window, FramebufferResizeCallback); CreateSwapchain(); - CreateRenderPass(); CreatePresentDescriptorSetLayout(); CreatePresentPipeline(); UpdatePresentDescriptorSets(); UpdateCamera(); - CreateFramebuffers(); CreateCommandPool(); CreatePresentCommandBuffers(); CreateCommandBuffers(); @@ -3630,9 +3633,6 @@ void DestroyWindow() { vkDestroyDescriptorPool(vkDevice, imGuiDescriptorPool, vkAllocator); vkDestroyDescriptorSetLayout(vkDevice, pkvk_present.descriptor_set_layout, vkAllocator); - vkDestroyRenderPass(vkDevice, pkvk_2d.render_pass, vkAllocator); - vkDestroyRenderPass(vkDevice, pkvk_3d.render_pass, vkAllocator); - vkDestroyRenderPass(vkDevice, pkvk_present.render_pass, vkAllocator); vkDestroySurfaceKHR(vkInstance, vkSurfaceKHR, vkAllocator); vkDestroySampler(vkDevice, global_sampler, vkAllocator); vkDestroyDevice(vkDevice, vkAllocator); @@ -3738,7 +3738,6 @@ void Render() { vkResetFences(vkDevice, 1, &pkvk_present.fences_in_flight[CURRENT_FRAME]); - vkResetCommandBuffer(pkvk_present.command_buffers[CURRENT_FRAME], 0); RecordCommandBuffer(pkvk_present.command_buffers[CURRENT_FRAME], imageIndex); VkSemaphore waitSemaphores[] = {pkvk_present.semaphores_image_available[CURRENT_FRAME]}; |
