From d1d57ab682c191208ad5cc1656e4a9bbe07a4588 Mon Sep 17 00:00:00 2001 From: "Zed A. Shaw" Date: Sun, 7 Dec 2025 23:26:21 -0500 Subject: [PATCH 1/6] Big cleanup to utilize C++20 designated initializers https://en.cppreference.com/w/cpp/language/aggregate_initialization.html#Designated_initializers --- vk_descriptors.cpp | 51 +++++------ vk_images.cpp | 91 ++++++++++--------- vk_initializers.cpp | 213 +++++++++++++++++++------------------------- vk_pipelines.cpp | 14 +-- 4 files changed, 170 insertions(+), 199 deletions(-) diff --git a/vk_descriptors.cpp b/vk_descriptors.cpp index bfad725..a8aca8b 100644 --- a/vk_descriptors.cpp +++ b/vk_descriptors.cpp @@ -3,10 +3,11 @@ void DescriptorLayoutBuilder::add_binding(uint32_t binding, VkDescriptorType type) { - VkDescriptorSetLayoutBinding newbind {}; - newbind.binding = binding; - newbind.descriptorCount = 1; - newbind.descriptorType = type; + VkDescriptorSetLayoutBinding newbind{ + .binding = binding, + .descriptorType = type, + .descriptorCount = 1, + }; bindings.push_back(newbind); } @@ -25,18 +26,16 @@ VkDescriptorSetLayout DescriptorLayoutBuilder::build(VkDevice device, b.stageFlags |= shaderStages; } - VkDescriptorSetLayoutCreateInfo info = { - .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO + VkDescriptorSetLayoutCreateInfo info{ + .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, + .pNext = pNext, + .flags = flags, + .bindingCount = (uint32_t)bindings.size(), + .pBindings = bindings.data(), }; - info.pNext = pNext; - - info.pBindings = bindings.data(); - info.bindingCount = (uint32_t)bindings.size(); - info.flags = flags; VkDescriptorSetLayout set; - VK_CHECK(vkCreateDescriptorSetLayout(device, - &info, nullptr, &set)); + VK_CHECK(vkCreateDescriptorSetLayout(device, &info, nullptr, &set)); return set; } @@ -46,19 +45,19 @@ void DescriptorAllocator::init_pool(VkDevice device, uint32_t maxSets, { std::vector poolSizes; for(PoolSizeRatio ratio : poolRatios) { - poolSizes.push_back(VkDescriptorPoolSize{ + poolSizes.push_back({ .type = ratio.type, .descriptorCount = uint32_t(ratio.ratio * maxSets) }); } - VkDescriptorPoolCreateInfo pool_info = { - .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO + VkDescriptorPoolCreateInfo pool_info{ + .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, + .flags = 0, + .maxSets = maxSets, + .poolSizeCount = (uint32_t)poolSizes.size(), + .pPoolSizes = poolSizes.data(), }; - pool_info.flags = 0; - pool_info.maxSets = maxSets; - pool_info.poolSizeCount = (uint32_t)poolSizes.size(); - pool_info.pPoolSizes = poolSizes.data(); vkCreateDescriptorPool(device, &pool_info, nullptr, &pool); } @@ -75,15 +74,13 @@ void DescriptorAllocator::destroy_pool(VkDevice device) VkDescriptorSet DescriptorAllocator::allocate(VkDevice device, VkDescriptorSetLayout layout) { - VkDescriptorSetAllocateInfo allocInfo = { - .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO + VkDescriptorSetAllocateInfo allocInfo{ + .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, + .descriptorPool = pool, + .descriptorSetCount = 1, + .pSetLayouts = &layout, }; - allocInfo.pNext = nullptr; - allocInfo.descriptorPool = pool; - allocInfo.descriptorSetCount = 1; - allocInfo.pSetLayouts = &layout; - VkDescriptorSet ds; VK_CHECK(vkAllocateDescriptorSets(device, &allocInfo, &ds)); diff --git a/vk_images.cpp b/vk_images.cpp index a457d61..c97537e 100644 --- a/vk_images.cpp +++ b/vk_images.cpp @@ -3,28 +3,25 @@ void vkutil::transition_image(VkCommandBuffer cmd, VkImage image, VkImageLayout currentLayout, VkImageLayout newLayout) { - VkImageMemoryBarrier2 imageBarrier{}; - imageBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2; - imageBarrier.pNext = nullptr; - - imageBarrier.srcStageMask = VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT; - imageBarrier.srcAccessMask = VK_ACCESS_2_MEMORY_WRITE_BIT; - imageBarrier.dstStageMask = VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT; - imageBarrier.dstAccessMask = VK_ACCESS_2_MEMORY_WRITE_BIT | VK_ACCESS_2_MEMORY_READ_BIT; - - - imageBarrier.oldLayout = currentLayout; - imageBarrier.newLayout = newLayout; - VkImageAspectFlags aspectMask = (newLayout == VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL) ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_COLOR_BIT; - imageBarrier.subresourceRange = vkinit::image_subresource_range(aspectMask); - imageBarrier.image = image; - VkDependencyInfo depInfo{}; - depInfo.sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO; - depInfo.pNext = nullptr; - depInfo.imageMemoryBarrierCount = 1; - depInfo.pImageMemoryBarriers = &imageBarrier; + VkImageMemoryBarrier2 imageBarrier{ + .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2, + .srcStageMask = VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT, + .srcAccessMask = VK_ACCESS_2_MEMORY_WRITE_BIT, + .dstStageMask = VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT, + .dstAccessMask = VK_ACCESS_2_MEMORY_WRITE_BIT | VK_ACCESS_2_MEMORY_READ_BIT, + .oldLayout = currentLayout, + .newLayout = newLayout, + .image = image, + .subresourceRange = vkinit::image_subresource_range(aspectMask), + }; + + VkDependencyInfo depInfo{ + .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO, + .imageMemoryBarrierCount = 1, + .pImageMemoryBarriers = &imageBarrier, + }; vkCmdPipelineBarrier2(cmd, &depInfo); } @@ -33,39 +30,45 @@ void vkutil::copy_image_to_image(VkCommandBuffer cmd, VkImage source, VkImage de { VkImageBlit2 blitRegion{ .sType = VK_STRUCTURE_TYPE_IMAGE_BLIT_2, - .pNext = nullptr }; - blitRegion.srcOffsets[1].x = srcSize.width; - blitRegion.srcOffsets[1].y = srcSize.height; - blitRegion.srcOffsets[1].z = 1; + blitRegion.srcSubresource = { + .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, + .mipLevel = 0, + .baseArrayLayer = 0, + .layerCount = 1, + }; - blitRegion.dstOffsets[1].x = dstSize.width; - blitRegion.dstOffsets[1].y = dstSize.height; - blitRegion.dstOffsets[1].z = 1; + blitRegion.dstSubresource = { + .aspectMask=VK_IMAGE_ASPECT_COLOR_BIT, + .mipLevel=0, + .baseArrayLayer=0, + .layerCount=1, + }; - blitRegion.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - blitRegion.srcSubresource.baseArrayLayer = 0; - blitRegion.srcSubresource.layerCount = 1; - blitRegion.srcSubresource.mipLevel = 0; + blitRegion.srcOffsets[1] = { + .x = int32_t(srcSize.width), + .y = int32_t(srcSize.height), + .z = 1, + }; - blitRegion.dstSubresource.aspectMask=VK_IMAGE_ASPECT_COLOR_BIT; - blitRegion.dstSubresource.baseArrayLayer=0; - blitRegion.dstSubresource.layerCount=1; - blitRegion.dstSubresource.mipLevel=0; + blitRegion.dstOffsets[1] = { + .x = int32_t(dstSize.width), + .y = int32_t(dstSize.height), + .z = 1, + }; VkBlitImageInfo2 blitInfo{ - .sType = VK_STRUCTURE_TYPE_BLIT_IMAGE_INFO_2, .pNext = nullptr + .sType = VK_STRUCTURE_TYPE_BLIT_IMAGE_INFO_2, + .srcImage = source, + .srcImageLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, + .dstImage = destination, + .dstImageLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + .regionCount = 1, + .pRegions = &blitRegion, + .filter = VK_FILTER_LINEAR, }; - blitInfo.dstImage = destination; - blitInfo.dstImageLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; - blitInfo.srcImage = source; - blitInfo.srcImageLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; - blitInfo.filter = VK_FILTER_LINEAR; - blitInfo.regionCount = 1; - blitInfo.pRegions = &blitRegion; - vkCmdBlitImage2(cmd, &blitInfo); } diff --git a/vk_initializers.cpp b/vk_initializers.cpp index 3c30974..f54839b 100644 --- a/vk_initializers.cpp +++ b/vk_initializers.cpp @@ -3,163 +3,137 @@ VkCommandPoolCreateInfo vkinit::command_pool_create_info(uint32_t queueFamilyIndex, VkCommandPoolCreateFlags flags /*= 0*/) { - VkCommandPoolCreateInfo info = {}; - info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; - info.pNext = nullptr; - info.queueFamilyIndex = queueFamilyIndex; - info.flags = flags; - return info; + return { + .sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, + .flags = flags, + .queueFamilyIndex = queueFamilyIndex, + }; } VkCommandBufferAllocateInfo vkinit::command_buffer_allocate_info( VkCommandPool pool, uint32_t count /*= 1*/) { - VkCommandBufferAllocateInfo info = {}; - info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; - info.pNext = nullptr; - - info.commandPool = pool; - info.commandBufferCount = count; - info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; - return info; + return { + .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, + .commandPool = pool, + .level = VK_COMMAND_BUFFER_LEVEL_PRIMARY, + .commandBufferCount = count, + }; } VkFenceCreateInfo vkinit::fence_create_info(VkFenceCreateFlags flags /*=0*/) { - VkFenceCreateInfo info = {}; - info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; - info.pNext = nullptr; - info.flags = flags; - return info; + return { + .sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, + .flags = flags + }; } VkSemaphoreCreateInfo vkinit::semaphore_create_info(VkSemaphoreCreateFlags flags/*=0*/) { - VkSemaphoreCreateInfo info = {}; - info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; - info.pNext = nullptr; - info.flags = flags; - return info; + return { + .sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO, + .flags = flags, + }; } VkCommandBufferBeginInfo vkinit::command_buffer_begin_info(VkCommandBufferUsageFlags flags /*= 0*/) { - VkCommandBufferBeginInfo info = {}; - info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; - info.pNext = nullptr; - - info.pInheritanceInfo = nullptr; - info.flags = flags; - return info; + return { + .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, + .flags = flags, + .pInheritanceInfo = nullptr, + }; } VkImageSubresourceRange vkinit::image_subresource_range(VkImageAspectFlags aspectMask) { - VkImageSubresourceRange subImage {}; - subImage.aspectMask = aspectMask; - subImage.baseMipLevel = 0; - subImage.levelCount = VK_REMAINING_MIP_LEVELS; - subImage.baseArrayLayer = 0; - subImage.layerCount = VK_REMAINING_ARRAY_LAYERS; - - return subImage; + return { + .aspectMask = aspectMask, + .baseMipLevel = 0, + .levelCount = VK_REMAINING_MIP_LEVELS, + .baseArrayLayer = 0, + .layerCount = VK_REMAINING_ARRAY_LAYERS, + }; } VkSemaphoreSubmitInfo vkinit::semaphore_submit_info(VkPipelineStageFlags2 stageMask, VkSemaphore semaphore) { - VkSemaphoreSubmitInfo submitInfo{}; - submitInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO; - submitInfo.pNext = nullptr; - submitInfo.semaphore = semaphore; - submitInfo.stageMask = stageMask; - submitInfo.deviceIndex = 0; - submitInfo.value = 1; - - return submitInfo; + return { + .sType = VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO, + .semaphore = semaphore, + .value = 1, + .stageMask = stageMask, + .deviceIndex = 0, + }; } VkCommandBufferSubmitInfo vkinit::command_buffer_submit_info(VkCommandBuffer cmd) { - VkCommandBufferSubmitInfo info{}; - info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_SUBMIT_INFO; - info.pNext = nullptr; - info.commandBuffer = cmd; - info.deviceMask = 0; - - return info; + return { + .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_SUBMIT_INFO, + .commandBuffer = cmd, + .deviceMask = 0, + }; } VkSubmitInfo2 vkinit::submit_info(VkCommandBufferSubmitInfo* cmd, VkSemaphoreSubmitInfo* signalSemaphoreInfo, VkSemaphoreSubmitInfo* waitSemaphoreInfo) { - VkSubmitInfo2 info = {}; - info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO_2; - info.pNext = nullptr; - - info.waitSemaphoreInfoCount = waitSemaphoreInfo == nullptr ? 0 : 1; - info.pWaitSemaphoreInfos = waitSemaphoreInfo; - - info.signalSemaphoreInfoCount = signalSemaphoreInfo == nullptr ? 0 : 1; - info.pSignalSemaphoreInfos = signalSemaphoreInfo; - - info.commandBufferInfoCount = 1; - info.pCommandBufferInfos = cmd; - - return info; + return { + .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO_2, + .waitSemaphoreInfoCount = (waitSemaphoreInfo == nullptr ? 0u : 1u), + .pWaitSemaphoreInfos = waitSemaphoreInfo, + .commandBufferInfoCount = 1, + .pCommandBufferInfos = cmd, + .signalSemaphoreInfoCount = (signalSemaphoreInfo == nullptr ? 0u : 1u), + .pSignalSemaphoreInfos = signalSemaphoreInfo, + }; } VkImageCreateInfo vkinit::image_create_info(VkFormat format, VkImageUsageFlags usageFlags, VkExtent3D extent) { - VkImageCreateInfo info{}; - info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; - info.pNext = nullptr; - - info.imageType = VK_IMAGE_TYPE_2D; - - info.format = format; - info.extent = extent; - - info.mipLevels = 1; - info.arrayLayers = 1; - - info.samples = VK_SAMPLE_COUNT_1_BIT; - - info.tiling = VK_IMAGE_TILING_OPTIMAL; - info.usage = usageFlags; - - return info; + return { + .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, + .imageType = VK_IMAGE_TYPE_2D, + .format = format, + .extent = extent, + .mipLevels = 1, + .arrayLayers = 1, + .samples = VK_SAMPLE_COUNT_1_BIT, + .tiling = VK_IMAGE_TILING_OPTIMAL, + .usage = usageFlags, + }; } VkImageViewCreateInfo vkinit::imageview_create_info(VkFormat format, VkImage image, VkImageAspectFlags aspectFlags) { - VkImageViewCreateInfo info{}; - info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; - info.pNext = nullptr; - - info.viewType = VK_IMAGE_VIEW_TYPE_2D; - info.image = image; - info.format = format; - info.subresourceRange.baseMipLevel = 0; - info.subresourceRange.levelCount = 1; - info.subresourceRange.baseArrayLayer = 0; - info.subresourceRange.layerCount = 1; - info.subresourceRange.aspectMask = aspectFlags; - - return info; + return { + .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, + .image = image, + .viewType = VK_IMAGE_VIEW_TYPE_2D, + .format = format, + .subresourceRange = { + .aspectMask = aspectFlags, + .baseMipLevel = 0, + .levelCount = 1, + .baseArrayLayer = 0, + .layerCount = 1, + } + }; } VkRenderingAttachmentInfo vkinit::attachment_info( VkImageView view, VkClearValue* clear ,VkImageLayout layout /*= VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL*/) { - VkRenderingAttachmentInfo colorAttachment {}; - colorAttachment.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO; - colorAttachment.pNext = nullptr; - - colorAttachment.imageView = view; - colorAttachment.imageLayout = layout; - colorAttachment.loadOp = clear ? VK_ATTACHMENT_LOAD_OP_CLEAR : VK_ATTACHMENT_LOAD_OP_LOAD; - colorAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE; + VkRenderingAttachmentInfo colorAttachment{ + .sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO, + .imageView = view, + .imageLayout = layout, + .loadOp = clear ? VK_ATTACHMENT_LOAD_OP_CLEAR : VK_ATTACHMENT_LOAD_OP_LOAD, + .storeOp = VK_ATTACHMENT_STORE_OP_STORE, + }; if (clear) { colorAttachment.clearValue = *clear; @@ -172,16 +146,13 @@ VkRenderingAttachmentInfo vkinit::attachment_info( VkRenderingInfo vkinit::rendering_info(VkExtent2D renderExtent, VkRenderingAttachmentInfo* colorAttachment, VkRenderingAttachmentInfo* depthAttachment) { - VkRenderingInfo renderInfo {}; - renderInfo.sType = VK_STRUCTURE_TYPE_RENDERING_INFO; - renderInfo.pNext = nullptr; - - renderInfo.renderArea = VkRect2D { VkOffset2D { 0, 0 }, renderExtent }; - renderInfo.layerCount = 1; - renderInfo.colorAttachmentCount = 1; - renderInfo.pColorAttachments = colorAttachment; - renderInfo.pDepthAttachment = depthAttachment; - renderInfo.pStencilAttachment = nullptr; - - return renderInfo; + return { + .sType = VK_STRUCTURE_TYPE_RENDERING_INFO, + .renderArea = VkRect2D { VkOffset2D { 0, 0 }, renderExtent }, + .layerCount = 1, + .colorAttachmentCount = 1, + .pColorAttachments = colorAttachment, + .pDepthAttachment = depthAttachment, + .pStencilAttachment = nullptr, + }; } diff --git a/vk_pipelines.cpp b/vk_pipelines.cpp index 4067f1d..acecc80 100644 --- a/vk_pipelines.cpp +++ b/vk_pipelines.cpp @@ -23,13 +23,13 @@ bool vkutil::load_shader_module(const char* filePath, file.close(); - VkShaderModuleCreateInfo createInfo = {}; - createInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; - createInfo.pNext = nullptr; - - // codeSize has to be in bytes - createInfo.codeSize = buffer.size() * sizeof(uint32_t); - createInfo.pCode = buffer.data(); + VkShaderModuleCreateInfo createInfo = { + .sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, + .pNext = nullptr, + // codeSize has to be in bytes + .codeSize = buffer.size() * sizeof(uint32_t), + .pCode = buffer.data(), + }; VkShaderModule shaderModule; if(vkCreateShaderModule(device, &createInfo, nullptr, &shaderModule) != VK_SUCCESS) { From 4f7ab6db68d1bf839ecb7a9fb3d58afc77b00a0d Mon Sep 17 00:00:00 2001 From: "Zed A. Shaw" Date: Sun, 7 Dec 2025 23:56:47 -0500 Subject: [PATCH 2/6] Cleaned up the struct inits in the engine too. --- vk_engine.cpp | 249 ++++++++++++++++++++++++++------------------------ 1 file changed, 130 insertions(+), 119 deletions(-) diff --git a/vk_engine.cpp b/vk_engine.cpp index da914ab..6e9dbc8 100644 --- a/vk_engine.cpp +++ b/vk_engine.cpp @@ -150,16 +150,15 @@ void VulkanEngine::draw() // this will put the image we just rendered to into the visible window. // we want to wait on the _renderSemaphore for that, // as its necessary that drawing commands have finished before the image is displayed to the user - VkPresentInfoKHR presentInfo{}; - presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; - presentInfo.pNext = nullptr; - presentInfo.pSwapchains = &_swapchain; - presentInfo.swapchainCount = 1; - - presentInfo.pWaitSemaphores = &get_current_frame()._renderSemaphore; - presentInfo.waitSemaphoreCount = 1; - - presentInfo.pImageIndices = &swapchainImageIndex; + VkPresentInfoKHR presentInfo{ + .sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR, + .pNext = nullptr, + .waitSemaphoreCount = 1, + .pWaitSemaphores = &get_current_frame()._renderSemaphore, + .swapchainCount = 1, + .pSwapchains = &_swapchain, + .pImageIndices = &swapchainImageIndex, + }; VK_CHECK(vkQueuePresentKHR(_graphicsQueue, &presentInfo)); @@ -251,18 +250,19 @@ void VulkanEngine::init_vulkan() { SDL_Vulkan_CreateSurface(_window, _instance, &_surface); //vulkan 1.3 features - VkPhysicalDeviceVulkan13Features features13{}; - - features13.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_3_FEATURES; - features13.dynamicRendering = true; - features13.synchronization2 = true; - + VkPhysicalDeviceVulkan13Features features13{ + .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_3_FEATURES, + .synchronization2 = true, + .dynamicRendering = true, + }; + //vulkan 1.2 features - VkPhysicalDeviceVulkan12Features features12{}; - features12.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES; - features12.bufferDeviceAddress = true; - features12.descriptorIndexing = true; - + VkPhysicalDeviceVulkan12Features features12{ + .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES, + .descriptorIndexing = true, + .bufferDeviceAddress = true, + }; + // use vkbootstrap to select a gpu // We want a gpu that can write to the SDL surface vkb::PhysicalDeviceSelector selector{ vkb_inst }; @@ -284,11 +284,13 @@ void VulkanEngine::init_vulkan() { _graphicsQueueFamily = vkbDevice.get_queue_index(vkb::QueueType::graphics).value(); // initialize the memory allocator - VmaAllocatorCreateInfo allocatorInfo{}; - allocatorInfo.physicalDevice = _chosenGPU; - allocatorInfo.device = _device; - allocatorInfo.instance = _instance; - allocatorInfo.flags = VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT; + VmaAllocatorCreateInfo allocatorInfo{ + .flags = VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT, + .physicalDevice = _chosenGPU, + .device = _device, + .instance = _instance, + }; + vmaCreateAllocator(&allocatorInfo, &_allocator); _mainDeletionQueue.push_function([&]() { @@ -339,18 +341,19 @@ void VulkanEngine::init_swapchain() { _drawImage.imageFormat = VK_FORMAT_R16G16B16A16_SFLOAT; _drawImage.imageExtent = drawImageExtent; - VkImageUsageFlags drawImageUsages{}; - drawImageUsages |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT; - drawImageUsages |= VK_IMAGE_USAGE_TRANSFER_DST_BIT; - drawImageUsages |= VK_IMAGE_USAGE_STORAGE_BIT; - drawImageUsages |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; + VkImageUsageFlags drawImageUsages = + VK_IMAGE_USAGE_TRANSFER_SRC_BIT + | VK_IMAGE_USAGE_TRANSFER_DST_BIT + | VK_IMAGE_USAGE_STORAGE_BIT + | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; VkImageCreateInfo rimg_info = vkinit::image_create_info(_drawImage.imageFormat, drawImageUsages, drawImageExtent); - VmaAllocationCreateInfo rimg_allocinfo{}; - rimg_allocinfo.usage = VMA_MEMORY_USAGE_GPU_ONLY; - rimg_allocinfo.requiredFlags = VkMemoryPropertyFlags(VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); - + VmaAllocationCreateInfo rimg_allocinfo{ + .usage = VMA_MEMORY_USAGE_GPU_ONLY, + .requiredFlags = VkMemoryPropertyFlags(VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT), + }; + //allocate and create the image vmaCreateImage(_allocator, &rimg_info, &rimg_allocinfo, &_drawImage.image, &_drawImage.allocation, nullptr); @@ -443,19 +446,19 @@ void VulkanEngine::init_descriptors() { //allocate a descriptor set for our draw image _drawImageDescriptors = globalDescriptorAllocator.allocate(_device,_drawImageDescriptorLayout); - VkDescriptorImageInfo imgInfo{}; - imgInfo.imageLayout = VK_IMAGE_LAYOUT_GENERAL; - imgInfo.imageView = _drawImage.imageView; - - VkWriteDescriptorSet drawImageWrite = {}; - drawImageWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - drawImageWrite.pNext = nullptr; - - drawImageWrite.dstBinding = 0; - drawImageWrite.dstSet = _drawImageDescriptors; - drawImageWrite.descriptorCount = 1; - drawImageWrite.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; - drawImageWrite.pImageInfo = &imgInfo; + VkDescriptorImageInfo imgInfo{ + .imageView = _drawImage.imageView, + .imageLayout = VK_IMAGE_LAYOUT_GENERAL, + }; + + VkWriteDescriptorSet drawImageWrite = { + .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, + .dstSet = _drawImageDescriptors, + .dstBinding = 0, + .descriptorCount = 1, + .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, + .pImageInfo = &imgInfo, + }; vkUpdateDescriptorSets(_device, 1, &drawImageWrite, 0, nullptr), @@ -474,20 +477,20 @@ void VulkanEngine::init_pipelines() void VulkanEngine::init_background_pipelines() { - VkPipelineLayoutCreateInfo computeLayout{}; - computeLayout.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; - computeLayout.pNext = nullptr; - computeLayout.pSetLayouts = &_drawImageDescriptorLayout; - computeLayout.setLayoutCount = 1; - - VkPushConstantRange pushConstant{}; - pushConstant.offset = 0; - pushConstant.size = sizeof(ComputePushConstants) ; - pushConstant.stageFlags = VK_SHADER_STAGE_COMPUTE_BIT; - - computeLayout.pPushConstantRanges = &pushConstant; - computeLayout.pushConstantRangeCount = 1; - + VkPushConstantRange pushConstant{ + .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT, + .offset = 0, + .size = sizeof(ComputePushConstants) , + }; + + VkPipelineLayoutCreateInfo computeLayout{ + .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, + .setLayoutCount = 1, + .pSetLayouts = &_drawImageDescriptorLayout, + .pushConstantRangeCount = 1, + .pPushConstantRanges = &pushConstant, + }; + VK_CHECK(vkCreatePipelineLayout(_device, &computeLayout, nullptr, &_gradientPipelineLayout)); VkShaderModule gradientShader; @@ -497,40 +500,42 @@ void VulkanEngine::init_background_pipelines() VkShaderModule skyShader; good = vkutil::load_shader_module("sky.comp.spv", _device, &skyShader); - VkPipelineShaderStageCreateInfo stageinfo{}; - stageinfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; - stageinfo.pNext = nullptr; - stageinfo.stage = VK_SHADER_STAGE_COMPUTE_BIT; - stageinfo.module = gradientShader; - stageinfo.pName = "main"; - - VkComputePipelineCreateInfo computePipelineCreateInfo{}; - computePipelineCreateInfo.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO; - computePipelineCreateInfo.pNext = nullptr; - computePipelineCreateInfo.layout = _gradientPipelineLayout; - computePipelineCreateInfo.stage = stageinfo; - - ComputeEffect gradient; - gradient.layout = _gradientPipelineLayout; - gradient.name = "gradient"; - gradient.data = {}; - gradient.data.data1 = glm::vec4(1, 0, 0, 1); - gradient.data.data2 = glm::vec4(0, 0, 1, 1); + VkPipelineShaderStageCreateInfo stageinfo{ + .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, + .stage = VK_SHADER_STAGE_COMPUTE_BIT, + .module = gradientShader, + .pName = "main", + }; + + VkComputePipelineCreateInfo computePipelineCreateInfo{ + .sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO, + .stage = stageinfo, + .layout = _gradientPipelineLayout, + }; + + ComputeEffect gradient{ + .name = "gradient", + .layout = _gradientPipelineLayout, + .data = { + .data1 = glm::vec4(1, 0, 0, 1), + .data2 = glm::vec4(0, 0, 1, 1), + }, + }; + VK_CHECK(vkCreateComputePipelines(_device, VK_NULL_HANDLE, 1, &computePipelineCreateInfo, nullptr, &gradient.pipeline)); // change the shader module only to create the sky computePipelineCreateInfo.stage.module = skyShader; - ComputeEffect sky; - sky.layout = _gradientPipelineLayout; - sky.name = "sky"; - sky.data = {}; - // default sky - sky.data.data1 = glm::vec4(0.1, 0.2, 0.4, 0.97); + ComputeEffect sky{ + .name = "sky", + .layout = _gradientPipelineLayout, + .data{.data1 = glm::vec4(0.1, 0.2, 0.4, 0.97)}, + }; + VK_CHECK(vkCreateComputePipelines(_device, VK_NULL_HANDLE, 1, &computePipelineCreateInfo, nullptr, &sky.pipeline)); - backgroundEffects.push_back(gradient); backgroundEffects.push_back(sky); @@ -574,25 +579,28 @@ void VulkanEngine::init_imgui() // 1: create descriptor pool for IMGUI // the size of the pool is very oversize, but it's copied from imgui demo // itself. - VkDescriptorPoolSize pool_sizes[] = { { VK_DESCRIPTOR_TYPE_SAMPLER, 1000 }, - { VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1000 }, - { VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1000 }, - { VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1000 }, - { VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, 1000 }, - { VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, 1000 }, - { VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1000 }, - { VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1000 }, - { VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1000 }, - { VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, 1000 }, - { VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 1000 } }; + VkDescriptorPoolSize pool_sizes[] = { + { VK_DESCRIPTOR_TYPE_SAMPLER, 1000 }, + { VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1000 }, + { VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1000 }, + { VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1000 }, + { VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, 1000 }, + { VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, 1000 }, + { VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1000 }, + { VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1000 }, + { VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1000 }, + { VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, 1000 }, + { VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 1000 } + }; - VkDescriptorPoolCreateInfo pool_info{}; - pool_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; - pool_info.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT; - pool_info.maxSets = 1000; - pool_info.poolSizeCount = (uint32_t)std::size(pool_sizes); - pool_info.pPoolSizes = pool_sizes; - + VkDescriptorPoolCreateInfo pool_info{ + .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, + .flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, + .maxSets = 1000, + .poolSizeCount = (uint32_t)std::size(pool_sizes), + .pPoolSizes = pool_sizes, + }; + VkDescriptorPool imguiPool; VK_CHECK(vkCreateDescriptorPool(_device, &pool_info, nullptr, &imguiPool)); @@ -600,21 +608,24 @@ void VulkanEngine::init_imgui() ImGui::CreateContext(); ImGui_ImplSDL2_InitForVulkan(_window); - ImGui_ImplVulkan_InitInfo init_info{}; - init_info.Instance = _instance; - init_info.PhysicalDevice = _chosenGPU; - init_info.Device = _device; - init_info.Queue = _graphicsQueue; - init_info.DescriptorPool = imguiPool; - init_info.MinImageCount = 3; - init_info.ImageCount = 3; - init_info.UseDynamicRendering = true; - init_info.PipelineRenderingCreateInfo = {.sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO}; - init_info.PipelineRenderingCreateInfo.colorAttachmentCount = 1; - init_info.PipelineRenderingCreateInfo.pColorAttachmentFormats = &_swapchainImageFormat; + ImGui_ImplVulkan_InitInfo init_info{ + .Instance = _instance, + .PhysicalDevice = _chosenGPU, + .Device = _device, + .Queue = _graphicsQueue, + .DescriptorPool = imguiPool, + .MinImageCount = 3, + .ImageCount = 3, + .MSAASamples = VK_SAMPLE_COUNT_1_BIT, + .UseDynamicRendering = true, + .PipelineRenderingCreateInfo = { + .sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO, + .colorAttachmentCount = 1, + .pColorAttachmentFormats = &_swapchainImageFormat, + }, + }; - init_info.MSAASamples = VK_SAMPLE_COUNT_1_BIT; ImGui_ImplVulkan_Init(&init_info); ImGui_ImplVulkan_CreateFontsTexture(); From 35198bce6bdb4b389c1c0742d82430e168463f3f Mon Sep 17 00:00:00 2001 From: "Zed A. Shaw" Date: Mon, 8 Dec 2025 00:58:09 -0500 Subject: [PATCH 3/6] Pulled the gui out into VkGUI to separate it out. --- meson.build | 1 + vk_engine.cpp | 155 +++----------------------------------------------- vk_engine.h | 22 +------ vk_gui.cpp | 151 ++++++++++++++++++++++++++++++++++++++++++++++++ vk_gui.h | 18 ++++++ vk_types.h | 17 ++++++ 6 files changed, 198 insertions(+), 166 deletions(-) create mode 100644 vk_gui.cpp create mode 100644 vk_gui.h diff --git a/meson.build b/meson.build index deacd3f..64df191 100644 --- a/meson.build +++ b/meson.build @@ -121,6 +121,7 @@ sources = [ 'vk_images.cpp', 'vk_descriptors.cpp', 'vk_pipelines.cpp', + 'vk_gui.cpp', 'main.cpp', ] diff --git a/vk_engine.cpp b/vk_engine.cpp index 6e9dbc8..cf70b02 100644 --- a/vk_engine.cpp +++ b/vk_engine.cpp @@ -3,18 +3,13 @@ #include "vk_pipelines.h" #include -#include -#include - #include #include #include "VkBootstrap.h" #include #include -#include "imgui.h" -#include "imgui_impl_sdl2.h" -#include "imgui_impl_vulkan.h" +#include #define VMA_IMPLEMENTATION #include "vk_mem_alloc.h" @@ -32,18 +27,7 @@ void VulkanEngine::init() assert(loadedEngine == nullptr); loadedEngine = this; - // We initialize SDL and create a window with it. - SDL_Init(SDL_INIT_VIDEO); - - SDL_WindowFlags window_flags = (SDL_WindowFlags)(SDL_WINDOW_VULKAN); - - _window = SDL_CreateWindow( - "Vulkan Engine", - SDL_WINDOWPOS_UNDEFINED, - SDL_WINDOWPOS_UNDEFINED, - int(_windowExtent.width), - int(_windowExtent.height), - window_flags); + _window = _gui.init_window(_windowExtent); init_vulkan(); init_swapchain(); @@ -51,7 +35,7 @@ void VulkanEngine::init() init_sync_structures(); init_descriptors(); init_pipelines(); - init_imgui(); + _gui.init_imgui(VulkanEngine::Get()); //everything went fine _isInitialized = true; @@ -81,7 +65,7 @@ void VulkanEngine::cleanup() vkDestroyDevice(_device, nullptr); vkb::destroy_debug_utils_messenger(_instance, _debug_messenger); vkDestroyInstance(_instance, nullptr); - SDL_DestroyWindow(_window); + _gui.destroy(_window); } loadedEngine = nullptr; @@ -125,7 +109,7 @@ void VulkanEngine::draw() vkutil::transition_image(cmd, _swapchainImages[swapchainImageIndex], VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); - draw_imgui(cmd, _swapchainImageViews[swapchainImageIndex]); + _gui.draw_imgui(_swapchainExtent, cmd, _swapchainImageViews[swapchainImageIndex]); vkutil::transition_image(cmd, _swapchainImages[swapchainImageIndex], VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR); @@ -168,68 +152,21 @@ void VulkanEngine::draw() void VulkanEngine::run() { - SDL_Event e; - bool bQuit = false; - bool stop_rendering = false; - //main loop - while(!bQuit) + while(!_gui.should_quit) { - //Handle events on queue - while(SDL_PollEvent(&e) != 0) - { - //close the window when user alt-f4s or clicks the X button - if(e.type == SDL_QUIT) { - bQuit = true; - } + _gui.poll_event(); - if(e.type == SDL_WINDOWEVENT) { - if(e.window.event == SDL_WINDOWEVENT_MINIMIZED) { - stop_rendering = true; - } - - if(e.window.event == SDL_WINDOWEVENT_RESTORED) { - stop_rendering = false; - } - } - - ImGui_ImplSDL2_ProcessEvent(&e); - } - - if(stop_rendering) { + if(_gui.stop_rendering) { std::this_thread::sleep_for(std::chrono::milliseconds(100)); continue; } - render_imgui(); + _gui.render_imgui(backgroundEffects, ¤tBackgroundEffect); draw(); } } -void VulkanEngine::render_imgui() { - ImGui_ImplVulkan_NewFrame(); - ImGui_ImplSDL2_NewFrame(); - - ImGui::NewFrame(); - - if (ImGui::Begin("background")) { - - ComputeEffect& selected = backgroundEffects[currentBackgroundEffect]; - - ImGui::Text("Selected effect: %s", selected.name); - - ImGui::SliderInt("Effect Index", ¤tBackgroundEffect,0, backgroundEffects.size() - 1); - - ImGui::InputFloat4("data1",(float*)& selected.data.data1); - ImGui::InputFloat4("data2",(float*)& selected.data.data2); - ImGui::InputFloat4("data3",(float*)& selected.data.data3); - ImGui::InputFloat4("data4",(float*)& selected.data.data4); - } - ImGui::End(); - - ImGui::Render(); -} - void VulkanEngine::init_vulkan() { vkb::InstanceBuilder builder; @@ -570,81 +507,7 @@ void VulkanEngine::immediate_submit(std::function&& f VK_CHECK(vkQueueSubmit2(_graphicsQueue, 1, &submit, _immFence)); VK_CHECK(vkWaitForFences(_device, 1, &_immFence, true,9999999999)); - } -void VulkanEngine::init_imgui() -{ -// 1: create descriptor pool for IMGUI - // the size of the pool is very oversize, but it's copied from imgui demo - // itself. - VkDescriptorPoolSize pool_sizes[] = { - { VK_DESCRIPTOR_TYPE_SAMPLER, 1000 }, - { VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1000 }, - { VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1000 }, - { VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1000 }, - { VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, 1000 }, - { VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, 1000 }, - { VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1000 }, - { VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1000 }, - { VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1000 }, - { VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, 1000 }, - { VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 1000 } - }; - - VkDescriptorPoolCreateInfo pool_info{ - .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, - .flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, - .maxSets = 1000, - .poolSizeCount = (uint32_t)std::size(pool_sizes), - .pPoolSizes = pool_sizes, - }; - - VkDescriptorPool imguiPool; - VK_CHECK(vkCreateDescriptorPool(_device, &pool_info, nullptr, &imguiPool)); - // 2: initialize the imgui library - ImGui::CreateContext(); - - ImGui_ImplSDL2_InitForVulkan(_window); - - ImGui_ImplVulkan_InitInfo init_info{ - .Instance = _instance, - .PhysicalDevice = _chosenGPU, - .Device = _device, - .Queue = _graphicsQueue, - .DescriptorPool = imguiPool, - .MinImageCount = 3, - .ImageCount = 3, - .MSAASamples = VK_SAMPLE_COUNT_1_BIT, - .UseDynamicRendering = true, - .PipelineRenderingCreateInfo = { - .sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO, - .colorAttachmentCount = 1, - .pColorAttachmentFormats = &_swapchainImageFormat, - }, - }; - - ImGui_ImplVulkan_Init(&init_info); - ImGui_ImplVulkan_CreateFontsTexture(); - - _mainDeletionQueue.push_function([=,this]() { - ImGui_ImplVulkan_Shutdown(); - vkDestroyDescriptorPool(_device, imguiPool, nullptr); - }); -} - - -void VulkanEngine::draw_imgui(VkCommandBuffer cmd, VkImageView targetImageView) -{ - VkRenderingAttachmentInfo colorAttachment = vkinit::attachment_info(targetImageView, nullptr, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); - - VkRenderingInfo renderInfo = vkinit::rendering_info(_swapchainExtent, &colorAttachment, nullptr); - - vkCmdBeginRendering(cmd, &renderInfo); - - ImGui_ImplVulkan_RenderDrawData(ImGui::GetDrawData(), cmd); - - vkCmdEndRendering(cmd); -} diff --git a/vk_engine.h b/vk_engine.h index 5a7903b..b5c85a5 100644 --- a/vk_engine.h +++ b/vk_engine.h @@ -5,22 +5,7 @@ #include #include - -struct ComputePushConstants { - glm::vec4 data1; - glm::vec4 data2; - glm::vec4 data3; - glm::vec4 data4; -}; - -struct ComputeEffect { - const char *name; - VkPipeline pipeline; - VkPipelineLayout layout; - - ComputePushConstants data; -}; - +#include "vk_gui.h" struct DeletionQueue { std::deque> deletors; @@ -48,7 +33,6 @@ struct FrameData { DeletionQueue _deletionQueue; }; -constexpr unsigned int FRAME_OVERLAP=2; class VulkanEngine { public: @@ -104,6 +88,7 @@ public: // imgui shader stuff std::vector backgroundEffects; int currentBackgroundEffect{0}; + VkGUI _gui; static VulkanEngine& Get(); @@ -129,11 +114,8 @@ private: void init_descriptors(); void init_pipelines(); void init_background_pipelines(); - void init_imgui(); void create_swapchain(uint32_t width, uint32_t height); void destroy_swapchain(); void draw_background(VkCommandBuffer cmd); - void draw_imgui(VkCommandBuffer cmd, VkImageView targetImageView); - void render_imgui(); }; diff --git a/vk_gui.cpp b/vk_gui.cpp new file mode 100644 index 0000000..86e4bd3 --- /dev/null +++ b/vk_gui.cpp @@ -0,0 +1,151 @@ +#include "vk_gui.h" +#include "vk_initializers.h" +#include +#include +#include +#include +#include +#include "vk_engine.h" + +struct SDL_Window* VkGUI::init_window(VkExtent2D windowExtent) +{ + SDL_Init(SDL_INIT_VIDEO); + + SDL_WindowFlags window_flags = (SDL_WindowFlags)(SDL_WINDOW_VULKAN); + + return SDL_CreateWindow( + "Vulkan Engine", + SDL_WINDOWPOS_UNDEFINED, + SDL_WINDOWPOS_UNDEFINED, + int(windowExtent.width), + int(windowExtent.height), + window_flags); +} + +void VkGUI::init_imgui(VulkanEngine& engine) +{ + // 1. create descriptor pool for IMGUI + // the size of the pool is very oversize, but it's copied from imgui demo + // itself. + VkDescriptorPoolSize pool_sizes[] = { + { VK_DESCRIPTOR_TYPE_SAMPLER, 1000 }, + { VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1000 }, + { VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1000 }, + { VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1000 }, + { VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, 1000 }, + { VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, 1000 }, + { VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1000 }, + { VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1000 }, + { VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1000 }, + { VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, 1000 }, + { VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 1000 } + }; + + VkDescriptorPoolCreateInfo pool_info{ + .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, + .flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, + .maxSets = 1000, + .poolSizeCount = (uint32_t)std::size(pool_sizes), + .pPoolSizes = pool_sizes, + }; + + VkDescriptorPool imguiPool; + VK_CHECK(vkCreateDescriptorPool(engine._device, &pool_info, nullptr, &imguiPool)); + + // 2: initialize the imgui library + ImGui::CreateContext(); + + ImGui_ImplSDL2_InitForVulkan(engine._window); + + ImGui_ImplVulkan_InitInfo init_info{ + .Instance = engine._instance, + .PhysicalDevice = engine._chosenGPU, + .Device = engine._device, + .Queue = engine._graphicsQueue, + .DescriptorPool = imguiPool, + .MinImageCount = 3, + .ImageCount = 3, + .MSAASamples = VK_SAMPLE_COUNT_1_BIT, + .UseDynamicRendering = true, + .PipelineRenderingCreateInfo = { + .sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO, + .colorAttachmentCount = 1, + .pColorAttachmentFormats = &engine._swapchainImageFormat, + }, + }; + + ImGui_ImplVulkan_Init(&init_info); + ImGui_ImplVulkan_CreateFontsTexture(); + + engine._mainDeletionQueue.push_function([=,this]() { + ImGui_ImplVulkan_Shutdown(); + vkDestroyDescriptorPool(engine._device, imguiPool, nullptr); + }); +} + +void VkGUI::draw_imgui(VkExtent2D& swapchainExtent, VkCommandBuffer cmd, VkImageView targetImageView) +{ + VkRenderingAttachmentInfo colorAttachment = vkinit::attachment_info(targetImageView, nullptr, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); + + VkRenderingInfo renderInfo = vkinit::rendering_info(swapchainExtent, &colorAttachment, nullptr); + + vkCmdBeginRendering(cmd, &renderInfo); + + ImGui_ImplVulkan_RenderDrawData(ImGui::GetDrawData(), cmd); + + vkCmdEndRendering(cmd); +} + +void VkGUI::render_imgui(std::vector& backgroundEffects, int* currentBackgroundEffect) +{ + ImGui_ImplVulkan_NewFrame(); + ImGui_ImplSDL2_NewFrame(); + + ImGui::NewFrame(); + + if (ImGui::Begin("background")) { + + ComputeEffect& selected = backgroundEffects[*currentBackgroundEffect]; + + ImGui::Text("Selected effect: %s", selected.name); + + ImGui::SliderInt("Effect Index", currentBackgroundEffect,0, backgroundEffects.size() - 1); + + ImGui::InputFloat4("data1",(float*)& selected.data.data1); + ImGui::InputFloat4("data2",(float*)& selected.data.data2); + ImGui::InputFloat4("data3",(float*)& selected.data.data3); + ImGui::InputFloat4("data4",(float*)& selected.data.data4); + } + ImGui::End(); + + ImGui::Render(); +} + +void VkGUI::destroy(struct SDL_Window* _window) +{ + SDL_DestroyWindow(_window); +} + + +void VkGUI::poll_event() { + SDL_Event event; + + while(SDL_PollEvent(&event) != 0) { + //close the window when user alt-f4s or clicks the X button + if(event.type == SDL_QUIT) { + should_quit = true; + } + + if(event.type == SDL_WINDOWEVENT) { + if(event.window.event == SDL_WINDOWEVENT_MINIMIZED) { + stop_rendering = true; + } + + if(event.window.event == SDL_WINDOWEVENT_RESTORED) { + stop_rendering = false; + } + } + + ImGui_ImplSDL2_ProcessEvent(&event); + } +} diff --git a/vk_gui.h b/vk_gui.h new file mode 100644 index 0000000..8890504 --- /dev/null +++ b/vk_gui.h @@ -0,0 +1,18 @@ +#pragma once +#include "vk_types.h" + +class VulkanEngine; + +class VkGUI { + public: + bool should_quit = false; + bool stop_rendering = false; + + struct SDL_Window* init_window(VkExtent2D windowExtent); + void init_imgui(VulkanEngine& engine); + void draw_imgui(VkExtent2D& swapchainExtent, VkCommandBuffer cmd, VkImageView targetImageView); + void render_imgui(std::vector& backgroundEffects, int* currentBackgroundEffect); + void destroy(struct SDL_Window* _window); + + void poll_event(); +}; diff --git a/vk_types.h b/vk_types.h index 9b880a6..ed4264a 100644 --- a/vk_types.h +++ b/vk_types.h @@ -37,3 +37,20 @@ struct AllocatedImage { VkExtent3D imageExtent; VkFormat imageFormat; }; + +struct ComputePushConstants { + glm::vec4 data1; + glm::vec4 data2; + glm::vec4 data3; + glm::vec4 data4; +}; + +struct ComputeEffect { + const char *name; + VkPipeline pipeline; + VkPipelineLayout layout; + + ComputePushConstants data; +}; + +constexpr unsigned int FRAME_OVERLAP=2; From 61931083c67cde2756f0353bf67c31a322100524 Mon Sep 17 00:00:00 2001 From: "Zed A. Shaw" Date: Tue, 9 Dec 2025 13:22:44 -0500 Subject: [PATCH 4/6] Refactored the shader loading. --- vk_engine.cpp | 106 +++++++++++++++++++++++++------------------------- vk_engine.h | 4 ++ 2 files changed, 58 insertions(+), 52 deletions(-) diff --git a/vk_engine.cpp b/vk_engine.cpp index cf70b02..642ceb2 100644 --- a/vk_engine.cpp +++ b/vk_engine.cpp @@ -410,14 +410,47 @@ void VulkanEngine::init_descriptors() { void VulkanEngine::init_pipelines() { init_background_pipelines(); + init_shaders(); } +void VulkanEngine::load_shader(const char *file_name, const char *entry_point, ComputeEffect sky) { + VkShaderModule skyShader; + bool good = vkutil::load_shader_module(file_name, _device, &skyShader); + assert(good && "failed to load shader"); + + VkPipelineShaderStageCreateInfo stageinfo{ + .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, + .stage = VK_SHADER_STAGE_COMPUTE_BIT, + .module = skyShader, + .pName = entry_point, + }; + + VkComputePipelineCreateInfo computePipelineCreateInfo{ + .sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO, + .stage = stageinfo, + .layout = _gradientPipelineLayout, + }; + + sky.layout = _gradientPipelineLayout; + + VK_CHECK(vkCreateComputePipelines(_device, VK_NULL_HANDLE, 1, &computePipelineCreateInfo, nullptr, &sky.pipeline)); + + backgroundEffects.push_back(sky); + + vkDestroyShaderModule(_device, skyShader, nullptr); + + _mainDeletionQueue.push_function([=,this]() { + vkDestroyPipeline(_device, sky.pipeline, nullptr); + }); +} + + void VulkanEngine::init_background_pipelines() { VkPushConstantRange pushConstant{ .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT, .offset = 0, - .size = sizeof(ComputePushConstants) , + .size = sizeof(ComputePushConstants), }; VkPipelineLayoutCreateInfo computeLayout{ @@ -430,59 +463,28 @@ void VulkanEngine::init_background_pipelines() VK_CHECK(vkCreatePipelineLayout(_device, &computeLayout, nullptr, &_gradientPipelineLayout)); - VkShaderModule gradientShader; - bool good = vkutil::load_shader_module("gradient_color.comp.spv", _device, &gradientShader); - assert(good && "failed to load gradient_color.comp.spv"); - - VkShaderModule skyShader; - good = vkutil::load_shader_module("sky.comp.spv", _device, &skyShader); - - VkPipelineShaderStageCreateInfo stageinfo{ - .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, - .stage = VK_SHADER_STAGE_COMPUTE_BIT, - .module = gradientShader, - .pName = "main", - }; - - VkComputePipelineCreateInfo computePipelineCreateInfo{ - .sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO, - .stage = stageinfo, - .layout = _gradientPipelineLayout, - }; - - ComputeEffect gradient{ - .name = "gradient", - .layout = _gradientPipelineLayout, - .data = { - .data1 = glm::vec4(1, 0, 0, 1), - .data2 = glm::vec4(0, 0, 1, 1), - }, - }; - - - VK_CHECK(vkCreateComputePipelines(_device, VK_NULL_HANDLE, 1, &computePipelineCreateInfo, nullptr, &gradient.pipeline)); - - // change the shader module only to create the sky - computePipelineCreateInfo.stage.module = skyShader; - - ComputeEffect sky{ - .name = "sky", - .layout = _gradientPipelineLayout, - .data{.data1 = glm::vec4(0.1, 0.2, 0.4, 0.97)}, - }; - - VK_CHECK(vkCreateComputePipelines(_device, VK_NULL_HANDLE, 1, &computePipelineCreateInfo, nullptr, &sky.pipeline)); - - backgroundEffects.push_back(gradient); - backgroundEffects.push_back(sky); - - vkDestroyShaderModule(_device, gradientShader, nullptr); - vkDestroyShaderModule(_device, skyShader, nullptr); - + // final cleanup _mainDeletionQueue.push_function([=,this]() { vkDestroyPipelineLayout(_device, _gradientPipelineLayout, nullptr); - vkDestroyPipeline(_device, sky.pipeline, nullptr); - vkDestroyPipeline(_device, sky.pipeline, nullptr); + }); +} + + +void VulkanEngine::init_shaders() { + /// gradient shader + load_shader("gradient_color.comp.spv", "main", { + .name="gradient", + .data={ + .data1 = glm::vec4(1, 0, 0, 1), + .data2 = glm::vec4(0, 0, 1, 1), + } + }); + + load_shader("sky.comp.spv", "main", { + .name="sky", + .data = { + .data1 = glm::vec4(0.1, 0.2, 0.4, 0.97) + } }); } diff --git a/vk_engine.h b/vk_engine.h index b5c85a5..c890046 100644 --- a/vk_engine.h +++ b/vk_engine.h @@ -88,6 +88,8 @@ public: // imgui shader stuff std::vector backgroundEffects; int currentBackgroundEffect{0}; + + // ZED's REFACTOR VkGUI _gui; static VulkanEngine& Get(); @@ -114,6 +116,8 @@ private: void init_descriptors(); void init_pipelines(); void init_background_pipelines(); + void init_shaders(); + void load_shader(const char *file_name, const char *entry_point, ComputeEffect data); void create_swapchain(uint32_t width, uint32_t height); void destroy_swapchain(); From b5c6774412cb8622ec7736fc1d82b361e22ec37e Mon Sep 17 00:00:00 2001 From: "Zed A. Shaw" Date: Tue, 9 Dec 2025 13:47:39 -0500 Subject: [PATCH 5/6] Clean out references to 'sky' in the load_shader. --- vk_engine.cpp | 49 ++++++++++++++++++++++++++++++++++++------------- 1 file changed, 36 insertions(+), 13 deletions(-) diff --git a/vk_engine.cpp b/vk_engine.cpp index 642ceb2..de223bb 100644 --- a/vk_engine.cpp +++ b/vk_engine.cpp @@ -73,6 +73,7 @@ void VulkanEngine::cleanup() void VulkanEngine::draw() { + // ZED: begin command transaction // wait until the gpu has finished rendering the last frame. Timeout of 1 second VK_CHECK(vkWaitForFences(_device, 1, &get_current_frame()._renderFence, true, 1000000000)); get_current_frame()._deletionQueue.flush(); @@ -87,38 +88,60 @@ void VulkanEngine::draw() VkCommandBufferBeginInfo cmdBeginInfo = vkinit::command_buffer_begin_info(VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT); + VK_CHECK(vkBeginCommandBuffer(cmd, &cmdBeginInfo)); + + + + + + + // ZED: draw the things _drawExtent.width = _drawImage.imageExtent.width; _drawExtent.height = _drawImage.imageExtent.height; - VK_CHECK(vkBeginCommandBuffer(cmd, &cmdBeginInfo)); - // transition our main draw image into general layout so we can write into it // we will overwrite it all so we dont care about what was the older layout - vkutil::transition_image(cmd, _drawImage.image, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL); draw_background(cmd); + // ZED: ? vkutil::transition_image(cmd, _drawImage.image, VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); + + + + // ZED: ? vkutil::transition_image(cmd, _swapchainImages[swapchainImageIndex], VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); vkutil::copy_image_to_image(cmd, _drawImage.image, _swapchainImages[swapchainImageIndex], _drawExtent, _swapchainExtent); + + + // ZED: ? vkutil::transition_image(cmd, _swapchainImages[swapchainImageIndex], VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); _gui.draw_imgui(_swapchainExtent, cmd, _swapchainImageViews[swapchainImageIndex]); + // ZED: end drawing the things + + + + + + // ZED: finalize image and commit command buffer vkutil::transition_image(cmd, _swapchainImages[swapchainImageIndex], VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR); VK_CHECK(vkEndCommandBuffer(cmd)); + + + // ZED: submit command to queue //prepare the submission to the queue. //we want to wait on the _presentSemaphore, as that semaphore is signaled when the swapchain is ready //we will signal the _renderSemaphore, to signal that rendering has finished - VkCommandBufferSubmitInfo cmdinfo = vkinit::command_buffer_submit_info(cmd); VkSemaphoreSubmitInfo waitInfo = vkinit::semaphore_submit_info(VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT_KHR,get_current_frame()._swapchainSemaphore); @@ -413,15 +436,15 @@ void VulkanEngine::init_pipelines() init_shaders(); } -void VulkanEngine::load_shader(const char *file_name, const char *entry_point, ComputeEffect sky) { - VkShaderModule skyShader; - bool good = vkutil::load_shader_module(file_name, _device, &skyShader); +void VulkanEngine::load_shader(const char *file_name, const char *entry_point, ComputeEffect effect) { + VkShaderModule shader; + bool good = vkutil::load_shader_module(file_name, _device, &shader); assert(good && "failed to load shader"); VkPipelineShaderStageCreateInfo stageinfo{ .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, .stage = VK_SHADER_STAGE_COMPUTE_BIT, - .module = skyShader, + .module = shader, .pName = entry_point, }; @@ -431,16 +454,16 @@ void VulkanEngine::load_shader(const char *file_name, const char *entry_point, C .layout = _gradientPipelineLayout, }; - sky.layout = _gradientPipelineLayout; + effect.layout = _gradientPipelineLayout; - VK_CHECK(vkCreateComputePipelines(_device, VK_NULL_HANDLE, 1, &computePipelineCreateInfo, nullptr, &sky.pipeline)); + VK_CHECK(vkCreateComputePipelines(_device, VK_NULL_HANDLE, 1, &computePipelineCreateInfo, nullptr, &effect.pipeline)); - backgroundEffects.push_back(sky); + backgroundEffects.push_back(effect); - vkDestroyShaderModule(_device, skyShader, nullptr); + vkDestroyShaderModule(_device, shader, nullptr); _mainDeletionQueue.push_function([=,this]() { - vkDestroyPipeline(_device, sky.pipeline, nullptr); + vkDestroyPipeline(_device, effect.pipeline, nullptr); }); } From 3d36517b4f41f7dc0338f4d9971a098ea96ad42e Mon Sep 17 00:00:00 2001 From: "Zed A. Shaw" Date: Wed, 10 Dec 2025 12:58:55 -0500 Subject: [PATCH 6/6] A bit more refactoring to expose the begin/end transactional nature. --- vk_descriptors.cpp | 1 - vk_engine.cpp | 105 +++++++++++++++++++++------------------------ vk_engine.h | 10 ++++- 3 files changed, 59 insertions(+), 57 deletions(-) diff --git a/vk_descriptors.cpp b/vk_descriptors.cpp index a8aca8b..d8d4f62 100644 --- a/vk_descriptors.cpp +++ b/vk_descriptors.cpp @@ -2,7 +2,6 @@ void DescriptorLayoutBuilder::add_binding(uint32_t binding, VkDescriptorType type) { - VkDescriptorSetLayoutBinding newbind{ .binding = binding, .descriptorType = type, diff --git a/vk_engine.cpp b/vk_engine.cpp index de223bb..448cffb 100644 --- a/vk_engine.cpp +++ b/vk_engine.cpp @@ -71,8 +71,7 @@ void VulkanEngine::cleanup() loadedEngine = nullptr; } -void VulkanEngine::draw() -{ +Transaction VulkanEngine::begin_transaction() { // ZED: begin command transaction // wait until the gpu has finished rendering the last frame. Timeout of 1 second VK_CHECK(vkWaitForFences(_device, 1, &get_current_frame()._renderFence, true, 1000000000)); @@ -90,64 +89,22 @@ void VulkanEngine::draw() VK_CHECK(vkBeginCommandBuffer(cmd, &cmdBeginInfo)); + return {cmd, swapchainImageIndex}; +} - - - - - // ZED: draw the things - _drawExtent.width = _drawImage.imageExtent.width; - _drawExtent.height = _drawImage.imageExtent.height; - - // transition our main draw image into general layout so we can write into it - // we will overwrite it all so we dont care about what was the older layout - vkutil::transition_image(cmd, _drawImage.image, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL); - - draw_background(cmd); - - // ZED: ? - vkutil::transition_image(cmd, _drawImage.image, VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); - - - - - // ZED: ? - vkutil::transition_image(cmd, _swapchainImages[swapchainImageIndex], VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); - - vkutil::copy_image_to_image(cmd, _drawImage.image, - _swapchainImages[swapchainImageIndex], - _drawExtent, _swapchainExtent); - - - - // ZED: ? - vkutil::transition_image(cmd, _swapchainImages[swapchainImageIndex], VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); - - _gui.draw_imgui(_swapchainExtent, cmd, _swapchainImageViews[swapchainImageIndex]); - // ZED: end drawing the things - - - - - - - // ZED: finalize image and commit command buffer - vkutil::transition_image(cmd, _swapchainImages[swapchainImageIndex], VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR); - - VK_CHECK(vkEndCommandBuffer(cmd)); - - +void VulkanEngine::commit_transaction(Transaction& t) { + VK_CHECK(vkEndCommandBuffer(t.cmd)); // ZED: submit command to queue //prepare the submission to the queue. //we want to wait on the _presentSemaphore, as that semaphore is signaled when the swapchain is ready //we will signal the _renderSemaphore, to signal that rendering has finished - VkCommandBufferSubmitInfo cmdinfo = vkinit::command_buffer_submit_info(cmd); + VkCommandBufferSubmitInfo cmdinfo = vkinit::command_buffer_submit_info(t.cmd); VkSemaphoreSubmitInfo waitInfo = vkinit::semaphore_submit_info(VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT_KHR,get_current_frame()._swapchainSemaphore); VkSemaphoreSubmitInfo signalInfo = vkinit::semaphore_submit_info(VK_PIPELINE_STAGE_2_ALL_GRAPHICS_BIT, get_current_frame()._renderSemaphore); - VkSubmitInfo2 submit = vkinit::submit_info(&cmdinfo,&signalInfo,&waitInfo); + VkSubmitInfo2 submit = vkinit::submit_info(&cmdinfo, &signalInfo, &waitInfo); //submit command buffer to the queue and execute it. // _renderFence will now block until the graphic commands finish execution @@ -164,7 +121,7 @@ void VulkanEngine::draw() .pWaitSemaphores = &get_current_frame()._renderSemaphore, .swapchainCount = 1, .pSwapchains = &_swapchain, - .pImageIndices = &swapchainImageIndex, + .pImageIndices = &t.swapchainImageIndex, }; VK_CHECK(vkQueuePresentKHR(_graphicsQueue, &presentInfo)); @@ -173,6 +130,44 @@ void VulkanEngine::draw() _frameNumber++; } +void VulkanEngine::draw() +{ + auto t = begin_transaction(); + + // ZED: draw the things + _drawExtent.width = _drawImage.imageExtent.width; + _drawExtent.height = _drawImage.imageExtent.height; + + // transition our main draw image into general layout so we can write into it + // we will overwrite it all so we dont care about what was the older layout + vkutil::transition_image(t.cmd, _drawImage.image, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL); + + draw_background(t.cmd); + + // ZED: ? + vkutil::transition_image(t.cmd, _drawImage.image, VK_IMAGE_LAYOUT_GENERAL, + VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); + + // ZED: ? + vkutil::transition_image(t.cmd, _swapchainImages[t.swapchainImageIndex], + VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); + + vkutil::copy_image_to_image(t.cmd, _drawImage.image, + _swapchainImages[t.swapchainImageIndex], + _drawExtent, _swapchainExtent); + + // ZED: ? + vkutil::transition_image(t.cmd, _swapchainImages[t.swapchainImageIndex], VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); + + _gui.draw_imgui(_swapchainExtent, t.cmd, _swapchainImageViews[t.swapchainImageIndex]); + // ZED: end drawing the things + + // ZED: finalize image and commit command buffer + vkutil::transition_image(t.cmd, _swapchainImages[t.swapchainImageIndex], VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR); + + commit_transaction(t); +} + void VulkanEngine::run() { //main loop @@ -393,7 +388,7 @@ void VulkanEngine::init_descriptors() { { VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1 } }; - globalDescriptorAllocator.init_pool(_device, 10, sizes); + _globalDescriptorAllocator.init_pool(_device, 10, sizes); // make the descriptor set layout for our compute draw { @@ -404,14 +399,14 @@ void VulkanEngine::init_descriptors() { // other code //allocate a descriptor set for our draw image - _drawImageDescriptors = globalDescriptorAllocator.allocate(_device,_drawImageDescriptorLayout); + _drawImageDescriptors = _globalDescriptorAllocator.allocate(_device,_drawImageDescriptorLayout); VkDescriptorImageInfo imgInfo{ .imageView = _drawImage.imageView, .imageLayout = VK_IMAGE_LAYOUT_GENERAL, }; - VkWriteDescriptorSet drawImageWrite = { + VkWriteDescriptorSet drawImageWrite{ .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, .dstSet = _drawImageDescriptors, .dstBinding = 0, @@ -424,7 +419,7 @@ void VulkanEngine::init_descriptors() { //make sure both the descriptor allocator and the new layout get cleaned up properly _mainDeletionQueue.push_function([&]() { - globalDescriptorAllocator.destroy_pool(_device); + _globalDescriptorAllocator.destroy_pool(_device); vkDestroyDescriptorSetLayout(_device, _drawImageDescriptorLayout, nullptr); }); diff --git a/vk_engine.h b/vk_engine.h index c890046..0f684f4 100644 --- a/vk_engine.h +++ b/vk_engine.h @@ -7,6 +7,11 @@ #include #include "vk_gui.h" +struct Transaction { + VkCommandBuffer cmd; + uint32_t swapchainImageIndex = 0; +}; + struct DeletionQueue { std::deque> deletors; @@ -42,7 +47,7 @@ public: VkPipeline _gradientPipeline; VkPipelineLayout _gradientPipelineLayout; - DescriptorAllocator globalDescriptorAllocator; + DescriptorAllocator _globalDescriptorAllocator; VkDescriptorSet _drawImageDescriptors; VkDescriptorSetLayout _drawImageDescriptorLayout; @@ -108,6 +113,9 @@ public: void immediate_submit(std::function&& function); + Transaction begin_transaction(); + void commit_transaction(Transaction& cmd); + private: void init_vulkan(); void init_swapchain();