Add depth testing

This commit is contained in:
Grayson Riffe 2025-02-25 02:39:57 -06:00
parent 47a2ea4ebf
commit b0e204f03c
6 changed files with 150 additions and 85 deletions

View File

@ -75,29 +75,22 @@ namespace nf::client::render {
VkCommandBufferAllocateInfo commandBufferAI = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO }; VkCommandBufferAllocateInfo commandBufferAI = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO };
commandBufferAI.commandPool = commandPool; commandBufferAI.commandPool = commandPool;
commandBufferAI.commandBufferCount = 1; commandBufferAI.commandBufferCount = 1;
vkAllocateCommandBuffers(m_device, &commandBufferAI, &commandBuffer);
if (vkAllocateCommandBuffers(m_device, &commandBufferAI, &commandBuffer) != VK_SUCCESS)
NFError("Could not create command buffer.");
VkCommandBufferBeginInfo commandBufferBI = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO }; VkCommandBufferBeginInfo commandBufferBI = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO };
commandBufferBI.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; commandBufferBI.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
vkBeginCommandBuffer(commandBuffer, &commandBufferBI); vkBeginCommandBuffer(commandBuffer, &commandBufferBI);
VkBufferCopy bufferCopyRegion = {}; VkBufferCopy bufferCopyRegion = {};
bufferCopyRegion.size = size; bufferCopyRegion.size = size;
vkCmdCopyBuffer(commandBuffer, bufferSource, bufferDestination, 1, &bufferCopyRegion); vkCmdCopyBuffer(commandBuffer, bufferSource, bufferDestination, 1, &bufferCopyRegion);
if (vkEndCommandBuffer(commandBuffer) != VK_SUCCESS) vkEndCommandBuffer(commandBuffer);
NFError("Could not end command buffer.");
VkSubmitInfo submitInfo = { VK_STRUCTURE_TYPE_SUBMIT_INFO }; VkSubmitInfo submitInfo = { VK_STRUCTURE_TYPE_SUBMIT_INFO };
submitInfo.commandBufferCount = 1; submitInfo.commandBufferCount = 1;
submitInfo.pCommandBuffers = &commandBuffer; submitInfo.pCommandBuffers = &commandBuffer;
vkQueueSubmit(queue, 1, &submitInfo, nullptr);
if (vkQueueSubmit(queue, 1, &submitInfo, nullptr) != VK_SUCCESS)
NFError("Could not submit to Vulkan queue.");
vkQueueWaitIdle(queue); vkQueueWaitIdle(queue);
vkFreeCommandBuffers(m_device, commandPool, 1, &commandBuffer); vkFreeCommandBuffers(m_device, commandPool, 1, &commandBuffer);

View File

