Use Ash builders for Vulkan struct construction + refactor (#2525)

* Use Ash builders for Vulkan struct construction + refactor

* Use pointer for `from_qnx_screen`

* Workaround for Ash bug

* Fix vulkano-taskgraph

---------

Co-authored-by: marc0246 <40955683+marc0246@users.noreply.github.com>
This commit is contained in:
Rua 2024-10-02 15:15:08 +02:00 committed by GitHub
parent bad11eef71
commit 9033311653
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
75 changed files with 10103 additions and 8225 deletions

View File

@ -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,
&region_vk,
)
@ -58,8 +57,7 @@ impl RecordingCommandBuffer<'_> {
} else {
let regions_vk = regions
.iter()
.cloned()
.map(vk::ImageSubresourceRange::from)
.map(ImageSubresourceRange::to_vk)
.collect::<SmallVec<[_; 8]>>();
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,
&region_vk,
)
@ -119,8 +117,7 @@ impl RecordingCommandBuffer<'_> {
} else {
let regions_vk = regions
.iter()
.cloned()
.map(vk::ImageSubresourceRange::from)
.map(ImageSubresourceRange::to_vk)
.collect::<SmallVec<[_; 8]>>();
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(),
)

View File

@ -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::<SmallVec<[_; 8]>>();
@ -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),
}

View File

@ -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::<SmallVec<[_; 2]>>();
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::<SmallVec<[_; 2]>>();
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::<SmallVec<[_; 2]>>();
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::<SmallVec<[_; 2]>>();
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::<SmallVec<[_; 2]>>();
let fns = self.device().fns();

View File

@ -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();

View File

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

View File

@ -165,22 +165,7 @@ impl AccelerationStructure {
device: Arc<Device>,
create_info: AccelerationStructureCreateInfo,
) -> Result<Arc<Self>, 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<ash::vk::AccelerationStructureGeometryKHR<'static>>,
) {
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<ash::vk::AccelerationStructureGeometryKHR<'static>>,
}
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<Vec<AccelerationStructureGeometryTrianglesData>> 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<Subbuffer<[DeviceSize]>>),
}
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<Subbuffer<[AccelerationStructureInstance]>>
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(()),
}
}
}

View File

@ -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]

View File

@ -173,6 +173,26 @@ impl<T: ?Sized> Subbuffer<T> {
// SAFETY: All `Subbuffer`s share the same layout.
mem::transmute::<&Subbuffer<T>, &Subbuffer<U>>(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<T> Subbuffer<T>

View File

@ -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<Device>,
create_info: BufferCreateInfo,
) -> Result<Self, VulkanError> {
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<Buffer, (VulkanError, RawBuffer, ResourceMemory)> {
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<ash::vk::ExternalMemoryBufferCreateInfo<'static>>,
}
#[cfg(test)]

View File

@ -287,18 +287,8 @@ impl BufferView {
subbuffer: Subbuffer<impl ?Sized>,
create_info: BufferViewCreateInfo,
) -> Result<Arc<BufferView>, 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)]

View File

@ -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},

View File

@ -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()),

View File

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

View File

@ -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)(

View File

@ -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,
}

File diff suppressed because it is too large Load Diff

View File

@ -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
}

View File

@ -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::<SmallVec<[_; 4]>>();
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::<SmallVec<[_; 2]>>();
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::<SmallVec<[_; 2]>>();
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::<SmallVec<[_; 2]>>();
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::<SmallVec<[_; 2]>>();
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::<SmallVec<[_; 2]>>();
if viewports.is_empty() {
return self;

View File

@ -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<ClearAttachment> 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<ClearAttachment> 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<u32>,
}
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,
}
}
}

View File

@ -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,

View File

@ -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<ash::vk::CommandBufferInheritanceRenderingInfo<'a>>,
}
pub(crate) struct CommandBufferInheritanceInfoFields1Vk {
pub(crate) rendering_info_fields1_vk: Option<CommandBufferInheritanceRenderingInfoFields1Vk>,
}
/// 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<ash::vk::TimelineSemaphoreSubmitInfo<'a>>,
}
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)]

View File

