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]] [[package]]
name = "ash" 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" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "39e9c3835d686b0a6084ab4234fcd1b07dbf6e4767dce60874b12356a25ecd4a" checksum = "0bb44936d800fea8f016d7f2311c6a4f97aebd5dc86f09906139ec848cf3a46f"
dependencies = [ dependencies = [
"libloading 0.7.4", "libloading 0.8.1",
] ]
[[package]] [[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. # 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: # All versions of vk.xml can be found at:
# https://github.com/KhronosGroup/Vulkan-Headers/commits/main/registry/vk.xml # https://github.com/KhronosGroup/Vulkan-Headers/commits/main/registry/vk.xml
ash = "0.37.3" ash = "0.38.0"
bytemuck = "1.9" bytemuck = "1.9"
core-graphics-types = "0.1" core-graphics-types = "0.1"
crossbeam-queue = "0.3" crossbeam-queue = "0.3"

View File

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

View File

@ -1,23 +1,27 @@
use super::{write_file, IndexMap, VkRegistryData}; use super::{write_file, IndexMap, VkRegistryData};
use heck::{ToSnakeCase, ToUpperCamelCase}; use proc_macro2::{Ident, Span, TokenStream};
use proc_macro2::{Ident, TokenStream};
use quote::{format_ident, quote}; use quote::{format_ident, quote};
use vk_parse::{Extension, ExtensionChild, InterfaceItem}; use vk_parse::{Command, Extension, ExtensionChild, InterfaceItem};
pub fn write(vk_data: &VkRegistryData<'_>) { pub fn write(vk_data: &VkRegistryData<'_>) {
// TODO: Long strings break rustfmt
let entry_fns_output = fns_output( let entry_fns_output = fns_output(
&[], std::iter::empty(),
"Entry", "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.", "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( let instance_fns_output = fns_output(
&instance_extension_fns_members(&vk_data.extensions), extension_fns_members(&vk_data.commands, &vk_data.extensions, false),
"Instance", "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.", "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( let device_fns_output = fns_output(
&device_extension_fns_members(&vk_data.extensions), extension_fns_members(&vk_data.commands, &vk_data.extensions, true),
"Device", "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.", "Raw Vulkan device-level functions.\n\nTo use these, you need to include the Ash crate, using the same version Vulkano uses.",
); );
write_file( write_file(
@ -37,26 +41,35 @@ pub fn write(vk_data: &VkRegistryData<'_>) {
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
struct FnsMember { struct FnsMember {
name: Ident, 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 struct_name = format_ident!("{}Functions", fns_level);
let members = ["1_0", "1_1", "1_2", "1_3"] let members = fns_versions
.into_iter() .iter()
.map(|version| FnsMember { .map(|version| {
name: format_ident!("v{}", version), let fn_struct = format_ident!("{}FnV{}", fns_level, version);
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<_>>(); .collect::<Vec<_>>();
let struct_items = members.iter().map(|FnsMember { name, fn_struct }| { 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 }| { 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! { 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 extensions
.values() .values()
// Include any device extensions that have functions. .filter(move |ext| {
.filter(|ext| ext.ext_type.as_ref().unwrap() == "device") ext.children.iter().any(move |ch| {
.filter(|ext| {
ext.children.iter().any(|ch| {
if let ExtensionChild::Require { items, .. } = ch { if let ExtensionChild::Require { items, .. } = ch {
items items
.iter() .iter()
.any(|i| matches!(i, InterfaceItem::Command { .. })) .any(move |i| matches!(i, InterfaceItem::Command { name, .. } if device_functions == is_device_command(commands, name)))
} else { } else {
false false
} }
}) })
}) })
.map(|ext| { .map(move |ext| {
let base = ext.name.strip_prefix("VK_").unwrap().to_snake_case(); 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 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 } 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}, io::{BufWriter, Write},
ops::BitOrAssign, ops::BitOrAssign,
path::Path, path::Path,
process::Command, process,
}; };
use vk_parse::{ use vk_parse::{
Enum, EnumSpec, Enums, EnumsChild, Extension, ExtensionChild, Feature, Format, InterfaceItem, Command, Enum, EnumSpec, Enums, EnumsChild, Extension, ExtensionChild, Feature, Format,
Registry, RegistryChild, SpirvExtOrCap, Type, TypeSpec, TypesChild, InterfaceItem, Registry, RegistryChild, SpirvExtOrCap, Type, TypeSpec, TypesChild,
}; };
mod conjunctive_normal_form; mod conjunctive_normal_form;
@ -68,7 +68,7 @@ fn write_file(file: impl AsRef<Path>, source: impl AsRef<str>, content: impl Dis
.unwrap(); .unwrap();
drop(writer); // Ensure that the file is fully written 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 { 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_capabilities: Vec<&'r SpirvExtOrCap>,
pub spirv_extensions: Vec<&'r SpirvExtOrCap>, pub spirv_extensions: Vec<&'r SpirvExtOrCap>,
pub types: HashMap<&'r str, (&'r Type, Vec<&'r str>)>, pub types: HashMap<&'r str, (&'r Type, Vec<&'r str>)>,
pub commands: IndexMap<&'r str, &'r Command>,
} }
impl<'r> VkRegistryData<'r> { impl<'r> VkRegistryData<'r> {
@ -107,6 +108,7 @@ impl<'r> VkRegistryData<'r> {
let errors = Self::get_errors(registry, &features, &extensions); let errors = Self::get_errors(registry, &features, &extensions);
let types = Self::get_types(registry, &aliases, &features, &extensions); let types = Self::get_types(registry, &aliases, &features, &extensions);
let header_version = Self::get_header_version(registry); let header_version = Self::get_header_version(registry);
let commands = Self::get_commands(registry);
VkRegistryData { VkRegistryData {
header_version, header_version,
@ -117,6 +119,7 @@ impl<'r> VkRegistryData<'r> {
spirv_capabilities, spirv_capabilities,
spirv_extensions, spirv_extensions,
types, types,
commands,
} }
} }
@ -435,6 +438,30 @@ impl<'r> VkRegistryData<'r> {
.filter(|(_key, val)| !val.1.is_empty()) .filter(|(_key, val)| !val.1.is_empty())
.collect() .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 { 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 { fn properties_ffi_output(members: &[PropertiesFfiMember]) -> TokenStream {
let struct_items = members.iter().map(|PropertiesFfiMember { name, ty, .. }| { 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( let make_chain_items = members.iter().map(
@ -345,7 +345,7 @@ fn properties_ffi_output(members: &[PropertiesFfiMember]) -> TokenStream {
quote! { quote! {
#[derive(Default)] #[derive(Default)]
pub(crate) struct DevicePropertiesFfi { pub(crate) struct DevicePropertiesFfi {
properties_vulkan10: ash::vk::PhysicalDeviceProperties2KHR, properties_vulkan10: ash::vk::PhysicalDeviceProperties2KHR<'static>,
#(#struct_items)* #(#struct_items)*
} }
@ -361,7 +361,7 @@ fn properties_ffi_output(members: &[PropertiesFfiMember]) -> TokenStream {
#(#make_chain_items)* #(#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 &mut self.properties_vulkan10
} }
} }

View File

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

View File

@ -1311,8 +1311,8 @@ impl RawRecordingCommandBuffer {
struct PerDescriptorWrite { struct PerDescriptorWrite {
write_info: DescriptorWriteInfo, write_info: DescriptorWriteInfo,
acceleration_structures: ash::vk::WriteDescriptorSetAccelerationStructureKHR, acceleration_structures: ash::vk::WriteDescriptorSetAccelerationStructureKHR<'static>,
inline_uniform_block: ash::vk::WriteDescriptorSetInlineUniformBlock, inline_uniform_block: ash::vk::WriteDescriptorSetInlineUniformBlock<'static>,
} }
let mut writes_vk: SmallVec<[_; 8]> = SmallVec::with_capacity(descriptor_writes.len()); let mut writes_vk: SmallVec<[_; 8]> = SmallVec::with_capacity(descriptor_writes.len());

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -119,8 +119,8 @@ impl RawDescriptorSet {
) { ) {
struct PerDescriptorWrite { struct PerDescriptorWrite {
write_info: DescriptorWriteInfo, write_info: DescriptorWriteInfo,
acceleration_structures: ash::vk::WriteDescriptorSetAccelerationStructureKHR, acceleration_structures: ash::vk::WriteDescriptorSetAccelerationStructureKHR<'static>,
inline_uniform_block: ash::vk::WriteDescriptorSetInlineUniformBlock, inline_uniform_block: ash::vk::WriteDescriptorSetInlineUniformBlock<'static>,
} }
let mut writes_vk: SmallVec<[_; 8]> = SmallVec::with_capacity(descriptor_writes.len()); let mut writes_vk: SmallVec<[_; 8]> = SmallVec::with_capacity(descriptor_writes.len());

View File

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

View File

@ -945,6 +945,7 @@ impl Device {
descriptor_count, descriptor_count,
stage_flags: stages.into(), stage_flags: stages.into(),
p_immutable_samplers: ptr::null(), p_immutable_samplers: ptr::null(),
..Default::default()
}); });
per_binding_vk.push(PerBinding { per_binding_vk.push(PerBinding {
immutable_samplers_vk: immutable_samplers immutable_samplers_vk: immutable_samplers
@ -1579,7 +1580,7 @@ impl Device {
}; };
unsafe { unsafe {
let fns = self.instance().fns(); 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)
.result() .result()
.map_err(VulkanError::from)?; .map_err(VulkanError::from)?;

View File

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

View File

@ -13,7 +13,7 @@ use crate::{
shader::ShaderStages, shader::ShaderStages,
DeviceSize, Version, DeviceSize, Version,
}; };
use std::{ffi::CStr, os::raw::c_char}; use std::ffi::c_char;
// Generated by build.rs // Generated by build.rs
include!(concat!(env!("OUT_DIR"), "/properties.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 { 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] #[inline]
fn from_vulkan(val: [c_char; N]) -> Option<Self> { 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> { ) -> Result<(), VulkanError> {
struct PerBindSparseInfo { struct PerBindSparseInfo {
wait_semaphores_vk: SmallVec<[ash::vk::Semaphore; 4]>, 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]>, 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_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]>, image_binds_vk: SmallVec<[SmallVec<[ash::vk::SparseImageMemoryBind; 4]>; 4]>,
signal_semaphores_vk: SmallVec<[ash::vk::Semaphore; 4]>, signal_semaphores_vk: SmallVec<[ash::vk::Semaphore; 4]>,
} }
@ -259,11 +260,8 @@ impl<'a> QueueGuard<'a> {
.iter() .iter()
.map(|(buffer, memory_binds)| { .map(|(buffer, memory_binds)| {
( (
ash::vk::SparseBufferMemoryBindInfo { ash::vk::SparseBufferMemoryBindInfo::default()
buffer: buffer.buffer().handle(), .buffer(buffer.buffer().handle()),
bind_count: 0,
p_binds: ptr::null(),
},
memory_binds memory_binds
.iter() .iter()
.map(|memory_bind| { .map(|memory_bind| {
@ -300,11 +298,8 @@ impl<'a> QueueGuard<'a> {
.iter() .iter()
.map(|(image, memory_binds)| { .map(|(image, memory_binds)| {
( (
ash::vk::SparseImageOpaqueMemoryBindInfo { ash::vk::SparseImageOpaqueMemoryBindInfo::default()
image: image.handle(), .image(image.handle()),
bind_count: 0,
p_binds: ptr::null(),
},
memory_binds memory_binds
.iter() .iter()
.map(|memory_bind| { .map(|memory_bind| {
@ -342,11 +337,7 @@ impl<'a> QueueGuard<'a> {
.iter() .iter()
.map(|(image, memory_binds)| { .map(|(image, memory_binds)| {
( (
ash::vk::SparseImageMemoryBindInfo { ash::vk::SparseImageMemoryBindInfo::default().image(image.handle()),
image: image.handle(),
bind_count: 0,
p_binds: ptr::null(),
},
memory_binds memory_binds
.iter() .iter()
.map(|memory_bind| { .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 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_ids_vk: SmallVec<[_; 4]> = SmallVec::with_capacity(swapchains.len());
let mut present_modes_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 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_ids = false;
let mut has_present_modes = false; let mut has_present_modes = false;
@ -689,10 +680,8 @@ impl<'a> QueueGuard<'a> {
for (present_regions_vk, rectangles_vk) in for (present_regions_vk, rectangles_vk) in
present_regions_vk.iter_mut().zip(rectangles_vk.iter()) present_regions_vk.iter_mut().zip(rectangles_vk.iter())
{ {
*present_regions_vk = ash::vk::PresentRegionKHR { *present_regions_vk =
rectangle_count: rectangles_vk.len() as u32, ash::vk::PresentRegionKHR::default().rectangles(rectangles_vk);
p_rectangles: rectangles_vk.as_ptr(),
};
} }
let next = present_region_info_vk.insert(ash::vk::PresentRegionsKHR { let next = present_region_info_vk.insert(ash::vk::PresentRegionsKHR {
@ -907,9 +896,9 @@ impl<'a> QueueGuard<'a> {
) -> Result<(), VulkanError> { ) -> Result<(), VulkanError> {
if self.queue.device.enabled_features().synchronization2 { if self.queue.device.enabled_features().synchronization2 {
struct PerSubmitInfo { struct PerSubmitInfo {
wait_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; 4]>, command_buffer_infos_vk: SmallVec<[ash::vk::CommandBufferSubmitInfo<'static>; 4]>,
signal_semaphore_infos_vk: SmallVec<[ash::vk::SemaphoreSubmitInfo; 4]>, signal_semaphore_infos_vk: SmallVec<[ash::vk::SemaphoreSubmitInfo<'static>; 4]>,
} }
let (mut submit_info_vk, mut per_submit_vk): (SmallVec<[_; 4]>, SmallVec<[_; 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) .map_err(VulkanError::from)
} else { } else {
struct PerSubmitInfo { 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_semaphores_vk: SmallVec<[ash::vk::Semaphore; 4]>,
wait_semaphore_values_vk: SmallVec<[u64; 4]>, wait_semaphore_values_vk: SmallVec<[u64; 4]>,
wait_dst_stage_mask_vk: SmallVec<[ash::vk::PipelineStageFlags; 4]>, wait_dst_stage_mask_vk: SmallVec<[ash::vk::PipelineStageFlags; 4]>,
@ -1261,7 +1251,7 @@ impl<'a> QueueGuard<'a> {
..Default::default() ..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); (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))] #[cfg_attr(not(feature = "document_unchecked"), doc(hidden))]
#[inline] #[inline]
pub unsafe fn end_debug_utils_label_unchecked(&mut self) { 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); (fns.ext_debug_utils.queue_end_debug_utils_label_ext)(self.queue.handle);
} }
@ -1366,7 +1356,7 @@ impl<'a> QueueGuard<'a> {
..Default::default() ..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); (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( pub(super) unsafe extern "system" fn trampoline(
message_severity_vk: ash::vk::DebugUtilsMessageSeverityFlagsEXT, message_severity_vk: ash::vk::DebugUtilsMessageSeverityFlagsEXT,
message_types_vk: ash::vk::DebugUtilsMessageTypeFlagsEXT, 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, user_data_vk: *mut c_void,
) -> ash::vk::Bool32 { ) -> ash::vk::Bool32 {
// Since we box the closure, the type system doesn't detect that the `UnwindSafe` // 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, p_cmd_buf_labels,
object_count, object_count,
p_objects, p_objects,
_marker: _,
} = *callback_data_vk; } = *callback_data_vk;
let callback_data = DebugUtilsMessengerCallbackData { let callback_data = DebugUtilsMessengerCallbackData {
@ -415,23 +416,18 @@ pub struct DebugUtilsMessengerCallbackLabel<'a> {
} }
#[derive(Clone, Debug)] #[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> { impl<'a> Iterator for DebugUtilsMessengerCallbackLabelIter<'a> {
type Item = DebugUtilsMessengerCallbackLabel<'a>; type Item = DebugUtilsMessengerCallbackLabel<'a>;
fn next(&mut self) -> Option<Self::Item> { fn next(&mut self) -> Option<Self::Item> {
self.0.next().map(|label| unsafe { self.0.next().map(|label| unsafe {
let &ash::vk::DebugUtilsLabelEXT {
s_type: _,
p_next: _,
p_label_name,
ref color,
} = label;
DebugUtilsMessengerCallbackLabel { DebugUtilsMessengerCallbackLabel {
label_name: CStr::from_ptr(p_label_name).to_str().unwrap(), label_name: label.label_name_as_c_str().unwrap().to_str().unwrap(),
color, color: &label.color,
} }
}) })
} }
@ -452,7 +448,7 @@ pub struct DebugUtilsMessengerCallbackObjectNameInfo<'a> {
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct DebugUtilsMessengerCallbackObjectNameInfoIter<'a>( pub struct DebugUtilsMessengerCallbackObjectNameInfoIter<'a>(
slice::Iter<'a, ash::vk::DebugUtilsObjectNameInfoEXT>, slice::Iter<'a, ash::vk::DebugUtilsObjectNameInfoEXT<'a>>,
); );
impl<'a> Iterator for DebugUtilsMessengerCallbackObjectNameInfoIter<'a> { impl<'a> Iterator for DebugUtilsMessengerCallbackObjectNameInfoIter<'a> {
@ -466,6 +462,7 @@ impl<'a> Iterator for DebugUtilsMessengerCallbackObjectNameInfoIter<'a> {
object_type, object_type,
object_handle, object_handle,
p_object_name, p_object_name,
_marker: _,
} = info; } = info;
DebugUtilsMessengerCallbackObjectNameInfo { DebugUtilsMessengerCallbackObjectNameInfo {

View File

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

View File

@ -453,14 +453,16 @@ impl From<ash::vk::PhysicalDeviceMemoryProperties> for MemoryProperties {
#[inline] #[inline]
fn from(val: ash::vk::PhysicalDeviceMemoryProperties) -> Self { fn from(val: ash::vk::PhysicalDeviceMemoryProperties) -> Self {
Self { Self {
memory_types: val.memory_types[0..val.memory_type_count as usize] memory_types: val
.memory_types_as_slice()
.iter() .iter()
.map(|vk_memory_type| MemoryType { .map(|vk_memory_type| MemoryType {
property_flags: vk_memory_type.property_flags.into(), property_flags: vk_memory_type.property_flags.into(),
heap_index: vk_memory_type.heap_index, heap_index: vk_memory_type.heap_index,
}) })
.collect(), .collect(),
memory_heaps: val.memory_heaps[0..val.memory_heap_count as usize] memory_heaps: val
.memory_heaps_as_slice()
.iter() .iter()
.map(|vk_memory_heap| MemoryHeap { .map(|vk_memory_heap| MemoryHeap {
size: vk_memory_heap.size, size: vk_memory_heap.size,

View File

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

View File

@ -232,11 +232,11 @@ impl GraphicsPipeline {
struct PerPipelineShaderStageCreateInfo { struct PerPipelineShaderStageCreateInfo {
name_vk: CString, 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_map_entries_vk: Vec<ash::vk::SpecializationMapEntry>,
specialization_data_vk: Vec<u8>, specialization_data_vk: Vec<u8>,
required_subgroup_size_create_info: 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 let (mut stages_vk, mut per_stage_vk): (SmallVec<[_; 5]>, SmallVec<[_; 5]>) = stages
@ -287,12 +287,13 @@ impl GraphicsPipeline {
..Default::default() ..Default::default()
}, },
PerPipelineShaderStageCreateInfo { 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 { specialization_info_vk: ash::vk::SpecializationInfo {
map_entry_count: specialization_map_entries_vk.len() as u32, map_entry_count: specialization_map_entries_vk.len() as u32,
p_map_entries: ptr::null(), p_map_entries: ptr::null(),
data_size: specialization_data_vk.len(), data_size: specialization_data_vk.len(),
p_data: ptr::null(), p_data: ptr::null(),
..Default::default()
}, },
specialization_map_entries_vk, specialization_map_entries_vk,
specialization_data_vk, specialization_data_vk,

View File

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

View File

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

View File

@ -80,7 +80,7 @@
//! # fn build_window() -> Arc<Window> { Arc::new(Window(ptr::null())) } //! # fn build_window() -> Arc<Window> { Arc::new(Window(ptr::null())) }
//! let window = build_window(); // Third-party function, not provided by vulkano //! let window = build_window(); // Third-party function, not provided by vulkano
//! let _surface = unsafe { //! 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( //! Surface::from_win32(
//! instance.clone(), //! instance.clone(),
//! hinstance, //! hinstance,

View File

@ -2389,7 +2389,7 @@ mod tests {
#[test] #[test]
fn khr_win32_surface_ext_missing() { fn khr_win32_surface_ext_missing() {
let instance = instance!(); 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)) Err(Validated::ValidationError(err))
if matches!( if matches!(
*err, *err,

View File

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

View File

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

View File

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