diff options
| author | Irene Knapp <ireneista@irenes.space> | 2026-07-18 17:21:42 -0700 |
|---|---|---|
| committer | Irene Knapp <ireneista@irenes.space> | 2026-07-18 17:40:13 -0700 |
| commit | 365c2f8bdc217f33264e3aed394f67840a4c075d (patch) | |
| tree | 0836ea0bce5136d89d5d4e140f5ba22f657b54bd | |
| parent | cbfe9b855c11b1ef603b7212c244e089b4461753 (diff) | |
depth buffer
yay Change-Id: I7795e22712f27b262cde807a942ddec342d07c55 Force-Push: yes
| -rw-r--r-- | src/graphics_window_dressing.rs | 195 |
1 files changed, 156 insertions, 39 deletions
diff --git a/src/graphics_window_dressing.rs b/src/graphics_window_dressing.rs index c1db68f..ce5ccda 100644 --- a/src/graphics_window_dressing.rs +++ b/src/graphics_window_dressing.rs @@ -30,6 +30,11 @@ pub const N_SIMULTANEOUS_FRAMES: usize = 5; pub struct WindowDressing { pub swapchain: Swapchain, + depth_image: vk::Image, + depth_image_memory: vk::DeviceMemory, + depth_image_view: vk::ImageView, + depth_format: vk::Format, + render_pass: vk::RenderPass, pipeline: vk::Pipeline, @@ -114,14 +119,20 @@ impl WindowDressing { let swapchain = init_swapchain( window, instance, surface, &physical_device, device, &indices)?; - let render_pass = init_render_pass(device, &swapchain.format)?; + let (depth_image, depth_image_memory, depth_image_view, depth_format) + = init_depth(instance, &physical_device, device, + &swapchain.extent)?; + + let render_pass = init_render_pass(device, &swapchain.format, + &depth_format)?; let (pipeline_layout, pipeline) = init_pipeline(device, descriptor_set_layout, &swapchain.extent, &render_pass)?; let framebuffers = init_framebuffers( - device, &swapchain.extent, &swapchain.image_views, &render_pass)?; + device, &swapchain.extent, &swapchain.image_views, + &depth_image_view, &render_pass)?; let (primary_command_pool, transient_command_pool) = init_command_pools(device, indices)?; @@ -158,6 +169,10 @@ impl WindowDressing { Ok(WindowDressing { swapchain, + depth_image, + depth_image_memory, + depth_image_view, + depth_format, render_pass, pipeline, pipeline_layout, @@ -202,14 +217,20 @@ impl WindowDressing { let swapchain = init_swapchain( window, instance, surface, &physical_device, device, &indices)?; - let render_pass = init_render_pass(device, &swapchain.format)?; + let (depth_image, depth_image_memory, depth_image_view, depth_format) + = init_depth(instance, &physical_device, device, + &swapchain.extent)?; + + let render_pass = init_render_pass(device, &swapchain.format, + &depth_format)?; let (pipeline_layout, pipeline) = init_pipeline(device, descriptor_set_layout, &swapchain.extent, &render_pass)?; let framebuffers = init_framebuffers( - device, &swapchain.extent, &swapchain.image_views, &render_pass)?; + device, &swapchain.extent, &swapchain.image_views, + &depth_image_view, &render_pass)?; let (uniform_buffers, uniform_buffer_memory) = init_uniform_buffers(instance, physical_device, device, @@ -236,6 +257,10 @@ impl WindowDressing { vk::Fence::null()); self.swapchain = swapchain; + self.depth_image = depth_image; + self.depth_image_memory = depth_image_memory; + self.depth_image_view = depth_image_view; + self.depth_format = depth_format; self.render_pass = render_pass; self.pipeline = pipeline; self.pipeline_layout = pipeline_layout; @@ -316,6 +341,9 @@ impl WindowDressing { unsafe { device.destroy_pipeline(self.pipeline, None) }; unsafe { device.destroy_pipeline_layout(self.pipeline_layout, None) }; unsafe { device.destroy_render_pass(self.render_pass, None) }; + unsafe { device.destroy_image(self.depth_image, None) }; + unsafe { device.free_memory(self.depth_image_memory, None) }; + unsafe { device.destroy_image_view(self.depth_image_view, None) }; for view in &self.swapchain.image_views { unsafe { device.destroy_image_view(*view, None) }; @@ -391,7 +419,8 @@ fn init_swapchain(window: &Window, instance: &Instance, let mut image_views = Vec::new(); for image in &images { - let view = init_image_view(device, image, format.format)?; + let view = init_image_view(device, image, format.format, + vk::ImageAspectFlags::COLOR)?; image_views.push(view); } @@ -404,42 +433,82 @@ fn init_swapchain(window: &Window, instance: &Instance, #[allow(unsafe_code)] -fn init_render_pass(device: &Device, format: &vk::Format) +fn init_depth(instance: &Instance, physical_device: &vk::PhysicalDevice, + device: &Device, extent: &vk::Extent2D) + -> Result<(vk::Image, vk::DeviceMemory, vk::ImageView, vk::Format)> +{ + let format = pick_depth_format(instance, physical_device)?; + + let (image, image_memory) + = allocate_image(instance, physical_device, device, + extent.width, extent.height, + format, + vk::ImageTiling::OPTIMAL, + vk::ImageUsageFlags::DEPTH_STENCIL_ATTACHMENT, + vk::MemoryPropertyFlags::DEVICE_LOCAL)?; + + let image_view = init_image_view(device, &image, format, + vk::ImageAspectFlags::DEPTH)?; + + Ok((image, image_memory, image_view, format)) +} + + +#[allow(unsafe_code)] +fn init_render_pass(device: &Device, color_format: &vk::Format, + depth_format: &vk::Format) -> Result<vk::RenderPass> { - let color_attachment - = vk::AttachmentDescription::builder() - .format(*format) - .samples(vk::SampleCountFlags::_1) - .load_op(vk::AttachmentLoadOp::CLEAR) - .store_op(vk::AttachmentStoreOp::STORE) - .stencil_load_op(vk::AttachmentLoadOp::DONT_CARE) - .stencil_store_op(vk::AttachmentStoreOp::DONT_CARE) - .initial_layout(vk::ImageLayout::UNDEFINED) - .final_layout(vk::ImageLayout::PRESENT_SRC_KHR); - - let color_attachment_reference - = vk::AttachmentReference::builder() - .attachment(0) - .layout(vk::ImageLayout::COLOR_ATTACHMENT_OPTIMAL); - - let subpass_attachments = [color_attachment_reference]; + let color_attachment = vk::AttachmentDescription::builder() + .format(*color_format) + .samples(vk::SampleCountFlags::_1) + .load_op(vk::AttachmentLoadOp::CLEAR) + .store_op(vk::AttachmentStoreOp::STORE) + .stencil_load_op(vk::AttachmentLoadOp::DONT_CARE) + .stencil_store_op(vk::AttachmentStoreOp::DONT_CARE) + .initial_layout(vk::ImageLayout::UNDEFINED) + .final_layout(vk::ImageLayout::PRESENT_SRC_KHR); + + let color_attachment_reference = vk::AttachmentReference::builder() + .attachment(0) + .layout(vk::ImageLayout::COLOR_ATTACHMENT_OPTIMAL); + + let depth_attachment = vk::AttachmentDescription::builder() + .format(*depth_format) + .samples(vk::SampleCountFlags::_1) + .load_op(vk::AttachmentLoadOp::CLEAR) + .store_op(vk::AttachmentStoreOp::DONT_CARE) + .stencil_load_op(vk::AttachmentLoadOp::DONT_CARE) + .stencil_store_op(vk::AttachmentStoreOp::DONT_CARE) + .initial_layout(vk::ImageLayout::UNDEFINED) + .final_layout(vk::ImageLayout::DEPTH_STENCIL_ATTACHMENT_OPTIMAL); + + let depth_attachment_reference = vk::AttachmentReference::builder() + .attachment(1) + .layout(vk::ImageLayout::DEPTH_STENCIL_ATTACHMENT_OPTIMAL); + + let color_attachments = [color_attachment_reference]; let subpass = vk::SubpassDescription::builder() .pipeline_bind_point(vk::PipelineBindPoint::GRAPHICS) - .color_attachments(&subpass_attachments); + .color_attachments(&color_attachments) + .depth_stencil_attachment(&depth_attachment_reference); let dependency = vk::SubpassDependency::builder() .src_subpass(vk::SUBPASS_EXTERNAL) .src_stage_mask( - vk::PipelineStageFlags::COLOR_ATTACHMENT_OUTPUT) + vk::PipelineStageFlags::COLOR_ATTACHMENT_OUTPUT + | vk::PipelineStageFlags::EARLY_FRAGMENT_TESTS) .src_access_mask(vk::AccessFlags::empty()) .dst_subpass(0) .dst_stage_mask( - vk::PipelineStageFlags::COLOR_ATTACHMENT_OUTPUT) - .dst_access_mask(vk::AccessFlags::COLOR_ATTACHMENT_WRITE); + vk::PipelineStageFlags::COLOR_ATTACHMENT_OUTPUT + | vk::PipelineStageFlags::EARLY_FRAGMENT_TESTS) + .dst_access_mask( + vk::AccessFlags::COLOR_ATTACHMENT_WRITE + | vk::AccessFlags::DEPTH_STENCIL_ATTACHMENT_WRITE); - let render_attachments = [color_attachment]; + let render_attachments = [color_attachment, depth_attachment]; let subpasses = [subpass]; let dependencies = [dependency]; let render_pass_info = vk::RenderPassCreateInfo::builder() @@ -526,6 +595,15 @@ fn init_pipeline(device: &Device, .sample_shading_enable(false) .rasterization_samples(vk::SampleCountFlags::_1); + let depth_state_info = vk::PipelineDepthStencilStateCreateInfo::builder() + .depth_test_enable(true) + .depth_write_enable(true) + .depth_compare_op(vk::CompareOp::LESS) + .depth_bounds_test_enable(false) + .min_depth_bounds(0.0) + .max_depth_bounds(1.0) + .stencil_test_enable(false); + let blend_attachment_info = vk::PipelineColorBlendAttachmentState::builder() .color_write_mask(vk::ColorComponentFlags::all()) @@ -561,6 +639,7 @@ fn init_pipeline(device: &Device, .viewport_state(&viewport_state_info) .rasterization_state(&rasterizer_state_info) .multisample_state(&multisample_state_info) + .depth_stencil_state(&depth_state_info) .color_blend_state(&blend_info) .layout(pipeline_layout) .render_pass(*render_pass) @@ -583,13 +662,14 @@ fn init_pipeline(device: &Device, #[allow(unsafe_code)] fn init_framebuffers(device: &Device, extent: &vk::Extent2D, swapchain_image_views: &Vec<vk::ImageView>, + depth_image_view: &vk::ImageView, render_pass: &vk::RenderPass) -> Result<Vec<vk::Framebuffer>> { let mut framebuffers = Vec::new(); - for image_view in swapchain_image_views { - let attachments = [*image_view]; + for color_image_view in swapchain_image_views { + let attachments = [*color_image_view, *depth_image_view]; let framebuffer_info = vk::FramebufferCreateInfo::builder() .render_pass(*render_pass) @@ -669,7 +749,8 @@ fn init_texture(instance: &Instance, vk::ImageLayout::TRANSFER_DST_OPTIMAL, vk::ImageLayout::SHADER_READ_ONLY_OPTIMAL)?; - let view = init_image_view(device, &image, vk::Format::R8G8B8A8_SRGB)?; + let view = init_image_view(device, &image, vk::Format::R8G8B8A8_SRGB, + vk::ImageAspectFlags::COLOR)?; unsafe { device.destroy_buffer(staging_buffer, None) }; unsafe { device.free_memory(staging_memory, None) }; @@ -861,12 +942,18 @@ fn init_commands(device: &Device, .offset(vk::Offset2D::default()) .extent(*extent); - let clear_value = vk::ClearValue { + let color_clear_value = vk::ClearValue { color: vk::ClearColorValue { float32: [0.0, 0.0, 0.0, 1.0] } }; - let clear_values = [clear_value]; + let depth_clear_value = vk::ClearValue { + depth_stencil: vk::ClearDepthStencilValue { + depth: 1.0, + stencil: 0, + } + }; + let clear_values = [color_clear_value, depth_clear_value]; let begin_pass_info = vk::RenderPassBeginInfo::builder() .render_pass(*render_pass) @@ -959,17 +1046,20 @@ fn init_concurrency(device: &Device, #[allow(unsafe_code)] -fn init_image_view(device: &Device, image: &vk::Image, format: vk::Format) +fn init_image_view(device: &Device, image: &vk::Image, format: vk::Format, + aspects: vk::ImageAspectFlags) -> Result<vk::ImageView> { + // Component mapping is only for color components (not, for example, depth + // or stencil components), so we always just want it like this. let components = vk::ComponentMapping::builder() - .r(vk::ComponentSwizzle::IDENTITY) - .g(vk::ComponentSwizzle::IDENTITY) - .b(vk::ComponentSwizzle::IDENTITY) - .a(vk::ComponentSwizzle::IDENTITY); + .r(vk::ComponentSwizzle::IDENTITY) + .g(vk::ComponentSwizzle::IDENTITY) + .b(vk::ComponentSwizzle::IDENTITY) + .a(vk::ComponentSwizzle::IDENTITY); let subresource_range = vk::ImageSubresourceRange::builder() - .aspect_mask(vk::ImageAspectFlags::COLOR) + .aspect_mask(aspects) .base_mip_level(0) .level_count(1) .base_array_layer(0) @@ -1005,6 +1095,33 @@ fn pick_surface_format(available_formats: &Vec<vk::SurfaceFormatKHR>) } +#[allow(unsafe_code)] +fn pick_depth_format(instance: &Instance, + physical_device: &vk::PhysicalDevice) + -> Result<vk::Format> +{ + let required_features = vk::FormatFeatureFlags::DEPTH_STENCIL_ATTACHMENT; + + for format in [vk::Format::D32_SFLOAT, + vk::Format::D32_SFLOAT_S8_UINT, + vk::Format::D24_UNORM_S8_UINT] + { + let properties = unsafe { + instance.get_physical_device_format_properties( + *physical_device, format) + }; + + if properties.optimal_tiling_features.contains(required_features) { + return Ok(format); + } + } + + Err(Error { + message: "There is no supported depth-buffer sample format.".to_string() + }) +} + + fn pick_presentation_mode(_available_modes: &Vec<vk::PresentModeKHR>) -> Result<vk::PresentModeKHR> { |