From d8f9b574b10c0daae61e06c99a39d10c563a5b93 Mon Sep 17 00:00:00 2001 From: Amber Date: Thu, 27 Oct 2022 16:09:57 +0200 Subject: [PATCH] Add depth testing. --- src/main.c | 112 ++++++++++++++++++++++++++++++++++------- src/vertex_simple.vert | 4 +- 2 files changed, 95 insertions(+), 21 deletions(-) diff --git a/src/main.c b/src/main.c index 51cc194..881b9a1 100644 --- a/src/main.c +++ b/src/main.c @@ -1,4 +1,5 @@ #define GLFW_INCLUDE_VULKAN +#define GLM_FORCE_DEPTH_ZERO_TO_ONE #include #include @@ -95,6 +96,10 @@ typedef struct ApplicationState { VkDeviceMemory texture_image_memory; VkImageView texture_image_view; VkSampler texture_sampler; + + VkImage depth_image; + VkDeviceMemory depth_image_memory; + VkImageView depth_image_view; } ApplicationState; typedef struct QueueFamilyIndices { @@ -105,20 +110,27 @@ typedef struct QueueFamilyIndices { } QueueFamilyIndices; typedef struct Vertex { - vec2 position; + vec3 position; vec3 color; vec2 tex_coord; } Vertex; const Vertex 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}} + {{-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}} }; const uint16_t indices[] = { - 0, 1, 2, 2, 3, 0 + 0, 1, 2, 2, 3, 0, + 4, 5, 6, 6, 7, 4 + }; typedef struct UBO { @@ -643,6 +655,16 @@ void create_render_pass(ApplicationState* state) { //images to be presented color_attachment.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; + VkAttachmentDescription depth_attachment = {0}; + depth_attachment.format = VK_FORMAT_D32_SFLOAT; + depth_attachment.samples = VK_SAMPLE_COUNT_1_BIT; + depth_attachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; + depth_attachment.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + depth_attachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + depth_attachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + depth_attachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + depth_attachment.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + //there may be multiple subpasses, subpasses depend on the previous framebuffer contents //they can be used for things sych as postprocessing //every subpass references one or more attachment @@ -650,18 +672,24 @@ void create_render_pass(ApplicationState* state) { color_attachment_reference.attachment = 0; color_attachment_reference.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + VkAttachmentReference depth_attachment_reference = {0}; + depth_attachment_reference.attachment = 1; + depth_attachment_reference.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + //now we create the subpass //layout(location = 0) out vec4 outColor; VkSubpassDescription subpass = {0}; subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; subpass.colorAttachmentCount = 1; subpass.pColorAttachments = &color_attachment_reference; + subpass.pDepthStencilAttachment = &depth_attachment_reference; + VkAttachmentDescription attachments[2] = {color_attachment, depth_attachment}; //let's create the render pass VkRenderPassCreateInfo render_pass_info = {0}; render_pass_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; - render_pass_info.attachmentCount = 1; - render_pass_info.pAttachments = &color_attachment; + render_pass_info.attachmentCount = ARRSIZE(attachments); + render_pass_info.pAttachments = attachments; render_pass_info.subpassCount = 1; render_pass_info.pSubpasses = &subpass; @@ -680,11 +708,11 @@ void create_render_pass(ApplicationState* state) { dependency.srcSubpass = VK_SUBPASS_EXTERNAL; dependency.dstSubpass = 0; //wait on the color attachment - dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT; dependency.srcAccessMask = 0; //the part of the subpass when the attachment is written has to wait - dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT; + dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; render_pass_info.dependencyCount = 1; render_pass_info.pDependencies = &dependency; @@ -786,7 +814,7 @@ void create_graphics_pipeline(ApplicationState* state) { //We have position and color, so we need two descriptions VkVertexInputAttributeDescription attribute_description[3] = { - {.binding = 0, .location = 0, .format = VK_FORMAT_R32G32_SFLOAT, .offset = offsetof(Vertex, position)}, + {.binding = 0, .location = 0, .format = VK_FORMAT_R32G32B32_SFLOAT, .offset = offsetof(Vertex, position)}, {.binding = 0, .location = 1, .format = VK_FORMAT_R32G32B32_SFLOAT, .offset = offsetof(Vertex, color)}, {.binding = 0, .location = 2, .format = VK_FORMAT_R32G32_SFLOAT, .offset = offsetof(Vertex, tex_coord)}, }; @@ -891,6 +919,16 @@ void create_graphics_pipeline(ApplicationState* state) { printf("created pipeline layout\n"); + VkPipelineDepthStencilStateCreateInfo depth_stencil = {0}; + depth_stencil.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO; + depth_stencil.depthTestEnable = VK_TRUE; + depth_stencil.depthWriteEnable = VK_TRUE; + depth_stencil.depthCompareOp = VK_COMPARE_OP_LESS; + depth_stencil.depthBoundsTestEnable = VK_FALSE; + depth_stencil.minDepthBounds = 0.0f; // Optional + depth_stencil.maxDepthBounds = 1.0f; // Optional + depth_stencil.stencilTestEnable = VK_FALSE; + VkGraphicsPipelineCreateInfo pipeline_info = {0}; pipeline_info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; //shaders @@ -905,6 +943,7 @@ void create_graphics_pipeline(ApplicationState* state) { pipeline_info.pDepthStencilState = NULL; // Optional pipeline_info.pColorBlendState = &color_blending; pipeline_info.pDynamicState = &dynamic_state; + pipeline_info.pDepthStencilState = &depth_stencil; pipeline_info.layout = state->pipeline_layout; pipeline_info.renderPass = state->render_pass; @@ -931,13 +970,14 @@ void create_framebuffers(ApplicationState* state) { for (int i = 0; i < state->swapchain_image_count; i++) { printf("creating framebuffer %x\n", i); VkImageView attachments[] = { - state->swapchain_image_views[i] + state->swapchain_image_views[i], + state->depth_image_view }; VkFramebufferCreateInfo framebuffer_info = {0}; framebuffer_info.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; framebuffer_info.renderPass = state->render_pass; - framebuffer_info.attachmentCount = 1; + framebuffer_info.attachmentCount = ARRSIZE(attachments); framebuffer_info.pAttachments = attachments; framebuffer_info.width = state->swapchain_extent.width; framebuffer_info.height = state->swapchain_extent.height; @@ -1136,7 +1176,7 @@ void create_image(ApplicationState* state, uint32_t width, uint32_t height, VkFo } VkMemoryRequirements mem_req; - vkGetImageMemoryRequirements(state->device, state->texture_image, &mem_req); + vkGetImageMemoryRequirements(state->device, *image, &mem_req); VkMemoryAllocateInfo alloc_info = {0}; alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; @@ -1224,6 +1264,27 @@ void copy_buffer_to_image(ApplicationState* state, VkBuffer to_copy, VkImage ima end_single_time_commands(state, buffer); } +void create_depth_resources(ApplicationState* state) { + create_image(state, state->swapchain_extent.width, state->swapchain_extent.height, VK_FORMAT_D32_SFLOAT, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, + &state->depth_image, &state->depth_image_memory); + + VkImageViewCreateInfo view_info = {0}; + view_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; + view_info.image = state->depth_image; + view_info.viewType = VK_IMAGE_VIEW_TYPE_2D; + view_info.format = VK_FORMAT_D32_SFLOAT; + view_info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; + view_info.subresourceRange.baseMipLevel = 0; + view_info.subresourceRange.levelCount = 1; + view_info.subresourceRange.baseArrayLayer = 0; + view_info.subresourceRange.layerCount = 1; + + if (vkCreateImageView(state->device, &view_info, NULL, &state->depth_image_view) != VK_SUCCESS) { + printf("failed to create texture image view\n"); + exit(1); + } +} + void create_texture_image(ApplicationState* state) { int width, height, channels; stbi_uc* pixels = stbi_load("../src/res/texture.jpg", &width, &height, &channels, STBI_rgb_alpha); @@ -1420,9 +1481,17 @@ void record_command_buffer(ApplicationState* state, VkCommandBuffer command_buff render_pass_info.renderArea.offset.y = 0; render_pass_info.renderArea.extent = state->swapchain_extent; - VkClearValue clearColor = {0}; - render_pass_info.clearValueCount = 1; - render_pass_info.pClearValues = &clearColor; + VkClearValue clear_color = {0}; + VkClearValue stencil_clear; + stencil_clear.depthStencil.depth = 1.0f; + stencil_clear.depthStencil.stencil = 0; + + VkClearValue clear_values[2]; + clear_values[0] = clear_color; + clear_values[1] = stencil_clear; + + render_pass_info.clearValueCount = ARRSIZE(clear_values); + render_pass_info.pClearValues = clear_values; //can also be VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS to execute command stored in secondary buffers vkCmdBeginRenderPass(command_buffer, &render_pass_info, VK_SUBPASS_CONTENTS_INLINE); @@ -1496,8 +1565,9 @@ void init_vulkan(ApplicationState* state) { create_render_pass(state); create_descriptor_set_layout(state); create_graphics_pipeline(state); - create_framebuffers(state); create_command_pool(state); + create_depth_resources(state); + create_framebuffers(state); create_texture_image(state); create_texture_image_view(state); create_texture_image_sampler(state); @@ -1512,6 +1582,7 @@ void init_vulkan(ApplicationState* state) { void update_uniform_buffer(ApplicationState* state, uint32_t current_frame) { uint64_t time = clock() / (CLOCKS_PER_SEC / 1000); + time = 0; UBO ubo = {0}; glm_mat4_identity(ubo.model); @@ -1626,6 +1697,9 @@ void terminate(ApplicationState* state) { vkDestroyImageView(state->device, state->texture_image_view, NULL); vkDestroyImage(state->device, state->texture_image, NULL); vkFreeMemory(state->device, state->texture_image_memory, NULL); + vkDestroyImageView(state->device, state->depth_image_view, NULL); + vkDestroyImage(state->device, state->depth_image, NULL); + vkFreeMemory(state->device, state->depth_image_memory, NULL); vkDestroySwapchainKHR(state->device, state->swapchain, NULL); vkDestroyDevice(state->device, NULL); diff --git a/src/vertex_simple.vert b/src/vertex_simple.vert index f44a8e1..3aeb5d8 100644 --- a/src/vertex_simple.vert +++ b/src/vertex_simple.vert @@ -6,7 +6,7 @@ layout(binding = 0) uniform UBO { 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; }