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;
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;