From 9ccfe3d0f70c6b5177bb64bdb87dab38e6f86acb Mon Sep 17 00:00:00 2001 From: Noah Metz Date: Tue, 9 Jan 2024 13:12:05 -0700 Subject: [PATCH] Added depth image to context --- src/main.c | 222 +++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 172 insertions(+), 50 deletions(-) diff --git a/src/main.c b/src/main.c index 16ed748..4f957b7 100644 --- a/src/main.c +++ b/src/main.c @@ -121,6 +121,10 @@ typedef struct VulkanContextStruct { VkImageView* swapchain_image_views; VkFramebuffer* swapchain_framebuffers; + AllocatedImage depth_image; + VkFormat depth_format; + VkImageView depth_image_view; + uint32_t max_frames_in_flight; // Per frame objects VkCommandBuffer* swapchain_command_buffers; @@ -219,6 +223,20 @@ GLFWwindow* init_window(int width, int height) { return window; } +VkFormat find_depth_format(VkPhysicalDevice physical_device, uint32_t num_requested, VkFormat* requested, VkImageTiling tiling, VkFormatFeatureFlags features) { + for(uint32_t i = 0; i < num_requested; i++) { + VkFormatProperties properties; + vkGetPhysicalDeviceFormatProperties(physical_device, requested[i], &properties); + + if(tiling == VK_IMAGE_TILING_LINEAR && (properties.linearTilingFeatures & features) == features) { + return requested[i]; + } else if (tiling == VK_IMAGE_TILING_OPTIMAL && (properties.optimalTilingFeatures & features) == features) { + return requested[i]; + } + } + return VK_FORMAT_MAX_ENUM; +} + bool check_validation_layers(const char ** layers, uint32_t num_layers) { uint32_t layer_count; VkResult result; @@ -883,7 +901,7 @@ VkImageView* create_image_views(VkDevice device, uint32_t image_count, VkImage* return image_views; } -VkFramebuffer* create_swapchain_framebuffers(VkDevice device, uint32_t image_count, VkImageView* image_views, VkRenderPass render_pass, VkExtent2D extent) { +VkFramebuffer* create_swapchain_framebuffers(VkDevice device, uint32_t image_count, VkImageView* image_views, VkImageView depth_image_view, VkRenderPass render_pass, VkExtent2D extent) { VkFramebuffer* framebuffers = malloc(sizeof(VkFramebuffer)*image_count); if(framebuffers == 0) { return 0; @@ -892,12 +910,13 @@ VkFramebuffer* create_swapchain_framebuffers(VkDevice device, uint32_t image_cou for(uint32_t i = 0; i < image_count; i++) { VkImageView attachments[] = { image_views[i], + depth_image_view, }; VkFramebufferCreateInfo framebuffer_info = {}; framebuffer_info.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; framebuffer_info.renderPass = render_pass; - framebuffer_info.attachmentCount = 1; + framebuffer_info.attachmentCount = 2; framebuffer_info.pAttachments = attachments; framebuffer_info.width = extent.width; framebuffer_info.height = extent.height; @@ -948,42 +967,67 @@ VkShaderModule load_shader_file(uint32_t buffer_size, const char* path, VkDevice return shader; } -VkRenderPass create_render_pass(VkDevice device, VkSurfaceFormatKHR format) { - VkAttachmentDescription color_attachment; - color_attachment.format = format.format; - color_attachment.samples = VK_SAMPLE_COUNT_1_BIT; - color_attachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; - color_attachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE; - color_attachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; - color_attachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE; - color_attachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - color_attachment.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; - - VkAttachmentReference color_attachment_ref = {}; - color_attachment_ref.attachment = 0; - color_attachment_ref.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - - VkSubpassDescription subpass = {}; - subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; - subpass.colorAttachmentCount = 1; - subpass.pColorAttachments = &color_attachment_ref; - - VkSubpassDependency dependency = {}; - dependency.srcSubpass = VK_SUBPASS_EXTERNAL; - dependency.dstSubpass = 0; - dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - dependency.srcAccessMask = 0; - dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - - VkRenderPassCreateInfo render_info = {}; - render_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; - render_info.attachmentCount = 1; - render_info.pAttachments = &color_attachment; - render_info.subpassCount = 1; - render_info.pSubpasses = &subpass; - render_info.dependencyCount = 1; - render_info.pDependencies = &dependency; +VkRenderPass create_render_pass(VkDevice device, VkSurfaceFormatKHR format, VkFormat depth_format) { + VkAttachmentDescription attachments[] = { + { + .format = format.format, + .samples = VK_SAMPLE_COUNT_1_BIT, + .loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR, + .storeOp = VK_ATTACHMENT_STORE_OP_STORE, + .stencilLoadOp = VK_ATTACHMENT_LOAD_OP_CLEAR, + .stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE, + .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED, + .finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, + }, + { + .format = depth_format, + .samples = VK_SAMPLE_COUNT_1_BIT, + .loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR, + .storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE, + .stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE, + .stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE, + .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED, + .finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, + }, + }; + + VkAttachmentReference color_attachment_refs[] = { + { + .attachment = 0, + .layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, + }, + }; + + VkAttachmentReference depth_attachment_ref = { + .attachment = 1, + .layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, + }; + + VkSubpassDescription subpass = { + .pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS, + .colorAttachmentCount = sizeof(color_attachment_refs)/sizeof(VkAttachmentReference), + .pColorAttachments = color_attachment_refs, + .pDepthStencilAttachment = &depth_attachment_ref, + }; + + VkSubpassDependency dependency = { + .srcSubpass = VK_SUBPASS_EXTERNAL, + .dstSubpass = 0, + .srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT, + .srcAccessMask = 0, + .dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT, + .dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, + }; + + VkRenderPassCreateInfo render_info = { + .sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, + .attachmentCount = sizeof(attachments)/sizeof(VkAttachmentDescription), + .pAttachments = attachments, + .subpassCount = 1, + .pSubpasses = &subpass, + .dependencyCount = 1, + .pDependencies = &dependency, + }; VkRenderPass render_pass; VkResult result = vkCreateRenderPass(device, &render_info, 0, &render_pass); @@ -1025,7 +1069,7 @@ uint32_t find_memory_type(VkPhysicalDevice physical_device, uint32_t type_filter return 0xFFFFFFFF; } -AllocatedImage allocate_image(VkPhysicalDevice physical_device, VkDevice device, VkImageType type, VkFormat format, VkExtent3D size, VkImageUsageFlags usage, VkMemoryPropertyFlags properties, VkSampleCountFlagBits samples) { +AllocatedImage allocate_image(VkPhysicalDevice physical_device, VkDevice device, VkImageType type, VkFormat format, VkExtent3D size, VkImageUsageFlags usage, VkMemoryPropertyFlags properties) { VkImageCreateInfo image_info = { .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, .imageType = type, @@ -1037,7 +1081,7 @@ AllocatedImage allocate_image(VkPhysicalDevice physical_device, VkDevice device, .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED, .usage = usage, .sharingMode = VK_SHARING_MODE_EXCLUSIVE, - .samples = samples, + .samples = VK_SAMPLE_COUNT_1_BIT, .flags = 0, }; @@ -1335,7 +1379,7 @@ Texture load_texture(VkPhysicalDevice physical_device, VkDevice device, VkComman .height = size.height, .depth = 1, }; - AllocatedImage image = allocate_image(physical_device, device, VK_IMAGE_TYPE_2D, format, full_extent, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, VK_SAMPLE_COUNT_1_BIT); + AllocatedImage image = allocate_image(physical_device, device, VK_IMAGE_TYPE_2D, format, full_extent, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); if(image.memory == VK_NULL_HANDLE) { deallocate_buffer(device, staging); deallocate_image(device, image); @@ -1495,6 +1539,19 @@ VkPipeline create_graphics_pipeline( multisample_info.alphaToCoverageEnable = VK_FALSE; multisample_info.alphaToOneEnable = VK_FALSE; + VkPipelineDepthStencilStateCreateInfo depth_info = { + .sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, + .depthTestEnable = VK_TRUE, + .depthWriteEnable = VK_TRUE, + .depthCompareOp = VK_COMPARE_OP_LESS, + .depthBoundsTestEnable = VK_FALSE, + .maxDepthBounds = 1.0f, + .minDepthBounds = 0.0f, + .stencilTestEnable = VK_FALSE, + .front = {}, + .back = {}, + }; + VkPipelineColorBlendAttachmentState color_blend_attachment = {}; color_blend_attachment.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; color_blend_attachment.blendEnable = VK_TRUE; @@ -1527,6 +1584,7 @@ VkPipeline create_graphics_pipeline( pipeline_info.pDepthStencilState = 0; pipeline_info.pColorBlendState = &color_blend_info; pipeline_info.pDynamicState = &dynamic_info; + pipeline_info.pDepthStencilState = &depth_info; pipeline_info.layout = layout; pipeline_info.renderPass = render_pass; pipeline_info.subpass = 0; @@ -1607,7 +1665,7 @@ VkResult recreate_swap_chain(VulkanContext* context, VkExtent2D new_extent) { context->swapchain_image_views = image_views; } - VkFramebuffer* framebuffers = create_swapchain_framebuffers(context->device, context->swapchain_image_count, context->swapchain_image_views, context->render_pass, context->swapchain_extent); + VkFramebuffer* framebuffers = create_swapchain_framebuffers(context->device, context->swapchain_image_count, context->swapchain_image_views, context->depth_image_view, context->render_pass, context->swapchain_extent); if(framebuffers == 0) { return VK_ERROR_INITIALIZATION_FAILED; } else { @@ -1653,9 +1711,18 @@ VkResult record_command_buffer_scene(uint32_t materials_count, Material* materia VkOffset2D render_offset = {.x = 0, .y = 0}; render_pass_info.renderArea.offset = render_offset; render_pass_info.renderArea.extent = extent; - VkClearValue clear_color = {{{0.0f, 0.0f, 0.0f, 1.0f}}}; - render_pass_info.clearValueCount = 1; - render_pass_info.pClearValues = &clear_color; + VkClearValue clear_colors[] = { + { + .color = { + {0.0f, 0.0f, 0.0f, 1.0f} + } + }, + { + .depthStencil = {1.0f, 0.0f}, + }, + }; + render_pass_info.clearValueCount = sizeof(clear_colors)/sizeof(VkClearValue); + render_pass_info.pClearValues = clear_colors; vkCmdBeginRenderPass(command_buffer, &render_pass_info, VK_SUBPASS_CONTENTS_INLINE); @@ -1816,8 +1883,8 @@ Material create_material( VkDescriptorSetLayoutBinding* mesh_set_bindings, uint32_t pcr_count, VkPushConstantRange* pcrs, - uint32_t bindings_count, - VkVertexInputBindingDescription* bindings, + uint32_t vertex_bindings_count, + VkVertexInputBindingDescription* vertex_bindings, uint32_t attributes_count, VkVertexInputAttributeDescription* attributes ) { @@ -1877,7 +1944,7 @@ Material create_material( return zero_material; } - VkPipeline pipeline = create_graphics_pipeline(device, extent, pipeline_layout, render_pass, shader_stage_count, shader_stages, bindings_count, bindings, attributes_count, attributes); + VkPipeline pipeline = create_graphics_pipeline(device, extent, pipeline_layout, render_pass, shader_stage_count, shader_stages, vertex_bindings_count, vertex_bindings, attributes_count, attributes); if(pipeline == VK_NULL_HANDLE) { return zero_material; } @@ -2088,7 +2155,20 @@ VulkanContext* init_vulkan(GLFWwindow* window, uint32_t max_frames_in_flight) { context->swapchain_image_views = image_views; } - VkRenderPass render_pass = create_render_pass(context->device, context->swapchain_format); + VkFormat requested[] = { + VK_FORMAT_D32_SFLOAT, + VK_FORMAT_D32_SFLOAT_S8_UINT, + VK_FORMAT_D24_UNORM_S8_UINT + }; + VkFormat depth_format = find_depth_format(context->physical_device, 3, requested, VK_IMAGE_TILING_OPTIMAL, VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT); + if(depth_format == VK_FORMAT_MAX_ENUM) { + fprintf(stderr, "failed to find a suitable depth image format\n"); + return 0; + } else { + context->depth_format = depth_format; + } + + VkRenderPass render_pass = create_render_pass(context->device, context->swapchain_format, context->depth_format); if(render_pass == VK_NULL_HANDLE) { fprintf(stderr, "failed to create vulkan render pass\n"); return 0; @@ -2096,7 +2176,49 @@ VulkanContext* init_vulkan(GLFWwindow* window, uint32_t max_frames_in_flight) { context->render_pass = render_pass; } - VkFramebuffer* framebuffers = create_swapchain_framebuffers(context->device, context->swapchain_image_count, context->swapchain_image_views, context->render_pass, context->swapchain_extent); + VkExtent3D depth_extent = { + .width = context->swapchain_extent.width, + .height = context->swapchain_extent.height, + .depth = 1, + }; + AllocatedImage depth_image = allocate_image(context->physical_device, context->device, VK_IMAGE_TYPE_2D, depth_format, depth_extent, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + if(depth_image.memory == VK_NULL_HANDLE) { + fprintf(stderr, "failed to create vulkan depth image\n"); + return 0; + } else { + context->depth_image = depth_image; + } + + VkImageViewCreateInfo depth_view_info = { + .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, + .image = depth_image.image, + .viewType = VK_IMAGE_VIEW_TYPE_2D, + .format = depth_format, + .components = { + .r = VK_COMPONENT_SWIZZLE_IDENTITY, + .g = VK_COMPONENT_SWIZZLE_IDENTITY, + .b = VK_COMPONENT_SWIZZLE_IDENTITY, + .a = VK_COMPONENT_SWIZZLE_IDENTITY, + }, + .subresourceRange = { + .aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT, + .baseMipLevel = 0, + .levelCount = 1, + .baseArrayLayer = 0, + .layerCount = 1, + }, + }; + + VkImageView depth_image_view; + VkResult result = vkCreateImageView(context->device, &depth_view_info, 0, &depth_image_view); + if(result != VK_SUCCESS) { + fprintf(stderr, "failed to create vulkan depth image view\n"); + return 0; + } else { + context->depth_image_view = depth_image_view; + } + + VkFramebuffer* framebuffers = create_swapchain_framebuffers(context->device, context->swapchain_image_count, context->swapchain_image_views, context->depth_image_view, context->render_pass, context->swapchain_extent); if(framebuffers == 0) { fprintf(stderr, "failed to create vulkan framebuffers\n"); return 0;