Vendor things
This commit is contained in:
parent
5deceec006
commit
977e3c17e5
19434 changed files with 10682014 additions and 0 deletions
556
third-party/vendor/gpu-allocator/examples/d3d12-visualization/main.rs
vendored
Normal file
556
third-party/vendor/gpu-allocator/examples/d3d12-visualization/main.rs
vendored
Normal file
|
|
@ -0,0 +1,556 @@
|
|||
#![windows_subsystem = "windows"]
|
||||
//! Example showcasing [`winapi`] interop with [`gpu-allocator`] which is driven by the [`windows`] crate.
|
||||
use log::info;
|
||||
use raw_window_handle::HasRawWindowHandle;
|
||||
|
||||
use gpu_allocator::d3d12::{Allocator, AllocatorCreateDesc, ToWindows};
|
||||
|
||||
mod all_dxgi {
|
||||
pub use winapi::shared::{
|
||||
dxgi::*, dxgi1_2::*, dxgi1_3::*, dxgi1_4::*, dxgi1_6::*, dxgiformat::*, dxgitype::*,
|
||||
};
|
||||
}
|
||||
|
||||
use winapi::um::d3d12::*;
|
||||
use winapi::um::d3dcommon::*;
|
||||
use winapi::um::winuser;
|
||||
|
||||
use winapi::shared::minwindef::UINT;
|
||||
use winapi::shared::winerror;
|
||||
use winapi::shared::winerror::{FAILED, SUCCEEDED};
|
||||
|
||||
use winapi::Interface;
|
||||
|
||||
mod imgui_renderer;
|
||||
use imgui_renderer::{handle_imgui_event, ImGuiRenderer};
|
||||
|
||||
const ENABLE_DEBUG_LAYER: bool = true;
|
||||
const FRAMES_IN_FLIGHT: usize = 2;
|
||||
|
||||
struct BackBuffer {
|
||||
resource: *mut ID3D12Resource,
|
||||
rtv_handle: D3D12_CPU_DESCRIPTOR_HANDLE,
|
||||
}
|
||||
|
||||
fn find_hardware_adapter(
|
||||
dxgi_factory: &all_dxgi::IDXGIFactory6,
|
||||
) -> Option<*mut all_dxgi::IDXGIAdapter4> {
|
||||
let mut adapter: *mut all_dxgi::IDXGIAdapter4 = std::ptr::null_mut();
|
||||
for adapter_index in 0.. {
|
||||
let hr = unsafe {
|
||||
dxgi_factory.EnumAdapters1(
|
||||
adapter_index,
|
||||
<*mut *mut all_dxgi::IDXGIAdapter4>::cast(&mut adapter),
|
||||
)
|
||||
};
|
||||
if hr == winerror::DXGI_ERROR_NOT_FOUND {
|
||||
break;
|
||||
}
|
||||
|
||||
let mut desc = Default::default();
|
||||
unsafe { adapter.as_ref().unwrap().GetDesc3(&mut desc) };
|
||||
|
||||
if (desc.Flags & all_dxgi::DXGI_ADAPTER_FLAG_SOFTWARE) != 0 {
|
||||
continue;
|
||||
}
|
||||
|
||||
let hr = unsafe {
|
||||
D3D12CreateDevice(
|
||||
adapter.cast(),
|
||||
D3D_FEATURE_LEVEL_12_0,
|
||||
&IID_ID3D12Device,
|
||||
std::ptr::null_mut(),
|
||||
)
|
||||
};
|
||||
if SUCCEEDED(hr) {
|
||||
return Some(adapter);
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
fn enable_d3d12_debug_layer() -> bool {
|
||||
use winapi::um::d3d12sdklayers::ID3D12Debug;
|
||||
let mut debug: *mut ID3D12Debug = std::ptr::null_mut();
|
||||
let hr = unsafe {
|
||||
D3D12GetDebugInterface(
|
||||
&ID3D12Debug::uuidof(),
|
||||
<*mut *mut ID3D12Debug>::cast(&mut debug),
|
||||
)
|
||||
};
|
||||
if FAILED(hr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let debug = unsafe { debug.as_mut().unwrap() };
|
||||
unsafe { debug.EnableDebugLayer() };
|
||||
unsafe { debug.Release() };
|
||||
|
||||
true
|
||||
}
|
||||
|
||||
fn create_d3d12_device(adapter: &mut all_dxgi::IDXGIAdapter4) -> *mut ID3D12Device {
|
||||
unsafe {
|
||||
let mut device: *mut ID3D12Device = std::ptr::null_mut();
|
||||
let hr = D3D12CreateDevice(
|
||||
<*mut all_dxgi::IDXGIAdapter4>::cast(adapter),
|
||||
D3D_FEATURE_LEVEL_12_0,
|
||||
&ID3D12Device::uuidof(),
|
||||
<*mut *mut ID3D12Device>::cast(&mut device),
|
||||
);
|
||||
if FAILED(hr) {
|
||||
panic!("Failed to create ID3D12Device.");
|
||||
}
|
||||
device
|
||||
}
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
fn transition_resource(
|
||||
resource: *mut ID3D12Resource,
|
||||
before: D3D12_RESOURCE_STATES,
|
||||
after: D3D12_RESOURCE_STATES,
|
||||
) -> D3D12_RESOURCE_BARRIER {
|
||||
let mut barrier = D3D12_RESOURCE_BARRIER {
|
||||
Type: D3D12_RESOURCE_BARRIER_TYPE_TRANSITION,
|
||||
Flags: D3D12_RESOURCE_BARRIER_FLAG_NONE,
|
||||
..D3D12_RESOURCE_BARRIER::default()
|
||||
};
|
||||
|
||||
unsafe {
|
||||
barrier.u.Transition_mut().pResource = resource;
|
||||
barrier.u.Transition_mut().StateBefore = before;
|
||||
barrier.u.Transition_mut().StateAfter = after;
|
||||
barrier.u.Transition_mut().Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
|
||||
}
|
||||
|
||||
barrier
|
||||
}
|
||||
|
||||
fn main() {
|
||||
env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("trace")).init();
|
||||
|
||||
// Disable automatic DPI scaling by windows
|
||||
unsafe { winuser::SetProcessDPIAware() };
|
||||
|
||||
let event_loop = winit::event_loop::EventLoop::new();
|
||||
|
||||
let window_width = 1920;
|
||||
let window_height = 1080;
|
||||
let window = winit::window::WindowBuilder::new()
|
||||
.with_title("gpu-allocator d3d12 visualization")
|
||||
.with_inner_size(winit::dpi::PhysicalSize::new(
|
||||
window_width as f64,
|
||||
window_height as f64,
|
||||
))
|
||||
.with_resizable(false)
|
||||
.build(&event_loop)
|
||||
.unwrap();
|
||||
|
||||
let (event_send, event_recv) = std::sync::mpsc::sync_channel(1);
|
||||
let quit_send = event_loop.create_proxy();
|
||||
|
||||
std::thread::spawn(move || {
|
||||
let mut dxgi_factory_flags = 0;
|
||||
if ENABLE_DEBUG_LAYER && enable_d3d12_debug_layer() {
|
||||
info!("Enabled D3D12 debug layer");
|
||||
dxgi_factory_flags |= all_dxgi::DXGI_CREATE_FACTORY_DEBUG;
|
||||
}
|
||||
|
||||
let dxgi_factory = unsafe {
|
||||
let mut factory: *mut all_dxgi::IDXGIFactory6 = std::ptr::null_mut();
|
||||
let hr = all_dxgi::CreateDXGIFactory2(
|
||||
dxgi_factory_flags,
|
||||
&all_dxgi::IID_IDXGIFactory6,
|
||||
<*mut *mut all_dxgi::IDXGIFactory6>::cast(&mut factory),
|
||||
);
|
||||
|
||||
if FAILED(hr) {
|
||||
panic!("Failed to create dxgi factory");
|
||||
}
|
||||
|
||||
factory.as_mut().unwrap()
|
||||
};
|
||||
|
||||
let adapter = find_hardware_adapter(dxgi_factory).unwrap();
|
||||
let adapter = unsafe { adapter.as_mut().unwrap() };
|
||||
|
||||
let device = create_d3d12_device(adapter);
|
||||
let device = unsafe { device.as_mut().unwrap() };
|
||||
|
||||
let queue = unsafe {
|
||||
let desc = D3D12_COMMAND_QUEUE_DESC {
|
||||
Type: D3D12_COMMAND_LIST_TYPE_DIRECT,
|
||||
Priority: 0, // ?
|
||||
Flags: D3D12_COMMAND_QUEUE_FLAG_NONE,
|
||||
NodeMask: 0,
|
||||
};
|
||||
|
||||
let mut queue: *mut ID3D12CommandQueue = std::ptr::null_mut();
|
||||
let hr = device.CreateCommandQueue(
|
||||
&desc,
|
||||
&ID3D12CommandQueue::uuidof(),
|
||||
<*mut *mut ID3D12CommandQueue>::cast(&mut queue),
|
||||
);
|
||||
if FAILED(hr) {
|
||||
panic!("Failed to create command queue.");
|
||||
}
|
||||
|
||||
queue.as_mut().unwrap()
|
||||
};
|
||||
|
||||
let swapchain = unsafe {
|
||||
let mut swapchain: *mut all_dxgi::IDXGISwapChain3 = std::ptr::null_mut();
|
||||
|
||||
let swap_chain_desc = all_dxgi::DXGI_SWAP_CHAIN_DESC1 {
|
||||
BufferCount: FRAMES_IN_FLIGHT as UINT,
|
||||
Width: window_width,
|
||||
Height: window_height,
|
||||
Format: all_dxgi::DXGI_FORMAT_R8G8B8A8_UNORM,
|
||||
BufferUsage: all_dxgi::DXGI_USAGE_RENDER_TARGET_OUTPUT,
|
||||
SwapEffect: all_dxgi::DXGI_SWAP_EFFECT_FLIP_DISCARD,
|
||||
SampleDesc: all_dxgi::DXGI_SAMPLE_DESC {
|
||||
Count: 1,
|
||||
Quality: 0,
|
||||
},
|
||||
..all_dxgi::DXGI_SWAP_CHAIN_DESC1::default()
|
||||
};
|
||||
|
||||
let raw_window_haver: &dyn HasRawWindowHandle = &window;
|
||||
let hwnd = if let raw_window_handle::RawWindowHandle::Win32(handle) =
|
||||
raw_window_haver.raw_window_handle()
|
||||
{
|
||||
handle.hwnd
|
||||
} else {
|
||||
panic!("Failed to get HWND.")
|
||||
};
|
||||
let hr = dxgi_factory.CreateSwapChainForHwnd(
|
||||
<*mut ID3D12CommandQueue>::cast(queue),
|
||||
hwnd.cast(),
|
||||
&swap_chain_desc,
|
||||
std::ptr::null(),
|
||||
std::ptr::null_mut(),
|
||||
<*mut *mut all_dxgi::IDXGISwapChain3>::cast(&mut swapchain),
|
||||
);
|
||||
if FAILED(hr) {
|
||||
panic!("Failed to create swapchain. hr: {:#x}", hr);
|
||||
}
|
||||
swapchain.as_mut().unwrap()
|
||||
};
|
||||
|
||||
let rtv_heap = unsafe {
|
||||
let desc = D3D12_DESCRIPTOR_HEAP_DESC {
|
||||
Type: D3D12_DESCRIPTOR_HEAP_TYPE_RTV,
|
||||
NumDescriptors: 2,
|
||||
Flags: D3D12_DESCRIPTOR_HEAP_FLAG_NONE,
|
||||
NodeMask: 0,
|
||||
};
|
||||
let mut heap: *mut ID3D12DescriptorHeap = std::ptr::null_mut();
|
||||
let hr = device.CreateDescriptorHeap(
|
||||
&desc,
|
||||
&IID_ID3D12DescriptorHeap,
|
||||
<*mut *mut ID3D12DescriptorHeap>::cast(&mut heap),
|
||||
);
|
||||
if FAILED(hr) {
|
||||
panic!("Failed to create RTV Descriptor heap");
|
||||
}
|
||||
|
||||
heap.as_mut().unwrap()
|
||||
};
|
||||
|
||||
let backbuffers = unsafe {
|
||||
(0..FRAMES_IN_FLIGHT)
|
||||
.map(|i| {
|
||||
let mut resource: *mut ID3D12Resource = std::ptr::null_mut();
|
||||
let hr = swapchain.GetBuffer(
|
||||
i as u32,
|
||||
&ID3D12Resource::uuidof(),
|
||||
<*mut *mut ID3D12Resource>::cast(&mut resource),
|
||||
);
|
||||
if FAILED(hr) {
|
||||
panic!("Failed to access swapchain buffer {}", i);
|
||||
}
|
||||
|
||||
let mut u = D3D12_RENDER_TARGET_VIEW_DESC_u::default();
|
||||
let t2d = u.Texture2D_mut();
|
||||
t2d.MipSlice = 0;
|
||||
t2d.PlaneSlice = 0;
|
||||
|
||||
let rtv_stride = device
|
||||
.GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV)
|
||||
as usize;
|
||||
let rtv_handle = D3D12_CPU_DESCRIPTOR_HANDLE {
|
||||
ptr: rtv_heap.GetCPUDescriptorHandleForHeapStart().ptr + i * rtv_stride,
|
||||
};
|
||||
|
||||
let mut rtv_desc = D3D12_RENDER_TARGET_VIEW_DESC {
|
||||
Format: all_dxgi::DXGI_FORMAT_R8G8B8A8_UNORM,
|
||||
ViewDimension: D3D12_RTV_DIMENSION_TEXTURE2D,
|
||||
..Default::default()
|
||||
};
|
||||
rtv_desc.u.Texture2D_mut().MipSlice = 0;
|
||||
rtv_desc.u.Texture2D_mut().PlaneSlice = 0;
|
||||
|
||||
device.CreateRenderTargetView(resource, &rtv_desc, rtv_handle);
|
||||
|
||||
BackBuffer {
|
||||
resource,
|
||||
rtv_handle,
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
};
|
||||
|
||||
let command_allocator = unsafe {
|
||||
let mut command_allocator: *mut ID3D12CommandAllocator = std::ptr::null_mut();
|
||||
|
||||
let hr = device.CreateCommandAllocator(
|
||||
D3D12_COMMAND_LIST_TYPE_DIRECT,
|
||||
&ID3D12CommandAllocator::uuidof(),
|
||||
<*mut *mut ID3D12CommandAllocator>::cast(&mut command_allocator),
|
||||
);
|
||||
if FAILED(hr) {
|
||||
panic!("Failed to create command allocator");
|
||||
}
|
||||
|
||||
command_allocator.as_mut().unwrap()
|
||||
};
|
||||
|
||||
let descriptor_heap = unsafe {
|
||||
let desc = D3D12_DESCRIPTOR_HEAP_DESC {
|
||||
Type: D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV,
|
||||
NumDescriptors: 4096,
|
||||
Flags: D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE,
|
||||
NodeMask: 0,
|
||||
};
|
||||
|
||||
let mut heap: *mut ID3D12DescriptorHeap = std::ptr::null_mut();
|
||||
let hr = device.CreateDescriptorHeap(
|
||||
&desc,
|
||||
&IID_ID3D12DescriptorHeap,
|
||||
<*mut *mut ID3D12DescriptorHeap>::cast(&mut heap),
|
||||
);
|
||||
if FAILED(hr) {
|
||||
panic!("Failed to create descriptor heap.");
|
||||
}
|
||||
|
||||
heap.as_mut().unwrap()
|
||||
};
|
||||
|
||||
let command_list = unsafe {
|
||||
let mut command_list: *mut ID3D12GraphicsCommandList = std::ptr::null_mut();
|
||||
let hr = device.CreateCommandList(
|
||||
0,
|
||||
D3D12_COMMAND_LIST_TYPE_DIRECT,
|
||||
command_allocator,
|
||||
std::ptr::null_mut(),
|
||||
&ID3D12GraphicsCommandList::uuidof(),
|
||||
<*mut *mut ID3D12GraphicsCommandList>::cast(&mut command_list),
|
||||
);
|
||||
if FAILED(hr) {
|
||||
panic!("Failed to create command list.");
|
||||
}
|
||||
|
||||
command_list.as_mut().unwrap()
|
||||
};
|
||||
|
||||
let mut allocator = Allocator::new(&AllocatorCreateDesc {
|
||||
device: device.as_windows().clone(),
|
||||
debug_settings: Default::default(),
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
let mut descriptor_heap_counter = 0;
|
||||
|
||||
let mut imgui = imgui::Context::create();
|
||||
imgui.io_mut().display_size = [window_width as f32, window_height as f32];
|
||||
let mut imgui_renderer = ImGuiRenderer::new(
|
||||
&mut imgui,
|
||||
device,
|
||||
&mut allocator,
|
||||
descriptor_heap,
|
||||
&mut descriptor_heap_counter,
|
||||
command_list,
|
||||
);
|
||||
|
||||
let fence = unsafe {
|
||||
let mut fence: *mut ID3D12Fence = std::ptr::null_mut();
|
||||
let hr = device.CreateFence(
|
||||
0,
|
||||
D3D12_FENCE_FLAG_NONE,
|
||||
&ID3D12Fence::uuidof(),
|
||||
<*mut *mut ID3D12Fence>::cast(&mut fence),
|
||||
);
|
||||
if FAILED(hr) {
|
||||
panic!("Failed to create fence");
|
||||
}
|
||||
|
||||
fence.as_mut().unwrap()
|
||||
};
|
||||
|
||||
let mut fence_value = 0_u64;
|
||||
|
||||
unsafe { command_list.Close() };
|
||||
|
||||
// Submit and wait idle
|
||||
unsafe {
|
||||
let lists = [<*mut ID3D12GraphicsCommandList>::cast(command_list)];
|
||||
queue.ExecuteCommandLists(lists.len() as u32, lists.as_ptr());
|
||||
fence_value += 1;
|
||||
queue.Signal(fence, fence_value);
|
||||
|
||||
while fence.GetCompletedValue() < fence_value {}
|
||||
};
|
||||
|
||||
let mut visualizer = gpu_allocator::d3d12::AllocatorVisualizer::new();
|
||||
|
||||
loop {
|
||||
let event = event_recv.recv().unwrap();
|
||||
handle_imgui_event(imgui.io_mut(), &window, &event);
|
||||
|
||||
let mut should_quit = false;
|
||||
if let winit::event::Event::WindowEvent { event, .. } = event {
|
||||
match event {
|
||||
winit::event::WindowEvent::KeyboardInput { input, .. } => {
|
||||
if let Some(winit::event::VirtualKeyCode::Escape) = input.virtual_keycode {
|
||||
should_quit = true;
|
||||
}
|
||||
}
|
||||
winit::event::WindowEvent::CloseRequested => {
|
||||
should_quit = true;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
if should_quit {
|
||||
quit_send.send_event(()).unwrap();
|
||||
break;
|
||||
}
|
||||
|
||||
let buffer_index = unsafe { swapchain.GetCurrentBackBufferIndex() };
|
||||
let current_backbuffer = &backbuffers[buffer_index as usize];
|
||||
|
||||
let ui = imgui.frame();
|
||||
visualizer.render(&allocator, ui, None);
|
||||
let imgui_draw_data = imgui.render();
|
||||
|
||||
unsafe {
|
||||
command_allocator.Reset();
|
||||
command_list.Reset(command_allocator, std::ptr::null_mut());
|
||||
|
||||
{
|
||||
let barriers = [transition_resource(
|
||||
current_backbuffer.resource,
|
||||
D3D12_RESOURCE_STATE_PRESENT,
|
||||
D3D12_RESOURCE_STATE_RENDER_TARGET,
|
||||
)];
|
||||
command_list.ResourceBarrier(barriers.len() as u32, barriers.as_ptr());
|
||||
}
|
||||
|
||||
command_list.ClearRenderTargetView(
|
||||
current_backbuffer.rtv_handle,
|
||||
&[1.0, 1.0, 0.0, 0.0],
|
||||
0,
|
||||
std::ptr::null_mut(),
|
||||
);
|
||||
|
||||
let rtv_handles = [current_backbuffer.rtv_handle];
|
||||
command_list.OMSetRenderTargets(
|
||||
rtv_handles.len() as u32,
|
||||
rtv_handles.as_ptr(),
|
||||
0,
|
||||
std::ptr::null_mut(),
|
||||
);
|
||||
|
||||
{
|
||||
let scissor_rects = [D3D12_RECT {
|
||||
left: 0,
|
||||
top: 0,
|
||||
right: window_width as i32,
|
||||
bottom: window_height as i32,
|
||||
}];
|
||||
command_list
|
||||
.RSSetScissorRects(scissor_rects.len() as u32, scissor_rects.as_ptr());
|
||||
}
|
||||
|
||||
let mut heaps: [*mut _; 1] = [descriptor_heap];
|
||||
command_list.SetDescriptorHeaps(heaps.len() as u32, heaps.as_mut_ptr());
|
||||
|
||||
imgui_renderer.render(
|
||||
imgui_draw_data,
|
||||
device,
|
||||
window_width,
|
||||
window_height,
|
||||
descriptor_heap,
|
||||
command_list,
|
||||
);
|
||||
|
||||
{
|
||||
let barriers = [transition_resource(
|
||||
current_backbuffer.resource,
|
||||
D3D12_RESOURCE_STATE_RENDER_TARGET,
|
||||
D3D12_RESOURCE_STATE_PRESENT,
|
||||
)];
|
||||
command_list.ResourceBarrier(barriers.len() as u32, barriers.as_ptr());
|
||||
}
|
||||
|
||||
command_list.Close();
|
||||
|
||||
let lists = [<*mut ID3D12GraphicsCommandList>::cast(command_list)];
|
||||
queue.ExecuteCommandLists(lists.len() as u32, lists.as_ptr());
|
||||
}
|
||||
|
||||
unsafe { swapchain.Present(0, 0) };
|
||||
|
||||
unsafe {
|
||||
fence_value += 1;
|
||||
queue.Signal(fence, fence_value);
|
||||
|
||||
loop {
|
||||
if fence_value == fence.GetCompletedValue() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsafe {
|
||||
fence_value += 1;
|
||||
queue.Signal(fence, fence_value);
|
||||
|
||||
while fence.GetCompletedValue() < fence_value {}
|
||||
}
|
||||
|
||||
imgui_renderer.destroy(&mut allocator);
|
||||
|
||||
unsafe {
|
||||
for b in backbuffers {
|
||||
b.resource.as_ref().unwrap().Release();
|
||||
}
|
||||
|
||||
fence.Release();
|
||||
command_list.Release();
|
||||
command_allocator.Release();
|
||||
swapchain.Release();
|
||||
|
||||
queue.Release();
|
||||
device.Release();
|
||||
adapter.Release();
|
||||
dxgi_factory.Release();
|
||||
}
|
||||
});
|
||||
|
||||
event_loop.run(move |event, _, control_flow| {
|
||||
*control_flow = winit::event_loop::ControlFlow::Wait;
|
||||
|
||||
if event == winit::event::Event::UserEvent(()) {
|
||||
*control_flow = winit::event_loop::ControlFlow::Exit;
|
||||
} else if let Some(event) = event.to_static() {
|
||||
let _ = event_send.send(event);
|
||||
} else {
|
||||
*control_flow = winit::event_loop::ControlFlow::Exit;
|
||||
}
|
||||
});
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue