Skip to content

Commit

Permalink
Configurable allocation sizes (#161)
Browse files Browse the repository at this point in the history
This adds an AllocationSizes struct to both the Vulkan and DX12 Allocator and AllocatorCreateDesc which allows users to configure the size of the memory blocks that are created to be suballocated from.

This doesn't currently clamp it to 256MB, which afaik is a problem for systems that don't support Resizable BAR, but I also don't know how to properly detect if someone is or isn't using Resizable BAR.

I also don't know if we need to enforce alignment, and if so what values do we need to use for alignment?

Commits:
* add AllocationSizes struct
* memblock_size 4MB alignment and clamp between 4MB and 256MB
* readme
  • Loading branch information
Elabajaba committed May 12, 2023
1 parent 614f915 commit 23d9704
Show file tree
Hide file tree
Showing 9 changed files with 85 additions and 12 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ let mut allocator = Allocator::new(&AllocatorCreateDesc {
physical_device,
debug_settings: Default::default(),
buffer_device_address: true, // Ideally, check the BufferDeviceAddressFeatures struct.
allocation_sizes: Default::default(),
});
```

Expand Down Expand Up @@ -78,6 +79,7 @@ use gpu_allocator::d3d12::*;
let mut allocator = Allocator::new(&AllocatorCreateDesc {
device,
debug_settings: Default::default(),
allocation_sizes: Default::default(),
});
```

Expand Down
1 change: 1 addition & 0 deletions examples/d3d12-buffer-winrs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ fn main() -> Result<()> {
let mut allocator = Allocator::new(&AllocatorCreateDesc {
device: device.clone(),
debug_settings: Default::default(),
allocation_sizes: Default::default(),
})
.unwrap();

Expand Down
1 change: 1 addition & 0 deletions examples/d3d12-buffer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ fn main() {
let mut allocator = Allocator::new(&AllocatorCreateDesc {
device: device.as_windows().clone(),
debug_settings: Default::default(),
allocation_sizes: Default::default(),
})
.unwrap();

Expand Down
1 change: 1 addition & 0 deletions examples/d3d12-visualization/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -358,6 +358,7 @@ fn main() {
let mut allocator = Allocator::new(&AllocatorCreateDesc {
device: device.as_windows().clone(),
debug_settings: Default::default(),
allocation_sizes: Default::default(),
})
.unwrap();

Expand Down
1 change: 1 addition & 0 deletions examples/vulkan-buffer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ fn main() {
physical_device: pdevice,
debug_settings: Default::default(),
buffer_device_address: false,
allocation_sizes: Default::default(),
})
.unwrap();

Expand Down
1 change: 1 addition & 0 deletions examples/vulkan-visualization/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,7 @@ fn main() -> ash::prelude::VkResult<()> {
physical_device: pdevice,
debug_settings: Default::default(),
buffer_device_address: false,
allocation_sizes: Default::default(),
})
.unwrap(),
);
Expand Down
15 changes: 9 additions & 6 deletions src/d3d12/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,8 @@ use super::allocator;
use super::allocator::AllocationType;

use crate::{
allocator::fmt_bytes, AllocationError, AllocatorDebugSettings, MemoryLocation, Result,
allocator::fmt_bytes, AllocationError, AllocationSizes, AllocatorDebugSettings, MemoryLocation,
Result,
};

/// [`ResourceCategory`] is used for supporting [`D3D12_RESOURCE_HEAP_TIER_1`].
Expand Down Expand Up @@ -231,6 +232,7 @@ impl<'a> AllocationCreateDesc<'a> {
pub struct AllocatorCreateDesc {
pub device: ID3D12Device,
pub debug_settings: AllocatorDebugSettings,
pub allocation_sizes: AllocationSizes,
}

pub enum ResourceType<'a> {
Expand Down Expand Up @@ -386,21 +388,20 @@ struct MemoryType {
active_general_blocks: usize,
}

const DEFAULT_DEVICE_MEMBLOCK_SIZE: u64 = 256 * 1024 * 1024;
const DEFAULT_HOST_MEMBLOCK_SIZE: u64 = 64 * 1024 * 1024;
impl MemoryType {
fn allocate(
&mut self,
device: &ID3D12Device,
desc: &AllocationCreateDesc<'_>,
backtrace: Option<backtrace::Backtrace>,
allocation_sizes: &AllocationSizes,
) -> Result<Allocation> {
let allocation_type = AllocationType::Linear;

let memblock_size = if self.heap_properties.Type == D3D12_HEAP_TYPE_DEFAULT {
DEFAULT_DEVICE_MEMBLOCK_SIZE
allocation_sizes.device_memblock_size
} else {
DEFAULT_HOST_MEMBLOCK_SIZE
allocation_sizes.host_memblock_size
};

let size = desc.size;
Expand Down Expand Up @@ -573,6 +574,7 @@ pub struct Allocator {
device: ID3D12Device,
debug_settings: AllocatorDebugSettings,
memory_types: Vec<MemoryType>,
allocation_sizes: AllocationSizes,
}

impl Allocator {
Expand Down Expand Up @@ -679,6 +681,7 @@ impl Allocator {
memory_types,
device,
debug_settings: desc.debug_settings,
allocation_sizes: desc.allocation_sizes,
})
}

Expand Down Expand Up @@ -722,7 +725,7 @@ impl Allocator {
})
.ok_or(AllocationError::NoCompatibleMemoryTypeFound)?;

memory_type.allocate(&self.device, desc, backtrace)
memory_type.allocate(&self.device, desc, backtrace, &self.allocation_sizes)
}

pub fn free(&mut self, allocation: Allocation) -> Result<()> {
Expand Down
59 changes: 59 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
//! physical_device,
//! debug_settings: Default::default(),
//! buffer_device_address: true, // Ideally, check the BufferDeviceAddressFeatures struct.
//! allocation_sizes: Default::default(),
//! });
//! # }
//! # #[cfg(not(feature = "vulkan"))]
Expand All @@ -48,6 +49,7 @@
//! # physical_device,
//! # debug_settings: Default::default(),
//! # buffer_device_address: true, // Ideally, check the BufferDeviceAddressFeatures struct.
//! # allocation_sizes: Default::default(),
//! # }).unwrap();
//!
//! // Setup vulkan info
Expand Down Expand Up @@ -89,6 +91,7 @@
//! let mut allocator = Allocator::new(&AllocatorCreateDesc {
//! device,
//! debug_settings: Default::default(),
//! allocation_sizes: Default::default(),
//! });
//! # }
//! # #[cfg(not(feature = "d3d12"))]
Expand All @@ -108,6 +111,7 @@
//! # let mut allocator = Allocator::new(&AllocatorCreateDesc {
//! # device: device,
//! # debug_settings: Default::default(),
//! # allocation_sizes: Default::default(),
//! # }).unwrap();
//!
//! let buffer_desc = Direct3D12::D3D12_RESOURCE_DESC {
Expand Down Expand Up @@ -210,3 +214,58 @@ impl Default for AllocatorDebugSettings {
}
}
}

