depth buffering

This commit is contained in:
Mars 2024-10-11 19:09:37 -04:00
parent f541f6ec8c
commit 02cd99a73a
Signed by: pupbrained
GPG key ID: 874E22DF2F9DFCB5
3 changed files with 176 additions and 120 deletions

View file

@ -1,11 +1,13 @@
#include <chrono>
#include <fmt/format.h>
#include <fstream>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <iostream>
#include <set>
#define GLM_FORCE_DEPTH_ZERO_TO_ONE
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#define STB_IMAGE_IMPLEMENTATION
#include <stb_image.h>
@ -42,7 +44,7 @@ constexpr bool enableValidationLayers = true;
#endif
struct Vertex {
glm::vec2 pos;
glm::vec3 pos;
glm::vec3 color;
glm::vec2 tex_coord;
@ -52,21 +54,30 @@ struct Vertex {
static fn getAttributeDescriptions() -> std::array<vk::VertexInputAttributeDescription, 3> {
return {
{ { 0, 0, vk::Format::eR32G32Sfloat, offsetof(Vertex, pos) },
{ { 0, 0, vk::Format::eR32G32B32Sfloat, offsetof(Vertex, pos) },
{ 1, 0, vk::Format::eR32G32B32Sfloat, offsetof(Vertex, color) },
{ 2, 0, vk::Format::eR32G32Sfloat, offsetof(Vertex, tex_coord) } }
};
}
};
constexpr std::array<Vertex, 4> vertices = {
{ { { -0.5F, -0.5F }, { 1.0F, 0.0F, 0.0F }, { 1.0F, 0.0F } },
{ { 0.5F, -0.5F }, { 0.0F, 1.0F, 0.0F }, { 0.0F, 0.0F } },
{ { 0.5F, 0.5F }, { 0.0F, 0.0F, 1.0F }, { 0.0F, 1.0F } },
{ { -0.5F, 0.5F }, { 1.0F, 1.0F, 1.0F }, { 1.0F, 1.0F } } }
constexpr std::array<Vertex, 8> vertices = {
{ { { -0.5F, -0.5F, 0.0F }, { 1.0F, 0.0F, 0.0F }, { 0.0F, 0.0F } },
{ { 0.5F, -0.5F, 0.0F }, { 0.0F, 1.0F, 0.0F }, { 1.0F, 0.0F } },
{ { 0.5F, 0.5F, 0.0F }, { 0.0F, 0.0F, 1.0F }, { 1.0F, 1.0F } },
{ { -0.5F, 0.5F, 0.0F }, { 1.0F, 1.0F, 1.0F }, { 0.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 } } }
};
constexpr std::array<u16, 6> indices = { 0, 1, 2, 2, 3, 0 };
// clang-format off
constexpr std::array<u16, 12> indices = {
0, 1, 2, 2, 3, 0,
4, 5, 6, 6, 7, 4
};
// clang-format on
class VulkanApp {
public:
@ -105,6 +116,10 @@ class VulkanApp {
vk::UniqueCommandPool mCommandPool;
vk::UniqueImage mDepthImage;
vk::UniqueDeviceMemory mDepthImageMemory;
vk::UniqueImageView mDepthImageView;
vk::UniqueImage mTextureImage;
vk::UniqueDeviceMemory mTextureImageMemory;
vk::UniqueImageView mTextureImageView;
@ -196,8 +211,9 @@ class VulkanApp {
createRenderPass();
createDescriptorSetLayout();
createGraphicsPipeline();
createFramebuffers();
createCommandPool();
createDepthResources();
createFramebuffers();
createTextureImage();
createTextureImageView();
createTextureSampler();
@ -220,10 +236,8 @@ class VulkanApp {
}
fn cleanupSwapChain() -> void {
for (vk::UniqueFramebuffer& mSwapChainFramebuffer : mSwapChainFramebuffers) {
mSwapChainFramebuffer.reset();
}
for (vk::UniqueImageView& mSwapChainImageView : mSwapChainImageViews) { mSwapChainImageView.reset(); }
for (vk::UniqueFramebuffer& mSwapChainFramebuffer : mSwapChainFramebuffers) mSwapChainFramebuffer.reset();
for (vk::UniqueImageView& mSwapChainImageView : mSwapChainImageViews) mSwapChainImageView.reset();
mSwapChain.reset();
}
@ -243,6 +257,7 @@ class VulkanApp {
createSwapChain();
createImageViews();
createDepthResources();
createFramebuffers();
}
@ -415,26 +430,9 @@ class VulkanApp {
fn createImageViews() -> void {
mSwapChainImageViews.resize(mSwapChainImages.size());
for (u32 i = 0; i < mSwapChainImages.size(); i++) {
vk::ImageViewCreateInfo createInfo {
.image = mSwapChainImages[i],
.viewType = vk::ImageViewType::e2D,
.format = mSwapChainImageFormat,
// clang-format off
.components = { .r = vk::ComponentSwizzle::eIdentity,
.g = vk::ComponentSwizzle::eIdentity,
.b = vk::ComponentSwizzle::eIdentity,
.a = vk::ComponentSwizzle::eIdentity },
.subresourceRange = { .aspectMask = vk::ImageAspectFlagBits::eColor,
.baseMipLevel = 0,
.levelCount = 1,
.baseArrayLayer = 0,
.layerCount = 1 },
// clang-format on
};
mSwapChainImageViews[i] = mDevice->createImageViewUnique(createInfo);
}
for (u32 i = 0; i < mSwapChainImages.size(); i++)
mSwapChainImageViews[i] =
createImageView(mSwapChainImages[i], mSwapChainImageFormat, vk::ImageAspectFlagBits::eColor);
}
fn createRenderPass() -> void {
@ -449,23 +447,47 @@ class VulkanApp {
.finalLayout = vk::ImageLayout::ePresentSrcKHR,
};
vk::AttachmentDescription depthAttachment { .format = findDepthFormat(),
.samples = vk::SampleCountFlagBits::e1,
.loadOp = vk::AttachmentLoadOp::eClear,
.storeOp = vk::AttachmentStoreOp::eDontCare,
.stencilLoadOp = vk::AttachmentLoadOp::eDontCare,
.stencilStoreOp = vk::AttachmentStoreOp::eDontCare,
.initialLayout = vk::ImageLayout::eUndefined,
.finalLayout =
vk::ImageLayout::eDepthStencilAttachmentOptimal };
vk::AttachmentReference colorAttachmentRef {
.attachment = 0,
.layout = vk::ImageLayout::eColorAttachmentOptimal,
};
vk::SubpassDescription subpass {
.pipelineBindPoint = vk::PipelineBindPoint::eGraphics,
.colorAttachmentCount = 1,
.pColorAttachments = &colorAttachmentRef,
};
vk::AttachmentReference depthAttachmentRef { .attachment = 1,
.layout = vk::ImageLayout::eDepthStencilAttachmentOptimal };
vk::RenderPassCreateInfo renderPassInfo {
.attachmentCount = 1,
.pAttachments = &colorAttachment,
.subpassCount = 1,
.pSubpasses = &subpass,
};
vk::SubpassDescription subpass { .pipelineBindPoint = vk::PipelineBindPoint::eGraphics,
.colorAttachmentCount = 1,
.pColorAttachments = &colorAttachmentRef,
.pDepthStencilAttachment = &depthAttachmentRef };
vk::SubpassDependency dependency { .srcSubpass = vk::SubpassExternal,
.dstSubpass = {},
.srcStageMask = vk::PipelineStageFlagBits::eColorAttachmentOutput |
vk::PipelineStageFlagBits::eEarlyFragmentTests,
.dstStageMask = vk::PipelineStageFlagBits::eColorAttachmentOutput |
vk::PipelineStageFlagBits::eEarlyFragmentTests,
.srcAccessMask = {},
.dstAccessMask = vk::AccessFlagBits::eColorAttachmentWrite |
vk::AccessFlagBits::eDepthStencilAttachmentWrite };
std::array<vk::AttachmentDescription, 2> attachments = { colorAttachment, depthAttachment };
vk::RenderPassCreateInfo renderPassInfo { .attachmentCount = static_cast<u32>(attachments.size()),
.pAttachments = attachments.data(),
.subpassCount = 1,
.pSubpasses = &subpass,
.dependencyCount = 1,
.pDependencies = &dependency };
mRenderPass = mDevice->createRenderPassUnique(renderPassInfo);
}
@ -504,17 +526,13 @@ class VulkanApp {
vk::UniqueShaderModule vertShaderModule = createShaderModule(vertShaderCode);
vk::UniqueShaderModule fragShaderModule = createShaderModule(fragShaderCode);
vk::PipelineShaderStageCreateInfo vertShaderStageInfo {
.stage = vk::ShaderStageFlagBits::eVertex,
.module = vertShaderModule.get(),
.pName = "main",
};
vk::PipelineShaderStageCreateInfo vertShaderStageInfo { .stage = vk::ShaderStageFlagBits::eVertex,
.module = vertShaderModule.get(),
.pName = "main" };
vk::PipelineShaderStageCreateInfo fragShaderStageInfo {
.stage = vk::ShaderStageFlagBits::eFragment,
.module = fragShaderModule.get(),
.pName = "main",
};
vk::PipelineShaderStageCreateInfo fragShaderStageInfo { .stage = vk::ShaderStageFlagBits::eFragment,
.module = fragShaderModule.get(),
.pName = "main" };
std::array<vk::PipelineShaderStageCreateInfo, 2> shaderStages = { vertShaderStageInfo,
fragShaderStageInfo };
@ -527,38 +545,36 @@ class VulkanApp {
.vertexBindingDescriptionCount = 1,
.pVertexBindingDescriptions = &bindingDescription,
.vertexAttributeDescriptionCount = static_cast<u32>(attributeDescriptions.size()),
.pVertexAttributeDescriptions = attributeDescriptions.data(),
.pVertexAttributeDescriptions = attributeDescriptions.data()
};
vk::PipelineInputAssemblyStateCreateInfo inputAssembly {
.topology = vk::PrimitiveTopology::eTriangleList,
.primitiveRestartEnable = vk::False,
};
vk::PipelineInputAssemblyStateCreateInfo inputAssembly { .topology = vk::PrimitiveTopology::eTriangleList,
.primitiveRestartEnable = vk::False };
vk::PipelineViewportStateCreateInfo viewportState {
.viewportCount = 1,
.scissorCount = 1,
};
vk::PipelineViewportStateCreateInfo viewportState { .viewportCount = 1, .scissorCount = 1 };
vk::PipelineRasterizationStateCreateInfo rasterizer {
.depthClampEnable = vk::False,
.rasterizerDiscardEnable = vk::False,
.polygonMode = vk::PolygonMode::eFill,
.cullMode = vk::CullModeFlagBits::eBack,
.frontFace = vk::FrontFace::eCounterClockwise,
.depthBiasEnable = vk::False,
.lineWidth = 1.0F,
};
vk::PipelineRasterizationStateCreateInfo rasterizer { .depthClampEnable = vk::False,
.rasterizerDiscardEnable = vk::False,
.polygonMode = vk::PolygonMode::eFill,
.cullMode = vk::CullModeFlagBits::eBack,
.frontFace = vk::FrontFace::eCounterClockwise,
.depthBiasEnable = vk::False,
.lineWidth = 1.0F };
vk::PipelineMultisampleStateCreateInfo multisampling {
.rasterizationSamples = vk::SampleCountFlagBits::e1,
.sampleShadingEnable = vk::False,
};
vk::PipelineMultisampleStateCreateInfo multisampling { .rasterizationSamples =
vk::SampleCountFlagBits::e1,
.sampleShadingEnable = vk::False };
vk::PipelineDepthStencilStateCreateInfo depthStencil { .depthTestEnable = vk::True,
.depthWriteEnable = vk::True,
.depthCompareOp = vk::CompareOp::eLess,
.depthBoundsTestEnable = vk::False,
.stencilTestEnable = vk::False };
vk::PipelineColorBlendAttachmentState colorBlendAttachment {
.blendEnable = vk::False,
.colorWriteMask = vk::ColorComponentFlagBits::eR | vk::ColorComponentFlagBits::eG |
vk::ColorComponentFlagBits::eB | vk::ColorComponentFlagBits::eA,
vk::ColorComponentFlagBits::eB | vk::ColorComponentFlagBits::eA
};
vk::PipelineColorBlendStateCreateInfo colorBlending {
@ -566,37 +582,33 @@ class VulkanApp {
.logicOp = vk::LogicOp::eCopy,
.attachmentCount = 1,
.pAttachments = &colorBlendAttachment,
.blendConstants = std::array<float, 4> { 0.0F, 0.0F, 0.0F, 0.0F },
.blendConstants = std::array<float, 4> { 0.0F, 0.0F, 0.0F, 0.0F }
};
std::vector<vk::DynamicState> dynamicStates = { vk::DynamicState::eViewport, vk::DynamicState::eScissor };
vk::PipelineDynamicStateCreateInfo dynamicState {
.dynamicStateCount = static_cast<u32>(dynamicStates.size()),
.pDynamicStates = dynamicStates.data(),
};
vk::PipelineDynamicStateCreateInfo dynamicState { .dynamicStateCount =
static_cast<u32>(dynamicStates.size()),
.pDynamicStates = dynamicStates.data() };
vk::PipelineLayoutCreateInfo pipelineLayoutInfo {
.setLayoutCount = 1,
.pSetLayouts = &mDescriptorSetLayout.get(),
};
vk::PipelineLayoutCreateInfo pipelineLayoutInfo { .setLayoutCount = 1,
.pSetLayouts = &mDescriptorSetLayout.get() };
mPipelineLayout = mDevice->createPipelineLayoutUnique(pipelineLayoutInfo);
vk::GraphicsPipelineCreateInfo pipelineInfo {
.stageCount = static_cast<u32>(shaderStages.size()),
.pStages = shaderStages.data(),
.pVertexInputState = &vertexInputInfo,
.pInputAssemblyState = &inputAssembly,
.pViewportState = &viewportState,
.pRasterizationState = &rasterizer,
.pMultisampleState = &multisampling,
.pColorBlendState = &colorBlending,
.pDynamicState = &dynamicState,
.layout = mPipelineLayout.get(),
.renderPass = mRenderPass.get(),
.subpass = 0,
};
vk::GraphicsPipelineCreateInfo pipelineInfo { .stageCount = static_cast<u32>(shaderStages.size()),
.pStages = shaderStages.data(),
.pVertexInputState = &vertexInputInfo,
.pInputAssemblyState = &inputAssembly,
.pViewportState = &viewportState,
.pRasterizationState = &rasterizer,
.pMultisampleState = &multisampling,
.pDepthStencilState = &depthStencil,
.pColorBlendState = &colorBlending,
.pDynamicState = &dynamicState,
.layout = mPipelineLayout.get(),
.renderPass = mRenderPass.get(),
.subpass = 0 };
vk::Result graphicsPipelineResult = vk::Result::eSuccess;
vk::UniquePipeline graphicsPipelineValue;
@ -614,14 +626,14 @@ class VulkanApp {
mSwapChainFramebuffers.resize(mSwapChainImageViews.size());
for (usize i = 0; i < mSwapChainImageViews.size(); i++) {
vk::FramebufferCreateInfo framebufferInfo {
.renderPass = mRenderPass.get(),
.attachmentCount = 1,
.pAttachments = &mSwapChainImageViews[i].get(),
.width = mSwapChainExtent.width,
.height = mSwapChainExtent.height,
.layers = 1,
};
std::array<vk::ImageView, 2> attachments = { mSwapChainImageViews[i].get(), mDepthImageView.get() };
vk::FramebufferCreateInfo framebufferInfo { .renderPass = mRenderPass.get(),
.attachmentCount = static_cast<u32>(attachments.size()),
.pAttachments = attachments.data(),
.width = mSwapChainExtent.width,
.height = mSwapChainExtent.height,
.layers = 1 };
mSwapChainFramebuffers[i] = mDevice->createFramebufferUnique(framebufferInfo);
}
@ -638,6 +650,51 @@ class VulkanApp {
mCommandPool = mDevice->createCommandPoolUnique(poolInfo);
}
fn createDepthResources() -> void {
vk::Format depthFormat = findDepthFormat();
createImage(
mSwapChainExtent.width,
mSwapChainExtent.height,
depthFormat,
vk::ImageTiling::eOptimal,
vk::ImageUsageFlagBits::eDepthStencilAttachment,
vk::MemoryPropertyFlagBits::eDeviceLocal,
mDepthImage,
mDepthImageMemory
);
mDepthImageView = createImageView(mDepthImage.get(), depthFormat, vk::ImageAspectFlagBits::eDepth);
}
fn findSupportedFormat(
const std::vector<vk::Format>& candidates,
vk::ImageTiling tiling,
vk::FormatFeatureFlags features
) -> vk::Format {
for (vk::Format format : candidates) {
vk::FormatProperties props = mPhysicalDevice.getFormatProperties(format);
if (tiling == vk::ImageTiling::eLinear && (props.linearTilingFeatures & features) == features)
return format;
if (tiling == vk::ImageTiling::eOptimal && (props.optimalTilingFeatures & features) == features)
return format;
}
throw std::runtime_error("Failed to find supported format!");
}
fn findDepthFormat() -> vk::Format {
return findSupportedFormat(
{ vk::Format::eD32Sfloat, vk::Format::eD32SfloatS8Uint, vk::Format::eD24UnormS8Uint },
vk::ImageTiling::eOptimal,
vk::FormatFeatureFlagBits::eDepthStencilAttachment
);
}
static fn hasStencilComponent(vk::Format format) {
return format == vk::Format::eD32SfloatS8Uint || format == vk::Format::eD24UnormS8Uint;
}
fn createTextureImage() -> void {
i32 texWidth = 0, texHeight = 0, texChannels = 0;
u8* pixels = stbi_load("src/textures/texture.jpg", &texWidth, &texHeight, &texChannels, STBI_rgb_alpha);
@ -783,8 +840,6 @@ class VulkanApp {
vk::UniqueCommandBuffer commandBuffer = beginSingleTimeCommands();
vk::ImageMemoryBarrier barrier {
.srcAccessMask = { },
.dstAccessMask = { },
.oldLayout = oldLayout,
.newLayout = newLayout,
.srcQueueFamilyIndex = vk::QueueFamilyIgnored,
@ -795,7 +850,7 @@ class VulkanApp {
.baseMipLevel = 0,
.levelCount = 1,
.baseArrayLayer = 0,
.layerCount = 1 },
.layerCount = 1 }
// clang-format on
};
@ -1080,14 +1135,17 @@ class VulkanApp {
commandBuffer.begin(beginInfo);
vk::ClearValue clearColor { .color = { .float32 = std::array<float, 4> { 0.0F, 0.0F, 0.0F, 1.0F } } };
std::array<vk::ClearValue, 2> clearValues {
{ { .color = { .float32 = std::array<float, 4> { 0.0F, 0.0F, 0.0F, 1.0F } } },
{ .depthStencil = { .depth = 1.0F, .stencil = 0 } } }
};
vk::RenderPassBeginInfo renderPassInfo {
.renderPass = mRenderPass.get(),
.framebuffer = mSwapChainFramebuffers[imageIndex].get(),
.renderArea = { .offset = { .x = 0, .y = 0 }, .extent = mSwapChainExtent },
.clearValueCount = 1,
.pClearValues = &clearColor,
.clearValueCount = static_cast<u32>(clearValues.size()),
.pClearValues = clearValues.data()
};
commandBuffer.beginRenderPass(renderPassInfo, vk::SubpassContents::eInline);
@ -1226,8 +1284,6 @@ class VulkanApp {
vk::Result presentResult = mPresentQueue.presentKHR(presentInfo);
fmt::println("Present result: {}", vk::to_string(presentResult));
if (presentResult == vk::Result::eErrorOutOfDateKHR || presentResult == vk::Result::eSuboptimalKHR ||
mFramebufferResized) {
mFramebufferResized = false;

View file

@ -6,7 +6,7 @@ layout(binding = 0) uniform UniformBufferObject {
mat4 proj;
} ubo;
layout(location = 0) in vec2 inPosition;
layout(location = 0) in vec3 inPosition;
layout(location = 1) in vec3 inColor;
layout(location = 2) in vec2 inTexCoord;
@ -14,7 +14,7 @@ layout(location = 0) out vec3 fragColor;
layout(location = 1) out vec2 fragTexCoord;
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;
fragTexCoord = inTexCoord;
}

Binary file not shown.