mirror of
https://github.com/vulkano-rs/vulkano.git
synced 2024-11-22 06:45:23 +00:00
Generate device properties that are alignment as DeviceAlignment
(#2155)
* Move `DeviceAlignment` * Generate alignment-properties with the type `DeviceAlignment` * Small fix * Another small fix * Switch to using `is_aligned` where possible * Oopsie
This commit is contained in:
parent
19acc71be3
commit
127b3eae61
@ -143,7 +143,8 @@ fn main() {
|
|||||||
let min_dynamic_align = device
|
let min_dynamic_align = device
|
||||||
.physical_device()
|
.physical_device()
|
||||||
.properties()
|
.properties()
|
||||||
.min_uniform_buffer_offset_alignment as usize;
|
.min_uniform_buffer_offset_alignment
|
||||||
|
.as_devicesize() as usize;
|
||||||
|
|
||||||
println!("Minimum uniform buffer offset alignment: {min_dynamic_align}");
|
println!("Minimum uniform buffer offset alignment: {min_dynamic_align}");
|
||||||
println!("Input: {data:?}");
|
println!("Input: {data:?}");
|
||||||
|
@ -196,6 +196,19 @@ fn properties_members(types: &HashMap<&str, (&Type, Vec<&str>)>) -> Vec<Properti
|
|||||||
let vulkano_member = name.to_snake_case();
|
let vulkano_member = name.to_snake_case();
|
||||||
let vulkano_ty = match name {
|
let vulkano_ty = match name {
|
||||||
"apiVersion" => quote! { Version },
|
"apiVersion" => quote! { Version },
|
||||||
|
"bufferImageGranularity"
|
||||||
|
| "minStorageBufferOffsetAlignment"
|
||||||
|
| "minTexelBufferOffsetAlignment"
|
||||||
|
| "minUniformBufferOffsetAlignment"
|
||||||
|
| "nonCoherentAtomSize"
|
||||||
|
| "optimalBufferCopyOffsetAlignment"
|
||||||
|
| "optimalBufferCopyRowPitchAlignment"
|
||||||
|
| "robustStorageBufferAccessSizeAlignment"
|
||||||
|
| "robustUniformBufferAccessSizeAlignment"
|
||||||
|
| "storageTexelBufferOffsetAlignmentBytes"
|
||||||
|
| "uniformTexelBufferOffsetAlignmentBytes" => {
|
||||||
|
quote! { DeviceAlignment }
|
||||||
|
}
|
||||||
_ => vulkano_type(ty, len),
|
_ => vulkano_type(ty, len),
|
||||||
};
|
};
|
||||||
match properties.entry(vulkano_member.clone()) {
|
match properties.entry(vulkano_member.clone()) {
|
||||||
|
@ -13,9 +13,12 @@ use super::{Buffer, BufferContents, BufferError, BufferMemory, BufferUsage, Subb
|
|||||||
use crate::{
|
use crate::{
|
||||||
buffer::BufferAllocateInfo,
|
buffer::BufferAllocateInfo,
|
||||||
device::{Device, DeviceOwned},
|
device::{Device, DeviceOwned},
|
||||||
memory::allocator::{
|
memory::{
|
||||||
align_up, AllocationCreationError, DeviceAlignment, DeviceLayout, MemoryAllocator,
|
allocator::{
|
||||||
MemoryUsage, StandardMemoryAllocator,
|
align_up, AllocationCreationError, DeviceLayout, MemoryAllocator, MemoryUsage,
|
||||||
|
StandardMemoryAllocator,
|
||||||
|
},
|
||||||
|
DeviceAlignment,
|
||||||
},
|
},
|
||||||
DeviceSize, NonZeroDeviceSize,
|
DeviceSize, NonZeroDeviceSize,
|
||||||
};
|
};
|
||||||
@ -145,7 +148,6 @@ where
|
|||||||
.into_iter()
|
.into_iter()
|
||||||
.flatten()
|
.flatten()
|
||||||
.max()
|
.max()
|
||||||
.map(|alignment| DeviceAlignment::new(alignment).unwrap())
|
|
||||||
.unwrap_or(DeviceAlignment::MIN);
|
.unwrap_or(DeviceAlignment::MIN);
|
||||||
|
|
||||||
SubbufferAllocator {
|
SubbufferAllocator {
|
||||||
|
@ -111,11 +111,11 @@ use crate::{
|
|||||||
macros::vulkan_bitflags,
|
macros::vulkan_bitflags,
|
||||||
memory::{
|
memory::{
|
||||||
allocator::{
|
allocator::{
|
||||||
AllocationCreateInfo, AllocationCreationError, AllocationType, DeviceAlignment,
|
AllocationCreateInfo, AllocationCreationError, AllocationType, DeviceLayout,
|
||||||
DeviceLayout, MemoryAlloc, MemoryAllocatePreference, MemoryAllocator, MemoryUsage,
|
MemoryAlloc, MemoryAllocatePreference, MemoryAllocator, MemoryUsage,
|
||||||
},
|
},
|
||||||
DedicatedAllocation, ExternalMemoryHandleType, ExternalMemoryHandleTypes,
|
is_aligned, DedicatedAllocation, DeviceAlignment, ExternalMemoryHandleType,
|
||||||
ExternalMemoryProperties, MemoryRequirements,
|
ExternalMemoryHandleTypes, ExternalMemoryProperties, MemoryRequirements,
|
||||||
},
|
},
|
||||||
range_map::RangeMap,
|
range_map::RangeMap,
|
||||||
sync::{future::AccessError, CurrentAccess, Sharing},
|
sync::{future::AccessError, CurrentAccess, Sharing},
|
||||||
@ -394,7 +394,10 @@ impl Buffer {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let mut allocation = unsafe { allocator.allocate_unchecked(create_info) }?;
|
let mut allocation = unsafe { allocator.allocate_unchecked(create_info) }?;
|
||||||
debug_assert!(allocation.offset() % requirements.layout.alignment().as_nonzero() == 0);
|
debug_assert!(is_aligned(
|
||||||
|
allocation.offset(),
|
||||||
|
requirements.layout.alignment(),
|
||||||
|
));
|
||||||
debug_assert!(allocation.size() == requirements.layout.size());
|
debug_assert!(allocation.size() == requirements.layout.size());
|
||||||
|
|
||||||
// The implementation might require a larger size than we wanted. With this it is easier to
|
// The implementation might require a larger size than we wanted. With this it is easier to
|
||||||
|
@ -15,8 +15,8 @@ use crate::{
|
|||||||
macros::try_opt,
|
macros::try_opt,
|
||||||
memory::{
|
memory::{
|
||||||
self,
|
self,
|
||||||
allocator::{align_down, align_up, DeviceAlignment, DeviceLayout},
|
allocator::{align_down, align_up, DeviceLayout},
|
||||||
is_aligned,
|
is_aligned, DeviceAlignment,
|
||||||
},
|
},
|
||||||
DeviceSize, NonZeroDeviceSize,
|
DeviceSize, NonZeroDeviceSize,
|
||||||
};
|
};
|
||||||
|
@ -17,9 +17,9 @@ use super::{Buffer, BufferCreateFlags, BufferError, BufferMemory, BufferUsage};
|
|||||||
use crate::{
|
use crate::{
|
||||||
device::{Device, DeviceOwned},
|
device::{Device, DeviceOwned},
|
||||||
memory::{
|
memory::{
|
||||||
allocator::{AllocationType, DeviceAlignment, DeviceLayout, MemoryAlloc},
|
allocator::{AllocationType, DeviceLayout, MemoryAlloc},
|
||||||
DedicatedTo, ExternalMemoryHandleTypes, MemoryAllocateFlags, MemoryPropertyFlags,
|
is_aligned, DedicatedTo, ExternalMemoryHandleTypes, MemoryAllocateFlags,
|
||||||
MemoryRequirements,
|
MemoryPropertyFlags, MemoryRequirements,
|
||||||
},
|
},
|
||||||
sync::Sharing,
|
sync::Sharing,
|
||||||
DeviceSize, RequiresOneOf, Version, VulkanError, VulkanObject,
|
DeviceSize, RequiresOneOf, Version, VulkanError, VulkanObject,
|
||||||
@ -290,27 +290,21 @@ impl RawBuffer {
|
|||||||
if usage.intersects(BufferUsage::UNIFORM_TEXEL_BUFFER | BufferUsage::STORAGE_TEXEL_BUFFER) {
|
if usage.intersects(BufferUsage::UNIFORM_TEXEL_BUFFER | BufferUsage::STORAGE_TEXEL_BUFFER) {
|
||||||
memory_requirements.layout = memory_requirements
|
memory_requirements.layout = memory_requirements
|
||||||
.layout
|
.layout
|
||||||
.align_to(
|
.align_to(properties.min_texel_buffer_offset_alignment)
|
||||||
DeviceAlignment::new(properties.min_texel_buffer_offset_alignment).unwrap(),
|
|
||||||
)
|
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
if usage.intersects(BufferUsage::STORAGE_BUFFER) {
|
if usage.intersects(BufferUsage::STORAGE_BUFFER) {
|
||||||
memory_requirements.layout = memory_requirements
|
memory_requirements.layout = memory_requirements
|
||||||
.layout
|
.layout
|
||||||
.align_to(
|
.align_to(properties.min_storage_buffer_offset_alignment)
|
||||||
DeviceAlignment::new(properties.min_storage_buffer_offset_alignment).unwrap(),
|
|
||||||
)
|
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
if usage.intersects(BufferUsage::UNIFORM_BUFFER) {
|
if usage.intersects(BufferUsage::UNIFORM_BUFFER) {
|
||||||
memory_requirements.layout = memory_requirements
|
memory_requirements.layout = memory_requirements
|
||||||
.layout
|
.layout
|
||||||
.align_to(
|
.align_to(properties.min_uniform_buffer_offset_alignment)
|
||||||
DeviceAlignment::new(properties.min_uniform_buffer_offset_alignment).unwrap(),
|
|
||||||
)
|
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -445,7 +439,7 @@ impl RawBuffer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// VUID-VkBindBufferMemoryInfo-memoryOffset-01036
|
// VUID-VkBindBufferMemoryInfo-memoryOffset-01036
|
||||||
if memory_offset % memory_requirements.layout.alignment().as_nonzero() != 0 {
|
if !is_aligned(memory_offset, memory_requirements.layout.alignment()) {
|
||||||
return Err(BufferError::MemoryAllocationNotAligned {
|
return Err(BufferError::MemoryAllocationNotAligned {
|
||||||
allocation_offset: memory_offset,
|
allocation_offset: memory_offset,
|
||||||
required_alignment: memory_requirements.layout.alignment(),
|
required_alignment: memory_requirements.layout.alignment(),
|
||||||
|
@ -49,6 +49,7 @@ use super::{BufferUsage, Subbuffer};
|
|||||||
use crate::{
|
use crate::{
|
||||||
device::{Device, DeviceOwned},
|
device::{Device, DeviceOwned},
|
||||||
format::{Format, FormatFeatures},
|
format::{Format, FormatFeatures},
|
||||||
|
memory::{is_aligned, DeviceAlignment},
|
||||||
DeviceSize, OomError, RequirementNotMet, RequiresOneOf, Version, VulkanError, VulkanObject,
|
DeviceSize, OomError, RequirementNotMet, RequiresOneOf, Version, VulkanError, VulkanObject,
|
||||||
};
|
};
|
||||||
use std::{
|
use std::{
|
||||||
@ -152,11 +153,12 @@ impl BufferView {
|
|||||||
|
|
||||||
if device.api_version() >= Version::V1_3 || device.enabled_features().texel_buffer_alignment
|
if device.api_version() >= Version::V1_3 || device.enabled_features().texel_buffer_alignment
|
||||||
{
|
{
|
||||||
let element_size = if block_size % 3 == 0 {
|
let element_size = DeviceAlignment::new(if block_size % 3 == 0 {
|
||||||
block_size / 3
|
block_size / 3
|
||||||
} else {
|
} else {
|
||||||
block_size
|
block_size
|
||||||
};
|
})
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
if buffer.usage().intersects(BufferUsage::STORAGE_TEXEL_BUFFER) {
|
if buffer.usage().intersects(BufferUsage::STORAGE_TEXEL_BUFFER) {
|
||||||
let mut required_alignment = properties
|
let mut required_alignment = properties
|
||||||
@ -171,7 +173,7 @@ impl BufferView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// VUID-VkBufferViewCreateInfo-buffer-02750
|
// VUID-VkBufferViewCreateInfo-buffer-02750
|
||||||
if offset % required_alignment != 0 {
|
if !is_aligned(offset, required_alignment) {
|
||||||
return Err(BufferViewCreationError::OffsetNotAligned {
|
return Err(BufferViewCreationError::OffsetNotAligned {
|
||||||
offset,
|
offset,
|
||||||
required_alignment,
|
required_alignment,
|
||||||
@ -192,7 +194,7 @@ impl BufferView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// VUID-VkBufferViewCreateInfo-buffer-02751
|
// VUID-VkBufferViewCreateInfo-buffer-02751
|
||||||
if offset % required_alignment != 0 {
|
if !is_aligned(offset, required_alignment) {
|
||||||
return Err(BufferViewCreationError::OffsetNotAligned {
|
return Err(BufferViewCreationError::OffsetNotAligned {
|
||||||
offset,
|
offset,
|
||||||
required_alignment,
|
required_alignment,
|
||||||
@ -203,7 +205,7 @@ impl BufferView {
|
|||||||
let required_alignment = properties.min_texel_buffer_offset_alignment;
|
let required_alignment = properties.min_texel_buffer_offset_alignment;
|
||||||
|
|
||||||
// VUID-VkBufferViewCreateInfo-offset-02749
|
// VUID-VkBufferViewCreateInfo-offset-02749
|
||||||
if offset % required_alignment != 0 {
|
if !is_aligned(offset, required_alignment) {
|
||||||
return Err(BufferViewCreationError::OffsetNotAligned {
|
return Err(BufferViewCreationError::OffsetNotAligned {
|
||||||
offset,
|
offset,
|
||||||
required_alignment,
|
required_alignment,
|
||||||
@ -340,7 +342,7 @@ pub enum BufferViewCreationError {
|
|||||||
/// The offset within the buffer is not a multiple of the required alignment.
|
/// The offset within the buffer is not a multiple of the required alignment.
|
||||||
OffsetNotAligned {
|
OffsetNotAligned {
|
||||||
offset: DeviceSize,
|
offset: DeviceSize,
|
||||||
required_alignment: DeviceSize,
|
required_alignment: DeviceAlignment,
|
||||||
},
|
},
|
||||||
|
|
||||||
/// The range within the buffer is not a multiple of the required alignment.
|
/// The range within the buffer is not a multiple of the required alignment.
|
||||||
|
@ -23,6 +23,7 @@ use crate::{
|
|||||||
WriteDescriptorSet,
|
WriteDescriptorSet,
|
||||||
},
|
},
|
||||||
device::{DeviceOwned, QueueFlags},
|
device::{DeviceOwned, QueueFlags},
|
||||||
|
memory::{is_aligned, DeviceAlignment},
|
||||||
pipeline::{
|
pipeline::{
|
||||||
graphics::{
|
graphics::{
|
||||||
input_assembly::{Index, IndexType},
|
input_assembly::{Index, IndexType},
|
||||||
@ -132,8 +133,8 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
let properties = self.device().physical_device().properties();
|
let properties = self.device().physical_device().properties();
|
||||||
let uniform_alignment = properties.min_uniform_buffer_offset_alignment as u32;
|
let uniform_alignment = properties.min_uniform_buffer_offset_alignment;
|
||||||
let storage_alignment = properties.min_storage_buffer_offset_alignment as u32;
|
let storage_alignment = properties.min_storage_buffer_offset_alignment;
|
||||||
|
|
||||||
for (i, set) in descriptor_sets.iter().enumerate() {
|
for (i, set) in descriptor_sets.iter().enumerate() {
|
||||||
let set_num = first_set + i as u32;
|
let set_num = first_set + i as u32;
|
||||||
@ -183,7 +184,7 @@ where
|
|||||||
{
|
{
|
||||||
// VUID-vkCmdBindDescriptorSets-pDynamicOffsets-01971
|
// VUID-vkCmdBindDescriptorSets-pDynamicOffsets-01971
|
||||||
// VUID-vkCmdBindDescriptorSets-pDynamicOffsets-01972
|
// VUID-vkCmdBindDescriptorSets-pDynamicOffsets-01972
|
||||||
if offset % required_alignment != 0 {
|
if !is_aligned(offset as DeviceSize, required_alignment) {
|
||||||
return Err(BindPushError::DynamicOffsetNotAligned {
|
return Err(BindPushError::DynamicOffsetNotAligned {
|
||||||
set_num,
|
set_num,
|
||||||
binding_num,
|
binding_num,
|
||||||
@ -1341,7 +1342,7 @@ pub(in super::super) enum BindPushError {
|
|||||||
binding_num: u32,
|
binding_num: u32,
|
||||||
index: u32,
|
index: u32,
|
||||||
offset: u32,
|
offset: u32,
|
||||||
required_alignment: u32,
|
required_alignment: DeviceAlignment,
|
||||||
},
|
},
|
||||||
|
|
||||||
/// In an element of `descriptor_sets`, a provided dynamic offset, when added to the end of the
|
/// In an element of `descriptor_sets`, a provided dynamic offset, when added to the end of the
|
||||||
@ -1459,7 +1460,7 @@ impl Display for BindPushError {
|
|||||||
"in the element of `descriptor_sets` being bound to slot {}, the dynamic offset \
|
"in the element of `descriptor_sets` being bound to slot {}, the dynamic offset \
|
||||||
provided for binding {} index {} ({}) is not a multiple of the value of the \
|
provided for binding {} index {} ({}) is not a multiple of the value of the \
|
||||||
`min_uniform_buffer_offset_alignment` or `min_storage_buffer_offset_alignment` \
|
`min_uniform_buffer_offset_alignment` or `min_storage_buffer_offset_alignment` \
|
||||||
property ({})",
|
property ({:?})",
|
||||||
set_num, binding_num, index, offset, required_alignment,
|
set_num, binding_num, index, offset, required_alignment,
|
||||||
),
|
),
|
||||||
Self::DynamicOffsetOutOfBufferBounds {
|
Self::DynamicOffsetOutOfBufferBounds {
|
||||||
|
@ -17,6 +17,7 @@ use crate::{
|
|||||||
DescriptorWriteInfo, WriteDescriptorSet,
|
DescriptorWriteInfo, WriteDescriptorSet,
|
||||||
},
|
},
|
||||||
device::{DeviceOwned, QueueFlags},
|
device::{DeviceOwned, QueueFlags},
|
||||||
|
memory::is_aligned,
|
||||||
pipeline::{
|
pipeline::{
|
||||||
graphics::{
|
graphics::{
|
||||||
input_assembly::{Index, IndexType},
|
input_assembly::{Index, IndexType},
|
||||||
@ -110,8 +111,8 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
let properties = self.device().physical_device().properties();
|
let properties = self.device().physical_device().properties();
|
||||||
let uniform_alignment = properties.min_uniform_buffer_offset_alignment as u32;
|
let uniform_alignment = properties.min_uniform_buffer_offset_alignment;
|
||||||
let storage_alignment = properties.min_storage_buffer_offset_alignment as u32;
|
let storage_alignment = properties.min_storage_buffer_offset_alignment;
|
||||||
|
|
||||||
for (i, set) in descriptor_sets.iter().enumerate() {
|
for (i, set) in descriptor_sets.iter().enumerate() {
|
||||||
let set_num = first_set + i as u32;
|
let set_num = first_set + i as u32;
|
||||||
@ -161,7 +162,7 @@ where
|
|||||||
{
|
{
|
||||||
// VUID-vkCmdBindDescriptorSets-pDynamicOffsets-01971
|
// VUID-vkCmdBindDescriptorSets-pDynamicOffsets-01971
|
||||||
// VUID-vkCmdBindDescriptorSets-pDynamicOffsets-01972
|
// VUID-vkCmdBindDescriptorSets-pDynamicOffsets-01972
|
||||||
if offset % required_alignment != 0 {
|
if !is_aligned(offset as DeviceSize, required_alignment) {
|
||||||
return Err(BindPushError::DynamicOffsetNotAligned {
|
return Err(BindPushError::DynamicOffsetNotAligned {
|
||||||
set_num,
|
set_num,
|
||||||
binding_num,
|
binding_num,
|
||||||
|
@ -1,17 +1,14 @@
|
|||||||
use super::physical::{
|
use super::physical::{
|
||||||
MemoryDecompressionMethods, OpticalFlowGridSizes, PipelineRobustnessBufferBehavior,
|
ConformanceVersion, DriverId, MemoryDecompressionMethods, OpticalFlowGridSizes,
|
||||||
PipelineRobustnessImageBehavior, RayTracingInvocationReorderMode,
|
PhysicalDeviceType, PipelineRobustnessBufferBehavior, PipelineRobustnessImageBehavior,
|
||||||
|
PointClippingBehavior, RayTracingInvocationReorderMode, ShaderCoreProperties,
|
||||||
|
ShaderFloatControlsIndependence, SubgroupFeatures,
|
||||||
};
|
};
|
||||||
use crate::{
|
use crate::{
|
||||||
device::{
|
device::{DeviceExtensions, QueueFlags},
|
||||||
physical::{
|
|
||||||
ConformanceVersion, DriverId, PhysicalDeviceType, PointClippingBehavior,
|
|
||||||
ShaderCoreProperties, ShaderFloatControlsIndependence, SubgroupFeatures,
|
|
||||||
},
|
|
||||||
DeviceExtensions, QueueFlags,
|
|
||||||
},
|
|
||||||
image::{SampleCount, SampleCounts},
|
image::{SampleCount, SampleCounts},
|
||||||
instance::InstanceExtensions,
|
instance::InstanceExtensions,
|
||||||
|
memory::DeviceAlignment,
|
||||||
render_pass::ResolveModes,
|
render_pass::ResolveModes,
|
||||||
shader::ShaderStages,
|
shader::ShaderStages,
|
||||||
DeviceSize, Version,
|
DeviceSize, Version,
|
||||||
@ -65,6 +62,13 @@ impl FromVulkan<u64> for u64 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl FromVulkan<u64> for DeviceAlignment {
|
||||||
|
#[inline]
|
||||||
|
fn from_vulkan(val: u64) -> Option<Self> {
|
||||||
|
DeviceAlignment::new(val)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl FromVulkan<usize> for usize {
|
impl FromVulkan<usize> for usize {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn from_vulkan(val: usize) -> Option<Self> {
|
fn from_vulkan(val: usize) -> Option<Self> {
|
||||||
|
@ -22,7 +22,7 @@ use crate::{
|
|||||||
AllocationCreateInfo, AllocationType, MemoryAllocatePreference, MemoryAllocator,
|
AllocationCreateInfo, AllocationType, MemoryAllocatePreference, MemoryAllocator,
|
||||||
MemoryUsage,
|
MemoryUsage,
|
||||||
},
|
},
|
||||||
DedicatedAllocation, DeviceMemoryError, ExternalMemoryHandleType,
|
is_aligned, DedicatedAllocation, DeviceMemoryError, ExternalMemoryHandleType,
|
||||||
ExternalMemoryHandleTypes,
|
ExternalMemoryHandleTypes,
|
||||||
},
|
},
|
||||||
DeviceSize,
|
DeviceSize,
|
||||||
@ -427,7 +427,7 @@ impl AttachmentImage {
|
|||||||
|
|
||||||
match unsafe { allocator.allocate_unchecked(create_info) } {
|
match unsafe { allocator.allocate_unchecked(create_info) } {
|
||||||
Ok(alloc) => {
|
Ok(alloc) => {
|
||||||
debug_assert!(alloc.offset() % requirements.layout.alignment().as_nonzero() == 0);
|
debug_assert!(is_aligned(alloc.offset(), requirements.layout.alignment()));
|
||||||
debug_assert!(alloc.size() == requirements.layout.size());
|
debug_assert!(alloc.size() == requirements.layout.size());
|
||||||
|
|
||||||
let inner = Arc::new(unsafe {
|
let inner = Arc::new(unsafe {
|
||||||
@ -532,7 +532,7 @@ impl AttachmentImage {
|
|||||||
)
|
)
|
||||||
} {
|
} {
|
||||||
Ok(alloc) => {
|
Ok(alloc) => {
|
||||||
debug_assert!(alloc.offset() % requirements.layout.alignment().as_nonzero() == 0);
|
debug_assert!(is_aligned(alloc.offset(), requirements.layout.alignment()));
|
||||||
debug_assert!(alloc.size() == requirements.layout.size());
|
debug_assert!(alloc.size() == requirements.layout.size());
|
||||||
|
|
||||||
let inner = Arc::new(unsafe {
|
let inner = Arc::new(unsafe {
|
||||||
|
@ -27,7 +27,7 @@ use crate::{
|
|||||||
AllocationCreateInfo, AllocationCreationError, AllocationType,
|
AllocationCreateInfo, AllocationCreationError, AllocationType,
|
||||||
MemoryAllocatePreference, MemoryAllocator, MemoryUsage,
|
MemoryAllocatePreference, MemoryAllocator, MemoryUsage,
|
||||||
},
|
},
|
||||||
DedicatedAllocation,
|
is_aligned, DedicatedAllocation,
|
||||||
},
|
},
|
||||||
sampler::Filter,
|
sampler::Filter,
|
||||||
sync::Sharing,
|
sync::Sharing,
|
||||||
@ -149,7 +149,7 @@ impl ImmutableImage {
|
|||||||
|
|
||||||
match unsafe { allocator.allocate_unchecked(create_info) } {
|
match unsafe { allocator.allocate_unchecked(create_info) } {
|
||||||
Ok(alloc) => {
|
Ok(alloc) => {
|
||||||
debug_assert!(alloc.offset() % requirements.layout.alignment().as_nonzero() == 0);
|
debug_assert!(is_aligned(alloc.offset(), requirements.layout.alignment()));
|
||||||
debug_assert!(alloc.size() == requirements.layout.size());
|
debug_assert!(alloc.size() == requirements.layout.size());
|
||||||
|
|
||||||
let inner = Arc::new(unsafe {
|
let inner = Arc::new(unsafe {
|
||||||
|
@ -22,7 +22,7 @@ use crate::{
|
|||||||
AllocationCreateInfo, AllocationType, MemoryAllocatePreference, MemoryAllocator,
|
AllocationCreateInfo, AllocationType, MemoryAllocatePreference, MemoryAllocator,
|
||||||
MemoryUsage,
|
MemoryUsage,
|
||||||
},
|
},
|
||||||
DedicatedAllocation, DeviceMemoryError, ExternalMemoryHandleType,
|
is_aligned, DedicatedAllocation, DeviceMemoryError, ExternalMemoryHandleType,
|
||||||
ExternalMemoryHandleTypes,
|
ExternalMemoryHandleTypes,
|
||||||
},
|
},
|
||||||
sync::Sharing,
|
sync::Sharing,
|
||||||
@ -125,7 +125,7 @@ impl StorageImage {
|
|||||||
|
|
||||||
match unsafe { allocator.allocate_unchecked(create_info) } {
|
match unsafe { allocator.allocate_unchecked(create_info) } {
|
||||||
Ok(alloc) => {
|
Ok(alloc) => {
|
||||||
debug_assert!(alloc.offset() % requirements.layout.alignment().as_nonzero() == 0);
|
debug_assert!(is_aligned(alloc.offset(), requirements.layout.alignment()));
|
||||||
debug_assert!(alloc.size() == requirements.layout.size());
|
debug_assert!(alloc.size() == requirements.layout.size());
|
||||||
|
|
||||||
let inner = Arc::new(unsafe {
|
let inner = Arc::new(unsafe {
|
||||||
@ -205,7 +205,7 @@ impl StorageImage {
|
|||||||
)
|
)
|
||||||
} {
|
} {
|
||||||
Ok(alloc) => {
|
Ok(alloc) => {
|
||||||
debug_assert!(alloc.offset() % requirements.layout.alignment().as_nonzero() == 0);
|
debug_assert!(is_aligned(alloc.offset(), requirements.layout.alignment()));
|
||||||
debug_assert!(alloc.size() == requirements.layout.size());
|
debug_assert!(alloc.size() == requirements.layout.size());
|
||||||
|
|
||||||
let inner = Arc::new(unsafe {
|
let inner = Arc::new(unsafe {
|
||||||
|
@ -28,11 +28,9 @@ use crate::{
|
|||||||
SparseImageFormatProperties,
|
SparseImageFormatProperties,
|
||||||
},
|
},
|
||||||
memory::{
|
memory::{
|
||||||
allocator::{
|
allocator::{AllocationCreationError, AllocationType, DeviceLayout, MemoryAlloc},
|
||||||
AllocationCreationError, AllocationType, DeviceAlignment, DeviceLayout, MemoryAlloc,
|
is_aligned, DedicatedTo, DeviceAlignment, ExternalMemoryHandleType,
|
||||||
},
|
ExternalMemoryHandleTypes, MemoryPropertyFlags, MemoryRequirements,
|
||||||
DedicatedTo, ExternalMemoryHandleType, ExternalMemoryHandleTypes, MemoryPropertyFlags,
|
|
||||||
MemoryRequirements,
|
|
||||||
},
|
},
|
||||||
range_map::RangeMap,
|
range_map::RangeMap,
|
||||||
swapchain::Swapchain,
|
swapchain::Swapchain,
|
||||||
@ -1479,7 +1477,7 @@ impl RawImage {
|
|||||||
|
|
||||||
// VUID-VkBindImageMemoryInfo-pNext-01616
|
// VUID-VkBindImageMemoryInfo-pNext-01616
|
||||||
// VUID-VkBindImageMemoryInfo-pNext-01620
|
// VUID-VkBindImageMemoryInfo-pNext-01620
|
||||||
if memory_offset % memory_requirements.layout.alignment().as_nonzero() != 0 {
|
if !is_aligned(memory_offset, memory_requirements.layout.alignment()) {
|
||||||
return Err(ImageError::MemoryAllocationNotAligned {
|
return Err(ImageError::MemoryAllocationNotAligned {
|
||||||
allocations_index,
|
allocations_index,
|
||||||
allocation_offset: memory_offset,
|
allocation_offset: memory_offset,
|
||||||
|
249
vulkano/src/memory/alignment.rs
Normal file
249
vulkano/src/memory/alignment.rs
Normal file
@ -0,0 +1,249 @@
|
|||||||
|
use crate::{DeviceSize, NonZeroDeviceSize};
|
||||||
|
use std::{
|
||||||
|
cmp::Ordering,
|
||||||
|
error::Error,
|
||||||
|
fmt::{Debug, Display, Formatter, Result as FmtResult},
|
||||||
|
hash::{Hash, Hasher},
|
||||||
|
mem::{self, align_of, size_of},
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Vulkan analog of std's [`Alignment`], stored as a [`DeviceSize`] that is guaranteed to be a
|
||||||
|
/// valid Vulkan alignment.
|
||||||
|
///
|
||||||
|
/// [`Alignment`]: std::ptr::Alignment
|
||||||
|
#[derive(Clone, Copy, PartialEq, Eq)]
|
||||||
|
#[repr(transparent)]
|
||||||
|
pub struct DeviceAlignment(AlignmentEnum);
|
||||||
|
|
||||||
|
const _: () = assert!(size_of::<DeviceAlignment>() == size_of::<DeviceSize>());
|
||||||
|
const _: () = assert!(align_of::<DeviceAlignment>() == align_of::<DeviceSize>());
|
||||||
|
|
||||||
|
impl DeviceAlignment {
|
||||||
|
/// The smallest possible alignment, 1.
|
||||||
|
pub const MIN: Self = Self(AlignmentEnum::_Align1Shl0);
|
||||||
|
|
||||||
|
/// The largest possible alignment, 2<sup>63</sup>.
|
||||||
|
pub const MAX: Self = Self(AlignmentEnum::_Align1Shl63);
|
||||||
|
|
||||||
|
/// Returns the alignment for a type.
|
||||||
|
#[inline]
|
||||||
|
pub const fn of<T>() -> Self {
|
||||||
|
#[cfg(any(
|
||||||
|
target_pointer_width = "64",
|
||||||
|
target_pointer_width = "32",
|
||||||
|
target_pointer_width = "16",
|
||||||
|
))]
|
||||||
|
{
|
||||||
|
const _: () = assert!(size_of::<DeviceSize>() >= size_of::<usize>());
|
||||||
|
|
||||||
|
// SAFETY: rustc guarantees that the alignment of types is a power of two.
|
||||||
|
unsafe { DeviceAlignment::new_unchecked(align_of::<T>() as DeviceSize) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Tries to create a `DeviceAlignment` from a [`DeviceSize`], returning [`None`] if it's not a
|
||||||
|
/// power of two.
|
||||||
|
#[inline]
|
||||||
|
pub const fn new(alignment: DeviceSize) -> Option<Self> {
|
||||||
|
if alignment.is_power_of_two() {
|
||||||
|
Some(unsafe { DeviceAlignment::new_unchecked(alignment) })
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Creates a `DeviceAlignment` from a [`DeviceSize`] without checking if it's a power of two.
|
||||||
|
///
|
||||||
|
/// # Safety
|
||||||
|
///
|
||||||
|
/// - `alignment` must be a power of two, which also means it must be non-zero.
|
||||||
|
#[inline]
|
||||||
|
pub const unsafe fn new_unchecked(alignment: DeviceSize) -> Self {
|
||||||
|
debug_assert!(alignment.is_power_of_two());
|
||||||
|
|
||||||
|
unsafe { mem::transmute::<DeviceSize, DeviceAlignment>(alignment) }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the alignment as a [`DeviceSize`].
|
||||||
|
#[inline]
|
||||||
|
pub const fn as_devicesize(self) -> DeviceSize {
|
||||||
|
self.0 as DeviceSize
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the alignment as a [`NonZeroDeviceSize`].
|
||||||
|
#[inline]
|
||||||
|
pub const fn as_nonzero(self) -> NonZeroDeviceSize {
|
||||||
|
// SAFETY: All the discriminants are non-zero.
|
||||||
|
unsafe { NonZeroDeviceSize::new_unchecked(self.as_devicesize()) }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the base-2 logarithm of the alignment.
|
||||||
|
#[inline]
|
||||||
|
pub const fn log2(self) -> u32 {
|
||||||
|
self.as_nonzero().trailing_zeros()
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Replace with `Ord::max` once its constness is stabilized.
|
||||||
|
#[inline(always)]
|
||||||
|
pub(crate) const fn max(self, other: Self) -> Self {
|
||||||
|
if self.as_devicesize() >= other.as_devicesize() {
|
||||||
|
self
|
||||||
|
} else {
|
||||||
|
other
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Debug for DeviceAlignment {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
|
||||||
|
write!(f, "{:?} (1 << {:?})", self.as_nonzero(), self.log2())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for DeviceAlignment {
|
||||||
|
#[inline]
|
||||||
|
fn default() -> Self {
|
||||||
|
DeviceAlignment::MIN
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<NonZeroDeviceSize> for DeviceAlignment {
|
||||||
|
type Error = TryFromIntError;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn try_from(alignment: NonZeroDeviceSize) -> Result<Self, Self::Error> {
|
||||||
|
if alignment.is_power_of_two() {
|
||||||
|
Ok(unsafe { DeviceAlignment::new_unchecked(alignment.get()) })
|
||||||
|
} else {
|
||||||
|
Err(TryFromIntError)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<DeviceSize> for DeviceAlignment {
|
||||||
|
type Error = TryFromIntError;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn try_from(alignment: DeviceSize) -> Result<Self, Self::Error> {
|
||||||
|
DeviceAlignment::new(alignment).ok_or(TryFromIntError)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<DeviceAlignment> for NonZeroDeviceSize {
|
||||||
|
#[inline]
|
||||||
|
fn from(alignment: DeviceAlignment) -> Self {
|
||||||
|
alignment.as_nonzero()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<DeviceAlignment> for DeviceSize {
|
||||||
|
#[inline]
|
||||||
|
fn from(alignment: DeviceAlignment) -> Self {
|
||||||
|
alignment.as_devicesize()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is a false-positive, the underlying values that this impl and the derived `PartialEq` work
|
||||||
|
// with are the same.
|
||||||
|
#[allow(clippy::derive_hash_xor_eq)]
|
||||||
|
impl Hash for DeviceAlignment {
|
||||||
|
#[inline]
|
||||||
|
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||||
|
self.as_nonzero().hash(state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PartialOrd for DeviceAlignment {
|
||||||
|
#[inline]
|
||||||
|
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||||
|
self.as_nonzero().partial_cmp(&other.as_nonzero())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Ord for DeviceAlignment {
|
||||||
|
#[inline]
|
||||||
|
fn cmp(&self, other: &Self) -> Ordering {
|
||||||
|
self.as_nonzero().cmp(&other.as_nonzero())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, PartialEq, Eq)]
|
||||||
|
#[repr(u64)]
|
||||||
|
enum AlignmentEnum {
|
||||||
|
_Align1Shl0 = 1 << 0,
|
||||||
|
_Align1Shl1 = 1 << 1,
|
||||||
|
_Align1Shl2 = 1 << 2,
|
||||||
|
_Align1Shl3 = 1 << 3,
|
||||||
|
_Align1Shl4 = 1 << 4,
|
||||||
|
_Align1Shl5 = 1 << 5,
|
||||||
|
_Align1Shl6 = 1 << 6,
|
||||||
|
_Align1Shl7 = 1 << 7,
|
||||||
|
_Align1Shl8 = 1 << 8,
|
||||||
|
_Align1Shl9 = 1 << 9,
|
||||||
|
_Align1Shl10 = 1 << 10,
|
||||||
|
_Align1Shl11 = 1 << 11,
|
||||||
|
_Align1Shl12 = 1 << 12,
|
||||||
|
_Align1Shl13 = 1 << 13,
|
||||||
|
_Align1Shl14 = 1 << 14,
|
||||||
|
_Align1Shl15 = 1 << 15,
|
||||||
|
_Align1Shl16 = 1 << 16,
|
||||||
|
_Align1Shl17 = 1 << 17,
|
||||||
|
_Align1Shl18 = 1 << 18,
|
||||||
|
_Align1Shl19 = 1 << 19,
|
||||||
|
_Align1Shl20 = 1 << 20,
|
||||||
|
_Align1Shl21 = 1 << 21,
|
||||||
|
_Align1Shl22 = 1 << 22,
|
||||||
|
_Align1Shl23 = 1 << 23,
|
||||||
|
_Align1Shl24 = 1 << 24,
|
||||||
|
_Align1Shl25 = 1 << 25,
|
||||||
|
_Align1Shl26 = 1 << 26,
|
||||||
|
_Align1Shl27 = 1 << 27,
|
||||||
|
_Align1Shl28 = 1 << 28,
|
||||||
|
_Align1Shl29 = 1 << 29,
|
||||||
|
_Align1Shl30 = 1 << 30,
|
||||||
|
_Align1Shl31 = 1 << 31,
|
||||||
|
_Align1Shl32 = 1 << 32,
|
||||||
|
_Align1Shl33 = 1 << 33,
|
||||||
|
_Align1Shl34 = 1 << 34,
|
||||||
|
_Align1Shl35 = 1 << 35,
|
||||||
|
_Align1Shl36 = 1 << 36,
|
||||||
|
_Align1Shl37 = 1 << 37,
|
||||||
|
_Align1Shl38 = 1 << 38,
|
||||||
|
_Align1Shl39 = 1 << 39,
|
||||||
|
_Align1Shl40 = 1 << 40,
|
||||||
|
_Align1Shl41 = 1 << 41,
|
||||||
|
_Align1Shl42 = 1 << 42,
|
||||||
|
_Align1Shl43 = 1 << 43,
|
||||||
|
_Align1Shl44 = 1 << 44,
|
||||||
|
_Align1Shl45 = 1 << 45,
|
||||||
|
_Align1Shl46 = 1 << 46,
|
||||||
|
_Align1Shl47 = 1 << 47,
|
||||||
|
_Align1Shl48 = 1 << 48,
|
||||||
|
_Align1Shl49 = 1 << 49,
|
||||||
|
_Align1Shl50 = 1 << 50,
|
||||||
|
_Align1Shl51 = 1 << 51,
|
||||||
|
_Align1Shl52 = 1 << 52,
|
||||||
|
_Align1Shl53 = 1 << 53,
|
||||||
|
_Align1Shl54 = 1 << 54,
|
||||||
|
_Align1Shl55 = 1 << 55,
|
||||||
|
_Align1Shl56 = 1 << 56,
|
||||||
|
_Align1Shl57 = 1 << 57,
|
||||||
|
_Align1Shl58 = 1 << 58,
|
||||||
|
_Align1Shl59 = 1 << 59,
|
||||||
|
_Align1Shl60 = 1 << 60,
|
||||||
|
_Align1Shl61 = 1 << 61,
|
||||||
|
_Align1Shl62 = 1 << 62,
|
||||||
|
_Align1Shl63 = 1 << 63,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Error that can happen when trying to convert an integer to a `DeviceAlignment`.
|
||||||
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
|
pub struct TryFromIntError;
|
||||||
|
|
||||||
|
impl Error for TryFromIntError {}
|
||||||
|
|
||||||
|
impl Display for TryFromIntError {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
|
||||||
|
f.write_str("attempted to convert a non-power-of-two integer to a `DeviceAlignment`")
|
||||||
|
}
|
||||||
|
}
|
@ -8,14 +8,13 @@
|
|||||||
// according to those terms.
|
// according to those terms.
|
||||||
|
|
||||||
use super::align_up;
|
use super::align_up;
|
||||||
use crate::{macros::try_opt, DeviceSize, NonZeroDeviceSize};
|
use crate::{macros::try_opt, memory::DeviceAlignment, DeviceSize, NonZeroDeviceSize};
|
||||||
use std::{
|
use std::{
|
||||||
alloc::Layout,
|
alloc::Layout,
|
||||||
cmp::Ordering,
|
|
||||||
error::Error,
|
error::Error,
|
||||||
fmt::{Debug, Display, Formatter, Result as FmtResult},
|
fmt::{Debug, Display, Formatter, Result as FmtResult},
|
||||||
hash::{Hash, Hasher},
|
hash::Hash,
|
||||||
mem::{self, align_of, size_of},
|
mem::size_of,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Vulkan analog of std's [`Layout`], represented using [`DeviceSize`]s.
|
/// Vulkan analog of std's [`Layout`], represented using [`DeviceSize`]s.
|
||||||
@ -351,237 +350,3 @@ impl Display for TryFromDeviceLayoutError {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Vulkan analog of std's [`Alignment`], stored as a [`DeviceSize`] that is guaranteed to be a
|
|
||||||
/// valid Vulkan alignment.
|
|
||||||
///
|
|
||||||
/// [`Alignment`]: std::ptr::Alignment
|
|
||||||
#[derive(Clone, Copy, PartialEq, Eq)]
|
|
||||||
#[repr(transparent)]
|
|
||||||
pub struct DeviceAlignment(AlignmentEnum);
|
|
||||||
|
|
||||||
const _: () = assert!(size_of::<DeviceAlignment>() == size_of::<DeviceSize>());
|
|
||||||
const _: () = assert!(align_of::<DeviceAlignment>() == align_of::<DeviceSize>());
|
|
||||||
|
|
||||||
impl DeviceAlignment {
|
|
||||||
/// The smallest possible alignment, 1.
|
|
||||||
pub const MIN: Self = Self(AlignmentEnum::_Align1Shl0);
|
|
||||||
|
|
||||||
/// The largest possible alignment, 2<sup>63</sup>.
|
|
||||||
pub const MAX: Self = Self(AlignmentEnum::_Align1Shl63);
|
|
||||||
|
|
||||||
/// Returns the alignment for a type.
|
|
||||||
#[inline]
|
|
||||||
pub const fn of<T>() -> Self {
|
|
||||||
#[cfg(any(
|
|
||||||
target_pointer_width = "64",
|
|
||||||
target_pointer_width = "32",
|
|
||||||
target_pointer_width = "16",
|
|
||||||
))]
|
|
||||||
{
|
|
||||||
const _: () = assert!(size_of::<DeviceSize>() >= size_of::<usize>());
|
|
||||||
|
|
||||||
// SAFETY: rustc guarantees that the alignment of types is a power of two.
|
|
||||||
unsafe { DeviceAlignment::new_unchecked(align_of::<T>() as DeviceSize) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Tries to create a `DeviceAlignment` from a [`DeviceSize`], returning [`None`] if it's not a
|
|
||||||
/// power of two.
|
|
||||||
#[inline]
|
|
||||||
pub const fn new(alignment: DeviceSize) -> Option<Self> {
|
|
||||||
if alignment.is_power_of_two() {
|
|
||||||
Some(unsafe { DeviceAlignment::new_unchecked(alignment) })
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Creates a `DeviceAlignment` from a [`DeviceSize`] without checking if it's a power of two.
|
|
||||||
///
|
|
||||||
/// # Safety
|
|
||||||
///
|
|
||||||
/// - `alignment` must be a power of two, which also means it must be non-zero.
|
|
||||||
#[inline]
|
|
||||||
pub const unsafe fn new_unchecked(alignment: DeviceSize) -> Self {
|
|
||||||
debug_assert!(alignment.is_power_of_two());
|
|
||||||
|
|
||||||
unsafe { mem::transmute::<DeviceSize, DeviceAlignment>(alignment) }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the alignment as a [`DeviceSize`].
|
|
||||||
#[inline]
|
|
||||||
pub const fn as_devicesize(self) -> DeviceSize {
|
|
||||||
self.0 as DeviceSize
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the alignment as a [`NonZeroDeviceSize`].
|
|
||||||
#[inline]
|
|
||||||
pub const fn as_nonzero(self) -> NonZeroDeviceSize {
|
|
||||||
// SAFETY: All the discriminants are non-zero.
|
|
||||||
unsafe { NonZeroDeviceSize::new_unchecked(self.as_devicesize()) }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the base-2 logarithm of the alignment.
|
|
||||||
#[inline]
|
|
||||||
pub const fn log2(self) -> u32 {
|
|
||||||
self.as_nonzero().trailing_zeros()
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Replace with `Ord::max` once its constness is stabilized.
|
|
||||||
#[inline(always)]
|
|
||||||
pub(crate) const fn max(self, other: Self) -> Self {
|
|
||||||
if self.as_devicesize() >= other.as_devicesize() {
|
|
||||||
self
|
|
||||||
} else {
|
|
||||||
other
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Debug for DeviceAlignment {
|
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
|
|
||||||
write!(f, "{:?} (1 << {:?})", self.as_nonzero(), self.log2())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl TryFrom<NonZeroDeviceSize> for DeviceAlignment {
|
|
||||||
type Error = TryFromIntError;
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn try_from(alignment: NonZeroDeviceSize) -> Result<Self, Self::Error> {
|
|
||||||
if alignment.is_power_of_two() {
|
|
||||||
Ok(unsafe { DeviceAlignment::new_unchecked(alignment.get()) })
|
|
||||||
} else {
|
|
||||||
Err(TryFromIntError)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl TryFrom<DeviceSize> for DeviceAlignment {
|
|
||||||
type Error = TryFromIntError;
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn try_from(alignment: DeviceSize) -> Result<Self, Self::Error> {
|
|
||||||
DeviceAlignment::new(alignment).ok_or(TryFromIntError)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<DeviceAlignment> for NonZeroDeviceSize {
|
|
||||||
#[inline]
|
|
||||||
fn from(alignment: DeviceAlignment) -> Self {
|
|
||||||
alignment.as_nonzero()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<DeviceAlignment> for DeviceSize {
|
|
||||||
#[inline]
|
|
||||||
fn from(alignment: DeviceAlignment) -> Self {
|
|
||||||
alignment.as_devicesize()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// This is a false-positive, the underlying values that this impl and the derived `PartialEq` work
|
|
||||||
// with are the same.
|
|
||||||
#[allow(clippy::derive_hash_xor_eq)]
|
|
||||||
impl Hash for DeviceAlignment {
|
|
||||||
#[inline]
|
|
||||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
|
||||||
self.as_nonzero().hash(state);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl PartialOrd for DeviceAlignment {
|
|
||||||
#[inline]
|
|
||||||
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
|
||||||
self.as_nonzero().partial_cmp(&other.as_nonzero())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Ord for DeviceAlignment {
|
|
||||||
#[inline]
|
|
||||||
fn cmp(&self, other: &Self) -> Ordering {
|
|
||||||
self.as_nonzero().cmp(&other.as_nonzero())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Copy, PartialEq, Eq)]
|
|
||||||
#[repr(u64)]
|
|
||||||
enum AlignmentEnum {
|
|
||||||
_Align1Shl0 = 1 << 0,
|
|
||||||
_Align1Shl1 = 1 << 1,
|
|
||||||
_Align1Shl2 = 1 << 2,
|
|
||||||
_Align1Shl3 = 1 << 3,
|
|
||||||
_Align1Shl4 = 1 << 4,
|
|
||||||
_Align1Shl5 = 1 << 5,
|
|
||||||
_Align1Shl6 = 1 << 6,
|
|
||||||
_Align1Shl7 = 1 << 7,
|
|
||||||
_Align1Shl8 = 1 << 8,
|
|
||||||
_Align1Shl9 = 1 << 9,
|
|
||||||
_Align1Shl10 = 1 << 10,
|
|
||||||
_Align1Shl11 = 1 << 11,
|
|
||||||
_Align1Shl12 = 1 << 12,
|
|
||||||
_Align1Shl13 = 1 << 13,
|
|
||||||
_Align1Shl14 = 1 << 14,
|
|
||||||
_Align1Shl15 = 1 << 15,
|
|
||||||
_Align1Shl16 = 1 << 16,
|
|
||||||
_Align1Shl17 = 1 << 17,
|
|
||||||
_Align1Shl18 = 1 << 18,
|
|
||||||
_Align1Shl19 = 1 << 19,
|
|
||||||
_Align1Shl20 = 1 << 20,
|
|
||||||
_Align1Shl21 = 1 << 21,
|
|
||||||
_Align1Shl22 = 1 << 22,
|
|
||||||
_Align1Shl23 = 1 << 23,
|
|
||||||
_Align1Shl24 = 1 << 24,
|
|
||||||
_Align1Shl25 = 1 << 25,
|
|
||||||
_Align1Shl26 = 1 << 26,
|
|
||||||
_Align1Shl27 = 1 << 27,
|
|
||||||
_Align1Shl28 = 1 << 28,
|
|
||||||
_Align1Shl29 = 1 << 29,
|
|
||||||
_Align1Shl30 = 1 << 30,
|
|
||||||
_Align1Shl31 = 1 << 31,
|
|
||||||
_Align1Shl32 = 1 << 32,
|
|
||||||
_Align1Shl33 = 1 << 33,
|
|
||||||
_Align1Shl34 = 1 << 34,
|
|
||||||
_Align1Shl35 = 1 << 35,
|
|
||||||
_Align1Shl36 = 1 << 36,
|
|
||||||
_Align1Shl37 = 1 << 37,
|
|
||||||
_Align1Shl38 = 1 << 38,
|
|
||||||
_Align1Shl39 = 1 << 39,
|
|
||||||
_Align1Shl40 = 1 << 40,
|
|
||||||
_Align1Shl41 = 1 << 41,
|
|
||||||
_Align1Shl42 = 1 << 42,
|
|
||||||
_Align1Shl43 = 1 << 43,
|
|
||||||
_Align1Shl44 = 1 << 44,
|
|
||||||
_Align1Shl45 = 1 << 45,
|
|
||||||
_Align1Shl46 = 1 << 46,
|
|
||||||
_Align1Shl47 = 1 << 47,
|
|
||||||
_Align1Shl48 = 1 << 48,
|
|
||||||
_Align1Shl49 = 1 << 49,
|
|
||||||
_Align1Shl50 = 1 << 50,
|
|
||||||
_Align1Shl51 = 1 << 51,
|
|
||||||
_Align1Shl52 = 1 << 52,
|
|
||||||
_Align1Shl53 = 1 << 53,
|
|
||||||
_Align1Shl54 = 1 << 54,
|
|
||||||
_Align1Shl55 = 1 << 55,
|
|
||||||
_Align1Shl56 = 1 << 56,
|
|
||||||
_Align1Shl57 = 1 << 57,
|
|
||||||
_Align1Shl58 = 1 << 58,
|
|
||||||
_Align1Shl59 = 1 << 59,
|
|
||||||
_Align1Shl60 = 1 << 60,
|
|
||||||
_Align1Shl61 = 1 << 61,
|
|
||||||
_Align1Shl62 = 1 << 62,
|
|
||||||
_Align1Shl63 = 1 << 63,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Error that can happen when trying to convert an integer to a `DeviceAlignment`.
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
|
||||||
pub struct TryFromIntError;
|
|
||||||
|
|
||||||
impl Error for TryFromIntError {}
|
|
||||||
|
|
||||||
impl Display for TryFromIntError {
|
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
|
|
||||||
f.write_str("attempted to convert a non-power-of-two integer to a `DeviceAlignment`")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -221,15 +221,16 @@ pub mod suballocator;
|
|||||||
|
|
||||||
use self::array_vec::ArrayVec;
|
use self::array_vec::ArrayVec;
|
||||||
pub use self::{
|
pub use self::{
|
||||||
layout::{DeviceAlignment, DeviceLayout},
|
layout::DeviceLayout,
|
||||||
suballocator::{
|
suballocator::{
|
||||||
AllocationType, BuddyAllocator, BumpAllocator, FreeListAllocator, MemoryAlloc,
|
AllocationType, BuddyAllocator, BumpAllocator, FreeListAllocator, MemoryAlloc,
|
||||||
PoolAllocator, SuballocationCreateInfo, SuballocationCreationError, Suballocator,
|
PoolAllocator, SuballocationCreateInfo, SuballocationCreationError, Suballocator,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use super::{
|
use super::{
|
||||||
DedicatedAllocation, DeviceMemory, ExternalMemoryHandleTypes, MemoryAllocateFlags,
|
DedicatedAllocation, DeviceAlignment, DeviceMemory, ExternalMemoryHandleTypes,
|
||||||
MemoryAllocateInfo, MemoryProperties, MemoryPropertyFlags, MemoryRequirements, MemoryType,
|
MemoryAllocateFlags, MemoryAllocateInfo, MemoryProperties, MemoryPropertyFlags,
|
||||||
|
MemoryRequirements, MemoryType,
|
||||||
};
|
};
|
||||||
use crate::{
|
use crate::{
|
||||||
device::{Device, DeviceOwned},
|
device::{Device, DeviceOwned},
|
||||||
|
@ -21,7 +21,7 @@ use super::{
|
|||||||
use crate::{
|
use crate::{
|
||||||
device::{Device, DeviceOwned},
|
device::{Device, DeviceOwned},
|
||||||
image::ImageTiling,
|
image::ImageTiling,
|
||||||
memory::{DeviceMemory, MemoryPropertyFlags},
|
memory::{is_aligned, DeviceMemory, MemoryPropertyFlags},
|
||||||
DeviceSize, NonZeroDeviceSize, VulkanError, VulkanObject,
|
DeviceSize, NonZeroDeviceSize, VulkanError, VulkanObject,
|
||||||
};
|
};
|
||||||
use crossbeam_queue::ArrayQueue;
|
use crossbeam_queue::ArrayQueue;
|
||||||
@ -135,9 +135,7 @@ impl MemoryAlloc {
|
|||||||
|
|
||||||
let atom_size = (property_flags.intersects(MemoryPropertyFlags::HOST_VISIBLE)
|
let atom_size = (property_flags.intersects(MemoryPropertyFlags::HOST_VISIBLE)
|
||||||
&& !property_flags.intersects(MemoryPropertyFlags::HOST_COHERENT))
|
&& !property_flags.intersects(MemoryPropertyFlags::HOST_COHERENT))
|
||||||
.then_some(
|
.then_some(physical_device.properties().non_coherent_atom_size);
|
||||||
DeviceAlignment::new(physical_device.properties().non_coherent_atom_size).unwrap(),
|
|
||||||
);
|
|
||||||
|
|
||||||
Ok(MemoryAlloc {
|
Ok(MemoryAlloc {
|
||||||
offset: 0,
|
offset: 0,
|
||||||
@ -301,8 +299,8 @@ impl MemoryAlloc {
|
|||||||
// VUID-VkMappedMemoryRange-offset-00687
|
// VUID-VkMappedMemoryRange-offset-00687
|
||||||
// VUID-VkMappedMemoryRange-size-01390
|
// VUID-VkMappedMemoryRange-size-01390
|
||||||
assert!(
|
assert!(
|
||||||
range.start % atom_size.as_nonzero() == 0
|
is_aligned(range.start, atom_size)
|
||||||
&& (range.end % atom_size.as_nonzero() == 0 || range.end == self.size)
|
&& (is_aligned(range.end, atom_size) || range.end == self.size)
|
||||||
);
|
);
|
||||||
|
|
||||||
// VUID-VkMappedMemoryRange-offset-00687
|
// VUID-VkMappedMemoryRange-offset-00687
|
||||||
@ -334,17 +332,15 @@ impl MemoryAlloc {
|
|||||||
/// to be host-coherent.
|
/// to be host-coherent.
|
||||||
fn debug_validate_memory_range(&self, range: &Range<DeviceSize>) {
|
fn debug_validate_memory_range(&self, range: &Range<DeviceSize>) {
|
||||||
debug_assert!(!range.is_empty() && range.end <= self.size);
|
debug_assert!(!range.is_empty() && range.end <= self.size);
|
||||||
debug_assert!(
|
|
||||||
{
|
|
||||||
let atom_size = self
|
|
||||||
.device()
|
|
||||||
.physical_device()
|
|
||||||
.properties()
|
|
||||||
.non_coherent_atom_size;
|
|
||||||
|
|
||||||
range.start % atom_size == 0
|
let atom_size = self
|
||||||
&& (range.end % atom_size == 0 || range.end == self.size)
|
.device()
|
||||||
},
|
.physical_device()
|
||||||
|
.properties()
|
||||||
|
.non_coherent_atom_size;
|
||||||
|
debug_assert!(
|
||||||
|
is_aligned(range.start, atom_size)
|
||||||
|
&& (is_aligned(range.end, atom_size) || range.end == self.size),
|
||||||
"attempted to invalidate or flush a memory range that is not aligned to the \
|
"attempted to invalidate or flush a memory range that is not aligned to the \
|
||||||
non-coherent atom size",
|
non-coherent atom size",
|
||||||
);
|
);
|
||||||
@ -1002,14 +998,12 @@ impl FreeListAllocator {
|
|||||||
.root()
|
.root()
|
||||||
.expect("dedicated allocations can't be suballocated")
|
.expect("dedicated allocations can't be suballocated")
|
||||||
.clone();
|
.clone();
|
||||||
let buffer_image_granularity = DeviceAlignment::new(
|
let buffer_image_granularity = device_memory
|
||||||
device_memory
|
.device()
|
||||||
.device()
|
.physical_device()
|
||||||
.physical_device()
|
.properties()
|
||||||
.properties()
|
.buffer_image_granularity;
|
||||||
.buffer_image_granularity,
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
let atom_size = region.atom_size.unwrap_or(DeviceAlignment::MIN);
|
let atom_size = region.atom_size.unwrap_or(DeviceAlignment::MIN);
|
||||||
let free_size = AtomicU64::new(region.size);
|
let free_size = AtomicU64::new(region.size);
|
||||||
|
|
||||||
@ -1600,14 +1594,11 @@ impl BuddyAllocator {
|
|||||||
.root()
|
.root()
|
||||||
.expect("dedicated allocations can't be suballocated")
|
.expect("dedicated allocations can't be suballocated")
|
||||||
.clone();
|
.clone();
|
||||||
let buffer_image_granularity = DeviceAlignment::new(
|
let buffer_image_granularity = device_memory
|
||||||
device_memory
|
.device()
|
||||||
.device()
|
.physical_device()
|
||||||
.physical_device()
|
.properties()
|
||||||
.properties()
|
.buffer_image_granularity;
|
||||||
.buffer_image_granularity,
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
let atom_size = region.atom_size.unwrap_or(DeviceAlignment::MIN);
|
let atom_size = region.atom_size.unwrap_or(DeviceAlignment::MIN);
|
||||||
let free_size = AtomicU64::new(region.size);
|
let free_size = AtomicU64::new(region.size);
|
||||||
|
|
||||||
@ -1742,7 +1733,7 @@ unsafe impl Suballocator for Arc<BuddyAllocator> {
|
|||||||
// Start searching at the lowest possible order going up.
|
// Start searching at the lowest possible order going up.
|
||||||
for (order, free_list) in state.free_list.iter_mut().enumerate().skip(min_order) {
|
for (order, free_list) in state.free_list.iter_mut().enumerate().skip(min_order) {
|
||||||
for (index, &offset) in free_list.iter().enumerate() {
|
for (index, &offset) in free_list.iter().enumerate() {
|
||||||
if offset % alignment.as_nonzero() == 0 {
|
if is_aligned(offset, alignment) {
|
||||||
free_list.remove(index);
|
free_list.remove(index);
|
||||||
|
|
||||||
// Go in the opposite direction, splitting nodes from higher orders. The lowest
|
// Go in the opposite direction, splitting nodes from higher orders. The lowest
|
||||||
@ -2117,14 +2108,11 @@ impl PoolAllocatorInner {
|
|||||||
.expect("dedicated allocations can't be suballocated")
|
.expect("dedicated allocations can't be suballocated")
|
||||||
.clone();
|
.clone();
|
||||||
#[cfg(not(test))]
|
#[cfg(not(test))]
|
||||||
let buffer_image_granularity = DeviceAlignment::new(
|
let buffer_image_granularity = device_memory
|
||||||
device_memory
|
.device()
|
||||||
.device()
|
.physical_device()
|
||||||
.physical_device()
|
.properties()
|
||||||
.properties()
|
.buffer_image_granularity;
|
||||||
.buffer_image_granularity,
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
let atom_size = region.atom_size.unwrap_or(DeviceAlignment::MIN);
|
let atom_size = region.atom_size.unwrap_or(DeviceAlignment::MIN);
|
||||||
if region.allocation_type == AllocationType::Unknown {
|
if region.allocation_type == AllocationType::Unknown {
|
||||||
block_size = align_up(block_size, buffer_image_granularity);
|
block_size = align_up(block_size, buffer_image_granularity);
|
||||||
@ -2294,14 +2282,11 @@ impl BumpAllocator {
|
|||||||
.root()
|
.root()
|
||||||
.expect("dedicated allocations can't be suballocated")
|
.expect("dedicated allocations can't be suballocated")
|
||||||
.clone();
|
.clone();
|
||||||
let buffer_image_granularity = DeviceAlignment::new(
|
let buffer_image_granularity = device_memory
|
||||||
device_memory
|
.device()
|
||||||
.device()
|
.physical_device()
|
||||||
.physical_device()
|
.properties()
|
||||||
.properties()
|
.buffer_image_granularity;
|
||||||
.buffer_image_granularity,
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
let atom_size = region.atom_size.unwrap_or(DeviceAlignment::MIN);
|
let atom_size = region.atom_size.unwrap_or(DeviceAlignment::MIN);
|
||||||
let state = AtomicU64::new(region.allocation_type as DeviceSize);
|
let state = AtomicU64::new(region.allocation_type as DeviceSize);
|
||||||
|
|
||||||
|
@ -7,11 +7,11 @@
|
|||||||
// notice may not be copied, modified, or distributed except
|
// notice may not be copied, modified, or distributed except
|
||||||
// according to those terms.
|
// according to those terms.
|
||||||
|
|
||||||
use super::{DedicatedAllocation, DedicatedTo};
|
use super::{DedicatedAllocation, DedicatedTo, DeviceAlignment};
|
||||||
use crate::{
|
use crate::{
|
||||||
device::{Device, DeviceOwned},
|
device::{Device, DeviceOwned},
|
||||||
macros::{vulkan_bitflags, vulkan_bitflags_enum},
|
macros::{vulkan_bitflags, vulkan_bitflags_enum},
|
||||||
memory::MemoryPropertyFlags,
|
memory::{is_aligned, MemoryPropertyFlags},
|
||||||
DeviceSize, OomError, RequirementNotMet, RequiresOneOf, Version, VulkanError, VulkanObject,
|
DeviceSize, OomError, RequirementNotMet, RequiresOneOf, Version, VulkanError, VulkanObject,
|
||||||
};
|
};
|
||||||
use std::{
|
use std::{
|
||||||
@ -1188,7 +1188,7 @@ pub struct MappedDeviceMemory {
|
|||||||
pointer: *mut c_void, // points to `range.start`
|
pointer: *mut c_void, // points to `range.start`
|
||||||
range: Range<DeviceSize>,
|
range: Range<DeviceSize>,
|
||||||
|
|
||||||
atom_size: DeviceSize,
|
atom_size: DeviceAlignment,
|
||||||
coherent: bool,
|
coherent: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1249,8 +1249,8 @@ impl MappedDeviceMemory {
|
|||||||
// parts of the mapped memory at the start and end that they're not able to
|
// parts of the mapped memory at the start and end that they're not able to
|
||||||
// invalidate/flush, which is probably unintended.
|
// invalidate/flush, which is probably unintended.
|
||||||
if !coherent
|
if !coherent
|
||||||
&& (range.start % atom_size != 0
|
&& (!is_aligned(range.start, atom_size)
|
||||||
|| (range.end % atom_size != 0 && range.end != memory.allocation_size))
|
|| (!is_aligned(range.end, atom_size) && range.end != memory.allocation_size))
|
||||||
{
|
{
|
||||||
return Err(MemoryMapError::RangeNotAlignedToAtomSize { range, atom_size });
|
return Err(MemoryMapError::RangeNotAlignedToAtomSize { range, atom_size });
|
||||||
}
|
}
|
||||||
@ -1275,7 +1275,6 @@ impl MappedDeviceMemory {
|
|||||||
memory,
|
memory,
|
||||||
pointer,
|
pointer,
|
||||||
range,
|
range,
|
||||||
|
|
||||||
atom_size,
|
atom_size,
|
||||||
coherent,
|
coherent,
|
||||||
})
|
})
|
||||||
@ -1460,8 +1459,9 @@ impl MappedDeviceMemory {
|
|||||||
if !self.coherent {
|
if !self.coherent {
|
||||||
// VUID-VkMappedMemoryRange-offset-00687
|
// VUID-VkMappedMemoryRange-offset-00687
|
||||||
// VUID-VkMappedMemoryRange-size-01390
|
// VUID-VkMappedMemoryRange-size-01390
|
||||||
if range.start % self.atom_size != 0
|
if !is_aligned(range.start, self.atom_size)
|
||||||
|| (range.end % self.atom_size != 0 && range.end != self.memory.allocation_size)
|
|| (!is_aligned(range.end, self.atom_size)
|
||||||
|
&& range.end != self.memory.allocation_size)
|
||||||
{
|
{
|
||||||
return Err(MemoryMapError::RangeNotAlignedToAtomSize {
|
return Err(MemoryMapError::RangeNotAlignedToAtomSize {
|
||||||
range,
|
range,
|
||||||
@ -1521,7 +1521,7 @@ pub enum MemoryMapError {
|
|||||||
/// property.
|
/// property.
|
||||||
RangeNotAlignedToAtomSize {
|
RangeNotAlignedToAtomSize {
|
||||||
range: Range<DeviceSize>,
|
range: Range<DeviceSize>,
|
||||||
atom_size: DeviceSize,
|
atom_size: DeviceAlignment,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1554,7 +1554,7 @@ impl Display for MemoryMapError {
|
|||||||
Self::RangeNotAlignedToAtomSize { range, atom_size } => write!(
|
Self::RangeNotAlignedToAtomSize { range, atom_size } => write!(
|
||||||
f,
|
f,
|
||||||
"the memory is not host-coherent, and the specified `range` bounds ({:?}) are not \
|
"the memory is not host-coherent, and the specified `range` bounds ({:?}) are not \
|
||||||
a multiple of the `non_coherent_atom_size` device property ({})",
|
a multiple of the `non_coherent_atom_size` device property ({:?})",
|
||||||
range, atom_size,
|
range, atom_size,
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
|
@ -91,7 +91,8 @@
|
|||||||
//! get memory from that pool. By default if you don't specify any pool when creating a buffer or
|
//! get memory from that pool. By default if you don't specify any pool when creating a buffer or
|
||||||
//! an image, an instance of `StandardMemoryPool` that is shared by the `Device` object is used.
|
//! an image, an instance of `StandardMemoryPool` that is shared by the `Device` object is used.
|
||||||
|
|
||||||
use self::allocator::{DeviceAlignment, DeviceLayout};
|
pub use self::alignment::DeviceAlignment;
|
||||||
|
use self::allocator::DeviceLayout;
|
||||||
pub use self::device_memory::{
|
pub use self::device_memory::{
|
||||||
DeviceMemory, DeviceMemoryError, ExternalMemoryHandleType, ExternalMemoryHandleTypes,
|
DeviceMemory, DeviceMemoryError, ExternalMemoryHandleType, ExternalMemoryHandleTypes,
|
||||||
MappedDeviceMemory, MemoryAllocateFlags, MemoryAllocateInfo, MemoryImportInfo, MemoryMapError,
|
MappedDeviceMemory, MemoryAllocateFlags, MemoryAllocateInfo, MemoryImportInfo, MemoryMapError,
|
||||||
@ -109,6 +110,7 @@ use std::{
|
|||||||
sync::Arc,
|
sync::Arc,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
mod alignment;
|
||||||
pub mod allocator;
|
pub mod allocator;
|
||||||
mod device_memory;
|
mod device_memory;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user