Skip to content

Commit ea361fc

Browse files
authored
hal/vulkan: Replace gpu-alloc by gpu-allocator (#8158)
1 parent 2a19037 commit ea361fc

File tree

9 files changed

+301
-389
lines changed

9 files changed

+301
-389
lines changed

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,14 @@ Bottom level categories:
4343

4444
### Major Changes
4545

46+
#### Switch from `gpu-alloc` to `gpu-allocator` in the `vulkan` backend
47+
48+
`gpu-allocator` is the allocator used in the `dx12` backend, allowing to configure
49+
the allocator the same way in those two backends converging their behavior.
50+
51+
This also brings the `Device::generate_allocator_report` feature to
52+
the vulkan backend.
53+
4654
#### `wgpu::Instance::enumerate_adapters` is now `async` & available on WebGPU
4755

4856
BREAKING CHANGE: `enumerate_adapters` is now `async`:

Cargo.lock

Lines changed: 1 addition & 20 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -208,17 +208,18 @@ objc = "0.2.5"
208208
# Vulkan dependencies
209209
android_system_properties = "0.1.1"
210210
ash = "0.38"
211-
gpu-alloc = "0.6"
212211
gpu-descriptor = "0.3.2"
213212

214213
# DX12 dependencies
215-
gpu-allocator = { version = "0.28", default-features = false, features = [
216-
"hashbrown",
217-
] }
218214
range-alloc = "0.1"
219215
mach-dxcompiler-rs = { version = "0.1.4", default-features = false } # remember to increase max_shader_model if applicable
220216
windows-core = { version = "0.62", default-features = false }
221217

218+
# DX12 and Vulkan dependencies
219+
gpu-allocator = { version = "0.28", default-features = false, features = [
220+
"hashbrown",
221+
] }
222+
222223
# Gles dependencies
223224
khronos-egl = "6"
224225
glow = "0.16"

wgpu-hal/Cargo.toml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,6 @@ vulkan = [
9292
"dep:arrayvec",
9393
"dep:ash",
9494
"dep:bytemuck",
95-
"dep:gpu-alloc",
9695
"dep:gpu-descriptor",
9796
"dep:hashbrown",
9897
"dep:libc",
@@ -103,6 +102,7 @@ vulkan = [
103102
"dep:profiling",
104103
"dep:smallvec",
105104
"dep:windows",
105+
"gpu-allocator/vulkan",
106106
"windows/Win32",
107107
]
108108
gles = [
@@ -224,9 +224,10 @@ glow = { workspace = true, optional = true }
224224
########################
225225

226226
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
227+
# Backend: Vulkan and Dx12
228+
gpu-allocator = { workspace = true, optional = true }
227229
# Backend: Vulkan
228230
ash = { workspace = true, optional = true }
229-
gpu-alloc = { workspace = true, optional = true }
230231
gpu-descriptor = { workspace = true, optional = true }
231232
smallvec = { workspace = true, optional = true, features = ["union"] }
232233
# Backend: GLES
@@ -253,7 +254,6 @@ windows-core = { workspace = true, optional = true }
253254
# Backend: Dx12
254255
bit-set = { workspace = true, optional = true }
255256
range-alloc = { workspace = true, optional = true }
256-
gpu-allocator = { workspace = true, optional = true, features = ["d3d12"] }
257257
once_cell = { workspace = true, optional = true }
258258
# backend: GLES
259259
glutin_wgl_sys = { workspace = true, optional = true }

wgpu-hal/src/dx12/suballocation.rs

Lines changed: 5 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use windows::Win32::Graphics::{Direct3D12, Dxgi};
77
use crate::{
88
auxil::dxgi::{name::ObjectExt as _, result::HResult as _},
99
dx12::conv,
10+
AllocationSizes,
1011
};
1112

1213
#[derive(Debug)]
@@ -74,36 +75,14 @@ impl Allocator {
7475
memory_hints: &wgt::MemoryHints,
7576
memory_budget_thresholds: wgt::MemoryBudgetThresholds,
7677
) -> Result<Self, crate::DeviceError> {
77-
// TODO: the allocator's configuration should take hardware capability into
78-
// account.
79-
const MB: u64 = 1024 * 1024;
80-
let (device_memblock_size, host_memblock_size) = match memory_hints {
81-
wgt::MemoryHints::Performance => (256 * MB, 64 * MB),
82-
wgt::MemoryHints::MemoryUsage => (8 * MB, 4 * MB),
83-
wgt::MemoryHints::Manual {
84-
suballocated_device_memory_block_size,
85-
} => {
86-
// TODO: Would it be useful to expose the host size in memory hints
87-
// instead of always using half of the device size?
88-
let device_size = suballocated_device_memory_block_size.start;
89-
let host_size = device_size / 2;
90-
(device_size, host_size)
91-
}
92-
};
93-
94-
// gpu_allocator clamps the sizes between 4MiB and 256MiB, but we clamp them ourselves since we use
95-
// the sizes when detecting high memory pressure and there is no way to query the values otherwise.
96-
97-
let device_memblock_size = device_memblock_size.clamp(4 * MB, 256 * MB);
98-
let host_memblock_size = host_memblock_size.clamp(4 * MB, 256 * MB);
99-
100-
let allocation_sizes =
101-
gpu_allocator::AllocationSizes::new(device_memblock_size, host_memblock_size);
78+
let allocation_sizes = AllocationSizes::from_memory_hints(memory_hints);
79+
let device_memblock_size = allocation_sizes.min_device_memblock_size;
80+
let host_memblock_size = allocation_sizes.min_host_memblock_size;
10281

10382
let allocator_desc = gpu_allocator::d3d12::AllocatorCreateDesc {
10483
device: gpu_allocator::d3d12::ID3D12DeviceVersion::Device(raw.clone()),
10584
debug_settings: Default::default(),
106-
allocation_sizes,
85+
allocation_sizes: allocation_sizes.into(),
10786
};
10887

10988
let allocator = gpu_allocator::d3d12::Allocator::new(&allocator_desc).inspect_err(|e| {
@@ -622,37 +601,3 @@ impl<'a> DeviceAllocationContext<'a> {
622601
Ok(allocation_info)
623602
}
624603
}
625-
626-
impl From<gpu_allocator::AllocationError> for crate::DeviceError {
627-
fn from(result: gpu_allocator::AllocationError) -> Self {
628-
match result {
629-
gpu_allocator::AllocationError::OutOfMemory => Self::OutOfMemory,
630-
gpu_allocator::AllocationError::FailedToMap(e) => {
631-
log::error!("DX12 gpu-allocator: Failed to map: {e}");
632-
Self::Lost
633-
}
634-
gpu_allocator::AllocationError::NoCompatibleMemoryTypeFound => {
635-
log::error!("DX12 gpu-allocator: No Compatible Memory Type Found");
636-
Self::Lost
637-
}
638-
gpu_allocator::AllocationError::InvalidAllocationCreateDesc => {
639-
log::error!("DX12 gpu-allocator: Invalid Allocation Creation Description");
640-
Self::Lost
641-
}
642-
gpu_allocator::AllocationError::InvalidAllocatorCreateDesc(e) => {
643-
log::error!("DX12 gpu-allocator: Invalid Allocator Creation Description: {e}");
644-
Self::Lost
645-
}
646-
647-
gpu_allocator::AllocationError::Internal(e) => {
648-
log::error!("DX12 gpu-allocator: Internal Error: {e}");
649-
Self::Lost
650-
}
651-
gpu_allocator::AllocationError::BarrierLayoutNeedsDevice10
652-
| gpu_allocator::AllocationError::CastableFormatsRequiresEnhancedBarriers
653-
| gpu_allocator::AllocationError::CastableFormatsRequiresAtLeastDevice12 => {
654-
unreachable!()
655-
}
656-
}
657-
}
658-
}

wgpu-hal/src/lib.rs

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -381,6 +381,107 @@ pub enum DeviceError {
381381
Unexpected,
382382
}
383383

384+
#[cfg(any(dx12, vulkan))]
385+
impl From<gpu_allocator::AllocationError> for DeviceError {
386+
fn from(result: gpu_allocator::AllocationError) -> Self {
387+
match result {
388+
gpu_allocator::AllocationError::OutOfMemory => Self::OutOfMemory,
389+
gpu_allocator::AllocationError::FailedToMap(e) => {
390+
log::error!("gpu-allocator: Failed to map: {e}");
391+
Self::Lost
392+
}
393+
gpu_allocator::AllocationError::NoCompatibleMemoryTypeFound => {
394+
log::error!("gpu-allocator: No Compatible Memory Type Found");
395+
Self::Lost
396+
}
397+
gpu_allocator::AllocationError::InvalidAllocationCreateDesc => {
398+
log::error!("gpu-allocator: Invalid Allocation Creation Description");
399+
Self::Lost
400+
}
401+
gpu_allocator::AllocationError::InvalidAllocatorCreateDesc(e) => {
402+
log::error!("gpu-allocator: Invalid Allocator Creation Description: {e}");
403+
Self::Lost
404+
}
405+
406+
gpu_allocator::AllocationError::Internal(e) => {
407+
log::error!("gpu-allocator: Internal Error: {e}");
408+
Self::Lost
409+
}
410+
gpu_allocator::AllocationError::BarrierLayoutNeedsDevice10
411+
| gpu_allocator::AllocationError::CastableFormatsRequiresEnhancedBarriers
412+
| gpu_allocator::AllocationError::CastableFormatsRequiresAtLeastDevice12 => {
413+
unreachable!()
414+
}
415+
}
416+
}
417+
}
418+
419+
// A copy of gpu_allocator::AllocationSizes, allowing to read the configured value for
420+
// the dx12 backend, we should instead add getters to gpu_allocator::AllocationSizes
421+
// and remove this type.
422+
// https://github.com/Traverse-Research/gpu-allocator/issues/295
423+
#[cfg_attr(not(any(dx12, vulkan)), expect(dead_code))]
424+
pub(crate) struct AllocationSizes {
425+
pub(crate) min_device_memblock_size: u64,
426+
pub(crate) max_device_memblock_size: u64,
427+
pub(crate) min_host_memblock_size: u64,
428+
pub(crate) max_host_memblock_size: u64,
429+
}
430+
431+
impl AllocationSizes {
432+
#[allow(dead_code)] // may be unused on some platforms
433+
pub(crate) fn from_memory_hints(memory_hints: &wgt::MemoryHints) -> Self {
434+
// TODO: the allocator's configuration should take hardware capability into
435+
// account.
436+
const MB: u64 = 1024 * 1024;
437+
438+
match memory_hints {
439+
wgt::MemoryHints::Performance => Self {
440+
min_device_memblock_size: 128 * MB,
441+
max_device_memblock_size: 256 * MB,
442+
min_host_memblock_size: 64 * MB,
443+
max_host_memblock_size: 128 * MB,
444+
},
445+
wgt::MemoryHints::MemoryUsage => Self {
446+
min_device_memblock_size: 8 * MB,
447+
max_device_memblock_size: 64 * MB,
448+
min_host_memblock_size: 4 * MB,
449+
max_host_memblock_size: 32 * MB,
450+
},
451+
wgt::MemoryHints::Manual {
452+
suballocated_device_memory_block_size,
453+
} => {
454+
// TODO: https://github.com/gfx-rs/wgpu/issues/8625
455+
// Would it be useful to expose the host size in memory hints
456+
// instead of always using half of the device size?
457+
let device_size = suballocated_device_memory_block_size;
458+
let host_size = device_size.start / 2..device_size.end / 2;
459+
460+
// gpu_allocator clamps the sizes between 4MiB and 256MiB, but we clamp them ourselves since we use
461+
// the sizes when detecting high memory pressure and there is no way to query the values otherwise.
462+
Self {
463+
min_device_memblock_size: device_size.start.clamp(4 * MB, 256 * MB),
464+
max_device_memblock_size: device_size.end.clamp(4 * MB, 256 * MB),
465+
min_host_memblock_size: host_size.start.clamp(4 * MB, 256 * MB),
466+
max_host_memblock_size: host_size.end.clamp(4 * MB, 256 * MB),
467+
}
468+
}
469+
}
470+
}
471+
}
472+
473+
#[cfg(any(dx12, vulkan))]
474+
impl From<AllocationSizes> for gpu_allocator::AllocationSizes {
475+
fn from(value: AllocationSizes) -> gpu_allocator::AllocationSizes {
476+
gpu_allocator::AllocationSizes::new(
477+
value.min_device_memblock_size,
478+
value.min_host_memblock_size,
479+
)
480+
.with_max_device_memblock_size(value.max_device_memblock_size)
481+
.with_max_host_memblock_size(value.max_host_memblock_size)
482+
}
483+
}
484+
384485
#[allow(dead_code)] // may be unused on some platforms
385486
#[cold]
386487
fn hal_usage_error<T: fmt::Display>(txt: T) -> ! {

0 commit comments

Comments
 (0)