@ -64,17 +64,7 @@ impl CommandPool {
device: Arc<Device>,
create_info: CommandPoolCreateInfo,
) -> Result<Self, VulkanError> {
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 {

View File

@ -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<Self, Validated<VulkanError>> {
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<ash::vk::CommandBufferInheritanceInfo<'a>>,
}
pub(crate) struct BeginInfoFields1ExtensionsVk<'a> {
pub(crate) inheritance_info_vk: Option<CommandBufferInheritanceInfoExtensionsVk<'a>>,
}
pub(crate) struct BeginInfoFields2Vk {
pub(crate) inheritance_info_fields1_vk: Option<CommandBufferInheritanceInfoFields1Vk>,
}
/// A raw command buffer that has finished recording.

View File

@ -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<Device>,
create_info: DescriptorSetLayoutCreateInfo,
) -> Result<Arc<DescriptorSetLayout>, VulkanError> {
let &DescriptorSetLayoutCreateInfo {
flags,
ref bindings,
_ne: _,
} = &create_info;
struct PerBinding {
immutable_samplers_vk: Vec<ash::vk::Sampler>,
}
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<ValidationError>> {
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<ash::vk::DescriptorSetLayoutBindingFlagsCreateInfo<'a>>,
}
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<ash::vk::Sampler>,
}
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<Self> {
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<ash::vk::DescriptorSetVariableDescriptorCountLayoutSupport<'static>>,
}
#[cfg(test)]
mod tests {
use crate::{

View File

@ -65,7 +65,6 @@
//!
//! [`StandardDescriptorSetAllocator`]: allocator::StandardDescriptorSetAllocator
pub(crate) use self::update::DescriptorWriteInfo;
use self::{
allocator::DescriptorSetAllocator,
layout::DescriptorSetLayout,

View File

@ -61,43 +61,10 @@ impl DescriptorPool {
device: Arc<Device>,
create_info: DescriptorPoolCreateInfo,
) -> Result<DescriptorPool, VulkanError> {
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<ash::vk::DescriptorPoolInlineUniformBlockCreateInfo<'static>>,
}
pub(crate) struct DescriptorPoolCreateInfoFields1Vk {
pub(crate) pool_sizes_vk: SmallVec<[ash::vk::DescriptorPoolSize; 8]>,
}
vulkan_bitflags! {

View File

@ -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)(

View File

@ -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<DescriptorTypeExtensionVk<'a>>,
}
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<u8>),
AccelerationStructure(SmallVec<[ash::vk::AccelerationStructureKHR; 1]>),
}
/// The elements held by a `WriteDescriptorSet`.
@ -1540,6 +1531,21 @@ pub struct DescriptorBufferInfo {
pub range: Range<DeviceSize>,
}
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<u8>),
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

View File

@ -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::<CString>::from(enabled_extensions);
let enabled_extensions_ptrs_vk = enabled_extensions_strings_vk
.iter()
.map(|extension| extension.as_ptr())
.collect::<SmallVec<[_; 16]>>();
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<DescriptorSetLayoutSupport> {
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<ash::vk::Sampler>,
}
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<usize>,
) -> 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<MemoryFdProperties, VulkanError> {
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::<CString>::from(&self.enabled_extensions);
DeviceCreateInfoFields2Vk {
enabled_extensions_vk,
}
}
}
pub(crate) struct DeviceCreateInfoExtensionsVk<'a, 'b> {
pub(crate) device_group_vk: Option<ash::vk::DeviceGroupDeviceCreateInfo<'a>>,
pub(crate) features2_vk: Option<&'a mut ash::vk::PhysicalDeviceFeatures2<'b>>,
pub(crate) private_data_vk: Option<ash::vk::DevicePrivateDataCreateInfo<'static>>,
}
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<CString>,
}
/// 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<T> Deref for DeviceOwnedDebugWrapper<T> {
}
}
/// 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::{

File diff suppressed because it is too large Load Diff

View File

@ -69,12 +69,7 @@ impl PrivateDataSlot {
device: Arc<Device>,
create_info: PrivateDataSlotCreateInfo,
) -> Result<Self, VulkanError> {
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<ValidationError>> {
Ok(())
}
pub(crate) fn to_vk(&self) -> ash::vk::PrivateDataSlotCreateInfo<'static> {
let &Self { _ne: _ } = self;
ash::vk::PrivateDataSlotCreateInfo::default()
.flags(ash::vk::PrivateDataSlotCreateFlags::empty())
}
}

View File

