From 7c85f8efaa6990bb8317d6521819eb07872c2849 Mon Sep 17 00:00:00 2001 From: Benjamin Kraft Date: Fri, 6 Sep 2024 18:56:43 +0200 Subject: [PATCH] depth testing --- src/vulkan/application.cpp | 17 +++--- src/vulkan/application.hpp | 6 +-- src/vulkan/buffer.cpp | 14 +---- src/vulkan/buffer.hpp | 2 - src/vulkan/image.cpp | 63 ++++++++++++++++++++++ src/vulkan/image.hpp | 19 +++++++ src/vulkan/pipeline.cpp | 8 +++ src/vulkan/swapchain.cpp | 108 ++++++++++++++++++++++++------------- src/vulkan/swapchain.hpp | 12 +++-- src/vulkan/utils.cpp | 17 ++++++ src/vulkan/utils.h | 3 ++ 11 files changed, 199 insertions(+), 70 deletions(-) create mode 100644 src/vulkan/image.cpp create mode 100644 src/vulkan/image.hpp create mode 100644 src/vulkan/utils.cpp create mode 100644 src/vulkan/utils.h diff --git a/src/vulkan/application.cpp b/src/vulkan/application.cpp index 69783b8..e3a8933 100644 --- a/src/vulkan/application.cpp +++ b/src/vulkan/application.cpp @@ -4,7 +4,7 @@ #include "instance.hpp" #include "buffer.hpp" #include "command_pool.hpp" - +#include "image.hpp" Application::Application() { @@ -34,8 +34,6 @@ Application::Application() { stagedVertexBuffer->copyTo(vertexBuffer, commandPool); stagedIndexBuffer->copyTo(indexBuffer, commandPool); - createDepthResources(); - delete stagedVertexBuffer; delete stagedIndexBuffer; @@ -71,9 +69,12 @@ void Application::recordCommandBuffer(VkCommandBuffer commandBuffer, uint32_t im renderPassInfo.renderArea.offset = {0, 0}; renderPassInfo.renderArea.extent = swapchain->extent; - VkClearValue clearColor = {{{0, 0, 0, 1}}}; - renderPassInfo.clearValueCount = 1; - renderPassInfo.pClearValues = &clearColor; + VkClearValue clearValues[2] {}; + clearValues[0].color = {{0, 0, 0, 1}}; + clearValues[1].depthStencil = {1.0f, 0}; + + renderPassInfo.clearValueCount = 2; + renderPassInfo.pClearValues = clearValues; vkCmdBeginRenderPass(commandBuffer, &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE); vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline->handle); @@ -199,10 +200,6 @@ Application::~Application() { delete Instance::instance; } -void Application::createDepthResources() { - -} - diff --git a/src/vulkan/application.hpp b/src/vulkan/application.hpp index f4ab997..d46a31f 100644 --- a/src/vulkan/application.hpp +++ b/src/vulkan/application.hpp @@ -19,6 +19,7 @@ class Swapchain; class Pipeline; class Buffer; class CommandPool; +class Image; constexpr int MAX_FRAMES_IN_FLIGHT = 1; @@ -50,11 +51,6 @@ private: void* uniformBufferMapped = nullptr; - VkImage depthImage = VK_NULL_HANDLE; - VkDeviceMemory depthImageMemory = VK_NULL_HANDLE; - VkImageView depthImageView = VK_NULL_HANDLE; - void createDepthResources(); - void updateUniformBuffer(); void recordCommandBuffer(VkCommandBuffer commandBuffer, uint32_t imageIndex); diff --git a/src/vulkan/buffer.cpp b/src/vulkan/buffer.cpp index ec48bce..e6c744c 100644 --- a/src/vulkan/buffer.cpp +++ b/src/vulkan/buffer.cpp @@ -4,6 +4,7 @@ #include "vertex.hpp" #include "instance.hpp" #include "command_pool.hpp" +#include "utils.h" Buffer::Buffer(VkDeviceSize size, VkBufferUsageFlags usage, VkMemoryPropertyFlags properties) : size(size){ VkBufferCreateInfo bufferInfo{}; @@ -27,19 +28,6 @@ Buffer::Buffer(VkDeviceSize size, VkBufferUsageFlags usage, VkMemoryPropertyFlag vkBindBufferMemory(Instance::instance->device, handle, memory, 0); } -uint32_t Buffer::findMemoryType(uint32_t typeFilter, VkMemoryPropertyFlags propertyFlags) { - VkPhysicalDeviceMemoryProperties memoryProperties; - vkGetPhysicalDeviceMemoryProperties(Instance::instance->physicalDevice, &memoryProperties); - - for (uint32_t type = 0; type < memoryProperties.memoryTypeCount; type++){ - if ((typeFilter & (1 << type)) && (memoryProperties.memoryTypes[type].propertyFlags & propertyFlags)){ - return type; - } - } - - throw std::runtime_error("failed to find suitable memory type!"); -} - Buffer::~Buffer() { vkFreeMemory(Instance::instance->device, memory, nullptr); vkDestroyBuffer(Instance::instance->device, handle, nullptr); diff --git a/src/vulkan/buffer.hpp b/src/vulkan/buffer.hpp index 979388b..2c1551a 100644 --- a/src/vulkan/buffer.hpp +++ b/src/vulkan/buffer.hpp @@ -26,6 +26,4 @@ public: void copyTo(Buffer* dst, CommandPool* commandPool); private: - - uint32_t findMemoryType(uint32_t typeFilter, VkMemoryPropertyFlags propertyFlags); }; \ No newline at end of file diff --git a/src/vulkan/image.cpp b/src/vulkan/image.cpp new file mode 100644 index 0000000..5ab6f37 --- /dev/null +++ b/src/vulkan/image.cpp @@ -0,0 +1,63 @@ +#include "image.hpp" +#include "instance.hpp" +#include "utils.h" + + +Image::Image(uint32_t width, uint32_t height, VkFormat format, VkImageTiling tiling, + VkImageUsageFlags usage, VkMemoryPropertyFlags properties) { + + VkImageCreateInfo imageCreateInfo {}; + imageCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; + imageCreateInfo.imageType = VK_IMAGE_TYPE_2D; + imageCreateInfo.extent.width = width; + imageCreateInfo.extent.height = height; + imageCreateInfo.extent.depth = 1; + imageCreateInfo.mipLevels = 1; + imageCreateInfo.arrayLayers = 1; + imageCreateInfo.format = format; + imageCreateInfo.tiling = tiling; + imageCreateInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + imageCreateInfo.usage = usage; + imageCreateInfo.samples = VK_SAMPLE_COUNT_1_BIT; + imageCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + + vkCreateImage(Instance::instance->device, &imageCreateInfo, nullptr, &handle); + + VkMemoryRequirements memoryRequirements; + vkGetImageMemoryRequirements(Instance::instance->device, handle, &memoryRequirements); + + VkMemoryAllocateInfo allocateInfo {}; + allocateInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; + allocateInfo.allocationSize = memoryRequirements.size; + allocateInfo.memoryTypeIndex = findMemoryType(memoryRequirements.memoryTypeBits, properties); + + vkAllocateMemory(Instance::instance->device, &allocateInfo, nullptr, &memory); + vkBindImageMemory(Instance::instance->device, handle, memory, 0); +} + +Image::~Image() { + vkFreeMemory(Instance::instance->device, memory, nullptr); + if (view) + vkDestroyImageView(Instance::instance->device, view, nullptr); + vkDestroyImage(Instance::instance->device, handle, nullptr); +} + +VkImageView Image::createView(VkFormat format, VkImageAspectFlags aspectFlags) { + VkImageSubresourceRange subresourceRange {}; + subresourceRange.aspectMask = aspectFlags; + subresourceRange.baseMipLevel = 0; + subresourceRange.levelCount = 1; + subresourceRange.baseArrayLayer = 0; + subresourceRange.layerCount = 1; + + VkImageViewCreateInfo createInfo {}; + createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; + createInfo.format = format; + createInfo.image = handle; + createInfo.viewType = VK_IMAGE_VIEW_TYPE_2D; + createInfo.subresourceRange = subresourceRange; + + vkCreateImageView(Instance::instance->device, &createInfo, nullptr, &view); + + return view; +} diff --git a/src/vulkan/image.hpp b/src/vulkan/image.hpp new file mode 100644 index 0000000..faa1a6d --- /dev/null +++ b/src/vulkan/image.hpp @@ -0,0 +1,19 @@ +#pragma once + +#include + +class Instance; + +class Image { +public: + explicit Image(uint32_t width, uint32_t height, VkFormat format, VkImageTiling tiling, + VkImageUsageFlags usage, VkMemoryPropertyFlags properties); + ~Image(); + + VkImageView createView(VkFormat format, VkImageAspectFlags aspectFlags); + + VkImage handle = VK_NULL_HANDLE; + VkImageView view = VK_NULL_HANDLE; +private: + VkDeviceMemory memory = VK_NULL_HANDLE; +}; \ No newline at end of file diff --git a/src/vulkan/pipeline.cpp b/src/vulkan/pipeline.cpp index 83f3400..c2591a6 100644 --- a/src/vulkan/pipeline.cpp +++ b/src/vulkan/pipeline.cpp @@ -102,6 +102,13 @@ Pipeline::Pipeline(VkRenderPass renderPass) { colorBlending.attachmentCount = 1; colorBlending.pAttachments = &colorBlendAttachment; + VkPipelineDepthStencilStateCreateInfo depthStencil {}; + depthStencil.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO; + depthStencil.depthTestEnable = VK_TRUE; + depthStencil.depthWriteEnable = VK_TRUE; + depthStencil.depthCompareOp = VK_COMPARE_OP_LESS; + depthStencil.stencilTestEnable = VK_FALSE; + VkPipelineLayoutCreateInfo pipelineLayoutInfo {}; pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; pipelineLayoutInfo.setLayoutCount = 1; @@ -123,6 +130,7 @@ Pipeline::Pipeline(VkRenderPass renderPass) { pipelineInfo.pMultisampleState = &multisample; pipelineInfo.pColorBlendState = &colorBlending; pipelineInfo.pDynamicState = &dynamicState; + pipelineInfo.pDepthStencilState = &depthStencil; pipelineInfo.layout = layout; diff --git a/src/vulkan/swapchain.cpp b/src/vulkan/swapchain.cpp index d5e52de..22a3686 100644 --- a/src/vulkan/swapchain.cpp +++ b/src/vulkan/swapchain.cpp @@ -2,6 +2,7 @@ #include #include "swapchain.hpp" #include "instance.hpp" +#include "image.hpp" SwapchainSupportDetails querySwapchainSupport(VkPhysicalDevice device, VkSurfaceKHR surface){ SwapchainSupportDetails details; @@ -29,6 +30,7 @@ Swapchain::Swapchain() { createSwapchain(); createImageViews(); createRenderpass(); + createDepthResources(); createFramebuffers(); } @@ -111,6 +113,7 @@ void Swapchain::cleanupSwapchain() { for (auto imageView : imageViews){ vkDestroyImageView(Instance::instance->device, imageView, nullptr); } + delete depthImage; vkDestroySwapchainKHR(Instance::instance->device, handle, nullptr); } @@ -121,6 +124,7 @@ void Swapchain::recreateSwapchain() { createSwapchain(); createImageViews(); + createDepthResources(); createFramebuffers(); } @@ -143,37 +147,6 @@ void Swapchain::createImageViews() { } } -void Swapchain::createFramebuffers() { - frameBuffers.resize(imageViews.size()); - for (size_t i = 0; i < imageViews.size(); i++){ - VkImageView attachments[] = {imageViews[i]}; - - VkFramebufferCreateInfo framebufferInfo {}; - framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; - framebufferInfo.renderPass = renderPass; - framebufferInfo.attachmentCount = 1; - framebufferInfo.pAttachments = attachments; - framebufferInfo.width = extent.width; - framebufferInfo.height = extent.height; - framebufferInfo.layers = 1; - - vkCreateFramebuffer(Instance::instance->device, &framebufferInfo, nullptr, &frameBuffers[i]); - } -} - -VkSurfaceFormatKHR Swapchain::chooseSwapSurfaceFormat(const std::vector &availableFormats) { - for (const auto& availableFormat : availableFormats){ - if (availableFormat.format == VK_FORMAT_B8G8R8A8_SRGB && availableFormat.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR){ - return availableFormat; - } - } - return availableFormats[0]; -} - -VkPresentModeKHR Swapchain::chooseSwapPresentMode(const std::vector &availablePresentModes) { - return VK_PRESENT_MODE_FIFO_KHR; -} - void Swapchain::createRenderpass() { VkAttachmentDescription colorAttachment {}; colorAttachment.format = imageFormat; @@ -185,27 +158,44 @@ void Swapchain::createRenderpass() { colorAttachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; colorAttachment.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; + VkAttachmentDescription depthAttachment {}; + depthAttachment.format = VK_FORMAT_D32_SFLOAT; + depthAttachment.samples = VK_SAMPLE_COUNT_1_BIT; + depthAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; + depthAttachment.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + depthAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + depthAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + depthAttachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + depthAttachment.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + + VkAttachmentDescription attachments[2] = {colorAttachment, depthAttachment}; + VkAttachmentReference colorAttachmentRef {}; colorAttachmentRef.attachment = 0; colorAttachmentRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + VkAttachmentReference depthAttachmentRef {}; + depthAttachmentRef.attachment = 1; + depthAttachmentRef.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + VkSubpassDescription subpass {}; subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; subpass.colorAttachmentCount = 1; subpass.pColorAttachments = &colorAttachmentRef; + subpass.pDepthStencilAttachment = &depthAttachmentRef; VkSubpassDependency dependency {}; dependency.srcSubpass = VK_SUBPASS_EXTERNAL; dependency.dstSubpass = 0; - dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT; dependency.srcAccessMask = 0; - dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT; + dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; VkRenderPassCreateInfo renderPassInfo {}; renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; - renderPassInfo.attachmentCount = 1; - renderPassInfo.pAttachments = &colorAttachment; + renderPassInfo.attachmentCount = 2; + renderPassInfo.pAttachments = attachments; renderPassInfo.subpassCount = 1; renderPassInfo.pSubpasses = &subpass; renderPassInfo.dependencyCount = 1; @@ -213,3 +203,49 @@ void Swapchain::createRenderpass() { vkCreateRenderPass(Instance::instance->device, &renderPassInfo, nullptr, &renderPass); } + +void Swapchain::createDepthResources() { + depthImage = new Image( + extent.width, + extent.height, + VK_FORMAT_D32_SFLOAT, + VK_IMAGE_TILING_OPTIMAL, + VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT + ); + depthImage->createView(VK_FORMAT_D32_SFLOAT, VK_IMAGE_ASPECT_DEPTH_BIT); +} + +void Swapchain::createFramebuffers() { + frameBuffers.resize(imageViews.size()); + for (size_t i = 0; i < imageViews.size(); i++){ + VkImageView attachments[] = { + imageViews[i], + depthImage->view + }; + + VkFramebufferCreateInfo framebufferInfo {}; + framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; + framebufferInfo.renderPass = renderPass; + framebufferInfo.attachmentCount = 2; + framebufferInfo.pAttachments = attachments; + framebufferInfo.width = extent.width; + framebufferInfo.height = extent.height; + framebufferInfo.layers = 1; + + vkCreateFramebuffer(Instance::instance->device, &framebufferInfo, nullptr, &frameBuffers[i]); + } +} + +VkSurfaceFormatKHR Swapchain::chooseSwapSurfaceFormat(const std::vector &availableFormats) { + for (const auto& availableFormat : availableFormats){ + if (availableFormat.format == VK_FORMAT_B8G8R8A8_SRGB && availableFormat.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR){ + return availableFormat; + } + } + return availableFormats[0]; +} + +VkPresentModeKHR Swapchain::chooseSwapPresentMode(const std::vector &availablePresentModes) { + return VK_PRESENT_MODE_FIFO_KHR; +} diff --git a/src/vulkan/swapchain.hpp b/src/vulkan/swapchain.hpp index 7de23dc..ea7c70b 100644 --- a/src/vulkan/swapchain.hpp +++ b/src/vulkan/swapchain.hpp @@ -3,6 +3,7 @@ #include #include +class Image; class Instance; struct SwapchainSupportDetails { @@ -28,7 +29,14 @@ private: std::vector images; VkFormat imageFormat {}; + std::vector imageViews; + void createImageViews(); + void createRenderpass(); + + Image* depthImage = nullptr; + void createDepthResources(); + void createFramebuffers(); static VkSurfaceFormatKHR chooseSwapSurfaceFormat(const std::vector& availableFormats); @@ -37,8 +45,4 @@ private: VkExtent2D chooseSwapExtent(const VkSurfaceCapabilitiesKHR& capabilities); void createSwapchain(); - - std::vector imageViews; - - void createImageViews(); }; \ No newline at end of file diff --git a/src/vulkan/utils.cpp b/src/vulkan/utils.cpp new file mode 100644 index 0000000..95338c2 --- /dev/null +++ b/src/vulkan/utils.cpp @@ -0,0 +1,17 @@ +#include +#include "utils.h" + +#include "instance.hpp" + +uint32_t findMemoryType(uint32_t typeFilter, VkMemoryPropertyFlags propertyFlags) { + VkPhysicalDeviceMemoryProperties memoryProperties; + vkGetPhysicalDeviceMemoryProperties(Instance::instance->physicalDevice, &memoryProperties); + + for (uint32_t type = 0; type < memoryProperties.memoryTypeCount; type++){ + if ((typeFilter & (1 << type)) && (memoryProperties.memoryTypes[type].propertyFlags & propertyFlags)){ + return type; + } + } + + throw std::runtime_error("failed to find suitable memory type!"); +} \ No newline at end of file diff --git a/src/vulkan/utils.h b/src/vulkan/utils.h new file mode 100644 index 0000000..97a3834 --- /dev/null +++ b/src/vulkan/utils.h @@ -0,0 +1,3 @@ +#include + +uint32_t findMemoryType(uint32_t typeFilter, VkMemoryPropertyFlags propertyFlags); \ No newline at end of file