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,