/// The sizes of the memory blocks that the allocator will create.
///
/// Useful for tuning the allocator to your application's needs. For example most games will be fine with the default
/// values, but eg. an app might want to use smaller block sizes to reduce the amount of memory used.
///
/// Clamped between 4MB and 256MB, and rounds up to the nearest multiple of 4MB for alignment reasons.
#[derive(Clone, Copy, Debug)]
pub struct AllocationSizes {
/// The size of the memory blocks that will be created for the GPU only memory type.
///
/// Defaults to 256MB.
device_memblock_size: u64,
/// The size of the memory blocks that will be created for the CPU visible memory types.
///
/// Defaults to 64MB.
host_memblock_size: u64,
}

impl AllocationSizes {
pub fn new(device_memblock_size: u64, host_memblock_size: u64) -> Self {
const FOUR_MB: u64 = 4 * 1024 * 1024;
const TWO_HUNDRED_AND_FIFTY_SIX_MB: u64 = 256 * 1024 * 1024;

let mut device_memblock_size =
device_memblock_size.clamp(FOUR_MB, TWO_HUNDRED_AND_FIFTY_SIX_MB);
let mut host_memblock_size = host_memblock_size.clamp(FOUR_MB, TWO_HUNDRED_AND_FIFTY_SIX_MB);

if device_memblock_size % FOUR_MB != 0 {
let val = device_memblock_size / FOUR_MB + 1;
device_memblock_size = val * FOUR_MB;
log::warn!("Device memory block size must be a multiple of 4MB, clamping to {}MB", device_memblock_size / 1024 / 1024)
}

if host_memblock_size % FOUR_MB != 0 {
let val = host_memblock_size / FOUR_MB + 1;
host_memblock_size = val * FOUR_MB;
log::warn!("Host memory block size must be a multiple of 4MB, clamping to {}MB", host_memblock_size / 1024 / 1024)
}

Self {
device_memblock_size,
host_memblock_size,
}
}
}

