Upgrade to ash 0.38 (#2510)

* Upgrade to `ash 0.38`

https://github.com/ash-rs/ash/releases/tag/0.38.0

* Clean up subpass shading -> shader pipeline stage name
This commit is contained in:
Marijn Suijten 2024-04-07 12:16:30 +02:00 committed by GitHub
parent 91015a5eb2
commit 77abaff2f0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
31 changed files with 232 additions and 205 deletions

6
Cargo.lock generated
View File

@ -99,11 +99,11 @@ checksum = "175571dd1d178ced59193a6fc02dde1b972eb0bc56c892cde9beeceac5bf0f6b"
[[package]]
name = "ash"
version = "0.37.3+1.3.251"
version = "0.38.0+1.3.281"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "39e9c3835d686b0a6084ab4234fcd1b07dbf6e4767dce60874b12356a25ecd4a"
checksum = "0bb44936d800fea8f016d7f2311c6a4f97aebd5dc86f09906139ec848cf3a46f"
dependencies = [
"libloading 0.7.4",
"libloading 0.8.1",
]
[[package]]

View File

@ -31,7 +31,7 @@ ahash = "0.8"
# When updating Ash, also update vk.xml to the same Vulkan patch version that Ash uses.
# All versions of vk.xml can be found at:
# https://github.com/KhronosGroup/Vulkan-Headers/commits/main/registry/vk.xml
ash = "0.37.3"
ash = "0.38.0"
bytemuck = "1.9"
core-graphics-types = "0.1"
crossbeam-queue = "0.3"

View File

@ -615,7 +615,7 @@ struct FeaturesFfiMember {
fn features_ffi_output(members: &[FeaturesFfiMember]) -> TokenStream {
let struct_items = members.iter().map(|FeaturesFfiMember { name, ty, .. }| {
quote! { #name: Option<ash::vk::#ty>, }
quote! { #name: Option<ash::vk::#ty<'static>>, }
});
let make_chain_items = members.iter().map(
@ -640,7 +640,7 @@ fn features_ffi_output(members: &[FeaturesFfiMember]) -> TokenStream {
quote! {
#[derive(Default)]
pub(crate) struct DeviceFeaturesFfi {
features_vulkan10: ash::vk::PhysicalDeviceFeatures2KHR,
features_vulkan10: ash::vk::PhysicalDeviceFeatures2KHR<'static>,
#(#struct_items)*
}
@ -656,11 +656,11 @@ fn features_ffi_output(members: &[FeaturesFfiMember]) -> TokenStream {
#(#make_chain_items)*
}
pub(crate) fn head_as_ref(&self) -> &ash::vk::PhysicalDeviceFeatures2KHR {
pub(crate) fn head_as_ref(&self) -> &ash::vk::PhysicalDeviceFeatures2KHR<'static> {
&self.features_vulkan10
}
pub(crate) fn head_as_mut(&mut self) -> &mut ash::vk::PhysicalDeviceFeatures2KHR {
pub(crate) fn head_as_mut(&mut self) -> &mut ash::vk::PhysicalDeviceFeatures2KHR<'static> {
&mut self.features_vulkan10
}
}

View File

@ -1,23 +1,27 @@
use super::{write_file, IndexMap, VkRegistryData};
use heck::{ToSnakeCase, ToUpperCamelCase};
use proc_macro2::{Ident, TokenStream};
use proc_macro2::{Ident, Span, TokenStream};
use quote::{format_ident, quote};
use vk_parse::{Extension, ExtensionChild, InterfaceItem};
use vk_parse::{Command, Extension, ExtensionChild, InterfaceItem};
pub fn write(vk_data: &VkRegistryData<'_>) {
// TODO: Long strings break rustfmt
let entry_fns_output = fns_output(
&[],
std::iter::empty(),
"Entry",
&["1_0", "1_1" /*, "1_2", "1_3"*/],
"Raw Vulkan global entry point-level functions.\n\nTo use these, you need to include the Ash crate, using the same version Vulkano uses.",
);
let instance_fns_output = fns_output(
&instance_extension_fns_members(&vk_data.extensions),
extension_fns_members(&vk_data.commands, &vk_data.extensions, false),
"Instance",
&["1_0", "1_1" /*, "1_2"*/, "1_3"],
"Raw Vulkan instance-level functions.\n\nTo use these, you need to include the Ash crate, using the same version Vulkano uses.",
);
let device_fns_output = fns_output(
&device_extension_fns_members(&vk_data.extensions),
extension_fns_members(&vk_data.commands, &vk_data.extensions, true),
"Device",
&["1_0", "1_1", "1_2", "1_3"],
"Raw Vulkan device-level functions.\n\nTo use these, you need to include the Ash crate, using the same version Vulkano uses.",
);
write_file(
@ -37,26 +41,35 @@ pub fn write(vk_data: &VkRegistryData<'_>) {
#[derive(Clone, Debug)]
struct FnsMember {
name: Ident,
fn_struct: Ident,
/// Path to the struct
fn_struct: TokenStream,
}
fn fns_output(extension_members: &[FnsMember], fns_level: &str, doc: &str) -> TokenStream {
fn fns_output(
extension_members: impl Iterator<Item = FnsMember>,
fns_level: &str,
fns_versions: &[&str], // TODO: Parse from vk.xml?
doc: &str,
) -> TokenStream {
let struct_name = format_ident!("{}Functions", fns_level);
let members = ["1_0", "1_1", "1_2", "1_3"]
.into_iter()
.map(|version| FnsMember {
name: format_ident!("v{}", version),
fn_struct: format_ident!("{}FnV{}", fns_level, version),
let members = fns_versions
.iter()
.map(|version| {
let fn_struct = format_ident!("{}FnV{}", fns_level, version);
FnsMember {
name: format_ident!("v{}", version),
fn_struct: quote!(#fn_struct),
}
})
.chain(extension_members.iter().cloned())
.chain(extension_members)
.collect::<Vec<_>>();
let struct_items = members.iter().map(|FnsMember { name, fn_struct }| {
quote! { pub #name: ash::vk::#fn_struct, }
quote! { pub #name: ash::#fn_struct, }
});
let load_items = members.iter().map(|FnsMember { name, fn_struct }| {
quote! { #name: ash::vk::#fn_struct::load(&mut load_fn), }
quote! { #name: ash::#fn_struct::load(&mut load_fn), }
});
quote! {
@ -87,65 +100,61 @@ fn fns_output(extension_members: &[FnsMember], fns_level: &str, doc: &str) -> To
}
}
fn device_extension_fns_members(extensions: &IndexMap<&str, &Extension>) -> Vec<FnsMember> {
/// Returns [`false`] when this is an `instance` or `entry` command
fn is_device_command(commands: &IndexMap<&str, &Command>, name: &str) -> bool {
// Based on
// https://github.com/ash-rs/ash/blob/b724b78dac8d83879ed7a1aad2b91bb9f2beb5cf/generator/src/lib.rs#L568-L586
let mut name = name;
loop {
let command = commands[name];
match command {
Command::Alias { alias, .. } => name = alias.as_str(),
Command::Definition(command) => {
break command.params.first().map_or(false, |field| {
matches!(
field.definition.type_name.as_deref(),
Some("VkDevice" | "VkCommandBuffer" | "VkQueue")
)
})
}
_ => todo!(),
}
}
}
fn extension_fns_members<'a>(
commands: &'a IndexMap<&str, &Command>,
extensions: &'a IndexMap<&str, &Extension>,
device_functions: bool,
// extension_filter: impl Fn(&str) -> bool,
) -> impl Iterator<Item = FnsMember> + 'a {
let fn_struct_name = if device_functions {
format_ident!("DeviceFn")
} else {
format_ident!("InstanceFn")
};
extensions
.values()
// Include any device extensions that have functions.
.filter(|ext| ext.ext_type.as_ref().unwrap() == "device")
.filter(|ext| {
ext.children.iter().any(|ch| {
.filter(move |ext| {
ext.children.iter().any(move |ch| {
if let ExtensionChild::Require { items, .. } = ch {
items
.iter()
.any(|i| matches!(i, InterfaceItem::Command { .. }))
.any(move |i| matches!(i, InterfaceItem::Command { name, .. } if device_functions == is_device_command(commands, name)))
} else {
false
}
})
})
.map(|ext| {
let base = ext.name.strip_prefix("VK_").unwrap().to_snake_case();
.map(move |ext| {
let base = ext.name.strip_prefix("VK_").unwrap().to_lowercase();
let (vendor, extension) = base.split_once('_').unwrap();
let vendor = Ident::new(vendor, Span::call_site());
let extension = Ident::new(extension, Span::call_site());
let name = format_ident!("{}", base);
let fn_struct = format_ident!("{}Fn", base.to_upper_camel_case());
let fn_struct = quote!(#vendor::#extension::#fn_struct_name);
FnsMember { name, fn_struct }
})
.collect()
}
fn instance_extension_fns_members(extensions: &IndexMap<&str, &Extension>) -> Vec<FnsMember> {
extensions
.values()
.filter(|ext| {
match ext.ext_type.as_deref().unwrap() {
// Include any instance extensions that have functions.
"instance" => ext.children.iter().any(|ch| {
if let ExtensionChild::Require { items, .. } = ch {
items
.iter()
.any(|i| matches!(i, InterfaceItem::Command { .. }))
} else {
false
}
}),
// Include device extensions that have functions containing "PhysicalDevice".
// Note: this test might not be sufficient in the long run...
"device" => ext.children.iter().any(|ch| {
if let ExtensionChild::Require { items, .. } = ch {
items
.iter()
.any(|i| matches!(i, InterfaceItem::Command { name, .. } if name.contains("PhysicalDevice")))
} else {
false
}
}),
_ => unreachable!(),
}
})
.map(|ext| {
let base = ext.name.strip_prefix("VK_").unwrap().to_snake_case();
let name = format_ident!("{}", base);
let fn_struct = format_ident!("{}Fn", base.to_upper_camel_case());
FnsMember { name, fn_struct }
})
.collect()
}

View File

@ -15,11 +15,11 @@ use std::{
io::{BufWriter, Write},
ops::BitOrAssign,
path::Path,
process::Command,
process,
};
use vk_parse::{
Enum, EnumSpec, Enums, EnumsChild, Extension, ExtensionChild, Feature, Format, InterfaceItem,
Registry, RegistryChild, SpirvExtOrCap, Type, TypeSpec, TypesChild,
Command, Enum, EnumSpec, Enums, EnumsChild, Extension, ExtensionChild, Feature, Format,
InterfaceItem, Registry, RegistryChild, SpirvExtOrCap, Type, TypeSpec, TypesChild,
};
mod conjunctive_normal_form;
@ -68,7 +68,7 @@ fn write_file(file: impl AsRef<Path>, source: impl AsRef<str>, content: impl Dis
.unwrap();
drop(writer); // Ensure that the file is fully written
Command::new("rustfmt").arg(&path).status().ok();
process::Command::new("rustfmt").arg(&path).status().ok();
}
fn get_vk_registry<P: AsRef<Path> + ?Sized>(path: &P) -> Registry {
@ -94,6 +94,7 @@ pub struct VkRegistryData<'r> {
pub spirv_capabilities: Vec<&'r SpirvExtOrCap>,
pub spirv_extensions: Vec<&'r SpirvExtOrCap>,
pub types: HashMap<&'r str, (&'r Type, Vec<&'r str>)>,
pub commands: IndexMap<&'r str, &'r Command>,
}
impl<'r> VkRegistryData<'r> {
@ -107,6 +108,7 @@ impl<'r> VkRegistryData<'r> {
let errors = Self::get_errors(registry, &features, &extensions);
let types = Self::get_types(registry, &aliases, &features, &extensions);
let header_version = Self::get_header_version(registry);
let commands = Self::get_commands(registry);
VkRegistryData {
header_version,
@ -117,6 +119,7 @@ impl<'r> VkRegistryData<'r> {
spirv_capabilities,
spirv_extensions,
types,
commands,
}
}
@ -435,6 +438,30 @@ impl<'r> VkRegistryData<'r> {
.filter(|(_key, val)| !val.1.is_empty())
.collect()
}
fn get_commands(registry: &Registry) -> IndexMap<&str, &Command> {
registry
.0
.iter()
.filter_map(|child| {
// TODO: resolve aliases into CommandDefinition immediately?
if let RegistryChild::Commands(commands) = child {
return Some(commands.children.iter().map(|c| {
(
match c {
Command::Alias { name, .. } => name.as_str(),
Command::Definition(d) => d.proto.name.as_str(),
_ => todo!(),
},
c,
)
}));
}
None
})
.flatten()
.collect()
}
}
pub fn get_spirv_grammar<P: AsRef<Path> + ?Sized>(path: &P) -> SpirvGrammar {

View File

@ -320,7 +320,7 @@ struct PropertiesFfiMember {
fn properties_ffi_output(members: &[PropertiesFfiMember]) -> TokenStream {
let struct_items = members.iter().map(|PropertiesFfiMember { name, ty, .. }| {
quote! { #name: Option<ash::vk::#ty>, }
quote! { #name: Option<ash::vk::#ty<'static>>, }
});
let make_chain_items = members.iter().map(
@ -345,7 +345,7 @@ fn properties_ffi_output(members: &[PropertiesFfiMember]) -> TokenStream {
quote! {
#[derive(Default)]
pub(crate) struct DevicePropertiesFfi {
properties_vulkan10: ash::vk::PhysicalDeviceProperties2KHR,
properties_vulkan10: ash::vk::PhysicalDeviceProperties2KHR<'static>,
#(#struct_items)*
}
@ -361,7 +361,7 @@ fn properties_ffi_output(members: &[PropertiesFfiMember]) -> TokenStream {
#(#make_chain_items)*
}
pub(crate) fn head_as_mut(&mut self) -> &mut ash::vk::PhysicalDeviceProperties2KHR {
pub(crate) fn head_as_mut(&mut self) -> &mut ash::vk::PhysicalDeviceProperties2KHR<'static> {
&mut self.properties_vulkan10
}
}

View File

@ -596,8 +596,8 @@ impl AccelerationStructureBuildGeometryInfo {
pub(crate) fn to_vulkan(
&self,
) -> (
ash::vk::AccelerationStructureBuildGeometryInfoKHR,
Vec<ash::vk::AccelerationStructureGeometryKHR>,
ash::vk::AccelerationStructureBuildGeometryInfoKHR<'static>,
Vec<ash::vk::AccelerationStructureGeometryKHR<'static>>,
) {
let &Self {
flags,

View File

@ -1311,8 +1311,8 @@ impl RawRecordingCommandBuffer {
struct PerDescriptorWrite {
write_info: DescriptorWriteInfo,
acceleration_structures: ash::vk::WriteDescriptorSetAccelerationStructureKHR,
inline_uniform_block: ash::vk::WriteDescriptorSetInlineUniformBlock,
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());

View File

@ -183,7 +183,7 @@ impl RawRecordingCommandBuffer {
..Default::default()
};
let fns = self.device().instance().fns();
let fns = self.device().fns();
(fns.ext_debug_utils.cmd_begin_debug_utils_label_ext)(self.handle(), &label_info);
self
@ -230,7 +230,7 @@ impl RawRecordingCommandBuffer {
#[cfg_attr(not(feature = "document_unchecked"), doc(hidden))]
pub unsafe fn end_debug_utils_label_unchecked(&mut self) -> &mut Self {
let fns = self.device().instance().fns();
let fns = self.device().fns();
(fns.ext_debug_utils.cmd_end_debug_utils_label_ext)(self.handle());
self
@ -299,7 +299,7 @@ impl RawRecordingCommandBuffer {
..Default::default()
};
let fns = self.device().instance().fns();
let fns = self.device().fns();
(fns.ext_debug_utils.cmd_insert_debug_utils_label_ext)(self.handle(), &label_info);
self

View File

@ -804,11 +804,11 @@ impl RawRecordingCommandBuffer {
}));
}
}
PipelineStage::SubpassShading => {
PipelineStage::SubpassShader => {
if !device.enabled_features().subpass_shading {
return Err(Box::new(ValidationError {
context: "stage".into(),
problem: "is `PipelineStage::SubpassShading`".into(),
problem: "is `PipelineStage::SubpassShader`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[
Requires::DeviceFeature("subpass_shading"),
])]),

View File

@ -999,9 +999,9 @@ impl RawRecordingCommandBuffer {
if self.device().enabled_features().synchronization2 {
struct PerDependencyInfo {
memory_barriers_vk: SmallVec<[ash::vk::MemoryBarrier2; 2]>,
buffer_memory_barriers_vk: SmallVec<[ash::vk::BufferMemoryBarrier2; 8]>,
image_memory_barriers_vk: SmallVec<[ash::vk::ImageMemoryBarrier2; 8]>,
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 mut events_vk: SmallVec<[_; 4]> = SmallVec::new();
@ -1486,10 +1486,10 @@ impl RawRecordingCommandBuffer {
}
if !device.enabled_features().subpass_shading {
if stages.intersects(PipelineStages::SUBPASS_SHADING) {
if stages.intersects(PipelineStages::SUBPASS_SHADER) {
return Err(Box::new(ValidationError {
context: "stages".into(),
problem: "contains `PipelineStages::SUBPASS_SHADING`".into(),
problem: "contains `PipelineStages::SUBPASS_SHADER`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::DeviceFeature(
"subpass_shading",
)])]),

View File

@ -1103,11 +1103,11 @@ impl SemaphoreSubmitInfo {
}
if !device.enabled_features().subpass_shading
&& stages.intersects(PipelineStages::SUBPASS_SHADING)
&& stages.intersects(PipelineStages::SUBPASS_SHADER)
{
return Err(Box::new(ValidationError {
context: "stages".into(),
problem: "contains `PipelineStages::SUBPASS_SHADING`".into(),
problem: "contains `PipelineStages::SUBPASS_SHADER`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::DeviceFeature(
"subpass_shading",
)])]),

View File

@ -117,6 +117,7 @@ impl DescriptorSetLayout {
descriptor_count,
stage_flags: stages.into(),
p_immutable_samplers: ptr::null(),
..Default::default()
});
per_binding_vk.push(PerBinding {
immutable_samplers_vk: immutable_samplers

View File

@ -119,8 +119,8 @@ impl RawDescriptorSet {
) {
struct PerDescriptorWrite {
write_info: DescriptorWriteInfo,
acceleration_structures: ash::vk::WriteDescriptorSetAccelerationStructureKHR,
inline_uniform_block: ash::vk::WriteDescriptorSetInlineUniformBlock,
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());

View File

@ -1478,7 +1478,7 @@ impl WriteDescriptorSet {
&self,
dst_set: ash::vk::DescriptorSet,
descriptor_type: DescriptorType,
) -> ash::vk::WriteDescriptorSet {
) -> ash::vk::WriteDescriptorSet<'static> {
ash::vk::WriteDescriptorSet {
dst_set,
dst_binding: self.binding,

View File

@ -945,6 +945,7 @@ impl Device {
descriptor_count,
stage_flags: stages.into(),
p_immutable_samplers: ptr::null(),
..Default::default()
});
per_binding_vk.push(PerBinding {
immutable_samplers_vk: immutable_samplers
@ -1579,7 +1580,7 @@ impl Device {
};
unsafe {
let fns = self.instance().fns();
let fns = self.fns();
(fns.ext_debug_utils.set_debug_utils_object_name_ext)(self.handle, &info)
.result()
.map_err(VulkanError::from)?;

View File

@ -30,7 +30,6 @@ use crate::{
use bytemuck::cast_slice;
use parking_lot::RwLock;
use std::{
ffi::CStr,
fmt::{Debug, Error as FmtError, Formatter},
mem::MaybeUninit,
num::NonZeroU64,
@ -560,9 +559,8 @@ impl PhysicalDevice {
self.display_properties
.get_or_insert(properties_vk.display, |&handle| {
let properties = DisplayProperties {
name: properties_vk.display_name.as_ref().map(|name| {
CStr::from_ptr(name)
.to_str()
name: properties_vk.display_name_as_c_str().map(|name| {
name.to_str()
.expect("non UTF-8 characters in display name")
.to_owned()
}),
@ -621,9 +619,8 @@ impl PhysicalDevice {
self.display_properties
.get_or_insert(properties_vk.display, |&handle| {
let properties = DisplayProperties {
name: properties_vk.display_name.as_ref().map(|name| {
CStr::from_ptr(name)
.to_str()
name: properties_vk.display_name_as_c_str().map(|name| {
name.to_str()
.expect("non UTF-8 characters in display name")
.to_owned()
}),

View File

@ -13,7 +13,7 @@ use crate::{
shader::ShaderStages,
DeviceSize, Version,
};
use std::{ffi::CStr, os::raw::c_char};
use std::ffi::c_char;
// Generated by build.rs
include!(concat!(env!("OUT_DIR"), "/properties.rs"));
@ -105,9 +105,17 @@ impl<const N: usize> FromVulkan<[f32; N]> for [f32; N] {
}
impl<const N: usize> FromVulkan<[c_char; N]> for String {
/// <https://github.com/ash-rs/ash/blob/b724b78dac8d83879ed7a1aad2b91bb9f2beb5cf/ash/src/vk/prelude.rs#L66-L73>
#[inline]
fn from_vulkan(val: [c_char; N]) -> Option<Self> {
Some(unsafe { CStr::from_ptr(val.as_ptr()).to_string_lossy().into_owned() })
// SAFETY: The cast from c_char to u8 is ok because a c_char is always one byte.
let bytes = unsafe { core::slice::from_raw_parts(val.as_ptr().cast(), val.len()) };
Some(
core::ffi::CStr::from_bytes_until_nul(bytes)
.unwrap()
.to_string_lossy()
.into_owned(),
)
}
}

View File

@ -228,11 +228,12 @@ impl<'a> QueueGuard<'a> {
) -> Result<(), VulkanError> {
struct PerBindSparseInfo {
wait_semaphores_vk: SmallVec<[ash::vk::Semaphore; 4]>,
buffer_bind_infos_vk: SmallVec<[ash::vk::SparseBufferMemoryBindInfo; 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; 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; 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]>,
}
@ -259,11 +260,8 @@ impl<'a> QueueGuard<'a> {
.iter()
.map(|(buffer, memory_binds)| {
(
ash::vk::SparseBufferMemoryBindInfo {
buffer: buffer.buffer().handle(),
bind_count: 0,
p_binds: ptr::null(),
},
ash::vk::SparseBufferMemoryBindInfo::default()
.buffer(buffer.buffer().handle()),
memory_binds
.iter()
.map(|memory_bind| {
@ -300,11 +298,8 @@ impl<'a> QueueGuard<'a> {
.iter()
.map(|(image, memory_binds)| {
(
ash::vk::SparseImageOpaqueMemoryBindInfo {
image: image.handle(),
bind_count: 0,
p_binds: ptr::null(),
},
ash::vk::SparseImageOpaqueMemoryBindInfo::default()
.image(image.handle()),
memory_binds
.iter()
.map(|memory_bind| {
@ -342,11 +337,7 @@ impl<'a> QueueGuard<'a> {
.iter()
.map(|(image, memory_binds)| {
(
ash::vk::SparseImageMemoryBindInfo {
image: image.handle(),
bind_count: 0,
p_binds: ptr::null(),
},
ash::vk::SparseImageMemoryBindInfo::default().image(image.handle()),
memory_binds
.iter()
.map(|memory_bind| {
@ -607,8 +598,8 @@ impl<'a> QueueGuard<'a> {
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 present_regions_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;
@ -689,10 +680,8 @@ impl<'a> QueueGuard<'a> {
for (present_regions_vk, rectangles_vk) in
present_regions_vk.iter_mut().zip(rectangles_vk.iter())
{
*present_regions_vk = ash::vk::PresentRegionKHR {
rectangle_count: rectangles_vk.len() as u32,
p_rectangles: rectangles_vk.as_ptr(),
};
*present_regions_vk =
ash::vk::PresentRegionKHR::default().rectangles(rectangles_vk);
}
let next = present_region_info_vk.insert(ash::vk::PresentRegionsKHR {
@ -907,9 +896,9 @@ impl<'a> QueueGuard<'a> {
) -> Result<(), VulkanError> {
if self.queue.device.enabled_features().synchronization2 {
struct PerSubmitInfo {
wait_semaphore_infos_vk: SmallVec<[ash::vk::SemaphoreSubmitInfo; 4]>,
command_buffer_infos_vk: SmallVec<[ash::vk::CommandBufferSubmitInfo; 4]>,
signal_semaphore_infos_vk: SmallVec<[ash::vk::SemaphoreSubmitInfo; 4]>,
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 (mut submit_info_vk, mut per_submit_vk): (SmallVec<[_; 4]>, SmallVec<[_; 4]>) =
@ -1045,7 +1034,8 @@ impl<'a> QueueGuard<'a> {
.map_err(VulkanError::from)
} else {
struct PerSubmitInfo {
timeline_semaphore_submit_info_vk: Option<ash::vk::TimelineSemaphoreSubmitInfo>,
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]>,
@ -1261,7 +1251,7 @@ impl<'a> QueueGuard<'a> {
..Default::default()
};
let fns = self.queue.device.instance().fns();
let fns = self.queue.device.fns();
(fns.ext_debug_utils.queue_begin_debug_utils_label_ext)(self.queue.handle, &label_info);
}
@ -1307,7 +1297,7 @@ impl<'a> QueueGuard<'a> {
#[cfg_attr(not(feature = "document_unchecked"), doc(hidden))]
#[inline]
pub unsafe fn end_debug_utils_label_unchecked(&mut self) {
let fns = self.queue.device.instance().fns();
let fns = self.queue.device.fns();
(fns.ext_debug_utils.queue_end_debug_utils_label_ext)(self.queue.handle);
}
@ -1366,7 +1356,7 @@ impl<'a> QueueGuard<'a> {
..Default::default()
};
let fns = self.queue.device.instance().fns();
let fns = self.queue.device.fns();
(fns.ext_debug_utils.queue_insert_debug_utils_label_ext)(self.queue.handle, &label_info);
}
}

View File

@ -312,7 +312,7 @@ impl DebugUtilsMessengerCallback {
pub(super) unsafe extern "system" fn trampoline(
message_severity_vk: ash::vk::DebugUtilsMessageSeverityFlagsEXT,
message_types_vk: ash::vk::DebugUtilsMessageTypeFlagsEXT,
callback_data_vk: *const ash::vk::DebugUtilsMessengerCallbackDataEXT,
callback_data_vk: *const ash::vk::DebugUtilsMessengerCallbackDataEXT<'_>,
user_data_vk: *mut c_void,
) -> ash::vk::Bool32 {
// Since we box the closure, the type system doesn't detect that the `UnwindSafe`
@ -331,6 +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 {
@ -415,23 +416,18 @@ pub struct DebugUtilsMessengerCallbackLabel<'a> {
}
#[derive(Clone, Debug)]
pub struct DebugUtilsMessengerCallbackLabelIter<'a>(slice::Iter<'a, ash::vk::DebugUtilsLabelEXT>);
pub struct DebugUtilsMessengerCallbackLabelIter<'a>(
slice::Iter<'a, ash::vk::DebugUtilsLabelEXT<'a>>,
);
impl<'a> Iterator for DebugUtilsMessengerCallbackLabelIter<'a> {
type Item = DebugUtilsMessengerCallbackLabel<'a>;
fn next(&mut self) -> Option<Self::Item> {
self.0.next().map(|label| unsafe {
let &ash::vk::DebugUtilsLabelEXT {
s_type: _,
p_next: _,
p_label_name,
ref color,
} = label;
DebugUtilsMessengerCallbackLabel {
label_name: CStr::from_ptr(p_label_name).to_str().unwrap(),
color,
label_name: label.label_name_as_c_str().unwrap().to_str().unwrap(),
color: &label.color,
}
})
}
@ -452,7 +448,7 @@ pub struct DebugUtilsMessengerCallbackObjectNameInfo<'a> {
#[derive(Clone, Debug)]
pub struct DebugUtilsMessengerCallbackObjectNameInfoIter<'a>(
slice::Iter<'a, ash::vk::DebugUtilsObjectNameInfoEXT>,
slice::Iter<'a, ash::vk::DebugUtilsObjectNameInfoEXT<'a>>,
);
impl<'a> Iterator for DebugUtilsMessengerCallbackObjectNameInfoIter<'a> {
@ -466,6 +462,7 @@ impl<'a> Iterator for DebugUtilsMessengerCallbackObjectNameInfoIter<'a> {
object_type,
object_handle,
p_object_name,
_marker: _,
} = info;
DebugUtilsMessengerCallbackObjectNameInfo {

View File

@ -1,5 +1,4 @@
use crate::Version;
use std::ffi::CStr;
/// Properties of a layer.
#[derive(Clone)]
@ -26,11 +25,7 @@ impl LayerProperties {
/// ```
#[inline]
pub fn name(&self) -> &str {
unsafe {
CStr::from_ptr(self.props.layer_name.as_ptr())
.to_str()
.unwrap()
}
self.props.layer_name_as_c_str().unwrap().to_str().unwrap()
}
/// Returns a description of the layer.
@ -50,11 +45,7 @@ impl LayerProperties {
/// ```
#[inline]
pub fn description(&self) -> &str {
unsafe {
CStr::from_ptr(self.props.description.as_ptr())
.to_str()
.unwrap()
}
self.props.description_as_c_str().unwrap().to_str().unwrap()
}
/// Returns the version of Vulkan supported by this layer.

View File

@ -453,14 +453,16 @@ impl From<ash::vk::PhysicalDeviceMemoryProperties> for MemoryProperties {
#[inline]
fn from(val: ash::vk::PhysicalDeviceMemoryProperties) -> Self {
Self {
memory_types: val.memory_types[0..val.memory_type_count as usize]
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[0..val.memory_heap_count as usize]
memory_heaps: val
.memory_heaps_as_slice()
.iter()
.map(|vk_memory_heap| MemoryHeap {
size: vk_memory_heap.size,

View File

@ -130,6 +130,7 @@ impl ComputePipeline {
p_map_entries: specialization_map_entries_vk.as_ptr(),
data_size: specialization_data_vk.len(),
p_data: specialization_data_vk.as_ptr() as *const _,
..Default::default()
};
required_subgroup_size_create_info =
required_subgroup_size.map(|required_subgroup_size| {

View File

@ -232,11 +232,11 @@ impl GraphicsPipeline {
struct PerPipelineShaderStageCreateInfo {
name_vk: CString,
specialization_info_vk: ash::vk::SpecializationInfo,
specialization_info_vk: ash::vk::SpecializationInfo<'static>,
specialization_map_entries_vk: Vec<ash::vk::SpecializationMapEntry>,
specialization_data_vk: Vec<u8>,
required_subgroup_size_create_info:
Option<ash::vk::PipelineShaderStageRequiredSubgroupSizeCreateInfo>,
Option<ash::vk::PipelineShaderStageRequiredSubgroupSizeCreateInfo<'static>>,
}
let (mut stages_vk, mut per_stage_vk): (SmallVec<[_; 5]>, SmallVec<[_; 5]>) = stages
@ -287,12 +287,13 @@ impl GraphicsPipeline {
..Default::default()
},
PerPipelineShaderStageCreateInfo {
name_vk: CString::new(entry_point_info.name.as_str()).unwrap(),
name_vk: CString::new(entry_point_info.name.as_str()).unwrap(), // TODO Borrow CStr for local data?
specialization_info_vk: ash::vk::SpecializationInfo {
map_entry_count: specialization_map_entries_vk.len() as u32,
p_map_entries: ptr::null(),
data_size: specialization_data_vk.len(),
p_data: ptr::null(),
..Default::default()
},
specialization_map_entries_vk,
specialization_data_vk,

View File

@ -22,7 +22,7 @@ impl RenderPass {
} = create_info;
struct PerAttachment {
stencil_layout_vk: Option<ash::vk::AttachmentDescriptionStencilLayout>,
stencil_layout_vk: Option<ash::vk::AttachmentDescriptionStencilLayout<'static>>,
}
let (mut attachments_vk, mut per_attachment_vk): (SmallVec<[_; 4]>, SmallVec<[_; 4]>) =
@ -84,20 +84,21 @@ impl RenderPass {
}
struct PerSubpassDescriptionVk {
input_attachments_vk: SmallVec<[ash::vk::AttachmentReference2; 4]>,
input_attachments_vk: SmallVec<[ash::vk::AttachmentReference2<'static>; 4]>,
per_input_attachments_vk: SmallVec<[PerAttachmentReferenceVk; 4]>,
color_attachments_vk: SmallVec<[ash::vk::AttachmentReference2; 4]>,
resolve_attachments_vk: SmallVec<[ash::vk::AttachmentReference2; 4]>,
depth_stencil_attachment_vk: ash::vk::AttachmentReference2,
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,
depth_stencil_resolve_attachment_vk: ash::vk::AttachmentReference2<'static>,
per_depth_stencil_resolve_attachment_vk: PerAttachmentReferenceVk,
depth_stencil_resolve_vk: Option<ash::vk::SubpassDescriptionDepthStencilResolve>,
depth_stencil_resolve_vk:
Option<ash::vk::SubpassDescriptionDepthStencilResolve<'static>>,
}
#[derive(Default)]
struct PerAttachmentReferenceVk {
stencil_layout_vk: Option<ash::vk::AttachmentReferenceStencilLayout>,
stencil_layout_vk: Option<ash::vk::AttachmentReferenceStencilLayout<'static>>,
}
let (mut subpasses_vk, mut per_subpass_vk): (SmallVec<[_; 4]>, SmallVec<[_; 4]>) =
@ -409,7 +410,7 @@ impl RenderPass {
}
struct PerSubpassDependencyVk {
memory_barrier_vk: Option<ash::vk::MemoryBarrier2>,
memory_barrier_vk: Option<ash::vk::MemoryBarrier2<'static>>,
}
let (mut dependencies_vk, mut per_dependency_vk): (SmallVec<[_; 4]>, SmallVec<[_; 4]>) =
@ -700,6 +701,7 @@ impl RenderPass {
} else {
preserve_attachments.as_ptr()
},
..Default::default()
},
PerSubpassDescriptionVk {
input_attachments_vk,

View File

@ -1545,7 +1545,7 @@ impl From<ShaderStages> for PipelineStages {
}
if stages.intersects(ShaderStages::SUBPASS_SHADING) {
result |= PipelineStages::SUBPASS_SHADING;
result |= PipelineStages::SUBPASS_SHADER;
}
result

View File

@ -80,7 +80,7 @@
//! # fn build_window() -> Arc<Window> { Arc::new(Window(ptr::null())) }
//! let window = build_window(); // Third-party function, not provided by vulkano
//! let _surface = unsafe {
//! let hinstance: *mut std::ffi::c_void = ptr::null_mut(); // Windows-specific object
//! let hinstance: ash::vk::HINSTANCE = 0; // Windows-specific object
//! Surface::from_win32(
//! instance.clone(),
//! hinstance,

View File

@ -2389,7 +2389,7 @@ mod tests {
#[test]
fn khr_win32_surface_ext_missing() {
let instance = instance!();
match unsafe { Surface::from_win32(instance, ptr::null_mut(), ptr::null_mut(), None) } {
match unsafe { Surface::from_win32(instance, 0, 0, None) } {
Err(Validated::ValidationError(err))
if matches!(
*err,

View File

@ -536,7 +536,7 @@ impl Fence {
pub fn export_win32_handle(
&self,
handle_type: ExternalFenceHandleType,
) -> Result<*mut std::ffi::c_void, Validated<VulkanError>> {
) -> Result<ash::vk::HANDLE, Validated<VulkanError>> {
self.validate_export_win32_handle(handle_type)?;
unsafe { Ok(self.export_win32_handle_unchecked(handle_type)?) }
@ -589,7 +589,7 @@ impl Fence {
pub unsafe fn export_win32_handle_unchecked(
&self,
handle_type: ExternalFenceHandleType,
) -> Result<*mut std::ffi::c_void, VulkanError> {
) -> Result<ash::vk::HANDLE, VulkanError> {
let info_vk = ash::vk::FenceGetWin32HandleInfoKHR {
fence: self.handle,
handle_type: handle_type.into(),
@ -1101,8 +1101,8 @@ pub struct ImportFenceWin32HandleInfo {
/// The file to import the fence from.
///
/// The default value is `null`, which must be overridden.
pub handle: *mut std::ffi::c_void,
/// The default value is `0`, which must be overridden.
pub handle: ash::vk::HANDLE,
pub _ne: crate::NonExhaustive,
}
@ -1114,7 +1114,7 @@ impl ImportFenceWin32HandleInfo {
Self {
flags: FenceImportFlags::empty(),
handle_type,
handle: ptr::null_mut(),
handle: 0,
_ne: crate::NonExhaustive(()),
}
}

View File

@ -376,8 +376,8 @@ vulkan_bitflags_enum! {
RequiresAllOf([DeviceExtension(nv_mesh_shader)]),
]),
/// Subpass shading shaders are executed.
SUBPASS_SHADING, SubpassShading = SUBPASS_SHADING_HUAWEI
/// Subpass shaders are executed.
SUBPASS_SHADER, SubpassShader = SUBPASS_SHADER_HUAWEI
RequiresOneOf([
RequiresAllOf([
APIVersion(V1_3),
@ -477,7 +477,7 @@ impl From<QueueFlags> for PipelineStages {
| PipelineStages::TASK_SHADER
| PipelineStages::MESH_SHADER
| PipelineStages::FRAGMENT_DENSITY_PROCESS
| PipelineStages::SUBPASS_SHADING
| PipelineStages::SUBPASS_SHADER
| PipelineStages::INVOCATION_MASK;
}
@ -983,7 +983,7 @@ impl From<PipelineStages> for AccessFlags {
| AccessFlags::ACCELERATION_STRUCTURE_READ;
}
if val.intersects(PipelineStages::FRAGMENT_SHADER | PipelineStages::SUBPASS_SHADING) {
if val.intersects(PipelineStages::FRAGMENT_SHADER | PipelineStages::SUBPASS_SHADER) {
result |= AccessFlags::INPUT_ATTACHMENT_READ;
}
@ -1383,7 +1383,7 @@ pipeline_stage_access! {
MeshShader_ShaderStorageRead, MESH_SHADER, SHADER_STORAGE_READ;
MeshShader_ShaderStorageWrite, MESH_SHADER, SHADER_STORAGE_WRITE;
MeshShader_AccelerationStructureRead, MESH_SHADER, ACCELERATION_STRUCTURE_READ;
SubpassShading_InputAttachmentRead, SUBPASS_SHADING, INPUT_ATTACHMENT_READ;
SubpassShading_InputAttachmentRead, SUBPASS_SHADER, INPUT_ATTACHMENT_READ;
InvocationMask_InvocationMaskRead, INVOCATION_MASK, INVOCATION_MASK_READ;
AccelerationStructureCopy_AccelerationStructureRead, ACCELERATION_STRUCTURE_COPY, ACCELERATION_STRUCTURE_READ;
AccelerationStructureCopy_AccelerationStructureWrite, ACCELERATION_STRUCTURE_COPY, ACCELERATION_STRUCTURE_WRITE;
@ -2171,10 +2171,10 @@ impl MemoryBarrier {
}
if !device.enabled_features().subpass_shading {
if src_stages.intersects(PipelineStages::SUBPASS_SHADING) {
if src_stages.intersects(PipelineStages::SUBPASS_SHADER) {
return Err(Box::new(ValidationError {
context: "src_stages".into(),
problem: "contains `PipelineStages::SUBPASS_SHADING`".into(),
problem: "contains `PipelineStages::SUBPASS_SHADER`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::DeviceFeature(
"subpass_shading",
)])]),
@ -2182,10 +2182,10 @@ impl MemoryBarrier {
}));
}
if dst_stages.intersects(PipelineStages::SUBPASS_SHADING) {
if dst_stages.intersects(PipelineStages::SUBPASS_SHADER) {
return Err(Box::new(ValidationError {
context: "dst_stages".into(),
problem: "contains `PipelineStages::SUBPASS_SHADING`".into(),
problem: "contains `PipelineStages::SUBPASS_SHADER`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::DeviceFeature(
"subpass_shading",
)])]),
@ -2691,10 +2691,10 @@ impl BufferMemoryBarrier {
}
if !device.enabled_features().subpass_shading {
if src_stages.intersects(PipelineStages::SUBPASS_SHADING) {
if src_stages.intersects(PipelineStages::SUBPASS_SHADER) {
return Err(Box::new(ValidationError {
context: "src_stages".into(),
problem: "contains `PipelineStages::SUBPASS_SHADING`".into(),
problem: "contains `PipelineStages::SUBPASS_SHADER`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::DeviceFeature(
"subpass_shading",
)])]),
@ -2702,10 +2702,10 @@ impl BufferMemoryBarrier {
}));
}
if dst_stages.intersects(PipelineStages::SUBPASS_SHADING) {
if dst_stages.intersects(PipelineStages::SUBPASS_SHADER) {
return Err(Box::new(ValidationError {
context: "dst_stages".into(),
problem: "contains `PipelineStages::SUBPASS_SHADING`".into(),
problem: "contains `PipelineStages::SUBPASS_SHADER`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::DeviceFeature(
"subpass_shading",
)])]),
@ -3369,10 +3369,10 @@ impl ImageMemoryBarrier {
}
if !device.enabled_features().subpass_shading {
if src_stages.intersects(PipelineStages::SUBPASS_SHADING) {
if src_stages.intersects(PipelineStages::SUBPASS_SHADER) {
return Err(Box::new(ValidationError {
context: "src_stages".into(),
problem: "contains `PipelineStages::SUBPASS_SHADING`".into(),
problem: "contains `PipelineStages::SUBPASS_SHADER`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::DeviceFeature(
"subpass_shading",
)])]),
@ -3380,10 +3380,10 @@ impl ImageMemoryBarrier {
}));
}
if dst_stages.intersects(PipelineStages::SUBPASS_SHADING) {
if dst_stages.intersects(PipelineStages::SUBPASS_SHADER) {
return Err(Box::new(ValidationError {
context: "dst_stages".into(),
problem: "contains `PipelineStages::SUBPASS_SHADING`".into(),
problem: "contains `PipelineStages::SUBPASS_SHADER`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::DeviceFeature(
"subpass_shading",
)])]),

View File

@ -676,7 +676,7 @@ impl Semaphore {
pub fn export_win32_handle(
&self,
handle_type: ExternalSemaphoreHandleType,
) -> Result<*mut std::ffi::c_void, Validated<VulkanError>> {
) -> Result<ash::vk::HANDLE, Validated<VulkanError>> {
self.validate_export_win32_handle(handle_type)?;
unsafe { Ok(self.export_win32_handle_unchecked(handle_type)?) }
@ -736,7 +736,7 @@ impl Semaphore {
pub unsafe fn export_win32_handle_unchecked(
&self,
handle_type: ExternalSemaphoreHandleType,
) -> Result<*mut std::ffi::c_void, VulkanError> {
) -> Result<ash::vk::HANDLE, VulkanError> {
let info_vk = ash::vk::SemaphoreGetWin32HandleInfoKHR {
semaphore: self.handle,
handle_type: handle_type.into(),
@ -1691,8 +1691,8 @@ pub struct ImportSemaphoreWin32HandleInfo {
/// The handle to import the semaphore from.
///
/// The default value is `null`, which must be overridden.
pub handle: *mut std::ffi::c_void,
/// The default value is `0`, which must be overridden.
pub handle: ash::vk::HANDLE,
pub _ne: crate::NonExhaustive,
}
@ -1704,7 +1704,7 @@ impl ImportSemaphoreWin32HandleInfo {
Self {
flags: SemaphoreImportFlags::empty(),
handle_type,
handle: ptr::null_mut(),
handle: 0,
_ne: crate::NonExhaustive(()),
}
}