From 2aacc3b11bad0886b3e2e541fac6967bf204e42c Mon Sep 17 00:00:00 2001 From: msiglreith Date: Sun, 2 Sep 2018 14:11:18 +0200 Subject: [PATCH 1/4] Add debug interface, factory creation and adapter enumeration --- Cargo.toml | 4 ++-- src/debug.rs | 21 +++++++++++++++++++++ src/dxgi.rs | 35 +++++++++++++++++++++++++++++++++++ src/lib.rs | 3 +++ 4 files changed, 61 insertions(+), 2 deletions(-) create mode 100644 src/debug.rs create mode 100644 src/dxgi.rs diff --git a/Cargo.toml b/Cargo.toml index 5e6b53e92..9e054e3be 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,8 +1,8 @@ [package] -name = "d3d12-rs" +name = "d3d12" version = "0.1.0" authors = ["msiglreith "] [dependencies] bitflags = "1" -winapi = { version = "0.3", features = ["d3d12","d3dcommon","d3dcompiler","dxgiformat","winerror"] } +winapi = { version = "0.3", features = ["dxgi1_3","dxgi1_4","d3d12","d3d12sdklayers","d3dcommon","d3dcompiler","dxgiformat","winerror"] } diff --git a/src/debug.rs b/src/debug.rs new file mode 100644 index 000000000..450beeac7 --- /dev/null +++ b/src/debug.rs @@ -0,0 +1,21 @@ +use com::WeakPtr; +use winapi::um::{d3d12, d3d12sdklayers}; +use winapi::Interface; +use D3DResult; + +pub type Debug = WeakPtr; + +impl Debug { + pub fn get_debug_interface() -> D3DResult { + let mut debug = Debug::null(); + let hr = unsafe { + d3d12::D3D12GetDebugInterface(&d3d12sdklayers::ID3D12Debug::uuidof(), debug.mut_void()) + }; + + (debug, hr) + } + + pub fn enable_debug_layer(&self) { + unsafe { self.EnableDebugLayer() } + } +} diff --git a/src/dxgi.rs b/src/dxgi.rs new file mode 100644 index 000000000..22d0d7352 --- /dev/null +++ b/src/dxgi.rs @@ -0,0 +1,35 @@ +use com::WeakPtr; +use winapi::shared::{dxgi, dxgi1_3, dxgi1_4}; +use winapi::Interface; +use D3DResult; + +bitflags! { + pub struct FactoryCreationFlags: u32 { + const DEBUG = dxgi1_3::DXGI_CREATE_FACTORY_DEBUG; + } +} + +pub type Adapter1 = WeakPtr; +pub type Factory4 = WeakPtr; + +impl Factory4 { + pub fn create(flags: FactoryCreationFlags) -> D3DResult { + 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 { + let mut adapter = Adapter1::null(); + let hr = unsafe { self.EnumAdapters1(id, adapter.mut_void() as *mut *mut _) }; + + (adapter, hr) + } +} diff --git a/src/lib.rs b/src/lib.rs index 036ff059e..5434912ff 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -9,8 +9,10 @@ use winapi::um::{d3d12, d3dcommon}; mod com; pub mod command_allocator; pub mod command_list; +pub mod debug; pub mod descriptor; pub mod device; +pub mod dxgi; pub mod pso; pub mod query; pub mod queue; @@ -20,6 +22,7 @@ pub mod sync; pub use self::com::WeakPtr; pub use self::command_allocator::CommandAllocator; pub use self::command_list::{CommandSignature, GraphicsCommandList}; +pub use self::debug::Debug; pub use self::descriptor::{CpuDescriptor, DescriptorHeap, GpuDescriptor, RootSignature}; pub use self::device::Device; pub use self::pso::{CachedPSO, PipelineState, Shader}; From 908c29ed7e37bf6119c10b76c4e15eb7d5ce026f Mon Sep 17 00:00:00 2001 From: msiglreith Date: Sun, 2 Sep 2018 18:37:44 +0200 Subject: [PATCH 2/4] Add swapchain handling and 2d RTV creation --- Cargo.toml | 5 +- src/com.rs | 4 ++ src/command_list.rs | 6 +++ src/descriptor.rs | 21 ++++++++ src/device.rs | 15 +++++- src/dxgi.rs | 129 +++++++++++++++++++++++++++++++++++++++++++- src/lib.rs | 5 ++ 7 files changed, 180 insertions(+), 5 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 9e054e3be..451272962 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,4 +5,7 @@ authors = ["msiglreith "] [dependencies] bitflags = "1" -winapi = { version = "0.3", features = ["dxgi1_3","dxgi1_4","d3d12","d3d12sdklayers","d3dcommon","d3dcompiler","dxgiformat","winerror"] } + +[dependencies.winapi] +version = "0.3" +features = ["dxgi1_2","dxgi1_3","dxgi1_4","d3d12","d3d12sdklayers","d3dcommon","d3dcompiler","dxgiformat","winerror"] \ No newline at end of file diff --git a/src/com.rs b/src/com.rs index 9ecc6baba..dc76b6f3c 100644 --- a/src/com.rs +++ b/src/com.rs @@ -15,6 +15,10 @@ impl WeakPtr { WeakPtr(ptr::null_mut()) } + pub unsafe fn from_raw(raw: *mut T) -> Self { + WeakPtr(raw) + } + pub fn is_null(&self) -> bool { self.0.is_null() } diff --git a/src/command_list.rs b/src/command_list.rs index 77108e532..64fb76a4f 100644 --- a/src/command_list.rs +++ b/src/command_list.rs @@ -103,6 +103,12 @@ impl GraphicsCommandList { } } + pub fn clear_render_target_view(&self, rtv: CpuDescriptor, color: [f32; 4], rects: &[Rect]) { + unsafe { + self.ClearRenderTargetView(rtv, &color, rects.len() as _, rects.as_ptr()); + } + } + pub fn dispatch(&self, count: WorkGroupCount) { unsafe { self.Dispatch(count[0], count[1], count[2]); diff --git a/src/descriptor.rs b/src/descriptor.rs index 97a2e19a6..c5e70d863 100644 --- a/src/descriptor.rs +++ b/src/descriptor.rs @@ -1,6 +1,7 @@ use com::WeakPtr; use std::mem; use std::ops::Range; +use winapi::shared::dxgiformat; use winapi::um::d3d12; use {Blob, D3DResult, Error, TextureAddressMode}; @@ -198,3 +199,23 @@ impl RootSignature { ((blob, error), hr) } } + +#[repr(transparent)] +pub struct RenderTargetViewDesc(pub(crate) d3d12::D3D12_RENDER_TARGET_VIEW_DESC); + +impl RenderTargetViewDesc { + pub fn texture_2d(format: dxgiformat::DXGI_FORMAT, mip_slice: u32, plane_slice: u32) -> Self { + let mut desc = d3d12::D3D12_RENDER_TARGET_VIEW_DESC { + Format: format, + ViewDimension: d3d12::D3D12_RTV_DIMENSION_TEXTURE2D, + ..unsafe { mem::zeroed() } + }; + + *unsafe { desc.u.Texture2D_mut() } = d3d12::D3D12_TEX2D_RTV { + MipSlice: mip_slice, + PlaneSlice: plane_slice, + }; + + RenderTargetViewDesc(desc) + } +} diff --git a/src/device.rs b/src/device.rs index fc34810b7..33781064a 100644 --- a/src/device.rs +++ b/src/device.rs @@ -2,14 +2,14 @@ use com::WeakPtr; use command_list::{CmdListType, CommandSignature, IndirectArgument}; -use descriptor::{CpuDescriptor, HeapFlags, HeapType}; +use descriptor::{CpuDescriptor, HeapFlags, HeapType, RenderTargetViewDesc}; use std::ops::Range; use winapi::um::d3d12; use winapi::Interface; use {pso, query, queue}; use { Blob, CachedPSO, CommandAllocator, CommandQueue, D3DResult, DescriptorHeap, FeatureLevel, - GraphicsCommandList, NodeMask, PipelineState, QueryHeap, RootSignature, Shader, + GraphicsCommandList, NodeMask, PipelineState, QueryHeap, Resource, RootSignature, Shader, TextureAddressMode, }; @@ -265,4 +265,15 @@ impl Device { (signature, hr) } + + pub fn create_render_target_view( + &self, + resource: Resource, + desc: &RenderTargetViewDesc, + descriptor: CpuDescriptor, + ) { + unsafe { + self.CreateRenderTargetView(resource.as_mut_ptr(), &desc.0 as *const _, descriptor); + } + } } diff --git a/src/dxgi.rs b/src/dxgi.rs index 22d0d7352..1dade86b8 100644 --- a/src/dxgi.rs +++ b/src/dxgi.rs @@ -1,7 +1,10 @@ use com::WeakPtr; -use winapi::shared::{dxgi, dxgi1_3, dxgi1_4}; +use std::ptr; +use winapi::shared::windef::HWND; +use winapi::shared::{dxgi, dxgi1_2, dxgi1_3, dxgi1_4, dxgiformat, dxgitype}; +use winapi::um::d3d12; use winapi::Interface; -use D3DResult; +use {CommandQueue, D3DResult, Resource, SampleDesc, HRESULT}; bitflags! { pub struct FactoryCreationFlags: u32 { @@ -9,8 +12,95 @@ bitflags! { } } +#[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 Adapter1 = WeakPtr; +pub type Factory2 = WeakPtr; pub type Factory4 = WeakPtr; +pub type SwapChain = WeakPtr; +pub type SwapChain1 = WeakPtr; +pub type SwapChain3 = WeakPtr; + +// 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 Factory2 { + // TODO: interface not complete + pub fn create_swapchain_for_hwnd( + &self, + queue: CommandQueue, + hwnd: HWND, + desc: &SwapchainDesc, + ) -> D3DResult { + let desc = dxgi1_2::DXGI_SWAP_CHAIN_DESC1 { + AlphaMode: desc.alpha_mode as _, + BufferCount: desc.buffer_count, + Width: desc.width, + Height: desc.height, + Format: desc.format, + Flags: desc.flags, + BufferUsage: desc.buffer_usage, + SampleDesc: dxgitype::DXGI_SAMPLE_DESC { + Count: desc.sample.count, + Quality: desc.sample.quality, + }, + Scaling: desc.scaling as _, + Stereo: desc.stereo as _, + SwapEffect: desc.swap_effect as _, + }; + + let mut swap_chain = SwapChain1::null(); + let hr = unsafe { + self.CreateSwapChainForHwnd( + queue.as_mut_ptr() as *mut _, + hwnd, + &desc, + ptr::null(), + ptr::null_mut(), + swap_chain.mut_void() as *mut *mut _, + ) + }; + + (swap_chain, hr) + } +} impl Factory4 { pub fn create(flags: FactoryCreationFlags) -> D3DResult { @@ -26,6 +116,10 @@ impl Factory4 { (factory, hr) } + pub fn as2(&self) -> Factory2 { + unsafe { Factory2::from_raw(self.as_mut_ptr() as *mut _) } + } + pub fn enumerate_adapters(&self, id: u32) -> D3DResult { let mut adapter = Adapter1::null(); let hr = unsafe { self.EnumAdapters1(id, adapter.mut_void() as *mut *mut _) }; @@ -33,3 +127,34 @@ impl Factory4 { (adapter, hr) } } + +impl SwapChain { + pub fn get_buffer(&self, id: u32) -> D3DResult { + let mut resource = Resource::null(); + let hr = + unsafe { self.GetBuffer(id, &d3d12::ID3D12Resource::uuidof(), resource.mut_void()) }; + + (resource, hr) + } + + // TODO: present flags + pub fn present(&self, interval: u32, flags: u32) -> HRESULT { + unsafe { self.Present(interval, flags) } + } +} + +impl SwapChain1 { + pub fn as0(&self) -> SwapChain { + unsafe { SwapChain::from_raw(self.as_mut_ptr() as *mut _) } + } +} + +impl SwapChain3 { + pub fn as0(&self) -> SwapChain { + unsafe { SwapChain::from_raw(self.as_mut_ptr() as *mut _) } + } + + pub fn get_current_back_buffer_index(&self) -> u32 { + unsafe { self.GetCurrentBackBufferIndex() } + } +} diff --git a/src/lib.rs b/src/lib.rs index 5434912ff..0712584ef 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -52,6 +52,11 @@ pub type WorkGroupCount = [u32; 3]; pub type TextureAddressMode = [d3d12::D3D12_TEXTURE_ADDRESS_MODE; 3]; +pub struct SampleDesc { + pub count: u32, + pub quality: u32, +} + #[repr(u32)] pub enum FeatureLevel { L9_1 = d3dcommon::D3D_FEATURE_LEVEL_9_1, From e6ba80cb3922f32022adbde16d4963bc7bb2fabf Mon Sep 17 00:00:00 2001 From: msiglreith Date: Tue, 4 Sep 2018 19:09:23 +0200 Subject: [PATCH 3/4] Extend event and fence support --- Cargo.toml | 2 +- src/command_list.rs | 5 +++++ src/device.rs | 19 +++++++++++++++++-- src/sync.rs | 28 ++++++++++++++++++++++++---- 4 files changed, 47 insertions(+), 7 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 451272962..1063f5d08 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,4 +8,4 @@ bitflags = "1" [dependencies.winapi] version = "0.3" -features = ["dxgi1_2","dxgi1_3","dxgi1_4","d3d12","d3d12sdklayers","d3dcommon","d3dcompiler","dxgiformat","winerror"] \ No newline at end of file +features = ["dxgi1_2","dxgi1_3","dxgi1_4","d3d12","d3d12sdklayers","d3dcommon","d3dcompiler","dxgiformat","synchapi","winerror"] \ No newline at end of file diff --git a/src/command_list.rs b/src/command_list.rs index 64fb76a4f..e3725b95b 100644 --- a/src/command_list.rs +++ b/src/command_list.rs @@ -57,9 +57,14 @@ impl IndirectArgument { } pub type CommandSignature = WeakPtr; +pub type CommandList = WeakPtr; pub type GraphicsCommandList = WeakPtr; impl GraphicsCommandList { + pub fn as_list(&self) -> CommandList { + unsafe { CommandList::from_raw(self.as_mut_ptr() as *mut _) } + } + pub fn close(&self) -> HRESULT { unsafe { self.Close() } } diff --git a/src/device.rs b/src/device.rs index 33781064a..376c30418 100644 --- a/src/device.rs +++ b/src/device.rs @@ -9,8 +9,8 @@ use winapi::Interface; use {pso, query, queue}; use { Blob, CachedPSO, CommandAllocator, CommandQueue, D3DResult, DescriptorHeap, FeatureLevel, - GraphicsCommandList, NodeMask, PipelineState, QueryHeap, Resource, RootSignature, Shader, - TextureAddressMode, + Fence, GraphicsCommandList, NodeMask, PipelineState, QueryHeap, Resource, RootSignature, + Shader, TextureAddressMode, }; pub type Device = WeakPtr; @@ -276,4 +276,19 @@ impl Device { self.CreateRenderTargetView(resource.as_mut_ptr(), &desc.0 as *const _, descriptor); } } + + // TODO: interface not complete + pub fn create_fence(&self, initial: u64) -> D3DResult { + let mut fence = Fence::null(); + let hr = unsafe { + self.CreateFence( + initial, + d3d12::D3D12_FENCE_FLAG_NONE, + &d3d12::ID3D12Fence::uuidof(), + fence.mut_void(), + ) + }; + + (fence, hr) + } } diff --git a/src/sync.rs b/src/sync.rs index c10c73519..650fa6d00 100644 --- a/src/sync.rs +++ b/src/sync.rs @@ -1,14 +1,34 @@ use com::WeakPtr; +use std::ptr; use winapi::um::d3d12; -use winapi::um::winnt; +use winapi::um::{synchapi, winnt}; use HRESULT; -pub type Event = winnt::HANDLE; -pub type Fence = WeakPtr; +#[derive(Copy, Clone)] +#[repr(transparent)] +pub struct Event(winnt::HANDLE); +impl Event { + pub fn create(manual_reset: bool, initial_state: bool) -> Self { + Event(unsafe { + synchapi::CreateEventA( + ptr::null_mut(), + manual_reset as _, + initial_state as _, + ptr::null(), + ) + }) + } + // TODO: return value + pub fn wait(&self, timeout_ms: u32) -> u32 { + unsafe { synchapi::WaitForSingleObject(self.0, timeout_ms) } + } +} + +pub type Fence = WeakPtr; impl Fence { pub fn set_event_on_completion(&self, event: Event, value: u64) -> HRESULT { - unsafe { self.SetEventOnCompletion(value, event) } + unsafe { self.SetEventOnCompletion(value, event.0) } } pub fn get_value(&self) -> u64 { From bf7f2e68441f387b83b8bfb2c44654b1a38c8d89 Mon Sep 17 00:00:00 2001 From: msiglreith Date: Mon, 10 Sep 2018 18:17:37 +0200 Subject: [PATCH 4/4] Address review comments --- Cargo.toml | 2 +- src/debug.rs | 4 ++-- src/dxgi.rs | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 1063f5d08..393b6cb19 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,4 +8,4 @@ bitflags = "1" [dependencies.winapi] version = "0.3" -features = ["dxgi1_2","dxgi1_3","dxgi1_4","d3d12","d3d12sdklayers","d3dcommon","d3dcompiler","dxgiformat","synchapi","winerror"] \ No newline at end of file +features = ["dxgi1_2","dxgi1_3","dxgi1_4","d3d12","d3d12sdklayers","d3dcommon","d3dcompiler","dxgiformat","synchapi","winerror"] diff --git a/src/debug.rs b/src/debug.rs index 450beeac7..f614a27fa 100644 --- a/src/debug.rs +++ b/src/debug.rs @@ -6,7 +6,7 @@ use D3DResult; pub type Debug = WeakPtr; impl Debug { - pub fn get_debug_interface() -> D3DResult { + pub fn get_interface() -> D3DResult { let mut debug = Debug::null(); let hr = unsafe { d3d12::D3D12GetDebugInterface(&d3d12sdklayers::ID3D12Debug::uuidof(), debug.mut_void()) @@ -15,7 +15,7 @@ impl Debug { (debug, hr) } - pub fn enable_debug_layer(&self) { + pub fn enable_layer(&self) { unsafe { self.EnableDebugLayer() } } } diff --git a/src/dxgi.rs b/src/dxgi.rs index 1dade86b8..ad8b91e44 100644 --- a/src/dxgi.rs +++ b/src/dxgi.rs @@ -116,7 +116,7 @@ impl Factory4 { (factory, hr) } - pub fn as2(&self) -> Factory2 { + pub fn as_factory2(&self) -> Factory2 { unsafe { Factory2::from_raw(self.as_mut_ptr() as *mut _) } } @@ -144,13 +144,13 @@ impl SwapChain { } impl SwapChain1 { - pub fn as0(&self) -> SwapChain { + pub fn as_swapchain0(&self) -> SwapChain { unsafe { SwapChain::from_raw(self.as_mut_ptr() as *mut _) } } } impl SwapChain3 { - pub fn as0(&self) -> SwapChain { + pub fn as_swapchain0(&self) -> SwapChain { unsafe { SwapChain::from_raw(self.as_mut_ptr() as *mut _) } }