diff --git a/src/main.cpp b/src/main.cpp index 0f0abce..5e43b7a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -100,8 +100,9 @@ class VulkanApp { vk::UniqueDebugUtilsMessengerEXT mDebugMessenger; vk::UniqueSurfaceKHR mSurface; - vk::PhysicalDevice mPhysicalDevice; - vk::UniqueDevice mDevice; + vk::PhysicalDevice mPhysicalDevice; + vk::SampleCountFlagBits mMsaaSamples = vk::SampleCountFlagBits::e1; + vk::UniqueDevice mDevice; vk::Queue mGraphicsQueue; vk::Queue mPresentQueue; @@ -120,6 +121,10 @@ class VulkanApp { vk::UniqueCommandPool mCommandPool; + vk::UniqueImage mColorImage; + vk::UniqueDeviceMemory mColorImageMemory; + vk::UniqueImageView mColorImageView; + vk::UniqueImage mDepthImage; vk::UniqueDeviceMemory mDepthImageMemory; vk::UniqueImageView mDepthImageView; @@ -219,6 +224,7 @@ class VulkanApp { createDescriptorSetLayout(); createGraphicsPipeline(); createCommandPool(); + createColorResources(); createDepthResources(); createFramebuffers(); createTextureImage(); @@ -265,6 +271,7 @@ class VulkanApp { createSwapChain(); createImageViews(); + createColorResources(); createDepthResources(); createFramebuffers(); } @@ -350,6 +357,7 @@ class VulkanApp { if (isDeviceSuitable(device)) { mPhysicalDevice = device; + mMsaaSamples = getMaxUsableSampleCount(); break; } } @@ -444,19 +452,17 @@ class VulkanApp { } fn createRenderPass() -> void { - vk::AttachmentDescription colorAttachment { - .format = mSwapChainImageFormat, - .samples = vk::SampleCountFlagBits::e1, - .loadOp = vk::AttachmentLoadOp::eClear, - .storeOp = vk::AttachmentStoreOp::eStore, - .stencilLoadOp = vk::AttachmentLoadOp::eDontCare, - .stencilStoreOp = vk::AttachmentStoreOp::eDontCare, - .initialLayout = vk::ImageLayout::eUndefined, - .finalLayout = vk::ImageLayout::ePresentSrcKHR, - }; + vk::AttachmentDescription colorAttachment { .format = mSwapChainImageFormat, + .samples = mMsaaSamples, + .loadOp = vk::AttachmentLoadOp::eClear, + .storeOp = vk::AttachmentStoreOp::eStore, + .stencilLoadOp = vk::AttachmentLoadOp::eDontCare, + .stencilStoreOp = vk::AttachmentStoreOp::eDontCare, + .initialLayout = vk::ImageLayout::eUndefined, + .finalLayout = vk::ImageLayout::eColorAttachmentOptimal }; vk::AttachmentDescription depthAttachment { .format = findDepthFormat(), - .samples = vk::SampleCountFlagBits::e1, + .samples = mMsaaSamples, .loadOp = vk::AttachmentLoadOp::eClear, .storeOp = vk::AttachmentStoreOp::eDontCare, .stencilLoadOp = vk::AttachmentLoadOp::eDontCare, @@ -465,17 +471,28 @@ class VulkanApp { .finalLayout = vk::ImageLayout::eDepthStencilAttachmentOptimal }; - vk::AttachmentReference colorAttachmentRef { - .attachment = 0, - .layout = vk::ImageLayout::eColorAttachmentOptimal, - }; + vk::AttachmentDescription colorAttachmentResolve { .format = mSwapChainImageFormat, + .samples = vk::SampleCountFlagBits::e1, + .loadOp = vk::AttachmentLoadOp::eDontCare, + .storeOp = vk::AttachmentStoreOp::eStore, + .stencilLoadOp = vk::AttachmentLoadOp::eDontCare, + .stencilStoreOp = vk::AttachmentStoreOp::eDontCare, + .initialLayout = vk::ImageLayout::eUndefined, + .finalLayout = vk::ImageLayout::ePresentSrcKHR }; + + vk::AttachmentReference colorAttachmentRef { .attachment = 0, + .layout = vk::ImageLayout::eColorAttachmentOptimal }; vk::AttachmentReference depthAttachmentRef { .attachment = 1, .layout = vk::ImageLayout::eDepthStencilAttachmentOptimal }; + vk::AttachmentReference colorAttachmentResolveRef { .attachment = 2, + .layout = vk::ImageLayout::eColorAttachmentOptimal }; + vk::SubpassDescription subpass { .pipelineBindPoint = vk::PipelineBindPoint::eGraphics, .colorAttachmentCount = 1, .pColorAttachments = &colorAttachmentRef, + .pResolveAttachments = &colorAttachmentResolveRef, .pDepthStencilAttachment = &depthAttachmentRef }; vk::SubpassDependency dependency { .srcSubpass = vk::SubpassExternal, @@ -488,7 +505,9 @@ class VulkanApp { .dstAccessMask = vk::AccessFlagBits::eColorAttachmentWrite | vk::AccessFlagBits::eDepthStencilAttachmentWrite }; - std::array attachments = { colorAttachment, depthAttachment }; + std::array attachments = { colorAttachment, + depthAttachment, + colorAttachmentResolve }; vk::RenderPassCreateInfo renderPassInfo { .attachmentCount = static_cast(attachments.size()), .pAttachments = attachments.data(), @@ -569,9 +588,8 @@ class VulkanApp { .depthBiasEnable = vk::False, .lineWidth = 1.0F }; - vk::PipelineMultisampleStateCreateInfo multisampling { .rasterizationSamples = - vk::SampleCountFlagBits::e1, - .sampleShadingEnable = vk::False }; + vk::PipelineMultisampleStateCreateInfo multisampling { .rasterizationSamples = mMsaaSamples, + .sampleShadingEnable = vk::False }; vk::PipelineDepthStencilStateCreateInfo depthStencil { .depthTestEnable = vk::True, .depthWriteEnable = vk::True, @@ -634,7 +652,9 @@ class VulkanApp { mSwapChainFramebuffers.resize(mSwapChainImageViews.size()); for (usize i = 0; i < mSwapChainImageViews.size(); i++) { - std::array attachments = { mSwapChainImageViews[i].get(), mDepthImageView.get() }; + std::array attachments = { mColorImageView.get(), + mDepthImageView.get(), + mSwapChainImageViews[i].get() }; vk::FramebufferCreateInfo framebufferInfo { .renderPass = mRenderPass.get(), .attachmentCount = static_cast(attachments.size()), @@ -658,6 +678,25 @@ class VulkanApp { mCommandPool = mDevice->createCommandPoolUnique(poolInfo); } + fn createColorResources() -> void { + vk::Format colorFormat = mSwapChainImageFormat; + + createImage( + mSwapChainExtent.width, + mSwapChainExtent.height, + 1, + mMsaaSamples, + colorFormat, + vk::ImageTiling::eOptimal, + vk::ImageUsageFlagBits::eTransientAttachment | vk::ImageUsageFlagBits::eColorAttachment, + vk::MemoryPropertyFlagBits::eDeviceLocal, + mColorImage, + mColorImageMemory + ); + + mColorImageView = createImageView(mColorImage.get(), colorFormat, vk::ImageAspectFlagBits::eColor, 1); + } + fn createDepthResources() -> void { vk::Format depthFormat = findDepthFormat(); @@ -665,6 +704,7 @@ class VulkanApp { mSwapChainExtent.width, mSwapChainExtent.height, 1, + mMsaaSamples, depthFormat, vk::ImageTiling::eOptimal, vk::ImageUsageFlagBits::eDepthStencilAttachment, @@ -736,6 +776,7 @@ class VulkanApp { static_cast(texWidth), static_cast(texHeight), mMipLevels, + vk::SampleCountFlagBits::e1, vk::Format::eR8G8B8A8Srgb, vk::ImageTiling::eOptimal, vk::ImageUsageFlagBits::eTransferSrc | vk::ImageUsageFlagBits::eTransferDst | @@ -856,6 +897,28 @@ class VulkanApp { endSingleTimeCommands(std::move(commandBuffer)); } + fn getMaxUsableSampleCount() -> vk::SampleCountFlagBits { + vk::PhysicalDeviceProperties physicalDeviceProperties = mPhysicalDevice.getProperties(); + + vk::SampleCountFlags counts = physicalDeviceProperties.limits.framebufferColorSampleCounts & + physicalDeviceProperties.limits.framebufferDepthSampleCounts; + + if (counts & vk::SampleCountFlagBits::e64) + return vk::SampleCountFlagBits::e64; + if (counts & vk::SampleCountFlagBits::e32) + return vk::SampleCountFlagBits::e32; + if (counts & vk::SampleCountFlagBits::e16) + return vk::SampleCountFlagBits::e16; + if (counts & vk::SampleCountFlagBits::e8) + return vk::SampleCountFlagBits::e8; + if (counts & vk::SampleCountFlagBits::e4) + return vk::SampleCountFlagBits::e4; + if (counts & vk::SampleCountFlagBits::e2) + return vk::SampleCountFlagBits::e2; + + return vk::SampleCountFlagBits::e1; + } + fn createTextureImageView() -> void { mTextureImageView = createImageView( mTextureImage.get(), vk::Format::eR8G8B8A8Srgb, vk::ImageAspectFlagBits::eColor, mMipLevels @@ -905,6 +968,7 @@ class VulkanApp { u32 width, u32 height, u32 mipLevels, + vk::SampleCountFlagBits numSamples, vk::Format format, vk::ImageTiling tiling, vk::ImageUsageFlags usage, @@ -918,7 +982,7 @@ class VulkanApp { .extent = { .width = width, .height = height, .depth = 1 }, .mipLevels = mipLevels, .arrayLayers = 1, - .samples = vk::SampleCountFlagBits::e1, + .samples = numSamples, .tiling = tiling, .usage = usage, .sharingMode = vk::SharingMode::eExclusive,