aboutsummaryrefslogtreecommitdiff
path: root/adapters/fparkan-render-vulkan/src/ffi.rs
diff options
context:
space:
mode:
Diffstat (limited to 'adapters/fparkan-render-vulkan/src/ffi.rs')
-rw-r--r--adapters/fparkan-render-vulkan/src/ffi.rs683
1 files changed, 6 insertions, 677 deletions
diff --git a/adapters/fparkan-render-vulkan/src/ffi.rs b/adapters/fparkan-render-vulkan/src/ffi.rs
index 7159204..b7ec403 100644
--- a/adapters/fparkan-render-vulkan/src/ffi.rs
+++ b/adapters/fparkan-render-vulkan/src/ffi.rs
@@ -28,6 +28,7 @@
//! This crate is the declared low-level Vulkan boundary.
mod instance;
+mod resources;
mod runtime;
mod surface;
mod validation;
@@ -40,6 +41,11 @@ pub use self::instance::{
};
#[cfg(test)]
use self::instance::{cstring_vec, ensure_instance_extensions_available};
+use self::resources::{
+ color_subresource_range, create_command_pool, create_frame_sync, create_swapchain_resources,
+ create_triangle_index_buffer, create_triangle_vertex_buffer, destroy_allocated_buffer,
+ destroy_swapchain_resources, VulkanAllocatedBuffer, VulkanFrameSync, VulkanSwapchainResources,
+};
pub use self::runtime::{
create_vulkan_logical_device_probe, create_vulkan_swapchain_probe,
create_vulkan_swapchain_probe_for_extent, probe_vulkan_runtime_capabilities,
@@ -560,35 +566,6 @@ impl std::fmt::Display for VulkanSmokeRendererError {
impl std::error::Error for VulkanSmokeRendererError {}
-struct VulkanAllocatedBuffer {
- buffer: vk::Buffer,
- memory: vk::DeviceMemory,
-}
-
-struct VulkanSwapchainResources {
- image_views: Vec<vk::ImageView>,
- render_pass: vk::RenderPass,
- pipeline_layout: vk::PipelineLayout,
- pipeline: vk::Pipeline,
- framebuffers: Vec<vk::Framebuffer>,
- command_buffers: Vec<vk::CommandBuffer>,
-}
-
-struct PartialSwapchainResources {
- image_views: Vec<vk::ImageView>,
- render_pass: Option<vk::RenderPass>,
- pipeline_layout: Option<vk::PipelineLayout>,
- pipeline: Option<vk::Pipeline>,
- framebuffers: Vec<vk::Framebuffer>,
- command_buffers: Vec<vk::CommandBuffer>,
-}
-
-struct VulkanFrameSync {
- image_available: vk::Semaphore,
- render_finished: vk::Semaphore,
- fence: vk::Fence,
-}
-
/// Live Stage 0 Vulkan triangle renderer used by the smoke app.
pub struct VulkanSmokeRenderer {
instance: Option<VulkanInstanceProbe>,
@@ -1204,654 +1181,6 @@ impl Drop for VulkanSmokeRenderer {
}
}
-fn create_command_pool(
- device: &VulkanLogicalDeviceProbe,
-) -> Result<vk::CommandPool, VulkanSmokeRendererError> {
- let create_info = vk::CommandPoolCreateInfo::default()
- .queue_family_index(device.report.graphics_queue_family)
- .flags(vk::CommandPoolCreateFlags::RESET_COMMAND_BUFFER);
- // SAFETY: The queue-family index belongs to this live logical device.
- unsafe { device.device().create_command_pool(&create_info, None) }.map_err(|error| {
- VulkanSmokeRendererError::VulkanOperation {
- context: "vkCreateCommandPool",
- result: error,
- }
- })
-}
-
-fn create_triangle_vertex_buffer(
- instance: &VulkanInstanceProbe,
- device: &VulkanLogicalDeviceProbe,
-) -> Result<VulkanAllocatedBuffer, VulkanSmokeRendererError> {
- let vertices: [[f32; 5]; 3] = [
- [0.0, -0.55, 1.0, 0.2, 0.2],
- [0.55, 0.55, 0.2, 1.0, 0.2],
- [-0.55, 0.55, 0.2, 0.4, 1.0],
- ];
- let mut bytes = Vec::with_capacity(vertices.len() * 5 * std::mem::size_of::<f32>());
- for vertex in vertices {
- for value in vertex {
- bytes.extend_from_slice(&value.to_ne_bytes());
- }
- }
- create_host_visible_buffer(
- instance,
- device,
- &bytes,
- vk::BufferUsageFlags::VERTEX_BUFFER,
- "triangle vertex buffer",
- )
-}
-
-fn create_triangle_index_buffer(
- instance: &VulkanInstanceProbe,
- device: &VulkanLogicalDeviceProbe,
-) -> Result<VulkanAllocatedBuffer, VulkanSmokeRendererError> {
- let indices = [0_u16, 1_u16, 2_u16];
- let mut bytes = Vec::with_capacity(indices.len() * std::mem::size_of::<u16>());
- for index in indices {
- bytes.extend_from_slice(&index.to_ne_bytes());
- }
- create_host_visible_buffer(
- instance,
- device,
- &bytes,
- vk::BufferUsageFlags::INDEX_BUFFER,
- "triangle index buffer",
- )
-}
-
-fn create_host_visible_buffer(
- instance: &VulkanInstanceProbe,
- device: &VulkanLogicalDeviceProbe,
- bytes: &[u8],
- usage: vk::BufferUsageFlags,
- context: &'static str,
-) -> Result<VulkanAllocatedBuffer, VulkanSmokeRendererError> {
- let create_info = vk::BufferCreateInfo::default()
- .size(bytes.len().try_into().unwrap_or(u64::MAX))
- .usage(usage)
- .sharing_mode(vk::SharingMode::EXCLUSIVE);
- // SAFETY: The create info is stack-owned and references no external memory.
- let buffer = unsafe { device.device().create_buffer(&create_info, None) }.map_err(|error| {
- VulkanSmokeRendererError::VulkanOperation {
- context,
- result: error,
- }
- })?;
- // SAFETY: The buffer belongs to this device and is queried immediately after creation.
- let requirements = unsafe { device.device().get_buffer_memory_requirements(buffer) };
- let Some(memory_type_index) = find_memory_type(
- instance,
- device.physical_device(),
- requirements.memory_type_bits,
- vk::MemoryPropertyFlags::HOST_VISIBLE | vk::MemoryPropertyFlags::HOST_COHERENT,
- ) else {
- // SAFETY: The buffer was created above on this logical device and is destroyed on setup failure.
- unsafe { device.device().destroy_buffer(buffer, None) };
- return Err(VulkanSmokeRendererError::MissingMemoryType { context });
- };
- let allocate_info = vk::MemoryAllocateInfo::default()
- .allocation_size(requirements.size)
- .memory_type_index(memory_type_index);
- let memory =
- // SAFETY: Allocation uses a memory type index selected from the physical-device requirements above.
- unsafe { device.device().allocate_memory(&allocate_info, None) }.map_err(|error| {
- // SAFETY: The buffer was created above on this logical device and is destroyed on setup failure.
- unsafe { device.device().destroy_buffer(buffer, None) };
- VulkanSmokeRendererError::VulkanOperation {
- context,
- result: error,
- }
- })?;
- // SAFETY: The buffer and allocation belong to the same live logical device.
- unsafe { device.device().bind_buffer_memory(buffer, memory, 0) }.map_err(|error| {
- // SAFETY: The buffer and allocation belong to this logical device and are destroyed on setup failure.
- unsafe {
- device.device().destroy_buffer(buffer, None);
- device.device().free_memory(memory, None);
- }
- VulkanSmokeRendererError::VulkanOperation {
- context,
- result: error,
- }
- })?;
- // SAFETY: The allocation is HOST_VISIBLE, mapped for the full buffer size and unmapped before return.
- let mapped = unsafe {
- device
- .device()
- .map_memory(memory, 0, requirements.size, vk::MemoryMapFlags::empty())
- }
- .map_err(|error| {
- // SAFETY: The buffer and allocation belong to this logical device and are destroyed on setup failure.
- unsafe {
- device.device().destroy_buffer(buffer, None);
- device.device().free_memory(memory, None);
- }
- VulkanSmokeRendererError::VulkanOperation {
- context,
- result: error,
- }
- })?;
- // SAFETY: The mapped pointer is valid for `bytes.len()` bytes and non-overlapping with the source slice.
- unsafe {
- std::ptr::copy_nonoverlapping(bytes.as_ptr(), mapped.cast::<u8>(), bytes.len());
- device.device().unmap_memory(memory);
- }
- Ok(VulkanAllocatedBuffer { buffer, memory })
-}
-
-fn find_memory_type(
- instance: &VulkanInstanceProbe,
- physical_device: vk::PhysicalDevice,
- memory_type_bits: u32,
- required_properties: vk::MemoryPropertyFlags,
-) -> Option<u32> {
- // SAFETY: Physical-device memory properties are queried from a live instance-owned physical device.
- let memory_properties = unsafe {
- instance
- .instance
- .get_physical_device_memory_properties(physical_device)
- };
- memory_properties
- .memory_types
- .iter()
- .enumerate()
- .find_map(|(index, memory_type)| {
- let supported = (memory_type_bits & (1_u32 << index)) != 0;
- let has_properties = memory_type.property_flags.contains(required_properties);
- (supported && has_properties).then(|| index.try_into().unwrap_or(u32::MAX))
- })
-}
-
-#[allow(clippy::too_many_lines)]
-fn create_swapchain_resources(
- device: &VulkanLogicalDeviceProbe,
- swapchain: &VulkanSwapchainProbe,
- command_pool: vk::CommandPool,
- _vertex_buffer: &VulkanAllocatedBuffer,
- _index_buffer: &VulkanAllocatedBuffer,
- _reuse_command_pool: bool,
-) -> Result<VulkanSwapchainResources, VulkanSmokeRendererError> {
- // SAFETY: The swapchain is live and owned by this renderer for the duration of the query.
- let images = unsafe {
- swapchain
- .loader()
- .get_swapchain_images(swapchain.swapchain())
- }
- .map_err(|error| VulkanSmokeRendererError::VulkanOperation {
- context: "vkGetSwapchainImagesKHR",
- result: error,
- })?;
- let mut partial = PartialSwapchainResources {
- image_views: Vec::with_capacity(images.len()),
- render_pass: None,
- pipeline_layout: None,
- pipeline: None,
- framebuffers: Vec::with_capacity(images.len()),
- command_buffers: Vec::new(),
- };
- for image in &images {
- match create_image_view(device, *image, swapchain.report.plan.format.format) {
- Ok(image_view) => partial.image_views.push(image_view),
- Err(error) => {
- destroy_partial_swapchain_resources(device, command_pool, partial);
- return Err(error);
- }
- }
- }
- let render_pass = match create_render_pass(device, swapchain.report.plan.format.format) {
- Ok(render_pass) => render_pass,
- Err(error) => {
- destroy_partial_swapchain_resources(device, command_pool, partial);
- return Err(error);
- }
- };
- partial.render_pass = Some(render_pass);
- let pipeline_layout = match create_pipeline_layout(device) {
- Ok(pipeline_layout) => pipeline_layout,
- Err(error) => {
- destroy_partial_swapchain_resources(device, command_pool, partial);
- return Err(error);
- }
- };
- partial.pipeline_layout = Some(pipeline_layout);
- let pipeline = match create_graphics_pipeline(
- device,
- render_pass,
- pipeline_layout,
- swapchain.report.plan.extent,
- ) {
- Ok(pipeline) => pipeline,
- Err(error) => {
- destroy_partial_swapchain_resources(device, command_pool, partial);
- return Err(error);
- }
- };
- partial.pipeline = Some(pipeline);
- for image_view in &partial.image_views {
- match create_framebuffer(
- device,
- render_pass,
- *image_view,
- swapchain.report.plan.extent,
- ) {
- Ok(framebuffer) => partial.framebuffers.push(framebuffer),
- Err(error) => {
- destroy_partial_swapchain_resources(device, command_pool, partial);
- return Err(error);
- }
- }
- }
- partial.command_buffers = match allocate_command_buffers(
- device,
- command_pool,
- partial.image_views.len().try_into().unwrap_or(u32::MAX),
- ) {
- Ok(command_buffers) => command_buffers,
- Err(error) => {
- destroy_partial_swapchain_resources(device, command_pool, partial);
- return Err(error);
- }
- };
- Ok(VulkanSwapchainResources {
- image_views: partial.image_views,
- render_pass,
- pipeline_layout,
- pipeline,
- framebuffers: partial.framebuffers,
- command_buffers: partial.command_buffers,
- })
-}
-
-fn create_image_view(
- device: &VulkanLogicalDeviceProbe,
- image: vk::Image,
- format: i32,
-) -> Result<vk::ImageView, VulkanSmokeRendererError> {
- let create_info = vk::ImageViewCreateInfo::default()
- .image(image)
- .view_type(vk::ImageViewType::TYPE_2D)
- .format(vk::Format::from_raw(format))
- .subresource_range(color_subresource_range());
- // SAFETY: The image comes from the live swapchain and the subresource range covers its color aspect.
- unsafe { device.device().create_image_view(&create_info, None) }.map_err(|error| {
- VulkanSmokeRendererError::VulkanOperation {
- context: "vkCreateImageView",
- result: error,
- }
- })
-}
-
-fn create_render_pass(
- device: &VulkanLogicalDeviceProbe,
- format: i32,
-) -> Result<vk::RenderPass, VulkanSmokeRendererError> {
- let color_attachment = vk::AttachmentDescription::default()
- .format(vk::Format::from_raw(format))
- .samples(vk::SampleCountFlags::TYPE_1)
- .load_op(vk::AttachmentLoadOp::CLEAR)
- .store_op(vk::AttachmentStoreOp::STORE)
- .initial_layout(vk::ImageLayout::COLOR_ATTACHMENT_OPTIMAL)
- .final_layout(vk::ImageLayout::COLOR_ATTACHMENT_OPTIMAL);
- let color_attachment_ref = vk::AttachmentReference::default()
- .attachment(0)
- .layout(vk::ImageLayout::COLOR_ATTACHMENT_OPTIMAL);
- let color_attachments = [color_attachment_ref];
- let subpass = vk::SubpassDescription::default()
- .pipeline_bind_point(vk::PipelineBindPoint::GRAPHICS)
- .color_attachments(&color_attachments);
- let dependency = vk::SubpassDependency::default()
- .src_subpass(vk::SUBPASS_EXTERNAL)
- .dst_subpass(0)
- .src_stage_mask(vk::PipelineStageFlags::COLOR_ATTACHMENT_OUTPUT)
- .dst_stage_mask(vk::PipelineStageFlags::COLOR_ATTACHMENT_OUTPUT)
- .dst_access_mask(vk::AccessFlags::COLOR_ATTACHMENT_WRITE);
- let attachments = [color_attachment];
- let subpasses = [subpass];
- let dependencies = [dependency];
- let create_info = vk::RenderPassCreateInfo::default()
- .attachments(&attachments)
- .subpasses(&subpasses)
- .dependencies(&dependencies);
- // SAFETY: The render-pass create info only references stack-owned descriptors.
- unsafe { device.device().create_render_pass(&create_info, None) }.map_err(|error| {
- VulkanSmokeRendererError::VulkanOperation {
- context: "vkCreateRenderPass",
- result: error,
- }
- })
-}
-
-fn create_pipeline_layout(
- device: &VulkanLogicalDeviceProbe,
-) -> Result<vk::PipelineLayout, VulkanSmokeRendererError> {
- let create_info = vk::PipelineLayoutCreateInfo::default();
- // SAFETY: The pipeline layout contains no descriptor sets or push constants.
- unsafe { device.device().create_pipeline_layout(&create_info, None) }.map_err(|error| {
- VulkanSmokeRendererError::VulkanOperation {
- context: "vkCreatePipelineLayout",
- result: error,
- }
- })
-}
-
-fn extent_component_to_f32(value: u32) -> f32 {
- u16::try_from(value).map_or(f32::from(u16::MAX), f32::from)
-}
-
-#[allow(clippy::too_many_lines)]
-fn create_graphics_pipeline(
- device: &VulkanLogicalDeviceProbe,
- render_pass: vk::RenderPass,
- pipeline_layout: vk::PipelineLayout,
- extent: (u32, u32),
-) -> Result<vk::Pipeline, VulkanSmokeRendererError> {
- let entry_point = c"main";
- let vertex_module = create_shader_module(device, TRIANGLE_VERTEX_SHADER_WORDS)?;
- let fragment_module = match create_shader_module(device, TRIANGLE_FRAGMENT_SHADER_WORDS) {
- Ok(fragment_module) => fragment_module,
- Err(error) => {
- // SAFETY: The vertex shader module was created above on this logical device and is destroyed on setup failure.
- unsafe { device.device().destroy_shader_module(vertex_module, None) };
- return Err(error);
- }
- };
- let stage_create_infos = [
- vk::PipelineShaderStageCreateInfo::default()
- .stage(vk::ShaderStageFlags::VERTEX)
- .module(vertex_module)
- .name(entry_point),
- vk::PipelineShaderStageCreateInfo::default()
- .stage(vk::ShaderStageFlags::FRAGMENT)
- .module(fragment_module)
- .name(entry_point),
- ];
- let binding_descriptions = [vk::VertexInputBindingDescription {
- binding: 0,
- stride: 20,
- input_rate: vk::VertexInputRate::VERTEX,
- }];
- let attribute_descriptions = [
- vk::VertexInputAttributeDescription {
- location: 0,
- binding: 0,
- format: vk::Format::R32G32_SFLOAT,
- offset: 0,
- },
- vk::VertexInputAttributeDescription {
- location: 1,
- binding: 0,
- format: vk::Format::R32G32B32_SFLOAT,
- offset: 8,
- },
- ];
- let vertex_input_state = vk::PipelineVertexInputStateCreateInfo::default()
- .vertex_binding_descriptions(&binding_descriptions)
- .vertex_attribute_descriptions(&attribute_descriptions);
- let input_assembly_state = vk::PipelineInputAssemblyStateCreateInfo::default()
- .topology(vk::PrimitiveTopology::TRIANGLE_LIST);
- let viewports = [vk::Viewport {
- x: 0.0,
- y: 0.0,
- width: extent_component_to_f32(extent.0),
- height: extent_component_to_f32(extent.1),
- min_depth: 0.0,
- max_depth: 1.0,
- }];
- let scissors = [vk::Rect2D {
- offset: vk::Offset2D { x: 0, y: 0 },
- extent: vk::Extent2D {
- width: extent.0,
- height: extent.1,
- },
- }];
- let viewport_state = vk::PipelineViewportStateCreateInfo::default()
- .viewports(&viewports)
- .scissors(&scissors);
- let rasterization_state = vk::PipelineRasterizationStateCreateInfo::default()
- .polygon_mode(vk::PolygonMode::FILL)
- .cull_mode(vk::CullModeFlags::BACK)
- .front_face(vk::FrontFace::CLOCKWISE)
- .line_width(1.0);
- let multisample_state = vk::PipelineMultisampleStateCreateInfo::default()
- .rasterization_samples(vk::SampleCountFlags::TYPE_1);
- let color_blend_attachment = [vk::PipelineColorBlendAttachmentState::default()
- .color_write_mask(
- vk::ColorComponentFlags::R
- | vk::ColorComponentFlags::G
- | vk::ColorComponentFlags::B
- | vk::ColorComponentFlags::A,
- )];
- let color_blend_state =
- vk::PipelineColorBlendStateCreateInfo::default().attachments(&color_blend_attachment);
- let create_info = [vk::GraphicsPipelineCreateInfo::default()
- .stages(&stage_create_infos)
- .vertex_input_state(&vertex_input_state)
- .input_assembly_state(&input_assembly_state)
- .viewport_state(&viewport_state)
- .rasterization_state(&rasterization_state)
- .multisample_state(&multisample_state)
- .color_blend_state(&color_blend_state)
- .layout(pipeline_layout)
- .render_pass(render_pass)
- .subpass(0)];
- // SAFETY: The pipeline creation references live shader modules and stack-owned fixed-function descriptors.
- let pipeline_result = unsafe {
- device
- .device()
- .create_graphics_pipelines(vk::PipelineCache::null(), &create_info, None)
- };
- // SAFETY: Shader modules are no longer needed after pipeline creation completes.
- unsafe {
- device.device().destroy_shader_module(vertex_module, None);
- device.device().destroy_shader_module(fragment_module, None);
- }
- let pipeline =
- pipeline_result.map_err(|(_, error)| VulkanSmokeRendererError::VulkanOperation {
- context: "vkCreateGraphicsPipelines",
- result: error,
- })?[0];
- Ok(pipeline)
-}
-
-fn create_shader_module(
- device: &VulkanLogicalDeviceProbe,
- words: &[u32],
-) -> Result<vk::ShaderModule, VulkanSmokeRendererError> {
- let create_info = vk::ShaderModuleCreateInfo::default().code(words);
- // SAFETY: SPIR-V words are immutable and valid for the duration of the call.
- unsafe { device.device().create_shader_module(&create_info, None) }.map_err(|error| {
- VulkanSmokeRendererError::VulkanOperation {
- context: "vkCreateShaderModule",
- result: error,
- }
- })
-}
-
-fn create_framebuffer(
- device: &VulkanLogicalDeviceProbe,
- render_pass: vk::RenderPass,
- image_view: vk::ImageView,
- extent: (u32, u32),
-) -> Result<vk::Framebuffer, VulkanSmokeRendererError> {
- let attachments = [image_view];
- let create_info = vk::FramebufferCreateInfo::default()
- .render_pass(render_pass)
- .attachments(&attachments)
- .width(extent.0)
- .height(extent.1)
- .layers(1);
- // SAFETY: The framebuffer attachments and render pass remain live for the duration of the call.
- unsafe { device.device().create_framebuffer(&create_info, None) }.map_err(|error| {
- VulkanSmokeRendererError::VulkanOperation {
- context: "vkCreateFramebuffer",
- result: error,
- }
- })
-}
-
-fn allocate_command_buffers(
- device: &VulkanLogicalDeviceProbe,
- command_pool: vk::CommandPool,
- count: u32,
-) -> Result<Vec<vk::CommandBuffer>, VulkanSmokeRendererError> {
- let allocate_info = vk::CommandBufferAllocateInfo::default()
- .command_pool(command_pool)
- .level(vk::CommandBufferLevel::PRIMARY)
- .command_buffer_count(count);
- // SAFETY: Command buffers are allocated from a live resettable pool owned by this device.
- unsafe { device.device().allocate_command_buffers(&allocate_info) }.map_err(|error| {
- VulkanSmokeRendererError::VulkanOperation {
- context: "vkAllocateCommandBuffers",
- result: error,
- }
- })
-}
-
-fn create_frame_sync(
- device: &VulkanLogicalDeviceProbe,
-) -> Result<Vec<VulkanFrameSync>, VulkanSmokeRendererError> {
- let semaphore_info = vk::SemaphoreCreateInfo::default();
- let fence_info = vk::FenceCreateInfo::default().flags(vk::FenceCreateFlags::SIGNALED);
- let mut sync = Vec::with_capacity(2);
- for _ in 0..2 {
- // SAFETY: The sync objects belong to this live logical device and are destroyed at teardown.
- let image_available = unsafe { device.device().create_semaphore(&semaphore_info, None) }
- .map_err(|error| VulkanSmokeRendererError::VulkanOperation {
- context: "vkCreateSemaphore(image_available)",
- result: error,
- })?;
- let render_finished =
- // SAFETY: The sync objects belong to this live logical device and are destroyed at teardown.
- match unsafe { device.device().create_semaphore(&semaphore_info, None) } {
- Ok(render_finished) => render_finished,
- Err(error) => {
- destroy_frame_sync_objects(device, &sync);
- // SAFETY: The semaphore was created above on this logical device and is destroyed on setup failure.
- unsafe { device.device().destroy_semaphore(image_available, None) };
- return Err(VulkanSmokeRendererError::VulkanOperation {
- context: "vkCreateSemaphore(render_finished)",
- result: error,
- });
- }
- };
- let fence =
- // SAFETY: The fence belongs to this live logical device and is destroyed at teardown.
- match unsafe { device.device().create_fence(&fence_info, None) } {
- Ok(fence) => fence,
- Err(error) => {
- destroy_frame_sync_objects(device, &sync);
- // SAFETY: These semaphores were created above on this logical device and are destroyed on setup failure.
- unsafe {
- device.device().destroy_semaphore(image_available, None);
- device.device().destroy_semaphore(render_finished, None);
- }
- return Err(VulkanSmokeRendererError::VulkanOperation {
- context: "vkCreateFence",
- result: error,
- });
- }
- };
- sync.push(VulkanFrameSync {
- image_available,
- render_finished,
- fence,
- });
- }
- Ok(sync)
-}
-
-fn destroy_swapchain_resources(
- device: &VulkanLogicalDeviceProbe,
- command_pool: vk::CommandPool,
- resources: VulkanSwapchainResources,
-) {
- // SAFETY: All swapchain-dependent objects belong to this device and are destroyed once.
- unsafe {
- device
- .device()
- .free_command_buffers(command_pool, &resources.command_buffers);
- for framebuffer in resources.framebuffers {
- device.device().destroy_framebuffer(framebuffer, None);
- }
- device.device().destroy_pipeline(resources.pipeline, None);
- device
- .device()
- .destroy_pipeline_layout(resources.pipeline_layout, None);
- device
- .device()
- .destroy_render_pass(resources.render_pass, None);
- for image_view in resources.image_views {
- device.device().destroy_image_view(image_view, None);
- }
- }
-}
-
-fn destroy_partial_swapchain_resources(
- device: &VulkanLogicalDeviceProbe,
- command_pool: vk::CommandPool,
- resources: PartialSwapchainResources,
-) {
- // SAFETY: All handles in this partial resource set were created on this live logical device and are destroyed once.
- unsafe {
- if !resources.command_buffers.is_empty() {
- device
- .device()
- .free_command_buffers(command_pool, &resources.command_buffers);
- }
- for framebuffer in resources.framebuffers {
- device.device().destroy_framebuffer(framebuffer, None);
- }
- if let Some(pipeline) = resources.pipeline {
- device.device().destroy_pipeline(pipeline, None);
- }
- if let Some(pipeline_layout) = resources.pipeline_layout {
- device
- .device()
- .destroy_pipeline_layout(pipeline_layout, None);
- }
- if let Some(render_pass) = resources.render_pass {
- device.device().destroy_render_pass(render_pass, None);
- }
- for image_view in resources.image_views {
- device.device().destroy_image_view(image_view, None);
- }
- }
-}
-
-fn destroy_frame_sync_objects(device: &VulkanLogicalDeviceProbe, sync: &[VulkanFrameSync]) {
- for frame_sync in sync {
- // SAFETY: These sync objects belong to this live logical device and are destroyed once during teardown.
- unsafe {
- device
- .device()
- .destroy_semaphore(frame_sync.image_available, None);
- device
- .device()
- .destroy_semaphore(frame_sync.render_finished, None);
- device.device().destroy_fence(frame_sync.fence, None);
- }
- }
-}
-
-fn destroy_allocated_buffer(device: &VulkanLogicalDeviceProbe, buffer: &VulkanAllocatedBuffer) {
- // SAFETY: The buffer and allocation belong to this live logical device and are destroyed once during teardown.
- unsafe {
- device.device().destroy_buffer(buffer.buffer, None);
- device.device().free_memory(buffer.memory, None);
- }
-}
-
-fn color_subresource_range() -> vk::ImageSubresourceRange {
- vk::ImageSubresourceRange::default()
- .aspect_mask(vk::ImageAspectFlags::COLOR)
- .base_mip_level(0)
- .level_count(1)
- .base_array_layer(0)
- .layer_count(1)
-}
-
#[cfg(test)]
mod tests {
use super::*;