Depth buffering set up! Needs documentation and cleanup (again...)

This commit is contained in:
Lillian Salehi 2024-10-14 05:26:02 -05:00
parent 19c25ba670
commit ac402dbef8
11 changed files with 150 additions and 32 deletions

View File

@ -291,14 +291,14 @@ namespace DeviceControl {
vkDestroySwapchainKHR(Global::device, Global::swapChain, nullptr); vkDestroySwapchainKHR(Global::device, Global::swapChain, nullptr);
if(Global::enableValidationLayers) std::cout << "Destroyed Swap Chain safely\n" << std::endl; if(Global::enableValidationLayers) std::cout << "Destroyed Swap Chain safely\n" << std::endl;
} }
VkImageView devicelibrary::createImageView(VkImage image, VkFormat format) { VkImageView devicelibrary::createImageView(VkImage image, VkFormat format, VkImageAspectFlags flags) {
// This defines the parameters of a newly created image object! // This defines the parameters of a newly created image object!
VkImageViewCreateInfo viewInfo{}; VkImageViewCreateInfo viewInfo{};
viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
viewInfo.image = image; viewInfo.image = image;
viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D; viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
viewInfo.format = format; viewInfo.format = format;
viewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; viewInfo.subresourceRange.aspectMask = flags;
viewInfo.subresourceRange.baseMipLevel = 0; viewInfo.subresourceRange.baseMipLevel = 0;
viewInfo.subresourceRange.levelCount = 1; viewInfo.subresourceRange.levelCount = 1;
viewInfo.subresourceRange.baseArrayLayer = 0; viewInfo.subresourceRange.baseArrayLayer = 0;
@ -315,7 +315,7 @@ namespace DeviceControl {
swapChainImageViews.resize(swapChainImages.size()); swapChainImageViews.resize(swapChainImages.size());
for (uint32_t i = 0; i < swapChainImages.size(); i++) { for (uint32_t i = 0; i < swapChainImages.size(); i++) {
swapChainImageViews[i] = createImageView(swapChainImages[i], swapChainImageFormat); swapChainImageViews[i] = createImageView(swapChainImages[i], swapChainImageFormat, VK_IMAGE_ASPECT_COLOR_BIT);
} }
} }
void devicelibrary::destroyImageViews() { void devicelibrary::destroyImageViews() {

View File

@ -1,5 +1,6 @@
#pragma once #pragma once
#include "global.h" #include "global.h"
#include <GLFW/glfw3.h>
#include <optional> #include <optional>
#include <algorithm> #include <algorithm>
#include <limits> #include <limits>
@ -16,7 +17,7 @@ class devicelibrary {
void destroySurface(VkInstance& instance); void destroySurface(VkInstance& instance);
void createSwapChain(GLFWwindow* window); void createSwapChain(GLFWwindow* window);
void destroySwapChain(); void destroySwapChain();
VkImageView createImageView(VkImage image, VkFormat format); VkImageView createImageView(VkImage image, VkFormat format, VkImageAspectFlags flags);
void createImageViews(); void createImageViews();
void destroyImageViews(); void destroyImageViews();
void createCommandPool(); void createCommandPool();

View File

@ -6,6 +6,7 @@ RenderPresent::render renderPresentation;
BuffersLibraries::buffers buffers; BuffersLibraries::buffers buffers;
TextureLibraries::texture texture; TextureLibraries::texture texture;
VkInstance vulkaninstance; VkInstance vulkaninstance;
//TODO: add global instances?
// Getters and Setters! // Getters and Setters!
void EntryApp::setFramebufferResized(bool setter) { void EntryApp::setFramebufferResized(bool setter) {
@ -60,8 +61,9 @@ void initVulkan() {
graphicsPipeline.createRenderPass(); graphicsPipeline.createRenderPass();
buffers.createDescriptorSetLayout(); buffers.createDescriptorSetLayout();
graphicsPipeline.createGraphicsPipeline(); graphicsPipeline.createGraphicsPipeline();
graphicsPipeline.createFramebuffers();
graphicsPipeline.createCommandPool(); graphicsPipeline.createCommandPool();
texture.createDepthResources();
graphicsPipeline.createFramebuffers();
texture.createTextureImage(); texture.createTextureImage();
texture.createTextureImageView(); texture.createTextureImageView();
texture.createTextureSampler(); texture.createTextureSampler();

View File

@ -26,6 +26,9 @@ namespace Global {
uint32_t currentFrame = 0; uint32_t currentFrame = 0;
VkImageView textureImageView; VkImageView textureImageView;
VkSampler textureSampler; VkSampler textureSampler;
VkImageView depthImageView;
VkImage depthImage;
VkDeviceMemory depthImageMemory;
Global::QueueFamilyIndices findQueueFamilies(VkPhysicalDevice device) { Global::QueueFamilyIndices findQueueFamilies(VkPhysicalDevice device) {
// First we feed in a integer we want to use to hold the number of queued items, that fills it, then we create that amount of default constructed *VkQueueFamilyProperties* structs. // First we feed in a integer we want to use to hold the number of queued items, that fills it, then we create that amount of default constructed *VkQueueFamilyProperties* structs.

View File

@ -1,4 +1,5 @@
#pragma once #pragma once
#include "graphics/texture.h"
#include <cstdint> #include <cstdint>
#include <glm/detail/qualifier.hpp> #include <glm/detail/qualifier.hpp>
#include <glm/ext/vector_float2.hpp> #include <glm/ext/vector_float2.hpp>
@ -8,16 +9,20 @@
#include <vector> #include <vector>
#include <optional> #include <optional>
#include <vulkan/vulkan_core.h> #include <vulkan/vulkan_core.h>
#include "debug/vulkandebuglibs.h" #include <glm/gtc/matrix_transform.hpp>
#include <array>
#define GLM_FORCE_DEPTH_ZERO_TO_ONE
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp> #include <glm/gtc/matrix_transform.hpp>
#include <array>
#define GLFW_INCLUDE_VULKAN #define GLFW_INCLUDE_VULKAN
#include <GLFW/glfw3.h> #include <GLFW/glfw3.h>
namespace Global { namespace Global {
// Global variables and includes we are going to use almost everywhere, validation layers hook into everything, and you need to check if they are enabled first, // Global variables and includes we are going to use almost everywhere, validation layers hook into everything, and you need to check if they are enabled first,
// so that's one obvious global, as well as the glfw includes! // so that's one obvious global, as well as the glfw includes!
extern const std::vector<const char*> validationLayers; extern const std::vector<const char*> validationLayers;
extern const bool enableValidationLayers; extern const bool enableValidationLayers;
extern VkDevice device; extern VkDevice device;
@ -32,6 +37,9 @@ namespace Global {
extern std::vector<VkDescriptorSet> descriptorSets; extern std::vector<VkDescriptorSet> descriptorSets;
extern VkImageView textureImageView; extern VkImageView textureImageView;
extern VkSampler textureSampler; extern VkSampler textureSampler;
extern VkImageView depthImageView;
extern VkImage depthImage;
extern VkDeviceMemory depthImageMemory;
struct UniformBufferObject { struct UniformBufferObject {
float time; float time;
@ -40,7 +48,9 @@ namespace Global {
alignas(16) glm::mat4 proj; alignas(16) glm::mat4 proj;
}; };
struct Vertex { struct Vertex {
glm::vec2 pos; // This defines what a vertex is!
// We control the position, color and texture coordinate here!
glm::vec3 pos;
glm::vec3 color; glm::vec3 color;
glm::vec2 texCoord; glm::vec2 texCoord;
@ -57,7 +67,7 @@ namespace Global {
attributeDescriptions[0].binding = 0; attributeDescriptions[0].binding = 0;
attributeDescriptions[0].location = 0; attributeDescriptions[0].location = 0;
attributeDescriptions[0].format = VK_FORMAT_R32G32_SFLOAT; attributeDescriptions[0].format = VK_FORMAT_R32G32B32_SFLOAT;
attributeDescriptions[0].offset = offsetof(Vertex, pos); attributeDescriptions[0].offset = offsetof(Vertex, pos);
attributeDescriptions[1].binding = 0; attributeDescriptions[1].binding = 0;
@ -73,7 +83,7 @@ namespace Global {
} }
}; };
const uint32_t WIDTH = 800; const uint32_t WIDTH = 800;
const uint32_t HEIGHT = 600; const uint32_t HEIGHT = 800;
struct QueueFamilyIndices { struct QueueFamilyIndices {
// We need to check that the Queue families support graphics operations and window presentation, sometimes they can support one or the other, // We need to check that the Queue families support graphics operations and window presentation, sometimes they can support one or the other,

View File

@ -1,7 +1,6 @@
#include "buffers.h" #include "buffers.h"
#include <chrono> #include <chrono>
#include <cstdint> #include <cstring>
#include <vulkan/vulkan_core.h>
#include "../devicelibrary.h" #include "../devicelibrary.h"
VkBuffer vertexBuffer; VkBuffer vertexBuffer;
@ -20,14 +19,22 @@ namespace BuffersLibraries {
const std::vector<Global::Vertex> vertices = { const std::vector<Global::Vertex> vertices = {
{{-0.5f, -0.5f}, {1.0f, 0.0f, 0.0f}, {1.0f, 0.0f}}, // X Y Z | R G B | W Q
{{0.5f, -0.5f}, {0.0f, 1.0f, 0.0f}, {0.0f, 0.0f}}, {{-0.5f, -0.5f, 0.0f}, {1.0f, 0.0f, 0.0f}, {1.0f, 0.0f}},
{{0.5f, 0.5f}, {0.0f, 0.0f, 1.0f}, {0.0f, 1.0f}}, {{0.5f, -0.5f, 0.0f}, {0.0f, 1.0f, 0.0f}, {0.0f, 0.0f}},
{{-0.5f, 0.5f}, {1.0f, 1.0f, 1.0f}, {1.0f, 1.0f}} {{0.5f, 0.5f, 0.0f}, {0.0f, 0.0f, 1.0f}, {0.0f, 1.0f}},
{{-0.5f, 0.5f, 0.0f}, {1.0f, 1.0f, 1.0f}, {1.0f, 1.0f}},
{{-0.5f, -0.5f, -0.5f}, {1.0f, 0.0f, 0.0f}, {0.0f, 0.0f}},
{{0.5f, -0.5f, -0.5f}, {0.0f, 1.0f, 0.0f}, {1.0f, 0.0f}},
{{0.5f, 0.5f, -0.5f}, {0.0f, 0.0f, 1.0f}, {1.0f, 1.0f}},
{{-0.5f, 0.5f, -0.5f}, {1.0f, 1.0f, 1.0f}, {0.0f, 1.0f}}
}; };
// Index buffer definition, showing which points to reuse. // Index buffer definition, showing which points to reuse.
const std::vector<uint16_t> indices = { const std::vector<uint16_t> indices = {
0, 1, 2, 2, 3, 0 0, 1, 2, 2, 3, 0,
4, 5, 6, 6, 7, 4
}; };
uint32_t buffers::findMemoryType(uint32_t typeFilter, VkMemoryPropertyFlags properties) { uint32_t buffers::findMemoryType(uint32_t typeFilter, VkMemoryPropertyFlags properties) {
@ -114,6 +121,7 @@ namespace BuffersLibraries {
void* data; void* data;
vkMapMemory(Global::device, stagingBufferMemory, 0, bufferSize, 0, &data); vkMapMemory(Global::device, stagingBufferMemory, 0, bufferSize, 0, &data);
memcpy(data, indices.data(), (size_t) bufferSize); memcpy(data, indices.data(), (size_t) bufferSize);
vkUnmapMemory(Global::device, stagingBufferMemory); vkUnmapMemory(Global::device, stagingBufferMemory);
createBuffer(bufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, indexBuffer, indexBufferMemory); createBuffer(bufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, indexBuffer, indexBufferMemory);
@ -226,7 +234,7 @@ namespace BuffersLibraries {
ubo.model = glm::rotate(glm::mat4(1.0f), time * glm::radians(90.0f), glm::vec3(0.0f, 0.0f, 1.0f)); ubo.model = glm::rotate(glm::mat4(1.0f), time * glm::radians(90.0f), glm::vec3(0.0f, 0.0f, 1.0f));
// Modify the view transformation to look at the object from above at a 45 degree angle. // Modify the view transformation to look at the object from above at a 45 degree angle.
// This takes the eye position, center position, and the up direction. // This takes the eye position, center position, and the up direction.
ubo.view = glm::lookAt(glm::vec3(2.0f, 2.0f, 2.0f), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 0.0f, 1.0f)); ubo.view = glm::lookAt(glm::vec3(1.0f, 1.0f, 1.0f), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 0.0f, 1.0f));
// 45 degree field of view, set aspect ratio, and near and far clipping range. // 45 degree field of view, set aspect ratio, and near and far clipping range.
ubo.proj = glm::perspective(glm::radians(45.0f), deviceLibrary.getSwapChainExtent().width / (float) deviceLibrary.getSwapChainExtent().height, 0.1f, 10.0f); ubo.proj = glm::perspective(glm::radians(45.0f), deviceLibrary.getSwapChainExtent().width / (float) deviceLibrary.getSwapChainExtent().height, 0.1f, 10.0f);

View File

@ -1,7 +1,10 @@
#include "graphicspipeline.h" #include "graphicspipeline.h"
#include "buffers.h" #include "buffers.h"
#include "texture.h"
#include <cstdint>
#include <vector> #include <vector>
#include <vulkan/vulkan_core.h>
namespace Graphics { namespace Graphics {
std::vector<VkDynamicState> dynamicStates = { std::vector<VkDynamicState> dynamicStates = {
VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_VIEWPORT,
@ -14,6 +17,7 @@ namespace Graphics {
VkPipeline graphicsPipeline; VkPipeline graphicsPipeline;
DeviceControl::devicelibrary deviceLibs; DeviceControl::devicelibrary deviceLibs;
BuffersLibraries::buffers buffers; BuffersLibraries::buffers buffers;
TextureLibraries::texture textureLibs;
std::vector<VkFramebuffer> swapChainFramebuffers; std::vector<VkFramebuffer> swapChainFramebuffers;
@ -136,6 +140,15 @@ namespace Graphics {
multisampling.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; multisampling.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
multisampling.sampleShadingEnable = VK_FALSE; multisampling.sampleShadingEnable = VK_FALSE;
multisampling.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; multisampling.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
// TODO: Document!
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.depthBoundsTestEnable = VK_FALSE;
depthStencil.stencilTestEnable = VK_FALSE;
// Most of the graphics pipeline is set in stone, some of the pipeline state can be modified without recreating it at runtime though! // Most of the graphics pipeline is set in stone, some of the pipeline state can be modified without recreating it at runtime though!
// There are TONS of settings, this would be another TODO to see what else we can mess with dynamically, but right now we just allow dynamic size of the viewport // There are TONS of settings, this would be another TODO to see what else we can mess with dynamically, but right now we just allow dynamic size of the viewport
// and dynamic scissor states. Scissors are pretty straightforward, they are basically pixel masks for the rasterizer. // and dynamic scissor states. Scissors are pretty straightforward, they are basically pixel masks for the rasterizer.
@ -168,6 +181,7 @@ namespace Graphics {
pipelineInfo.layout = pipelineLayout; pipelineInfo.layout = pipelineLayout;
pipelineInfo.renderPass = renderPass; pipelineInfo.renderPass = renderPass;
pipelineInfo.subpass = 0; pipelineInfo.subpass = 0;
pipelineInfo.pDepthStencilState = &depthStencil;
if (vkCreateGraphicsPipelines(Global::device, VK_NULL_HANDLE, 1, &pipelineInfo, nullptr, &graphicsPipeline) != VK_SUCCESS) { if (vkCreateGraphicsPipelines(Global::device, VK_NULL_HANDLE, 1, &pipelineInfo, nullptr, &graphicsPipeline) != VK_SUCCESS) {
throw std::runtime_error("failed to create graphics pipeline!"); throw std::runtime_error("failed to create graphics pipeline!");
@ -192,18 +206,45 @@ namespace Graphics {
colorAttachmentRef.attachment = 0; colorAttachmentRef.attachment = 0;
colorAttachmentRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; colorAttachmentRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
VkAttachmentDescription depthAttachment{};
depthAttachment.format = textureLibs.findDepthFormat();
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;
VkAttachmentReference depthAttachmentRef{};
depthAttachmentRef.attachment = 1;
depthAttachmentRef.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
VkSubpassDescription subpass{}; VkSubpassDescription subpass{};
subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
subpass.colorAttachmentCount = 1; subpass.colorAttachmentCount = 1;
subpass.pColorAttachments = &colorAttachmentRef; 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 | 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;
std::array<VkAttachmentDescription, 2> attachments = {colorAttachment, depthAttachment};
VkRenderPassCreateInfo renderPassInfo{}; VkRenderPassCreateInfo renderPassInfo{};
renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
renderPassInfo.attachmentCount = 1; renderPassInfo.attachmentCount = static_cast<uint32_t>(attachments.size());
renderPassInfo.pAttachments = &colorAttachment; renderPassInfo.pAttachments = attachments.data();
renderPassInfo.subpassCount = 1; renderPassInfo.subpassCount = 1;
renderPassInfo.pSubpasses = &subpass; renderPassInfo.pSubpasses = &subpass;
renderPassInfo.dependencyCount = 1;
renderPassInfo.pDependencies = &dependency;
if (vkCreateRenderPass(Global::device, &renderPassInfo, nullptr, &renderPass) != VK_SUCCESS) { if (vkCreateRenderPass(Global::device, &renderPassInfo, nullptr, &renderPass) != VK_SUCCESS) {
throw std::runtime_error("failed to create render pass!"); throw std::runtime_error("failed to create render pass!");
} }
@ -219,15 +260,16 @@ namespace Graphics {
swapChainFramebuffers.resize(framebuffersSize); swapChainFramebuffers.resize(framebuffersSize);
for(size_t i = 0; i < framebuffersSize; i++) { for(size_t i = 0; i < framebuffersSize; i++) {
VkImageView attachments[] = { std::array<VkImageView, 2> attachments = {
deviceLibs.getSwapChainImageViews()[i] deviceLibs.getSwapChainImageViews()[i],
Global::depthImageView
}; };
VkFramebufferCreateInfo framebufferInfo{}; VkFramebufferCreateInfo framebufferInfo{};
framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
framebufferInfo.renderPass = renderPass; framebufferInfo.renderPass = renderPass;
framebufferInfo.attachmentCount = 1; framebufferInfo.attachmentCount = static_cast<uint32_t>(attachments.size());
framebufferInfo.pAttachments = attachments; framebufferInfo.pAttachments = attachments.data();
framebufferInfo.width = deviceLibs.getSwapChainExtent().width; framebufferInfo.width = deviceLibs.getSwapChainExtent().width;
framebufferInfo.height = deviceLibs.getSwapChainExtent().height; framebufferInfo.height = deviceLibs.getSwapChainExtent().height;
framebufferInfo.layers = 1; framebufferInfo.layers = 1;
@ -285,9 +327,12 @@ namespace Graphics {
renderPassInfo.renderArea.offset = {0, 0}; renderPassInfo.renderArea.offset = {0, 0};
renderPassInfo.renderArea.extent = deviceLibs.getSwapChainExtent(); renderPassInfo.renderArea.extent = deviceLibs.getSwapChainExtent();
VkClearValue clearColor = {{{0.0f, 0.0f, 0.0f, 1.0f}}}; std::array<VkClearValue, 2> clearValues{};
renderPassInfo.clearValueCount = 1; clearValues[0].color = {{0.0f, 0.0f, 0.0f, 1.0f}};
renderPassInfo.pClearValues = &clearColor; clearValues[1].depthStencil = {1.0f, 0};
renderPassInfo.clearValueCount = static_cast<uint32_t>(clearValues.size());
renderPassInfo.pClearValues = clearValues.data();
vkCmdBeginRenderPass(commandBuffer, &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE); vkCmdBeginRenderPass(commandBuffer, &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE);

View File

@ -2,6 +2,8 @@
#include "graphicspipeline.h" #include "graphicspipeline.h"
#include "../devicelibrary.h" #include "../devicelibrary.h"
#include "../entrypoint.h" #include "../entrypoint.h"
#include "texture.h"
#include <vulkan/vulkan_core.h>
namespace RenderPresent { namespace RenderPresent {
std::vector<VkSemaphore> imageAvailableSemaphores; std::vector<VkSemaphore> imageAvailableSemaphores;
@ -10,6 +12,7 @@ namespace RenderPresent {
Graphics::graphicspipeline pipeline; Graphics::graphicspipeline pipeline;
DeviceControl::devicelibrary deviceLibs; DeviceControl::devicelibrary deviceLibs;
BuffersLibraries::buffers buffers; BuffersLibraries::buffers buffers;
TextureLibraries::texture tex;
void recreateSwapChain() { void recreateSwapChain() {
int width = 0, height = 0; int width = 0, height = 0;
@ -30,6 +33,7 @@ namespace RenderPresent {
deviceLibs.createSwapChain(Global::window); deviceLibs.createSwapChain(Global::window);
deviceLibs.createImageViews(); deviceLibs.createImageViews();
tex.createDepthResources();
pipeline.createFramebuffers(); pipeline.createFramebuffers();
} }
// At a high level, rendering in Vulkan consists of 5 steps: // At a high level, rendering in Vulkan consists of 5 steps:
@ -153,6 +157,9 @@ namespace RenderPresent {
} }
} }
void render::cleanupSwapChain() { void render::cleanupSwapChain() {
vkDestroyImageView(Global::device, Global::depthImageView, nullptr);
vkDestroyImage(Global::device, Global::depthImage, nullptr);
vkFreeMemory(Global::device, Global::depthImageMemory, nullptr);
for(auto framebuffer : pipeline.getSwapChainFramebuffers()) { for(auto framebuffer : pipeline.getSwapChainFramebuffers()) {
vkDestroyFramebuffer(Global::device, framebuffer, nullptr); vkDestroyFramebuffer(Global::device, framebuffer, nullptr);
} }

View File

@ -1,3 +1,4 @@
#include <vulkan/vulkan_core.h>
#define STB_IMAGE_IMPLEMENTATION #define STB_IMAGE_IMPLEMENTATION
#include <stb/stb_image.h> #include <stb/stb_image.h>
#include "texture.h" #include "texture.h"
@ -12,6 +13,7 @@ VkPipelineStageFlags sourceStage;
VkPipelineStageFlags destinationStage; VkPipelineStageFlags destinationStage;
namespace TextureLibraries { namespace TextureLibraries {
void createImage(uint32_t width, uint32_t height, VkFormat format, VkImageTiling tiling, VkImageUsageFlags usage, VkMemoryPropertyFlags properties, VkImage& image, VkDeviceMemory& imageMemory) { void createImage(uint32_t width, uint32_t height, VkFormat format, VkImageTiling tiling, VkImageUsageFlags usage, VkMemoryPropertyFlags properties, VkImage& image, VkDeviceMemory& imageMemory) {
// This function specifies all the data in an image object, this is called directly after the creation of an image object. // This function specifies all the data in an image object, this is called directly after the creation of an image object.
@ -164,6 +166,25 @@ void copyBufferToImage(VkBuffer buffer, VkImage image, uint32_t width, uint32_t
endSingleTimeCommands(commandBuffer); endSingleTimeCommands(commandBuffer);
} }
VkFormat findSupportedFormat(const std::vector<VkFormat>& candidates, VkImageTiling tiling, VkFormatFeatureFlags features) {
for(VkFormat format : candidates) {
VkFormatProperties props;
vkGetPhysicalDeviceFormatProperties(Global::physicalDevice, format, &props);
// Do we support linear tiling?
if (tiling == VK_IMAGE_TILING_LINEAR && (props.linearTilingFeatures & features) == features) {
return format;
// Or do we support optimal tiling?
} else if (tiling == VK_IMAGE_TILING_OPTIMAL && (props.optimalTilingFeatures & features) == features) {
return format;
}
}
throw std::runtime_error("failed to find supported depth buffering format!");
}
bool hasStencilComponent(VkFormat format) {
return format == VK_FORMAT_D32_SFLOAT_S8_UINT || format == VK_FORMAT_D24_UNORM_S8_UINT;
}
// -------------------------------- Image Libraries ------------------------------- // // -------------------------------- Image Libraries ------------------------------- //
void texture::createTextureImage() { void texture::createTextureImage() {
// Import pixels from image with data on color channels, width and height, and colorspace! // Import pixels from image with data on color channels, width and height, and colorspace!
@ -198,7 +219,7 @@ void copyBufferToImage(VkBuffer buffer, VkImage image, uint32_t width, uint32_t
} }
void texture::createTextureImageView() { void texture::createTextureImageView() {
// Create a texture image view, which is a struct of information about the image. // Create a texture image view, which is a struct of information about the image.
Global::textureImageView = deviceLibraries.createImageView(textureImage, VK_FORMAT_R8G8B8A8_SRGB); Global::textureImageView = deviceLibraries.createImageView(textureImage, VK_FORMAT_R8G8B8A8_SRGB, VK_IMAGE_ASPECT_COLOR_BIT);
} }
void texture::createTextureSampler() { void texture::createTextureSampler() {
// Create a sampler to access and parse the texture object. // Create a sampler to access and parse the texture object.
@ -250,5 +271,21 @@ void copyBufferToImage(VkBuffer buffer, VkImage image, uint32_t width, uint32_t
vkDestroyImage(Global::device, textureImage, nullptr); vkDestroyImage(Global::device, textureImage, nullptr);
vkFreeMemory(Global::device, textureImageMemory, nullptr); vkFreeMemory(Global::device, textureImageMemory, nullptr);
} }
VkFormat texture::findDepthFormat() {
return findSupportedFormat(
{VK_FORMAT_D32_SFLOAT, VK_FORMAT_D32_SFLOAT_S8_UINT, VK_FORMAT_D24_UNORM_S8_UINT},
VK_IMAGE_TILING_OPTIMAL,
VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT
);
}
void texture::createDepthResources() {
VkFormat depthFormat = findDepthFormat();
VkExtent2D swapChainExtent = deviceLibraries.getSwapChainExtent();
createImage(swapChainExtent.width, swapChainExtent.height, depthFormat, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, Global::depthImage, Global::depthImageMemory);
Global::depthImageView = deviceLibraries.createImageView(Global::depthImage, depthFormat, VK_IMAGE_ASPECT_DEPTH_BIT);
// Explicit transition from the layout of the image to the depth attachment is unnecessary here, since that will be handled in the render pass!
}
} }

View File

@ -1,5 +1,6 @@
#pragma once #pragma once
#include "../global.h" #include "../global.h"
#include <vulkan/vulkan_core.h>
namespace TextureLibraries { namespace TextureLibraries {
class texture { class texture {
@ -9,5 +10,7 @@ namespace TextureLibraries {
void createTextureSampler(); void createTextureSampler();
void destroyTextureImage(); void destroyTextureImage();
void destroyTextureSampler(); void destroyTextureSampler();
VkFormat findDepthFormat();
void createDepthResources();
}; };
} }

View File

@ -6,9 +6,11 @@ layout(binding = 0) uniform UniformBufferObject {
mat4 view; mat4 view;
mat4 proj; mat4 proj;
} ubo; } ubo;
// inPosition and inColor are vertex attributes, per-vertex properties defined in the vertex buffer! // inPosition and inColor are vertex attributes, per-vertex properties defined in the vertex buffer!
// Layout assigns indices to access these inputs, dvec3 takes 2 slots so we must index it at 2. https://www.khronos.org/opengl/wiki/Layout_Qualifier_(GLSL) // Layout assigns indices to access these inputs, dvec3 takes 2 slots so we must index it at 2. https://www.khronos.org/opengl/wiki/Layout_Qualifier_(GLSL)
layout(location = 0) in vec2 inPosition;
layout(location = 0) in vec3 inPosition;
layout(location = 1) in vec3 inColor; layout(location = 1) in vec3 inColor;
layout(location = 2) in vec2 inTexCoord; layout(location = 2) in vec2 inTexCoord;
@ -16,7 +18,7 @@ layout(location = 0) out vec3 fragColor;
layout(location = 1) out vec2 fragTexCoord; layout(location = 1) out vec2 fragTexCoord;
void main() { void main() {
gl_Position = ubo.proj * ubo.view * ubo.model * vec4(inPosition, 0.0, 1.0); gl_Position = ubo.proj * ubo.view * ubo.model * vec4(inPosition, 1.0);
fragColor = inColor; fragColor = inColor;
fragTexCoord = inTexCoord; fragTexCoord = inTexCoord;
} }