@@ -329,24 +329,27 @@ class HelloTriangleApplication
329329 bool framebufferResized = false ;
330330
331331 // Vulkan objects
332- vk::raii::Context context;
333- vk::raii::Instance instance = nullptr ;
334- vk::raii::DebugUtilsMessengerEXT debugMessenger = nullptr ;
335- vk::raii::SurfaceKHR surface = nullptr ;
336- vk::raii::PhysicalDevice physicalDevice = nullptr ;
337- vk::raii::Device device = nullptr ;
338- uint32_t queueIndex = ~0 ;
339- vk::raii::Queue queue = nullptr ;
340- vk::raii::SwapchainKHR swapChain = nullptr ;
341- std::vector<vk::Image> swapChainImages;
342- vk::SurfaceFormatKHR swapChainSurfaceFormat;
343- vk::Extent2D swapChainExtent;
344- std::vector<vk::raii::ImageView> swapChainImageViews;
345-
332+ vk::raii::Context context;
333+ vk::raii::Instance instance = nullptr ;
334+ vk::raii::DebugUtilsMessengerEXT debugMessenger = nullptr ;
335+ vk::raii::SurfaceKHR surface = nullptr ;
336+ vk::raii::PhysicalDevice physicalDevice = nullptr ;
337+ vk::raii::Device device = nullptr ;
338+ uint32_t queueIndex = ~0 ;
339+ vk::raii::Queue queue = nullptr ;
340+ vk::raii::SwapchainKHR swapChain = nullptr ;
341+ std::vector<vk::Image> swapChainImages;
342+ vk::SurfaceFormatKHR swapChainSurfaceFormat;
343+ vk::Extent2D swapChainExtent;
344+ std::vector<vk::raii::ImageView> swapChainImageViews;
346345 vk::raii::RenderPass renderPass = nullptr ;
347346 vk::raii::DescriptorSetLayout descriptorSetLayout = nullptr ;
348347 vk::raii::PipelineLayout pipelineLayout = nullptr ;
349348 vk::raii::Pipeline graphicsPipeline = nullptr ;
349+ vk::Format depthFormat;
350+ vk::raii::Image depthImage = nullptr ;
351+ vk::raii::DeviceMemory depthImageMemory = nullptr ;
352+ vk::raii::ImageView depthImageView = nullptr ;
350353 std::vector<vk::raii::Framebuffer> swapChainFramebuffers;
351354 vk::raii::CommandPool commandPool = nullptr ;
352355 std::vector<vk::raii::CommandBuffer> commandBuffers;
@@ -396,6 +399,7 @@ class HelloTriangleApplication
396399 createLogicalDevice ();
397400 createSwapChain ();
398401 createImageViews ();
402+ createDepthResources ();
399403 createRenderPass ();
400404 createDescriptorSetLayout ();
401405 createGraphicsPipeline ();
@@ -694,22 +698,42 @@ class HelloTriangleApplication
694698 .attachment = 0 ,
695699 .layout = vk::ImageLayout::eColorAttachmentOptimal};
696700
701+ vk::AttachmentDescription depthAttachment{
702+ .format = depthFormat,
703+ .samples = vk::SampleCountFlagBits::e1 ,
704+ .loadOp = vk::AttachmentLoadOp::eClear,
705+ .storeOp = vk::AttachmentStoreOp::eStore,
706+ .stencilLoadOp = vk::AttachmentLoadOp::eDontCare,
707+ .stencilStoreOp = vk::AttachmentStoreOp::eDontCare,
708+ .initialLayout = vk::ImageLayout::eUndefined,
709+ .finalLayout = vk::ImageLayout::eDepthStencilAttachmentOptimal};
710+
711+ vk::AttachmentReference depthAttachmentRef{
712+ .attachment = 1 ,
713+ .layout = vk::ImageLayout::eDepthStencilAttachmentOptimal};
714+
697715 vk::SubpassDescription subpass{
698- .pipelineBindPoint = vk::PipelineBindPoint::eGraphics,
699- .colorAttachmentCount = 1 ,
700- .pColorAttachments = &colorAttachmentRef};
716+ .pipelineBindPoint = vk::PipelineBindPoint::eGraphics,
717+ .colorAttachmentCount = 1 ,
718+ .pColorAttachments = &colorAttachmentRef,
719+ .pDepthStencilAttachment = &depthAttachmentRef};
701720
721+ // @todo: barrier for deoth
702722 vk::SubpassDependency dependency{
703723 .srcSubpass = VK_SUBPASS_EXTERNAL,
704724 .dstSubpass = 0 ,
705- .srcStageMask = vk::PipelineStageFlagBits::eColorAttachmentOutput,
706- .dstStageMask = vk::PipelineStageFlagBits::eColorAttachmentOutput,
707- .srcAccessMask = vk::AccessFlagBits::eNone,
708- .dstAccessMask = vk::AccessFlagBits::eColorAttachmentWrite};
725+ .srcStageMask = vk::PipelineStageFlagBits::eColorAttachmentOutput | vk::PipelineStageFlagBits::eEarlyFragmentTests | vk::PipelineStageFlagBits::eLateFragmentTests,
726+ .dstStageMask = vk::PipelineStageFlagBits::eColorAttachmentOutput | vk::PipelineStageFlagBits::eEarlyFragmentTests | vk::PipelineStageFlagBits::eLateFragmentTests,
727+ .srcAccessMask = vk::AccessFlagBits::eDepthStencilAttachmentWrite,
728+ .dstAccessMask = vk::AccessFlagBits::eColorAttachmentWrite | vk::AccessFlagBits::eDepthStencilAttachmentWrite};
729+
730+ vk::AttachmentDescription attachments[] = {
731+ colorAttachment,
732+ depthAttachment};
709733
710734 vk::RenderPassCreateInfo renderPassInfo{
711- .attachmentCount = 1 ,
712- .pAttachments = &colorAttachment ,
735+ .attachmentCount = 2 ,
736+ .pAttachments = attachments ,
713737 .subpassCount = 1 ,
714738 .pSubpasses = &subpass,
715739 .dependencyCount = 1 ,
@@ -809,6 +833,12 @@ class HelloTriangleApplication
809833 .depthBiasEnable = VK_FALSE,
810834 .lineWidth = 1 .0f };
811835
836+ // Depth/Stencil
837+ vk::PipelineDepthStencilStateCreateInfo depthStencil{
838+ .depthTestEnable = vk::True,
839+ .depthWriteEnable = vk::True,
840+ .depthCompareOp = vk::CompareOp::eLessOrEqual};
841+
812842 // Multisampling
813843 vk::PipelineMultisampleStateCreateInfo multisampling{
814844 .rasterizationSamples = vk::SampleCountFlagBits::e1 ,
@@ -850,7 +880,7 @@ class HelloTriangleApplication
850880 .pViewportState = &viewportState,
851881 .pRasterizationState = &rasterizer,
852882 .pMultisampleState = &multisampling,
853- .pDepthStencilState = nullptr ,
883+ .pDepthStencilState = &depthStencil ,
854884 .pColorBlendState = &colorBlending,
855885 .pDynamicState = &dynamicState,
856886 .layout = *pipelineLayout,
@@ -869,11 +899,12 @@ class HelloTriangleApplication
869899 for (size_t i = 0 ; i < swapChainImageViews.size (); i++)
870900 {
871901 vk::ImageView attachments[] = {
872- *swapChainImageViews[i]};
902+ *swapChainImageViews[i],
903+ *depthImageView};
873904
874905 vk::FramebufferCreateInfo framebufferInfo{
875906 .renderPass = *renderPass,
876- .attachmentCount = 1 ,
907+ .attachmentCount = 2 ,
877908 .pAttachments = attachments,
878909 .width = swapChainExtent.width ,
879910 .height = swapChainExtent.height ,
@@ -893,6 +924,35 @@ class HelloTriangleApplication
893924 commandPool = device.createCommandPool (poolInfo);
894925 }
895926
927+ vk::Format findSupportedFormat (const std::vector<vk::Format> &candidates, vk::ImageTiling tiling, vk::FormatFeatureFlags features) const
928+ {
929+ for (const auto format : candidates)
930+ {
931+ vk::FormatProperties props = physicalDevice.getFormatProperties (format);
932+
933+ if (tiling == vk::ImageTiling::eLinear && (props.linearTilingFeatures & features) == features)
934+ {
935+ return format;
936+ }
937+ if (tiling == vk::ImageTiling::eOptimal && (props.optimalTilingFeatures & features) == features)
938+ {
939+ return format;
940+ }
941+ }
942+
943+ throw std::runtime_error (" failed to find supported format!" );
944+ }
945+
946+ void createDepthResources ()
947+ {
948+ depthFormat = findSupportedFormat ({vk::Format::eD32Sfloat, vk::Format::eD32SfloatS8Uint, vk::Format::eD24UnormS8Uint},
949+ vk::ImageTiling::eOptimal,
950+ vk::FormatFeatureFlagBits::eDepthStencilAttachment);
951+
952+ createImage (swapChainExtent.width , swapChainExtent.height , 1 , depthFormat, vk::ImageTiling::eOptimal, vk::ImageUsageFlagBits::eDepthStencilAttachment, vk::MemoryPropertyFlagBits::eDeviceLocal, depthImage, depthImageMemory);
953+ depthImageView = createImageView (depthImage, depthFormat, vk::ImageAspectFlagBits::eDepth, 1 );
954+ }
955+
896956 // Create texture image
897957 void createTextureImage ()
898958 {
@@ -941,32 +1001,7 @@ class HelloTriangleApplication
9411001 }
9421002
9431003 // Create image
944- vk::ImageCreateInfo imageInfo{
945- .imageType = vk::ImageType::e2D,
946- .format = vk::Format::eR8G8B8A8Srgb,
947- .extent = {
948- .width = static_cast <uint32_t >(texWidth),
949- .height = static_cast <uint32_t >(texHeight),
950- .depth = 1 },
951- .mipLevels = 1 ,
952- .arrayLayers = 1 ,
953- .samples = vk::SampleCountFlagBits::e1 ,
954- .tiling = vk::ImageTiling::eOptimal,
955- .usage = vk::ImageUsageFlagBits::eTransferDst | vk::ImageUsageFlagBits::eSampled,
956- .sharingMode = vk::SharingMode::eExclusive,
957- .initialLayout = vk::ImageLayout::eUndefined};
958-
959- textureImage = device.createImage (imageInfo);
960-
961- // Allocate memory for the image
962- vk::MemoryRequirements memRequirements = textureImage.getMemoryRequirements ();
963-
964- vk::MemoryAllocateInfo allocInfo{
965- .allocationSize = memRequirements.size ,
966- .memoryTypeIndex = findMemoryType (memRequirements.memoryTypeBits , vk::MemoryPropertyFlagBits::eDeviceLocal)};
967-
968- textureImageMemory = device.allocateMemory (allocInfo);
969- textureImage.bindMemory (*textureImageMemory, 0 );
1004+ createImage (texWidth, texHeight, 1 , vk::Format::eR8G8B8A8Srgb, vk::ImageTiling::eOptimal, vk::ImageUsageFlagBits::eTransferSrc | vk::ImageUsageFlagBits::eTransferDst | vk::ImageUsageFlagBits::eSampled, vk::MemoryPropertyFlagBits::eDeviceLocal, textureImage, textureImageMemory);
9701005
9711006 // Transition image layout and copy buffer to image
9721007 transitionImageLayout (textureImage, vk::Format::eR8G8B8A8Srgb, vk::ImageLayout::eUndefined, vk::ImageLayout::eTransferDstOptimal);
@@ -977,7 +1012,7 @@ class HelloTriangleApplication
9771012 // Create texture image view
9781013 void createTextureImageView ()
9791014 {
980- textureImageView = createImageView (textureImage, vk::Format::eR8G8B8A8Srgb);
1015+ textureImageView = createImageView (textureImage, vk::Format::eR8G8B8A8Srgb, vk::ImageAspectFlagBits::eColor, 1 );
9811016 }
9821017
9831018 // Create texture sampler
@@ -1238,17 +1273,18 @@ class HelloTriangleApplication
12381273 vk::CommandBufferBeginInfo beginInfo{};
12391274 commandBuffer.begin (beginInfo);
12401275
1276+ vk::ClearValue clearValues[]{
1277+ vk::ClearValue{vk::ClearColorValue (0 .0f , 0 .0f , 0 .0f , 1 .0f )},
1278+ vk::ClearValue{vk::ClearDepthStencilValue (1 .0f , 0 )}};
1279+
12411280 vk::RenderPassBeginInfo renderPassInfo{
12421281 .renderPass = *renderPass,
12431282 .framebuffer = *swapChainFramebuffers[imageIndex],
12441283 .renderArea = {
12451284 .offset = {0 , 0 },
1246- .extent = swapChainExtent}};
1247-
1248- vk::ClearValue clearColor;
1249- clearColor.color .float32 = std::array<float , 4 >{0 .0f , 0 .0f , 0 .0f , 1 .0f };
1250- renderPassInfo.clearValueCount = 1 ;
1251- renderPassInfo.pClearValues = &clearColor;
1285+ .extent = swapChainExtent},
1286+ .clearValueCount = 2 ,
1287+ .pClearValues = clearValues};
12521288
12531289 commandBuffer.beginRenderPass (renderPassInfo, vk::SubpassContents::eInline);
12541290 commandBuffer.bindPipeline (vk::PipelineBindPoint::eGraphics, *graphicsPipeline);
@@ -1374,6 +1410,7 @@ class HelloTriangleApplication
13741410 // Create new swap chain and dependent resources
13751411 createSwapChain ();
13761412 createImageViews ();
1413+ createDepthResources ();
13771414 createFramebuffers ();
13781415
13791416 // Recreate per-swapchain-image present semaphores for presenting
@@ -1563,20 +1600,37 @@ class HelloTriangleApplication
15631600 }
15641601
15651602 // Create image view
1566- vk::raii::ImageView createImageView (vk::raii::Image &image, vk::Format format)
1603+ [[nodiscard]] vk::raii::ImageView createImageView (const vk::raii::Image &image, vk::Format format, vk::ImageAspectFlags aspectFlags, uint32_t mipLevels) const
15671604 {
15681605 vk::ImageViewCreateInfo viewInfo{
15691606 .image = *image,
15701607 .viewType = vk::ImageViewType::e2D,
15711608 .format = format,
1572- .subresourceRange = {
1573- .aspectMask = vk::ImageAspectFlagBits::eColor,
1574- .baseMipLevel = 0 ,
1575- .levelCount = 1 ,
1576- .baseArrayLayer = 0 ,
1577- .layerCount = 1 }};
1578-
1579- return device.createImageView (viewInfo);
1609+ .subresourceRange = {aspectFlags, 0 , mipLevels, 0 , 1 }};
1610+ return vk::raii::ImageView (device, viewInfo);
1611+ }
1612+
1613+ void createImage (uint32_t width, uint32_t height, uint32_t mipLevels, vk::Format format, vk::ImageTiling tiling, vk::ImageUsageFlags usage, vk::MemoryPropertyFlags properties, vk::raii::Image &image, vk::raii::DeviceMemory &imageMemory)
1614+ {
1615+ vk::ImageCreateInfo imageInfo{
1616+ .imageType = vk::ImageType::e2D,
1617+ .format = format,
1618+ .extent = {width, height, 1 },
1619+ .mipLevels = mipLevels,
1620+ .arrayLayers = 1 ,
1621+ .samples = vk::SampleCountFlagBits::e1 ,
1622+ .tiling = tiling,
1623+ .usage = usage,
1624+ .sharingMode = vk::SharingMode::eExclusive,
1625+ .initialLayout = vk::ImageLayout::eUndefined};
1626+ image = vk::raii::Image (device, imageInfo);
1627+
1628+ vk::MemoryRequirements memRequirements = image.getMemoryRequirements ();
1629+ vk::MemoryAllocateInfo allocInfo{
1630+ .allocationSize = memRequirements.size ,
1631+ .memoryTypeIndex = findMemoryType (memRequirements.memoryTypeBits , properties)};
1632+ imageMemory = vk::raii::DeviceMemory (device, allocInfo);
1633+ image.bindMemory (*imageMemory, 0 );
15801634 }
15811635
15821636 // Transition image layout
0 commit comments