diff --git a/Cargo.toml b/Cargo.toml index 2033e5d36a..dbb116eb9e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "d3d12" -version = "0.6.0" +version = "0.7.0" authors = [ "gfx-rs developers", ] diff --git a/src/com.rs b/src/com.rs index f3a85789ce..66b338c9ee 100644 --- a/src/com.rs +++ b/src/com.rs @@ -8,15 +8,18 @@ use std::{ use winapi::{ctypes::c_void, um::unknwnbase::IUnknown, Interface}; #[repr(transparent)] -pub struct WeakPtr(*mut T); +pub struct ComPtr(*mut T); -impl WeakPtr { +impl ComPtr { pub fn null() -> Self { - WeakPtr(ptr::null_mut()) + ComPtr(ptr::null_mut()) } pub unsafe fn from_raw(raw: *mut T) -> Self { - WeakPtr(raw) + if !raw.is_null() { + (&*(raw as *mut IUnknown)).AddRef(); + } + ComPtr(raw) } pub fn is_null(&self) -> bool { @@ -40,40 +43,42 @@ impl WeakPtr { } } -impl WeakPtr { +impl ComPtr { pub unsafe fn as_unknown(&self) -> &IUnknown { debug_assert!(!self.is_null()); &*(self.0 as *mut IUnknown) } - // Cast creates a new WeakPtr requiring explicit destroy call. - pub unsafe fn cast(&self) -> D3DResult> + pub unsafe fn cast(&self) -> D3DResult> where U: Interface, { - let mut obj = WeakPtr::::null(); + debug_assert!(!self.is_null()); + let mut obj = ComPtr::::null(); let hr = self .as_unknown() .QueryInterface(&U::uuidof(), obj.mut_void()); (obj, hr) } - - // Destroying one instance of the WeakPtr will invalidate all - // copies and clones. - pub unsafe fn destroy(&self) { - self.as_unknown().Release(); - } } -impl Clone for WeakPtr { +impl Clone for ComPtr { fn clone(&self) -> Self { - WeakPtr(self.0) + debug_assert!(!self.is_null()); + unsafe { self.as_unknown().AddRef(); } + ComPtr(self.0) } } -impl Copy for WeakPtr {} +impl Drop for ComPtr { + fn drop(&mut self) { + if !self.0.is_null() { + unsafe { self.as_unknown().Release(); } + } + } +} -impl Deref for WeakPtr { +impl Deref for ComPtr { type Target = T; fn deref(&self) -> &T { debug_assert!(!self.is_null()); @@ -81,25 +86,25 @@ impl Deref for WeakPtr { } } -impl fmt::Debug for WeakPtr { +impl fmt::Debug for ComPtr { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "WeakPtr( ptr: {:?} )", self.0) + write!(f, "ComPtr( ptr: {:?} )", self.0) } } -impl PartialEq<*mut T> for WeakPtr { +impl PartialEq<*mut T> for ComPtr { fn eq(&self, other: &*mut T) -> bool { self.0 == *other } } -impl PartialEq for WeakPtr { +impl PartialEq for ComPtr { fn eq(&self, other: &Self) -> bool { self.0 == other.0 } } -impl Hash for WeakPtr { +impl Hash for ComPtr { fn hash(&self, state: &mut H) { self.0.hash(state); } @@ -110,9 +115,9 @@ impl Hash for WeakPtr { /// Give the variants so that parents come before children. This often manifests as going up in order (1 -> 2 -> 3). This is vital for safety. /// /// Three function names need to be attached to each variant. The examples are given for the MyComObject1 variant below: -/// - the from function (`WeakPtr -> Self`) -/// - the as function (`&self -> Option>`) -/// - the unwrap function (`&self -> WeakPtr` panicing on failure to cast) +/// - the from function (`ComPtr -> Self`) +/// - the as function (`&self -> Option>`) +/// - the unwrap function (`&self -> ComPtr` panicing on failure to cast) /// /// ```rust /// # pub use d3d12::weak_com_inheritance_chain; @@ -145,21 +150,12 @@ macro_rules! weak_com_inheritance_chain { ) => { $(#[$meta])* $vis enum $name { - $first_variant($crate::WeakPtr<$first_type>), + $first_variant($crate::ComPtr<$first_type>), $( - $variant($crate::WeakPtr<$type>) + $variant($crate::ComPtr<$type>) ),+ } impl $name { - $vis unsafe fn destroy(&self) { - match *self { - Self::$first_variant(v) => v.destroy(), - $( - Self::$variant(v) => v.destroy(), - )* - } - } - $crate::weak_com_inheritance_chain! { @recursion_logic, $vis, @@ -170,7 +166,7 @@ macro_rules! weak_com_inheritance_chain { } impl std::ops::Deref for $name { - type Target = $crate::WeakPtr<$first_type>; + type Target = $crate::ComPtr<$first_type>; fn deref(&self) -> &Self::Target { self.$first_unwrap_name() } @@ -223,12 +219,12 @@ macro_rules! weak_com_inheritance_chain { $($next_variant:ident),*; ) => { // Construct this enum from weak pointer to this interface. For best usability, always use the highest constructor you can. This doesn't try to upcast. - $vis unsafe fn $from_name(value: $crate::WeakPtr<$type>) -> Self { + $vis unsafe fn $from_name(value: $crate::ComPtr<$type>) -> Self { Self::$variant(value) } // Returns Some if the value implements the interface otherwise returns None. - $vis fn $as_name(&self) -> Option<&$crate::WeakPtr<$type>> { + $vis fn $as_name(&self) -> Option<&$crate::ComPtr<$type>> { match *self { $( Self::$prev_variant(_) => None, @@ -236,7 +232,7 @@ macro_rules! weak_com_inheritance_chain { Self::$variant(ref v) => Some(v), $( Self::$next_variant(ref v) => { - // v is &WeakPtr and se cast to &WeakPtr + // v is &ComPtr and se cast to &ComPtr Some(unsafe { std::mem::transmute(v) }) } )* @@ -245,7 +241,7 @@ macro_rules! weak_com_inheritance_chain { // Returns the interface if the value implements it, otherwise panics. #[track_caller] - $vis fn $unwrap_name(&self) -> &$crate::WeakPtr<$type> { + $vis fn $unwrap_name(&self) -> &$crate::ComPtr<$type> { match *self { $( Self::$prev_variant(_) => panic!(concat!("Tried to unwrap a ", stringify!($prev_variant), " as a ", stringify!($variant))), @@ -253,7 +249,7 @@ macro_rules! weak_com_inheritance_chain { Self::$variant(ref v) => &*v, $( Self::$next_variant(ref v) => { - // v is &WeakPtr and se cast to &WeakPtr + // v is &ComPtr and se cast to &ComPtr unsafe { std::mem::transmute(v) } } )* diff --git a/src/command_allocator.rs b/src/command_allocator.rs index 15b373583e..b50ec00d4a 100644 --- a/src/command_allocator.rs +++ b/src/command_allocator.rs @@ -1,9 +1,9 @@ //! Command Allocator -use crate::com::WeakPtr; +use crate::com::ComPtr; use winapi::um::d3d12; -pub type CommandAllocator = WeakPtr; +pub type CommandAllocator = ComPtr; impl CommandAllocator { pub fn reset(&self) { diff --git a/src/command_list.rs b/src/command_list.rs index 5ea04db809..015d5788b4 100644 --- a/src/command_list.rs +++ b/src/command_list.rs @@ -1,7 +1,7 @@ //! Graphics command list use crate::{ - com::WeakPtr, resource::DiscardRegion, CommandAllocator, CpuDescriptor, DescriptorHeap, Format, + com::ComPtr, resource::DiscardRegion, CommandAllocator, CpuDescriptor, DescriptorHeap, Format, GpuAddress, GpuDescriptor, IndexCount, InstanceCount, PipelineState, Rect, Resource, RootIndex, RootSignature, Subresource, VertexCount, VertexOffset, WorkGroupCount, HRESULT, }; @@ -140,9 +140,9 @@ impl ResourceBarrier { } } -pub type CommandSignature = WeakPtr; -pub type CommandList = WeakPtr; -pub type GraphicsCommandList = WeakPtr; +pub type CommandSignature = ComPtr; +pub type CommandList = ComPtr; +pub type GraphicsCommandList = ComPtr; impl GraphicsCommandList { pub fn as_list(&self) -> CommandList { @@ -153,7 +153,7 @@ impl GraphicsCommandList { unsafe { self.Close() } } - pub fn reset(&self, allocator: CommandAllocator, initial_pso: PipelineState) -> HRESULT { + pub fn reset(&self, allocator: &CommandAllocator, initial_pso: PipelineState) -> HRESULT { unsafe { self.Reset(allocator.as_mut_ptr(), initial_pso.as_mut_ptr()) } } @@ -263,7 +263,7 @@ impl GraphicsCommandList { } } - pub fn set_pipeline_state(&self, pso: PipelineState) { + pub fn set_pipeline_state(&self, pso:&PipelineState) { unsafe { self.SetPipelineState(pso.as_mut_ptr()); } @@ -284,13 +284,13 @@ impl GraphicsCommandList { } } - pub fn set_compute_root_signature(&self, signature: RootSignature) { + pub fn set_compute_root_signature(&self, signature: &RootSignature) { unsafe { self.SetComputeRootSignature(signature.as_mut_ptr()); } } - pub fn set_graphics_root_signature(&self, signature: RootSignature) { + pub fn set_graphics_root_signature(&self, signature: &RootSignature) { unsafe { self.SetGraphicsRootSignature(signature.as_mut_ptr()); } diff --git a/src/debug.rs b/src/debug.rs index d7768191b7..3a6abc46b7 100644 --- a/src/debug.rs +++ b/src/debug.rs @@ -1,9 +1,9 @@ -use crate::com::WeakPtr; +use crate::com::ComPtr; use winapi::um::d3d12sdklayers; #[cfg(any(feature = "libloading", feature = "implicit-link"))] use winapi::Interface as _; -pub type Debug = WeakPtr; +pub type Debug = ComPtr; #[cfg(feature = "libloading")] impl crate::D3D12Lib { diff --git a/src/descriptor.rs b/src/descriptor.rs index be9825f916..5bb1b5b351 100644 --- a/src/descriptor.rs +++ b/src/descriptor.rs @@ -1,4 +1,4 @@ -use crate::{com::WeakPtr, Blob, D3DResult, Error, TextureAddressMode}; +use crate::{com::ComPtr, Blob, D3DResult, Error, TextureAddressMode}; use std::{fmt, mem, ops::Range}; use winapi::{shared::dxgiformat, um::d3d12}; @@ -27,7 +27,7 @@ bitflags! { } } -pub type DescriptorHeap = WeakPtr; +pub type DescriptorHeap = ComPtr; impl DescriptorHeap { pub fn start_cpu_descriptor(&self) -> CpuDescriptor { @@ -265,7 +265,7 @@ bitflags! { } } -pub type RootSignature = WeakPtr; +pub type RootSignature = ComPtr; pub type BlobResult = D3DResult<(Blob, Error)>; #[cfg(feature = "libloading")] diff --git a/src/device.rs b/src/device.rs index 188eb40b1d..517b858bbf 100644 --- a/src/device.rs +++ b/src/device.rs @@ -1,7 +1,7 @@ //! Device use crate::{ - com::WeakPtr, + com::ComPtr, command_list::{CmdListType, CommandSignature, IndirectArgument}, descriptor::{CpuDescriptor, DescriptorHeapFlags, DescriptorHeapType, RenderTargetViewDesc}, heap::{Heap, HeapFlags, HeapProperties}, @@ -12,13 +12,13 @@ use crate::{ use std::ops::Range; use winapi::{um::d3d12, Interface}; -pub type Device = WeakPtr; +pub type Device = ComPtr; #[cfg(feature = "libloading")] impl crate::D3D12Lib { - pub fn create_device( +pub fn create_device( &self, - adapter: WeakPtr, + adapter: &ComPtr, feature_level: crate::FeatureLevel, ) -> Result, libloading::Error> { type Fun = extern "system" fn( @@ -46,7 +46,7 @@ impl crate::D3D12Lib { impl Device { #[cfg(feature = "implicit-link")] pub fn create( - adapter: WeakPtr, + adapter: ComPtr, feature_level: crate::FeatureLevel, ) -> D3DResult { let mut device = Device::null(); @@ -155,7 +155,7 @@ impl Device { pub fn create_graphics_command_list( &self, list_type: CmdListType, - allocator: CommandAllocator, + allocator: &CommandAllocator, initial: PipelineState, node_mask: NodeMask, ) -> D3DResult { @@ -215,7 +215,7 @@ impl Device { pub fn create_compute_pipeline_state( &self, - root_signature: RootSignature, + root_signature: &RootSignature, cs: Shader, node_mask: NodeMask, cached_pso: CachedPSO, diff --git a/src/dxgi.rs b/src/dxgi.rs index d66e0a86a7..81e2aaa1eb 100644 --- a/src/dxgi.rs +++ b/src/dxgi.rs @@ -1,4 +1,4 @@ -use crate::{com::WeakPtr, D3DResult, Resource, SampleDesc, HRESULT}; +use crate::{com::ComPtr, D3DResult, Resource, SampleDesc, HRESULT}; use std::ptr; use winapi::{ shared::{ @@ -43,14 +43,14 @@ pub enum AlphaMode { ForceDword = dxgi1_2::DXGI_ALPHA_MODE_FORCE_DWORD, } -pub type InfoQueue = WeakPtr; +pub type InfoQueue = ComPtr; -pub type Adapter1 = WeakPtr; -pub type Adapter2 = WeakPtr; -pub type Adapter3 = WeakPtr; -pub type Adapter4 = WeakPtr; +pub type Adapter1 = ComPtr; +pub type Adapter2 = ComPtr; +pub type Adapter3 = ComPtr; +pub type Adapter4 = ComPtr; crate::weak_com_inheritance_chain! { - #[derive(Debug, Copy, Clone, PartialEq, Hash)] + #[derive(Debug, Clone, PartialEq, Hash)] pub enum DxgiAdapter { Adapter1(dxgi::IDXGIAdapter1), from_adapter1, as_adapter1, adapter1; Adapter2(dxgi1_2::IDXGIAdapter2), from_adapter2, as_adapter2, unwrap_adapter2; @@ -59,14 +59,14 @@ crate::weak_com_inheritance_chain! { } } -pub type Factory1 = WeakPtr; -pub type Factory2 = WeakPtr; -pub type Factory3 = WeakPtr; -pub type Factory4 = WeakPtr; -pub type Factory5 = WeakPtr; -pub type Factory6 = WeakPtr; +pub type Factory1 = ComPtr; +pub type Factory2 = ComPtr; +pub type Factory3 = ComPtr; +pub type Factory4 = ComPtr; +pub type Factory5 = ComPtr; +pub type Factory6 = ComPtr; crate::weak_com_inheritance_chain! { - #[derive(Debug, Copy, Clone, PartialEq, Hash)] + #[derive(Debug, Clone, PartialEq, Hash)] pub enum DxgiFactory { Factory1(dxgi::IDXGIFactory1), from_factory1, as_factory1, factory1; Factory2(dxgi1_2::IDXGIFactory2), from_factory2, as_factory2, unwrap_factory2; @@ -77,14 +77,14 @@ crate::weak_com_inheritance_chain! { } } -pub type FactoryMedia = WeakPtr; +pub type FactoryMedia = ComPtr; -pub type SwapChain = WeakPtr; -pub type SwapChain1 = WeakPtr; -pub type SwapChain2 = WeakPtr; -pub type SwapChain3 = WeakPtr; +pub type SwapChain = ComPtr; +pub type SwapChain1 = ComPtr; +pub type SwapChain2 = ComPtr; +pub type SwapChain3 = ComPtr; crate::weak_com_inheritance_chain! { - #[derive(Debug, Copy, Clone, PartialEq, Hash)] + #[derive(Debug, 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; diff --git a/src/heap.rs b/src/heap.rs index 02e68bf279..8d081a2138 100644 --- a/src/heap.rs +++ b/src/heap.rs @@ -1,7 +1,7 @@ -use crate::com::WeakPtr; +use crate::com::ComPtr; use winapi::um::d3d12; -pub type Heap = WeakPtr; +pub type Heap = ComPtr; #[repr(u32)] #[derive(Clone, Copy)] diff --git a/src/lib.rs b/src/lib.rs index e52f9d9d46..8a68475dea 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -96,9 +96,9 @@ impl TryFrom for FeatureLevel { } } -pub type Blob = WeakPtr; +pub type Blob = ComPtr; -pub type Error = WeakPtr; +pub type Error = ComPtr; impl Error { pub unsafe fn as_c_str(&self) -> &CStr { debug_assert!(!self.is_null()); diff --git a/src/pso.rs b/src/pso.rs index 13f8ad82ed..2c19bd48d0 100644 --- a/src/pso.rs +++ b/src/pso.rs @@ -1,7 +1,7 @@ //! Pipeline state -use crate::{com::WeakPtr, Blob, D3DResult, Error}; -use std::{ffi, ops::Deref, ptr}; +use crate::{com::ComPtr, Blob, D3DResult, Error}; +use std::{ffi::{self, c_void}, ops::Deref, ptr, marker::PhantomData}; use winapi::um::{d3d12, d3dcompiler}; bitflags! { @@ -25,28 +25,28 @@ bitflags! { } #[derive(Copy, Clone)] -pub struct Shader(d3d12::D3D12_SHADER_BYTECODE); -impl Shader { +pub struct Shader<'a>(d3d12::D3D12_SHADER_BYTECODE, PhantomData<&'a c_void>); +impl<'a> Shader<'a> { pub fn null() -> Self { Shader(d3d12::D3D12_SHADER_BYTECODE { BytecodeLength: 0, pShaderBytecode: ptr::null(), - }) + }, PhantomData) } - pub fn from_raw(data: &[u8]) -> Self { + pub fn from_raw(data: &'a [u8]) -> Self { Shader(d3d12::D3D12_SHADER_BYTECODE { BytecodeLength: data.len() as _, pShaderBytecode: data.as_ptr() as _, - }) + }, PhantomData) } // `blob` may not be null. - pub fn from_blob(blob: Blob) -> Self { + pub fn from_blob(blob: &'a Blob) -> Self { Shader(d3d12::D3D12_SHADER_BYTECODE { BytecodeLength: unsafe { blob.GetBufferSize() }, pShaderBytecode: unsafe { blob.GetBufferPointer() }, - }) + }, PhantomData) } /// Compile a shader from raw HLSL. @@ -81,49 +81,40 @@ impl Shader { } } -impl Deref for Shader { +impl<'a> Deref for Shader<'a> { type Target = d3d12::D3D12_SHADER_BYTECODE; fn deref(&self) -> &Self::Target { &self.0 } } -impl From> for Shader { - fn from(blob: Option) -> Self { - match blob { - Some(b) => Shader::from_blob(b), - None => Shader::null(), - } - } -} - #[derive(Copy, Clone)] -pub struct CachedPSO(d3d12::D3D12_CACHED_PIPELINE_STATE); -impl CachedPSO { +pub struct CachedPSO<'a>(d3d12::D3D12_CACHED_PIPELINE_STATE, PhantomData<&'a c_void>); +impl<'a> CachedPSO<'a> { pub fn null() -> Self { CachedPSO(d3d12::D3D12_CACHED_PIPELINE_STATE { CachedBlobSizeInBytes: 0, pCachedBlob: ptr::null(), - }) + }, PhantomData) } // `blob` may not be null. - pub fn from_blob(blob: Blob) -> Self { + pub fn from_blob(blob: &'a Blob) -> Self { CachedPSO(d3d12::D3D12_CACHED_PIPELINE_STATE { CachedBlobSizeInBytes: unsafe { blob.GetBufferSize() }, pCachedBlob: unsafe { blob.GetBufferPointer() }, - }) + }, PhantomData) } } -impl Deref for CachedPSO { +impl<'a> Deref for CachedPSO<'a> { type Target = d3d12::D3D12_CACHED_PIPELINE_STATE; fn deref(&self) -> &Self::Target { &self.0 } } -pub type PipelineState = WeakPtr; +pub type PipelineState = ComPtr; #[repr(u32)] pub enum Subobject { diff --git a/src/query.rs b/src/query.rs index b5925c860b..a9dca262bc 100644 --- a/src/query.rs +++ b/src/query.rs @@ -1,4 +1,4 @@ -use crate::com::WeakPtr; +use crate::com::ComPtr; use winapi::um::d3d12; #[repr(u32)] @@ -12,4 +12,4 @@ pub enum QueryHeapType { // CopyQueueTimestamp = d3d12::D3D12_QUERY_HEAP_TYPE_COPY_QUEUE_TIMESTAMP, } -pub type QueryHeap = WeakPtr; +pub type QueryHeap = ComPtr; diff --git a/src/queue.rs b/src/queue.rs index c3869f0cd9..944cb6f327 100644 --- a/src/queue.rs +++ b/src/queue.rs @@ -1,4 +1,4 @@ -use crate::{com::WeakPtr, sync::Fence, CommandList, HRESULT}; +use crate::{com::ComPtr, sync::Fence, CommandList, HRESULT}; use winapi::um::d3d12; #[repr(u32)] @@ -15,7 +15,7 @@ bitflags! { } } -pub type CommandQueue = WeakPtr; +pub type CommandQueue = ComPtr; impl CommandQueue { pub fn execute_command_lists(&self, command_lists: &[CommandList]) { @@ -26,7 +26,7 @@ impl CommandQueue { unsafe { self.ExecuteCommandLists(command_lists.len() as _, command_lists.as_ptr()) } } - pub fn signal(&self, fence: Fence, value: u64) -> HRESULT { + pub fn signal(&self, fence: &Fence, value: u64) -> HRESULT { unsafe { self.Signal(fence.as_mut_ptr(), value) } } } diff --git a/src/resource.rs b/src/resource.rs index a1242228cd..bdc669dd31 100644 --- a/src/resource.rs +++ b/src/resource.rs @@ -1,6 +1,6 @@ //! GPU Resource -use crate::{com::WeakPtr, D3DResult, Rect}; +use crate::{com::ComPtr, D3DResult, Rect}; use std::{ops::Range, ptr}; use winapi::um::d3d12; @@ -11,7 +11,7 @@ pub struct DiscardRegion<'a> { pub subregions: Range, } -pub type Resource = WeakPtr; +pub type Resource = ComPtr; impl Resource { /// diff --git a/src/sync.rs b/src/sync.rs index f1f3bb9bca..fa5f090409 100644 --- a/src/sync.rs +++ b/src/sync.rs @@ -1,4 +1,4 @@ -use crate::{com::WeakPtr, HRESULT}; +use crate::{com::ComPtr, HRESULT}; use std::ptr; use winapi::um::{d3d12, synchapi, winnt}; @@ -23,7 +23,7 @@ impl Event { } } -pub type Fence = WeakPtr; +pub type Fence = ComPtr; impl Fence { pub fn set_event_on_completion(&self, event: Event, value: u64) -> HRESULT { unsafe { self.SetEventOnCompletion(value, event.0) }