Add DeviceAddress, handle pointers as SPIR-V struct members (#2351)

* Add `DeviceAddress`, handle pointers as SPIR-V struct members

* Add pointers to vulkano-shaders
This commit is contained in:
Rua 2023-10-07 15:13:58 +02:00 committed by GitHub
parent fb828a6db2
commit 0175bcd2a6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 49 additions and 15 deletions

View File

@ -220,6 +220,7 @@ fn is_aligned(offset: usize, alignment: Alignment) -> bool {
#[derive(Clone, Debug, PartialEq, Eq)] #[derive(Clone, Debug, PartialEq, Eq)]
enum Type { enum Type {
Scalar(TypeScalar), Scalar(TypeScalar),
Pointer(TypePointer),
Vector(TypeVector), Vector(TypeVector),
Matrix(TypeMatrix), Matrix(TypeMatrix),
Array(TypeArray), Array(TypeArray),
@ -238,6 +239,7 @@ impl Type {
Instruction::TypeFloat { width, .. } => { Instruction::TypeFloat { width, .. } => {
Type::Scalar(TypeScalar::Float(TypeFloat::new(shader, width)?)) Type::Scalar(TypeScalar::Float(TypeFloat::new(shader, width)?))
} }
Instruction::TypePointer { .. } => Type::Pointer(TypePointer::new(shader)?),
Instruction::TypeVector { Instruction::TypeVector {
component_type, component_type,
component_count, component_count,
@ -268,6 +270,7 @@ impl Type {
fn size(&self) -> Option<usize> { fn size(&self) -> Option<usize> {
match self { match self {
Self::Scalar(ty) => Some(ty.size()), Self::Scalar(ty) => Some(ty.size()),
Self::Pointer(ty) => Some(ty.size()),
Self::Vector(ty) => Some(ty.size()), Self::Vector(ty) => Some(ty.size()),
Self::Matrix(ty) => Some(ty.size()), Self::Matrix(ty) => Some(ty.size()),
Self::Array(ty) => ty.size(), Self::Array(ty) => ty.size(),
@ -278,6 +281,7 @@ impl Type {
fn scalar_alignment(&self) -> Alignment { fn scalar_alignment(&self) -> Alignment {
match self { match self {
Self::Scalar(ty) => ty.alignment(), Self::Scalar(ty) => ty.alignment(),
Self::Pointer(ty) => ty.alignment(),
Self::Vector(ty) => ty.component_type.alignment(), Self::Vector(ty) => ty.component_type.alignment(),
Self::Matrix(ty) => ty.component_type.alignment(), Self::Matrix(ty) => ty.component_type.alignment(),
Self::Array(ty) => ty.scalar_alignment(), Self::Array(ty) => ty.scalar_alignment(),
@ -439,6 +443,29 @@ impl ToTokens for TypeFloat {
} }
} }
#[derive(Clone, Debug, PartialEq, Eq)]
struct TypePointer;
impl TypePointer {
fn new(_shader: &Shader) -> Result<Self> {
Ok(TypePointer)
}
fn size(&self) -> usize {
8
}
fn alignment(&self) -> Alignment {
Alignment::A8
}
}
impl ToTokens for TypePointer {
fn to_tokens(&self, tokens: &mut TokenStream) {
tokens.extend(quote! { ::vulkano::DeviceAddress });
}
}
#[derive(Clone, Debug, PartialEq, Eq)] #[derive(Clone, Debug, PartialEq, Eq)]
struct TypeVector { struct TypeVector {
component_type: TypeScalar, component_type: TypeScalar,
@ -863,6 +890,7 @@ impl ToTokens for Serializer<'_, Type> {
fn to_tokens(&self, tokens: &mut TokenStream) { fn to_tokens(&self, tokens: &mut TokenStream) {
match &self.0 { match &self.0 {
Type::Scalar(ty) => ty.to_tokens(tokens), Type::Scalar(ty) => ty.to_tokens(tokens),
Type::Pointer(ty) => ty.to_tokens(tokens),
Type::Vector(ty) => Serializer(ty, self.1).to_tokens(tokens), Type::Vector(ty) => Serializer(ty, self.1).to_tokens(tokens),
Type::Matrix(ty) => Serializer(ty, self.1).to_tokens(tokens), Type::Matrix(ty) => Serializer(ty, self.1).to_tokens(tokens),
Type::Array(ty) => Serializer(ty, self.1).to_tokens(tokens), Type::Array(ty) => Serializer(ty, self.1).to_tokens(tokens),

View File

@ -97,8 +97,8 @@ use crate::{
format::{Format, FormatFeatures}, format::{Format, FormatFeatures},
instance::InstanceOwnedDebugWrapper, instance::InstanceOwnedDebugWrapper,
macros::{impl_id_counter, vulkan_bitflags, vulkan_enum}, macros::{impl_id_counter, vulkan_bitflags, vulkan_enum},
DeviceSize, NonZeroDeviceSize, Packed24_8, Requires, RequiresAllOf, RequiresOneOf, Validated, DeviceAddress, DeviceSize, NonNullDeviceAddress, Packed24_8, Requires, RequiresAllOf,
ValidationError, VulkanError, VulkanObject, RequiresOneOf, Validated, ValidationError, VulkanError, VulkanObject,
}; };
use bytemuck::{Pod, Zeroable}; use bytemuck::{Pod, Zeroable};
use std::{fmt::Debug, hash::Hash, mem::MaybeUninit, num::NonZeroU64, ptr, sync::Arc}; use std::{fmt::Debug, hash::Hash, mem::MaybeUninit, num::NonZeroU64, ptr, sync::Arc};
@ -264,7 +264,7 @@ impl AccelerationStructure {
/// ///
/// The device address of the acceleration structure may be different from the device address /// The device address of the acceleration structure may be different from the device address
/// of the underlying buffer. /// of the underlying buffer.
pub fn device_address(&self) -> NonZeroDeviceSize { pub fn device_address(&self) -> NonNullDeviceAddress {
let info_vk = ash::vk::AccelerationStructureDeviceAddressInfoKHR { let info_vk = ash::vk::AccelerationStructureDeviceAddressInfoKHR {
acceleration_structure: self.handle, acceleration_structure: self.handle,
..Default::default() ..Default::default()
@ -277,7 +277,7 @@ impl AccelerationStructure {
) )
}; };
NonZeroDeviceSize::new(ptr).unwrap() NonNullDeviceAddress::new(ptr).unwrap()
} }
} }
@ -1277,7 +1277,7 @@ pub struct AccelerationStructureInstance {
/// The device address of the bottom-level acceleration structure in this instance. /// The device address of the bottom-level acceleration structure in this instance.
/// ///
/// The default value is 0 (null). /// The default value is 0 (null).
pub acceleration_structure_reference: DeviceSize, pub acceleration_structure_reference: DeviceAddress,
} }
impl Default for AccelerationStructureInstance { impl Default for AccelerationStructureInstance {

View File

@ -93,8 +93,8 @@ use crate::{
}, },
range_map::RangeMap, range_map::RangeMap,
sync::{future::AccessError, AccessConflict, CurrentAccess, Sharing}, sync::{future::AccessError, AccessConflict, CurrentAccess, Sharing},
DeviceSize, NonZeroDeviceSize, Requires, RequiresAllOf, RequiresOneOf, Validated, DeviceSize, NonNullDeviceAddress, NonZeroDeviceSize, Requires, RequiresAllOf, RequiresOneOf,
ValidationError, Version, VulkanError, VulkanObject, Validated, ValidationError, Version, VulkanError, VulkanObject,
}; };
use parking_lot::{Mutex, MutexGuard}; use parking_lot::{Mutex, MutexGuard};
use smallvec::SmallVec; use smallvec::SmallVec;
@ -476,7 +476,7 @@ impl Buffer {
/// Returns the device address for this buffer. /// Returns the device address for this buffer.
// TODO: Caching? // TODO: Caching?
pub fn device_address(&self) -> Result<NonZeroDeviceSize, Box<ValidationError>> { pub fn device_address(&self) -> Result<NonNullDeviceAddress, Box<ValidationError>> {
self.validate_device_address()?; self.validate_device_address()?;
unsafe { Ok(self.device_address_unchecked()) } unsafe { Ok(self.device_address_unchecked()) }
@ -508,7 +508,7 @@ impl Buffer {
} }
#[cfg_attr(not(feature = "document_unchecked"), doc(hidden))] #[cfg_attr(not(feature = "document_unchecked"), doc(hidden))]
pub unsafe fn device_address_unchecked(&self) -> NonZeroDeviceSize { pub unsafe fn device_address_unchecked(&self) -> NonNullDeviceAddress {
let device = self.device(); let device = self.device();
let info_vk = ash::vk::BufferDeviceAddressInfo { let info_vk = ash::vk::BufferDeviceAddressInfo {
@ -528,7 +528,7 @@ impl Buffer {
f(device.handle(), &info_vk) f(device.handle(), &info_vk)
}; };
NonZeroDeviceSize::new(ptr).unwrap() NonNullDeviceAddress::new(ptr).unwrap()
} }
pub(crate) fn state(&self) -> MutexGuard<'_, BufferState> { pub(crate) fn state(&self) -> MutexGuard<'_, BufferState> {

View File

@ -19,7 +19,7 @@ use crate::{
is_aligned, DeviceAlignment, MappedMemoryRange, is_aligned, DeviceAlignment, MappedMemoryRange,
}, },
sync::HostAccessError, sync::HostAccessError,
DeviceSize, NonZeroDeviceSize, ValidationError, DeviceSize, NonNullDeviceAddress, NonZeroDeviceSize, ValidationError,
}; };
use bytemuck::AnyBitPattern; use bytemuck::AnyBitPattern;
use std::{ use std::{
@ -138,21 +138,21 @@ impl<T: ?Sized> Subbuffer<T> {
} }
/// Returns the device address for this subbuffer. /// Returns the device address for this subbuffer.
pub fn device_address(&self) -> Result<NonZeroDeviceSize, Box<ValidationError>> { pub fn device_address(&self) -> Result<NonNullDeviceAddress, Box<ValidationError>> {
self.buffer().device_address().map(|ptr| { self.buffer().device_address().map(|ptr| {
// SAFETY: The original address came from the Vulkan implementation, and allocation // SAFETY: The original address came from the Vulkan implementation, and allocation
// sizes are guaranteed to not exceed `DeviceLayout::MAX_SIZE`, so the offset better be // sizes are guaranteed to not exceed `DeviceLayout::MAX_SIZE`, so the offset better be
// in range. // in range.
unsafe { NonZeroDeviceSize::new_unchecked(ptr.get() + self.offset) } unsafe { NonNullDeviceAddress::new_unchecked(ptr.get() + self.offset) }
}) })
} }
#[cfg_attr(not(feature = "document_unchecked"), doc(hidden))] #[cfg_attr(not(feature = "document_unchecked"), doc(hidden))]
pub unsafe fn device_address_unchecked(&self) -> NonZeroDeviceSize { pub unsafe fn device_address_unchecked(&self) -> NonNullDeviceAddress {
// SAFETY: The original address came from the Vulkan implementation, and allocation // SAFETY: The original address came from the Vulkan implementation, and allocation
// sizes are guaranteed to not exceed `DeviceLayout::MAX_SIZE`, so the offset better be // sizes are guaranteed to not exceed `DeviceLayout::MAX_SIZE`, so the offset better be
// in range. // in range.
NonZeroDeviceSize::new_unchecked( NonNullDeviceAddress::new_unchecked(
self.buffer().device_address_unchecked().get() + self.offset, self.buffer().device_address_unchecked().get() + self.offset,
) )
} }

View File

@ -206,6 +206,12 @@ pub use ash::vk::DeviceSize;
/// A [`DeviceSize`] that is known not to equal zero. /// A [`DeviceSize`] that is known not to equal zero.
pub type NonZeroDeviceSize = NonZeroU64; pub type NonZeroDeviceSize = NonZeroU64;
/// Represents an address (pointer) on a Vulkan device.
pub use ash::vk::DeviceAddress;
/// A [`DeviceAddress`] that is known not to equal zero.
pub type NonNullDeviceAddress = NonZeroU64;
/// Holds 24 bits in the least significant bits of memory, /// Holds 24 bits in the least significant bits of memory,
/// and 8 bytes in the most significant bits of that memory, /// and 8 bytes in the most significant bits of that memory,
/// occupying a single [`u32`] in total. /// occupying a single [`u32`] in total.