Skip to content

Commit dae232e

Browse files
authored
Migrate core gpu-allocator crate and basic examples to windows-rs (#107)
As has long been planned and discussed we'd like to get rid of the ancient and barely maintained `winapi` crate, in favour of something more modern: `windows-rs` is actively developed and maintained by Microsoft themselves, and generated out of header metadata rather than written by hand. Besides, it provides a more sophisticated and safer API for dealing with objects (abstracting away return types behind `Result`, hiding COM lifetime management, etc). The choice for the "heavier" `windows` crate over `windows-sys` is fairly obvious: DirectX APIs are built on the COM object model which is completely unsupported in `windows-sys` making us unable to perform any method calls. Besides, the `windows-sys` crate does very little to make the API more convenient nor safer to use, effectively taking us a step back from `winapi` instead of a step forward.
1 parent 5394d52 commit dae232e

9 files changed

Lines changed: 306 additions & 278 deletions

File tree

Cargo.toml

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,21 @@ ash = { version = ">=0.34, <=0.37", optional = true, default-features = false, f
2929
imgui = { version = "0.8", optional = true }
3030

3131
[target.'cfg(windows)'.dependencies]
32-
# Only needed for d3d12.
32+
# Only needed for public-winapi interop helpers
3333
winapi = { version = "0.3.9", features = ["d3d12", "winerror", "impl-default", "impl-debug"], optional = true }
3434

35+
[target.'cfg(windows)'.dependencies.windows]
36+
version = "0.36"
37+
features = [
38+
"Win32_Foundation",
39+
"Win32_Graphics",
40+
"Win32_Graphics_Direct3D",
41+
"Win32_Graphics_Direct3D12",
42+
"Win32_Graphics_Dxgi",
43+
"Win32_Graphics_Dxgi_Common",
44+
]
45+
optional = true
46+
3547
[dev-dependencies]
3648
# Enable the "loaded" feature to be able to access the Vulkan entrypoint.
3749
ash = { version = "0.37", default-features = false, features = ["debug", "loaded"] }
@@ -44,7 +56,7 @@ imgui-winit-support = { version = "0.8", default-features = false, features = ["
4456
winapi = { version = "0.3.9", features = ["d3d12", "d3d12sdklayers", "dxgi1_6", "winerror", "impl-default", "impl-debug", "winuser", "windowsx", "libloaderapi"] }
4557

4658
[target.'cfg(windows)'.dev-dependencies.windows]
47-
version = "0.29"
59+
version = "0.36"
4860
features = [
4961
"Win32_Foundation",
5062
"Win32_Graphics",
@@ -78,7 +90,8 @@ required-features = ["d3d12", "public-winapi", "visualizer"]
7890
[features]
7991
visualizer = ["imgui"]
8092
vulkan = ["ash"]
81-
d3d12 = ["winapi"]
82-
public-winapi = ["winapi"]
93+
d3d12 = ["windows"]
94+
# Expose helper functionality for winapi types to interface with gpu-allocator, which is primarily windows-rs driven
95+
public-winapi = ["dep:winapi"]
8396

84-
default = ["d3d12", "vulkan", "public-winapi"]
97+
default = ["d3d12", "vulkan"]

README.md

Lines changed: 20 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,13 @@ gpu-allocator = "0.17.0"
1717

1818
This crate provides a fully written in Rust memory allocator for Vulkan and DirectX 12.
1919

20+
### [Windows-rs] and [winapi]
21+
22+
`gpu-allocator` recently migrated from [winapi] to [windows-rs] but still provides convenient helpers to convert to and from [winapi] types, enabled when compiling with the `public-winapi` crate feature.
23+
24+
[Windows-rs]: https://github.com/microsoft/windows-rs
25+
[winapi]: https://github.com/retep998/winapi-rs
26+
2027
### Setting up the Vulkan memory allocator
2128

2229
```rust
@@ -80,20 +87,20 @@ use gpu_allocator::d3d12::*;
8087
use gpu_allocator::MemoryLocation;
8188

8289

83-
let buffer_desc = d3d12::D3D12_RESOURCE_DESC {
84-
Dimension: d3d12::D3D12_RESOURCE_DIMENSION_BUFFER,
90+
let buffer_desc = Direct3D12::D3D12_RESOURCE_DESC {
91+
Dimension: Direct3D12::D3D12_RESOURCE_DIMENSION_BUFFER,
8592
Alignment: 0,
8693
Width: 512,
8794
Height: 1,
8895
DepthOrArraySize: 1,
8996
MipLevels: 1,
90-
Format: dxgiformat::DXGI_FORMAT_UNKNOWN,
91-
SampleDesc: dxgitype::DXGI_SAMPLE_DESC {
97+
Format: Dxgi::Common::DXGI_FORMAT_UNKNOWN,
98+
SampleDesc: Dxgi::Common::DXGI_SAMPLE_DESC {
9299
Count: 1,
93100
Quality: 0,
94101
},
95-
Layout: d3d12::D3D12_TEXTURE_LAYOUT_ROW_MAJOR,
96-
Flags: d3d12::D3D12_RESOURCE_FLAG_NONE,
102+
Layout: Direct3D12::D3D12_TEXTURE_LAYOUT_ROW_MAJOR,
103+
Flags: Direct3D12::D3D12_RESOURCE_FLAG_NONE,
97104
};
98105
let allocation_desc = AllocationCreateDesc::from_d3d12_resource_desc(
99106
&allocator.device(),
@@ -102,24 +109,20 @@ let allocation_desc = AllocationCreateDesc::from_d3d12_resource_desc(
102109
MemoryLocation::GpuOnly,
103110
);
104111
let allocation = allocator.allocate(&allocation_desc).unwrap();
105-
let mut resource: *mut d3d12::ID3D12Resource = std::ptr::null_mut();
112+
let mut resource: Option<Direct3D12::ID3D12Resource> = None;
106113
let hr = unsafe {
107-
device.as_ref().unwrap().CreatePlacedResource(
108-
allocation.heap().as_winapi_mut(),
114+
device.CreatePlacedResource(
115+
allocation.heap(),
109116
allocation.offset(),
110117
&buffer_desc,
111-
d3d12::D3D12_RESOURCE_STATE_COMMON,
118+
Direct3D12::D3D12_RESOURCE_STATE_COMMON,
112119
std::ptr::null(),
113-
&d3d12::IID_ID3D12Resource,
114-
&mut resource as *mut _ as *mut _,
120+
&mut resource,
115121
)
116-
};
117-
if hr != winerror::S_OK {
118-
panic!("Failed to create placed resource.");
119-
}
122+
}?;
120123

121124
// Cleanup
122-
unsafe { resource.as_ref().unwrap().Release() };
125+
drop(resource);
123126
allocator.free(allocation).unwrap();
124127
```
125128

examples/d3d12-buffer-winrs.rs

Lines changed: 11 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1+
//! Example showcasing [`gpu-allocator`] with types and functions from the [`windows`] crate.
12
use gpu_allocator::d3d12::{
2-
AllocationCreateDesc, Allocator, AllocatorCreateDesc, Dx12DevicePtr, ResourceCategory,
3+
AllocationCreateDesc, Allocator, AllocatorCreateDesc, ResourceCategory,
34
};
45
use gpu_allocator::MemoryLocation;
56
use log::error;
@@ -9,7 +10,7 @@ use windows::Win32::{
910
Graphics::{
1011
Direct3D::{D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_11_1, D3D_FEATURE_LEVEL_12_0},
1112
Direct3D12::{
12-
D3D12CreateDevice, ID3D12Device, ID3D12Heap, ID3D12Resource,
13+
D3D12CreateDevice, ID3D12Device, ID3D12Resource,
1314
D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT, D3D12_RESOURCE_DESC,
1415
D3D12_RESOURCE_DIMENSION_BUFFER, D3D12_RESOURCE_FLAG_NONE, D3D12_RESOURCE_STATE_COMMON,
1516
D3D12_TEXTURE_LAYOUT_ROW_MAJOR,
@@ -82,11 +83,9 @@ fn main() -> Result<()> {
8283

8384
let device = create_d3d12_device(&dxgi_factory).expect("Failed to create D3D12 device.");
8485

85-
let device_ptr: Dx12DevicePtr = unsafe { std::mem::transmute_copy(&device) };
86-
8786
// Setting up the allocator
8887
let mut allocator = Allocator::new(&AllocatorCreateDesc {
89-
device: device_ptr,
88+
device: device.clone(),
9089
debug_settings: Default::default(),
9190
})
9291
.unwrap();
@@ -110,19 +109,17 @@ fn main() -> Result<()> {
110109
};
111110

112111
let allocation_desc = AllocationCreateDesc::from_d3d12_resource_desc(
113-
&allocator.device(),
114-
// Raw structs are binary-compatible
115-
unsafe { std::mem::transmute(&test_buffer_desc) },
112+
allocator.device(),
113+
&test_buffer_desc,
116114
"Test allocation (Gpu only)",
117115
MemoryLocation::GpuOnly,
118116
);
119117
let allocation = allocator.allocate(&allocation_desc).unwrap();
120118

121119
let mut resource: Option<ID3D12Resource> = None;
122-
let heap: &ID3D12Heap = unsafe { std::mem::transmute(&allocation.heap()) };
123120
unsafe {
124121
device.CreatePlacedResource(
125-
heap,
122+
allocation.heap(),
126123
allocation.offset(),
127124
&test_buffer_desc,
128125
D3D12_RESOURCE_STATE_COMMON,
@@ -155,7 +152,7 @@ fn main() -> Result<()> {
155152
Flags: D3D12_RESOURCE_FLAG_NONE,
156153
};
157154

158-
let alloc_info = unsafe { device.GetResourceAllocationInfo(0, 1, &test_buffer_desc) };
155+
let alloc_info = unsafe { device.GetResourceAllocationInfo(0, &[test_buffer_desc]) };
159156

160157
let allocation = allocator
161158
.allocate(&AllocationCreateDesc {
@@ -168,10 +165,9 @@ fn main() -> Result<()> {
168165
.unwrap();
169166

170167
let mut resource: Option<ID3D12Resource> = None;
171-
let heap: &ID3D12Heap = unsafe { std::mem::transmute(&allocation.heap()) };
172168
unsafe {
173169
device.CreatePlacedResource(
174-
heap,
170+
allocation.heap(),
175171
allocation.offset(),
176172
&test_buffer_desc,
177173
D3D12_RESOURCE_STATE_COMMON,
@@ -204,7 +200,7 @@ fn main() -> Result<()> {
204200
Flags: D3D12_RESOURCE_FLAG_NONE,
205201
};
206202

207-
let alloc_info = unsafe { device.GetResourceAllocationInfo(0, 1, &test_buffer_desc) };
203+
let alloc_info = unsafe { device.GetResourceAllocationInfo(0, &[test_buffer_desc]) };
208204

209205
let allocation = allocator
210206
.allocate(&AllocationCreateDesc {
@@ -217,10 +213,9 @@ fn main() -> Result<()> {
217213
.unwrap();
218214

219215
let mut resource: Option<ID3D12Resource> = None;
220-
let heap: &ID3D12Heap = unsafe { std::mem::transmute(&allocation.heap()) };
221216
unsafe {
222217
device.CreatePlacedResource(
223-
heap,
218+
allocation.heap(),
224219
allocation.offset(),
225220
&test_buffer_desc,
226221
D3D12_RESOURCE_STATE_COMMON,
@@ -235,7 +230,5 @@ fn main() -> Result<()> {
235230
println!("Allocation and deallocation of CpuToGpu memory was successful.");
236231
}
237232

238-
drop(allocator); // Explicitly drop before destruction of device.
239-
240233
Ok(())
241234
}

examples/d3d12-buffer.rs

Lines changed: 20 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
//! Example showcasing [`winapi`] interop with [`gpu-allocator`] which is driven by the [`windows`] crate.
12
use winapi::shared::{dxgiformat, winerror};
23
use winapi::um::{d3d12, d3dcommon};
34
use winapi::Interface;
@@ -9,8 +10,7 @@ mod all_dxgi {
910
use log::*;
1011

1112
use gpu_allocator::d3d12::{
12-
AbstractWinapiPtr, AllocationCreateDesc, Allocator, AllocatorCreateDesc, Dx12DevicePtr,
13-
ResourceCategory,
13+
AllocationCreateDesc, Allocator, AllocatorCreateDesc, ResourceCategory, ToWinapi, ToWindows,
1414
};
1515
use gpu_allocator::MemoryLocation;
1616

@@ -68,7 +68,7 @@ fn create_d3d12_device(
6868
};
6969
match hr {
7070
winapi::shared::winerror::S_OK => {
71-
info!("Using D3D12 feature level: {}.", feature_level_name);
71+
println!("Using D3D12 feature level: {}.", feature_level_name);
7272
Some(device)
7373
}
7474
winapi::shared::winerror::E_NOINTERFACE => {
@@ -115,11 +115,13 @@ fn main() {
115115

116116
// Setting up the allocator
117117
let mut allocator = Allocator::new(&AllocatorCreateDesc {
118-
device: Dx12DevicePtr(device.cast()),
118+
device: device.as_windows().clone(),
119119
debug_settings: Default::default(),
120120
})
121121
.unwrap();
122122

123+
let device = unsafe { device.as_ref() }.unwrap();
124+
123125
// Test allocating Gpu Only memory
124126
{
125127
let test_buffer_desc = d3d12::D3D12_RESOURCE_DESC {
@@ -138,8 +140,8 @@ fn main() {
138140
Flags: d3d12::D3D12_RESOURCE_FLAG_NONE,
139141
};
140142

141-
let allocation_desc = AllocationCreateDesc::from_d3d12_resource_desc(
142-
&allocator.device(),
143+
let allocation_desc = AllocationCreateDesc::from_winapi_d3d12_resource_desc(
144+
device,
143145
&test_buffer_desc,
144146
"Test allocation (Gpu Only)",
145147
MemoryLocation::GpuOnly,
@@ -148,8 +150,8 @@ fn main() {
148150

149151
let mut resource: *mut d3d12::ID3D12Resource = std::ptr::null_mut();
150152
let hr = unsafe {
151-
device.as_ref().unwrap().CreatePlacedResource(
152-
allocation.heap().as_winapi_mut(),
153+
device.CreatePlacedResource(
154+
allocation.heap().as_winapi() as *mut _,
153155
allocation.offset(),
154156
&test_buffer_desc,
155157
d3d12::D3D12_RESOURCE_STATE_COMMON,
@@ -165,7 +167,7 @@ fn main() {
165167
unsafe { resource.as_ref().unwrap().Release() };
166168

167169
allocator.free(allocation).unwrap();
168-
info!("Allocation and deallocation of GpuOnly memory was successful.");
170+
println!("Allocation and deallocation of GpuOnly memory was successful.");
169171
}
170172

171173
// Test allocating Cpu to Gpu memory
@@ -186,12 +188,7 @@ fn main() {
186188
Flags: d3d12::D3D12_RESOURCE_FLAG_NONE,
187189
};
188190

189-
let alloc_info = unsafe {
190-
device
191-
.as_ref()
192-
.unwrap()
193-
.GetResourceAllocationInfo(0, 1, &test_buffer_desc)
194-
};
191+
let alloc_info = unsafe { device.GetResourceAllocationInfo(0, 1, &test_buffer_desc) };
195192

196193
let allocation = allocator
197194
.allocate(&AllocationCreateDesc {
@@ -205,8 +202,8 @@ fn main() {
205202

206203
let mut resource: *mut d3d12::ID3D12Resource = std::ptr::null_mut();
207204
let hr = unsafe {
208-
device.as_ref().unwrap().CreatePlacedResource(
209-
allocation.heap().as_winapi_mut(),
205+
device.CreatePlacedResource(
206+
allocation.heap().as_winapi() as *mut _,
210207
allocation.offset(),
211208
&test_buffer_desc,
212209
d3d12::D3D12_RESOURCE_STATE_COMMON,
@@ -222,7 +219,7 @@ fn main() {
222219
unsafe { resource.as_ref().unwrap().Release() };
223220

224221
allocator.free(allocation).unwrap();
225-
info!("Allocation and deallocation of CpuToGpu memory was successful.");
222+
println!("Allocation and deallocation of CpuToGpu memory was successful.");
226223
}
227224

228225
// Test allocating Gpu to Cpu memory
@@ -243,12 +240,7 @@ fn main() {
243240
Flags: d3d12::D3D12_RESOURCE_FLAG_NONE,
244241
};
245242

246-
let alloc_info = unsafe {
247-
device
248-
.as_ref()
249-
.unwrap()
250-
.GetResourceAllocationInfo(0, 1, &test_buffer_desc)
251-
};
243+
let alloc_info = unsafe { device.GetResourceAllocationInfo(0, 1, &test_buffer_desc) };
252244

253245
let allocation = allocator
254246
.allocate(&AllocationCreateDesc {
@@ -262,8 +254,8 @@ fn main() {
262254

263255
let mut resource: *mut d3d12::ID3D12Resource = std::ptr::null_mut();
264256
let hr = unsafe {
265-
device.as_ref().unwrap().CreatePlacedResource(
266-
allocation.heap().as_winapi_mut(),
257+
device.CreatePlacedResource(
258+
allocation.heap().as_winapi() as *mut _,
267259
allocation.offset(),
268260
&test_buffer_desc,
269261
d3d12::D3D12_RESOURCE_STATE_COMMON,
@@ -279,10 +271,10 @@ fn main() {
279271
unsafe { resource.as_ref().unwrap().Release() };
280272

281273
allocator.free(allocation).unwrap();
282-
info!("Allocation and deallocation of CpuToGpu memory was successful.");
274+
println!("Allocation and deallocation of CpuToGpu memory was successful.");
283275
}
284276

285277
drop(allocator); // Explicitly drop before destruction of device.
286-
unsafe { device.as_ref().unwrap().Release() };
278+
unsafe { device.Release() };
287279
unsafe { dxgi_factory.as_ref().unwrap().Release() };
288280
}

0 commit comments

Comments
 (0)