forked from mirrors/gecko-dev
		
	
		
			
				
	
	
		
			284 lines
		
	
	
	
		
			9.8 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
			
		
		
	
	
			284 lines
		
	
	
	
		
			9.8 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
//! Example showcasing [`winapi`] interop with [`gpu-allocator`] which is driven by the [`windows`] crate.
 | 
						|
use winapi::shared::{dxgiformat, winerror};
 | 
						|
use winapi::um::{d3d12, d3dcommon};
 | 
						|
use winapi::Interface;
 | 
						|
 | 
						|
mod all_dxgi {
 | 
						|
    pub use winapi::shared::{dxgi1_3::*, dxgi1_6::*, dxgitype::*};
 | 
						|
}
 | 
						|
 | 
						|
use log::*;
 | 
						|
 | 
						|
use gpu_allocator::d3d12::{
 | 
						|
    AllocationCreateDesc, Allocator, AllocatorCreateDesc, ID3D12DeviceVersion, ResourceCategory,
 | 
						|
    ToWinapi, ToWindows,
 | 
						|
};
 | 
						|
use gpu_allocator::MemoryLocation;
 | 
						|
 | 
						|
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 {
 | 
						|
                        winapi::shared::winerror::S_OK => {
 | 
						|
                            info!("Using D3D12 feature level: {}.", feature_level_name);
 | 
						|
                            Some(device)
 | 
						|
                        }
 | 
						|
                        winapi::shared::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,
 | 
						|
            winapi::shared::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() };
 | 
						|
}
 |