Vendor things
This commit is contained in:
parent
5deceec006
commit
977e3c17e5
19434 changed files with 10682014 additions and 0 deletions
237
third-party/vendor/gpu-allocator/examples/d3d12-buffer-winrs.rs
vendored
Normal file
237
third-party/vendor/gpu-allocator/examples/d3d12-buffer-winrs.rs
vendored
Normal file
|
|
@ -0,0 +1,237 @@
|
|||
//! Example showcasing [`gpu-allocator`] with types and functions from the [`windows`] crate.
|
||||
use gpu_allocator::d3d12::{
|
||||
AllocationCreateDesc, Allocator, AllocatorCreateDesc, ResourceCategory,
|
||||
};
|
||||
use gpu_allocator::MemoryLocation;
|
||||
use log::*;
|
||||
use windows::core::{Interface, Result};
|
||||
use windows::Win32::{
|
||||
Foundation::E_NOINTERFACE,
|
||||
Graphics::{
|
||||
Direct3D::{D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_11_1, D3D_FEATURE_LEVEL_12_0},
|
||||
Direct3D12::{
|
||||
D3D12CreateDevice, ID3D12Device, ID3D12Resource,
|
||||
D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT, D3D12_RESOURCE_DESC,
|
||||
D3D12_RESOURCE_DIMENSION_BUFFER, D3D12_RESOURCE_FLAG_NONE, D3D12_RESOURCE_STATE_COMMON,
|
||||
D3D12_TEXTURE_LAYOUT_ROW_MAJOR,
|
||||
},
|
||||
Dxgi::Common::{DXGI_FORMAT_UNKNOWN, DXGI_SAMPLE_DESC},
|
||||
Dxgi::{
|
||||
CreateDXGIFactory2, IDXGIAdapter4, IDXGIFactory6, DXGI_ADAPTER_FLAG3_SOFTWARE,
|
||||
DXGI_ERROR_NOT_FOUND,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
fn create_d3d12_device(dxgi_factory: &IDXGIFactory6) -> Option<ID3D12Device> {
|
||||
for idx in 0.. {
|
||||
// TODO: Might as well return Result<> from this function
|
||||
let adapter1 = match unsafe { dxgi_factory.EnumAdapters1(idx) } {
|
||||
Ok(a) => a,
|
||||
Err(e) if e.code() == DXGI_ERROR_NOT_FOUND => break,
|
||||
Err(e) => panic!("{:?}", e),
|
||||
};
|
||||
let adapter4: IDXGIAdapter4 = adapter1.cast().unwrap();
|
||||
|
||||
let mut desc = Default::default();
|
||||
unsafe { adapter4.GetDesc3(&mut desc) }.unwrap();
|
||||
// Skip software adapters
|
||||
// Vote for https://github.com/microsoft/windows-rs/issues/793!
|
||||
if (desc.Flags & DXGI_ADAPTER_FLAG3_SOFTWARE) == DXGI_ADAPTER_FLAG3_SOFTWARE {
|
||||
continue;
|
||||
}
|
||||
|
||||
let feature_levels = [
|
||||
(D3D_FEATURE_LEVEL_11_0, "D3D_FEATURE_LEVEL_11_0"),
|
||||
(D3D_FEATURE_LEVEL_11_1, "D3D_FEATURE_LEVEL_11_1"),
|
||||
(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 = None;
|
||||
match unsafe { D3D12CreateDevice(&adapter4, feature_level, &mut device) } {
|
||||
Ok(()) => {
|
||||
info!("Using D3D12 feature level: {}", feature_level_name);
|
||||
Some(device.unwrap())
|
||||
}
|
||||
Err(e) if e.code() == E_NOINTERFACE => {
|
||||
error!("ID3D12Device interface not supported");
|
||||
None
|
||||
}
|
||||
Err(e) => {
|
||||
info!(
|
||||
"D3D12 feature level {} not supported: {}",
|
||||
feature_level_name, e
|
||||
);
|
||||
None
|
||||
}
|
||||
}
|
||||
});
|
||||
if device.is_some() {
|
||||
return device;
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
fn main() -> Result<()> {
|
||||
env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("trace")).init();
|
||||
|
||||
let dxgi_factory = unsafe { CreateDXGIFactory2(0) }?;
|
||||
|
||||
let device = create_d3d12_device(&dxgi_factory).expect("Failed to create D3D12 device.");
|
||||
|
||||
// Setting up the allocator
|
||||
let mut allocator = Allocator::new(&AllocatorCreateDesc {
|
||||
device: device.clone(),
|
||||
debug_settings: Default::default(),
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
// Test allocating Gpu Only memory
|
||||
{
|
||||
let test_buffer_desc = D3D12_RESOURCE_DESC {
|
||||
Dimension: D3D12_RESOURCE_DIMENSION_BUFFER,
|
||||
Alignment: D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT as u64,
|
||||
Width: 512,
|
||||
Height: 1,
|
||||
DepthOrArraySize: 1,
|
||||
MipLevels: 1,
|
||||
Format: DXGI_FORMAT_UNKNOWN,
|
||||
SampleDesc: DXGI_SAMPLE_DESC {
|
||||
Count: 1,
|
||||
Quality: 0,
|
||||
},
|
||||
Layout: D3D12_TEXTURE_LAYOUT_ROW_MAJOR,
|
||||
Flags: D3D12_RESOURCE_FLAG_NONE,
|
||||
};
|
||||
|
||||
let allocation_desc = AllocationCreateDesc::from_d3d12_resource_desc(
|
||||
allocator.device(),
|
||||
&test_buffer_desc,
|
||||
"Test allocation (Gpu only)",
|
||||
MemoryLocation::GpuOnly,
|
||||
);
|
||||
let allocation = allocator.allocate(&allocation_desc).unwrap();
|
||||
|
||||
let mut resource: Option<ID3D12Resource> = None;
|
||||
unsafe {
|
||||
device.CreatePlacedResource(
|
||||
allocation.heap(),
|
||||
allocation.offset(),
|
||||
&test_buffer_desc,
|
||||
D3D12_RESOURCE_STATE_COMMON,
|
||||
None,
|
||||
&mut resource,
|
||||
)
|
||||
}?;
|
||||
|
||||
drop(resource);
|
||||
|
||||
allocator.free(allocation).unwrap();
|
||||
info!("Allocation and deallocation of GpuOnly memory was successful.");
|
||||
}
|
||||
|
||||
// Test allocating Cpu to Gpu memory
|
||||
{
|
||||
let test_buffer_desc = D3D12_RESOURCE_DESC {
|
||||
Dimension: D3D12_RESOURCE_DIMENSION_BUFFER,
|
||||
Alignment: D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT as u64,
|
||||
Width: 512,
|
||||
Height: 1,
|
||||
DepthOrArraySize: 1,
|
||||
MipLevels: 1,
|
||||
Format: DXGI_FORMAT_UNKNOWN,
|
||||
SampleDesc: DXGI_SAMPLE_DESC {
|
||||
Count: 1,
|
||||
Quality: 0,
|
||||
},
|
||||
Layout: D3D12_TEXTURE_LAYOUT_ROW_MAJOR,
|
||||
Flags: D3D12_RESOURCE_FLAG_NONE,
|
||||
};
|
||||
|
||||
let alloc_info = unsafe { device.GetResourceAllocationInfo(0, &[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: Option<ID3D12Resource> = None;
|
||||
unsafe {
|
||||
device.CreatePlacedResource(
|
||||
allocation.heap(),
|
||||
allocation.offset(),
|
||||
&test_buffer_desc,
|
||||
D3D12_RESOURCE_STATE_COMMON,
|
||||
None,
|
||||
&mut resource,
|
||||
)
|
||||
}?;
|
||||
|
||||
drop(resource);
|
||||
|
||||
allocator.free(allocation).unwrap();
|
||||
info!("Allocation and deallocation of CpuToGpu memory was successful.");
|
||||
}
|
||||
|
||||
// Test allocating Gpu to Cpu memory
|
||||
{
|
||||
let test_buffer_desc = D3D12_RESOURCE_DESC {
|
||||
Dimension: D3D12_RESOURCE_DIMENSION_BUFFER,
|
||||
Alignment: D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT as u64,
|
||||
Width: 512,
|
||||
Height: 1,
|
||||
DepthOrArraySize: 1,
|
||||
MipLevels: 1,
|
||||
Format: DXGI_FORMAT_UNKNOWN,
|
||||
SampleDesc: DXGI_SAMPLE_DESC {
|
||||
Count: 1,
|
||||
Quality: 0,
|
||||
},
|
||||
Layout: D3D12_TEXTURE_LAYOUT_ROW_MAJOR,
|
||||
Flags: D3D12_RESOURCE_FLAG_NONE,
|
||||
};
|
||||
|
||||
let alloc_info = unsafe { device.GetResourceAllocationInfo(0, &[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: Option<ID3D12Resource> = None;
|
||||
unsafe {
|
||||
device.CreatePlacedResource(
|
||||
allocation.heap(),
|
||||
allocation.offset(),
|
||||
&test_buffer_desc,
|
||||
D3D12_RESOURCE_STATE_COMMON,
|
||||
None,
|
||||
&mut resource,
|
||||
)
|
||||
}?;
|
||||
|
||||
drop(resource);
|
||||
|
||||
allocator.free(allocation).unwrap();
|
||||
info!("Allocation and deallocation of CpuToGpu memory was successful.");
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
282
third-party/vendor/gpu-allocator/examples/d3d12-buffer.rs
vendored
Normal file
282
third-party/vendor/gpu-allocator/examples/d3d12-buffer.rs
vendored
Normal file
|
|
@ -0,0 +1,282 @@
|
|||
//! 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, 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: device.as_windows().clone(),
|
||||
debug_settings: 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() };
|
||||
}
|
||||
BIN
third-party/vendor/gpu-allocator/examples/d3d12-visualization/dxil/imgui.ps.dxil
vendored
Normal file
BIN
third-party/vendor/gpu-allocator/examples/d3d12-visualization/dxil/imgui.ps.dxil
vendored
Normal file
Binary file not shown.
BIN
third-party/vendor/gpu-allocator/examples/d3d12-visualization/dxil/imgui.vs.dxil
vendored
Normal file
BIN
third-party/vendor/gpu-allocator/examples/d3d12-visualization/dxil/imgui.vs.dxil
vendored
Normal file
Binary file not shown.
990
third-party/vendor/gpu-allocator/examples/d3d12-visualization/imgui_renderer.rs
vendored
Normal file
990
third-party/vendor/gpu-allocator/examples/d3d12-visualization/imgui_renderer.rs
vendored
Normal file
|
|
@ -0,0 +1,990 @@
|
|||
mod all_dxgi {
|
||||
pub use winapi::shared::{
|
||||
dxgi::*, dxgi1_2::*, dxgi1_3::*, dxgi1_4::*, dxgi1_6::*, dxgiformat::*, dxgitype::*,
|
||||
};
|
||||
}
|
||||
use gpu_allocator::d3d12::ToWinapi;
|
||||
use winapi::um::d3d12::*;
|
||||
use winapi::um::d3dcommon::*;
|
||||
use winapi::Interface;
|
||||
|
||||
use winapi::shared::winerror::FAILED;
|
||||
|
||||
use gpu_allocator::d3d12::{Allocation, AllocationCreateDesc, Allocator};
|
||||
use gpu_allocator::MemoryLocation;
|
||||
|
||||
use super::transition_resource;
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy)]
|
||||
struct ImGuiCBuffer {
|
||||
scale: [f32; 2],
|
||||
translation: [f32; 2],
|
||||
}
|
||||
|
||||
pub struct ImGuiRenderer {
|
||||
root_signature: *mut ID3D12RootSignature,
|
||||
pipeline: *mut ID3D12PipelineState,
|
||||
|
||||
vb_capacity: u64,
|
||||
ib_capacity: u64,
|
||||
vb_allocation: Allocation,
|
||||
ib_allocation: Allocation,
|
||||
vb_pointer: *mut u8,
|
||||
ib_pointer: *mut u8,
|
||||
vertex_buffer: *mut ID3D12Resource,
|
||||
index_buffer: *mut ID3D12Resource,
|
||||
|
||||
cb_allocation: Allocation,
|
||||
cb_pointer: *mut u8,
|
||||
constant_buffer: *mut ID3D12Resource,
|
||||
|
||||
font_image: *mut ID3D12Resource,
|
||||
font_image_memory: Allocation,
|
||||
font_image_srv_index: usize,
|
||||
|
||||
font_image_upload_buffer: *mut ID3D12Resource,
|
||||
font_image_upload_buffer_memory: Allocation,
|
||||
}
|
||||
|
||||
impl ImGuiRenderer {
|
||||
pub(crate) fn new(
|
||||
imgui: &mut imgui::Context,
|
||||
device: &mut ID3D12Device,
|
||||
allocator: &mut Allocator,
|
||||
descriptor_heap: &mut ID3D12DescriptorHeap,
|
||||
descriptor_heap_counter: &mut usize,
|
||||
cmd: &mut ID3D12GraphicsCommandList,
|
||||
) -> Self {
|
||||
let root_signature = {
|
||||
let mut root_parameters = [
|
||||
D3D12_ROOT_PARAMETER {
|
||||
ParameterType: D3D12_ROOT_PARAMETER_TYPE_CBV,
|
||||
ShaderVisibility: D3D12_SHADER_VISIBILITY_ALL,
|
||||
..Default::default()
|
||||
},
|
||||
D3D12_ROOT_PARAMETER {
|
||||
ParameterType: D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE,
|
||||
ShaderVisibility: D3D12_SHADER_VISIBILITY_ALL,
|
||||
..Default::default()
|
||||
},
|
||||
];
|
||||
|
||||
let ranges = [D3D12_DESCRIPTOR_RANGE {
|
||||
RangeType: D3D12_DESCRIPTOR_RANGE_TYPE_SRV,
|
||||
NumDescriptors: 1,
|
||||
BaseShaderRegister: 2,
|
||||
RegisterSpace: 0,
|
||||
OffsetInDescriptorsFromTableStart: 0,
|
||||
}];
|
||||
unsafe {
|
||||
root_parameters[0].u.Descriptor_mut().ShaderRegister = 0;
|
||||
root_parameters[0].u.Descriptor_mut().RegisterSpace = 0;
|
||||
root_parameters[1]
|
||||
.u
|
||||
.DescriptorTable_mut()
|
||||
.NumDescriptorRanges = ranges.len() as u32;
|
||||
root_parameters[1].u.DescriptorTable_mut().pDescriptorRanges = ranges.as_ptr();
|
||||
}
|
||||
|
||||
let static_samplers = [D3D12_STATIC_SAMPLER_DESC {
|
||||
Filter: D3D12_FILTER_MIN_MAG_MIP_LINEAR,
|
||||
AddressU: D3D12_TEXTURE_ADDRESS_MODE_CLAMP,
|
||||
AddressV: D3D12_TEXTURE_ADDRESS_MODE_CLAMP,
|
||||
AddressW: D3D12_TEXTURE_ADDRESS_MODE_CLAMP,
|
||||
MipLODBias: 0.0,
|
||||
MaxAnisotropy: 0,
|
||||
ComparisonFunc: D3D12_COMPARISON_FUNC_ALWAYS,
|
||||
BorderColor: D3D12_STATIC_BORDER_COLOR_OPAQUE_BLACK,
|
||||
MinLOD: 0.0,
|
||||
MaxLOD: 0.0,
|
||||
ShaderRegister: 1,
|
||||
RegisterSpace: 0,
|
||||
ShaderVisibility: D3D12_SHADER_VISIBILITY_ALL,
|
||||
}];
|
||||
|
||||
let rsig_desc = D3D12_ROOT_SIGNATURE_DESC {
|
||||
NumParameters: root_parameters.len() as u32,
|
||||
pParameters: root_parameters.as_ptr(),
|
||||
NumStaticSamplers: static_samplers.len() as u32,
|
||||
pStaticSamplers: static_samplers.as_ptr(),
|
||||
Flags: D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT,
|
||||
};
|
||||
|
||||
let mut blob = std::ptr::null_mut();
|
||||
let mut error_blob = std::ptr::null_mut();
|
||||
let hr = unsafe {
|
||||
D3D12SerializeRootSignature(
|
||||
&rsig_desc,
|
||||
D3D_ROOT_SIGNATURE_VERSION_1,
|
||||
&mut blob,
|
||||
&mut error_blob,
|
||||
)
|
||||
};
|
||||
if FAILED(hr) {
|
||||
let error = unsafe {
|
||||
let error_blob = error_blob.as_ref().unwrap();
|
||||
std::slice::from_raw_parts(
|
||||
error_blob.GetBufferPointer() as *const u8,
|
||||
error_blob.GetBufferSize(),
|
||||
)
|
||||
};
|
||||
|
||||
panic!(
|
||||
"Failed to serialize root signature: '{}'. hr: {:#x}",
|
||||
std::str::from_utf8(error).unwrap(),
|
||||
hr
|
||||
);
|
||||
}
|
||||
|
||||
let blob = unsafe { blob.as_ref() }.unwrap();
|
||||
let mut rsig = std::ptr::null_mut();
|
||||
let hr = unsafe {
|
||||
device.CreateRootSignature(
|
||||
0,
|
||||
blob.GetBufferPointer(),
|
||||
blob.GetBufferSize(),
|
||||
&ID3D12RootSignature::uuidof(),
|
||||
<*mut *mut ID3D12RootSignature>::cast(&mut rsig),
|
||||
)
|
||||
};
|
||||
if FAILED(hr) {
|
||||
panic!("Failed to create root signature. hr: {:#x}", hr);
|
||||
}
|
||||
|
||||
unsafe { rsig.as_mut() }.unwrap()
|
||||
};
|
||||
|
||||
let pipeline = unsafe {
|
||||
let vs = include_bytes!("./dxil/imgui.vs.dxil");
|
||||
let ps = include_bytes!("./dxil/imgui.ps.dxil");
|
||||
|
||||
let input_elements = [
|
||||
D3D12_INPUT_ELEMENT_DESC {
|
||||
SemanticName: b"POSITION\0".as_ptr().cast(),
|
||||
SemanticIndex: 0,
|
||||
Format: all_dxgi::DXGI_FORMAT_R32G32_FLOAT,
|
||||
InputSlot: 0,
|
||||
AlignedByteOffset: 0,
|
||||
InputSlotClass: D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA,
|
||||
InstanceDataStepRate: 0,
|
||||
},
|
||||
D3D12_INPUT_ELEMENT_DESC {
|
||||
SemanticName: b"TEXCOORD\0".as_ptr().cast(),
|
||||
SemanticIndex: 0,
|
||||
Format: all_dxgi::DXGI_FORMAT_R32G32_FLOAT,
|
||||
InputSlot: 0,
|
||||
AlignedByteOffset: 8,
|
||||
InputSlotClass: D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA,
|
||||
InstanceDataStepRate: 0,
|
||||
},
|
||||
D3D12_INPUT_ELEMENT_DESC {
|
||||
SemanticName: b"COLOR\0".as_ptr().cast(),
|
||||
SemanticIndex: 0,
|
||||
Format: all_dxgi::DXGI_FORMAT_R8G8B8A8_UNORM,
|
||||
InputSlot: 0,
|
||||
AlignedByteOffset: 16,
|
||||
InputSlotClass: D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA,
|
||||
InstanceDataStepRate: 0,
|
||||
},
|
||||
];
|
||||
|
||||
let desc = D3D12_GRAPHICS_PIPELINE_STATE_DESC {
|
||||
pRootSignature: root_signature,
|
||||
VS: D3D12_SHADER_BYTECODE {
|
||||
pShaderBytecode: vs.as_ptr().cast(),
|
||||
BytecodeLength: vs.len(),
|
||||
},
|
||||
PS: D3D12_SHADER_BYTECODE {
|
||||
pShaderBytecode: ps.as_ptr().cast(),
|
||||
BytecodeLength: ps.len(),
|
||||
},
|
||||
BlendState: D3D12_BLEND_DESC {
|
||||
AlphaToCoverageEnable: 0,
|
||||
IndependentBlendEnable: 0,
|
||||
RenderTarget: [
|
||||
D3D12_RENDER_TARGET_BLEND_DESC {
|
||||
BlendEnable: 1,
|
||||
LogicOpEnable: 0,
|
||||
SrcBlend: D3D12_BLEND_SRC_ALPHA,
|
||||
DestBlend: D3D12_BLEND_INV_SRC_ALPHA,
|
||||
BlendOp: D3D12_BLEND_OP_ADD,
|
||||
SrcBlendAlpha: D3D12_BLEND_ONE,
|
||||
DestBlendAlpha: D3D12_BLEND_ZERO,
|
||||
BlendOpAlpha: D3D12_BLEND_OP_ADD,
|
||||
LogicOp: D3D12_LOGIC_OP_NOOP,
|
||||
RenderTargetWriteMask: D3D12_COLOR_WRITE_ENABLE_ALL as u8,
|
||||
},
|
||||
D3D12_RENDER_TARGET_BLEND_DESC::default(),
|
||||
D3D12_RENDER_TARGET_BLEND_DESC::default(),
|
||||
D3D12_RENDER_TARGET_BLEND_DESC::default(),
|
||||
D3D12_RENDER_TARGET_BLEND_DESC::default(),
|
||||
D3D12_RENDER_TARGET_BLEND_DESC::default(),
|
||||
D3D12_RENDER_TARGET_BLEND_DESC::default(),
|
||||
D3D12_RENDER_TARGET_BLEND_DESC::default(),
|
||||
],
|
||||
},
|
||||
SampleMask: !0u32,
|
||||
RasterizerState: D3D12_RASTERIZER_DESC {
|
||||
FillMode: D3D12_FILL_MODE_SOLID,
|
||||
CullMode: D3D12_CULL_MODE_NONE,
|
||||
FrontCounterClockwise: 0,
|
||||
DepthBias: 0,
|
||||
DepthBiasClamp: 0.0,
|
||||
SlopeScaledDepthBias: 0.0,
|
||||
DepthClipEnable: 0,
|
||||
MultisampleEnable: 0,
|
||||
AntialiasedLineEnable: 0,
|
||||
ForcedSampleCount: 1,
|
||||
ConservativeRaster: D3D12_CONSERVATIVE_RASTERIZATION_MODE_OFF,
|
||||
},
|
||||
DepthStencilState: D3D12_DEPTH_STENCIL_DESC {
|
||||
DepthEnable: 0,
|
||||
DepthWriteMask: D3D12_DEPTH_WRITE_MASK_ZERO,
|
||||
DepthFunc: D3D12_COMPARISON_FUNC_ALWAYS,
|
||||
StencilEnable: 0,
|
||||
StencilReadMask: 0,
|
||||
StencilWriteMask: 0,
|
||||
FrontFace: D3D12_DEPTH_STENCILOP_DESC::default(),
|
||||
BackFace: D3D12_DEPTH_STENCILOP_DESC::default(),
|
||||
},
|
||||
InputLayout: D3D12_INPUT_LAYOUT_DESC {
|
||||
pInputElementDescs: input_elements.as_ptr(),
|
||||
NumElements: input_elements.len() as u32,
|
||||
},
|
||||
PrimitiveTopologyType: D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE,
|
||||
NumRenderTargets: 1,
|
||||
RTVFormats: [
|
||||
all_dxgi::DXGI_FORMAT_R8G8B8A8_UNORM,
|
||||
all_dxgi::DXGI_FORMAT_UNKNOWN,
|
||||
all_dxgi::DXGI_FORMAT_UNKNOWN,
|
||||
all_dxgi::DXGI_FORMAT_UNKNOWN,
|
||||
all_dxgi::DXGI_FORMAT_UNKNOWN,
|
||||
all_dxgi::DXGI_FORMAT_UNKNOWN,
|
||||
all_dxgi::DXGI_FORMAT_UNKNOWN,
|
||||
all_dxgi::DXGI_FORMAT_UNKNOWN,
|
||||
],
|
||||
SampleDesc: all_dxgi::DXGI_SAMPLE_DESC {
|
||||
Quality: 0,
|
||||
Count: 1,
|
||||
},
|
||||
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let mut pipeline: *mut ID3D12PipelineState = std::ptr::null_mut();
|
||||
let hr = device.CreateGraphicsPipelineState(
|
||||
&desc,
|
||||
&ID3D12PipelineState::uuidof(),
|
||||
<*mut *mut ID3D12PipelineState>::cast(&mut pipeline),
|
||||
);
|
||||
if FAILED(hr) {
|
||||
panic!("Failed to create imgui pipeline: {:#x}", hr);
|
||||
}
|
||||
|
||||
pipeline.as_mut().unwrap()
|
||||
};
|
||||
|
||||
let (
|
||||
font_image,
|
||||
font_image_memory,
|
||||
font_image_srv_index,
|
||||
font_image_upload_buffer,
|
||||
font_image_upload_buffer_memory,
|
||||
) = {
|
||||
let fonts = imgui.fonts();
|
||||
let font_atlas = fonts.build_rgba32_texture();
|
||||
|
||||
let desc = D3D12_RESOURCE_DESC {
|
||||
Dimension: D3D12_RESOURCE_DIMENSION_TEXTURE2D,
|
||||
Alignment: 0,
|
||||
Width: font_atlas.width as u64,
|
||||
Height: font_atlas.height,
|
||||
DepthOrArraySize: 1,
|
||||
MipLevels: 1,
|
||||
Format: all_dxgi::DXGI_FORMAT_R8G8B8A8_UNORM,
|
||||
SampleDesc: all_dxgi::DXGI_SAMPLE_DESC {
|
||||
Count: 1,
|
||||
Quality: 0,
|
||||
},
|
||||
Layout: D3D12_TEXTURE_LAYOUT_UNKNOWN,
|
||||
Flags: D3D12_RESOURCE_FLAG_NONE,
|
||||
};
|
||||
let font_image_memory = allocator
|
||||
.allocate(&AllocationCreateDesc::from_winapi_d3d12_resource_desc(
|
||||
device,
|
||||
&desc,
|
||||
"font_image",
|
||||
MemoryLocation::GpuOnly,
|
||||
))
|
||||
.unwrap();
|
||||
|
||||
let font_image = unsafe {
|
||||
let mut font_image: *mut ID3D12Resource = std::ptr::null_mut();
|
||||
let hr = device.CreatePlacedResource(
|
||||
font_image_memory.heap().as_winapi() as *mut _,
|
||||
font_image_memory.offset(),
|
||||
&desc,
|
||||
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
|
||||
std::ptr::null(),
|
||||
&ID3D12Resource::uuidof(),
|
||||
<*mut *mut ID3D12Resource>::cast(&mut font_image),
|
||||
);
|
||||
if FAILED(hr) {
|
||||
panic!("Failed to create font image. hr: {:#x}", hr);
|
||||
}
|
||||
|
||||
font_image
|
||||
};
|
||||
|
||||
//Create SRV
|
||||
let srv_index = unsafe {
|
||||
let srv_index = *descriptor_heap_counter;
|
||||
*descriptor_heap_counter += 1;
|
||||
|
||||
let srv_size = device
|
||||
.GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV)
|
||||
as usize;
|
||||
|
||||
let desc_heap_handle = descriptor_heap.GetCPUDescriptorHandleForHeapStart();
|
||||
let desc_heap_handle = D3D12_CPU_DESCRIPTOR_HANDLE {
|
||||
ptr: desc_heap_handle.ptr + srv_index * srv_size,
|
||||
};
|
||||
|
||||
const fn d3d12_encode_shader_4_component_mapping(
|
||||
src0: u32,
|
||||
src1: u32,
|
||||
src2: u32,
|
||||
src3: u32,
|
||||
) -> u32 {
|
||||
(src0 & D3D12_SHADER_COMPONENT_MAPPING_MASK)
|
||||
| ((src1 & D3D12_SHADER_COMPONENT_MAPPING_MASK)
|
||||
<< (D3D12_SHADER_COMPONENT_MAPPING_SHIFT))
|
||||
| ((src2 & D3D12_SHADER_COMPONENT_MAPPING_MASK)
|
||||
<< (D3D12_SHADER_COMPONENT_MAPPING_SHIFT * 2))
|
||||
| ((src3 & D3D12_SHADER_COMPONENT_MAPPING_MASK)
|
||||
<< (D3D12_SHADER_COMPONENT_MAPPING_SHIFT * 3))
|
||||
| D3D12_SHADER_COMPONENT_MAPPING_ALWAYS_SET_BIT_AVOIDING_ZEROMEM_MISTAKES
|
||||
}
|
||||
const fn d3d12_default_shader_4_component_mapping() -> u32 {
|
||||
d3d12_encode_shader_4_component_mapping(0, 1, 2, 3)
|
||||
}
|
||||
|
||||
let mut srv_desc = D3D12_SHADER_RESOURCE_VIEW_DESC {
|
||||
Format: all_dxgi::DXGI_FORMAT_R8G8B8A8_UNORM,
|
||||
ViewDimension: D3D12_SRV_DIMENSION_TEXTURE2D,
|
||||
Shader4ComponentMapping: d3d12_default_shader_4_component_mapping(),
|
||||
..Default::default()
|
||||
};
|
||||
srv_desc.u.Texture2D_mut().MostDetailedMip = 0;
|
||||
srv_desc.u.Texture2D_mut().MipLevels = 1;
|
||||
srv_desc.u.Texture2D_mut().PlaneSlice = 0;
|
||||
srv_desc.u.Texture2D_mut().ResourceMinLODClamp = 0.0;
|
||||
device.CreateShaderResourceView(font_image, &srv_desc, desc_heap_handle);
|
||||
srv_index
|
||||
};
|
||||
|
||||
let mut layouts = [D3D12_PLACED_SUBRESOURCE_FOOTPRINT::default()];
|
||||
let mut num_rows: u32 = 0;
|
||||
let mut row_size_in_bytes: u64 = 0;
|
||||
let mut total_bytes: u64 = 0;
|
||||
unsafe {
|
||||
device.GetCopyableFootprints(
|
||||
&font_image.as_ref().unwrap().GetDesc(),
|
||||
0, // first sub
|
||||
layouts.len() as u32, // num sub
|
||||
0, // intermediate offset
|
||||
layouts.as_mut_ptr(),
|
||||
&mut num_rows,
|
||||
&mut row_size_in_bytes,
|
||||
&mut total_bytes,
|
||||
)
|
||||
};
|
||||
|
||||
// Create upload buffer
|
||||
let (upload_buffer, upload_buffer_memory) = {
|
||||
let desc = D3D12_RESOURCE_DESC {
|
||||
Dimension: D3D12_RESOURCE_DIMENSION_BUFFER,
|
||||
Alignment: 0,
|
||||
Width: total_bytes,
|
||||
Height: 1,
|
||||
DepthOrArraySize: 1,
|
||||
MipLevels: 1,
|
||||
Format: all_dxgi::DXGI_FORMAT_UNKNOWN,
|
||||
SampleDesc: all_dxgi::DXGI_SAMPLE_DESC {
|
||||
Count: 1,
|
||||
Quality: 0,
|
||||
},
|
||||
Layout: D3D12_TEXTURE_LAYOUT_ROW_MAJOR,
|
||||
Flags: D3D12_RESOURCE_FLAG_NONE,
|
||||
};
|
||||
|
||||
let upload_buffer_memory = allocator
|
||||
.allocate(&AllocationCreateDesc::from_winapi_d3d12_resource_desc(
|
||||
device,
|
||||
&desc,
|
||||
"font_image upload buffer",
|
||||
MemoryLocation::CpuToGpu,
|
||||
))
|
||||
.unwrap();
|
||||
|
||||
let mut upload_buffer: *mut ID3D12Resource = std::ptr::null_mut();
|
||||
let hr = unsafe {
|
||||
device.CreatePlacedResource(
|
||||
upload_buffer_memory.heap().as_winapi() as *mut _,
|
||||
upload_buffer_memory.offset(),
|
||||
&desc,
|
||||
D3D12_RESOURCE_STATE_GENERIC_READ,
|
||||
std::ptr::null(),
|
||||
&ID3D12Resource::uuidof(),
|
||||
<*mut *mut ID3D12Resource>::cast(&mut upload_buffer),
|
||||
)
|
||||
};
|
||||
|
||||
if FAILED(hr) {
|
||||
panic!("Failed to create font image upload buffer. hr: {:x}.", hr);
|
||||
}
|
||||
|
||||
(upload_buffer, upload_buffer_memory)
|
||||
};
|
||||
|
||||
unsafe {
|
||||
let mut mapped_ptr = std::ptr::null_mut();
|
||||
upload_buffer
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.Map(0, std::ptr::null(), &mut mapped_ptr);
|
||||
let mapped_ptr = mapped_ptr.cast::<u8>();
|
||||
|
||||
let layout = &layouts[0];
|
||||
let mapped_ptr = mapped_ptr.add(layout.Offset as usize);
|
||||
let source_ptr = font_atlas.data.as_ptr();
|
||||
|
||||
for y in 0..layout.Footprint.Height {
|
||||
let mapped_ptr = mapped_ptr.add((y * layout.Footprint.RowPitch) as usize);
|
||||
let source_ptr = source_ptr.add((y * font_atlas.width * 4) as usize);
|
||||
|
||||
std::ptr::copy_nonoverlapping(
|
||||
source_ptr,
|
||||
mapped_ptr,
|
||||
(layout.Footprint.Width * 4) as usize,
|
||||
);
|
||||
}
|
||||
|
||||
upload_buffer.as_ref().unwrap().Unmap(0, std::ptr::null())
|
||||
};
|
||||
|
||||
let mut dst = D3D12_TEXTURE_COPY_LOCATION {
|
||||
pResource: font_image,
|
||||
Type: D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX,
|
||||
..Default::default()
|
||||
};
|
||||
unsafe { *dst.u.SubresourceIndex_mut() = 0 };
|
||||
|
||||
let mut src = D3D12_TEXTURE_COPY_LOCATION {
|
||||
pResource: upload_buffer,
|
||||
Type: D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT,
|
||||
..Default::default()
|
||||
};
|
||||
unsafe { *src.u.PlacedFootprint_mut() = layouts[0] };
|
||||
|
||||
unsafe {
|
||||
let barriers = [transition_resource(
|
||||
font_image,
|
||||
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
|
||||
D3D12_RESOURCE_STATE_COPY_DEST,
|
||||
)];
|
||||
cmd.ResourceBarrier(barriers.len() as u32, barriers.as_ptr());
|
||||
cmd.CopyTextureRegion(&dst, 0, 0, 0, &src, std::ptr::null())
|
||||
};
|
||||
|
||||
(
|
||||
font_image,
|
||||
font_image_memory,
|
||||
srv_index,
|
||||
upload_buffer,
|
||||
upload_buffer_memory,
|
||||
)
|
||||
};
|
||||
|
||||
let (constant_buffer, cb_allocation, cb_pointer) = {
|
||||
let desc = D3D12_RESOURCE_DESC {
|
||||
Dimension: D3D12_RESOURCE_DIMENSION_BUFFER,
|
||||
Alignment: 0,
|
||||
Width: std::mem::size_of::<ImGuiCBuffer>() as u64,
|
||||
Height: 1,
|
||||
DepthOrArraySize: 1,
|
||||
MipLevels: 1,
|
||||
Format: all_dxgi::DXGI_FORMAT_UNKNOWN,
|
||||
SampleDesc: all_dxgi::DXGI_SAMPLE_DESC {
|
||||
Count: 1,
|
||||
Quality: 0,
|
||||
},
|
||||
Layout: D3D12_TEXTURE_LAYOUT_ROW_MAJOR,
|
||||
Flags: D3D12_RESOURCE_FLAG_NONE,
|
||||
};
|
||||
|
||||
let allocation = allocator
|
||||
.allocate(&AllocationCreateDesc::from_winapi_d3d12_resource_desc(
|
||||
device,
|
||||
&desc,
|
||||
"ImGui Constant buffer",
|
||||
MemoryLocation::CpuToGpu,
|
||||
))
|
||||
.unwrap();
|
||||
|
||||
let mut buffer: *mut ID3D12Resource = std::ptr::null_mut();
|
||||
let hr = unsafe {
|
||||
device.CreatePlacedResource(
|
||||
allocation.heap().as_winapi() as *mut _,
|
||||
allocation.offset(),
|
||||
&desc,
|
||||
D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER,
|
||||
std::ptr::null(),
|
||||
&ID3D12Resource::uuidof(),
|
||||
<*mut *mut ID3D12Resource>::cast(&mut buffer),
|
||||
)
|
||||
};
|
||||
if FAILED(hr) {
|
||||
panic!("Failed to create constant buffer. hr: {:x}.", hr);
|
||||
}
|
||||
|
||||
let mut mapped_ptr: *mut u8 = std::ptr::null_mut();
|
||||
unsafe {
|
||||
buffer.as_ref().unwrap().Map(
|
||||
0,
|
||||
std::ptr::null(),
|
||||
<*mut *mut u8>::cast(&mut mapped_ptr),
|
||||
)
|
||||
};
|
||||
|
||||
(buffer, allocation, mapped_ptr)
|
||||
};
|
||||
|
||||
let vb_capacity = 1024 * 1024;
|
||||
let (vertex_buffer, vb_allocation, vb_pointer) = {
|
||||
let desc = D3D12_RESOURCE_DESC {
|
||||
Dimension: D3D12_RESOURCE_DIMENSION_BUFFER,
|
||||
Alignment: 0,
|
||||
Width: vb_capacity,
|
||||
Height: 1,
|
||||
DepthOrArraySize: 1,
|
||||
MipLevels: 1,
|
||||
Format: all_dxgi::DXGI_FORMAT_UNKNOWN,
|
||||
SampleDesc: all_dxgi::DXGI_SAMPLE_DESC {
|
||||
Count: 1,
|
||||
Quality: 0,
|
||||
},
|
||||
Layout: D3D12_TEXTURE_LAYOUT_ROW_MAJOR,
|
||||
Flags: D3D12_RESOURCE_FLAG_NONE,
|
||||
};
|
||||
|
||||
let allocation = allocator
|
||||
.allocate(&AllocationCreateDesc::from_winapi_d3d12_resource_desc(
|
||||
device,
|
||||
&desc,
|
||||
"ImGui Vertex buffer",
|
||||
MemoryLocation::CpuToGpu,
|
||||
))
|
||||
.unwrap();
|
||||
|
||||
let mut buffer: *mut ID3D12Resource = std::ptr::null_mut();
|
||||
let hr = unsafe {
|
||||
device.CreatePlacedResource(
|
||||
allocation.heap().as_winapi() as *mut _,
|
||||
allocation.offset(),
|
||||
&desc,
|
||||
D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER,
|
||||
std::ptr::null(),
|
||||
&ID3D12Resource::uuidof(),
|
||||
<*mut *mut ID3D12Resource>::cast(&mut buffer),
|
||||
)
|
||||
};
|
||||
if FAILED(hr) {
|
||||
panic!("Failed to create vertex buffer. hr: {:x}.", hr);
|
||||
}
|
||||
|
||||
let mut mapped_ptr: *mut u8 = std::ptr::null_mut();
|
||||
unsafe {
|
||||
buffer.as_ref().unwrap().Map(
|
||||
0,
|
||||
std::ptr::null(),
|
||||
<*mut *mut u8>::cast(&mut mapped_ptr),
|
||||
)
|
||||
};
|
||||
(buffer, allocation, mapped_ptr)
|
||||
};
|
||||
|
||||
let ib_capacity = 1024 * 1024;
|
||||
let (index_buffer, ib_allocation, ib_pointer) = {
|
||||
let desc = D3D12_RESOURCE_DESC {
|
||||
Dimension: D3D12_RESOURCE_DIMENSION_BUFFER,
|
||||
Alignment: 0,
|
||||
Width: ib_capacity,
|
||||
Height: 1,
|
||||
DepthOrArraySize: 1,
|
||||
MipLevels: 1,
|
||||
Format: all_dxgi::DXGI_FORMAT_UNKNOWN,
|
||||
SampleDesc: all_dxgi::DXGI_SAMPLE_DESC {
|
||||
Count: 1,
|
||||
Quality: 0,
|
||||
},
|
||||
Layout: D3D12_TEXTURE_LAYOUT_ROW_MAJOR,
|
||||
Flags: D3D12_RESOURCE_FLAG_NONE,
|
||||
};
|
||||
|
||||
let allocation = allocator
|
||||
.allocate(&AllocationCreateDesc::from_winapi_d3d12_resource_desc(
|
||||
device,
|
||||
&desc,
|
||||
"ImGui Vertex buffer",
|
||||
MemoryLocation::CpuToGpu,
|
||||
))
|
||||
.unwrap();
|
||||
|
||||
let mut buffer: *mut ID3D12Resource = std::ptr::null_mut();
|
||||
let hr = unsafe {
|
||||
device.CreatePlacedResource(
|
||||
allocation.heap().as_winapi() as *mut _,
|
||||
allocation.offset(),
|
||||
&desc,
|
||||
D3D12_RESOURCE_STATE_INDEX_BUFFER,
|
||||
std::ptr::null(),
|
||||
&ID3D12Resource::uuidof(),
|
||||
<*mut *mut ID3D12Resource>::cast(&mut buffer),
|
||||
)
|
||||
};
|
||||
if FAILED(hr) {
|
||||
panic!("Failed to create vertex buffer. hr: {:x}.", hr);
|
||||
}
|
||||
|
||||
let mut mapped_ptr: *mut u8 = std::ptr::null_mut();
|
||||
unsafe {
|
||||
buffer.as_ref().unwrap().Map(
|
||||
0,
|
||||
std::ptr::null(),
|
||||
<*mut *mut u8>::cast(&mut mapped_ptr),
|
||||
)
|
||||
};
|
||||
(buffer, allocation, mapped_ptr)
|
||||
};
|
||||
|
||||
Self {
|
||||
root_signature,
|
||||
pipeline,
|
||||
|
||||
vb_capacity,
|
||||
ib_capacity,
|
||||
vb_allocation,
|
||||
ib_allocation,
|
||||
vb_pointer,
|
||||
ib_pointer,
|
||||
vertex_buffer,
|
||||
index_buffer,
|
||||
|
||||
cb_allocation,
|
||||
cb_pointer,
|
||||
constant_buffer,
|
||||
|
||||
font_image,
|
||||
font_image_memory,
|
||||
font_image_srv_index,
|
||||
|
||||
font_image_upload_buffer,
|
||||
font_image_upload_buffer_memory,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn render(
|
||||
&mut self,
|
||||
imgui_draw_data: &imgui::DrawData,
|
||||
device: &mut ID3D12Device,
|
||||
window_width: u32,
|
||||
window_height: u32,
|
||||
descriptor_heap: &mut ID3D12DescriptorHeap,
|
||||
cmd: &mut ID3D12GraphicsCommandList,
|
||||
) {
|
||||
// Update constant buffer
|
||||
{
|
||||
let left = imgui_draw_data.display_pos[0];
|
||||
let right = imgui_draw_data.display_pos[0] + imgui_draw_data.display_size[0];
|
||||
let top = imgui_draw_data.display_pos[1] + imgui_draw_data.display_size[1];
|
||||
let bottom = imgui_draw_data.display_pos[1];
|
||||
|
||||
let cbuffer_data = ImGuiCBuffer {
|
||||
scale: [(2.0 / (right - left)), (2.0 / (bottom - top))],
|
||||
translation: [
|
||||
(right + left) / (left - right),
|
||||
(top + bottom) / (top - bottom),
|
||||
],
|
||||
};
|
||||
|
||||
unsafe { std::ptr::copy_nonoverlapping(&cbuffer_data, self.cb_pointer.cast(), 1) };
|
||||
}
|
||||
|
||||
let (vtx_count, idx_count) =
|
||||
imgui_draw_data
|
||||
.draw_lists()
|
||||
.fold((0, 0), |(vtx_count, idx_count), draw_list| {
|
||||
(
|
||||
vtx_count + draw_list.vtx_buffer().len(),
|
||||
idx_count + draw_list.idx_buffer().len(),
|
||||
)
|
||||
});
|
||||
|
||||
let vtx_size = (vtx_count * std::mem::size_of::<imgui::DrawVert>()) as u64;
|
||||
if vtx_size > self.vb_capacity {
|
||||
// reallocate vertex buffer
|
||||
todo!();
|
||||
}
|
||||
let idx_size = (idx_count * std::mem::size_of::<imgui::DrawIdx>()) as u64;
|
||||
if idx_size > self.ib_capacity {
|
||||
// reallocate index buffer
|
||||
todo!();
|
||||
}
|
||||
|
||||
let mut vb_offset = 0;
|
||||
let mut ib_offset = 0;
|
||||
|
||||
unsafe {
|
||||
let viewports = [D3D12_VIEWPORT {
|
||||
TopLeftX: 0.0,
|
||||
TopLeftY: 0.0,
|
||||
Width: window_width as f32,
|
||||
Height: window_height as f32,
|
||||
MinDepth: 0.0,
|
||||
MaxDepth: 1.0,
|
||||
}];
|
||||
cmd.RSSetViewports(viewports.len() as u32, viewports.as_ptr());
|
||||
|
||||
cmd.SetPipelineState(self.pipeline);
|
||||
cmd.SetGraphicsRootSignature(self.root_signature);
|
||||
cmd.IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
|
||||
|
||||
{
|
||||
let constant_buffer = self.constant_buffer.as_mut().unwrap();
|
||||
let addr = constant_buffer.GetGPUVirtualAddress();
|
||||
cmd.SetGraphicsRootConstantBufferView(0, addr);
|
||||
}
|
||||
|
||||
{
|
||||
let srv_stride =
|
||||
device.GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
|
||||
let heap_handle = descriptor_heap.GetGPUDescriptorHandleForHeapStart();
|
||||
let heap_handle = D3D12_GPU_DESCRIPTOR_HANDLE {
|
||||
ptr: heap_handle.ptr + srv_stride as u64 * self.font_image_srv_index as u64,
|
||||
};
|
||||
cmd.SetGraphicsRootDescriptorTable(1, heap_handle);
|
||||
}
|
||||
}
|
||||
|
||||
for draw_list in imgui_draw_data.draw_lists() {
|
||||
let vertices = draw_list.vtx_buffer();
|
||||
let indices = draw_list.idx_buffer();
|
||||
|
||||
let vbv = {
|
||||
let vertex_buffer = unsafe { self.vertex_buffer.as_mut().unwrap() };
|
||||
let stride = std::mem::size_of::<imgui::DrawVert>();
|
||||
let address =
|
||||
unsafe { vertex_buffer.GetGPUVirtualAddress() } + (vb_offset * stride) as u64;
|
||||
|
||||
D3D12_VERTEX_BUFFER_VIEW {
|
||||
BufferLocation: address,
|
||||
SizeInBytes: (vertices.len() * stride) as u32,
|
||||
StrideInBytes: stride as u32,
|
||||
}
|
||||
};
|
||||
let ibv = {
|
||||
let index_buffer = unsafe { self.index_buffer.as_mut().unwrap() };
|
||||
let stride = std::mem::size_of::<u16>();
|
||||
let address =
|
||||
unsafe { index_buffer.GetGPUVirtualAddress() } + (ib_offset * stride) as u64;
|
||||
|
||||
D3D12_INDEX_BUFFER_VIEW {
|
||||
BufferLocation: address,
|
||||
SizeInBytes: (indices.len() * stride) as u32,
|
||||
Format: all_dxgi::DXGI_FORMAT_R16_UINT,
|
||||
}
|
||||
};
|
||||
|
||||
// Upload vertices
|
||||
unsafe {
|
||||
let stride = std::mem::size_of::<imgui::DrawVert>();
|
||||
let dst_ptr = self
|
||||
.vb_pointer
|
||||
.add(vb_offset * stride)
|
||||
.cast::<imgui::DrawVert>();
|
||||
std::ptr::copy_nonoverlapping(vertices.as_ptr(), dst_ptr, vertices.len());
|
||||
}
|
||||
vb_offset += vertices.len();
|
||||
|
||||
// Upload indices
|
||||
unsafe {
|
||||
let stride = std::mem::size_of::<u16>();
|
||||
let dst_ptr = self.ib_pointer.add(ib_offset * stride).cast();
|
||||
std::ptr::copy_nonoverlapping(indices.as_ptr(), dst_ptr, indices.len());
|
||||
}
|
||||
ib_offset += indices.len();
|
||||
|
||||
unsafe {
|
||||
cmd.IASetVertexBuffers(0, 1, &vbv);
|
||||
cmd.IASetIndexBuffer(&ibv);
|
||||
};
|
||||
for command in draw_list.commands() {
|
||||
match command {
|
||||
imgui::DrawCmd::Elements { count, cmd_params } => {
|
||||
let scissor_rect = D3D12_RECT {
|
||||
left: cmd_params.clip_rect[0] as i32,
|
||||
top: cmd_params.clip_rect[1] as i32,
|
||||
right: cmd_params.clip_rect[2] as i32,
|
||||
bottom: cmd_params.clip_rect[3] as i32,
|
||||
};
|
||||
unsafe {
|
||||
cmd.RSSetScissorRects(1, &scissor_rect);
|
||||
cmd.DrawIndexedInstanced(
|
||||
count as u32,
|
||||
1,
|
||||
cmd_params.idx_offset as u32,
|
||||
cmd_params.vtx_offset as i32,
|
||||
0,
|
||||
);
|
||||
};
|
||||
}
|
||||
_ => todo!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn destroy(self, allocator: &mut Allocator) {
|
||||
unsafe { self.pipeline.as_ref().unwrap().Release() };
|
||||
|
||||
unsafe { self.font_image_upload_buffer.as_ref().unwrap().Release() };
|
||||
unsafe { self.vertex_buffer.as_ref().unwrap().Release() };
|
||||
unsafe { self.index_buffer.as_ref().unwrap().Release() };
|
||||
unsafe { self.constant_buffer.as_ref().unwrap().Release() };
|
||||
unsafe { self.font_image.as_ref().unwrap().Release() };
|
||||
|
||||
allocator
|
||||
.free(self.font_image_upload_buffer_memory)
|
||||
.unwrap();
|
||||
allocator.free(self.vb_allocation).unwrap();
|
||||
allocator.free(self.ib_allocation).unwrap();
|
||||
allocator.free(self.cb_allocation).unwrap();
|
||||
allocator.free(self.font_image_memory).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn handle_imgui_event(
|
||||
io: &mut imgui::Io,
|
||||
window: &winit::window::Window,
|
||||
event: &winit::event::Event<'_, ()>,
|
||||
) -> bool {
|
||||
use winit::event::{
|
||||
DeviceEvent, ElementState, Event, KeyboardInput, MouseButton, MouseScrollDelta, TouchPhase,
|
||||
VirtualKeyCode, WindowEvent,
|
||||
};
|
||||
|
||||
match event {
|
||||
Event::WindowEvent { event, window_id } if *window_id == window.id() => match *event {
|
||||
WindowEvent::Resized(physical_size) => {
|
||||
io.display_size = [physical_size.width as f32, physical_size.height as f32];
|
||||
false
|
||||
}
|
||||
WindowEvent::KeyboardInput {
|
||||
input:
|
||||
KeyboardInput {
|
||||
virtual_keycode: Some(key),
|
||||
state,
|
||||
..
|
||||
},
|
||||
..
|
||||
} => {
|
||||
let pressed = state == ElementState::Pressed;
|
||||
io.keys_down[key as usize] = pressed;
|
||||
match key {
|
||||
VirtualKeyCode::LShift | VirtualKeyCode::RShift => io.key_shift = pressed,
|
||||
VirtualKeyCode::LControl | VirtualKeyCode::RControl => io.key_ctrl = pressed,
|
||||
VirtualKeyCode::LAlt | VirtualKeyCode::RAlt => io.key_alt = pressed,
|
||||
VirtualKeyCode::LWin | VirtualKeyCode::RWin => io.key_super = pressed,
|
||||
_ => (),
|
||||
}
|
||||
|
||||
io.want_capture_keyboard
|
||||
}
|
||||
WindowEvent::ReceivedCharacter(ch) => {
|
||||
io.add_input_character(ch);
|
||||
|
||||
io.want_capture_keyboard
|
||||
}
|
||||
|
||||
WindowEvent::CursorMoved { position, .. } => {
|
||||
io.mouse_pos = [position.x as f32, position.y as f32];
|
||||
|
||||
io.want_capture_mouse
|
||||
}
|
||||
WindowEvent::MouseWheel {
|
||||
delta,
|
||||
phase: TouchPhase::Moved,
|
||||
..
|
||||
} => {
|
||||
match delta {
|
||||
MouseScrollDelta::LineDelta(h, v) => {
|
||||
io.mouse_wheel_h = h;
|
||||
io.mouse_wheel = v;
|
||||
}
|
||||
MouseScrollDelta::PixelDelta(pos) => {
|
||||
match pos.x.partial_cmp(&0.0) {
|
||||
Some(std::cmp::Ordering::Greater) => io.mouse_wheel_h += 1.0,
|
||||
Some(std::cmp::Ordering::Less) => io.mouse_wheel_h -= 1.0,
|
||||
_ => (),
|
||||
}
|
||||
match pos.y.partial_cmp(&0.0) {
|
||||
Some(std::cmp::Ordering::Greater) => io.mouse_wheel += 1.0,
|
||||
Some(std::cmp::Ordering::Less) => io.mouse_wheel -= 1.0,
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
io.want_capture_mouse
|
||||
}
|
||||
WindowEvent::MouseInput { state, button, .. } => {
|
||||
let pressed = state == ElementState::Pressed;
|
||||
match button {
|
||||
MouseButton::Left => io.mouse_down[0] = pressed,
|
||||
MouseButton::Right => io.mouse_down[1] = pressed,
|
||||
MouseButton::Middle => io.mouse_down[2] = pressed,
|
||||
MouseButton::Other(idx @ 0..=4) => io.mouse_down[idx as usize] = pressed,
|
||||
MouseButton::Other(_) => (),
|
||||
}
|
||||
|
||||
io.want_capture_mouse
|
||||
}
|
||||
_ => false,
|
||||
},
|
||||
// Track key release events outside our window. If we don't do this,
|
||||
// we might never see the release event if some other window gets focus.
|
||||
Event::DeviceEvent {
|
||||
event:
|
||||
DeviceEvent::Key(KeyboardInput {
|
||||
state: ElementState::Released,
|
||||
virtual_keycode: Some(key),
|
||||
..
|
||||
}),
|
||||
..
|
||||
} => {
|
||||
io.keys_down[*key as usize] = false;
|
||||
match *key {
|
||||
VirtualKeyCode::LShift | VirtualKeyCode::RShift => io.key_shift = false,
|
||||
VirtualKeyCode::LControl | VirtualKeyCode::RControl => io.key_ctrl = false,
|
||||
VirtualKeyCode::LAlt | VirtualKeyCode::RAlt => io.key_alt = false,
|
||||
VirtualKeyCode::LWin | VirtualKeyCode::RWin => io.key_super = false,
|
||||
_ => (),
|
||||
}
|
||||
|
||||
io.want_capture_keyboard
|
||||
}
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
});
|
||||
}
|
||||
14
third-party/vendor/gpu-allocator/examples/d3d12-visualization/shaders/imgui.ps.hlsl
vendored
Normal file
14
third-party/vendor/gpu-allocator/examples/d3d12-visualization/shaders/imgui.ps.hlsl
vendored
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
SamplerState g_sampler : register(s1, space0);
|
||||
Texture2D g_texture : register(t2, space0);
|
||||
|
||||
struct VertexInput
|
||||
{
|
||||
float4 position : SV_POSITION;
|
||||
float2 texCoord: TEXCOORD0;
|
||||
float4 color: COLOR;
|
||||
};
|
||||
|
||||
float4 main(VertexInput input) : SV_Target0
|
||||
{
|
||||
return input.color * g_texture.Sample(g_sampler, input.texCoord);
|
||||
}
|
||||
30
third-party/vendor/gpu-allocator/examples/d3d12-visualization/shaders/imgui.vs.hlsl
vendored
Normal file
30
third-party/vendor/gpu-allocator/examples/d3d12-visualization/shaders/imgui.vs.hlsl
vendored
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
struct VertexInput
|
||||
{
|
||||
float2 pos : POSITION;
|
||||
float2 texCoord : TEXCOORD0;
|
||||
float4 color: COLOR;
|
||||
};
|
||||
|
||||
struct VertexOutput
|
||||
{
|
||||
float4 position : SV_POSITION;
|
||||
float2 texCoord: TEXCOORD0;
|
||||
float4 color: COLOR;
|
||||
};
|
||||
|
||||
struct Constants
|
||||
{
|
||||
float2 scale;
|
||||
float2 translation;
|
||||
};
|
||||
|
||||
ConstantBuffer<Constants> g_constants : register(b0, space0);
|
||||
|
||||
VertexOutput main(VertexInput vertex)
|
||||
{
|
||||
VertexOutput o;
|
||||
o.position = float4(vertex.pos * g_constants.scale + g_constants.translation, 0.0, 1.0);
|
||||
o.texCoord = vertex.texCoord;
|
||||
o.color = vertex.color;
|
||||
return o;
|
||||
}
|
||||
206
third-party/vendor/gpu-allocator/examples/vulkan-buffer.rs
vendored
Normal file
206
third-party/vendor/gpu-allocator/examples/vulkan-buffer.rs
vendored
Normal file
|
|
@ -0,0 +1,206 @@
|
|||
use ash::vk;
|
||||
use log::info;
|
||||
|
||||
use std::default::Default;
|
||||
use std::ffi::CString;
|
||||
|
||||
use gpu_allocator::vulkan::{
|
||||
AllocationCreateDesc, AllocationScheme, Allocator, AllocatorCreateDesc,
|
||||
};
|
||||
use gpu_allocator::MemoryLocation;
|
||||
|
||||
fn main() {
|
||||
env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("trace")).init();
|
||||
|
||||
let entry = unsafe { ash::Entry::load() }.unwrap();
|
||||
|
||||
// Create Vulkan instance
|
||||
let instance = {
|
||||
let app_name = CString::new("Vulkan gpu-allocator test").unwrap();
|
||||
|
||||
let appinfo = vk::ApplicationInfo::builder()
|
||||
.application_name(&app_name)
|
||||
.application_version(0)
|
||||
.engine_name(&app_name)
|
||||
.engine_version(0)
|
||||
.api_version(vk::make_api_version(0, 1, 0, 0));
|
||||
|
||||
let layer_names = [CString::new("VK_LAYER_KHRONOS_validation").unwrap()];
|
||||
let layers_names_raw: Vec<*const i8> = layer_names
|
||||
.iter()
|
||||
.map(|raw_name| raw_name.as_ptr())
|
||||
.collect();
|
||||
|
||||
let extensions_names_raw = vec![];
|
||||
|
||||
let create_info = vk::InstanceCreateInfo::builder()
|
||||
.application_info(&appinfo)
|
||||
.enabled_layer_names(&layers_names_raw)
|
||||
.enabled_extension_names(&extensions_names_raw);
|
||||
|
||||
unsafe {
|
||||
entry
|
||||
.create_instance(&create_info, None)
|
||||
.expect("Instance creation error")
|
||||
}
|
||||
};
|
||||
|
||||
// Look for vulkan physical device
|
||||
let (pdevice, queue_family_index) = {
|
||||
let pdevices = unsafe {
|
||||
instance
|
||||
.enumerate_physical_devices()
|
||||
.expect("Physical device error")
|
||||
};
|
||||
pdevices
|
||||
.iter()
|
||||
.find_map(|pdevice| {
|
||||
unsafe { instance.get_physical_device_queue_family_properties(*pdevice) }
|
||||
.iter()
|
||||
.enumerate()
|
||||
.find_map(|(index, &info)| {
|
||||
let supports_graphics = info.queue_flags.contains(vk::QueueFlags::GRAPHICS);
|
||||
if supports_graphics {
|
||||
Some((*pdevice, index))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
})
|
||||
.expect("Couldn't find suitable device.")
|
||||
};
|
||||
|
||||
// Create vulkan device
|
||||
let device = {
|
||||
let device_extension_names_raw = vec![];
|
||||
let features = vk::PhysicalDeviceFeatures {
|
||||
shader_clip_distance: 1,
|
||||
..Default::default()
|
||||
};
|
||||
let priorities = [1.0];
|
||||
|
||||
let queue_info = vk::DeviceQueueCreateInfo::builder()
|
||||
.queue_family_index(queue_family_index as u32)
|
||||
.queue_priorities(&priorities);
|
||||
|
||||
let create_info = vk::DeviceCreateInfo::builder()
|
||||
.queue_create_infos(std::slice::from_ref(&queue_info))
|
||||
.enabled_extension_names(&device_extension_names_raw)
|
||||
.enabled_features(&features);
|
||||
|
||||
unsafe { instance.create_device(pdevice, &create_info, None).unwrap() }
|
||||
};
|
||||
|
||||
// Setting up the allocator
|
||||
let mut allocator = Allocator::new(&AllocatorCreateDesc {
|
||||
instance: instance.clone(),
|
||||
device: device.clone(),
|
||||
physical_device: pdevice,
|
||||
debug_settings: Default::default(),
|
||||
buffer_device_address: false,
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
// Test allocating Gpu Only memory
|
||||
{
|
||||
let test_buffer_info = vk::BufferCreateInfo::builder()
|
||||
.size(512)
|
||||
.usage(vk::BufferUsageFlags::STORAGE_BUFFER)
|
||||
.sharing_mode(vk::SharingMode::EXCLUSIVE);
|
||||
let test_buffer = unsafe { device.create_buffer(&test_buffer_info, None) }.unwrap();
|
||||
let requirements = unsafe { device.get_buffer_memory_requirements(test_buffer) };
|
||||
let location = MemoryLocation::GpuOnly;
|
||||
|
||||
let allocation = allocator
|
||||
.allocate(&AllocationCreateDesc {
|
||||
requirements,
|
||||
location,
|
||||
linear: true,
|
||||
allocation_scheme: AllocationScheme::GpuAllocatorManaged,
|
||||
name: "Test allocation (Gpu Only)",
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
unsafe {
|
||||
device
|
||||
.bind_buffer_memory(test_buffer, allocation.memory(), allocation.offset())
|
||||
.unwrap()
|
||||
};
|
||||
|
||||
allocator.free(allocation).unwrap();
|
||||
|
||||
unsafe { device.destroy_buffer(test_buffer, None) };
|
||||
|
||||
info!("Allocation and deallocation of GpuOnly memory was successful.");
|
||||
}
|
||||
|
||||
// Test allocating Cpu to Gpu memory
|
||||
{
|
||||
let test_buffer_info = vk::BufferCreateInfo::builder()
|
||||
.size(512)
|
||||
.usage(vk::BufferUsageFlags::STORAGE_BUFFER)
|
||||
.sharing_mode(vk::SharingMode::EXCLUSIVE);
|
||||
let test_buffer = unsafe { device.create_buffer(&test_buffer_info, None) }.unwrap();
|
||||
let requirements = unsafe { device.get_buffer_memory_requirements(test_buffer) };
|
||||
let location = MemoryLocation::CpuToGpu;
|
||||
|
||||
let allocation = allocator
|
||||
.allocate(&AllocationCreateDesc {
|
||||
requirements,
|
||||
location,
|
||||
linear: true,
|
||||
allocation_scheme: AllocationScheme::GpuAllocatorManaged,
|
||||
name: "Test allocation (Cpu to Gpu)",
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
unsafe {
|
||||
device
|
||||
.bind_buffer_memory(test_buffer, allocation.memory(), allocation.offset())
|
||||
.unwrap()
|
||||
};
|
||||
|
||||
allocator.free(allocation).unwrap();
|
||||
|
||||
unsafe { device.destroy_buffer(test_buffer, None) };
|
||||
|
||||
info!("Allocation and deallocation of CpuToGpu memory was successful.");
|
||||
}
|
||||
|
||||
// Test allocating Gpu to Cpu memory
|
||||
{
|
||||
let test_buffer_info = vk::BufferCreateInfo::builder()
|
||||
.size(512)
|
||||
.usage(vk::BufferUsageFlags::STORAGE_BUFFER)
|
||||
.sharing_mode(vk::SharingMode::EXCLUSIVE);
|
||||
let test_buffer = unsafe { device.create_buffer(&test_buffer_info, None) }.unwrap();
|
||||
let requirements = unsafe { device.get_buffer_memory_requirements(test_buffer) };
|
||||
let location = MemoryLocation::GpuToCpu;
|
||||
|
||||
let allocation = allocator
|
||||
.allocate(&AllocationCreateDesc {
|
||||
requirements,
|
||||
location,
|
||||
linear: true,
|
||||
allocation_scheme: AllocationScheme::GpuAllocatorManaged,
|
||||
name: "Test allocation (Gpu to Cpu)",
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
unsafe {
|
||||
device
|
||||
.bind_buffer_memory(test_buffer, allocation.memory(), allocation.offset())
|
||||
.unwrap()
|
||||
};
|
||||
|
||||
allocator.free(allocation).unwrap();
|
||||
|
||||
unsafe { device.destroy_buffer(test_buffer, None) };
|
||||
|
||||
info!("Allocation and deallocation of GpuToCpu memory was successful.");
|
||||
}
|
||||
|
||||
drop(allocator); // Explicitly drop before destruction of device and instance.
|
||||
unsafe { device.destroy_device(None) };
|
||||
unsafe { instance.destroy_instance(None) };
|
||||
}
|
||||
47
third-party/vendor/gpu-allocator/examples/vulkan-visualization/helper.rs
vendored
Normal file
47
third-party/vendor/gpu-allocator/examples/vulkan-visualization/helper.rs
vendored
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
use ash::vk;
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub(crate) fn record_and_submit_command_buffer<F: FnOnce(&ash::Device, vk::CommandBuffer)>(
|
||||
device: &ash::Device,
|
||||
command_buffer: vk::CommandBuffer,
|
||||
command_buffer_reuse_fence: vk::Fence,
|
||||
submit_queue: vk::Queue,
|
||||
wait_mask: &[vk::PipelineStageFlags],
|
||||
wait_semaphores: &[vk::Semaphore],
|
||||
signal_semaphores: &[vk::Semaphore],
|
||||
f: F,
|
||||
) {
|
||||
unsafe { device.wait_for_fences(&[command_buffer_reuse_fence], true, u64::MAX) }.unwrap();
|
||||
unsafe { device.reset_fences(&[command_buffer_reuse_fence]) }.unwrap();
|
||||
unsafe {
|
||||
device.reset_command_buffer(
|
||||
command_buffer,
|
||||
vk::CommandBufferResetFlags::RELEASE_RESOURCES,
|
||||
)
|
||||
}
|
||||
.unwrap();
|
||||
|
||||
let command_buffer_begin_info =
|
||||
vk::CommandBufferBeginInfo::builder().flags(vk::CommandBufferUsageFlags::ONE_TIME_SUBMIT);
|
||||
unsafe { device.begin_command_buffer(command_buffer, &command_buffer_begin_info) }.unwrap();
|
||||
|
||||
f(device, command_buffer);
|
||||
|
||||
unsafe { device.end_command_buffer(command_buffer) }.unwrap();
|
||||
|
||||
let command_buffers = [command_buffer];
|
||||
let submit_info = vk::SubmitInfo::builder()
|
||||
.wait_semaphores(wait_semaphores)
|
||||
.wait_dst_stage_mask(wait_mask)
|
||||
.command_buffers(&command_buffers)
|
||||
.signal_semaphores(signal_semaphores);
|
||||
|
||||
unsafe {
|
||||
device.queue_submit(
|
||||
submit_queue,
|
||||
std::slice::from_ref(&submit_info),
|
||||
command_buffer_reuse_fence,
|
||||
)
|
||||
}
|
||||
.unwrap();
|
||||
}
|
||||
953
third-party/vendor/gpu-allocator/examples/vulkan-visualization/imgui_renderer.rs
vendored
Normal file
953
third-party/vendor/gpu-allocator/examples/vulkan-visualization/imgui_renderer.rs
vendored
Normal file
|
|
@ -0,0 +1,953 @@
|
|||
use ash::vk;
|
||||
|
||||
use crate::helper::record_and_submit_command_buffer;
|
||||
use gpu_allocator::vulkan::{Allocation, AllocationCreateDesc, AllocationScheme, Allocator};
|
||||
use gpu_allocator::MemoryLocation;
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy)]
|
||||
struct ImGuiCBuffer {
|
||||
scale: [f32; 2],
|
||||
translation: [f32; 2],
|
||||
}
|
||||
pub struct ImGuiRenderer {
|
||||
sampler: vk::Sampler,
|
||||
|
||||
vb_capacity: u64,
|
||||
ib_capacity: u64,
|
||||
vb_allocation: Allocation,
|
||||
ib_allocation: Allocation,
|
||||
vertex_buffer: vk::Buffer,
|
||||
index_buffer: vk::Buffer,
|
||||
|
||||
cb_allocation: Allocation,
|
||||
constant_buffer: vk::Buffer,
|
||||
|
||||
font_image: vk::Image,
|
||||
font_image_memory: Allocation,
|
||||
font_image_view: vk::ImageView,
|
||||
|
||||
descriptor_sets: Vec<vk::DescriptorSet>,
|
||||
|
||||
vs_module: vk::ShaderModule,
|
||||
ps_module: vk::ShaderModule,
|
||||
descriptor_set_layouts: Vec<vk::DescriptorSetLayout>,
|
||||
pipeline_layout: vk::PipelineLayout,
|
||||
pub(crate) render_pass: vk::RenderPass,
|
||||
pipeline: vk::Pipeline,
|
||||
}
|
||||
|
||||
impl ImGuiRenderer {
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub(crate) fn new(
|
||||
imgui: &mut imgui::Context,
|
||||
device: &ash::Device,
|
||||
descriptor_pool: vk::DescriptorPool,
|
||||
render_target_format: vk::Format,
|
||||
allocator: &mut Allocator,
|
||||
cmd: vk::CommandBuffer,
|
||||
cmd_reuse_fence: vk::Fence,
|
||||
queue: vk::Queue,
|
||||
) -> Result<Self, vk::Result> {
|
||||
let (pipeline_layout, descriptor_set_layouts) = {
|
||||
let bindings = [
|
||||
vk::DescriptorSetLayoutBinding {
|
||||
binding: 0,
|
||||
descriptor_type: vk::DescriptorType::UNIFORM_BUFFER,
|
||||
descriptor_count: 1,
|
||||
stage_flags: vk::ShaderStageFlags::VERTEX,
|
||||
p_immutable_samplers: std::ptr::null(),
|
||||
},
|
||||
vk::DescriptorSetLayoutBinding {
|
||||
binding: 1,
|
||||
descriptor_type: vk::DescriptorType::SAMPLER,
|
||||
descriptor_count: 1,
|
||||
stage_flags: vk::ShaderStageFlags::FRAGMENT,
|
||||
p_immutable_samplers: std::ptr::null(),
|
||||
},
|
||||
vk::DescriptorSetLayoutBinding {
|
||||
binding: 2,
|
||||
descriptor_type: vk::DescriptorType::SAMPLED_IMAGE,
|
||||
descriptor_count: 1,
|
||||
stage_flags: vk::ShaderStageFlags::FRAGMENT,
|
||||
p_immutable_samplers: std::ptr::null(),
|
||||
},
|
||||
];
|
||||
|
||||
let set_layout_infos =
|
||||
[vk::DescriptorSetLayoutCreateInfo::builder().bindings(&bindings)];
|
||||
let set_layouts = set_layout_infos
|
||||
.iter()
|
||||
.map(|info| unsafe { device.create_descriptor_set_layout(info, None) })
|
||||
.collect::<Result<Vec<_>, vk::Result>>()?;
|
||||
|
||||
let layout_info = vk::PipelineLayoutCreateInfo::builder().set_layouts(&set_layouts);
|
||||
let pipeline_layout = unsafe { device.create_pipeline_layout(&layout_info, None) }?;
|
||||
|
||||
(pipeline_layout, set_layouts)
|
||||
};
|
||||
|
||||
let render_pass = {
|
||||
let attachments = vk::AttachmentDescription::builder()
|
||||
.format(render_target_format)
|
||||
.samples(vk::SampleCountFlags::TYPE_1)
|
||||
.load_op(vk::AttachmentLoadOp::CLEAR)
|
||||
.store_op(vk::AttachmentStoreOp::STORE)
|
||||
.final_layout(vk::ImageLayout::COLOR_ATTACHMENT_OPTIMAL);
|
||||
|
||||
let subpass_attachment = vk::AttachmentReference::builder()
|
||||
.attachment(0)
|
||||
.layout(vk::ImageLayout::COLOR_ATTACHMENT_OPTIMAL);
|
||||
let subpass_description = vk::SubpassDescription::builder()
|
||||
.pipeline_bind_point(vk::PipelineBindPoint::GRAPHICS)
|
||||
.color_attachments(std::slice::from_ref(&subpass_attachment));
|
||||
|
||||
let dependencies = vk::SubpassDependency::builder()
|
||||
.src_subpass(vk::SUBPASS_EXTERNAL)
|
||||
.src_stage_mask(vk::PipelineStageFlags::COLOR_ATTACHMENT_OUTPUT)
|
||||
.dst_access_mask(
|
||||
vk::AccessFlags::COLOR_ATTACHMENT_READ
|
||||
| vk::AccessFlags::COLOR_ATTACHMENT_WRITE,
|
||||
)
|
||||
.dst_stage_mask(vk::PipelineStageFlags::COLOR_ATTACHMENT_OUTPUT);
|
||||
|
||||
let render_pass_create_info = vk::RenderPassCreateInfo::builder()
|
||||
.attachments(std::slice::from_ref(&attachments))
|
||||
.subpasses(std::slice::from_ref(&subpass_description))
|
||||
.dependencies(std::slice::from_ref(&dependencies));
|
||||
unsafe { device.create_render_pass(&render_pass_create_info, None) }.unwrap()
|
||||
};
|
||||
|
||||
let vs_module = {
|
||||
let vs = include_bytes!("./spirv/imgui.vs.spv");
|
||||
|
||||
#[allow(clippy::cast_ptr_alignment)]
|
||||
let shader_info = vk::ShaderModuleCreateInfo::builder().code(unsafe {
|
||||
assert_eq!(vs.len() % 4, 0);
|
||||
std::slice::from_raw_parts(vs.as_ptr().cast(), vs.len() / 4)
|
||||
});
|
||||
unsafe { device.create_shader_module(&shader_info, None) }?
|
||||
};
|
||||
let ps_module = {
|
||||
let ps = include_bytes!("./spirv/imgui.ps.spv");
|
||||
|
||||
#[allow(clippy::cast_ptr_alignment)]
|
||||
let shader_info = vk::ShaderModuleCreateInfo::builder().code(unsafe {
|
||||
assert_eq!(ps.len() % 4, 0);
|
||||
std::slice::from_raw_parts(ps.as_ptr().cast(), ps.len() / 4)
|
||||
});
|
||||
unsafe { device.create_shader_module(&shader_info, None) }?
|
||||
};
|
||||
|
||||
let pipeline = {
|
||||
let vertex_stage = vk::PipelineShaderStageCreateInfo::builder()
|
||||
.stage(vk::ShaderStageFlags::VERTEX)
|
||||
.module(vs_module)
|
||||
.name(std::ffi::CStr::from_bytes_with_nul(b"main\0").unwrap());
|
||||
let fragment_stage = vk::PipelineShaderStageCreateInfo::builder()
|
||||
.stage(vk::ShaderStageFlags::FRAGMENT)
|
||||
.module(ps_module)
|
||||
.name(std::ffi::CStr::from_bytes_with_nul(b"main\0").unwrap());
|
||||
let stages = [vertex_stage.build(), fragment_stage.build()];
|
||||
|
||||
let vertex_binding_descriptions = [vk::VertexInputBindingDescription {
|
||||
binding: 0,
|
||||
stride: std::mem::size_of::<imgui::DrawVert>() as u32,
|
||||
input_rate: vk::VertexInputRate::VERTEX,
|
||||
}];
|
||||
let vertex_attribute_descriptions = [
|
||||
vk::VertexInputAttributeDescription {
|
||||
location: 0,
|
||||
binding: 0,
|
||||
format: vk::Format::R32G32_SFLOAT,
|
||||
offset: 0,
|
||||
},
|
||||
vk::VertexInputAttributeDescription {
|
||||
location: 1,
|
||||
binding: 0,
|
||||
format: vk::Format::R32G32_SFLOAT,
|
||||
offset: 8,
|
||||
},
|
||||
vk::VertexInputAttributeDescription {
|
||||
location: 2,
|
||||
binding: 0,
|
||||
format: vk::Format::R8G8B8A8_UNORM,
|
||||
offset: 16,
|
||||
},
|
||||
];
|
||||
let vertex_input_state = vk::PipelineVertexInputStateCreateInfo::builder()
|
||||
.vertex_binding_descriptions(&vertex_binding_descriptions)
|
||||
.vertex_attribute_descriptions(&vertex_attribute_descriptions);
|
||||
let input_assembly_state = vk::PipelineInputAssemblyStateCreateInfo::builder()
|
||||
.topology(vk::PrimitiveTopology::TRIANGLE_LIST);
|
||||
let viewport_state = vk::PipelineViewportStateCreateInfo::builder()
|
||||
.viewport_count(1)
|
||||
.scissor_count(1);
|
||||
let rasterization_state = vk::PipelineRasterizationStateCreateInfo::builder()
|
||||
.polygon_mode(vk::PolygonMode::FILL)
|
||||
.cull_mode(vk::CullModeFlags::NONE)
|
||||
.front_face(vk::FrontFace::CLOCKWISE)
|
||||
.depth_bias_enable(false)
|
||||
.line_width(1.0);
|
||||
let multisample_state = vk::PipelineMultisampleStateCreateInfo::builder()
|
||||
.rasterization_samples(vk::SampleCountFlags::TYPE_1);
|
||||
let noop_stencil_state = vk::StencilOpState {
|
||||
fail_op: vk::StencilOp::KEEP,
|
||||
pass_op: vk::StencilOp::KEEP,
|
||||
depth_fail_op: vk::StencilOp::KEEP,
|
||||
compare_op: vk::CompareOp::ALWAYS,
|
||||
..Default::default()
|
||||
};
|
||||
let depth_stencil_state = vk::PipelineDepthStencilStateCreateInfo::builder()
|
||||
.depth_test_enable(false)
|
||||
.depth_write_enable(false)
|
||||
.depth_compare_op(vk::CompareOp::ALWAYS)
|
||||
.depth_bounds_test_enable(false)
|
||||
.stencil_test_enable(false)
|
||||
.front(noop_stencil_state)
|
||||
.back(noop_stencil_state)
|
||||
.max_depth_bounds(1.0);
|
||||
let attachments = vk::PipelineColorBlendAttachmentState::builder()
|
||||
.blend_enable(true)
|
||||
.src_color_blend_factor(vk::BlendFactor::SRC_ALPHA)
|
||||
.dst_color_blend_factor(vk::BlendFactor::ONE_MINUS_SRC_ALPHA)
|
||||
.color_blend_op(vk::BlendOp::ADD)
|
||||
.src_alpha_blend_factor(vk::BlendFactor::ZERO)
|
||||
.dst_alpha_blend_factor(vk::BlendFactor::ZERO)
|
||||
.alpha_blend_op(vk::BlendOp::ADD)
|
||||
.color_write_mask({
|
||||
vk::ColorComponentFlags::R
|
||||
| vk::ColorComponentFlags::G
|
||||
| vk::ColorComponentFlags::B
|
||||
| vk::ColorComponentFlags::A
|
||||
});
|
||||
let color_blend_state = vk::PipelineColorBlendStateCreateInfo::builder()
|
||||
.logic_op(vk::LogicOp::CLEAR)
|
||||
.attachments(std::slice::from_ref(&attachments));
|
||||
let dynamic_state = vk::PipelineDynamicStateCreateInfo::builder()
|
||||
.dynamic_states(&[vk::DynamicState::VIEWPORT, vk::DynamicState::SCISSOR]);
|
||||
|
||||
let pipeline_create_info = vk::GraphicsPipelineCreateInfo::builder()
|
||||
.stages(&stages)
|
||||
.vertex_input_state(&vertex_input_state)
|
||||
.input_assembly_state(&input_assembly_state)
|
||||
.viewport_state(&viewport_state)
|
||||
.rasterization_state(&rasterization_state)
|
||||
.multisample_state(&multisample_state)
|
||||
.depth_stencil_state(&depth_stencil_state)
|
||||
.color_blend_state(&color_blend_state)
|
||||
.dynamic_state(&dynamic_state)
|
||||
.layout(pipeline_layout)
|
||||
.render_pass(render_pass)
|
||||
.subpass(0);
|
||||
|
||||
unsafe {
|
||||
device.create_graphics_pipelines(
|
||||
vk::PipelineCache::null(),
|
||||
std::slice::from_ref(&pipeline_create_info),
|
||||
None,
|
||||
)
|
||||
}
|
||||
.unwrap()[0]
|
||||
};
|
||||
|
||||
let (font_image, font_image_memory, font_image_view) = {
|
||||
let fonts = imgui.fonts();
|
||||
let font_atlas = fonts.build_rgba32_texture();
|
||||
|
||||
// Create image
|
||||
let image_usage = vk::ImageUsageFlags::SAMPLED
|
||||
| vk::ImageUsageFlags::TRANSFER_DST
|
||||
| vk::ImageUsageFlags::TRANSFER_SRC;
|
||||
let create_info = vk::ImageCreateInfo::builder()
|
||||
.image_type(vk::ImageType::TYPE_2D)
|
||||
.format(vk::Format::R8G8B8A8_UNORM)
|
||||
.extent(vk::Extent3D {
|
||||
width: font_atlas.width,
|
||||
height: font_atlas.height,
|
||||
depth: 1,
|
||||
})
|
||||
.mip_levels(1)
|
||||
.array_layers(1)
|
||||
.samples(vk::SampleCountFlags::TYPE_1)
|
||||
.tiling(vk::ImageTiling::OPTIMAL)
|
||||
.usage(image_usage)
|
||||
.initial_layout(vk::ImageLayout::UNDEFINED);
|
||||
let image = unsafe { device.create_image(&create_info, None) }?;
|
||||
|
||||
// Allocate and bind memory to image
|
||||
let requirements = unsafe { device.get_image_memory_requirements(image) };
|
||||
let allocation = allocator
|
||||
.allocate(&AllocationCreateDesc {
|
||||
name: "ImGui font image",
|
||||
requirements,
|
||||
location: MemoryLocation::GpuOnly,
|
||||
linear: false,
|
||||
allocation_scheme: AllocationScheme::GpuAllocatorManaged,
|
||||
})
|
||||
.unwrap();
|
||||
unsafe { device.bind_image_memory(image, allocation.memory(), allocation.offset()) }
|
||||
.unwrap();
|
||||
|
||||
// Create image view
|
||||
let view_create_info = vk::ImageViewCreateInfo::builder()
|
||||
.image(image)
|
||||
.view_type(vk::ImageViewType::TYPE_2D)
|
||||
.format(vk::Format::R8G8B8A8_UNORM)
|
||||
.components(vk::ComponentMapping {
|
||||
r: vk::ComponentSwizzle::R,
|
||||
g: vk::ComponentSwizzle::G,
|
||||
b: vk::ComponentSwizzle::B,
|
||||
a: vk::ComponentSwizzle::A,
|
||||
})
|
||||
.subresource_range(vk::ImageSubresourceRange {
|
||||
aspect_mask: vk::ImageAspectFlags::COLOR,
|
||||
base_mip_level: 0,
|
||||
level_count: 1,
|
||||
base_array_layer: 0,
|
||||
layer_count: 1,
|
||||
});
|
||||
let image_view = unsafe { device.create_image_view(&view_create_info, None) }?;
|
||||
|
||||
// Create upload buffer
|
||||
let (upload_buffer, upload_buffer_memory) = {
|
||||
let create_info = vk::BufferCreateInfo::builder()
|
||||
.size((font_atlas.width * font_atlas.height * 4) as u64)
|
||||
.usage(vk::BufferUsageFlags::TRANSFER_SRC);
|
||||
let buffer = unsafe { device.create_buffer(&create_info, None) }?;
|
||||
|
||||
let requirements = unsafe { device.get_buffer_memory_requirements(buffer) };
|
||||
|
||||
let buffer_memory = allocator
|
||||
.allocate(&AllocationCreateDesc {
|
||||
name: "ImGui font image upload buffer",
|
||||
requirements,
|
||||
location: MemoryLocation::CpuToGpu,
|
||||
linear: true,
|
||||
allocation_scheme: AllocationScheme::GpuAllocatorManaged,
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
unsafe {
|
||||
device.bind_buffer_memory(
|
||||
buffer,
|
||||
buffer_memory.memory(),
|
||||
buffer_memory.offset(),
|
||||
)
|
||||
}?;
|
||||
|
||||
(buffer, buffer_memory)
|
||||
};
|
||||
|
||||
// Copy font data to upload buffer
|
||||
let dst = upload_buffer_memory.mapped_ptr().unwrap().cast().as_ptr();
|
||||
unsafe {
|
||||
std::ptr::copy_nonoverlapping(
|
||||
font_atlas.data.as_ptr(),
|
||||
dst,
|
||||
(font_atlas.width * font_atlas.height * 4) as usize,
|
||||
);
|
||||
}
|
||||
|
||||
// Copy upload buffer to image
|
||||
record_and_submit_command_buffer(
|
||||
device,
|
||||
cmd,
|
||||
cmd_reuse_fence,
|
||||
queue,
|
||||
&[],
|
||||
&[],
|
||||
&[],
|
||||
|device, cmd| {
|
||||
{
|
||||
let layout_transition_barriers = vk::ImageMemoryBarrier::builder()
|
||||
.image(image)
|
||||
.dst_access_mask(vk::AccessFlags::TRANSFER_WRITE)
|
||||
.new_layout(vk::ImageLayout::TRANSFER_DST_OPTIMAL)
|
||||
.old_layout(vk::ImageLayout::UNDEFINED)
|
||||
.subresource_range(vk::ImageSubresourceRange {
|
||||
aspect_mask: vk::ImageAspectFlags::COLOR,
|
||||
base_mip_level: 0,
|
||||
level_count: vk::REMAINING_MIP_LEVELS,
|
||||
base_array_layer: 0,
|
||||
layer_count: vk::REMAINING_ARRAY_LAYERS,
|
||||
});
|
||||
|
||||
unsafe {
|
||||
device.cmd_pipeline_barrier(
|
||||
cmd,
|
||||
vk::PipelineStageFlags::BOTTOM_OF_PIPE,
|
||||
vk::PipelineStageFlags::TRANSFER,
|
||||
vk::DependencyFlags::empty(),
|
||||
&[],
|
||||
&[],
|
||||
std::slice::from_ref(&layout_transition_barriers),
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
let regions = vk::BufferImageCopy::builder()
|
||||
.buffer_offset(0)
|
||||
.buffer_row_length(font_atlas.width)
|
||||
.buffer_image_height(font_atlas.height)
|
||||
.image_subresource(vk::ImageSubresourceLayers {
|
||||
aspect_mask: vk::ImageAspectFlags::COLOR,
|
||||
mip_level: 0,
|
||||
base_array_layer: 0,
|
||||
layer_count: 1,
|
||||
})
|
||||
.image_offset(vk::Offset3D { x: 0, y: 0, z: 0 })
|
||||
.image_extent(vk::Extent3D {
|
||||
width: font_atlas.width,
|
||||
height: font_atlas.height,
|
||||
depth: 1,
|
||||
});
|
||||
unsafe {
|
||||
device.cmd_copy_buffer_to_image(
|
||||
cmd,
|
||||
upload_buffer,
|
||||
image,
|
||||
vk::ImageLayout::TRANSFER_DST_OPTIMAL,
|
||||
std::slice::from_ref(®ions),
|
||||
)
|
||||
};
|
||||
|
||||
{
|
||||
let layout_transition_barriers = vk::ImageMemoryBarrier::builder()
|
||||
.image(image)
|
||||
.dst_access_mask(vk::AccessFlags::SHADER_READ)
|
||||
.new_layout(vk::ImageLayout::SHADER_READ_ONLY_OPTIMAL)
|
||||
.old_layout(vk::ImageLayout::TRANSFER_DST_OPTIMAL)
|
||||
.subresource_range(vk::ImageSubresourceRange {
|
||||
aspect_mask: vk::ImageAspectFlags::COLOR,
|
||||
base_mip_level: 0,
|
||||
level_count: vk::REMAINING_MIP_LEVELS,
|
||||
base_array_layer: 0,
|
||||
layer_count: vk::REMAINING_ARRAY_LAYERS,
|
||||
});
|
||||
|
||||
unsafe {
|
||||
device.cmd_pipeline_barrier(
|
||||
cmd,
|
||||
vk::PipelineStageFlags::BOTTOM_OF_PIPE,
|
||||
vk::PipelineStageFlags::FRAGMENT_SHADER,
|
||||
vk::DependencyFlags::empty(),
|
||||
&[],
|
||||
&[],
|
||||
std::slice::from_ref(&layout_transition_barriers),
|
||||
)
|
||||
};
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
unsafe { device.queue_wait_idle(queue) }?;
|
||||
|
||||
// Free upload buffer
|
||||
unsafe { device.destroy_buffer(upload_buffer, None) };
|
||||
allocator.free(upload_buffer_memory).unwrap();
|
||||
|
||||
(image, allocation, image_view)
|
||||
};
|
||||
|
||||
let sampler = {
|
||||
let create_info = vk::SamplerCreateInfo::builder()
|
||||
.mag_filter(vk::Filter::NEAREST)
|
||||
.min_filter(vk::Filter::NEAREST)
|
||||
.mipmap_mode(vk::SamplerMipmapMode::NEAREST)
|
||||
.address_mode_u(vk::SamplerAddressMode::REPEAT)
|
||||
.address_mode_v(vk::SamplerAddressMode::REPEAT)
|
||||
.address_mode_w(vk::SamplerAddressMode::REPEAT)
|
||||
.mip_lod_bias(0.0)
|
||||
.anisotropy_enable(false)
|
||||
.compare_enable(false)
|
||||
.unnormalized_coordinates(false);
|
||||
unsafe { device.create_sampler(&create_info, None) }?
|
||||
};
|
||||
|
||||
let (vertex_buffer, vb_allocation, vb_capacity) = {
|
||||
let capacity = 1024 * 1024;
|
||||
|
||||
let create_info = vk::BufferCreateInfo::builder()
|
||||
.size(capacity)
|
||||
.usage(vk::BufferUsageFlags::VERTEX_BUFFER)
|
||||
.sharing_mode(vk::SharingMode::EXCLUSIVE);
|
||||
|
||||
let buffer = unsafe { device.create_buffer(&create_info, None) }?;
|
||||
|
||||
let requirements = unsafe { device.get_buffer_memory_requirements(buffer) };
|
||||
|
||||
let allocation = allocator
|
||||
.allocate(&AllocationCreateDesc {
|
||||
name: "ImGui Vertex buffer",
|
||||
requirements,
|
||||
location: MemoryLocation::CpuToGpu,
|
||||
linear: true,
|
||||
allocation_scheme: AllocationScheme::GpuAllocatorManaged,
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
unsafe { device.bind_buffer_memory(buffer, allocation.memory(), allocation.offset()) }?;
|
||||
|
||||
(buffer, allocation, capacity)
|
||||
};
|
||||
let (index_buffer, ib_allocation, ib_capacity) = {
|
||||
let capacity = 1024 * 1024;
|
||||
|
||||
let create_info = vk::BufferCreateInfo::builder()
|
||||
.size(capacity)
|
||||
.usage(vk::BufferUsageFlags::INDEX_BUFFER)
|
||||
.sharing_mode(vk::SharingMode::EXCLUSIVE);
|
||||
|
||||
let buffer = unsafe { device.create_buffer(&create_info, None) }?;
|
||||
|
||||
let requirements = unsafe { device.get_buffer_memory_requirements(buffer) };
|
||||
|
||||
let allocation = allocator
|
||||
.allocate(&AllocationCreateDesc {
|
||||
name: "ImGui Index buffer",
|
||||
requirements,
|
||||
location: MemoryLocation::CpuToGpu,
|
||||
linear: true,
|
||||
allocation_scheme: AllocationScheme::GpuAllocatorManaged,
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
unsafe { device.bind_buffer_memory(buffer, allocation.memory(), allocation.offset()) }?;
|
||||
|
||||
(buffer, allocation, capacity)
|
||||
};
|
||||
let (constant_buffer, cb_allocation) = {
|
||||
let create_info = vk::BufferCreateInfo::builder()
|
||||
.size(std::mem::size_of::<ImGuiCBuffer>() as u64)
|
||||
.usage(vk::BufferUsageFlags::UNIFORM_BUFFER)
|
||||
.sharing_mode(vk::SharingMode::EXCLUSIVE);
|
||||
|
||||
let buffer = unsafe { device.create_buffer(&create_info, None) }?;
|
||||
|
||||
let requirements = unsafe { device.get_buffer_memory_requirements(buffer) };
|
||||
|
||||
let allocation = allocator
|
||||
.allocate(&AllocationCreateDesc {
|
||||
name: "ImGui Constant buffer",
|
||||
requirements,
|
||||
location: MemoryLocation::CpuToGpu,
|
||||
linear: true,
|
||||
allocation_scheme: AllocationScheme::GpuAllocatorManaged,
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
unsafe { device.bind_buffer_memory(buffer, allocation.memory(), allocation.offset()) }?;
|
||||
|
||||
(buffer, allocation)
|
||||
};
|
||||
|
||||
let descriptor_sets = {
|
||||
let alloc_info = vk::DescriptorSetAllocateInfo::builder()
|
||||
.descriptor_pool(descriptor_pool)
|
||||
.set_layouts(&descriptor_set_layouts);
|
||||
let descriptor_sets = unsafe { device.allocate_descriptor_sets(&alloc_info) }?;
|
||||
|
||||
let buffer_info = vk::DescriptorBufferInfo::builder()
|
||||
.buffer(constant_buffer)
|
||||
.offset(0)
|
||||
.range(std::mem::size_of::<ImGuiCBuffer>() as u64);
|
||||
let uniform_buffer = vk::WriteDescriptorSet::builder()
|
||||
.dst_set(descriptor_sets[0])
|
||||
.dst_binding(0)
|
||||
.descriptor_type(vk::DescriptorType::UNIFORM_BUFFER)
|
||||
.buffer_info(std::slice::from_ref(&buffer_info));
|
||||
|
||||
let image_info = vk::DescriptorImageInfo::builder().sampler(sampler);
|
||||
let sampler = vk::WriteDescriptorSet::builder()
|
||||
.dst_set(descriptor_sets[0])
|
||||
.dst_binding(1)
|
||||
.descriptor_type(vk::DescriptorType::SAMPLER)
|
||||
.image_info(std::slice::from_ref(&image_info));
|
||||
|
||||
let image_info = vk::DescriptorImageInfo::builder()
|
||||
.image_view(font_image_view)
|
||||
.image_layout(vk::ImageLayout::SHADER_READ_ONLY_OPTIMAL);
|
||||
let sampled_image = vk::WriteDescriptorSet::builder()
|
||||
.dst_set(descriptor_sets[0])
|
||||
.dst_binding(2)
|
||||
.descriptor_type(vk::DescriptorType::SAMPLED_IMAGE)
|
||||
.image_info(std::slice::from_ref(&image_info));
|
||||
|
||||
unsafe {
|
||||
device.update_descriptor_sets(
|
||||
&[
|
||||
uniform_buffer.build(),
|
||||
sampler.build(),
|
||||
sampled_image.build(),
|
||||
],
|
||||
&[],
|
||||
)
|
||||
};
|
||||
descriptor_sets
|
||||
};
|
||||
|
||||
Ok(Self {
|
||||
sampler,
|
||||
|
||||
vb_capacity,
|
||||
ib_capacity,
|
||||
vb_allocation,
|
||||
ib_allocation,
|
||||
vertex_buffer,
|
||||
index_buffer,
|
||||
cb_allocation,
|
||||
constant_buffer,
|
||||
|
||||
font_image,
|
||||
font_image_memory,
|
||||
font_image_view,
|
||||
|
||||
descriptor_sets,
|
||||
|
||||
vs_module,
|
||||
ps_module,
|
||||
descriptor_set_layouts,
|
||||
pipeline_layout,
|
||||
render_pass,
|
||||
pipeline,
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn render(
|
||||
&mut self,
|
||||
imgui_draw_data: &imgui::DrawData,
|
||||
device: &ash::Device,
|
||||
window_width: u32,
|
||||
window_height: u32,
|
||||
framebuffer: vk::Framebuffer,
|
||||
cmd: vk::CommandBuffer,
|
||||
) {
|
||||
// Update constant buffer
|
||||
{
|
||||
let left = imgui_draw_data.display_pos[0];
|
||||
let right = imgui_draw_data.display_pos[0] + imgui_draw_data.display_size[0];
|
||||
let top = imgui_draw_data.display_pos[1];
|
||||
let bottom = imgui_draw_data.display_pos[1] + imgui_draw_data.display_size[1];
|
||||
|
||||
let cbuffer_data = ImGuiCBuffer {
|
||||
scale: [(2.0 / (right - left)), (2.0 / (bottom - top))],
|
||||
translation: [
|
||||
(right + left) / (left - right),
|
||||
(top + bottom) / (top - bottom),
|
||||
],
|
||||
};
|
||||
|
||||
unsafe {
|
||||
std::ptr::copy_nonoverlapping(
|
||||
&cbuffer_data,
|
||||
self.cb_allocation.mapped_ptr().unwrap().cast().as_ptr(),
|
||||
1,
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
let render_pass_begin_info = vk::RenderPassBeginInfo::builder()
|
||||
.render_pass(self.render_pass)
|
||||
.framebuffer(framebuffer)
|
||||
.render_area(vk::Rect2D {
|
||||
offset: vk::Offset2D { x: 0, y: 0 },
|
||||
extent: vk::Extent2D {
|
||||
width: window_width,
|
||||
height: window_height,
|
||||
},
|
||||
})
|
||||
.clear_values(&[vk::ClearValue {
|
||||
color: vk::ClearColorValue {
|
||||
float32: [1.0, 0.5, 1.0, 0.0],
|
||||
},
|
||||
}]);
|
||||
unsafe {
|
||||
device.cmd_begin_render_pass(cmd, &render_pass_begin_info, vk::SubpassContents::INLINE)
|
||||
};
|
||||
|
||||
unsafe { device.cmd_bind_pipeline(cmd, vk::PipelineBindPoint::GRAPHICS, self.pipeline) };
|
||||
|
||||
let viewport = vk::Viewport::builder()
|
||||
.x(0.0)
|
||||
.y(0.0)
|
||||
.width(window_width as f32)
|
||||
.height(window_height as f32);
|
||||
unsafe { device.cmd_set_viewport(cmd, 0, std::slice::from_ref(&viewport)) };
|
||||
{
|
||||
let scissor_rect = vk::Rect2D {
|
||||
offset: vk::Offset2D { x: 0, y: 0 },
|
||||
extent: vk::Extent2D {
|
||||
width: window_width,
|
||||
height: window_height,
|
||||
},
|
||||
};
|
||||
unsafe { device.cmd_set_scissor(cmd, 0, &[scissor_rect]) };
|
||||
}
|
||||
|
||||
unsafe {
|
||||
device.cmd_bind_descriptor_sets(
|
||||
cmd,
|
||||
vk::PipelineBindPoint::GRAPHICS,
|
||||
self.pipeline_layout,
|
||||
0,
|
||||
&self.descriptor_sets,
|
||||
&[],
|
||||
)
|
||||
};
|
||||
|
||||
let (vtx_count, idx_count) =
|
||||
imgui_draw_data
|
||||
.draw_lists()
|
||||
.fold((0, 0), |(vtx_count, idx_count), draw_list| {
|
||||
(
|
||||
vtx_count + draw_list.vtx_buffer().len(),
|
||||
idx_count + draw_list.idx_buffer().len(),
|
||||
)
|
||||
});
|
||||
|
||||
let vtx_size = (vtx_count * std::mem::size_of::<imgui::DrawVert>()) as u64;
|
||||
if vtx_size > self.vb_capacity {
|
||||
// reallocate vertex buffer
|
||||
todo!();
|
||||
}
|
||||
let idx_size = (idx_count * std::mem::size_of::<imgui::DrawIdx>()) as u64;
|
||||
if idx_size > self.ib_capacity {
|
||||
// reallocate index buffer
|
||||
todo!();
|
||||
}
|
||||
|
||||
let mut vb_offset = 0;
|
||||
let mut ib_offset = 0;
|
||||
|
||||
for draw_list in imgui_draw_data.draw_lists() {
|
||||
unsafe {
|
||||
device.cmd_bind_vertex_buffers(
|
||||
cmd,
|
||||
0,
|
||||
&[self.vertex_buffer],
|
||||
&[vb_offset as u64 * std::mem::size_of::<imgui::DrawVert>() as u64],
|
||||
)
|
||||
};
|
||||
unsafe {
|
||||
device.cmd_bind_index_buffer(
|
||||
cmd,
|
||||
self.index_buffer,
|
||||
ib_offset as u64 * std::mem::size_of::<imgui::DrawIdx>() as u64,
|
||||
vk::IndexType::UINT16,
|
||||
)
|
||||
};
|
||||
|
||||
{
|
||||
let vertices = draw_list.vtx_buffer();
|
||||
let dst_ptr = self
|
||||
.vb_allocation
|
||||
.mapped_ptr()
|
||||
.unwrap()
|
||||
.cast::<imgui::DrawVert>()
|
||||
.as_ptr();
|
||||
let dst_ptr = unsafe { dst_ptr.offset(vb_offset) };
|
||||
unsafe {
|
||||
std::ptr::copy_nonoverlapping(vertices.as_ptr(), dst_ptr, vertices.len())
|
||||
};
|
||||
vb_offset += vertices.len() as isize;
|
||||
}
|
||||
|
||||
{
|
||||
let indices = draw_list.idx_buffer();
|
||||
let dst_ptr = self
|
||||
.ib_allocation
|
||||
.mapped_ptr()
|
||||
.unwrap()
|
||||
.cast::<imgui::DrawIdx>()
|
||||
.as_ptr();
|
||||
let dst_ptr = unsafe { dst_ptr.offset(ib_offset) };
|
||||
unsafe { std::ptr::copy_nonoverlapping(indices.as_ptr(), dst_ptr, indices.len()) };
|
||||
ib_offset += indices.len() as isize;
|
||||
}
|
||||
|
||||
for command in draw_list.commands() {
|
||||
match command {
|
||||
imgui::DrawCmd::Elements { count, cmd_params } => {
|
||||
let scissor_rect = vk::Rect2D {
|
||||
offset: vk::Offset2D {
|
||||
x: cmd_params.clip_rect[0] as i32,
|
||||
y: cmd_params.clip_rect[1] as i32,
|
||||
},
|
||||
extent: vk::Extent2D {
|
||||
width: (cmd_params.clip_rect[2] - cmd_params.clip_rect[0]) as u32,
|
||||
height: (cmd_params.clip_rect[3] - cmd_params.clip_rect[1]) as u32,
|
||||
},
|
||||
};
|
||||
unsafe { device.cmd_set_scissor(cmd, 0, &[scissor_rect]) };
|
||||
|
||||
unsafe {
|
||||
device.cmd_draw_indexed(
|
||||
cmd,
|
||||
count as u32,
|
||||
1,
|
||||
cmd_params.idx_offset as u32,
|
||||
cmd_params.vtx_offset as i32,
|
||||
0,
|
||||
)
|
||||
};
|
||||
}
|
||||
_ => todo!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsafe { device.cmd_end_render_pass(cmd) };
|
||||
}
|
||||
|
||||
pub(crate) fn destroy(self, device: &ash::Device, allocator: &mut Allocator) {
|
||||
unsafe { device.destroy_buffer(self.constant_buffer, None) };
|
||||
allocator.free(self.cb_allocation).unwrap();
|
||||
|
||||
unsafe { device.destroy_buffer(self.index_buffer, None) };
|
||||
allocator.free(self.ib_allocation).unwrap();
|
||||
|
||||
unsafe { device.destroy_buffer(self.vertex_buffer, None) };
|
||||
allocator.free(self.vb_allocation).unwrap();
|
||||
|
||||
unsafe {
|
||||
device.destroy_sampler(self.sampler, None);
|
||||
}
|
||||
unsafe {
|
||||
device.destroy_image_view(self.font_image_view, None);
|
||||
}
|
||||
unsafe {
|
||||
device.destroy_image(self.font_image, None);
|
||||
}
|
||||
allocator.free(self.font_image_memory).unwrap();
|
||||
|
||||
unsafe { device.destroy_shader_module(self.ps_module, None) };
|
||||
unsafe { device.destroy_shader_module(self.vs_module, None) };
|
||||
|
||||
unsafe { device.destroy_pipeline(self.pipeline, None) };
|
||||
|
||||
unsafe { device.destroy_render_pass(self.render_pass, None) };
|
||||
|
||||
unsafe {
|
||||
device.destroy_pipeline_layout(self.pipeline_layout, None);
|
||||
}
|
||||
|
||||
for &layout in self.descriptor_set_layouts.iter() {
|
||||
unsafe { device.destroy_descriptor_set_layout(layout, None) };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn handle_imgui_event(
|
||||
io: &mut imgui::Io,
|
||||
window: &winit::window::Window,
|
||||
event: &winit::event::Event<'_, ()>,
|
||||
) -> bool {
|
||||
use winit::event::{
|
||||
DeviceEvent, ElementState, Event, KeyboardInput, MouseButton, MouseScrollDelta, TouchPhase,
|
||||
VirtualKeyCode, WindowEvent,
|
||||
};
|
||||
|
||||
match event {
|
||||
Event::WindowEvent { event, window_id } if *window_id == window.id() => match *event {
|
||||
WindowEvent::Resized(physical_size) => {
|
||||
io.display_size = [physical_size.width as f32, physical_size.height as f32];
|
||||
false
|
||||
}
|
||||
WindowEvent::KeyboardInput {
|
||||
input:
|
||||
KeyboardInput {
|
||||
virtual_keycode: Some(key),
|
||||
state,
|
||||
..
|
||||
},
|
||||
..
|
||||
} => {
|
||||
let pressed = state == ElementState::Pressed;
|
||||
io.keys_down[key as usize] = pressed;
|
||||
match key {
|
||||
VirtualKeyCode::LShift | VirtualKeyCode::RShift => io.key_shift = pressed,
|
||||
VirtualKeyCode::LControl | VirtualKeyCode::RControl => io.key_ctrl = pressed,
|
||||
VirtualKeyCode::LAlt | VirtualKeyCode::RAlt => io.key_alt = pressed,
|
||||
VirtualKeyCode::LWin | VirtualKeyCode::RWin => io.key_super = pressed,
|
||||
_ => (),
|
||||
}
|
||||
|
||||
io.want_capture_keyboard
|
||||
}
|
||||
WindowEvent::ReceivedCharacter(ch) => {
|
||||
io.add_input_character(ch);
|
||||
|
||||
io.want_capture_keyboard
|
||||
}
|
||||
|
||||
WindowEvent::CursorMoved { position, .. } => {
|
||||
io.mouse_pos = [position.x as f32, position.y as f32];
|
||||
|
||||
io.want_capture_mouse
|
||||
}
|
||||
WindowEvent::MouseWheel {
|
||||
delta,
|
||||
phase: TouchPhase::Moved,
|
||||
..
|
||||
} => {
|
||||
match delta {
|
||||
MouseScrollDelta::LineDelta(h, v) => {
|
||||
io.mouse_wheel_h = h;
|
||||
io.mouse_wheel = v;
|
||||
}
|
||||
MouseScrollDelta::PixelDelta(pos) => {
|
||||
match pos.x.partial_cmp(&0.0) {
|
||||
Some(std::cmp::Ordering::Greater) => io.mouse_wheel_h += 1.0,
|
||||
Some(std::cmp::Ordering::Less) => io.mouse_wheel_h -= 1.0,
|
||||
_ => (),
|
||||
}
|
||||
match pos.y.partial_cmp(&0.0) {
|
||||
Some(std::cmp::Ordering::Greater) => io.mouse_wheel += 1.0,
|
||||
Some(std::cmp::Ordering::Less) => io.mouse_wheel -= 1.0,
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
io.want_capture_mouse
|
||||
}
|
||||
WindowEvent::MouseInput { state, button, .. } => {
|
||||
let pressed = state == ElementState::Pressed;
|
||||
match button {
|
||||
MouseButton::Left => io.mouse_down[0] = pressed,
|
||||
MouseButton::Right => io.mouse_down[1] = pressed,
|
||||
MouseButton::Middle => io.mouse_down[2] = pressed,
|
||||
MouseButton::Other(idx @ 0..=4) => io.mouse_down[idx as usize] = pressed,
|
||||
MouseButton::Other(_) => (),
|
||||
}
|
||||
|
||||
io.want_capture_mouse
|
||||
}
|
||||
_ => false,
|
||||
},
|
||||
// Track key release events outside our window. If we don't do this,
|
||||
// we might never see the release event if some other window gets focus.
|
||||
Event::DeviceEvent {
|
||||
event:
|
||||
DeviceEvent::Key(KeyboardInput {
|
||||
state: ElementState::Released,
|
||||
virtual_keycode: Some(key),
|
||||
..
|
||||
}),
|
||||
..
|
||||
} => {
|
||||
io.keys_down[*key as usize] = false;
|
||||
match *key {
|
||||
VirtualKeyCode::LShift | VirtualKeyCode::RShift => io.key_shift = false,
|
||||
VirtualKeyCode::LControl | VirtualKeyCode::RControl => io.key_ctrl = false,
|
||||
VirtualKeyCode::LAlt | VirtualKeyCode::RAlt => io.key_alt = false,
|
||||
VirtualKeyCode::LWin | VirtualKeyCode::RWin => io.key_super = false,
|
||||
_ => (),
|
||||
}
|
||||
|
||||
io.want_capture_keyboard
|
||||
}
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
440
third-party/vendor/gpu-allocator/examples/vulkan-visualization/main.rs
vendored
Normal file
440
third-party/vendor/gpu-allocator/examples/vulkan-visualization/main.rs
vendored
Normal file
|
|
@ -0,0 +1,440 @@
|
|||
use std::default::Default;
|
||||
use std::ffi::CString;
|
||||
|
||||
use ash::vk;
|
||||
use gpu_allocator::vulkan::{Allocator, AllocatorCreateDesc};
|
||||
use raw_window_handle::{HasRawDisplayHandle, HasRawWindowHandle};
|
||||
|
||||
mod imgui_renderer;
|
||||
use imgui_renderer::{handle_imgui_event, ImGuiRenderer};
|
||||
|
||||
mod helper;
|
||||
use helper::record_and_submit_command_buffer;
|
||||
|
||||
fn main() -> ash::prelude::VkResult<()> {
|
||||
env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("trace")).init();
|
||||
|
||||
let entry = unsafe { ash::Entry::load() }.unwrap();
|
||||
|
||||
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 Vulkan visualization")
|
||||
.with_inner_size(winit::dpi::PhysicalSize::new(
|
||||
window_width as f64,
|
||||
window_height as f64,
|
||||
))
|
||||
.with_resizable(false)
|
||||
.build(&event_loop)
|
||||
.unwrap();
|
||||
|
||||
// Create Vulkan instance
|
||||
let instance = {
|
||||
let app_name = CString::new("gpu-allocator examples vulkan-visualization").unwrap();
|
||||
|
||||
let appinfo = vk::ApplicationInfo::builder()
|
||||
.application_name(&app_name)
|
||||
.application_version(0)
|
||||
.engine_name(&app_name)
|
||||
.engine_version(0)
|
||||
.api_version(vk::make_api_version(0, 1, 0, 0));
|
||||
|
||||
let layer_names: &[CString] = &[CString::new("VK_LAYER_KHRONOS_validation").unwrap()];
|
||||
let layers_names_raw: Vec<*const i8> = layer_names
|
||||
.iter()
|
||||
.map(|raw_name| raw_name.as_ptr())
|
||||
.collect();
|
||||
|
||||
let surface_extensions =
|
||||
ash_window::enumerate_required_extensions(event_loop.raw_display_handle()).unwrap();
|
||||
|
||||
let create_info = vk::InstanceCreateInfo::builder()
|
||||
.application_info(&appinfo)
|
||||
.enabled_layer_names(&layers_names_raw)
|
||||
.enabled_extension_names(surface_extensions);
|
||||
|
||||
unsafe {
|
||||
entry
|
||||
.create_instance(&create_info, None)
|
||||
.expect("Instance creation error")
|
||||
}
|
||||
};
|
||||
|
||||
let surface = unsafe {
|
||||
ash_window::create_surface(
|
||||
&entry,
|
||||
&instance,
|
||||
window.raw_display_handle(),
|
||||
window.raw_window_handle(),
|
||||
None,
|
||||
)
|
||||
}
|
||||
.unwrap();
|
||||
let surface_loader = ash::extensions::khr::Surface::new(&entry, &instance);
|
||||
|
||||
// Look for Vulkan physical device
|
||||
let (pdevice, queue_family_index) = {
|
||||
let pdevices = unsafe {
|
||||
instance
|
||||
.enumerate_physical_devices()
|
||||
.expect("Physical device error")
|
||||
};
|
||||
pdevices
|
||||
.iter()
|
||||
.find_map(|pdevice| {
|
||||
unsafe { instance.get_physical_device_queue_family_properties(*pdevice) }
|
||||
.iter()
|
||||
.enumerate()
|
||||
.find_map(|(index, &info)| {
|
||||
let supports_graphics = info.queue_flags.contains(vk::QueueFlags::GRAPHICS);
|
||||
let supports_surface = unsafe {
|
||||
surface_loader.get_physical_device_surface_support(
|
||||
*pdevice,
|
||||
index as u32,
|
||||
surface,
|
||||
)
|
||||
}
|
||||
.unwrap();
|
||||
if supports_graphics && supports_surface {
|
||||
Some((*pdevice, index))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
})
|
||||
.expect("Couldn't find suitable device.")
|
||||
};
|
||||
|
||||
// Create Vulkan device
|
||||
let device = {
|
||||
let device_extension_names_raw = [ash::extensions::khr::Swapchain::name().as_ptr()];
|
||||
let features = vk::PhysicalDeviceFeatures {
|
||||
shader_clip_distance: 1,
|
||||
..Default::default()
|
||||
};
|
||||
let priorities = [1.0];
|
||||
|
||||
let queue_info = vk::DeviceQueueCreateInfo::builder()
|
||||
.queue_family_index(queue_family_index as u32)
|
||||
.queue_priorities(&priorities);
|
||||
|
||||
let create_info = vk::DeviceCreateInfo::builder()
|
||||
.queue_create_infos(std::slice::from_ref(&queue_info))
|
||||
.enabled_extension_names(&device_extension_names_raw)
|
||||
.enabled_features(&features);
|
||||
|
||||
unsafe { instance.create_device(pdevice, &create_info, None) }.unwrap()
|
||||
};
|
||||
|
||||
let present_queue = unsafe { device.get_device_queue(queue_family_index as u32, 0) };
|
||||
|
||||
let surface_format =
|
||||
unsafe { surface_loader.get_physical_device_surface_formats(pdevice, surface) }.unwrap()[0];
|
||||
let surface_capabilities =
|
||||
unsafe { surface_loader.get_physical_device_surface_capabilities(pdevice, surface) }
|
||||
.unwrap();
|
||||
let mut desired_image_count = surface_capabilities.min_image_count + 1;
|
||||
if surface_capabilities.max_image_count > 0
|
||||
&& desired_image_count > surface_capabilities.max_image_count
|
||||
{
|
||||
desired_image_count = surface_capabilities.max_image_count;
|
||||
}
|
||||
let surface_resolution = match surface_capabilities.current_extent.width {
|
||||
u32::MAX => vk::Extent2D {
|
||||
width: window_width,
|
||||
height: window_height,
|
||||
},
|
||||
_ => surface_capabilities.current_extent,
|
||||
};
|
||||
let pre_transform = if surface_capabilities
|
||||
.supported_transforms
|
||||
.contains(vk::SurfaceTransformFlagsKHR::IDENTITY)
|
||||
{
|
||||
vk::SurfaceTransformFlagsKHR::IDENTITY
|
||||
} else {
|
||||
surface_capabilities.current_transform
|
||||
};
|
||||
let present_modes =
|
||||
unsafe { surface_loader.get_physical_device_surface_present_modes(pdevice, surface) }
|
||||
.unwrap();
|
||||
let present_mode = present_modes
|
||||
.iter()
|
||||
.cloned()
|
||||
.find(|&mode| mode == vk::PresentModeKHR::MAILBOX)
|
||||
.unwrap_or(vk::PresentModeKHR::FIFO);
|
||||
let swapchain_loader = ash::extensions::khr::Swapchain::new(&instance, &device);
|
||||
|
||||
let swapchain_create_info = vk::SwapchainCreateInfoKHR::builder()
|
||||
.surface(surface)
|
||||
.min_image_count(desired_image_count)
|
||||
.image_color_space(surface_format.color_space)
|
||||
.image_format(surface_format.format)
|
||||
.image_extent(surface_resolution)
|
||||
.image_usage(vk::ImageUsageFlags::COLOR_ATTACHMENT)
|
||||
.image_sharing_mode(vk::SharingMode::EXCLUSIVE)
|
||||
.pre_transform(pre_transform)
|
||||
.composite_alpha(vk::CompositeAlphaFlagsKHR::OPAQUE)
|
||||
.present_mode(present_mode)
|
||||
.clipped(true)
|
||||
.image_array_layers(1);
|
||||
|
||||
let swapchain =
|
||||
unsafe { swapchain_loader.create_swapchain(&swapchain_create_info, None) }.unwrap();
|
||||
|
||||
let pool_create_info = vk::CommandPoolCreateInfo::builder()
|
||||
.flags(vk::CommandPoolCreateFlags::RESET_COMMAND_BUFFER)
|
||||
.queue_family_index(queue_family_index as u32);
|
||||
let command_pool = unsafe { device.create_command_pool(&pool_create_info, None) }.unwrap();
|
||||
|
||||
let command_buffer_allocate_info = vk::CommandBufferAllocateInfo::builder()
|
||||
.command_buffer_count(2)
|
||||
.command_pool(command_pool)
|
||||
.level(vk::CommandBufferLevel::PRIMARY);
|
||||
|
||||
let command_buffers =
|
||||
unsafe { device.allocate_command_buffers(&command_buffer_allocate_info) }.unwrap();
|
||||
let setup_command_buffer = command_buffers[0];
|
||||
let draw_command_buffer = command_buffers[1];
|
||||
|
||||
let present_images = unsafe { swapchain_loader.get_swapchain_images(swapchain) }.unwrap();
|
||||
let mut present_image_views = present_images
|
||||
.iter()
|
||||
.map(|&image| {
|
||||
let create_view_info = vk::ImageViewCreateInfo::builder()
|
||||
.view_type(vk::ImageViewType::TYPE_2D)
|
||||
.format(surface_format.format)
|
||||
.components(vk::ComponentMapping {
|
||||
r: vk::ComponentSwizzle::R,
|
||||
g: vk::ComponentSwizzle::G,
|
||||
b: vk::ComponentSwizzle::B,
|
||||
a: vk::ComponentSwizzle::A,
|
||||
})
|
||||
.subresource_range(vk::ImageSubresourceRange {
|
||||
aspect_mask: vk::ImageAspectFlags::COLOR,
|
||||
base_mip_level: 0,
|
||||
level_count: 1,
|
||||
base_array_layer: 0,
|
||||
layer_count: 1,
|
||||
})
|
||||
.image(image);
|
||||
unsafe { device.create_image_view(&create_view_info, None) }.unwrap()
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
// Setting up the allocator
|
||||
let mut allocator = Some(
|
||||
Allocator::new(&AllocatorCreateDesc {
|
||||
instance: instance.clone(),
|
||||
device: device.clone(),
|
||||
physical_device: pdevice,
|
||||
debug_settings: Default::default(),
|
||||
buffer_device_address: false,
|
||||
})
|
||||
.unwrap(),
|
||||
);
|
||||
|
||||
let fence_create_info = vk::FenceCreateInfo::builder().flags(vk::FenceCreateFlags::SIGNALED);
|
||||
let draw_commands_reuse_fence =
|
||||
unsafe { device.create_fence(&fence_create_info, None) }.unwrap();
|
||||
let setup_commands_reuse_fence =
|
||||
unsafe { device.create_fence(&fence_create_info, None) }.unwrap();
|
||||
|
||||
let semaphore_create_info = vk::SemaphoreCreateInfo::default();
|
||||
|
||||
let present_complete_semaphore =
|
||||
unsafe { device.create_semaphore(&semaphore_create_info, None) }.unwrap();
|
||||
let rendering_complete_semaphore =
|
||||
unsafe { device.create_semaphore(&semaphore_create_info, None) }.unwrap();
|
||||
|
||||
let mut imgui = imgui::Context::create();
|
||||
imgui.io_mut().display_size = [window_width as f32, window_height as f32];
|
||||
|
||||
let descriptor_pool = {
|
||||
let pool_sizes = [
|
||||
vk::DescriptorPoolSize {
|
||||
ty: vk::DescriptorType::UNIFORM_BUFFER,
|
||||
descriptor_count: 1,
|
||||
},
|
||||
vk::DescriptorPoolSize {
|
||||
ty: vk::DescriptorType::SAMPLED_IMAGE,
|
||||
descriptor_count: 1,
|
||||
},
|
||||
vk::DescriptorPoolSize {
|
||||
ty: vk::DescriptorType::SAMPLER,
|
||||
descriptor_count: 1,
|
||||
},
|
||||
];
|
||||
let create_info = vk::DescriptorPoolCreateInfo::builder()
|
||||
.max_sets(1)
|
||||
.pool_sizes(&pool_sizes);
|
||||
unsafe { device.create_descriptor_pool(&create_info, None) }?
|
||||
};
|
||||
|
||||
let mut imgui_renderer = Some(ImGuiRenderer::new(
|
||||
&mut imgui,
|
||||
&device,
|
||||
descriptor_pool,
|
||||
surface_format.format,
|
||||
allocator.as_mut().unwrap(),
|
||||
setup_command_buffer,
|
||||
setup_commands_reuse_fence,
|
||||
present_queue,
|
||||
)?);
|
||||
|
||||
let mut framebuffers = present_image_views
|
||||
.iter()
|
||||
.map(|&view| {
|
||||
let create_info = vk::FramebufferCreateInfo::builder()
|
||||
.render_pass(imgui_renderer.as_ref().unwrap().render_pass)
|
||||
.attachments(std::slice::from_ref(&view))
|
||||
.width(window_width)
|
||||
.height(window_height)
|
||||
.layers(1);
|
||||
|
||||
unsafe { device.create_framebuffer(&create_info, None) }.unwrap()
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let mut visualizer = Some(gpu_allocator::vulkan::AllocatorVisualizer::new());
|
||||
|
||||
event_loop.run(move |event, _, control_flow| {
|
||||
*control_flow = winit::event_loop::ControlFlow::Wait;
|
||||
|
||||
handle_imgui_event(imgui.io_mut(), &window, &event);
|
||||
|
||||
let mut ready_for_rendering = false;
|
||||
match event {
|
||||
winit::event::Event::WindowEvent { event, .. } => match event {
|
||||
winit::event::WindowEvent::CloseRequested
|
||||
| winit::event::WindowEvent::KeyboardInput {
|
||||
input:
|
||||
winit::event::KeyboardInput {
|
||||
virtual_keycode: Some(winit::event::VirtualKeyCode::Escape),
|
||||
..
|
||||
},
|
||||
..
|
||||
} => {
|
||||
*control_flow = winit::event_loop::ControlFlow::Exit;
|
||||
}
|
||||
_ => {}
|
||||
},
|
||||
winit::event::Event::MainEventsCleared => ready_for_rendering = true,
|
||||
_ => {}
|
||||
}
|
||||
|
||||
if ready_for_rendering {
|
||||
let (present_index, _) = unsafe {
|
||||
swapchain_loader.acquire_next_image(
|
||||
swapchain,
|
||||
u64::MAX,
|
||||
present_complete_semaphore,
|
||||
vk::Fence::null(),
|
||||
)
|
||||
}
|
||||
.unwrap();
|
||||
|
||||
// Start ImGui frame
|
||||
let ui = imgui.frame();
|
||||
|
||||
// Submit visualizer ImGui commands
|
||||
visualizer
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.render(allocator.as_ref().unwrap(), ui, None);
|
||||
|
||||
// Finish ImGui Frame
|
||||
let imgui_draw_data = imgui.render();
|
||||
|
||||
record_and_submit_command_buffer(
|
||||
&device,
|
||||
draw_command_buffer,
|
||||
draw_commands_reuse_fence,
|
||||
present_queue,
|
||||
&[vk::PipelineStageFlags::COLOR_ATTACHMENT_OUTPUT],
|
||||
&[present_complete_semaphore],
|
||||
&[rendering_complete_semaphore],
|
||||
|device, cmd| {
|
||||
// Render ImGui to swapchain image
|
||||
imgui_renderer.as_mut().unwrap().render(
|
||||
imgui_draw_data,
|
||||
device,
|
||||
window_width,
|
||||
window_height,
|
||||
framebuffers[present_index as usize],
|
||||
cmd,
|
||||
);
|
||||
|
||||
// Transition swapchain image to present state
|
||||
let image_barriers = vk::ImageMemoryBarrier::builder()
|
||||
.src_access_mask(
|
||||
vk::AccessFlags::COLOR_ATTACHMENT_READ
|
||||
| vk::AccessFlags::COLOR_ATTACHMENT_WRITE,
|
||||
)
|
||||
.old_layout(vk::ImageLayout::COLOR_ATTACHMENT_OPTIMAL)
|
||||
.new_layout(vk::ImageLayout::PRESENT_SRC_KHR)
|
||||
.image(present_images[present_index as usize])
|
||||
.subresource_range(vk::ImageSubresourceRange {
|
||||
aspect_mask: vk::ImageAspectFlags::COLOR,
|
||||
base_mip_level: 0,
|
||||
level_count: vk::REMAINING_MIP_LEVELS,
|
||||
base_array_layer: 0,
|
||||
layer_count: vk::REMAINING_ARRAY_LAYERS,
|
||||
});
|
||||
unsafe {
|
||||
device.cmd_pipeline_barrier(
|
||||
cmd,
|
||||
vk::PipelineStageFlags::COLOR_ATTACHMENT_OUTPUT,
|
||||
vk::PipelineStageFlags::BOTTOM_OF_PIPE,
|
||||
vk::DependencyFlags::empty(),
|
||||
&[],
|
||||
&[],
|
||||
std::slice::from_ref(&image_barriers),
|
||||
)
|
||||
};
|
||||
},
|
||||
);
|
||||
|
||||
let present_create_info = vk::PresentInfoKHR::builder()
|
||||
.wait_semaphores(std::slice::from_ref(&rendering_complete_semaphore))
|
||||
.swapchains(std::slice::from_ref(&swapchain))
|
||||
.image_indices(std::slice::from_ref(&present_index));
|
||||
|
||||
unsafe { swapchain_loader.queue_present(present_queue, &present_create_info) }.unwrap();
|
||||
} else if *control_flow == winit::event_loop::ControlFlow::Exit {
|
||||
unsafe { device.queue_wait_idle(present_queue) }.unwrap();
|
||||
|
||||
visualizer.take();
|
||||
|
||||
for fb in framebuffers.drain(..) {
|
||||
unsafe { device.destroy_framebuffer(fb, None) };
|
||||
}
|
||||
|
||||
let mut allocator = allocator.take().unwrap();
|
||||
|
||||
imgui_renderer
|
||||
.take()
|
||||
.unwrap()
|
||||
.destroy(&device, &mut allocator);
|
||||
|
||||
unsafe { device.destroy_descriptor_pool(descriptor_pool, None) };
|
||||
unsafe { device.destroy_semaphore(rendering_complete_semaphore, None) };
|
||||
unsafe { device.destroy_semaphore(present_complete_semaphore, None) };
|
||||
unsafe { device.destroy_fence(setup_commands_reuse_fence, None) };
|
||||
unsafe { device.destroy_fence(draw_commands_reuse_fence, None) };
|
||||
drop(allocator);
|
||||
for view in present_image_views.drain(..) {
|
||||
unsafe { device.destroy_image_view(view, None) };
|
||||
}
|
||||
unsafe { device.free_command_buffers(command_pool, &command_buffers) };
|
||||
unsafe { device.destroy_command_pool(command_pool, None) };
|
||||
unsafe { swapchain_loader.destroy_swapchain(swapchain, None) };
|
||||
unsafe { device.destroy_device(None) };
|
||||
unsafe {
|
||||
surface_loader.destroy_surface(surface, None);
|
||||
}
|
||||
unsafe { instance.destroy_instance(None) };
|
||||
}
|
||||
});
|
||||
}
|
||||
14
third-party/vendor/gpu-allocator/examples/vulkan-visualization/shaders/imgui.ps.hlsl
vendored
Normal file
14
third-party/vendor/gpu-allocator/examples/vulkan-visualization/shaders/imgui.ps.hlsl
vendored
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
SamplerState g_sampler : register(s1, space0);
|
||||
Texture2D g_texture : register(t2, space0);
|
||||
|
||||
struct VertexInput
|
||||
{
|
||||
float4 position : SV_POSITION;
|
||||
float2 texCoord: TEXCOORD0;
|
||||
float4 color: COLOR;
|
||||
};
|
||||
|
||||
float4 main(VertexInput input) : SV_Target0
|
||||
{
|
||||
return input.color * g_texture.Sample(g_sampler, input.texCoord);
|
||||
}
|
||||
30
third-party/vendor/gpu-allocator/examples/vulkan-visualization/shaders/imgui.vs.hlsl
vendored
Normal file
30
third-party/vendor/gpu-allocator/examples/vulkan-visualization/shaders/imgui.vs.hlsl
vendored
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
struct VertexInput
|
||||
{
|
||||
float2 pos : POSITION;
|
||||
float2 texCoord : TEXCOORD0;
|
||||
float4 color: COLOR;
|
||||
};
|
||||
|
||||
struct VertexOutput
|
||||
{
|
||||
float4 position : SV_POSITION;
|
||||
float2 texCoord: TEXCOORD0;
|
||||
float4 color: COLOR;
|
||||
};
|
||||
|
||||
struct Constants
|
||||
{
|
||||
float2 scale;
|
||||
float2 translation;
|
||||
};
|
||||
|
||||
ConstantBuffer<Constants> g_constants : register(b0, space0);
|
||||
|
||||
VertexOutput main(VertexInput vertex)
|
||||
{
|
||||
VertexOutput o;
|
||||
o.position = float4(vertex.pos * g_constants.scale + g_constants.translation, 0.0, 1.0);
|
||||
o.texCoord = vertex.texCoord;
|
||||
o.color = vertex.color;
|
||||
return o;
|
||||
}
|
||||
BIN
third-party/vendor/gpu-allocator/examples/vulkan-visualization/spirv/imgui.ps.spv
vendored
Normal file
BIN
third-party/vendor/gpu-allocator/examples/vulkan-visualization/spirv/imgui.ps.spv
vendored
Normal file
Binary file not shown.
BIN
third-party/vendor/gpu-allocator/examples/vulkan-visualization/spirv/imgui.vs.spv
vendored
Normal file
BIN
third-party/vendor/gpu-allocator/examples/vulkan-visualization/spirv/imgui.vs.spv
vendored
Normal file
Binary file not shown.
Loading…
Add table
Add a link
Reference in a new issue