@ -9,36 +9,46 @@
#include "stb_image.h" #include "stb_image.h"
namespace nf::client::render { 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) : GraphicsResource(device)
, m_allocator(allocator) , m_allocator(allocator)
, m_handle() , m_handle()
, m_allocation() , m_allocation()
, m_view() , 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; 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); 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); Buffer stagingBuffer(BufferType::Staging, m_device, m_allocator, nullptr, nullptr, rawImageData, imageSize);
stbi_image_free(rawImageData); stbi_image_free(rawImageData);
VkImageCreateInfo imageCI = { VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO }; VkExtent2D imageExtent = { static_cast<uint32_t>(imageWidth), static_cast<uint32_t>(imageHeight) };
imageCI.imageType = VK_IMAGE_TYPE_2D; createImage(imageFormat, imageExtent, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT);
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);
VkCommandBuffer commandBuffer = nullptr; VkCommandBuffer commandBuffer = nullptr;
VkCommandBufferAllocateInfo commandBufferAI = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO }; 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 }; VkCommandBufferBeginInfo commandBufferBI = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO };
commandBufferBI.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; commandBufferBI.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
vkBeginCommandBuffer(commandBuffer, &commandBufferBI); vkBeginCommandBuffer(commandBuffer, &commandBufferBI);
// Image transition undefined -> transfer destination // Image transition undefined -> transfer destination
@ -63,6 +72,7 @@ namespace nf::client::render {
imageMemoryBarrier.srcAccessMask = 0; imageMemoryBarrier.srcAccessMask = 0;
imageMemoryBarrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; 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); vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, 0, nullptr, 1, &imageMemoryBarrier);
vkEndCommandBuffer(commandBuffer); vkEndCommandBuffer(commandBuffer);
VkSubmitInfo submitInfo = { VK_STRUCTURE_TYPE_SUBMIT_INFO }; VkSubmitInfo submitInfo = { VK_STRUCTURE_TYPE_SUBMIT_INFO };
@ -91,18 +101,41 @@ namespace nf::client::render {
imageMemoryBarrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; imageMemoryBarrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
imageMemoryBarrier.dstAccessMask = VK_ACCESS_SHADER_READ_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); vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 0, nullptr, 0, nullptr, 1, &imageMemoryBarrier);
vkEndCommandBuffer(commandBuffer); vkEndCommandBuffer(commandBuffer);
vkQueueSubmit(queue, 1, &submitInfo, nullptr); vkQueueSubmit(queue, 1, &submitInfo, nullptr);
vkQueueWaitIdle(queue); vkQueueWaitIdle(queue);
vkFreeCommandBuffers(m_device, commandPool, 1, &commandBuffer); 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 }; VkImageViewCreateInfo imageViewCI = { VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO };
imageViewCI.image = m_handle; imageViewCI.image = m_handle;
imageViewCI.viewType = VK_IMAGE_VIEW_TYPE_2D; imageViewCI.viewType = VK_IMAGE_VIEW_TYPE_2D;
imageViewCI.format = VK_FORMAT_R8G8B8A8_SRGB; imageViewCI.format = format;
imageViewCI.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; imageViewCI.subresourceRange.aspectMask = aspectMask;
imageViewCI.subresourceRange.levelCount = 1; imageViewCI.subresourceRange.levelCount = 1;
imageViewCI.subresourceRange.layerCount = 1; imageViewCI.subresourceRange.layerCount = 1;
@ -110,10 +143,6 @@ namespace nf::client::render {
NFError("Could not create image view."); NFError("Could not create image view.");
} }
const VkImageView& Image::getView() const {
return m_view;
}
Image::~Image() { Image::~Image() {
vkDestroyImageView(m_device, m_view, nullptr); vkDestroyImageView(m_device, m_view, nullptr);
m_allocator.deallocate(m_allocation); m_allocator.deallocate(m_allocation);

View File

@ -5,14 +5,23 @@
#include "VideoMemoryAllocator.h" #include "VideoMemoryAllocator.h"
namespace nf::client::render { namespace nf::client::render {
enum class ImageType {
Texture,
DepthAttachment
};
class Image : GraphicsResource { class Image : GraphicsResource {
public: 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; const VkImageView& getView() const;
~Image(); ~Image();
private: 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; VideoMemoryAllocator& m_allocator;
VkImage m_handle; VkImage m_handle;

View File

@ -29,7 +29,6 @@ namespace nf::client::render {
, m_swapchainExtent() , m_swapchainExtent()
, m_swapchainImages() , m_swapchainImages()
, m_swapchainImageViews() , m_swapchainImageViews()
, m_swapchainFramebuffers()
, m_pipelineOutputDescriptorSetLayout() , m_pipelineOutputDescriptorSetLayout()
, m_pipelineOutputLayout() , m_pipelineOutputLayout()
, m_pipelineOutputDescriptorPool() , m_pipelineOutputDescriptorPool()
@ -40,6 +39,8 @@ namespace nf::client::render {
, m_semaphoreRenderingDone() , m_semaphoreRenderingDone()
, m_fenceFrameInFlight() , m_fenceFrameInFlight()
, m_allocator() , m_allocator()
, m_swapchainFramebuffers()
, m_imageDepth()
, m_bufferVertex() , m_bufferVertex()
, m_bufferIndex() , m_bufferIndex()
, m_imageTest() , m_imageTest()
@ -56,11 +57,11 @@ namespace nf::client::render {
createDevice(); createDevice();
createSwapchain(); createSwapchain();
createOutputRenderPass(); createOutputRenderPass();
createSwapchainFramebuffers();
createOutputPipeline(); createOutputPipeline();
createExecutionObjects(); createExecutionObjects();
m_allocator = std::make_unique<VideoMemoryAllocator>(m_device, m_physicalDevice); m_allocator = std::make_unique<VideoMemoryAllocator>(m_device, m_physicalDevice);
createSwapchainFramebuffers();
createBuffers(); createBuffers();
createImage(); createImage();
createDescriptorSet(); createDescriptorSet();
@ -285,34 +286,46 @@ namespace nf::client::render {
} }
void RenderEngine::createOutputRenderPass() { void RenderEngine::createOutputRenderPass() {
VkAttachmentDescription outputColorAttachment = {}; VkAttachmentDescription attachmentDescriptions[2] = {};
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;
VkAttachmentReference outputColorAttachmentReference = {}; // Color attachment
outputColorAttachmentReference.attachment = 0; attachmentDescriptions[0].format = m_swapchainImageFormat;
outputColorAttachmentReference.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; 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 = {}; VkSubpassDescription subpassDescription = {};
subpassDescription.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; subpassDescription.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
subpassDescription.colorAttachmentCount = 1; subpassDescription.colorAttachmentCount = 1;
subpassDescription.pColorAttachments = &outputColorAttachmentReference; subpassDescription.pColorAttachments = &attachmentReferences[0];
subpassDescription.pDepthStencilAttachment = &attachmentReferences[1];
VkSubpassDependency dependency = {}; VkSubpassDependency dependency = {};
dependency.srcSubpass = VK_SUBPASS_EXTERNAL; dependency.srcSubpass = VK_SUBPASS_EXTERNAL;
dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; dependency.dstSubpass = 0;
dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_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 }; VkRenderPassCreateInfo renderPassCI = { VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO };
renderPassCI.attachmentCount = 1; renderPassCI.attachmentCount = 2;
renderPassCI.pAttachments = &outputColorAttachment; renderPassCI.pAttachments = attachmentDescriptions;
renderPassCI.subpassCount = 1; renderPassCI.subpassCount = 1;
renderPassCI.pSubpasses = &subpassDescription; renderPassCI.pSubpasses = &subpassDescription;
renderPassCI.dependencyCount = 1; renderPassCI.dependencyCount = 1;
@ -322,22 +335,6 @@ namespace nf::client::render {
NFError("Could not create Vulkan output render pass."); 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() { void RenderEngine::createOutputPipeline() {
// First, create shader modules // First, create shader modules
std::string outputShaderVertexBinary, outputShaderFragmentBinary; std::string outputShaderVertexBinary, outputShaderFragmentBinary;
@ -365,7 +362,7 @@ namespace nf::client::render {
VkPipelineVertexInputStateCreateInfo vertexInputStateCI = { VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO }; VkPipelineVertexInputStateCreateInfo vertexInputStateCI = { VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO };
VkVertexInputBindingDescription vertexBindingDescription = {}; VkVertexInputBindingDescription vertexBindingDescription = {};
vertexBindingDescription.stride = sizeof(Vertex); vertexBindingDescription.stride = sizeof(Vertex);
std::array<VkVertexInputAttributeDescription, 2> vertexAttributeDescriptions = {}; VkVertexInputAttributeDescription vertexAttributeDescriptions[2] = {};
vertexAttributeDescriptions[0].location = 0; vertexAttributeDescriptions[0].location = 0;
vertexAttributeDescriptions[0].format = VK_FORMAT_R32G32B32_SFLOAT; vertexAttributeDescriptions[0].format = VK_FORMAT_R32G32B32_SFLOAT;
vertexAttributeDescriptions[0].offset = offsetof(Vertex, position); vertexAttributeDescriptions[0].offset = offsetof(Vertex, position);
@ -374,8 +371,8 @@ namespace nf::client::render {
vertexAttributeDescriptions[1].offset = offsetof(Vertex, textureCoordinates); vertexAttributeDescriptions[1].offset = offsetof(Vertex, textureCoordinates);
vertexInputStateCI.vertexBindingDescriptionCount = 1; vertexInputStateCI.vertexBindingDescriptionCount = 1;
vertexInputStateCI.pVertexBindingDescriptions = &vertexBindingDescription; vertexInputStateCI.pVertexBindingDescriptions = &vertexBindingDescription;
vertexInputStateCI.vertexAttributeDescriptionCount = vertexAttributeDescriptions.size(); vertexInputStateCI.vertexAttributeDescriptionCount = 2;
vertexInputStateCI.pVertexAttributeDescriptions = vertexAttributeDescriptions.data(); vertexInputStateCI.pVertexAttributeDescriptions = vertexAttributeDescriptions;
// Specify input assembly state // Specify input assembly state
VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateCI = { VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO }; 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 }; VkPipelineMultisampleStateCreateInfo multisampleStateCI = { VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO };
multisampleStateCI.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; 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 // Specify color blend state
VkPipelineColorBlendAttachmentState colorBlendAttachmentState = {}; VkPipelineColorBlendAttachmentState colorBlendAttachmentState = {};
colorBlendAttachmentState.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; 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.pViewportState = &viewportStateCI;
pipelineCI.pRasterizationState = &rasterizationCI; pipelineCI.pRasterizationState = &rasterizationCI;
pipelineCI.pMultisampleState = &multisampleStateCI; pipelineCI.pMultisampleState = &multisampleStateCI;
pipelineCI.pDepthStencilState = &depthStencilStateCI;
pipelineCI.pColorBlendState = &colorBlendStateCI; pipelineCI.pColorBlendState = &colorBlendStateCI;
pipelineCI.pDynamicState = &dynamicStateCI; pipelineCI.pDynamicState = &dynamicStateCI;
pipelineCI.layout = m_pipelineOutputLayout; pipelineCI.layout = m_pipelineOutputLayout;
@ -487,6 +491,27 @@ namespace nf::client::render {
NFError("Could not create fence."); 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() { void RenderEngine::createBuffers() {
std::vector<Vertex> cubeVertices = { std::vector<Vertex> cubeVertices = {
{{-0.5, -0.5, 0.5}, {0.0, 1.0}}, {{-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}, {1.0, 0.0}},
{{-0.5, 0.5, -0.5}, {0.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}, {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(); size_t cubeVerticesSize = sizeof(cubeVertices[0]) * cubeVertices.size();
@ -540,7 +569,9 @@ namespace nf::client::render {
17, 19, 18, 17, 19, 18,
20, 23, 21, 20, 23, 21,
23, 22, 21 23, 22, 21,
24, 25, 26
}; };
size_t cubeIndicesSize = sizeof(cubeIndices[0]) * cubeIndices.size(); size_t cubeIndicesSize = sizeof(cubeIndices[0]) * cubeIndices.size();
@ -553,7 +584,7 @@ namespace nf::client::render {
void RenderEngine::createImage() { void RenderEngine::createImage() {
std::string imageData; std::string imageData;
util::readFile("grayson.jpg", 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 }; VkSamplerCreateInfo samplerCI = { VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO };
samplerCI.magFilter = samplerCI.minFilter = VK_FILTER_LINEAR; samplerCI.magFilter = samplerCI.minFilter = VK_FILTER_LINEAR;
@ -617,13 +648,13 @@ namespace nf::client::render {
vkBeginCommandBuffer(m_commandBuffer, &commandBufferBI); vkBeginCommandBuffer(m_commandBuffer, &commandBufferBI);
// Start the render pass // 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 }; VkRenderPassBeginInfo renderPassBI = { VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO };
renderPassBI.renderPass = m_renderPassOutput; renderPassBI.renderPass = m_renderPassOutput;
renderPassBI.framebuffer = m_swapchainFramebuffers[nextImageIndex]; renderPassBI.framebuffer = m_swapchainFramebuffers[nextImageIndex];
renderPassBI.renderArea.extent = m_swapchainExtent; renderPassBI.renderArea.extent = m_swapchainExtent;
renderPassBI.clearValueCount = 1; renderPassBI.clearValueCount = 2;
renderPassBI.pClearValues = &black; renderPassBI.pClearValues = clearValues;
vkCmdBeginRenderPass(m_commandBuffer, &renderPassBI, VK_SUBPASS_CONTENTS_INLINE); vkCmdBeginRenderPass(m_commandBuffer, &renderPassBI, VK_SUBPASS_CONTENTS_INLINE);
// Bind output pipeline // Bind output pipeline
@ -646,7 +677,7 @@ namespace nf::client::render {
static auto startTime = std::chrono::high_resolution_clock::now(); static auto startTime = std::chrono::high_resolution_clock::now();
auto currentTime = std::chrono::high_resolution_clock::now(); auto currentTime = std::chrono::high_resolution_clock::now();
float time = std::chrono::duration<float>(currentTime - startTime).count(); 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)), 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); 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); vkCmdEndRenderPass(m_commandBuffer);
// Finish recording // Finish recording
if (vkEndCommandBuffer(m_commandBuffer) != VK_SUCCESS) vkEndCommandBuffer(m_commandBuffer);
NFError("Could not end command buffer.");
// Submit to graphics queue // Submit to graphics queue
VkPipelineStageFlags waitStage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; 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++) for (int i = 0; i < m_swapchainFramebuffers.size(); i++)
vkDestroyFramebuffer(m_device, m_swapchainFramebuffers[i], nullptr); vkDestroyFramebuffer(m_device, m_swapchainFramebuffers[i], nullptr);
m_imageDepth.reset();
for (int i = 0; i < m_swapchainImageViews.size(); i++) for (int i = 0; i < m_swapchainImageViews.size(); i++)
vkDestroyImageView(m_device, m_swapchainImageViews[i], nullptr); vkDestroyImageView(m_device, m_swapchainImageViews[i], nullptr);

View File

@ -24,10 +24,10 @@ namespace nf::client::render {
void createSwapchain(); void createSwapchain();
void createOutputRenderPass(); void createOutputRenderPass();
void createSwapchainFramebuffers();
void createOutputPipeline(); void createOutputPipeline();
void createExecutionObjects(); void createExecutionObjects();
void createSwapchainFramebuffers();
void createBuffers(); void createBuffers();
void createImage(); void createImage();
void createDescriptorSet(); void createDescriptorSet();
@ -56,7 +56,6 @@ namespace nf::client::render {
VkExtent2D m_swapchainExtent; VkExtent2D m_swapchainExtent;
std::vector<VkImage> m_swapchainImages; std::vector<VkImage> m_swapchainImages;
std::vector<VkImageView> m_swapchainImageViews; std::vector<VkImageView> m_swapchainImageViews;
std::vector<VkFramebuffer> m_swapchainFramebuffers;
// Pipelines // Pipelines
VkDescriptorSetLayout m_pipelineOutputDescriptorSetLayout; VkDescriptorSetLayout m_pipelineOutputDescriptorSetLayout;
@ -73,6 +72,8 @@ namespace nf::client::render {
// Temporary objects // Temporary objects
std::unique_ptr<VideoMemoryAllocator> m_allocator; 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_bufferVertex;
std::unique_ptr<Buffer> m_bufferIndex; std::unique_ptr<Buffer> m_bufferIndex;
std::unique_ptr<Buffer> m_bufferUniformMVP; std::unique_ptr<Buffer> m_bufferUniformMVP;

View File

@ -44,5 +44,6 @@
#include <vulkan/vulkan.h> #include <vulkan/vulkan.h>
// GLM // GLM
#define GLM_FORCE_DEPTH_ZERO_TO_ONE
#include <glm/glm.hpp> #include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp> #include <glm/gtc/matrix_transform.hpp>