Add depth testing
This commit is contained in:
		
							parent
							
								
									47a2ea4ebf
								
							
						
					
					
						commit
						b0e204f03c
					
				@ -75,29 +75,22 @@ namespace nf::client::render {
 | 
			
		||||
        VkCommandBufferAllocateInfo commandBufferAI = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO };
 | 
			
		||||
        commandBufferAI.commandPool = commandPool;
 | 
			
		||||
        commandBufferAI.commandBufferCount = 1;
 | 
			
		||||
 | 
			
		||||
        if (vkAllocateCommandBuffers(m_device, &commandBufferAI, &commandBuffer) != VK_SUCCESS)
 | 
			
		||||
            NFError("Could not create command buffer.");
 | 
			
		||||
        vkAllocateCommandBuffers(m_device, &commandBufferAI, &commandBuffer);
 | 
			
		||||
 | 
			
		||||
        VkCommandBufferBeginInfo commandBufferBI = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO };
 | 
			
		||||
        commandBufferBI.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
 | 
			
		||||
 | 
			
		||||
        vkBeginCommandBuffer(commandBuffer, &commandBufferBI);
 | 
			
		||||
 | 
			
		||||
        VkBufferCopy bufferCopyRegion = {};
 | 
			
		||||
        bufferCopyRegion.size = size;
 | 
			
		||||
        vkCmdCopyBuffer(commandBuffer, bufferSource, bufferDestination, 1, &bufferCopyRegion);
 | 
			
		||||
 | 
			
		||||
        if (vkEndCommandBuffer(commandBuffer) != VK_SUCCESS)
 | 
			
		||||
            NFError("Could not end command buffer.");
 | 
			
		||||
        vkEndCommandBuffer(commandBuffer);
 | 
			
		||||
 | 
			
		||||
        VkSubmitInfo submitInfo = { VK_STRUCTURE_TYPE_SUBMIT_INFO };
 | 
			
		||||
        submitInfo.commandBufferCount = 1;
 | 
			
		||||
        submitInfo.pCommandBuffers = &commandBuffer;
 | 
			
		||||
 | 
			
		||||
        if (vkQueueSubmit(queue, 1, &submitInfo, nullptr) != VK_SUCCESS)
 | 
			
		||||
            NFError("Could not submit to Vulkan queue.");
 | 
			
		||||
 | 
			
		||||
        vkQueueSubmit(queue, 1, &submitInfo, nullptr);
 | 
			
		||||
        vkQueueWaitIdle(queue);
 | 
			
		||||
 | 
			
		||||
        vkFreeCommandBuffers(m_device, commandPool, 1, &commandBuffer);
 | 
			
		||||
 | 
			
		||||
@ -9,36 +9,46 @@
 | 
			
		||||
#include "stb_image.h"
 | 
			
		||||
 | 
			
		||||
namespace nf::client::render {
 | 
			
		||||
    Image::Image(const VkDevice& device, VideoMemoryAllocator& allocator, const VkCommandPool& commandPool, const VkQueue& queue, const std::string& imageData)
 | 
			
		||||
    Image::Image(ImageType type, const VkDevice& device, VideoMemoryAllocator& allocator, const VkCommandPool& commandPool, const VkQueue& queue, const std::string& imageData, VkExtent2D attachmentExtent)
 | 
			
		||||
        : GraphicsResource(device)
 | 
			
		||||
        , m_allocator(allocator)
 | 
			
		||||
        , m_handle()
 | 
			
		||||
        , m_allocation()
 | 
			
		||||
        , m_view()
 | 
			
