Skip to content

Commit f8fb4a4

Browse files
authored
Add Metal implementation (#199)
* Add skeleton for Metal Allocator * Implement allocating/freeing buffers and textures * Fetch size and align from metal device for buffer allocations * Implement allocating acceleration structures * Add function to get all metal heaps Use this function in `encoder.use_heaps(gpu_allocator.get_heaps())` * Fixes & clean up * Specify linear or non-linear allocation Similar to how the Vulkan implementation does it * Revert "Specify linear or non-linear allocation" I wasn't sure about this change, so I'm reverting it for now * Put metal behind feature toggle
1 parent 766b755 commit f8fb4a4

4 files changed

Lines changed: 605 additions & 0 deletions

File tree

Cargo.toml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@ ash = { version = ">=0.34, <=0.37", optional = true, default-features = false, f
3333
egui = { version = ">=0.24, <=0.26", optional = true, default-features = false }
3434
egui_extras = { version = ">=0.24, <=0.26", optional = true, default-features = false }
3535

36+
[target.'cfg(any(target_os = "macos", target_os = "ios"))'.dependencies]
37+
metal = { version = "0.27.0", default-features = false, features = ["link", "dispatch",] }
38+
3639
[target.'cfg(windows)'.dependencies]
3740
# Only needed for public-winapi interop helpers
3841
winapi = { version = "0.3.9", features = ["d3d12", "winerror", "impl-default", "impl-debug"], optional = true }
@@ -80,11 +83,19 @@ required-features = ["d3d12", "public-winapi"]
8083
name = "d3d12-buffer-winrs"
8184
required-features = ["d3d12"]
8285

86+
[[example]]
87+
name = "metal-buffer"
88+
required-features = ["metal"]
89+
8390
[features]
8491
visualizer = ["egui", "egui_extras"]
8592
vulkan = ["ash"]
8693
d3d12 = ["windows"]
94+
metal = []
8795
# Expose helper functionality for winapi types to interface with gpu-allocator, which is primarily windows-rs driven
8896
public-winapi = ["dep:winapi"]
8997

9098
default = ["d3d12", "vulkan"]
99+
100+
[patch.crates-io]
101+
metal = { git = "https://github.com/Traverse-Research/metal-rs", rev = "a354c33" }

examples/metal-buffer.rs

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
use std::sync::Arc;
2+
3+
use gpu_allocator::metal::{AllocationCreateDesc, Allocator, AllocatorCreateDesc};
4+
use log::info;
5+
6+
fn main() {
7+
env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("trace")).init();
8+
9+
let device = Arc::new(metal::Device::system_default().unwrap());
10+
11+
// Setting up the allocator
12+
let mut allocator = Allocator::new(&AllocatorCreateDesc {
13+
device: device.clone(),
14+
debug_settings: Default::default(),
15+
allocation_sizes: Default::default(),
16+
})
17+
.unwrap();
18+
19+
// Test allocating Gpu Only memory
20+
{
21+
let allocation_desc = AllocationCreateDesc::buffer(
22+
&device,
23+
"Test allocation (Gpu Only)",
24+
512,
25+
gpu_allocator::MemoryLocation::GpuOnly,
26+
);
27+
let allocation = allocator.allocate(&allocation_desc).unwrap();
28+
let _buffer = allocation.make_buffer().unwrap();
29+
allocator.free(&allocation).unwrap();
30+
info!("Allocation and deallocation of GpuOnly memory was successful.");
31+
}
32+
33+
// Test allocating Cpu to Gpu memory
34+
{
35+
let allocation_desc = AllocationCreateDesc::buffer(
36+
&device,
37+
"Test allocation (Cpu to Gpu)",
38+
512,
39+
gpu_allocator::MemoryLocation::CpuToGpu,
40+
);
41+
let allocation = allocator.allocate(&allocation_desc).unwrap();
42+
let _buffer = allocation.make_buffer().unwrap();
43+
allocator.free(&allocation).unwrap();
44+
info!("Allocation and deallocation of CpuToGpu memory was successful.");
45+
}
46+
47+
// Test allocating Gpu to Cpu memory
48+
{
49+
let allocation_desc = AllocationCreateDesc::buffer(
50+
&device,
51+
"Test allocation (Gpu to Cpu)",
52+
512,
53+
gpu_allocator::MemoryLocation::GpuToCpu,
54+
);
55+
let allocation = allocator.allocate(&allocation_desc).unwrap();
56+
let _buffer = allocation.make_buffer().unwrap();
57+
allocator.free(&allocation).unwrap();
58+
info!("Allocation and deallocation of GpuToCpu memory was successful.");
59+
}
60+
61+
// Test allocating texture
62+
{
63+
let texture_desc = metal::TextureDescriptor::new();
64+
texture_desc.set_pixel_format(metal::MTLPixelFormat::RGBA8Unorm);
65+
texture_desc.set_width(64);
66+
texture_desc.set_height(64);
67+
texture_desc.set_storage_mode(metal::MTLStorageMode::Private);
68+
let allocation_desc =
69+
AllocationCreateDesc::texture(&device, "Test allocation (Texture)", &texture_desc);
70+
let allocation = allocator.allocate(&allocation_desc).unwrap();
71+
let _texture = allocation.make_texture(&texture_desc).unwrap();
72+
allocator.free(&allocation).unwrap();
73+
info!("Allocation and deallocation of Texture was successful.");
74+
}
75+
76+
// Test allocating acceleration structure
77+
{
78+
let empty_array = metal::Array::from_slice(&[]);
79+
let acc_desc = metal::PrimitiveAccelerationStructureDescriptor::descriptor();
80+
acc_desc.set_geometry_descriptors(&empty_array);
81+
let sizes = device.acceleration_structure_sizes_with_descriptor(&acc_desc);
82+
let allocation_desc = AllocationCreateDesc::acceleration_structure_with_size(
83+
&device,
84+
"Test allocation (Acceleration structure)",
85+
sizes.acceleration_structure_size,
86+
gpu_allocator::MemoryLocation::GpuOnly,
87+
);
88+
let allocation = allocator.allocate(&allocation_desc).unwrap();
89+
let _acc_structure = allocation.make_acceleration_structure();
90+
allocator.free(&allocation).unwrap();
91+
info!("Allocation and deallocation of Acceleration structure was successful.");
92+
}
93+
}

src/lib.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,9 @@ pub mod vulkan;
170170
#[cfg(all(windows, feature = "d3d12"))]
171171
pub mod d3d12;
172172

173+
#[cfg(all(any(target_os = "macos", target_os = "ios"), feature = "metal"))]
174+
pub mod metal;
175+
173176
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
174177
pub enum MemoryLocation {
175178
/// The allocated resource is stored at an unknown memory location; let the driver decide what's the best location

0 commit comments

Comments
 (0)