283 lines
9.7 KiB
Rust
283 lines
9.7 KiB
Rust
//! Example showcasing [`winapi`] interop with [`gpu-allocator`] which is driven by the [`windows`] crate.
|
|
use winapi::{
|
|
shared::{dxgiformat, winerror},
|
|
um::{d3d12, d3dcommon},
|
|
Interface,
|
|
};
|
|
|
|
mod all_dxgi {
|
|
pub use winapi::shared::{dxgi1_3::*, dxgi1_6::*, dxgitype::*};
|
|
}
|
|
|
|
use gpu_allocator::{
|
|
d3d12::{
|
|
AllocationCreateDesc, Allocator, AllocatorCreateDesc, ID3D12DeviceVersion,
|
|
ResourceCategory, ToWinapi, ToWindows,
|
|
},
|
|
MemoryLocation,
|
|
};
|
|
use log::*;
|
|
|
|
fn create_d3d12_device(
|
|
dxgi_factory: *mut all_dxgi::IDXGIFactory6,
|
|
) -> Option<*mut d3d12::ID3D12Device> {
|
|
for idx in 0.. {
|
|
let mut adapter4: *mut all_dxgi::IDXGIAdapter4 = std::ptr::null_mut();
|
|
let hr = unsafe {
|
|
dxgi_factory.as_ref().unwrap().EnumAdapters1(
|
|
idx,
|
|
<*mut *mut all_dxgi::IDXGIAdapter4>::cast(&mut adapter4),
|
|
)
|
|
};
|
|
|
|
if hr == winerror::DXGI_ERROR_NOT_FOUND {
|
|
break;
|
|
}
|
|
|
|
assert_eq!(hr, winerror::S_OK);
|
|
|
|
let mut desc = all_dxgi::DXGI_ADAPTER_DESC3::default();
|
|
let hr = unsafe { adapter4.as_ref().unwrap().GetDesc3(&mut desc) };
|
|
if hr != winerror::S_OK {
|
|
error!("Failed to get adapter description for adapter");
|
|
continue;
|
|
}
|
|
|
|
// Skip software adapters
|
|
if (desc.Flags & all_dxgi::DXGI_ADAPTER_FLAG3_SOFTWARE)
|
|
== all_dxgi::DXGI_ADAPTER_FLAG3_SOFTWARE
|
|
{
|
|
continue;
|
|
}
|
|
|
|
let feature_levels = [
|
|
(d3dcommon::D3D_FEATURE_LEVEL_11_0, "D3D_FEATURE_LEVEL_11_0"),
|
|
(d3dcommon::D3D_FEATURE_LEVEL_11_1, "D3D_FEATURE_LEVEL_11_1"),
|
|
(d3dcommon::D3D_FEATURE_LEVEL_12_0, "D3D_FEATURE_LEVEL_12_0"),
|
|
];
|
|
|
|
let device =
|
|
feature_levels
|
|
.iter()
|
|
.rev()
|
|
.find_map(|&(feature_level, feature_level_name)| {
|
|
let mut device: *mut d3d12::ID3D12Device = std::ptr::null_mut();
|
|
let hr = unsafe {
|
|
d3d12::D3D12CreateDevice(
|
|
adapter4.cast(),
|
|
feature_level,
|
|
&d3d12::ID3D12Device::uuidof(),
|
|
<*mut *mut d3d12::ID3D12Device>::cast(&mut device),
|
|
)
|
|
};
|
|
match hr {
|
|
winerror::S_OK => {
|
|
info!("Using D3D12 feature level: {}.", feature_level_name);
|
|
Some(device)
|
|
}
|
|
winerror::E_NOINTERFACE => {
|
|
error!("ID3D12Device interface not supported.");
|
|
None
|
|
}
|
|
_ => {
|
|
info!(
|
|
"D3D12 feature level: {} not supported: {:x}",
|
|
feature_level_name, hr
|
|
);
|
|
None
|
|
}
|
|
}
|
|
});
|
|
if device.is_some() {
|
|
return device;
|
|
}
|
|
}
|
|
|
|
None
|
|
}
|
|
|
|
fn main() {
|
|
env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("trace")).init();
|
|
|
|
let dxgi_factory = {
|
|
let mut dxgi_factory: *mut all_dxgi::IDXGIFactory6 = std::ptr::null_mut();
|
|
let hr = unsafe {
|
|
all_dxgi::CreateDXGIFactory2(
|
|
0,
|
|
&all_dxgi::IID_IDXGIFactory6,
|
|
<*mut *mut all_dxgi::IDXGIFactory6>::cast(&mut dxgi_factory),
|
|
)
|
|
};
|
|
|
|
assert_eq!(hr, winerror::S_OK, "Failed to create DXGI factory");
|
|
dxgi_factory
|
|
};
|
|
|
|
let device = create_d3d12_device(dxgi_factory).expect("Failed to create D3D12 device.");
|
|
|
|
// Setting up the allocator
|
|
let mut allocator = Allocator::new(&AllocatorCreateDesc {
|
|
device: ID3D12DeviceVersion::Device(device.as_windows().clone()),
|
|
debug_settings: Default::default(),
|
|
allocation_sizes: Default::default(),
|
|
})
|
|
.unwrap();
|
|
|
|
let device = unsafe { device.as_ref() }.unwrap();
|
|
|
|
// Test allocating Gpu Only memory
|
|
{
|
|
let test_buffer_desc = d3d12::D3D12_RESOURCE_DESC {
|
|
Dimension: d3d12::D3D12_RESOURCE_DIMENSION_BUFFER,
|
|
Alignment: d3d12::D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT as u64,
|
|
Width: 512,
|
|
Height: 1,
|
|
DepthOrArraySize: 1,
|
|
MipLevels: 1,
|
|
Format: dxgiformat::DXGI_FORMAT_UNKNOWN,
|
|
SampleDesc: all_dxgi::DXGI_SAMPLE_DESC {
|
|
Count: 1,
|
|
Quality: 0,
|
|
},
|
|
Layout: d3d12::D3D12_TEXTURE_LAYOUT_ROW_MAJOR,
|
|
Flags: d3d12::D3D12_RESOURCE_FLAG_NONE,
|
|
};
|
|
|
|
let allocation_desc = AllocationCreateDesc::from_winapi_d3d12_resource_desc(
|
|
device,
|
|
&test_buffer_desc,
|
|
"Test allocation (Gpu Only)",
|
|
MemoryLocation::GpuOnly,
|
|
);
|
|
let allocation = allocator.allocate(&allocation_desc).unwrap();
|
|
|
|
let mut resource: *mut d3d12::ID3D12Resource = std::ptr::null_mut();
|
|
let hr = unsafe {
|
|
device.CreatePlacedResource(
|
|
allocation.heap().as_winapi() as *mut _,
|
|
allocation.offset(),
|
|
&test_buffer_desc,
|
|
d3d12::D3D12_RESOURCE_STATE_COMMON,
|
|
std::ptr::null(),
|
|
&d3d12::IID_ID3D12Resource,
|
|
<*mut *mut d3d12::ID3D12Resource>::cast(&mut resource),
|
|
)
|
|
};
|
|
if hr != winerror::S_OK {
|
|
panic!("Failed to create placed resource.");
|
|
}
|
|
|
|
unsafe { resource.as_ref().unwrap().Release() };
|
|
|
|
allocator.free(allocation).unwrap();
|
|
info!("Allocation and deallocation of GpuOnly memory was successful.");
|
|
}
|
|
|
|
// Test allocating Cpu to Gpu memory
|
|
{
|
|
let test_buffer_desc = d3d12::D3D12_RESOURCE_DESC {
|
|
Dimension: d3d12::D3D12_RESOURCE_DIMENSION_BUFFER,
|
|
Alignment: d3d12::D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT as u64,
|
|
Width: 512,
|
|
Height: 1,
|
|
DepthOrArraySize: 1,
|
|
MipLevels: 1,
|
|
Format: dxgiformat::DXGI_FORMAT_UNKNOWN,
|
|
SampleDesc: all_dxgi::DXGI_SAMPLE_DESC {
|
|
Count: 1,
|
|
Quality: 0,
|
|
},
|
|
Layout: d3d12::D3D12_TEXTURE_LAYOUT_ROW_MAJOR,
|
|
Flags: d3d12::D3D12_RESOURCE_FLAG_NONE,
|
|
};
|
|
|
|
let alloc_info = unsafe { device.GetResourceAllocationInfo(0, 1, &test_buffer_desc) };
|
|
|
|
let allocation = allocator
|
|
.allocate(&AllocationCreateDesc {
|
|
name: "Test allocation (Cpu to Gpu)",
|
|
location: MemoryLocation::CpuToGpu,
|
|
size: alloc_info.SizeInBytes,
|
|
alignment: alloc_info.Alignment,
|
|
resource_category: ResourceCategory::Buffer,
|
|
})
|
|
.unwrap();
|
|
|
|
let mut resource: *mut d3d12::ID3D12Resource = std::ptr::null_mut();
|
|
let hr = unsafe {
|
|
device.CreatePlacedResource(
|
|
allocation.heap().as_winapi() as *mut _,
|
|
allocation.offset(),
|
|
&test_buffer_desc,
|
|
d3d12::D3D12_RESOURCE_STATE_COMMON,
|
|
std::ptr::null(),
|
|
&d3d12::IID_ID3D12Resource,
|
|
<*mut *mut d3d12::ID3D12Resource>::cast(&mut resource),
|
|
)
|
|
};
|
|
if hr != winerror::S_OK {
|
|
panic!("Failed to create placed resource.");
|
|
}
|
|
|
|
unsafe { resource.as_ref().unwrap().Release() };
|
|
|
|
allocator.free(allocation).unwrap();
|
|
info!("Allocation and deallocation of CpuToGpu memory was successful.");
|
|
}
|
|
|
|
// Test allocating Gpu to Cpu memory
|
|
{
|
|
let test_buffer_desc = d3d12::D3D12_RESOURCE_DESC {
|
|
Dimension: d3d12::D3D12_RESOURCE_DIMENSION_BUFFER,
|
|
Alignment: d3d12::D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT as u64,
|
|
Width: 512,
|
|
Height: 1,
|
|
DepthOrArraySize: 1,
|
|
MipLevels: 1,
|
|
Format: dxgiformat::DXGI_FORMAT_UNKNOWN,
|
|
SampleDesc: all_dxgi::DXGI_SAMPLE_DESC {
|
|
Count: 1,
|
|
Quality: 0,
|
|
},
|
|
Layout: d3d12::D3D12_TEXTURE_LAYOUT_ROW_MAJOR,
|
|
Flags: d3d12::D3D12_RESOURCE_FLAG_NONE,
|
|
};
|
|
|
|
let alloc_info = unsafe { device.GetResourceAllocationInfo(0, 1, &test_buffer_desc) };
|
|
|
|
let allocation = allocator
|
|
.allocate(&AllocationCreateDesc {
|
|
name: "Test allocation (Gpu to Cpu)",
|
|
location: MemoryLocation::GpuToCpu,
|
|
size: alloc_info.SizeInBytes,
|
|
alignment: alloc_info.Alignment,
|
|
resource_category: ResourceCategory::Buffer,
|
|
})
|
|
.unwrap();
|
|
|
|
let mut resource: *mut d3d12::ID3D12Resource = std::ptr::null_mut();
|
|
let hr = unsafe {
|
|
device.CreatePlacedResource(
|
|
allocation.heap().as_winapi() as *mut _,
|
|
allocation.offset(),
|
|
&test_buffer_desc,
|
|
d3d12::D3D12_RESOURCE_STATE_COMMON,
|
|
std::ptr::null(),
|
|
&d3d12::IID_ID3D12Resource,
|
|
<*mut *mut d3d12::ID3D12Resource>::cast(&mut resource),
|
|
)
|
|
};
|
|
if hr != winerror::S_OK {
|
|
panic!("Failed to create placed resource.");
|
|
}
|
|
|
|
unsafe { resource.as_ref().unwrap().Release() };
|
|
|
|
allocator.free(allocation).unwrap();
|
|
info!("Allocation and deallocation of CpuToGpu memory was successful.");
|
|
}
|
|
|
|
drop(allocator); // Explicitly drop before destruction of device.
|
|
unsafe { device.Release() };
|
|
unsafe { dxgi_factory.as_ref().unwrap().Release() };
|
|
}
|