@ -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<Device>, queue_info: DeviceQueueInfo) -> Arc<Self> {
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<Queue>,
_state: MutexGuard<'a, QueueState>,
@ -226,243 +226,22 @@ impl<'a> QueueGuard<'a> {
bind_infos: &[BindSparseInfo],
fence: Option<&Arc<Fence>>,
) -> 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::<SmallVec<[_; 4]>>(),
)
})
.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::<SmallVec<[_; 4]>>(),
)
})
.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::<SmallVec<[_; 4]>>(),
)
})
.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<impl ExactSizeIterator<Item = Result<bool, VulkanError>>, 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::<SmallVec<[_; 4]>>(),
);
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<Fence>>,
) -> 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<ash::vk::TimelineSemaphoreSubmitInfo<'static>>,
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<ash::vk::QueueFamilyProperties> 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,
],
}
}

View File

@ -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<Display>,
create_info: DisplayModeCreateInfo,
) -> Result<Arc<Self>, 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]

View File

@ -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<ValidationError>> {
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<ClearValue> 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<ClearColorValue> 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<ClearDepthStencilValue> 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<FormatProperties2ExtensionsVk<'static>> {
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<FormatProperties2ExtensionsVk<'_>>,
) -> 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<ash::vk::DrmFormatModifierPropertiesListEXT<'a>>,
pub(crate) drm_format_modifier_properties_list2_vk:
Option<ash::vk::DrmFormatModifierPropertiesList2EXT<'a>>,
pub(crate) format_properties3_vk: Option<ash::vk::FormatProperties3<'static>>,
}
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<Vec<ash::vk::DrmFormatModifierPropertiesEXT>>,
pub(crate) drm_format_modifier_properties2_vk:
Option<Vec<ash::vk::DrmFormatModifierProperties2EXT>>,
}
/// 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]

View File

@ -1453,26 +1453,20 @@ impl ImageSubresourceLayers {
}
}
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,
}
}
}
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<ImageSubresourceRange> 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<DeviceSize>,
}
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<ash::vk::PhysicalDeviceImageDrmFormatModifierInfoEXT<'a>>,
pub(crate) external_vk: Option<ash::vk::PhysicalDeviceExternalImageFormatInfo<'static>>,
pub(crate) format_list_vk: Option<ash::vk::ImageFormatListCreateInfo<'a>>,
pub(crate) image_view_vk: Option<ash::vk::PhysicalDeviceImageViewImageFormatInfoEXT<'static>>,
pub(crate) stencil_usage_vk: Option<ash::vk::ImageStencilUsageCreateInfo<'static>>,
}
pub(crate) struct ImageFormatInfo2Fields1Vk {
pub(crate) view_formats_vk: Vec<ash::vk::Format>,
}
/// 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<ash::vk::ImageFormatProperties> 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<ash::vk::ExternalImageFormatProperties<'static>>,
pub(crate) filter_cubic_image_view_vk:
Option<ash::vk::FilterCubicImageViewImageFormatPropertiesEXT<'static>>,
}
/// 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<DeviceSize>,
}
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]

View File

@ -135,78 +135,8 @@ impl Sampler {
device: Arc<Device>,
create_info: SamplerCreateInfo,
) -> Result<Arc<Sampler>, 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<ash::vk::SamplerReductionModeCreateInfo<'static>>,
pub(crate) ycbcr_conversion_vk: Option<ash::vk::SamplerYcbcrConversionInfo<'static>>,
}
/// A special value to indicate that the maximum LOD should not be clamped.
@ -1251,16 +1279,16 @@ impl ComponentMapping {
Ok(())
}
}
impl From<ComponentMapping> 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(),
}
}
}

View File

@ -176,28 +176,7 @@ impl SamplerYcbcrConversion {
device: Arc<Device>,
create_info: SamplerYcbcrConversionCreateInfo,
) -> Result<Arc<SamplerYcbcrConversion>, 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! {

View File

@ -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<Device>,
create_info: ImageCreateInfo,
) -> Result<Self, VulkanError> {
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<ash::vk::ImageDrmFormatModifierExplicitCreateInfoEXT<'a>>,
pub(crate) drm_format_modifier_list_vk:
Option<ash::vk::ImageDrmFormatModifierListCreateInfoEXT<'a>>,
pub(crate) external_memory_vk: Option<ash::vk::ExternalMemoryImageCreateInfo<'static>>,
pub(crate) format_list_vk: Option<ash::vk::ImageFormatListCreateInfo<'a>>,
pub(crate) stencil_usage_vk: Option<ash::vk::ImageStencilUsageCreateInfo<'static>>,
}
pub(crate) struct ImageCreateInfoFields1Vk {
plane_layouts_vk: SmallVec<[ash::vk::SubresourceLayout; 4]>,
view_formats_vk: Vec<ash::vk::Format>,
}
#[cfg(test)]

View File

@ -556,65 +556,18 @@ impl ImageView {
image: Arc<Image>,
create_info: ImageViewCreateInfo,
) -> Result<Arc<Self>, 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<ash::vk::SamplerYcbcrConversionInfo<'static>>,
pub(crate) usage_vk: Option<ash::vk::ImageViewUsageCreateInfo<'static>>,
}
vulkan_enum! {

View File

@ -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<Instance>,
create_info: DebugUtilsMessengerCreateInfo,
) -> Result<Self, VulkanError> {
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::Item> {
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]

View File

@ -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<CString> = 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::<SmallVec<[_; 2]>>();
let enabled_extensions_vk: Vec<CString> = enabled_extensions.as_ref().into();
let enabled_extensions_ptrs_vk = enabled_extensions_vk
.iter()
.map(|extension| extension.as_ptr())
.collect::<SmallVec<[_; 2]>>();
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<CString> = enabled_layers
.iter()
.map(|name| CString::new(name.clone()).unwrap())
.collect();
let enabled_extensions_vk: Vec<CString> = 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<ash::vk::DebugUtilsMessengerCreateInfoEXT<'a>>,
pub(crate) validation_features_vk: Option<ash::vk::ValidationFeaturesEXT<'a>>,
}
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<CString>,
pub(crate) engine_name_vk: Option<CString>,
pub(crate) enabled_layers_vk: Vec<CString>,
pub(crate) enabled_extensions_vk: Vec<CString>,
}
vulkan_bitflags! {

View File

@ -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<NonNull<c_void>>,
) -> 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<File, VulkanError> {
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<MemoryImportInfoVk>,
) -> 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<ash::vk::MemoryDedicatedAllocateInfo<'static>>,
pub(crate) export_vk: Option<ash::vk::ExportMemoryAllocateInfo<'static>>,
pub(crate) flags_vk: Option<MemoryAllocateFlagsInfo<'static>>,
pub(crate) import_vk: Option<MemoryImportInfoVk>,
}
/// 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<NonNull<c_void>>,
) -> 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<ash::vk::MemoryMapPlacedInfoEXT<'static>>,
}
vulkan_bitflags! {
@ -1673,14 +1719,6 @@ pub struct MemoryUnmapInfo {
pub _ne: crate::NonExhaustive,
}
impl MemoryUnmapInfo {
pub(crate) fn validate(&self, _memory: &DeviceMemory) -> Result<(), Box<ValidationError>> {
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<ValidationError>> {
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)?;

View File

@ -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<MemoryHeap>,
}
impl From<ash::vk::PhysicalDeviceMemoryProperties> 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<ash::vk::MemoryDedicatedRequirements<'static>>,
}
/// 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<ash::vk::ExternalMemoryProperties> 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<DeviceMemory>, 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<DeviceMemory>, 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

View File

@ -106,29 +106,14 @@ impl PipelineCache {
device: Arc<Device>,
create_info: PipelineCacheCreateInfo,
) -> Result<Arc<PipelineCache>, 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! {

View File

@ -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<Arc<PipelineCache>>,
create_info: ComputePipelineCreateInfo,
) -> Result<Arc<ComputePipeline>, 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<u8>;
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)]

View File

@ -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<ash::vk::PipelineColorWriteCreateInfoEXT<'a>>,
}
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<AttachmentBlend> 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(),
}
}

View File

@ -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<ValidationError>> {
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
}
}

View File

@ -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.

View File

@ -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! {

View File

@ -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! {

File diff suppressed because it is too large Load Diff

View File

@ -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)
}
}

View File

@ -78,6 +78,17 @@ pub struct RasterizationState {
/// The default value is `None`.
pub line_stipple: Option<LineStipple>,
/// 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<RasterizationConservativeState>,
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<ash::vk::PipelineRasterizationLineStateCreateInfoKHR<'static>>,
pub(crate) conservative_vk:
Option<ash::vk::PipelineRasterizationConservativeStateCreateInfoEXT<'static>>,
}
/// 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<ValidationError>> {
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
}
}

