mirror of
https://github.com/vulkano-rs/vulkano.git
synced 2024-11-23 23:35:54 +00:00
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:
parent
bad11eef71
commit
9033311653
@ -3,7 +3,6 @@ use crate::{
|
||||
resource::{AccessType, ImageLayoutType},
|
||||
Id,
|
||||
};
|
||||
use ash::vk;
|
||||
use smallvec::SmallVec;
|
||||
use std::{ffi::c_void, mem};
|
||||
use vulkano::{
|
||||
@ -43,14 +42,14 @@ impl RecordingCommandBuffer<'_> {
|
||||
let cmd_clear_color_image = fns.v1_0.cmd_clear_color_image;
|
||||
|
||||
if regions.is_empty() {
|
||||
let region_vk = image.subresource_range().into();
|
||||
let region_vk = image.subresource_range().to_vk();
|
||||
|
||||
unsafe {
|
||||
cmd_clear_color_image(
|
||||
self.handle(),
|
||||
image.handle(),
|
||||
image_layout.into(),
|
||||
&clear_value.into(),
|
||||
&clear_value.to_vk(),
|
||||
1,
|
||||
®ion_vk,
|
||||
)
|
||||
@ -58,8 +57,7 @@ impl RecordingCommandBuffer<'_> {
|
||||
} else {
|
||||
let regions_vk = regions
|
||||
.iter()
|
||||
.cloned()
|
||||
.map(vk::ImageSubresourceRange::from)
|
||||
.map(ImageSubresourceRange::to_vk)
|
||||
.collect::<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,
|
||||
®ion_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(),
|
||||
)
|
||||
|
@ -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),
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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(()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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]
|
||||
|
||||
|
@ -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>
|
||||
|
@ -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)]
|
||||
|
@ -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)]
|
||||
|
@ -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},
|
||||
|
@ -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()),
|
||||
|
@ -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
|
||||
|
@ -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)(
|
||||
|
@ -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
@ -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
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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)]
|
||||
|
@ -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 {
|
||||
|
@ -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.
|
||||
|
@ -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::{
|
||||
|
@ -65,7 +65,6 @@
|
||||
//!
|
||||
//! [`StandardDescriptorSetAllocator`]: allocator::StandardDescriptorSetAllocator
|
||||
|
||||
pub(crate) use self::update::DescriptorWriteInfo;
|
||||
use self::{
|
||||
allocator::DescriptorSetAllocator,
|
||||
layout::DescriptorSetLayout,
|
||||
|
@ -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! {
|
||||
|
@ -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)(
|
||||
|
@ -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
|
||||
|
@ -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
@ -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())
|
||||
}
|
||||
}
|
||||
|
@ -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,
|
||||
],
|
||||
}
|
||||
}
|
||||
|
@ -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]
|
||||
|
||||
|
@ -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]
|
||||
|
||||
|
@ -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]
|
||||
|
@ -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(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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! {
|
||||
|
@ -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)]
|
||||
|
@ -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! {
|
||||
|
@ -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]
|
||||
|
||||
|
@ -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! {
|
||||
|
@ -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)?;
|
||||
|
||||
|
@ -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
|
||||
|
@ -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! {
|
||||
|
@ -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)]
|
||||
|
@ -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(),
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
}
|
@ -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.
|
||||
|
@ -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! {
|
||||
|
@ -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
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -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]>,
|
||||
}
|
||||
|
@ -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! {
|
||||
|
@ -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),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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`
|
||||
|
@ -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! {
|
||||
|
@ -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! {
|
||||
|
@ -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()
|
||||
})
|
||||
}
|
||||
}
|
@ -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
@ -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.
|
||||
|
@ -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;
|
||||
|
@ -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! {
|
||||
|
@ -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 {
|
||||
|
@ -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! {
|
||||
|
@ -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::{
|
||||
|
@ -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)
|
||||
}) {
|
||||
|
@ -571,7 +571,7 @@ pub(crate) unsafe fn queue_present(
|
||||
|
||||
let PresentInfo {
|
||||
wait_semaphores: _,
|
||||
swapchains,
|
||||
swapchain_infos: swapchains,
|
||||
_ne: _,
|
||||
} = &present_info;
|
||||
|
||||
|
@ -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)
|
||||
}) {
|
||||
|
@ -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.
|
||||
|
@ -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,
|
||||
),
|
||||
|
@ -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::{
|
||||
|
Loading…
Reference in New Issue
Block a user