		||||
    {
 | 
			
		||||
        VkFormat imageFormat = VK_FORMAT_UNDEFINED;
 | 
			
		||||
 | 
			
		||||
        switch (type) {
 | 
			
		||||
            case ImageType::Texture:
 | 
			
		||||
                imageFormat = VK_FORMAT_R8G8B8A8_SRGB;
 | 
			
		||||
                createTextureImage(imageFormat, commandPool, queue, imageData);
 | 
			
		||||
                break;
 | 
			
		||||
 | 
			
		||||
            case ImageType::DepthAttachment:
 | 
			
		||||
                imageFormat = VK_FORMAT_D32_SFLOAT;
 | 
			
		||||
                createImage(imageFormat, attachmentExtent, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT);
 | 
			
		||||
                break;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        createImageView(imageFormat);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const VkImageView& Image::getView() const {
 | 
			
		||||
        return m_view;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void Image::createTextureImage(VkFormat imageFormat, const VkCommandPool& commandPool, const VkQueue& queue, const std::string& imageData) {
 | 
			
		||||
        int imageWidth = 0, imageHeight = 0, numChannels = 0;
 | 
			
		||||
        stbi_uc* rawImageData = stbi_load_from_memory(reinterpret_cast<const stbi_uc*>(imageData.data()), imageData.size(), &imageWidth, &imageHeight, &numChannels, STBI_rgb_alpha);
 | 
			
		||||
 | 
			
		||||
        VkDeviceSize imageSize = imageWidth * imageHeight * 4;
 | 
			
		||||
        VkDeviceSize imageSize = static_cast<VkDeviceSize>(imageWidth) * imageHeight * 4;
 | 
			
		||||
 | 
			
		||||
        Buffer stagingBuffer(BufferType::Staging, m_device, m_allocator, nullptr, nullptr, rawImageData, imageSize);
 | 
			
		||||
 | 
			
		||||
        stbi_image_free(rawImageData);
 | 
			
		||||
 | 
			
		||||
        VkImageCreateInfo imageCI = { VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO };
 | 
			
		||||
        imageCI.imageType = VK_IMAGE_TYPE_2D;
 | 
			
		||||
        imageCI.extent.width = imageWidth, imageCI.extent.height = imageHeight, imageCI.extent.depth = 1;
 | 
			
		||||
        imageCI.mipLevels = 1;
 | 
			
		||||
        imageCI.arrayLayers = 1;
 | 
			
		||||
        imageCI.samples = VK_SAMPLE_COUNT_1_BIT;
 | 
			
		||||
        imageCI.format = VK_FORMAT_R8G8B8A8_SRGB;
 | 
			
		||||
        imageCI.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;
 | 
			
		||||
        imageCI.tiling = VK_IMAGE_TILING_OPTIMAL;
 | 
			
		||||
 | 
			
		||||
        if (vkCreateImage(m_device, &imageCI, nullptr, &m_handle) != VK_SUCCESS)
 | 
			
		||||
            NFError("Could not create image.");
 | 
			
		||||
 | 
			
		||||
        m_allocator.allocateForImage(m_handle, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, m_allocation);
 | 
			
		||||
        VkExtent2D imageExtent = { static_cast<uint32_t>(imageWidth), static_cast<uint32_t>(imageHeight) };
 | 
			
		||||
        createImage(imageFormat, imageExtent, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT);
 | 
			
		||||
 | 
			
		||||
        VkCommandBuffer commandBuffer = nullptr;
 | 
			
		||||
        VkCommandBufferAllocateInfo commandBufferAI = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO };
 | 
			
		||||
@ -48,7 +58,6 @@ namespace nf::client::render {
 | 
			
		||||
 | 
			
		||||
        VkCommandBufferBeginInfo commandBufferBI = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO };
 | 
			
		||||
        commandBufferBI.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
 | 
			
		||||
 | 
			
		||||
        vkBeginCommandBuffer(commandBuffer, &commandBufferBI);
 | 
			
		||||
 | 
			
		||||
        // Image transition undefined -> transfer destination
 | 
			
		||||
@ -63,6 +72,7 @@ namespace nf::client::render {
 | 
			
		||||
        imageMemoryBarrier.srcAccessMask = 0;
 | 
			
		||||
        imageMemoryBarrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
 | 
			
		||||
        vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, 0, nullptr, 1, &imageMemoryBarrier);
 | 
			
		||||
 | 
			
		||||
        vkEndCommandBuffer(commandBuffer);
 | 
			
		||||
 | 
			
		||||
        VkSubmitInfo submitInfo = { VK_STRUCTURE_TYPE_SUBMIT_INFO };
 | 
			
		||||
@ -91,18 +101,41 @@ namespace nf::client::render {
 | 
			
		||||
        imageMemoryBarrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
 | 
			
		||||
        imageMemoryBarrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
 | 
			
		||||
        vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 0, nullptr, 0, nullptr, 1, &imageMemoryBarrier);
 | 
			
		||||
 | 
			
		||||
        vkEndCommandBuffer(commandBuffer);
 | 
			
		||||
        vkQueueSubmit(queue, 1, &submitInfo, nullptr);
 | 
			
		||||
        vkQueueWaitIdle(queue);
 | 
			
		||||
 | 
			
		||||
        vkFreeCommandBuffers(m_device, commandPool, 1, &commandBuffer);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void Image::createImage(VkFormat format, VkExtent2D& size, VkImageUsageFlags usage) {
 | 
			
		||||
        VkImageCreateInfo imageCI = { VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO };
 | 
			
		||||
        imageCI.imageType = VK_IMAGE_TYPE_2D;
 | 
			
		||||
        imageCI.extent = { size.width, size.height, 1 };
 | 
			
		||||
        imageCI.mipLevels = 1;
 | 
			
		||||
        imageCI.arrayLayers = 1;
 | 
			
		||||
        imageCI.samples = VK_SAMPLE_COUNT_1_BIT;
 | 
			
		||||
        imageCI.format = format;
 | 
			
		||||
        imageCI.usage = usage;
 | 
			
		||||
        imageCI.tiling = VK_IMAGE_TILING_OPTIMAL;
 | 
			
		||||
 | 
			
		||||
        if (vkCreateImage(m_device, &imageCI, nullptr, &m_handle) != VK_SUCCESS)
 | 
			
		||||
            NFError("Could not create image.");
 | 
			
		||||
 | 
			
		||||
        m_allocator.allocateForImage(m_handle, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, m_allocation);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void Image::createImageView(VkFormat format) {
 | 
			
		||||
        VkImageAspectFlags aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
 | 
			
		||||
        if (format == VK_FORMAT_D32_SFLOAT)
 | 
			
		||||
            aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
 | 
			
		||||
 | 
			
		||||
        // Create image view
 | 
			
		||||
        VkImageViewCreateInfo imageViewCI = { VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO };
 | 
			
		||||
        imageViewCI.image = m_handle;
 | 
			
		||||
        imageViewCI.viewType = VK_IMAGE_VIEW_TYPE_2D;
 | 
			
		||||
        imageViewCI.format = VK_FORMAT_R8G8B8A8_SRGB;
 | 
			
		||||
        imageViewCI.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
 | 
			
		||||
        imageViewCI.format = format;
 | 
			
		||||
        imageViewCI.subresourceRange.aspectMask = aspectMask;
 | 
			
		||||
        imageViewCI.subresourceRange.levelCount = 1;
 | 
			
		||||
        imageViewCI.subresourceRange.layerCount = 1;
 | 
			
		||||
 | 
			
		||||
@ -110,10 +143,6 @@ namespace nf::client::render {
 | 
			
		||||
            NFError("Could not create image view.");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const VkImageView& Image::getView() const {
 | 
			
		||||
        return m_view;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    Image::~Image() {
 | 
			
		||||
        vkDestroyImageView(m_device, m_view, nullptr);
 | 
			
		||||
        m_allocator.deallocate(m_allocation);
 | 
			
		||||
 | 
			
		||||
@ -5,14 +5,23 @@
 | 
			
		||||
#include "VideoMemoryAllocator.h"
 | 
			
		||||
 | 
			
		||||
namespace nf::client::render {
 | 
			
		||||
    enum class ImageType {
 | 
			
		||||
        Texture,
 | 
			
		||||
        DepthAttachment
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    class Image : GraphicsResource {
 | 
			
		||||
    public:
 | 
			
		||||
        Image(const VkDevice& device, VideoMemoryAllocator& allocator, const VkCommandPool& commandPool, const VkQueue& queue, const std::string& data);
 | 
			
		||||
        Image(ImageType type, const VkDevice& device, VideoMemoryAllocator& allocator, const VkCommandPool& commandPool, const VkQueue& queue, const std::string& imageData, VkExtent2D attachmentExtent = {});
 | 
			
		||||
 | 
			
		||||
        const VkImageView& getView() const;
 | 
			
		||||
 | 
			
		||||
        ~Image();
 | 
			
		||||
    private:
 | 
			
		||||
        void createTextureImage(VkFormat imageFormat, const VkCommandPool& commandPool, const VkQueue& queue, const std::string& imageData);
 | 
			
		||||
        void createImage(VkFormat imageFormat, VkExtent2D& size, VkImageUsageFlags usage);
 | 
			
		||||
        void createImageView(VkFormat format);
 | 
			
		||||
 | 
			
		||||
        VideoMemoryAllocator& m_allocator;
 | 
			
		||||
 | 
			
		||||
        VkImage m_handle;
 | 
			
		||||
 | 
			
		||||
@ -29,7 +29,6 @@ namespace nf::client::render {
 | 
			
		||||
        , m_swapchainExtent()
 | 
			
		||||
        , m_swapchainImages()
 | 
			
		||||
        , m_swapchainImageViews()
 | 
			
		||||
        , m_swapchainFramebuffers()
 | 
			
		||||
        , m_pipelineOutputDescriptorSetLayout()
 | 
			
		||||
        , m_pipelineOutputLayout()
 | 
			
		||||
        , m_pipelineOutputDescriptorPool()
 | 
			
		||||
@ -40,6 +39,8 @@ namespace nf::client::render {
 | 
			
		||||
        , m_semaphoreRenderingDone()
 | 
			
		||||
        , m_fenceFrameInFlight()
 | 
			
		||||
        , m_allocator()
 | 
			
		||||
        , m_swapchainFramebuffers()
 | 
			
		||||
        , m_imageDepth()
 | 
			
		||||
        , m_bufferVertex()
 | 
			
		||||
        , m_bufferIndex()
 | 
			
		||||
        , m_imageTest()
 | 
			
		||||
@ -56,11 +57,11 @@ namespace nf::client::render {
 | 
			
		||||
        createDevice();
 | 
			
		||||
        createSwapchain();
 | 
			
		||||
        createOutputRenderPass();
 | 
			
		||||
        createSwapchainFramebuffers();
 | 
			
		||||
        createOutputPipeline();
 | 
			
		||||
        createExecutionObjects();
 | 
			
		||||
 | 
			
		||||
        m_allocator = std::make_unique<VideoMemoryAllocator>(m_device, m_physicalDevice);
 | 
			
		||||
        createSwapchainFramebuffers();
 | 
			
		||||
        createBuffers();
 | 
			
		||||
        createImage();
 | 
			
		||||
        createDescriptorSet();
 | 
			
		||||
@ -285,34 +286,46 @@ namespace nf::client::render {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void RenderEngine::createOutputRenderPass() {
 | 
			
		||||
        VkAttachmentDescription outputColorAttachment = {};
 | 
			
		||||
        outputColorAttachment.format = m_swapchainImageFormat;
 | 
			
		||||
        outputColorAttachment.samples = VK_SAMPLE_COUNT_1_BIT;
 | 
			
		||||
        outputColorAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
 | 
			
		||||
        outputColorAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
 | 
			
		||||
        outputColorAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
 | 
			
		||||
        outputColorAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
 | 
			
		||||
        outputColorAttachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
 | 
			
		||||
        outputColorAttachment.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
 | 
			
		||||
        VkAttachmentDescription attachmentDescriptions[2] = {};
 | 
			
		||||
 | 
			
		||||
        VkAttachmentReference outputColorAttachmentReference = {};
 | 
			
		||||
        outputColorAttachmentReference.attachment = 0;
 | 
			
		||||
        outputColorAttachmentReference.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
 | 
			
		||||
        // Color attachment
 | 
			
		||||
        attachmentDescriptions[0].format = m_swapchainImageFormat;
 | 
			
		||||
        attachmentDescriptions[0].samples = VK_SAMPLE_COUNT_1_BIT;
 | 
			
		||||
        attachmentDescriptions[0].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
 | 
			
		||||
        attachmentDescriptions[0].storeOp = VK_ATTACHMENT_STORE_OP_STORE;
 | 
			
		||||
        attachmentDescriptions[0].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
 | 
			
		||||
        attachmentDescriptions[0].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
 | 
			
		||||
        attachmentDescriptions[0].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
 | 
			
		||||
        attachmentDescriptions[0].finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
 | 
			
		||||
 | 
			
		||||
        // Depth attachment
 | 
			
		||||
        attachmentDescriptions[1] = attachmentDescriptions[0];
 | 
			
		||||
        attachmentDescriptions[1].format = VK_FORMAT_D32_SFLOAT;
 | 
			
		||||
        attachmentDescriptions[1].finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
 | 
			
		||||
 | 
			
		||||
        VkAttachmentReference attachmentReferences[2] = {};
 | 
			
		||||
        attachmentReferences[0].attachment = 0;
 | 
			
		||||
        attachmentReferences[0].layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
 | 
			
		||||
        attachmentReferences[1].attachment = 1;
 | 
			
		||||
        attachmentReferences[1].layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
 | 
			
		||||
 | 
			
		||||
        VkSubpassDescription subpassDescription = {};
 | 
			
		||||
        subpassDescription.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
 | 
			
		||||
        subpassDescription.colorAttachmentCount = 1;
 | 
			
		||||
        subpassDescription.pColorAttachments = &outputColorAttachmentReference;
 | 
			
		||||
        subpassDescription.pColorAttachments = &attachmentReferences[0];
 | 
			
		||||
        subpassDescription.pDepthStencilAttachment = &attachmentReferences[1];
 | 
			
		||||
 | 
			
		||||
        VkSubpassDependency dependency = {};
 | 
			
		||||
        dependency.srcSubpass = VK_SUBPASS_EXTERNAL;
 | 
			
		||||
        dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
 | 
			
		||||
        dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
 | 
			
		||||
        dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
 | 
			
		||||
        dependency.dstSubpass = 0;
 | 
			
		||||
        dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
 | 
			
		||||
        dependency.srcAccessMask = VK_ACCESS_DEPTH_STENCIL_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 renderPassCI = { VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO };
 | 
			
		||||
        renderPassCI.attachmentCount = 1;
 | 
			
		||||
        renderPassCI.pAttachments = &outputColorAttachment;
 | 
			
		||||
        renderPassCI.attachmentCount = 2;
 | 
			
		||||
        renderPassCI.pAttachments = attachmentDescriptions;
 | 
			
		||||
        renderPassCI.subpassCount = 1;
 | 
			
		||||
        renderPassCI.pSubpasses = &subpassDescription;
 | 
			
		||||
        renderPassCI.dependencyCount = 1;
 | 
			
		||||
@ -322,22 +335,6 @@ namespace nf::client::render {
 | 
			
		||||
            NFError("Could not create Vulkan output render pass.");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void RenderEngine::createSwapchainFramebuffers() {
 | 
			
		||||
        // TODO: Won't need these forever
 | 
			
		||||
        m_swapchainFramebuffers.resize(m_swapchainImageViews.size());
 | 
			
		||||
        for (int i = 0; i < m_swapchainImageViews.size(); i++) {
 | 
			
		||||
            VkFramebufferCreateInfo framebufferCI = { VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO };
 | 
			
		||||
            framebufferCI.renderPass = m_renderPassOutput;
 | 
			
		||||
            framebufferCI.attachmentCount = 1;
 | 
			
		||||
            framebufferCI.pAttachments = &m_swapchainImageViews[i];
 | 
			
		||||
            framebufferCI.width = m_swapchainExtent.width, framebufferCI.height = m_swapchainExtent.height;
 | 
			
		||||
            framebufferCI.layers = 1;
 | 
			
		||||
 | 
			
		||||
            if (vkCreateFramebuffer(m_device, &framebufferCI, nullptr, &m_swapchainFramebuffers[i]) != VK_SUCCESS)
 | 
			
		||||
                NFError("Could not create framebuffer.");
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void RenderEngine::createOutputPipeline() {
 | 
			
		||||
        // First, create shader modules
 | 
			
		||||
        std::string outputShaderVertexBinary, outputShaderFragmentBinary;
 | 
			
		||||
@ -365,7 +362,7 @@ namespace nf::client::render {
 | 
			
		||||
        VkPipelineVertexInputStateCreateInfo vertexInputStateCI = { VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO };
 | 
			
		||||
        VkVertexInputBindingDescription vertexBindingDescription = {};
 | 
			
		||||
        vertexBindingDescription.stride = sizeof(Vertex);
 | 
			
		||||
        std::array<VkVertexInputAttributeDescription, 2> vertexAttributeDescriptions = {};
 | 
			
		||||
        VkVertexInputAttributeDescription vertexAttributeDescriptions[2] = {};
 | 
			
		||||
        vertexAttributeDescriptions[0].location = 0;
 | 
			
		||||
        vertexAttributeDescriptions[0].format = VK_FORMAT_R32G32B32_SFLOAT;
 | 
			
		||||
        vertexAttributeDescriptions[0].offset = offsetof(Vertex, position);
 | 
			
		||||
@ -374,8 +371,8 @@ namespace nf::client::render {
 | 
			
		||||
        vertexAttributeDescriptions[1].offset = offsetof(Vertex, textureCoordinates);
 | 
			
		||||
        vertexInputStateCI.vertexBindingDescriptionCount = 1;
 | 
			
		||||
        vertexInputStateCI.pVertexBindingDescriptions = &vertexBindingDescription;
 | 
			
		||||
        vertexInputStateCI.vertexAttributeDescriptionCount = vertexAttributeDescriptions.size();
 | 
			
		||||
        vertexInputStateCI.pVertexAttributeDescriptions = vertexAttributeDescriptions.data();
 | 
			
		||||
        vertexInputStateCI.vertexAttributeDescriptionCount = 2;
 | 
			
		||||
        vertexInputStateCI.pVertexAttributeDescriptions = vertexAttributeDescriptions;
 | 
			
		||||
 | 
			
		||||
        // Specify input assembly state
 | 
			
		||||
        VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateCI = { VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO };
 | 
			
		||||
@ -396,6 +393,12 @@ namespace nf::client::render {
 | 
			
		||||
        VkPipelineMultisampleStateCreateInfo multisampleStateCI = { VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO };
 | 
			
		||||
        multisampleStateCI.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
 | 
			
		||||
 | 
			
		||||
        // Specify depth stencil state
 | 
			
		||||
        VkPipelineDepthStencilStateCreateInfo depthStencilStateCI = { VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO };
 | 
			
		||||
        depthStencilStateCI.depthTestEnable = VK_TRUE;
 | 
			
		||||
        depthStencilStateCI.depthWriteEnable = VK_TRUE;
 | 
			
		||||
        depthStencilStateCI.depthCompareOp = VK_COMPARE_OP_LESS;
 | 
			
		||||
 | 
			
		||||
        // Specify color blend state
 | 
			
		||||
        VkPipelineColorBlendAttachmentState colorBlendAttachmentState = {};
 | 
			
		||||
        colorBlendAttachmentState.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
 | 
			
		||||
@ -452,6 +455,7 @@ namespace nf::client::render {
 | 
			
		||||
        pipelineCI.pViewportState = &viewportStateCI;
 | 
			
		||||
        pipelineCI.pRasterizationState = &rasterizationCI;
 | 
			
		||||
        pipelineCI.pMultisampleState = &multisampleStateCI;
 | 
			
		||||
        pipelineCI.pDepthStencilState = &depthStencilStateCI;
 | 
			
		||||
        pipelineCI.pColorBlendState = &colorBlendStateCI;
 | 
			
		||||
        pipelineCI.pDynamicState = &dynamicStateCI;
 | 
			
		||||
        pipelineCI.layout = m_pipelineOutputLayout;
 | 
			
		||||
@ -487,6 +491,27 @@ namespace nf::client::render {
 | 
			
		||||
            NFError("Could not create fence.");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void RenderEngine::createSwapchainFramebuffers() {
 | 
			
		||||
        // TODO: Won't need these forever
 | 
			
		||||
 | 
			
		||||
        // Create depth buffer first
 | 
			
		||||
        m_imageDepth = std::make_unique<Image>(ImageType::DepthAttachment, m_device, *m_allocator, nullptr, nullptr, std::string(), m_swapchainExtent);
 | 
			
		||||
 | 
			
		||||
        m_swapchainFramebuffers.resize(m_swapchainImageViews.size());
 | 
			
		||||
        for (int i = 0; i < m_swapchainImageViews.size(); i++) {
 | 
			
		||||
            VkFramebufferCreateInfo framebufferCI = { VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO };
 | 
			
		||||
            framebufferCI.renderPass = m_renderPassOutput;
 | 
			
		||||
            VkImageView views[] = { m_swapchainImageViews[i], m_imageDepth->getView() };
 | 
			
		||||
            framebufferCI.attachmentCount = 2;
 | 
			
		||||
            framebufferCI.pAttachments = views;
 | 
			
		||||
            framebufferCI.width = m_swapchainExtent.width, framebufferCI.height = m_swapchainExtent.height;
 | 
			
		||||
            framebufferCI.layers = 1;
 | 
			
		||||
 | 
			
		||||
            if (vkCreateFramebuffer(m_device, &framebufferCI, nullptr, &m_swapchainFramebuffers[i]) != VK_SUCCESS)
 | 
			
		||||
                NFError("Could not create framebuffer.");
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void RenderEngine::createBuffers() {
 | 
			
		||||
        std::vector<Vertex> cubeVertices = {
 | 
			
		||||
            {{-0.5, -0.5,  0.5}, {0.0, 1.0}},
 | 
			
		||||
@ -517,7 +542,11 @@ namespace nf::client::render {
 | 
			
		||||
            {{ 0.5,  0.5, -0.5}, {1.0, 0.0}},
 | 
			
		||||
            {{-0.5,  0.5, -0.5}, {0.0, 0.0}},
 | 
			
		||||
            {{-0.5, -0.5, -0.5}, {0.0, 1.0}},
 | 
			
		||||
            {{ 0.5, -0.5, -0.5}, {1.0, 1.0}}
 | 
			
		||||
            {{ 0.5, -0.5, -0.5}, {1.0, 1.0}},
 | 
			
		||||
 | 
			
		||||
            {{ 0.5, -0.6,  0.5}, {1.0, 1.0}},
 | 
			
		||||
            {{ 0.5, -0.6, -0.5}, {1.0, 0.0}},
 | 
			
		||||
            {{-0.5, -0.6,  0.5}, {0.0, 1.0}}
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        size_t cubeVerticesSize = sizeof(cubeVertices[0]) * cubeVertices.size();
 | 
			
		||||
@ -540,7 +569,9 @@ namespace nf::client::render {
 | 
			
		||||
            17, 19, 18,
 | 
			
		||||
 | 
			
		||||
            20, 23, 21,
 | 
			
		||||
            23, 22, 21
 | 
			
		||||
            23, 22, 21,
 | 
			
		||||
 | 
			
		||||
            24, 25, 26
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        size_t cubeIndicesSize = sizeof(cubeIndices[0]) * cubeIndices.size();
 | 
			
		||||
@ -553,7 +584,7 @@ namespace nf::client::render {
 | 
			
		||||
    void RenderEngine::createImage() {
 | 
			
		||||
        std::string imageData;
 | 
			
		||||
        util::readFile("grayson.jpg", imageData);
 | 
			
		||||
        m_imageTest = std::make_unique<Image>(m_device, *m_allocator, m_commandPool, m_queueGraphics, imageData);
 | 
			
		||||
        m_imageTest = std::make_unique<Image>(ImageType::Texture, m_device, *m_allocator, m_commandPool, m_queueGraphics, imageData);
 | 
			
		||||
 | 
			
		||||
        VkSamplerCreateInfo samplerCI = { VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO };
 | 
			
		||||
        samplerCI.magFilter = samplerCI.minFilter = VK_FILTER_LINEAR;
 | 
			
		||||
@ -617,13 +648,13 @@ namespace nf::client::render {
 | 
			
		||||
        vkBeginCommandBuffer(m_commandBuffer, &commandBufferBI);
 | 
			
		||||
 | 
			
		||||
        // Start the render pass
 | 
			
		||||
        VkClearValue black = { {{0.0, 0.0, 0.0, 1.0}} };
 | 
			
		||||
        VkClearValue clearValues[] = { {{0.0, 0.0, 0.0, 1.0}}, {1.0, 0} };
 | 
			
		||||
        VkRenderPassBeginInfo renderPassBI = { VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO };
 | 
			
		||||
        renderPassBI.renderPass = m_renderPassOutput;
 | 
			
		||||
        renderPassBI.framebuffer = m_swapchainFramebuffers[nextImageIndex];
 | 
			
		||||
        renderPassBI.renderArea.extent = m_swapchainExtent;
 | 
			
		||||
        renderPassBI.clearValueCount = 1;
 | 
			
		||||
        renderPassBI.pClearValues = &black;
 | 
			
		||||
        renderPassBI.clearValueCount = 2;
 | 
			
		||||
        renderPassBI.pClearValues = clearValues;
 | 
			
		||||
        vkCmdBeginRenderPass(m_commandBuffer, &renderPassBI, VK_SUBPASS_CONTENTS_INLINE);
 | 
			
		||||
 | 
			
		||||
        // Bind output pipeline
 | 
			
		||||
@ -646,7 +677,7 @@ namespace nf::client::render {
 | 
			
		||||
        static auto startTime = std::chrono::high_resolution_clock::now();
 | 
			
		||||
        auto currentTime = std::chrono::high_resolution_clock::now();
 | 
			
		||||
        float time = std::chrono::duration<float>(currentTime - startTime).count();
 | 
			
		||||
        glm::mat4 modelMatrix = glm::rotate(glm::mat4(1.0), time * glm::radians(20.0f), glm::vec3(0.0, 0.0, 1.0)),
 | 
			
		||||
        glm::mat4 modelMatrix = glm::rotate(glm::mat4(1.0), time * glm::radians(20.0f), glm::vec3(0.0, 1.0, 0.0)),
 | 
			
		||||
            viewMatrix = glm::lookAt(glm::vec3(1.0, 1.0, 2.0), glm::vec3(0.0), glm::vec3(0.0, 1.0, 0.0)),
 | 
			
		||||
            projectionMatrix = glm::perspective(glm::radians(45.0f), static_cast<float>(m_swapchainExtent.width) / m_swapchainExtent.height, 0.1f, 10.0f);
 | 
			
		||||
 | 
			
		||||
@ -664,8 +695,7 @@ namespace nf::client::render {
 | 
			
		||||
        vkCmdEndRenderPass(m_commandBuffer);
 | 
			
		||||
 | 
			
		||||
        // Finish recording
 | 
			
		||||
        if (vkEndCommandBuffer(m_commandBuffer) != VK_SUCCESS)
 | 
			
		||||
            NFError("Could not end command buffer.");
 | 
			
		||||
        vkEndCommandBuffer(m_commandBuffer);
 | 
			
		||||
 | 
			
		||||
        // Submit to graphics queue
 | 
			
		||||
        VkPipelineStageFlags waitStage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
 | 
			
		||||
@ -718,6 +748,8 @@ namespace nf::client::render {
 | 
			
		||||
        for (int i = 0; i < m_swapchainFramebuffers.size(); i++)
 | 
			
		||||
            vkDestroyFramebuffer(m_device, m_swapchainFramebuffers[i], nullptr);
 | 
			
		||||
 | 
			
		||||
        m_imageDepth.reset();
 | 
			
		||||
 | 
			
		||||
        for (int i = 0; i < m_swapchainImageViews.size(); i++)
 | 
			
		||||
            vkDestroyImageView(m_device, m_swapchainImageViews[i], nullptr);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -24,10 +24,10 @@ namespace nf::client::render {
 | 
			
		||||
 | 
			
		||||
        void createSwapchain();
 | 
			
		||||
        void createOutputRenderPass();
 | 
			
		||||
        void createSwapchainFramebuffers();
 | 
			
		||||
        void createOutputPipeline();
 | 
			
		||||
        void createExecutionObjects();
 | 
			
		||||
 | 
			
		||||
        void createSwapchainFramebuffers();
 | 
			
		||||
        void createBuffers();
 | 
			
		||||
        void createImage();
 | 
			
		||||
        void createDescriptorSet();
 | 
			
		||||
@ -56,7 +56,6 @@ namespace nf::client::render {
 | 
			
		||||
        VkExtent2D m_swapchainExtent;
 | 
			
		||||
        std::vector<VkImage> m_swapchainImages;
 | 
			
		||||
        std::vector<VkImageView> m_swapchainImageViews;
 | 
			
		||||
        std::vector<VkFramebuffer> m_swapchainFramebuffers;
 | 
			
		||||
 | 
			
		||||
        // Pipelines
 | 
			
		||||
        VkDescriptorSetLayout m_pipelineOutputDescriptorSetLayout;
 | 
			
		||||
@ -73,6 +72,8 @@ namespace nf::client::render {
 | 
			
		||||
 | 
			
		||||
        // Temporary objects
 | 
			
		||||
        std::unique_ptr<VideoMemoryAllocator> m_allocator;
 | 
			
		||||
        std::unique_ptr<Image> m_imageDepth;
 | 
			
		||||
        std::vector<VkFramebuffer> m_swapchainFramebuffers;
 | 
			
		||||
        std::unique_ptr<Buffer> m_bufferVertex;
 | 
			
		||||
        std::unique_ptr<Buffer> m_bufferIndex;
 | 
			
		||||
        std::unique_ptr<Buffer> m_bufferUniformMVP;
 | 
			
		||||
 | 
			
		||||
@ -44,5 +44,6 @@
 | 
			
		||||
#include <vulkan/vulkan.h>
 | 
			
		||||
 | 
			
		||||
// GLM
 | 
			
		||||
#define GLM_FORCE_DEPTH_ZERO_TO_ONE
 | 
			
		||||
#include <glm/glm.hpp>
 | 
			
		||||
#include <glm/gtc/matrix_transform.hpp>
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user