View File

@ -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<PipelineRenderingCreateInfoFields1Vk> {
match self {
PipelineSubpassType::BeginRenderPass(_) => None,
PipelineSubpassType::BeginRendering(rendering_info) => {
Some(rendering_info.to_vk_fields1())
}
}
}
}
impl From<Subpass> 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]>,
}

View File

@ -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<ash::vk::PipelineTessellationDomainOriginStateCreateInfo<'static>>,
}
vulkan_enum! {

View File

@ -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<ash::vk::PipelineVertexInputDivisorStateCreateInfoEXT<'a>>,
}
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<ash::vk::VertexInputBindingDivisorDescriptionKHR> {
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<VertexInputRate> 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),
}
}
}

View File

@ -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<ash::vk::Rect2D> 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],
}
}
}

View File

@ -123,31 +123,8 @@ impl PipelineLayout {
device: Arc<Device>,
create_info: PipelineLayoutCreateInfo,
) -> Result<Arc<PipelineLayout>, 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`

View File

@ -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<u8> = 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<ash::vk::PipelineShaderStageRequiredSubgroupSizeCreateInfo<'static>>,
}
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<ash::vk::SpecializationMapEntry>,
pub(crate) specialization_data_vk: Vec<u8>,
}
vulkan_bitflags! {

View File

@ -60,20 +60,7 @@ impl QueryPool {
device: Arc<Device>,
create_info: QueryPoolCreateInfo,
) -> Result<Arc<QueryPool>, 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! {

View File

@ -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<ash::vk::RenderPass, VulkanError> {
let &RenderPassCreateInfo {
flags,
ref attachments,
ref subpasses,
ref dependencies,
ref correlated_view_masks,
_ne: _,
} = create_info;
struct PerAttachment {
stencil_layout_vk: Option<ash::vk::AttachmentDescriptionStencilLayout<'static>>,
}
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<ash::vk::SubpassDescriptionDepthStencilResolve<'static>>,
}
#[derive(Default)]
struct PerAttachmentReferenceVk {
stencil_layout_vk: Option<ash::vk::AttachmentReferenceStencilLayout<'static>>,
}
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<ash::vk::MemoryBarrier2<'static>>,
}
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<ash::vk::RenderPass, VulkanError> {
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::<SmallVec<[_; 4]>>();
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::<SmallVec<[_; 4]>>();
/* 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()
})
}
}

View File

@ -247,27 +247,8 @@ impl Framebuffer {
) -> Result<Arc<Framebuffer>, 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! {

File diff suppressed because it is too large Load Diff

View File

@ -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<Arc<ShaderModule>, 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.

View File

@ -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<SwapchainPresentInfo>,
pub swapchain_infos: Vec<SwapchainPresentInfo>,
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<ValidationError>> {
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<ash::vk::Result> {
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<ash::vk::PresentIdKHR<'a>>,
pub(crate) present_mode_vk: Option<ash::vk::SwapchainPresentModeInfoEXT<'a>>,
pub(crate) present_regions_vk: Option<ash::vk::PresentRegionsKHR<'a>>,
}
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<RectangleLayer>,
pub present_region: Vec<RectangleLayer>,
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;

View File

@ -978,135 +978,13 @@ impl Swapchain {
create_info: &SwapchainCreateInfo,
old_swapchain: Option<&Swapchain>,
) -> Result<(ash::vk::SwapchainKHR, Vec<ash::vk::Image>), 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<AcquiredImage, VulkanError> {
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<ash::vk::SurfaceFullScreenExclusiveInfoEXT<'static>>,
pub(crate) full_screen_exclusive_win32_vk:
Option<ash::vk::SurfaceFullScreenExclusiveWin32InfoEXT<'static>>,
pub(crate) image_format_list_vk: Option<ash::vk::ImageFormatListCreateInfo<'a>>,
pub(crate) present_modes_vk: Option<ash::vk::SwapchainPresentModesCreateInfoEXT<'a>>,
pub(crate) present_scaling_vk: Option<ash::vk::SwapchainPresentScalingCreateInfoEXT<'static>>,
}
pub(crate) struct SwapchainCreateInfoFields1Vk {
pub(crate) present_modes_vk: SmallVec<[ash::vk::PresentModeKHR; PresentMode::COUNT]>,
pub(crate) view_formats_vk: Vec<ash::vk::Format>,
}
vulkan_bitflags! {

View File

@ -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<Instance>,
object: Option<Arc<dyn Any + Send + Sync>>,
) -> Result<Arc<Self>, 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<DisplayMode>,
create_info: DisplaySurfaceCreateInfo,
) -> Result<Arc<Self>, 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<Arc<dyn Any + Send + Sync>>,
) -> Result<Arc<Self>, 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<Arc<dyn Any + Send + Sync>>,
) -> Result<Arc<Self>, 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<Arc<dyn Any + Send + Sync>>,
) -> Result<Arc<Self>, 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<Arc<dyn Any + Send + Sync>>,
) -> Result<Arc<Self>, 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<Arc<dyn Any + Send + Sync>>,
) -> Result<Arc<Self>, 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<Arc<dyn Any + Send + Sync>>,
) -> Result<Arc<Self>, 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<Arc<dyn Any + Send + Sync>>,
) -> Result<Arc<Self>, 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<Arc<dyn Any + Send + Sync>>,
) -> Result<Arc<Self>, 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<Arc<dyn Any + Send + Sync>>,
) -> Result<Arc<Self>, 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<Arc<dyn Any + Send + Sync>>,
) -> Result<Arc<Self>, 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<Arc<dyn Any + Send + Sync>>,
) -> Result<Arc<Self>, 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<Arc<dyn Any + Send + Sync>>,
) -> Result<Arc<Self>, 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<Arc<dyn Any + Send + Sync>>,
) -> Result<Arc<Self>, 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<ash::vk::SurfaceFullScreenExclusiveInfoEXT<'static>>,
pub(crate) full_screen_exclusive_win32_vk:
Option<ash::vk::SurfaceFullScreenExclusiveWin32InfoEXT<'static>>,
pub(crate) present_mode_vk: Option<ash::vk::SurfacePresentModeEXT<'static>>,
}
/// 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<ash::vk::SurfaceCapabilitiesFullScreenExclusiveEXT<'static>>,
pub(crate) present_mode_compatibility_vk:
Option<ash::vk::SurfacePresentModeCompatibilityEXT<'a>>,
pub(crate) present_scaling_vk: Option<ash::vk::SurfacePresentScalingCapabilitiesEXT<'static>>,
pub(crate) protected_vk: Option<ash::vk::SurfaceProtectedCapabilitiesKHR<'static>>,
}
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 {

View File

@ -84,12 +84,7 @@ impl Event {
device: Arc<Device>,
create_info: EventCreateInfo,
) -> Result<Event, VulkanError> {
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! {

View File

@ -87,29 +87,8 @@ impl Fence {
device: Arc<Device>,
create_info: FenceCreateInfo,
) -> Result<Fence, VulkanError> {
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<File, VulkanError> {
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<ash::vk::HANDLE, VulkanError> {
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<ash::vk::ExportFenceCreateInfo<'static>>,
}
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::{

View File

@ -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)
}) {

View File

@ -571,7 +571,7 @@ pub(crate) unsafe fn queue_present(
let PresentInfo {
wait_semaphores: _,
swapchains,
swapchain_infos: swapchains,
_ne: _,
} = &present_info;

View File

@ -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)
}) {

View File

@ -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<I> Sharing<I>
where
I: IntoIterator<Item = u32>,
{
impl Sharing<SmallVec<[u32; 4]>> {
/// 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.

View File

@ -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<QueueFamilyOwnershipTransfer> 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,
),

View File

@ -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<Device>,
create_info: SemaphoreCreateInfo,
) -> Result<Semaphore, VulkanError> {
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<Duration>,
) -> 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<Duration>,
) -> 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<File, VulkanError> {
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<ash::vk::HANDLE, VulkanError> {
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<ash::vk::zx_handle_t, VulkanError> {
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<ash::vk::ExportSemaphoreCreateInfo<'static>>,
pub(crate) type_vk: Option<ash::vk::SemaphoreTypeCreateInfo<'static>>,
}
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<ash::vk::SemaphoreTypeCreateInfo<'static>>,
}
/// 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::{