diff --git a/vulkano-taskgraph/src/command_buffer/commands/clear.rs b/vulkano-taskgraph/src/command_buffer/commands/clear.rs index f5170be8..73d3eb97 100644 --- a/vulkano-taskgraph/src/command_buffer/commands/clear.rs +++ b/vulkano-taskgraph/src/command_buffer/commands/clear.rs @@ -3,7 +3,6 @@ use crate::{ resource::{AccessType, ImageLayoutType}, Id, }; -use ash::vk; use smallvec::SmallVec; use std::{ffi::c_void, mem}; use vulkano::{ @@ -43,14 +42,14 @@ impl RecordingCommandBuffer<'_> { let cmd_clear_color_image = fns.v1_0.cmd_clear_color_image; if regions.is_empty() { - let region_vk = image.subresource_range().into(); + let region_vk = image.subresource_range().to_vk(); unsafe { cmd_clear_color_image( self.handle(), image.handle(), image_layout.into(), - &clear_value.into(), + &clear_value.to_vk(), 1, ®ion_vk, ) @@ -58,8 +57,7 @@ impl RecordingCommandBuffer<'_> { } else { let regions_vk = regions .iter() - .cloned() - .map(vk::ImageSubresourceRange::from) + .map(ImageSubresourceRange::to_vk) .collect::>(); unsafe { @@ -67,7 +65,7 @@ impl RecordingCommandBuffer<'_> { self.handle(), image.handle(), image_layout.into(), - &clear_value.into(), + &clear_value.to_vk(), regions_vk.len() as u32, regions_vk.as_ptr(), ) @@ -104,14 +102,14 @@ impl RecordingCommandBuffer<'_> { let cmd_clear_depth_stencil_image = fns.v1_0.cmd_clear_depth_stencil_image; if regions.is_empty() { - let region_vk = image.subresource_range().into(); + let region_vk = image.subresource_range().to_vk(); unsafe { cmd_clear_depth_stencil_image( self.handle(), image.handle(), image_layout.into(), - &clear_value.into(), + &clear_value.to_vk(), 1, ®ion_vk, ) @@ -119,8 +117,7 @@ impl RecordingCommandBuffer<'_> { } else { let regions_vk = regions .iter() - .cloned() - .map(vk::ImageSubresourceRange::from) + .map(ImageSubresourceRange::to_vk) .collect::>(); unsafe { @@ -128,7 +125,7 @@ impl RecordingCommandBuffer<'_> { self.handle(), image.handle(), image_layout.into(), - &clear_value.into(), + &clear_value.to_vk(), regions_vk.len() as u32, regions_vk.as_ptr(), ) diff --git a/vulkano-taskgraph/src/command_buffer/commands/copy.rs b/vulkano-taskgraph/src/command_buffer/commands/copy.rs index 624475b1..980fcd83 100644 --- a/vulkano-taskgraph/src/command_buffer/commands/copy.rs +++ b/vulkano-taskgraph/src/command_buffer/commands/copy.rs @@ -196,7 +196,7 @@ impl RecordingCommandBuffer<'_> { array_layers: 0..min_array_layers, ..src_image.subresource_layers() } - .into(), + .to_vk(), ) .src_offset(convert_offset([0; 3])) .dst_subresource( @@ -204,7 +204,7 @@ impl RecordingCommandBuffer<'_> { array_layers: 0..min_array_layers, ..dst_image.subresource_layers() } - .into(), + .to_vk(), ) .dst_offset(convert_offset([0; 3])) .extent(convert_extent([ @@ -235,9 +235,9 @@ impl RecordingCommandBuffer<'_> { } = region; vk::ImageCopy2::default() - .src_subresource(src_subresource.into()) + .src_subresource(src_subresource.to_vk()) .src_offset(convert_offset(src_offset)) - .dst_subresource(dst_subresource.into()) + .dst_subresource(dst_subresource.to_vk()) .dst_offset(convert_offset(dst_offset)) .extent(convert_extent(extent)) }) @@ -264,13 +264,13 @@ impl RecordingCommandBuffer<'_> { array_layers: 0..min_array_layers, ..src_image.subresource_layers() } - .into(), + .to_vk(), src_offset: convert_offset([0; 3]), dst_subresource: ImageSubresourceLayers { array_layers: 0..min_array_layers, ..dst_image.subresource_layers() } - .into(), + .to_vk(), dst_offset: convert_offset([0; 3]), extent: convert_extent([ cmp::min(src_extent[0], dst_extent[0]), @@ -304,9 +304,9 @@ impl RecordingCommandBuffer<'_> { } = region; vk::ImageCopy { - src_subresource: src_subresource.into(), + src_subresource: src_subresource.to_vk(), src_offset: convert_offset(src_offset), - dst_subresource: dst_subresource.into(), + dst_subresource: dst_subresource.to_vk(), dst_offset: convert_offset(dst_offset), extent: convert_extent(extent), } @@ -370,7 +370,7 @@ impl RecordingCommandBuffer<'_> { .buffer_offset(0) .buffer_row_length(0) .buffer_image_height(0) - .image_subresource(dst_image.subresource_layers().into()) + .image_subresource(dst_image.subresource_layers().to_vk()) .image_offset(convert_offset([0; 3])) .image_extent(convert_extent(dst_image.extent()))]; @@ -399,7 +399,7 @@ impl RecordingCommandBuffer<'_> { .buffer_offset(buffer_offset) .buffer_row_length(buffer_row_length) .buffer_image_height(buffer_image_height) - .image_subresource(image_subresource.into()) + .image_subresource(image_subresource.to_vk()) .image_offset(convert_offset(image_offset)) .image_extent(convert_extent(image_extent)) }) @@ -421,7 +421,7 @@ impl RecordingCommandBuffer<'_> { buffer_offset: 0, buffer_row_length: 0, buffer_image_height: 0, - image_subresource: dst_image.subresource_layers().into(), + image_subresource: dst_image.subresource_layers().to_vk(), image_offset: convert_offset([0; 3]), image_extent: convert_extent(dst_image.extent()), }; @@ -454,7 +454,7 @@ impl RecordingCommandBuffer<'_> { buffer_offset, buffer_row_length, buffer_image_height, - image_subresource: image_subresource.into(), + image_subresource: image_subresource.to_vk(), image_offset: convert_offset(image_offset), image_extent: convert_extent(image_extent), } @@ -517,7 +517,7 @@ impl RecordingCommandBuffer<'_> { .buffer_offset(0) .buffer_row_length(0) .buffer_image_height(0) - .image_subresource(src_image.subresource_layers().into()) + .image_subresource(src_image.subresource_layers().to_vk()) .image_offset(convert_offset([0; 3])) .image_extent(convert_extent(src_image.extent()))]; @@ -546,7 +546,7 @@ impl RecordingCommandBuffer<'_> { .buffer_offset(buffer_offset) .buffer_row_length(buffer_row_length) .buffer_image_height(buffer_image_height) - .image_subresource(image_subresource.into()) + .image_subresource(image_subresource.to_vk()) .image_offset(convert_offset(image_offset)) .image_extent(convert_extent(image_extent)) }) @@ -568,7 +568,7 @@ impl RecordingCommandBuffer<'_> { buffer_offset: 0, buffer_row_length: 0, buffer_image_height: 0, - image_subresource: src_image.subresource_layers().into(), + image_subresource: src_image.subresource_layers().to_vk(), image_offset: convert_offset([0; 3]), image_extent: convert_extent(src_image.extent()), }; @@ -601,7 +601,7 @@ impl RecordingCommandBuffer<'_> { buffer_offset, buffer_row_length, buffer_image_height, - image_subresource: image_subresource.into(), + image_subresource: image_subresource.to_vk(), image_offset: convert_offset(image_offset), image_extent: convert_extent(image_extent), } @@ -692,7 +692,7 @@ impl RecordingCommandBuffer<'_> { array_layers: 0..min_array_layers, ..src_image.subresource_layers() } - .into(), + .to_vk(), ) .src_offsets([[0; 3], src_image.extent()].map(convert_offset)) .dst_subresource( @@ -700,7 +700,7 @@ impl RecordingCommandBuffer<'_> { array_layers: 0..min_array_layers, ..src_image.subresource_layers() } - .into(), + .to_vk(), ) .dst_offsets([[0; 3], dst_image.extent()].map(convert_offset))]; @@ -726,9 +726,9 @@ impl RecordingCommandBuffer<'_> { } = region; vk::ImageBlit2::default() - .src_subresource(src_subresource.into()) + .src_subresource(src_subresource.to_vk()) .src_offsets(src_offsets.map(convert_offset)) - .dst_subresource(dst_subresource.into()) + .dst_subresource(dst_subresource.to_vk()) .dst_offsets(dst_offsets.map(convert_offset)) }) .collect::>(); @@ -753,13 +753,13 @@ impl RecordingCommandBuffer<'_> { array_layers: 0..min_array_layers, ..src_image.subresource_layers() } - .into(), + .to_vk(), src_offsets: [[0; 3], src_image.extent()].map(convert_offset), dst_subresource: ImageSubresourceLayers { array_layers: 0..min_array_layers, ..dst_image.subresource_layers() } - .into(), + .to_vk(), dst_offsets: [[0; 3], dst_image.extent()].map(convert_offset), }; @@ -788,9 +788,9 @@ impl RecordingCommandBuffer<'_> { } = region; vk::ImageBlit { - src_subresource: src_subresource.into(), + src_subresource: src_subresource.to_vk(), src_offsets: src_offsets.map(convert_offset), - dst_subresource: dst_subresource.into(), + dst_subresource: dst_subresource.to_vk(), dst_offsets: dst_offsets.map(convert_offset), } }) @@ -861,7 +861,7 @@ impl RecordingCommandBuffer<'_> { array_layers: 0..min_array_layers, ..src_image.subresource_layers() } - .into(), + .to_vk(), ) .src_offset(convert_offset([0; 3])) .dst_subresource( @@ -869,7 +869,7 @@ impl RecordingCommandBuffer<'_> { array_layers: 0..min_array_layers, ..src_image.subresource_layers() } - .into(), + .to_vk(), ) .dst_offset(convert_offset([0; 3])) .extent(convert_extent([ @@ -900,9 +900,9 @@ impl RecordingCommandBuffer<'_> { } = region; vk::ImageResolve2::default() - .src_subresource(src_subresource.into()) + .src_subresource(src_subresource.to_vk()) .src_offset(convert_offset(src_offset)) - .dst_subresource(dst_subresource.into()) + .dst_subresource(dst_subresource.to_vk()) .dst_offset(convert_offset(dst_offset)) .extent(convert_extent(extent)) }) @@ -929,13 +929,13 @@ impl RecordingCommandBuffer<'_> { array_layers: 0..min_array_layers, ..src_image.subresource_layers() } - .into(), + .to_vk(), src_offset: convert_offset([0; 3]), dst_subresource: ImageSubresourceLayers { array_layers: 0..min_array_layers, ..dst_image.subresource_layers() } - .into(), + .to_vk(), dst_offset: convert_offset([0; 3]), extent: convert_extent([ cmp::min(src_extent[0], dst_extent[0]), @@ -969,9 +969,9 @@ impl RecordingCommandBuffer<'_> { } = region; vk::ImageResolve { - src_subresource: src_subresource.into(), + src_subresource: src_subresource.to_vk(), src_offset: convert_offset(src_offset), - dst_subresource: dst_subresource.into(), + dst_subresource: dst_subresource.to_vk(), dst_offset: convert_offset(dst_offset), extent: convert_extent(extent), } diff --git a/vulkano-taskgraph/src/command_buffer/commands/dynamic_state.rs b/vulkano-taskgraph/src/command_buffer/commands/dynamic_state.rs index 6c3eb4bd..e3d9168f 100644 --- a/vulkano-taskgraph/src/command_buffer/commands/dynamic_state.rs +++ b/vulkano-taskgraph/src/command_buffer/commands/dynamic_state.rs @@ -6,13 +6,11 @@ use vulkano::{ device::DeviceOwned, pipeline::graphics::{ color_blend::LogicOp, - conservative_rasterization::ConservativeRasterizationMode, depth_stencil::{CompareOp, StencilFaces, StencilOp}, input_assembly::PrimitiveTopology, - rasterization::{CullMode, FrontFace}, + rasterization::{ConservativeRasterizationMode, CullMode, FrontFace}, vertex_input::{ - VertexInputAttributeDescription, VertexInputBindingDescription, VertexInputRate, - VertexInputState, + VertexInputAttributeDescription, VertexInputBindingDescription, VertexInputState, }, viewport::{Scissor, Viewport}, }, @@ -230,7 +228,7 @@ impl RecordingCommandBuffer<'_> { let rectangles_vk = rectangles .iter() - .map(|v| v.into()) + .map(Scissor::to_vk) .collect::>(); let fns = self.device().fns(); @@ -402,7 +400,7 @@ impl RecordingCommandBuffer<'_> { let scissors_vk = scissors .iter() - .map(vk::Rect2D::from) + .map(Scissor::to_vk) .collect::>(); let fns = self.device().fns(); @@ -430,7 +428,7 @@ impl RecordingCommandBuffer<'_> { let scissors_vk = scissors .iter() - .map(vk::Rect2D::from) + .map(Scissor::to_vk) .collect::>(); let fns = self.device().fns(); @@ -604,16 +602,12 @@ impl RecordingCommandBuffer<'_> { _ne: _, } = binding_desc; - let divisor = match input_rate { - // VUID-VkVertexInputBindingDescription2EXT-divisor-06227 - VertexInputRate::Vertex => 1, - VertexInputRate::Instance { divisor } => divisor, - }; + let (input_rate, divisor) = input_rate.to_vk(); vk::VertexInputBindingDescription2EXT { binding, stride, - input_rate: input_rate.into(), + input_rate, divisor, ..Default::default() } @@ -672,7 +666,7 @@ impl RecordingCommandBuffer<'_> { let viewports_vk = viewports .iter() - .map(|v| v.into()) + .map(Viewport::to_vk) .collect::>(); let fns = self.device().fns(); @@ -703,7 +697,7 @@ impl RecordingCommandBuffer<'_> { let viewports_vk = viewports .iter() - .map(|v| v.into()) + .map(Viewport::to_vk) .collect::>(); let fns = self.device().fns(); diff --git a/vulkano-taskgraph/src/command_buffer/commands/sync.rs b/vulkano-taskgraph/src/command_buffer/commands/sync.rs index 33f95107..5cc5e26d 100644 --- a/vulkano-taskgraph/src/command_buffer/commands/sync.rs +++ b/vulkano-taskgraph/src/command_buffer/commands/sync.rs @@ -113,7 +113,7 @@ impl RecordingCommandBuffer<'_> { .src_queue_family_index(vk::QUEUE_FAMILY_IGNORED) .dst_queue_family_index(vk::QUEUE_FAMILY_IGNORED) .image(image.handle()) - .subresource_range(subresource_range.clone().into()) + .subresource_range(subresource_range.clone().to_vk()) }) .collect(); @@ -212,7 +212,7 @@ impl RecordingCommandBuffer<'_> { .src_queue_family_index(vk::QUEUE_FAMILY_IGNORED) .dst_queue_family_index(vk::QUEUE_FAMILY_IGNORED) .image(image.handle()) - .subresource_range(subresource_range.clone().into()) + .subresource_range(subresource_range.clone().to_vk()) }) .collect(); diff --git a/vulkano-taskgraph/src/graph/execute.rs b/vulkano-taskgraph/src/graph/execute.rs index d32c45a0..798704bc 100644 --- a/vulkano-taskgraph/src/graph/execute.rs +++ b/vulkano-taskgraph/src/graph/execute.rs @@ -776,7 +776,7 @@ impl<'a, W: ?Sized + 'static> ExecuteState2<'a, W> { .src_queue_family_index(vk::QUEUE_FAMILY_IGNORED) .dst_queue_family_index(vk::QUEUE_FAMILY_IGNORED) .image(image.handle()) - .subresource_range(image.subresource_range().into()), + .subresource_range(image.subresource_range().to_vk()), ); } } @@ -900,7 +900,7 @@ impl<'a, W: ?Sized + 'static> ExecuteState2<'a, W> { .src_queue_family_index(barrier.src_queue_family_index) .dst_queue_family_index(barrier.dst_queue_family_index) .image(image.handle()) - .subresource_range(image.subresource_range().into()), + .subresource_range(image.subresource_range().to_vk()), ); } } @@ -1196,7 +1196,7 @@ impl<'a, W: ?Sized + 'static> ExecuteState<'a, W> { .src_queue_family_index(vk::QUEUE_FAMILY_IGNORED) .dst_queue_family_index(vk::QUEUE_FAMILY_IGNORED) .image(image.handle()) - .subresource_range(image.subresource_range().into()), + .subresource_range(image.subresource_range().to_vk()), ); self.current_src_stage_mask |= convert_stage_mask(src_stage_mask); @@ -1324,7 +1324,7 @@ impl<'a, W: ?Sized + 'static> ExecuteState<'a, W> { .src_queue_family_index(barrier.src_queue_family_index) .dst_queue_family_index(barrier.dst_queue_family_index) .image(image.handle()) - .subresource_range(image.subresource_range().into()), + .subresource_range(image.subresource_range().to_vk()), ); self.current_src_stage_mask |= convert_stage_mask(barrier.src_stage_mask); diff --git a/vulkano/src/acceleration_structure.rs b/vulkano/src/acceleration_structure.rs index d0d91cab..aa8484da 100644 --- a/vulkano/src/acceleration_structure.rs +++ b/vulkano/src/acceleration_structure.rs @@ -165,22 +165,7 @@ impl AccelerationStructure { device: Arc, create_info: AccelerationStructureCreateInfo, ) -> Result, VulkanError> { - let &AccelerationStructureCreateInfo { - create_flags, - ref buffer, - ty, - _ne: _, - } = &create_info; - - let create_info_vk = ash::vk::AccelerationStructureCreateInfoKHR { - create_flags: create_flags.into(), - buffer: buffer.buffer().handle(), - offset: buffer.offset(), - size: buffer.size(), - ty: ty.into(), - device_address: 0, // TODO: allow user to specify - ..Default::default() - }; + let create_info_vk = create_info.to_vk(); let handle = { let fns = device.fns(); @@ -258,10 +243,8 @@ impl AccelerationStructure { /// The device address of the acceleration structure may be different from the device address /// of the underlying buffer. pub fn device_address(&self) -> NonNullDeviceAddress { - let info_vk = ash::vk::AccelerationStructureDeviceAddressInfoKHR { - acceleration_structure: self.handle, - ..Default::default() - }; + let info_vk = ash::vk::AccelerationStructureDeviceAddressInfoKHR::default() + .acceleration_structure(self.handle); let ptr = unsafe { let fns = self.device.fns(); (fns.khr_acceleration_structure @@ -410,6 +393,23 @@ impl AccelerationStructureCreateInfo { Ok(()) } + + pub(crate) fn to_vk(&self) -> ash::vk::AccelerationStructureCreateInfoKHR<'static> { + let &Self { + create_flags, + ref buffer, + ty, + _ne: _, + } = self; + + ash::vk::AccelerationStructureCreateInfoKHR::default() + .create_flags(create_flags.into()) + .buffer(buffer.buffer().handle()) + .offset(buffer.offset()) + .size(buffer.size()) + .ty(ty.into()) + .device_address(0) // TODO: allow user to specify + } } vulkan_bitflags! { @@ -593,12 +593,10 @@ impl AccelerationStructureBuildGeometryInfo { Ok(()) } - pub(crate) fn to_vulkan( + pub(crate) fn to_vk<'a>( &self, - ) -> ( - ash::vk::AccelerationStructureBuildGeometryInfoKHR<'static>, - Vec>, - ) { + fields1_vk: &'a AccelerationStructureBuildGeometryInfoFields1Vk, + ) -> ash::vk::AccelerationStructureBuildGeometryInfoKHR<'a> { let &Self { flags, ref mode, @@ -607,178 +605,58 @@ impl AccelerationStructureBuildGeometryInfo { ref scratch_data, _ne: _, } = self; + let AccelerationStructureBuildGeometryInfoFields1Vk { geometries_vk } = fields1_vk; - let (ty, geometries_vk): (_, Vec<_>) = match geometries { - AccelerationStructureGeometries::Triangles(geometries) => ( - ash::vk::AccelerationStructureTypeKHR::BOTTOM_LEVEL, - geometries - .iter() - .map(|triangles_data| { - let &AccelerationStructureGeometryTrianglesData { - flags, - vertex_format, - ref vertex_data, - vertex_stride, - max_vertex, - ref index_data, - ref transform_data, - _ne, - } = triangles_data; + ash::vk::AccelerationStructureBuildGeometryInfoKHR::default() + .ty(geometries.to_vk_ty()) + .flags(flags.into()) + .mode(mode.to_vk()) + .src_acceleration_structure(match mode { + BuildAccelerationStructureMode::Build => Default::default(), + BuildAccelerationStructureMode::Update(src_acceleration_structure) => { + src_acceleration_structure.handle() + } + }) + .dst_acceleration_structure( + dst_acceleration_structure + .as_ref() + .map_or_else(Default::default, VulkanObject::handle), + ) + .geometries(geometries_vk) + .scratch_data( + scratch_data + .as_ref() + .map_or_else(Default::default, Subbuffer::to_vk_device_or_host_address), + ) + } - ash::vk::AccelerationStructureGeometryKHR { - geometry_type: ash::vk::GeometryTypeKHR::TRIANGLES, - geometry: ash::vk::AccelerationStructureGeometryDataKHR { - triangles: ash::vk::AccelerationStructureGeometryTrianglesDataKHR { - vertex_format: vertex_format.into(), - vertex_data: ash::vk::DeviceOrHostAddressConstKHR { - device_address: vertex_data.as_ref().map_or( - 0, - |vertex_data| { - vertex_data.device_address().unwrap().into() - }, - ), - }, - vertex_stride: vertex_stride as DeviceSize, - max_vertex, - index_type: index_data - .as_ref() - .map_or(ash::vk::IndexType::NONE_KHR, |index_data| { - index_data.index_type().into() - }), - index_data: ash::vk::DeviceOrHostAddressConstKHR { - device_address: index_data.as_ref().map_or( - 0, - |index_data| { - index_data - .as_bytes() - .device_address() - .unwrap() - .get() - }, - ), - }, - transform_data: ash::vk::DeviceOrHostAddressConstKHR { - device_address: transform_data.as_ref().map_or( - 0, - |transform_data| { - transform_data.device_address().unwrap().get() - }, - ), - }, - ..Default::default() - }, - }, - flags: flags.into(), - ..Default::default() - } - }) - .collect(), - ), - AccelerationStructureGeometries::Aabbs(geometries) => ( - ash::vk::AccelerationStructureTypeKHR::BOTTOM_LEVEL, - geometries - .iter() - .map(|aabbs_data| { - let &AccelerationStructureGeometryAabbsData { - flags, - ref data, - stride, - _ne: _, - } = aabbs_data; + pub(crate) fn to_vk_fields1(&self) -> AccelerationStructureBuildGeometryInfoFields1Vk { + let Self { geometries, .. } = self; + + let geometries_vk = match geometries { + AccelerationStructureGeometries::Triangles(geometries) => geometries + .iter() + .map(AccelerationStructureGeometryTrianglesData::to_vk) + .collect(), + + AccelerationStructureGeometries::Aabbs(geometries) => geometries + .iter() + .map(AccelerationStructureGeometryAabbsData::to_vk) + .collect(), - ash::vk::AccelerationStructureGeometryKHR { - geometry_type: ash::vk::GeometryTypeKHR::AABBS, - geometry: ash::vk::AccelerationStructureGeometryDataKHR { - aabbs: ash::vk::AccelerationStructureGeometryAabbsDataKHR { - data: ash::vk::DeviceOrHostAddressConstKHR { - device_address: data.as_ref().map_or(0, |data| { - data.device_address().unwrap().into() - }), - }, - stride: stride as DeviceSize, - ..Default::default() - }, - }, - flags: flags.into(), - ..Default::default() - } - }) - .collect(), - ), AccelerationStructureGeometries::Instances(instances_data) => { - (ash::vk::AccelerationStructureTypeKHR::TOP_LEVEL, { - let &AccelerationStructureGeometryInstancesData { - flags, - ref data, - _ne: _, - } = instances_data; - - let (array_of_pointers, data) = match data { - AccelerationStructureGeometryInstancesDataType::Values(data) => ( - ash::vk::FALSE, - ash::vk::DeviceOrHostAddressConstKHR { - device_address: data - .as_ref() - .map_or(0, |data| data.device_address().unwrap().into()), - }, - ), - AccelerationStructureGeometryInstancesDataType::Pointers(data) => ( - ash::vk::TRUE, - ash::vk::DeviceOrHostAddressConstKHR { - device_address: data - .as_ref() - .map_or(0, |data| data.device_address().unwrap().into()), - }, - ), - }; - - [ash::vk::AccelerationStructureGeometryKHR { - geometry_type: ash::vk::GeometryTypeKHR::INSTANCES, - geometry: ash::vk::AccelerationStructureGeometryDataKHR { - instances: ash::vk::AccelerationStructureGeometryInstancesDataKHR { - array_of_pointers, - data, - ..Default::default() - }, - }, - flags: flags.into(), - ..Default::default() - }] - .into_iter() - .collect() - }) + [instances_data.to_vk()].into_iter().collect() } }; - ( - ash::vk::AccelerationStructureBuildGeometryInfoKHR { - ty, - flags: flags.into(), - mode: mode.into(), - src_acceleration_structure: match mode { - BuildAccelerationStructureMode::Build => Default::default(), - BuildAccelerationStructureMode::Update(src_acceleration_structure) => { - src_acceleration_structure.handle() - } - }, - dst_acceleration_structure: dst_acceleration_structure - .as_ref() - .map_or_else(Default::default, VulkanObject::handle), - geometry_count: 0, - p_geometries: ptr::null(), - pp_geometries: ptr::null(), - scratch_data: ash::vk::DeviceOrHostAddressKHR { - device_address: scratch_data.as_ref().map_or(0, |scratch_data| { - scratch_data.device_address().unwrap().into() - }), - }, - ..Default::default() - }, - geometries_vk, - ) + AccelerationStructureBuildGeometryInfoFields1Vk { geometries_vk } } } +pub(crate) struct AccelerationStructureBuildGeometryInfoFields1Vk { + pub(crate) geometries_vk: Vec>, +} + vulkan_bitflags! { #[non_exhaustive] @@ -860,10 +738,9 @@ pub enum BuildAccelerationStructureMode { ash::vk::BuildAccelerationStructureModeKHR::UPDATE.as_raw(), } -impl From<&BuildAccelerationStructureMode> for ash::vk::BuildAccelerationStructureModeKHR { - #[inline] - fn from(val: &BuildAccelerationStructureMode) -> Self { - match val { +impl BuildAccelerationStructureMode { + pub(crate) fn to_vk(&self) -> ash::vk::BuildAccelerationStructureModeKHR { + match self { BuildAccelerationStructureMode::Build => { ash::vk::BuildAccelerationStructureModeKHR::BUILD } @@ -897,6 +774,20 @@ impl AccelerationStructureGeometries { AccelerationStructureGeometries::Instances(_) => 1, } } + + pub(crate) fn to_vk_ty(&self) -> ash::vk::AccelerationStructureTypeKHR { + match self { + AccelerationStructureGeometries::Triangles(_) => { + ash::vk::AccelerationStructureTypeKHR::BOTTOM_LEVEL + } + AccelerationStructureGeometries::Aabbs(_) => { + ash::vk::AccelerationStructureTypeKHR::BOTTOM_LEVEL + } + AccelerationStructureGeometries::Instances(_) => { + ash::vk::AccelerationStructureTypeKHR::TOP_LEVEL + } + } + } } impl From> for AccelerationStructureGeometries { @@ -1076,6 +967,48 @@ impl AccelerationStructureGeometryTrianglesData { Ok(()) } + + pub(crate) fn to_vk(&self) -> ash::vk::AccelerationStructureGeometryKHR<'static> { + let &AccelerationStructureGeometryTrianglesData { + flags, + vertex_format, + ref vertex_data, + vertex_stride, + max_vertex, + ref index_data, + ref transform_data, + _ne, + } = self; + + ash::vk::AccelerationStructureGeometryKHR::default() + .geometry_type(ash::vk::GeometryTypeKHR::TRIANGLES) + .geometry(ash::vk::AccelerationStructureGeometryDataKHR { + triangles: ash::vk::AccelerationStructureGeometryTrianglesDataKHR::default() + .vertex_format(vertex_format.into()) + .vertex_data(vertex_data.as_ref().map_or_else( + Default::default, + Subbuffer::to_vk_device_or_host_address_const, + )) + .vertex_stride(vertex_stride as DeviceSize) + .max_vertex(max_vertex) + .index_type( + index_data + .as_ref() + .map_or(ash::vk::IndexType::NONE_KHR, |index_data| { + index_data.index_type().into() + }), + ) + .index_data(index_data.as_ref().map(IndexBuffer::as_bytes).map_or_else( + Default::default, + Subbuffer::to_vk_device_or_host_address_const, + )) + .transform_data(transform_data.as_ref().map_or_else( + Default::default, + Subbuffer::to_vk_device_or_host_address_const, + )), + }) + .flags(flags.into()) + } } /// A 3x4 transformation matrix. @@ -1146,6 +1079,27 @@ impl AccelerationStructureGeometryAabbsData { Ok(()) } + + pub(crate) fn to_vk(&self) -> ash::vk::AccelerationStructureGeometryKHR<'static> { + let &Self { + flags, + ref data, + stride, + _ne: _, + } = self; + + ash::vk::AccelerationStructureGeometryKHR::default() + .geometry_type(ash::vk::GeometryTypeKHR::AABBS) + .geometry(ash::vk::AccelerationStructureGeometryDataKHR { + aabbs: ash::vk::AccelerationStructureGeometryAabbsDataKHR::default() + .data(data.as_ref().map_or_else( + Default::default, + Subbuffer::to_vk_device_or_host_address_const, + )) + .stride(stride as DeviceSize), + }) + .flags(flags.into()) + } } /// Specifies two opposing corners of an axis-aligned bounding box. @@ -1206,6 +1160,25 @@ impl AccelerationStructureGeometryInstancesData { Ok(()) } + + pub(crate) fn to_vk(&self) -> ash::vk::AccelerationStructureGeometryKHR<'static> { + let &Self { + flags, + ref data, + _ne: _, + } = self; + + let (array_of_pointers_vk, data_vk) = data.to_vk(); + + ash::vk::AccelerationStructureGeometryKHR::default() + .geometry_type(ash::vk::GeometryTypeKHR::INSTANCES) + .geometry(ash::vk::AccelerationStructureGeometryDataKHR { + instances: ash::vk::AccelerationStructureGeometryInstancesDataKHR::default() + .array_of_pointers(array_of_pointers_vk) + .data(data_vk), + }) + .flags(flags.into()) + } } /// The data type of an instances geometry. @@ -1225,6 +1198,27 @@ pub enum AccelerationStructureGeometryInstancesDataType { Pointers(Option>), } +impl AccelerationStructureGeometryInstancesDataType { + pub(crate) fn to_vk(&self) -> (bool, ash::vk::DeviceOrHostAddressConstKHR) { + match self { + AccelerationStructureGeometryInstancesDataType::Values(data) => ( + false, + data.as_ref().map_or_else( + Default::default, + Subbuffer::to_vk_device_or_host_address_const, + ), + ), + AccelerationStructureGeometryInstancesDataType::Pointers(data) => ( + true, + data.as_ref().map_or_else( + Default::default, + Subbuffer::to_vk_device_or_host_address_const, + ), + ), + } + } +} + impl From> for AccelerationStructureGeometryInstancesDataType { @@ -1360,6 +1354,25 @@ pub struct AccelerationStructureBuildRangeInfo { pub transform_offset: u32, } +impl AccelerationStructureBuildRangeInfo { + #[allow(clippy::wrong_self_convention)] + pub(crate) fn to_vk(&self) -> ash::vk::AccelerationStructureBuildRangeInfoKHR { + let &Self { + primitive_count, + primitive_offset, + first_vertex, + transform_offset, + } = self; + + ash::vk::AccelerationStructureBuildRangeInfoKHR { + primitive_count, + primitive_offset, + first_vertex, + transform_offset, + } + } +} + /// Parameters for copying an acceleration structure. #[derive(Clone, Debug)] pub struct CopyAccelerationStructureInfo { @@ -1440,6 +1453,20 @@ impl CopyAccelerationStructureInfo { Ok(()) } + + pub(crate) fn to_vk(&self) -> ash::vk::CopyAccelerationStructureInfoKHR<'static> { + let &Self { + ref src, + ref dst, + mode, + _ne: _, + } = self; + + ash::vk::CopyAccelerationStructureInfoKHR::default() + .src(src.handle()) + .dst(dst.handle()) + .mode(mode.into()) + } } /// Parameters for copying from an acceleration structure into memory. @@ -1508,6 +1535,20 @@ impl CopyAccelerationStructureToMemoryInfo { Ok(()) } + + pub(crate) fn to_vk(&self) -> ash::vk::CopyAccelerationStructureToMemoryInfoKHR<'static> { + let &Self { + ref src, + ref dst, + mode, + _ne: _, + } = self; + + ash::vk::CopyAccelerationStructureToMemoryInfoKHR::default() + .src(src.handle()) + .dst(dst.to_vk_device_or_host_address()) + .mode(mode.into()) + } } /// Parameters for copying from memory into an acceleration structure. @@ -1579,6 +1620,20 @@ impl CopyMemoryToAccelerationStructureInfo { Ok(()) } + + pub(crate) fn to_vk(&self) -> ash::vk::CopyMemoryToAccelerationStructureInfoKHR<'static> { + let &Self { + ref src, + ref dst, + mode, + _ne: _, + } = self; + + ash::vk::CopyMemoryToAccelerationStructureInfoKHR::default() + .src(src.to_vk_device_or_host_address_const()) + .dst(dst.handle()) + .mode(mode.into()) + } } vulkan_enum! { @@ -1642,3 +1697,25 @@ pub struct AccelerationStructureBuildSizesInfo { pub _ne: crate::NonExhaustive, } + +impl AccelerationStructureBuildSizesInfo { + pub(crate) fn to_mut_vk() -> ash::vk::AccelerationStructureBuildSizesInfoKHR<'static> { + ash::vk::AccelerationStructureBuildSizesInfoKHR::default() + } + + pub(crate) fn from_vk(val_vk: &ash::vk::AccelerationStructureBuildSizesInfoKHR<'_>) -> Self { + let &ash::vk::AccelerationStructureBuildSizesInfoKHR { + acceleration_structure_size, + update_scratch_size, + build_scratch_size, + .. + } = val_vk; + + AccelerationStructureBuildSizesInfo { + acceleration_structure_size, + update_scratch_size, + build_scratch_size, + _ne: crate::NonExhaustive(()), + } + } +} diff --git a/vulkano/src/buffer/mod.rs b/vulkano/src/buffer/mod.rs index 1caff316..1a7ac923 100644 --- a/vulkano/src/buffer/mod.rs +++ b/vulkano/src/buffer/mod.rs @@ -510,10 +510,7 @@ impl Buffer { pub unsafe fn device_address_unchecked(&self) -> NonNullDeviceAddress { let device = self.device(); - let info_vk = ash::vk::BufferDeviceAddressInfo { - buffer: self.handle(), - ..Default::default() - }; + let info_vk = ash::vk::BufferDeviceAddressInfo::default().buffer(self.handle()); let ptr = { let fns = device.fns(); @@ -933,6 +930,20 @@ impl ExternalBufferInfo { Ok(()) } + + pub(crate) fn to_vk(&self) -> ash::vk::PhysicalDeviceExternalBufferInfo<'static> { + let &Self { + flags, + usage, + handle_type, + _ne: _, + } = self; + + ash::vk::PhysicalDeviceExternalBufferInfo::default() + .flags(flags.into()) + .usage(usage.into()) + .handle_type(handle_type.into()) + } } /// The external memory properties supported for buffers with a given configuration. @@ -943,6 +954,25 @@ pub struct ExternalBufferProperties { pub external_memory_properties: ExternalMemoryProperties, } +impl ExternalBufferProperties { + pub(crate) fn to_mut_vk() -> ash::vk::ExternalBufferProperties<'static> { + ash::vk::ExternalBufferProperties::default() + } + + pub(crate) fn from_vk(val_vk: &ash::vk::ExternalBufferProperties<'_>) -> Self { + let &ash::vk::ExternalBufferProperties { + ref external_memory_properties, + .. + } = val_vk; + + Self { + external_memory_properties: ExternalMemoryProperties::from_vk( + external_memory_properties, + ), + } + } +} + vulkan_enum! { #[non_exhaustive] diff --git a/vulkano/src/buffer/subbuffer.rs b/vulkano/src/buffer/subbuffer.rs index 85a42fa0..3ed53344 100644 --- a/vulkano/src/buffer/subbuffer.rs +++ b/vulkano/src/buffer/subbuffer.rs @@ -173,6 +173,26 @@ impl Subbuffer { // SAFETY: All `Subbuffer`s share the same layout. mem::transmute::<&Subbuffer, &Subbuffer>(self) } + + pub(crate) fn to_vk_device_or_host_address(&self) -> ash::vk::DeviceOrHostAddressKHR { + ash::vk::DeviceOrHostAddressKHR { + device_address: self + .device_address() + .expect("Can't get device address. Is the extension enabled?") + .into(), + } + } + + pub(crate) fn to_vk_device_or_host_address_const( + &self, + ) -> ash::vk::DeviceOrHostAddressConstKHR { + ash::vk::DeviceOrHostAddressConstKHR { + device_address: self + .device_address() + .expect("Can't get device address. Is the extension enabled?") + .into(), + } + } } impl Subbuffer diff --git a/vulkano/src/buffer/sys.rs b/vulkano/src/buffer/sys.rs index d141ff8d..f4d24ef8 100644 --- a/vulkano/src/buffer/sys.rs +++ b/vulkano/src/buffer/sys.rs @@ -11,16 +11,15 @@ use crate::{ instance::InstanceOwnedDebugWrapper, macros::impl_id_counter, memory::{ - allocator::{AllocationType, DeviceLayout}, - is_aligned, DedicatedTo, ExternalMemoryHandleTypes, MemoryAllocateFlags, - MemoryPropertyFlags, MemoryRequirements, ResourceMemory, + allocator::AllocationType, is_aligned, DedicatedTo, ExternalMemoryHandleTypes, + MemoryAllocateFlags, MemoryPropertyFlags, MemoryRequirements, ResourceMemory, }, sync::Sharing, DeviceSize, Requires, RequiresAllOf, RequiresOneOf, Validated, ValidationError, Version, VulkanError, VulkanObject, }; use smallvec::SmallVec; -use std::{mem::MaybeUninit, num::NonZeroU64, ptr, sync::Arc}; +use std::{marker::PhantomData, mem::MaybeUninit, num::NonZeroU64, ptr, sync::Arc}; /// A raw buffer, with no memory backing it. /// @@ -78,44 +77,8 @@ impl RawBuffer { device: Arc, create_info: BufferCreateInfo, ) -> Result { - let &BufferCreateInfo { - flags, - ref sharing, - size, - usage, - external_memory_handle_types, - _ne: _, - } = &create_info; - - let (sharing_mode, queue_family_index_count, p_queue_family_indices) = match sharing { - Sharing::Exclusive => (ash::vk::SharingMode::EXCLUSIVE, 0, ptr::null()), - Sharing::Concurrent(queue_family_indices) => ( - ash::vk::SharingMode::CONCURRENT, - queue_family_indices.len() as u32, - queue_family_indices.as_ptr(), - ), - }; - - let mut create_info_vk = ash::vk::BufferCreateInfo { - flags: flags.into(), - size, - usage: usage.into(), - sharing_mode, - queue_family_index_count, - p_queue_family_indices, - ..Default::default() - }; - let mut external_memory_info_vk = None; - - if !external_memory_handle_types.is_empty() { - let next = external_memory_info_vk.insert(ash::vk::ExternalMemoryBufferCreateInfo { - handle_types: external_memory_handle_types.into(), - ..Default::default() - }); - - next.p_next = create_info_vk.p_next; - create_info_vk.p_next = <*const _>::cast(next); - } + let mut extensions_vk = create_info.to_vk_extensions(); + let create_info_vk = create_info.to_vk(&mut extensions_vk); let handle = { let fns = device.fns(); @@ -225,28 +188,12 @@ impl RawBuffer { } fn get_memory_requirements(device: &Device, handle: ash::vk::Buffer) -> MemoryRequirements { - let info_vk = ash::vk::BufferMemoryRequirementsInfo2 { - buffer: handle, - ..Default::default() - }; + let info_vk = ash::vk::BufferMemoryRequirementsInfo2::default().buffer(handle); - let mut memory_requirements2_vk = ash::vk::MemoryRequirements2::default(); - let mut memory_dedicated_requirements_vk = None; - - if device.api_version() >= Version::V1_1 - || device.enabled_extensions().khr_dedicated_allocation - { - debug_assert!( - device.api_version() >= Version::V1_1 - || device.enabled_extensions().khr_get_memory_requirements2 - ); - - let next = memory_dedicated_requirements_vk - .insert(ash::vk::MemoryDedicatedRequirements::default()); - - next.p_next = memory_requirements2_vk.p_next; - memory_requirements2_vk.p_next = <*mut _>::cast(next); - } + let mut memory_requirements2_extensions_vk = + MemoryRequirements::to_mut_vk2_extensions(device); + let mut memory_requirements2_vk = + MemoryRequirements::to_mut_vk2(&mut memory_requirements2_extensions_vk); unsafe { let fns = device.fns(); @@ -277,18 +224,16 @@ impl RawBuffer { } } - MemoryRequirements { - layout: DeviceLayout::from_size_alignment( - memory_requirements2_vk.memory_requirements.size, - memory_requirements2_vk.memory_requirements.alignment, - ) - .unwrap(), - memory_type_bits: memory_requirements2_vk.memory_requirements.memory_type_bits, - prefers_dedicated_allocation: memory_dedicated_requirements_vk - .map_or(false, |dreqs| dreqs.prefers_dedicated_allocation != 0), - requires_dedicated_allocation: memory_dedicated_requirements_vk - .map_or(false, |dreqs| dreqs.requires_dedicated_allocation != 0), - } + // Unborrow + let memory_requirements2_vk = ash::vk::MemoryRequirements2 { + _marker: PhantomData, + ..memory_requirements2_vk + }; + + MemoryRequirements::from_vk2( + &memory_requirements2_vk, + &memory_requirements2_extensions_vk, + ) } /// Binds device memory to this buffer. @@ -532,20 +477,14 @@ impl RawBuffer { self, allocation: ResourceMemory, ) -> Result { - let memory = allocation.device_memory(); - let memory_offset = allocation.offset(); + let bind_info_vk = allocation.to_vk_bind_buffer_memory_info(self.handle()); let fns = self.device.fns(); let result = if self.device.api_version() >= Version::V1_1 || self.device.enabled_extensions().khr_bind_memory2 { - let bind_infos_vk = [ash::vk::BindBufferMemoryInfo { - buffer: self.handle, - memory: memory.handle(), - memory_offset, - ..Default::default() - }]; + let bind_infos_vk = [bind_info_vk]; if self.device.api_version() >= Version::V1_1 { (fns.v1_1.bind_buffer_memory2)( @@ -563,9 +502,9 @@ impl RawBuffer { } else { (fns.v1_0.bind_buffer_memory)( self.device.handle(), - self.handle, - memory.handle(), - memory_offset, + bind_info_vk.buffer, + bind_info_vk.memory, + bind_info_vk.memory_offset, ) } .result(); @@ -859,6 +798,55 @@ impl BufferCreateInfo { Ok(()) } + + pub(crate) fn to_vk<'a>( + &'a self, + extensions_vk: &'a mut BufferCreateInfoExtensionsVk, + ) -> ash::vk::BufferCreateInfo<'a> { + let &Self { + flags, + ref sharing, + size, + usage, + external_memory_handle_types: _, + _ne: _, + } = self; + + let (sharing_mode_vk, queue_family_indices) = sharing.to_vk(); + + let mut val_vk = ash::vk::BufferCreateInfo::default() + .flags(flags.into()) + .size(size) + .usage(usage.into()) + .sharing_mode(sharing_mode_vk) + .queue_family_indices(queue_family_indices); + + let BufferCreateInfoExtensionsVk { external_memory_vk } = extensions_vk; + + if let Some(next) = external_memory_vk { + val_vk = val_vk.push_next(next); + } + + val_vk + } + + pub(crate) fn to_vk_extensions(&self) -> BufferCreateInfoExtensionsVk { + let &Self { + external_memory_handle_types, + .. + } = self; + + let external_memory_vk = (!external_memory_handle_types.is_empty()).then(|| { + ash::vk::ExternalMemoryBufferCreateInfo::default() + .handle_types(external_memory_handle_types.into()) + }); + + BufferCreateInfoExtensionsVk { external_memory_vk } + } +} + +pub(crate) struct BufferCreateInfoExtensionsVk { + pub(crate) external_memory_vk: Option>, } #[cfg(test)] diff --git a/vulkano/src/buffer/view.rs b/vulkano/src/buffer/view.rs index 8d11ca81..d969af62 100644 --- a/vulkano/src/buffer/view.rs +++ b/vulkano/src/buffer/view.rs @@ -287,18 +287,8 @@ impl BufferView { subbuffer: Subbuffer, create_info: BufferViewCreateInfo, ) -> Result, VulkanError> { - let &BufferViewCreateInfo { format, _ne: _ } = &create_info; - let device = subbuffer.device(); - - let create_info_vk = ash::vk::BufferViewCreateInfo { - flags: ash::vk::BufferViewCreateFlags::empty(), - buffer: subbuffer.buffer().handle(), - format: format.into(), - offset: subbuffer.offset(), - range: subbuffer.size(), - ..Default::default() - }; + let create_info_vk = create_info.to_vk(subbuffer.as_bytes()); let handle = unsafe { let fns = device.fns(); @@ -437,6 +427,20 @@ impl BufferViewCreateInfo { Ok(()) } + + pub(crate) fn to_vk( + &self, + subbuffer: &Subbuffer<[u8]>, + ) -> ash::vk::BufferViewCreateInfo<'static> { + let &Self { format, _ne: _ } = self; + + ash::vk::BufferViewCreateInfo::default() + .flags(ash::vk::BufferViewCreateFlags::empty()) + .buffer(subbuffer.buffer().handle()) + .format(format.into()) + .offset(subbuffer.offset()) + .range(subbuffer.size()) + } } #[cfg(test)] diff --git a/vulkano/src/command_buffer/auto/builder.rs b/vulkano/src/command_buffer/auto/builder.rs index 43d80e89..4a47d3e9 100644 --- a/vulkano/src/command_buffer/auto/builder.rs +++ b/vulkano/src/command_buffer/auto/builder.rs @@ -18,10 +18,11 @@ use crate::{ pipeline::{ graphics::{ color_blend::LogicOp, - conservative_rasterization::ConservativeRasterizationMode, depth_stencil::{CompareOp, StencilOps}, input_assembly::PrimitiveTopology, - rasterization::{CullMode, DepthBiasState, FrontFace, LineStipple}, + rasterization::{ + ConservativeRasterizationMode, CullMode, DepthBiasState, FrontFace, LineStipple, + }, subpass::PipelineRenderingCreateInfo, vertex_input::VertexInputState, viewport::{Scissor, Viewport}, diff --git a/vulkano/src/command_buffer/auto/mod.rs b/vulkano/src/command_buffer/auto/mod.rs index c89b376f..926c8afe 100644 --- a/vulkano/src/command_buffer/auto/mod.rs +++ b/vulkano/src/command_buffer/auto/mod.rs @@ -715,7 +715,7 @@ mod tests { let mut builder = RecordingCommandBuffer::new( cb_allocator.clone(), queue.queue_family_index(), - CommandBufferLevel::Secondary, + CommandBufferLevel::Primary, CommandBufferBeginInfo { usage: CommandBufferUsage::SimultaneousUse, inheritance_info: Some(Default::default()), @@ -743,7 +743,7 @@ mod tests { let mut builder = RecordingCommandBuffer::new( cb_allocator, queue.queue_family_index(), - CommandBufferLevel::Secondary, + CommandBufferLevel::Primary, CommandBufferBeginInfo { usage: CommandBufferUsage::SimultaneousUse, inheritance_info: Some(Default::default()), diff --git a/vulkano/src/command_buffer/commands/acceleration_structure.rs b/vulkano/src/command_buffer/commands/acceleration_structure.rs index 8957216b..8236aa42 100644 --- a/vulkano/src/command_buffer/commands/acceleration_structure.rs +++ b/vulkano/src/command_buffer/commands/acceleration_structure.rs @@ -1539,30 +1539,12 @@ impl RawRecordingCommandBuffer { info: &AccelerationStructureBuildGeometryInfo, build_range_infos: &[AccelerationStructureBuildRangeInfo], ) -> &mut Self { - let (mut info_vk, geometries_vk) = info.to_vulkan(); - info_vk = ash::vk::AccelerationStructureBuildGeometryInfoKHR { - geometry_count: geometries_vk.len() as u32, - p_geometries: geometries_vk.as_ptr(), - ..info_vk - }; + let info_fields1_vk = info.to_vk_fields1(); + let info_vk = info.to_vk(&info_fields1_vk); let build_range_info_elements_vk: SmallVec<[_; 8]> = build_range_infos .iter() - .map(|build_range_info| { - let &AccelerationStructureBuildRangeInfo { - primitive_count, - primitive_offset, - first_vertex, - transform_offset, - } = build_range_info; - - ash::vk::AccelerationStructureBuildRangeInfoKHR { - primitive_count, - primitive_offset, - first_vertex, - transform_offset, - } - }) + .map(AccelerationStructureBuildRangeInfo::to_vk) .collect(); let build_range_info_pointers_vk: SmallVec<[_; 8]> = build_range_info_elements_vk .iter() @@ -2182,12 +2164,8 @@ impl RawRecordingCommandBuffer { stride: u32, max_primitive_counts: &[u32], ) -> &mut Self { - let (mut info_vk, geometries_vk) = info.to_vulkan(); - info_vk = ash::vk::AccelerationStructureBuildGeometryInfoKHR { - geometry_count: geometries_vk.len() as u32, - p_geometries: geometries_vk.as_ptr(), - ..info_vk - }; + let info_fields1_vk = info.to_vk_fields1(); + let info_vk = info.to_vk(&info_fields1_vk); let fns = self.device().fns(); (fns.khr_acceleration_structure @@ -2242,19 +2220,7 @@ impl RawRecordingCommandBuffer { &mut self, info: &CopyAccelerationStructureInfo, ) -> &mut Self { - let &CopyAccelerationStructureInfo { - ref src, - ref dst, - mode, - _ne: _, - } = info; - - let info_vk = ash::vk::CopyAccelerationStructureInfoKHR { - src: src.handle(), - dst: dst.handle(), - mode: mode.into(), - ..Default::default() - }; + let info_vk = info.to_vk(); let fns = self.device().fns(); (fns.khr_acceleration_structure @@ -2311,21 +2277,7 @@ impl RawRecordingCommandBuffer { &mut self, info: &CopyAccelerationStructureToMemoryInfo, ) -> &mut Self { - let &CopyAccelerationStructureToMemoryInfo { - ref src, - ref dst, - mode, - _ne: _, - } = info; - - let info_vk = ash::vk::CopyAccelerationStructureToMemoryInfoKHR { - src: src.handle(), - dst: ash::vk::DeviceOrHostAddressKHR { - device_address: dst.device_address().unwrap().get(), - }, - mode: mode.into(), - ..Default::default() - }; + let info_vk = info.to_vk(); let fns = self.device().fns(); (fns.khr_acceleration_structure @@ -2382,21 +2334,7 @@ impl RawRecordingCommandBuffer { &mut self, info: &CopyMemoryToAccelerationStructureInfo, ) -> &mut Self { - let &CopyMemoryToAccelerationStructureInfo { - ref src, - ref dst, - mode, - _ne: _, - } = info; - - let info_vk = ash::vk::CopyMemoryToAccelerationStructureInfoKHR { - src: ash::vk::DeviceOrHostAddressConstKHR { - device_address: src.device_address().unwrap().get(), - }, - dst: dst.handle(), - mode: mode.into(), - ..Default::default() - }; + let info_vk = info.to_vk(); let fns = self.device().fns(); (fns.khr_acceleration_structure diff --git a/vulkano/src/command_buffer/commands/bind_push.rs b/vulkano/src/command_buffer/commands/bind_push.rs index 369e3198..e2b75a90 100644 --- a/vulkano/src/command_buffer/commands/bind_push.rs +++ b/vulkano/src/command_buffer/commands/bind_push.rs @@ -4,8 +4,7 @@ use crate::{ descriptor_set::{ layout::{DescriptorBindingFlags, DescriptorSetLayoutCreateFlags, DescriptorType}, DescriptorBindingResources, DescriptorBufferInfo, DescriptorSetResources, - DescriptorSetWithOffsets, DescriptorSetsCollection, DescriptorWriteInfo, - WriteDescriptorSet, + DescriptorSetWithOffsets, DescriptorSetsCollection, WriteDescriptorSet, }, device::{DeviceOwned, QueueFlags}, memory::is_aligned, @@ -1307,65 +1306,34 @@ impl RawRecordingCommandBuffer { return self; } - let set_layout = &pipeline_layout.set_layouts()[set_num as usize]; - - struct PerDescriptorWrite { - write_info: DescriptorWriteInfo, - acceleration_structures: ash::vk::WriteDescriptorSetAccelerationStructureKHR<'static>, - inline_uniform_block: ash::vk::WriteDescriptorSetInlineUniformBlock<'static>, - } - - let mut writes_vk: SmallVec<[_; 8]> = SmallVec::with_capacity(descriptor_writes.len()); - let mut per_writes_vk: SmallVec<[_; 8]> = SmallVec::with_capacity(descriptor_writes.len()); - - for write in descriptor_writes { - let layout_binding = &set_layout.bindings()[&write.binding()]; - - writes_vk.push(write.to_vulkan( - ash::vk::DescriptorSet::null(), - layout_binding.descriptor_type, - )); - per_writes_vk.push(PerDescriptorWrite { - write_info: write.to_vulkan_info(layout_binding.descriptor_type), - acceleration_structures: Default::default(), - inline_uniform_block: Default::default(), - }); - } - - for (write_vk, per_write_vk) in writes_vk.iter_mut().zip(per_writes_vk.iter_mut()) { - match &mut per_write_vk.write_info { - DescriptorWriteInfo::Image(info) => { - write_vk.descriptor_count = info.len() as u32; - write_vk.p_image_info = info.as_ptr(); - } - DescriptorWriteInfo::Buffer(info) => { - write_vk.descriptor_count = info.len() as u32; - write_vk.p_buffer_info = info.as_ptr(); - } - DescriptorWriteInfo::BufferView(info) => { - write_vk.descriptor_count = info.len() as u32; - write_vk.p_texel_buffer_view = info.as_ptr(); - } - DescriptorWriteInfo::InlineUniformBlock(data) => { - write_vk.descriptor_count = data.len() as u32; - write_vk.p_next = <*const _>::cast(&per_write_vk.inline_uniform_block); - per_write_vk.inline_uniform_block.data_size = write_vk.descriptor_count; - per_write_vk.inline_uniform_block.p_data = data.as_ptr().cast(); - } - DescriptorWriteInfo::AccelerationStructure(info) => { - write_vk.descriptor_count = info.len() as u32; - write_vk.p_next = <*const _>::cast(&per_write_vk.acceleration_structures); - per_write_vk - .acceleration_structures - .acceleration_structure_count = write_vk.descriptor_count; - per_write_vk - .acceleration_structures - .p_acceleration_structures = info.as_ptr(); - } - } - - debug_assert!(write_vk.descriptor_count != 0); - } + let set_layout_bindings = &pipeline_layout.set_layouts()[set_num as usize].bindings(); + let writes_fields1_vk: SmallVec<[_; 8]> = descriptor_writes + .iter() + .map(|write| { + let default_image_layout = set_layout_bindings[&write.binding()] + .descriptor_type + .default_image_layout(); + write.to_vk_fields1(default_image_layout) + }) + .collect(); + let mut writes_extensions_vk: SmallVec<[_; 8]> = descriptor_writes + .iter() + .zip(&writes_fields1_vk) + .map(|(write, fields1_vk)| write.to_vk_extensions(fields1_vk)) + .collect(); + let writes_vk: SmallVec<[_; 8]> = descriptor_writes + .iter() + .zip(&writes_fields1_vk) + .zip(&mut writes_extensions_vk) + .map(|((write, write_info_vk), write_extension_vk)| { + write.to_vk( + ash::vk::DescriptorSet::null(), + set_layout_bindings[&write.binding()].descriptor_type, + write_info_vk, + write_extension_vk, + ) + }) + .collect(); let fns = self.device().fns(); (fns.khr_push_descriptor.cmd_push_descriptor_set_khr)( diff --git a/vulkano/src/command_buffer/commands/clear.rs b/vulkano/src/command_buffer/commands/clear.rs index 7f12b1c4..0007f249 100644 --- a/vulkano/src/command_buffer/commands/clear.rs +++ b/vulkano/src/command_buffer/commands/clear.rs @@ -313,31 +313,19 @@ impl RawRecordingCommandBuffer { &mut self, clear_info: &ClearColorImageInfo, ) -> &mut Self { - let &ClearColorImageInfo { - ref image, - image_layout, - clear_value, - ref regions, - _ne: _, - } = clear_info; - - if regions.is_empty() { + if clear_info.regions.is_empty() { return self; } - let clear_value_vk = clear_value.into(); - let ranges_vk: SmallVec<[_; 8]> = regions - .iter() - .cloned() - .map(ash::vk::ImageSubresourceRange::from) - .collect(); + let clear_info_vk = clear_info.to_vk(); + let ranges_vk = clear_info.to_vk_ranges(); let fns = self.device().fns(); (fns.v1_0.cmd_clear_color_image)( self.handle(), - image.handle(), - image_layout.into(), - &clear_value_vk, + clear_info_vk.image, + clear_info_vk.image_layout, + &clear_info_vk.color, ranges_vk.len() as u32, ranges_vk.as_ptr(), ); @@ -385,31 +373,19 @@ impl RawRecordingCommandBuffer { &mut self, clear_info: &ClearDepthStencilImageInfo, ) -> &mut Self { - let &ClearDepthStencilImageInfo { - ref image, - image_layout, - clear_value, - ref regions, - _ne: _, - } = clear_info; - - if regions.is_empty() { + if clear_info.regions.is_empty() { return self; } - let clear_value_vk = clear_value.into(); - let ranges_vk: SmallVec<[_; 8]> = regions - .iter() - .cloned() - .map(ash::vk::ImageSubresourceRange::from) - .collect(); + let clear_info_vk = clear_info.to_vk(); + let ranges_vk = clear_info.to_vk_ranges(); let fns = self.device().fns(); (fns.v1_0.cmd_clear_depth_stencil_image)( self.handle(), - image.handle(), - image_layout.into(), - &clear_value_vk, + clear_info_vk.image, + clear_info_vk.image_layout, + &clear_info_vk.depth_stencil, ranges_vk.len() as u32, ranges_vk.as_ptr(), ); @@ -814,6 +790,35 @@ impl ClearColorImageInfo { Ok(()) } + + pub(crate) fn to_vk(&self) -> ClearColorImageInfoVk { + let &Self { + ref image, + image_layout, + clear_value, + regions: _, + _ne: _, + } = self; + + ClearColorImageInfoVk { + image: image.handle(), + image_layout: image_layout.into(), + color: clear_value.to_vk(), + } + } + + pub(crate) fn to_vk_ranges(&self) -> SmallVec<[ash::vk::ImageSubresourceRange; 8]> { + self.regions + .iter() + .map(ImageSubresourceRange::to_vk) + .collect() + } +} + +pub(crate) struct ClearColorImageInfoVk { + pub(crate) image: ash::vk::Image, + pub(crate) image_layout: ash::vk::ImageLayout, + pub(crate) color: ash::vk::ClearColorValue, } /// Parameters to clear a depth/stencil image. @@ -1020,4 +1025,33 @@ impl ClearDepthStencilImageInfo { Ok(()) } + + pub(crate) fn to_vk(&self) -> ClearDepthStencilImageInfoVk { + let &Self { + ref image, + image_layout, + clear_value, + regions: _, + _ne: _, + } = self; + + ClearDepthStencilImageInfoVk { + image: image.handle(), + image_layout: image_layout.into(), + depth_stencil: clear_value.to_vk(), + } + } + + pub(crate) fn to_vk_ranges(&self) -> SmallVec<[ash::vk::ImageSubresourceRange; 8]> { + self.regions + .iter() + .map(ImageSubresourceRange::to_vk) + .collect() + } +} + +pub(crate) struct ClearDepthStencilImageInfoVk { + pub(crate) image: ash::vk::Image, + pub(crate) image_layout: ash::vk::ImageLayout, + pub(crate) depth_stencil: ash::vk::ClearDepthStencilValue, } diff --git a/vulkano/src/command_buffer/commands/copy.rs b/vulkano/src/command_buffer/commands/copy.rs index 5caf6559..ee61f1b8 100644 --- a/vulkano/src/command_buffer/commands/copy.rs +++ b/vulkano/src/command_buffer/commands/copy.rs @@ -625,14 +625,7 @@ impl RawRecordingCommandBuffer { #[cfg_attr(not(feature = "document_unchecked"), doc(hidden))] pub unsafe fn copy_buffer_unchecked(&mut self, copy_buffer_info: &CopyBufferInfo) -> &mut Self { - let CopyBufferInfo { - src_buffer, - dst_buffer, - regions, - _ne: _, - } = copy_buffer_info; - - if regions.is_empty() { + if copy_buffer_info.regions.is_empty() { return self; } @@ -641,63 +634,27 @@ impl RawRecordingCommandBuffer { if self.device().api_version() >= Version::V1_3 || self.device().enabled_extensions().khr_copy_commands2 { - let regions: SmallVec<[_; 8]> = regions - .iter() - .map(|region| { - let &BufferCopy { - src_offset, - dst_offset, - size, - _ne, - } = region; - - ash::vk::BufferCopy2 { - src_offset: src_offset + src_buffer.offset(), - dst_offset: dst_offset + dst_buffer.offset(), - size, - ..Default::default() - } - }) - .collect(); - - let copy_buffer_info = ash::vk::CopyBufferInfo2 { - src_buffer: src_buffer.buffer().handle(), - dst_buffer: dst_buffer.buffer().handle(), - region_count: regions.len() as u32, - p_regions: regions.as_ptr(), - ..Default::default() - }; + let regions_vk = copy_buffer_info.to_vk2_regions(); + let copy_buffer_info_vk = copy_buffer_info.to_vk2(®ions_vk); if self.device().api_version() >= Version::V1_3 { - (fns.v1_3.cmd_copy_buffer2)(self.handle(), ©_buffer_info); + (fns.v1_3.cmd_copy_buffer2)(self.handle(), ©_buffer_info_vk); } else { - (fns.khr_copy_commands2.cmd_copy_buffer2_khr)(self.handle(), ©_buffer_info); + (fns.khr_copy_commands2.cmd_copy_buffer2_khr)(self.handle(), ©_buffer_info_vk); } } else { - let regions: SmallVec<[_; 8]> = regions - .iter() - .map(|region| { - let &BufferCopy { - src_offset, - dst_offset, - size, - _ne, - } = region; - - ash::vk::BufferCopy { - src_offset: src_offset + src_buffer.offset(), - dst_offset: dst_offset + dst_buffer.offset(), - size, - } - }) - .collect(); + let regions_vk = copy_buffer_info.to_vk_regions(); + let CopyBufferInfoVk { + src_buffer_vk, + dst_buffer_vk, + } = copy_buffer_info.to_vk(); (fns.v1_0.cmd_copy_buffer)( self.handle(), - src_buffer.buffer().handle(), - dst_buffer.buffer().handle(), - regions.len() as u32, - regions.as_ptr(), + src_buffer_vk, + dst_buffer_vk, + regions_vk.len() as u32, + regions_vk.as_ptr(), ); } @@ -1011,16 +968,7 @@ impl RawRecordingCommandBuffer { #[cfg_attr(not(feature = "document_unchecked"), doc(hidden))] pub unsafe fn copy_image_unchecked(&mut self, copy_image_info: &CopyImageInfo) -> &mut Self { - let &CopyImageInfo { - ref src_image, - src_image_layout, - ref dst_image, - dst_image_layout, - ref regions, - _ne: _, - } = copy_image_info; - - if regions.is_empty() { + if copy_image_info.regions.is_empty() { return self; } @@ -1029,99 +977,31 @@ impl RawRecordingCommandBuffer { if self.device().api_version() >= Version::V1_3 || self.device().enabled_extensions().khr_copy_commands2 { - let regions: SmallVec<[_; 8]> = regions - .iter() - .map(|region| { - let &ImageCopy { - ref src_subresource, - src_offset, - ref dst_subresource, - dst_offset, - extent, - _ne: _, - } = region; - - ash::vk::ImageCopy2 { - src_subresource: src_subresource.into(), - src_offset: ash::vk::Offset3D { - x: src_offset[0] as i32, - y: src_offset[1] as i32, - z: src_offset[2] as i32, - }, - dst_subresource: dst_subresource.into(), - dst_offset: ash::vk::Offset3D { - x: dst_offset[0] as i32, - y: dst_offset[1] as i32, - z: dst_offset[2] as i32, - }, - extent: ash::vk::Extent3D { - width: extent[0], - height: extent[1], - depth: extent[2], - }, - ..Default::default() - } - }) - .collect(); - - let copy_image_info = ash::vk::CopyImageInfo2 { - src_image: src_image.handle(), - src_image_layout: src_image_layout.into(), - dst_image: dst_image.handle(), - dst_image_layout: dst_image_layout.into(), - region_count: regions.len() as u32, - p_regions: regions.as_ptr(), - ..Default::default() - }; + let regions_vk = copy_image_info.to_vk2_regions(); + let copy_image_info_vk = copy_image_info.to_vk2(®ions_vk); if self.device().api_version() >= Version::V1_3 { - (fns.v1_3.cmd_copy_image2)(self.handle(), ©_image_info); + (fns.v1_3.cmd_copy_image2)(self.handle(), ©_image_info_vk); } else { - (fns.khr_copy_commands2.cmd_copy_image2_khr)(self.handle(), ©_image_info); + (fns.khr_copy_commands2.cmd_copy_image2_khr)(self.handle(), ©_image_info_vk); } } else { - let regions: SmallVec<[_; 8]> = regions - .iter() - .map(|region| { - let &ImageCopy { - ref src_subresource, - src_offset, - ref dst_subresource, - dst_offset, - extent, - _ne: _, - } = region; - - ash::vk::ImageCopy { - src_subresource: src_subresource.into(), - src_offset: ash::vk::Offset3D { - x: src_offset[0] as i32, - y: src_offset[1] as i32, - z: src_offset[2] as i32, - }, - dst_subresource: dst_subresource.into(), - dst_offset: ash::vk::Offset3D { - x: dst_offset[0] as i32, - y: dst_offset[1] as i32, - z: dst_offset[2] as i32, - }, - extent: ash::vk::Extent3D { - width: extent[0], - height: extent[1], - depth: extent[2], - }, - } - }) - .collect(); + let regions_vk = copy_image_info.to_vk_regions(); + let CopyImageInfoVk { + src_image_vk, + src_image_layout_vk, + dst_image_vk, + dst_image_layout_vk, + } = copy_image_info.to_vk(); (fns.v1_0.cmd_copy_image)( self.handle(), - src_image.handle(), - src_image_layout.into(), - dst_image.handle(), - dst_image_layout.into(), - regions.len() as u32, - regions.as_ptr(), + src_image_vk, + src_image_layout_vk, + dst_image_vk, + dst_image_layout_vk, + regions_vk.len() as u32, + regions_vk.as_ptr(), ); } @@ -1358,15 +1238,7 @@ impl RawRecordingCommandBuffer { &mut self, copy_buffer_to_image_info: &CopyBufferToImageInfo, ) -> &mut Self { - let &CopyBufferToImageInfo { - ref src_buffer, - ref dst_image, - dst_image_layout, - ref regions, - _ne: _, - } = copy_buffer_to_image_info; - - if regions.is_empty() { + if copy_buffer_to_image_info.regions.is_empty() { return self; } @@ -1375,96 +1247,32 @@ impl RawRecordingCommandBuffer { if self.device().api_version() >= Version::V1_3 || self.device().enabled_extensions().khr_copy_commands2 { - let regions: SmallVec<[_; 8]> = regions - .iter() - .map(|region| { - let &BufferImageCopy { - buffer_offset, - buffer_row_length, - buffer_image_height, - ref image_subresource, - image_offset, - image_extent, - _ne: _, - } = region; - - ash::vk::BufferImageCopy2 { - buffer_offset: buffer_offset + src_buffer.offset(), - buffer_row_length, - buffer_image_height, - image_subresource: image_subresource.into(), - image_offset: ash::vk::Offset3D { - x: image_offset[0] as i32, - y: image_offset[1] as i32, - z: image_offset[2] as i32, - }, - image_extent: ash::vk::Extent3D { - width: image_extent[0], - height: image_extent[1], - depth: image_extent[2], - }, - ..Default::default() - } - }) - .collect(); - - let copy_buffer_to_image_info = ash::vk::CopyBufferToImageInfo2 { - src_buffer: src_buffer.buffer().handle(), - dst_image: dst_image.handle(), - dst_image_layout: dst_image_layout.into(), - region_count: regions.len() as u32, - p_regions: regions.as_ptr(), - ..Default::default() - }; + let regions_vk = copy_buffer_to_image_info.to_vk2_regions(); + let copy_buffer_to_image_info_vk = copy_buffer_to_image_info.to_vk2(®ions_vk); if self.device().api_version() >= Version::V1_3 { - (fns.v1_3.cmd_copy_buffer_to_image2)(self.handle(), ©_buffer_to_image_info); + (fns.v1_3.cmd_copy_buffer_to_image2)(self.handle(), ©_buffer_to_image_info_vk); } else { (fns.khr_copy_commands2.cmd_copy_buffer_to_image2_khr)( self.handle(), - ©_buffer_to_image_info, + ©_buffer_to_image_info_vk, ); } } else { - let regions: SmallVec<[_; 8]> = regions - .iter() - .map(|region| { - let &BufferImageCopy { - buffer_offset, - buffer_row_length, - buffer_image_height, - ref image_subresource, - image_offset, - image_extent, - _ne: _, - } = region; - - ash::vk::BufferImageCopy { - buffer_offset: buffer_offset + src_buffer.offset(), - buffer_row_length, - buffer_image_height, - image_subresource: image_subresource.into(), - image_offset: ash::vk::Offset3D { - x: image_offset[0] as i32, - y: image_offset[1] as i32, - z: image_offset[2] as i32, - }, - image_extent: ash::vk::Extent3D { - width: image_extent[0], - height: image_extent[1], - depth: image_extent[2], - }, - } - }) - .collect(); + let regions_vk = copy_buffer_to_image_info.to_vk_regions(); + let CopyBufferToImageInfoVk { + src_buffer_vk, + dst_image_vk, + dst_image_layout_vk, + } = copy_buffer_to_image_info.to_vk(); (fns.v1_0.cmd_copy_buffer_to_image)( self.handle(), - src_buffer.buffer().handle(), - dst_image.handle(), - dst_image_layout.into(), - regions.len() as u32, - regions.as_ptr(), + src_buffer_vk, + dst_image_vk, + dst_image_layout_vk, + regions_vk.len() as u32, + regions_vk.as_ptr(), ); } @@ -1680,15 +1488,7 @@ impl RawRecordingCommandBuffer { &mut self, copy_image_to_buffer_info: &CopyImageToBufferInfo, ) -> &mut Self { - let &CopyImageToBufferInfo { - ref src_image, - src_image_layout, - ref dst_buffer, - ref regions, - _ne: _, - } = copy_image_to_buffer_info; - - if regions.is_empty() { + if copy_image_to_buffer_info.regions.is_empty() { return self; } @@ -1697,96 +1497,32 @@ impl RawRecordingCommandBuffer { if self.device().api_version() >= Version::V1_3 || self.device().enabled_extensions().khr_copy_commands2 { - let regions: SmallVec<[_; 8]> = regions - .iter() - .map(|region| { - let &BufferImageCopy { - buffer_offset, - buffer_row_length, - buffer_image_height, - ref image_subresource, - image_offset, - image_extent, - _ne: _, - } = region; - - ash::vk::BufferImageCopy2 { - buffer_offset: buffer_offset + dst_buffer.offset(), - buffer_row_length, - buffer_image_height, - image_subresource: image_subresource.into(), - image_offset: ash::vk::Offset3D { - x: image_offset[0] as i32, - y: image_offset[1] as i32, - z: image_offset[2] as i32, - }, - image_extent: ash::vk::Extent3D { - width: image_extent[0], - height: image_extent[1], - depth: image_extent[2], - }, - ..Default::default() - } - }) - .collect(); - - let copy_image_to_buffer_info = ash::vk::CopyImageToBufferInfo2 { - src_image: src_image.handle(), - src_image_layout: src_image_layout.into(), - dst_buffer: dst_buffer.buffer().handle(), - region_count: regions.len() as u32, - p_regions: regions.as_ptr(), - ..Default::default() - }; + let regions_vk = copy_image_to_buffer_info.to_vk2_regions(); + let copy_image_to_buffer_info_vk = copy_image_to_buffer_info.to_vk2(®ions_vk); if self.device().api_version() >= Version::V1_3 { - (fns.v1_3.cmd_copy_image_to_buffer2)(self.handle(), ©_image_to_buffer_info); + (fns.v1_3.cmd_copy_image_to_buffer2)(self.handle(), ©_image_to_buffer_info_vk); } else { (fns.khr_copy_commands2.cmd_copy_image_to_buffer2_khr)( self.handle(), - ©_image_to_buffer_info, + ©_image_to_buffer_info_vk, ); } } else { - let regions: SmallVec<[_; 8]> = regions - .iter() - .map(|region| { - let &BufferImageCopy { - buffer_offset, - buffer_row_length, - buffer_image_height, - ref image_subresource, - image_offset, - image_extent, - _ne: _, - } = region; - - ash::vk::BufferImageCopy { - buffer_offset: buffer_offset + dst_buffer.offset(), - buffer_row_length, - buffer_image_height, - image_subresource: image_subresource.into(), - image_offset: ash::vk::Offset3D { - x: image_offset[0] as i32, - y: image_offset[1] as i32, - z: image_offset[2] as i32, - }, - image_extent: ash::vk::Extent3D { - width: image_extent[0], - height: image_extent[1], - depth: image_extent[2], - }, - } - }) - .collect(); + let regions_vk = copy_image_to_buffer_info.to_vk_regions(); + let CopyImageToBufferInfoVk { + src_image_vk, + src_image_layout_vk, + dst_buffer_vk, + } = copy_image_to_buffer_info.to_vk(); (fns.v1_0.cmd_copy_image_to_buffer)( self.handle(), - src_image.handle(), - src_image_layout.into(), - dst_buffer.buffer().handle(), - regions.len() as u32, - regions.as_ptr(), + src_image_vk, + src_image_layout_vk, + dst_buffer_vk, + regions_vk.len() as u32, + regions_vk.as_ptr(), ); } @@ -1830,17 +1566,7 @@ impl RawRecordingCommandBuffer { #[cfg_attr(not(feature = "document_unchecked"), doc(hidden))] pub unsafe fn blit_image_unchecked(&mut self, blit_image_info: &BlitImageInfo) -> &mut Self { - let &BlitImageInfo { - ref src_image, - src_image_layout, - ref dst_image, - dst_image_layout, - ref regions, - filter, - _ne, - } = blit_image_info; - - if regions.is_empty() { + if blit_image_info.regions.is_empty() { return self; } @@ -1849,117 +1575,33 @@ impl RawRecordingCommandBuffer { if self.device().api_version() >= Version::V1_3 || self.device().enabled_extensions().khr_copy_commands2 { - let regions: SmallVec<[_; 8]> = regions - .iter() - .map(|region| { - let &ImageBlit { - ref src_subresource, - src_offsets, - ref dst_subresource, - dst_offsets, - _ne: _, - } = region; - - ash::vk::ImageBlit2 { - src_subresource: src_subresource.into(), - src_offsets: [ - ash::vk::Offset3D { - x: src_offsets[0][0] as i32, - y: src_offsets[0][1] as i32, - z: src_offsets[0][2] as i32, - }, - ash::vk::Offset3D { - x: src_offsets[1][0] as i32, - y: src_offsets[1][1] as i32, - z: src_offsets[1][2] as i32, - }, - ], - dst_subresource: dst_subresource.into(), - dst_offsets: [ - ash::vk::Offset3D { - x: dst_offsets[0][0] as i32, - y: dst_offsets[0][1] as i32, - z: dst_offsets[0][2] as i32, - }, - ash::vk::Offset3D { - x: dst_offsets[1][0] as i32, - y: dst_offsets[1][1] as i32, - z: dst_offsets[1][2] as i32, - }, - ], - ..Default::default() - } - }) - .collect(); - - let blit_image_info = ash::vk::BlitImageInfo2 { - src_image: src_image.handle(), - src_image_layout: src_image_layout.into(), - dst_image: dst_image.handle(), - dst_image_layout: dst_image_layout.into(), - region_count: regions.len() as u32, - p_regions: regions.as_ptr(), - filter: filter.into(), - ..Default::default() - }; + let regions_vk = blit_image_info.to_vk2_regions(); + let blit_image_info_vk = blit_image_info.to_vk2(®ions_vk); if self.device().api_version() >= Version::V1_3 { - (fns.v1_3.cmd_blit_image2)(self.handle(), &blit_image_info); + (fns.v1_3.cmd_blit_image2)(self.handle(), &blit_image_info_vk); } else { - (fns.khr_copy_commands2.cmd_blit_image2_khr)(self.handle(), &blit_image_info); + (fns.khr_copy_commands2.cmd_blit_image2_khr)(self.handle(), &blit_image_info_vk); } } else { - let regions: SmallVec<[_; 8]> = regions - .iter() - .map(|region| { - let &ImageBlit { - ref src_subresource, - src_offsets, - ref dst_subresource, - dst_offsets, - _ne: _, - } = region; - - ash::vk::ImageBlit { - src_subresource: src_subresource.into(), - src_offsets: [ - ash::vk::Offset3D { - x: src_offsets[0][0] as i32, - y: src_offsets[0][1] as i32, - z: src_offsets[0][2] as i32, - }, - ash::vk::Offset3D { - x: src_offsets[1][0] as i32, - y: src_offsets[1][1] as i32, - z: src_offsets[1][2] as i32, - }, - ], - dst_subresource: dst_subresource.into(), - dst_offsets: [ - ash::vk::Offset3D { - x: dst_offsets[0][0] as i32, - y: dst_offsets[0][1] as i32, - z: dst_offsets[0][2] as i32, - }, - ash::vk::Offset3D { - x: dst_offsets[1][0] as i32, - y: dst_offsets[1][1] as i32, - z: dst_offsets[1][2] as i32, - }, - ], - } - }) - .collect(); + let regions_vk = blit_image_info.to_vk_regions(); + let BlitImageInfoVk { + src_image_vk, + src_image_layout_vk, + dst_image_vk, + dst_image_layout_vk, + filter_vk, + } = blit_image_info.to_vk(); (fns.v1_0.cmd_blit_image)( self.handle(), - src_image.handle(), - src_image_layout.into(), - dst_image.handle(), - dst_image_layout.into(), - regions.len() as u32, - regions.as_ptr(), - filter.into(), + src_image_vk, + src_image_layout_vk, + dst_image_vk, + dst_image_layout_vk, + regions_vk.len() as u32, + regions_vk.as_ptr(), + filter_vk, ); } @@ -2006,16 +1648,7 @@ impl RawRecordingCommandBuffer { &mut self, resolve_image_info: &ResolveImageInfo, ) -> &mut Self { - let &ResolveImageInfo { - ref src_image, - src_image_layout, - ref dst_image, - dst_image_layout, - ref regions, - _ne: _, - } = resolve_image_info; - - if regions.is_empty() { + if resolve_image_info.regions.is_empty() { return self; } @@ -2024,99 +1657,34 @@ impl RawRecordingCommandBuffer { if self.device().api_version() >= Version::V1_3 || self.device().enabled_extensions().khr_copy_commands2 { - let regions: SmallVec<[_; 8]> = regions - .iter() - .map(|region| { - let &ImageResolve { - ref src_subresource, - src_offset, - ref dst_subresource, - dst_offset, - extent, - _ne: _, - } = region; - - ash::vk::ImageResolve2 { - src_subresource: src_subresource.into(), - src_offset: ash::vk::Offset3D { - x: src_offset[0] as i32, - y: src_offset[1] as i32, - z: src_offset[2] as i32, - }, - dst_subresource: dst_subresource.into(), - dst_offset: ash::vk::Offset3D { - x: dst_offset[0] as i32, - y: dst_offset[1] as i32, - z: dst_offset[2] as i32, - }, - extent: ash::vk::Extent3D { - width: extent[0], - height: extent[1], - depth: extent[2], - }, - ..Default::default() - } - }) - .collect(); - - let resolve_image_info = ash::vk::ResolveImageInfo2 { - src_image: src_image.handle(), - src_image_layout: src_image_layout.into(), - dst_image: dst_image.handle(), - dst_image_layout: dst_image_layout.into(), - region_count: regions.len() as u32, - p_regions: regions.as_ptr(), - ..Default::default() - }; + let regions_vk = resolve_image_info.to_vk2_regions(); + let resolve_image_info_vk = resolve_image_info.to_vk2(®ions_vk); if self.device().api_version() >= Version::V1_3 { - (fns.v1_3.cmd_resolve_image2)(self.handle(), &resolve_image_info); + (fns.v1_3.cmd_resolve_image2)(self.handle(), &resolve_image_info_vk); } else { - (fns.khr_copy_commands2.cmd_resolve_image2_khr)(self.handle(), &resolve_image_info); + (fns.khr_copy_commands2.cmd_resolve_image2_khr)( + self.handle(), + &resolve_image_info_vk, + ); } } else { - let regions: SmallVec<[_; 8]> = regions - .iter() - .map(|region| { - let ImageResolve { - ref src_subresource, - src_offset, - ref dst_subresource, - dst_offset, - extent, - _ne: _, - } = region; - - ash::vk::ImageResolve { - src_subresource: src_subresource.into(), - src_offset: ash::vk::Offset3D { - x: src_offset[0] as i32, - y: src_offset[1] as i32, - z: src_offset[2] as i32, - }, - dst_subresource: dst_subresource.into(), - dst_offset: ash::vk::Offset3D { - x: dst_offset[0] as i32, - y: dst_offset[1] as i32, - z: dst_offset[2] as i32, - }, - extent: ash::vk::Extent3D { - width: extent[0], - height: extent[1], - depth: extent[2], - }, - } - }) - .collect(); + let regions_vk = resolve_image_info.to_vk_regions(); + let ResolveImageInfoVk { + src_image_vk, + src_image_layout_vk, + dst_image_vk, + dst_image_layout_vk, + } = resolve_image_info.to_vk(); (fns.v1_0.cmd_resolve_image)( self.handle(), - src_image.handle(), - src_image_layout.into(), - dst_image.handle(), - dst_image_layout.into(), - regions.len() as u32, - regions.as_ptr(), + src_image_vk, + src_image_layout_vk, + dst_image_vk, + dst_image_layout_vk, + regions_vk.len() as u32, + regions_vk.as_ptr(), ); } @@ -2289,6 +1857,80 @@ impl CopyBufferInfo { Ok(()) } + + pub(crate) fn to_vk2<'a>( + &self, + regions_vk: &'a [ash::vk::BufferCopy2<'static>], + ) -> ash::vk::CopyBufferInfo2<'a> { + let &Self { + ref src_buffer, + ref dst_buffer, + regions: _, + _ne: _, + } = self; + + ash::vk::CopyBufferInfo2::default() + .src_buffer(src_buffer.buffer().handle()) + .dst_buffer(dst_buffer.buffer().handle()) + .regions(regions_vk) + } + + pub(crate) fn to_vk2_regions(&self) -> SmallVec<[ash::vk::BufferCopy2<'static>; 8]> { + let &Self { + ref src_buffer, + ref dst_buffer, + ref regions, + _ne: _, + } = self; + + regions + .iter() + .map(|region| { + let mut region_vk = region.to_vk2(); + region_vk.src_offset += src_buffer.offset(); + region_vk.dst_offset += dst_buffer.offset(); + region_vk + }) + .collect() + } + + pub(crate) fn to_vk(&self) -> CopyBufferInfoVk { + let &Self { + ref src_buffer, + ref dst_buffer, + regions: _, + _ne: _, + } = self; + + CopyBufferInfoVk { + src_buffer_vk: src_buffer.buffer().handle(), + dst_buffer_vk: dst_buffer.buffer().handle(), + } + } + + pub(crate) fn to_vk_regions(&self) -> SmallVec<[ash::vk::BufferCopy; 8]> { + let &Self { + ref src_buffer, + ref dst_buffer, + ref regions, + _ne: _, + } = self; + + regions + .iter() + .map(|region| { + let mut region_vk = region.to_vk(); + region_vk.src_offset += src_buffer.offset(); + region_vk.dst_offset += dst_buffer.offset(); + region_vk + }) + .collect() + } +} + +pub(crate) struct CopyBufferInfoVk { + pub(crate) src_buffer_vk: ash::vk::Buffer, + pub(crate) dst_buffer_vk: ash::vk::Buffer, } /// Parameters to copy data from a buffer to another buffer, with type information. @@ -2411,6 +2053,35 @@ impl BufferCopy { Ok(()) } + + pub(crate) fn to_vk2(&self) -> ash::vk::BufferCopy2<'static> { + let &Self { + src_offset, + dst_offset, + size, + _ne, + } = self; + + ash::vk::BufferCopy2::default() + .src_offset(src_offset) + .dst_offset(dst_offset) + .size(size) + } + + pub(crate) fn to_vk(&self) -> ash::vk::BufferCopy { + let &Self { + src_offset, + dst_offset, + size, + _ne, + } = self; + + ash::vk::BufferCopy { + src_offset, + dst_offset, + size, + } + } } /// Parameters to copy data from an image to another image. @@ -3669,6 +3340,60 @@ impl CopyImageInfo { Ok(()) } + + pub(crate) fn to_vk2<'a>( + &self, + regions_vk: &'a [ash::vk::ImageCopy2<'static>], + ) -> ash::vk::CopyImageInfo2<'a> { + let &Self { + ref src_image, + src_image_layout, + ref dst_image, + dst_image_layout, + regions: _, + _ne: _, + } = self; + + ash::vk::CopyImageInfo2::default() + .src_image(src_image.handle()) + .src_image_layout(src_image_layout.into()) + .dst_image(dst_image.handle()) + .dst_image_layout(dst_image_layout.into()) + .regions(regions_vk) + } + + pub(crate) fn to_vk2_regions(&self) -> SmallVec<[ash::vk::ImageCopy2<'static>; 8]> { + self.regions.iter().map(ImageCopy::to_vk2).collect() + } + + pub(crate) fn to_vk(&self) -> CopyImageInfoVk { + let &Self { + ref src_image, + src_image_layout, + ref dst_image, + dst_image_layout, + regions: _, + _ne: _, + } = self; + + CopyImageInfoVk { + src_image_vk: src_image.handle(), + src_image_layout_vk: src_image_layout.into(), + dst_image_vk: dst_image.handle(), + dst_image_layout_vk: dst_image_layout.into(), + } + } + + pub(crate) fn to_vk_regions(&self) -> SmallVec<[ash::vk::ImageCopy; 8]> { + self.regions.iter().map(ImageCopy::to_vk).collect() + } +} + +pub(crate) struct CopyImageInfoVk { + pub(crate) src_image_vk: ash::vk::Image, + pub(crate) src_image_layout_vk: ash::vk::ImageLayout, + pub(crate) dst_image_vk: ash::vk::Image, + pub(crate) dst_image_layout_vk: ash::vk::ImageLayout, } /// A region of data to copy between images. @@ -3797,6 +3522,67 @@ impl ImageCopy { Ok(()) } + + pub(crate) fn to_vk2(&self) -> ash::vk::ImageCopy2<'static> { + let &Self { + ref src_subresource, + src_offset, + ref dst_subresource, + dst_offset, + extent, + _ne: _, + } = self; + + ash::vk::ImageCopy2::default() + .src_subresource(src_subresource.to_vk()) + .src_offset(ash::vk::Offset3D { + x: src_offset[0] as i32, + y: src_offset[1] as i32, + z: src_offset[2] as i32, + }) + .dst_subresource(dst_subresource.to_vk()) + .dst_offset(ash::vk::Offset3D { + x: dst_offset[0] as i32, + y: dst_offset[1] as i32, + z: dst_offset[2] as i32, + }) + .extent(ash::vk::Extent3D { + width: extent[0], + height: extent[1], + depth: extent[2], + }) + } + + pub(crate) fn to_vk(&self) -> ash::vk::ImageCopy { + let &Self { + ref src_subresource, + src_offset, + ref dst_subresource, + dst_offset, + extent, + _ne: _, + } = self; + + ash::vk::ImageCopy { + src_subresource: src_subresource.to_vk(), + src_offset: ash::vk::Offset3D { + x: src_offset[0] as i32, + y: src_offset[1] as i32, + z: src_offset[2] as i32, + }, + dst_subresource: dst_subresource.to_vk(), + dst_offset: ash::vk::Offset3D { + x: dst_offset[0] as i32, + y: dst_offset[1] as i32, + z: dst_offset[2] as i32, + }, + extent: ash::vk::Extent3D { + width: extent[0], + height: extent[1], + depth: extent[2], + }, + } + } } /// Parameters to copy data from a buffer to an image. @@ -4406,6 +4192,81 @@ impl CopyBufferToImageInfo { Ok(()) } + + pub(crate) fn to_vk2<'a>( + &self, + regions_vk: &'a [ash::vk::BufferImageCopy2<'static>], + ) -> ash::vk::CopyBufferToImageInfo2<'a> { + let &Self { + ref src_buffer, + ref dst_image, + dst_image_layout, + regions: _, + _ne: _, + } = self; + + ash::vk::CopyBufferToImageInfo2::default() + .src_buffer(src_buffer.buffer().handle()) + .dst_image(dst_image.handle()) + .dst_image_layout(dst_image_layout.into()) + .regions(regions_vk) + } + + pub(crate) fn to_vk2_regions(&self) -> SmallVec<[ash::vk::BufferImageCopy2<'static>; 8]> { + let Self { + src_buffer, + regions, + .. + } = self; + + regions + .iter() + .map(|region| { + let mut region_vk = region.to_vk2(); + region_vk.buffer_offset += src_buffer.offset(); + region_vk + }) + .collect() + } + + pub(crate) fn to_vk(&self) -> CopyBufferToImageInfoVk { + let &Self { + ref src_buffer, + ref dst_image, + dst_image_layout, + regions: _, + _ne: _, + } = self; + + CopyBufferToImageInfoVk { + src_buffer_vk: src_buffer.buffer().handle(), + dst_image_vk: dst_image.handle(), + dst_image_layout_vk: dst_image_layout.into(), + } + } + + pub(crate) fn to_vk_regions(&self) -> SmallVec<[ash::vk::BufferImageCopy; 8]> { + let Self { + src_buffer, + regions, + .. + } = self; + + regions + .iter() + .map(|region| { + let mut region_vk = region.to_vk(); + region_vk.buffer_offset += src_buffer.offset(); + region_vk + }) + .collect() + } +} + +pub(crate) struct CopyBufferToImageInfoVk { + pub(crate) src_buffer_vk: ash::vk::Buffer, + pub(crate) dst_image_vk: ash::vk::Image, + pub(crate) dst_image_layout_vk: ash::vk::ImageLayout, } /// Parameters to copy data from an image to a buffer. @@ -5012,6 +4873,81 @@ impl CopyImageToBufferInfo { Ok(()) } + + pub(crate) fn to_vk2<'a>( + &self, + regions_vk: &'a [ash::vk::BufferImageCopy2<'static>], + ) -> ash::vk::CopyImageToBufferInfo2<'a> { + let &Self { + ref src_image, + src_image_layout, + ref dst_buffer, + regions: _, + _ne: _, + } = self; + + ash::vk::CopyImageToBufferInfo2::default() + .src_image(src_image.handle()) + .src_image_layout(src_image_layout.into()) + .dst_buffer(dst_buffer.buffer().handle()) + .regions(regions_vk) + } + + pub(crate) fn to_vk2_regions(&self) -> SmallVec<[ash::vk::BufferImageCopy2<'static>; 8]> { + let Self { + dst_buffer, + regions, + .. + } = self; + + regions + .iter() + .map(|region| { + let mut region_vk = region.to_vk2(); + region_vk.buffer_offset += dst_buffer.offset(); + region_vk + }) + .collect() + } + + pub(crate) fn to_vk(&self) -> CopyImageToBufferInfoVk { + let &Self { + ref src_image, + src_image_layout, + ref dst_buffer, + regions: _, + _ne: _, + } = self; + + CopyImageToBufferInfoVk { + src_image_vk: src_image.handle(), + src_image_layout_vk: src_image_layout.into(), + dst_buffer_vk: dst_buffer.buffer().handle(), + } + } + + pub(crate) fn to_vk_regions(&self) -> SmallVec<[ash::vk::BufferImageCopy; 8]> { + let Self { + dst_buffer, + regions, + .. + } = self; + + regions + .iter() + .map(|region| { + let mut region_vk = region.to_vk(); + region_vk.buffer_offset += dst_buffer.offset(); + region_vk + }) + .collect() + } +} + +pub(crate) struct CopyImageToBufferInfoVk { + pub(crate) src_image_vk: ash::vk::Image, + pub(crate) src_image_layout_vk: ash::vk::ImageLayout, + pub(crate) dst_buffer_vk: ash::vk::Buffer, } /// A region of data to copy between a buffer and an image. @@ -5193,6 +5129,63 @@ impl BufferImageCopy { Ok(()) } + + pub(crate) fn to_vk2(&self) -> ash::vk::BufferImageCopy2<'static> { + let &Self { + buffer_offset, + buffer_row_length, + buffer_image_height, + ref image_subresource, + image_offset, + image_extent, + _ne: _, + } = self; + + ash::vk::BufferImageCopy2::default() + .buffer_offset(buffer_offset) + .buffer_row_length(buffer_row_length) + .buffer_image_height(buffer_image_height) + .image_subresource(image_subresource.to_vk()) + .image_offset(ash::vk::Offset3D { + x: image_offset[0] as i32, + y: image_offset[1] as i32, + z: image_offset[2] as i32, + }) + .image_extent(ash::vk::Extent3D { + width: image_extent[0], + height: image_extent[1], + depth: image_extent[2], + }) + } + + pub(crate) fn to_vk(&self) -> ash::vk::BufferImageCopy { + let &Self { + buffer_offset, + buffer_row_length, + buffer_image_height, + ref image_subresource, + image_offset, + image_extent, + _ne: _, + } = self; + + ash::vk::BufferImageCopy { + buffer_offset, + buffer_row_length, + buffer_image_height, + image_subresource: image_subresource.to_vk(), + image_offset: ash::vk::Offset3D { + x: image_offset[0] as i32, + y: image_offset[1] as i32, + z: image_offset[2] as i32, + }, + image_extent: ash::vk::Extent3D { + width: image_extent[0], + height: image_extent[1], + depth: image_extent[2], + }, + } + } } /// Parameters to blit image data. @@ -6004,6 +5997,65 @@ impl BlitImageInfo { Ok(()) } + + pub(crate) fn to_vk2<'a>( + &self, + regions_vk: &'a [ash::vk::ImageBlit2<'static>], + ) -> ash::vk::BlitImageInfo2<'a> { + let &Self { + ref src_image, + src_image_layout, + ref dst_image, + dst_image_layout, + regions: _, + filter, + _ne: _, + } = self; + + ash::vk::BlitImageInfo2::default() + .src_image(src_image.handle()) + .src_image_layout(src_image_layout.into()) + .dst_image(dst_image.handle()) + .dst_image_layout(dst_image_layout.into()) + .regions(regions_vk) + .filter(filter.into()) + } + + pub(crate) fn to_vk2_regions(&self) -> SmallVec<[ash::vk::ImageBlit2<'static>; 8]> { + self.regions.iter().map(ImageBlit::to_vk2).collect() + } + + pub(crate) fn to_vk(&self) -> BlitImageInfoVk { + let &Self { + ref src_image, + src_image_layout, + ref dst_image, + dst_image_layout, + regions: _, + filter, + _ne: _, + } = self; + + BlitImageInfoVk { + src_image_vk: src_image.handle(), + src_image_layout_vk: src_image_layout.into(), + dst_image_vk: dst_image.handle(), + dst_image_layout_vk: dst_image_layout.into(), + filter_vk: filter.into(), + } + } + + pub(crate) fn to_vk_regions(&self) -> SmallVec<[ash::vk::ImageBlit; 8]> { + self.regions.iter().map(ImageBlit::to_vk).collect() + } +} + +pub(crate) struct BlitImageInfoVk { + pub(crate) src_image_vk: ash::vk::Image, + pub(crate) src_image_layout_vk: ash::vk::ImageLayout, + pub(crate) dst_image_vk: ash::vk::Image, + pub(crate) dst_image_layout_vk: ash::vk::ImageLayout, + pub(crate) filter_vk: ash::vk::Filter, } /// A region of data to blit between images. @@ -6098,6 +6150,83 @@ impl ImageBlit { Ok(()) } + + pub(crate) fn to_vk2(&self) -> ash::vk::ImageBlit2<'static> { + let &Self { + ref src_subresource, + src_offsets, + ref dst_subresource, + dst_offsets, + _ne: _, + } = self; + + ash::vk::ImageBlit2::default() + .src_subresource(src_subresource.to_vk()) + .src_offsets([ + ash::vk::Offset3D { + x: src_offsets[0][0] as i32, + y: src_offsets[0][1] as i32, + z: src_offsets[0][2] as i32, + }, + ash::vk::Offset3D { + x: src_offsets[1][0] as i32, + y: src_offsets[1][1] as i32, + z: src_offsets[1][2] as i32, + }, + ]) + .dst_subresource(dst_subresource.to_vk()) + .dst_offsets([ + ash::vk::Offset3D { + x: dst_offsets[0][0] as i32, + y: dst_offsets[0][1] as i32, + z: dst_offsets[0][2] as i32, + }, + ash::vk::Offset3D { + x: dst_offsets[1][0] as i32, + y: dst_offsets[1][1] as i32, + z: dst_offsets[1][2] as i32, + }, + ]) + } + + pub(crate) fn to_vk(&self) -> ash::vk::ImageBlit { + let &Self { + ref src_subresource, + src_offsets, + ref dst_subresource, + dst_offsets, + _ne: _, + } = self; + + ash::vk::ImageBlit { + src_subresource: src_subresource.to_vk(), + src_offsets: [ + ash::vk::Offset3D { + x: src_offsets[0][0] as i32, + y: src_offsets[0][1] as i32, + z: src_offsets[0][2] as i32, + }, + ash::vk::Offset3D { + x: src_offsets[1][0] as i32, + y: src_offsets[1][1] as i32, + z: src_offsets[1][2] as i32, + }, + ], + dst_subresource: dst_subresource.to_vk(), + dst_offsets: [ + ash::vk::Offset3D { + x: dst_offsets[0][0] as i32, + y: dst_offsets[0][1] as i32, + z: dst_offsets[0][2] as i32, + }, + ash::vk::Offset3D { + x: dst_offsets[1][0] as i32, + y: dst_offsets[1][1] as i32, + z: dst_offsets[1][2] as i32, + }, + ], + } + } } /// Parameters to resolve image data. @@ -6686,6 +6815,60 @@ impl ResolveImageInfo { Ok(()) } + + pub(crate) fn to_vk2<'a>( + &self, + regions_vk: &'a [ash::vk::ImageResolve2<'static>], + ) -> ash::vk::ResolveImageInfo2<'a> { + let &Self { + ref src_image, + src_image_layout, + ref dst_image, + dst_image_layout, + regions: _, + _ne: _, + } = self; + + ash::vk::ResolveImageInfo2::default() + .src_image(src_image.handle()) + .src_image_layout(src_image_layout.into()) + .dst_image(dst_image.handle()) + .dst_image_layout(dst_image_layout.into()) + .regions(regions_vk) + } + + pub(crate) fn to_vk2_regions(&self) -> SmallVec<[ash::vk::ImageResolve2<'static>; 8]> { + self.regions.iter().map(ImageResolve::to_vk2).collect() + } + + pub(crate) fn to_vk(&self) -> ResolveImageInfoVk { + let &Self { + ref src_image, + src_image_layout, + ref dst_image, + dst_image_layout, + regions: _, + _ne: _, + } = self; + + ResolveImageInfoVk { + src_image_vk: src_image.handle(), + src_image_layout_vk: src_image_layout.into(), + dst_image_vk: dst_image.handle(), + dst_image_layout_vk: dst_image_layout.into(), + } + } + + pub(crate) fn to_vk_regions(&self) -> SmallVec<[ash::vk::ImageResolve; 8]> { + self.regions.iter().map(ImageResolve::to_vk).collect() + } +} + +pub(crate) struct ResolveImageInfoVk { + pub(crate) src_image_vk: ash::vk::Image, + pub(crate) src_image_layout_vk: ash::vk::ImageLayout, + pub(crate) dst_image_vk: ash::vk::Image, + pub(crate) dst_image_layout_vk: ash::vk::ImageLayout, } /// A region of data to resolve between images. @@ -6788,6 +6971,67 @@ impl ImageResolve { Ok(()) } + + pub(crate) fn to_vk2(&self) -> ash::vk::ImageResolve2<'static> { + let &Self { + ref src_subresource, + src_offset, + ref dst_subresource, + dst_offset, + extent, + _ne: _, + } = self; + + ash::vk::ImageResolve2::default() + .src_subresource(src_subresource.to_vk()) + .src_offset(ash::vk::Offset3D { + x: src_offset[0] as i32, + y: src_offset[1] as i32, + z: src_offset[2] as i32, + }) + .dst_subresource(dst_subresource.to_vk()) + .dst_offset(ash::vk::Offset3D { + x: dst_offset[0] as i32, + y: dst_offset[1] as i32, + z: dst_offset[2] as i32, + }) + .extent(ash::vk::Extent3D { + width: extent[0], + height: extent[1], + depth: extent[2], + }) + } + + pub(crate) fn to_vk(&self) -> ash::vk::ImageResolve { + let &Self { + ref src_subresource, + src_offset, + ref dst_subresource, + dst_offset, + extent, + _ne: _, + } = self; + + ash::vk::ImageResolve { + src_subresource: src_subresource.to_vk(), + src_offset: ash::vk::Offset3D { + x: src_offset[0] as i32, + y: src_offset[1] as i32, + z: src_offset[2] as i32, + }, + dst_subresource: dst_subresource.to_vk(), + dst_offset: ash::vk::Offset3D { + x: dst_offset[0] as i32, + y: dst_offset[1] as i32, + z: dst_offset[2] as i32, + }, + extent: ash::vk::Extent3D { + width: extent[0], + height: extent[1], + depth: extent[2], + }, + } + } } #[cfg(test)] diff --git a/vulkano/src/command_buffer/commands/debug.rs b/vulkano/src/command_buffer/commands/debug.rs index 5fa33414..dba8a044 100644 --- a/vulkano/src/command_buffer/commands/debug.rs +++ b/vulkano/src/command_buffer/commands/debug.rs @@ -4,7 +4,6 @@ use crate::{ instance::debug::DebugUtilsLabel, Requires, RequiresAllOf, RequiresOneOf, ValidationError, VulkanObject, }; -use std::ffi::CString; /// # Commands for debugging. /// @@ -170,21 +169,11 @@ impl RawRecordingCommandBuffer { &mut self, label_info: &DebugUtilsLabel, ) -> &mut Self { - let &DebugUtilsLabel { - ref label_name, - color, - _ne: _, - } = label_info; - - let label_name_vk = CString::new(label_name.as_str()).unwrap(); - let label_info = ash::vk::DebugUtilsLabelEXT { - p_label_name: label_name_vk.as_ptr(), - color, - ..Default::default() - }; + let label_info_fields1_vk = label_info.to_vk_fields1(); + let label_info_vk = label_info.to_vk(&label_info_fields1_vk); let fns = self.device().fns(); - (fns.ext_debug_utils.cmd_begin_debug_utils_label_ext)(self.handle(), &label_info); + (fns.ext_debug_utils.cmd_begin_debug_utils_label_ext)(self.handle(), &label_info_vk); self } @@ -286,21 +275,11 @@ impl RawRecordingCommandBuffer { &mut self, label_info: &DebugUtilsLabel, ) -> &mut Self { - let &DebugUtilsLabel { - ref label_name, - color, - _ne: _, - } = label_info; - - let label_name_vk = CString::new(label_name.as_str()).unwrap(); - let label_info = ash::vk::DebugUtilsLabelEXT { - p_label_name: label_name_vk.as_ptr(), - color, - ..Default::default() - }; + let label_info_fields1_vk = label_info.to_vk_fields1(); + let label_info_vk = label_info.to_vk(&label_info_fields1_vk); let fns = self.device().fns(); - (fns.ext_debug_utils.cmd_insert_debug_utils_label_ext)(self.handle(), &label_info); + (fns.ext_debug_utils.cmd_insert_debug_utils_label_ext)(self.handle(), &label_info_vk); self } diff --git a/vulkano/src/command_buffer/commands/dynamic_state.rs b/vulkano/src/command_buffer/commands/dynamic_state.rs index c95f18cc..b01b350a 100644 --- a/vulkano/src/command_buffer/commands/dynamic_state.rs +++ b/vulkano/src/command_buffer/commands/dynamic_state.rs @@ -4,14 +4,12 @@ use crate::{ pipeline::{ graphics::{ color_blend::LogicOp, - conservative_rasterization::ConservativeRasterizationMode, depth_stencil::{CompareOp, StencilFaces, StencilOp, StencilOps}, input_assembly::PrimitiveTopology, - rasterization::{CullMode, DepthBiasState, FrontFace, LineStipple}, - vertex_input::{ - VertexInputAttributeDescription, VertexInputBindingDescription, VertexInputRate, - VertexInputState, + rasterization::{ + ConservativeRasterizationMode, CullMode, DepthBiasState, FrontFace, LineStipple, }, + vertex_input::VertexInputState, viewport::{Scissor, Viewport}, }, DynamicState, @@ -1367,21 +1365,21 @@ impl RawRecordingCommandBuffer { #[cfg_attr(not(feature = "document_unchecked"), doc(hidden))] pub unsafe fn set_color_write_enable_unchecked(&mut self, enables: &[bool]) -> &mut Self { - let enables = enables + let enables_vk = enables .iter() .copied() .map(|v| v as ash::vk::Bool32) .collect::>(); - if enables.is_empty() { + if enables_vk.is_empty() { return self; } let fns = self.device().fns(); (fns.ext_color_write_enable.cmd_set_color_write_enable_ext)( self.handle(), - enables.len() as u32, - enables.as_ptr(), + enables_vk.len() as u32, + enables_vk.as_ptr(), ); self @@ -1924,7 +1922,7 @@ impl RawRecordingCommandBuffer { ) -> &mut Self { let rectangles = rectangles .iter() - .map(|v| v.into()) + .map(|v| v.to_vk()) .collect::>(); if rectangles.is_empty() { return self; @@ -2537,7 +2535,7 @@ impl RawRecordingCommandBuffer { ) -> &mut Self { let scissors = scissors .iter() - .map(ash::vk::Rect2D::from) + .map(|s| s.to_vk()) .collect::>(); if scissors.is_empty() { return self; @@ -2623,7 +2621,7 @@ impl RawRecordingCommandBuffer { pub unsafe fn set_scissor_with_count_unchecked(&mut self, scissors: &[Scissor]) -> &mut Self { let scissors = scissors .iter() - .map(ash::vk::Rect2D::from) + .map(|s| s.to_vk()) .collect::>(); if scissors.is_empty() { return self; @@ -3029,46 +3027,17 @@ impl RawRecordingCommandBuffer { _ne: _, } = vertex_input_state; - vertex_binding_descriptions_vk.extend(bindings.iter().map(|(&binding, binding_desc)| { - let &VertexInputBindingDescription { - stride, - input_rate, - _ne: _, - } = binding_desc; + vertex_binding_descriptions_vk.extend( + bindings + .iter() + .map(|(&binding, binding_desc)| binding_desc.to_vk2(binding)), + ); - let divisor = match input_rate { - // VUID-VkVertexInputBindingDescription2EXT-divisor-06227 - VertexInputRate::Vertex => 1, - VertexInputRate::Instance { divisor } => divisor, - }; - - ash::vk::VertexInputBindingDescription2EXT { - binding, - stride, - input_rate: input_rate.into(), - divisor, - ..Default::default() - } - })); - - vertex_attribute_descriptions_vk.extend(attributes.iter().map( - |(&location, attribute_desc)| { - let &VertexInputAttributeDescription { - binding, - format, - offset, - _ne: _, - } = attribute_desc; - - ash::vk::VertexInputAttributeDescription2EXT { - location, - binding, - format: format.into(), - offset, - ..Default::default() - } - }, - )); + vertex_attribute_descriptions_vk.extend( + attributes + .iter() + .map(|(&location, attribute_desc)| attribute_desc.to_vk2(location)), + ); let fns = self.device().fns(); (fns.ext_vertex_input_dynamic_state.cmd_set_vertex_input_ext)( @@ -3158,7 +3127,7 @@ impl RawRecordingCommandBuffer { ) -> &mut Self { let viewports = viewports .iter() - .map(|v| v.into()) + .map(|v| v.to_vk()) .collect::>(); if viewports.is_empty() { return self; @@ -3247,7 +3216,7 @@ impl RawRecordingCommandBuffer { ) -> &mut Self { let viewports = viewports .iter() - .map(|v| v.into()) + .map(|v| v.to_vk()) .collect::>(); if viewports.is_empty() { return self; diff --git a/vulkano/src/command_buffer/commands/render_pass.rs b/vulkano/src/command_buffer/commands/render_pass.rs index 48ebd3ca..6b04d278 100644 --- a/vulkano/src/command_buffer/commands/render_pass.rs +++ b/vulkano/src/command_buffer/commands/render_pass.rs @@ -1246,45 +1246,11 @@ impl RawRecordingCommandBuffer { render_pass_begin_info: &RenderPassBeginInfo, subpass_begin_info: &SubpassBeginInfo, ) -> &mut Self { - let &RenderPassBeginInfo { - ref render_pass, - ref framebuffer, - render_area_offset, - render_area_extent, - ref clear_values, - _ne: _, - } = render_pass_begin_info; + let render_pass_begin_info_fields1_vk = render_pass_begin_info.to_vk_fields1(); + let render_pass_begin_info_vk = + render_pass_begin_info.to_vk(&render_pass_begin_info_fields1_vk); - let clear_values_vk: SmallVec<[_; 4]> = clear_values - .iter() - .copied() - .map(|clear_value| clear_value.map(Into::into).unwrap_or_default()) - .collect(); - - let render_pass_begin_info = ash::vk::RenderPassBeginInfo { - render_pass: render_pass.handle(), - framebuffer: framebuffer.handle(), - render_area: ash::vk::Rect2D { - offset: ash::vk::Offset2D { - x: render_area_offset[0] as i32, - y: render_area_offset[1] as i32, - }, - extent: ash::vk::Extent2D { - width: render_area_extent[0], - height: render_area_extent[1], - }, - }, - clear_value_count: clear_values_vk.len() as u32, - p_clear_values: clear_values_vk.as_ptr(), - ..Default::default() - }; - - let &SubpassBeginInfo { contents, _ne: _ } = subpass_begin_info; - - let subpass_begin_info = ash::vk::SubpassBeginInfo { - contents: contents.into(), - ..Default::default() - }; + let subpass_begin_info_vk = subpass_begin_info.to_vk(); let fns = self.device().fns(); @@ -1294,23 +1260,23 @@ impl RawRecordingCommandBuffer { if self.device().api_version() >= Version::V1_2 { (fns.v1_2.cmd_begin_render_pass2)( self.handle(), - &render_pass_begin_info, - &subpass_begin_info, + &render_pass_begin_info_vk, + &subpass_begin_info_vk, ); } else { (fns.khr_create_renderpass2.cmd_begin_render_pass2_khr)( self.handle(), - &render_pass_begin_info, - &subpass_begin_info, + &render_pass_begin_info_vk, + &subpass_begin_info_vk, ); } } else { - debug_assert!(subpass_begin_info.p_next.is_null()); + debug_assert!(subpass_begin_info_vk.p_next.is_null()); (fns.v1_0.cmd_begin_render_pass)( self.handle(), - &render_pass_begin_info, - subpass_begin_info.contents, + &render_pass_begin_info_vk, + subpass_begin_info_vk.contents, ); } @@ -1374,16 +1340,8 @@ impl RawRecordingCommandBuffer { ) -> &mut Self { let fns = self.device().fns(); - let &SubpassEndInfo { _ne: _ } = subpass_end_info; - - let subpass_end_info_vk = ash::vk::SubpassEndInfo::default(); - - let &SubpassBeginInfo { contents, _ne: _ } = subpass_begin_info; - - let subpass_begin_info_vk = ash::vk::SubpassBeginInfo { - contents: contents.into(), - ..Default::default() - }; + let subpass_end_info_vk = subpass_end_info.to_vk(); + let subpass_begin_info_vk = subpass_begin_info.to_vk(); if self.device().api_version() >= Version::V1_2 || self.device().enabled_extensions().khr_create_renderpass2 @@ -1459,12 +1417,10 @@ impl RawRecordingCommandBuffer { &mut self, subpass_end_info: &SubpassEndInfo, ) -> &mut Self { + let subpass_end_info_vk = subpass_end_info.to_vk(); + let fns = self.device().fns(); - let &SubpassEndInfo { _ne: _ } = subpass_end_info; - - let subpass_end_info_vk = ash::vk::SubpassEndInfo::default(); - if self.device().api_version() >= Version::V1_2 || self.device().enabled_extensions().khr_create_renderpass2 { @@ -1561,98 +1517,15 @@ impl RawRecordingCommandBuffer { &mut self, rendering_info: &RenderingInfo, ) -> &mut Self { - let &RenderingInfo { - render_area_offset, - render_area_extent, - layer_count, - view_mask, - ref color_attachments, - ref depth_attachment, - ref stencil_attachment, - contents, - _ne: _, - } = rendering_info; - - let map_attachment_info = |attachment_info: &Option<_>| { - if let Some(attachment_info) = attachment_info { - let &RenderingAttachmentInfo { - ref image_view, - image_layout, - resolve_info: ref resolve, - load_op, - store_op, - clear_value, - _ne: _, - } = attachment_info; - - let (resolve_mode, resolve_image_view, resolve_image_layout) = - if let Some(resolve) = resolve { - let &RenderingAttachmentResolveInfo { - mode, - ref image_view, - image_layout, - } = resolve; - - (mode.into(), image_view.handle(), image_layout.into()) - } else { - ( - ash::vk::ResolveModeFlags::NONE, - Default::default(), - Default::default(), - ) - }; - - ash::vk::RenderingAttachmentInfo { - image_view: image_view.handle(), - image_layout: image_layout.into(), - resolve_mode, - resolve_image_view, - resolve_image_layout, - load_op: load_op.into(), - store_op: store_op.into(), - clear_value: clear_value.map_or_else(Default::default, Into::into), - ..Default::default() - } - } else { - ash::vk::RenderingAttachmentInfo { - image_view: ash::vk::ImageView::null(), - ..Default::default() - } - } - }; - - let color_attachments_vk: SmallVec<[_; 2]> = - color_attachments.iter().map(map_attachment_info).collect(); - let depth_attachment_vk = map_attachment_info(depth_attachment); - let stencil_attachment_vk = map_attachment_info(stencil_attachment); - - let rendering_info = ash::vk::RenderingInfo { - flags: contents.into(), - render_area: ash::vk::Rect2D { - offset: ash::vk::Offset2D { - x: render_area_offset[0] as i32, - y: render_area_offset[1] as i32, - }, - extent: ash::vk::Extent2D { - width: render_area_extent[0], - height: render_area_extent[1], - }, - }, - layer_count, - view_mask, - color_attachment_count: color_attachments_vk.len() as u32, - p_color_attachments: color_attachments_vk.as_ptr(), - p_depth_attachment: &depth_attachment_vk, - p_stencil_attachment: &stencil_attachment_vk, - ..Default::default() - }; + let rendering_info_fields1_vk = rendering_info.to_vk_fields1(); + let rendering_info_vk = rendering_info.to_vk(&rendering_info_fields1_vk); let fns = self.device().fns(); if self.device().api_version() >= Version::V1_3 { - (fns.v1_3.cmd_begin_rendering)(self.handle(), &rendering_info); + (fns.v1_3.cmd_begin_rendering)(self.handle(), &rendering_info_vk); } else { - (fns.khr_dynamic_rendering.cmd_begin_rendering_khr)(self.handle(), &rendering_info); + (fns.khr_dynamic_rendering.cmd_begin_rendering_khr)(self.handle(), &rendering_info_vk); } self @@ -1781,24 +1654,8 @@ impl RawRecordingCommandBuffer { } let attachments_vk: SmallVec<[_; 4]> = - attachments.iter().copied().map(|v| v.into()).collect(); - let rects_vk: SmallVec<[_; 4]> = rects - .iter() - .map(|rect| ash::vk::ClearRect { - rect: ash::vk::Rect2D { - offset: ash::vk::Offset2D { - x: rect.offset[0] as i32, - y: rect.offset[1] as i32, - }, - extent: ash::vk::Extent2D { - width: rect.extent[0], - height: rect.extent[1], - }, - }, - base_array_layer: rect.array_layers.start, - layer_count: rect.array_layers.end - rect.array_layers.start, - }) - .collect(); + attachments.iter().map(ClearAttachment::to_vk).collect(); + let rects_vk: SmallVec<[_; 4]> = rects.iter().map(ClearRect::to_vk).collect(); let fns = self.device().fns(); (fns.v1_0.cmd_clear_attachments)( @@ -1996,6 +1853,54 @@ impl RenderPassBeginInfo { Ok(()) } + + pub(crate) fn to_vk<'a>( + &self, + fields1_vk: &'a RenderPassBeginInfoFields1Vk, + ) -> ash::vk::RenderPassBeginInfo<'a> { + let &Self { + ref render_pass, + ref framebuffer, + render_area_offset, + render_area_extent, + clear_values: _, + _ne, + } = self; + let RenderPassBeginInfoFields1Vk { clear_values_vk } = fields1_vk; + + ash::vk::RenderPassBeginInfo::default() + .render_pass(render_pass.handle()) + .framebuffer(framebuffer.handle()) + .render_area(ash::vk::Rect2D { + offset: ash::vk::Offset2D { + x: render_area_offset[0] as i32, + y: render_area_offset[1] as i32, + }, + extent: ash::vk::Extent2D { + width: render_area_extent[0], + height: render_area_extent[1], + }, + }) + .clear_values(clear_values_vk) + } + + pub(crate) fn to_vk_fields1(&self) -> RenderPassBeginInfoFields1Vk { + let clear_values_vk = self + .clear_values + .iter() + .map(|clear_value| { + clear_value + .as_ref() + .map_or_else(Default::default, ClearValue::to_vk) + }) + .collect(); + + RenderPassBeginInfoFields1Vk { clear_values_vk } + } +} + +pub(crate) struct RenderPassBeginInfoFields1Vk { + pub(crate) clear_values_vk: SmallVec<[ash::vk::ClearValue; 4]>, } /// Parameters to begin a new subpass within a render pass. @@ -2030,6 +1935,12 @@ impl SubpassBeginInfo { Ok(()) } + + pub(crate) fn to_vk(&self) -> ash::vk::SubpassBeginInfo<'static> { + let &Self { contents, _ne: _ } = self; + + ash::vk::SubpassBeginInfo::default().contents(contents.into()) + } } /// Parameters to end the current subpass within a render pass. @@ -2053,6 +1964,12 @@ impl SubpassEndInfo { Ok(()) } + + pub(crate) fn to_vk(&self) -> ash::vk::SubpassEndInfo<'static> { + let &Self { _ne: _ } = self; + + ash::vk::SubpassEndInfo::default() + } } /// Parameters to begin rendering. @@ -2831,6 +2748,88 @@ impl RenderingInfo { Ok(()) } + + pub(crate) fn to_vk<'a>( + &self, + fields1_vk: &'a RenderingInfoFields1Vk, + ) -> ash::vk::RenderingInfo<'a> { + let &Self { + render_area_offset, + render_area_extent, + layer_count, + view_mask, + color_attachments: _, + depth_attachment: _, + stencil_attachment: _, + contents, + _ne: _, + } = self; + let RenderingInfoFields1Vk { + color_attachments_vk, + depth_attachment_vk, + stencil_attachment_vk, + } = fields1_vk; + + ash::vk::RenderingInfo::default() + .flags(contents.into()) + .render_area(ash::vk::Rect2D { + offset: ash::vk::Offset2D { + x: render_area_offset[0] as i32, + y: render_area_offset[1] as i32, + }, + extent: ash::vk::Extent2D { + width: render_area_extent[0], + height: render_area_extent[1], + }, + }) + .layer_count(layer_count) + .view_mask(view_mask) + .color_attachments(color_attachments_vk) + .depth_attachment(depth_attachment_vk) + .stencil_attachment(stencil_attachment_vk) + } + + pub(crate) fn to_vk_fields1(&self) -> RenderingInfoFields1Vk { + let Self { + color_attachments, + depth_attachment, + stencil_attachment, + .. + } = self; + + let color_attachments_vk = color_attachments + .iter() + .map(|attachment_info| { + attachment_info.as_ref().map_or( + ash::vk::RenderingAttachmentInfo::default() + .image_view(ash::vk::ImageView::null()), + RenderingAttachmentInfo::to_vk, + ) + }) + .collect(); + + let depth_attachment_vk = depth_attachment.as_ref().map_or( + ash::vk::RenderingAttachmentInfo::default().image_view(ash::vk::ImageView::null()), + RenderingAttachmentInfo::to_vk, + ); + + let stencil_attachment_vk = stencil_attachment.as_ref().map_or( + ash::vk::RenderingAttachmentInfo::default().image_view(ash::vk::ImageView::null()), + RenderingAttachmentInfo::to_vk, + ); + + RenderingInfoFields1Vk { + color_attachments_vk, + depth_attachment_vk, + stencil_attachment_vk, + } + } +} + +pub(crate) struct RenderingInfoFields1Vk { + pub(crate) color_attachments_vk: SmallVec<[ash::vk::RenderingAttachmentInfo<'static>; 2]>, + pub(crate) depth_attachment_vk: ash::vk::RenderingAttachmentInfo<'static>, + pub(crate) stencil_attachment_vk: ash::vk::RenderingAttachmentInfo<'static>, } /// Parameters to specify properties of an attachment. @@ -3007,6 +3006,42 @@ impl RenderingAttachmentInfo { Ok(()) } + + pub(crate) fn to_vk(&self) -> ash::vk::RenderingAttachmentInfo<'static> { + let &Self { + ref image_view, + image_layout, + ref resolve_info, + load_op, + store_op, + ref clear_value, + _ne: _, + } = self; + + let (resolve_mode, resolve_image_view, resolve_image_layout) = + resolve_info.as_ref().map_or( + ( + ash::vk::ResolveModeFlags::NONE, + Default::default(), + Default::default(), + ), + RenderingAttachmentResolveInfo::to_vk, + ); + + ash::vk::RenderingAttachmentInfo::default() + .image_view(image_view.handle()) + .image_layout(image_layout.into()) + .resolve_mode(resolve_mode) + .resolve_image_view(resolve_image_view) + .resolve_image_layout(resolve_image_layout) + .load_op(load_op.into()) + .store_op(store_op.into()) + .clear_value( + clear_value + .as_ref() + .map_or_else(Default::default, ClearValue::to_vk), + ) + } } /// Parameters to specify the resolve behavior of an attachment. @@ -3136,6 +3171,22 @@ impl RenderingAttachmentResolveInfo { Ok(()) } + + pub(crate) fn to_vk( + &self, + ) -> ( + ash::vk::ResolveModeFlags, + ash::vk::ImageView, + ash::vk::ImageLayout, + ) { + let &Self { + mode, + ref image_view, + image_layout, + } = self; + + (mode.into(), image_view.handle(), image_layout.into()) + } } /// Clear attachment type, used in [`clear_attachments`] command. @@ -3180,12 +3231,10 @@ impl ClearAttachment { Ok(()) } -} -impl From for ash::vk::ClearAttachment { - #[inline] - fn from(v: ClearAttachment) -> Self { - match v { + #[allow(clippy::wrong_self_convention)] + pub(crate) fn to_vk(&self) -> ash::vk::ClearAttachment { + match *self { ClearAttachment::Color { color_attachment, clear_value, @@ -3193,7 +3242,7 @@ impl From for ash::vk::ClearAttachment { aspect_mask: ash::vk::ImageAspectFlags::COLOR, color_attachment, clear_value: ash::vk::ClearValue { - color: clear_value.into(), + color: clear_value.to_vk(), }, }, ClearAttachment::Depth(depth) => ash::vk::ClearAttachment { @@ -3238,3 +3287,28 @@ pub struct ClearRect { /// The range of array layers to be cleared. pub array_layers: Range, } + +impl ClearRect { + pub(crate) fn to_vk(&self) -> ash::vk::ClearRect { + let &Self { + offset, + extent, + ref array_layers, + } = self; + + ash::vk::ClearRect { + rect: ash::vk::Rect2D { + offset: ash::vk::Offset2D { + x: offset[0] as i32, + y: offset[1] as i32, + }, + extent: ash::vk::Extent2D { + width: extent[0], + height: extent[1], + }, + }, + base_array_layer: array_layers.start, + layer_count: array_layers.end - array_layers.start, + } + } +} diff --git a/vulkano/src/command_buffer/commands/sync.rs b/vulkano/src/command_buffer/commands/sync.rs index 9e547d76..e56d33b1 100644 --- a/vulkano/src/command_buffer/commands/sync.rs +++ b/vulkano/src/command_buffer/commands/sync.rs @@ -2,13 +2,13 @@ use crate::{ command_buffer::sys::RawRecordingCommandBuffer, device::{DeviceOwned, QueueFlags}, sync::{ - event::Event, BufferMemoryBarrier, DependencyFlags, DependencyInfo, ImageMemoryBarrier, - MemoryBarrier, PipelineStages, + event::Event, BufferMemoryBarrier, DependencyInfo, DependencyInfo2Fields1Vk, + DependencyInfoFields1Vk, ImageMemoryBarrier, MemoryBarrier, PipelineStages, }, Requires, RequiresAllOf, RequiresOneOf, ValidationError, Version, VulkanObject, }; use smallvec::SmallVec; -use std::{ptr, sync::Arc}; +use std::sync::Arc; impl RawRecordingCommandBuffer { #[inline] @@ -197,119 +197,17 @@ impl RawRecordingCommandBuffer { return self; } - let &DependencyInfo { - dependency_flags, - ref memory_barriers, - ref buffer_memory_barriers, - ref image_memory_barriers, - _ne: _, - } = dependency_info; - if self.device().enabled_features().synchronization2 { - let memory_barriers_vk: SmallVec<[_; 2]> = memory_barriers - .iter() - .map(|barrier| { - let &MemoryBarrier { - src_stages, - src_access, - dst_stages, - dst_access, - _ne: _, - } = barrier; - - ash::vk::MemoryBarrier2 { - src_stage_mask: src_stages.into(), - src_access_mask: src_access.into(), - dst_stage_mask: dst_stages.into(), - dst_access_mask: dst_access.into(), - ..Default::default() - } - }) - .collect(); - - let buffer_memory_barriers_vk: SmallVec<[_; 8]> = buffer_memory_barriers - .iter() - .map(|barrier| { - let &BufferMemoryBarrier { - src_stages, - src_access, - dst_stages, - dst_access, - queue_family_ownership_transfer, - ref buffer, - ref range, - _ne: _, - } = barrier; - - let (src_queue_family_index, dst_queue_family_index) = - queue_family_ownership_transfer.map_or( - (ash::vk::QUEUE_FAMILY_IGNORED, ash::vk::QUEUE_FAMILY_IGNORED), - Into::into, - ); - - ash::vk::BufferMemoryBarrier2 { - src_stage_mask: src_stages.into(), - src_access_mask: src_access.into(), - dst_stage_mask: dst_stages.into(), - dst_access_mask: dst_access.into(), - src_queue_family_index, - dst_queue_family_index, - buffer: buffer.handle(), - offset: range.start, - size: range.end - range.start, - ..Default::default() - } - }) - .collect(); - - let image_memory_barriers_vk: SmallVec<[_; 8]> = image_memory_barriers - .iter() - .map(|barrier| { - let &ImageMemoryBarrier { - src_stages, - src_access, - dst_stages, - dst_access, - old_layout, - new_layout, - queue_family_ownership_transfer, - ref image, - ref subresource_range, - _ne: _, - } = barrier; - - let (src_queue_family_index, dst_queue_family_index) = - queue_family_ownership_transfer.map_or( - (ash::vk::QUEUE_FAMILY_IGNORED, ash::vk::QUEUE_FAMILY_IGNORED), - Into::into, - ); - - ash::vk::ImageMemoryBarrier2 { - src_stage_mask: src_stages.into(), - src_access_mask: src_access.into(), - dst_stage_mask: dst_stages.into(), - dst_access_mask: dst_access.into(), - old_layout: old_layout.into(), - new_layout: new_layout.into(), - src_queue_family_index, - dst_queue_family_index, - image: image.handle(), - subresource_range: subresource_range.clone().into(), - ..Default::default() - } - }) - .collect(); - - let dependency_info_vk = ash::vk::DependencyInfo { - dependency_flags: dependency_flags.into(), - memory_barrier_count: memory_barriers_vk.len() as u32, - p_memory_barriers: memory_barriers_vk.as_ptr(), - buffer_memory_barrier_count: buffer_memory_barriers_vk.len() as u32, - p_buffer_memory_barriers: buffer_memory_barriers_vk.as_ptr(), - image_memory_barrier_count: image_memory_barriers_vk.len() as u32, - p_image_memory_barriers: image_memory_barriers_vk.as_ptr(), - ..Default::default() - }; + let DependencyInfo2Fields1Vk { + memory_barriers_vk, + buffer_memory_barriers_vk, + image_memory_barriers_vk, + } = dependency_info.to_vk2_fields1(); + let dependency_info_vk = dependency_info.to_vk2( + &memory_barriers_vk, + &buffer_memory_barriers_vk, + &image_memory_barriers_vk, + ); let fns = self.device().fns(); @@ -322,124 +220,21 @@ impl RawRecordingCommandBuffer { ); } } else { - let mut src_stage_mask = ash::vk::PipelineStageFlags::empty(); - let mut dst_stage_mask = ash::vk::PipelineStageFlags::empty(); - - let memory_barriers_vk: SmallVec<[_; 2]> = memory_barriers - .iter() - .map(|barrier| { - let &MemoryBarrier { - src_stages, - src_access, - dst_stages, - dst_access, - _ne: _, - } = barrier; - - src_stage_mask |= src_stages.into(); - dst_stage_mask |= dst_stages.into(); - - ash::vk::MemoryBarrier { - src_access_mask: src_access.into(), - dst_access_mask: dst_access.into(), - ..Default::default() - } - }) - .collect(); - - let buffer_memory_barriers_vk: SmallVec<[_; 8]> = buffer_memory_barriers - .iter() - .map(|barrier| { - let &BufferMemoryBarrier { - src_stages, - src_access, - dst_stages, - dst_access, - queue_family_ownership_transfer, - ref buffer, - ref range, - _ne: _, - } = barrier; - - src_stage_mask |= src_stages.into(); - dst_stage_mask |= dst_stages.into(); - - let (src_queue_family_index, dst_queue_family_index) = - queue_family_ownership_transfer.map_or( - (ash::vk::QUEUE_FAMILY_IGNORED, ash::vk::QUEUE_FAMILY_IGNORED), - Into::into, - ); - - ash::vk::BufferMemoryBarrier { - src_access_mask: src_access.into(), - dst_access_mask: dst_access.into(), - src_queue_family_index, - dst_queue_family_index, - buffer: buffer.handle(), - offset: range.start, - size: range.end - range.start, - ..Default::default() - } - }) - .collect(); - - let image_memory_barriers_vk: SmallVec<[_; 8]> = image_memory_barriers - .iter() - .map(|barrier| { - let &ImageMemoryBarrier { - src_stages, - src_access, - dst_stages, - dst_access, - old_layout, - new_layout, - queue_family_ownership_transfer, - ref image, - ref subresource_range, - _ne: _, - } = barrier; - - src_stage_mask |= src_stages.into(); - dst_stage_mask |= dst_stages.into(); - - let (src_queue_family_index, dst_queue_family_index) = - queue_family_ownership_transfer.map_or( - (ash::vk::QUEUE_FAMILY_IGNORED, ash::vk::QUEUE_FAMILY_IGNORED), - Into::into, - ); - - ash::vk::ImageMemoryBarrier { - src_access_mask: src_access.into(), - dst_access_mask: dst_access.into(), - old_layout: old_layout.into(), - new_layout: new_layout.into(), - src_queue_family_index, - dst_queue_family_index, - image: image.handle(), - subresource_range: subresource_range.clone().into(), - ..Default::default() - } - }) - .collect(); - - if src_stage_mask.is_empty() { - // "VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT is [...] equivalent to - // VK_PIPELINE_STAGE_2_NONE in the first scope." - src_stage_mask |= ash::vk::PipelineStageFlags::TOP_OF_PIPE; - } - - if dst_stage_mask.is_empty() { - // "VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT is [...] equivalent to - // VK_PIPELINE_STAGE_2_NONE in the second scope." - dst_stage_mask |= ash::vk::PipelineStageFlags::BOTTOM_OF_PIPE; - } + let DependencyInfoFields1Vk { + memory_barriers_vk, + buffer_memory_barriers_vk, + image_memory_barriers_vk, + src_stage_mask_vk, + dst_stage_mask_vk, + } = dependency_info.to_vk_fields1(); + let dependency_flags_vk = dependency_info.to_vk_dependency_flags(); let fns = self.device().fns(); (fns.v1_0.cmd_pipeline_barrier)( self.handle(), - src_stage_mask, - dst_stage_mask, - dependency_flags.into(), + src_stage_mask_vk, + dst_stage_mask_vk, + dependency_flags_vk, memory_barriers_vk.len() as u32, memory_barriers_vk.as_ptr(), buffer_memory_barriers_vk.len() as u32, @@ -648,124 +443,19 @@ impl RawRecordingCommandBuffer { event: &Event, dependency_info: &DependencyInfo, ) -> &mut Self { - let &DependencyInfo { - mut dependency_flags, - ref memory_barriers, - ref buffer_memory_barriers, - ref image_memory_barriers, - _ne: _, - } = dependency_info; - - // TODO: Is this needed? - dependency_flags |= DependencyFlags::BY_REGION; - let fns = self.device().fns(); if self.device().enabled_features().synchronization2 { - let memory_barriers_vk: SmallVec<[_; 2]> = memory_barriers - .iter() - .map(|barrier| { - let &MemoryBarrier { - src_stages, - src_access, - dst_stages, - dst_access, - _ne: _, - } = barrier; - - ash::vk::MemoryBarrier2 { - src_stage_mask: src_stages.into(), - src_access_mask: src_access.into(), - dst_stage_mask: dst_stages.into(), - dst_access_mask: dst_access.into(), - ..Default::default() - } - }) - .collect(); - - let buffer_memory_barriers_vk: SmallVec<[_; 8]> = buffer_memory_barriers - .iter() - .map(|barrier| { - let &BufferMemoryBarrier { - src_stages, - src_access, - dst_stages, - dst_access, - queue_family_ownership_transfer, - ref buffer, - ref range, - _ne: _, - } = barrier; - - let (src_queue_family_index, dst_queue_family_index) = - queue_family_ownership_transfer.map_or( - (ash::vk::QUEUE_FAMILY_IGNORED, ash::vk::QUEUE_FAMILY_IGNORED), - Into::into, - ); - - ash::vk::BufferMemoryBarrier2 { - src_stage_mask: src_stages.into(), - src_access_mask: src_access.into(), - dst_stage_mask: dst_stages.into(), - dst_access_mask: dst_access.into(), - src_queue_family_index, - dst_queue_family_index, - buffer: buffer.handle(), - offset: range.start, - size: range.end - range.start, - ..Default::default() - } - }) - .collect(); - - let image_memory_barriers_vk: SmallVec<[_; 8]> = image_memory_barriers - .iter() - .map(|barrier| { - let &ImageMemoryBarrier { - src_stages, - src_access, - dst_stages, - dst_access, - old_layout, - new_layout, - queue_family_ownership_transfer, - ref image, - ref subresource_range, - _ne: _, - } = barrier; - - let (src_queue_family_index, dst_queue_family_index) = - queue_family_ownership_transfer.map_or( - (ash::vk::QUEUE_FAMILY_IGNORED, ash::vk::QUEUE_FAMILY_IGNORED), - Into::into, - ); - - ash::vk::ImageMemoryBarrier2 { - src_stage_mask: src_stages.into(), - src_access_mask: src_access.into(), - dst_stage_mask: dst_stages.into(), - dst_access_mask: dst_access.into(), - old_layout: old_layout.into(), - new_layout: new_layout.into(), - src_queue_family_index, - dst_queue_family_index, - image: image.handle(), - subresource_range: subresource_range.clone().into(), - ..Default::default() - } - }) - .collect(); - - let dependency_info_vk = ash::vk::DependencyInfo { - dependency_flags: dependency_flags.into(), - memory_barrier_count: memory_barriers_vk.len() as u32, - p_memory_barriers: memory_barriers_vk.as_ptr(), - buffer_memory_barrier_count: buffer_memory_barriers_vk.len() as u32, - p_buffer_memory_barriers: buffer_memory_barriers_vk.as_ptr(), - image_memory_barrier_count: image_memory_barriers_vk.len() as u32, - p_image_memory_barriers: image_memory_barriers_vk.as_ptr(), - ..Default::default() - }; + let DependencyInfo2Fields1Vk { + memory_barriers_vk, + buffer_memory_barriers_vk, + image_memory_barriers_vk, + } = dependency_info.to_vk2_fields1(); + let dependency_info_vk = dependency_info.to_vk2( + &memory_barriers_vk, + &buffer_memory_barriers_vk, + &image_memory_barriers_vk, + ); if self.device().api_version() >= Version::V1_3 { (fns.v1_3.cmd_set_event2)(self.handle(), event.handle(), &dependency_info_vk); @@ -780,28 +470,9 @@ impl RawRecordingCommandBuffer { // The original function only takes a source stage mask; the rest of the info is // provided with `wait_events` instead. Therefore, we condense the source stages // here and ignore the rest. + let stage_mask_vk = dependency_info.to_vk_src_stage_mask(); - let mut stage_mask = ash::vk::PipelineStageFlags::empty(); - - for barrier in memory_barriers { - stage_mask |= barrier.src_stages.into(); - } - - for barrier in buffer_memory_barriers { - stage_mask |= barrier.src_stages.into(); - } - - for barrier in image_memory_barriers { - stage_mask |= barrier.src_stages.into(); - } - - if stage_mask.is_empty() { - // "VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT is [...] equivalent to - // VK_PIPELINE_STAGE_2_NONE in the first scope." - stage_mask |= ash::vk::PipelineStageFlags::TOP_OF_PIPE; - } - - (fns.v1_0.cmd_set_event)(self.handle(), event.handle(), stage_mask); + (fns.v1_0.cmd_set_event)(self.handle(), event.handle(), stage_mask_vk); } self @@ -998,161 +669,29 @@ impl RawRecordingCommandBuffer { let fns = self.device().fns(); if self.device().enabled_features().synchronization2 { - struct PerDependencyInfo { - memory_barriers_vk: SmallVec<[ash::vk::MemoryBarrier2<'static>; 2]>, - buffer_memory_barriers_vk: SmallVec<[ash::vk::BufferMemoryBarrier2<'static>; 8]>, - image_memory_barriers_vk: SmallVec<[ash::vk::ImageMemoryBarrier2<'static>; 8]>, - } + let events_vk: SmallVec<[_; 4]> = + events.iter().map(|(event, _)| event.handle()).collect(); + let dependency_infos_fields1_vk: SmallVec<[_; 4]> = events + .iter() + .map(|(_, dependency_info)| dependency_info.to_vk2_fields1()) + .collect(); + let dependency_infos_vk: SmallVec<[_; 4]> = events + .iter() + .zip(&dependency_infos_fields1_vk) + .map(|((_, dependency_info), dependency_info_fields1_vk)| { + let DependencyInfo2Fields1Vk { + memory_barriers_vk, + buffer_memory_barriers_vk, + image_memory_barriers_vk, + } = dependency_info_fields1_vk; - let mut events_vk: SmallVec<[_; 4]> = SmallVec::new(); - let mut dependency_infos_vk: SmallVec<[_; 4]> = SmallVec::new(); - let mut per_dependency_info_vk: SmallVec<[_; 4]> = SmallVec::new(); - - for (event, dependency_info) in events { - let &DependencyInfo { - mut dependency_flags, - ref memory_barriers, - ref buffer_memory_barriers, - ref image_memory_barriers, - _ne: _, - } = dependency_info; - - // TODO: Is this needed? - dependency_flags |= DependencyFlags::BY_REGION; - - let memory_barriers_vk: SmallVec<[_; 2]> = memory_barriers - .iter() - .map(|barrier| { - let &MemoryBarrier { - src_stages, - src_access, - dst_stages, - dst_access, - _ne: _, - } = barrier; - - ash::vk::MemoryBarrier2 { - src_stage_mask: src_stages.into(), - src_access_mask: src_access.into(), - dst_stage_mask: dst_stages.into(), - dst_access_mask: dst_access.into(), - ..Default::default() - } - }) - .collect(); - - let buffer_memory_barriers_vk: SmallVec<[_; 8]> = buffer_memory_barriers - .iter() - .map(|barrier| { - let &BufferMemoryBarrier { - src_stages, - src_access, - dst_stages, - dst_access, - queue_family_ownership_transfer, - ref buffer, - ref range, - _ne: _, - } = barrier; - - let (src_queue_family_index, dst_queue_family_index) = - queue_family_ownership_transfer.map_or( - (ash::vk::QUEUE_FAMILY_IGNORED, ash::vk::QUEUE_FAMILY_IGNORED), - Into::into, - ); - - ash::vk::BufferMemoryBarrier2 { - src_stage_mask: src_stages.into(), - src_access_mask: src_access.into(), - dst_stage_mask: dst_stages.into(), - dst_access_mask: dst_access.into(), - src_queue_family_index, - dst_queue_family_index, - buffer: buffer.handle(), - offset: range.start, - size: range.end - range.start, - ..Default::default() - } - }) - .collect(); - - let image_memory_barriers_vk: SmallVec<[_; 8]> = image_memory_barriers - .iter() - .map(|barrier| { - let &ImageMemoryBarrier { - src_stages, - src_access, - dst_stages, - dst_access, - old_layout, - new_layout, - queue_family_ownership_transfer, - ref image, - ref subresource_range, - _ne: _, - } = barrier; - - let (src_queue_family_index, dst_queue_family_index) = - queue_family_ownership_transfer.map_or( - (ash::vk::QUEUE_FAMILY_IGNORED, ash::vk::QUEUE_FAMILY_IGNORED), - Into::into, - ); - - ash::vk::ImageMemoryBarrier2 { - src_stage_mask: src_stages.into(), - src_access_mask: src_access.into(), - dst_stage_mask: dst_stages.into(), - dst_access_mask: dst_access.into(), - old_layout: old_layout.into(), - new_layout: new_layout.into(), - src_queue_family_index, - dst_queue_family_index, - image: image.handle(), - subresource_range: subresource_range.clone().into(), - ..Default::default() - } - }) - .collect(); - - events_vk.push(event.handle()); - dependency_infos_vk.push(ash::vk::DependencyInfo { - dependency_flags: dependency_flags.into(), - memory_barrier_count: 0, - p_memory_barriers: ptr::null(), - buffer_memory_barrier_count: 0, - p_buffer_memory_barriers: ptr::null(), - image_memory_barrier_count: 0, - p_image_memory_barriers: ptr::null(), - ..Default::default() - }); - per_dependency_info_vk.push(PerDependencyInfo { - memory_barriers_vk, - buffer_memory_barriers_vk, - image_memory_barriers_vk, - }); - } - - for ( - dependency_info_vk, - PerDependencyInfo { - memory_barriers_vk, - buffer_memory_barriers_vk, - image_memory_barriers_vk, - }, - ) in dependency_infos_vk - .iter_mut() - .zip(per_dependency_info_vk.iter_mut()) - { - *dependency_info_vk = ash::vk::DependencyInfo { - memory_barrier_count: memory_barriers_vk.len() as u32, - p_memory_barriers: memory_barriers_vk.as_ptr(), - buffer_memory_barrier_count: buffer_memory_barriers_vk.len() as u32, - p_buffer_memory_barriers: buffer_memory_barriers_vk.as_ptr(), - image_memory_barrier_count: image_memory_barriers_vk.len() as u32, - p_image_memory_barriers: image_memory_barriers_vk.as_ptr(), - ..*dependency_info_vk - } - } + dependency_info.to_vk2( + memory_barriers_vk, + buffer_memory_barriers_vk, + image_memory_barriers_vk, + ) + }) + .collect(); if self.device().api_version() >= Version::V1_3 { (fns.v1_3.cmd_wait_events2)( @@ -1177,133 +716,20 @@ impl RawRecordingCommandBuffer { for (event, dependency_info) in events { let events_vk = [event.handle()]; - - let &DependencyInfo { - dependency_flags: _, - ref memory_barriers, - ref buffer_memory_barriers, - ref image_memory_barriers, - _ne: _, - } = dependency_info; - - let mut src_stage_mask = ash::vk::PipelineStageFlags::empty(); - let mut dst_stage_mask = ash::vk::PipelineStageFlags::empty(); - - let memory_barriers_vk: SmallVec<[_; 2]> = memory_barriers - .iter() - .map(|barrier| { - let &MemoryBarrier { - src_stages, - src_access, - dst_stages, - dst_access, - _ne: _, - } = barrier; - - src_stage_mask |= src_stages.into(); - dst_stage_mask |= dst_stages.into(); - - ash::vk::MemoryBarrier { - src_access_mask: src_access.into(), - dst_access_mask: dst_access.into(), - ..Default::default() - } - }) - .collect(); - - let buffer_memory_barriers_vk: SmallVec<[_; 8]> = buffer_memory_barriers - .iter() - .map(|barrier| { - let &BufferMemoryBarrier { - src_stages, - src_access, - dst_stages, - dst_access, - queue_family_ownership_transfer, - ref buffer, - ref range, - _ne: _, - } = barrier; - - src_stage_mask |= src_stages.into(); - dst_stage_mask |= dst_stages.into(); - - let (src_queue_family_index, dst_queue_family_index) = - queue_family_ownership_transfer.map_or( - (ash::vk::QUEUE_FAMILY_IGNORED, ash::vk::QUEUE_FAMILY_IGNORED), - Into::into, - ); - - ash::vk::BufferMemoryBarrier { - src_access_mask: src_access.into(), - dst_access_mask: dst_access.into(), - src_queue_family_index, - dst_queue_family_index, - buffer: buffer.handle(), - offset: range.start, - size: range.end - range.start, - ..Default::default() - } - }) - .collect(); - - let image_memory_barriers_vk: SmallVec<[_; 8]> = image_memory_barriers - .iter() - .map(|barrier| { - let &ImageMemoryBarrier { - src_stages, - src_access, - dst_stages, - dst_access, - old_layout, - new_layout, - queue_family_ownership_transfer, - ref image, - ref subresource_range, - _ne: _, - } = barrier; - - src_stage_mask |= src_stages.into(); - dst_stage_mask |= dst_stages.into(); - - let (src_queue_family_index, dst_queue_family_index) = - queue_family_ownership_transfer.map_or( - (ash::vk::QUEUE_FAMILY_IGNORED, ash::vk::QUEUE_FAMILY_IGNORED), - Into::into, - ); - - ash::vk::ImageMemoryBarrier { - src_access_mask: src_access.into(), - dst_access_mask: dst_access.into(), - old_layout: old_layout.into(), - new_layout: new_layout.into(), - src_queue_family_index, - dst_queue_family_index, - image: image.handle(), - subresource_range: subresource_range.clone().into(), - ..Default::default() - } - }) - .collect(); - - if src_stage_mask.is_empty() { - // "VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT is [...] equivalent to - // VK_PIPELINE_STAGE_2_NONE in the first scope." - src_stage_mask |= ash::vk::PipelineStageFlags::TOP_OF_PIPE; - } - - if dst_stage_mask.is_empty() { - // "VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT is [...] equivalent to - // VK_PIPELINE_STAGE_2_NONE in the second scope." - dst_stage_mask |= ash::vk::PipelineStageFlags::BOTTOM_OF_PIPE; - } + let DependencyInfoFields1Vk { + memory_barriers_vk, + buffer_memory_barriers_vk, + image_memory_barriers_vk, + src_stage_mask_vk, + dst_stage_mask_vk, + } = dependency_info.to_vk_fields1(); (fns.v1_0.cmd_wait_events)( self.handle(), 1, events_vk.as_ptr(), - src_stage_mask, - dst_stage_mask, + src_stage_mask_vk, + dst_stage_mask_vk, memory_barriers_vk.len() as u32, memory_barriers_vk.as_ptr(), buffer_memory_barriers_vk.len() as u32, diff --git a/vulkano/src/command_buffer/mod.rs b/vulkano/src/command_buffer/mod.rs index 361a7959..6c1f9c61 100644 --- a/vulkano/src/command_buffer/mod.rs +++ b/vulkano/src/command_buffer/mod.rs @@ -117,7 +117,7 @@ use crate::{ semaphore::{Semaphore, SemaphoreType}, PipelineStageAccessFlags, PipelineStages, }, - DeviceSize, Requires, RequiresAllOf, RequiresOneOf, ValidationError, + DeviceSize, Requires, RequiresAllOf, RequiresOneOf, ValidationError, VulkanObject, }; #[cfg(doc)] use crate::{ @@ -126,6 +126,7 @@ use crate::{ }; use ahash::HashMap; use bytemuck::{Pod, Zeroable}; +use smallvec::SmallVec; use std::{ops::Range, sync::Arc}; pub mod allocator; @@ -390,6 +391,110 @@ impl CommandBufferInheritanceInfo { Ok(()) } + + pub(crate) fn to_vk<'a>( + &self, + extensions_vk: &'a mut CommandBufferInheritanceInfoExtensionsVk<'_>, + ) -> ash::vk::CommandBufferInheritanceInfo<'a> { + let &Self { + ref render_pass, + occlusion_query, + pipeline_statistics, + _ne: _, + } = self; + + let (render_pass_vk, subpass_vk, framebuffer_vk) = render_pass + .as_ref() + .and_then(|render_pass| match render_pass { + CommandBufferInheritanceRenderPassType::BeginRenderPass(render_pass_info) => { + let &CommandBufferInheritanceRenderPassInfo { + ref subpass, + ref framebuffer, + } = render_pass_info; + + Some(( + subpass.render_pass().handle(), + subpass.index(), + framebuffer + .as_ref() + .map(|fb| fb.handle()) + .unwrap_or_default(), + )) + } + CommandBufferInheritanceRenderPassType::BeginRendering(_) => None, + }) + .unwrap_or_default(); + + let (occlusion_query_enable, query_flags_vk) = occlusion_query + .map(|flags| (true, flags.into())) + .unwrap_or_default(); + + let mut val_vk = ash::vk::CommandBufferInheritanceInfo::default() + .render_pass(render_pass_vk) + .subpass(subpass_vk) + .framebuffer(framebuffer_vk) + .occlusion_query_enable(occlusion_query_enable) + .query_flags(query_flags_vk) + .pipeline_statistics(pipeline_statistics.into()); + + let CommandBufferInheritanceInfoExtensionsVk { + rendering_info_vk: rendering_vk, + } = extensions_vk; + + if let Some(next) = rendering_vk { + val_vk = val_vk.push_next(next); + } + + val_vk + } + + pub(crate) fn to_vk_extensions<'a>( + &self, + fields1_vk: &'a CommandBufferInheritanceInfoFields1Vk, + ) -> CommandBufferInheritanceInfoExtensionsVk<'a> { + let CommandBufferInheritanceInfoFields1Vk { + rendering_info_fields1_vk, + } = fields1_vk; + + let rendering_info_vk = self + .render_pass + .as_ref() + .zip(rendering_info_fields1_vk.as_ref()) + .and_then( + |(render_pass, rendering_info_fields1_vk)| match render_pass { + CommandBufferInheritanceRenderPassType::BeginRenderPass(_) => None, + CommandBufferInheritanceRenderPassType::BeginRendering(rendering_info) => { + Some(rendering_info.to_vk(rendering_info_fields1_vk)) + } + }, + ); + + CommandBufferInheritanceInfoExtensionsVk { rendering_info_vk } + } + + pub(crate) fn to_vk_fields1(&self) -> CommandBufferInheritanceInfoFields1Vk { + let rendering_info_fields1_vk = + self.render_pass + .as_ref() + .and_then(|render_pass| match render_pass { + CommandBufferInheritanceRenderPassType::BeginRenderPass(_) => None, + CommandBufferInheritanceRenderPassType::BeginRendering(rendering_info) => { + Some(rendering_info.to_vk_fields1()) + } + }); + + CommandBufferInheritanceInfoFields1Vk { + rendering_info_fields1_vk, + } + } +} + +pub(crate) struct CommandBufferInheritanceInfoExtensionsVk<'a> { + pub(crate) rendering_info_vk: Option>, +} + +pub(crate) struct CommandBufferInheritanceInfoFields1Vk { + pub(crate) rendering_info_fields1_vk: Option, } /// Selects the type of render pass for command buffer inheritance. @@ -737,6 +842,54 @@ impl CommandBufferInheritanceRenderingInfo { Ok(()) } + + pub(crate) fn to_vk<'a>( + &self, + fields1_vk: &'a CommandBufferInheritanceRenderingInfoFields1Vk, + ) -> ash::vk::CommandBufferInheritanceRenderingInfo<'a> { + let &Self { + view_mask, + color_attachment_formats: _, + depth_attachment_format, + stencil_attachment_format, + rasterization_samples, + } = self; + let CommandBufferInheritanceRenderingInfoFields1Vk { + color_attachment_formats_vk, + } = fields1_vk; + + ash::vk::CommandBufferInheritanceRenderingInfo::default() + .flags(ash::vk::RenderingFlags::empty()) + .view_mask(view_mask) + .color_attachment_formats(color_attachment_formats_vk) + .depth_attachment_format( + depth_attachment_format.map_or(ash::vk::Format::UNDEFINED, Into::into), + ) + .stencil_attachment_format( + stencil_attachment_format.map_or(ash::vk::Format::UNDEFINED, Into::into), + ) + .rasterization_samples(rasterization_samples.into()) + } + + pub(crate) fn to_vk_fields1(&self) -> CommandBufferInheritanceRenderingInfoFields1Vk { + let Self { + color_attachment_formats, + .. + } = self; + + let color_attachment_formats_vk = color_attachment_formats + .iter() + .map(|format| format.map_or(ash::vk::Format::UNDEFINED, Into::into)) + .collect(); + + CommandBufferInheritanceRenderingInfoFields1Vk { + color_attachment_formats_vk, + } + } +} + +pub(crate) struct CommandBufferInheritanceRenderingInfoFields1Vk { + pub(crate) color_attachment_formats_vk: SmallVec<[ash::vk::Format; 4]>, } /// Usage flags to pass when creating a command buffer. @@ -857,6 +1010,187 @@ impl SubmitInfo { Ok(()) } + + pub(crate) fn to_vk2<'a>( + &self, + fields1_vk: &'a SubmitInfo2Fields1Vk, + ) -> ash::vk::SubmitInfo2<'a> { + let SubmitInfo2Fields1Vk { + wait_semaphore_infos_vk, + command_buffer_infos_vk, + signal_semaphore_infos_vk, + } = fields1_vk; + + ash::vk::SubmitInfo2::default() + .flags(ash::vk::SubmitFlags::empty()) // TODO: + .wait_semaphore_infos(wait_semaphore_infos_vk) + .command_buffer_infos(command_buffer_infos_vk) + .signal_semaphore_infos(signal_semaphore_infos_vk) + } + + pub(crate) fn to_vk2_fields1(&self) -> SubmitInfo2Fields1Vk { + let &Self { + ref wait_semaphores, + ref command_buffers, + ref signal_semaphores, + _ne: _, + } = self; + + SubmitInfo2Fields1Vk { + wait_semaphore_infos_vk: wait_semaphores + .iter() + .map(SemaphoreSubmitInfo::to_vk2) + .collect(), + command_buffer_infos_vk: command_buffers + .iter() + .map(CommandBufferSubmitInfo::to_vk2) + .collect(), + signal_semaphore_infos_vk: signal_semaphores + .iter() + .map(SemaphoreSubmitInfo::to_vk2) + .collect(), + } + } + + pub(crate) fn to_vk<'a>( + &self, + fields1_vk: &'a SubmitInfoFields1Vk, + extensions_vk: &'a mut SubmitInfoExtensionsVk<'_>, + ) -> ash::vk::SubmitInfo<'a> { + let SubmitInfoFields1Vk { + wait_semaphores_vk, + wait_dst_stage_mask_vk, + wait_semaphore_values_vk: _, + command_buffers_vk, + signal_semaphores_vk, + signal_semaphore_values_vk: _, + } = fields1_vk; + + let mut val_vk = ash::vk::SubmitInfo::default() + .wait_semaphores(wait_semaphores_vk) + .wait_dst_stage_mask(wait_dst_stage_mask_vk) + .command_buffers(command_buffers_vk) + .signal_semaphores(signal_semaphores_vk); + + let SubmitInfoExtensionsVk { + timeline_semaphore_vk, + } = extensions_vk; + + if let Some(next) = timeline_semaphore_vk { + val_vk = val_vk.push_next(next); + } + + val_vk + } + + pub(crate) fn to_vk_extensions<'a>( + &self, + fields1_vk: &'a SubmitInfoFields1Vk, + ) -> SubmitInfoExtensionsVk<'a> { + let Self { + wait_semaphores, + command_buffers: _, + signal_semaphores, + _ne: _, + } = self; + let SubmitInfoFields1Vk { + wait_semaphores_vk: _, + wait_dst_stage_mask_vk: _, + command_buffers_vk: _, + signal_semaphores_vk: _, + wait_semaphore_values_vk, + signal_semaphore_values_vk, + } = fields1_vk; + + let timeline_semaphore_vk = (wait_semaphores.iter()) + .chain(signal_semaphores.iter()) + .any(|semaphore_submit_info| { + semaphore_submit_info.semaphore.semaphore_type() == SemaphoreType::Timeline + }) + .then(|| { + ash::vk::TimelineSemaphoreSubmitInfo::default() + .wait_semaphore_values(wait_semaphore_values_vk) + .signal_semaphore_values(signal_semaphore_values_vk) + }); + + SubmitInfoExtensionsVk { + timeline_semaphore_vk, + } + } + + pub(crate) fn to_vk_fields1(&self) -> SubmitInfoFields1Vk { + let Self { + wait_semaphores, + command_buffers, + signal_semaphores, + _ne: _, + } = self; + + let mut wait_semaphores_vk = SmallVec::with_capacity(wait_semaphores.len()); + let mut wait_dst_stage_mask_vk = SmallVec::with_capacity(wait_semaphores.len()); + let mut wait_semaphore_values_vk = SmallVec::with_capacity(wait_semaphores.len()); + + for semaphore_submit_info in wait_semaphores { + let &SemaphoreSubmitInfo { + ref semaphore, + value, + stages, + _ne: _, + } = semaphore_submit_info; + + wait_semaphores_vk.push(semaphore.handle()); + wait_dst_stage_mask_vk.push(stages.into()); + wait_semaphore_values_vk.push(value); + } + + let command_buffers_vk = command_buffers + .iter() + .map(CommandBufferSubmitInfo::to_vk) + .collect(); + + let mut signal_semaphores_vk = SmallVec::with_capacity(signal_semaphores.len()); + let mut signal_semaphore_values_vk = SmallVec::with_capacity(signal_semaphores.len()); + + for semaphore_submit_info in signal_semaphores { + let &SemaphoreSubmitInfo { + ref semaphore, + value, + stages: _, + _ne: _, + } = semaphore_submit_info; + + signal_semaphores_vk.push(semaphore.handle()); + signal_semaphore_values_vk.push(value); + } + + SubmitInfoFields1Vk { + wait_semaphores_vk, + wait_dst_stage_mask_vk, + wait_semaphore_values_vk, + command_buffers_vk, + signal_semaphores_vk, + signal_semaphore_values_vk, + } + } +} + +pub(crate) struct SubmitInfo2Fields1Vk { + pub(crate) wait_semaphore_infos_vk: SmallVec<[ash::vk::SemaphoreSubmitInfo<'static>; 4]>, + pub(crate) command_buffer_infos_vk: SmallVec<[ash::vk::CommandBufferSubmitInfo<'static>; 4]>, + pub(crate) signal_semaphore_infos_vk: SmallVec<[ash::vk::SemaphoreSubmitInfo<'static>; 4]>, +} + +pub(crate) struct SubmitInfoExtensionsVk<'a> { + pub(crate) timeline_semaphore_vk: Option>, +} + +pub(crate) struct SubmitInfoFields1Vk { + pub(crate) wait_semaphores_vk: SmallVec<[ash::vk::Semaphore; 4]>, + pub(crate) wait_dst_stage_mask_vk: SmallVec<[ash::vk::PipelineStageFlags; 4]>, + pub(crate) wait_semaphore_values_vk: SmallVec<[u64; 4]>, + pub(crate) command_buffers_vk: SmallVec<[ash::vk::CommandBuffer; 4]>, + pub(crate) signal_semaphores_vk: SmallVec<[ash::vk::Semaphore; 4]>, + pub(crate) signal_semaphore_values_vk: SmallVec<[u64; 4]>, } /// Parameters for a command buffer in a queue submit operation. @@ -900,6 +1234,26 @@ impl CommandBufferSubmitInfo { Ok(()) } + + pub(crate) fn to_vk2(&self) -> ash::vk::CommandBufferSubmitInfo<'static> { + let &Self { + ref command_buffer, + _ne: _, + } = self; + + ash::vk::CommandBufferSubmitInfo::default() + .command_buffer(command_buffer.handle()) + .device_mask(0) // TODO: + } + + pub(crate) fn to_vk(&self) -> ash::vk::CommandBuffer { + let &Self { + ref command_buffer, + _ne: _, + } = self; + + command_buffer.handle() + } } /// Parameters for a semaphore signal or wait operation in a queue submit operation. @@ -1145,6 +1499,21 @@ impl SemaphoreSubmitInfo { Ok(()) } + + pub(crate) fn to_vk2(&self) -> ash::vk::SemaphoreSubmitInfo<'static> { + let &Self { + ref semaphore, + value, + stages, + _ne: _, + } = self; + + ash::vk::SemaphoreSubmitInfo::default() + .semaphore(semaphore.handle()) + .value(value) + .stage_mask(stages.into()) + .device_index(0) // TODO: + } } #[derive(Debug, Default)] diff --git a/vulkano/src/command_buffer/pool.rs b/vulkano/src/command_buffer/pool.rs index 778bd97c..e9cba01c 100644 --- a/vulkano/src/command_buffer/pool.rs +++ b/vulkano/src/command_buffer/pool.rs @@ -64,17 +64,7 @@ impl CommandPool { device: Arc, create_info: CommandPoolCreateInfo, ) -> Result { - let &CommandPoolCreateInfo { - flags, - queue_family_index, - _ne: _, - } = &create_info; - - let create_info_vk = ash::vk::CommandPoolCreateInfo { - flags: flags.into(), - queue_family_index, - ..Default::default() - }; + let create_info_vk = create_info.to_vk(); let handle = { let fns = device.fns(); @@ -182,24 +172,20 @@ impl CommandPool { let out = if command_buffer_count == 0 { vec![] } else { - let allocate_info = ash::vk::CommandBufferAllocateInfo { - command_pool: self.handle, - level: level.into(), - command_buffer_count, - ..Default::default() - }; + let allocate_info_vk = allocate_info.to_vk(self.handle); + let command_buffer_count = command_buffer_count as usize; unsafe { let fns = self.device.fns(); - let mut out = Vec::with_capacity(command_buffer_count as usize); + let mut out = Vec::with_capacity(command_buffer_count); (fns.v1_0.allocate_command_buffers)( self.device.handle(), - &allocate_info, + &allocate_info_vk, out.as_mut_ptr(), ) .result() .map_err(VulkanError::from)?; - out.set_len(command_buffer_count as usize); + out.set_len(command_buffer_count); out } }; @@ -394,6 +380,18 @@ impl CommandPoolCreateInfo { Ok(()) } + + pub(crate) fn to_vk(&self) -> ash::vk::CommandPoolCreateInfo<'static> { + let &Self { + flags, + queue_family_index, + _ne: _, + } = self; + + ash::vk::CommandPoolCreateInfo::default() + .flags(flags.into()) + .queue_family_index(queue_family_index) + } } vulkan_bitflags! { @@ -444,6 +442,24 @@ pub struct CommandBufferAllocateInfo { pub _ne: crate::NonExhaustive, } +impl CommandBufferAllocateInfo { + pub(crate) fn to_vk( + &self, + command_pool_vk: ash::vk::CommandPool, + ) -> ash::vk::CommandBufferAllocateInfo<'static> { + let &Self { + level, + command_buffer_count, + _ne: _, + } = self; + + ash::vk::CommandBufferAllocateInfo::default() + .command_pool(command_pool_vk) + .level(level.into()) + .command_buffer_count(command_buffer_count) + } +} + impl Default for CommandBufferAllocateInfo { #[inline] fn default() -> Self { diff --git a/vulkano/src/command_buffer/sys.rs b/vulkano/src/command_buffer/sys.rs index 4d6f4969..d33da9cb 100644 --- a/vulkano/src/command_buffer/sys.rs +++ b/vulkano/src/command_buffer/sys.rs @@ -1,18 +1,13 @@ use super::{ allocator::{CommandBufferAlloc, CommandBufferAllocator}, - CommandBufferInheritanceInfo, CommandBufferLevel, CommandBufferUsage, + CommandBufferInheritanceInfo, CommandBufferInheritanceInfoExtensionsVk, + CommandBufferInheritanceInfoFields1Vk, CommandBufferLevel, CommandBufferUsage, }; use crate::{ - command_buffer::{ - CommandBufferInheritanceRenderPassInfo, CommandBufferInheritanceRenderPassType, - CommandBufferInheritanceRenderingInfo, - }, device::{Device, DeviceOwned, QueueFamilyProperties}, - query::QueryControlFlags, Validated, ValidationError, VulkanError, VulkanObject, }; -use smallvec::SmallVec; -use std::{fmt::Debug, mem::ManuallyDrop, ptr, sync::Arc}; +use std::{fmt::Debug, mem::ManuallyDrop, sync::Arc}; /// A raw command buffer in the recording state. /// @@ -82,109 +77,13 @@ impl RawRecordingCommandBuffer { ) -> Result> { let allocation = allocator.allocate(queue_family_index, level)?; - let CommandBufferBeginInfo { - usage, - inheritance_info, - _ne: _, - } = begin_info; - { - let mut flags = ash::vk::CommandBufferUsageFlags::from(usage); - let mut inheritance_info_vk = None; - let mut inheritance_rendering_info_vk = None; - let mut color_attachment_formats_vk: SmallVec<[_; 4]> = SmallVec::new(); - - if let Some(inheritance_info) = &inheritance_info { - let &CommandBufferInheritanceInfo { - ref render_pass, - occlusion_query, - pipeline_statistics, - _ne: _, - } = inheritance_info; - - let inheritance_info_vk = - inheritance_info_vk.insert(ash::vk::CommandBufferInheritanceInfo { - render_pass: ash::vk::RenderPass::null(), - subpass: 0, - framebuffer: ash::vk::Framebuffer::null(), - occlusion_query_enable: ash::vk::FALSE, - query_flags: ash::vk::QueryControlFlags::empty(), - pipeline_statistics: pipeline_statistics.into(), - ..Default::default() - }); - - if let Some(flags) = occlusion_query { - inheritance_info_vk.occlusion_query_enable = ash::vk::TRUE; - - if flags.intersects(QueryControlFlags::PRECISE) { - inheritance_info_vk.query_flags = ash::vk::QueryControlFlags::PRECISE; - } - } - - if let Some(render_pass) = render_pass { - flags |= ash::vk::CommandBufferUsageFlags::RENDER_PASS_CONTINUE; - - match render_pass { - CommandBufferInheritanceRenderPassType::BeginRenderPass( - render_pass_info, - ) => { - let &CommandBufferInheritanceRenderPassInfo { - ref subpass, - ref framebuffer, - } = render_pass_info; - - inheritance_info_vk.render_pass = subpass.render_pass().handle(); - inheritance_info_vk.subpass = subpass.index(); - inheritance_info_vk.framebuffer = framebuffer - .as_ref() - .map(|fb| fb.handle()) - .unwrap_or_default(); - } - CommandBufferInheritanceRenderPassType::BeginRendering(rendering_info) => { - let &CommandBufferInheritanceRenderingInfo { - view_mask, - ref color_attachment_formats, - depth_attachment_format, - stencil_attachment_format, - rasterization_samples, - } = rendering_info; - - color_attachment_formats_vk.extend( - color_attachment_formats.iter().map(|format| { - format.map_or(ash::vk::Format::UNDEFINED, Into::into) - }), - ); - - let inheritance_rendering_info_vk = inheritance_rendering_info_vk - .insert(ash::vk::CommandBufferInheritanceRenderingInfo { - flags: ash::vk::RenderingFlags::empty(), - view_mask, - color_attachment_count: color_attachment_formats_vk.len() - as u32, - p_color_attachment_formats: color_attachment_formats_vk - .as_ptr(), - depth_attachment_format: depth_attachment_format - .map_or(ash::vk::Format::UNDEFINED, Into::into), - stencil_attachment_format: stencil_attachment_format - .map_or(ash::vk::Format::UNDEFINED, Into::into), - rasterization_samples: rasterization_samples.into(), - ..Default::default() - }); - - inheritance_info_vk.p_next = - <*const _>::cast(inheritance_rendering_info_vk); - } - } - } - } - - let begin_info_vk = ash::vk::CommandBufferBeginInfo { - flags, - p_inheritance_info: inheritance_info_vk - .as_ref() - .map_or(ptr::null(), |info| info), - ..Default::default() - }; + let begin_info_fields2_vk = begin_info.to_vk_fields2(); + let mut begin_info_fields1_extensions_vk = + begin_info.to_vk_fields1_extensions(&begin_info_fields2_vk); + let begin_info_fields1_vk = + begin_info.to_vk_fields1(&mut begin_info_fields1_extensions_vk); + let begin_info_vk = begin_info.to_vk(&begin_info_fields1_vk); let fns = allocation.inner.device().fns(); (fns.v1_0.begin_command_buffer)(allocation.inner.handle(), &begin_info_vk) @@ -192,6 +91,12 @@ impl RawRecordingCommandBuffer { .map_err(VulkanError::from)?; } + let CommandBufferBeginInfo { + usage, + inheritance_info, + _ne: _, + } = begin_info; + Ok(RawRecordingCommandBuffer { allocation: ManuallyDrop::new(allocation), allocator, @@ -323,6 +228,104 @@ impl CommandBufferBeginInfo { Ok(()) } + + pub(crate) fn to_vk<'a>( + &self, + fields1_vk: &'a BeginInfoFields1Vk<'_>, + ) -> ash::vk::CommandBufferBeginInfo<'a> { + let &Self { + usage: _, + ref inheritance_info, + _ne: _, + } = self; + + let flags_vk = inheritance_info + .as_ref() + .and_then(|inheritance_info| { + inheritance_info + .render_pass + .is_some() + .then_some(ash::vk::CommandBufferUsageFlags::RENDER_PASS_CONTINUE) + }) + .unwrap_or_default(); + + let mut val_vk = ash::vk::CommandBufferBeginInfo::default().flags(flags_vk); + + let BeginInfoFields1Vk { + inheritance_info_vk, + } = fields1_vk; + + if let Some(inheritance_info_vk) = inheritance_info_vk { + val_vk = val_vk.inheritance_info(inheritance_info_vk); + } + + val_vk + } + + pub(crate) fn to_vk_fields1<'a>( + &self, + fields1_extensions_vk: &'a mut BeginInfoFields1ExtensionsVk<'_>, + ) -> BeginInfoFields1Vk<'a> { + let BeginInfoFields1ExtensionsVk { + inheritance_info_vk, + } = fields1_extensions_vk; + + let inheritance_info_vk = self + .inheritance_info + .as_ref() + .zip(inheritance_info_vk.as_mut()) + .map(|(inheritance_info, inheritance_info_extensions_vk)| { + inheritance_info.to_vk(inheritance_info_extensions_vk) + }); + + BeginInfoFields1Vk { + inheritance_info_vk, + } + } + + pub(crate) fn to_vk_fields1_extensions<'a>( + &self, + fields2_vk: &'a BeginInfoFields2Vk, + ) -> BeginInfoFields1ExtensionsVk<'a> { + let BeginInfoFields2Vk { + inheritance_info_fields1_vk, + } = fields2_vk; + + let inheritance_info_vk = self + .inheritance_info + .as_ref() + .zip(inheritance_info_fields1_vk.as_ref()) + .map(|(inheritance_info, inheritance_info_fields1_vk)| { + inheritance_info.to_vk_extensions(inheritance_info_fields1_vk) + }); + + BeginInfoFields1ExtensionsVk { + inheritance_info_vk, + } + } + + pub(crate) fn to_vk_fields2(&self) -> BeginInfoFields2Vk { + let inheritance_info_fields1_vk = self + .inheritance_info + .as_ref() + .map(|inheritance_info| inheritance_info.to_vk_fields1()); + + BeginInfoFields2Vk { + inheritance_info_fields1_vk, + } + } +} + +pub(crate) struct BeginInfoFields1Vk<'a> { + pub(crate) inheritance_info_vk: Option>, +} + +pub(crate) struct BeginInfoFields1ExtensionsVk<'a> { + pub(crate) inheritance_info_vk: Option>, +} + +pub(crate) struct BeginInfoFields2Vk { + pub(crate) inheritance_info_fields1_vk: Option, } /// A raw command buffer that has finished recording. diff --git a/vulkano/src/descriptor_set/layout.rs b/vulkano/src/descriptor_set/layout.rs index a064aa2f..3445ae9d 100644 --- a/vulkano/src/descriptor_set/layout.rs +++ b/vulkano/src/descriptor_set/layout.rs @@ -12,6 +12,7 @@ use crate::{ VulkanObject, }; use ahash::HashMap; +use smallvec::SmallVec; use std::{collections::BTreeMap, mem::MaybeUninit, num::NonZeroU64, ptr, sync::Arc}; /// Describes to the Vulkan implementation the layout of all descriptors within a descriptor set. @@ -86,78 +87,11 @@ impl DescriptorSetLayout { device: Arc, create_info: DescriptorSetLayoutCreateInfo, ) -> Result, VulkanError> { - let &DescriptorSetLayoutCreateInfo { - flags, - ref bindings, - _ne: _, - } = &create_info; - - struct PerBinding { - immutable_samplers_vk: Vec, - } - - let mut bindings_vk = Vec::with_capacity(bindings.len()); - let mut per_binding_vk = Vec::with_capacity(bindings.len()); - let mut binding_flags_info_vk = None; - let mut binding_flags_vk = Vec::with_capacity(bindings.len()); - - for (&binding_num, binding) in bindings.iter() { - let &DescriptorSetLayoutBinding { - binding_flags, - descriptor_type, - descriptor_count, - stages, - ref immutable_samplers, - _ne: _, - } = binding; - - bindings_vk.push(ash::vk::DescriptorSetLayoutBinding { - binding: binding_num, - descriptor_type: descriptor_type.into(), - descriptor_count, - stage_flags: stages.into(), - p_immutable_samplers: ptr::null(), - ..Default::default() - }); - per_binding_vk.push(PerBinding { - immutable_samplers_vk: immutable_samplers - .iter() - .map(VulkanObject::handle) - .collect(), - }); - binding_flags_vk.push(binding_flags.into()); - } - - for (binding_vk, per_binding_vk) in bindings_vk.iter_mut().zip(per_binding_vk.iter()) { - let PerBinding { - immutable_samplers_vk, - } = per_binding_vk; - - if !immutable_samplers_vk.is_empty() { - binding_vk.p_immutable_samplers = immutable_samplers_vk.as_ptr(); - } - } - - let mut create_info_vk = ash::vk::DescriptorSetLayoutCreateInfo { - flags: flags.into(), - binding_count: bindings_vk.len() as u32, - p_bindings: bindings_vk.as_ptr(), - ..Default::default() - }; - - if device.api_version() >= Version::V1_2 - || device.enabled_extensions().ext_descriptor_indexing - { - let next = - binding_flags_info_vk.insert(ash::vk::DescriptorSetLayoutBindingFlagsCreateInfo { - binding_count: binding_flags_vk.len() as u32, - p_binding_flags: binding_flags_vk.as_ptr(), - ..Default::default() - }); - - next.p_next = create_info_vk.p_next; - create_info_vk.p_next = <*const _>::cast(next); - } + let create_info_fields2_vk = create_info.to_vk_fields2(); + let create_info_fields1_vk = create_info.to_vk_fields1(&create_info_fields2_vk); + let mut create_info_extensions_vk = create_info.to_vk_extensions(&create_info_fields2_vk); + let create_info_vk = + create_info.to_vk(&create_info_fields1_vk, &mut create_info_extensions_vk); let handle = { let fns = device.fns(); @@ -313,6 +247,17 @@ pub struct DescriptorSetLayoutCreateInfo { pub _ne: crate::NonExhaustive, } +impl Default for DescriptorSetLayoutCreateInfo { + #[inline] + fn default() -> Self { + Self { + flags: DescriptorSetLayoutCreateFlags::empty(), + bindings: BTreeMap::new(), + _ne: crate::NonExhaustive(()), + } + } +} + impl DescriptorSetLayoutCreateInfo { pub(crate) fn validate(&self, device: &Device) -> Result<(), Box> { let &Self { @@ -480,19 +425,106 @@ impl DescriptorSetLayoutCreateInfo { Ok(()) } -} -impl Default for DescriptorSetLayoutCreateInfo { - #[inline] - fn default() -> Self { - Self { - flags: DescriptorSetLayoutCreateFlags::empty(), - bindings: BTreeMap::new(), - _ne: crate::NonExhaustive(()), + pub(crate) fn to_vk<'a>( + &self, + fields1_vk: &'a DescriptorSetLayoutCreateInfoFields1Vk<'_>, + extensions_vk: &'a mut DescriptorSetLayoutCreateInfoExtensionsVk<'_>, + ) -> ash::vk::DescriptorSetLayoutCreateInfo<'a> { + let &Self { + flags, + bindings: _, + _ne: _, + } = self; + let DescriptorSetLayoutCreateInfoFields1Vk { bindings_vk } = fields1_vk; + + let mut val_vk = ash::vk::DescriptorSetLayoutCreateInfo::default() + .flags(flags.into()) + .bindings(bindings_vk); + + let DescriptorSetLayoutCreateInfoExtensionsVk { binding_flags_vk } = extensions_vk; + + if let Some(next) = binding_flags_vk { + val_vk = val_vk.push_next(next); + } + + val_vk + } + + pub(crate) fn to_vk_fields1<'a>( + &self, + fields2_vk: &'a DescriptorSetLayoutCreateInfoFields2Vk, + ) -> DescriptorSetLayoutCreateInfoFields1Vk<'a> { + let DescriptorSetLayoutCreateInfoFields2Vk { + bindings_fields1_vk, + binding_flags_vk: _, + } = fields2_vk; + + let bindings_vk = self + .bindings + .iter() + .zip(bindings_fields1_vk) + .map(|((&binding_num, binding), binding_fields1_vk)| { + let DescriptorSetLayoutBindingFields1Vk { + immutable_samplers_vk, + } = binding_fields1_vk; + + binding.to_vk(binding_num, immutable_samplers_vk) + }) + .collect(); + + DescriptorSetLayoutCreateInfoFields1Vk { bindings_vk } + } + + pub(crate) fn to_vk_extensions<'a>( + &self, + fields2_vk: &'a DescriptorSetLayoutCreateInfoFields2Vk, + ) -> DescriptorSetLayoutCreateInfoExtensionsVk<'a> { + let DescriptorSetLayoutCreateInfoFields2Vk { + binding_flags_vk, .. + } = fields2_vk; + + let binding_flags_vk = self + .bindings + .values() + .any(|binding| !binding.binding_flags.is_empty()) + .then(|| { + ash::vk::DescriptorSetLayoutBindingFlagsCreateInfo::default() + .binding_flags(binding_flags_vk) + }); + + DescriptorSetLayoutCreateInfoExtensionsVk { binding_flags_vk } + } + + pub(crate) fn to_vk_fields2(&self) -> DescriptorSetLayoutCreateInfoFields2Vk { + let mut bindings_fields1_vk = SmallVec::new(); + let mut binding_flags_vk = SmallVec::new(); + + for binding in self.bindings.values() { + bindings_fields1_vk.push(binding.to_vk_fields1()); + binding_flags_vk.push(binding.to_vk_binding_flags()); + } + + DescriptorSetLayoutCreateInfoFields2Vk { + bindings_fields1_vk, + binding_flags_vk, } } } +pub(crate) struct DescriptorSetLayoutCreateInfoExtensionsVk<'a> { + pub(crate) binding_flags_vk: Option>, +} + +pub(crate) struct DescriptorSetLayoutCreateInfoFields1Vk<'a> { + pub(crate) bindings_vk: SmallVec<[ash::vk::DescriptorSetLayoutBinding<'a>; 4]>, +} + +pub(crate) struct DescriptorSetLayoutCreateInfoFields2Vk { + pub(crate) bindings_fields1_vk: SmallVec<[DescriptorSetLayoutBindingFields1Vk; 4]>, + pub(crate) binding_flags_vk: SmallVec<[ash::vk::DescriptorBindingFlags; 4]>, +} + vulkan_bitflags! { #[non_exhaustive] @@ -671,6 +703,21 @@ impl DescriptorSetLayoutBinding { _ne: _, } = self; + if !binding_flags.is_empty() + && !(device.api_version() >= Version::V1_2 + || device.enabled_extensions().ext_descriptor_indexing) + { + return Err(Box::new(ValidationError { + context: "binding_flags".into(), + problem: "is not empty".into(), + requires_one_of: RequiresOneOf(&[ + RequiresAllOf(&[Requires::APIVersion(Version::V1_2)]), + RequiresAllOf(&[Requires::DeviceExtension("ext_descriptor_indexing")]), + ]), + ..Default::default() + })); + } + binding_flags.validate_device(device).map_err(|err| { err.add_context("binding_flags").set_vuids(&[ "VUID-VkDescriptorSetLayoutBindingFlagsCreateInfo-pBindingFlags-parameter", @@ -1009,6 +1056,53 @@ impl DescriptorSetLayoutBinding { Ok(()) } + + pub(crate) fn to_vk<'a>( + &self, + binding_num: u32, + immutable_samplers_vk: &'a [ash::vk::Sampler], + ) -> ash::vk::DescriptorSetLayoutBinding<'a> { + let &Self { + binding_flags: _, + descriptor_type, + descriptor_count, + stages, + immutable_samplers: _, + _ne: _, + } = self; + + let mut binding_vk = ash::vk::DescriptorSetLayoutBinding::default() + .binding(binding_num) + .descriptor_type(descriptor_type.into()) + .descriptor_count(descriptor_count) + .stage_flags(stages.into()); + + if !immutable_samplers_vk.is_empty() { + binding_vk = binding_vk.immutable_samplers(immutable_samplers_vk); + } + + binding_vk + } + + pub(crate) fn to_vk_fields1(&self) -> DescriptorSetLayoutBindingFields1Vk { + let immutable_samplers_vk = self + .immutable_samplers + .iter() + .map(VulkanObject::handle) + .collect(); + + DescriptorSetLayoutBindingFields1Vk { + immutable_samplers_vk, + } + } + + pub(crate) fn to_vk_binding_flags(&self) -> ash::vk::DescriptorBindingFlags { + self.binding_flags.into() + } +} + +pub(crate) struct DescriptorSetLayoutBindingFields1Vk { + pub(crate) immutable_samplers_vk: Vec, } impl From<&DescriptorBindingRequirements> for DescriptorSetLayoutBinding { @@ -1043,11 +1137,7 @@ vulkan_bitflags! { /// descriptor type of the binding must be enabled. /// /// [`DescriptorPoolCreateFlags::UPDATE_AFTER_BIND`]: crate::descriptor_set::pool::DescriptorPoolCreateFlags::UPDATE_AFTER_BIND - UPDATE_AFTER_BIND = UPDATE_AFTER_BIND - RequiresOneOf([ - RequiresAllOf([APIVersion(V1_2)]), - RequiresAllOf([DeviceExtension(ext_descriptor_indexing)]), - ]), + UPDATE_AFTER_BIND = UPDATE_AFTER_BIND, /// Allows descriptors in this binding to be updated after a command buffer has already /// recorded a bind command containing a descriptor set with this layout, as long as the @@ -1064,11 +1154,7 @@ vulkan_bitflags! { /// being used, otherwise all *static use* by a shader invocation is considered used. /// /// [`descriptor_binding_update_unused_while_pending`]: crate::device::DeviceFeatures::descriptor_binding_update_unused_while_pending - UPDATE_UNUSED_WHILE_PENDING = UPDATE_UNUSED_WHILE_PENDING - RequiresOneOf([ - RequiresAllOf([APIVersion(V1_2)]), - RequiresAllOf([DeviceExtension(ext_descriptor_indexing)]), - ]), + UPDATE_UNUSED_WHILE_PENDING = UPDATE_UNUSED_WHILE_PENDING, /// Allows descriptors to be left empty or invalid even if they are *statically used* by a /// shader invocation, as long as they are not *dynamically used* . Additionally, if @@ -1079,11 +1165,7 @@ vulkan_bitflags! { /// The [`descriptor_binding_partially_bound`] feature must be enabled on the device. /// /// [`descriptor_binding_partially_bound`]: crate::device::DeviceFeatures::descriptor_binding_partially_bound - PARTIALLY_BOUND = PARTIALLY_BOUND - RequiresOneOf([ - RequiresAllOf([APIVersion(V1_2)]), - RequiresAllOf([DeviceExtension(ext_descriptor_indexing)]), - ]), + PARTIALLY_BOUND = PARTIALLY_BOUND, /// Whether the binding has a variable number of descriptors. /// @@ -1096,11 +1178,7 @@ vulkan_bitflags! { /// [`DescriptorType::UniformBufferDynamic`] or [`DescriptorType::StorageBufferDynamic`]. /// /// [`descriptor_binding_variable_descriptor_count`]: crate::device::DeviceFeatures::descriptor_binding_variable_descriptor_count - VARIABLE_DESCRIPTOR_COUNT = VARIABLE_DESCRIPTOR_COUNT - RequiresOneOf([ - RequiresAllOf([APIVersion(V1_2)]), - RequiresAllOf([DeviceExtension(ext_descriptor_indexing)]), - ]), + VARIABLE_DESCRIPTOR_COUNT = VARIABLE_DESCRIPTOR_COUNT, } vulkan_enum! { @@ -1253,6 +1331,70 @@ pub struct DescriptorSetLayoutSupport { pub max_variable_descriptor_count: u32, } +impl DescriptorSetLayoutSupport { + pub(crate) fn to_mut_vk( + extensions_vk: &mut DescriptorSetLayoutSupportExtensionsVk, + ) -> ash::vk::DescriptorSetLayoutSupport<'_> { + let mut val_vk = ash::vk::DescriptorSetLayoutSupport::default(); + + let DescriptorSetLayoutSupportExtensionsVk { + variable_descriptor_count_vk, + } = extensions_vk; + + if let Some(next) = variable_descriptor_count_vk { + val_vk = val_vk.push_next(next); + } + + val_vk + } + + pub(crate) fn to_mut_vk_extensions(device: &Device) -> DescriptorSetLayoutSupportExtensionsVk { + let variable_descriptor_count_vk = (device.api_version() >= Version::V1_2 + || device.enabled_extensions().ext_descriptor_indexing) + .then(ash::vk::DescriptorSetVariableDescriptorCountLayoutSupport::default); + + DescriptorSetLayoutSupportExtensionsVk { + variable_descriptor_count_vk, + } + } + + pub(crate) fn from_vk( + val_vk: &ash::vk::DescriptorSetLayoutSupport<'_>, + extensions_vk: &DescriptorSetLayoutSupportExtensionsVk, + ) -> Option { + let &ash::vk::DescriptorSetLayoutSupport { supported, .. } = val_vk; + + (supported != ash::vk::FALSE).then(|| { + let mut val = DescriptorSetLayoutSupport { + max_variable_descriptor_count: 0, + }; + + let DescriptorSetLayoutSupportExtensionsVk { + variable_descriptor_count_vk, + } = extensions_vk; + + if let Some(val_vk) = variable_descriptor_count_vk { + let &ash::vk::DescriptorSetVariableDescriptorCountLayoutSupport { + max_variable_descriptor_count, + .. + } = val_vk; + + val = Self { + max_variable_descriptor_count, + ..val + }; + } + + val + }) + } +} + +pub(crate) struct DescriptorSetLayoutSupportExtensionsVk { + pub(crate) variable_descriptor_count_vk: + Option>, +} + #[cfg(test)] mod tests { use crate::{ diff --git a/vulkano/src/descriptor_set/mod.rs b/vulkano/src/descriptor_set/mod.rs index 7d39d701..c858c02c 100644 --- a/vulkano/src/descriptor_set/mod.rs +++ b/vulkano/src/descriptor_set/mod.rs @@ -65,7 +65,6 @@ //! //! [`StandardDescriptorSetAllocator`]: allocator::StandardDescriptorSetAllocator -pub(crate) use self::update::DescriptorWriteInfo; use self::{ allocator::DescriptorSetAllocator, layout::DescriptorSetLayout, diff --git a/vulkano/src/descriptor_set/pool.rs b/vulkano/src/descriptor_set/pool.rs index 37efecec..e9b0f0e2 100644 --- a/vulkano/src/descriptor_set/pool.rs +++ b/vulkano/src/descriptor_set/pool.rs @@ -61,43 +61,10 @@ impl DescriptorPool { device: Arc, create_info: DescriptorPoolCreateInfo, ) -> Result { - let &DescriptorPoolCreateInfo { - flags, - max_sets, - ref pool_sizes, - max_inline_uniform_block_bindings, - _ne: _, - } = &create_info; - - let pool_sizes_vk: SmallVec<[_; 8]> = pool_sizes - .iter() - .map(|(&ty, &descriptor_count)| ash::vk::DescriptorPoolSize { - ty: ty.into(), - descriptor_count, - }) - .collect(); - - let mut create_info_vk = ash::vk::DescriptorPoolCreateInfo { - flags: flags.into(), - max_sets, - pool_size_count: pool_sizes_vk.len() as u32, - p_pool_sizes: pool_sizes_vk.as_ptr(), - ..Default::default() - }; - - let mut inline_uniform_block_create_info_vk = None; - - if max_inline_uniform_block_bindings != 0 { - let next = inline_uniform_block_create_info_vk.insert( - ash::vk::DescriptorPoolInlineUniformBlockCreateInfo { - max_inline_uniform_block_bindings, - ..Default::default() - }, - ); - - next.p_next = create_info_vk.p_next; - create_info_vk.p_next = <*const _>::cast(next); - } + let create_info_fields1_vk = create_info.to_vk_fields1(); + let mut create_info_extensions_vk = create_info.to_vk_extensions(); + let create_info_vk = + create_info.to_vk(&create_info_fields1_vk, &mut create_info_extensions_vk); let handle = unsafe { let fns = device.fns(); @@ -270,30 +237,22 @@ impl DescriptorPool { let mut output: SmallVec<[_; 1]> = SmallVec::new(); if !layouts_vk.is_empty() { - let variable_desc_count_alloc_info = if (self.device.api_version() >= Version::V1_2 + let mut variable_desc_count_alloc_info = None; + + let mut info_vk = ash::vk::DescriptorSetAllocateInfo::default() + .descriptor_pool(self.handle) + .set_layouts(&layouts_vk); + + if (self.device.api_version() >= Version::V1_2 || self.device.enabled_extensions().ext_descriptor_indexing) && variable_descriptor_counts.iter().any(|c| *c != 0) { - Some(ash::vk::DescriptorSetVariableDescriptorCountAllocateInfo { - descriptor_set_count: layouts_vk.len() as u32, - p_descriptor_counts: variable_descriptor_counts.as_ptr(), - ..Default::default() - }) - } else { - None - }; - - let info_vk = ash::vk::DescriptorSetAllocateInfo { - descriptor_pool: self.handle, - descriptor_set_count: layouts_vk.len() as u32, - p_set_layouts: layouts_vk.as_ptr(), - p_next: if let Some(next) = variable_desc_count_alloc_info.as_ref() { - <*const _>::cast(next) - } else { - ptr::null() - }, - ..Default::default() - }; + let next = variable_desc_count_alloc_info.insert( + ash::vk::DescriptorSetVariableDescriptorCountAllocateInfo::default() + .descriptor_counts(&variable_descriptor_counts), + ); + info_vk = info_vk.push_next(next); + } output.reserve(layouts_vk.len()); @@ -564,6 +523,69 @@ impl DescriptorPoolCreateInfo { Ok(()) } + + pub(crate) fn to_vk<'a>( + &self, + fields1_vk: &'a DescriptorPoolCreateInfoFields1Vk, + extensions_vk: &'a mut DescriptorPoolCreateInfoExtensionsVk, + ) -> ash::vk::DescriptorPoolCreateInfo<'a> { + let &Self { + flags, + max_sets, + pool_sizes: _, + max_inline_uniform_block_bindings: _, + _ne: _, + } = self; + let DescriptorPoolCreateInfoFields1Vk { pool_sizes_vk } = fields1_vk; + + let mut val_vk = ash::vk::DescriptorPoolCreateInfo::default() + .flags(flags.into()) + .max_sets(max_sets) + .pool_sizes(pool_sizes_vk); + + let DescriptorPoolCreateInfoExtensionsVk { + inline_uniform_block_vk, + } = extensions_vk; + + if let Some(next) = inline_uniform_block_vk { + val_vk = val_vk.push_next(next); + } + + val_vk + } + + pub(crate) fn to_vk_fields1(&self) -> DescriptorPoolCreateInfoFields1Vk { + let pool_sizes_vk = self + .pool_sizes + .iter() + .map(|(&ty, &descriptor_count)| ash::vk::DescriptorPoolSize { + ty: ty.into(), + descriptor_count, + }) + .collect(); + + DescriptorPoolCreateInfoFields1Vk { pool_sizes_vk } + } + + pub(crate) fn to_vk_extensions(&self) -> DescriptorPoolCreateInfoExtensionsVk { + let inline_uniform_block_vk = (self.max_inline_uniform_block_bindings != 0).then(|| { + ash::vk::DescriptorPoolInlineUniformBlockCreateInfo::default() + .max_inline_uniform_block_bindings(self.max_inline_uniform_block_bindings) + }); + + DescriptorPoolCreateInfoExtensionsVk { + inline_uniform_block_vk, + } + } +} + +pub(crate) struct DescriptorPoolCreateInfoExtensionsVk { + pub(crate) inline_uniform_block_vk: + Option>, +} + +pub(crate) struct DescriptorPoolCreateInfoFields1Vk { + pub(crate) pool_sizes_vk: SmallVec<[ash::vk::DescriptorPoolSize; 8]>, } vulkan_bitflags! { diff --git a/vulkano/src/descriptor_set/sys.rs b/vulkano/src/descriptor_set/sys.rs index f86deace..238a532d 100644 --- a/vulkano/src/descriptor_set/sys.rs +++ b/vulkano/src/descriptor_set/sys.rs @@ -6,10 +6,7 @@ use super::{ CopyDescriptorSet, }; use crate::{ - descriptor_set::{ - layout::DescriptorSetLayout, - update::{DescriptorWriteInfo, WriteDescriptorSet}, - }, + descriptor_set::{layout::DescriptorSetLayout, update::WriteDescriptorSet}, device::{Device, DeviceOwned}, Validated, ValidationError, VulkanError, VulkanObject, }; @@ -125,84 +122,39 @@ impl RawDescriptorSet { return; } - struct PerDescriptorWrite { - write_info: DescriptorWriteInfo, - acceleration_structures: ash::vk::WriteDescriptorSetAccelerationStructureKHR<'static>, - inline_uniform_block: ash::vk::WriteDescriptorSetInlineUniformBlock<'static>, - } + let set_layout_bindings = self.layout().bindings(); + let writes_fields1_vk: SmallVec<[_; 8]> = descriptor_writes + .iter() + .map(|write| { + let default_image_layout = set_layout_bindings[&write.binding()] + .descriptor_type + .default_image_layout(); + write.to_vk_fields1(default_image_layout) + }) + .collect(); + let mut write_extensions_vk: SmallVec<[_; 8]> = descriptor_writes + .iter() + .zip(&writes_fields1_vk) + .map(|(write, fields1_vk)| write.to_vk_extensions(fields1_vk)) + .collect(); + let writes_vk: SmallVec<[_; 8]> = descriptor_writes + .iter() + .zip(&writes_fields1_vk) + .zip(&mut write_extensions_vk) + .map(|((write, write_info_vk), write_extension_vk)| { + write.to_vk( + self.handle(), + set_layout_bindings[&write.binding()].descriptor_type, + write_info_vk, + write_extension_vk, + ) + }) + .collect(); - let mut writes_vk: SmallVec<[_; 8]> = SmallVec::with_capacity(descriptor_writes.len()); - let mut per_writes_vk: SmallVec<[_; 8]> = SmallVec::with_capacity(descriptor_writes.len()); - - for write in descriptor_writes { - let layout_binding = &self.layout().bindings()[&write.binding()]; - writes_vk.push(write.to_vulkan(self.handle(), layout_binding.descriptor_type)); - per_writes_vk.push(PerDescriptorWrite { - write_info: write.to_vulkan_info(layout_binding.descriptor_type), - acceleration_structures: Default::default(), - inline_uniform_block: Default::default(), - }); - } - - for (write_vk, per_write_vk) in writes_vk.iter_mut().zip(per_writes_vk.iter_mut()) { - match &mut per_write_vk.write_info { - DescriptorWriteInfo::Image(info) => { - write_vk.descriptor_count = info.len() as u32; - write_vk.p_image_info = info.as_ptr(); - } - DescriptorWriteInfo::Buffer(info) => { - write_vk.descriptor_count = info.len() as u32; - write_vk.p_buffer_info = info.as_ptr(); - } - DescriptorWriteInfo::BufferView(info) => { - write_vk.descriptor_count = info.len() as u32; - write_vk.p_texel_buffer_view = info.as_ptr(); - } - DescriptorWriteInfo::InlineUniformBlock(data) => { - write_vk.descriptor_count = data.len() as u32; - write_vk.p_next = <*const _>::cast(&per_write_vk.inline_uniform_block); - per_write_vk.inline_uniform_block.data_size = write_vk.descriptor_count; - per_write_vk.inline_uniform_block.p_data = data.as_ptr().cast(); - } - DescriptorWriteInfo::AccelerationStructure(info) => { - write_vk.descriptor_count = info.len() as u32; - write_vk.p_next = <*const _>::cast(&per_write_vk.acceleration_structures); - per_write_vk - .acceleration_structures - .acceleration_structure_count = write_vk.descriptor_count; - per_write_vk - .acceleration_structures - .p_acceleration_structures = info.as_ptr(); - } - } - - debug_assert!(write_vk.descriptor_count != 0); - } - - let mut copies_vk: SmallVec<[_; 8]> = SmallVec::with_capacity(descriptor_copies.len()); - - for copy in descriptor_copies { - let &CopyDescriptorSet { - ref src_set, - src_binding, - src_first_array_element, - dst_binding, - dst_first_array_element, - descriptor_count, - _ne: _, - } = copy; - - copies_vk.push(ash::vk::CopyDescriptorSet { - src_set: src_set.handle(), - src_binding, - src_array_element: src_first_array_element, - dst_set: self.handle(), - dst_binding, - dst_array_element: dst_first_array_element, - descriptor_count, - ..Default::default() - }); - } + let copies_vk: SmallVec<[_; 8]> = descriptor_copies + .iter() + .map(|copy| copy.to_vk(self.handle())) + .collect(); let fns = self.device().fns(); (fns.v1_0.update_descriptor_sets)( diff --git a/vulkano/src/descriptor_set/update.rs b/vulkano/src/descriptor_set/update.rs index 36c933b1..0816b824 100644 --- a/vulkano/src/descriptor_set/update.rs +++ b/vulkano/src/descriptor_set/update.rs @@ -19,7 +19,7 @@ use crate::{ DeviceSize, Requires, RequiresAllOf, RequiresOneOf, ValidationError, VulkanObject, }; use smallvec::SmallVec; -use std::{ops::Range, ptr, sync::Arc}; +use std::{ops::Range, sync::Arc}; /// Represents a single write operation to the binding of a descriptor set. /// @@ -1327,170 +1327,161 @@ impl WriteDescriptorSet { Ok(()) } - pub(crate) fn to_vulkan_info(&self, descriptor_type: DescriptorType) -> DescriptorWriteInfo { - let default_image_layout = descriptor_type.default_image_layout(); - - match &self.elements { - WriteDescriptorSetElements::None(num_elements) => { - debug_assert!(matches!(descriptor_type, DescriptorType::Sampler)); - DescriptorWriteInfo::Image( - std::iter::repeat_with(|| ash::vk::DescriptorImageInfo { - sampler: ash::vk::Sampler::null(), - image_view: ash::vk::ImageView::null(), - image_layout: ash::vk::ImageLayout::UNDEFINED, - }) - .take(*num_elements as usize) - .collect(), - ) - } - WriteDescriptorSetElements::Buffer(elements) => { - debug_assert!(matches!( - descriptor_type, - DescriptorType::UniformBuffer - | DescriptorType::StorageBuffer - | DescriptorType::UniformBufferDynamic - | DescriptorType::StorageBufferDynamic - )); - DescriptorWriteInfo::Buffer( - elements - .iter() - .map(|buffer_info| { - let DescriptorBufferInfo { buffer, range } = buffer_info; - - debug_assert!(!range.is_empty()); - debug_assert!(range.end <= buffer.buffer().size()); - - ash::vk::DescriptorBufferInfo { - buffer: buffer.buffer().handle(), - offset: buffer.offset() + range.start, - range: range.end - range.start, - } - }) - .collect(), - ) - } - WriteDescriptorSetElements::BufferView(elements) => { - debug_assert!(matches!( - descriptor_type, - DescriptorType::UniformTexelBuffer | DescriptorType::StorageTexelBuffer - )); - DescriptorWriteInfo::BufferView( - elements - .iter() - .map(|buffer_view| buffer_view.handle()) - .collect(), - ) - } - WriteDescriptorSetElements::ImageView(elements) => { - // NOTE: combined image sampler can occur with immutable samplers - debug_assert!(matches!( - descriptor_type, - DescriptorType::CombinedImageSampler - | DescriptorType::SampledImage - | DescriptorType::StorageImage - | DescriptorType::InputAttachment - )); - DescriptorWriteInfo::Image( - elements - .iter() - .map(|image_view_info| { - let &DescriptorImageViewInfo { - ref image_view, - mut image_layout, - } = image_view_info; - - if image_layout == ImageLayout::Undefined { - image_layout = default_image_layout; - } - - ash::vk::DescriptorImageInfo { - sampler: ash::vk::Sampler::null(), - image_view: image_view.handle(), - image_layout: image_layout.into(), - } - }) - .collect(), - ) - } - WriteDescriptorSetElements::ImageViewSampler(elements) => { - debug_assert!(matches!( - descriptor_type, - DescriptorType::CombinedImageSampler - )); - DescriptorWriteInfo::Image( - elements - .iter() - .map(|(image_view_info, sampler)| { - let &DescriptorImageViewInfo { - ref image_view, - mut image_layout, - } = image_view_info; - - if image_layout == ImageLayout::Undefined { - image_layout = default_image_layout; - } - - ash::vk::DescriptorImageInfo { - sampler: sampler.handle(), - image_view: image_view.handle(), - image_layout: image_layout.into(), - } - }) - .collect(), - ) - } - WriteDescriptorSetElements::Sampler(elements) => { - debug_assert!(matches!(descriptor_type, DescriptorType::Sampler)); - DescriptorWriteInfo::Image( - elements - .iter() - .map(|sampler| ash::vk::DescriptorImageInfo { - sampler: sampler.handle(), - image_view: ash::vk::ImageView::null(), - image_layout: ash::vk::ImageLayout::UNDEFINED, - }) - .collect(), - ) - } - WriteDescriptorSetElements::InlineUniformBlock(data) => { - debug_assert!(matches!( - descriptor_type, - DescriptorType::InlineUniformBlock - )); - DescriptorWriteInfo::InlineUniformBlock(data.clone()) - } - WriteDescriptorSetElements::AccelerationStructure(elements) => { - debug_assert!(matches!( - descriptor_type, - DescriptorType::AccelerationStructure - )); - DescriptorWriteInfo::AccelerationStructure( - elements - .iter() - .map(|acceleration_structure| acceleration_structure.handle()) - .collect(), - ) - } - } - } - - pub(crate) fn to_vulkan( + pub(crate) fn to_vk<'a>( &self, dst_set: ash::vk::DescriptorSet, descriptor_type: DescriptorType, - ) -> ash::vk::WriteDescriptorSet<'static> { - ash::vk::WriteDescriptorSet { - dst_set, - dst_binding: self.binding, - dst_array_element: self.first_array_element, - descriptor_count: 0, - descriptor_type: descriptor_type.into(), - p_image_info: ptr::null(), - p_buffer_info: ptr::null(), - p_texel_buffer_view: ptr::null(), - ..Default::default() + fields1_vk: &'a WriteDescriptorSetFields1, + extensions_vk: &'a mut WriteDescriptorSetExtensionsVk<'_>, + ) -> ash::vk::WriteDescriptorSet<'a> { + let &Self { + binding, + first_array_element, + elements: _, + } = self; + let WriteDescriptorSetFields1 { + descriptor_infos_vk, + } = fields1_vk; + + let mut val_vk = ash::vk::WriteDescriptorSet::default() + .dst_set(dst_set) + .dst_binding(binding) + .dst_array_element(first_array_element) + .descriptor_type(descriptor_type.into()); + + match descriptor_infos_vk { + DescriptorInfosVk::Image(info) => val_vk = val_vk.image_info(info), + DescriptorInfosVk::Buffer(info) => val_vk = val_vk.buffer_info(info), + DescriptorInfosVk::BufferView(info) => val_vk = val_vk.texel_buffer_view(info), + _ => (), + } + + let WriteDescriptorSetExtensionsVk { + descriptor_type_extension_vk, + } = extensions_vk; + + if let Some(descriptor_type_extension_vk) = descriptor_type_extension_vk { + match descriptor_type_extension_vk { + DescriptorTypeExtensionVk::AccelerationStructure(next) => { + val_vk = val_vk + .descriptor_count(next.acceleration_structure_count) + .push_next(next) + } + DescriptorTypeExtensionVk::InlineUniformBlock(next) => { + val_vk = val_vk.descriptor_count(next.data_size).push_next(next) + } + } + } + + debug_assert!(val_vk.descriptor_count != 0); + val_vk + } + + pub(crate) fn to_vk_extensions<'a>( + &self, + fields1_vk: &'a WriteDescriptorSetFields1, + ) -> WriteDescriptorSetExtensionsVk<'a> { + let WriteDescriptorSetFields1 { + descriptor_infos_vk, + } = fields1_vk; + + let descriptor_type_extension_vk = match descriptor_infos_vk { + DescriptorInfosVk::Image(_) + | DescriptorInfosVk::Buffer(_) + | DescriptorInfosVk::BufferView(_) => None, + DescriptorInfosVk::AccelerationStructure(info) => { + Some(DescriptorTypeExtensionVk::AccelerationStructure( + ash::vk::WriteDescriptorSetAccelerationStructureKHR::default() + .acceleration_structures(info), + )) + } + DescriptorInfosVk::InlineUniformBlock(data) => { + Some(DescriptorTypeExtensionVk::InlineUniformBlock( + ash::vk::WriteDescriptorSetInlineUniformBlock::default().data(data), + )) + } + }; + + WriteDescriptorSetExtensionsVk { + descriptor_type_extension_vk, } } + + pub(crate) fn to_vk_fields1( + &self, + default_image_layout: ImageLayout, + ) -> WriteDescriptorSetFields1 { + let descriptor_infos_vk = match &self.elements { + WriteDescriptorSetElements::None(num_elements) => DescriptorInfosVk::Image( + std::iter::repeat_with(ash::vk::DescriptorImageInfo::default) + .take(*num_elements as usize) + .collect(), + ), + WriteDescriptorSetElements::Buffer(elements) => DescriptorInfosVk::Buffer( + elements.iter().map(DescriptorBufferInfo::to_vk).collect(), + ), + WriteDescriptorSetElements::BufferView(elements) => { + DescriptorInfosVk::BufferView(elements.iter().map(VulkanObject::handle).collect()) + } + WriteDescriptorSetElements::ImageView(elements) => DescriptorInfosVk::Image( + elements + .iter() + .map(|image_view_info| image_view_info.to_vk(default_image_layout)) + .collect(), + ), + WriteDescriptorSetElements::ImageViewSampler(elements) => DescriptorInfosVk::Image( + elements + .iter() + .map(|(image_view_info, sampler)| ash::vk::DescriptorImageInfo { + sampler: sampler.handle(), + ..image_view_info.to_vk(default_image_layout) + }) + .collect(), + ), + WriteDescriptorSetElements::Sampler(elements) => DescriptorInfosVk::Image( + elements + .iter() + .map(|sampler| ash::vk::DescriptorImageInfo { + sampler: sampler.handle(), + ..Default::default() + }) + .collect(), + ), + WriteDescriptorSetElements::InlineUniformBlock(data) => { + DescriptorInfosVk::InlineUniformBlock(data.clone()) + } + WriteDescriptorSetElements::AccelerationStructure(elements) => { + DescriptorInfosVk::AccelerationStructure( + elements.iter().map(VulkanObject::handle).collect(), + ) + } + }; + + WriteDescriptorSetFields1 { + descriptor_infos_vk, + } + } +} + +pub(crate) struct WriteDescriptorSetExtensionsVk<'a> { + pub(crate) descriptor_type_extension_vk: Option>, +} + +pub(crate) enum DescriptorTypeExtensionVk<'a> { + AccelerationStructure(ash::vk::WriteDescriptorSetAccelerationStructureKHR<'a>), + InlineUniformBlock(ash::vk::WriteDescriptorSetInlineUniformBlock<'a>), +} + +pub(crate) struct WriteDescriptorSetFields1 { + pub(crate) descriptor_infos_vk: DescriptorInfosVk, +} + +pub(crate) enum DescriptorInfosVk { + Image(SmallVec<[ash::vk::DescriptorImageInfo; 1]>), + Buffer(SmallVec<[ash::vk::DescriptorBufferInfo; 1]>), + BufferView(SmallVec<[ash::vk::BufferView; 1]>), + InlineUniformBlock(Vec), + AccelerationStructure(SmallVec<[ash::vk::AccelerationStructureKHR; 1]>), } /// The elements held by a `WriteDescriptorSet`. @@ -1540,6 +1531,21 @@ pub struct DescriptorBufferInfo { pub range: Range, } +impl DescriptorBufferInfo { + pub(crate) fn to_vk(&self) -> ash::vk::DescriptorBufferInfo { + let Self { buffer, range } = self; + + debug_assert!(!range.is_empty()); + debug_assert!(range.end <= buffer.buffer().size()); + + ash::vk::DescriptorBufferInfo { + buffer: buffer.buffer().handle(), + offset: buffer.offset() + range.start, + range: range.end - range.start, + } + } +} + /// Parameters to write an image view reference to a descriptor. #[derive(Clone, Debug)] pub struct DescriptorImageViewInfo { @@ -1566,13 +1572,23 @@ pub struct DescriptorImageViewInfo { pub image_layout: ImageLayout, } -#[derive(Clone, Debug)] -pub(crate) enum DescriptorWriteInfo { - Image(SmallVec<[ash::vk::DescriptorImageInfo; 1]>), - Buffer(SmallVec<[ash::vk::DescriptorBufferInfo; 1]>), - BufferView(SmallVec<[ash::vk::BufferView; 1]>), - InlineUniformBlock(Vec), - AccelerationStructure(SmallVec<[ash::vk::AccelerationStructureKHR; 1]>), +impl DescriptorImageViewInfo { + pub(crate) fn to_vk(&self, default_image_layout: ImageLayout) -> ash::vk::DescriptorImageInfo { + let &Self { + ref image_view, + image_layout, + } = self; + + ash::vk::DescriptorImageInfo { + sampler: ash::vk::Sampler::null(), + image_view: image_view.handle(), + image_layout: if image_layout == ImageLayout::Undefined { + default_image_layout.into() + } else { + image_layout.into() + }, + } + } } /// Represents a single copy operation to the binding of a descriptor set. @@ -1833,6 +1849,30 @@ impl CopyDescriptorSet { Ok(()) } + + pub(crate) fn to_vk( + &self, + dst_set: ash::vk::DescriptorSet, + ) -> ash::vk::CopyDescriptorSet<'static> { + let &Self { + ref src_set, + src_binding, + src_first_array_element, + dst_binding, + dst_first_array_element, + descriptor_count, + _ne: _, + } = self; + + ash::vk::CopyDescriptorSet::default() + .src_set(src_set.handle()) + .src_binding(src_binding) + .src_array_element(src_first_array_element) + .dst_set(dst_set) + .dst_binding(dst_binding) + .dst_array_element(dst_first_array_element) + .descriptor_count(descriptor_count) + } } /// Invalidates descriptors within a descriptor set. Doesn't actually call into vulkan and only diff --git a/vulkano/src/device/mod.rs b/vulkano/src/device/mod.rs index 1b853da0..89253e2f 100644 --- a/vulkano/src/device/mod.rs +++ b/vulkano/src/device/mod.rs @@ -109,14 +109,11 @@ use crate::{ AccelerationStructureBuildType, AccelerationStructureGeometries, }, buffer::BufferCreateInfo, - descriptor_set::layout::{ - DescriptorSetLayoutBinding, DescriptorSetLayoutCreateInfo, DescriptorSetLayoutSupport, - }, - image::{ImageCreateFlags, ImageCreateInfo, ImageTiling}, + descriptor_set::layout::{DescriptorSetLayoutCreateInfo, DescriptorSetLayoutSupport}, + image::{sys::ImageCreateInfoExtensionsVk, ImageCreateFlags, ImageCreateInfo, ImageTiling}, instance::{Instance, InstanceOwned, InstanceOwnedDebugWrapper}, macros::{impl_id_counter, vulkan_bitflags}, - memory::{allocator::DeviceLayout, ExternalMemoryHandleType, MemoryRequirements}, - sync::Sharing, + memory::{ExternalMemoryHandleType, MemoryFdProperties, MemoryRequirements}, Requires, RequiresAllOf, RequiresOneOf, Validated, ValidationError, Version, VulkanError, VulkanObject, }; @@ -124,9 +121,10 @@ use ash::vk::Handle; use parking_lot::Mutex; use smallvec::{smallvec, SmallVec}; use std::{ - ffi::CString, + ffi::{c_char, CString}, fmt::{Debug, Error as FmtError, Formatter}, fs::File, + marker::PhantomData, mem::MaybeUninit, num::NonZeroU64, ops::Deref, @@ -334,121 +332,50 @@ impl Device { // VUID-VkPhysicalDeviceRobustness2FeaturesEXT-robustBufferAccess2-04000 enable_feature_required_features!(robust_buffer_access2, robust_buffer_access); - let &DeviceCreateInfo { - ref queue_create_infos, - ref enabled_extensions, - ref enabled_features, - ref physical_devices, - private_data_slot_request_count, - _ne: _, - } = &create_info; + let handle = { + let has_khr_get_physical_device_properties2 = physical_device.instance().api_version() + >= Version::V1_1 + || physical_device + .instance() + .enabled_extensions() + .khr_get_physical_device_properties2; - let queue_create_infos_vk: SmallVec<[_; 2]> = queue_create_infos - .iter() - .map(|queue_create_info| { - let &QueueCreateInfo { - flags, - queue_family_index, - ref queues, - _ne: _, - } = queue_create_info; + let mut features_ffi = DeviceFeaturesFfi::default(); + features_ffi.make_chain( + physical_device.api_version(), + &create_info.enabled_extensions, + physical_device.instance().enabled_extensions(), + ); + features_ffi.write(&create_info.enabled_features); - ash::vk::DeviceQueueCreateInfo { - flags: flags.into(), - queue_family_index, - queue_count: queues.len() as u32, - p_queue_priorities: queues.as_ptr(), - ..Default::default() - } - }) - .collect(); + // VUID-VkDeviceCreateInfo-pNext-00373 + let (features_vk, features2_vk) = if has_khr_get_physical_device_properties2 { + (None, Some(features_ffi.head_as_mut())) + } else { + (Some(&features_ffi.head_as_ref().features), None) + }; - let enabled_extensions_strings_vk = Vec::::from(enabled_extensions); - let enabled_extensions_ptrs_vk = enabled_extensions_strings_vk - .iter() - .map(|extension| extension.as_ptr()) - .collect::>(); + let create_info_fields2_vk = create_info.to_vk_fields2(); + let create_info_fields1_vk = + create_info.to_vk_fields1(&create_info_fields2_vk, features_vk); + let mut create_info_extensions = + create_info.to_vk_extensions(&create_info_fields1_vk, features2_vk); + let create_info_vk = + create_info.to_vk(&create_info_fields1_vk, &mut create_info_extensions); - let mut features_ffi = DeviceFeaturesFfi::default(); - features_ffi.make_chain( - physical_device.api_version(), - enabled_extensions, - physical_device.instance().enabled_extensions(), - ); - features_ffi.write(enabled_features); - - let has_khr_get_physical_device_properties2 = physical_device.instance().api_version() - >= Version::V1_1 - || physical_device - .instance() - .enabled_extensions() - .khr_get_physical_device_properties2; - - let mut create_info_vk = ash::vk::DeviceCreateInfo { - flags: ash::vk::DeviceCreateFlags::empty(), - queue_create_info_count: queue_create_infos_vk.len() as u32, - p_queue_create_infos: queue_create_infos_vk.as_ptr(), - enabled_extension_count: enabled_extensions_ptrs_vk.len() as u32, - pp_enabled_extension_names: enabled_extensions_ptrs_vk.as_ptr(), - p_enabled_features: ptr::null(), - ..Default::default() - }; - let mut device_group_create_info_vk = None; - let device_group_physical_devices_vk: SmallVec<[_; 2]>; - - // Length of zero and length of one are completely equivalent, - // so only do anything special here if more than one physical device was given. - // Spec: - // A logical device created without using VkDeviceGroupDeviceCreateInfo, - // or with physicalDeviceCount equal to zero, is equivalent to a physicalDeviceCount of one - // and pPhysicalDevices pointing to the physicalDevice parameter to vkCreateDevice. - if physical_devices.len() > 1 { - device_group_physical_devices_vk = physical_devices - .iter() - .map(|physical_device| physical_device.handle()) - .collect(); - - let next = device_group_create_info_vk.insert(ash::vk::DeviceGroupDeviceCreateInfo { - physical_device_count: device_group_physical_devices_vk.len() as u32, - p_physical_devices: device_group_physical_devices_vk.as_ptr(), - ..Default::default() - }); - - next.p_next = create_info_vk.p_next; - create_info_vk.p_next = <*mut _>::cast(next); - } - - let mut private_data_create_info_vk = None; - - if private_data_slot_request_count != 0 { - let next = private_data_create_info_vk.insert(ash::vk::DevicePrivateDataCreateInfo { - private_data_slot_request_count, - ..Default::default() - }); - - next.p_next = create_info_vk.p_next; - create_info_vk.p_next = <*mut _>::cast(next); - } - - // VUID-VkDeviceCreateInfo-pNext-00373 - if has_khr_get_physical_device_properties2 { - create_info_vk.p_next = <*const _>::cast(features_ffi.head_as_ref()); - } else { - create_info_vk.p_enabled_features = &features_ffi.head_as_ref().features; - } - - let handle = unsafe { - let fns = physical_device.instance().fns(); - let mut output = MaybeUninit::uninit(); - (fns.v1_0.create_device)( - physical_device.handle(), - &create_info_vk, - ptr::null(), - output.as_mut_ptr(), - ) - .result() - .map_err(VulkanError::from)?; - output.assume_init() + unsafe { + let fns = physical_device.instance().fns(); + let mut output = MaybeUninit::uninit(); + (fns.v1_0.create_device)( + physical_device.handle(), + &create_info_vk, + ptr::null(), + output.as_mut_ptr(), + ) + .result() + .map_err(VulkanError::from)?; + output.assume_init() + } }; Ok(Self::from_handle(physical_device, handle, create_info)) @@ -774,14 +701,10 @@ impl Device { build_info: &AccelerationStructureBuildGeometryInfo, max_primitive_counts: &[u32], ) -> AccelerationStructureBuildSizesInfo { - let (mut build_info_vk, geometries_vk) = build_info.to_vulkan(); - build_info_vk = ash::vk::AccelerationStructureBuildGeometryInfoKHR { - geometry_count: geometries_vk.len() as u32, - p_geometries: geometries_vk.as_ptr(), - ..build_info_vk - }; + let build_info_fields1_vk = build_info.to_vk_fields1(); + let build_info_vk = build_info.to_vk(&build_info_fields1_vk); - let mut build_sizes_info_vk = ash::vk::AccelerationStructureBuildSizesInfoKHR::default(); + let mut build_sizes_info_vk = AccelerationStructureBuildSizesInfo::to_mut_vk(); let fns = self.fns(); (fns.khr_acceleration_structure @@ -793,12 +716,7 @@ impl Device { &mut build_sizes_info_vk, ); - AccelerationStructureBuildSizesInfo { - acceleration_structure_size: build_sizes_info_vk.acceleration_structure_size, - update_scratch_size: build_sizes_info_vk.update_scratch_size, - build_scratch_size: build_sizes_info_vk.build_scratch_size, - _ne: crate::NonExhaustive(()), - } + AccelerationStructureBuildSizesInfo::from_vk(&build_sizes_info_vk) } /// Returns whether a serialized acceleration structure with the specified version data @@ -844,10 +762,8 @@ impl Device { &self, version_data: &[u8; 2 * ash::vk::UUID_SIZE], ) -> bool { - let version_info_vk = ash::vk::AccelerationStructureVersionInfoKHR { - p_version_data: version_data, - ..Default::default() - }; + let version_info_vk = + ash::vk::AccelerationStructureVersionInfoKHR::default().version_data(version_data); let mut compatibility_vk = ash::vk::AccelerationStructureCompatibilityKHR::default(); let fns = self.fns(); @@ -911,80 +827,14 @@ impl Device { &self, create_info: &DescriptorSetLayoutCreateInfo, ) -> Option { - let &DescriptorSetLayoutCreateInfo { - flags, - ref bindings, - _ne: _, - } = create_info; + let create_info_fields2_vk = create_info.to_vk_fields2(); + let create_info_fields1_vk = create_info.to_vk_fields1(&create_info_fields2_vk); + let mut create_info_extensions_vk = create_info.to_vk_extensions(&create_info_fields2_vk); + let create_info_vk = + create_info.to_vk(&create_info_fields1_vk, &mut create_info_extensions_vk); - struct PerBinding { - immutable_samplers_vk: Vec, - } - - let mut bindings_vk = Vec::with_capacity(bindings.len()); - let mut per_binding_vk = Vec::with_capacity(bindings.len()); - let mut binding_flags_info_vk = None; - let mut binding_flags_vk = Vec::with_capacity(bindings.len()); - - let mut support_vk = ash::vk::DescriptorSetLayoutSupport::default(); - let mut variable_descriptor_count_support_vk = None; - - for (&binding_num, binding) in bindings.iter() { - let &DescriptorSetLayoutBinding { - binding_flags, - descriptor_type, - descriptor_count, - stages, - ref immutable_samplers, - _ne: _, - } = binding; - - bindings_vk.push(ash::vk::DescriptorSetLayoutBinding { - binding: binding_num, - descriptor_type: descriptor_type.into(), - descriptor_count, - stage_flags: stages.into(), - p_immutable_samplers: ptr::null(), - ..Default::default() - }); - per_binding_vk.push(PerBinding { - immutable_samplers_vk: immutable_samplers - .iter() - .map(VulkanObject::handle) - .collect(), - }); - binding_flags_vk.push(binding_flags.into()); - } - - for (binding_vk, per_binding_vk) in bindings_vk.iter_mut().zip(per_binding_vk.iter_mut()) { - binding_vk.p_immutable_samplers = per_binding_vk.immutable_samplers_vk.as_ptr(); - } - - let mut create_info_vk = ash::vk::DescriptorSetLayoutCreateInfo { - flags: flags.into(), - binding_count: bindings_vk.len() as u32, - p_bindings: bindings_vk.as_ptr(), - ..Default::default() - }; - - if self.api_version() >= Version::V1_2 || self.enabled_extensions().ext_descriptor_indexing - { - let next = - binding_flags_info_vk.insert(ash::vk::DescriptorSetLayoutBindingFlagsCreateInfo { - binding_count: binding_flags_vk.len() as u32, - p_binding_flags: binding_flags_vk.as_ptr(), - ..Default::default() - }); - - next.p_next = create_info_vk.p_next; - create_info_vk.p_next = <*const _>::cast(next); - - let next = variable_descriptor_count_support_vk - .insert(ash::vk::DescriptorSetVariableDescriptorCountLayoutSupport::default()); - - next.p_next = support_vk.p_next; - support_vk.p_next = <*mut _>::cast(next); - } + let mut support_extensions_vk = DescriptorSetLayoutSupport::to_mut_vk_extensions(self); + let mut support_vk = DescriptorSetLayoutSupport::to_mut_vk(&mut support_extensions_vk); let fns = self.fns(); @@ -1002,10 +852,13 @@ impl Device { ) } - (support_vk.supported != ash::vk::FALSE).then(|| DescriptorSetLayoutSupport { - max_variable_descriptor_count: variable_descriptor_count_support_vk - .map_or(0, |s| s.max_variable_descriptor_count), - }) + // Unborrow + let support_vk = ash::vk::DescriptorSetLayoutSupport { + _marker: PhantomData, + ..support_vk + }; + + DescriptorSetLayoutSupport::from_vk(&support_vk, &support_extensions_vk) } /// Returns the memory requirements that would apply for a buffer created with the specified @@ -1051,62 +904,16 @@ impl Device { &self, create_info: BufferCreateInfo, ) -> MemoryRequirements { - let &BufferCreateInfo { - flags, - ref sharing, - size, - usage, - external_memory_handle_types, - _ne: _, - } = &create_info; + let mut extensions_vk = create_info.to_vk_extensions(); + let create_info_vk = create_info.to_vk(&mut extensions_vk); - let (sharing_mode, queue_family_index_count, p_queue_family_indices) = match sharing { - Sharing::Exclusive => (ash::vk::SharingMode::EXCLUSIVE, 0, ptr::null()), - Sharing::Concurrent(queue_family_indices) => ( - ash::vk::SharingMode::CONCURRENT, - queue_family_indices.len() as u32, - queue_family_indices.as_ptr(), - ), - }; + let info_vk = + ash::vk::DeviceBufferMemoryRequirements::default().create_info(&create_info_vk); - let mut create_info_vk = ash::vk::BufferCreateInfo { - flags: flags.into(), - size, - usage: usage.into(), - sharing_mode, - queue_family_index_count, - p_queue_family_indices, - ..Default::default() - }; - let mut external_memory_info_vk = None; - - if !external_memory_handle_types.is_empty() { - let next = external_memory_info_vk.insert(ash::vk::ExternalMemoryBufferCreateInfo { - handle_types: external_memory_handle_types.into(), - ..Default::default() - }); - - next.p_next = create_info_vk.p_next; - create_info_vk.p_next = <*const _>::cast(next); - } - - let info_vk = ash::vk::DeviceBufferMemoryRequirements { - p_create_info: &create_info_vk, - ..Default::default() - }; - - let mut memory_requirements2_vk = ash::vk::MemoryRequirements2::default(); - let mut memory_dedicated_requirements_vk = None; - - // `khr_maintenance4` requires Vulkan 1.1, - // which means dedicated allocation support is always available. - { - let next = memory_dedicated_requirements_vk - .insert(ash::vk::MemoryDedicatedRequirements::default()); - - next.p_next = memory_requirements2_vk.p_next; - memory_requirements2_vk.p_next = <*mut _>::cast(next); - } + let mut memory_requirements2_extensions_vk = + MemoryRequirements::to_mut_vk2_extensions(self); + let mut memory_requirements2_vk = + MemoryRequirements::to_mut_vk2(&mut memory_requirements2_extensions_vk); unsafe { let fns = self.fns(); @@ -1128,18 +935,16 @@ impl Device { } } - MemoryRequirements { - layout: DeviceLayout::from_size_alignment( - memory_requirements2_vk.memory_requirements.size, - memory_requirements2_vk.memory_requirements.alignment, - ) - .unwrap(), - memory_type_bits: memory_requirements2_vk.memory_requirements.memory_type_bits, - prefers_dedicated_allocation: memory_dedicated_requirements_vk - .map_or(false, |dreqs| dreqs.prefers_dedicated_allocation != 0), - requires_dedicated_allocation: memory_dedicated_requirements_vk - .map_or(false, |dreqs| dreqs.requires_dedicated_allocation != 0), - } + // Unborrow + let memory_requirements2_vk = ash::vk::MemoryRequirements2 { + _marker: PhantomData, + ..memory_requirements2_vk + }; + + MemoryRequirements::from_vk2( + &memory_requirements2_vk, + &memory_requirements2_extensions_vk, + ) } /// Returns the memory requirements that would apply for an image created with the specified @@ -1282,123 +1087,25 @@ impl Device { create_info: ImageCreateInfo, plane: Option, ) -> MemoryRequirements { - let &ImageCreateInfo { - flags, - image_type, - format, - ref view_formats, - extent, - array_layers, - mip_levels, - samples, - tiling, - usage, - stencil_usage, - ref sharing, - initial_layout, - ref drm_format_modifiers, - drm_format_modifier_plane_layouts: _, - external_memory_handle_types, - _ne: _, - } = &create_info; - - let (sharing_mode, queue_family_index_count, p_queue_family_indices) = match sharing { - Sharing::Exclusive => (ash::vk::SharingMode::EXCLUSIVE, 0, ptr::null()), - Sharing::Concurrent(queue_family_indices) => ( - ash::vk::SharingMode::CONCURRENT, - queue_family_indices.len() as u32, - queue_family_indices.as_ptr(), - ), + let create_info_fields1_vk = create_info.to_vk_fields1(); + let mut create_info_extensions_vk = ImageCreateInfoExtensionsVk { + drm_format_modifier_explicit_vk: None, + ..create_info.to_vk_extensions(&create_info_fields1_vk) }; - - let mut create_info_vk = ash::vk::ImageCreateInfo { - flags: flags.into(), - image_type: image_type.into(), - format: format.into(), - extent: ash::vk::Extent3D { - width: extent[0], - height: extent[1], - depth: extent[2], - }, - mip_levels, - array_layers, - samples: samples.into(), - tiling: tiling.into(), - usage: usage.into(), - sharing_mode, - queue_family_index_count, - p_queue_family_indices, - initial_layout: initial_layout.into(), - ..Default::default() - }; - let mut drm_format_modifier_list_info_vk = None; - let mut external_memory_info_vk = None; - let mut format_list_info_vk = None; - let format_list_view_formats_vk: Vec<_>; - let mut stencil_usage_info_vk = None; - - if !drm_format_modifiers.is_empty() { - let next = drm_format_modifier_list_info_vk.insert( - ash::vk::ImageDrmFormatModifierListCreateInfoEXT { - drm_format_modifier_count: drm_format_modifiers.len() as u32, - p_drm_format_modifiers: drm_format_modifiers.as_ptr(), - ..Default::default() - }, - ); - - next.p_next = create_info_vk.p_next; - create_info_vk.p_next = <*const _>::cast(next); - } - - if !external_memory_handle_types.is_empty() { - let next = external_memory_info_vk.insert(ash::vk::ExternalMemoryImageCreateInfo { - handle_types: external_memory_handle_types.into(), - ..Default::default() - }); - - next.p_next = create_info_vk.p_next; - create_info_vk.p_next = <*const _>::cast(next); - } - - if !view_formats.is_empty() { - format_list_view_formats_vk = view_formats - .iter() - .copied() - .map(ash::vk::Format::from) - .collect(); - - let next = format_list_info_vk.insert(ash::vk::ImageFormatListCreateInfo { - view_format_count: format_list_view_formats_vk.len() as u32, - p_view_formats: format_list_view_formats_vk.as_ptr(), - ..Default::default() - }); - - next.p_next = create_info_vk.p_next; - create_info_vk.p_next = <*const _>::cast(next); - } - - if let Some(stencil_usage) = stencil_usage { - let next = stencil_usage_info_vk.insert(ash::vk::ImageStencilUsageCreateInfo { - stencil_usage: stencil_usage.into(), - ..Default::default() - }); - - next.p_next = create_info_vk.p_next; - create_info_vk.p_next = <*const _>::cast(next); - } + let create_info_vk = create_info.to_vk(&mut create_info_extensions_vk); // This is currently necessary because of an issue with the spec. The plane aspect should // only be needed if the image is disjoint, but the spec currently demands a valid aspect // even for non-disjoint DRM format modifier images. // See: https://github.com/KhronosGroup/Vulkan-Docs/issues/2309 // Replace this variable with ash::vk::ImageAspectFlags::NONE when resolved. - let default_aspect = if tiling == ImageTiling::DrmFormatModifier { + let default_aspect = if create_info.tiling == ImageTiling::DrmFormatModifier { // Hopefully valid for any DrmFormatModifier image? ash::vk::ImageAspectFlags::MEMORY_PLANE_0_EXT } else { ash::vk::ImageAspectFlags::NONE }; - let plane_aspect = plane.map_or(default_aspect, |plane| match tiling { + let plane_aspect = plane.map_or(default_aspect, |plane| match create_info.tiling { ImageTiling::Optimal | ImageTiling::Linear => match plane { 0 => ash::vk::ImageAspectFlags::PLANE_0, 1 => ash::vk::ImageAspectFlags::PLANE_1, @@ -1414,24 +1121,14 @@ impl Device { }, }); - let info_vk = ash::vk::DeviceImageMemoryRequirements { - p_create_info: &create_info_vk, - plane_aspect, - ..Default::default() - }; + let info_vk = ash::vk::DeviceImageMemoryRequirements::default() + .create_info(&create_info_vk) + .plane_aspect(plane_aspect); - let mut memory_requirements2_vk = ash::vk::MemoryRequirements2::default(); - let mut memory_dedicated_requirements_vk = None; - - // `khr_maintenance4` requires Vulkan 1.1, - // which means dedicated allocation support is always available. - { - let next = memory_dedicated_requirements_vk - .insert(ash::vk::MemoryDedicatedRequirements::default()); - - next.p_next = memory_requirements2_vk.p_next; - memory_requirements2_vk.p_next = <*mut _>::cast(next); - } + let mut memory_requirements2_extensions_vk = + MemoryRequirements::to_mut_vk2_extensions(self); + let mut memory_requirements2_vk = + MemoryRequirements::to_mut_vk2(&mut memory_requirements2_extensions_vk); unsafe { let fns = self.fns(); @@ -1453,18 +1150,16 @@ impl Device { } } - MemoryRequirements { - layout: DeviceLayout::from_size_alignment( - memory_requirements2_vk.memory_requirements.size, - memory_requirements2_vk.memory_requirements.alignment, - ) - .unwrap(), - memory_type_bits: memory_requirements2_vk.memory_requirements.memory_type_bits, - prefers_dedicated_allocation: memory_dedicated_requirements_vk - .map_or(false, |dreqs| dreqs.prefers_dedicated_allocation != 0), - requires_dedicated_allocation: memory_dedicated_requirements_vk - .map_or(false, |dreqs| dreqs.requires_dedicated_allocation != 0), - } + // Unborrow + let memory_requirements2_vk = ash::vk::MemoryRequirements2 { + _marker: PhantomData, + ..memory_requirements2_vk + }; + + MemoryRequirements::from_vk2( + &memory_requirements2_vk, + &memory_requirements2_extensions_vk, + ) } // TODO: image_sparse_memory_requirements @@ -1527,7 +1222,7 @@ impl Device { handle_type: ExternalMemoryHandleType, file: File, ) -> Result { - let mut memory_fd_properties = ash::vk::MemoryFdPropertiesKHR::default(); + let mut memory_fd_properties = MemoryFdProperties::to_mut_vk(); #[cfg(unix)] let fd = { @@ -1551,9 +1246,7 @@ impl Device { .result() .map_err(VulkanError::from)?; - Ok(MemoryFdProperties { - memory_type_bits: memory_fd_properties.memory_type_bits, - }) + Ok(MemoryFdProperties::from_vk(&memory_fd_properties)) } /// Assigns a human-readable name to `object` for debugging purposes. @@ -1570,18 +1263,16 @@ impl Device { assert_eq!(object.device().handle(), self.handle()); let object_name_vk = object_name.map(|object_name| CString::new(object_name).unwrap()); - let info = ash::vk::DebugUtilsObjectNameInfoEXT { - object_type: T::Handle::TYPE, - object_handle: object.handle().as_raw(), - p_object_name: object_name_vk - .as_ref() - .map_or(ptr::null(), |object_name| object_name.as_ptr()), - ..Default::default() - }; + let mut info_vk = + ash::vk::DebugUtilsObjectNameInfoEXT::default().object_handle(object.handle()); + + if let Some(object_name_vk) = &object_name_vk { + info_vk = info_vk.object_name(object_name_vk); + } unsafe { let fns = self.fns(); - (fns.ext_debug_utils.set_debug_utils_object_name_ext)(self.handle, &info) + (fns.ext_debug_utils.set_debug_utils_object_name_ext)(self.handle, &info_vk) .result() .map_err(VulkanError::from)?; } @@ -2091,6 +1782,140 @@ impl DeviceCreateInfo { Ok(()) } + + pub(crate) fn to_vk<'a>( + &self, + fields1_vk: &'a DeviceCreateInfoFields1Vk<'_>, + extensions_vk: &'a mut DeviceCreateInfoExtensionsVk<'_, '_>, + ) -> ash::vk::DeviceCreateInfo<'a> { + let DeviceCreateInfoFields1Vk { + queue_create_infos_vk, + enabled_extension_names_vk, + features_vk, + device_group_physical_devices_vk: _, + } = fields1_vk; + + let mut val_vk = ash::vk::DeviceCreateInfo::default() + .flags(ash::vk::DeviceCreateFlags::empty()) + .queue_create_infos(queue_create_infos_vk) + .enabled_extension_names(enabled_extension_names_vk); + + if let Some(features_vk) = features_vk { + val_vk = val_vk.enabled_features(features_vk); + } + + let DeviceCreateInfoExtensionsVk { + device_group_vk, + features2_vk, + private_data_vk, + } = extensions_vk; + + if let Some(next) = device_group_vk { + val_vk = val_vk.push_next(next); + } + + if let Some(next) = features2_vk { + val_vk = val_vk.push_next(*next); + } + + if let Some(next) = private_data_vk { + val_vk = val_vk.push_next(next); + } + + val_vk + } + + pub(crate) fn to_vk_extensions<'a, 'b>( + &self, + fields1_vk: &'a DeviceCreateInfoFields1Vk<'_>, + features2_vk: Option<&'a mut ash::vk::PhysicalDeviceFeatures2<'b>>, + ) -> DeviceCreateInfoExtensionsVk<'a, 'b> { + let DeviceCreateInfoFields1Vk { + queue_create_infos_vk: _, + enabled_extension_names_vk: _, + features_vk: _, + device_group_physical_devices_vk, + } = fields1_vk; + + // Length of zero and length of one are completely equivalent, + // so only do anything special here if more than one physical device was given. + // Spec: + // A logical device created without using VkDeviceGroupDeviceCreateInfo, + // or with physicalDeviceCount equal to zero, is equivalent to a physicalDeviceCount of one + // and pPhysicalDevices pointing to the physicalDevice parameter to vkCreateDevice. + let device_group_vk = (device_group_physical_devices_vk.len() > 1).then(|| { + ash::vk::DeviceGroupDeviceCreateInfo::default() + .physical_devices(device_group_physical_devices_vk) + }); + + let private_data_vk = (self.private_data_slot_request_count != 0).then(|| { + ash::vk::DevicePrivateDataCreateInfo::default() + .private_data_slot_request_count(self.private_data_slot_request_count) + }); + + DeviceCreateInfoExtensionsVk { + device_group_vk, + features2_vk, + private_data_vk, + } + } + + pub(crate) fn to_vk_fields1<'a>( + &'a self, + fields2_vk: &'a DeviceCreateInfoFields2Vk, + features_vk: Option<&'a ash::vk::PhysicalDeviceFeatures>, + ) -> DeviceCreateInfoFields1Vk<'a> { + let DeviceCreateInfoFields2Vk { + enabled_extensions_vk, + } = fields2_vk; + + let queue_create_infos_vk = self + .queue_create_infos + .iter() + .map(QueueCreateInfo::to_vk) + .collect(); + let enabled_extension_names_vk = enabled_extensions_vk + .iter() + .map(|extension| extension.as_ptr()) + .collect(); + let device_group_physical_devices_vk = self + .physical_devices + .iter() + .map(VulkanObject::handle) + .collect(); + + DeviceCreateInfoFields1Vk { + queue_create_infos_vk, + enabled_extension_names_vk, + features_vk, + device_group_physical_devices_vk, + } + } + + pub(crate) fn to_vk_fields2(&self) -> DeviceCreateInfoFields2Vk { + let enabled_extensions_vk = Vec::::from(&self.enabled_extensions); + + DeviceCreateInfoFields2Vk { + enabled_extensions_vk, + } + } +} + +pub(crate) struct DeviceCreateInfoExtensionsVk<'a, 'b> { + pub(crate) device_group_vk: Option>, + pub(crate) features2_vk: Option<&'a mut ash::vk::PhysicalDeviceFeatures2<'b>>, + pub(crate) private_data_vk: Option>, +} + +pub(crate) struct DeviceCreateInfoFields1Vk<'a> { + pub(crate) queue_create_infos_vk: SmallVec<[ash::vk::DeviceQueueCreateInfo<'a>; 2]>, + pub(crate) enabled_extension_names_vk: SmallVec<[*const c_char; 16]>, + pub(crate) features_vk: Option<&'a ash::vk::PhysicalDeviceFeatures>, + pub(crate) device_group_physical_devices_vk: SmallVec<[ash::vk::PhysicalDevice; 2]>, +} + +pub(crate) struct DeviceCreateInfoFields2Vk { + pub(crate) enabled_extensions_vk: Vec, } /// Parameters to create queues in a new `Device`. @@ -2202,6 +2027,20 @@ impl QueueCreateInfo { Ok(()) } + + pub(crate) fn to_vk(&self) -> ash::vk::DeviceQueueCreateInfo<'_> { + let &Self { + flags, + queue_family_index, + ref queues, + _ne: _, + } = self; + + ash::vk::DeviceQueueCreateInfo::default() + .flags(flags.into()) + .queue_family_index(queue_family_index) + .queue_priorities(queues) + } } vulkan_bitflags! { @@ -2289,14 +2128,6 @@ impl Deref for DeviceOwnedDebugWrapper { } } -/// The properties of a Unix file descriptor when it is imported. -#[derive(Clone, Debug)] -#[non_exhaustive] -pub struct MemoryFdProperties { - /// A bitmask of the indices of memory types that can be used with the file. - pub memory_type_bits: u32, -} - #[cfg(test)] mod tests { use crate::device::{ diff --git a/vulkano/src/device/physical.rs b/vulkano/src/device/physical.rs index 52cf7b08..395304fd 100644 --- a/vulkano/src/device/physical.rs +++ b/vulkano/src/device/physical.rs @@ -7,22 +7,20 @@ use crate::{ DevicePropertiesFfi, }, display::{Display, DisplayPlaneProperties, DisplayPlanePropertiesRaw, DisplayProperties}, - format::{DrmFormatModifierProperties, Format, FormatProperties}, + format::{Format, FormatProperties}, image::{ - ImageDrmFormatModifierInfo, ImageFormatInfo, ImageFormatProperties, ImageUsage, - SparseImageFormatInfo, SparseImageFormatProperties, + ImageFormatInfo, ImageFormatProperties, SparseImageFormatInfo, SparseImageFormatProperties, }, instance::{Instance, InstanceOwned}, macros::{impl_id_counter, vulkan_bitflags, vulkan_enum}, memory::{ExternalMemoryHandleType, MemoryProperties}, swapchain::{ ColorSpace, FullScreenExclusive, PresentMode, Surface, SurfaceApi, SurfaceCapabilities, - SurfaceInfo, SurfaceTransforms, + SurfaceInfo, SurfaceInfo2ExtensionsVk, }, sync::{ fence::{ExternalFenceInfo, ExternalFenceProperties}, - semaphore::{ExternalSemaphoreInfo, ExternalSemaphoreProperties, SemaphoreType}, - Sharing, + semaphore::{ExternalSemaphoreInfo, ExternalSemaphoreProperties}, }, DebugWrapper, ExtensionProperties, Requires, RequiresAllOf, RequiresOneOf, Validated, ValidationError, Version, VulkanError, VulkanObject, @@ -32,6 +30,7 @@ use parking_lot::RwLock; use raw_window_handle::{HandleError, HasDisplayHandle, RawDisplayHandle}; use std::{ fmt::{Debug, Error as FmtError, Formatter}, + marker::PhantomData, mem::MaybeUninit, num::NonZeroU64, ptr, @@ -283,25 +282,25 @@ impl PhysicalDevice { let fns = instance.fns(); (fns.v1_0.get_physical_device_memory_properties)(handle, output.as_mut_ptr()); - output.assume_init().into() + MemoryProperties::from_vk(&output.assume_init()) } unsafe fn get_memory_properties2( handle: ash::vk::PhysicalDevice, instance: &Instance, ) -> MemoryProperties { - let mut output = ash::vk::PhysicalDeviceMemoryProperties2KHR::default(); + let mut properties_vk = MemoryProperties::to_mut_vk2(); let fns = instance.fns(); if instance.api_version() >= Version::V1_1 { - (fns.v1_1.get_physical_device_memory_properties2)(handle, &mut output); + (fns.v1_1.get_physical_device_memory_properties2)(handle, &mut properties_vk); } else { (fns.khr_get_physical_device_properties2 - .get_physical_device_memory_properties2_khr)(handle, &mut output); + .get_physical_device_memory_properties2_khr)(handle, &mut properties_vk); } - output.memory_properties.into() + MemoryProperties::from_vk2(&properties_vk) } unsafe fn get_queue_family_properties( @@ -321,7 +320,7 @@ impl PhysicalDevice { ); output.set_len(num as usize); - output.into_iter().map(Into::into).collect() + output.iter().map(QueueFamilyProperties::from_vk).collect() } unsafe fn get_queue_family_properties2( @@ -346,26 +345,26 @@ impl PhysicalDevice { ); } - let mut output = vec![ash::vk::QueueFamilyProperties2::default(); num as usize]; + let mut properties_vk = vec![QueueFamilyProperties::to_mut_vk2(); num as usize]; if instance.api_version() >= Version::V1_1 { (fns.v1_1.get_physical_device_queue_family_properties2)( handle, &mut num, - output.as_mut_ptr(), + properties_vk.as_mut_ptr(), ); } else { (fns.khr_get_physical_device_properties2 .get_physical_device_queue_family_properties2_khr)( handle, &mut num, - output.as_mut_ptr(), + properties_vk.as_mut_ptr(), ); } - output - .into_iter() - .map(|family| family.queue_family_properties.into()) + properties_vk + .iter() + .map(QueueFamilyProperties::from_vk2) .collect() } @@ -467,20 +466,19 @@ impl PhysicalDevice { .result() .map_err(VulkanError::from)?; - let mut properties = - vec![ash::vk::DisplayProperties2KHR::default(); count as usize]; + let mut properties_vk = vec![DisplayProperties::to_mut_vk2(); count as usize]; let result = (fns .khr_get_display_properties2 .get_physical_device_display_properties2_khr)( self.handle, &mut count, - properties.as_mut_ptr(), + properties_vk.as_mut_ptr(), ); match result { ash::vk::Result::SUCCESS => { - properties.set_len(count as usize); - break properties; + properties_vk.set_len(count as usize); + break properties_vk; } ash::vk::Result::INCOMPLETE => (), err => return Err(VulkanError::from(err)), @@ -489,33 +487,16 @@ impl PhysicalDevice { }; Ok(properties_vk - .into_iter() + .iter() .map(|properties_vk| { let properties_vk = &properties_vk.display_properties; self.display_properties .get_or_insert(properties_vk.display, |&handle| { - let properties = DisplayProperties { - name: properties_vk.display_name_as_c_str().map(|name| { - name.to_str() - .expect("non UTF-8 characters in display name") - .to_owned() - }), - physical_dimensions: [ - properties_vk.physical_dimensions.width, - properties_vk.physical_dimensions.height, - ], - physical_resolution: [ - properties_vk.physical_resolution.width, - properties_vk.physical_resolution.height, - ], - supported_transforms: properties_vk.supported_transforms.into(), - plane_reorder_possible: properties_vk.plane_reorder_possible - != ash::vk::FALSE, - persistent_content: properties_vk.persistent_content - != ash::vk::FALSE, - }; - - Display::from_handle(self.clone(), handle, properties) + Display::from_handle( + self.clone(), + handle, + DisplayProperties::from_vk(properties_vk), + ) }) }) .collect()) @@ -531,17 +512,17 @@ impl PhysicalDevice { .result() .map_err(VulkanError::from)?; - let mut properties = Vec::with_capacity(count as usize); + let mut properties_vk = Vec::with_capacity(count as usize); let result = (fns.khr_display.get_physical_device_display_properties_khr)( self.handle, &mut count, - properties.as_mut_ptr(), + properties_vk.as_mut_ptr(), ); match result { ash::vk::Result::SUCCESS => { - properties.set_len(count as usize); - break properties; + properties_vk.set_len(count as usize); + break properties_vk; } ash::vk::Result::INCOMPLETE => (), err => return Err(VulkanError::from(err)), @@ -550,32 +531,15 @@ impl PhysicalDevice { }; Ok(properties_vk - .into_iter() + .iter() .map(|properties_vk| { self.display_properties .get_or_insert(properties_vk.display, |&handle| { - let properties = DisplayProperties { - name: properties_vk.display_name_as_c_str().map(|name| { - name.to_str() - .expect("non UTF-8 characters in display name") - .to_owned() - }), - physical_dimensions: [ - properties_vk.physical_dimensions.width, - properties_vk.physical_dimensions.height, - ], - physical_resolution: [ - properties_vk.physical_resolution.width, - properties_vk.physical_resolution.height, - ], - supported_transforms: properties_vk.supported_transforms.into(), - plane_reorder_possible: properties_vk.plane_reorder_possible - != ash::vk::FALSE, - persistent_content: properties_vk.persistent_content - != ash::vk::FALSE, - }; - - Display::from_handle(self.clone(), handle, properties) + Display::from_handle( + self.clone(), + handle, + DisplayProperties::from_vk(properties_vk), + ) }) }) .collect()) @@ -674,7 +638,7 @@ impl PhysicalDevice { .map_err(VulkanError::from)?; let mut properties = - vec![ash::vk::DisplayPlaneProperties2KHR::default(); count as usize]; + vec![DisplayPlanePropertiesRaw::to_mut_vk2(); count as usize]; let result = (fns .khr_get_display_properties2 .get_physical_device_display_plane_properties2_khr)( @@ -695,14 +659,10 @@ impl PhysicalDevice { }; properties_vk - .into_iter() + .iter() .map(|properties_vk| { let properties_vk = &properties_vk.display_plane_properties; - DisplayPlanePropertiesRaw { - current_display: Some(properties_vk.current_display) - .filter(|&x| x != ash::vk::DisplayKHR::null()), - current_stack_index: properties_vk.current_stack_index, - } + DisplayPlanePropertiesRaw::from_vk(properties_vk) }) .collect() } else { @@ -739,12 +699,8 @@ impl PhysicalDevice { }; properties_vk - .into_iter() - .map(|properties_vk| DisplayPlanePropertiesRaw { - current_display: Some(properties_vk.current_display) - .filter(|&x| x != ash::vk::DisplayKHR::null()), - current_stack_index: properties_vk.current_stack_index, - }) + .iter() + .map(DisplayPlanePropertiesRaw::from_vk) .collect() }; @@ -915,23 +871,11 @@ impl PhysicalDevice { self.external_buffer_properties.get_or_insert(info, |info| { /* Input */ - let &ExternalBufferInfo { - flags, - usage, - handle_type, - _ne: _, - } = info; - - let external_buffer_info = ash::vk::PhysicalDeviceExternalBufferInfo { - flags: flags.into(), - usage: usage.into(), - handle_type: handle_type.into(), - ..Default::default() - }; + let info_vk = info.to_vk(); /* Output */ - let mut external_buffer_properties = ash::vk::ExternalBufferProperties::default(); + let mut properties_vk = ExternalBufferProperties::to_mut_vk(); /* Call */ @@ -940,23 +884,19 @@ impl PhysicalDevice { if self.instance.api_version() >= Version::V1_1 { (fns.v1_1.get_physical_device_external_buffer_properties)( self.handle, - &external_buffer_info, - &mut external_buffer_properties, + &info_vk, + &mut properties_vk, ) } else { (fns.khr_external_memory_capabilities .get_physical_device_external_buffer_properties_khr)( self.handle, - &external_buffer_info, - &mut external_buffer_properties, + &info_vk, + &mut properties_vk, ); } - ExternalBufferProperties { - external_memory_properties: external_buffer_properties - .external_memory_properties - .into(), - } + ExternalBufferProperties::from_vk(&properties_vk) }) } @@ -1015,19 +955,11 @@ impl PhysicalDevice { self.external_fence_properties.get_or_insert(info, |info| { /* Input */ - let &ExternalFenceInfo { - handle_type, - _ne: _, - } = info; - - let external_fence_info = ash::vk::PhysicalDeviceExternalFenceInfo { - handle_type: handle_type.into(), - ..Default::default() - }; + let info_vk = info.to_vk(); /* Output */ - let mut external_fence_properties = ash::vk::ExternalFenceProperties::default(); + let mut properties_vk = ExternalFenceProperties::to_mut_vk(); /* Call */ @@ -1036,30 +968,19 @@ impl PhysicalDevice { if self.instance.api_version() >= Version::V1_1 { (fns.v1_1.get_physical_device_external_fence_properties)( self.handle, - &external_fence_info, - &mut external_fence_properties, + &info_vk, + &mut properties_vk, ) } else { (fns.khr_external_fence_capabilities .get_physical_device_external_fence_properties_khr)( self.handle, - &external_fence_info, - &mut external_fence_properties, + &info_vk, + &mut properties_vk, ); } - ExternalFenceProperties { - exportable: external_fence_properties - .external_fence_features - .intersects(ash::vk::ExternalFenceFeatureFlags::EXPORTABLE), - importable: external_fence_properties - .external_fence_features - .intersects(ash::vk::ExternalFenceFeatureFlags::IMPORTABLE), - export_from_imported_handle_types: external_fence_properties - .export_from_imported_handle_types - .into(), - compatible_handle_types: external_fence_properties.compatible_handle_types.into(), - } + ExternalFenceProperties::from_vk(&properties_vk) }) } @@ -1119,35 +1040,12 @@ impl PhysicalDevice { .get_or_insert(info, |info| { /* Input */ - let &ExternalSemaphoreInfo { - handle_type, - semaphore_type, - initial_value, - _ne: _, - } = info; - - let mut external_semaphore_info_vk = ash::vk::PhysicalDeviceExternalSemaphoreInfo { - handle_type: handle_type.into(), - ..Default::default() - }; - let mut semaphore_type_create_info_vk = None; - - if semaphore_type != SemaphoreType::Binary { - let next = - semaphore_type_create_info_vk.insert(ash::vk::SemaphoreTypeCreateInfo { - semaphore_type: semaphore_type.into(), - initial_value, - ..Default::default() - }); - - next.p_next = external_semaphore_info_vk.p_next; - external_semaphore_info_vk.p_next = <*const _>::cast(next); - } + let mut info_extensions_vk = info.to_vk_extensions(); + let info_vk = info.to_vk(&mut info_extensions_vk); /* Output */ - let mut external_semaphore_properties = - ash::vk::ExternalSemaphoreProperties::default(); + let mut properties_vk = ExternalSemaphoreProperties::to_mut_vk(); /* Call */ @@ -1156,32 +1054,19 @@ impl PhysicalDevice { if self.instance.api_version() >= Version::V1_1 { (fns.v1_1.get_physical_device_external_semaphore_properties)( self.handle, - &external_semaphore_info_vk, - &mut external_semaphore_properties, + &info_vk, + &mut properties_vk, ) } else { (fns.khr_external_semaphore_capabilities .get_physical_device_external_semaphore_properties_khr)( self.handle, - &external_semaphore_info_vk, - &mut external_semaphore_properties, + &info_vk, + &mut properties_vk, ); } - ExternalSemaphoreProperties { - exportable: external_semaphore_properties - .external_semaphore_features - .intersects(ash::vk::ExternalSemaphoreFeatureFlags::EXPORTABLE), - importable: external_semaphore_properties - .external_semaphore_features - .intersects(ash::vk::ExternalSemaphoreFeatureFlags::IMPORTABLE), - export_from_imported_handle_types: external_semaphore_properties - .export_from_imported_handle_types - .into(), - compatible_handle_types: external_semaphore_properties - .compatible_handle_types - .into(), - } + ExternalSemaphoreProperties::from_vk(&properties_vk) }) } @@ -1212,48 +1097,13 @@ impl PhysicalDevice { #[inline] pub unsafe fn format_properties_unchecked(&self, format: Format) -> FormatProperties { self.format_properties.get_or_insert(format, |&format| { - let mut format_properties2_vk = ash::vk::FormatProperties2::default(); - let mut format_properties3_vk = None; - let mut drm_format_modifier_properties_list_vk = None; - let mut drm_format_modifier_properties_vk = Vec::new(); - let mut drm_format_modifier_properties_list2_vk = None; - let mut drm_format_modifier_properties2_vk = Vec::new(); - - if self.api_version() >= Version::V1_3 - || self.supported_extensions().khr_format_feature_flags2 - { - let next = format_properties3_vk.insert(ash::vk::FormatProperties3KHR::default()); - next.p_next = format_properties2_vk.p_next; - format_properties2_vk.p_next = <*mut _>::cast(next); - } - - if self.supported_extensions().ext_image_drm_format_modifier { - let next = drm_format_modifier_properties_list_vk - .insert(ash::vk::DrmFormatModifierPropertiesListEXT::default()); - next.p_next = format_properties2_vk.p_next; - format_properties2_vk.p_next = <*mut _>::cast(next); - - if self.api_version() >= Version::V1_3 - || self.supported_extensions().khr_format_feature_flags2 - { - let next = drm_format_modifier_properties_list2_vk - .insert(ash::vk::DrmFormatModifierPropertiesList2EXT::default()); - next.p_next = format_properties2_vk.p_next; - format_properties2_vk.p_next = <*mut _>::cast(next); - } - } - let fns = self.instance.fns(); - - // Get the number of DRM format modifier properties first. - if let Some(drm_format_modifier_properties_list_vk) = - &mut drm_format_modifier_properties_list_vk - { + let call = |format_properties2_vk: &mut ash::vk::FormatProperties2<'_>| { if self.api_version() >= Version::V1_1 { (fns.v1_1.get_physical_device_format_properties2)( self.handle, format.into(), - &mut format_properties2_vk, + format_properties2_vk, ); } else if self .instance @@ -1264,111 +1114,48 @@ impl PhysicalDevice { .get_physical_device_format_properties2_khr)( self.handle, format.into(), - &mut format_properties2_vk, + format_properties2_vk, + ); + } else { + (fns.v1_0.get_physical_device_format_properties)( + self.handle(), + format.into(), + &mut format_properties2_vk.format_properties, ); } + }; - drm_format_modifier_properties_vk = vec![ - ash::vk::DrmFormatModifierPropertiesEXT::default(); - drm_format_modifier_properties_list_vk.drm_format_modifier_count as usize - ]; - drm_format_modifier_properties_list_vk.p_drm_format_modifier_properties = - drm_format_modifier_properties_vk.as_mut_ptr(); + let mut properties2_fields1_vk = FormatProperties::to_mut_vk2_fields1( + FormatProperties::to_mut_vk2_extensions_query_count(self).map( + |mut properties2_extensions_query_count_vk| { + // If `to_mut_vk2_extensions_query_count` returns `Some`, we must query + // the element count and then pass it to `to_mut_vk2_fields1`. + let mut properties2_query_count_vk = FormatProperties::to_mut_vk2( + &mut properties2_extensions_query_count_vk, + ); + call(&mut properties2_query_count_vk); + properties2_extensions_query_count_vk + }, + ), + ); + let mut properties2_extensions_vk = + FormatProperties::to_mut_vk2_extensions(&mut properties2_fields1_vk, self); + let mut properties2_vk = FormatProperties::to_mut_vk2(&mut properties2_extensions_vk); - if let Some(drm_format_modifier_properties_list2_vk) = - &mut drm_format_modifier_properties_list2_vk - { - drm_format_modifier_properties2_vk = vec![ - ash::vk::DrmFormatModifierProperties2EXT::default(); - drm_format_modifier_properties_list2_vk.drm_format_modifier_count as usize - ]; - drm_format_modifier_properties_list2_vk.p_drm_format_modifier_properties = - drm_format_modifier_properties2_vk.as_mut_ptr(); - } - } + call(&mut properties2_vk); - if self.api_version() >= Version::V1_1 { - (fns.v1_1.get_physical_device_format_properties2)( - self.handle, - format.into(), - &mut format_properties2_vk, - ); - } else if self - .instance - .enabled_extensions() - .khr_get_physical_device_properties2 - { - (fns.khr_get_physical_device_properties2 - .get_physical_device_format_properties2_khr)( - self.handle, - format.into(), - &mut format_properties2_vk, - ); - } else { - (fns.v1_0.get_physical_device_format_properties)( - self.handle(), - format.into(), - &mut format_properties2_vk.format_properties, - ); - } + // Unborrow + let properties2_vk = ash::vk::FormatProperties2 { + _marker: PhantomData, + ..properties2_vk + }; + let properties2_extensions_vk = properties2_extensions_vk.unborrow(); - match format_properties3_vk { - Some(format_properties3) => { - FormatProperties { - linear_tiling_features: format_properties3.linear_tiling_features.into(), - optimal_tiling_features: format_properties3.optimal_tiling_features.into(), - buffer_features: format_properties3.buffer_features.into(), - drm_format_modifier_properties: drm_format_modifier_properties_list2_vk - .map_or(Vec::new(), |list2_vk| { - drm_format_modifier_properties2_vk - [..list2_vk.drm_format_modifier_count as usize] - .iter() - .map(|properties2_vk| DrmFormatModifierProperties { - drm_format_modifier: properties2_vk.drm_format_modifier, - drm_format_modifier_plane_count: properties2_vk - .drm_format_modifier_plane_count, - drm_format_modifier_tiling_features: properties2_vk - .drm_format_modifier_tiling_features - .into(), - }) - .collect() - }), - _ne: crate::NonExhaustive(()), - } - } - None => { - FormatProperties { - linear_tiling_features: format_properties2_vk - .format_properties - .linear_tiling_features - .into(), - optimal_tiling_features: format_properties2_vk - .format_properties - .optimal_tiling_features - .into(), - buffer_features: format_properties2_vk - .format_properties - .buffer_features - .into(), - drm_format_modifier_properties: drm_format_modifier_properties_list_vk - .map_or(Vec::new(), |list_vk| { - drm_format_modifier_properties_vk - [..list_vk.drm_format_modifier_count as usize] - .iter() - .map(|properties_vk| DrmFormatModifierProperties { - drm_format_modifier: properties_vk.drm_format_modifier, - drm_format_modifier_plane_count: properties_vk - .drm_format_modifier_plane_count, - drm_format_modifier_tiling_features: properties_vk - .drm_format_modifier_tiling_features - .into(), - }) - .collect() - }), - _ne: crate::NonExhaustive(()), - } - } - } + FormatProperties::from_vk2( + &properties2_vk, + &properties2_fields1_vk, + &properties2_extensions_vk, + ) }) } @@ -1412,137 +1199,17 @@ impl PhysicalDevice { self.image_format_properties .get_or_try_insert(image_format_info, |image_format_info| { /* Input */ - let &ImageFormatInfo { - flags, - format, - image_type, - tiling, - usage, - stencil_usage, - external_memory_handle_type, - image_view_type, - ref drm_format_modifier_info, - ref view_formats, - _ne: _, - } = image_format_info; - - let mut info2_vk = ash::vk::PhysicalDeviceImageFormatInfo2 { - format: format.into(), - ty: image_type.into(), - tiling: tiling.into(), - usage: usage.into(), - flags: flags.into(), - ..Default::default() - }; - let mut drm_format_modifier_info_vk = None; - let mut external_info_vk = None; - let mut format_list_info_vk = None; - let format_list_view_formats_vk: Vec<_>; - let mut image_view_info_vk = None; - let mut stencil_usage_info_vk = None; - - if let Some(drm_format_modifier_info) = drm_format_modifier_info { - let &ImageDrmFormatModifierInfo { - drm_format_modifier, - ref sharing, - _ne: _, - } = drm_format_modifier_info; - - let (sharing_mode, queue_family_index_count, p_queue_family_indices) = - match sharing { - Sharing::Exclusive => (ash::vk::SharingMode::EXCLUSIVE, 0, ptr::null()), - Sharing::Concurrent(queue_family_indices) => ( - ash::vk::SharingMode::CONCURRENT, - queue_family_indices.len() as u32, - queue_family_indices.as_ptr(), - ), - }; - - let next = drm_format_modifier_info_vk.insert( - ash::vk::PhysicalDeviceImageDrmFormatModifierInfoEXT { - drm_format_modifier, - sharing_mode, - queue_family_index_count, - p_queue_family_indices, - ..Default::default() - }, - ); - - next.p_next = info2_vk.p_next; - info2_vk.p_next = <*const _>::cast(next); - } - - if let Some(handle_type) = external_memory_handle_type { - let next = - external_info_vk.insert(ash::vk::PhysicalDeviceExternalImageFormatInfo { - handle_type: handle_type.into(), - ..Default::default() - }); - - next.p_next = info2_vk.p_next; - info2_vk.p_next = <*const _>::cast(next); - } - - if !view_formats.is_empty() { - format_list_view_formats_vk = view_formats - .iter() - .copied() - .map(ash::vk::Format::from) - .collect(); - - let next = format_list_info_vk.insert(ash::vk::ImageFormatListCreateInfo { - view_format_count: format_list_view_formats_vk.len() as u32, - p_view_formats: format_list_view_formats_vk.as_ptr(), - ..Default::default() - }); - - next.p_next = info2_vk.p_next; - info2_vk.p_next = <*const _>::cast(next); - } - - if let Some(image_view_type) = image_view_type { - let next = image_view_info_vk.insert( - ash::vk::PhysicalDeviceImageViewImageFormatInfoEXT { - image_view_type: image_view_type.into(), - ..Default::default() - }, - ); - - next.p_next = info2_vk.p_next.cast_mut(); - info2_vk.p_next = <*const _>::cast(next); - } - - if let Some(stencil_usage) = stencil_usage { - let next = stencil_usage_info_vk.insert(ash::vk::ImageStencilUsageCreateInfo { - stencil_usage: stencil_usage.into(), - ..Default::default() - }); - - next.p_next = info2_vk.p_next.cast_mut(); - info2_vk.p_next = <*const _>::cast(next); - } + let info2_fields1_vk = image_format_info.to_vk2_fields1(); + let mut info2_extensions_vk = + image_format_info.to_vk2_extensions(&info2_fields1_vk); + let info2_vk = image_format_info.to_vk2(&mut info2_extensions_vk); /* Output */ - let mut properties2_vk = ash::vk::ImageFormatProperties2::default(); - let mut external_properties_vk = None; - let mut filter_cubic_image_view_properties_vk = None; - - if external_info_vk.is_some() { - let next = external_properties_vk - .insert(ash::vk::ExternalImageFormatProperties::default()); - - next.p_next = properties2_vk.p_next; - properties2_vk.p_next = <*mut _>::cast(next); - } - - if image_view_info_vk.is_some() { - let next = filter_cubic_image_view_properties_vk - .insert(ash::vk::FilterCubicImageViewImageFormatPropertiesEXT::default()); - - next.p_next = properties2_vk.p_next; - properties2_vk.p_next = <*mut _>::cast(next); - } + let mut properties2_extensions_vk = + ImageFormatProperties::to_mut_vk2_extensions(image_format_info); + let mut properties2_vk = + ImageFormatProperties::to_mut_vk2(&mut properties2_extensions_vk); let result = { let fns = self.instance.fns(); @@ -1569,7 +1236,8 @@ impl PhysicalDevice { if !info2_vk.p_next.is_null() { return Ok(None); } - if let Some(ExternalMemoryHandleType::DmaBuf) = external_memory_handle_type + if let Some(ExternalMemoryHandleType::DmaBuf) = + image_format_info.external_memory_handle_type { // VUID-vkGetPhysicalDeviceImageFormatProperties-tiling-02248 // VUID-VkPhysicalDeviceImageFormatInfo2-tiling-02249 @@ -1590,24 +1258,20 @@ impl PhysicalDevice { .map_err(VulkanError::from) }; - Ok(match result { - Ok(_) => Some(ImageFormatProperties { - external_memory_properties: external_properties_vk - .map(|properties| properties.external_memory_properties.into()) - .unwrap_or_default(), - filter_cubic: filter_cubic_image_view_properties_vk - .map_or(false, |properties| { - properties.filter_cubic != ash::vk::FALSE - }), - filter_cubic_minmax: filter_cubic_image_view_properties_vk - .map_or(false, |properties| { - properties.filter_cubic_minmax != ash::vk::FALSE - }), - ..properties2_vk.image_format_properties.into() - }), - Err(VulkanError::FormatNotSupported) => None, - Err(err) => return Err(err), - }) + // Unborrow + let properties2_vk = ash::vk::ImageFormatProperties2 { + _marker: PhantomData, + ..properties2_vk + }; + + match result { + Ok(_) => Ok(Some(ImageFormatProperties::from_vk2( + &properties2_vk, + &properties2_extensions_vk, + ))), + Err(VulkanError::FormatNotSupported) => Ok(None), + Err(err) => Err(err), + } }) } @@ -1648,23 +1312,7 @@ impl PhysicalDevice { ) -> Vec { self.sparse_image_format_properties .get_or_insert(format_info, |format_info| { - let &SparseImageFormatInfo { - format, - image_type, - samples, - usage, - tiling, - _ne: _, - } = format_info; - - let format_info2 = ash::vk::PhysicalDeviceSparseImageFormatInfo2 { - format: format.into(), - ty: image_type.into(), - samples: samples.into(), - usage: usage.into(), - tiling: tiling.into(), - ..Default::default() - }; + let format_info2_vk = format_info.to_vk(); let fns = self.instance.fns(); @@ -1679,7 +1327,7 @@ impl PhysicalDevice { if self.api_version() >= Version::V1_1 { (fns.v1_1.get_physical_device_sparse_image_format_properties2)( self.handle, - &format_info2, + &format_info2_vk, &mut count, ptr::null_mut(), ); @@ -1687,19 +1335,19 @@ impl PhysicalDevice { (fns.khr_get_physical_device_properties2 .get_physical_device_sparse_image_format_properties2_khr)( self.handle, - &format_info2, + &format_info2_vk, &mut count, ptr::null_mut(), ); } let mut sparse_image_format_properties2 = - vec![ash::vk::SparseImageFormatProperties2::default(); count as usize]; + vec![SparseImageFormatProperties::to_mut_vk2(); count as usize]; if self.api_version() >= Version::V1_1 { (fns.v1_1.get_physical_device_sparse_image_format_properties2)( self.handle, - &format_info2, + &format_info2_vk, &mut count, sparse_image_format_properties2.as_mut_ptr(), ); @@ -1707,7 +1355,7 @@ impl PhysicalDevice { (fns.khr_get_physical_device_properties2 .get_physical_device_sparse_image_format_properties2_khr)( self.handle, - &format_info2, + &format_info2_vk, &mut count, sparse_image_format_properties2.as_mut_ptr(), ); @@ -1717,54 +1365,34 @@ impl PhysicalDevice { sparse_image_format_properties2 .into_iter() - .map( - |sparse_image_format_properties2| SparseImageFormatProperties { - aspects: sparse_image_format_properties2 - .properties - .aspect_mask - .into(), - image_granularity: [ - sparse_image_format_properties2 - .properties - .image_granularity - .width, - sparse_image_format_properties2 - .properties - .image_granularity - .height, - sparse_image_format_properties2 - .properties - .image_granularity - .depth, - ], - flags: sparse_image_format_properties2.properties.flags.into(), - }, - ) + .map(|properties2_vk| { + SparseImageFormatProperties::from_vk(&properties2_vk.properties) + }) .collect() } else { let mut count = 0; (fns.v1_0.get_physical_device_sparse_image_format_properties)( self.handle, - format_info2.format, - format_info2.ty, - format_info2.samples, - format_info2.usage, - format_info2.tiling, + format_info2_vk.format, + format_info2_vk.ty, + format_info2_vk.samples, + format_info2_vk.usage, + format_info2_vk.tiling, &mut count, ptr::null_mut(), ); let mut sparse_image_format_properties = - vec![ash::vk::SparseImageFormatProperties::default(); count as usize]; + vec![SparseImageFormatProperties::to_mut_vk(); count as usize]; (fns.v1_0.get_physical_device_sparse_image_format_properties)( self.handle, - format_info2.format, - format_info2.ty, - format_info2.samples, - format_info2.usage, - format_info2.tiling, + format_info2_vk.format, + format_info2_vk.ty, + format_info2_vk.samples, + format_info2_vk.usage, + format_info2_vk.tiling, &mut count, sparse_image_format_properties.as_mut_ptr(), ); @@ -1773,17 +1401,7 @@ impl PhysicalDevice { sparse_image_format_properties .into_iter() - .map( - |sparse_image_format_properties| SparseImageFormatProperties { - aspects: sparse_image_format_properties.aspect_mask.into(), - image_granularity: [ - sparse_image_format_properties.image_granularity.width, - sparse_image_format_properties.image_granularity.height, - sparse_image_format_properties.image_granularity.depth, - ], - flags: sparse_image_format_properties.flags.into(), - }, - ) + .map(|properties_vk| SparseImageFormatProperties::from_vk(&properties_vk)) .collect() } }) @@ -1921,106 +1539,18 @@ impl PhysicalDevice { ) -> Result { /* Input */ - let SurfaceInfo { - present_mode, - full_screen_exclusive, - win32_monitor, - _ne: _, - } = surface_info; - - let mut info_vk = ash::vk::PhysicalDeviceSurfaceInfo2KHR { - surface: surface.handle(), - ..Default::default() - }; - let mut present_mode_vk = None; - let mut full_screen_exclusive_info_vk = None; - let mut full_screen_exclusive_win32_info_vk = None; - - if let Some(present_mode) = present_mode { - let next = present_mode_vk.insert(ash::vk::SurfacePresentModeEXT { - present_mode: present_mode.into(), - ..Default::default() - }); - - next.p_next = info_vk.p_next.cast_mut(); - info_vk.p_next = <*const _>::cast(next); - } - - if full_screen_exclusive != FullScreenExclusive::Default { - let next = - full_screen_exclusive_info_vk.insert(ash::vk::SurfaceFullScreenExclusiveInfoEXT { - full_screen_exclusive: full_screen_exclusive.into(), - ..Default::default() - }); - - next.p_next = info_vk.p_next.cast_mut(); - info_vk.p_next = <*const _>::cast(next); - } - - if let Some(win32_monitor) = win32_monitor { - let next = full_screen_exclusive_win32_info_vk.insert( - ash::vk::SurfaceFullScreenExclusiveWin32InfoEXT { - hmonitor: win32_monitor.0, - ..Default::default() - }, - ); - - next.p_next = info_vk.p_next.cast_mut(); - info_vk.p_next = <*const _>::cast(next); - } + let mut info2_extensions_vk = surface_info.to_vk2_extensions(); + let info2_vk = surface_info.to_vk2(surface.handle(), &mut info2_extensions_vk); /* Output */ - let mut capabilities_vk = ash::vk::SurfaceCapabilities2KHR::default(); - let mut capabilities_full_screen_exclusive_vk = None; - let mut capabilities_present_modes_vk = - [ash::vk::PresentModeKHR::default(); PresentMode::COUNT]; - let mut capabilities_present_mode_compatibility_vk = None; - let mut capabilities_present_scaling_vk = None; - let mut capabilities_protected_vk = None; - - if full_screen_exclusive_info_vk.is_some() { - let next = capabilities_full_screen_exclusive_vk - .insert(ash::vk::SurfaceCapabilitiesFullScreenExclusiveEXT::default()); - - next.p_next = capabilities_vk.p_next.cast(); - capabilities_vk.p_next = <*mut _>::cast(next); - } - - if present_mode.is_some() { - { - let next = capabilities_present_mode_compatibility_vk.insert( - ash::vk::SurfacePresentModeCompatibilityEXT { - present_mode_count: capabilities_present_modes_vk.len() as u32, - p_present_modes: capabilities_present_modes_vk.as_mut_ptr(), - ..Default::default() - }, - ); - - next.p_next = capabilities_vk.p_next.cast(); - capabilities_vk.p_next = <*mut _>::cast(next); - } - - { - let next = capabilities_present_scaling_vk - .insert(ash::vk::SurfacePresentScalingCapabilitiesEXT::default()); - - next.p_next = capabilities_vk.p_next.cast(); - capabilities_vk.p_next = <*mut _>::cast(next); - } - } - - if self - .instance - .enabled_extensions() - .khr_surface_protected_capabilities - { - let next = capabilities_protected_vk - .insert(ash::vk::SurfaceProtectedCapabilitiesKHR::default()); - - next.p_next = capabilities_vk.p_next.cast(); - capabilities_vk.p_next = <*mut _>::cast(next); - } + let mut capabilities_fields1_vk = SurfaceCapabilities::to_mut_vk2_fields(); + let mut capabilities_extensions_vk = SurfaceCapabilities::to_mut_vk2_extensions( + &mut capabilities_fields1_vk, + self, + &surface_info, + ); + let mut capabilities_vk = SurfaceCapabilities::to_mut_vk2(&mut capabilities_extensions_vk); let fns = self.instance.fns(); @@ -2032,7 +1562,7 @@ impl PhysicalDevice { (fns.khr_get_surface_capabilities2 .get_physical_device_surface_capabilities2_khr)( self.handle(), - &info_vk, + &info2_vk, &mut capabilities_vk, ) .result() @@ -2040,126 +1570,25 @@ impl PhysicalDevice { } else { (fns.khr_surface.get_physical_device_surface_capabilities_khr)( self.handle(), - info_vk.surface, + info2_vk.surface, &mut capabilities_vk.surface_capabilities, ) .result() .map_err(VulkanError::from)?; }; - Ok(SurfaceCapabilities { - min_image_count: capabilities_vk.surface_capabilities.min_image_count, - max_image_count: (capabilities_vk.surface_capabilities.max_image_count != 0) - .then_some(capabilities_vk.surface_capabilities.max_image_count), - current_extent: (!matches!( - capabilities_vk.surface_capabilities.current_extent, - ash::vk::Extent2D { - width: u32::MAX, - height: u32::MAX - } - )) - .then_some([ - capabilities_vk.surface_capabilities.current_extent.width, - capabilities_vk.surface_capabilities.current_extent.height, - ]), - min_image_extent: [ - capabilities_vk.surface_capabilities.min_image_extent.width, - capabilities_vk.surface_capabilities.min_image_extent.height, - ], - max_image_extent: [ - capabilities_vk.surface_capabilities.max_image_extent.width, - capabilities_vk.surface_capabilities.max_image_extent.height, - ], - max_image_array_layers: capabilities_vk.surface_capabilities.max_image_array_layers, - supported_transforms: capabilities_vk - .surface_capabilities - .supported_transforms - .into(), + // Unborrow + let capabilities_vk = ash::vk::SurfaceCapabilities2KHR { + _marker: PhantomData, + ..capabilities_vk + }; + let capabilities_extensions_vk = capabilities_extensions_vk.unborrow(); - current_transform: SurfaceTransforms::from( - capabilities_vk.surface_capabilities.current_transform, - ) - .into_iter() - .next() - .unwrap(), // TODO: - supported_composite_alpha: capabilities_vk - .surface_capabilities - .supported_composite_alpha - .into(), - supported_usage_flags: ImageUsage::from( - capabilities_vk.surface_capabilities.supported_usage_flags, - ), - - compatible_present_modes: capabilities_present_mode_compatibility_vk.map_or_else( - Default::default, - |capabilities_present_mode_compatibility_vk| { - capabilities_present_modes_vk - [..capabilities_present_mode_compatibility_vk.present_mode_count as usize] - .iter() - .copied() - .map(PresentMode::try_from) - .filter_map(Result::ok) - .collect() - }, - ), - - supported_present_scaling: capabilities_present_scaling_vk - .as_ref() - .map_or_else(Default::default, |c| c.supported_present_scaling.into()), - supported_present_gravity: capabilities_present_scaling_vk.as_ref().map_or_else( - Default::default, - |c| { - [ - c.supported_present_gravity_x.into(), - c.supported_present_gravity_y.into(), - ] - }, - ), - min_scaled_image_extent: capabilities_present_scaling_vk.as_ref().map_or( - Some([ - capabilities_vk.surface_capabilities.min_image_extent.width, - capabilities_vk.surface_capabilities.min_image_extent.height, - ]), - |c| { - (!matches!( - c.min_scaled_image_extent, - ash::vk::Extent2D { - width: u32::MAX, - height: u32::MAX, - } - )) - .then_some([ - c.min_scaled_image_extent.width, - c.min_scaled_image_extent.height, - ]) - }, - ), - max_scaled_image_extent: capabilities_present_scaling_vk.as_ref().map_or( - Some([ - capabilities_vk.surface_capabilities.max_image_extent.width, - capabilities_vk.surface_capabilities.max_image_extent.height, - ]), - |c| { - (!matches!( - c.max_scaled_image_extent, - ash::vk::Extent2D { - width: u32::MAX, - height: u32::MAX, - } - )) - .then_some([ - c.max_scaled_image_extent.width, - c.max_scaled_image_extent.height, - ]) - }, - ), - - supports_protected: capabilities_protected_vk - .map_or(false, |c| c.supports_protected != 0), - - full_screen_exclusive_supported: capabilities_full_screen_exclusive_vk - .map_or(false, |c| c.full_screen_exclusive_supported != 0), - }) + Ok(SurfaceCapabilities::from_vk2( + &capabilities_vk, + &capabilities_fields1_vk, + &capabilities_extensions_vk, + )) } /// Returns the combinations of format and color space that are supported by the physical @@ -2324,54 +1753,8 @@ impl PhysicalDevice { surface.surface_formats.get_or_try_insert( (self.handle, surface_info), |(_, surface_info)| { - let &SurfaceInfo { - present_mode, - full_screen_exclusive, - win32_monitor, - _ne: _, - } = surface_info; - - let mut info_vk = ash::vk::PhysicalDeviceSurfaceInfo2KHR { - surface: surface.handle(), - ..Default::default() - }; - let mut present_mode_vk = None; - let mut full_screen_exclusive_info_vk = None; - let mut full_screen_exclusive_win32_info_vk = None; - - if let Some(present_mode) = present_mode { - let next = present_mode_vk.insert(ash::vk::SurfacePresentModeEXT { - present_mode: present_mode.into(), - ..Default::default() - }); - - next.p_next = info_vk.p_next.cast_mut(); - info_vk.p_next = <*const _>::cast(next); - } - - if full_screen_exclusive != FullScreenExclusive::Default { - let next = full_screen_exclusive_info_vk.insert( - ash::vk::SurfaceFullScreenExclusiveInfoEXT { - full_screen_exclusive: full_screen_exclusive.into(), - ..Default::default() - }, - ); - - next.p_next = info_vk.p_next.cast_mut(); - info_vk.p_next = <*const _>::cast(next); - } - - if let Some(win32_monitor) = win32_monitor { - let next = full_screen_exclusive_win32_info_vk.insert( - ash::vk::SurfaceFullScreenExclusiveWin32InfoEXT { - hmonitor: win32_monitor.0, - ..Default::default() - }, - ); - - next.p_next = info_vk.p_next.cast_mut(); - info_vk.p_next = <*const _>::cast(next); - } + let mut info2_extensions_vk = surface_info.to_vk2_extensions(); + let info2_vk = surface_info.to_vk2(surface.handle(), &mut info2_extensions_vk); let fns = self.instance.fns(); @@ -2385,7 +1768,7 @@ impl PhysicalDevice { (fns.khr_get_surface_capabilities2 .get_physical_device_surface_formats2_khr)( self.handle(), - &info_vk, + &info2_vk, &mut count, ptr::null_mut(), ) @@ -2398,7 +1781,7 @@ impl PhysicalDevice { .khr_get_surface_capabilities2 .get_physical_device_surface_formats2_khr)( self.handle(), - &info_vk, + &info2_vk, &mut count, surface_format2s_vk.as_mut_ptr(), ); @@ -2414,14 +1797,18 @@ impl PhysicalDevice { }; Ok(surface_format2s_vk - .into_iter() - .filter_map(|surface_format2| { - surface_format2 - .surface_format - .format - .try_into() - .ok() - .zip(surface_format2.surface_format.color_space.try_into().ok()) + .iter() + .filter_map(|surface_format2_vk| { + let &ash::vk::SurfaceFormat2KHR { + surface_format: + ash::vk::SurfaceFormatKHR { + format, + color_space, + }, + .. + } = surface_format2_vk; + + format.try_into().ok().zip(color_space.try_into().ok()) }) .collect()) } else { @@ -2455,13 +1842,14 @@ impl PhysicalDevice { }; Ok(surface_formats - .into_iter() - .filter_map(|surface_format| { - surface_format - .format - .try_into() - .ok() - .zip(surface_format.color_space.try_into().ok()) + .iter() + .filter_map(|surface_format_vk| { + let &ash::vk::SurfaceFormatKHR { + format, + color_space, + } = surface_format_vk; + + format.try_into().ok().zip(color_space.try_into().ok()) }) .collect()) } @@ -2602,43 +1990,11 @@ impl PhysicalDevice { surface.surface_present_modes.get_or_try_insert( (self.handle, surface_info), |(_, surface_info)| { - let &SurfaceInfo { - present_mode: _, - full_screen_exclusive, - win32_monitor, - _ne: _, - } = surface_info; - - let mut info_vk = ash::vk::PhysicalDeviceSurfaceInfo2KHR { - surface: surface.handle(), - ..Default::default() + let mut info2_extensions_vk = SurfaceInfo2ExtensionsVk { + present_mode_vk: None, + ..surface_info.to_vk2_extensions() }; - let mut full_screen_exclusive_info_vk = None; - let mut full_screen_exclusive_win32_info_vk = None; - - if full_screen_exclusive != FullScreenExclusive::Default { - let next = full_screen_exclusive_info_vk.insert( - ash::vk::SurfaceFullScreenExclusiveInfoEXT { - full_screen_exclusive: full_screen_exclusive.into(), - ..Default::default() - }, - ); - - next.p_next = info_vk.p_next.cast_mut(); - info_vk.p_next = <*const _>::cast(next); - } - - if let Some(win32_monitor) = win32_monitor { - let next = full_screen_exclusive_win32_info_vk.insert( - ash::vk::SurfaceFullScreenExclusiveWin32InfoEXT { - hmonitor: win32_monitor.0, - ..Default::default() - }, - ); - - next.p_next = info_vk.p_next.cast_mut(); - info_vk.p_next = <*const _>::cast(next); - } + let info2_vk = surface_info.to_vk2(surface.handle(), &mut info2_extensions_vk); let fns = self.instance.fns(); @@ -2648,7 +2004,7 @@ impl PhysicalDevice { (fns.ext_full_screen_exclusive .get_physical_device_surface_present_modes2_ext)( self.handle(), - &info_vk, + &info2_vk, &mut count, ptr::null_mut(), ) @@ -2660,7 +2016,7 @@ impl PhysicalDevice { .ext_full_screen_exclusive .get_physical_device_surface_present_modes2_ext)( self.handle(), - &info_vk, + &info2_vk, &mut count, modes.as_mut_ptr(), ); @@ -2868,30 +2224,8 @@ impl PhysicalDevice { tool_properties.set_len(count as usize); return Ok(tool_properties - .into_iter() - .map(|tool_properties| ToolProperties { - name: { - let bytes = cast_slice(tool_properties.name.as_slice()); - let end = bytes.iter().position(|&b| b == 0).unwrap_or(bytes.len()); - String::from_utf8_lossy(&bytes[0..end]).into() - }, - version: { - let bytes = cast_slice(tool_properties.version.as_slice()); - let end = bytes.iter().position(|&b| b == 0).unwrap_or(bytes.len()); - String::from_utf8_lossy(&bytes[0..end]).into() - }, - purposes: tool_properties.purposes.into(), - description: { - let bytes = cast_slice(tool_properties.description.as_slice()); - let end = bytes.iter().position(|&b| b == 0).unwrap_or(bytes.len()); - String::from_utf8_lossy(&bytes[0..end]).into() - }, - layer: { - let bytes = cast_slice(tool_properties.layer.as_slice()); - let end = bytes.iter().position(|&b| b == 0).unwrap_or(bytes.len()); - String::from_utf8_lossy(&bytes[0..end]).into() - }, - }) + .iter() + .map(ToolProperties::from_vk) .collect()); } err => return Err(VulkanError::from(err)), @@ -3673,6 +3007,43 @@ pub struct ToolProperties { pub layer: String, } +impl ToolProperties { + pub(crate) fn from_vk(val_vk: &ash::vk::PhysicalDeviceToolProperties<'_>) -> Self { + let &ash::vk::PhysicalDeviceToolProperties { + name, + version, + purposes, + description, + layer, + .. + } = val_vk; + + Self { + name: { + let bytes = cast_slice(name.as_slice()); + let end = bytes.iter().position(|&b| b == 0).unwrap_or(bytes.len()); + String::from_utf8_lossy(&bytes[0..end]).into() + }, + version: { + let bytes = cast_slice(version.as_slice()); + let end = bytes.iter().position(|&b| b == 0).unwrap_or(bytes.len()); + String::from_utf8_lossy(&bytes[0..end]).into() + }, + purposes: purposes.into(), + description: { + let bytes = cast_slice(description.as_slice()); + let end = bytes.iter().position(|&b| b == 0).unwrap_or(bytes.len()); + String::from_utf8_lossy(&bytes[0..end]).into() + }, + layer: { + let bytes = cast_slice(layer.as_slice()); + let end = bytes.iter().position(|&b| b == 0).unwrap_or(bytes.len()); + String::from_utf8_lossy(&bytes[0..end]).into() + }, + } + } +} + vulkan_bitflags! { #[non_exhaustive] diff --git a/vulkano/src/device/private_data.rs b/vulkano/src/device/private_data.rs index 13c8ba60..b4d2abc8 100644 --- a/vulkano/src/device/private_data.rs +++ b/vulkano/src/device/private_data.rs @@ -69,12 +69,7 @@ impl PrivateDataSlot { device: Arc, create_info: PrivateDataSlotCreateInfo, ) -> Result { - let &PrivateDataSlotCreateInfo { _ne: _ } = &create_info; - - let create_info_vk = ash::vk::PrivateDataSlotCreateInfo { - flags: ash::vk::PrivateDataSlotCreateFlags::empty(), - ..Default::default() - }; + let create_info_vk = create_info.to_vk(); let handle = { let fns = device.fns(); @@ -264,4 +259,11 @@ impl PrivateDataSlotCreateInfo { pub(crate) fn validate(&self, _device: &Device) -> Result<(), Box> { Ok(()) } + + pub(crate) fn to_vk(&self) -> ash::vk::PrivateDataSlotCreateInfo<'static> { + let &Self { _ne: _ } = self; + + ash::vk::PrivateDataSlotCreateInfo::default() + .flags(ash::vk::PrivateDataSlotCreateFlags::empty()) + } } diff --git a/vulkano/src/device/queue.rs b/vulkano/src/device/queue.rs index 87679074..ba0db366 100644 --- a/vulkano/src/device/queue.rs +++ b/vulkano/src/device/queue.rs @@ -3,21 +3,17 @@ use crate::{ command_buffer::{CommandBufferSubmitInfo, SemaphoreSubmitInfo, SubmitInfo}, instance::{debug::DebugUtilsLabel, InstanceOwnedDebugWrapper}, macros::vulkan_bitflags, - memory::{ - BindSparseInfo, SparseBufferMemoryBind, SparseImageMemoryBind, SparseImageOpaqueMemoryBind, - }, - swapchain::{PresentInfo, SemaphorePresentInfo, SwapchainPresentInfo}, - sync::{fence::Fence, semaphore::SemaphoreType, PipelineStages}, + memory::BindSparseInfo, + swapchain::{PresentInfo, SwapchainPresentInfo}, + sync::{fence::Fence, PipelineStages}, Requires, RequiresAllOf, RequiresOneOf, Validated, ValidationError, Version, VulkanError, VulkanObject, }; use parking_lot::{Mutex, MutexGuard}; use smallvec::SmallVec; use std::{ - ffi::CString, hash::{Hash, Hasher}, mem::MaybeUninit, - ptr, sync::Arc, }; @@ -37,19 +33,7 @@ pub struct Queue { impl Queue { pub(super) unsafe fn new(device: Arc, queue_info: DeviceQueueInfo) -> Arc { - let &DeviceQueueInfo { - flags, - queue_family_index, - queue_index, - _ne: _, - } = &queue_info; - - let queue_info_vk = ash::vk::DeviceQueueInfo2 { - flags: flags.into(), - queue_family_index, - queue_index, - ..Default::default() - }; + let queue_info_vk = queue_info.to_vk(); let fns = device.fns(); let mut output = MaybeUninit::uninit(); @@ -196,6 +180,22 @@ impl Default for DeviceQueueInfo { } } +impl DeviceQueueInfo { + pub(crate) fn to_vk(&self) -> ash::vk::DeviceQueueInfo2<'static> { + let &Self { + flags, + queue_family_index, + queue_index, + _ne: _, + } = self; + + ash::vk::DeviceQueueInfo2::default() + .flags(flags.into()) + .queue_family_index(queue_family_index) + .queue_index(queue_index) + } +} + pub struct QueueGuard<'a> { queue: &'a Arc, _state: MutexGuard<'a, QueueState>, @@ -226,243 +226,22 @@ impl<'a> QueueGuard<'a> { bind_infos: &[BindSparseInfo], fence: Option<&Arc>, ) -> Result<(), VulkanError> { - struct PerBindSparseInfo { - wait_semaphores_vk: SmallVec<[ash::vk::Semaphore; 4]>, - buffer_bind_infos_vk: SmallVec<[ash::vk::SparseBufferMemoryBindInfo<'static>; 4]>, - buffer_binds_vk: SmallVec<[SmallVec<[ash::vk::SparseMemoryBind; 4]>; 4]>, - image_opaque_bind_infos_vk: - SmallVec<[ash::vk::SparseImageOpaqueMemoryBindInfo<'static>; 4]>, - image_opaque_binds_vk: SmallVec<[SmallVec<[ash::vk::SparseMemoryBind; 4]>; 4]>, - image_bind_infos_vk: SmallVec<[ash::vk::SparseImageMemoryBindInfo<'static>; 4]>, - image_binds_vk: SmallVec<[SmallVec<[ash::vk::SparseImageMemoryBind; 4]>; 4]>, - signal_semaphores_vk: SmallVec<[ash::vk::Semaphore; 4]>, - } - - let (mut bind_infos_vk, mut per_bind_vk): (SmallVec<[_; 4]>, SmallVec<[_; 4]>) = bind_infos + let bind_infos_fields2_vk: SmallVec<[_; 4]> = bind_infos .iter() - .map(|bind_info| { - let &BindSparseInfo { - ref wait_semaphores, - ref buffer_binds, - ref image_opaque_binds, - ref image_binds, - ref signal_semaphores, - _ne: _, - } = bind_info; + .map(BindSparseInfo::to_vk_fields2) + .collect(); - let wait_semaphores_vk: SmallVec<[_; 4]> = wait_semaphores - .iter() - .map(|semaphore| semaphore.handle()) - .collect(); + let bind_infos_fields1_vk: SmallVec<[_; 4]> = bind_infos + .iter() + .zip(&bind_infos_fields2_vk) + .map(|(bind_info, fields2_vk)| bind_info.to_vk_fields1(fields2_vk)) + .collect(); - let (buffer_bind_infos_vk, buffer_binds_vk): (SmallVec<[_; 4]>, SmallVec<[_; 4]>) = - buffer_binds - .iter() - .map(|(buffer, memory_binds)| { - ( - ash::vk::SparseBufferMemoryBindInfo::default() - .buffer(buffer.buffer().handle()), - memory_binds - .iter() - .map(|memory_bind| { - let &SparseBufferMemoryBind { - offset, - size, - ref memory, - } = memory_bind; - - let (memory, memory_offset) = memory.as_ref().map_or_else( - Default::default, - |(memory, memory_offset)| { - (memory.handle(), *memory_offset) - }, - ); - - ash::vk::SparseMemoryBind { - resource_offset: offset, - size, - memory, - memory_offset, - flags: ash::vk::SparseMemoryBindFlags::empty(), - } - }) - .collect::>(), - ) - }) - .unzip(); - - let (image_opaque_bind_infos_vk, image_opaque_binds_vk): ( - SmallVec<[_; 4]>, - SmallVec<[_; 4]>, - ) = image_opaque_binds - .iter() - .map(|(image, memory_binds)| { - ( - ash::vk::SparseImageOpaqueMemoryBindInfo::default() - .image(image.handle()), - memory_binds - .iter() - .map(|memory_bind| { - let &SparseImageOpaqueMemoryBind { - offset, - size, - ref memory, - metadata, - } = memory_bind; - - let (memory, memory_offset) = memory.as_ref().map_or_else( - Default::default, - |(memory, memory_offset)| (memory.handle(), *memory_offset), - ); - - ash::vk::SparseMemoryBind { - resource_offset: offset, - size, - memory, - memory_offset, - flags: if metadata { - ash::vk::SparseMemoryBindFlags::METADATA - } else { - ash::vk::SparseMemoryBindFlags::empty() - }, - } - }) - .collect::>(), - ) - }) - .unzip(); - - let (image_bind_infos_vk, image_binds_vk): (SmallVec<[_; 4]>, SmallVec<[_; 4]>) = - image_binds - .iter() - .map(|(image, memory_binds)| { - ( - ash::vk::SparseImageMemoryBindInfo::default().image(image.handle()), - memory_binds - .iter() - .map(|memory_bind| { - let &SparseImageMemoryBind { - aspects, - mip_level, - array_layer, - offset, - extent, - ref memory, - } = memory_bind; - - let (memory, memory_offset) = memory.as_ref().map_or_else( - Default::default, - |(memory, memory_offset)| { - (memory.handle(), *memory_offset) - }, - ); - - ash::vk::SparseImageMemoryBind { - subresource: ash::vk::ImageSubresource { - aspect_mask: aspects.into(), - mip_level, - array_layer, - }, - offset: ash::vk::Offset3D { - x: offset[0] as i32, - y: offset[1] as i32, - z: offset[2] as i32, - }, - extent: ash::vk::Extent3D { - width: extent[0], - height: extent[1], - depth: extent[2], - }, - memory, - memory_offset, - flags: ash::vk::SparseMemoryBindFlags::empty(), - } - }) - .collect::>(), - ) - }) - .unzip(); - - let signal_semaphores_vk: SmallVec<[_; 4]> = signal_semaphores - .iter() - .map(|semaphore| semaphore.handle()) - .collect(); - - ( - ash::vk::BindSparseInfo::default(), - PerBindSparseInfo { - wait_semaphores_vk, - buffer_bind_infos_vk, - buffer_binds_vk, - image_opaque_bind_infos_vk, - image_opaque_binds_vk, - image_bind_infos_vk, - image_binds_vk, - signal_semaphores_vk, - }, - ) - }) - .unzip(); - - for ( - bind_info_vk, - PerBindSparseInfo { - wait_semaphores_vk, - buffer_bind_infos_vk, - buffer_binds_vk, - image_opaque_bind_infos_vk, - image_opaque_binds_vk, - image_bind_infos_vk, - image_binds_vk, - signal_semaphores_vk, - }, - ) in bind_infos_vk.iter_mut().zip(per_bind_vk.iter_mut()) - { - for (buffer_bind_infos_vk, buffer_binds_vk) in - buffer_bind_infos_vk.iter_mut().zip(buffer_binds_vk.iter()) - { - *buffer_bind_infos_vk = ash::vk::SparseBufferMemoryBindInfo { - bind_count: buffer_binds_vk.len() as u32, - p_binds: buffer_binds_vk.as_ptr(), - ..*buffer_bind_infos_vk - }; - } - - for (image_opaque_bind_infos_vk, image_opaque_binds_vk) in image_opaque_bind_infos_vk - .iter_mut() - .zip(image_opaque_binds_vk.iter()) - { - *image_opaque_bind_infos_vk = ash::vk::SparseImageOpaqueMemoryBindInfo { - bind_count: image_opaque_binds_vk.len() as u32, - p_binds: image_opaque_binds_vk.as_ptr(), - ..*image_opaque_bind_infos_vk - }; - } - - for (image_bind_infos_vk, image_binds_vk) in - image_bind_infos_vk.iter_mut().zip(image_binds_vk.iter()) - { - *image_bind_infos_vk = ash::vk::SparseImageMemoryBindInfo { - bind_count: image_binds_vk.len() as u32, - p_binds: image_binds_vk.as_ptr(), - ..*image_bind_infos_vk - }; - } - - *bind_info_vk = ash::vk::BindSparseInfo { - wait_semaphore_count: wait_semaphores_vk.len() as u32, - p_wait_semaphores: wait_semaphores_vk.as_ptr(), - buffer_bind_count: buffer_bind_infos_vk.len() as u32, - p_buffer_binds: buffer_bind_infos_vk.as_ptr(), - image_opaque_bind_count: image_opaque_bind_infos_vk.len() as u32, - p_image_opaque_binds: image_opaque_bind_infos_vk.as_ptr(), - image_bind_count: image_bind_infos_vk.len() as u32, - p_image_binds: image_bind_infos_vk.as_ptr(), - signal_semaphore_count: signal_semaphores_vk.len() as u32, - p_signal_semaphores: signal_semaphores_vk.as_ptr(), - ..*bind_info_vk - } - } + let bind_infos_vk: SmallVec<[_; 4]> = bind_infos + .iter() + .zip(&bind_infos_fields1_vk) + .map(|(bind_info, fields1_vk)| bind_info.to_vk(fields1_vk)) + .collect(); let fns = self.queue.device.fns(); (fns.v1_0.queue_bind_sparse)( @@ -529,7 +308,7 @@ impl<'a> QueueGuard<'a> { let &PresentInfo { wait_semaphores: _, - ref swapchains, + swapchain_infos: ref swapchains, _ne: _, } = present_info; @@ -539,7 +318,7 @@ impl<'a> QueueGuard<'a> { image_index: _, present_id: _, present_mode: _, - present_regions: _, + present_region: _, _ne: _, } = swapchain_info; @@ -576,123 +355,16 @@ impl<'a> QueueGuard<'a> { &mut self, present_info: &PresentInfo, ) -> Result>, VulkanError> { - let PresentInfo { - wait_semaphores, - swapchains, - _ne: _, - } = present_info; - - let wait_semaphores_vk: SmallVec<[_; 4]> = wait_semaphores - .iter() - .map(|semaphore_present_info| { - let &SemaphorePresentInfo { - ref semaphore, - _ne: _, - } = semaphore_present_info; - - semaphore.handle() - }) - .collect(); - - let mut swapchains_vk: SmallVec<[_; 4]> = SmallVec::with_capacity(swapchains.len()); - let mut image_indices_vk: SmallVec<[_; 4]> = SmallVec::with_capacity(swapchains.len()); - let mut present_ids_vk: SmallVec<[_; 4]> = SmallVec::with_capacity(swapchains.len()); - let mut present_modes_vk: SmallVec<[_; 4]> = SmallVec::with_capacity(swapchains.len()); - let mut rectangles_vk: SmallVec<[_; 4]> = SmallVec::with_capacity(swapchains.len()); - let mut present_regions_vk: SmallVec<[_; 4]> = SmallVec::with_capacity(swapchains.len()); - - let mut has_present_ids = false; - let mut has_present_modes = false; - let mut has_present_regions = false; - - for swapchain_info in swapchains { - let &SwapchainPresentInfo { - ref swapchain, - image_index, - present_id, - present_mode, - ref present_regions, - _ne: _, - } = swapchain_info; - - swapchains_vk.push(swapchain.handle()); - image_indices_vk.push(image_index); - present_ids_vk.push(present_id.map_or(0, u64::from)); - present_modes_vk.push(present_mode.map_or_else(Default::default, Into::into)); - present_regions_vk.push(ash::vk::PresentRegionKHR::default()); - rectangles_vk.push( - present_regions - .iter() - .map(ash::vk::RectLayerKHR::from) - .collect::>(), - ); - - if present_id.is_some() { - has_present_ids = true; - } - - if present_mode.is_some() { - has_present_modes = true; - } - - if !present_regions.is_empty() { - has_present_regions = true; - } - } - - let mut results = vec![ash::vk::Result::SUCCESS; swapchains.len()]; - let mut info_vk = ash::vk::PresentInfoKHR { - wait_semaphore_count: wait_semaphores_vk.len() as u32, - p_wait_semaphores: wait_semaphores_vk.as_ptr(), - swapchain_count: swapchains_vk.len() as u32, - p_swapchains: swapchains_vk.as_ptr(), - p_image_indices: image_indices_vk.as_ptr(), - p_results: results.as_mut_ptr(), - ..Default::default() - }; - let mut present_id_info_vk = None; - let mut present_mode_info_vk = None; - let mut present_region_info_vk = None; - - if has_present_ids { - let next = present_id_info_vk.insert(ash::vk::PresentIdKHR { - swapchain_count: present_ids_vk.len() as u32, - p_present_ids: present_ids_vk.as_ptr(), - ..Default::default() - }); - - next.p_next = info_vk.p_next; - info_vk.p_next = <*const _>::cast(next); - } - - if has_present_modes { - let next = present_mode_info_vk.insert(ash::vk::SwapchainPresentModeInfoEXT { - swapchain_count: present_modes_vk.len() as u32, - p_present_modes: present_modes_vk.as_ptr(), - ..Default::default() - }); - - next.p_next = info_vk.p_next.cast(); - info_vk.p_next = <*const _>::cast(next); - } - - if has_present_regions { - for (present_regions_vk, rectangles_vk) in - present_regions_vk.iter_mut().zip(rectangles_vk.iter()) - { - *present_regions_vk = - ash::vk::PresentRegionKHR::default().rectangles(rectangles_vk); - } - - let next = present_region_info_vk.insert(ash::vk::PresentRegionsKHR { - swapchain_count: present_regions_vk.len() as u32, - p_regions: present_regions_vk.as_ptr(), - ..Default::default() - }); - - next.p_next = info_vk.p_next; - info_vk.p_next = <*const _>::cast(next); - } + let present_info_fields2_vk = present_info.to_vk_fields2(); + let present_info_fields1_vk = present_info.to_vk_fields1(&present_info_fields2_vk); + let mut results_vk = present_info.to_vk_results(); + let mut present_info_extensions_vk = + present_info.to_vk_extensions(&present_info_fields1_vk); + let info_vk = present_info.to_vk( + &present_info_fields1_vk, + &mut results_vk, + &mut present_info_extensions_vk, + ); let fns = self.queue.device().fns(); let result = (fns.khr_swapchain.queue_present_khr)(self.queue.handle, &info_vk); @@ -712,7 +384,7 @@ impl<'a> QueueGuard<'a> { return Err(VulkanError::from(result)); } - Ok(results.into_iter().map(|result| match result { + Ok(results_vk.into_iter().map(|result| match result { ash::vk::Result::SUCCESS => Ok(false), ash::vk::Result::SUBOPTIMAL_KHR => Ok(true), err => Err(VulkanError::from(err)), @@ -895,126 +567,24 @@ impl<'a> QueueGuard<'a> { fence: Option<&Arc>, ) -> Result<(), VulkanError> { if self.queue.device.enabled_features().synchronization2 { - struct PerSubmitInfo { - wait_semaphore_infos_vk: SmallVec<[ash::vk::SemaphoreSubmitInfo<'static>; 4]>, - command_buffer_infos_vk: SmallVec<[ash::vk::CommandBufferSubmitInfo<'static>; 4]>, - signal_semaphore_infos_vk: SmallVec<[ash::vk::SemaphoreSubmitInfo<'static>; 4]>, - } + let submit_infos_fields1_vk: SmallVec<[_; 4]> = submit_infos + .iter() + .map(SubmitInfo::to_vk2_fields1) + .collect(); - let (mut submit_info_vk, mut per_submit_vk): (SmallVec<[_; 4]>, SmallVec<[_; 4]>) = - submit_infos - .iter() - .map(|submit_info| { - let &SubmitInfo { - ref wait_semaphores, - ref command_buffers, - ref signal_semaphores, - _ne: _, - } = submit_info; - - let mut per_submit_vk = PerSubmitInfo { - wait_semaphore_infos_vk: SmallVec::with_capacity(wait_semaphores.len()), - command_buffer_infos_vk: SmallVec::with_capacity(command_buffers.len()), - signal_semaphore_infos_vk: SmallVec::with_capacity( - signal_semaphores.len(), - ), - }; - let PerSubmitInfo { - wait_semaphore_infos_vk, - command_buffer_infos_vk, - signal_semaphore_infos_vk, - } = &mut per_submit_vk; - - for semaphore_submit_info in wait_semaphores { - let &SemaphoreSubmitInfo { - ref semaphore, - value, - stages, - _ne: _, - } = semaphore_submit_info; - - wait_semaphore_infos_vk.push(ash::vk::SemaphoreSubmitInfo { - semaphore: semaphore.handle(), - value, - stage_mask: stages.into(), - device_index: 0, // TODO: - ..Default::default() - }); - } - - for command_buffer_submit_info in command_buffers { - let &CommandBufferSubmitInfo { - ref command_buffer, - _ne: _, - } = command_buffer_submit_info; - - command_buffer_infos_vk.push(ash::vk::CommandBufferSubmitInfo { - command_buffer: command_buffer.handle(), - device_mask: 0, // TODO: - ..Default::default() - }); - } - - for semaphore_submit_info in signal_semaphores { - let &SemaphoreSubmitInfo { - ref semaphore, - value, - stages, - _ne: _, - } = semaphore_submit_info; - - signal_semaphore_infos_vk.push(ash::vk::SemaphoreSubmitInfo { - semaphore: semaphore.handle(), - value, - stage_mask: stages.into(), - device_index: 0, // TODO: - ..Default::default() - }); - } - - ( - ash::vk::SubmitInfo2 { - flags: ash::vk::SubmitFlags::empty(), // TODO: - wait_semaphore_info_count: 0, - p_wait_semaphore_infos: ptr::null(), - command_buffer_info_count: 0, - p_command_buffer_infos: ptr::null(), - signal_semaphore_info_count: 0, - p_signal_semaphore_infos: ptr::null(), - ..Default::default() - }, - per_submit_vk, - ) - }) - .unzip(); - - for ( - submit_info_vk, - PerSubmitInfo { - wait_semaphore_infos_vk, - command_buffer_infos_vk, - signal_semaphore_infos_vk, - }, - ) in submit_info_vk.iter_mut().zip(per_submit_vk.iter_mut()) - { - *submit_info_vk = ash::vk::SubmitInfo2 { - wait_semaphore_info_count: wait_semaphore_infos_vk.len() as u32, - p_wait_semaphore_infos: wait_semaphore_infos_vk.as_ptr(), - command_buffer_info_count: command_buffer_infos_vk.len() as u32, - p_command_buffer_infos: command_buffer_infos_vk.as_ptr(), - signal_semaphore_info_count: signal_semaphore_infos_vk.len() as u32, - p_signal_semaphore_infos: signal_semaphore_infos_vk.as_ptr(), - ..*submit_info_vk - }; - } + let submit_infos_vk: SmallVec<[_; 4]> = submit_infos + .iter() + .zip(&submit_infos_fields1_vk) + .map(|(submit_info, fields1_vk)| submit_info.to_vk2(fields1_vk)) + .collect(); let fns = self.queue.device.fns(); if self.queue.device.api_version() >= Version::V1_3 { (fns.v1_3.queue_submit2)( self.queue.handle, - submit_info_vk.len() as u32, - submit_info_vk.as_ptr(), + submit_infos_vk.len() as u32, + submit_infos_vk.as_ptr(), fence .as_ref() .map_or_else(Default::default, VulkanObject::handle), @@ -1023,8 +593,8 @@ impl<'a> QueueGuard<'a> { debug_assert!(self.queue.device.enabled_extensions().khr_synchronization2); (fns.khr_synchronization2.queue_submit2_khr)( self.queue.handle, - submit_info_vk.len() as u32, - submit_info_vk.as_ptr(), + submit_infos_vk.len() as u32, + submit_infos_vk.as_ptr(), fence .as_ref() .map_or_else(Default::default, VulkanObject::handle), @@ -1033,159 +603,33 @@ impl<'a> QueueGuard<'a> { .result() .map_err(VulkanError::from) } else { - struct PerSubmitInfo { - timeline_semaphore_submit_info_vk: - Option>, - wait_semaphores_vk: SmallVec<[ash::vk::Semaphore; 4]>, - wait_semaphore_values_vk: SmallVec<[u64; 4]>, - wait_dst_stage_mask_vk: SmallVec<[ash::vk::PipelineStageFlags; 4]>, - command_buffers_vk: SmallVec<[ash::vk::CommandBuffer; 4]>, - signal_semaphores_vk: SmallVec<[ash::vk::Semaphore; 4]>, - signal_semaphore_values_vk: SmallVec<[u64; 4]>, - } + let fields1_vk: SmallVec<[_; 4]> = submit_infos + .iter() + .map(|submit_info| submit_info.to_vk_fields1()) + .collect(); - let (mut submit_info_vk, mut per_submit_vk): (SmallVec<[_; 4]>, SmallVec<[_; 4]>) = - submit_infos - .iter() - .map(|submit_info| { - let &SubmitInfo { - ref wait_semaphores, - ref command_buffers, - ref signal_semaphores, - _ne: _, - } = submit_info; + let mut submit_infos_extensions_vk: SmallVec<[_; 4]> = submit_infos + .iter() + .zip(&fields1_vk) + .map(|(submit_info, submit_info_fields1_vk)| { + submit_info.to_vk_extensions(submit_info_fields1_vk) + }) + .collect(); - let mut per_submit_vk = PerSubmitInfo { - timeline_semaphore_submit_info_vk: None, - wait_semaphores_vk: SmallVec::with_capacity(wait_semaphores.len()), - wait_semaphore_values_vk: SmallVec::with_capacity( - wait_semaphores.len(), - ), - wait_dst_stage_mask_vk: SmallVec::with_capacity(wait_semaphores.len()), - command_buffers_vk: SmallVec::with_capacity(command_buffers.len()), - signal_semaphores_vk: SmallVec::with_capacity(signal_semaphores.len()), - signal_semaphore_values_vk: SmallVec::with_capacity( - signal_semaphores.len(), - ), - }; - let PerSubmitInfo { - timeline_semaphore_submit_info_vk, - wait_semaphores_vk, - wait_semaphore_values_vk, - wait_dst_stage_mask_vk, - command_buffers_vk, - signal_semaphores_vk, - signal_semaphore_values_vk, - } = &mut per_submit_vk; - - let mut has_timeline_semaphores = false; - - for semaphore_submit_info in wait_semaphores { - let &SemaphoreSubmitInfo { - ref semaphore, - value, - stages, - _ne: _, - } = semaphore_submit_info; - - if semaphore.semaphore_type() == SemaphoreType::Timeline { - has_timeline_semaphores = true; - } - - wait_semaphores_vk.push(semaphore.handle()); - wait_semaphore_values_vk.push(value); - wait_dst_stage_mask_vk.push(stages.into()); - } - - for command_buffer_submit_info in command_buffers { - let &CommandBufferSubmitInfo { - ref command_buffer, - _ne: _, - } = command_buffer_submit_info; - - command_buffers_vk.push(command_buffer.handle()); - } - - for semaphore_submit_info in signal_semaphores { - let &SemaphoreSubmitInfo { - ref semaphore, - value, - stages: _, - _ne: _, - } = semaphore_submit_info; - - if semaphore.semaphore_type() == SemaphoreType::Timeline { - has_timeline_semaphores = true; - } - - signal_semaphores_vk.push(semaphore.handle()); - signal_semaphore_values_vk.push(value); - } - - if has_timeline_semaphores { - *timeline_semaphore_submit_info_vk = - Some(ash::vk::TimelineSemaphoreSubmitInfo::default()); - } - - ( - ash::vk::SubmitInfo { - wait_semaphore_count: 0, - p_wait_semaphores: ptr::null(), - p_wait_dst_stage_mask: ptr::null(), - command_buffer_count: 0, - p_command_buffers: ptr::null(), - signal_semaphore_count: 0, - p_signal_semaphores: ptr::null(), - ..Default::default() - }, - per_submit_vk, - ) - }) - .unzip(); - - for ( - submit_info_vk, - PerSubmitInfo { - timeline_semaphore_submit_info_vk, - wait_semaphores_vk, - wait_semaphore_values_vk, - wait_dst_stage_mask_vk, - command_buffers_vk, - signal_semaphores_vk, - signal_semaphore_values_vk, - }, - ) in submit_info_vk.iter_mut().zip(per_submit_vk.iter_mut()) - { - *submit_info_vk = ash::vk::SubmitInfo { - wait_semaphore_count: wait_semaphores_vk.len() as u32, - p_wait_semaphores: wait_semaphores_vk.as_ptr(), - p_wait_dst_stage_mask: wait_dst_stage_mask_vk.as_ptr(), - command_buffer_count: command_buffers_vk.len() as u32, - p_command_buffers: command_buffers_vk.as_ptr(), - signal_semaphore_count: signal_semaphores_vk.len() as u32, - p_signal_semaphores: signal_semaphores_vk.as_ptr(), - ..*submit_info_vk - }; - - if let Some(timeline_semaphore_submit_info_vk) = timeline_semaphore_submit_info_vk { - *timeline_semaphore_submit_info_vk = ash::vk::TimelineSemaphoreSubmitInfo { - wait_semaphore_value_count: wait_semaphore_values_vk.len() as u32, - p_wait_semaphore_values: wait_semaphore_values_vk.as_ptr(), - signal_semaphore_value_count: signal_semaphore_values_vk.len() as u32, - p_signal_semaphore_values: signal_semaphore_values_vk.as_ptr(), - ..*timeline_semaphore_submit_info_vk - }; - - timeline_semaphore_submit_info_vk.p_next = submit_info_vk.p_next; - submit_info_vk.p_next = <*mut _>::cast(timeline_semaphore_submit_info_vk); - } - } + let submit_infos_vk: SmallVec<[_; 4]> = submit_infos + .iter() + .zip(&fields1_vk) + .zip(&mut submit_infos_extensions_vk) + .map(|((submit_infos, fields1_vk), extensions_vk)| { + submit_infos.to_vk(fields1_vk, extensions_vk) + }) + .collect(); let fns = self.queue.device.fns(); (fns.v1_0.queue_submit)( self.queue.handle, - submit_info_vk.len() as u32, - submit_info_vk.as_ptr(), + submit_infos_vk.len() as u32, + submit_infos_vk.as_ptr(), fence .as_ref() .map_or_else(Default::default, VulkanObject::handle), @@ -1238,21 +682,11 @@ impl<'a> QueueGuard<'a> { #[cfg_attr(not(feature = "document_unchecked"), doc(hidden))] #[inline] pub unsafe fn begin_debug_utils_label_unchecked(&mut self, label_info: DebugUtilsLabel) { - let DebugUtilsLabel { - label_name, - color, - _ne: _, - } = label_info; - - let label_name_vk = CString::new(label_name.as_str()).unwrap(); - let label_info = ash::vk::DebugUtilsLabelEXT { - p_label_name: label_name_vk.as_ptr(), - color, - ..Default::default() - }; + let label_info_fields1_vk = label_info.to_vk_fields1(); + let label_info_vk = label_info.to_vk(&label_info_fields1_vk); let fns = self.queue.device.fns(); - (fns.ext_debug_utils.queue_begin_debug_utils_label_ext)(self.queue.handle, &label_info); + (fns.ext_debug_utils.queue_begin_debug_utils_label_ext)(self.queue.handle, &label_info_vk); } /// Closes a queue debug label region. @@ -1343,21 +777,11 @@ impl<'a> QueueGuard<'a> { #[cfg_attr(not(feature = "document_unchecked"), doc(hidden))] #[inline] pub unsafe fn insert_debug_utils_label_unchecked(&mut self, label_info: DebugUtilsLabel) { - let DebugUtilsLabel { - label_name, - color, - _ne: _, - } = label_info; - - let label_name_vk = CString::new(label_name.as_str()).unwrap(); - let label_info = ash::vk::DebugUtilsLabelEXT { - p_label_name: label_name_vk.as_ptr(), - color, - ..Default::default() - }; + let label_info_fields1_vk = label_info.to_vk_fields1(); + let label_info_vk = label_info.to_vk(&label_info_fields1_vk); let fns = self.queue.device.fns(); - (fns.ext_debug_utils.queue_insert_debug_utils_label_ext)(self.queue.handle, &label_info); + (fns.ext_debug_utils.queue_insert_debug_utils_label_ext)(self.queue.handle, &label_info_vk); } } @@ -1387,18 +811,36 @@ pub struct QueueFamilyProperties { pub min_image_transfer_granularity: [u32; 3], } -impl From for QueueFamilyProperties { - #[inline] - fn from(val: ash::vk::QueueFamilyProperties) -> Self { +impl QueueFamilyProperties { + pub(crate) fn to_mut_vk2() -> ash::vk::QueueFamilyProperties2<'static> { + ash::vk::QueueFamilyProperties2::default() + } + + pub(crate) fn from_vk2(val_vk: &ash::vk::QueueFamilyProperties2<'_>) -> Self { + let &ash::vk::QueueFamilyProperties2 { + ref queue_family_properties, + .. + } = val_vk; + + Self::from_vk(queue_family_properties) + } + + pub(crate) fn from_vk(val_vk: &ash::vk::QueueFamilyProperties) -> Self { + let &ash::vk::QueueFamilyProperties { + queue_flags, + queue_count, + timestamp_valid_bits, + min_image_transfer_granularity, + } = val_vk; + Self { - queue_flags: val.queue_flags.into(), - queue_count: val.queue_count, - timestamp_valid_bits: (val.timestamp_valid_bits != 0) - .then_some(val.timestamp_valid_bits), + queue_flags: queue_flags.into(), + queue_count, + timestamp_valid_bits: (timestamp_valid_bits != 0).then_some(timestamp_valid_bits), min_image_transfer_granularity: [ - val.min_image_transfer_granularity.width, - val.min_image_transfer_granularity.height, - val.min_image_transfer_granularity.depth, + min_image_transfer_granularity.width, + min_image_transfer_granularity.height, + min_image_transfer_granularity.depth, ], } } diff --git a/vulkano/src/display.rs b/vulkano/src/display.rs index d006b67a..c967d3ce 100644 --- a/vulkano/src/display.rs +++ b/vulkano/src/display.rs @@ -154,7 +154,7 @@ impl Display { .result() .map_err(VulkanError::from)?; - let mut properties = + let mut properties_vk = vec![ash::vk::DisplayModeProperties2KHR::default(); count as usize]; let result = (fns .khr_get_display_properties2 @@ -162,13 +162,13 @@ impl Display { self.physical_device.handle(), self.handle, &mut count, - properties.as_mut_ptr(), + properties_vk.as_mut_ptr(), ); match result { ash::vk::Result::SUCCESS => { - properties.set_len(count as usize); - break properties; + properties_vk.set_len(count as usize); + break properties_vk; } ash::vk::Result::INCOMPLETE => (), err => return Err(VulkanError::from(err)), @@ -185,14 +185,9 @@ impl Display { DisplayMode::from_handle( self.clone(), handle, - DisplayModeCreateInfo { - visible_region: [ - properties_vk.parameters.visible_region.width, - properties_vk.parameters.visible_region.height, - ], - refresh_rate: properties_vk.parameters.refresh_rate, - _ne: crate::NonExhaustive(()), - }, + DisplayModeCreateInfo::from_vk_parameters( + &properties_vk.parameters, + ), ) }) }) @@ -237,14 +232,9 @@ impl Display { DisplayMode::from_handle( self.clone(), handle, - DisplayModeCreateInfo { - visible_region: [ - properties_vk.parameters.visible_region.width, - properties_vk.parameters.visible_region.height, - ], - refresh_rate: properties_vk.parameters.refresh_rate, - _ne: crate::NonExhaustive(()), - }, + DisplayModeCreateInfo::from_vk_parameters( + &properties_vk.parameters, + ), ) }) }) @@ -309,6 +299,39 @@ pub struct DisplayProperties { pub persistent_content: bool, } +impl DisplayProperties { + pub(crate) fn to_mut_vk2() -> ash::vk::DisplayProperties2KHR<'static> { + ash::vk::DisplayProperties2KHR::default() + } + + pub(crate) fn from_vk(val_vk: &ash::vk::DisplayPropertiesKHR<'_>) -> Self { + let display_name_vk = unsafe { val_vk.display_name_as_c_str() }; + let &ash::vk::DisplayPropertiesKHR { + display: _, + display_name: _, + physical_dimensions, + physical_resolution, + supported_transforms, + plane_reorder_possible, + persistent_content, + .. + } = val_vk; + + DisplayProperties { + name: display_name_vk.map(|name| { + name.to_str() + .expect("non UTF-8 characters in display name") + .to_owned() + }), + physical_dimensions: [physical_dimensions.width, physical_dimensions.height], + physical_resolution: [physical_resolution.width, physical_resolution.height], + supported_transforms: supported_transforms.into(), + plane_reorder_possible: plane_reorder_possible != ash::vk::FALSE, + persistent_content: persistent_content != ash::vk::FALSE, + } + } +} + /// Represents a mode on a specific display. /// /// A display mode describes a supported display resolution and refresh rate. @@ -352,25 +375,8 @@ impl DisplayMode { display: Arc, create_info: DisplayModeCreateInfo, ) -> Result, VulkanError> { - let &DisplayModeCreateInfo { - visible_region, - refresh_rate, - _ne: _, - } = &create_info; - - let physical_device = display.physical_device.clone(); - - let create_info_vk = ash::vk::DisplayModeCreateInfoKHR { - flags: ash::vk::DisplayModeCreateFlagsKHR::empty(), - parameters: ash::vk::DisplayModeParametersKHR { - visible_region: ash::vk::Extent2D { - width: visible_region[0], - height: visible_region[1], - }, - refresh_rate, - }, - ..Default::default() - }; + let physical_device = &display.physical_device; + let create_info_vk = create_info.to_vk(); let handle = { let fns = physical_device.instance().fns(); @@ -489,18 +495,16 @@ impl DisplayMode { .get_or_try_insert(plane_index, |&plane_index| unsafe { let fns = self.display.physical_device.instance().fns(); - let mut capabilities_vk = ash::vk::DisplayPlaneCapabilities2KHR::default(); + let mut capabilities_vk = DisplayPlaneCapabilities::to_mut_vk2(); if self .instance() .enabled_extensions() .khr_get_display_properties2 { - let info_vk = ash::vk::DisplayPlaneInfo2KHR { - mode: self.handle, - plane_index, - ..Default::default() - }; + let info_vk = ash::vk::DisplayPlaneInfo2KHR::default() + .mode(self.handle) + .plane_index(plane_index); (fns.khr_get_display_properties2 .get_display_plane_capabilities2_khr)( @@ -521,41 +525,7 @@ impl DisplayMode { .map_err(VulkanError::from)?; } - Ok(DisplayPlaneCapabilities { - supported_alpha: capabilities_vk.capabilities.supported_alpha.into(), - min_src_position: [ - capabilities_vk.capabilities.min_src_position.x as u32, - capabilities_vk.capabilities.min_src_position.y as u32, - ], - max_src_position: [ - capabilities_vk.capabilities.max_src_position.x as u32, - capabilities_vk.capabilities.max_src_position.y as u32, - ], - min_src_extent: [ - capabilities_vk.capabilities.min_src_extent.width, - capabilities_vk.capabilities.min_src_extent.height, - ], - max_src_extent: [ - capabilities_vk.capabilities.max_src_extent.width, - capabilities_vk.capabilities.max_src_extent.height, - ], - min_dst_position: [ - capabilities_vk.capabilities.min_dst_position.x as u32, - capabilities_vk.capabilities.min_dst_position.y as u32, - ], - max_dst_position: [ - capabilities_vk.capabilities.max_dst_position.x, - capabilities_vk.capabilities.max_dst_position.y, - ], - min_dst_extent: [ - capabilities_vk.capabilities.min_dst_extent.width, - capabilities_vk.capabilities.min_dst_extent.height, - ], - max_dst_extent: [ - capabilities_vk.capabilities.max_dst_extent.width, - capabilities_vk.capabilities.max_dst_extent.height, - ], - }) + Ok(DisplayPlaneCapabilities::from_vk2(&capabilities_vk)) }) } } @@ -661,6 +631,37 @@ impl DisplayModeCreateInfo { Ok(()) } + + pub(crate) fn to_vk(&self) -> ash::vk::DisplayModeCreateInfoKHR<'static> { + let &Self { + visible_region, + refresh_rate, + _ne: _, + } = self; + + ash::vk::DisplayModeCreateInfoKHR::default() + .flags(ash::vk::DisplayModeCreateFlagsKHR::empty()) + .parameters(ash::vk::DisplayModeParametersKHR { + visible_region: ash::vk::Extent2D { + width: visible_region[0], + height: visible_region[1], + }, + refresh_rate, + }) + } + + pub(crate) fn from_vk_parameters(val_vk: &ash::vk::DisplayModeParametersKHR) -> Self { + let &ash::vk::DisplayModeParametersKHR { + visible_region, + refresh_rate, + } = val_vk; + + DisplayModeCreateInfo { + visible_region: [visible_region.width, visible_region.height], + refresh_rate, + _ne: crate::NonExhaustive(()), + } + } } /// The properties of a display plane. @@ -680,6 +681,24 @@ pub(crate) struct DisplayPlanePropertiesRaw { pub(crate) current_stack_index: u32, } +impl DisplayPlanePropertiesRaw { + pub(crate) fn to_mut_vk2() -> ash::vk::DisplayPlaneProperties2KHR<'static> { + ash::vk::DisplayPlaneProperties2KHR::default() + } + + pub(crate) fn from_vk(val_vk: &ash::vk::DisplayPlanePropertiesKHR) -> Self { + let &ash::vk::DisplayPlanePropertiesKHR { + current_display, + current_stack_index, + } = val_vk; + + DisplayPlanePropertiesRaw { + current_display: Some(current_display).filter(|&x| x != ash::vk::DisplayKHR::null()), + current_stack_index, + } + } +} + /// The capabilities of a display plane. #[derive(Clone, Debug)] #[non_exhaustive] @@ -712,6 +731,42 @@ pub struct DisplayPlaneCapabilities { pub max_dst_extent: [u32; 2], } +impl DisplayPlaneCapabilities { + pub(crate) fn to_mut_vk2() -> ash::vk::DisplayPlaneCapabilities2KHR<'static> { + ash::vk::DisplayPlaneCapabilities2KHR::default() + } + + pub(crate) fn from_vk2(val_vk: &ash::vk::DisplayPlaneCapabilities2KHR<'_>) -> Self { + let &ash::vk::DisplayPlaneCapabilities2KHR { + capabilities: + ash::vk::DisplayPlaneCapabilitiesKHR { + supported_alpha, + min_src_position, + max_src_position, + min_src_extent, + max_src_extent, + min_dst_position, + max_dst_position, + min_dst_extent, + max_dst_extent, + }, + .. + } = val_vk; + + DisplayPlaneCapabilities { + supported_alpha: supported_alpha.into(), + min_src_position: [min_src_position.x as u32, min_src_position.y as u32], + max_src_position: [max_src_position.x as u32, max_src_position.y as u32], + min_src_extent: [min_src_extent.width, min_src_extent.height], + max_src_extent: [max_src_extent.width, max_src_extent.height], + min_dst_position: [min_dst_position.x as u32, min_dst_position.y as u32], + max_dst_position: [max_dst_position.x, max_dst_position.y], + min_dst_extent: [min_dst_extent.width, min_dst_extent.height], + max_dst_extent: [max_dst_extent.width, max_dst_extent.height], + } + } +} + vulkan_bitflags_enum! { #[non_exhaustive] diff --git a/vulkano/src/format.rs b/vulkano/src/format.rs index dfb0ee40..057bfb8b 100644 --- a/vulkano/src/format.rs +++ b/vulkano/src/format.rs @@ -85,12 +85,13 @@ //! method on a format. use crate::{ - device::Device, + device::{physical::PhysicalDevice, Device}, image::{ImageAspects, ImageTiling}, macros::vulkan_bitflags, shader::spirv::ImageFormat, - DeviceSize, Requires, RequiresAllOf, RequiresOneOf, ValidationError, + DeviceSize, Requires, RequiresAllOf, RequiresOneOf, ValidationError, Version, }; +use std::marker::PhantomData; // Generated by build.rs include!(concat!(env!("OUT_DIR"), "/formats.rs")); @@ -432,6 +433,17 @@ pub enum ClearValue { } impl ClearValue { + pub(crate) fn clear_value_type(&self) -> ClearValueType { + match self { + ClearValue::Float(_) => ClearValueType::Float, + ClearValue::Int(_) => ClearValueType::Int, + ClearValue::Uint(_) => ClearValueType::Uint, + ClearValue::Depth(_) => ClearValueType::Depth, + ClearValue::Stencil(_) => ClearValueType::Stencil, + ClearValue::DepthStencil(_) => ClearValueType::DepthStencil, + } + } + pub(crate) fn validate(&self, device: &Device) -> Result<(), Box> { if let ClearValue::Depth(depth) | ClearValue::DepthStencil((depth, _)) = self { if !(0.0..=1.0).contains(depth) @@ -453,41 +465,28 @@ impl ClearValue { Ok(()) } - pub(crate) fn clear_value_type(&self) -> ClearValueType { - match self { - ClearValue::Float(_) => ClearValueType::Float, - ClearValue::Int(_) => ClearValueType::Int, - ClearValue::Uint(_) => ClearValueType::Uint, - ClearValue::Depth(_) => ClearValueType::Depth, - ClearValue::Stencil(_) => ClearValueType::Stencil, - ClearValue::DepthStencil(_) => ClearValueType::DepthStencil, - } - } -} - -impl From for ash::vk::ClearValue { - #[inline] - fn from(val: ClearValue) -> Self { - match val { - ClearValue::Float(val) => Self { + #[allow(clippy::wrong_self_convention)] + pub(crate) fn to_vk(&self) -> ash::vk::ClearValue { + match *self { + ClearValue::Float(val) => ash::vk::ClearValue { color: ash::vk::ClearColorValue { float32: val }, }, - ClearValue::Int(val) => Self { + ClearValue::Int(val) => ash::vk::ClearValue { color: ash::vk::ClearColorValue { int32: val }, }, - ClearValue::Uint(val) => Self { + ClearValue::Uint(val) => ash::vk::ClearValue { color: ash::vk::ClearColorValue { uint32: val }, }, - ClearValue::Depth(depth) => Self { + ClearValue::Depth(depth) => ash::vk::ClearValue { depth_stencil: ash::vk::ClearDepthStencilValue { depth, stencil: 0 }, }, - ClearValue::Stencil(stencil) => Self { + ClearValue::Stencil(stencil) => ash::vk::ClearValue { depth_stencil: ash::vk::ClearDepthStencilValue { depth: 0.0, stencil, }, }, - ClearValue::DepthStencil((depth, stencil)) => Self { + ClearValue::DepthStencil((depth, stencil)) => ash::vk::ClearValue { depth_stencil: ash::vk::ClearDepthStencilValue { depth, stencil }, }, } @@ -640,15 +639,14 @@ impl ClearColorValue { ClearColorValue::Uint(_) => NumericType::Uint, } } -} -impl From for ash::vk::ClearColorValue { - #[inline] - fn from(val: ClearColorValue) -> Self { - match val { - ClearColorValue::Float(float32) => Self { float32 }, - ClearColorValue::Int(int32) => Self { int32 }, - ClearColorValue::Uint(uint32) => Self { uint32 }, + #[allow(clippy::wrong_self_convention)] + #[doc(hidden)] + pub fn to_vk(&self) -> ash::vk::ClearColorValue { + match *self { + ClearColorValue::Float(float32) => ash::vk::ClearColorValue { float32 }, + ClearColorValue::Int(int32) => ash::vk::ClearColorValue { int32 }, + ClearColorValue::Uint(uint32) => ash::vk::ClearColorValue { uint32 }, } } } @@ -746,13 +744,13 @@ pub struct ClearDepthStencilValue { pub stencil: u32, } -impl From for ash::vk::ClearDepthStencilValue { - #[inline] - fn from(val: ClearDepthStencilValue) -> Self { - Self { - depth: val.depth, - stencil: val.stencil, - } +impl ClearDepthStencilValue { + #[allow(clippy::trivially_copy_pass_by_ref, clippy::wrong_self_convention)] + #[doc(hidden)] + pub fn to_vk(&self) -> ash::vk::ClearDepthStencilValue { + let &Self { depth, stencil } = self; + + ash::vk::ClearDepthStencilValue { depth, stencil } } } @@ -842,6 +840,280 @@ impl FormatProperties { pub fn potential_format_features(&self) -> FormatFeatures { self.linear_tiling_features | self.optimal_tiling_features } + + pub(crate) fn to_mut_vk2<'a>( + extensions_vk: &'a mut FormatProperties2ExtensionsVk<'_>, + ) -> ash::vk::FormatProperties2<'a> { + let mut val_vk = ash::vk::FormatProperties2::default(); + + let FormatProperties2ExtensionsVk { + drm_format_modifier_properties_list_vk, + drm_format_modifier_properties_list2_vk, + format_properties3_vk, + } = extensions_vk; + + if let Some(next) = drm_format_modifier_properties_list_vk { + val_vk = val_vk.push_next(next); + } + + if let Some(next) = drm_format_modifier_properties_list2_vk { + val_vk = val_vk.push_next(next); + } + + if let Some(next) = format_properties3_vk { + val_vk = val_vk.push_next(next); + } + + val_vk + } + + pub(crate) fn to_mut_vk2_extensions<'a>( + fields1_vk: &'a mut FormatProperties2Fields1Vk, + physical_device: &PhysicalDevice, + ) -> FormatProperties2ExtensionsVk<'a> { + let FormatProperties2Fields1Vk { + drm_format_modifier_properties_vk, + drm_format_modifier_properties2_vk, + } = fields1_vk; + + let mut val_vk = FormatProperties2ExtensionsVk { + drm_format_modifier_properties_list_vk: None, + drm_format_modifier_properties_list2_vk: None, + format_properties3_vk: None, + }; + + if physical_device.api_version() >= Version::V1_3 + || physical_device + .supported_extensions() + .khr_format_feature_flags2 + { + val_vk.format_properties3_vk = Some(ash::vk::FormatProperties3::default()); + val_vk.drm_format_modifier_properties_list2_vk = drm_format_modifier_properties2_vk + .as_mut() + .map(|properties_vk| { + ash::vk::DrmFormatModifierPropertiesList2EXT::default() + .drm_format_modifier_properties(properties_vk) + }); + } else { + val_vk.drm_format_modifier_properties_list_vk = drm_format_modifier_properties_vk + .as_mut() + .map(|properties_vk| { + ash::vk::DrmFormatModifierPropertiesListEXT::default() + .drm_format_modifier_properties(properties_vk) + }); + } + + val_vk + } + + pub(crate) fn to_mut_vk2_extensions_query_count( + physical_device: &PhysicalDevice, + ) -> Option> { + let must_query_drm_format_modifier_count = physical_device + .supported_extensions() + .ext_image_drm_format_modifier; + let must_query_count = must_query_drm_format_modifier_count; + + must_query_count.then(|| { + let mut val_vk = FormatProperties2ExtensionsVk { + drm_format_modifier_properties_list_vk: None, + drm_format_modifier_properties_list2_vk: None, + format_properties3_vk: None, + }; + + if must_query_drm_format_modifier_count { + if physical_device.api_version() >= Version::V1_3 + || physical_device + .supported_extensions() + .khr_format_feature_flags2 + { + val_vk.drm_format_modifier_properties_list2_vk = + Some(ash::vk::DrmFormatModifierPropertiesList2EXT::default()); + } else { + val_vk.drm_format_modifier_properties_list_vk = + Some(ash::vk::DrmFormatModifierPropertiesListEXT::default()); + } + } + + val_vk + }) + } + + pub(crate) fn to_mut_vk2_fields1( + extensions_vk: Option>, + ) -> FormatProperties2Fields1Vk { + let mut val_vk = FormatProperties2Fields1Vk { + drm_format_modifier_properties_vk: None, + drm_format_modifier_properties2_vk: None, + }; + + if let Some(extensions_vk) = extensions_vk { + let FormatProperties2ExtensionsVk { + drm_format_modifier_properties_list_vk, + drm_format_modifier_properties_list2_vk, + format_properties3_vk: _, + } = extensions_vk; + + val_vk.drm_format_modifier_properties_vk = drm_format_modifier_properties_list_vk + .as_ref() + .map(|list_vk| { + vec![ + ash::vk::DrmFormatModifierPropertiesEXT::default(); + list_vk.drm_format_modifier_count as usize + ] + }); + + val_vk.drm_format_modifier_properties2_vk = drm_format_modifier_properties_list2_vk + .as_ref() + .map(|list_vk| { + vec![ + ash::vk::DrmFormatModifierProperties2EXT::default(); + list_vk.drm_format_modifier_count as usize + ] + }); + } + + val_vk + } + + pub(crate) fn from_vk2( + val_vk: &ash::vk::FormatProperties2<'_>, + fields1_vk: &FormatProperties2Fields1Vk, + extensions_vk: &FormatProperties2ExtensionsVk<'_>, + ) -> Self { + let FormatProperties2Fields1Vk { + drm_format_modifier_properties_vk, + drm_format_modifier_properties2_vk, + } = fields1_vk; + let FormatProperties2ExtensionsVk { + drm_format_modifier_properties_list_vk, + drm_format_modifier_properties_list2_vk, + format_properties3_vk, + } = extensions_vk; + + let mut properties = format_properties3_vk.as_ref().map_or_else( + || { + let &ash::vk::FormatProperties2 { + format_properties: + ash::vk::FormatProperties { + linear_tiling_features, + optimal_tiling_features, + buffer_features, + }, + .. + } = val_vk; + + Self { + linear_tiling_features: linear_tiling_features.into(), + optimal_tiling_features: optimal_tiling_features.into(), + buffer_features: buffer_features.into(), + drm_format_modifier_properties: Vec::new(), + _ne: crate::NonExhaustive(()), + } + }, + |val_vk| { + let &ash::vk::FormatProperties3 { + linear_tiling_features, + optimal_tiling_features, + buffer_features, + .. + } = val_vk; + + Self { + linear_tiling_features: linear_tiling_features.into(), + optimal_tiling_features: optimal_tiling_features.into(), + buffer_features: buffer_features.into(), + drm_format_modifier_properties: Vec::new(), + _ne: crate::NonExhaustive(()), + } + }, + ); + + if let Some((list_vk, properties_vk)) = drm_format_modifier_properties_list2_vk + .as_ref() + .zip(drm_format_modifier_properties2_vk.as_ref()) + { + let &ash::vk::DrmFormatModifierPropertiesList2EXT { + drm_format_modifier_count, + p_drm_format_modifier_properties: _, + .. + } = list_vk; + + properties = Self { + drm_format_modifier_properties: properties_vk[..drm_format_modifier_count as usize] + .iter() + .map(DrmFormatModifierProperties::from_vk2) + .collect(), + ..properties + }; + } else if let Some((list_vk, properties_vk)) = drm_format_modifier_properties_list_vk + .as_ref() + .zip(drm_format_modifier_properties_vk.as_ref()) + { + let &ash::vk::DrmFormatModifierPropertiesListEXT { + drm_format_modifier_count, + p_drm_format_modifier_properties: _, + .. + } = list_vk; + + properties = Self { + drm_format_modifier_properties: properties_vk[..drm_format_modifier_count as usize] + .iter() + .map(DrmFormatModifierProperties::from_vk) + .collect(), + ..properties + }; + } + + properties + } +} + +pub(crate) struct FormatProperties2ExtensionsVk<'a> { + pub(crate) drm_format_modifier_properties_list_vk: + Option>, + pub(crate) drm_format_modifier_properties_list2_vk: + Option>, + pub(crate) format_properties3_vk: Option>, +} + +impl<'a> FormatProperties2ExtensionsVk<'a> { + pub(crate) fn unborrow(self) -> FormatProperties2ExtensionsVk<'static> { + let Self { + drm_format_modifier_properties_list_vk, + drm_format_modifier_properties_list2_vk, + format_properties3_vk, + } = self; + + let drm_format_modifier_properties_list_vk = + drm_format_modifier_properties_list_vk.map(|val_vk| { + ash::vk::DrmFormatModifierPropertiesListEXT { + _marker: PhantomData, + ..val_vk + } + }); + + let drm_format_modifier_properties_list2_vk = + drm_format_modifier_properties_list2_vk.map(|val_vk| { + ash::vk::DrmFormatModifierPropertiesList2EXT { + _marker: PhantomData, + ..val_vk + } + }); + + FormatProperties2ExtensionsVk { + drm_format_modifier_properties_list_vk, + drm_format_modifier_properties_list2_vk, + format_properties3_vk, + } + } +} + +pub(crate) struct FormatProperties2Fields1Vk { + pub(crate) drm_format_modifier_properties_vk: + Option>, + pub(crate) drm_format_modifier_properties2_vk: + Option>, } /// The properties of a format when combined with a Linux DRM format modifier. @@ -858,6 +1130,36 @@ pub struct DrmFormatModifierProperties { pub drm_format_modifier_tiling_features: FormatFeatures, } +impl DrmFormatModifierProperties { + pub(crate) fn from_vk2(val_vk: &ash::vk::DrmFormatModifierProperties2EXT) -> Self { + let &ash::vk::DrmFormatModifierProperties2EXT { + drm_format_modifier, + drm_format_modifier_plane_count, + drm_format_modifier_tiling_features, + } = val_vk; + + Self { + drm_format_modifier, + drm_format_modifier_plane_count, + drm_format_modifier_tiling_features: drm_format_modifier_tiling_features.into(), + } + } + + pub(crate) fn from_vk(val_vk: &ash::vk::DrmFormatModifierPropertiesEXT) -> Self { + let &ash::vk::DrmFormatModifierPropertiesEXT { + drm_format_modifier, + drm_format_modifier_plane_count, + drm_format_modifier_tiling_features, + } = val_vk; + + Self { + drm_format_modifier, + drm_format_modifier_plane_count, + drm_format_modifier_tiling_features: drm_format_modifier_tiling_features.into(), + } + } +} + vulkan_bitflags! { #[non_exhaustive] diff --git a/vulkano/src/image/mod.rs b/vulkano/src/image/mod.rs index 563f2181..320462a4 100644 --- a/vulkano/src/image/mod.rs +++ b/vulkano/src/image/mod.rs @@ -1453,26 +1453,20 @@ impl ImageSubresourceLayers { } } -impl From for ash::vk::ImageSubresourceLayers { - #[inline] - fn from(val: ImageSubresourceLayers) -> Self { - Self { - aspect_mask: val.aspects.into(), - mip_level: val.mip_level, - base_array_layer: val.array_layers.start, - layer_count: val.array_layers.end - val.array_layers.start, - } - } -} +impl ImageSubresourceLayers { + #[doc(hidden)] + pub fn to_vk(&self) -> ash::vk::ImageSubresourceLayers { + let &Self { + aspects, + mip_level, + ref array_layers, + } = self; -impl From<&ImageSubresourceLayers> for ash::vk::ImageSubresourceLayers { - #[inline] - fn from(val: &ImageSubresourceLayers) -> Self { - Self { - aspect_mask: val.aspects.into(), - mip_level: val.mip_level, - base_array_layer: val.array_layers.start, - layer_count: val.array_layers.end - val.array_layers.start, + ash::vk::ImageSubresourceLayers { + aspect_mask: aspects.into(), + mip_level, + base_array_layer: array_layers.start, + layer_count: array_layers.end - array_layers.start, } } } @@ -1582,17 +1576,21 @@ impl ImageSubresourceRange { Ok(()) } -} -impl From for ash::vk::ImageSubresourceRange { - #[inline] - fn from(val: ImageSubresourceRange) -> Self { - Self { - aspect_mask: val.aspects.into(), - base_mip_level: val.mip_levels.start, - level_count: val.mip_levels.end - val.mip_levels.start, - base_array_layer: val.array_layers.start, - layer_count: val.array_layers.end - val.array_layers.start, + #[doc(hidden)] + pub fn to_vk(&self) -> ash::vk::ImageSubresourceRange { + let &Self { + aspects, + ref mip_levels, + ref array_layers, + } = self; + + ash::vk::ImageSubresourceRange { + aspect_mask: aspects.into(), + base_mip_level: mip_levels.start, + level_count: mip_levels.end - mip_levels.start, + base_array_layer: array_layers.start, + layer_count: array_layers.end - array_layers.start, } } } @@ -1634,6 +1632,27 @@ pub struct SubresourceLayout { pub depth_pitch: Option, } +impl SubresourceLayout { + #[allow(clippy::wrong_self_convention)] + pub(crate) fn to_vk(&self) -> ash::vk::SubresourceLayout { + let &Self { + offset, + size, + row_pitch, + array_pitch, + depth_pitch, + } = self; + + ash::vk::SubresourceLayout { + offset, + size, + row_pitch, + array_pitch: array_pitch.unwrap_or(0), + depth_pitch: depth_pitch.unwrap_or(0), + } + } +} + /// The image configuration to query in /// [`PhysicalDevice::image_format_properties`]. #[derive(Clone, Debug, PartialEq, Eq, Hash)] @@ -1974,6 +1993,135 @@ impl ImageFormatInfo { Ok(()) } + + pub(crate) fn to_vk2<'a>( + &self, + extensions_vk: &'a mut ImageFormatInfo2ExtensionsVk<'_>, + ) -> ash::vk::PhysicalDeviceImageFormatInfo2<'a> { + let &Self { + flags, + format, + image_type, + tiling, + usage, + stencil_usage: _, + external_memory_handle_type: _, + image_view_type: _, + drm_format_modifier_info: _, + view_formats: _, + _ne: _, + } = self; + + let mut val_vk = ash::vk::PhysicalDeviceImageFormatInfo2::default() + .format(format.into()) + .ty(image_type.into()) + .tiling(tiling.into()) + .usage(usage.into()) + .flags(flags.into()); + + let ImageFormatInfo2ExtensionsVk { + drm_format_modifier_vk, + external_vk, + format_list_vk, + image_view_vk, + stencil_usage_vk, + } = extensions_vk; + + if let Some(next) = drm_format_modifier_vk { + val_vk = val_vk.push_next(next); + } + + if let Some(next) = external_vk { + val_vk = val_vk.push_next(next); + } + + if let Some(next) = format_list_vk { + val_vk = val_vk.push_next(next); + } + + if let Some(next) = image_view_vk { + val_vk = val_vk.push_next(next); + } + + if let Some(next) = stencil_usage_vk { + val_vk = val_vk.push_next(next); + } + + val_vk + } + + pub(crate) fn to_vk2_extensions<'a>( + &'a self, + fields1_vk: &'a ImageFormatInfo2Fields1Vk, + ) -> ImageFormatInfo2ExtensionsVk<'a> { + let &Self { + flags: _, + format: _, + image_type: _, + tiling: _, + usage: _, + stencil_usage, + external_memory_handle_type, + image_view_type, + ref drm_format_modifier_info, + view_formats: _, + _ne: _, + } = self; + let ImageFormatInfo2Fields1Vk { view_formats_vk } = fields1_vk; + + let drm_format_modifier_vk = drm_format_modifier_info + .as_ref() + .map(ImageDrmFormatModifierInfo::to_vk); + + let external_vk = external_memory_handle_type.map(|handle_type| { + ash::vk::PhysicalDeviceExternalImageFormatInfo::default() + .handle_type(handle_type.into()) + }); + + let format_list_vk = (!view_formats_vk.is_empty()) + .then(|| ash::vk::ImageFormatListCreateInfo::default().view_formats(view_formats_vk)); + + let image_view_vk = image_view_type.map(|image_view_type| { + ash::vk::PhysicalDeviceImageViewImageFormatInfoEXT::default() + .image_view_type(image_view_type.into()) + }); + + let stencil_usage_vk = stencil_usage.map(|stencil_usage| { + ash::vk::ImageStencilUsageCreateInfo::default().stencil_usage(stencil_usage.into()) + }); + + ImageFormatInfo2ExtensionsVk { + drm_format_modifier_vk, + external_vk, + format_list_vk, + image_view_vk, + stencil_usage_vk, + } + } + + pub(crate) fn to_vk2_fields1(&self) -> ImageFormatInfo2Fields1Vk { + let view_formats_vk = self + .view_formats + .iter() + .copied() + .map(ash::vk::Format::from) + .collect(); + + ImageFormatInfo2Fields1Vk { view_formats_vk } + } +} + +pub(crate) struct ImageFormatInfo2ExtensionsVk<'a> { + pub(crate) drm_format_modifier_vk: + Option>, + pub(crate) external_vk: Option>, + pub(crate) format_list_vk: Option>, + pub(crate) image_view_vk: Option>, + pub(crate) stencil_usage_vk: Option>, +} + +pub(crate) struct ImageFormatInfo2Fields1Vk { + pub(crate) view_formats_vk: Vec, } /// The image's DRM format modifier configuration to query in @@ -2062,6 +2210,27 @@ impl ImageDrmFormatModifierInfo { Ok(()) } + + pub(crate) fn to_vk(&self) -> ash::vk::PhysicalDeviceImageDrmFormatModifierInfoEXT<'_> { + let &Self { + drm_format_modifier, + ref sharing, + _ne: _, + } = self; + + let (sharing_mode, queue_family_indices) = match sharing { + Sharing::Exclusive => (ash::vk::SharingMode::EXCLUSIVE, [].as_slice()), + Sharing::Concurrent(queue_family_indices) => ( + ash::vk::SharingMode::CONCURRENT, + queue_family_indices.as_slice(), + ), + }; + + ash::vk::PhysicalDeviceImageDrmFormatModifierInfoEXT::default() + .drm_format_modifier(drm_format_modifier) + .sharing_mode(sharing_mode) + .queue_family_indices(queue_family_indices) + } } /// The properties that are supported by a physical device for images of a certain type. @@ -2099,26 +2268,113 @@ pub struct ImageFormatProperties { pub filter_cubic_minmax: bool, } -impl From for ImageFormatProperties { - #[inline] - fn from(props: ash::vk::ImageFormatProperties) -> Self { - Self { - max_extent: [ - props.max_extent.width, - props.max_extent.height, - props.max_extent.depth, - ], - max_mip_levels: props.max_mip_levels, - max_array_layers: props.max_array_layers, - sample_counts: props.sample_counts.into(), - max_resource_size: props.max_resource_size, +impl ImageFormatProperties { + pub(crate) fn to_mut_vk2( + extensions_vk: &mut ImageFormatProperties2ExtensionsVk, + ) -> ash::vk::ImageFormatProperties2<'_> { + let mut val_vk = ash::vk::ImageFormatProperties2::default(); + + let ImageFormatProperties2ExtensionsVk { + external_vk, + filter_cubic_image_view_vk, + } = extensions_vk; + + if let Some(next) = external_vk { + val_vk = val_vk.push_next(next); + } + + if let Some(next) = filter_cubic_image_view_vk { + val_vk = val_vk.push_next(next); + } + + val_vk + } + + pub(crate) fn to_mut_vk2_extensions( + image_format_info: &ImageFormatInfo, + ) -> ImageFormatProperties2ExtensionsVk { + let external_vk = (image_format_info.external_memory_handle_type.is_some()) + .then(ash::vk::ExternalImageFormatProperties::default); + + let filter_cubic_image_view_vk = (image_format_info.image_view_type.is_some()) + .then(ash::vk::FilterCubicImageViewImageFormatPropertiesEXT::default); + + ImageFormatProperties2ExtensionsVk { + external_vk, + filter_cubic_image_view_vk, + } + } + + pub(crate) fn from_vk2( + val_vk: &ash::vk::ImageFormatProperties2<'_>, + extensions_vk: &ImageFormatProperties2ExtensionsVk, + ) -> Self { + let &ash::vk::ImageFormatProperties2 { + image_format_properties: + ash::vk::ImageFormatProperties { + max_extent, + max_mip_levels, + max_array_layers, + sample_counts, + max_resource_size, + }, + .. + } = val_vk; + + let mut val = Self { + max_extent: [max_extent.width, max_extent.height, max_extent.depth], + max_mip_levels, + max_array_layers, + sample_counts: sample_counts.into(), + max_resource_size, external_memory_properties: Default::default(), filter_cubic: false, filter_cubic_minmax: false, + }; + + let ImageFormatProperties2ExtensionsVk { + external_vk, + filter_cubic_image_view_vk, + } = extensions_vk; + + if let Some(val_vk) = external_vk { + let ash::vk::ExternalImageFormatProperties { + ref external_memory_properties, + .. + } = val_vk; + + val = Self { + external_memory_properties: ExternalMemoryProperties::from_vk( + external_memory_properties, + ), + ..val + }; } + + if let Some(val_vk) = filter_cubic_image_view_vk { + let &ash::vk::FilterCubicImageViewImageFormatPropertiesEXT { + filter_cubic, + filter_cubic_minmax, + .. + } = val_vk; + + val = Self { + filter_cubic: filter_cubic != ash::vk::FALSE, + filter_cubic_minmax: filter_cubic_minmax != ash::vk::FALSE, + ..val + }; + } + + val } } +pub(crate) struct ImageFormatProperties2ExtensionsVk { + pub(crate) external_vk: Option>, + pub(crate) filter_cubic_image_view_vk: + Option>, +} + /// The image configuration to query in /// [`PhysicalDevice::sparse_image_format_properties`]. #[derive(Clone, Debug, PartialEq, Eq, Hash)] @@ -2228,6 +2484,24 @@ impl SparseImageFormatInfo { Ok(()) } + + pub(crate) fn to_vk(&self) -> ash::vk::PhysicalDeviceSparseImageFormatInfo2<'static> { + let &Self { + format, + image_type, + samples, + usage, + tiling, + _ne: _, + } = self; + + ash::vk::PhysicalDeviceSparseImageFormatInfo2::default() + .format(format.into()) + .ty(image_type.into()) + .samples(samples.into()) + .usage(usage.into()) + .tiling(tiling.into()) + } } /// The properties that are supported by a physical device for sparse images of a certain type. @@ -2247,6 +2521,34 @@ pub struct SparseImageFormatProperties { pub flags: SparseImageFormatFlags, } +impl SparseImageFormatProperties { + pub(crate) fn to_mut_vk2() -> ash::vk::SparseImageFormatProperties2<'static> { + ash::vk::SparseImageFormatProperties2::default() + } + + pub(crate) fn to_mut_vk() -> ash::vk::SparseImageFormatProperties { + ash::vk::SparseImageFormatProperties::default() + } + + pub(crate) fn from_vk(val_vk: &ash::vk::SparseImageFormatProperties) -> Self { + let &ash::vk::SparseImageFormatProperties { + aspect_mask, + image_granularity, + flags, + } = val_vk; + + SparseImageFormatProperties { + aspects: aspect_mask.into(), + image_granularity: [ + image_granularity.width, + image_granularity.height, + image_granularity.depth, + ], + flags: flags.into(), + } + } +} + vulkan_bitflags! { #[non_exhaustive] @@ -2290,6 +2592,46 @@ pub struct SparseImageMemoryRequirements { pub image_mip_tail_stride: Option, } +impl SparseImageMemoryRequirements { + pub(crate) fn to_mut_vk2() -> ash::vk::SparseImageMemoryRequirements2<'static> { + ash::vk::SparseImageMemoryRequirements2::default() + } + + pub(crate) fn to_mut_vk() -> ash::vk::SparseImageMemoryRequirements { + ash::vk::SparseImageMemoryRequirements::default() + } + + pub(crate) fn from_vk2(val_vk: &ash::vk::SparseImageMemoryRequirements2<'_>) -> Self { + let ash::vk::SparseImageMemoryRequirements2 { + ref memory_requirements, + .. + } = val_vk; + + SparseImageMemoryRequirements::from_vk(memory_requirements) + } + + pub(crate) fn from_vk(val_vk: &ash::vk::SparseImageMemoryRequirements) -> Self { + let &ash::vk::SparseImageMemoryRequirements { + ref format_properties, + image_mip_tail_first_lod, + image_mip_tail_size, + image_mip_tail_offset, + image_mip_tail_stride, + } = val_vk; + + SparseImageMemoryRequirements { + format_properties: SparseImageFormatProperties::from_vk(format_properties), + image_mip_tail_first_lod, + image_mip_tail_size, + image_mip_tail_offset, + image_mip_tail_stride: (!format_properties + .flags + .intersects(ash::vk::SparseImageFormatFlags::SINGLE_MIPTAIL)) + .then_some(image_mip_tail_stride), + } + } +} + #[cfg(test)] mod tests { #[test] diff --git a/vulkano/src/image/sampler/mod.rs b/vulkano/src/image/sampler/mod.rs index 7adc0436..a779d187 100644 --- a/vulkano/src/image/sampler/mod.rs +++ b/vulkano/src/image/sampler/mod.rs @@ -135,78 +135,8 @@ impl Sampler { device: Arc, create_info: SamplerCreateInfo, ) -> Result, VulkanError> { - let &SamplerCreateInfo { - mag_filter, - min_filter, - mipmap_mode, - address_mode, - mip_lod_bias, - anisotropy, - compare, - ref lod, - border_color, - unnormalized_coordinates, - reduction_mode, - ref sampler_ycbcr_conversion, - _ne: _, - } = &create_info; - - let (anisotropy_enable, max_anisotropy) = if let Some(max_anisotropy) = anisotropy { - (ash::vk::TRUE, max_anisotropy) - } else { - (ash::vk::FALSE, 1.0) - }; - - let (compare_enable, compare_op) = if let Some(compare_op) = compare { - (ash::vk::TRUE, compare_op) - } else { - (ash::vk::FALSE, CompareOp::Never) - }; - - let mut create_info_vk = ash::vk::SamplerCreateInfo { - flags: ash::vk::SamplerCreateFlags::empty(), - mag_filter: mag_filter.into(), - min_filter: min_filter.into(), - mipmap_mode: mipmap_mode.into(), - address_mode_u: address_mode[0].into(), - address_mode_v: address_mode[1].into(), - address_mode_w: address_mode[2].into(), - mip_lod_bias, - anisotropy_enable, - max_anisotropy, - compare_enable, - compare_op: compare_op.into(), - min_lod: *lod.start(), - max_lod: *lod.end(), - border_color: border_color.into(), - unnormalized_coordinates: unnormalized_coordinates as ash::vk::Bool32, - ..Default::default() - }; - let mut sampler_reduction_mode_create_info_vk = None; - let mut sampler_ycbcr_conversion_info_vk = None; - - if reduction_mode != SamplerReductionMode::WeightedAverage { - let next = sampler_reduction_mode_create_info_vk.insert( - ash::vk::SamplerReductionModeCreateInfo { - reduction_mode: reduction_mode.into(), - ..Default::default() - }, - ); - - next.p_next = create_info_vk.p_next; - create_info_vk.p_next = <*const _>::cast(next); - } - - if let Some(sampler_ycbcr_conversion) = sampler_ycbcr_conversion { - let next = - sampler_ycbcr_conversion_info_vk.insert(ash::vk::SamplerYcbcrConversionInfo { - conversion: sampler_ycbcr_conversion.handle(), - ..Default::default() - }); - - next.p_next = create_info_vk.p_next; - create_info_vk.p_next = <*const _>::cast(next); - } + let mut create_info_extensions_vk = create_info.to_vk_extensions(); + let create_info_vk = create_info.to_vk(&mut create_info_extensions_vk); let handle = unsafe { let fns = device.fns(); @@ -1122,6 +1052,104 @@ impl SamplerCreateInfo { Ok(()) } + + pub(crate) fn to_vk<'a>( + &self, + extensions_vk: &'a mut SamplerCreateInfoExtensionsVk, + ) -> ash::vk::SamplerCreateInfo<'a> { + let &Self { + mag_filter, + min_filter, + mipmap_mode, + address_mode, + mip_lod_bias, + anisotropy, + compare, + ref lod, + border_color, + unnormalized_coordinates, + reduction_mode: _, + sampler_ycbcr_conversion: _, + _ne: _, + } = self; + + let (anisotropy_enable_vk, max_anisotropy_vk) = if let Some(max_anisotropy) = anisotropy { + (true, max_anisotropy) + } else { + (false, 1.0) + }; + + let (compare_enable_vk, compare_op_vk) = if let Some(compare_op) = compare { + (true, compare_op) + } else { + (false, CompareOp::Never) + }; + + let mut val_vk = ash::vk::SamplerCreateInfo::default() + .flags(ash::vk::SamplerCreateFlags::empty()) + .mag_filter(mag_filter.into()) + .min_filter(min_filter.into()) + .mipmap_mode(mipmap_mode.into()) + .address_mode_u(address_mode[0].into()) + .address_mode_v(address_mode[1].into()) + .address_mode_w(address_mode[2].into()) + .mip_lod_bias(mip_lod_bias) + .anisotropy_enable(anisotropy_enable_vk) + .max_anisotropy(max_anisotropy_vk) + .compare_enable(compare_enable_vk) + .compare_op(compare_op_vk.into()) + .min_lod(*lod.start()) + .max_lod(*lod.end()) + .border_color(border_color.into()) + .unnormalized_coordinates(unnormalized_coordinates); + + let SamplerCreateInfoExtensionsVk { + reduction_mode_vk, + ycbcr_conversion_vk, + } = extensions_vk; + + if let Some(next) = reduction_mode_vk { + val_vk = val_vk.push_next(next); + } + + if let Some(next) = ycbcr_conversion_vk { + val_vk = val_vk.push_next(next); + } + + val_vk + } + + pub(crate) fn to_vk_extensions(&self) -> SamplerCreateInfoExtensionsVk { + let &Self { + reduction_mode, + ref sampler_ycbcr_conversion, + .. + } = self; + + let reduction_mode_vk = + (reduction_mode != SamplerReductionMode::WeightedAverage).then(|| { + ash::vk::SamplerReductionModeCreateInfo::default() + .reduction_mode(reduction_mode.into()) + }); + + let ycbcr_conversion_vk = + sampler_ycbcr_conversion + .as_ref() + .map(|sampler_ycbcr_conversion| { + ash::vk::SamplerYcbcrConversionInfo::default() + .conversion(sampler_ycbcr_conversion.handle()) + }); + + SamplerCreateInfoExtensionsVk { + reduction_mode_vk, + ycbcr_conversion_vk, + } + } +} + +pub(crate) struct SamplerCreateInfoExtensionsVk { + pub(crate) reduction_mode_vk: Option>, + pub(crate) ycbcr_conversion_vk: Option>, } /// A special value to indicate that the maximum LOD should not be clamped. @@ -1251,16 +1279,16 @@ impl ComponentMapping { Ok(()) } -} -impl From for ash::vk::ComponentMapping { - #[inline] - fn from(value: ComponentMapping) -> Self { - Self { - r: value.r.into(), - g: value.g.into(), - b: value.b.into(), - a: value.a.into(), + #[allow(clippy::wrong_self_convention)] + pub(crate) fn to_vk(&self) -> ash::vk::ComponentMapping { + let &Self { r, g, b, a } = self; + + ash::vk::ComponentMapping { + r: r.into(), + g: g.into(), + b: b.into(), + a: a.into(), } } } diff --git a/vulkano/src/image/sampler/ycbcr.rs b/vulkano/src/image/sampler/ycbcr.rs index 30a747eb..4491ffc4 100644 --- a/vulkano/src/image/sampler/ycbcr.rs +++ b/vulkano/src/image/sampler/ycbcr.rs @@ -176,28 +176,7 @@ impl SamplerYcbcrConversion { device: Arc, create_info: SamplerYcbcrConversionCreateInfo, ) -> Result, VulkanError> { - let &SamplerYcbcrConversionCreateInfo { - format, - ycbcr_model, - ycbcr_range, - component_mapping, - chroma_offset, - chroma_filter, - force_explicit_reconstruction, - _ne: _, - } = &create_info; - - let create_info_vk = ash::vk::SamplerYcbcrConversionCreateInfo { - format: format.into(), - ycbcr_model: ycbcr_model.into(), - ycbcr_range: ycbcr_range.into(), - components: component_mapping.into(), - x_chroma_offset: chroma_offset[0].into(), - y_chroma_offset: chroma_offset[1].into(), - chroma_filter: chroma_filter.into(), - force_explicit_reconstruction: force_explicit_reconstruction as ash::vk::Bool32, - ..Default::default() - }; + let create_info_vk = create_info.to_vk(); let handle = unsafe { let fns = device.fns(); @@ -836,6 +815,29 @@ impl SamplerYcbcrConversionCreateInfo { Ok(()) } + + pub(crate) fn to_vk(&self) -> ash::vk::SamplerYcbcrConversionCreateInfo<'static> { + let &Self { + format, + ycbcr_model, + ycbcr_range, + component_mapping, + chroma_offset, + chroma_filter, + force_explicit_reconstruction, + _ne: _, + } = self; + + ash::vk::SamplerYcbcrConversionCreateInfo::default() + .format(format.into()) + .ycbcr_model(ycbcr_model.into()) + .ycbcr_range(ycbcr_range.into()) + .components(component_mapping.to_vk()) + .x_chroma_offset(chroma_offset[0].into()) + .y_chroma_offset(chroma_offset[1].into()) + .chroma_filter(chroma_filter.into()) + .force_explicit_reconstruction(force_explicit_reconstruction) + } } vulkan_enum! { diff --git a/vulkano/src/image/sys.rs b/vulkano/src/image/sys.rs index 1ba0ccf0..f81efdee 100644 --- a/vulkano/src/image/sys.rs +++ b/vulkano/src/image/sys.rs @@ -21,21 +21,20 @@ use crate::{ format::{ChromaSampling, Format, FormatFeatures}, image::{ max_mip_levels, ImageDrmFormatModifierInfo, ImageFormatInfo, ImageFormatProperties, - ImageType, SparseImageFormatProperties, + ImageType, }, instance::InstanceOwnedDebugWrapper, macros::impl_id_counter, memory::{ - allocator::{AllocationType, DeviceLayout}, - is_aligned, DedicatedTo, ExternalMemoryHandleTypes, MemoryPropertyFlags, - MemoryRequirements, ResourceMemory, + allocator::AllocationType, is_aligned, DedicatedTo, ExternalMemoryHandleTypes, + MemoryPropertyFlags, MemoryRequirements, ResourceMemory, }, sync::Sharing, Requires, RequiresAllOf, RequiresOneOf, Validated, ValidationError, Version, VulkanError, VulkanObject, }; use smallvec::{smallvec, SmallVec}; -use std::{mem::MaybeUninit, num::NonZeroU64, ptr, sync::Arc}; +use std::{marker::PhantomData, mem::MaybeUninit, num::NonZeroU64, ptr, sync::Arc}; /// A raw image, with no memory backing it. /// @@ -103,148 +102,9 @@ impl RawImage { device: Arc, create_info: ImageCreateInfo, ) -> Result { - let &ImageCreateInfo { - flags, - image_type, - format, - ref view_formats, - extent, - array_layers, - mip_levels, - samples, - tiling, - usage, - stencil_usage, - ref sharing, - initial_layout, - ref drm_format_modifiers, - ref drm_format_modifier_plane_layouts, - external_memory_handle_types, - _ne: _, - } = &create_info; - - let (sharing_mode, queue_family_index_count, p_queue_family_indices) = match sharing { - Sharing::Exclusive => (ash::vk::SharingMode::EXCLUSIVE, 0, ptr::null()), - Sharing::Concurrent(queue_family_indices) => ( - ash::vk::SharingMode::CONCURRENT, - queue_family_indices.len() as u32, - queue_family_indices.as_ptr(), - ), - }; - - let mut create_info_vk = ash::vk::ImageCreateInfo { - flags: flags.into(), - image_type: image_type.into(), - format: format.into(), - extent: ash::vk::Extent3D { - width: extent[0], - height: extent[1], - depth: extent[2], - }, - mip_levels, - array_layers, - samples: samples.into(), - tiling: tiling.into(), - usage: usage.into(), - sharing_mode, - queue_family_index_count, - p_queue_family_indices, - initial_layout: initial_layout.into(), - ..Default::default() - }; - let mut drm_format_modifier_explicit_info_vk = None; - let drm_format_modifier_plane_layouts_vk: SmallVec<[_; 4]>; - let mut drm_format_modifier_list_info_vk = None; - let mut external_memory_info_vk = None; - let mut format_list_info_vk = None; - let format_list_view_formats_vk: Vec<_>; - let mut stencil_usage_info_vk = None; - - if !drm_format_modifiers.is_empty() { - if drm_format_modifier_plane_layouts.is_empty() { - let next = drm_format_modifier_list_info_vk.insert( - ash::vk::ImageDrmFormatModifierListCreateInfoEXT { - drm_format_modifier_count: drm_format_modifiers.len() as u32, - p_drm_format_modifiers: drm_format_modifiers.as_ptr(), - ..Default::default() - }, - ); - - next.p_next = create_info_vk.p_next; - create_info_vk.p_next = <*const _>::cast(next); - } else { - drm_format_modifier_plane_layouts_vk = drm_format_modifier_plane_layouts - .iter() - .map(|subresource_layout| { - let &SubresourceLayout { - offset, - size, - row_pitch, - array_pitch, - depth_pitch, - } = subresource_layout; - - ash::vk::SubresourceLayout { - offset, - size, - row_pitch, - array_pitch: array_pitch.unwrap_or(0), - depth_pitch: depth_pitch.unwrap_or(0), - } - }) - .collect(); - - let next = drm_format_modifier_explicit_info_vk.insert( - ash::vk::ImageDrmFormatModifierExplicitCreateInfoEXT { - drm_format_modifier: drm_format_modifiers[0], - drm_format_modifier_plane_count: drm_format_modifier_plane_layouts_vk.len() - as u32, - p_plane_layouts: drm_format_modifier_plane_layouts_vk.as_ptr(), - ..Default::default() - }, - ); - - next.p_next = create_info_vk.p_next; - create_info_vk.p_next = <*const _>::cast(next); - } - } - - if !external_memory_handle_types.is_empty() { - let next = external_memory_info_vk.insert(ash::vk::ExternalMemoryImageCreateInfo { - handle_types: external_memory_handle_types.into(), - ..Default::default() - }); - - next.p_next = create_info_vk.p_next; - create_info_vk.p_next = <*const _>::cast(next); - } - - if !view_formats.is_empty() { - format_list_view_formats_vk = view_formats - .iter() - .copied() - .map(ash::vk::Format::from) - .collect(); - - let next = format_list_info_vk.insert(ash::vk::ImageFormatListCreateInfo { - view_format_count: format_list_view_formats_vk.len() as u32, - p_view_formats: format_list_view_formats_vk.as_ptr(), - ..Default::default() - }); - - next.p_next = create_info_vk.p_next; - create_info_vk.p_next = <*const _>::cast(next); - } - - if let Some(stencil_usage) = stencil_usage { - let next = stencil_usage_info_vk.insert(ash::vk::ImageStencilUsageCreateInfo { - stencil_usage: stencil_usage.into(), - ..Default::default() - }); - - next.p_next = create_info_vk.p_next; - create_info_vk.p_next = <*const _>::cast(next); - } + let create_info_fields1_vk = create_info.to_vk_fields1(); + let mut create_info_extensions_vk = create_info.to_vk_extensions(&create_info_fields1_vk); + let create_info_vk = create_info.to_vk(&mut create_info_extensions_vk); let handle = { let fns = device.fns(); @@ -399,10 +259,7 @@ impl RawImage { handle: ash::vk::Image, plane_tiling: Option<(usize, ImageTiling)>, ) -> MemoryRequirements { - let mut info_vk = ash::vk::ImageMemoryRequirementsInfo2 { - image: handle, - ..Default::default() - }; + let mut info_vk = ash::vk::ImageMemoryRequirementsInfo2::default().image(handle); let mut plane_info_vk = None; if let Some((plane, tiling)) = plane_tiling { @@ -438,33 +295,17 @@ impl RawImage { } }; - let next = plane_info_vk.insert(ash::vk::ImagePlaneMemoryRequirementsInfo { - plane_aspect, - ..Default::default() - }); - - next.p_next = info_vk.p_next; - info_vk.p_next = <*mut _>::cast(next); - } - - let mut memory_requirements2_vk = ash::vk::MemoryRequirements2::default(); - let mut memory_dedicated_requirements_vk = None; - - if device.api_version() >= Version::V1_1 - || device.enabled_extensions().khr_dedicated_allocation - { - debug_assert!( - device.api_version() >= Version::V1_1 - || device.enabled_extensions().khr_get_memory_requirements2 + let next = plane_info_vk.insert( + ash::vk::ImagePlaneMemoryRequirementsInfo::default().plane_aspect(plane_aspect), ); - - let next = memory_dedicated_requirements_vk - .insert(ash::vk::MemoryDedicatedRequirements::default()); - - next.p_next = memory_requirements2_vk.p_next; - memory_requirements2_vk.p_next = <*mut _>::cast(next); + info_vk = info_vk.push_next(next); } + let mut memory_requirements2_extensions_vk = + MemoryRequirements::to_mut_vk2_extensions(device); + let mut memory_requirements2_vk = + MemoryRequirements::to_mut_vk2(&mut memory_requirements2_extensions_vk); + unsafe { let fns = device.fns(); @@ -494,18 +335,16 @@ impl RawImage { } } - MemoryRequirements { - layout: DeviceLayout::from_size_alignment( - memory_requirements2_vk.memory_requirements.size, - memory_requirements2_vk.memory_requirements.alignment, - ) - .unwrap(), - memory_type_bits: memory_requirements2_vk.memory_requirements.memory_type_bits, - prefers_dedicated_allocation: memory_dedicated_requirements_vk - .map_or(false, |dreqs| dreqs.prefers_dedicated_allocation != 0), - requires_dedicated_allocation: memory_dedicated_requirements_vk - .map_or(false, |dreqs| dreqs.requires_dedicated_allocation != 0), - } + // Unborrow + let memory_requirements2_vk = ash::vk::MemoryRequirements2 { + _marker: PhantomData, + ..memory_requirements2_vk + }; + + MemoryRequirements::from_vk2( + &memory_requirements2_vk, + &memory_requirements2_extensions_vk, + ) } #[allow(dead_code)] // Remove when sparse memory is implemented @@ -518,17 +357,15 @@ impl RawImage { if device.api_version() >= Version::V1_1 || device.enabled_extensions().khr_get_memory_requirements2 { - let info2 = ash::vk::ImageSparseMemoryRequirementsInfo2 { - image: self.handle, - ..Default::default() - }; + let info2_vk = + ash::vk::ImageSparseMemoryRequirementsInfo2::default().image(self.handle); let mut count = 0; if device.api_version() >= Version::V1_1 { (fns.v1_1.get_image_sparse_memory_requirements2)( device.handle(), - &info2, + &info2_vk, &mut count, ptr::null_mut(), ); @@ -536,88 +373,37 @@ impl RawImage { (fns.khr_get_memory_requirements2 .get_image_sparse_memory_requirements2_khr)( device.handle(), - &info2, + &info2_vk, &mut count, ptr::null_mut(), ); } - let mut sparse_image_memory_requirements2 = - vec![ash::vk::SparseImageMemoryRequirements2::default(); count as usize]; + let mut requirements2_vk = + vec![SparseImageMemoryRequirements::to_mut_vk2(); count as usize]; if device.api_version() >= Version::V1_1 { (fns.v1_1.get_image_sparse_memory_requirements2)( self.device.handle(), - &info2, + &info2_vk, &mut count, - sparse_image_memory_requirements2.as_mut_ptr(), + requirements2_vk.as_mut_ptr(), ); } else { (fns.khr_get_memory_requirements2 .get_image_sparse_memory_requirements2_khr)( self.device.handle(), - &info2, + &info2_vk, &mut count, - sparse_image_memory_requirements2.as_mut_ptr(), + requirements2_vk.as_mut_ptr(), ); } - sparse_image_memory_requirements2.set_len(count as usize); + requirements2_vk.set_len(count as usize); - sparse_image_memory_requirements2 - .into_iter() - .map( - |sparse_image_memory_requirements2| SparseImageMemoryRequirements { - format_properties: SparseImageFormatProperties { - aspects: sparse_image_memory_requirements2 - .memory_requirements - .format_properties - .aspect_mask - .into(), - image_granularity: [ - sparse_image_memory_requirements2 - .memory_requirements - .format_properties - .image_granularity - .width, - sparse_image_memory_requirements2 - .memory_requirements - .format_properties - .image_granularity - .height, - sparse_image_memory_requirements2 - .memory_requirements - .format_properties - .image_granularity - .depth, - ], - flags: sparse_image_memory_requirements2 - .memory_requirements - .format_properties - .flags - .into(), - }, - image_mip_tail_first_lod: sparse_image_memory_requirements2 - .memory_requirements - .image_mip_tail_first_lod, - image_mip_tail_size: sparse_image_memory_requirements2 - .memory_requirements - .image_mip_tail_size, - image_mip_tail_offset: sparse_image_memory_requirements2 - .memory_requirements - .image_mip_tail_offset, - image_mip_tail_stride: (!sparse_image_memory_requirements2 - .memory_requirements - .format_properties - .flags - .intersects(ash::vk::SparseImageFormatFlags::SINGLE_MIPTAIL)) - .then_some( - sparse_image_memory_requirements2 - .memory_requirements - .image_mip_tail_stride, - ), - }, - ) + requirements2_vk + .iter() + .map(SparseImageMemoryRequirements::from_vk2) .collect() } else { let mut count = 0; @@ -629,59 +415,21 @@ impl RawImage { ptr::null_mut(), ); - let mut sparse_image_memory_requirements = - vec![ash::vk::SparseImageMemoryRequirements::default(); count as usize]; + let mut requirements_vk = + vec![SparseImageMemoryRequirements::to_mut_vk(); count as usize]; (fns.v1_0.get_image_sparse_memory_requirements)( device.handle(), self.handle, &mut count, - sparse_image_memory_requirements.as_mut_ptr(), + requirements_vk.as_mut_ptr(), ); - sparse_image_memory_requirements.set_len(count as usize); + requirements_vk.set_len(count as usize); - sparse_image_memory_requirements - .into_iter() - .map( - |sparse_image_memory_requirements| SparseImageMemoryRequirements { - format_properties: SparseImageFormatProperties { - aspects: sparse_image_memory_requirements - .format_properties - .aspect_mask - .into(), - image_granularity: [ - sparse_image_memory_requirements - .format_properties - .image_granularity - .width, - sparse_image_memory_requirements - .format_properties - .image_granularity - .height, - sparse_image_memory_requirements - .format_properties - .image_granularity - .depth, - ], - flags: sparse_image_memory_requirements - .format_properties - .flags - .into(), - }, - image_mip_tail_first_lod: sparse_image_memory_requirements - .image_mip_tail_first_lod, - image_mip_tail_size: sparse_image_memory_requirements - .image_mip_tail_size, - image_mip_tail_offset: sparse_image_memory_requirements - .image_mip_tail_offset, - image_mip_tail_stride: (!sparse_image_memory_requirements - .format_properties - .flags - .intersects(ash::vk::SparseImageFormatFlags::SINGLE_MIPTAIL)) - .then_some(sparse_image_memory_requirements.image_mip_tail_stride), - }, - ) + requirements_vk + .iter() + .map(SparseImageMemoryRequirements::from_vk) .collect() } } @@ -1130,76 +878,68 @@ impl RawImage { ), > { let allocations: SmallVec<[_; 4]> = allocations.into_iter().collect(); + + const PLANE_ASPECTS_VK_NORMAL: &[ash::vk::ImageAspectFlags] = &[ + ash::vk::ImageAspectFlags::PLANE_0, + ash::vk::ImageAspectFlags::PLANE_1, + ash::vk::ImageAspectFlags::PLANE_2, + ]; + const PLANE_ASPECTS_VK_DRM_FORMAT_MODIFIER: &[ash::vk::ImageAspectFlags] = &[ + ash::vk::ImageAspectFlags::MEMORY_PLANE_0_EXT, + ash::vk::ImageAspectFlags::MEMORY_PLANE_1_EXT, + ash::vk::ImageAspectFlags::MEMORY_PLANE_2_EXT, + ash::vk::ImageAspectFlags::MEMORY_PLANE_3_EXT, + ]; + let needs_plane = (self.device.api_version() >= Version::V1_1 + || self.device.enabled_extensions().khr_bind_memory2) + && self.flags.intersects(ImageCreateFlags::DISJOINT); + + let plane_aspects_vk = if needs_plane { + Some(match self.tiling { + // VUID-VkBindImagePlaneMemoryInfo-planeAspect-02283 + ImageTiling::Optimal | ImageTiling::Linear => { + let plane_count = self.format.planes().len(); + &PLANE_ASPECTS_VK_NORMAL[..plane_count] + } + // VUID-VkBindImagePlaneMemoryInfo-planeAspect-02284 + ImageTiling::DrmFormatModifier => { + let plane_count = self.drm_format_modifier.unwrap().1 as usize; + &PLANE_ASPECTS_VK_DRM_FORMAT_MODIFIER[..plane_count] + } + }) + } else { + debug_assert_eq!(allocations.len(), 1); + None + }; + + let mut plane_infos_vk: SmallVec<[_; 4]> = (0..allocations.len()) + .map(|plane_num| { + plane_aspects_vk.map(|plane_aspects_vk| { + let plane_aspect_vk = plane_aspects_vk[plane_num]; + ash::vk::BindImagePlaneMemoryInfo::default().plane_aspect(plane_aspect_vk) + }) + }) + .collect(); + + let infos_vk: SmallVec<[_; 4]> = allocations + .iter() + .zip(&mut plane_infos_vk) + .map(|(allocation, plane_info_vk)| { + let mut info_vk = allocation.to_vk_bind_image_memory_info(self.handle); + + if let Some(next) = plane_info_vk { + info_vk = info_vk.push_next(next); + } + + info_vk + }) + .collect(); + let fns = self.device.fns(); let result = if self.device.api_version() >= Version::V1_1 || self.device.enabled_extensions().khr_bind_memory2 { - let mut infos_vk: SmallVec<[_; 4]> = SmallVec::with_capacity(3); - let mut plane_infos_vk: SmallVec<[_; 4]> = SmallVec::with_capacity(3); - - if self.flags.intersects(ImageCreateFlags::DISJOINT) { - for (plane, allocation) in allocations.iter().enumerate() { - let memory = allocation.device_memory(); - let memory_offset = allocation.offset(); - let plane_aspect = match self.tiling { - // VUID-VkBindImagePlaneMemoryInfo-planeAspect-02283 - ImageTiling::Optimal | ImageTiling::Linear => { - debug_assert_eq!(allocations.len(), self.format.planes().len()); - match plane { - 0 => ash::vk::ImageAspectFlags::PLANE_0, - 1 => ash::vk::ImageAspectFlags::PLANE_1, - 2 => ash::vk::ImageAspectFlags::PLANE_2, - _ => unreachable!(), - } - } - // VUID-VkBindImagePlaneMemoryInfo-planeAspect-02284 - ImageTiling::DrmFormatModifier => { - debug_assert_eq!( - allocations.len(), - self.drm_format_modifier.unwrap().1 as usize - ); - match plane { - 0 => ash::vk::ImageAspectFlags::MEMORY_PLANE_0_EXT, - 1 => ash::vk::ImageAspectFlags::MEMORY_PLANE_1_EXT, - 2 => ash::vk::ImageAspectFlags::MEMORY_PLANE_2_EXT, - 3 => ash::vk::ImageAspectFlags::MEMORY_PLANE_3_EXT, - _ => unreachable!(), - } - } - }; - - infos_vk.push(ash::vk::BindImageMemoryInfo { - image: self.handle, - memory: memory.handle(), - memory_offset, - ..Default::default() - }); - // VUID-VkBindImageMemoryInfo-pNext-01618 - plane_infos_vk.push(ash::vk::BindImagePlaneMemoryInfo { - plane_aspect, - ..Default::default() - }); - } - } else { - debug_assert_eq!(allocations.len(), 1); - - let allocation = &allocations[0]; - let memory = allocation.device_memory(); - let memory_offset = allocation.offset(); - - infos_vk.push(ash::vk::BindImageMemoryInfo { - image: self.handle, - memory: memory.handle(), - memory_offset, - ..Default::default() - }); - }; - - for (info_vk, plane_info_vk) in infos_vk.iter_mut().zip(plane_infos_vk.iter_mut()) { - info_vk.p_next = <*mut _>::cast(plane_info_vk); - } - if self.device.api_version() >= Version::V1_1 { (fns.v1_1.bind_image_memory2)( self.device.handle(), @@ -1214,17 +954,13 @@ impl RawImage { ) } } else { - debug_assert_eq!(allocations.len(), 1); - - let allocation = &allocations[0]; - let memory = allocation.device_memory(); - let memory_offset = allocation.offset(); + let info_vk = &infos_vk[0]; (fns.v1_0.bind_image_memory)( self.device.handle(), - self.handle, - memory.handle(), - memory_offset, + info_vk.image, + info_vk.memory, + info_vk.memory_offset, ) } .result(); @@ -1646,7 +1382,7 @@ impl RawImage { |&(aspect, mip_level, array_layer)| { let fns = self.device.fns(); - let subresource = ash::vk::ImageSubresource { + let subresource_vk = ash::vk::ImageSubresource { aspect_mask: aspect.into(), mip_level, array_layer, @@ -1656,7 +1392,7 @@ impl RawImage { (fns.v1_0.get_image_subresource_layout)( self.device.handle(), self.handle, - &subresource, + &subresource_vk, output.as_mut_ptr(), ); let output = output.assume_init(); @@ -3006,6 +2742,164 @@ impl ImageCreateInfo { Ok(()) } + + pub(crate) fn to_vk<'a>( + &'a self, + extensions_vk: &'a mut ImageCreateInfoExtensionsVk<'_>, + ) -> ash::vk::ImageCreateInfo<'_> { + let &Self { + flags, + image_type, + format, + view_formats: _, + extent, + array_layers, + mip_levels, + samples, + tiling, + usage, + stencil_usage: _, + ref sharing, + initial_layout, + drm_format_modifiers: _, + drm_format_modifier_plane_layouts: _, + external_memory_handle_types: _, + _ne: _, + } = self; + + let (sharing_mode, queue_family_indices_vk) = match sharing { + Sharing::Exclusive => (ash::vk::SharingMode::EXCLUSIVE, [].as_slice()), + Sharing::Concurrent(queue_family_indices) => ( + ash::vk::SharingMode::CONCURRENT, + queue_family_indices.as_slice(), + ), + }; + + let mut val_vk = ash::vk::ImageCreateInfo::default() + .flags(flags.into()) + .image_type(image_type.into()) + .format(format.into()) + .extent(ash::vk::Extent3D { + width: extent[0], + height: extent[1], + depth: extent[2], + }) + .mip_levels(mip_levels) + .array_layers(array_layers) + .samples(samples.into()) + .tiling(tiling.into()) + .usage(usage.into()) + .sharing_mode(sharing_mode) + .queue_family_indices(queue_family_indices_vk) + .initial_layout(initial_layout.into()); + + let ImageCreateInfoExtensionsVk { + drm_format_modifier_explicit_vk, + drm_format_modifier_list_vk, + external_memory_vk, + format_list_vk, + stencil_usage_vk, + } = extensions_vk; + + if let Some(next) = drm_format_modifier_explicit_vk { + val_vk = val_vk.push_next(next); + } + + if let Some(next) = drm_format_modifier_list_vk { + val_vk = val_vk.push_next(next); + } + + if let Some(next) = external_memory_vk { + val_vk = val_vk.push_next(next); + } + + if let Some(next) = format_list_vk { + val_vk = val_vk.push_next(next); + } + + if let Some(next) = stencil_usage_vk { + val_vk = val_vk.push_next(next); + } + + val_vk + } + + pub(crate) fn to_vk_extensions<'a>( + &'a self, + fields1_vk: &'a ImageCreateInfoFields1Vk, + ) -> ImageCreateInfoExtensionsVk<'a> { + let ImageCreateInfoFields1Vk { + plane_layouts_vk, + view_formats_vk, + } = fields1_vk; + + let drm_format_modifier_explicit_vk = (!plane_layouts_vk.is_empty()).then(|| { + ash::vk::ImageDrmFormatModifierExplicitCreateInfoEXT::default() + .drm_format_modifier(self.drm_format_modifiers[0]) + .plane_layouts(plane_layouts_vk) + }); + + let drm_format_modifier_list_vk = (!self.drm_format_modifier_plane_layouts.is_empty()) + .then(|| { + ash::vk::ImageDrmFormatModifierListCreateInfoEXT::default() + .drm_format_modifiers(&self.drm_format_modifiers) + }); + + let external_memory_vk = (!self.external_memory_handle_types.is_empty()).then(|| { + ash::vk::ExternalMemoryImageCreateInfo::default() + .handle_types(self.external_memory_handle_types.into()) + }); + + let format_list_vk = (!view_formats_vk.is_empty()) + .then(|| ash::vk::ImageFormatListCreateInfo::default().view_formats(view_formats_vk)); + + let stencil_usage_vk = self.stencil_usage.map(|stencil_usage| { + ash::vk::ImageStencilUsageCreateInfo::default().stencil_usage(stencil_usage.into()) + }); + + ImageCreateInfoExtensionsVk { + drm_format_modifier_explicit_vk, + drm_format_modifier_list_vk, + external_memory_vk, + format_list_vk, + stencil_usage_vk, + } + } + + pub(crate) fn to_vk_fields1(&self) -> ImageCreateInfoFields1Vk { + let plane_layouts_vk = self + .drm_format_modifier_plane_layouts + .iter() + .map(SubresourceLayout::to_vk) + .collect(); + + let view_formats_vk = self + .view_formats + .iter() + .copied() + .map(ash::vk::Format::from) + .collect(); + + ImageCreateInfoFields1Vk { + plane_layouts_vk, + view_formats_vk, + } + } +} + +pub(crate) struct ImageCreateInfoExtensionsVk<'a> { + pub(crate) drm_format_modifier_explicit_vk: + Option>, + pub(crate) drm_format_modifier_list_vk: + Option>, + pub(crate) external_memory_vk: Option>, + pub(crate) format_list_vk: Option>, + pub(crate) stencil_usage_vk: Option>, +} + +pub(crate) struct ImageCreateInfoFields1Vk { + plane_layouts_vk: SmallVec<[ash::vk::SubresourceLayout; 4]>, + view_formats_vk: Vec, } #[cfg(test)] diff --git a/vulkano/src/image/view.rs b/vulkano/src/image/view.rs index 9f57d951..fb040743 100644 --- a/vulkano/src/image/view.rs +++ b/vulkano/src/image/view.rs @@ -556,65 +556,18 @@ impl ImageView { image: Arc, create_info: ImageViewCreateInfo, ) -> Result, VulkanError> { - let &ImageViewCreateInfo { - view_type, - format, - component_mapping, - ref subresource_range, - mut usage, - ref sampler_ycbcr_conversion, - _ne: _, - } = &create_info; - - let device = image.device(); - let implicit_default_usage = get_implicit_default_usage(subresource_range.aspects, &image); - - let has_non_default_usage = if usage.is_empty() { - usage = implicit_default_usage; - false - } else { - usage != implicit_default_usage - }; - - let mut info_vk = ash::vk::ImageViewCreateInfo { - flags: ash::vk::ImageViewCreateFlags::empty(), - image: image.handle(), - view_type: view_type.into(), - format: format.into(), - components: component_mapping.into(), - subresource_range: subresource_range.clone().into(), - ..Default::default() - }; - let mut image_view_usage_info_vk = None; - let mut sampler_ycbcr_conversion_info_vk = None; - - if has_non_default_usage { - let next = image_view_usage_info_vk.insert(ash::vk::ImageViewUsageCreateInfo { - usage: usage.into(), - ..Default::default() - }); - - next.p_next = info_vk.p_next; - info_vk.p_next = <*const _>::cast(next); - } - - if let Some(conversion) = sampler_ycbcr_conversion { - let next = - sampler_ycbcr_conversion_info_vk.insert(ash::vk::SamplerYcbcrConversionInfo { - conversion: conversion.handle(), - ..Default::default() - }); - - next.p_next = info_vk.p_next; - info_vk.p_next = <*const _>::cast(next); - } + let implicit_default_usage = + get_implicit_default_usage(create_info.subresource_range.aspects, &image); + let mut create_info_extensions_vk = create_info.to_vk_extensions(implicit_default_usage); + let create_info_vk = create_info.to_vk(image.handle(), &mut create_info_extensions_vk); let handle = { + let device = image.device(); let fns = device.fns(); let mut output = MaybeUninit::uninit(); (fns.v1_0.create_image_view)( device.handle(), - &info_vk, + &create_info_vk, ptr::null(), output.as_mut_ptr(), ) @@ -1068,6 +1021,74 @@ impl ImageViewCreateInfo { Ok(()) } + + pub(crate) fn to_vk<'a>( + &self, + image_vk: ash::vk::Image, + extensions_vk: &'a mut ImageViewCreateInfoExtensionsVk, + ) -> ash::vk::ImageViewCreateInfo<'a> { + let &Self { + view_type, + format, + component_mapping, + ref subresource_range, + usage: _, + sampler_ycbcr_conversion: _, + _ne: _, + } = self; + + let mut val_vk = ash::vk::ImageViewCreateInfo::default() + .flags(ash::vk::ImageViewCreateFlags::empty()) + .image(image_vk) + .view_type(view_type.into()) + .format(format.into()) + .components(component_mapping.to_vk()) + .subresource_range(subresource_range.to_vk()); + + let ImageViewCreateInfoExtensionsVk { + sampler_ycbcr_conversion_vk, + usage_vk, + } = extensions_vk; + + if let Some(next) = sampler_ycbcr_conversion_vk { + val_vk = val_vk.push_next(next); + } + + if let Some(next) = usage_vk { + val_vk = val_vk.push_next(next); + } + + val_vk + } + + pub(crate) fn to_vk_extensions( + &self, + implicit_default_usage: ImageUsage, + ) -> ImageViewCreateInfoExtensionsVk { + let &Self { + usage, + ref sampler_ycbcr_conversion, + .. + } = self; + + let sampler_ycbcr_conversion_vk = sampler_ycbcr_conversion.as_ref().map(|conversion| { + ash::vk::SamplerYcbcrConversionInfo::default().conversion(conversion.handle()) + }); + + let has_non_default_usage = !(usage.is_empty() || usage == implicit_default_usage); + let usage_vk = has_non_default_usage + .then(|| ash::vk::ImageViewUsageCreateInfo::default().usage(usage.into())); + + ImageViewCreateInfoExtensionsVk { + sampler_ycbcr_conversion_vk, + usage_vk, + } + } +} + +pub(crate) struct ImageViewCreateInfoExtensionsVk { + pub(crate) sampler_ycbcr_conversion_vk: Option>, + pub(crate) usage_vk: Option>, } vulkan_enum! { diff --git a/vulkano/src/instance/debug.rs b/vulkano/src/instance/debug.rs index c1a3b677..9a0ca0e6 100644 --- a/vulkano/src/instance/debug.rs +++ b/vulkano/src/instance/debug.rs @@ -42,7 +42,7 @@ use crate::{ VulkanError, VulkanObject, }; use std::{ - ffi::{c_void, CStr}, + ffi::{c_void, CStr, CString}, fmt::{Debug, Error as FmtError, Formatter}, mem::MaybeUninit, panic::{catch_unwind, AssertUnwindSafe, RefUnwindSafe}, @@ -97,21 +97,7 @@ impl DebugUtilsMessenger { instance: Arc, create_info: DebugUtilsMessengerCreateInfo, ) -> Result { - let DebugUtilsMessengerCreateInfo { - message_severity, - message_type, - user_callback, - _ne: _, - } = create_info; - - let create_info_vk = ash::vk::DebugUtilsMessengerCreateInfoEXT { - flags: ash::vk::DebugUtilsMessengerCreateFlagsEXT::empty(), - message_severity: message_severity.into(), - message_type: message_type.into(), - pfn_user_callback: Some(trampoline), - p_user_data: user_callback.as_ptr().cast_mut().cast(), - ..Default::default() - }; + let create_info_vk = create_info.to_vk(); let handle = { let fns = instance.fns(); @@ -130,7 +116,7 @@ impl DebugUtilsMessenger { Ok(DebugUtilsMessenger { handle, instance: DebugWrapper(instance), - _user_callback: user_callback, + _user_callback: create_info.user_callback, }) } } @@ -257,6 +243,22 @@ impl DebugUtilsMessengerCreateInfo { Ok(()) } + + pub(crate) fn to_vk(&self) -> ash::vk::DebugUtilsMessengerCreateInfoEXT<'static> { + let &Self { + message_type, + message_severity, + ref user_callback, + _ne: _, + } = self; + + ash::vk::DebugUtilsMessengerCreateInfoEXT::default() + .flags(ash::vk::DebugUtilsMessengerCreateFlagsEXT::empty()) + .message_severity(message_severity.into()) + .message_type(message_type.into()) + .pfn_user_callback(Some(trampoline)) + .user_data(user_callback.as_ptr().cast_mut().cast()) + } } impl Debug for DebugUtilsMessengerCreateInfo { @@ -319,8 +321,6 @@ pub(super) unsafe extern "system" fn trampoline( // bound is enforced. Therefore we enforce it manually. let _ = catch_unwind(AssertUnwindSafe(move || { let ash::vk::DebugUtilsMessengerCallbackDataEXT { - s_type: _, - p_next: _, flags: _, p_message_id_name, message_id_number, @@ -331,7 +331,7 @@ pub(super) unsafe extern "system" fn trampoline( p_cmd_buf_labels, object_count, p_objects, - _marker: _, + .. } = *callback_data_vk; let callback_data = DebugUtilsMessengerCallbackData { @@ -457,12 +457,10 @@ impl<'a> Iterator for DebugUtilsMessengerCallbackObjectNameInfoIter<'a> { fn next(&mut self) -> Option { self.0.next().map(|info| unsafe { let &ash::vk::DebugUtilsObjectNameInfoEXT { - s_type: _, - p_next: _, object_type, object_handle, p_object_name, - _marker: _, + .. } = info; DebugUtilsMessengerCallbackObjectNameInfo { @@ -544,6 +542,35 @@ impl Default for DebugUtilsLabel { } } +impl DebugUtilsLabel { + pub(crate) fn to_vk<'a>( + &self, + fields1_vk: &'a DebugUtilsLabelFields1Vk, + ) -> ash::vk::DebugUtilsLabelEXT<'a> { + let &Self { + label_name: _, + color, + _ne, + } = self; + + let DebugUtilsLabelFields1Vk { label_name_vk } = fields1_vk; + + ash::vk::DebugUtilsLabelEXT::default() + .label_name(label_name_vk) + .color(color) + } + + pub(crate) fn to_vk_fields1(&self) -> DebugUtilsLabelFields1Vk { + let label_name_vk = CString::new(self.label_name.as_str()).unwrap(); + + DebugUtilsLabelFields1Vk { label_name_vk } + } +} + +pub(crate) struct DebugUtilsLabelFields1Vk { + pub(crate) label_name_vk: CString, +} + vulkan_enum! { #[non_exhaustive] diff --git a/vulkano/src/instance/mod.rs b/vulkano/src/instance/mod.rs index aea1ea36..47978f71 100644 --- a/vulkano/src/instance/mod.rs +++ b/vulkano/src/instance/mod.rs @@ -83,7 +83,6 @@ use crate::{ device::physical::{ PhysicalDevice, PhysicalDeviceGroupProperties, PhysicalDeviceGroupPropertiesRaw, }, - instance::debug::trampoline, macros::{impl_id_counter, vulkan_bitflags}, Requires, RequiresAllOf, RequiresOneOf, Validated, ValidationError, VulkanError, VulkanLibrary, VulkanObject, @@ -93,8 +92,7 @@ use ash::vk::Handle; use parking_lot::RwLock; use smallvec::SmallVec; use std::{ - borrow::Cow, - ffi::CString, + ffi::{c_char, CString}, fmt::{Debug, Error as FmtError, Formatter}, mem::MaybeUninit, num::NonZeroU64, @@ -367,140 +365,28 @@ impl Instance { .unwrap(), ); - let &InstanceCreateInfo { - mut flags, - ref application_name, - application_version, - ref engine_name, - engine_version, - max_api_version, - ref enabled_layers, - ref enabled_extensions, - ref debug_utils_messengers, - ref enabled_validation_features, - ref disabled_validation_features, - _ne: _, - } = &create_info; - - let mut enabled_extensions = Cow::Borrowed(enabled_extensions); - - if flags.intersects(InstanceCreateFlags::ENUMERATE_PORTABILITY) { + if create_info + .flags + .intersects(InstanceCreateFlags::ENUMERATE_PORTABILITY) + { // VUID-VkInstanceCreateInfo-flags-06559 if library - .supported_extensions_with_layers(enabled_layers.iter().map(String::as_str))? + .supported_extensions_with_layers( + create_info.enabled_layers.iter().map(String::as_str), + )? .khr_portability_enumeration { - enabled_extensions.to_mut().khr_portability_enumeration = true; + create_info.enabled_extensions.khr_portability_enumeration = true; } else { - flags -= InstanceCreateFlags::ENUMERATE_PORTABILITY; + create_info.flags -= InstanceCreateFlags::ENUMERATE_PORTABILITY; } } - let enabled_layers_vk: Vec = enabled_layers - .iter() - .map(|name| CString::new(name.clone()).unwrap()) - .collect(); - let enabled_layers_ptrs_vk = enabled_layers_vk - .iter() - .map(|layer| layer.as_ptr()) - .collect::>(); - - let enabled_extensions_vk: Vec = enabled_extensions.as_ref().into(); - let enabled_extensions_ptrs_vk = enabled_extensions_vk - .iter() - .map(|extension| extension.as_ptr()) - .collect::>(); - - let application_name_vk = application_name - .as_ref() - .map(|name| CString::new(name.clone()).unwrap()); - let engine_name_vk = engine_name - .as_ref() - .map(|name| CString::new(name.clone()).unwrap()); - let application_info_vk = ash::vk::ApplicationInfo { - p_application_name: application_name_vk - .as_ref() - .map(|s| s.as_ptr()) - .unwrap_or(ptr::null()), - application_version: application_version - .try_into() - .expect("Version out of range"), - p_engine_name: engine_name_vk - .as_ref() - .map(|s| s.as_ptr()) - .unwrap_or(ptr::null()), - engine_version: engine_version.try_into().expect("Version out of range"), - api_version: max_api_version - .unwrap() - .try_into() - .expect("Version out of range"), - ..Default::default() - }; - - let enable_validation_features_vk: SmallVec<[_; 5]> = enabled_validation_features - .iter() - .copied() - .map(Into::into) - .collect(); - let disable_validation_features_vk: SmallVec<[_; 8]> = disabled_validation_features - .iter() - .copied() - .map(Into::into) - .collect(); - - let mut create_info_vk = ash::vk::InstanceCreateInfo { - flags: flags.into(), - p_application_info: &application_info_vk, - enabled_layer_count: enabled_layers_ptrs_vk.len() as u32, - pp_enabled_layer_names: enabled_layers_ptrs_vk.as_ptr(), - enabled_extension_count: enabled_extensions_ptrs_vk.len() as u32, - pp_enabled_extension_names: enabled_extensions_ptrs_vk.as_ptr(), - ..Default::default() - }; - let mut validation_features_vk = None; - - if !enabled_validation_features.is_empty() || !disabled_validation_features.is_empty() { - let next = validation_features_vk.insert(ash::vk::ValidationFeaturesEXT { - enabled_validation_feature_count: enable_validation_features_vk.len() as u32, - p_enabled_validation_features: enable_validation_features_vk.as_ptr(), - disabled_validation_feature_count: disable_validation_features_vk.len() as u32, - p_disabled_validation_features: disable_validation_features_vk.as_ptr(), - ..Default::default() - }); - - next.p_next = create_info_vk.p_next; - create_info_vk.p_next = <*const _>::cast(next); - } - - let mut debug_utils_messenger_create_infos_vk: Vec<_> = debug_utils_messengers - .iter() - .map(|create_info| { - let &DebugUtilsMessengerCreateInfo { - message_type, - message_severity, - ref user_callback, - _ne: _, - } = create_info; - - ash::vk::DebugUtilsMessengerCreateInfoEXT { - flags: ash::vk::DebugUtilsMessengerCreateFlagsEXT::empty(), - message_severity: message_severity.into(), - message_type: message_type.into(), - pfn_user_callback: Some(trampoline), - p_user_data: user_callback.as_ptr().cast_mut().cast(), - ..Default::default() - } - }) - .collect(); - - for i in 1..debug_utils_messenger_create_infos_vk.len() { - debug_utils_messenger_create_infos_vk[i - 1].p_next = - <*const _>::cast(&debug_utils_messenger_create_infos_vk[i]); - } - - if let Some(info) = debug_utils_messenger_create_infos_vk.first() { - create_info_vk.p_next = <*const _>::cast(info); - } + let create_info_fields2_vk = create_info.to_vk_fields2(); + let create_info_fields1_vk = create_info.to_vk_fields1(&create_info_fields2_vk); + let mut create_info_extensions_vk = create_info.to_vk_extensions(&create_info_fields1_vk); + let create_info_vk = + create_info.to_vk(&create_info_fields1_vk, &mut create_info_extensions_vk); let handle = { let mut output = MaybeUninit::uninit(); @@ -1151,6 +1037,220 @@ impl InstanceCreateInfo { Ok(()) } + + pub(crate) fn to_vk<'a>( + &self, + fields1_vk: &'a InstanceCreateInfoFields1Vk<'_>, + extensions_vk: &'a mut InstanceCreateInfoExtensionsVk<'_>, + ) -> ash::vk::InstanceCreateInfo<'a> { + let &Self { + flags, + application_name: _, + application_version: _, + engine_name: _, + engine_version: _, + max_api_version: _, + enabled_layers: _, + enabled_extensions: _, + debug_utils_messengers: _, + enabled_validation_features: _, + disabled_validation_features: _, + _ne: _, + } = self; + let InstanceCreateInfoFields1Vk { + application_info_vk, + enabled_layer_names_vk, + enabled_extension_names_vk, + enable_validation_features_vk: _, + disable_validation_features_vk: _, + } = fields1_vk; + + let mut val_vk = ash::vk::InstanceCreateInfo::default() + .flags(flags.into()) + .application_info(application_info_vk) + .enabled_layer_names(enabled_layer_names_vk) + .enabled_extension_names(enabled_extension_names_vk); + + let InstanceCreateInfoExtensionsVk { + debug_utils_messengers_vk, + validation_features_vk, + } = extensions_vk; + + // push_next adds in reverse + for next in debug_utils_messengers_vk.iter_mut().rev() { + val_vk = val_vk.push_next(next); + } + + if let Some(next) = validation_features_vk { + val_vk = val_vk.push_next(next); + } + + val_vk + } + + pub(crate) fn to_vk_extensions<'a>( + &self, + fields1_vk: &'a InstanceCreateInfoFields1Vk<'_>, + ) -> InstanceCreateInfoExtensionsVk<'a> { + let InstanceCreateInfoFields1Vk { + application_info_vk: _, + enabled_layer_names_vk: _, + enabled_extension_names_vk: _, + enable_validation_features_vk, + disable_validation_features_vk, + } = fields1_vk; + + let validation_features_vk = (!enable_validation_features_vk.is_empty() + || !disable_validation_features_vk.is_empty()) + .then(|| { + ash::vk::ValidationFeaturesEXT::default() + .enabled_validation_features(enable_validation_features_vk) + .disabled_validation_features(disable_validation_features_vk) + }); + + let debug_utils_messengers_vk: Vec<_> = self + .debug_utils_messengers + .iter() + .map(DebugUtilsMessengerCreateInfo::to_vk) + .collect(); + + InstanceCreateInfoExtensionsVk { + debug_utils_messengers_vk, + validation_features_vk, + } + } + + pub(crate) fn to_vk_fields1<'a>( + &self, + fields2_vk: &'a InstanceCreateInfoFields2Vk, + ) -> InstanceCreateInfoFields1Vk<'a> { + let &Self { + flags: _, + application_name: _, + application_version, + engine_name: _, + engine_version, + max_api_version, + enabled_layers: _, + enabled_extensions: _, + debug_utils_messengers: _, + ref enabled_validation_features, + ref disabled_validation_features, + _ne: _, + } = self; + let InstanceCreateInfoFields2Vk { + application_name_vk, + engine_name_vk, + enabled_layers_vk, + enabled_extensions_vk, + } = fields2_vk; + + let mut application_info_vk = ash::vk::ApplicationInfo::default() + .application_version( + application_version + .try_into() + .expect("Version out of range"), + ) + .engine_version(engine_version.try_into().expect("Version out of range")) + .api_version( + max_api_version + .unwrap() + .try_into() + .expect("Version out of range"), + ); + + if let Some(application_name_vk) = application_name_vk { + application_info_vk = application_info_vk.application_name(application_name_vk); + } + + if let Some(engine_name_vk) = engine_name_vk { + application_info_vk = application_info_vk.application_name(engine_name_vk); + } + + let enabled_layer_names_vk = enabled_layers_vk + .iter() + .map(|layer| layer.as_ptr()) + .collect(); + let enabled_extension_names_vk = enabled_extensions_vk + .iter() + .map(|extension| extension.as_ptr()) + .collect(); + + let enable_validation_features_vk = enabled_validation_features + .iter() + .copied() + .map(Into::into) + .collect(); + let disable_validation_features_vk = disabled_validation_features + .iter() + .copied() + .map(Into::into) + .collect(); + + InstanceCreateInfoFields1Vk { + application_info_vk, + enabled_layer_names_vk, + enabled_extension_names_vk, + enable_validation_features_vk, + disable_validation_features_vk, + } + } + + pub(crate) fn to_vk_fields2(&self) -> InstanceCreateInfoFields2Vk { + let &Self { + flags: _, + ref application_name, + application_version: _, + ref engine_name, + engine_version: _, + max_api_version: _, + ref enabled_layers, + ref enabled_extensions, + debug_utils_messengers: _, + enabled_validation_features: _, + disabled_validation_features: _, + _ne: _, + } = self; + + let application_name_vk = application_name + .as_ref() + .map(|name| CString::new(name.clone()).unwrap()); + let engine_name_vk = engine_name + .as_ref() + .map(|name| CString::new(name.clone()).unwrap()); + let enabled_layers_vk: Vec = enabled_layers + .iter() + .map(|name| CString::new(name.clone()).unwrap()) + .collect(); + let enabled_extensions_vk: Vec = enabled_extensions.into(); + + InstanceCreateInfoFields2Vk { + application_name_vk, + engine_name_vk, + enabled_layers_vk, + enabled_extensions_vk, + } + } +} + +pub(crate) struct InstanceCreateInfoExtensionsVk<'a> { + pub(crate) debug_utils_messengers_vk: Vec>, + pub(crate) validation_features_vk: Option>, +} + +pub(crate) struct InstanceCreateInfoFields1Vk<'a> { + pub(crate) application_info_vk: ash::vk::ApplicationInfo<'a>, + pub(crate) enabled_layer_names_vk: SmallVec<[*const c_char; 2]>, + pub(crate) enabled_extension_names_vk: SmallVec<[*const c_char; 2]>, + pub(crate) enable_validation_features_vk: SmallVec<[ash::vk::ValidationFeatureEnableEXT; 5]>, + pub(crate) disable_validation_features_vk: SmallVec<[ash::vk::ValidationFeatureDisableEXT; 5]>, +} + +pub(crate) struct InstanceCreateInfoFields2Vk { + pub(crate) application_name_vk: Option, + pub(crate) engine_name_vk: Option, + pub(crate) enabled_layers_vk: Vec, + pub(crate) enabled_extensions_vk: Vec, } vulkan_bitflags! { diff --git a/vulkano/src/memory/device_memory.rs b/vulkano/src/memory/device_memory.rs index ad6b9a95..b7cb2281 100644 --- a/vulkano/src/memory/device_memory.rs +++ b/vulkano/src/memory/device_memory.rs @@ -7,6 +7,7 @@ use crate::{ DeviceSize, Requires, RequiresAllOf, RequiresOneOf, Validated, ValidationError, Version, VulkanError, VulkanObject, }; +use ash::vk::MemoryAllocateFlagsInfo; use std::{ ffi::c_void, fs::File, @@ -151,124 +152,25 @@ impl DeviceMemory { allocate_info.dedicated_allocation = None; } - let MemoryAllocateInfo { - allocation_size, - memory_type_index, - dedicated_allocation, - export_handle_types, - flags, - _ne: _, - } = allocate_info; - - let mut allocate_info_vk = ash::vk::MemoryAllocateInfo { - allocation_size, - memory_type_index, - ..Default::default() - }; - - let mut dedicated_allocate_info_vk = None; - let mut export_allocate_info_vk = None; - let mut import_fd_info_vk = None; - let mut import_win32_handle_info_vk = None; - let mut flags_info_vk = None; - - // VUID-VkMemoryDedicatedAllocateInfo-image-01432 - if let Some(dedicated_allocation) = dedicated_allocation { - let next = dedicated_allocate_info_vk.insert(match dedicated_allocation { - DedicatedAllocation::Buffer(buffer) => ash::vk::MemoryDedicatedAllocateInfo { - buffer: buffer.handle(), - ..Default::default() - }, - DedicatedAllocation::Image(image) => ash::vk::MemoryDedicatedAllocateInfo { - image: image.handle(), - ..Default::default() - }, - }); - - next.p_next = allocate_info_vk.p_next; - allocate_info_vk.p_next = <*const _>::cast(next); - } - - if !export_handle_types.is_empty() { - let next = export_allocate_info_vk.insert(ash::vk::ExportMemoryAllocateInfo { - handle_types: export_handle_types.into(), - ..Default::default() - }); - - next.p_next = allocate_info_vk.p_next; - allocate_info_vk.p_next = <*const _>::cast(next); - } - - let imported_handle_type = import_info.as_ref().map(|import_info| match import_info { - MemoryImportInfo::Fd { handle_type, .. } => *handle_type, - MemoryImportInfo::Win32 { handle_type, .. } => *handle_type, - }); - - if let Some(import_info) = import_info { - match import_info { - MemoryImportInfo::Fd { handle_type, file } => { - #[cfg(unix)] - let fd = { - use std::os::fd::IntoRawFd; - file.into_raw_fd() - }; - - #[cfg(not(unix))] - let fd = { - let _ = file; - -1 - }; - - let next = import_fd_info_vk.insert(ash::vk::ImportMemoryFdInfoKHR { - handle_type: handle_type.into(), - fd, - ..Default::default() - }); - - next.p_next = allocate_info_vk.p_next; - allocate_info_vk.p_next = <*const _>::cast(next); - } - MemoryImportInfo::Win32 { - handle_type, - handle, - } => { - let next = import_win32_handle_info_vk.insert( - ash::vk::ImportMemoryWin32HandleInfoKHR { - handle_type: handle_type.into(), - handle, - ..Default::default() - }, - ); - - next.p_next = allocate_info_vk.p_next; - allocate_info_vk.p_next = <*const _>::cast(next); - } - } - } - - if !flags.is_empty() { - let next = flags_info_vk.insert(ash::vk::MemoryAllocateFlagsInfo { - flags: flags.into(), - ..Default::default() - }); - - next.p_next = allocate_info_vk.p_next; - allocate_info_vk.p_next = <*const _>::cast(next); - } - - // VUID-vkAllocateMemory-maxMemoryAllocationCount-04101 - let max_allocations = device - .physical_device() - .properties() - .max_memory_allocation_count; - device - .allocation_count - .fetch_update(Ordering::Acquire, Ordering::Relaxed, move |count| { - (count < max_allocations).then_some(count + 1) - }) - .map_err(|_| VulkanError::TooManyObjects)?; + let imported_handle_type = import_info.as_ref().map(MemoryImportInfo::handle_type); let handle = { + let import_vk = import_info.map(MemoryImportInfo::into_vk); + let mut allocate_info_extensions_vk = allocate_info.to_vk_extensions(import_vk); + let allocate_info_vk = allocate_info.to_vk(&mut allocate_info_extensions_vk); + + // VUID-vkAllocateMemory-maxMemoryAllocationCount-04101 + let max_allocations = device + .physical_device() + .properties() + .max_memory_allocation_count; + device + .allocation_count + .fetch_update(Ordering::Acquire, Ordering::Relaxed, move |count| { + (count < max_allocations).then_some(count + 1) + }) + .map_err(|_| VulkanError::TooManyObjects)?; + let fns = device.fns(); let mut output = MaybeUninit::uninit(); (fns.v1_0.allocate_memory)( @@ -286,6 +188,15 @@ impl DeviceMemory { output.assume_init() }; + let MemoryAllocateInfo { + allocation_size, + memory_type_index, + dedicated_allocation, + export_handle_types, + flags, + _ne: _, + } = allocate_info; + let atom_size = device.physical_device().properties().non_coherent_atom_size; let is_coherent = device.physical_device().memory_properties().memory_types @@ -512,40 +423,16 @@ impl DeviceMemory { map_info: MemoryMapInfo, placed_address: Option>, ) -> Result<(), VulkanError> { - let MemoryMapInfo { - flags, - offset, - size, - _ne: _, - } = map_info; - - // Sanity check: this would lead to UB when calculating pointer offsets. - assert!(size <= isize::MAX.try_into().unwrap()); - let device = self.device(); let ptr = { + let mut extensions_vk = map_info.to_vk_extensions(placed_address); + let map_info_vk = map_info.to_vk(self.handle(), &mut extensions_vk); + let fns = device.fns(); let mut output = MaybeUninit::uninit(); if device.enabled_extensions().khr_map_memory2 { - let map_info_vk = ash::vk::MemoryMapInfoKHR { - flags: flags.into(), - memory: self.handle(), - offset, - size, - ..Default::default() - }; - - let mut map_placed_info_vk = ash::vk::MemoryMapPlacedInfoEXT::default(); - - let map_info_vk = if let Some(it) = placed_address { - map_placed_info_vk.p_placed_address = it.as_ptr(); - map_info_vk.push_next(&mut map_placed_info_vk) - } else { - map_info_vk - }; - (fns.khr_map_memory2.map_memory2_khr)( device.handle(), &map_info_vk, @@ -556,10 +443,10 @@ impl DeviceMemory { } else { (fns.v1_0.map_memory)( device.handle(), - self.handle, - offset, - size, - ash::vk::MemoryMapFlags::empty(), + map_info_vk.memory, + map_info_vk.offset, + map_info_vk.size, + map_info_vk.flags, output.as_mut_ptr(), ) .result() @@ -569,6 +456,13 @@ impl DeviceMemory { output.assume_init() }; + let MemoryMapInfo { + flags: _, + offset, + size, + _ne: _, + } = map_info; + let ptr = NonNull::new(ptr).unwrap(); let range = offset..offset + size; self.mapping_state = Some(MappingState { ptr, range }); @@ -615,23 +509,17 @@ impl DeviceMemory { &mut self, unmap_info: MemoryUnmapInfo, ) -> Result<(), VulkanError> { - let MemoryUnmapInfo { _ne: _ } = unmap_info; + let unmap_info_vk = unmap_info.to_vk(self.handle()); let device = self.device(); let fns = device.fns(); if device.enabled_extensions().khr_map_memory2 { - let unmap_info_vk = ash::vk::MemoryUnmapInfoKHR { - flags: ash::vk::MemoryUnmapFlagsKHR::empty(), - memory: self.handle(), - ..Default::default() - }; - (fns.khr_map_memory2.unmap_memory2_khr)(device.handle(), &unmap_info_vk) .result() .map_err(VulkanError::from)?; } else { - (fns.v1_0.unmap_memory)(device.handle(), self.handle); + (fns.v1_0.unmap_memory)(device.handle(), unmap_info_vk.memory); } self.mapping_state = None; @@ -674,18 +562,7 @@ impl DeviceMemory { return Ok(()); } - let MappedMemoryRange { - offset, - size, - _ne: _, - } = memory_range; - - let memory_range_vk = ash::vk::MappedMemoryRange { - memory: self.handle(), - offset, - size, - ..Default::default() - }; + let memory_range_vk = memory_range.to_vk(self.handle()); let fns = self.device().fns(); (fns.v1_0.invalidate_mapped_memory_ranges)(self.device().handle(), 1, &memory_range_vk) @@ -729,18 +606,7 @@ impl DeviceMemory { return Ok(()); } - let MappedMemoryRange { - offset, - size, - _ne: _, - } = memory_range; - - let memory_range_vk = ash::vk::MappedMemoryRange { - memory: self.handle(), - offset, - size, - ..Default::default() - }; + let memory_range_vk = memory_range.to_vk(self.handle()); let fns = self.device().fns(); (fns.v1_0.flush_mapped_memory_ranges)(self.device().handle(), 1, &memory_range_vk) @@ -870,11 +736,9 @@ impl DeviceMemory { &self, handle_type: ExternalMemoryHandleType, ) -> Result { - let info_vk = ash::vk::MemoryGetFdInfoKHR { - memory: self.handle, - handle_type: handle_type.into(), - ..Default::default() - }; + let info_vk = ash::vk::MemoryGetFdInfoKHR::default() + .memory(self.handle) + .handle_type(handle_type.into()); let fns = self.device.fns(); let mut output = MaybeUninit::uninit(); @@ -1173,6 +1037,99 @@ impl<'d> MemoryAllocateInfo<'d> { Ok(()) } + + pub(crate) fn to_vk<'a>( + &self, + extensions_vk: &'a mut MemoryAllocateInfoExtensionsVk, + ) -> ash::vk::MemoryAllocateInfo<'a> { + let &Self { + allocation_size, + memory_type_index, + dedicated_allocation: _, + export_handle_types: _, + flags: _, + _ne: _, + } = self; + + let mut val_vk = ash::vk::MemoryAllocateInfo::default() + .allocation_size(allocation_size) + .memory_type_index(memory_type_index); + + let MemoryAllocateInfoExtensionsVk { + dedicated_vk, + export_vk, + flags_vk, + import_vk, + } = extensions_vk; + + if let Some(next) = dedicated_vk { + val_vk = val_vk.push_next(next); + } + + if let Some(next) = export_vk { + val_vk = val_vk.push_next(next); + } + + if let Some(next) = flags_vk { + val_vk = val_vk.push_next(next); + } + + if let Some(next) = import_vk { + match next { + MemoryImportInfoVk::Fd(next) => val_vk = val_vk.push_next(next), + MemoryImportInfoVk::Win32Handle(next) => val_vk = val_vk.push_next(next), + } + } + + val_vk + } + + pub(crate) fn to_vk_extensions( + &self, + import_vk: Option, + ) -> MemoryAllocateInfoExtensionsVk { + let &Self { + allocation_size: _, + memory_type_index: _, + dedicated_allocation, + export_handle_types, + flags, + _ne: _, + } = self; + + let dedicated_vk = + dedicated_allocation + .as_ref() + .map(|dedicated_allocation| match dedicated_allocation { + DedicatedAllocation::Buffer(buffer) => { + ash::vk::MemoryDedicatedAllocateInfo::default().buffer(buffer.handle()) + } + DedicatedAllocation::Image(image) => { + ash::vk::MemoryDedicatedAllocateInfo::default().image(image.handle()) + } + }); + + let export_vk = (!export_handle_types.is_empty()).then(|| { + ash::vk::ExportMemoryAllocateInfo::default().handle_types(export_handle_types.into()) + }); + + let flags_vk = (!flags.is_empty()) + .then(|| ash::vk::MemoryAllocateFlagsInfo::default().flags(flags.into())); + + MemoryAllocateInfoExtensionsVk { + dedicated_vk, + export_vk, + flags_vk, + import_vk, + } + } +} + +pub(crate) struct MemoryAllocateInfoExtensionsVk { + pub(crate) dedicated_vk: Option>, + pub(crate) export_vk: Option>, + pub(crate) flags_vk: Option>, + pub(crate) import_vk: Option, } /// Parameters to import memory from an external source. @@ -1328,6 +1285,50 @@ impl MemoryImportInfo { Ok(()) } + + pub(crate) fn handle_type(&self) -> ExternalMemoryHandleType { + match self { + MemoryImportInfo::Fd { handle_type, .. } => *handle_type, + MemoryImportInfo::Win32 { handle_type, .. } => *handle_type, + } + } + + pub(crate) fn into_vk(self) -> MemoryImportInfoVk { + match self { + MemoryImportInfo::Fd { handle_type, file } => { + #[cfg(unix)] + let fd = { + use std::os::fd::IntoRawFd; + file.into_raw_fd() + }; + + #[cfg(not(unix))] + let fd = { + let _ = file; + -1 + }; + + MemoryImportInfoVk::Fd( + ash::vk::ImportMemoryFdInfoKHR::default() + .handle_type(handle_type.into()) + .fd(fd), + ) + } + MemoryImportInfo::Win32 { + handle_type, + handle, + } => MemoryImportInfoVk::Win32Handle( + ash::vk::ImportMemoryWin32HandleInfoKHR::default() + .handle_type(handle_type.into()) + .handle(handle), + ), + } + } +} + +pub(crate) enum MemoryImportInfoVk { + Fd(ash::vk::ImportMemoryFdInfoKHR<'static>), + Win32Handle(ash::vk::ImportMemoryWin32HandleInfoKHR<'static>), } vulkan_bitflags_enum! { @@ -1455,6 +1456,18 @@ pub struct MemoryMapInfo { pub _ne: crate::NonExhaustive, } +impl Default for MemoryMapInfo { + #[inline] + fn default() -> Self { + MemoryMapInfo { + flags: MemoryMapFlags::empty(), + offset: 0, + size: 0, + _ne: crate::NonExhaustive(()), + } + } +} + impl MemoryMapInfo { pub(crate) fn validate( &self, @@ -1646,18 +1659,51 @@ impl MemoryMapInfo { Ok(()) } + + pub(crate) fn to_vk<'a>( + &self, + memory_vk: ash::vk::DeviceMemory, + extensions_vk: &'a mut MemoryMapInfoExtensionsVk, + ) -> ash::vk::MemoryMapInfoKHR<'a> { + let &Self { + flags, + offset, + size, + _ne: _, + } = self; + + // Sanity check: this would lead to UB when calculating pointer offsets. + assert!(size <= isize::MAX.try_into().unwrap()); + + let mut val_vk = ash::vk::MemoryMapInfoKHR::default() + .flags(flags.into()) + .memory(memory_vk) + .offset(offset) + .size(size); + + let MemoryMapInfoExtensionsVk { placed_vk } = extensions_vk; + + if let Some(next) = placed_vk { + val_vk = val_vk.push_next(next); + } + + val_vk + } + + pub(crate) fn to_vk_extensions( + &self, + placed_address: Option>, + ) -> MemoryMapInfoExtensionsVk { + let placed_vk = placed_address.map(|placed_address| { + ash::vk::MemoryMapPlacedInfoEXT::default().placed_address(placed_address.as_ptr()) + }); + + MemoryMapInfoExtensionsVk { placed_vk } + } } -impl Default for MemoryMapInfo { - #[inline] - fn default() -> Self { - MemoryMapInfo { - flags: MemoryMapFlags::empty(), - offset: 0, - size: 0, - _ne: crate::NonExhaustive(()), - } - } +pub(crate) struct MemoryMapInfoExtensionsVk { + pub(crate) placed_vk: Option>, } vulkan_bitflags! { @@ -1673,14 +1719,6 @@ pub struct MemoryUnmapInfo { pub _ne: crate::NonExhaustive, } -impl MemoryUnmapInfo { - pub(crate) fn validate(&self, _memory: &DeviceMemory) -> Result<(), Box> { - let &Self { _ne: _ } = self; - - Ok(()) - } -} - impl Default for MemoryUnmapInfo { #[inline] fn default() -> Self { @@ -1690,6 +1728,25 @@ impl Default for MemoryUnmapInfo { } } +impl MemoryUnmapInfo { + pub(crate) fn validate(&self, _memory: &DeviceMemory) -> Result<(), Box> { + let &Self { _ne: _ } = self; + + Ok(()) + } + + pub(crate) fn to_vk( + &self, + memory_vk: ash::vk::DeviceMemory, + ) -> ash::vk::MemoryUnmapInfoKHR<'static> { + let &Self { _ne: _ } = self; + + ash::vk::MemoryUnmapInfoKHR::default() + .flags(ash::vk::MemoryUnmapFlagsKHR::empty()) + .memory(memory_vk) + } +} + /// Represents the currently host-mapped region of a [`DeviceMemory`] block. #[derive(Debug)] pub struct MappingState { @@ -1849,6 +1906,22 @@ impl MappedMemoryRange { Ok(()) } + + pub(crate) fn to_vk( + &self, + memory_vk: ash::vk::DeviceMemory, + ) -> ash::vk::MappedMemoryRange<'static> { + let &Self { + offset, + size, + _ne: _, + } = self; + + ash::vk::MappedMemoryRange::default() + .memory(memory_vk) + .offset(offset) + .size(size) + } } impl Default for MappedMemoryRange { @@ -2121,15 +2194,15 @@ impl MappedDeviceMemory { return Ok(()); } - let range = ash::vk::MappedMemoryRange { - memory: self.memory.handle(), + let range_vk = MappedMemoryRange { offset: range.start, size: range.end - range.start, ..Default::default() - }; + } + .to_vk(self.memory.handle()); let fns = self.memory.device().fns(); - (fns.v1_0.invalidate_mapped_memory_ranges)(self.memory.device().handle(), 1, &range) + (fns.v1_0.invalidate_mapped_memory_ranges)(self.memory.device().handle(), 1, &range_vk) .result() .map_err(VulkanError::from)?; @@ -2175,15 +2248,15 @@ impl MappedDeviceMemory { return Ok(()); } - let range = ash::vk::MappedMemoryRange { - memory: self.memory.handle(), + let range_vk = MappedMemoryRange { offset: range.start, size: range.end - range.start, ..Default::default() - }; + } + .to_vk(self.memory.handle()); let fns = self.device().fns(); - (fns.v1_0.flush_mapped_memory_ranges)(self.memory.device().handle(), 1, &range) + (fns.v1_0.flush_mapped_memory_ranges)(self.memory.device().handle(), 1, &range_vk) .result() .map_err(VulkanError::from)?; diff --git a/vulkano/src/memory/mod.rs b/vulkano/src/memory/mod.rs index 444f5790..1595ff75 100644 --- a/vulkano/src/memory/mod.rs +++ b/vulkano/src/memory/mod.rs @@ -99,8 +99,9 @@ use crate::{ image::{sys::RawImage, Image, ImageAspects}, macros::vulkan_bitflags, sync::{semaphore::Semaphore, HostAccessError}, - DeviceSize, Validated, ValidationError, VulkanError, + DeviceSize, Validated, ValidationError, Version, VulkanError, VulkanObject, }; +use smallvec::SmallVec; use std::{ cmp, mem::ManuallyDrop, @@ -446,6 +447,38 @@ impl ResourceMemory { _ne: crate::NonExhaustive(()), } } + + pub(crate) fn to_vk_bind_buffer_memory_info( + &self, + buffer_vk: ash::vk::Buffer, + ) -> ash::vk::BindBufferMemoryInfo<'static> { + let &Self { + ref device_memory, + offset, + .. + } = self; + + ash::vk::BindBufferMemoryInfo::default() + .buffer(buffer_vk) + .memory(device_memory.handle()) + .memory_offset(offset) + } + + pub(crate) fn to_vk_bind_image_memory_info( + &self, + image_vk: ash::vk::Image, + ) -> ash::vk::BindImageMemoryInfo<'static> { + let &Self { + ref device_memory, + offset, + .. + } = self; + + ash::vk::BindImageMemoryInfo::default() + .image(image_vk) + .memory(device_memory.handle()) + .memory_offset(offset) + } } impl Drop for ResourceMemory { @@ -484,26 +517,27 @@ pub struct MemoryProperties { pub memory_heaps: Vec, } -impl From for MemoryProperties { - #[inline] - fn from(val: ash::vk::PhysicalDeviceMemoryProperties) -> Self { +impl MemoryProperties { + pub(crate) fn to_mut_vk2() -> ash::vk::PhysicalDeviceMemoryProperties2KHR<'static> { + ash::vk::PhysicalDeviceMemoryProperties2KHR::default() + } + + pub(crate) fn from_vk2(val_vk: &ash::vk::PhysicalDeviceMemoryProperties2<'_>) -> Self { + let &ash::vk::PhysicalDeviceMemoryProperties2 { + ref memory_properties, + .. + } = val_vk; + + Self::from_vk(memory_properties) + } + + pub(crate) fn from_vk(val_vk: &ash::vk::PhysicalDeviceMemoryProperties) -> Self { + let memory_types_vk = val_vk.memory_types_as_slice(); + let memory_heaps_vk = val_vk.memory_heaps_as_slice(); + Self { - memory_types: val - .memory_types_as_slice() - .iter() - .map(|vk_memory_type| MemoryType { - property_flags: vk_memory_type.property_flags.into(), - heap_index: vk_memory_type.heap_index, - }) - .collect(), - memory_heaps: val - .memory_heaps_as_slice() - .iter() - .map(|vk_memory_heap| MemoryHeap { - size: vk_memory_heap.size, - flags: vk_memory_heap.flags.into(), - }) - .collect(), + memory_types: memory_types_vk.iter().map(MemoryType::from_vk).collect(), + memory_heaps: memory_heaps_vk.iter().map(MemoryHeap::from_vk).collect(), } } } @@ -519,6 +553,21 @@ pub struct MemoryType { pub heap_index: u32, } +impl MemoryType { + #[allow(clippy::trivially_copy_pass_by_ref)] + pub(crate) fn from_vk(val_vk: &ash::vk::MemoryType) -> Self { + let &ash::vk::MemoryType { + property_flags, + heap_index, + } = val_vk; + + MemoryType { + property_flags: property_flags.into(), + heap_index, + } + } +} + vulkan_bitflags! { #[non_exhaustive] @@ -650,6 +699,17 @@ pub struct MemoryHeap { pub flags: MemoryHeapFlags, } +impl MemoryHeap { + pub(crate) fn from_vk(val_vk: &ash::vk::MemoryHeap) -> Self { + let &ash::vk::MemoryHeap { size, flags } = val_vk; + + Self { + size, + flags: flags.into(), + } + } +} + vulkan_bitflags! { #[non_exhaustive] @@ -694,6 +754,81 @@ pub struct MemoryRequirements { pub requires_dedicated_allocation: bool, } +impl MemoryRequirements { + pub(crate) fn to_mut_vk2( + extensions_vk: &mut MemoryRequirements2ExtensionsVk, + ) -> ash::vk::MemoryRequirements2<'_> { + let mut val_vk = ash::vk::MemoryRequirements2::default(); + + let MemoryRequirements2ExtensionsVk { dedicated_vk } = extensions_vk; + + if let Some(next) = dedicated_vk { + val_vk = val_vk.push_next(next); + } + + val_vk + } + + pub(crate) fn to_mut_vk2_extensions(device: &Device) -> MemoryRequirements2ExtensionsVk { + let dedicated_vk = (device.api_version() >= Version::V1_1 + || device.enabled_extensions().khr_dedicated_allocation) + .then(|| { + debug_assert!( + device.api_version() >= Version::V1_1 + || device.enabled_extensions().khr_get_memory_requirements2 + ); + + ash::vk::MemoryDedicatedRequirements::default() + }); + + MemoryRequirements2ExtensionsVk { dedicated_vk } + } + + pub(crate) fn from_vk2( + val_vk: &ash::vk::MemoryRequirements2<'_>, + extensions_vk: &MemoryRequirements2ExtensionsVk, + ) -> Self { + let &ash::vk::MemoryRequirements2 { + memory_requirements: + ash::vk::MemoryRequirements { + size, + alignment, + memory_type_bits, + }, + .. + } = val_vk; + + let mut val = Self { + layout: DeviceLayout::from_size_alignment(size, alignment).unwrap(), + memory_type_bits, + prefers_dedicated_allocation: false, + requires_dedicated_allocation: false, + }; + + let MemoryRequirements2ExtensionsVk { dedicated_vk } = extensions_vk; + + if let Some(val_vk) = dedicated_vk { + let &ash::vk::MemoryDedicatedRequirements { + prefers_dedicated_allocation, + requires_dedicated_allocation, + .. + } = val_vk; + + val = Self { + prefers_dedicated_allocation: prefers_dedicated_allocation != 0, + requires_dedicated_allocation: requires_dedicated_allocation != 0, + ..val + }; + } + + val + } +} + +pub(crate) struct MemoryRequirements2ExtensionsVk { + pub(crate) dedicated_vk: Option>, +} + /// Indicates a specific resource to allocate memory for. /// /// Using dedicated allocations can yield better performance, but requires the @@ -750,25 +885,49 @@ pub struct ExternalMemoryProperties { pub compatible_handle_types: ExternalMemoryHandleTypes, } -impl From for ExternalMemoryProperties { - #[inline] - fn from(val: ash::vk::ExternalMemoryProperties) -> Self { +impl ExternalMemoryProperties { + pub(crate) fn from_vk(val_vk: &ash::vk::ExternalMemoryProperties) -> Self { + let &ash::vk::ExternalMemoryProperties { + external_memory_features, + export_from_imported_handle_types, + compatible_handle_types, + } = val_vk; + Self { - dedicated_only: val - .external_memory_features + dedicated_only: external_memory_features .intersects(ash::vk::ExternalMemoryFeatureFlags::DEDICATED_ONLY), - exportable: val - .external_memory_features + exportable: external_memory_features .intersects(ash::vk::ExternalMemoryFeatureFlags::EXPORTABLE), - importable: val - .external_memory_features + importable: external_memory_features .intersects(ash::vk::ExternalMemoryFeatureFlags::IMPORTABLE), - export_from_imported_handle_types: val.export_from_imported_handle_types.into(), - compatible_handle_types: val.compatible_handle_types.into(), + export_from_imported_handle_types: export_from_imported_handle_types.into(), + compatible_handle_types: compatible_handle_types.into(), } } } +/// The properties of a Unix file descriptor when it is imported. +#[derive(Clone, Debug)] +#[non_exhaustive] +pub struct MemoryFdProperties { + /// A bitmask of the indices of memory types that can be used with the file. + pub memory_type_bits: u32, +} + +impl MemoryFdProperties { + pub(crate) fn to_mut_vk() -> ash::vk::MemoryFdPropertiesKHR<'static> { + ash::vk::MemoryFdPropertiesKHR::default() + } + + pub(crate) fn from_vk(val_vk: &ash::vk::MemoryFdPropertiesKHR<'_>) -> Self { + let &ash::vk::MemoryFdPropertiesKHR { + memory_type_bits, .. + } = val_vk; + + Self { memory_type_bits } + } +} + /// Parameters to execute sparse bind operations on a queue. #[derive(Clone, Debug)] pub struct BindSparseInfo { @@ -824,6 +983,157 @@ impl Default for BindSparseInfo { } } +impl BindSparseInfo { + pub(crate) fn to_vk<'a>( + &self, + fields1_vk: &'a BindSparseInfoFields1Vk<'_>, + ) -> ash::vk::BindSparseInfo<'a> { + let BindSparseInfoFields1Vk { + wait_semaphores_vk, + buffer_bind_infos_vk, + image_opaque_bind_infos_vk, + image_bind_infos_vk, + signal_semaphores_vk, + } = fields1_vk; + + ash::vk::BindSparseInfo::default() + .wait_semaphores(wait_semaphores_vk) + .buffer_binds(buffer_bind_infos_vk) + .image_opaque_binds(image_opaque_bind_infos_vk) + .image_binds(image_bind_infos_vk) + .signal_semaphores(signal_semaphores_vk) + } + + pub(crate) fn to_vk_fields1<'a>( + &self, + fields2_vk: &'a BindSparseInfoFields2Vk, + ) -> BindSparseInfoFields1Vk<'a> { + let &BindSparseInfo { + ref wait_semaphores, + ref buffer_binds, + ref image_opaque_binds, + ref image_binds, + ref signal_semaphores, + _ne: _, + } = self; + let BindSparseInfoFields2Vk { + buffer_binds_vk, + image_opaque_binds_vk, + image_binds_vk, + } = fields2_vk; + + let wait_semaphores_vk = wait_semaphores + .iter() + .map(|semaphore| semaphore.handle()) + .collect(); + + let buffer_bind_infos_vk = buffer_binds + .iter() + .zip(buffer_binds_vk) + .map(|((buffer, _), buffer_binds_vk)| { + ash::vk::SparseBufferMemoryBindInfo::default() + .buffer(buffer.buffer().handle()) + .binds(buffer_binds_vk) + }) + .collect(); + + let image_opaque_bind_infos_vk = image_opaque_binds + .iter() + .zip(image_opaque_binds_vk) + .map(|((image, _), image_opaque_binds_vk)| { + ash::vk::SparseImageOpaqueMemoryBindInfo::default() + .image(image.handle()) + .binds(image_opaque_binds_vk) + }) + .collect(); + + let image_bind_infos_vk = image_binds + .iter() + .zip(image_binds_vk) + .map(|((image, _), image_binds_vk)| { + ash::vk::SparseImageMemoryBindInfo::default() + .image(image.handle()) + .binds(image_binds_vk) + }) + .collect(); + + let signal_semaphores_vk = signal_semaphores + .iter() + .map(|semaphore| semaphore.handle()) + .collect(); + + BindSparseInfoFields1Vk { + wait_semaphores_vk, + buffer_bind_infos_vk, + image_opaque_bind_infos_vk, + image_bind_infos_vk, + signal_semaphores_vk, + } + } + + pub(crate) fn to_vk_fields2(&self) -> BindSparseInfoFields2Vk { + let &Self { + wait_semaphores: _, + ref buffer_binds, + ref image_opaque_binds, + ref image_binds, + signal_semaphores: _, + _ne: _, + } = self; + + let buffer_binds_vk = buffer_binds + .iter() + .map(|(_, memory_binds)| { + memory_binds + .iter() + .map(SparseBufferMemoryBind::to_vk) + .collect() + }) + .collect(); + + let image_opaque_binds_vk = image_opaque_binds + .iter() + .map(|(_, memory_binds)| { + memory_binds + .iter() + .map(SparseImageOpaqueMemoryBind::to_vk) + .collect() + }) + .collect(); + + let image_binds_vk = image_binds + .iter() + .map(|(_, memory_binds)| { + memory_binds + .iter() + .map(SparseImageMemoryBind::to_vk) + .collect() + }) + .collect(); + + BindSparseInfoFields2Vk { + buffer_binds_vk, + image_opaque_binds_vk, + image_binds_vk, + } + } +} + +pub(crate) struct BindSparseInfoFields1Vk<'a> { + pub(crate) wait_semaphores_vk: SmallVec<[ash::vk::Semaphore; 4]>, + pub(crate) buffer_bind_infos_vk: SmallVec<[ash::vk::SparseBufferMemoryBindInfo<'a>; 4]>, + pub(crate) image_opaque_bind_infos_vk: + SmallVec<[ash::vk::SparseImageOpaqueMemoryBindInfo<'a>; 4]>, + pub(crate) image_bind_infos_vk: SmallVec<[ash::vk::SparseImageMemoryBindInfo<'a>; 4]>, + pub(crate) signal_semaphores_vk: SmallVec<[ash::vk::Semaphore; 4]>, +} + +pub(crate) struct BindSparseInfoFields2Vk { + pub(crate) buffer_binds_vk: SmallVec<[SmallVec<[ash::vk::SparseMemoryBind; 4]>; 4]>, + pub(crate) image_opaque_binds_vk: SmallVec<[SmallVec<[ash::vk::SparseMemoryBind; 4]>; 4]>, + pub(crate) image_binds_vk: SmallVec<[SmallVec<[ash::vk::SparseImageMemoryBind; 4]>; 4]>, +} + /// Parameters for a single sparse bind operation on a buffer. #[derive(Clone, Debug, Default)] pub struct SparseBufferMemoryBind { @@ -846,6 +1156,30 @@ pub struct SparseBufferMemoryBind { pub memory: Option<(Arc, DeviceSize)>, } +impl SparseBufferMemoryBind { + pub(crate) fn to_vk(&self) -> ash::vk::SparseMemoryBind { + let &Self { + offset, + size, + ref memory, + } = self; + + let (memory, memory_offset) = memory + .as_ref() + .map_or_else(Default::default, |(memory, memory_offset)| { + (memory.handle(), *memory_offset) + }); + + ash::vk::SparseMemoryBind { + resource_offset: offset, + size, + memory, + memory_offset, + flags: ash::vk::SparseMemoryBindFlags::empty(), + } + } +} + /// Parameters for a single sparse bind operation on parts of an image with an opaque memory /// layout. /// @@ -878,6 +1212,35 @@ pub struct SparseImageOpaqueMemoryBind { pub metadata: bool, } +impl SparseImageOpaqueMemoryBind { + pub(crate) fn to_vk(&self) -> ash::vk::SparseMemoryBind { + let &Self { + offset, + size, + ref memory, + metadata, + } = self; + + let (memory, memory_offset) = memory + .as_ref() + .map_or_else(Default::default, |(memory, memory_offset)| { + (memory.handle(), *memory_offset) + }); + + ash::vk::SparseMemoryBind { + resource_offset: offset, + size, + memory, + memory_offset, + flags: if metadata { + ash::vk::SparseMemoryBindFlags::METADATA + } else { + ash::vk::SparseMemoryBindFlags::empty() + }, + } + } +} + /// Parameters for a single sparse bind operation on parts of an image with a known memory layout. /// /// This type of sparse bind can only be used for images that have the `sparse_residency` flag set. @@ -930,6 +1293,46 @@ pub struct SparseImageMemoryBind { pub memory: Option<(Arc, DeviceSize)>, } +impl SparseImageMemoryBind { + pub(crate) fn to_vk(&self) -> ash::vk::SparseImageMemoryBind { + let &Self { + aspects, + mip_level, + array_layer, + offset, + extent, + ref memory, + } = self; + + let (memory, memory_offset) = memory + .as_ref() + .map_or_else(Default::default, |(memory, memory_offset)| { + (memory.handle(), *memory_offset) + }); + + ash::vk::SparseImageMemoryBind { + subresource: ash::vk::ImageSubresource { + aspect_mask: aspects.into(), + mip_level, + array_layer, + }, + offset: ash::vk::Offset3D { + x: offset[0] as i32, + y: offset[1] as i32, + z: offset[2] as i32, + }, + extent: ash::vk::Extent3D { + width: extent[0], + height: extent[1], + depth: extent[2], + }, + memory, + memory_offset, + flags: ash::vk::SparseMemoryBindFlags::empty(), + } + } +} + #[inline(always)] pub(crate) fn is_aligned(offset: DeviceSize, alignment: DeviceAlignment) -> bool { offset & (alignment.as_devicesize() - 1) == 0 diff --git a/vulkano/src/pipeline/cache.rs b/vulkano/src/pipeline/cache.rs index ff2787e9..4215cfdb 100644 --- a/vulkano/src/pipeline/cache.rs +++ b/vulkano/src/pipeline/cache.rs @@ -106,29 +106,14 @@ impl PipelineCache { device: Arc, create_info: PipelineCacheCreateInfo, ) -> Result, VulkanError> { - let &PipelineCacheCreateInfo { - flags, - ref initial_data, - _ne: _, - } = &create_info; - - let infos = ash::vk::PipelineCacheCreateInfo { - flags: flags.into(), - initial_data_size: initial_data.len(), - p_initial_data: if initial_data.is_empty() { - ptr::null() - } else { - initial_data.as_ptr().cast() - }, - ..Default::default() - }; + let create_info_vk = create_info.to_vk(); let handle = { let fns = device.fns(); let mut output = MaybeUninit::uninit(); (fns.v1_0.create_pipeline_cache)( device.handle(), - &infos, + &create_info_vk, ptr::null(), output.as_mut_ptr(), ) @@ -361,6 +346,22 @@ impl PipelineCacheCreateInfo { Ok(()) } + + pub(crate) fn to_vk(&self) -> ash::vk::PipelineCacheCreateInfo<'_> { + let &Self { + flags, + ref initial_data, + _ne: _, + } = self; + + let mut val_vk = ash::vk::PipelineCacheCreateInfo::default().flags(flags.into()); + + if !initial_data.is_empty() { + val_vk = val_vk.initial_data(initial_data); + } + + val_vk + } } vulkan_bitflags! { diff --git a/vulkano/src/pipeline/compute.rs b/vulkano/src/pipeline/compute.rs index dc54319e..ced9b1ec 100644 --- a/vulkano/src/pipeline/compute.rs +++ b/vulkano/src/pipeline/compute.rs @@ -13,17 +13,20 @@ //! binding any descriptor sets and/or push constants that the pipeline needs, and then issuing a //! `dispatch` command on the command buffer. -use super::{PipelineCreateFlags, PipelineShaderStageCreateInfo}; +use super::{ + PipelineCreateFlags, PipelineShaderStageCreateInfo, PipelineShaderStageCreateInfoExtensionsVk, + PipelineShaderStageCreateInfoFields1Vk, PipelineShaderStageCreateInfoFields2Vk, +}; use crate::{ device::{Device, DeviceOwned, DeviceOwnedDebugWrapper}, instance::InstanceOwnedDebugWrapper, macros::impl_id_counter, pipeline::{cache::PipelineCache, layout::PipelineLayout, Pipeline, PipelineBindPoint}, - shader::{spirv::ExecutionModel, DescriptorBindingRequirements, ShaderStage}, + shader::{spirv::ExecutionModel, DescriptorBindingRequirements}, Validated, ValidationError, VulkanError, VulkanObject, }; use ahash::HashMap; -use std::{ffi::CString, fmt::Debug, mem::MaybeUninit, num::NonZeroU64, ptr, sync::Arc}; +use std::{fmt::Debug, mem::MaybeUninit, num::NonZeroU64, ptr, sync::Arc}; /// A pipeline object that describes to the Vulkan implementation how it should perform compute /// operations. @@ -80,95 +83,11 @@ impl ComputePipeline { cache: Option>, create_info: ComputePipelineCreateInfo, ) -> Result, VulkanError> { - let &ComputePipelineCreateInfo { - flags, - ref stage, - ref layout, - ref base_pipeline, - _ne: _, - } = &create_info; - - let stage_vk; - let name_vk; - let specialization_info_vk; - let specialization_map_entries_vk: Vec<_>; - let mut specialization_data_vk: Vec; - let required_subgroup_size_create_info; - - { - let &PipelineShaderStageCreateInfo { - flags, - ref entry_point, - ref required_subgroup_size, - _ne: _, - } = stage; - - let entry_point_info = entry_point.info(); - name_vk = CString::new(entry_point_info.name.as_str()).unwrap(); - - specialization_data_vk = Vec::new(); - specialization_map_entries_vk = entry_point - .module() - .specialization_info() - .iter() - .map(|(&constant_id, value)| { - let data = value.as_bytes(); - let offset = specialization_data_vk.len() as u32; - let size = data.len(); - specialization_data_vk.extend(data); - - ash::vk::SpecializationMapEntry { - constant_id, - offset, - size, - } - }) - .collect(); - - specialization_info_vk = ash::vk::SpecializationInfo { - map_entry_count: specialization_map_entries_vk.len() as u32, - p_map_entries: specialization_map_entries_vk.as_ptr(), - data_size: specialization_data_vk.len(), - p_data: specialization_data_vk.as_ptr().cast(), - ..Default::default() - }; - required_subgroup_size_create_info = - required_subgroup_size.map(|required_subgroup_size| { - ash::vk::PipelineShaderStageRequiredSubgroupSizeCreateInfo { - required_subgroup_size, - ..Default::default() - } - }); - stage_vk = ash::vk::PipelineShaderStageCreateInfo { - p_next: required_subgroup_size_create_info.as_ref().map_or( - ptr::null(), - |required_subgroup_size_create_info| { - <*const _>::cast(required_subgroup_size_create_info) - }, - ), - flags: flags.into(), - stage: ShaderStage::from(entry_point_info.execution_model).into(), - module: entry_point.module().handle(), - p_name: name_vk.as_ptr(), - p_specialization_info: if specialization_info_vk.data_size == 0 { - ptr::null() - } else { - &specialization_info_vk - }, - ..Default::default() - }; - } - - let create_infos_vk = ash::vk::ComputePipelineCreateInfo { - flags: flags.into(), - stage: stage_vk, - layout: layout.handle(), - base_pipeline_handle: base_pipeline - .as_ref() - .map_or(ash::vk::Pipeline::null(), VulkanObject::handle), - base_pipeline_index: -1, - ..Default::default() - }; + let create_info_fields2_vk = create_info.to_vk_fields2(); + let create_info_fields1_vk = create_info.to_vk_fields1(&create_info_fields2_vk); + let mut create_info_extensions_vk = create_info.to_vk_extensions(); + let create_info_vk = + create_info.to_vk(&create_info_fields1_vk, &mut create_info_extensions_vk); let handle = { let fns = device.fns(); @@ -177,7 +96,7 @@ impl ComputePipeline { device.handle(), cache.as_ref().map_or_else(Default::default, |c| c.handle()), 1, - &create_infos_vk, + &create_info_vk, ptr::null(), output.as_mut_ptr(), ) @@ -439,6 +358,74 @@ impl ComputePipelineCreateInfo { Ok(()) } + + pub(crate) fn to_vk<'a>( + &self, + fields1_vk: &'a ComputePipelineCreateInfoFields1Vk<'_>, + extensions_vk: &'a mut ComputePipelineCreateInfoExtensionsVk, + ) -> ash::vk::ComputePipelineCreateInfo<'a> { + let &Self { + flags, + ref stage, + ref layout, + ref base_pipeline, + _ne: _, + } = self; + let ComputePipelineCreateInfoFields1Vk { stage_fields1_vk } = fields1_vk; + let ComputePipelineCreateInfoExtensionsVk { + stage_extensions_vk, + } = extensions_vk; + + let stage_vk = stage.to_vk(stage_fields1_vk, stage_extensions_vk); + + ash::vk::ComputePipelineCreateInfo::default() + .flags(flags.into()) + .stage(stage_vk) + .layout(layout.handle()) + .base_pipeline_handle( + base_pipeline + .as_ref() + .map_or(ash::vk::Pipeline::null(), VulkanObject::handle), + ) + .base_pipeline_index(-1) + } + + pub(crate) fn to_vk_extensions(&self) -> ComputePipelineCreateInfoExtensionsVk { + let stage_extensions_vk = self.stage.to_vk_extensions(); + + ComputePipelineCreateInfoExtensionsVk { + stage_extensions_vk, + } + } + + pub(crate) fn to_vk_fields1<'a>( + &self, + fields2_vk: &'a ComputePipelineCreateInfoFields2Vk, + ) -> ComputePipelineCreateInfoFields1Vk<'a> { + let ComputePipelineCreateInfoFields2Vk { stage_fields2_vk } = fields2_vk; + + let stage_fields1_vk = self.stage.to_vk_fields1(stage_fields2_vk); + + ComputePipelineCreateInfoFields1Vk { stage_fields1_vk } + } + + pub(crate) fn to_vk_fields2(&self) -> ComputePipelineCreateInfoFields2Vk { + let stage_fields2_vk = self.stage.to_vk_fields2(); + + ComputePipelineCreateInfoFields2Vk { stage_fields2_vk } + } +} + +pub(crate) struct ComputePipelineCreateInfoExtensionsVk { + pub(crate) stage_extensions_vk: PipelineShaderStageCreateInfoExtensionsVk, +} + +pub(crate) struct ComputePipelineCreateInfoFields1Vk<'a> { + pub(crate) stage_fields1_vk: PipelineShaderStageCreateInfoFields1Vk<'a>, +} + +pub(crate) struct ComputePipelineCreateInfoFields2Vk { + pub(crate) stage_fields2_vk: PipelineShaderStageCreateInfoFields2Vk, } #[cfg(test)] diff --git a/vulkano/src/pipeline/graphics/color_blend.rs b/vulkano/src/pipeline/graphics/color_blend.rs index 07dcb5c1..098735b2 100644 --- a/vulkano/src/pipeline/graphics/color_blend.rs +++ b/vulkano/src/pipeline/graphics/color_blend.rs @@ -21,6 +21,7 @@ use crate::{ Requires, RequiresAllOf, RequiresOneOf, ValidationError, }; use ahash::HashMap; +use smallvec::SmallVec; use std::iter; /// Describes how the color output of the fragment shader is written to the attachment. See the @@ -118,7 +119,7 @@ impl ColorBlendState { pub fn blend(mut self, blend: AttachmentBlend) -> Self { self.attachments .iter_mut() - .for_each(|attachment_state| attachment_state.blend = Some(blend)); + .for_each(|attachment_state| attachment_state.blend = Some(blend.clone())); self } @@ -460,6 +461,90 @@ impl ColorBlendState { Ok(()) } + + pub(crate) fn to_vk<'a>( + &self, + fields1_vk: &'a ColorBlendStateFields1Vk, + extensions_vk: &'a mut ColorBlendStateExtensionsVk<'_>, + ) -> ash::vk::PipelineColorBlendStateCreateInfo<'a> { + let &Self { + flags, + logic_op, + attachments: _, + blend_constants, + _ne: _, + } = self; + let ColorBlendStateFields1Vk { + color_blend_attachments_vk, + color_write_enables_vk: _, + } = fields1_vk; + + let (logic_op_enable_vk, logic_op_vk) = if let Some(logic_op) = logic_op { + (true, logic_op.into()) + } else { + (false, Default::default()) + }; + + let mut val_vk = ash::vk::PipelineColorBlendStateCreateInfo::default() + .flags(flags.into()) + .logic_op_enable(logic_op_enable_vk) + .logic_op(logic_op_vk) + .attachments(color_blend_attachments_vk) + .blend_constants(blend_constants); + + let ColorBlendStateExtensionsVk { color_write_vk } = extensions_vk; + + if let Some(next) = color_write_vk { + val_vk = val_vk.push_next(next); + } + + val_vk + } + + pub(crate) fn to_vk_extensions<'a>( + &self, + fields1_vk: &'a ColorBlendStateFields1Vk, + ) -> ColorBlendStateExtensionsVk<'a> { + let ColorBlendStateFields1Vk { + color_blend_attachments_vk: _, + color_write_enables_vk, + } = fields1_vk; + + let color_write_vk = (!color_write_enables_vk.is_empty()).then(|| { + ash::vk::PipelineColorWriteCreateInfoEXT::default() + .color_write_enables(color_write_enables_vk) + }); + + ColorBlendStateExtensionsVk { color_write_vk } + } + + pub(crate) fn to_vk_fields1(&self) -> ColorBlendStateFields1Vk { + let mut color_blend_attachments_vk = SmallVec::with_capacity(self.attachments.len()); + let mut color_write_enables_vk = SmallVec::with_capacity(self.attachments.len()); + let mut has_color_write_enables = false; + + for color_blend_attachment_state in &self.attachments { + color_blend_attachments_vk.push(color_blend_attachment_state.to_vk()); + color_write_enables_vk.push(color_blend_attachment_state.color_write_enable as _); + has_color_write_enables |= !color_blend_attachment_state.color_write_enable; + } + + ColorBlendStateFields1Vk { + color_blend_attachments_vk, + color_write_enables_vk: has_color_write_enables + .then_some(color_write_enables_vk) + .unwrap_or_default(), + } + } +} + +pub(crate) struct ColorBlendStateExtensionsVk<'a> { + pub(crate) color_write_vk: Option>, +} + +pub(crate) struct ColorBlendStateFields1Vk { + color_blend_attachments_vk: SmallVec<[ash::vk::PipelineColorBlendAttachmentState; 4]>, + color_write_enables_vk: SmallVec<[ash::vk::Bool32; 4]>, } vulkan_bitflags! { @@ -565,7 +650,7 @@ pub struct ColorBlendAttachmentState { /// that is written is determined by the `color_write_mask`. If disabled, the mask is ignored /// and nothing is written. /// - /// If set to anything other than `Fixed(true)`, the + /// If set to `false`, the /// [`color_write_enable`](crate::device::DeviceFeatures::color_write_enable) feature must be /// enabled on the device. /// @@ -611,10 +696,26 @@ impl ColorBlendAttachmentState { Ok(()) } + + pub(crate) fn to_vk(&self) -> ash::vk::PipelineColorBlendAttachmentState { + let &Self { + ref blend, + color_write_mask, + color_write_enable: _, + } = self; + + ash::vk::PipelineColorBlendAttachmentState { + color_write_mask: color_write_mask.into(), + ..blend + .as_ref() + .map(AttachmentBlend::to_vk) + .unwrap_or_default() + } + } } /// Describes how the blending system should behave for an attachment. -#[derive(Clone, Copy, Debug, PartialEq, Eq)] +#[derive(Clone, Debug, PartialEq, Eq)] pub struct AttachmentBlend { /// The operation to apply to the source color component before applying `color_op`. /// @@ -866,19 +967,25 @@ impl AttachmentBlend { Ok(()) } -} -impl From for ash::vk::PipelineColorBlendAttachmentState { - #[inline] - fn from(val: AttachmentBlend) -> Self { + pub(crate) fn to_vk(&self) -> ash::vk::PipelineColorBlendAttachmentState { + let &Self { + src_color_blend_factor, + dst_color_blend_factor, + color_blend_op, + src_alpha_blend_factor, + dst_alpha_blend_factor, + alpha_blend_op, + } = self; + ash::vk::PipelineColorBlendAttachmentState { blend_enable: ash::vk::TRUE, - src_color_blend_factor: val.src_color_blend_factor.into(), - dst_color_blend_factor: val.dst_color_blend_factor.into(), - color_blend_op: val.color_blend_op.into(), - src_alpha_blend_factor: val.src_alpha_blend_factor.into(), - dst_alpha_blend_factor: val.dst_alpha_blend_factor.into(), - alpha_blend_op: val.alpha_blend_op.into(), + src_color_blend_factor: src_color_blend_factor.into(), + dst_color_blend_factor: dst_color_blend_factor.into(), + color_blend_op: color_blend_op.into(), + src_alpha_blend_factor: src_alpha_blend_factor.into(), + dst_alpha_blend_factor: dst_alpha_blend_factor.into(), + alpha_blend_op: alpha_blend_op.into(), color_write_mask: ash::vk::ColorComponentFlags::empty(), } } diff --git a/vulkano/src/pipeline/graphics/conservative_rasterization.rs b/vulkano/src/pipeline/graphics/conservative_rasterization.rs deleted file mode 100644 index 5ead23ec..00000000 --- a/vulkano/src/pipeline/graphics/conservative_rasterization.rs +++ /dev/null @@ -1,90 +0,0 @@ -//! A mode of rasterization where the edges of primitives are modified so that fragments are -//! generated if the edge of a primitive touches any part of a pixel, or if a pixel is fully -//! covered by a primitive. -use crate::{device::Device, macros::vulkan_enum, ValidationError}; - -/// The state in a graphics pipeline describing how the conservative rasterization mode should -/// behave. -#[derive(Clone, Debug)] -pub struct ConservativeRasterizationState { - /// Sets the conservative rasterization mode. - /// - /// The default value is [`ConservativeRasterizationMode::Disabled`]. - pub mode: ConservativeRasterizationMode, - - /// The extra size in pixels to increase the generating primitive during conservative - /// rasterization. If the mode is set to anything other than - /// [`ConservativeRasterizationMode::Overestimate`] this value is ignored. - /// - /// The default value is 0.0. - pub overestimation_size: f32, - - pub _ne: crate::NonExhaustive, -} - -impl Default for ConservativeRasterizationState { - #[inline] - fn default() -> Self { - Self { - mode: ConservativeRasterizationMode::Disabled, - overestimation_size: 0.0, - _ne: crate::NonExhaustive(()), - } - } -} - -impl ConservativeRasterizationState { - pub(crate) fn validate(&self, device: &Device) -> Result<(), Box> { - let &Self { - mode, - overestimation_size, - _ne: _, - } = self; - - let properties = device.physical_device().properties(); - - mode.validate_device(device).map_err(|err| { - err.add_context("mode").set_vuids(&[ - "VUID-VkPipelineRasterizationConservativeStateCreateInfoEXT-conservativeRasterizationMode-parameter", - ]) - })?; - - if overestimation_size < 0.0 - || overestimation_size > properties.max_extra_primitive_overestimation_size.unwrap() - { - return Err(Box::new(ValidationError { - context: "overestimation size".into(), - problem: "the overestimation size is not in the range of 0.0 to `max_extra_primitive_overestimation_size` inclusive".into(), - vuids: &[ - "VUID-VkPipelineRasterizationConservativeStateCreateInfoEXT-extraPrimitiveOverestimationSize-01769", - ], - ..Default::default() - })); - } - - Ok(()) - } -} - -vulkan_enum! { - #[non_exhaustive] - - /// Describes how fragments will be generated based on how much is covered by a primitive. - ConservativeRasterizationMode = ConservativeRasterizationModeEXT(i32); - - /// Conservative rasterization is disabled and rasterization proceeds as normal. - Disabled = DISABLED, - - /// Fragments will be generated if any part of a primitive touches a pixel. - Overestimate = OVERESTIMATE, - - /// Fragments will be generated only if a primitive completely covers a pixel. - Underestimate = UNDERESTIMATE, -} - -impl Default for ConservativeRasterizationMode { - #[inline] - fn default() -> ConservativeRasterizationMode { - ConservativeRasterizationMode::Disabled - } -} diff --git a/vulkano/src/pipeline/graphics/depth_stencil.rs b/vulkano/src/pipeline/graphics/depth_stencil.rs index dfa9ba3b..60063dca 100644 --- a/vulkano/src/pipeline/graphics/depth_stencil.rs +++ b/vulkano/src/pipeline/graphics/depth_stencil.rs @@ -156,6 +156,57 @@ impl DepthStencilState { Ok(()) } + + pub(crate) fn to_vk(&self) -> ash::vk::PipelineDepthStencilStateCreateInfo<'static> { + let &Self { + flags, + ref depth, + ref depth_bounds, + ref stencil, + _ne: _, + } = self; + + let (depth_test_enable_vk, depth_write_enable_vk, depth_compare_op_vk) = + if let Some(depth_state) = depth { + let &DepthState { + write_enable, + compare_op, + } = depth_state; + + (true, write_enable, compare_op.into()) + } else { + (false, false, ash::vk::CompareOp::ALWAYS) + }; + + let (depth_bounds_test_enable_vk, min_depth_bounds_vk, max_depth_bounds_vk) = + if let Some(depth_bounds) = depth_bounds { + (true, *depth_bounds.start(), *depth_bounds.end()) + } else { + (false, 0.0, 1.0) + }; + + let (stencil_test_enable_vk, front_vk, back_vk) = if let Some(stencil_state) = stencil { + let StencilState { front, back } = stencil_state; + + let [front, back] = [front, back].map(|stencil_op_state| stencil_op_state.to_vk()); + + (true, front, back) + } else { + (false, Default::default(), Default::default()) + }; + + ash::vk::PipelineDepthStencilStateCreateInfo::default() + .flags(flags.into()) + .depth_test_enable(depth_test_enable_vk) + .depth_write_enable(depth_write_enable_vk) + .depth_compare_op(depth_compare_op_vk) + .depth_bounds_test_enable(depth_bounds_test_enable_vk) + .stencil_test_enable(stencil_test_enable_vk) + .front(front_vk) + .back(back_vk) + .min_depth_bounds(min_depth_bounds_vk) + .max_depth_bounds(max_depth_bounds_vk) + } } vulkan_bitflags! { @@ -333,6 +384,28 @@ impl Default for StencilOpState { } } +impl StencilOpState { + #[allow(clippy::wrong_self_convention)] + pub(crate) fn to_vk(&self) -> ash::vk::StencilOpState { + let &Self { + ops, + compare_mask, + write_mask, + reference, + } = self; + + ash::vk::StencilOpState { + fail_op: ops.fail_op.into(), + pass_op: ops.pass_op.into(), + depth_fail_op: ops.depth_fail_op.into(), + compare_op: ops.compare_op.into(), + compare_mask, + write_mask, + reference, + } + } +} + #[derive(Clone, Copy, Debug)] pub struct StencilOps { /// The operation to perform when the stencil test failed. diff --git a/vulkano/src/pipeline/graphics/discard_rectangle.rs b/vulkano/src/pipeline/graphics/discard_rectangle.rs index 1fda8b01..018b7a37 100644 --- a/vulkano/src/pipeline/graphics/discard_rectangle.rs +++ b/vulkano/src/pipeline/graphics/discard_rectangle.rs @@ -5,6 +5,7 @@ use crate::{ device::Device, macros::vulkan_enum, pipeline::graphics::viewport::Scissor, ValidationError, }; +use smallvec::SmallVec; /// The state in a graphics pipeline describing how the discard rectangle test should behave. #[derive(Clone, Debug)] @@ -82,6 +83,43 @@ impl DiscardRectangleState { Ok(()) } + + pub(crate) fn to_vk<'a>( + &self, + fields1_vk: &'a DiscardRectangleStateFields1Vk, + ) -> ash::vk::PipelineDiscardRectangleStateCreateInfoEXT<'a> { + let &Self { + mode, + rectangles: _, + _ne: _, + } = self; + let DiscardRectangleStateFields1Vk { + discard_rectangles_vk, + } = fields1_vk; + + ash::vk::PipelineDiscardRectangleStateCreateInfoEXT::default() + .flags(ash::vk::PipelineDiscardRectangleStateCreateFlagsEXT::empty()) + .discard_rectangle_mode(mode.into()) + .discard_rectangles(discard_rectangles_vk) + } + + pub(crate) fn to_vk_fields1(&self) -> DiscardRectangleStateFields1Vk { + let Self { + mode: _, + rectangles, + _ne: _, + } = self; + + let discard_rectangles_vk = rectangles.iter().map(|rect| rect.to_vk()).collect(); + + DiscardRectangleStateFields1Vk { + discard_rectangles_vk, + } + } +} + +pub(crate) struct DiscardRectangleStateFields1Vk { + pub(crate) discard_rectangles_vk: SmallVec<[ash::vk::Rect2D; 2]>, } vulkan_enum! { diff --git a/vulkano/src/pipeline/graphics/input_assembly.rs b/vulkano/src/pipeline/graphics/input_assembly.rs index 4631396f..8449c7fd 100644 --- a/vulkano/src/pipeline/graphics/input_assembly.rs +++ b/vulkano/src/pipeline/graphics/input_assembly.rs @@ -5,7 +5,7 @@ use crate::{ }; /// The state in a graphics pipeline describing how the input assembly stage should behave. -#[derive(Clone, Copy, Debug)] +#[derive(Clone, Debug)] pub struct InputAssemblyState { /// The type of primitives. /// @@ -179,6 +179,19 @@ impl InputAssemblyState { Ok(()) } + + pub(crate) fn to_vk(&self) -> ash::vk::PipelineInputAssemblyStateCreateInfo<'static> { + let &Self { + topology, + primitive_restart_enable, + _ne: _, + } = self; + + ash::vk::PipelineInputAssemblyStateCreateInfo::default() + .flags(ash::vk::PipelineInputAssemblyStateCreateFlags::empty()) + .topology(topology.into()) + .primitive_restart_enable(primitive_restart_enable) + } } vulkan_enum! { diff --git a/vulkano/src/pipeline/graphics/mod.rs b/vulkano/src/pipeline/graphics/mod.rs index 23ee8abb..7e6d3277 100644 --- a/vulkano/src/pipeline/graphics/mod.rs +++ b/vulkano/src/pipeline/graphics/mod.rs @@ -78,24 +78,27 @@ //! command. use self::{ - color_blend::ColorBlendState, - conservative_rasterization::ConservativeRasterizationMode, - depth_stencil::{DepthState, DepthStencilState}, - discard_rectangle::DiscardRectangleState, + color_blend::{ColorBlendState, ColorBlendStateExtensionsVk, ColorBlendStateFields1Vk}, + depth_stencil::DepthStencilState, + discard_rectangle::{DiscardRectangleState, DiscardRectangleStateFields1Vk}, input_assembly::{InputAssemblyState, PrimitiveTopology}, multisample::MultisampleState, - rasterization::RasterizationState, - subpass::PipelineSubpassType, - tessellation::TessellationState, - vertex_input::{RequiredVertexInputsVUIDs, VertexInputState}, - viewport::ViewportState, + rasterization::{RasterizationState, RasterizationStateExtensionsVk}, + subpass::{PipelineRenderingCreateInfoFields1Vk, PipelineSubpassType}, + tessellation::{TessellationState, TessellationStateExtensionsVk}, + vertex_input::{ + RequiredVertexInputsVUIDs, VertexInputState, VertexInputStateExtensionsVk, + VertexInputStateFields1Vk, + }, + viewport::{ViewportState, ViewportStateFields1Vk}, }; use super::{ cache::PipelineCache, inout_interface::{shader_interface_location_info, ShaderInterfaceLocationInfo}, shader::inout_interface::validate_interfaces_compatible, DynamicState, Pipeline, PipelineBindPoint, PipelineCreateFlags, PipelineLayout, - PipelineShaderStageCreateInfo, + PipelineShaderStageCreateInfo, PipelineShaderStageCreateInfoExtensionsVk, + PipelineShaderStageCreateInfoFields1Vk, PipelineShaderStageCreateInfoFields2Vk, }; use crate::{ device::{Device, DeviceOwned, DeviceOwnedDebugWrapper}, @@ -103,17 +106,7 @@ use crate::{ image::{ImageAspect, ImageAspects}, instance::InstanceOwnedDebugWrapper, macros::impl_id_counter, - pipeline::graphics::{ - color_blend::ColorBlendAttachmentState, - conservative_rasterization::ConservativeRasterizationState, - depth_stencil::{StencilOpState, StencilState}, - rasterization::{CullMode, DepthBiasState}, - subpass::PipelineRenderingCreateInfo, - tessellation::TessellationDomainOrigin, - vertex_input::{ - VertexInputAttributeDescription, VertexInputBindingDescription, VertexInputRate, - }, - }, + pipeline::graphics::rasterization::{ConservativeRasterizationMode, CullMode, DepthBiasState}, shader::{ spirv::{ExecutionMode, ExecutionModel, Instruction, StorageClass}, DescriptorBindingRequirements, ShaderStage, ShaderStages, @@ -123,12 +116,10 @@ use crate::{ use ahash::{HashMap, HashSet}; use smallvec::SmallVec; use std::{ - collections::hash_map::Entry, ffi::CString, fmt::Debug, mem::MaybeUninit, num::NonZeroU64, ptr, - sync::Arc, + collections::hash_map::Entry, fmt::Debug, mem::MaybeUninit, num::NonZeroU64, ptr, sync::Arc, }; pub mod color_blend; -pub mod conservative_rasterization; pub mod depth_stencil; pub mod discard_rectangle; pub mod input_assembly; @@ -166,7 +157,6 @@ pub struct GraphicsPipeline { subpass: PipelineSubpassType, discard_rectangle_state: Option, - conservative_rasterization_state: Option, descriptor_binding_requirements: HashMap<(u32, u32), DescriptorBindingRequirements>, num_used_descriptor_sets: u32, @@ -207,719 +197,23 @@ impl GraphicsPipeline { cache: Option>, create_info: GraphicsPipelineCreateInfo, ) -> Result, VulkanError> { - let &GraphicsPipelineCreateInfo { - flags, - ref stages, - - ref vertex_input_state, - ref input_assembly_state, - ref tessellation_state, - ref viewport_state, - ref rasterization_state, - ref multisample_state, - ref depth_stencil_state, - ref color_blend_state, - ref dynamic_state, - - ref layout, - ref subpass, - ref base_pipeline, - - ref discard_rectangle_state, - ref conservative_rasterization_state, - _ne: _, - } = &create_info; - - struct PerPipelineShaderStageCreateInfo { - name_vk: CString, - specialization_info_vk: ash::vk::SpecializationInfo<'static>, - specialization_map_entries_vk: Vec, - specialization_data_vk: Vec, - required_subgroup_size_create_info: - Option>, - } - - let (mut stages_vk, mut per_stage_vk): (SmallVec<[_; 5]>, SmallVec<[_; 5]>) = stages - .iter() - .map(|stage| { - let &PipelineShaderStageCreateInfo { - flags, - ref entry_point, - ref required_subgroup_size, - _ne: _, - } = stage; - - let entry_point_info = entry_point.info(); - let stage = ShaderStage::from(entry_point_info.execution_model); - - let mut specialization_data_vk: Vec = Vec::new(); - let specialization_map_entries_vk: Vec<_> = entry_point - .module() - .specialization_info() - .iter() - .map(|(&constant_id, value)| { - let data = value.as_bytes(); - let offset = specialization_data_vk.len() as u32; - let size = data.len(); - specialization_data_vk.extend(data); - - ash::vk::SpecializationMapEntry { - constant_id, - offset, - size, - } - }) - .collect(); - let required_subgroup_size_create_info = - required_subgroup_size.map(|required_subgroup_size| { - ash::vk::PipelineShaderStageRequiredSubgroupSizeCreateInfo { - required_subgroup_size, - ..Default::default() - } - }); - ( - ash::vk::PipelineShaderStageCreateInfo { - flags: flags.into(), - stage: stage.into(), - module: entry_point.module().handle(), - p_name: ptr::null(), - p_specialization_info: ptr::null(), - ..Default::default() - }, - PerPipelineShaderStageCreateInfo { - name_vk: CString::new(entry_point_info.name.as_str()).unwrap(), // TODO Borrow CStr for local data? - specialization_info_vk: ash::vk::SpecializationInfo { - map_entry_count: specialization_map_entries_vk.len() as u32, - p_map_entries: ptr::null(), - data_size: specialization_data_vk.len(), - p_data: ptr::null(), - ..Default::default() - }, - specialization_map_entries_vk, - specialization_data_vk, - required_subgroup_size_create_info, - }, - ) - }) - .unzip(); - - for ( - stage_vk, - PerPipelineShaderStageCreateInfo { - name_vk, - specialization_info_vk, - specialization_map_entries_vk, - specialization_data_vk, - required_subgroup_size_create_info, - }, - ) in stages_vk.iter_mut().zip(per_stage_vk.iter_mut()) - { - *stage_vk = ash::vk::PipelineShaderStageCreateInfo { - p_next: required_subgroup_size_create_info.as_ref().map_or( - ptr::null(), - |required_subgroup_size_create_info| { - <*const _>::cast(required_subgroup_size_create_info) - }, - ), - p_name: name_vk.as_ptr(), - p_specialization_info: specialization_info_vk, - ..*stage_vk - }; - - *specialization_info_vk = ash::vk::SpecializationInfo { - p_map_entries: specialization_map_entries_vk.as_ptr(), - p_data: specialization_data_vk.as_ptr().cast(), - ..*specialization_info_vk - }; - } - - let mut vertex_input_state_vk = None; - let mut vertex_binding_descriptions_vk: SmallVec<[_; 8]> = SmallVec::new(); - let mut vertex_attribute_descriptions_vk: SmallVec<[_; 8]> = SmallVec::new(); - let mut vertex_binding_divisor_state_vk = None; - let mut vertex_binding_divisor_descriptions_vk: SmallVec<[_; 8]> = SmallVec::new(); - - if let Some(vertex_input_state) = vertex_input_state { - let VertexInputState { - bindings, - attributes, - _ne: _, - } = vertex_input_state; - - vertex_binding_descriptions_vk.extend(bindings.iter().map( - |(&binding, binding_desc)| { - let &VertexInputBindingDescription { - stride, - input_rate, - _ne: _, - } = binding_desc; - - ash::vk::VertexInputBindingDescription { - binding, - stride, - input_rate: input_rate.into(), - } - }, - )); - - vertex_attribute_descriptions_vk.extend(attributes.iter().map( - |(&location, attribute_desc)| { - let &VertexInputAttributeDescription { - binding, - format, - offset, - _ne: _, - } = attribute_desc; - - ash::vk::VertexInputAttributeDescription { - location, - binding, - format: format.into(), - offset, - } - }, - )); - - let vertex_input_state = - vertex_input_state_vk.insert(ash::vk::PipelineVertexInputStateCreateInfo { - flags: ash::vk::PipelineVertexInputStateCreateFlags::empty(), - vertex_binding_description_count: vertex_binding_descriptions_vk.len() as u32, - p_vertex_binding_descriptions: vertex_binding_descriptions_vk.as_ptr(), - vertex_attribute_description_count: vertex_attribute_descriptions_vk.len() - as u32, - p_vertex_attribute_descriptions: vertex_attribute_descriptions_vk.as_ptr(), - ..Default::default() - }); - - { - vertex_binding_divisor_descriptions_vk.extend( - bindings - .iter() - .filter_map(|(&binding, binding_desc)| match binding_desc.input_rate { - VertexInputRate::Instance { divisor } if divisor != 1 => { - Some((binding, divisor)) - } - _ => None, - }) - .map(|(binding, divisor)| { - ash::vk::VertexInputBindingDivisorDescriptionEXT { binding, divisor } - }), - ); - - // VUID-VkPipelineVertexInputDivisorStateCreateInfoEXT-vertexBindingDivisorCount-arraylength - if !vertex_binding_divisor_descriptions_vk.is_empty() { - let next = vertex_binding_divisor_state_vk.insert( - ash::vk::PipelineVertexInputDivisorStateCreateInfoEXT { - vertex_binding_divisor_count: vertex_binding_divisor_descriptions_vk - .len() - as u32, - p_vertex_binding_divisors: vertex_binding_divisor_descriptions_vk - .as_ptr(), - ..Default::default() - }, - ); - vertex_input_state.p_next = <*const _>::cast(next); - } - } - } - - let mut input_assembly_state_vk = None; - - if let Some(input_assembly_state) = input_assembly_state { - let &InputAssemblyState { - topology, - primitive_restart_enable, - _ne: _, - } = input_assembly_state; - - let _ = input_assembly_state_vk.insert(ash::vk::PipelineInputAssemblyStateCreateInfo { - flags: ash::vk::PipelineInputAssemblyStateCreateFlags::empty(), - topology: topology.into(), - primitive_restart_enable: primitive_restart_enable as ash::vk::Bool32, - ..Default::default() - }); - } - - let mut tessellation_state_vk = None; - let mut tessellation_domain_origin_state_vk = None; - - if let Some(tessellation_state) = tessellation_state { - let &TessellationState { - patch_control_points, - domain_origin, - _ne: _, - } = tessellation_state; - - let tessellation_state_vk = - tessellation_state_vk.insert(ash::vk::PipelineTessellationStateCreateInfo { - flags: ash::vk::PipelineTessellationStateCreateFlags::empty(), - patch_control_points, - ..Default::default() - }); - - if domain_origin != TessellationDomainOrigin::default() { - let tessellation_domain_origin_state_vk = tessellation_domain_origin_state_vk - .insert(ash::vk::PipelineTessellationDomainOriginStateCreateInfo { - domain_origin: domain_origin.into(), - ..Default::default() - }); - - tessellation_domain_origin_state_vk.p_next = tessellation_state_vk.p_next; - tessellation_state_vk.p_next = - <*const _>::cast(tessellation_domain_origin_state_vk); - } - } - - let mut viewport_state_vk = None; - let mut viewports_vk: SmallVec<[_; 2]> = SmallVec::new(); - let mut scissors_vk: SmallVec<[_; 2]> = SmallVec::new(); - - if let Some(viewport_state) = viewport_state { - let ViewportState { - viewports, - scissors, - _ne: _, - } = viewport_state; - - viewports_vk.extend(viewports.iter().map(Into::into)); - scissors_vk.extend(scissors.iter().map(Into::into)); - - let _ = viewport_state_vk.insert(ash::vk::PipelineViewportStateCreateInfo { - flags: ash::vk::PipelineViewportStateCreateFlags::empty(), - viewport_count: viewports_vk.len() as u32, - p_viewports: if viewports_vk.is_empty() { - ptr::null() - } else { - viewports_vk.as_ptr() - }, - scissor_count: scissors_vk.len() as u32, - p_scissors: if scissors_vk.is_empty() { - ptr::null() - } else { - scissors_vk.as_ptr() - }, - ..Default::default() - }); - } - - let mut rasterization_state_vk = None; - let mut rasterization_line_state_vk = None; - - if let Some(rasterization_state) = rasterization_state { - let &RasterizationState { - depth_clamp_enable, - rasterizer_discard_enable, - polygon_mode, - cull_mode, - front_face, - ref depth_bias, - line_width, - line_rasterization_mode, - line_stipple, - _ne: _, - } = rasterization_state; - - let ( - depth_bias_enable, - depth_bias_constant_factor, - depth_bias_clamp, - depth_bias_slope_factor, - ) = if let Some(depth_bias_state) = depth_bias { - let &DepthBiasState { - constant_factor, - clamp, - slope_factor, - } = depth_bias_state; - - (ash::vk::TRUE, constant_factor, clamp, slope_factor) - } else { - (ash::vk::FALSE, 0.0, 0.0, 0.0) - }; - - let rasterization_state = - rasterization_state_vk.insert(ash::vk::PipelineRasterizationStateCreateInfo { - flags: ash::vk::PipelineRasterizationStateCreateFlags::empty(), - depth_clamp_enable: depth_clamp_enable as ash::vk::Bool32, - rasterizer_discard_enable: rasterizer_discard_enable as ash::vk::Bool32, - polygon_mode: polygon_mode.into(), - cull_mode: cull_mode.into(), - front_face: front_face.into(), - depth_bias_enable, - depth_bias_constant_factor, - depth_bias_clamp, - depth_bias_slope_factor, - line_width, - ..Default::default() - }); - - if device.enabled_extensions().ext_line_rasterization { - let (stippled_line_enable, line_stipple_factor, line_stipple_pattern) = - if let Some(line_stipple) = line_stipple { - (ash::vk::TRUE, line_stipple.factor, line_stipple.pattern) - } else { - (ash::vk::FALSE, 1, 0) - }; - - let next = rasterization_line_state_vk.insert( - ash::vk::PipelineRasterizationLineStateCreateInfoEXT { - line_rasterization_mode: line_rasterization_mode.into(), - stippled_line_enable, - line_stipple_factor, - line_stipple_pattern, - ..Default::default() - }, - ); - rasterization_state.p_next = <*const _>::cast(next); - } - } - - let mut multisample_state_vk = None; - - if let Some(multisample_state) = multisample_state { - let &MultisampleState { - rasterization_samples, - sample_shading, - ref sample_mask, - alpha_to_coverage_enable, - alpha_to_one_enable, - _ne: _, - } = multisample_state; - - let (sample_shading_enable, min_sample_shading) = - if let Some(min_sample_shading) = sample_shading { - (ash::vk::TRUE, min_sample_shading) - } else { - (ash::vk::FALSE, 0.0) - }; - - let _ = multisample_state_vk.insert(ash::vk::PipelineMultisampleStateCreateInfo { - flags: ash::vk::PipelineMultisampleStateCreateFlags::empty(), - rasterization_samples: rasterization_samples.into(), - sample_shading_enable, - min_sample_shading, - p_sample_mask: sample_mask.as_ptr(), - alpha_to_coverage_enable: alpha_to_coverage_enable as ash::vk::Bool32, - alpha_to_one_enable: alpha_to_one_enable as ash::vk::Bool32, - ..Default::default() - }); - } - - let mut depth_stencil_state_vk = None; - - if let Some(depth_stencil_state) = depth_stencil_state { - let &DepthStencilState { - flags, - ref depth, - ref depth_bounds, - ref stencil, - _ne: _, - } = depth_stencil_state; - - let (depth_test_enable, depth_write_enable, depth_compare_op) = - if let Some(depth_state) = depth { - let &DepthState { - write_enable, - compare_op, - } = depth_state; - - ( - ash::vk::TRUE, - write_enable as ash::vk::Bool32, - compare_op.into(), - ) - } else { - (ash::vk::FALSE, ash::vk::FALSE, ash::vk::CompareOp::ALWAYS) - }; - - let (depth_bounds_test_enable, min_depth_bounds, max_depth_bounds) = - if let Some(depth_bounds) = depth_bounds { - (ash::vk::TRUE, *depth_bounds.start(), *depth_bounds.end()) - } else { - (ash::vk::FALSE, 0.0, 1.0) - }; - - let (stencil_test_enable, front, back) = if let Some(stencil_state) = stencil { - let StencilState { front, back } = stencil_state; - - let [front, back] = [front, back].map(|stencil_op_state| { - let &StencilOpState { - ops, - compare_mask, - write_mask, - reference, - } = stencil_op_state; - - ash::vk::StencilOpState { - fail_op: ops.fail_op.into(), - pass_op: ops.pass_op.into(), - depth_fail_op: ops.depth_fail_op.into(), - compare_op: ops.compare_op.into(), - compare_mask, - write_mask, - reference, - } - }); - - (ash::vk::TRUE, front, back) - } else { - (ash::vk::FALSE, Default::default(), Default::default()) - }; - - let _ = depth_stencil_state_vk.insert(ash::vk::PipelineDepthStencilStateCreateInfo { - flags: flags.into(), - depth_test_enable, - depth_write_enable, - depth_compare_op, - depth_bounds_test_enable, - stencil_test_enable, - front, - back, - min_depth_bounds, - max_depth_bounds, - ..Default::default() - }); - } - - let mut color_blend_state_vk = None; - let mut color_blend_attachments_vk: SmallVec<[_; 4]> = SmallVec::new(); - let mut color_write_vk = None; - let mut color_write_enables_vk: SmallVec<[_; 4]> = SmallVec::new(); - - if let Some(color_blend_state) = color_blend_state { - let &ColorBlendState { - flags, - logic_op, - ref attachments, - blend_constants, - _ne: _, - } = color_blend_state; - - color_blend_attachments_vk.extend(attachments.iter().map( - |color_blend_attachment_state| { - let &ColorBlendAttachmentState { - blend, - color_write_mask, - color_write_enable: _, - } = color_blend_attachment_state; - - let blend = if let Some(blend) = blend { - blend.into() - } else { - Default::default() - }; - - ash::vk::PipelineColorBlendAttachmentState { - color_write_mask: color_write_mask.into(), - ..blend - } - }, - )); - - let (logic_op_enable, logic_op) = if let Some(logic_op) = logic_op { - (ash::vk::TRUE, logic_op.into()) - } else { - (ash::vk::FALSE, Default::default()) - }; - - let color_blend_state_vk = - color_blend_state_vk.insert(ash::vk::PipelineColorBlendStateCreateInfo { - flags: flags.into(), - logic_op_enable, - logic_op, - attachment_count: color_blend_attachments_vk.len() as u32, - p_attachments: color_blend_attachments_vk.as_ptr(), - blend_constants, - ..Default::default() - }); - - if device.enabled_extensions().ext_color_write_enable { - color_write_enables_vk.extend(attachments.iter().map( - |color_blend_attachment_state| { - let &ColorBlendAttachmentState { - blend: _, - color_write_mask: _, - color_write_enable, - } = color_blend_attachment_state; - - color_write_enable as ash::vk::Bool32 - }, - )); - - let next = color_write_vk.insert(ash::vk::PipelineColorWriteCreateInfoEXT { - attachment_count: color_write_enables_vk.len() as u32, - p_color_write_enables: color_write_enables_vk.as_ptr(), - ..Default::default() - }); - color_blend_state_vk.p_next = <*const _>::cast(next); - } - } - - let dynamic_state_list_vk: SmallVec<[_; 4]> = - dynamic_state.iter().copied().map(Into::into).collect(); - let dynamic_state_vk = - (!dynamic_state_list_vk.is_empty()).then(|| ash::vk::PipelineDynamicStateCreateInfo { - flags: ash::vk::PipelineDynamicStateCreateFlags::empty(), - dynamic_state_count: dynamic_state_list_vk.len() as u32, - p_dynamic_states: dynamic_state_list_vk.as_ptr(), - ..Default::default() - }); - - let render_pass = subpass.as_ref().unwrap(); - let mut render_pass_vk = ash::vk::RenderPass::null(); - let mut subpass_vk = 0; - let mut color_attachment_formats_vk: SmallVec<[_; 4]> = SmallVec::new(); - let mut rendering_create_info_vk = None; - - match render_pass { - PipelineSubpassType::BeginRenderPass(subpass) => { - render_pass_vk = subpass.render_pass().handle(); - subpass_vk = subpass.index(); - } - PipelineSubpassType::BeginRendering(rendering_info) => { - let &PipelineRenderingCreateInfo { - view_mask, - ref color_attachment_formats, - depth_attachment_format, - stencil_attachment_format, - _ne: _, - } = rendering_info; - - color_attachment_formats_vk.extend( - color_attachment_formats - .iter() - .map(|format| format.map_or(ash::vk::Format::UNDEFINED, Into::into)), - ); - - let _ = rendering_create_info_vk.insert(ash::vk::PipelineRenderingCreateInfo { - view_mask, - color_attachment_count: color_attachment_formats_vk.len() as u32, - p_color_attachment_formats: color_attachment_formats_vk.as_ptr(), - depth_attachment_format: depth_attachment_format - .map_or(ash::vk::Format::UNDEFINED, Into::into), - stencil_attachment_format: stencil_attachment_format - .map_or(ash::vk::Format::UNDEFINED, Into::into), - ..Default::default() - }); - } - } - - let mut discard_rectangle_state_vk = None; - let mut discard_rectangles_vk: SmallVec<[_; 2]> = SmallVec::new(); - - if let Some(discard_rectangle_state) = discard_rectangle_state { - let DiscardRectangleState { - mode, - rectangles, - _ne: _, - } = discard_rectangle_state; - - discard_rectangles_vk.extend(rectangles.iter().map(|rect| rect.into())); - - let _ = discard_rectangle_state_vk.insert( - ash::vk::PipelineDiscardRectangleStateCreateInfoEXT { - flags: ash::vk::PipelineDiscardRectangleStateCreateFlagsEXT::empty(), - discard_rectangle_mode: (*mode).into(), - discard_rectangle_count: discard_rectangles_vk.len() as u32, - p_discard_rectangles: discard_rectangles_vk.as_ptr(), - ..Default::default() - }, - ); - } - - let mut conservative_rasterization_state_vk = None; - - if let Some(conservative_rasterization_state) = conservative_rasterization_state { - let ConservativeRasterizationState { - mode, - overestimation_size, - _ne: _, - } = conservative_rasterization_state; - - let _ = conservative_rasterization_state_vk.insert( - ash::vk::PipelineRasterizationConservativeStateCreateInfoEXT { - flags: ash::vk::PipelineRasterizationConservativeStateCreateFlagsEXT::empty(), - conservative_rasterization_mode: (*mode).into(), - extra_primitive_overestimation_size: *overestimation_size, - ..Default::default() - }, - ); - } - - /* - Create - */ - - let mut create_info_vk = ash::vk::GraphicsPipelineCreateInfo { - flags: flags.into(), - stage_count: stages_vk.len() as u32, - p_stages: stages_vk.as_ptr(), - p_vertex_input_state: vertex_input_state_vk - .as_ref() - .map(|p| -> *const _ { p }) - .unwrap_or(ptr::null()), - p_input_assembly_state: input_assembly_state_vk - .as_ref() - .map(|p| -> *const _ { p }) - .unwrap_or(ptr::null()), - p_tessellation_state: tessellation_state_vk - .as_ref() - .map(|p| -> *const _ { p }) - .unwrap_or(ptr::null()), - p_viewport_state: viewport_state_vk - .as_ref() - .map(|p| -> *const _ { p }) - .unwrap_or(ptr::null()), - p_rasterization_state: rasterization_state_vk - .as_ref() - .map(|p| -> *const _ { p }) - .unwrap_or(ptr::null()), - p_multisample_state: multisample_state_vk - .as_ref() - .map(|p| -> *const _ { p }) - .unwrap_or(ptr::null()), - p_depth_stencil_state: depth_stencil_state_vk - .as_ref() - .map(|p| -> *const _ { p }) - .unwrap_or(ptr::null()), - p_color_blend_state: color_blend_state_vk - .as_ref() - .map(|p| -> *const _ { p }) - .unwrap_or(ptr::null()), - p_dynamic_state: dynamic_state_vk - .as_ref() - .map(|p| -> *const _ { p }) - .unwrap_or(ptr::null()), - layout: layout.handle(), - render_pass: render_pass_vk, - subpass: subpass_vk, - base_pipeline_handle: base_pipeline - .as_ref() - .map_or(ash::vk::Pipeline::null(), VulkanObject::handle), - base_pipeline_index: -1, - ..Default::default() - }; - - if let Some(info) = discard_rectangle_state_vk.as_mut() { - info.p_next = create_info_vk.p_next; - create_info_vk.p_next = <*const _>::cast(info); - } - - if let Some(info) = conservative_rasterization_state_vk.as_mut() { - info.p_next = create_info_vk.p_next; - create_info_vk.p_next = <*const _>::cast(info); - } - - if let Some(info) = rendering_create_info_vk.as_mut() { - info.p_next = create_info_vk.p_next; - create_info_vk.p_next = <*const _>::cast(info); - } - - let cache_handle = match cache.as_ref() { - Some(cache) => cache.handle(), - None => ash::vk::PipelineCache::null(), - }; - let handle = { + let create_info_fields3_vk = create_info.to_vk_fields3(); + let create_info_fields2_vk = create_info.to_vk_fields2(&create_info_fields3_vk); + let mut create_info_fields1_extensions = + create_info.to_vk_fields1_extensions(&create_info_fields2_vk); + let create_info_fields1_vk = create_info + .to_vk_fields1(&create_info_fields2_vk, &mut create_info_fields1_extensions); + let mut create_info_extensions_vk = + create_info.to_vk_extensions(&create_info_fields2_vk); + let create_info_vk = + create_info.to_vk(&create_info_fields1_vk, &mut create_info_extensions_vk); + + let cache_handle = match cache.as_ref() { + Some(cache) => cache.handle(), + None => ash::vk::PipelineCache::null(), + }; + let fns = device.fns(); let mut output = MaybeUninit::uninit(); (fns.v1_0.create_graphics_pipelines)( @@ -977,7 +271,6 @@ impl GraphicsPipeline { base_pipeline: _, discard_rectangle_state, - conservative_rasterization_state, _ne: _, } = create_info; @@ -1084,6 +377,8 @@ impl GraphicsPipeline { DynamicState::DepthBias, DynamicState::LineWidth, DynamicState::LineStipple, + DynamicState::ConservativeRasterizationMode, + DynamicState::ExtraPrimitiveOverestimationSize, ]); } @@ -1114,13 +409,6 @@ impl GraphicsPipeline { fixed_state.extend([DynamicState::DiscardRectangle]); } - if conservative_rasterization_state.is_some() { - fixed_state.extend([ - DynamicState::ConservativeRasterizationMode, - DynamicState::ExtraPrimitiveOverestimationSize, - ]); - } - fixed_state.retain(|state| !dynamic_state.contains(state)); Arc::new(Self { @@ -1144,7 +432,6 @@ impl GraphicsPipeline { subpass: subpass.unwrap(), discard_rectangle_state, - conservative_rasterization_state, descriptor_binding_requirements, num_used_descriptor_sets, @@ -1244,12 +531,6 @@ impl GraphicsPipeline { self.discard_rectangle_state.as_ref() } - /// Returns the conservative rasterization state used to create this pipeline. - #[inline] - pub fn conservative_rasterization_state(&self) -> Option<&ConservativeRasterizationState> { - self.conservative_rasterization_state.as_ref() - } - /// If the pipeline has a fragment shader, returns the fragment tests stages used. #[inline] pub fn fragment_tests_stages(&self) -> Option { @@ -1442,11 +723,6 @@ pub struct GraphicsPipelineCreateInfo { /// The default value is `None`. pub discard_rectangle_state: Option, - /// The conservative rasterization state. - /// - /// The default value is `None`. - pub conservative_rasterization_state: Option, - pub _ne: crate::NonExhaustive, } @@ -1473,12 +749,13 @@ impl GraphicsPipelineCreateInfo { base_pipeline: None, discard_rectangle_state: None, - conservative_rasterization_state: None, _ne: crate::NonExhaustive(()), } } pub(crate) fn validate(&self, device: &Device) -> Result<(), Box> { + let properties = device.physical_device().properties(); + let &Self { flags, ref stages, @@ -1498,7 +775,6 @@ impl GraphicsPipelineCreateInfo { ref base_pipeline, ref discard_rectangle_state, - ref conservative_rasterization_state, _ne: _, } = self; @@ -2209,23 +1485,6 @@ impl GraphicsPipelineCreateInfo { .map_err(|err| err.add_context("discard_rectangle_state"))?; } - if let Some(conservative_rasterization_state) = conservative_rasterization_state { - if !device.enabled_extensions().ext_conservative_rasterization { - return Err(Box::new(ValidationError { - context: "conservative_rasterization_state".into(), - problem: "is `Some`".into(), - requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::DeviceExtension( - "ext_conservative_rasterization", - )])]), - ..Default::default() - })); - } - - conservative_rasterization_state - .validate(device) - .map_err(|err| err.add_context("conservative_rasterization_state"))?; - } - for dynamic_state in dynamic_state.iter().copied() { dynamic_state.validate_device(device).map_err(|err| { err.add_context("dynamic_state") @@ -2370,6 +1629,7 @@ impl GraphicsPipelineCreateInfo { line_width, line_rasterization_mode: _, line_stipple, + ref conservative, _ne: _, } = rasterization_state; @@ -2429,6 +1689,106 @@ impl GraphicsPipelineCreateInfo { } } + if let Some(conservative) = conservative { + if matches!(conservative.mode, ConservativeRasterizationMode::Disabled) + && !properties + .conservative_point_and_line_rasterization + .unwrap_or(false) + { + if let (None, Some(input_assembly_state)) = + (geometry_stage, input_assembly_state) + { + if matches!( + input_assembly_state.topology, + PrimitiveTopology::PointList + | PrimitiveTopology::LineList + | PrimitiveTopology::LineStrip + ) && (!dynamic_state.contains(&DynamicState::PrimitiveTopology) + || match device + .physical_device() + .properties() + .dynamic_primitive_topology_unrestricted + { + Some(b) => !b, + None => false, + }) + { + return Err(Box::new(ValidationError { + problem: "`input_assembly_state.topology` is not compatible with the \ + conservative rasterization mode" + .into(), + vuids: &["VUID-VkGraphicsPipelineCreateInfo-conservativePointAndLineRasterization-08892"], + ..Default::default() + })); + } + } + + if let (Some(geometry_stage), Some(_)) = (geometry_stage, input_assembly_state) + { + let spirv = geometry_stage.entry_point.module().spirv(); + let entry_point_function = spirv.function(geometry_stage.entry_point.id()); + + let invalid_output = + entry_point_function + .execution_modes() + .iter() + .any(|instruction| { + matches!( + instruction, + Instruction::ExecutionMode { + mode: ExecutionMode::OutputPoints + | ExecutionMode::OutputLineStrip, + .. + }, + ) + }); + + if invalid_output { + return Err(Box::new(ValidationError { + problem: "the output topology of the geometry shader is not compatible with the \ + conservative rasterization mode" + .into(), + vuids: &["VUID-VkGraphicsPipelineCreateInfo-conservativePointAndLineRasterization-06760"], + ..Default::default() + })); + } + } + + if let Some(mesh_stage) = mesh_stage { + let spirv = mesh_stage.entry_point.module().spirv(); + let entry_point_function = spirv.function(mesh_stage.entry_point.id()); + + let mut invalid_output = false; + + for instruction in entry_point_function.execution_modes() { + if let Instruction::ExecutionMode { mode, .. } = *instruction { + match mode { + ExecutionMode::OutputPoints => { + invalid_output = true; + break; + } + ExecutionMode::OutputLineStrip => { + invalid_output = true; + break; + } + _ => {} + } + } + } + + if invalid_output { + return Err(Box::new(ValidationError { + problem: "the output topology of the mesh shader is not compatible with the \ + conservative rasterization mode" + .into(), + vuids: &["VUID-VkGraphicsPipelineCreateInfo-conservativePointAndLineRasterization-06761"], + ..Default::default() + })); + } + } + } + } + // TODO: // VUID-VkGraphicsPipelineCreateInfo-pStages-00740 // VUID-VkGraphicsPipelineCreateInfo-renderPass-06049 @@ -2576,107 +1936,6 @@ impl GraphicsPipelineCreateInfo { } } - if let Some(conservative_rasterization_state) = conservative_rasterization_state { - let properties = device.physical_device().properties(); - - if matches!( - conservative_rasterization_state.mode, - ConservativeRasterizationMode::Disabled - ) && !properties - .conservative_point_and_line_rasterization - .unwrap_or(false) - { - if let (None, Some(input_assembly_state)) = (geometry_stage, input_assembly_state) { - if matches!( - input_assembly_state.topology, - PrimitiveTopology::PointList - | PrimitiveTopology::LineList - | PrimitiveTopology::LineStrip - ) && (!dynamic_state.contains(&DynamicState::PrimitiveTopology) - || match device - .physical_device() - .properties() - .dynamic_primitive_topology_unrestricted - { - Some(b) => !b, - None => false, - }) - { - return Err(Box::new(ValidationError { - problem: "`input_assembly_state.topology` is not compatible with the \ - conservative rasterization mode" - .into(), - vuids: &["VUID-VkGraphicsPipelineCreateInfo-conservativePointAndLineRasterization-08892"], - ..Default::default() - })); - } - } - - if let (Some(geometry_stage), Some(_)) = (geometry_stage, input_assembly_state) { - let spirv = geometry_stage.entry_point.module().spirv(); - let entry_point_function = spirv.function(geometry_stage.entry_point.id()); - - let invalid_output = - entry_point_function - .execution_modes() - .iter() - .any(|instruction| { - matches!( - instruction, - Instruction::ExecutionMode { - mode: ExecutionMode::OutputPoints - | ExecutionMode::OutputLineStrip, - .. - }, - ) - }); - - if invalid_output { - return Err(Box::new(ValidationError { - problem: "the output topology of the geometry shader is not compatible with the \ - conservative rasterization mode" - .into(), - vuids: &["VUID-VkGraphicsPipelineCreateInfo-conservativePointAndLineRasterization-06760"], - ..Default::default() - })); - } - } - - if let Some(mesh_stage) = mesh_stage { - let spirv = mesh_stage.entry_point.module().spirv(); - let entry_point_function = spirv.function(mesh_stage.entry_point.id()); - - let mut invalid_output = false; - - for instruction in entry_point_function.execution_modes() { - if let Instruction::ExecutionMode { mode, .. } = *instruction { - match mode { - ExecutionMode::OutputPoints => { - invalid_output = true; - break; - } - ExecutionMode::OutputLineStrip => { - invalid_output = true; - break; - } - _ => {} - } - } - } - - if invalid_output { - return Err(Box::new(ValidationError { - problem: "the output topology of the mesh shader is not compatible with the \ - conservative rasterization mode" - .into(), - vuids: &["VUID-VkGraphicsPipelineCreateInfo-conservativePointAndLineRasterization-06761"], - ..Default::default() - })); - } - } - } - } - if let (Some(fragment_stage), Some(color_blend_state), Some(subpass)) = (fragment_stage, color_blend_state, subpass) { @@ -3003,6 +2262,389 @@ impl GraphicsPipelineCreateInfo { Ok(()) } + + pub(crate) fn to_vk<'a>( + &self, + fields1_vk: &'a GraphicsPipelineCreateInfoFields1Vk<'_>, + extensions_vk: &'a mut GraphicsPipelineCreateInfoExtensionsVk<'_>, + ) -> ash::vk::GraphicsPipelineCreateInfo<'a> { + let &Self { + flags, + stages: _, + + vertex_input_state: _, + input_assembly_state: _, + tessellation_state: _, + viewport_state: _, + rasterization_state: _, + multisample_state: _, + depth_stencil_state: _, + color_blend_state: _, + dynamic_state: _, + + ref layout, + ref subpass, + ref base_pipeline, + + discard_rectangle_state: _, + _ne: _, + } = self; + let (render_pass_vk, subpass_vk) = match subpass { + Some(PipelineSubpassType::BeginRenderPass(subpass)) => { + (subpass.render_pass().handle(), subpass.index()) + } + _ => (ash::vk::RenderPass::null(), 0), + }; + let GraphicsPipelineCreateInfoFields1Vk { + stages_vk, + vertex_input_state_vk, + input_assembly_state_vk, + tessellation_state_vk, + viewport_state_vk, + rasterization_state_vk, + multisample_state_vk, + depth_stencil_state_vk, + color_blend_state_vk, + dynamic_state_vk, + } = fields1_vk; + + let mut val_vk = ash::vk::GraphicsPipelineCreateInfo::default() + .flags(flags.into()) + .stages(stages_vk) + .layout(layout.handle()) + .render_pass(render_pass_vk) + .subpass(subpass_vk) + .base_pipeline_handle( + base_pipeline + .as_ref() + .map_or(ash::vk::Pipeline::null(), VulkanObject::handle), + ) + .base_pipeline_index(-1); + + if let Some(vertex_input_state_vk) = vertex_input_state_vk { + val_vk = val_vk.vertex_input_state(vertex_input_state_vk); + } + + if let Some(input_assembly_state_vk) = input_assembly_state_vk { + val_vk = val_vk.input_assembly_state(input_assembly_state_vk); + } + + if let Some(tessellation_state_vk) = tessellation_state_vk { + val_vk = val_vk.tessellation_state(tessellation_state_vk); + } + + if let Some(viewport_state_vk) = viewport_state_vk { + val_vk = val_vk.viewport_state(viewport_state_vk); + } + + if let Some(rasterization_state_vk) = rasterization_state_vk { + val_vk = val_vk.rasterization_state(rasterization_state_vk); + } + + if let Some(multisample_state_vk) = multisample_state_vk { + val_vk = val_vk.multisample_state(multisample_state_vk); + } + + if let Some(depth_stencil_state_vk) = depth_stencil_state_vk { + val_vk = val_vk.depth_stencil_state(depth_stencil_state_vk); + } + + if let Some(color_blend_state_vk) = color_blend_state_vk { + val_vk = val_vk.color_blend_state(color_blend_state_vk); + } + + if let Some(dynamic_state_vk) = dynamic_state_vk { + val_vk = val_vk.dynamic_state(dynamic_state_vk); + } + + let GraphicsPipelineCreateInfoExtensionsVk { + discard_rectangle_state_vk, + rendering_vk, + } = extensions_vk; + + if let Some(next) = discard_rectangle_state_vk { + val_vk = val_vk.push_next(next); + } + + if let Some(next) = rendering_vk { + val_vk = val_vk.push_next(next); + } + + val_vk + } + + pub(crate) fn to_vk_extensions<'a>( + &self, + fields2_vk: &'a GraphicsPipelineCreateInfoFields2Vk<'_>, + ) -> GraphicsPipelineCreateInfoExtensionsVk<'a> { + let GraphicsPipelineCreateInfoFields2Vk { + discard_rectangle_state_fields1_vk, + rendering_fields1_vk, + .. + } = fields2_vk; + let discard_rectangle_state_vk = self + .discard_rectangle_state + .as_ref() + .zip(discard_rectangle_state_fields1_vk.as_ref()) + .map(|(discard_rectangle_state, fields1_vk)| discard_rectangle_state.to_vk(fields1_vk)); + let rendering_vk = self + .subpass + .as_ref() + .zip(rendering_fields1_vk.as_ref()) + .map(|(subpass, fields1_vk)| subpass.to_vk_rendering(fields1_vk)); + + GraphicsPipelineCreateInfoExtensionsVk { + discard_rectangle_state_vk, + rendering_vk, + } + } + + pub(crate) fn to_vk_fields1<'a>( + &'a self, + fields2_vk: &'a GraphicsPipelineCreateInfoFields2Vk<'_>, + extensions_vk: &'a mut GraphicsPipelineCreateInfoFields1ExtensionsVk<'_>, + ) -> GraphicsPipelineCreateInfoFields1Vk<'a> { + let Self { + stages, + + vertex_input_state, + input_assembly_state, + tessellation_state, + viewport_state, + rasterization_state, + multisample_state, + depth_stencil_state, + color_blend_state, + .. + } = self; + let GraphicsPipelineCreateInfoFields2Vk { + stages_fields1_vk, + vertex_input_state_fields1_vk, + viewport_state_fields1_vk, + color_blend_state_fields1_vk, + dynamic_states_vk, + discard_rectangle_state_fields1_vk: _, + rendering_fields1_vk: _, + } = fields2_vk; + let GraphicsPipelineCreateInfoFields1ExtensionsVk { + stages_extensions_vk, + vertex_input_state_extensions_vk, + tessellation_state_extensions_vk, + rasterization_state_extensions_vk, + color_blend_state_extensions_vk, + } = extensions_vk; + + let stages_vk = stages + .iter() + .zip(stages_fields1_vk) + .zip(stages_extensions_vk) + .map(|((stage, fields1_vk), extensions_vk)| stage.to_vk(fields1_vk, extensions_vk)) + .collect(); + let vertex_input_state_vk = vertex_input_state + .as_ref() + .zip(vertex_input_state_fields1_vk.as_ref()) + .zip(vertex_input_state_extensions_vk.as_mut()) + .map(|((vertex_input_state, fields1_vk), extensions_vk)| { + vertex_input_state.to_vk(fields1_vk, extensions_vk) + }); + let input_assembly_state_vk = input_assembly_state.as_ref().map(InputAssemblyState::to_vk); + let tessellation_state_vk = tessellation_state + .as_ref() + .zip(tessellation_state_extensions_vk.as_mut()) + .map(|(tessellation_state, extensions_vk)| tessellation_state.to_vk(extensions_vk)); + let viewport_state_vk = viewport_state + .as_ref() + .zip(viewport_state_fields1_vk.as_ref()) + .map(|(viewport_state, fields1_vk)| viewport_state.to_vk(fields1_vk)); + let rasterization_state_vk = rasterization_state + .as_ref() + .zip(rasterization_state_extensions_vk.as_mut()) + .map(|(rasterization_state, extensions_vk)| rasterization_state.to_vk(extensions_vk)); + let multisample_state_vk = multisample_state.as_ref().map(MultisampleState::to_vk); + let depth_stencil_state_vk = depth_stencil_state.as_ref().map(DepthStencilState::to_vk); + let color_blend_state_vk = color_blend_state + .as_ref() + .zip(color_blend_state_fields1_vk.as_ref()) + .zip(color_blend_state_extensions_vk.as_mut()) + .map(|((color_blend_state, fields1_vk), extensions_vk)| { + color_blend_state.to_vk(fields1_vk, extensions_vk) + }); + let dynamic_state_vk = (!dynamic_states_vk.is_empty()).then(|| { + ash::vk::PipelineDynamicStateCreateInfo::default() + .flags(ash::vk::PipelineDynamicStateCreateFlags::empty()) + .dynamic_states(dynamic_states_vk) + }); + + GraphicsPipelineCreateInfoFields1Vk { + stages_vk, + vertex_input_state_vk, + input_assembly_state_vk, + tessellation_state_vk, + viewport_state_vk, + rasterization_state_vk, + multisample_state_vk, + depth_stencil_state_vk, + color_blend_state_vk, + dynamic_state_vk, + } + } + + pub(crate) fn to_vk_fields1_extensions<'a>( + &self, + fields2_vk: &'a GraphicsPipelineCreateInfoFields2Vk<'_>, + ) -> GraphicsPipelineCreateInfoFields1ExtensionsVk<'a> { + let Self { + stages, + + vertex_input_state, + tessellation_state, + rasterization_state, + color_blend_state, + .. + } = self; + + let GraphicsPipelineCreateInfoFields2Vk { + stages_fields1_vk: _, + vertex_input_state_fields1_vk, + viewport_state_fields1_vk: _, + color_blend_state_fields1_vk, + dynamic_states_vk: _, + discard_rectangle_state_fields1_vk: _, + rendering_fields1_vk: _, + } = fields2_vk; + + let stages_extensions_vk = stages + .iter() + .map(|stage| stage.to_vk_extensions()) + .collect(); + let vertex_input_state_extensions_vk = vertex_input_state + .as_ref() + .zip(vertex_input_state_fields1_vk.as_ref()) + .map(|(vertex_input_state, fields1_vk)| { + vertex_input_state.to_vk_extensions(fields1_vk) + }); + let tessellation_state_extensions_vk = tessellation_state + .as_ref() + .map(TessellationState::to_vk_extensions); + let rasterization_state_extensions_vk = rasterization_state + .as_ref() + .map(RasterizationState::to_vk_extensions); + let color_blend_state_extensions_vk = color_blend_state + .as_ref() + .zip(color_blend_state_fields1_vk.as_ref()) + .map(|(color_blend_state, fields1_vk)| color_blend_state.to_vk_extensions(fields1_vk)); + + GraphicsPipelineCreateInfoFields1ExtensionsVk { + stages_extensions_vk, + vertex_input_state_extensions_vk, + tessellation_state_extensions_vk, + rasterization_state_extensions_vk, + color_blend_state_extensions_vk, + } + } + + pub(crate) fn to_vk_fields2<'a>( + &self, + fields3_vk: &'a GraphicsPipelineCreateInfoFields3Vk, + ) -> GraphicsPipelineCreateInfoFields2Vk<'a> { + let Self { + stages, + + vertex_input_state, + viewport_state, + color_blend_state, + dynamic_state, + + subpass, + + discard_rectangle_state, + .. + } = self; + let GraphicsPipelineCreateInfoFields3Vk { stages_fields2_vk } = fields3_vk; + + let stages_fields1_vk = stages + .iter() + .zip(stages_fields2_vk) + .map(|(stage, fields2_vk)| stage.to_vk_fields1(fields2_vk)) + .collect(); + let vertex_input_state_fields1_vk = vertex_input_state + .as_ref() + .map(VertexInputState::to_vk_fields1); + let viewport_state_fields1_vk = viewport_state.as_ref().map(ViewportState::to_vk_fields1); + let color_blend_state_fields1_vk = color_blend_state + .as_ref() + .map(ColorBlendState::to_vk_fields1); + let dynamic_states_vk = dynamic_state.iter().copied().map(Into::into).collect(); + let discard_rectangle_state_fields1_vk = discard_rectangle_state + .as_ref() + .map(DiscardRectangleState::to_vk_fields1); + let rendering_fields1_vk = subpass + .as_ref() + .and_then(PipelineSubpassType::to_vk_rendering_fields1); + + GraphicsPipelineCreateInfoFields2Vk { + stages_fields1_vk, + vertex_input_state_fields1_vk, + viewport_state_fields1_vk, + color_blend_state_fields1_vk, + dynamic_states_vk, + discard_rectangle_state_fields1_vk, + rendering_fields1_vk, + } + } + + pub(crate) fn to_vk_fields3(&self) -> GraphicsPipelineCreateInfoFields3Vk { + let stages_fields2_vk = self + .stages + .iter() + .map(|stage| stage.to_vk_fields2()) + .collect(); + + GraphicsPipelineCreateInfoFields3Vk { stages_fields2_vk } + } +} + +pub(crate) struct GraphicsPipelineCreateInfoExtensionsVk<'a> { + pub(crate) discard_rectangle_state_vk: + Option>, + pub(crate) rendering_vk: Option>, +} + +pub(crate) struct GraphicsPipelineCreateInfoFields1Vk<'a> { + pub(crate) stages_vk: SmallVec<[ash::vk::PipelineShaderStageCreateInfo<'a>; 5]>, + pub(crate) vertex_input_state_vk: Option>, + pub(crate) input_assembly_state_vk: + Option>, + pub(crate) tessellation_state_vk: Option>, + pub(crate) viewport_state_vk: Option>, + pub(crate) rasterization_state_vk: Option>, + pub(crate) multisample_state_vk: Option>, + pub(crate) depth_stencil_state_vk: + Option>, + pub(crate) color_blend_state_vk: Option>, + pub(crate) dynamic_state_vk: Option>, +} + +pub(crate) struct GraphicsPipelineCreateInfoFields1ExtensionsVk<'a> { + pub(crate) stages_extensions_vk: SmallVec<[PipelineShaderStageCreateInfoExtensionsVk; 5]>, + pub(crate) vertex_input_state_extensions_vk: Option>, + pub(crate) tessellation_state_extensions_vk: Option, + pub(crate) rasterization_state_extensions_vk: Option, + pub(crate) color_blend_state_extensions_vk: Option>, +} + +pub(crate) struct GraphicsPipelineCreateInfoFields2Vk<'a> { + pub(crate) stages_fields1_vk: SmallVec<[PipelineShaderStageCreateInfoFields1Vk<'a>; 5]>, + pub(crate) vertex_input_state_fields1_vk: Option, + pub(crate) viewport_state_fields1_vk: Option, + pub(crate) color_blend_state_fields1_vk: Option, + pub(crate) dynamic_states_vk: SmallVec<[ash::vk::DynamicState; 4]>, + pub(crate) discard_rectangle_state_fields1_vk: Option, + pub(crate) rendering_fields1_vk: Option, +} + +pub(crate) struct GraphicsPipelineCreateInfoFields3Vk { + pub(crate) stages_fields2_vk: SmallVec<[PipelineShaderStageCreateInfoFields2Vk; 5]>, } /// The input primitive type that is expected by a geometry shader. diff --git a/vulkano/src/pipeline/graphics/multisample.rs b/vulkano/src/pipeline/graphics/multisample.rs index 95657bf4..b860d46c 100644 --- a/vulkano/src/pipeline/graphics/multisample.rs +++ b/vulkano/src/pipeline/graphics/multisample.rs @@ -8,7 +8,7 @@ use crate::{ // TODO: handle some weird behaviors with non-floating-point targets /// State of the multisampling. -#[derive(Copy, Clone, Debug)] +#[derive(Clone, Debug)] pub struct MultisampleState { /// The number of rasterization samples to take per pixel. The GPU will pick this many /// different locations within each pixel and assign to each of these locations a different @@ -134,4 +134,31 @@ impl MultisampleState { Ok(()) } + + pub(crate) fn to_vk(&self) -> ash::vk::PipelineMultisampleStateCreateInfo<'_> { + let &Self { + rasterization_samples, + sample_shading, + ref sample_mask, + alpha_to_coverage_enable, + alpha_to_one_enable, + _ne: _, + } = self; + + let (sample_shading_enable_vk, min_sample_shading_vk) = + if let Some(min_sample_shading) = sample_shading { + (true, min_sample_shading) + } else { + (false, 0.0) + }; + + ash::vk::PipelineMultisampleStateCreateInfo::default() + .flags(ash::vk::PipelineMultisampleStateCreateFlags::empty()) + .rasterization_samples(rasterization_samples.into()) + .sample_shading_enable(sample_shading_enable_vk) + .min_sample_shading(min_sample_shading_vk) + .sample_mask(sample_mask) + .alpha_to_coverage_enable(alpha_to_coverage_enable) + .alpha_to_one_enable(alpha_to_one_enable) + } } diff --git a/vulkano/src/pipeline/graphics/rasterization.rs b/vulkano/src/pipeline/graphics/rasterization.rs index d446f503..e830222b 100644 --- a/vulkano/src/pipeline/graphics/rasterization.rs +++ b/vulkano/src/pipeline/graphics/rasterization.rs @@ -78,6 +78,17 @@ pub struct RasterizationState { /// The default value is `None`. pub line_stipple: Option, + /// Enables a mode of rasterization where the edges of primitives are modified so that + /// fragments are generated if the edge of a primitive touches any part of a pixel, or if a + /// pixel is fully covered by a primitive. + /// + /// If this is set to `Some`, the + /// [`ext_conservative_rasterization`](crate::device::DeviceExtensions::ext_conservative_rasterization) + /// extension must be enabled on the device. + /// + /// The default value is `None`. + pub conservative: Option, + pub _ne: crate::NonExhaustive, } @@ -94,6 +105,7 @@ impl Default for RasterizationState { line_width: 1.0, line_rasterization_mode: Default::default(), line_stipple: None, + conservative: None, _ne: crate::NonExhaustive(()), } } @@ -144,6 +156,7 @@ impl RasterizationState { line_width: _, line_rasterization_mode, ref line_stipple, + ref conservative, _ne: _, } = self; @@ -344,8 +357,127 @@ impl RasterizationState { } } + if let Some(conservative) = conservative { + if !device.enabled_extensions().ext_conservative_rasterization { + return Err(Box::new(ValidationError { + context: "conservative".into(), + problem: "is `Some`".into(), + requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::DeviceExtension( + "ext_conservative_rasterization", + )])]), + ..Default::default() + })); + } + + conservative + .validate(device) + .map_err(|err| err.add_context("conservative"))?; + } + Ok(()) } + + pub(crate) fn to_vk<'a>( + &self, + extensions_vk: &'a mut RasterizationStateExtensionsVk, + ) -> ash::vk::PipelineRasterizationStateCreateInfo<'a> { + let &Self { + depth_clamp_enable, + rasterizer_discard_enable, + polygon_mode, + cull_mode, + front_face, + ref depth_bias, + line_width, + line_rasterization_mode: _, + line_stipple: _, + conservative: _, + _ne: _, + } = self; + + let ( + depth_bias_enable_vk, + depth_bias_constant_factor_vk, + depth_bias_clamp_vk, + depth_bias_slope_factor_vk, + ) = if let Some(depth_bias_state) = depth_bias { + let &DepthBiasState { + constant_factor, + clamp, + slope_factor, + } = depth_bias_state; + + (true, constant_factor, clamp, slope_factor) + } else { + (false, 0.0, 0.0, 0.0) + }; + + let mut val_vk = ash::vk::PipelineRasterizationStateCreateInfo::default() + .flags(ash::vk::PipelineRasterizationStateCreateFlags::empty()) + .depth_clamp_enable(depth_clamp_enable) + .rasterizer_discard_enable(rasterizer_discard_enable) + .polygon_mode(polygon_mode.into()) + .cull_mode(cull_mode.into()) + .front_face(front_face.into()) + .depth_bias_enable(depth_bias_enable_vk) + .depth_bias_constant_factor(depth_bias_constant_factor_vk) + .depth_bias_clamp(depth_bias_clamp_vk) + .depth_bias_slope_factor(depth_bias_slope_factor_vk) + .line_width(line_width); + + let RasterizationStateExtensionsVk { + line_vk, + conservative_vk, + } = extensions_vk; + + if let Some(next) = line_vk { + val_vk = val_vk.push_next(next); + } + + if let Some(next) = conservative_vk { + val_vk = val_vk.push_next(next); + } + + val_vk + } + + pub(crate) fn to_vk_extensions(&self) -> RasterizationStateExtensionsVk { + let &Self { + line_rasterization_mode, + ref line_stipple, + ref conservative, + .. + } = self; + + let line_vk = (line_rasterization_mode != LineRasterizationMode::Default).then(|| { + let (stippled_line_enable, line_stipple_factor, line_stipple_pattern) = + if let Some(line_stipple) = line_stipple { + (true, line_stipple.factor, line_stipple.pattern) + } else { + (false, 1, 0) + }; + + ash::vk::PipelineRasterizationLineStateCreateInfoKHR::default() + .line_rasterization_mode(line_rasterization_mode.into()) + .stippled_line_enable(stippled_line_enable) + .line_stipple_factor(line_stipple_factor) + .line_stipple_pattern(line_stipple_pattern) + }); + let conservative_vk = conservative + .as_ref() + .map(RasterizationConservativeState::to_vk); + + RasterizationStateExtensionsVk { + line_vk, + conservative_vk, + } + } +} + +pub(crate) struct RasterizationStateExtensionsVk { + pub(crate) line_vk: Option>, + pub(crate) conservative_vk: + Option>, } /// The values to use for depth biasing. @@ -526,3 +658,104 @@ pub struct LineStipple { /// The bit pattern used in stippled line rasterization. pub pattern: u16, } + +/// The state in a graphics pipeline describing how the conservative rasterization mode should +/// behave. +#[derive(Clone, Debug)] +pub struct RasterizationConservativeState { + /// Sets the conservative rasterization mode. + /// + /// The default value is [`ConservativeRasterizationMode::Disabled`]. + pub mode: ConservativeRasterizationMode, + + /// The extra size in pixels to increase the generating primitive during conservative + /// rasterization. If the mode is set to anything other than + /// [`ConservativeRasterizationMode::Overestimate`] this value is ignored. + /// + /// The default value is 0.0. + pub overestimation_size: f32, + + pub _ne: crate::NonExhaustive, +} + +impl Default for RasterizationConservativeState { + #[inline] + fn default() -> Self { + Self { + mode: ConservativeRasterizationMode::Disabled, + overestimation_size: 0.0, + _ne: crate::NonExhaustive(()), + } + } +} + +impl RasterizationConservativeState { + pub(crate) fn validate(&self, device: &Device) -> Result<(), Box> { + let &Self { + mode, + overestimation_size, + _ne: _, + } = self; + + let properties = device.physical_device().properties(); + + mode.validate_device(device).map_err(|err| { + err.add_context("mode").set_vuids(&[ + "VUID-VkPipelineRasterizationConservativeStateCreateInfoEXT-conservativeRasterizationMode-parameter", + ]) + })?; + + if overestimation_size < 0.0 + || overestimation_size > properties.max_extra_primitive_overestimation_size.unwrap() + { + return Err(Box::new(ValidationError { + context: "overestimation size".into(), + problem: "the overestimation size is not in the range of 0.0 to `max_extra_primitive_overestimation_size` inclusive".into(), + vuids: &[ + "VUID-VkPipelineRasterizationConservativeStateCreateInfoEXT-extraPrimitiveOverestimationSize-01769", + ], + ..Default::default() + })); + } + + Ok(()) + } + + pub(crate) fn to_vk( + &self, + ) -> ash::vk::PipelineRasterizationConservativeStateCreateInfoEXT<'static> { + let &Self { + mode, + overestimation_size, + _ne: _, + } = self; + + ash::vk::PipelineRasterizationConservativeStateCreateInfoEXT::default() + .flags(ash::vk::PipelineRasterizationConservativeStateCreateFlagsEXT::empty()) + .conservative_rasterization_mode(mode.into()) + .extra_primitive_overestimation_size(overestimation_size) + } +} + +vulkan_enum! { + #[non_exhaustive] + + /// Describes how fragments will be generated based on how much is covered by a primitive. + ConservativeRasterizationMode = ConservativeRasterizationModeEXT(i32); + + /// Conservative rasterization is disabled and rasterization proceeds as normal. + Disabled = DISABLED, + + /// Fragments will be generated if any part of a primitive touches a pixel. + Overestimate = OVERESTIMATE, + + /// Fragments will be generated only if a primitive completely covers a pixel. + Underestimate = UNDERESTIMATE, +} + +impl Default for ConservativeRasterizationMode { + #[inline] + fn default() -> ConservativeRasterizationMode { + ConservativeRasterizationMode::Disabled + } +} diff --git a/vulkano/src/pipeline/graphics/subpass.rs b/vulkano/src/pipeline/graphics/subpass.rs index 7eaba878..a85717ed 100644 --- a/vulkano/src/pipeline/graphics/subpass.rs +++ b/vulkano/src/pipeline/graphics/subpass.rs @@ -6,6 +6,7 @@ use crate::{ render_pass::Subpass, Requires, RequiresAllOf, RequiresOneOf, ValidationError, }; +use smallvec::SmallVec; /// Selects the type of subpass that a graphics pipeline is created for. #[derive(Clone, Debug)] @@ -14,6 +15,27 @@ pub enum PipelineSubpassType { BeginRendering(PipelineRenderingCreateInfo), } +impl PipelineSubpassType { + pub(crate) fn to_vk_rendering<'a>( + &self, + fields1_vk: &'a PipelineRenderingCreateInfoFields1Vk, + ) -> ash::vk::PipelineRenderingCreateInfo<'a> { + match self { + PipelineSubpassType::BeginRenderPass(_) => unreachable!(), + PipelineSubpassType::BeginRendering(rendering_info) => rendering_info.to_vk(fields1_vk), + } + } + + pub(crate) fn to_vk_rendering_fields1(&self) -> Option { + match self { + PipelineSubpassType::BeginRenderPass(_) => None, + PipelineSubpassType::BeginRendering(rendering_info) => { + Some(rendering_info.to_vk_fields1()) + } + } + } +} + impl From for PipelineSubpassType { #[inline] fn from(val: Subpass) -> Self { @@ -310,4 +332,46 @@ impl PipelineRenderingCreateInfo { Ok(()) } + + pub(crate) fn to_vk<'a>( + &self, + fields1_vk: &'a PipelineRenderingCreateInfoFields1Vk, + ) -> ash::vk::PipelineRenderingCreateInfo<'a> { + let &Self { + view_mask, + color_attachment_formats: _, + depth_attachment_format, + stencil_attachment_format, + _ne: _, + } = self; + let PipelineRenderingCreateInfoFields1Vk { + color_attachment_formats_vk, + } = fields1_vk; + + ash::vk::PipelineRenderingCreateInfo::default() + .view_mask(view_mask) + .color_attachment_formats(color_attachment_formats_vk) + .depth_attachment_format( + depth_attachment_format.map_or(ash::vk::Format::UNDEFINED, Into::into), + ) + .stencil_attachment_format( + stencil_attachment_format.map_or(ash::vk::Format::UNDEFINED, Into::into), + ) + } + + pub(crate) fn to_vk_fields1(&self) -> PipelineRenderingCreateInfoFields1Vk { + let color_attachment_formats_vk = self + .color_attachment_formats + .iter() + .map(|format| format.map_or(ash::vk::Format::UNDEFINED, Into::into)) + .collect(); + + PipelineRenderingCreateInfoFields1Vk { + color_attachment_formats_vk, + } + } +} + +pub(crate) struct PipelineRenderingCreateInfoFields1Vk { + pub(crate) color_attachment_formats_vk: SmallVec<[ash::vk::Format; 4]>, } diff --git a/vulkano/src/pipeline/graphics/tessellation.rs b/vulkano/src/pipeline/graphics/tessellation.rs index 1d3ce50f..52142ff9 100644 --- a/vulkano/src/pipeline/graphics/tessellation.rs +++ b/vulkano/src/pipeline/graphics/tessellation.rs @@ -7,7 +7,7 @@ use crate::{ /// The state in a graphics pipeline describing the tessellation shader execution of a graphics /// pipeline. -#[derive(Clone, Copy, Debug)] +#[derive(Clone, Debug)] pub struct TessellationState { /// The number of patch control points to use. /// @@ -104,6 +104,49 @@ impl TessellationState { Ok(()) } + + pub(crate) fn to_vk<'a>( + &self, + extensions_vk: &'a mut TessellationStateExtensionsVk, + ) -> ash::vk::PipelineTessellationStateCreateInfo<'a> { + let &Self { + patch_control_points, + domain_origin: _, + _ne: _, + } = self; + + let mut val_vk = ash::vk::PipelineTessellationStateCreateInfo::default() + .flags(ash::vk::PipelineTessellationStateCreateFlags::empty()) + .patch_control_points(patch_control_points); + + let TessellationStateExtensionsVk { domain_origin_vk } = extensions_vk; + + if let Some(next) = domain_origin_vk { + val_vk = val_vk.push_next(next); + } + + val_vk + } + + pub(crate) fn to_vk_extensions(&self) -> TessellationStateExtensionsVk { + let &Self { + patch_control_points: _, + domain_origin, + _ne: _, + } = self; + + let domain_origin_vk = (domain_origin != TessellationDomainOrigin::default()).then(|| { + ash::vk::PipelineTessellationDomainOriginStateCreateInfo::default() + .domain_origin(domain_origin.into()) + }); + + TessellationStateExtensionsVk { domain_origin_vk } + } +} + +pub(crate) struct TessellationStateExtensionsVk { + pub(crate) domain_origin_vk: + Option>, } vulkan_enum! { diff --git a/vulkano/src/pipeline/graphics/vertex_input/mod.rs b/vulkano/src/pipeline/graphics/vertex_input/mod.rs index dce36b99..e907e32d 100644 --- a/vulkano/src/pipeline/graphics/vertex_input/mod.rs +++ b/vulkano/src/pipeline/graphics/vertex_input/mod.rs @@ -105,6 +105,7 @@ use crate::{ DeviceSize, Requires, RequiresAllOf, RequiresOneOf, ValidationError, }; use ahash::HashMap; +use smallvec::SmallVec; mod buffers; mod collection; @@ -125,6 +126,13 @@ pub struct VertexInputState { pub _ne: crate::NonExhaustive, } +impl Default for VertexInputState { + #[inline] + fn default() -> Self { + Self::new() + } +} + impl VertexInputState { /// Constructs a new `VertexInputState` with no bindings or attributes. #[inline] @@ -443,13 +451,89 @@ impl VertexInputState { Ok(()) } + + pub(crate) fn to_vk<'a>( + &self, + fields1_vk: &'a VertexInputStateFields1Vk, + extensions_vk: &'a mut VertexInputStateExtensionsVk<'_>, + ) -> ash::vk::PipelineVertexInputStateCreateInfo<'a> { + let VertexInputStateFields1Vk { + bindings_vk, + attributes_vk, + binding_divisors_vk: _, + } = fields1_vk; + + let mut val_vk = ash::vk::PipelineVertexInputStateCreateInfo::default() + .flags(ash::vk::PipelineVertexInputStateCreateFlags::empty()) + .vertex_binding_descriptions(bindings_vk) + .vertex_attribute_descriptions(attributes_vk); + + let VertexInputStateExtensionsVk { divisor_vk } = extensions_vk; + + if let Some(next) = divisor_vk { + val_vk = val_vk.push_next(next); + } + + val_vk + } + + pub(crate) fn to_vk_extensions<'a>( + &self, + fields1_vk: &'a VertexInputStateFields1Vk, + ) -> VertexInputStateExtensionsVk<'a> { + let VertexInputStateFields1Vk { + bindings_vk: _, + attributes_vk: _, + binding_divisors_vk, + } = fields1_vk; + + let divisor_vk = (!binding_divisors_vk.is_empty()).then(|| { + ash::vk::PipelineVertexInputDivisorStateCreateInfoEXT::default() + .vertex_binding_divisors(binding_divisors_vk) + }); + + VertexInputStateExtensionsVk { divisor_vk } + } + + pub(crate) fn to_vk_fields1(&self) -> VertexInputStateFields1Vk { + let Self { + bindings, + attributes, + _ne: _, + } = self; + + let mut bindings_vk = SmallVec::with_capacity(bindings.len()); + let mut binding_divisors_vk = SmallVec::new(); + + for (&binding, binding_desc) in bindings { + bindings_vk.push(binding_desc.to_vk(binding)); + + if let Some(divisor_vk) = binding_desc.to_vk_divisor(binding) { + binding_divisors_vk.push(divisor_vk); + } + } + + let attributes_vk = attributes + .iter() + .map(|(&location, attribute_desc)| attribute_desc.to_vk(location)) + .collect(); + + VertexInputStateFields1Vk { + bindings_vk, + attributes_vk, + binding_divisors_vk, + } + } } -impl Default for VertexInputState { - #[inline] - fn default() -> Self { - Self::new() - } +pub(crate) struct VertexInputStateExtensionsVk<'a> { + pub(crate) divisor_vk: Option>, +} + +pub(crate) struct VertexInputStateFields1Vk { + pub(crate) bindings_vk: SmallVec<[ash::vk::VertexInputBindingDescription; 8]>, + pub(crate) attributes_vk: SmallVec<[ash::vk::VertexInputAttributeDescription; 8]>, + pub(crate) binding_divisors_vk: SmallVec<[ash::vk::VertexInputBindingDivisorDescriptionKHR; 8]>, } /// Describes a single vertex buffer binding. @@ -579,10 +663,58 @@ impl VertexInputBindingDescription { Ok(()) } + + pub(crate) fn to_vk2( + &self, + binding_vk: u32, + ) -> ash::vk::VertexInputBindingDescription2EXT<'static> { + let &Self { + stride, + input_rate, + _ne: _, + } = self; + + let (input_rate_vk, divisor_vk) = input_rate.to_vk(); + + ash::vk::VertexInputBindingDescription2EXT::default() + .binding(binding_vk) + .stride(stride) + .input_rate(input_rate_vk) + .divisor(divisor_vk) + } + + pub(crate) fn to_vk(&self, binding_vk: u32) -> ash::vk::VertexInputBindingDescription { + let &Self { + stride, + input_rate, + _ne: _, + } = self; + + let (input_rate_vk, _) = input_rate.to_vk(); + + ash::vk::VertexInputBindingDescription::default() + .binding(binding_vk) + .stride(stride) + .input_rate(input_rate_vk) + } + + pub(crate) fn to_vk_divisor( + &self, + binding_vk: u32, + ) -> Option { + match self.input_rate { + VertexInputRate::Instance { divisor } if divisor != 1 => Some( + ash::vk::VertexInputBindingDivisorDescriptionKHR::default() + .binding(binding_vk) + .divisor(divisor), + ), + _ => None, + } + } } /// Describes a single vertex buffer attribute mapping. -#[derive(Clone, Copy, Debug)] +#[derive(Clone, Debug)] pub struct VertexInputAttributeDescription { /// The vertex buffer binding number that this attribute should take its data from. /// @@ -685,6 +817,39 @@ impl VertexInputAttributeDescription { Ok(()) } + + pub(crate) fn to_vk2( + &self, + location_vk: u32, + ) -> ash::vk::VertexInputAttributeDescription2EXT<'static> { + let &Self { + binding, + format, + offset, + _ne: _, + } = self; + + ash::vk::VertexInputAttributeDescription2EXT::default() + .location(location_vk) + .binding(binding) + .format(format.into()) + .offset(offset) + } + + pub(crate) fn to_vk(&self, location_vk: u32) -> ash::vk::VertexInputAttributeDescription { + let &Self { + binding, + format, + offset, + _ne: _, + } = self; + + ash::vk::VertexInputAttributeDescription::default() + .location(location_vk) + .binding(binding) + .format(format.into()) + .offset(offset) + } } /// How the vertex source should be unrolled. @@ -707,12 +872,14 @@ pub enum VertexInputRate { Instance { divisor: u32 }, } -impl From for ash::vk::VertexInputRate { - #[inline] - fn from(val: VertexInputRate) -> Self { - match val { - VertexInputRate::Vertex => ash::vk::VertexInputRate::VERTEX, - VertexInputRate::Instance { .. } => ash::vk::VertexInputRate::INSTANCE, +impl VertexInputRate { + #[allow(clippy::trivially_copy_pass_by_ref, clippy::wrong_self_convention)] + #[doc(hidden)] + pub fn to_vk(&self) -> (ash::vk::VertexInputRate, u32) { + match *self { + // VUID-VkVertexInputBindingDescription2EXT-divisor-06227 + VertexInputRate::Vertex => (ash::vk::VertexInputRate::VERTEX, 1), + VertexInputRate::Instance { divisor } => (ash::vk::VertexInputRate::INSTANCE, divisor), } } } diff --git a/vulkano/src/pipeline/graphics/viewport.rs b/vulkano/src/pipeline/graphics/viewport.rs index 27baf3f3..ab12c71b 100644 --- a/vulkano/src/pipeline/graphics/viewport.rs +++ b/vulkano/src/pipeline/graphics/viewport.rs @@ -225,6 +225,50 @@ impl ViewportState { Ok(()) } + + pub(crate) fn to_vk<'a>( + &self, + fields1_vk: &'a ViewportStateFields1Vk, + ) -> ash::vk::PipelineViewportStateCreateInfo<'a> { + let ViewportStateFields1Vk { + viewports_vk, + scissors_vk, + } = fields1_vk; + + let mut val_vk = ash::vk::PipelineViewportStateCreateInfo::default() + .flags(ash::vk::PipelineViewportStateCreateFlags::empty()); + + if !viewports_vk.is_empty() { + val_vk = val_vk.viewports(viewports_vk); + } + + if !scissors_vk.is_empty() { + val_vk = val_vk.scissors(scissors_vk); + } + + val_vk + } + + pub(crate) fn to_vk_fields1(&self) -> ViewportStateFields1Vk { + let Self { + viewports, + scissors, + _ne: _, + } = self; + + let viewports_vk = viewports.iter().map(Viewport::to_vk).collect(); + let scissors_vk = scissors.iter().map(Scissor::to_vk).collect(); + + ViewportStateFields1Vk { + viewports_vk, + scissors_vk, + } + } +} + +pub(crate) struct ViewportStateFields1Vk { + pub(crate) viewports_vk: SmallVec<[ash::vk::Viewport; 2]>, + pub(crate) scissors_vk: SmallVec<[ash::vk::Rect2D; 2]>, } /// State of a single viewport. @@ -397,18 +441,22 @@ impl Viewport { Ok(()) } -} -impl From<&Viewport> for ash::vk::Viewport { - #[inline] - fn from(val: &Viewport) -> Self { + #[doc(hidden)] + pub fn to_vk(&self) -> ash::vk::Viewport { + let &Self { + offset, + extent, + ref depth_range, + } = self; + ash::vk::Viewport { - x: val.offset[0], - y: val.offset[1], - width: val.extent[0], - height: val.extent[1], - min_depth: *val.depth_range.start(), - max_depth: *val.depth_range.end(), + x: offset[0], + y: offset[1], + width: extent[0], + height: extent[1], + min_depth: *depth_range.start(), + max_depth: *depth_range.end(), } } } @@ -445,30 +493,21 @@ impl Scissor { pub fn irrelevant() -> Scissor { Self::default() } -} -impl From<&Scissor> for ash::vk::Rect2D { - #[inline] - fn from(val: &Scissor) -> Self { + #[allow(clippy::wrong_self_convention)] + #[doc(hidden)] + pub fn to_vk(&self) -> ash::vk::Rect2D { + let &Self { offset, extent } = self; + ash::vk::Rect2D { offset: ash::vk::Offset2D { - x: val.offset[0] as i32, - y: val.offset[1] as i32, + x: offset[0] as i32, + y: offset[1] as i32, }, extent: ash::vk::Extent2D { - width: val.extent[0], - height: val.extent[1], + width: extent[0], + height: extent[1], }, } } } - -impl From for Scissor { - #[inline] - fn from(val: ash::vk::Rect2D) -> Self { - Scissor { - offset: [val.offset.x as u32, val.offset.y as u32], - extent: [val.extent.width, val.extent.height], - } - } -} diff --git a/vulkano/src/pipeline/layout.rs b/vulkano/src/pipeline/layout.rs index b94c3e08..debf7d46 100644 --- a/vulkano/src/pipeline/layout.rs +++ b/vulkano/src/pipeline/layout.rs @@ -123,31 +123,8 @@ impl PipelineLayout { device: Arc, create_info: PipelineLayoutCreateInfo, ) -> Result, VulkanError> { - let &PipelineLayoutCreateInfo { - flags, - ref set_layouts, - ref push_constant_ranges, - _ne: _, - } = &create_info; - - let set_layouts_vk: SmallVec<[_; 4]> = set_layouts.iter().map(|l| l.handle()).collect(); - let push_constant_ranges_vk: SmallVec<[_; 4]> = push_constant_ranges - .iter() - .map(|range| ash::vk::PushConstantRange { - stage_flags: range.stages.into(), - offset: range.offset, - size: range.size, - }) - .collect(); - - let create_info_vk = ash::vk::PipelineLayoutCreateInfo { - flags: flags.into(), - set_layout_count: set_layouts_vk.len() as u32, - p_set_layouts: set_layouts_vk.as_ptr(), - push_constant_range_count: push_constant_ranges_vk.len() as u32, - p_push_constant_ranges: push_constant_ranges_vk.as_ptr(), - ..Default::default() - }; + let create_info_fields1_vk = create_info.to_vk_fields1(); + let create_info_vk = create_info.to_vk(&create_info_fields1_vk); let handle = { let fns = device.fns(); @@ -906,6 +883,51 @@ impl PipelineLayoutCreateInfo { Ok(()) } + + pub(crate) fn to_vk<'a>( + &self, + fields1_vk: &'a PipelineLayoutCreateInfoFields1Vk, + ) -> ash::vk::PipelineLayoutCreateInfo<'a> { + let &Self { + flags, + set_layouts: _, + push_constant_ranges: _, + _ne: _, + } = self; + let PipelineLayoutCreateInfoFields1Vk { + set_layouts_vk, + push_constant_ranges_vk, + } = fields1_vk; + + ash::vk::PipelineLayoutCreateInfo::default() + .flags(flags.into()) + .set_layouts(set_layouts_vk) + .push_constant_ranges(push_constant_ranges_vk) + } + + pub(crate) fn to_vk_fields1(&self) -> PipelineLayoutCreateInfoFields1Vk { + let &Self { + ref set_layouts, + ref push_constant_ranges, + .. + } = self; + + let set_layouts_vk = set_layouts.iter().map(|l| l.handle()).collect(); + let push_constant_ranges_vk = push_constant_ranges + .iter() + .map(|range| range.to_vk()) + .collect(); + + PipelineLayoutCreateInfoFields1Vk { + set_layouts_vk, + push_constant_ranges_vk, + } + } +} + +pub(crate) struct PipelineLayoutCreateInfoFields1Vk { + pub(crate) set_layouts_vk: SmallVec<[ash::vk::DescriptorSetLayout; 4]>, + pub(crate) push_constant_ranges_vk: SmallVec<[ash::vk::PushConstantRange; 4]>, } vulkan_bitflags! { @@ -1030,6 +1052,21 @@ impl PushConstantRange { Ok(()) } + + #[allow(clippy::wrong_self_convention)] + pub(crate) fn to_vk(&self) -> ash::vk::PushConstantRange { + let &Self { + stages, + offset, + size, + } = self; + + ash::vk::PushConstantRange { + stage_flags: stages.into(), + offset, + size, + } + } } /// Parameters to create a new `PipelineLayout` as well as its accompanying `DescriptorSetLayout` diff --git a/vulkano/src/pipeline/shader/mod.rs b/vulkano/src/pipeline/shader/mod.rs index 5a1423ae..532694d2 100644 --- a/vulkano/src/pipeline/shader/mod.rs +++ b/vulkano/src/pipeline/shader/mod.rs @@ -5,8 +5,9 @@ use crate::{ spirv::{BuiltIn, Decoration, ExecutionMode, Id, Instruction}, EntryPoint, ShaderStage, }, - Requires, RequiresAllOf, RequiresOneOf, ValidationError, + Requires, RequiresAllOf, RequiresOneOf, ValidationError, VulkanObject, }; +use std::ffi::CString; pub(crate) mod inout_interface; pub(crate) mod validate_runtime; @@ -494,6 +495,137 @@ impl PipelineShaderStageCreateInfo { Ok(()) } + + pub(crate) fn to_vk<'a>( + &self, + fields1_vk: &'a PipelineShaderStageCreateInfoFields1Vk<'_>, + extensions_vk: &'a mut PipelineShaderStageCreateInfoExtensionsVk, + ) -> ash::vk::PipelineShaderStageCreateInfo<'a> { + let &Self { + flags, + ref entry_point, + required_subgroup_size: _, + _ne: _, + } = self; + let PipelineShaderStageCreateInfoFields1Vk { + name_vk, + specialization_info_vk, + } = fields1_vk; + + let entry_point_info = entry_point.info(); + let stage = ShaderStage::from(entry_point_info.execution_model); + + let mut val_vk = ash::vk::PipelineShaderStageCreateInfo::default() + .flags(flags.into()) + .stage(stage.into()) + .module(entry_point.module().handle()) + .name(name_vk); + + if specialization_info_vk.data_size != 0 { + val_vk = val_vk.specialization_info(specialization_info_vk) + } + + let PipelineShaderStageCreateInfoExtensionsVk { + required_subgroup_size_vk, + } = extensions_vk; + + if let Some(next) = required_subgroup_size_vk { + val_vk = val_vk.push_next(next); + } + + val_vk + } + + pub(crate) fn to_vk_extensions(&self) -> PipelineShaderStageCreateInfoExtensionsVk { + let &Self { + flags: _, + entry_point: _, + required_subgroup_size, + _ne: _, + } = self; + + let required_subgroup_size_vk = required_subgroup_size.map(|required_subgroup_size| { + ash::vk::PipelineShaderStageRequiredSubgroupSizeCreateInfo::default() + .required_subgroup_size(required_subgroup_size) + }); + + PipelineShaderStageCreateInfoExtensionsVk { + required_subgroup_size_vk, + } + } + + pub(crate) fn to_vk_fields1<'a>( + &self, + fields2_vk: &'a PipelineShaderStageCreateInfoFields2Vk, + ) -> PipelineShaderStageCreateInfoFields1Vk<'a> { + let &Self { + flags: _, + ref entry_point, + required_subgroup_size: _, + _ne: _, + } = self; + let PipelineShaderStageCreateInfoFields2Vk { + specialization_map_entries_vk, + specialization_data_vk, + } = fields2_vk; + + let entry_point_info = entry_point.info(); + + PipelineShaderStageCreateInfoFields1Vk { + name_vk: CString::new(entry_point_info.name.as_str()).unwrap(), + specialization_info_vk: ash::vk::SpecializationInfo::default() + .map_entries(specialization_map_entries_vk) + .data(specialization_data_vk), + } + } + + pub(crate) fn to_vk_fields2(&self) -> PipelineShaderStageCreateInfoFields2Vk { + let &Self { + flags: _, + ref entry_point, + required_subgroup_size: _, + _ne: _, + } = self; + + let mut specialization_data_vk: Vec = Vec::new(); + let specialization_map_entries_vk = entry_point + .module() + .specialization_info() + .iter() + .map(|(&constant_id, value)| { + let data = value.as_bytes(); + let offset = specialization_data_vk.len() as u32; + let size = data.len(); + specialization_data_vk.extend(data); + + ash::vk::SpecializationMapEntry { + constant_id, + offset, + size, + } + }) + .collect(); + + PipelineShaderStageCreateInfoFields2Vk { + specialization_map_entries_vk, + specialization_data_vk, + } + } +} + +pub(crate) struct PipelineShaderStageCreateInfoExtensionsVk { + pub(crate) required_subgroup_size_vk: + Option>, +} + +pub(crate) struct PipelineShaderStageCreateInfoFields1Vk<'a> { + pub(crate) name_vk: CString, + pub(crate) specialization_info_vk: ash::vk::SpecializationInfo<'a>, +} + +pub(crate) struct PipelineShaderStageCreateInfoFields2Vk { + pub(crate) specialization_map_entries_vk: Vec, + pub(crate) specialization_data_vk: Vec, } vulkan_bitflags! { diff --git a/vulkano/src/query.rs b/vulkano/src/query.rs index bee4c763..8b4d3be1 100644 --- a/vulkano/src/query.rs +++ b/vulkano/src/query.rs @@ -60,20 +60,7 @@ impl QueryPool { device: Arc, create_info: QueryPoolCreateInfo, ) -> Result, VulkanError> { - let &QueryPoolCreateInfo { - query_type, - query_count, - pipeline_statistics, - _ne: _, - } = &create_info; - - let create_info_vk = ash::vk::QueryPoolCreateInfo { - flags: ash::vk::QueryPoolCreateFlags::empty(), - query_type: query_type.into(), - query_count, - pipeline_statistics: pipeline_statistics.into(), - ..Default::default() - }; + let create_info_vk = create_info.to_vk(); let handle = unsafe { let fns = device.fns(); @@ -524,6 +511,21 @@ impl QueryPoolCreateInfo { Ok(()) } + + pub(crate) fn to_vk(&self) -> ash::vk::QueryPoolCreateInfo<'static> { + let &Self { + query_type, + query_count, + pipeline_statistics, + _ne: _, + } = self; + + ash::vk::QueryPoolCreateInfo::default() + .flags(ash::vk::QueryPoolCreateFlags::empty()) + .query_type(query_type.into()) + .query_count(query_count) + .pipeline_statistics(pipeline_statistics.into()) + } } vulkan_enum! { diff --git a/vulkano/src/render_pass/create.rs b/vulkano/src/render_pass/create.rs deleted file mode 100644 index 2b202412..00000000 --- a/vulkano/src/render_pass/create.rs +++ /dev/null @@ -1,892 +0,0 @@ -use super::{AttachmentDescription, AttachmentReference, RenderPass, RenderPassCreateInfo}; -use crate::{ - device::Device, - render_pass::{SubpassDependency, SubpassDescription}, - Version, VulkanError, VulkanObject, -}; -use smallvec::SmallVec; -use std::{mem::MaybeUninit, ptr}; - -impl RenderPass { - pub(super) unsafe fn create_v2( - device: &Device, - create_info: &RenderPassCreateInfo, - ) -> Result { - let &RenderPassCreateInfo { - flags, - ref attachments, - ref subpasses, - ref dependencies, - ref correlated_view_masks, - _ne: _, - } = create_info; - - struct PerAttachment { - stencil_layout_vk: Option>, - } - - let (mut attachments_vk, mut per_attachment_vk): (SmallVec<[_; 4]>, SmallVec<[_; 4]>) = - attachments - .iter() - .map(|attachment| { - let &AttachmentDescription { - flags, - format, - samples, - load_op, - store_op, - initial_layout, - final_layout, - stencil_load_op, - stencil_store_op, - stencil_initial_layout, - stencil_final_layout, - _ne: _, - } = attachment; - - ( - ash::vk::AttachmentDescription2 { - flags: flags.into(), - format: format.into(), - samples: samples.into(), - load_op: load_op.into(), - store_op: store_op.into(), - stencil_load_op: stencil_load_op.unwrap_or(load_op).into(), - stencil_store_op: stencil_store_op.unwrap_or(store_op).into(), - initial_layout: initial_layout.into(), - final_layout: final_layout.into(), - ..Default::default() - }, - PerAttachment { - stencil_layout_vk: stencil_initial_layout - .zip(stencil_final_layout) - .map(|(stencil_initial_layout, stencil_final_layout)| { - ash::vk::AttachmentDescriptionStencilLayout { - stencil_initial_layout: stencil_initial_layout.into(), - stencil_final_layout: stencil_final_layout.into(), - ..Default::default() - } - }), - }, - ) - }) - .unzip(); - - for (attachment_vk, per_attachment_vk) in - attachments_vk.iter_mut().zip(per_attachment_vk.iter_mut()) - { - let PerAttachment { stencil_layout_vk } = per_attachment_vk; - - if let Some(next) = stencil_layout_vk { - next.p_next = attachment_vk.p_next.cast_mut(); - attachment_vk.p_next = <*const _>::cast(next); - } - } - - struct PerSubpassDescriptionVk { - input_attachments_vk: SmallVec<[ash::vk::AttachmentReference2<'static>; 4]>, - per_input_attachments_vk: SmallVec<[PerAttachmentReferenceVk; 4]>, - color_attachments_vk: SmallVec<[ash::vk::AttachmentReference2<'static>; 4]>, - resolve_attachments_vk: SmallVec<[ash::vk::AttachmentReference2<'static>; 4]>, - depth_stencil_attachment_vk: ash::vk::AttachmentReference2<'static>, - per_depth_stencil_attachment_vk: PerAttachmentReferenceVk, - depth_stencil_resolve_attachment_vk: ash::vk::AttachmentReference2<'static>, - per_depth_stencil_resolve_attachment_vk: PerAttachmentReferenceVk, - depth_stencil_resolve_vk: - Option>, - } - - #[derive(Default)] - struct PerAttachmentReferenceVk { - stencil_layout_vk: Option>, - } - - let (mut subpasses_vk, mut per_subpass_vk): (SmallVec<[_; 4]>, SmallVec<[_; 4]>) = - subpasses - .iter() - .map(|subpass| { - let &SubpassDescription { - flags, - view_mask, - ref input_attachments, - ref color_attachments, - ref color_resolve_attachments, - ref depth_stencil_attachment, - ref depth_stencil_resolve_attachment, - depth_resolve_mode, - stencil_resolve_mode, - ref preserve_attachments, - _ne: _, - } = subpass; - - let (input_attachments_vk, per_input_attachments_vk) = input_attachments - .iter() - .map(|input_attachment| { - if let Some(input_attachment) = input_attachment { - let &AttachmentReference { - attachment, - layout, - stencil_layout, - aspects, - _ne: _, - } = input_attachment; - - ( - ash::vk::AttachmentReference2 { - attachment, - layout: layout.into(), - aspect_mask: aspects.into(), - ..Default::default() - }, - PerAttachmentReferenceVk { - stencil_layout_vk: stencil_layout.map(|stencil_layout| { - ash::vk::AttachmentReferenceStencilLayout { - stencil_layout: stencil_layout.into(), - ..Default::default() - } - }), - }, - ) - } else { - ( - ash::vk::AttachmentReference2 { - attachment: ash::vk::ATTACHMENT_UNUSED, - ..Default::default() - }, - PerAttachmentReferenceVk::default(), - ) - } - }) - .unzip(); - - let color_attachments_vk = color_attachments - .iter() - .map(|color_attachment| { - if let Some(color_attachment) = color_attachment { - let &AttachmentReference { - attachment, - layout, - stencil_layout: _, - aspects: _, - _ne: _, - } = color_attachment; - - ash::vk::AttachmentReference2 { - attachment, - layout: layout.into(), - ..Default::default() - } - } else { - ash::vk::AttachmentReference2 { - attachment: ash::vk::ATTACHMENT_UNUSED, - ..Default::default() - } - } - }) - .collect(); - - let resolve_attachments_vk = color_resolve_attachments - .iter() - .map(|color_resolve_attachment| { - if let Some(color_resolve_attachment) = color_resolve_attachment { - let &AttachmentReference { - attachment, - layout, - stencil_layout: _, - aspects: _, - _ne: _, - } = color_resolve_attachment; - - ash::vk::AttachmentReference2 { - attachment, - layout: layout.into(), - ..Default::default() - } - } else { - ash::vk::AttachmentReference2 { - attachment: ash::vk::ATTACHMENT_UNUSED, - ..Default::default() - } - } - }) - .collect(); - - let (depth_stencil_attachment_vk, per_depth_stencil_attachment_vk) = - if let Some(depth_stencil_attachment) = depth_stencil_attachment { - let &AttachmentReference { - attachment, - layout, - stencil_layout, - aspects: _, - _ne: _, - } = depth_stencil_attachment; - - ( - ash::vk::AttachmentReference2 { - attachment, - layout: layout.into(), - ..Default::default() - }, - PerAttachmentReferenceVk { - stencil_layout_vk: stencil_layout.map(|stencil_layout| { - ash::vk::AttachmentReferenceStencilLayout { - stencil_layout: stencil_layout.into(), - ..Default::default() - } - }), - }, - ) - } else { - ( - ash::vk::AttachmentReference2 { - attachment: ash::vk::ATTACHMENT_UNUSED, - ..Default::default() - }, - PerAttachmentReferenceVk::default(), - ) - }; - - let ( - depth_stencil_resolve_attachment_vk, - per_depth_stencil_resolve_attachment_vk, - ) = if let Some(depth_stencil_resolve_attachment) = - depth_stencil_resolve_attachment - { - let &AttachmentReference { - attachment, - layout, - stencil_layout, - aspects: _, - _ne: _, - } = depth_stencil_resolve_attachment; - - ( - ash::vk::AttachmentReference2 { - attachment, - layout: layout.into(), - ..Default::default() - }, - PerAttachmentReferenceVk { - stencil_layout_vk: stencil_layout.map(|stencil_layout| { - ash::vk::AttachmentReferenceStencilLayout { - stencil_layout: stencil_layout.into(), - ..Default::default() - } - }), - }, - ) - } else { - ( - ash::vk::AttachmentReference2 { - attachment: ash::vk::ATTACHMENT_UNUSED, - ..Default::default() - }, - PerAttachmentReferenceVk::default(), - ) - }; - - let depth_stencil_resolve_vk = depth_stencil_resolve_attachment - .is_some() - .then_some(ash::vk::SubpassDescriptionDepthStencilResolve { - depth_resolve_mode: depth_resolve_mode - .map_or(ash::vk::ResolveModeFlags::NONE, Into::into), - stencil_resolve_mode: stencil_resolve_mode - .map_or(ash::vk::ResolveModeFlags::NONE, Into::into), - p_depth_stencil_resolve_attachment: ptr::null(), - ..Default::default() - }); - - ( - ash::vk::SubpassDescription2 { - flags: flags.into(), - pipeline_bind_point: ash::vk::PipelineBindPoint::GRAPHICS, // TODO: any need to make this user-specifiable? - view_mask, - input_attachment_count: 0, - p_input_attachments: ptr::null(), - color_attachment_count: 0, - p_color_attachments: ptr::null(), - p_resolve_attachments: ptr::null(), - p_depth_stencil_attachment: ptr::null(), - preserve_attachment_count: preserve_attachments.len() as u32, - p_preserve_attachments: if preserve_attachments.is_empty() { - ptr::null() - } else { - preserve_attachments.as_ptr() - }, - ..Default::default() - }, - PerSubpassDescriptionVk { - input_attachments_vk, - per_input_attachments_vk, - color_attachments_vk, - resolve_attachments_vk, - depth_stencil_attachment_vk, - per_depth_stencil_attachment_vk, - depth_stencil_resolve_attachment_vk, - per_depth_stencil_resolve_attachment_vk, - depth_stencil_resolve_vk, - }, - ) - }) - .unzip(); - - for (subpass_vk, per_subpass_vk) in subpasses_vk.iter_mut().zip(per_subpass_vk.iter_mut()) { - let PerSubpassDescriptionVk { - input_attachments_vk, - per_input_attachments_vk, - color_attachments_vk, - resolve_attachments_vk, - depth_stencil_attachment_vk, - per_depth_stencil_attachment_vk, - depth_stencil_resolve_attachment_vk, - per_depth_stencil_resolve_attachment_vk, - depth_stencil_resolve_vk, - } = per_subpass_vk; - - for (input_attachment_vk, per_input_attachment_vk) in input_attachments_vk - .iter_mut() - .zip(per_input_attachments_vk) - { - let PerAttachmentReferenceVk { stencil_layout_vk } = per_input_attachment_vk; - - if let Some(stencil_layout_vk) = stencil_layout_vk { - stencil_layout_vk.p_next = input_attachment_vk.p_next.cast_mut(); - input_attachment_vk.p_next = <*const _>::cast(stencil_layout_vk); - } - } - - { - let PerAttachmentReferenceVk { stencil_layout_vk } = - per_depth_stencil_attachment_vk; - - if let Some(stencil_layout_vk) = stencil_layout_vk { - stencil_layout_vk.p_next = depth_stencil_attachment_vk.p_next.cast_mut(); - depth_stencil_attachment_vk.p_next = <*const _>::cast(stencil_layout_vk); - } - } - - { - let PerAttachmentReferenceVk { stencil_layout_vk } = - per_depth_stencil_resolve_attachment_vk; - - if let Some(stencil_layout_vk) = stencil_layout_vk { - stencil_layout_vk.p_next = - depth_stencil_resolve_attachment_vk.p_next.cast_mut(); - depth_stencil_resolve_attachment_vk.p_next = - <*const _>::cast(stencil_layout_vk); - } - } - - *subpass_vk = ash::vk::SubpassDescription2 { - input_attachment_count: input_attachments_vk.len() as u32, - p_input_attachments: if input_attachments_vk.is_empty() { - ptr::null() - } else { - input_attachments_vk.as_ptr() - }, - color_attachment_count: color_attachments_vk.len() as u32, - p_color_attachments: if color_attachments_vk.is_empty() { - ptr::null() - } else { - color_attachments_vk.as_ptr() - }, - p_resolve_attachments: if resolve_attachments_vk.is_empty() { - ptr::null() - } else { - resolve_attachments_vk.as_ptr() - }, - p_depth_stencil_attachment: depth_stencil_attachment_vk, - ..*subpass_vk - }; - - if let Some(depth_stencil_resolve_vk) = depth_stencil_resolve_vk { - *depth_stencil_resolve_vk = ash::vk::SubpassDescriptionDepthStencilResolve { - p_depth_stencil_resolve_attachment: depth_stencil_resolve_attachment_vk, - ..*depth_stencil_resolve_vk - }; - - depth_stencil_resolve_vk.p_next = subpass_vk.p_next; - subpass_vk.p_next = <*const _>::cast(depth_stencil_resolve_vk); - } - } - - struct PerSubpassDependencyVk { - memory_barrier_vk: Option>, - } - - let (mut dependencies_vk, mut per_dependency_vk): (SmallVec<[_; 4]>, SmallVec<[_; 4]>) = - dependencies - .iter() - .map(|dependency| { - let &SubpassDependency { - src_subpass, - dst_subpass, - src_stages, - dst_stages, - src_access, - dst_access, - dependency_flags, - view_offset, - _ne: _, - } = dependency; - - ( - ash::vk::SubpassDependency2 { - src_subpass: src_subpass.unwrap_or(ash::vk::SUBPASS_EXTERNAL), - dst_subpass: dst_subpass.unwrap_or(ash::vk::SUBPASS_EXTERNAL), - src_stage_mask: src_stages.into(), - dst_stage_mask: dst_stages.into(), - src_access_mask: src_access.into(), - dst_access_mask: dst_access.into(), - dependency_flags: dependency_flags.into(), - // VUID-VkSubpassDependency2-dependencyFlags-03092 - view_offset, - ..Default::default() - }, - PerSubpassDependencyVk { - memory_barrier_vk: device - .enabled_features() - .synchronization2 - .then_some(ash::vk::MemoryBarrier2 { - src_stage_mask: src_stages.into(), - src_access_mask: src_access.into(), - dst_stage_mask: dst_stages.into(), - dst_access_mask: dst_access.into(), - ..Default::default() - }), - }, - ) - }) - .unzip(); - - for (dependency_vk, per_dependency_vk) in - dependencies_vk.iter_mut().zip(&mut per_dependency_vk) - { - let PerSubpassDependencyVk { memory_barrier_vk } = per_dependency_vk; - - if let Some(next) = memory_barrier_vk { - next.p_next = dependency_vk.p_next; - dependency_vk.p_next = <*const _>::cast(next); - } - } - - let create_info = ash::vk::RenderPassCreateInfo2 { - flags: flags.into(), - attachment_count: attachments_vk.len() as u32, - p_attachments: if attachments_vk.is_empty() { - ptr::null() - } else { - attachments_vk.as_ptr() - }, - subpass_count: subpasses_vk.len() as u32, - p_subpasses: if subpasses_vk.is_empty() { - ptr::null() - } else { - subpasses_vk.as_ptr() - }, - dependency_count: dependencies_vk.len() as u32, - p_dependencies: if dependencies_vk.is_empty() { - ptr::null() - } else { - dependencies_vk.as_ptr() - }, - correlated_view_mask_count: correlated_view_masks.len() as u32, - p_correlated_view_masks: correlated_view_masks.as_ptr(), - ..Default::default() - }; - - Ok({ - let fns = device.fns(); - let mut output = MaybeUninit::uninit(); - - if device.api_version() >= Version::V1_2 { - (fns.v1_2.create_render_pass2)( - device.handle(), - &create_info, - ptr::null(), - output.as_mut_ptr(), - ) - } else { - (fns.khr_create_renderpass2.create_render_pass2_khr)( - device.handle(), - &create_info, - ptr::null(), - output.as_mut_ptr(), - ) - } - .result() - .map_err(VulkanError::from)?; - - output.assume_init() - }) - } - - pub(super) unsafe fn create_v1( - device: &Device, - create_info: &RenderPassCreateInfo, - ) -> Result { - let &RenderPassCreateInfo { - flags, - ref attachments, - ref subpasses, - ref dependencies, - ref correlated_view_masks, - _ne: _, - } = create_info; - - let attachments_vk = attachments - .iter() - .map(|attachment| { - let &AttachmentDescription { - flags, - format, - samples, - load_op, - store_op, - initial_layout, - final_layout, - stencil_load_op, - stencil_store_op, - stencil_initial_layout: _, - stencil_final_layout: _, - _ne: _, - } = attachment; - - ash::vk::AttachmentDescription { - flags: flags.into(), - format: format.into(), - samples: samples.into(), - load_op: load_op.into(), - store_op: store_op.into(), - stencil_load_op: stencil_load_op.unwrap_or(load_op).into(), - stencil_store_op: stencil_store_op.unwrap_or(store_op).into(), - initial_layout: initial_layout.into(), - final_layout: final_layout.into(), - } - }) - .collect::>(); - - struct PerSubpassDescriptionVk { - input_attachments_vk: SmallVec<[ash::vk::AttachmentReference; 4]>, - color_attachments_vk: SmallVec<[ash::vk::AttachmentReference; 4]>, - resolve_attachments_vk: SmallVec<[ash::vk::AttachmentReference; 4]>, - depth_stencil_attachment_vk: ash::vk::AttachmentReference, - } - - let (mut subpasses_vk, per_subpass_vk): (SmallVec<[_; 4]>, SmallVec<[_; 4]>) = subpasses - .iter() - .map(|subpass| { - let &SubpassDescription { - flags, - view_mask: _, - ref input_attachments, - ref color_attachments, - ref color_resolve_attachments, - ref depth_stencil_attachment, - depth_stencil_resolve_attachment: _, - depth_resolve_mode: _, - stencil_resolve_mode: _, - ref preserve_attachments, - _ne: _, - } = subpass; - - let input_attachments_vk = input_attachments - .iter() - .map(|input_attachment| { - if let Some(input_attachment) = input_attachment { - let &AttachmentReference { - attachment, - layout, - stencil_layout: _, - aspects: _, - _ne: _, - } = input_attachment; - - ash::vk::AttachmentReference { - attachment, - layout: layout.into(), - } - } else { - ash::vk::AttachmentReference { - attachment: ash::vk::ATTACHMENT_UNUSED, - ..Default::default() - } - } - }) - .collect(); - - let color_attachments_vk = color_attachments - .iter() - .map(|color_attachment| { - if let Some(color_attachment) = color_attachment { - let &AttachmentReference { - attachment, - layout, - stencil_layout: _, - aspects: _, - _ne: _, - } = color_attachment; - - ash::vk::AttachmentReference { - attachment, - layout: layout.into(), - } - } else { - ash::vk::AttachmentReference { - attachment: ash::vk::ATTACHMENT_UNUSED, - ..Default::default() - } - } - }) - .collect(); - - let resolve_attachments_vk = color_resolve_attachments - .iter() - .map(|color_resolve_attachment| { - if let Some(color_resolve_attachment) = color_resolve_attachment { - let &AttachmentReference { - attachment, - layout, - stencil_layout: _, - aspects: _, - _ne: _, - } = color_resolve_attachment; - - ash::vk::AttachmentReference { - attachment, - layout: layout.into(), - } - } else { - ash::vk::AttachmentReference { - attachment: ash::vk::ATTACHMENT_UNUSED, - ..Default::default() - } - } - }) - .collect(); - - let depth_stencil_attachment_vk = - if let Some(depth_stencil_attachment) = depth_stencil_attachment { - let &AttachmentReference { - attachment, - layout, - stencil_layout: _, - aspects: _, - _ne: _, - } = depth_stencil_attachment; - - ash::vk::AttachmentReference { - attachment, - layout: layout.into(), - } - } else { - ash::vk::AttachmentReference { - attachment: ash::vk::ATTACHMENT_UNUSED, - ..Default::default() - } - }; - - ( - ash::vk::SubpassDescription { - flags: flags.into(), - pipeline_bind_point: ash::vk::PipelineBindPoint::GRAPHICS, - input_attachment_count: 0, - p_input_attachments: ptr::null(), - color_attachment_count: 0, - p_color_attachments: ptr::null(), - p_resolve_attachments: ptr::null(), - p_depth_stencil_attachment: ptr::null(), - preserve_attachment_count: preserve_attachments.len() as u32, - p_preserve_attachments: if preserve_attachments.is_empty() { - ptr::null() - } else { - preserve_attachments.as_ptr() - }, - ..Default::default() - }, - PerSubpassDescriptionVk { - input_attachments_vk, - color_attachments_vk, - resolve_attachments_vk, - depth_stencil_attachment_vk, - }, - ) - }) - .unzip(); - - for (subpass_vk, per_subpass_vk) in subpasses_vk.iter_mut().zip(&per_subpass_vk) { - let PerSubpassDescriptionVk { - input_attachments_vk, - color_attachments_vk, - resolve_attachments_vk, - depth_stencil_attachment_vk, - } = per_subpass_vk; - - *subpass_vk = ash::vk::SubpassDescription { - input_attachment_count: input_attachments_vk.len() as u32, - p_input_attachments: if input_attachments_vk.is_empty() { - ptr::null() - } else { - input_attachments_vk.as_ptr() - }, - color_attachment_count: color_attachments_vk.len() as u32, - p_color_attachments: if color_attachments_vk.is_empty() { - ptr::null() - } else { - color_attachments_vk.as_ptr() - }, - p_resolve_attachments: if resolve_attachments_vk.is_empty() { - ptr::null() - } else { - resolve_attachments_vk.as_ptr() - }, - p_depth_stencil_attachment: depth_stencil_attachment_vk, - ..*subpass_vk - }; - } - - let dependencies_vk = dependencies - .iter() - .map(|dependency| { - let &SubpassDependency { - src_subpass, - dst_subpass, - src_stages, - dst_stages, - src_access, - dst_access, - dependency_flags, - view_offset: _, - _ne: _, - } = dependency; - - ash::vk::SubpassDependency { - src_subpass: src_subpass.unwrap_or(ash::vk::SUBPASS_EXTERNAL), - dst_subpass: dst_subpass.unwrap_or(ash::vk::SUBPASS_EXTERNAL), - src_stage_mask: src_stages.into(), - dst_stage_mask: dst_stages.into(), - src_access_mask: src_access.into(), - dst_access_mask: dst_access.into(), - dependency_flags: dependency_flags.into(), - } - }) - .collect::>(); - - /* Create */ - - let mut create_info_vk = ash::vk::RenderPassCreateInfo { - flags: flags.into(), - attachment_count: attachments_vk.len() as u32, - p_attachments: if attachments_vk.is_empty() { - ptr::null() - } else { - attachments_vk.as_ptr() - }, - subpass_count: subpasses_vk.len() as u32, - p_subpasses: if subpasses_vk.is_empty() { - ptr::null() - } else { - subpasses_vk.as_ptr() - }, - dependency_count: dependencies_vk.len() as u32, - p_dependencies: if dependencies_vk.is_empty() { - ptr::null() - } else { - dependencies_vk.as_ptr() - }, - ..Default::default() - }; - - /* Input attachment aspect */ - - let input_attachment_aspect_references_vk: SmallVec<[_; 8]>; - let mut input_attachment_aspect_create_info_vk = None; - - if device.api_version() >= Version::V1_1 || device.enabled_extensions().khr_maintenance2 { - input_attachment_aspect_references_vk = subpasses - .iter() - .enumerate() - .flat_map(|(subpass_num, subpass)| { - subpass.input_attachments.iter().enumerate().flat_map( - move |(atch_num, input_attachment)| { - input_attachment.as_ref().map(|input_attachment| { - let &AttachmentReference { - attachment: _, - layout: _, - stencil_layout: _, - aspects, - _ne, - } = input_attachment; - - ash::vk::InputAttachmentAspectReference { - subpass: subpass_num as u32, - input_attachment_index: atch_num as u32, - aspect_mask: aspects.into(), - } - }) - }, - ) - }) - .collect(); - - if !input_attachment_aspect_references_vk.is_empty() { - let next = input_attachment_aspect_create_info_vk.insert( - ash::vk::RenderPassInputAttachmentAspectCreateInfo { - aspect_reference_count: input_attachment_aspect_references_vk.len() as u32, - p_aspect_references: input_attachment_aspect_references_vk.as_ptr(), - ..Default::default() - }, - ); - - next.p_next = create_info_vk.p_next; - create_info_vk.p_next = <*const _>::cast(next); - } - } - - /* Multiview */ - - let mut multiview_create_info_vk = None; - let multiview_view_masks_vk: SmallVec<[_; 4]>; - let multiview_view_offsets_vk: SmallVec<[_; 4]>; - - let is_multiview = subpasses[0].view_mask != 0; - - if is_multiview { - multiview_view_masks_vk = subpasses.iter().map(|subpass| subpass.view_mask).collect(); - multiview_view_offsets_vk = dependencies - .iter() - .map(|dependency| dependency.view_offset) - .collect(); - - debug_assert!(multiview_view_masks_vk.len() == subpasses.len()); - debug_assert!(multiview_view_offsets_vk.len() == dependencies.len()); - - let next = multiview_create_info_vk.insert(ash::vk::RenderPassMultiviewCreateInfo { - subpass_count: multiview_view_masks_vk.len() as u32, - p_view_masks: multiview_view_masks_vk.as_ptr(), - dependency_count: multiview_view_offsets_vk.len() as u32, - p_view_offsets: multiview_view_offsets_vk.as_ptr(), - correlation_mask_count: correlated_view_masks.len() as u32, - p_correlation_masks: correlated_view_masks.as_ptr(), - ..Default::default() - }); - - next.p_next = create_info_vk.p_next; - create_info_vk.p_next = <*const _>::cast(next); - } - - Ok({ - let fns = device.fns(); - let mut output = MaybeUninit::uninit(); - (fns.v1_0.create_render_pass)( - device.handle(), - &create_info_vk, - ptr::null(), - output.as_mut_ptr(), - ) - .result() - .map_err(VulkanError::from)?; - output.assume_init() - }) - } -} diff --git a/vulkano/src/render_pass/framebuffer.rs b/vulkano/src/render_pass/framebuffer.rs index 9944aad0..d37052c8 100644 --- a/vulkano/src/render_pass/framebuffer.rs +++ b/vulkano/src/render_pass/framebuffer.rs @@ -247,27 +247,8 @@ impl Framebuffer { ) -> Result, VulkanError> { create_info.set_auto_extent_layers(&render_pass); - let &FramebufferCreateInfo { - flags, - ref attachments, - extent, - layers, - _ne: _, - } = &create_info; - - let attachments_vk: SmallVec<[_; 4]> = - attachments.iter().map(VulkanObject::handle).collect(); - - let create_info_vk = ash::vk::FramebufferCreateInfo { - flags: flags.into(), - render_pass: render_pass.handle(), - attachment_count: attachments_vk.len() as u32, - p_attachments: attachments_vk.as_ptr(), - width: extent[0], - height: extent[1], - layers, - ..Default::default() - }; + let create_info_fields1_vk = create_info.to_vk_fields1(); + let create_info_vk = create_info.to_vk(render_pass.handle(), &create_info_fields1_vk); let handle = unsafe { let fns = render_pass.device().fns(); @@ -632,6 +613,44 @@ impl FramebufferCreateInfo { Ok(()) } + + pub(crate) fn to_vk<'a>( + &self, + render_pass_vk: ash::vk::RenderPass, + fields1_vk: &'a FramebufferCreateInfoFields1Vk, + ) -> ash::vk::FramebufferCreateInfo<'a> { + let &Self { + flags, + attachments: _, + extent, + layers, + _ne: _, + } = self; + let FramebufferCreateInfoFields1Vk { attachments_vk } = fields1_vk; + + ash::vk::FramebufferCreateInfo::default() + .flags(flags.into()) + .render_pass(render_pass_vk) + .attachments(attachments_vk) + .width(extent[0]) + .height(extent[1]) + .layers(layers) + } + + pub(crate) fn to_vk_fields1(&self) -> FramebufferCreateInfoFields1Vk { + let &Self { + ref attachments, .. + } = self; + + let attachments_vk: SmallVec<[_; 4]> = + attachments.iter().map(VulkanObject::handle).collect(); + + FramebufferCreateInfoFields1Vk { attachments_vk } + } +} + +pub(crate) struct FramebufferCreateInfoFields1Vk { + pub(crate) attachments_vk: SmallVec<[ash::vk::ImageView; 4]>, } vulkan_bitflags! { diff --git a/vulkano/src/render_pass/mod.rs b/vulkano/src/render_pass/mod.rs index fd82ca2d..deb2c5db 100644 --- a/vulkano/src/render_pass/mod.rs +++ b/vulkano/src/render_pass/mod.rs @@ -28,6 +28,7 @@ use crate::{ VulkanObject, }; use ahash::HashMap; +use smallvec::SmallVec; use std::{ cmp::max, collections::hash_map::Entry, @@ -39,7 +40,6 @@ use std::{ #[macro_use] mod macros; -mod create; mod framebuffer; /// An object representing the discrete steps in which rendering is done. @@ -178,9 +178,58 @@ impl RenderPass { if device.api_version() >= Version::V1_2 || device.enabled_extensions().khr_create_renderpass2 { - Self::create_v2(&device, &create_info)? + let mut create_info_fields2_extensions_vk = create_info.to_vk2_fields2_extensions(); + let create_info_fields2_vk = + create_info.to_vk2_fields2(&mut create_info_fields2_extensions_vk); + let mut create_info_fields1_extensions_vk = + create_info.to_vk2_fields1_extensions(&create_info_fields2_vk); + let create_info_fields1_vk = create_info.to_vk2_fields1( + &create_info_fields2_vk, + &mut create_info_fields1_extensions_vk, + ); + let create_info_vk = create_info.to_vk2(&create_info_fields1_vk); + + let fns = device.fns(); + let mut output = MaybeUninit::uninit(); + + if device.api_version() >= Version::V1_2 { + (fns.v1_2.create_render_pass2)( + device.handle(), + &create_info_vk, + ptr::null(), + output.as_mut_ptr(), + ) + } else { + (fns.khr_create_renderpass2.create_render_pass2_khr)( + device.handle(), + &create_info_vk, + ptr::null(), + output.as_mut_ptr(), + ) + } + .result() + .map_err(VulkanError::from)?; + + output.assume_init() } else { - Self::create_v1(&device, &create_info)? + let create_info_fields2_vk = create_info.to_vk_fields2(); + let create_info_fields1_vk = create_info.to_vk_fields1(&create_info_fields2_vk); + let mut create_info_extensions_vk = + create_info.to_vk_extensions(&create_info_fields1_vk); + let create_info_vk = + create_info.to_vk(&create_info_fields1_vk, &mut create_info_extensions_vk); + + let fns = device.fns(); + let mut output = MaybeUninit::uninit(); + (fns.v1_0.create_render_pass)( + device.handle(), + &create_info_vk, + ptr::null(), + output.as_mut_ptr(), + ) + .result() + .map_err(VulkanError::from)?; + output.assume_init() } }; @@ -1579,6 +1628,372 @@ impl RenderPassCreateInfo { Ok(()) } + + pub(crate) fn to_vk2<'a>( + &'a self, + fields1_vk: &'a RenderPassCreateInfo2Fields1Vk<'_>, + ) -> ash::vk::RenderPassCreateInfo2<'a> { + let &Self { + flags, + attachments: _, + subpasses: _, + dependencies: _, + ref correlated_view_masks, + _ne: _, + } = self; + let RenderPassCreateInfo2Fields1Vk { + attachments_vk, + subpasses_vk, + dependencies_vk, + } = fields1_vk; + + ash::vk::RenderPassCreateInfo2::default() + .flags(flags.into()) + .attachments(attachments_vk) + .subpasses(subpasses_vk) + .dependencies(dependencies_vk) + .correlated_view_masks(correlated_view_masks) + } + + pub(crate) fn to_vk2_fields1<'a>( + &'a self, + fields2_vk: &'a RenderPassCreateInfo2Fields2Vk<'_>, + extensions_vk: &'a mut RenderPassCreateInfo2Fields1ExtensionsVk<'_>, + ) -> RenderPassCreateInfo2Fields1Vk<'a> { + let &Self { + flags: _, + ref attachments, + ref subpasses, + ref dependencies, + correlated_view_masks: _, + _ne: _, + } = self; + let RenderPassCreateInfo2Fields2Vk { + subpasses_fields1_vk, + } = fields2_vk; + let RenderPassCreateInfo2Fields1ExtensionsVk { + attachments_extensions_vk, + subpasses_extensions_vk, + dependencies_extensions_vk, + } = extensions_vk; + + let attachments_vk = attachments + .iter() + .zip(attachments_extensions_vk) + .map(|(attachment, extensions_vk)| attachment.to_vk2(extensions_vk)) + .collect(); + let subpasses_vk = subpasses + .iter() + .zip(subpasses_fields1_vk) + .zip(subpasses_extensions_vk) + .map(|((subpass, fields1_vk), extensions_vk)| subpass.to_vk2(fields1_vk, extensions_vk)) + .collect(); + let dependencies_vk = dependencies + .iter() + .zip(dependencies_extensions_vk) + .map(|(dependency, extensions_vk)| dependency.to_vk2(extensions_vk)) + .collect(); + + RenderPassCreateInfo2Fields1Vk { + attachments_vk, + subpasses_vk, + dependencies_vk, + } + } + + pub(crate) fn to_vk2_fields1_extensions<'a>( + &self, + fields2_vk: &'a RenderPassCreateInfo2Fields2Vk<'_>, + ) -> RenderPassCreateInfo2Fields1ExtensionsVk<'a> { + let &Self { + flags: _, + ref attachments, + ref subpasses, + ref dependencies, + correlated_view_masks: _, + _ne: _, + } = self; + let RenderPassCreateInfo2Fields2Vk { + subpasses_fields1_vk, + } = fields2_vk; + + let attachments_extensions_vk = attachments + .iter() + .map(AttachmentDescription::to_vk2_extensions) + .collect(); + let subpasses_extensions_vk = subpasses + .iter() + .zip(subpasses_fields1_vk) + .map(|(subpass, fields1_vk)| subpass.to_vk2_extensions(fields1_vk)) + .collect(); + let dependencies_extensions_vk = dependencies + .iter() + .map(SubpassDependency::to_vk2_extensions) + .collect(); + + RenderPassCreateInfo2Fields1ExtensionsVk { + attachments_extensions_vk, + subpasses_extensions_vk, + dependencies_extensions_vk, + } + } + + pub(crate) fn to_vk2_fields2<'a>( + &self, + extensions_vk: &'a mut RenderPassCreateInfo2Fields2ExtensionsVk, + ) -> RenderPassCreateInfo2Fields2Vk<'a> { + let RenderPassCreateInfo2Fields2ExtensionsVk { + subpasses_fields1_extensions_vk, + } = extensions_vk; + let subpasses_fields1_vk = self + .subpasses + .iter() + .zip(subpasses_fields1_extensions_vk) + .map(|(subpass, fields1_extensions_vk)| subpass.to_vk2_fields1(fields1_extensions_vk)) + .collect(); + + RenderPassCreateInfo2Fields2Vk { + subpasses_fields1_vk, + } + } + + pub(crate) fn to_vk2_fields2_extensions(&self) -> RenderPassCreateInfo2Fields2ExtensionsVk { + let subpasses_fields1_extensions_vk = self + .subpasses + .iter() + .map(SubpassDescription::to_vk2_fields1_extensions) + .collect(); + + RenderPassCreateInfo2Fields2ExtensionsVk { + subpasses_fields1_extensions_vk, + } + } + + pub(crate) fn to_vk<'a>( + &self, + fields1_vk: &'a RenderPassCreateInfoFields1Vk<'_>, + extensions_vk: &'a mut RenderPassCreateInfoExtensionsVk<'_>, + ) -> ash::vk::RenderPassCreateInfo<'a> { + let &Self { + flags, + attachments: _, + subpasses: _, + dependencies: _, + correlated_view_masks: _, + _ne: _, + } = self; + let RenderPassCreateInfoFields1Vk { + attachments_vk, + subpasses_vk, + dependencies_vk, + input_attachments_aspect_reference_vk: _, + multiview_view_masks_vk: _, + multiview_view_offsets_vk: _, + } = fields1_vk; + + let mut val_vk = ash::vk::RenderPassCreateInfo::default() + .flags(flags.into()) + .attachments(attachments_vk) + .subpasses(subpasses_vk) + .dependencies(dependencies_vk); + + let RenderPassCreateInfoExtensionsVk { + input_attachment_aspect_vk, + multiview_vk, + } = extensions_vk; + + if let Some(next) = input_attachment_aspect_vk { + val_vk = val_vk.push_next(next); + } + + if let Some(next) = multiview_vk { + val_vk = val_vk.push_next(next); + } + + val_vk + } + + pub(crate) fn to_vk_extensions<'a>( + &'a self, + fields1_vk: &'a RenderPassCreateInfoFields1Vk<'_>, + ) -> RenderPassCreateInfoExtensionsVk<'a> { + let &Self { + flags: _, + attachments: _, + subpasses: _, + dependencies: _, + ref correlated_view_masks, + _ne: _, + } = self; + let RenderPassCreateInfoFields1Vk { + attachments_vk: _, + subpasses_vk: _, + dependencies_vk: _, + input_attachments_aspect_reference_vk, + multiview_view_masks_vk, + multiview_view_offsets_vk, + } = fields1_vk; + + let input_attachment_aspect_vk = + (!input_attachments_aspect_reference_vk.is_empty()).then(|| { + ash::vk::RenderPassInputAttachmentAspectCreateInfo::default() + .aspect_references(input_attachments_aspect_reference_vk) + }); + + let is_multiview = self.subpasses[0].view_mask != 0; + let multiview_vk = is_multiview.then(|| { + ash::vk::RenderPassMultiviewCreateInfo::default() + .view_masks(multiview_view_masks_vk) + .view_offsets(multiview_view_offsets_vk) + .correlation_masks(correlated_view_masks) + }); + + RenderPassCreateInfoExtensionsVk { + input_attachment_aspect_vk, + multiview_vk, + } + } + + pub(crate) fn to_vk_fields1<'a>( + &'a self, + fields2_vk: &'a RenderPassCreateInfoFields2Vk, + ) -> RenderPassCreateInfoFields1Vk<'a> { + let &Self { + flags: _, + ref attachments, + ref subpasses, + ref dependencies, + correlated_view_masks: _, + _ne: _, + } = self; + let RenderPassCreateInfoFields2Vk { + subpasses_fields1_vk, + } = fields2_vk; + + let is_multiview = subpasses[0].view_mask != 0; + + let attachments_vk = attachments + .iter() + .map(AttachmentDescription::to_vk) + .collect(); + + let mut subpasses_vk = SmallVec::with_capacity(subpasses.len()); + let mut input_attachments_aspect_reference_vk = SmallVec::new(); + let mut multiview_view_masks_vk = SmallVec::with_capacity(subpasses.len()); + + for (subpass_num, (subpass, fields1_vk)) in + subpasses.iter().zip(subpasses_fields1_vk).enumerate() + { + subpasses_vk.push(subpass.to_vk(fields1_vk)); + + for (atch_num, input_attachment) in subpass.input_attachments.iter().enumerate() { + if let Some(atch_ref) = input_attachment { + let &AttachmentReference { + attachment, + layout: _, + stencil_layout: _, + aspects, + _ne, + } = atch_ref; + + if aspects.is_empty() { + continue; + } + + let attachment_desc = &attachments[attachment as usize]; + let format_aspects = attachment_desc.format.aspects(); + + if aspects == format_aspects { + continue; + } + + input_attachments_aspect_reference_vk.push( + ash::vk::InputAttachmentAspectReference { + subpass: subpass_num as u32, + input_attachment_index: atch_num as u32, + aspect_mask: aspects.into(), + }, + ); + } + } + + multiview_view_masks_vk.push(subpass.view_mask); + } + + let mut dependencies_vk = SmallVec::with_capacity(subpasses.len()); + let mut multiview_view_offsets_vk = SmallVec::with_capacity(subpasses.len()); + + for dependency in dependencies { + dependencies_vk.push(dependency.to_vk()); + multiview_view_offsets_vk.push(dependency.view_offset); + } + + RenderPassCreateInfoFields1Vk { + attachments_vk, + subpasses_vk, + dependencies_vk, + input_attachments_aspect_reference_vk, + multiview_view_masks_vk: is_multiview + .then_some(multiview_view_masks_vk) + .unwrap_or_default(), + multiview_view_offsets_vk: is_multiview + .then_some(multiview_view_offsets_vk) + .unwrap_or_default(), + } + } + + pub(crate) fn to_vk_fields2(&self) -> RenderPassCreateInfoFields2Vk { + let subpasses_fields1_vk = self + .subpasses + .iter() + .map(SubpassDescription::to_vk_fields1) + .collect(); + + RenderPassCreateInfoFields2Vk { + subpasses_fields1_vk, + } + } +} + +pub(crate) struct RenderPassCreateInfo2Fields1Vk<'a> { + pub(crate) attachments_vk: SmallVec<[ash::vk::AttachmentDescription2<'a>; 4]>, + pub(crate) subpasses_vk: SmallVec<[ash::vk::SubpassDescription2<'a>; 4]>, + pub(crate) dependencies_vk: SmallVec<[ash::vk::SubpassDependency2<'a>; 4]>, +} + +pub(crate) struct RenderPassCreateInfo2Fields1ExtensionsVk<'a> { + pub(crate) attachments_extensions_vk: SmallVec<[AttachmentDescription2ExtensionsVk; 4]>, + pub(crate) subpasses_extensions_vk: SmallVec<[SubpassDescription2ExtensionsVk<'a>; 4]>, + pub(crate) dependencies_extensions_vk: SmallVec<[SubpassDependency2ExtensionsVk; 4]>, +} + +pub(crate) struct RenderPassCreateInfo2Fields2Vk<'a> { + pub(crate) subpasses_fields1_vk: SmallVec<[SubpassDescription2Fields1Vk<'a>; 4]>, +} + +pub(crate) struct RenderPassCreateInfo2Fields2ExtensionsVk { + pub(crate) subpasses_fields1_extensions_vk: + SmallVec<[SubpassDescription2Fields1ExtensionsVk; 4]>, +} + +pub(crate) struct RenderPassCreateInfoExtensionsVk<'a> { + pub(crate) input_attachment_aspect_vk: + Option>, + pub(crate) multiview_vk: Option>, +} + +pub(crate) struct RenderPassCreateInfoFields1Vk<'a> { + pub(crate) attachments_vk: SmallVec<[ash::vk::AttachmentDescription; 4]>, + pub(crate) subpasses_vk: SmallVec<[ash::vk::SubpassDescription<'a>; 4]>, + pub(crate) dependencies_vk: SmallVec<[ash::vk::SubpassDependency; 4]>, + pub(crate) input_attachments_aspect_reference_vk: + SmallVec<[ash::vk::InputAttachmentAspectReference; 8]>, + pub(crate) multiview_view_masks_vk: SmallVec<[u32; 4]>, + pub(crate) multiview_view_offsets_vk: SmallVec<[i32; 4]>, +} + +pub(crate) struct RenderPassCreateInfoFields2Vk { + pub(crate) subpasses_fields1_vk: SmallVec<[SubpassDescriptionFields1Vk; 4]>, } vulkan_bitflags! { @@ -1595,7 +2010,7 @@ vulkan_bitflags! { } /// Describes an attachment that will be used in a render pass. -#[derive(Clone, Copy, Debug)] +#[derive(Clone, Debug)] pub struct AttachmentDescription { /// Additional properties of the attachment. /// @@ -2131,6 +2546,96 @@ impl AttachmentDescription { } } } + + pub(crate) fn to_vk2<'a>( + &self, + extensions_vk: &'a mut AttachmentDescription2ExtensionsVk, + ) -> ash::vk::AttachmentDescription2<'a> { + let &Self { + flags, + format, + samples, + load_op, + store_op, + initial_layout, + final_layout, + stencil_load_op, + stencil_store_op, + stencil_initial_layout: _, + stencil_final_layout: _, + _ne: _, + } = self; + + let mut val_vk = ash::vk::AttachmentDescription2::default() + .flags(flags.into()) + .format(format.into()) + .samples(samples.into()) + .load_op(load_op.into()) + .store_op(store_op.into()) + .stencil_load_op(stencil_load_op.unwrap_or(load_op).into()) + .stencil_store_op(stencil_store_op.unwrap_or(store_op).into()) + .initial_layout(initial_layout.into()) + .final_layout(final_layout.into()); + + let AttachmentDescription2ExtensionsVk { stencil_layout_vk } = extensions_vk; + + if let Some(next) = stencil_layout_vk { + val_vk = val_vk.push_next(next); + } + + val_vk + } + + pub(crate) fn to_vk2_extensions(&self) -> AttachmentDescription2ExtensionsVk { + let &Self { + stencil_initial_layout, + stencil_final_layout, + .. + } = self; + + let stencil_layout_vk = stencil_initial_layout.zip(stencil_final_layout).map( + |(stencil_initial_layout, stencil_final_layout)| { + ash::vk::AttachmentDescriptionStencilLayout::default() + .stencil_initial_layout(stencil_initial_layout.into()) + .stencil_final_layout(stencil_final_layout.into()) + }, + ); + + AttachmentDescription2ExtensionsVk { stencil_layout_vk } + } + + pub(crate) fn to_vk(&self) -> ash::vk::AttachmentDescription { + let &Self { + flags, + format, + samples, + load_op, + store_op, + initial_layout, + final_layout, + stencil_load_op, + stencil_store_op, + stencil_initial_layout: _, + stencil_final_layout: _, + _ne: _, + } = self; + + ash::vk::AttachmentDescription { + flags: flags.into(), + format: format.into(), + samples: samples.into(), + load_op: load_op.into(), + store_op: store_op.into(), + stencil_load_op: stencil_load_op.unwrap_or(load_op).into(), + stencil_store_op: stencil_store_op.unwrap_or(store_op).into(), + initial_layout: initial_layout.into(), + final_layout: final_layout.into(), + } + } +} + +pub(crate) struct AttachmentDescription2ExtensionsVk { + pub(crate) stencil_layout_vk: Option>, } vulkan_bitflags! { @@ -2961,6 +3466,363 @@ impl SubpassDescription { Ok(()) } + + pub(crate) fn to_vk2<'a>( + &'a self, + fields1_vk: &'a SubpassDescription2Fields1Vk<'_>, + extensions_vk: &'a mut SubpassDescription2ExtensionsVk<'_>, + ) -> ash::vk::SubpassDescription2<'a> { + let &Self { + flags, + view_mask, + ref preserve_attachments, + .. + } = self; + let SubpassDescription2Fields1Vk { + input_attachments_vk, + color_attachments_vk, + color_resolve_attachments_vk, + depth_stencil_attachment_vk, + depth_stencil_resolve_attachment_vk: _, + } = fields1_vk; + + let mut val_vk = ash::vk::SubpassDescription2::default() + .flags(flags.into()) + .pipeline_bind_point(ash::vk::PipelineBindPoint::GRAPHICS) // TODO: any need to make this user-specifiable? + .view_mask(view_mask); + + if !input_attachments_vk.is_empty() { + val_vk = val_vk.input_attachments(input_attachments_vk); + } + + if !color_attachments_vk.is_empty() { + val_vk = val_vk.color_attachments(color_attachments_vk); + } + + if !color_resolve_attachments_vk.is_empty() { + val_vk = val_vk.resolve_attachments(color_resolve_attachments_vk); + } + + if let Some(depth_stencil_attachment_vk) = depth_stencil_attachment_vk { + val_vk = val_vk.depth_stencil_attachment(depth_stencil_attachment_vk); + } + + if !preserve_attachments.is_empty() { + val_vk = val_vk.preserve_attachments(preserve_attachments); + } + + let SubpassDescription2ExtensionsVk { + depth_stencil_resolve_vk, + } = extensions_vk; + + if let Some(next) = depth_stencil_resolve_vk { + val_vk = val_vk.push_next(next); + } + + val_vk + } + + pub(crate) fn to_vk2_extensions<'a>( + &self, + fields1_vk: &'a SubpassDescription2Fields1Vk<'_>, + ) -> SubpassDescription2ExtensionsVk<'a> { + let &Self { + depth_resolve_mode, + stencil_resolve_mode, + .. + } = self; + let SubpassDescription2Fields1Vk { + depth_stencil_resolve_attachment_vk, + .. + } = fields1_vk; + + let depth_stencil_resolve_vk = depth_stencil_resolve_attachment_vk.as_ref().map( + |depth_stencil_resolve_attachment_vk| { + ash::vk::SubpassDescriptionDepthStencilResolve::default() + .depth_resolve_mode( + depth_resolve_mode.map_or(ash::vk::ResolveModeFlags::NONE, Into::into), + ) + .stencil_resolve_mode( + stencil_resolve_mode.map_or(ash::vk::ResolveModeFlags::NONE, Into::into), + ) + .depth_stencil_resolve_attachment(depth_stencil_resolve_attachment_vk) + }, + ); + + SubpassDescription2ExtensionsVk { + depth_stencil_resolve_vk, + } + } + + pub(crate) fn to_vk2_fields1<'a>( + &self, + extensions_vk: &'a mut SubpassDescription2Fields1ExtensionsVk, + ) -> SubpassDescription2Fields1Vk<'a> { + let Self { + input_attachments, + color_attachments, + color_resolve_attachments, + depth_stencil_attachment, + depth_stencil_resolve_attachment, + .. + } = self; + let SubpassDescription2Fields1ExtensionsVk { + input_attachments_extensions_vk, + color_attachments_extensions_vk, + color_resolve_attachments_extensions_vk, + depth_stencil_attachment_extensions_vk, + depth_stencil_resolve_attachment_extensions_vk, + } = extensions_vk; + + let unused_vk = + ash::vk::AttachmentReference2::default().attachment(ash::vk::ATTACHMENT_UNUSED); + + let input_attachments_vk = input_attachments + .iter() + .zip(input_attachments_extensions_vk) + .map(|(attachment, extensions_vk)| { + attachment + .as_ref() + .zip(extensions_vk.as_mut()) + .map_or(unused_vk, |(attachment, extensions_vk)| { + attachment.to_vk2(extensions_vk) + }) + }) + .collect(); + + let color_attachments_vk = color_attachments + .iter() + .zip(color_attachments_extensions_vk) + .map(|(attachment, extensions_vk)| { + attachment + .as_ref() + .zip(extensions_vk.as_mut()) + .map_or(unused_vk, |(attachment, extensions_vk)| { + attachment.to_vk2(extensions_vk) + }) + }) + .collect(); + + let color_resolve_attachments_vk = color_resolve_attachments + .iter() + .zip(color_resolve_attachments_extensions_vk) + .map(|(attachment, extensions_vk)| { + attachment + .as_ref() + .zip(extensions_vk.as_mut()) + .map_or(unused_vk, |(attachment, extensions_vk)| { + attachment.to_vk2(extensions_vk) + }) + }) + .collect(); + + let depth_stencil_attachment_vk = depth_stencil_attachment + .as_ref() + .zip(depth_stencil_attachment_extensions_vk.as_mut()) + .map(|(attachment, extensions_vk)| attachment.to_vk2(extensions_vk)); + + let depth_stencil_resolve_attachment_vk = depth_stencil_resolve_attachment + .as_ref() + .zip(depth_stencil_resolve_attachment_extensions_vk.as_mut()) + .map(|(attachment, extensions_vk)| attachment.to_vk2(extensions_vk)); + + SubpassDescription2Fields1Vk { + input_attachments_vk, + color_attachments_vk, + color_resolve_attachments_vk, + depth_stencil_attachment_vk, + depth_stencil_resolve_attachment_vk, + } + } + + pub(crate) fn to_vk2_fields1_extensions(&self) -> SubpassDescription2Fields1ExtensionsVk { + let Self { + input_attachments, + color_attachments, + color_resolve_attachments, + depth_stencil_attachment, + depth_stencil_resolve_attachment, + .. + } = self; + + let input_attachments_extensions_vk = input_attachments + .iter() + .map(|attachment| { + attachment + .as_ref() + .map(AttachmentReference::to_vk2_extensions) + }) + .collect(); + + let color_attachments_extensions_vk = color_attachments + .iter() + .map(|attachment| { + attachment + .as_ref() + .map(AttachmentReference::to_vk2_extensions) + }) + .collect(); + + let color_resolve_attachments_extensions_vk = color_resolve_attachments + .iter() + .map(|attachment| { + attachment + .as_ref() + .map(AttachmentReference::to_vk2_extensions) + }) + .collect(); + + let depth_stencil_attachment_extensions_vk = depth_stencil_attachment + .as_ref() + .map(AttachmentReference::to_vk2_extensions); + + let depth_stencil_resolve_attachment_extensions_vk = depth_stencil_resolve_attachment + .as_ref() + .map(AttachmentReference::to_vk2_extensions); + + SubpassDescription2Fields1ExtensionsVk { + input_attachments_extensions_vk, + color_attachments_extensions_vk, + color_resolve_attachments_extensions_vk, + depth_stencil_attachment_extensions_vk, + depth_stencil_resolve_attachment_extensions_vk, + } + } + + pub(crate) fn to_vk<'a>( + &'a self, + fields1_vk: &'a SubpassDescriptionFields1Vk, + ) -> ash::vk::SubpassDescription<'a> { + let &Self { + flags, + view_mask: _, + input_attachments: _, + color_attachments: _, + color_resolve_attachments: _, + depth_stencil_attachment: _, + depth_stencil_resolve_attachment: _, + depth_resolve_mode: _, + stencil_resolve_mode: _, + ref preserve_attachments, + _ne: _, + } = self; + let SubpassDescriptionFields1Vk { + input_attachments_vk, + color_attachments_vk, + color_resolve_attachments_vk, + depth_stencil_attachment_vk, + } = fields1_vk; + + let mut val_vk = ash::vk::SubpassDescription::default() + .flags(flags.into()) + .pipeline_bind_point(ash::vk::PipelineBindPoint::GRAPHICS); + + if !input_attachments_vk.is_empty() { + val_vk = val_vk.input_attachments(input_attachments_vk); + } + + if !color_attachments_vk.is_empty() { + val_vk = val_vk.color_attachments(color_attachments_vk); + } + + if !color_resolve_attachments_vk.is_empty() { + val_vk = val_vk.resolve_attachments(color_resolve_attachments_vk); + } + + if let Some(depth_stencil_attachment_vk) = depth_stencil_attachment_vk { + val_vk = val_vk.depth_stencil_attachment(depth_stencil_attachment_vk); + } + + if !preserve_attachments.is_empty() { + val_vk = val_vk.preserve_attachments(preserve_attachments); + } + + val_vk + } + + pub(crate) fn to_vk_fields1(&self) -> SubpassDescriptionFields1Vk { + let Self { + input_attachments, + color_attachments, + color_resolve_attachments, + depth_stencil_attachment, + .. + } = self; + + let unused_vk = ash::vk::AttachmentReference { + attachment: ash::vk::ATTACHMENT_UNUSED, + ..Default::default() + }; + + let input_attachments_vk = input_attachments + .iter() + .map(|attachment| { + attachment + .as_ref() + .map_or(unused_vk, |attachment| attachment.to_vk()) + }) + .collect(); + + let color_attachments_vk = color_attachments + .iter() + .map(|attachment| { + attachment + .as_ref() + .map_or(unused_vk, |attachment| attachment.to_vk()) + }) + .collect(); + + let color_resolve_attachments_vk = color_resolve_attachments + .iter() + .map(|attachment| { + attachment + .as_ref() + .map_or(unused_vk, |attachment| attachment.to_vk()) + }) + .collect(); + + let depth_stencil_attachment_vk = depth_stencil_attachment + .as_ref() + .map(|attachment| attachment.to_vk()); + + SubpassDescriptionFields1Vk { + input_attachments_vk, + color_attachments_vk, + color_resolve_attachments_vk, + depth_stencil_attachment_vk, + } + } +} + +pub(crate) struct SubpassDescription2ExtensionsVk<'a> { + pub(crate) depth_stencil_resolve_vk: Option>, +} + +pub(crate) struct SubpassDescription2Fields1Vk<'a> { + pub(crate) input_attachments_vk: SmallVec<[ash::vk::AttachmentReference2<'a>; 4]>, + pub(crate) color_attachments_vk: SmallVec<[ash::vk::AttachmentReference2<'a>; 4]>, + pub(crate) color_resolve_attachments_vk: SmallVec<[ash::vk::AttachmentReference2<'a>; 4]>, + pub(crate) depth_stencil_attachment_vk: Option>, + pub(crate) depth_stencil_resolve_attachment_vk: Option>, +} + +pub(crate) struct SubpassDescription2Fields1ExtensionsVk { + pub(crate) input_attachments_extensions_vk: + SmallVec<[Option; 4]>, + pub(crate) color_attachments_extensions_vk: + SmallVec<[Option; 4]>, + pub(crate) color_resolve_attachments_extensions_vk: + SmallVec<[Option; 4]>, + pub(crate) depth_stencil_attachment_extensions_vk: Option, + pub(crate) depth_stencil_resolve_attachment_extensions_vk: + Option, +} + +pub(crate) struct SubpassDescriptionFields1Vk { + pub(crate) input_attachments_vk: SmallVec<[ash::vk::AttachmentReference; 4]>, + pub(crate) color_attachments_vk: SmallVec<[ash::vk::AttachmentReference; 4]>, + pub(crate) color_resolve_attachments_vk: SmallVec<[ash::vk::AttachmentReference; 4]>, + pub(crate) depth_stencil_attachment_vk: Option, } vulkan_bitflags! { @@ -3195,6 +4057,61 @@ impl AttachmentReference { Ok(()) } + + fn to_vk2<'a>( + &self, + extensions_vk: &'a mut AttachmentReference2ExtensionsVk, + ) -> ash::vk::AttachmentReference2<'a> { + let &Self { + attachment, + layout, + stencil_layout: _, + aspects, + _ne: _, + } = self; + + let mut val_vk = ash::vk::AttachmentReference2::default() + .attachment(attachment) + .layout(layout.into()) + .aspect_mask(aspects.into()); + + let AttachmentReference2ExtensionsVk { stencil_layout_vk } = extensions_vk; + + if let Some(next) = stencil_layout_vk { + val_vk = val_vk.push_next(next); + } + + val_vk + } + + fn to_vk2_extensions(&self) -> AttachmentReference2ExtensionsVk { + let stencil_layout_vk = self.stencil_layout.map(|stencil_layout| { + ash::vk::AttachmentReferenceStencilLayout::default() + .stencil_layout(stencil_layout.into()) + }); + + AttachmentReference2ExtensionsVk { stencil_layout_vk } + } + + fn to_vk(&self) -> ash::vk::AttachmentReference { + let &Self { + attachment, + layout, + stencil_layout: _, + aspects: _, + _ne: _, + } = self; + + ash::vk::AttachmentReference { + attachment, + layout: layout.into(), + } + } +} + +#[derive(Default)] +pub(crate) struct AttachmentReference2ExtensionsVk { + pub(crate) stencil_layout_vk: Option>, } /// A dependency between two subpasses of a render pass. @@ -3501,6 +4418,94 @@ impl SubpassDependency { Ok(()) } + + pub(crate) fn to_vk2<'a>( + &self, + extensions_vk: &'a mut SubpassDependency2ExtensionsVk, + ) -> ash::vk::SubpassDependency2<'a> { + let &Self { + src_subpass, + dst_subpass, + src_stages, + dst_stages, + src_access, + dst_access, + dependency_flags, + view_offset, + _ne: _, + } = self; + + let mut val_vk = ash::vk::SubpassDependency2::default() + .src_subpass(src_subpass.unwrap_or(ash::vk::SUBPASS_EXTERNAL)) + .dst_subpass(dst_subpass.unwrap_or(ash::vk::SUBPASS_EXTERNAL)) + .src_stage_mask(src_stages.into()) + .dst_stage_mask(dst_stages.into()) + .src_access_mask(src_access.into()) + .dst_access_mask(dst_access.into()) + .dependency_flags(dependency_flags.into()) + // VUID-VkSubpassDependency2-dependencyFlags-03092 + .view_offset(view_offset); + + let SubpassDependency2ExtensionsVk { memory_barrier_vk } = extensions_vk; + + if let Some(next) = memory_barrier_vk { + val_vk = val_vk.push_next(next); + } + + val_vk + } + + pub(crate) fn to_vk2_extensions(&self) -> SubpassDependency2ExtensionsVk { + let &Self { + src_stages, + dst_stages, + src_access, + dst_access, + .. + } = self; + + let memory_barrier_vk = (src_stages.contains_flags2() + || src_access.contains_flags2() + || dst_stages.contains_flags2() + || dst_access.contains_flags2()) + .then(|| { + ash::vk::MemoryBarrier2::default() + .src_stage_mask(src_stages.into()) + .src_access_mask(src_access.into()) + .dst_stage_mask(dst_stages.into()) + .dst_access_mask(dst_access.into()) + }); + + SubpassDependency2ExtensionsVk { memory_barrier_vk } + } + + pub(crate) fn to_vk(&self) -> ash::vk::SubpassDependency { + let &Self { + src_subpass, + dst_subpass, + src_stages, + dst_stages, + src_access, + dst_access, + dependency_flags, + view_offset: _, + _ne: _, + } = self; + + ash::vk::SubpassDependency { + src_subpass: src_subpass.unwrap_or(ash::vk::SUBPASS_EXTERNAL), + dst_subpass: dst_subpass.unwrap_or(ash::vk::SUBPASS_EXTERNAL), + src_stage_mask: src_stages.into(), + dst_stage_mask: dst_stages.into(), + src_access_mask: src_access.into(), + dst_access_mask: dst_access.into(), + dependency_flags: dependency_flags.into(), + } + } +} + +pub(crate) struct SubpassDependency2ExtensionsVk { + pub(crate) memory_barrier_vk: Option>, } vulkan_enum! { diff --git a/vulkano/src/shader/mod.rs b/vulkano/src/shader/mod.rs index d2d61ed5..42f2d0ef 100644 --- a/vulkano/src/shader/mod.rs +++ b/vulkano/src/shader/mod.rs @@ -434,7 +434,7 @@ use smallvec::SmallVec; use spirv::ExecutionModel; use std::{ collections::hash_map::Entry, - mem::{discriminant, size_of_val, MaybeUninit}, + mem::{discriminant, MaybeUninit}, num::NonZeroU64, ptr, sync::Arc, @@ -507,21 +507,14 @@ impl ShaderModule { create_info: ShaderModuleCreateInfo<'_>, spirv: Spirv, ) -> Result, VulkanError> { - let &ShaderModuleCreateInfo { code, _ne: _ } = &create_info; + let create_info_vk = create_info.to_vk(); let handle = { - let infos = ash::vk::ShaderModuleCreateInfo { - flags: ash::vk::ShaderModuleCreateFlags::empty(), - code_size: size_of_val(code), - p_code: code.as_ptr(), - ..Default::default() - }; - let fns = device.fns(); let mut output = MaybeUninit::uninit(); (fns.v1_0.create_shader_module)( device.handle(), - &infos, + &create_info_vk, ptr::null(), output.as_mut_ptr(), ) @@ -846,6 +839,14 @@ impl<'a> ShaderModuleCreateInfo<'a> { Ok(()) } + + pub(crate) fn to_vk(&self) -> ash::vk::ShaderModuleCreateInfo<'_> { + let &Self { code, _ne: _ } = self; + + ash::vk::ShaderModuleCreateInfo::default() + .flags(ash::vk::ShaderModuleCreateFlags::empty()) + .code(code) + } } /// The value to provide for a specialization constant, when creating a pipeline. diff --git a/vulkano/src/swapchain/acquire_present.rs b/vulkano/src/swapchain/acquire_present.rs index cb007085..714954ec 100644 --- a/vulkano/src/swapchain/acquire_present.rs +++ b/vulkano/src/swapchain/acquire_present.rs @@ -11,7 +11,7 @@ use crate::{ DeviceSize, Requires, RequiresAllOf, RequiresOneOf, Validated, ValidationError, VulkanError, VulkanObject, }; -use smallvec::smallvec; +use smallvec::{smallvec, SmallVec}; use std::{ fmt::Debug, mem::MaybeUninit, @@ -113,6 +113,33 @@ impl AcquireNextImageInfo { Ok(()) } + + pub(crate) fn to_vk( + &self, + swapchain_vk: ash::vk::SwapchainKHR, + device_mask_vk: u32, + ) -> ash::vk::AcquireNextImageInfoKHR<'static> { + let &Self { + timeout, + ref semaphore, + ref fence, + _ne: _, + } = self; + + ash::vk::AcquireNextImageInfoKHR::default() + .swapchain(swapchain_vk) + .timeout(timeout.map_or(u64::MAX, |duration| { + u64::try_from(duration.as_nanos()).unwrap() + })) + .semaphore( + semaphore + .as_ref() + .map(VulkanObject::handle) + .unwrap_or_default(), + ) + .fence(fence.as_ref().map(VulkanObject::handle).unwrap_or_default()) + .device_mask(device_mask_vk) + } } /// Tries to take ownership of an image in order to draw on it. @@ -417,7 +444,7 @@ pub struct PresentInfo { /// The present operations to perform. /// /// The default value is empty. - pub swapchains: Vec, + pub swapchain_infos: Vec, pub _ne: crate::NonExhaustive, } @@ -427,7 +454,7 @@ impl Default for PresentInfo { fn default() -> Self { Self { wait_semaphores: Vec::new(), - swapchains: Vec::new(), + swapchain_infos: Vec::new(), _ne: crate::NonExhaustive(()), } } @@ -437,7 +464,7 @@ impl PresentInfo { pub(crate) fn validate(&self, device: &Device) -> Result<(), Box> { let &Self { ref wait_semaphores, - swapchains: ref swapchain_infos, + ref swapchain_infos, _ne: _, } = self; @@ -463,7 +490,7 @@ impl PresentInfo { image_index: _, present_id: _, present_mode, - present_regions: _, + present_region: _, _ne: _, } = swapchain_info; @@ -498,6 +525,191 @@ impl PresentInfo { Ok(()) } + + pub(crate) fn to_vk<'a>( + &self, + fields1_vk: &'a PresentInfoFields1Vk<'_>, + results_vk: &'a mut [ash::vk::Result], + extensions_vk: &'a mut PresentInfoExtensionsVk<'_>, + ) -> ash::vk::PresentInfoKHR<'a> { + let &Self { + wait_semaphores: _, + swapchain_infos: _, + _ne: _, + } = self; + let PresentInfoFields1Vk { + wait_semaphores_vk, + swapchains_vk, + image_indices_vk, + present_ids_vk: _, + present_modes_vk: _, + present_regions_vk: _, + } = fields1_vk; + let PresentInfoExtensionsVk { + present_id_vk, + present_mode_vk, + present_regions_vk, + } = extensions_vk; + + let mut val_vk = ash::vk::PresentInfoKHR::default() + .wait_semaphores(wait_semaphores_vk) + .swapchains(swapchains_vk) + .image_indices(image_indices_vk) + .results(results_vk); + + if let Some(next) = present_id_vk { + val_vk = val_vk.push_next(next); + } + + if let Some(next) = present_mode_vk { + val_vk = val_vk.push_next(next); + } + + if let Some(next) = present_regions_vk { + val_vk = val_vk.push_next(next); + } + + val_vk + } + + pub(crate) fn to_vk_results(&self) -> Vec { + vec![ash::vk::Result::SUCCESS; self.swapchain_infos.len()] + } + + pub(crate) fn to_vk_extensions<'a>( + &self, + fields1_vk: &'a PresentInfoFields1Vk<'_>, + ) -> PresentInfoExtensionsVk<'a> { + let PresentInfoFields1Vk { + wait_semaphores_vk: _, + swapchains_vk: _, + image_indices_vk: _, + present_ids_vk, + present_modes_vk, + present_regions_vk, + } = fields1_vk; + + let mut has_present_ids = false; + let mut has_present_modes = false; + let mut has_present_regions = false; + + for swapchain_info in &self.swapchain_infos { + let &SwapchainPresentInfo { + swapchain: _, + image_index: _, + present_id, + present_mode, + ref present_region, + _ne: _, + } = swapchain_info; + + has_present_ids |= present_id.is_some(); + has_present_modes |= present_mode.is_some(); + has_present_regions |= !present_region.is_empty(); + } + + let present_id_vk = + has_present_ids.then(|| ash::vk::PresentIdKHR::default().present_ids(present_ids_vk)); + let present_mode_vk = has_present_modes.then(|| { + ash::vk::SwapchainPresentModeInfoEXT::default().present_modes(present_modes_vk) + }); + let present_regions_vk = has_present_regions + .then(|| ash::vk::PresentRegionsKHR::default().regions(present_regions_vk)); + + PresentInfoExtensionsVk { + present_id_vk, + present_mode_vk, + present_regions_vk, + } + } + + pub(crate) fn to_vk_fields1<'a>( + &self, + fields2_vk: &'a PresentInfoFields2Vk, + ) -> PresentInfoFields1Vk<'a> { + let &Self { + ref wait_semaphores, + ref swapchain_infos, + _ne: _, + } = self; + let PresentInfoFields2Vk { + swapchain_infos_fields1_vk, + } = fields2_vk; + + let wait_semaphores_vk = wait_semaphores + .iter() + .map(SemaphorePresentInfo::to_vk) + .collect(); + + let mut swapchains_vk = SmallVec::with_capacity(swapchain_infos.len()); + let mut image_indices_vk = SmallVec::with_capacity(swapchain_infos.len()); + let mut present_ids_vk = SmallVec::with_capacity(swapchain_infos.len()); + let mut present_modes_vk = SmallVec::with_capacity(swapchain_infos.len()); + let mut present_regions_vk = SmallVec::with_capacity(swapchain_infos.len()); + + for (swapchain_info, fields1_vk) in swapchain_infos.iter().zip(swapchain_infos_fields1_vk) { + let &SwapchainPresentInfo { + ref swapchain, + image_index, + present_id, + present_mode, + present_region: _, + _ne: _, + } = swapchain_info; + + let SwapchainPresentInfoFields1Vk { + present_region_rectangles_vk, + } = fields1_vk; + + swapchains_vk.push(swapchain.handle()); + image_indices_vk.push(image_index); + present_ids_vk.push(present_id.map_or(0, u64::from)); + present_modes_vk.push(present_mode.map_or_else(Default::default, Into::into)); + present_regions_vk.push( + ash::vk::PresentRegionKHR::default().rectangles(present_region_rectangles_vk), + ); + } + + PresentInfoFields1Vk { + wait_semaphores_vk, + swapchains_vk, + image_indices_vk, + present_ids_vk, + present_modes_vk, + present_regions_vk, + } + } + + pub(crate) fn to_vk_fields2(&self) -> PresentInfoFields2Vk { + let swapchain_infos_fields1_vk = self + .swapchain_infos + .iter() + .map(SwapchainPresentInfo::to_vk_fields1) + .collect(); + + PresentInfoFields2Vk { + swapchain_infos_fields1_vk, + } + } +} + +pub(crate) struct PresentInfoExtensionsVk<'a> { + pub(crate) present_id_vk: Option>, + pub(crate) present_mode_vk: Option>, + pub(crate) present_regions_vk: Option>, +} + +pub(crate) struct PresentInfoFields1Vk<'a> { + pub(crate) wait_semaphores_vk: SmallVec<[ash::vk::Semaphore; 4]>, + pub(crate) swapchains_vk: SmallVec<[ash::vk::SwapchainKHR; 4]>, + pub(crate) image_indices_vk: SmallVec<[u32; 4]>, + pub(crate) present_ids_vk: SmallVec<[u64; 4]>, + pub(crate) present_modes_vk: SmallVec<[ash::vk::PresentModeKHR; 4]>, + pub(crate) present_regions_vk: SmallVec<[ash::vk::PresentRegionKHR<'a>; 4]>, +} + +pub(crate) struct PresentInfoFields2Vk { + pub(crate) swapchain_infos_fields1_vk: SmallVec<[SwapchainPresentInfoFields1Vk; 4]>, } /// Parameters for a single present operation on a swapchain. @@ -560,7 +772,7 @@ pub struct SwapchainPresentInfo { /// If `present_regions` is empty, that means that all of the swapchain image must be updated. /// /// The default value is empty. - pub present_regions: Vec, + pub present_region: Vec, pub _ne: crate::NonExhaustive, } @@ -574,7 +786,7 @@ impl SwapchainPresentInfo { image_index, present_id: None, present_mode: None, - present_regions: Vec::new(), + present_region: Vec::new(), _ne: crate::NonExhaustive(()), } } @@ -585,7 +797,7 @@ impl SwapchainPresentInfo { image_index, present_id, present_mode, - ref present_regions, + ref present_region, _ne: _, } = self; @@ -621,7 +833,7 @@ impl SwapchainPresentInfo { } } - if !present_regions.is_empty() && !device.enabled_extensions().khr_incremental_present { + if !present_region.is_empty() && !device.enabled_extensions().khr_incremental_present { return Err(Box::new(ValidationError { context: "present_regions".into(), problem: "is not empty".into(), @@ -632,7 +844,7 @@ impl SwapchainPresentInfo { })); } - for (index, rectangle_layer) in present_regions.iter().enumerate() { + for (index, rectangle_layer) in present_region.iter().enumerate() { let &RectangleLayer { offset, extent, @@ -642,7 +854,7 @@ impl SwapchainPresentInfo { if offset[0] + extent[0] > swapchain.image_extent()[0] { return Err(Box::new(ValidationError { problem: format!( - "`present_regions[{0}].offset[0]` + `present_regions[{0}].extent[0]` is \ + "`present_region[{0}].offset[0]` + `present_regions[{0}].extent[0]` is \ greater than `swapchain.image_extent()[0]`", index ) @@ -655,7 +867,7 @@ impl SwapchainPresentInfo { if offset[1] + extent[1] > swapchain.image_extent()[1] { return Err(Box::new(ValidationError { problem: format!( - "`present_regions[{0}].offset[1]` + `present_regions[{0}].extent[1]` is \ + "`present_region[{0}].offset[1]` + `present_regions[{0}].extent[1]` is \ greater than `swapchain.image_extent()[1]`", index ) @@ -668,7 +880,7 @@ impl SwapchainPresentInfo { if layer >= swapchain.image_array_layers() { return Err(Box::new(ValidationError { problem: format!( - "`present_regions[{0}].layer` is greater than \ + "`present_region[{0}].layer` is greater than \ `swapchain.image_array_layers()`", index ) @@ -685,6 +897,22 @@ impl SwapchainPresentInfo { Ok(()) } + + pub(crate) fn to_vk_fields1(&self) -> SwapchainPresentInfoFields1Vk { + let present_region_rectangles_vk = self + .present_region + .iter() + .map(RectangleLayer::to_vk) + .collect(); + + SwapchainPresentInfoFields1Vk { + present_region_rectangles_vk, + } + } +} + +pub(crate) struct SwapchainPresentInfoFields1Vk { + pub(crate) present_region_rectangles_vk: SmallVec<[ash::vk::RectLayerKHR; 4]>, } /// Represents a rectangular region on an image layer. @@ -708,21 +936,25 @@ impl RectangleLayer { && self.offset[1] + self.extent[1] <= swapchain.image_extent()[1] && self.layer < swapchain.image_array_layers() } -} -impl From<&RectangleLayer> for ash::vk::RectLayerKHR { - #[inline] - fn from(val: &RectangleLayer) -> Self { + #[allow(clippy::wrong_self_convention)] + pub(crate) fn to_vk(&self) -> ash::vk::RectLayerKHR { + let &Self { + offset, + extent, + layer, + } = self; + ash::vk::RectLayerKHR { offset: ash::vk::Offset2D { - x: val.offset[0] as i32, - y: val.offset[1] as i32, + x: offset[0] as i32, + y: offset[1] as i32, }, extent: ash::vk::Extent2D { - width: val.extent[0], - height: val.extent[1], + width: extent[0], + height: extent[1], }, - layer: val.layer, + layer, } } } @@ -768,6 +1000,15 @@ impl SemaphorePresentInfo { Ok(()) } + + pub(crate) fn to_vk(&self) -> ash::vk::Semaphore { + let &Self { + ref semaphore, + _ne: _, + } = self; + + semaphore.handle() + } } /// Represents a swapchain image being presented on the screen. @@ -824,11 +1065,11 @@ where } if device.enabled_extensions().khr_incremental_present { - for rectangle in &swapchain_info.present_regions { + for rectangle in &swapchain_info.present_region { assert!(rectangle.is_compatible_with(swapchain_info.swapchain.as_ref())); } } else { - swapchain_info.present_regions = Default::default(); + swapchain_info.present_region = Default::default(); } let _queue = self.previous.queue(); @@ -838,7 +1079,7 @@ where Ok(match self.previous.build_submission()? { SubmitAnyBuilder::Empty => SubmitAnyBuilder::QueuePresent(PresentInfo { - swapchains: vec![self.swapchain_info.clone()], + swapchain_infos: vec![self.swapchain_info.clone()], ..Default::default() }), SubmitAnyBuilder::SemaphoresWait(semaphores) => { @@ -847,7 +1088,7 @@ where .into_iter() .map(SemaphorePresentInfo::new) .collect(), - swapchains: vec![self.swapchain_info.clone()], + swapchain_infos: vec![self.swapchain_info.clone()], ..Default::default() }) } @@ -855,7 +1096,7 @@ where self.previous.flush()?; SubmitAnyBuilder::QueuePresent(PresentInfo { - swapchains: vec![self.swapchain_info.clone()], + swapchain_infos: vec![self.swapchain_info.clone()], ..Default::default() }) } @@ -863,24 +1104,26 @@ where self.previous.flush()?; SubmitAnyBuilder::QueuePresent(PresentInfo { - swapchains: vec![self.swapchain_info.clone()], + swapchain_infos: vec![self.swapchain_info.clone()], ..Default::default() }) } SubmitAnyBuilder::QueuePresent(mut present_info) => { - if present_info.swapchains.first().map_or(false, |prev| { + if present_info.swapchain_infos.first().map_or(false, |prev| { prev.present_mode.is_some() != self.swapchain_info.present_mode.is_some() }) { // If the present mode Option variants don't match, create a new command. self.previous.flush()?; SubmitAnyBuilder::QueuePresent(PresentInfo { - swapchains: vec![self.swapchain_info.clone()], + swapchain_infos: vec![self.swapchain_info.clone()], ..Default::default() }) } else { // Otherwise, add our swapchain to the previous. - present_info.swapchains.push(self.swapchain_info.clone()); + present_info + .swapchain_infos + .push(self.swapchain_info.clone()); SubmitAnyBuilder::QueuePresent(present_info) } @@ -900,7 +1143,7 @@ where SubmitAnyBuilder::QueuePresent(present_info) => { let PresentInfo { wait_semaphores: _, - swapchains, + swapchain_infos: swapchains, _ne: _, } = &present_info; @@ -909,7 +1152,7 @@ where ref swapchain, image_index: _, present_id, - present_regions: _, + present_region: _, present_mode: _, _ne: _, } = swapchain_info; diff --git a/vulkano/src/swapchain/mod.rs b/vulkano/src/swapchain/mod.rs index 728c67e6..12b3e2b0 100644 --- a/vulkano/src/swapchain/mod.rs +++ b/vulkano/src/swapchain/mod.rs @@ -978,135 +978,13 @@ impl Swapchain { create_info: &SwapchainCreateInfo, old_swapchain: Option<&Swapchain>, ) -> Result<(ash::vk::SwapchainKHR, Vec), VulkanError> { - let &SwapchainCreateInfo { - flags, - min_image_count, - image_format, - ref image_view_formats, - image_color_space, - image_extent, - image_array_layers, - image_usage, - ref image_sharing, - pre_transform, - composite_alpha, - present_mode, - ref present_modes, - clipped, - scaling_behavior, - present_gravity, - full_screen_exclusive, - win32_monitor, - _ne: _, - } = create_info; - - let (image_sharing_mode_vk, queue_family_index_count_vk, p_queue_family_indices_vk) = - match image_sharing { - Sharing::Exclusive => (ash::vk::SharingMode::EXCLUSIVE, 0, ptr::null()), - Sharing::Concurrent(ref ids) => ( - ash::vk::SharingMode::CONCURRENT, - ids.len() as u32, - ids.as_ptr(), - ), - }; - - let mut create_info_vk = ash::vk::SwapchainCreateInfoKHR { - flags: flags.into(), - surface: surface.handle(), - min_image_count, - image_format: image_format.into(), - image_color_space: image_color_space.into(), - image_extent: ash::vk::Extent2D { - width: image_extent[0], - height: image_extent[1], - }, - image_array_layers, - image_usage: image_usage.into(), - image_sharing_mode: image_sharing_mode_vk, - queue_family_index_count: queue_family_index_count_vk, - p_queue_family_indices: p_queue_family_indices_vk, - pre_transform: pre_transform.into(), - composite_alpha: composite_alpha.into(), - present_mode: present_mode.into(), - clipped: clipped as ash::vk::Bool32, - old_swapchain: old_swapchain.map_or(ash::vk::SwapchainKHR::null(), |os| os.handle), - ..Default::default() - }; - let mut format_list_info_vk = None; - let format_list_view_formats_vk: Vec<_>; - let mut full_screen_exclusive_info_vk = None; - let mut full_screen_exclusive_win32_info_vk = None; - let mut present_modes_info_vk = None; - let present_modes_vk: SmallVec<[ash::vk::PresentModeKHR; PresentMode::COUNT]>; - let mut present_scaling_info_vk = None; - - if !image_view_formats.is_empty() { - format_list_view_formats_vk = image_view_formats - .iter() - .copied() - .map(ash::vk::Format::from) - .collect(); - - let next = format_list_info_vk.insert(ash::vk::ImageFormatListCreateInfo { - view_format_count: format_list_view_formats_vk.len() as u32, - p_view_formats: format_list_view_formats_vk.as_ptr(), - ..Default::default() - }); - - next.p_next = create_info_vk.p_next; - create_info_vk.p_next = <*const _>::cast(next); - } - - if full_screen_exclusive != FullScreenExclusive::Default { - let next = - full_screen_exclusive_info_vk.insert(ash::vk::SurfaceFullScreenExclusiveInfoEXT { - full_screen_exclusive: full_screen_exclusive.into(), - ..Default::default() - }); - - next.p_next = create_info_vk.p_next.cast_mut(); - create_info_vk.p_next = <*const _>::cast(next); - } - - if let Some(Win32Monitor(hmonitor)) = win32_monitor { - let next = full_screen_exclusive_win32_info_vk.insert( - ash::vk::SurfaceFullScreenExclusiveWin32InfoEXT { - hmonitor, - ..Default::default() - }, - ); - - next.p_next = create_info_vk.p_next.cast_mut(); - create_info_vk.p_next = <*const _>::cast(next); - } - - if !present_modes.is_empty() { - present_modes_vk = present_modes.iter().copied().map(Into::into).collect(); - - let next = present_modes_info_vk.insert(ash::vk::SwapchainPresentModesCreateInfoEXT { - present_mode_count: present_modes_vk.len() as u32, - p_present_modes: present_modes_vk.as_ptr(), - ..Default::default() - }); - - next.p_next = create_info_vk.p_next.cast_mut(); - create_info_vk.p_next = <*const _>::cast(next); - } - - if scaling_behavior.is_some() || present_gravity.is_some() { - let [present_gravity_x, present_gravity_y] = - present_gravity.map_or_else(Default::default, |pg| pg.map(Into::into)); - let next = - present_scaling_info_vk.insert(ash::vk::SwapchainPresentScalingCreateInfoEXT { - scaling_behavior: scaling_behavior.map_or_else(Default::default, Into::into), - present_gravity_x, - present_gravity_y, - ..Default::default() - }); - - next.p_next = create_info_vk.p_next.cast_mut(); - create_info_vk.p_next = <*const _>::cast(next); - } + let create_info_fields1_vk = create_info.to_vk_fields1(); + let mut create_info_extensions_vk = create_info.to_vk_extensions(&create_info_fields1_vk); + let create_info_vk = create_info.to_vk( + surface.handle(), + old_swapchain.map_or(ash::vk::SwapchainKHR::null(), |os| os.handle), + &mut create_info_extensions_vk, + ); let fns = device.fns(); @@ -1458,26 +1336,7 @@ impl Swapchain { &self, acquire_info: &AcquireNextImageInfo, ) -> Result { - let &AcquireNextImageInfo { - timeout, - ref semaphore, - ref fence, - _ne: _, - } = acquire_info; - - let acquire_info_vk = ash::vk::AcquireNextImageInfoKHR { - swapchain: self.handle, - timeout: timeout.map_or(u64::MAX, |duration| { - u64::try_from(duration.as_nanos()).unwrap() - }), - semaphore: semaphore - .as_ref() - .map(VulkanObject::handle) - .unwrap_or_default(), - fence: fence.as_ref().map(VulkanObject::handle).unwrap_or_default(), - device_mask: self.device.device_mask(), - ..Default::default() - }; + let acquire_info_vk = acquire_info.to_vk(self.handle(), self.device.device_mask()); let fns = self.device.fns(); let mut output = MaybeUninit::uninit(); @@ -2326,6 +2185,186 @@ impl SwapchainCreateInfo { Ok(()) } + + pub(crate) fn to_vk<'a>( + &'a self, + surface_vk: ash::vk::SurfaceKHR, + old_swapchain_vk: ash::vk::SwapchainKHR, + extensions_vk: &'a mut SwapchainCreateInfoExtensionsVk<'_>, + ) -> ash::vk::SwapchainCreateInfoKHR<'a> { + let &Self { + flags, + min_image_count, + image_format, + image_view_formats: _, + image_color_space, + image_extent, + image_array_layers, + image_usage, + ref image_sharing, + pre_transform, + composite_alpha, + present_mode, + present_modes: _, + clipped, + scaling_behavior: _, + present_gravity: _, + full_screen_exclusive: _, + win32_monitor: _, + _ne: _, + } = self; + + let (image_sharing_mode_vk, queue_family_indices_vk) = match image_sharing { + Sharing::Exclusive => (ash::vk::SharingMode::EXCLUSIVE, [].as_slice()), + Sharing::Concurrent(ref ids) => (ash::vk::SharingMode::CONCURRENT, ids.as_slice()), + }; + + let mut val_vk = ash::vk::SwapchainCreateInfoKHR::default() + .flags(flags.into()) + .surface(surface_vk) + .min_image_count(min_image_count) + .image_format(image_format.into()) + .image_color_space(image_color_space.into()) + .image_extent(ash::vk::Extent2D { + width: image_extent[0], + height: image_extent[1], + }) + .image_array_layers(image_array_layers) + .image_usage(image_usage.into()) + .image_sharing_mode(image_sharing_mode_vk) + .queue_family_indices(queue_family_indices_vk) + .pre_transform(pre_transform.into()) + .composite_alpha(composite_alpha.into()) + .present_mode(present_mode.into()) + .clipped(clipped) + .old_swapchain(old_swapchain_vk); + + let SwapchainCreateInfoExtensionsVk { + full_screen_exclusive_vk, + full_screen_exclusive_win32_vk, + image_format_list_vk, + present_modes_vk, + present_scaling_vk, + } = extensions_vk; + + if let Some(next) = full_screen_exclusive_vk { + val_vk = val_vk.push_next(next); + } + + if let Some(next) = full_screen_exclusive_win32_vk { + val_vk = val_vk.push_next(next); + } + + if let Some(next) = image_format_list_vk { + val_vk = val_vk.push_next(next); + } + + if let Some(next) = present_modes_vk { + val_vk = val_vk.push_next(next); + } + + if let Some(next) = present_scaling_vk { + val_vk = val_vk.push_next(next); + } + + val_vk + } + + pub(crate) fn to_vk_extensions<'a>( + &self, + fields1_vk: &'a SwapchainCreateInfoFields1Vk, + ) -> SwapchainCreateInfoExtensionsVk<'a> { + let &Self { + flags: _, + min_image_count: _, + image_format: _, + image_view_formats: _, + image_color_space: _, + image_extent: _, + image_array_layers: _, + image_usage: _, + image_sharing: _, + pre_transform: _, + composite_alpha: _, + present_mode: _, + present_modes: _, + clipped: _, + scaling_behavior, + present_gravity, + full_screen_exclusive, + win32_monitor, + _ne: _, + } = self; + let SwapchainCreateInfoFields1Vk { + present_modes_vk, + view_formats_vk, + } = fields1_vk; + + let full_screen_exclusive_vk = (full_screen_exclusive != FullScreenExclusive::Default) + .then(|| { + ash::vk::SurfaceFullScreenExclusiveInfoEXT::default() + .full_screen_exclusive(full_screen_exclusive.into()) + }); + + let full_screen_exclusive_win32_vk = win32_monitor.map(|win32_monitor| { + ash::vk::SurfaceFullScreenExclusiveWin32InfoEXT::default().hmonitor(win32_monitor.0) + }); + + let image_format_list_vk = (!view_formats_vk.is_empty()) + .then(|| ash::vk::ImageFormatListCreateInfo::default().view_formats(view_formats_vk)); + + let present_modes_vk = (!present_modes_vk.is_empty()).then(|| { + ash::vk::SwapchainPresentModesCreateInfoEXT::default().present_modes(present_modes_vk) + }); + + let present_scaling_vk = + (scaling_behavior.is_some() || present_gravity.is_some()).then(|| { + let [present_gravity_x, present_gravity_y] = + present_gravity.map_or_else(Default::default, |pg| pg.map(Into::into)); + ash::vk::SwapchainPresentScalingCreateInfoEXT::default() + .scaling_behavior(scaling_behavior.map_or_else(Default::default, Into::into)) + .present_gravity_x(present_gravity_x) + .present_gravity_y(present_gravity_y) + }); + + SwapchainCreateInfoExtensionsVk { + full_screen_exclusive_vk, + full_screen_exclusive_win32_vk, + image_format_list_vk, + present_modes_vk, + present_scaling_vk, + } + } + + pub(crate) fn to_vk_fields1(&self) -> SwapchainCreateInfoFields1Vk { + let present_modes_vk = self.present_modes.iter().copied().map(Into::into).collect(); + let view_formats_vk = self + .image_view_formats + .iter() + .copied() + .map(ash::vk::Format::from) + .collect(); + + SwapchainCreateInfoFields1Vk { + present_modes_vk, + view_formats_vk, + } + } +} + +pub(crate) struct SwapchainCreateInfoExtensionsVk<'a> { + pub(crate) full_screen_exclusive_vk: + Option>, + pub(crate) full_screen_exclusive_win32_vk: + Option>, + pub(crate) image_format_list_vk: Option>, + pub(crate) present_modes_vk: Option>, + pub(crate) present_scaling_vk: Option>, +} + +pub(crate) struct SwapchainCreateInfoFields1Vk { + pub(crate) present_modes_vk: SmallVec<[ash::vk::PresentModeKHR; PresentMode::COUNT]>, + pub(crate) view_formats_vk: Vec, } vulkan_bitflags! { diff --git a/vulkano/src/swapchain/surface.rs b/vulkano/src/swapchain/surface.rs index 854cfc05..ee3301d6 100644 --- a/vulkano/src/swapchain/surface.rs +++ b/vulkano/src/swapchain/surface.rs @@ -19,6 +19,7 @@ use std::{ error::Error, ffi::c_void, fmt::{Debug, Display, Error as FmtError, Formatter}, + marker::PhantomData, mem::MaybeUninit, num::NonZeroU64, ptr, @@ -208,17 +209,15 @@ impl Surface { instance: Arc, object: Option>, ) -> Result, VulkanError> { - let create_info = ash::vk::HeadlessSurfaceCreateInfoEXT { - flags: ash::vk::HeadlessSurfaceCreateFlagsEXT::empty(), - ..Default::default() - }; + let create_info_vk = ash::vk::HeadlessSurfaceCreateInfoEXT::default() + .flags(ash::vk::HeadlessSurfaceCreateFlagsEXT::empty()); let handle = { let fns = instance.fns(); let mut output = MaybeUninit::uninit(); (fns.ext_headless_surface.create_headless_surface_ext)( instance.handle(), - &create_info, + &create_info_vk, ptr::null(), output.as_mut_ptr(), ) @@ -368,31 +367,7 @@ impl Surface { display_mode: Arc, create_info: DisplaySurfaceCreateInfo, ) -> Result, VulkanError> { - let &DisplaySurfaceCreateInfo { - plane_index, - plane_stack_index, - transform, - alpha_mode, - global_alpha, - image_extent, - _ne: _, - } = &create_info; - - let create_info_vk = ash::vk::DisplaySurfaceCreateInfoKHR { - flags: ash::vk::DisplaySurfaceCreateFlagsKHR::empty(), - display_mode: display_mode.handle(), - plane_index, - plane_stack_index, - transform: transform.into(), - alpha_mode: alpha_mode.into(), - global_alpha, - image_extent: ash::vk::Extent2D { - width: image_extent[0], - height: image_extent[1], - }, - ..Default::default() - }; - + let create_info_vk = create_info.to_vk(display_mode.handle()); let instance = display_mode.instance(); let handle = { @@ -459,18 +434,16 @@ impl Surface { window: *mut ash::vk::ANativeWindow, object: Option>, ) -> Result, VulkanError> { - let create_info = ash::vk::AndroidSurfaceCreateInfoKHR { - flags: ash::vk::AndroidSurfaceCreateFlagsKHR::empty(), - window, - ..Default::default() - }; + let create_info_vk = ash::vk::AndroidSurfaceCreateInfoKHR::default() + .flags(ash::vk::AndroidSurfaceCreateFlagsKHR::empty()) + .window(window); let handle = { let fns = instance.fns(); let mut output = MaybeUninit::uninit(); (fns.khr_android_surface.create_android_surface_khr)( instance.handle(), - &create_info, + &create_info_vk, ptr::null(), output.as_mut_ptr(), ) @@ -538,19 +511,17 @@ impl Surface { surface: *mut ash::vk::IDirectFBSurface, object: Option>, ) -> Result, VulkanError> { - let create_info = ash::vk::DirectFBSurfaceCreateInfoEXT { - flags: ash::vk::DirectFBSurfaceCreateFlagsEXT::empty(), - dfb, - surface, - ..Default::default() - }; + let create_info_vk = ash::vk::DirectFBSurfaceCreateInfoEXT::default() + .flags(ash::vk::DirectFBSurfaceCreateFlagsEXT::empty()) + .dfb(dfb) + .surface(surface); let handle = { let fns = instance.fns(); let mut output = MaybeUninit::uninit(); (fns.ext_directfb_surface.create_direct_fb_surface_ext)( instance.handle(), - &create_info, + &create_info_vk, ptr::null(), output.as_mut_ptr(), ) @@ -613,11 +584,9 @@ impl Surface { image_pipe_handle: ash::vk::zx_handle_t, object: Option>, ) -> Result, VulkanError> { - let create_info = ash::vk::ImagePipeSurfaceCreateInfoFUCHSIA { - flags: ash::vk::ImagePipeSurfaceCreateFlagsFUCHSIA::empty(), - image_pipe_handle, - ..Default::default() - }; + let create_info_vk = ash::vk::ImagePipeSurfaceCreateInfoFUCHSIA::default() + .flags(ash::vk::ImagePipeSurfaceCreateFlagsFUCHSIA::empty()) + .image_pipe_handle(image_pipe_handle); let handle = { let fns = instance.fns(); @@ -625,7 +594,7 @@ impl Surface { (fns.fuchsia_imagepipe_surface .create_image_pipe_surface_fuchsia)( instance.handle(), - &create_info, + &create_info_vk, ptr::null(), output.as_mut_ptr(), ) @@ -688,11 +657,9 @@ impl Surface { stream_descriptor: ash::vk::GgpStreamDescriptor, object: Option>, ) -> Result, VulkanError> { - let create_info = ash::vk::StreamDescriptorSurfaceCreateInfoGGP { - flags: ash::vk::StreamDescriptorSurfaceCreateFlagsGGP::empty(), - stream_descriptor, - ..Default::default() - }; + let create_info_vk = ash::vk::StreamDescriptorSurfaceCreateInfoGGP::default() + .flags(ash::vk::StreamDescriptorSurfaceCreateFlagsGGP::empty()) + .stream_descriptor(stream_descriptor); let handle = { let fns = instance.fns(); @@ -700,7 +667,7 @@ impl Surface { (fns.ggp_stream_descriptor_surface .create_stream_descriptor_surface_ggp)( instance.handle(), - &create_info, + &create_info_vk, ptr::null(), output.as_mut_ptr(), ) @@ -763,18 +730,16 @@ impl Surface { view: *const c_void, object: Option>, ) -> Result, VulkanError> { - let create_info = ash::vk::IOSSurfaceCreateInfoMVK { - flags: ash::vk::IOSSurfaceCreateFlagsMVK::empty(), - p_view: view, - ..Default::default() - }; + let create_info_vk = ash::vk::IOSSurfaceCreateInfoMVK::default() + .flags(ash::vk::IOSSurfaceCreateFlagsMVK::empty()) + .view(view); let handle = { let fns = instance.fns(); let mut output = MaybeUninit::uninit(); (fns.mvk_ios_surface.create_ios_surface_mvk)( instance.handle(), - &create_info, + &create_info_vk, ptr::null(), output.as_mut_ptr(), ) @@ -837,18 +802,16 @@ impl Surface { view: *const c_void, object: Option>, ) -> Result, VulkanError> { - let create_info = ash::vk::MacOSSurfaceCreateInfoMVK { - flags: ash::vk::MacOSSurfaceCreateFlagsMVK::empty(), - p_view: view, - ..Default::default() - }; + let create_info_vk = ash::vk::MacOSSurfaceCreateInfoMVK::default() + .flags(ash::vk::MacOSSurfaceCreateFlagsMVK::empty()) + .view(view); let handle = { let fns = instance.fns(); let mut output = MaybeUninit::uninit(); (fns.mvk_macos_surface.create_mac_os_surface_mvk)( instance.handle(), - &create_info, + &create_info_vk, ptr::null(), output.as_mut_ptr(), ) @@ -913,18 +876,16 @@ impl Surface { layer: *const ash::vk::CAMetalLayer, object: Option>, ) -> Result, VulkanError> { - let create_info = ash::vk::MetalSurfaceCreateInfoEXT { - flags: ash::vk::MetalSurfaceCreateFlagsEXT::empty(), - p_layer: layer, - ..Default::default() - }; + let create_info_vk = ash::vk::MetalSurfaceCreateInfoEXT::default() + .flags(ash::vk::MetalSurfaceCreateFlagsEXT::empty()) + .layer(layer); let handle = { let fns = instance.fns(); let mut output = MaybeUninit::uninit(); (fns.ext_metal_surface.create_metal_surface_ext)( instance.handle(), - &create_info, + &create_info_vk, ptr::null(), output.as_mut_ptr(), ) @@ -992,7 +953,7 @@ impl Surface { window: *mut ash::vk::_screen_window, object: Option>, ) -> Result, VulkanError> { - let create_info = ash::vk::ScreenSurfaceCreateInfoQNX { + let create_info_vk = ash::vk::ScreenSurfaceCreateInfoQNX { flags: ash::vk::ScreenSurfaceCreateFlagsQNX::empty(), context, window, @@ -1004,7 +965,7 @@ impl Surface { let mut output = MaybeUninit::uninit(); (fns.qnx_screen_surface.create_screen_surface_qnx)( instance.handle(), - &create_info, + &create_info_vk, ptr::null(), output.as_mut_ptr(), ) @@ -1063,18 +1024,16 @@ impl Surface { window: *mut c_void, object: Option>, ) -> Result, VulkanError> { - let create_info = ash::vk::ViSurfaceCreateInfoNN { - flags: ash::vk::ViSurfaceCreateFlagsNN::empty(), - window, - ..Default::default() - }; + let create_info_vk = ash::vk::ViSurfaceCreateInfoNN::default() + .flags(ash::vk::ViSurfaceCreateFlagsNN::empty()) + .window(window); let handle = { let fns = instance.fns(); let mut output = MaybeUninit::uninit(); (fns.nn_vi_surface.create_vi_surface_nn)( instance.handle(), - &create_info, + &create_info_vk, ptr::null(), output.as_mut_ptr(), ) @@ -1144,19 +1103,17 @@ impl Surface { surface: *mut ash::vk::wl_surface, object: Option>, ) -> Result, VulkanError> { - let create_info = ash::vk::WaylandSurfaceCreateInfoKHR { - flags: ash::vk::WaylandSurfaceCreateFlagsKHR::empty(), - display, - surface, - ..Default::default() - }; + let create_info_vk = ash::vk::WaylandSurfaceCreateInfoKHR::default() + .flags(ash::vk::WaylandSurfaceCreateFlagsKHR::empty()) + .display(display) + .surface(surface); let handle = { let fns = instance.fns(); let mut output = MaybeUninit::uninit(); (fns.khr_wayland_surface.create_wayland_surface_khr)( instance.handle(), - &create_info, + &create_info_vk, ptr::null(), output.as_mut_ptr(), ) @@ -1226,19 +1183,17 @@ impl Surface { hwnd: ash::vk::HWND, object: Option>, ) -> Result, VulkanError> { - let create_info = ash::vk::Win32SurfaceCreateInfoKHR { - flags: ash::vk::Win32SurfaceCreateFlagsKHR::empty(), - hinstance, - hwnd, - ..Default::default() - }; + let create_info_vk = ash::vk::Win32SurfaceCreateInfoKHR::default() + .flags(ash::vk::Win32SurfaceCreateFlagsKHR::empty()) + .hinstance(hinstance) + .hwnd(hwnd); let handle = { let fns = instance.fns(); let mut output = MaybeUninit::uninit(); (fns.khr_win32_surface.create_win32_surface_khr)( instance.handle(), - &create_info, + &create_info_vk, ptr::null(), output.as_mut_ptr(), ) @@ -1308,19 +1263,17 @@ impl Surface { window: ash::vk::xcb_window_t, object: Option>, ) -> Result, VulkanError> { - let create_info = ash::vk::XcbSurfaceCreateInfoKHR { - flags: ash::vk::XcbSurfaceCreateFlagsKHR::empty(), - connection, - window, - ..Default::default() - }; + let create_info_vk = ash::vk::XcbSurfaceCreateInfoKHR::default() + .flags(ash::vk::XcbSurfaceCreateFlagsKHR::empty()) + .connection(connection) + .window(window); let handle = { let fns = instance.fns(); let mut output = MaybeUninit::uninit(); (fns.khr_xcb_surface.create_xcb_surface_khr)( instance.handle(), - &create_info, + &create_info_vk, ptr::null(), output.as_mut_ptr(), ) @@ -1390,19 +1343,17 @@ impl Surface { window: ash::vk::Window, object: Option>, ) -> Result, VulkanError> { - let create_info = ash::vk::XlibSurfaceCreateInfoKHR { - flags: ash::vk::XlibSurfaceCreateFlagsKHR::empty(), - dpy: display, - window, - ..Default::default() - }; + let create_info_vk = ash::vk::XlibSurfaceCreateInfoKHR::default() + .flags(ash::vk::XlibSurfaceCreateFlagsKHR::empty()) + .dpy(display) + .window(window); let handle = { let fns = instance.fns(); let mut output = MaybeUninit::uninit(); (fns.khr_xlib_surface.create_xlib_surface_khr)( instance.handle(), - &create_info, + &create_info_vk, ptr::null(), output.as_mut_ptr(), ) @@ -1627,6 +1578,34 @@ impl DisplaySurfaceCreateInfo { Ok(()) } + + pub(crate) fn to_vk( + &self, + display_mode_vk: ash::vk::DisplayModeKHR, + ) -> ash::vk::DisplaySurfaceCreateInfoKHR<'static> { + let &Self { + plane_index, + plane_stack_index, + transform, + alpha_mode, + global_alpha, + image_extent, + _ne: _, + } = self; + + ash::vk::DisplaySurfaceCreateInfoKHR::default() + .flags(ash::vk::DisplaySurfaceCreateFlagsKHR::empty()) + .display_mode(display_mode_vk) + .plane_index(plane_index) + .plane_stack_index(plane_stack_index) + .transform(transform.into()) + .alpha_mode(alpha_mode.into()) + .global_alpha(global_alpha) + .image_extent(ash::vk::Extent2D { + width: image_extent[0], + height: image_extent[1], + }) + } } /// The windowing API function that was used to construct a surface. @@ -2156,6 +2135,71 @@ impl SurfaceInfo { Ok(()) } + + pub(crate) fn to_vk2<'a>( + &self, + surface_vk: ash::vk::SurfaceKHR, + extensions_vk: &'a mut SurfaceInfo2ExtensionsVk, + ) -> ash::vk::PhysicalDeviceSurfaceInfo2KHR<'a> { + let mut val_vk = ash::vk::PhysicalDeviceSurfaceInfo2KHR::default().surface(surface_vk); + + let SurfaceInfo2ExtensionsVk { + full_screen_exclusive_vk, + full_screen_exclusive_win32_vk, + present_mode_vk, + } = extensions_vk; + + if let Some(next) = full_screen_exclusive_vk { + val_vk = val_vk.push_next(next); + } + + if let Some(next) = full_screen_exclusive_win32_vk { + val_vk = val_vk.push_next(next); + } + + if let Some(next) = present_mode_vk { + val_vk = val_vk.push_next(next); + } + + val_vk + } + + pub(crate) fn to_vk2_extensions(&self) -> SurfaceInfo2ExtensionsVk { + let &Self { + present_mode, + full_screen_exclusive, + win32_monitor, + _ne, + } = self; + + let full_screen_exclusive_vk = (full_screen_exclusive != FullScreenExclusive::Default) + .then(|| { + ash::vk::SurfaceFullScreenExclusiveInfoEXT::default() + .full_screen_exclusive(full_screen_exclusive.into()) + }); + + let full_screen_exclusive_win32_vk = win32_monitor.map(|win32_monitor| { + ash::vk::SurfaceFullScreenExclusiveWin32InfoEXT::default().hmonitor(win32_monitor.0) + }); + + let present_mode_vk = present_mode.map(|present_mode| { + ash::vk::SurfacePresentModeEXT::default().present_mode(present_mode.into()) + }); + + SurfaceInfo2ExtensionsVk { + full_screen_exclusive_vk, + full_screen_exclusive_win32_vk, + present_mode_vk, + } + } +} + +pub(crate) struct SurfaceInfo2ExtensionsVk { + pub(crate) full_screen_exclusive_vk: + Option>, + pub(crate) full_screen_exclusive_win32_vk: + Option>, + pub(crate) present_mode_vk: Option>, } /// The capabilities of a surface when used by a physical device. @@ -2249,6 +2293,241 @@ pub struct SurfaceCapabilities { pub full_screen_exclusive_supported: bool, } +impl SurfaceCapabilities { + pub(crate) fn to_mut_vk2<'a>( + extensions_vk: &'a mut SurfaceCapabilities2ExtensionsVk<'_>, + ) -> ash::vk::SurfaceCapabilities2KHR<'a> { + let mut val_vk = ash::vk::SurfaceCapabilities2KHR::default(); + + let SurfaceCapabilities2ExtensionsVk { + full_screen_exclusive_vk, + present_mode_compatibility_vk: present_modes_vk, + present_scaling_vk, + protected_vk, + } = extensions_vk; + + if let Some(next) = full_screen_exclusive_vk { + val_vk = val_vk.push_next(next); + } + + if let Some(next) = present_modes_vk { + val_vk = val_vk.push_next(next); + } + + if let Some(next) = present_scaling_vk { + val_vk = val_vk.push_next(next); + } + + if let Some(next) = protected_vk { + val_vk = val_vk.push_next(next); + } + + val_vk + } + + pub(crate) fn to_mut_vk2_extensions<'a>( + fields1_vk: &'a mut SurfaceCapabilities2Fields1Vk, + physical_device: &PhysicalDevice, + surface_info: &SurfaceInfo, + ) -> SurfaceCapabilities2ExtensionsVk<'a> { + let SurfaceCapabilities2Fields1Vk { present_modes_vk } = fields1_vk; + + let full_screen_exclusive_vk = (surface_info.full_screen_exclusive + != FullScreenExclusive::Default) + .then(ash::vk::SurfaceCapabilitiesFullScreenExclusiveEXT::default); + + let present_mode_compatibility_vk = (surface_info.present_mode.is_some()).then(|| { + ash::vk::SurfacePresentModeCompatibilityEXT::default().present_modes(present_modes_vk) + }); + + let present_scaling_vk = (surface_info.present_mode.is_some()) + .then(ash::vk::SurfacePresentScalingCapabilitiesEXT::default); + + let protected_vk = (physical_device + .instance() + .enabled_extensions() + .khr_surface_protected_capabilities) + .then(ash::vk::SurfaceProtectedCapabilitiesKHR::default); + + SurfaceCapabilities2ExtensionsVk { + full_screen_exclusive_vk, + present_mode_compatibility_vk, + present_scaling_vk, + protected_vk, + } + } + + pub(crate) fn to_mut_vk2_fields() -> SurfaceCapabilities2Fields1Vk { + let present_modes_vk = Default::default(); + + SurfaceCapabilities2Fields1Vk { present_modes_vk } + } + + pub(crate) fn from_vk2( + val_vk: &ash::vk::SurfaceCapabilities2KHR<'_>, + fields1_vk: &SurfaceCapabilities2Fields1Vk, + extensions_vk: &SurfaceCapabilities2ExtensionsVk<'_>, + ) -> Self { + let &ash::vk::SurfaceCapabilities2KHR { + surface_capabilities: + ash::vk::SurfaceCapabilitiesKHR { + min_image_count, + max_image_count, + current_extent, + min_image_extent, + max_image_extent, + max_image_array_layers, + supported_transforms, + current_transform, + supported_composite_alpha, + supported_usage_flags, + }, + .. + } = val_vk; + + let mut val = Self { + min_image_count, + max_image_count: (max_image_count != 0).then_some(max_image_count), + current_extent: filter_max(current_extent), + min_image_extent: [min_image_extent.width, min_image_extent.height], + max_image_extent: [max_image_extent.width, max_image_extent.height], + max_image_array_layers, + supported_transforms: supported_transforms.into(), + current_transform: SurfaceTransforms::from(current_transform) + .into_iter() + .next() + .unwrap(), // TODO: + supported_composite_alpha: supported_composite_alpha.into(), + supported_usage_flags: ImageUsage::from(supported_usage_flags), + + compatible_present_modes: Default::default(), + supported_present_scaling: Default::default(), + supported_present_gravity: Default::default(), + min_scaled_image_extent: Some([min_image_extent.width, min_image_extent.height]), + max_scaled_image_extent: Some([max_image_extent.width, max_image_extent.height]), + supports_protected: false, + full_screen_exclusive_supported: false, + }; + + let SurfaceCapabilities2ExtensionsVk { + full_screen_exclusive_vk, + present_mode_compatibility_vk, + present_scaling_vk, + protected_vk, + } = extensions_vk; + let SurfaceCapabilities2Fields1Vk { present_modes_vk } = fields1_vk; + + if let Some(val_vk) = full_screen_exclusive_vk { + let &ash::vk::SurfaceCapabilitiesFullScreenExclusiveEXT { + full_screen_exclusive_supported, + .. + } = val_vk; + + val = Self { + full_screen_exclusive_supported: full_screen_exclusive_supported != 0, + ..val + }; + } + + if let Some(val_vk) = present_mode_compatibility_vk { + let &ash::vk::SurfacePresentModeCompatibilityEXT { + present_mode_count, .. + } = val_vk; + + val = Self { + compatible_present_modes: present_modes_vk[..present_mode_count as usize] + .iter() + .copied() + .map(PresentMode::try_from) + .filter_map(Result::ok) + .collect(), + ..val + }; + } + + if let Some(val_vk) = present_scaling_vk { + let &ash::vk::SurfacePresentScalingCapabilitiesEXT { + supported_present_scaling, + supported_present_gravity_x, + supported_present_gravity_y, + min_scaled_image_extent, + max_scaled_image_extent, + .. + } = val_vk; + + val = Self { + supported_present_scaling: supported_present_scaling.into(), + supported_present_gravity: [ + supported_present_gravity_x.into(), + supported_present_gravity_y.into(), + ], + min_scaled_image_extent: filter_max(min_scaled_image_extent), + max_scaled_image_extent: filter_max(max_scaled_image_extent), + ..val + }; + } + + if let Some(val_vk) = protected_vk { + let &ash::vk::SurfaceProtectedCapabilitiesKHR { + supports_protected, .. + } = val_vk; + + val = Self { + supports_protected: supports_protected != 0, + ..val + }; + } + + val + } +} + +pub(crate) struct SurfaceCapabilities2ExtensionsVk<'a> { + pub(crate) full_screen_exclusive_vk: + Option>, + pub(crate) present_mode_compatibility_vk: + Option>, + pub(crate) present_scaling_vk: Option>, + pub(crate) protected_vk: Option>, +} + +impl<'a> SurfaceCapabilities2ExtensionsVk<'a> { + pub(crate) fn unborrow(self) -> SurfaceCapabilities2ExtensionsVk<'static> { + let Self { + full_screen_exclusive_vk, + present_mode_compatibility_vk, + present_scaling_vk, + protected_vk, + } = self; + + let present_mode_compatibility_vk = present_mode_compatibility_vk.map(|val_vk| { + ash::vk::SurfacePresentModeCompatibilityEXT { + _marker: PhantomData, + ..val_vk + } + }); + + SurfaceCapabilities2ExtensionsVk { + full_screen_exclusive_vk, + present_mode_compatibility_vk, + present_scaling_vk, + protected_vk, + } + } +} + +pub(crate) struct SurfaceCapabilities2Fields1Vk { + pub(crate) present_modes_vk: [ash::vk::PresentModeKHR; PresentMode::COUNT], +} + +fn filter_max(extent: ash::vk::Extent2D) -> Option<[u32; 2]> { + if extent.width == u32::MAX && extent.height == u32::MAX { + None + } else { + Some([extent.width, extent.height]) + } +} + /// Error that can happen when creating a [`Surface`] from a window. #[derive(Clone, Debug)] pub enum FromWindowError { diff --git a/vulkano/src/sync/event.rs b/vulkano/src/sync/event.rs index 0bea0382..413b320d 100644 --- a/vulkano/src/sync/event.rs +++ b/vulkano/src/sync/event.rs @@ -84,12 +84,7 @@ impl Event { device: Arc, create_info: EventCreateInfo, ) -> Result { - let &EventCreateInfo { flags, _ne: _ } = &create_info; - - let create_info_vk = ash::vk::EventCreateInfo { - flags: flags.into(), - ..Default::default() - }; + let create_info_vk = create_info.to_vk(); let handle = unsafe { let mut output = MaybeUninit::uninit(); @@ -327,6 +322,12 @@ impl EventCreateInfo { Ok(()) } + + pub(crate) fn to_vk(&self) -> ash::vk::EventCreateInfo<'static> { + let &Self { flags, _ne: _ } = self; + + ash::vk::EventCreateInfo::default().flags(flags.into()) + } } vulkan_bitflags! { diff --git a/vulkano/src/sync/fence.rs b/vulkano/src/sync/fence.rs index bcd0e457..bf4a5453 100644 --- a/vulkano/src/sync/fence.rs +++ b/vulkano/src/sync/fence.rs @@ -87,29 +87,8 @@ impl Fence { device: Arc, create_info: FenceCreateInfo, ) -> Result { - let FenceCreateInfo { - flags, - export_handle_types, - _ne: _, - } = create_info; - - let mut create_info_vk = ash::vk::FenceCreateInfo { - flags: flags.into(), - ..Default::default() - }; - let mut export_fence_create_info_vk = None; - - if !export_handle_types.is_empty() { - let _ = export_fence_create_info_vk.insert(ash::vk::ExportFenceCreateInfo { - handle_types: export_handle_types.into(), - ..Default::default() - }); - } - - if let Some(info) = export_fence_create_info_vk.as_mut() { - info.p_next = create_info_vk.p_next; - create_info_vk.p_next = <*const _>::cast(info); - } + let mut create_info_extensions_vk = create_info.to_vk_extensions(); + let create_info_vk = create_info.to_vk(&mut create_info_extensions_vk); let handle = { let fns = device.fns(); @@ -126,16 +105,7 @@ impl Fence { output.assume_init() }; - Ok(Fence { - handle, - device: InstanceOwnedDebugWrapper(device), - id: Self::next_id(), - - flags, - export_handle_types, - - must_put_in_pool: false, - }) + Ok(Self::from_handle(device, handle, create_info)) } /// Takes a fence from the vulkano-provided fence pool. @@ -489,11 +459,9 @@ impl Fence { &self, handle_type: ExternalFenceHandleType, ) -> Result { - let info_vk = ash::vk::FenceGetFdInfoKHR { - fence: self.handle, - handle_type: handle_type.into(), - ..Default::default() - }; + let info_vk = ash::vk::FenceGetFdInfoKHR::default() + .fence(self.handle) + .handle_type(handle_type.into()); let mut output = MaybeUninit::uninit(); let fns = self.device.fns(); @@ -590,11 +558,9 @@ impl Fence { &self, handle_type: ExternalFenceHandleType, ) -> Result { - let info_vk = ash::vk::FenceGetWin32HandleInfoKHR { - fence: self.handle, - handle_type: handle_type.into(), - ..Default::default() - }; + let info_vk = ash::vk::FenceGetWin32HandleInfoKHR::default() + .fence(self.handle) + .handle_type(handle_type.into()); let mut output = MaybeUninit::uninit(); let fns = self.device.fns(); @@ -655,32 +621,7 @@ impl Fence { &self, import_fence_fd_info: ImportFenceFdInfo, ) -> Result<(), VulkanError> { - let ImportFenceFdInfo { - flags, - handle_type, - file, - _ne: _, - } = import_fence_fd_info; - - #[cfg(unix)] - let fd = { - use std::os::fd::IntoRawFd; - file.map_or(-1, |file| file.into_raw_fd()) - }; - - #[cfg(not(unix))] - let fd = { - let _ = file; - -1 - }; - - let info_vk = ash::vk::ImportFenceFdInfoKHR { - fence: self.handle, - flags: flags.into(), - handle_type: handle_type.into(), - fd, - ..Default::default() - }; + let info_vk = import_fence_fd_info.into_vk(self.handle()); let fns = self.device.fns(); (fns.khr_external_fence_fd.import_fence_fd_khr)(self.device.handle(), &info_vk) @@ -736,21 +677,7 @@ impl Fence { &self, import_fence_win32_handle_info: ImportFenceWin32HandleInfo, ) -> Result<(), VulkanError> { - let ImportFenceWin32HandleInfo { - flags, - handle_type, - handle, - _ne: _, - } = import_fence_win32_handle_info; - - let info_vk = ash::vk::ImportFenceWin32HandleInfoKHR { - fence: self.handle, - flags: flags.into(), - handle_type: handle_type.into(), - handle, - name: ptr::null(), // TODO: support? - ..Default::default() - }; + let info_vk = import_fence_win32_handle_info.to_vk(self.handle()); let fns = self.device.fns(); (fns.khr_external_fence_win32.import_fence_win32_handle_khr)( @@ -929,6 +856,45 @@ impl FenceCreateInfo { Ok(()) } + + pub(crate) fn to_vk<'a>( + &self, + extensions_vk: &'a mut FenceCreateInfoExtensionsVk, + ) -> ash::vk::FenceCreateInfo<'a> { + let &Self { + flags, + export_handle_types: _, + _ne: _, + } = self; + + let mut val_vk = ash::vk::FenceCreateInfo::default().flags(flags.into()); + + let FenceCreateInfoExtensionsVk { export_vk } = extensions_vk; + + if let Some(next) = export_vk { + val_vk = val_vk.push_next(next); + } + + val_vk + } + + pub(crate) fn to_vk_extensions(&self) -> FenceCreateInfoExtensionsVk { + let &Self { + flags: _, + export_handle_types, + _ne: _, + } = self; + + let export_vk = (!export_handle_types.is_empty()).then(|| { + ash::vk::ExportFenceCreateInfo::default().handle_types(export_handle_types.into()) + }); + + FenceCreateInfoExtensionsVk { export_vk } + } +} + +pub(crate) struct FenceCreateInfoExtensionsVk { + pub(crate) export_vk: Option>, } vulkan_bitflags! { @@ -1083,6 +1049,36 @@ impl ImportFenceFdInfo { Ok(()) } + + pub(crate) fn into_vk( + self, + fence_vk: ash::vk::Fence, + ) -> ash::vk::ImportFenceFdInfoKHR<'static> { + let ImportFenceFdInfo { + flags, + handle_type, + file, + _ne: _, + } = self; + + #[cfg(unix)] + let fd = { + use std::os::fd::IntoRawFd; + file.map_or(-1, |file| file.into_raw_fd()) + }; + + #[cfg(not(unix))] + let fd = { + let _ = file; + -1 + }; + + ash::vk::ImportFenceFdInfoKHR::default() + .fence(fence_vk) + .flags(flags.into()) + .handle_type(handle_type.into()) + .fd(fd) + } } #[derive(Debug)] @@ -1166,6 +1162,25 @@ impl ImportFenceWin32HandleInfo { Ok(()) } + + pub(crate) fn to_vk( + &self, + fence_vk: ash::vk::Fence, + ) -> ash::vk::ImportFenceWin32HandleInfoKHR<'static> { + let &Self { + flags, + handle_type, + handle, + _ne: _, + } = self; + + ash::vk::ImportFenceWin32HandleInfoKHR::default() + .fence(fence_vk) + .flags(flags.into()) + .handle_type(handle_type.into()) + .handle(handle) + // .name() // TODO: support? + } } /// The fence configuration to query in @@ -1206,6 +1221,15 @@ impl ExternalFenceInfo { Ok(()) } + + pub(crate) fn to_vk(&self) -> ash::vk::PhysicalDeviceExternalFenceInfo<'static> { + let &Self { + handle_type, + _ne: _, + } = self; + + ash::vk::PhysicalDeviceExternalFenceInfo::default().handle_type(handle_type.into()) + } } /// The properties for exporting or importing external handles, when a fence is created @@ -1230,6 +1254,30 @@ pub struct ExternalFenceProperties { pub compatible_handle_types: ExternalFenceHandleTypes, } +impl ExternalFenceProperties { + pub(crate) fn to_mut_vk() -> ash::vk::ExternalFenceProperties<'static> { + ash::vk::ExternalFenceProperties::default() + } + + pub(crate) fn from_vk(val_vk: &ash::vk::ExternalFenceProperties<'_>) -> Self { + let &ash::vk::ExternalFenceProperties { + export_from_imported_handle_types, + compatible_handle_types, + external_fence_features, + .. + } = val_vk; + + ExternalFenceProperties { + exportable: external_fence_features + .intersects(ash::vk::ExternalFenceFeatureFlags::EXPORTABLE), + importable: external_fence_features + .intersects(ash::vk::ExternalFenceFeatureFlags::IMPORTABLE), + export_from_imported_handle_types: export_from_imported_handle_types.into(), + compatible_handle_types: compatible_handle_types.into(), + } + } +} + #[cfg(test)] mod tests { use crate::{ diff --git a/vulkano/src/sync/future/fence_signal.rs b/vulkano/src/sync/future/fence_signal.rs index f2f69c1d..ccf5fb52 100644 --- a/vulkano/src/sync/future/fence_signal.rs +++ b/vulkano/src/sync/future/fence_signal.rs @@ -299,7 +299,7 @@ where ) .map_err(OutcomeErr::Partial) } else { - for swapchain_info in &present_info.swapchains { + for swapchain_info in &present_info.swapchain_infos { if swapchain_info.present_id.map_or(false, |present_id| { !swapchain_info.swapchain.try_claim_present_id(present_id) }) { diff --git a/vulkano/src/sync/future/mod.rs b/vulkano/src/sync/future/mod.rs index 512430eb..ba95dba2 100644 --- a/vulkano/src/sync/future/mod.rs +++ b/vulkano/src/sync/future/mod.rs @@ -571,7 +571,7 @@ pub(crate) unsafe fn queue_present( let PresentInfo { wait_semaphores: _, - swapchains, + swapchain_infos: swapchains, _ne: _, } = &present_info; diff --git a/vulkano/src/sync/future/semaphore_signal.rs b/vulkano/src/sync/future/semaphore_signal.rs index c169a73d..06078271 100644 --- a/vulkano/src/sync/future/semaphore_signal.rs +++ b/vulkano/src/sync/future/semaphore_signal.rs @@ -135,7 +135,7 @@ where builder.submit(&queue)?;*/ } SubmitAnyBuilder::QueuePresent(present_info) => { - for swapchain_info in &present_info.swapchains { + for swapchain_info in &present_info.swapchain_infos { if swapchain_info.present_id.map_or(false, |present_id| { !swapchain_info.swapchain.try_claim_present_id(present_id) }) { diff --git a/vulkano/src/sync/mod.rs b/vulkano/src/sync/mod.rs index 3c9b372b..a1df51c4 100644 --- a/vulkano/src/sync/mod.rs +++ b/vulkano/src/sync/mod.rs @@ -8,7 +8,7 @@ //! knowledge if you want to avoid errors. #[allow(unused)] -pub(crate) use self::pipeline::{PipelineStageAccess, PipelineStageAccessFlags}; +pub(crate) use self::pipeline::*; pub use self::{ future::{now, GpuFuture}, pipeline::{ @@ -17,6 +17,7 @@ pub use self::{ }, }; use crate::{device::Queue, VulkanError}; +use smallvec::SmallVec; use std::{ error::Error, fmt::{Display, Formatter}, @@ -74,10 +75,7 @@ where Concurrent(I), } -impl Sharing -where - I: IntoIterator, -{ +impl Sharing> { /// Returns `true` if `self` is the `Exclusive` variant. #[inline] pub fn is_exclusive(&self) -> bool { @@ -89,6 +87,16 @@ where pub fn is_concurrent(&self) -> bool { matches!(self, Self::Concurrent(..)) } + + pub(crate) fn to_vk(&self) -> (ash::vk::SharingMode, &[u32]) { + match self { + Sharing::Exclusive => (ash::vk::SharingMode::EXCLUSIVE, [].as_slice()), + Sharing::Concurrent(queue_family_indices) => ( + ash::vk::SharingMode::CONCURRENT, + queue_family_indices.as_slice(), + ), + } + } } /// How the memory of a resource is currently being accessed. diff --git a/vulkano/src/sync/pipeline.rs b/vulkano/src/sync/pipeline.rs index 9a2bf431..288704de 100644 --- a/vulkano/src/sync/pipeline.rs +++ b/vulkano/src/sync/pipeline.rs @@ -7,7 +7,7 @@ use crate::{ }, macros::{vulkan_bitflags, vulkan_bitflags_enum}, shader::ShaderStages, - DeviceSize, Requires, RequiresAllOf, RequiresOneOf, ValidationError, + DeviceSize, Requires, RequiresAllOf, RequiresOneOf, ValidationError, VulkanObject, }; use ahash::HashMap; use once_cell::sync::Lazy; @@ -1742,6 +1742,19 @@ pub struct DependencyInfo { pub _ne: crate::NonExhaustive, } +impl Default for DependencyInfo { + #[inline] + fn default() -> Self { + Self { + dependency_flags: DependencyFlags::empty(), + memory_barriers: SmallVec::new(), + buffer_memory_barriers: SmallVec::new(), + image_memory_barriers: SmallVec::new(), + _ne: crate::NonExhaustive(()), + } + } +} + impl DependencyInfo { /// Returns whether `self` contains any barriers. #[inline] @@ -1785,19 +1798,161 @@ impl DependencyInfo { Ok(()) } -} -impl Default for DependencyInfo { - #[inline] - fn default() -> Self { - Self { - dependency_flags: DependencyFlags::empty(), - memory_barriers: SmallVec::new(), - buffer_memory_barriers: SmallVec::new(), - image_memory_barriers: SmallVec::new(), - _ne: crate::NonExhaustive(()), + pub(crate) fn to_vk2<'a>( + &self, + memory_barriers_vk: &'a [ash::vk::MemoryBarrier2<'_>], + buffer_memory_barriers_vk: &'a [ash::vk::BufferMemoryBarrier2<'_>], + image_memory_barriers_vk: &'a [ash::vk::ImageMemoryBarrier2<'_>], + ) -> ash::vk::DependencyInfo<'a> { + let &Self { + dependency_flags, + memory_barriers: _, + buffer_memory_barriers: _, + image_memory_barriers: _, + _ne: _, + } = self; + + ash::vk::DependencyInfo::default() + .dependency_flags(dependency_flags.into()) + .memory_barriers(memory_barriers_vk) + .buffer_memory_barriers(buffer_memory_barriers_vk) + .image_memory_barriers(image_memory_barriers_vk) + } + + pub(crate) fn to_vk2_fields1(&self) -> DependencyInfo2Fields1Vk { + let &Self { + dependency_flags: _, + ref memory_barriers, + ref buffer_memory_barriers, + ref image_memory_barriers, + _ne: _, + } = self; + + let memory_barriers_vk = memory_barriers.iter().map(MemoryBarrier::to_vk2).collect(); + let buffer_memory_barriers_vk = buffer_memory_barriers + .iter() + .map(BufferMemoryBarrier::to_vk2) + .collect(); + let image_memory_barriers_vk = image_memory_barriers + .iter() + .map(ImageMemoryBarrier::to_vk2) + .collect(); + + DependencyInfo2Fields1Vk { + memory_barriers_vk, + buffer_memory_barriers_vk, + image_memory_barriers_vk, } } + + pub(crate) fn to_vk_dependency_flags(&self) -> ash::vk::DependencyFlags { + self.dependency_flags.into() + } + + pub(crate) fn to_vk_fields1(&self) -> DependencyInfoFields1Vk { + let &Self { + dependency_flags: _, + ref memory_barriers, + ref buffer_memory_barriers, + ref image_memory_barriers, + _ne: _, + } = self; + + let mut src_stage_mask_vk = ash::vk::PipelineStageFlags::empty(); + let mut dst_stage_mask_vk = ash::vk::PipelineStageFlags::empty(); + + let memory_barriers_vk = memory_barriers + .iter() + .inspect(|barrier| { + src_stage_mask_vk |= barrier.src_stages.into(); + dst_stage_mask_vk |= barrier.dst_stages.into(); + }) + .map(MemoryBarrier::to_vk) + .collect(); + let buffer_memory_barriers_vk = buffer_memory_barriers + .iter() + .inspect(|barrier| { + src_stage_mask_vk |= barrier.src_stages.into(); + dst_stage_mask_vk |= barrier.dst_stages.into(); + }) + .map(BufferMemoryBarrier::to_vk) + .collect(); + let image_memory_barriers_vk = image_memory_barriers + .iter() + .inspect(|barrier| { + src_stage_mask_vk |= barrier.src_stages.into(); + dst_stage_mask_vk |= barrier.dst_stages.into(); + }) + .map(ImageMemoryBarrier::to_vk) + .collect(); + + if src_stage_mask_vk.is_empty() { + // "VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT is [...] equivalent to + // VK_PIPELINE_STAGE_2_NONE in the first scope." + src_stage_mask_vk |= ash::vk::PipelineStageFlags::TOP_OF_PIPE; + } + + if dst_stage_mask_vk.is_empty() { + // "VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT is [...] equivalent to + // VK_PIPELINE_STAGE_2_NONE in the second scope." + dst_stage_mask_vk |= ash::vk::PipelineStageFlags::BOTTOM_OF_PIPE; + } + + DependencyInfoFields1Vk { + memory_barriers_vk, + buffer_memory_barriers_vk, + image_memory_barriers_vk, + src_stage_mask_vk, + dst_stage_mask_vk, + } + } + + pub(crate) fn to_vk_src_stage_mask(&self) -> ash::vk::PipelineStageFlags { + let &Self { + dependency_flags: _, + ref memory_barriers, + ref buffer_memory_barriers, + ref image_memory_barriers, + _ne: _, + } = self; + + let mut src_stage_mask_vk = ash::vk::PipelineStageFlags::empty(); + + for barrier in memory_barriers { + src_stage_mask_vk |= barrier.src_stages.into(); + } + + for barrier in buffer_memory_barriers { + src_stage_mask_vk |= barrier.src_stages.into(); + } + + for barrier in image_memory_barriers { + src_stage_mask_vk |= barrier.src_stages.into(); + } + + if src_stage_mask_vk.is_empty() { + // "VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT is [...] equivalent to + // VK_PIPELINE_STAGE_2_NONE in the first scope." + src_stage_mask_vk |= ash::vk::PipelineStageFlags::TOP_OF_PIPE; + } + + src_stage_mask_vk + } +} + +pub(crate) struct DependencyInfo2Fields1Vk { + pub(crate) memory_barriers_vk: SmallVec<[ash::vk::MemoryBarrier2<'static>; 2]>, + pub(crate) buffer_memory_barriers_vk: SmallVec<[ash::vk::BufferMemoryBarrier2<'static>; 8]>, + pub(crate) image_memory_barriers_vk: SmallVec<[ash::vk::ImageMemoryBarrier2<'static>; 8]>, +} + +pub(crate) struct DependencyInfoFields1Vk { + pub(crate) memory_barriers_vk: SmallVec<[ash::vk::MemoryBarrier<'static>; 2]>, + pub(crate) buffer_memory_barriers_vk: SmallVec<[ash::vk::BufferMemoryBarrier<'static>; 8]>, + pub(crate) image_memory_barriers_vk: SmallVec<[ash::vk::ImageMemoryBarrier<'static>; 8]>, + pub(crate) src_stage_mask_vk: ash::vk::PipelineStageFlags, + pub(crate) dst_stage_mask_vk: ash::vk::PipelineStageFlags, } vulkan_bitflags! { @@ -2350,6 +2505,36 @@ impl MemoryBarrier { Ok(()) } + + pub(crate) fn to_vk2(&self) -> ash::vk::MemoryBarrier2<'static> { + let &Self { + src_stages, + src_access, + dst_stages, + dst_access, + _ne: _, + } = self; + + ash::vk::MemoryBarrier2::default() + .src_stage_mask(src_stages.into()) + .src_access_mask(src_access.into()) + .dst_stage_mask(dst_stages.into()) + .dst_access_mask(dst_access.into()) + } + + pub(crate) fn to_vk(&self) -> ash::vk::MemoryBarrier<'static> { + let &Self { + src_stages: _, + src_access, + dst_stages: _, + dst_access, + _ne: _, + } = self; + + ash::vk::MemoryBarrier::default() + .src_access_mask(src_access.into()) + .dst_access_mask(dst_access.into()) + } } /// A memory barrier that is applied to a single buffer. @@ -3011,6 +3196,64 @@ impl BufferMemoryBarrier { Ok(()) } + + pub(crate) fn to_vk2(&self) -> ash::vk::BufferMemoryBarrier2<'static> { + let &Self { + src_stages, + src_access, + dst_stages, + dst_access, + ref queue_family_ownership_transfer, + ref buffer, + ref range, + _ne: _, + } = self; + + let (src_queue_family_index, dst_queue_family_index) = + queue_family_ownership_transfer.as_ref().map_or( + (ash::vk::QUEUE_FAMILY_IGNORED, ash::vk::QUEUE_FAMILY_IGNORED), + QueueFamilyOwnershipTransfer::to_vk, + ); + + ash::vk::BufferMemoryBarrier2::default() + .src_stage_mask(src_stages.into()) + .src_access_mask(src_access.into()) + .dst_stage_mask(dst_stages.into()) + .dst_access_mask(dst_access.into()) + .src_queue_family_index(src_queue_family_index) + .dst_queue_family_index(dst_queue_family_index) + .buffer(buffer.handle()) + .offset(range.start) + .size(range.end - range.start) + } + + pub(crate) fn to_vk(&self) -> ash::vk::BufferMemoryBarrier<'static> { + let &Self { + src_stages: _, + src_access, + dst_stages: _, + dst_access, + queue_family_ownership_transfer, + ref buffer, + ref range, + _ne: _, + } = self; + + let (src_queue_family_index, dst_queue_family_index) = + queue_family_ownership_transfer.as_ref().map_or( + (ash::vk::QUEUE_FAMILY_IGNORED, ash::vk::QUEUE_FAMILY_IGNORED), + QueueFamilyOwnershipTransfer::to_vk, + ); + + ash::vk::BufferMemoryBarrier::default() + .src_access_mask(src_access.into()) + .dst_access_mask(dst_access.into()) + .src_queue_family_index(src_queue_family_index) + .dst_queue_family_index(dst_queue_family_index) + .buffer(buffer.handle()) + .offset(range.start) + .size(range.end - range.start) + } } /// A memory barrier that is applied to a single image. @@ -4066,6 +4309,70 @@ impl ImageMemoryBarrier { Ok(()) } + + pub(crate) fn to_vk2(&self) -> ash::vk::ImageMemoryBarrier2<'static> { + let &Self { + src_stages, + src_access, + dst_stages, + dst_access, + old_layout, + new_layout, + ref queue_family_ownership_transfer, + ref image, + ref subresource_range, + _ne: _, + } = self; + + let (src_queue_family_index, dst_queue_family_index) = + queue_family_ownership_transfer.as_ref().map_or( + (ash::vk::QUEUE_FAMILY_IGNORED, ash::vk::QUEUE_FAMILY_IGNORED), + QueueFamilyOwnershipTransfer::to_vk, + ); + + ash::vk::ImageMemoryBarrier2::default() + .src_stage_mask(src_stages.into()) + .src_access_mask(src_access.into()) + .dst_stage_mask(dst_stages.into()) + .dst_access_mask(dst_access.into()) + .old_layout(old_layout.into()) + .new_layout(new_layout.into()) + .src_queue_family_index(src_queue_family_index) + .dst_queue_family_index(dst_queue_family_index) + .image(image.handle()) + .subresource_range(subresource_range.to_vk()) + } + + pub(crate) fn to_vk(&self) -> ash::vk::ImageMemoryBarrier<'static> { + let &Self { + src_stages: _, + src_access, + dst_stages: _, + dst_access, + old_layout, + new_layout, + ref queue_family_ownership_transfer, + ref image, + ref subresource_range, + _ne: _, + } = self; + + let (src_queue_family_index, dst_queue_family_index) = + queue_family_ownership_transfer.as_ref().map_or( + (ash::vk::QUEUE_FAMILY_IGNORED, ash::vk::QUEUE_FAMILY_IGNORED), + QueueFamilyOwnershipTransfer::to_vk, + ); + + ash::vk::ImageMemoryBarrier::default() + .src_access_mask(src_access.into()) + .dst_access_mask(dst_access.into()) + .old_layout(old_layout.into()) + .new_layout(new_layout.into()) + .src_queue_family_index(src_queue_family_index) + .dst_queue_family_index(dst_queue_family_index) + .image(image.handle()) + .subresource_range(subresource_range.to_vk()) + } } /// Specifies a queue family ownership transfer for a resource. @@ -4182,38 +4489,37 @@ pub enum QueueFamilyOwnershipTransfer { ConcurrentFromForeign, } -impl From for (u32, u32) { - fn from(val: QueueFamilyOwnershipTransfer) -> Self { - match val { - QueueFamilyOwnershipTransfer::ExclusiveBetweenLocal { +impl QueueFamilyOwnershipTransfer { + #[allow(clippy::wrong_self_convention)] + pub(crate) fn to_vk(&self) -> (u32, u32) { + match *self { + Self::ExclusiveBetweenLocal { src_index, dst_index, } => (src_index, dst_index), - QueueFamilyOwnershipTransfer::ExclusiveToExternal { src_index } => { - (src_index, ash::vk::QUEUE_FAMILY_EXTERNAL) - } - QueueFamilyOwnershipTransfer::ExclusiveFromExternal { dst_index } => { + Self::ExclusiveToExternal { src_index } => (src_index, ash::vk::QUEUE_FAMILY_EXTERNAL), + Self::ExclusiveFromExternal { dst_index } => { (ash::vk::QUEUE_FAMILY_EXTERNAL, dst_index) } - QueueFamilyOwnershipTransfer::ExclusiveToForeign { src_index } => { + Self::ExclusiveToForeign { src_index } => { (src_index, ash::vk::QUEUE_FAMILY_FOREIGN_EXT) } - QueueFamilyOwnershipTransfer::ExclusiveFromForeign { dst_index } => { + Self::ExclusiveFromForeign { dst_index } => { (ash::vk::QUEUE_FAMILY_FOREIGN_EXT, dst_index) } - QueueFamilyOwnershipTransfer::ConcurrentToExternal => ( + Self::ConcurrentToExternal => ( ash::vk::QUEUE_FAMILY_IGNORED, ash::vk::QUEUE_FAMILY_EXTERNAL, ), - QueueFamilyOwnershipTransfer::ConcurrentFromExternal => ( + Self::ConcurrentFromExternal => ( ash::vk::QUEUE_FAMILY_EXTERNAL, ash::vk::QUEUE_FAMILY_IGNORED, ), - QueueFamilyOwnershipTransfer::ConcurrentToForeign => ( + Self::ConcurrentToForeign => ( ash::vk::QUEUE_FAMILY_IGNORED, ash::vk::QUEUE_FAMILY_FOREIGN_EXT, ), - QueueFamilyOwnershipTransfer::ConcurrentFromForeign => ( + Self::ConcurrentFromForeign => ( ash::vk::QUEUE_FAMILY_FOREIGN_EXT, ash::vk::QUEUE_FAMILY_IGNORED, ), diff --git a/vulkano/src/sync/semaphore.rs b/vulkano/src/sync/semaphore.rs index 37e1f56e..07d1464c 100644 --- a/vulkano/src/sync/semaphore.rs +++ b/vulkano/src/sync/semaphore.rs @@ -71,6 +71,7 @@ use crate::{ Requires, RequiresAllOf, RequiresOneOf, Validated, ValidationError, Version, VulkanError, VulkanObject, }; +use core::slice; use smallvec::SmallVec; use std::{fs::File, mem::MaybeUninit, num::NonZeroU64, ptr, sync::Arc, time::Duration}; @@ -118,40 +119,8 @@ impl Semaphore { device: Arc, create_info: SemaphoreCreateInfo, ) -> Result { - let &SemaphoreCreateInfo { - semaphore_type, - initial_value, - export_handle_types, - _ne: _, - } = &create_info; - - let mut create_info_vk = ash::vk::SemaphoreCreateInfo { - flags: ash::vk::SemaphoreCreateFlags::empty(), - ..Default::default() - }; - let mut semaphore_type_create_info_vk = None; - let mut export_semaphore_create_info_vk = None; - - if semaphore_type != SemaphoreType::Binary { - let next = semaphore_type_create_info_vk.insert(ash::vk::SemaphoreTypeCreateInfo { - semaphore_type: semaphore_type.into(), - initial_value, - ..Default::default() - }); - - next.p_next = create_info_vk.p_next; - create_info_vk.p_next = <*const _>::cast(next); - } - - if !export_handle_types.is_empty() { - let next = export_semaphore_create_info_vk.insert(ash::vk::ExportSemaphoreCreateInfo { - handle_types: export_handle_types.into(), - ..Default::default() - }); - - next.p_next = create_info_vk.p_next; - create_info_vk.p_next = <*const _>::cast(next); - } + let mut create_info_extensions_vk = create_info.to_vk_extensions(); + let create_info_vk = create_info.to_vk(&mut create_info_extensions_vk); let handle = { let fns = device.fns(); @@ -338,13 +307,7 @@ impl Semaphore { &self, signal_info: SemaphoreSignalInfo, ) -> Result<(), VulkanError> { - let &SemaphoreSignalInfo { value, _ne: _ } = &signal_info; - - let signal_info_vk = ash::vk::SemaphoreSignalInfo { - semaphore: self.handle, - value, - ..Default::default() - }; + let signal_info_vk = signal_info.to_vk(self.handle()); let fns = self.device.fns(); @@ -407,22 +370,7 @@ impl Semaphore { wait_info: SemaphoreWaitInfo, timeout: Option, ) -> Result<(), VulkanError> { - let &SemaphoreWaitInfo { - flags, - value, - _ne: _, - } = &wait_info; - - let semaphores_vk = [self.handle]; - let values_vk = [value]; - - let wait_info_vk = ash::vk::SemaphoreWaitInfo { - flags: flags.into(), - semaphore_count: 1, - p_semaphores: semaphores_vk.as_ptr(), - p_values: values_vk.as_ptr(), - ..Default::default() - }; + let wait_info_vk = wait_info.to_vk(&self.handle); let fns = self.device.fns(); @@ -493,39 +441,14 @@ impl Semaphore { wait_info: SemaphoreWaitMultipleInfo, timeout: Option, ) -> Result<(), VulkanError> { - let &SemaphoreWaitMultipleInfo { - flags, - ref semaphores, - _ne: _, - } = &wait_info; - - if semaphores.is_empty() { + if wait_info.semaphores.is_empty() { return Ok(()); } - let mut semaphores_vk: SmallVec<[_; 8]> = SmallVec::with_capacity(semaphores.len()); - let mut values_vk: SmallVec<[_; 8]> = SmallVec::with_capacity(semaphores.len()); + let wait_info_fields1_vk = wait_info.to_vk_fields1(); + let wait_info_vk = wait_info.to_vk(&wait_info_fields1_vk); - for value_info in semaphores { - let &SemaphoreWaitValueInfo { - ref semaphore, - value, - _ne: _, - } = value_info; - - semaphores_vk.push(semaphore.handle); - values_vk.push(value); - } - - let wait_info_vk = ash::vk::SemaphoreWaitInfo { - flags: flags.into(), - semaphore_count: semaphores_vk.len() as u32, - p_semaphores: semaphores_vk.as_ptr(), - p_values: values_vk.as_ptr(), - ..Default::default() - }; - - let device = &semaphores[0].semaphore.device; + let device = &wait_info.semaphores[0].semaphore.device; let fns = device.fns(); if device.api_version() >= Version::V1_2 { @@ -627,11 +550,9 @@ impl Semaphore { &self, handle_type: ExternalSemaphoreHandleType, ) -> Result { - let info_vk = ash::vk::SemaphoreGetFdInfoKHR { - semaphore: self.handle, - handle_type: handle_type.into(), - ..Default::default() - }; + let info_vk = ash::vk::SemaphoreGetFdInfoKHR::default() + .semaphore(self.handle) + .handle_type(handle_type.into()); let mut output = MaybeUninit::uninit(); let fns = self.device.fns(); @@ -737,11 +658,9 @@ impl Semaphore { &self, handle_type: ExternalSemaphoreHandleType, ) -> Result { - let info_vk = ash::vk::SemaphoreGetWin32HandleInfoKHR { - semaphore: self.handle, - handle_type: handle_type.into(), - ..Default::default() - }; + let info_vk = ash::vk::SemaphoreGetWin32HandleInfoKHR::default() + .semaphore(self.handle) + .handle_type(handle_type.into()); let mut output = MaybeUninit::uninit(); let fns = self.device.fns(); @@ -827,11 +746,9 @@ impl Semaphore { &self, handle_type: ExternalSemaphoreHandleType, ) -> Result { - let info_vk = ash::vk::SemaphoreGetZirconHandleInfoFUCHSIA { - semaphore: self.handle, - handle_type: handle_type.into(), - ..Default::default() - }; + let info_vk = ash::vk::SemaphoreGetZirconHandleInfoFUCHSIA::default() + .semaphore(self.handle) + .handle_type(handle_type.into()); let mut output = MaybeUninit::uninit(); let fns = self.device.fns(); @@ -913,32 +830,7 @@ impl Semaphore { &self, import_semaphore_fd_info: ImportSemaphoreFdInfo, ) -> Result<(), VulkanError> { - let ImportSemaphoreFdInfo { - flags, - handle_type, - file, - _ne: _, - } = import_semaphore_fd_info; - - #[cfg(unix)] - let fd = { - use std::os::fd::IntoRawFd; - file.map_or(-1, |file| file.into_raw_fd()) - }; - - #[cfg(not(unix))] - let fd = { - let _ = file; - -1 - }; - - let info_vk = ash::vk::ImportSemaphoreFdInfoKHR { - semaphore: self.handle, - flags: flags.into(), - handle_type: handle_type.into(), - fd, - ..Default::default() - }; + let info_vk = import_semaphore_fd_info.into_vk(self.handle()); let fns = self.device.fns(); (fns.khr_external_semaphore_fd.import_semaphore_fd_khr)(self.device.handle(), &info_vk) @@ -1018,21 +910,7 @@ impl Semaphore { &self, import_semaphore_win32_handle_info: ImportSemaphoreWin32HandleInfo, ) -> Result<(), VulkanError> { - let ImportSemaphoreWin32HandleInfo { - flags, - handle_type, - handle, - _ne: _, - } = import_semaphore_win32_handle_info; - - let info_vk = ash::vk::ImportSemaphoreWin32HandleInfoKHR { - semaphore: self.handle, - flags: flags.into(), - handle_type: handle_type.into(), - handle, - name: ptr::null(), // TODO: support? - ..Default::default() - }; + let info_vk = import_semaphore_win32_handle_info.to_vk(self.handle()); let fns = self.device.fns(); (fns.khr_external_semaphore_win32 @@ -1096,20 +974,7 @@ impl Semaphore { &self, import_semaphore_zircon_handle_info: ImportSemaphoreZirconHandleInfo, ) -> Result<(), VulkanError> { - let ImportSemaphoreZirconHandleInfo { - flags, - handle_type, - zircon_handle, - _ne: _, - } = import_semaphore_zircon_handle_info; - - let info_vk = ash::vk::ImportSemaphoreZirconHandleInfoFUCHSIA { - semaphore: self.handle, - flags: flags.into(), - handle_type: handle_type.into(), - zircon_handle, - ..Default::default() - }; + let info_vk = import_semaphore_zircon_handle_info.to_vk(self.handle()); let fns = self.device.fns(); (fns.fuchsia_external_semaphore @@ -1298,6 +1163,58 @@ impl SemaphoreCreateInfo { Ok(()) } + + pub(crate) fn to_vk<'a>( + &self, + extensions_vk: &'a mut SemaphoreCreateInfoExtensionsVk, + ) -> ash::vk::SemaphoreCreateInfo<'a> { + let &Self { + semaphore_type: _, + initial_value: _, + export_handle_types: _, + _ne: _, + } = self; + + let mut val_vk = + ash::vk::SemaphoreCreateInfo::default().flags(ash::vk::SemaphoreCreateFlags::empty()); + + let SemaphoreCreateInfoExtensionsVk { export_vk, type_vk } = extensions_vk; + + if let Some(next) = export_vk { + val_vk = val_vk.push_next(next); + } + + if let Some(next) = type_vk { + val_vk = val_vk.push_next(next); + } + + val_vk + } + + pub(crate) fn to_vk_extensions(&self) -> SemaphoreCreateInfoExtensionsVk { + let &Self { + semaphore_type, + initial_value, + export_handle_types, + _ne: _, + } = self; + + let export_vk = (!export_handle_types.is_empty()).then(|| { + ash::vk::ExportSemaphoreCreateInfo::default().handle_types(export_handle_types.into()) + }); + let type_vk = (semaphore_type != SemaphoreType::Binary).then(|| { + ash::vk::SemaphoreTypeCreateInfo::default() + .semaphore_type(semaphore_type.into()) + .initial_value(initial_value) + }); + + SemaphoreCreateInfoExtensionsVk { export_vk, type_vk } + } +} + +pub(crate) struct SemaphoreCreateInfoExtensionsVk { + pub(crate) export_vk: Option>, + pub(crate) type_vk: Option>, } vulkan_enum! { @@ -1414,6 +1331,17 @@ impl SemaphoreSignalInfo { Ok(()) } + + pub(crate) fn to_vk( + &self, + semaphore_vk: ash::vk::Semaphore, + ) -> ash::vk::SemaphoreSignalInfo<'static> { + let &Self { value, _ne: _ } = self; + + ash::vk::SemaphoreSignalInfo::default() + .semaphore(semaphore_vk) + .value(value) + } } /// Parameters to wait for a single timeline semaphore. @@ -1458,6 +1386,22 @@ impl SemaphoreWaitInfo { Ok(()) } + + pub(crate) fn to_vk<'a>( + &'a self, + semaphore_vk: &'a ash::vk::Semaphore, + ) -> ash::vk::SemaphoreWaitInfo<'a> { + let &Self { + flags, + ref value, + _ne: _, + } = self; + + ash::vk::SemaphoreWaitInfo::default() + .flags(flags.into()) + .semaphores(slice::from_ref(semaphore_vk)) + .values(slice::from_ref(value)) + } } /// Parameters to wait for multiple timeline semaphores. @@ -1512,6 +1456,54 @@ impl SemaphoreWaitMultipleInfo { Ok(()) } + + pub(crate) fn to_vk<'a>( + &self, + fields1_vk: &'a SemaphoreWaitMultipleInfoFields1Vk, + ) -> ash::vk::SemaphoreWaitInfo<'a> { + let &Self { + flags, + semaphores: _, + _ne: _, + } = self; + let SemaphoreWaitMultipleInfoFields1Vk { + semaphores_vk, + values_vk, + } = fields1_vk; + + ash::vk::SemaphoreWaitInfo::default() + .flags(flags.into()) + .semaphores(semaphores_vk) + .values(values_vk) + } + + pub(crate) fn to_vk_fields1(&self) -> SemaphoreWaitMultipleInfoFields1Vk { + let &SemaphoreWaitMultipleInfo { ref semaphores, .. } = self; + + let mut semaphores_vk: SmallVec<[_; 8]> = SmallVec::with_capacity(semaphores.len()); + let mut values_vk: SmallVec<[_; 8]> = SmallVec::with_capacity(semaphores.len()); + + for value_info in semaphores { + let &SemaphoreWaitValueInfo { + ref semaphore, + value, + _ne: _, + } = value_info; + + semaphores_vk.push(semaphore.handle); + values_vk.push(value); + } + + SemaphoreWaitMultipleInfoFields1Vk { + semaphores_vk, + values_vk, + } + } +} + +pub(crate) struct SemaphoreWaitMultipleInfoFields1Vk { + semaphores_vk: SmallVec<[ash::vk::Semaphore; 8]>, + values_vk: SmallVec<[u64; 8]>, } vulkan_bitflags! { @@ -1673,6 +1665,36 @@ impl ImportSemaphoreFdInfo { Ok(()) } + + pub(crate) fn into_vk( + self, + semaphore_vk: ash::vk::Semaphore, + ) -> ash::vk::ImportSemaphoreFdInfoKHR<'static> { + let Self { + flags, + handle_type, + file, + _ne: _, + } = self; + + #[cfg(unix)] + let fd = { + use std::os::fd::IntoRawFd; + file.map_or(-1, |file| file.into_raw_fd()) + }; + + #[cfg(not(unix))] + let fd = { + let _ = file; + -1 + }; + + ash::vk::ImportSemaphoreFdInfoKHR::default() + .semaphore(semaphore_vk) + .flags(flags.into()) + .handle_type(handle_type.into()) + .fd(fd) + } } #[derive(Debug)] @@ -1760,6 +1782,25 @@ impl ImportSemaphoreWin32HandleInfo { Ok(()) } + + pub(crate) fn to_vk( + &self, + semaphore_vk: ash::vk::Semaphore, + ) -> ash::vk::ImportSemaphoreWin32HandleInfoKHR<'static> { + let &Self { + flags, + handle_type, + handle, + _ne: _, + } = self; + + ash::vk::ImportSemaphoreWin32HandleInfoKHR::default() + .semaphore(semaphore_vk) + .flags(flags.into()) + .handle_type(handle_type.into()) + .handle(handle) + // .name() // TODO: support? + } } #[derive(Debug)] @@ -1840,6 +1881,24 @@ impl ImportSemaphoreZirconHandleInfo { Ok(()) } + + pub(crate) fn to_vk( + &self, + semaphore_vk: ash::vk::Semaphore, + ) -> ash::vk::ImportSemaphoreZirconHandleInfoFUCHSIA<'static> { + let &Self { + flags, + handle_type, + zircon_handle, + _ne: _, + } = self; + + ash::vk::ImportSemaphoreZirconHandleInfoFUCHSIA::default() + .semaphore(semaphore_vk) + .flags(flags.into()) + .handle_type(handle_type.into()) + .zircon_handle(zircon_handle) + } } /// The semaphore configuration to query in @@ -1929,6 +1988,50 @@ impl ExternalSemaphoreInfo { Ok(()) } + + pub(crate) fn to_vk<'a>( + &self, + extensions_vk: &'a mut ExternalSemaphoreInfoExtensionsVk, + ) -> ash::vk::PhysicalDeviceExternalSemaphoreInfo<'a> { + let &Self { + handle_type, + semaphore_type: _, + initial_value: _, + _ne: _, + } = self; + + let mut val_vk = + ash::vk::PhysicalDeviceExternalSemaphoreInfo::default().handle_type(handle_type.into()); + + let ExternalSemaphoreInfoExtensionsVk { type_vk } = extensions_vk; + + if let Some(next) = type_vk { + val_vk = val_vk.push_next(next); + } + + val_vk + } + + pub(crate) fn to_vk_extensions(&self) -> ExternalSemaphoreInfoExtensionsVk { + let &Self { + handle_type: _, + semaphore_type, + initial_value, + _ne: _, + } = self; + + let type_vk = (semaphore_type != SemaphoreType::Binary).then(|| { + ash::vk::SemaphoreTypeCreateInfo::default() + .semaphore_type(semaphore_type.into()) + .initial_value(initial_value) + }); + + ExternalSemaphoreInfoExtensionsVk { type_vk } + } +} + +pub(crate) struct ExternalSemaphoreInfoExtensionsVk { + pub(crate) type_vk: Option>, } /// The properties for exporting or importing external handles, when a semaphore is created @@ -1953,6 +2056,30 @@ pub struct ExternalSemaphoreProperties { pub compatible_handle_types: ExternalSemaphoreHandleTypes, } +impl ExternalSemaphoreProperties { + pub(crate) fn to_mut_vk() -> ash::vk::ExternalSemaphoreProperties<'static> { + ash::vk::ExternalSemaphoreProperties::default() + } + + pub(crate) fn from_vk(val_vk: &ash::vk::ExternalSemaphoreProperties<'_>) -> Self { + let &ash::vk::ExternalSemaphoreProperties { + export_from_imported_handle_types, + compatible_handle_types, + external_semaphore_features, + .. + } = val_vk; + + ExternalSemaphoreProperties { + exportable: external_semaphore_features + .intersects(ash::vk::ExternalSemaphoreFeatureFlags::EXPORTABLE), + importable: external_semaphore_features + .intersects(ash::vk::ExternalSemaphoreFeatureFlags::IMPORTABLE), + export_from_imported_handle_types: export_from_imported_handle_types.into(), + compatible_handle_types: compatible_handle_types.into(), + } + } +} + #[cfg(test)] mod tests { use crate::{