diff options
Diffstat (limited to 'third_party/rust/d3d12/src/dxgi.rs')
-rw-r--r-- | third_party/rust/d3d12/src/dxgi.rs | 375 |
1 files changed, 375 insertions, 0 deletions
diff --git a/third_party/rust/d3d12/src/dxgi.rs b/third_party/rust/d3d12/src/dxgi.rs new file mode 100644 index 0000000000..3c0396e88e --- /dev/null +++ b/third_party/rust/d3d12/src/dxgi.rs @@ -0,0 +1,375 @@ +use crate::{com::WeakPtr, D3DResult, Resource, SampleDesc, HRESULT}; +use std::ptr; +use winapi::{ + shared::{ + dxgi, dxgi1_2, dxgi1_3, dxgi1_4, dxgi1_5, dxgi1_6, dxgiformat, dxgitype, minwindef::TRUE, + windef::HWND, + }, + um::{d3d12, dxgidebug, unknwnbase::IUnknown, winnt::HANDLE}, + Interface, +}; + +bitflags! { + pub struct FactoryCreationFlags: u32 { + const DEBUG = dxgi1_3::DXGI_CREATE_FACTORY_DEBUG; + } +} + +#[repr(u32)] +#[derive(Debug, Copy, Clone)] +pub enum Scaling { + Stretch = dxgi1_2::DXGI_SCALING_STRETCH, + Identity = dxgi1_2::DXGI_SCALING_NONE, + Aspect = dxgi1_2::DXGI_SCALING_ASPECT_RATIO_STRETCH, +} + +#[repr(u32)] +#[derive(Debug, Copy, Clone)] +pub enum SwapEffect { + Discard = dxgi::DXGI_SWAP_EFFECT_DISCARD, + Sequential = dxgi::DXGI_SWAP_EFFECT_SEQUENTIAL, + FlipDiscard = dxgi::DXGI_SWAP_EFFECT_FLIP_DISCARD, + FlipSequential = dxgi::DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL, +} + +#[repr(u32)] +#[derive(Debug, Copy, Clone)] +pub enum AlphaMode { + Unspecified = dxgi1_2::DXGI_ALPHA_MODE_UNSPECIFIED, + Premultiplied = dxgi1_2::DXGI_ALPHA_MODE_PREMULTIPLIED, + Straight = dxgi1_2::DXGI_ALPHA_MODE_STRAIGHT, + Ignore = dxgi1_2::DXGI_ALPHA_MODE_IGNORE, + ForceDword = dxgi1_2::DXGI_ALPHA_MODE_FORCE_DWORD, +} + +pub type InfoQueue = WeakPtr<dxgidebug::IDXGIInfoQueue>; + +pub type Adapter1 = WeakPtr<dxgi::IDXGIAdapter1>; +pub type Adapter2 = WeakPtr<dxgi1_2::IDXGIAdapter2>; +pub type Adapter3 = WeakPtr<dxgi1_4::IDXGIAdapter3>; +pub type Adapter4 = WeakPtr<dxgi1_6::IDXGIAdapter4>; +crate::weak_com_inheritance_chain! { + #[derive(Debug, Copy, Clone, PartialEq, Hash)] + pub enum DxgiAdapter { + Adapter1(dxgi::IDXGIAdapter1), from_adapter1, as_adapter1, adapter1; + Adapter2(dxgi1_2::IDXGIAdapter2), from_adapter2, as_adapter2, unwrap_adapter2; + Adapter3(dxgi1_4::IDXGIAdapter3), from_adapter3, as_adapter3, unwrap_adapter3; + Adapter4(dxgi1_6::IDXGIAdapter4), from_adapter4, as_adapter4, unwrap_adapter4; + } +} + +pub type Factory1 = WeakPtr<dxgi::IDXGIFactory1>; +pub type Factory2 = WeakPtr<dxgi1_2::IDXGIFactory2>; +pub type Factory3 = WeakPtr<dxgi1_3::IDXGIFactory3>; +pub type Factory4 = WeakPtr<dxgi1_4::IDXGIFactory4>; +pub type Factory5 = WeakPtr<dxgi1_5::IDXGIFactory5>; +pub type Factory6 = WeakPtr<dxgi1_6::IDXGIFactory6>; +crate::weak_com_inheritance_chain! { + #[derive(Debug, Copy, Clone, PartialEq, Hash)] + pub enum DxgiFactory { + Factory1(dxgi::IDXGIFactory1), from_factory1, as_factory1, factory1; + Factory2(dxgi1_2::IDXGIFactory2), from_factory2, as_factory2, unwrap_factory2; + Factory3(dxgi1_3::IDXGIFactory3), from_factory3, as_factory3, unwrap_factory3; + Factory4(dxgi1_4::IDXGIFactory4), from_factory4, as_factory4, unwrap_factory4; + Factory5(dxgi1_5::IDXGIFactory5), from_factory5, as_factory5, unwrap_factory5; + Factory6(dxgi1_6::IDXGIFactory6), from_factory6, as_factory6, unwrap_factory6; + } +} + +pub type FactoryMedia = WeakPtr<dxgi1_3::IDXGIFactoryMedia>; + +pub type SwapChain = WeakPtr<dxgi::IDXGISwapChain>; +pub type SwapChain1 = WeakPtr<dxgi1_2::IDXGISwapChain1>; +pub type SwapChain2 = WeakPtr<dxgi1_3::IDXGISwapChain2>; +pub type SwapChain3 = WeakPtr<dxgi1_4::IDXGISwapChain3>; +crate::weak_com_inheritance_chain! { + #[derive(Debug, Copy, Clone, PartialEq, Hash)] + pub enum DxgiSwapchain { + SwapChain(dxgi::IDXGISwapChain), from_swap_chain, as_swap_chain, swap_chain; + SwapChain1(dxgi1_2::IDXGISwapChain1), from_swap_chain1, as_swap_chain1, unwrap_swap_chain1; + SwapChain2(dxgi1_3::IDXGISwapChain2), from_swap_chain2, as_swap_chain2, unwrap_swap_chain2; + SwapChain3(dxgi1_4::IDXGISwapChain3), from_swap_chain3, as_swap_chain3, unwrap_swap_chain3; + } +} + +#[cfg(feature = "libloading")] +#[derive(Debug)] +pub struct DxgiLib { + lib: libloading::Library, +} + +#[cfg(feature = "libloading")] +impl DxgiLib { + pub fn new() -> Result<Self, libloading::Error> { + unsafe { libloading::Library::new("dxgi.dll").map(|lib| DxgiLib { lib }) } + } + + pub fn create_factory2( + &self, + flags: FactoryCreationFlags, + ) -> Result<D3DResult<Factory4>, libloading::Error> { + type Fun = extern "system" fn( + winapi::shared::minwindef::UINT, + winapi::shared::guiddef::REFIID, + *mut *mut winapi::ctypes::c_void, + ) -> HRESULT; + + let mut factory = Factory4::null(); + let hr = unsafe { + let func: libloading::Symbol<Fun> = self.lib.get(b"CreateDXGIFactory2")?; + func( + flags.bits(), + &dxgi1_4::IDXGIFactory4::uuidof(), + factory.mut_void(), + ) + }; + + Ok((factory, hr)) + } + + pub fn create_factory1(&self) -> Result<D3DResult<Factory1>, libloading::Error> { + type Fun = extern "system" fn( + winapi::shared::guiddef::REFIID, + *mut *mut winapi::ctypes::c_void, + ) -> HRESULT; + + let mut factory = Factory1::null(); + let hr = unsafe { + let func: libloading::Symbol<Fun> = self.lib.get(b"CreateDXGIFactory1")?; + func(&dxgi::IDXGIFactory1::uuidof(), factory.mut_void()) + }; + + Ok((factory, hr)) + } + + pub fn create_factory_media(&self) -> Result<D3DResult<FactoryMedia>, libloading::Error> { + type Fun = extern "system" fn( + winapi::shared::guiddef::REFIID, + *mut *mut winapi::ctypes::c_void, + ) -> HRESULT; + + let mut factory = FactoryMedia::null(); + let hr = unsafe { + // https://learn.microsoft.com/en-us/windows/win32/api/dxgi1_3/nn-dxgi1_3-idxgifactorymedia + let func: libloading::Symbol<Fun> = self.lib.get(b"CreateDXGIFactory1")?; + func(&dxgi1_3::IDXGIFactoryMedia::uuidof(), factory.mut_void()) + }; + + Ok((factory, hr)) + } + + pub fn get_debug_interface1(&self) -> Result<D3DResult<InfoQueue>, libloading::Error> { + type Fun = extern "system" fn( + winapi::shared::minwindef::UINT, + winapi::shared::guiddef::REFIID, + *mut *mut winapi::ctypes::c_void, + ) -> HRESULT; + + let mut queue = InfoQueue::null(); + let hr = unsafe { + let func: libloading::Symbol<Fun> = self.lib.get(b"DXGIGetDebugInterface1")?; + func(0, &dxgidebug::IDXGIInfoQueue::uuidof(), queue.mut_void()) + }; + Ok((queue, hr)) + } +} + +// TODO: strong types +pub struct SwapchainDesc { + pub width: u32, + pub height: u32, + pub format: dxgiformat::DXGI_FORMAT, + pub stereo: bool, + pub sample: SampleDesc, + pub buffer_usage: dxgitype::DXGI_USAGE, + pub buffer_count: u32, + pub scaling: Scaling, + pub swap_effect: SwapEffect, + pub alpha_mode: AlphaMode, + pub flags: u32, +} +impl SwapchainDesc { + pub fn to_desc1(&self) -> dxgi1_2::DXGI_SWAP_CHAIN_DESC1 { + dxgi1_2::DXGI_SWAP_CHAIN_DESC1 { + AlphaMode: self.alpha_mode as _, + BufferCount: self.buffer_count, + Width: self.width, + Height: self.height, + Format: self.format, + Flags: self.flags, + BufferUsage: self.buffer_usage, + SampleDesc: dxgitype::DXGI_SAMPLE_DESC { + Count: self.sample.count, + Quality: self.sample.quality, + }, + Scaling: self.scaling as _, + Stereo: self.stereo as _, + SwapEffect: self.swap_effect as _, + } + } +} + +impl Factory1 { + pub fn create_swapchain( + &self, + queue: *mut IUnknown, + hwnd: HWND, + desc: &SwapchainDesc, + ) -> D3DResult<SwapChain> { + let mut desc = dxgi::DXGI_SWAP_CHAIN_DESC { + BufferDesc: dxgitype::DXGI_MODE_DESC { + Width: desc.width, + Height: desc.width, + RefreshRate: dxgitype::DXGI_RATIONAL { + Numerator: 1, + Denominator: 60, + }, + Format: desc.format, + ScanlineOrdering: dxgitype::DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED, + Scaling: dxgitype::DXGI_MODE_SCALING_UNSPECIFIED, + }, + SampleDesc: dxgitype::DXGI_SAMPLE_DESC { + Count: desc.sample.count, + Quality: desc.sample.quality, + }, + BufferUsage: desc.buffer_usage, + BufferCount: desc.buffer_count, + OutputWindow: hwnd, + Windowed: TRUE, + SwapEffect: desc.swap_effect as _, + Flags: desc.flags, + }; + + let mut swapchain = SwapChain::null(); + let hr = + unsafe { self.CreateSwapChain(queue, &mut desc, swapchain.mut_void() as *mut *mut _) }; + + (swapchain, hr) + } +} + +impl Factory2 { + // TODO: interface not complete + pub fn create_swapchain_for_hwnd( + &self, + queue: *mut IUnknown, + hwnd: HWND, + desc: &SwapchainDesc, + ) -> D3DResult<SwapChain1> { + let mut swap_chain = SwapChain1::null(); + let hr = unsafe { + self.CreateSwapChainForHwnd( + queue, + hwnd, + &desc.to_desc1(), + ptr::null(), + ptr::null_mut(), + swap_chain.mut_void() as *mut *mut _, + ) + }; + + (swap_chain, hr) + } + + pub fn create_swapchain_for_composition( + &self, + queue: *mut IUnknown, + desc: &SwapchainDesc, + ) -> D3DResult<SwapChain1> { + let mut swap_chain = SwapChain1::null(); + let hr = unsafe { + self.CreateSwapChainForComposition( + queue, + &desc.to_desc1(), + ptr::null_mut(), + swap_chain.mut_void() as *mut *mut _, + ) + }; + + (swap_chain, hr) + } +} + +impl Factory4 { + #[cfg(feature = "implicit-link")] + pub fn create(flags: FactoryCreationFlags) -> D3DResult<Self> { + let mut factory = Factory4::null(); + let hr = unsafe { + dxgi1_3::CreateDXGIFactory2( + flags.bits(), + &dxgi1_4::IDXGIFactory4::uuidof(), + factory.mut_void(), + ) + }; + + (factory, hr) + } + + pub fn enumerate_adapters(&self, id: u32) -> D3DResult<Adapter1> { + let mut adapter = Adapter1::null(); + let hr = unsafe { self.EnumAdapters1(id, adapter.mut_void() as *mut *mut _) }; + + (adapter, hr) + } +} + +impl FactoryMedia { + pub fn create_swapchain_for_composition_surface_handle( + &self, + queue: *mut IUnknown, + surface_handle: HANDLE, + desc: &SwapchainDesc, + ) -> D3DResult<SwapChain1> { + let mut swap_chain = SwapChain1::null(); + let hr = unsafe { + self.CreateSwapChainForCompositionSurfaceHandle( + queue, + surface_handle, + &desc.to_desc1(), + ptr::null_mut(), + swap_chain.mut_void() as *mut *mut _, + ) + }; + + (swap_chain, hr) + } +} + +bitflags! { + pub struct SwapChainPresentFlags: u32 { + const DXGI_PRESENT_DO_NOT_SEQUENCE = dxgi::DXGI_PRESENT_DO_NOT_SEQUENCE; + const DXGI_PRESENT_TEST = dxgi::DXGI_PRESENT_TEST; + const DXGI_PRESENT_RESTART = dxgi::DXGI_PRESENT_RESTART; + const DXGI_PRESENT_DO_NOT_WAIT = dxgi::DXGI_PRESENT_DO_NOT_WAIT; + const DXGI_PRESENT_RESTRICT_TO_OUTPUT = dxgi::DXGI_PRESENT_RESTRICT_TO_OUTPUT; + const DXGI_PRESENT_STEREO_PREFER_RIGHT = dxgi::DXGI_PRESENT_STEREO_PREFER_RIGHT; + const DXGI_PRESENT_STEREO_TEMPORARY_MONO = dxgi::DXGI_PRESENT_STEREO_TEMPORARY_MONO; + const DXGI_PRESENT_USE_DURATION = dxgi::DXGI_PRESENT_USE_DURATION; + const DXGI_PRESENT_ALLOW_TEARING = dxgi::DXGI_PRESENT_ALLOW_TEARING; + } +} + +impl SwapChain { + pub fn get_buffer(&self, id: u32) -> D3DResult<Resource> { + let mut resource = Resource::null(); + let hr = + unsafe { self.GetBuffer(id, &d3d12::ID3D12Resource::uuidof(), resource.mut_void()) }; + + (resource, hr) + } + + //TODO: replace by present_flags + pub fn present(&self, interval: u32, flags: u32) -> HRESULT { + unsafe { self.Present(interval, flags) } + } + + pub fn present_flags(&self, interval: u32, flags: SwapChainPresentFlags) -> HRESULT { + unsafe { self.Present(interval, flags.bits()) } + } +} + +impl SwapChain3 { + pub fn get_current_back_buffer_index(&self) -> u32 { + unsafe { self.GetCurrentBackBufferIndex() } + } +} |