Added depth image to context

main
noah metz 2024-01-09 13:12:05 -07:00
parent b9befc50a2
commit 9ccfe3d0f7
1 changed files with 172 additions and 50 deletions

@ -121,6 +121,10 @@ typedef struct VulkanContextStruct {
VkImageView* swapchain_image_views; VkImageView* swapchain_image_views;
VkFramebuffer* swapchain_framebuffers; VkFramebuffer* swapchain_framebuffers;
AllocatedImage depth_image;
VkFormat depth_format;
VkImageView depth_image_view;
uint32_t max_frames_in_flight; uint32_t max_frames_in_flight;
// Per frame objects // Per frame objects
VkCommandBuffer* swapchain_command_buffers; VkCommandBuffer* swapchain_command_buffers;
@ -219,6 +223,20 @@ GLFWwindow* init_window(int width, int height) {
return window; 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) { bool check_validation_layers(const char ** layers, uint32_t num_layers) {
uint32_t layer_count; uint32_t layer_count;
VkResult result; VkResult result;
@ -883,7 +901,7 @@ VkImageView* create_image_views(VkDevice device, uint32_t image_count, VkImage*
return image_views; 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); VkFramebuffer* framebuffers = malloc(sizeof(VkFramebuffer)*image_count);
if(framebuffers == 0) { if(framebuffers == 0) {
return 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++) { for(uint32_t i = 0; i < image_count; i++) {
VkImageView attachments[] = { VkImageView attachments[] = {
image_views[i], image_views[i],
depth_image_view,
}; };
VkFramebufferCreateInfo framebuffer_info = {}; VkFramebufferCreateInfo framebuffer_info = {};
framebuffer_info.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; framebuffer_info.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
framebuffer_info.renderPass = render_pass; framebuffer_info.renderPass = render_pass;
framebuffer_info.attachmentCount = 1; framebuffer_info.attachmentCount = 2;
framebuffer_info.pAttachments = attachments; framebuffer_info.pAttachments = attachments;
framebuffer_info.width = extent.width; framebuffer_info.width = extent.width;
framebuffer_info.height = extent.height; framebuffer_info.height = extent.height;
@ -948,42 +967,67 @@ VkShaderModule load_shader_file(uint32_t buffer_size, const char* path, VkDevice
return shader; return shader;
} }
VkRenderPass create_render_pass(VkDevice device, VkSurfaceFormatKHR format) { VkRenderPass create_render_pass(VkDevice device, VkSurfaceFormatKHR format, VkFormat depth_format) {
VkAttachmentDescription color_attachment; VkAttachmentDescription attachments[] = {
color_attachment.format = format.format; {
color_attachment.samples = VK_SAMPLE_COUNT_1_BIT; .format = format.format,
color_attachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; .samples = VK_SAMPLE_COUNT_1_BIT,
color_attachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE; .loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR,
color_attachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; .storeOp = VK_ATTACHMENT_STORE_OP_STORE,
color_attachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE; .stencilLoadOp = VK_ATTACHMENT_LOAD_OP_CLEAR,
color_attachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; .stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE,
color_attachment.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED,
.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; .format = depth_format,
.samples = VK_SAMPLE_COUNT_1_BIT,
VkSubpassDescription subpass = {}; .loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR,
subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; .storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE,
subpass.colorAttachmentCount = 1; .stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE,
subpass.pColorAttachments = &color_attachment_ref; .stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE,
.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED,
VkSubpassDependency dependency = {}; .finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
dependency.srcSubpass = VK_SUBPASS_EXTERNAL; },
dependency.dstSubpass = 0; };
dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
dependency.srcAccessMask = 0; VkAttachmentReference color_attachment_refs[] = {
dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; {
dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; .attachment = 0,
.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
VkRenderPassCreateInfo render_info = {}; },
render_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; };
render_info.attachmentCount = 1;
render_info.pAttachments = &color_attachment; VkAttachmentReference depth_attachment_ref = {
render_info.subpassCount = 1; .attachment = 1,
render_info.pSubpasses = &subpass; .layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
render_info.dependencyCount = 1; };
render_info.pDependencies = &dependency;
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; VkRenderPass render_pass;
VkResult result = vkCreateRenderPass(device, &render_info, 0, &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; 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 = { VkImageCreateInfo image_info = {
.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
.imageType = type, .imageType = type,
@ -1037,7 +1081,7 @@ AllocatedImage allocate_image(VkPhysicalDevice physical_device, VkDevice device,
.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED, .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED,
.usage = usage, .usage = usage,
.sharingMode = VK_SHARING_MODE_EXCLUSIVE, .sharingMode = VK_SHARING_MODE_EXCLUSIVE,
.samples = samples, .samples = VK_SAMPLE_COUNT_1_BIT,
.flags = 0, .flags = 0,
}; };
@ -1335,7 +1379,7 @@ Texture load_texture(VkPhysicalDevice physical_device, VkDevice device, VkComman
.height = size.height, .height = size.height,
.depth = 1, .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) { if(image.memory == VK_NULL_HANDLE) {
deallocate_buffer(device, staging); deallocate_buffer(device, staging);
deallocate_image(device, image); deallocate_image(device, image);
@ -1495,6 +1539,19 @@ VkPipeline create_graphics_pipeline(
multisample_info.alphaToCoverageEnable = VK_FALSE; multisample_info.alphaToCoverageEnable = VK_FALSE;
multisample_info.alphaToOneEnable = 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 = {}; 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.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; color_blend_attachment.blendEnable = VK_TRUE;
@ -1527,6 +1584,7 @@ VkPipeline create_graphics_pipeline(
pipeline_info.pDepthStencilState = 0; pipeline_info.pDepthStencilState = 0;
pipeline_info.pColorBlendState = &color_blend_info; pipeline_info.pColorBlendState = &color_blend_info;
pipeline_info.pDynamicState = &dynamic_info; pipeline_info.pDynamicState = &dynamic_info;
pipeline_info.pDepthStencilState = &depth_info;
pipeline_info.layout = layout; pipeline_info.layout = layout;
pipeline_info.renderPass = render_pass; pipeline_info.renderPass = render_pass;
pipeline_info.subpass = 0; pipeline_info.subpass = 0;
@ -1607,7 +1665,7 @@ VkResult recreate_swap_chain(VulkanContext* context, VkExtent2D new_extent) {
context->swapchain_image_views = image_views; 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) { if(framebuffers == 0) {
return VK_ERROR_INITIALIZATION_FAILED; return VK_ERROR_INITIALIZATION_FAILED;
} else { } else {
@ -1653,9 +1711,18 @@ VkResult record_command_buffer_scene(uint32_t materials_count, Material* materia
VkOffset2D render_offset = {.x = 0, .y = 0}; VkOffset2D render_offset = {.x = 0, .y = 0};
render_pass_info.renderArea.offset = render_offset; render_pass_info.renderArea.offset = render_offset;
render_pass_info.renderArea.extent = extent; render_pass_info.renderArea.extent = extent;
VkClearValue clear_color = {{{0.0f, 0.0f, 0.0f, 1.0f}}}; VkClearValue clear_colors[] = {
render_pass_info.clearValueCount = 1; {
render_pass_info.pClearValues = &clear_color; .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); vkCmdBeginRenderPass(command_buffer, &render_pass_info, VK_SUBPASS_CONTENTS_INLINE);
@ -1816,8 +1883,8 @@ Material create_material(
VkDescriptorSetLayoutBinding* mesh_set_bindings, VkDescriptorSetLayoutBinding* mesh_set_bindings,
uint32_t pcr_count, uint32_t pcr_count,
VkPushConstantRange* pcrs, VkPushConstantRange* pcrs,
uint32_t bindings_count, uint32_t vertex_bindings_count,
VkVertexInputBindingDescription* bindings, VkVertexInputBindingDescription* vertex_bindings,
uint32_t attributes_count, uint32_t attributes_count,
VkVertexInputAttributeDescription* attributes VkVertexInputAttributeDescription* attributes
) { ) {
@ -1877,7 +1944,7 @@ Material create_material(
return zero_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) { if(pipeline == VK_NULL_HANDLE) {
return zero_material; return zero_material;
} }
@ -2088,7 +2155,20 @@ VulkanContext* init_vulkan(GLFWwindow* window, uint32_t max_frames_in_flight) {
context->swapchain_image_views = image_views; 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) { if(render_pass == VK_NULL_HANDLE) {
fprintf(stderr, "failed to create vulkan render pass\n"); fprintf(stderr, "failed to create vulkan render pass\n");
return 0; return 0;
@ -2096,7 +2176,49 @@ VulkanContext* init_vulkan(GLFWwindow* window, uint32_t max_frames_in_flight) {
context->render_pass = render_pass; 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) { if(framebuffers == 0) {
fprintf(stderr, "failed to create vulkan framebuffers\n"); fprintf(stderr, "failed to create vulkan framebuffers\n");
return 0; return 0;