impl Default for AllocationSizes {
fn default() -> Self {
Self {
device_memblock_size: 256 * 1024 * 1024,
host_memblock_size: 64 * 1024 * 1024,
}
}
}
16 changes: 10 additions & 6 deletions src/vulkan/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ use log::{debug, Level};
use std::fmt;

use crate::{
allocator::fmt_bytes, AllocationError, AllocatorDebugSettings, MemoryLocation, Result,
allocator::fmt_bytes, AllocationError, AllocationSizes, AllocatorDebugSettings, MemoryLocation,
Result,
};

#[derive(Copy, Clone, Debug, Eq, PartialEq)]
Expand Down Expand Up @@ -61,6 +62,7 @@ pub struct AllocatorCreateDesc {
pub physical_device: ash::vk::PhysicalDevice,
pub debug_settings: AllocatorDebugSettings,
pub buffer_device_address: bool,
pub allocation_sizes: AllocationSizes,
}

/// A piece of allocated memory.
Expand Down Expand Up @@ -441,16 +443,14 @@ pub(crate) struct MemoryType {
pub(crate) buffer_device_address: bool,
}

const DEFAULT_DEVICE_MEMBLOCK_SIZE: u64 = 256 * 1024 * 1024;
const DEFAULT_HOST_MEMBLOCK_SIZE: u64 = 64 * 1024 * 1024;

impl MemoryType {
fn allocate(
&mut self,
device: &ash::Device,
desc: &AllocationCreateDesc<'_>,
granularity: u64,
backtrace: Option<backtrace::Backtrace>,
allocation_sizes: &AllocationSizes,
) -> Result<Allocation> {
let allocation_type = if desc.linear {
AllocationType::Linear
Expand All @@ -462,9 +462,9 @@ impl MemoryType {
.memory_properties
.contains(vk::MemoryPropertyFlags::HOST_VISIBLE)
{
DEFAULT_HOST_MEMBLOCK_SIZE
allocation_sizes.host_memblock_size
} else {
DEFAULT_DEVICE_MEMBLOCK_SIZE
allocation_sizes.device_memblock_size
};

let size = desc.requirements.size;
Expand Down Expand Up @@ -677,6 +677,7 @@ pub struct Allocator {
device: ash::Device,
pub(crate) buffer_image_granularity: u64,
pub(crate) debug_settings: AllocatorDebugSettings,
allocation_sizes: AllocationSizes,
}

impl fmt::Debug for Allocator {
Expand Down Expand Up @@ -793,6 +794,7 @@ impl Allocator {
device: desc.device.clone(),
buffer_image_granularity: granularity,
debug_settings: desc.debug_settings,
allocation_sizes: AllocationSizes::default(),
})
}

Expand Down Expand Up @@ -866,6 +868,7 @@ impl Allocator {
desc,
self.buffer_image_granularity,
backtrace.clone(),
&self.allocation_sizes,
)
};

Expand All @@ -887,6 +890,7 @@ impl Allocator {
desc,
self.buffer_image_granularity,
backtrace,
&self.allocation_sizes,
)
} else {
allocation
Expand Down

0 comments on commit 23d9704

Please sign in to comment.