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)]
enum Type {
Scalar(TypeScalar),
Pointer(TypePointer),
Vector(TypeVector),
Matrix(TypeMatrix),
Array(TypeArray),
@ -238,6 +239,7 @@ impl Type {
Instruction::TypeFloat { width, .. } => {
Type::Scalar(TypeScalar::Float(TypeFloat::new(shader, width)?))
}
Instruction::TypePointer { .. } => Type::Pointer(TypePointer::new(shader)?),
Instruction::TypeVector {
component_type,
component_count,
@ -268,6 +270,7 @@ impl Type {
fn size(&self) -> Option<usize> {
match self {
Self::Scalar(ty) => Some(ty.size()),
Self::Pointer(ty) => Some(ty.size()),
Self::Vector(ty) => Some(ty.size()),
Self::Matrix(ty) => Some(ty.size()),
Self::Array(ty) => ty.size(),
@ -278,6 +281,7 @@ impl Type {
fn scalar_alignment(&self) -> Alignment {
match self {
Self::Scalar(ty) => ty.alignment(),
Self::Pointer(ty) => ty.alignment(),
Self::Vector(ty) => ty.component_type.alignment(),
Self::Matrix(ty) => ty.component_type.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)]
struct TypeVector {
component_type: TypeScalar,
@ -863,6 +890,7 @@ impl ToTokens for Serializer<'_, Type> {
fn to_tokens(&self, tokens: &mut TokenStream) {
match &self.0 {
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::Matrix(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},
instance::InstanceOwnedDebugWrapper,
macros::{impl_id_counter, vulkan_bitflags, vulkan_enum},
DeviceSize, NonZeroDeviceSize, Packed24_8, Requires, RequiresAllOf, RequiresOneOf, Validated,
ValidationError, VulkanError, VulkanObject,
DeviceAddress, DeviceSize, NonNullDeviceAddress, Packed24_8, Requires, RequiresAllOf,
RequiresOneOf, Validated, ValidationError, VulkanError, VulkanObject,
};
use bytemuck::{Pod, Zeroable};
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
/// of the underlying buffer.
pub fn device_address(&self) -> NonZeroDeviceSize {
pub fn device_address(&self) -> NonNullDeviceAddress {
let info_vk = ash::vk::AccelerationStructureDeviceAddressInfoKHR {
acceleration_structure: self.handle,
..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 default value is 0 (null).
pub acceleration_structure_reference: DeviceSize,
pub acceleration_structure_reference: DeviceAddress,
}
impl Default for AccelerationStructureInstance {

View File

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

View File

@ -19,7 +19,7 @@ use crate::{
is_aligned, DeviceAlignment, MappedMemoryRange,
},
sync::HostAccessError,
DeviceSize, NonZeroDeviceSize, ValidationError,
DeviceSize, NonNullDeviceAddress, NonZeroDeviceSize, ValidationError,
};
use bytemuck::AnyBitPattern;
use std::{
@ -138,21 +138,21 @@ impl<T: ?Sized> Subbuffer<T> {
}
/// 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| {
// 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
// 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))]
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
// sizes are guaranteed to not exceed `DeviceLayout::MAX_SIZE`, so the offset better be
// in range.
NonZeroDeviceSize::new_unchecked(
NonNullDeviceAddress::new_unchecked(
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.
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,
/// and 8 bytes in the most significant bits of that memory,
/// occupying a single [`u32`] in total.