diff --git a/CHANGELOG.md b/CHANGELOG.md index 324ebd9f9..5caf8235b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -88,6 +88,10 @@ By @wumpf in [#6069](https://github.com/gfx-rs/wgpu/pull/6069), [#6099](https:// - Replace `winapi` code in WGL wrapper to use the `windows` crate. By @MarijnS95 in [#6006](https://github.com/gfx-rs/wgpu/pull/6006) +#### DX12 + +- Replace `winapi` code to use the `windows` crate. By @MarijnS95 in [#5956](https://github.com/gfx-rs/wgpu/pull/5956) + ## 22.0.0 (2024-07-17) ### Overview @@ -749,7 +753,7 @@ The easiest way to make this code safe is to use shared ownership: ```rust let window: Arc; // ... -let surface = instance.create_surface(my_window.clone())?; +let surface = instance.create_surface(window.clone())?; ``` All platform specific surface creation using points have moved into `SurfaceTargetUnsafe` as well. diff --git a/Cargo.lock b/Cargo.lock index c010f7045..f8c89e846 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -915,15 +915,6 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96a6ac251f4a2aca6b3f91340350eab87ae57c3f127ffeb585e92bd336717991" -[[package]] -name = "d3d12" -version = "22.0.0" -dependencies = [ - "bitflags 2.6.0", - "libloading 0.8.5", - "winapi", -] - [[package]] name = "darling" version = "0.13.4" @@ -1684,7 +1675,6 @@ dependencies = [ "log", "presser", "thiserror", - "winapi", "windows", ] @@ -4325,7 +4315,6 @@ dependencies = [ "cfg-if", "cfg_aliases", "core-graphics-types", - "d3d12", "env_logger", "glam", "glow", @@ -4356,8 +4345,8 @@ dependencies = [ "wasm-bindgen", "web-sys", "wgpu-types", - "winapi", "windows", + "windows-core", "winit 0.29.15", ] diff --git a/Cargo.toml b/Cargo.toml index 04b26b804..6f1c7ec89 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,7 +6,6 @@ members = [ # default members "benches", - "d3d12", "examples", "naga-cli", "naga", @@ -24,7 +23,6 @@ members = [ exclude = [] default-members = [ "benches", - "d3d12", "examples", "naga-cli", "naga", @@ -96,8 +94,7 @@ indexmap = "2" itertools = { version = "0.10.5" } ktx2 = "0.3" libc = "0.2" -# libloading 0.8 switches from `winapi` to `windows-sys`; permit either -libloading = ">=0.7, <0.9" +libloading = "0.8" libtest-mimic = "0.6" log = "0.4" nanorand = { version = "0.7", default-features = false, features = ["wyrand"] } @@ -148,14 +145,10 @@ gpu-descriptor = "0.3" # DX dependencies bit-set = "0.8" -gpu-allocator = { version = "0.27", default-features = false, features = [ - "d3d12", - "public-winapi", -] } -d3d12 = { version = "22.0.0", path = "./d3d12/" } +gpu-allocator = { version = "0.27", default-features = false } range-alloc = "0.1" -winapi = "0.3" hassle-rs = "0.11.0" +windows-core = { version = "0.58", default-features = false } # Gles dependencies khronos-egl = "6" diff --git a/d3d12/CHANGELOG.md b/d3d12/CHANGELOG.md deleted file mode 100644 index 6af566ae6..000000000 --- a/d3d12/CHANGELOG.md +++ /dev/null @@ -1,32 +0,0 @@ -# Change Log - -## v0.6.0 (2023-01-25) - - add helpers for IDXGIFactoryMedia - - add `create_swapchain_for_composition_surface_handle` - -## v0.5.0 (2022-07-01) - - add COM helpers - - enable D3D11 adapter use - -## v0.4.1 (2021-08-18) - - expose all indirect argument types - - expose methods for setting root constants - -## v0.4.0 (2021-04-29) - - update `libloading` to 0.7 - -## v0.3.1 (2020-07-07) - - create shader from IL - - fix default doc target - - debug impl for root descriptors - -## v0.3.0 (2019-11-01) - - resource transitions - - dynamic library loading - -## v0.2.2 (2019-10-04) - - add `D3DHeap` - - add root descriptor - -## v0.1.0 (2018-12-26) - - basic version diff --git a/d3d12/Cargo.toml b/d3d12/Cargo.toml deleted file mode 100644 index a792aeab6..000000000 --- a/d3d12/Cargo.toml +++ /dev/null @@ -1,45 +0,0 @@ -[package] -name = "d3d12" -version = "22.0.0" -authors = ["gfx-rs developers"] -description = "Low level D3D12 API wrapper" -repository = "https://github.com/gfx-rs/wgpu/tree/trunk/d3d12" -keywords = ["windows", "graphics"] -license = "MIT OR Apache-2.0" -documentation = "https://docs.rs/d3d12" -categories = [ - "api-bindings", - "graphics", - "memory-management", - "os::windows-apis", -] -edition = "2018" - -[features] -implicit-link = [] - -[target.'cfg(windows)'.dependencies] -bitflags = "2" -# libloading 0.8 switches from `winapi` to `windows-sys`; permit either -libloading = { version = ">=0.7, <0.9", optional = true } - -[target.'cfg(windows)'.dependencies.winapi] -version = "0.3" -features = [ - "dxgi1_2", - "dxgi1_3", - "dxgi1_4", - "dxgi1_5", - "dxgi1_6", - "dxgidebug", - "d3d12", - "d3d12sdklayers", - "d3dcommon", - "d3dcompiler", - "dxgiformat", - "synchapi", - "winerror", -] - -[package.metadata.docs.rs] -targets = ["x86_64-pc-windows-msvc"] diff --git a/d3d12/README.md b/d3d12/README.md deleted file mode 100644 index 718bf7355..000000000 --- a/d3d12/README.md +++ /dev/null @@ -1,5 +0,0 @@ -# d3d12-rs -[![Crates.io](https://img.shields.io/crates/v/d3d12.svg)](https://crates.io/crates/d3d12) -[![Docs.rs](https://docs.rs/d3d12/badge.svg)](https://docs.rs/d3d12) - -Rust wrapper for raw D3D12 access. diff --git a/d3d12/src/com.rs b/d3d12/src/com.rs deleted file mode 100644 index 556495f61..000000000 --- a/d3d12/src/com.rs +++ /dev/null @@ -1,263 +0,0 @@ -use crate::D3DResult; -use std::{ - fmt, - hash::{Hash, Hasher}, - ops::Deref, - ptr, -}; -use winapi::{ctypes::c_void, um::unknwnbase::IUnknown, Interface}; - -#[repr(transparent)] -pub struct ComPtr(*mut T); - -impl ComPtr { - pub fn null() -> Self { - ComPtr(ptr::null_mut()) - } - - pub unsafe fn from_raw(raw: *mut T) -> Self { - if !raw.is_null() { - (*(raw as *mut IUnknown)).AddRef(); - } - ComPtr(raw) - } - - pub fn is_null(&self) -> bool { - self.0.is_null() - } - - pub fn as_ptr(&self) -> *const T { - self.0 - } - - pub fn as_mut_ptr(&self) -> *mut T { - self.0 - } - - pub fn mut_void(&mut self) -> *mut *mut c_void { - &mut self.0 as *mut *mut _ as *mut *mut _ - } - - pub fn mut_self(&mut self) -> *mut *mut T { - &mut self.0 as *mut *mut _ - } -} - -impl ComPtr { - pub unsafe fn as_unknown(&self) -> &IUnknown { - debug_assert!(!self.is_null()); - &*(self.0 as *mut IUnknown) - } - - pub unsafe fn cast(&self) -> D3DResult> - where - U: Interface, - { - debug_assert!(!self.is_null()); - let mut obj = ComPtr::::null(); - let hr = self - .as_unknown() - .QueryInterface(&U::uuidof(), obj.mut_void()); - (obj, hr) - } -} - -impl Clone for ComPtr { - fn clone(&self) -> Self { - debug_assert!(!self.is_null()); - unsafe { - self.as_unknown().AddRef(); - } - ComPtr(self.0) - } -} - -impl Drop for ComPtr { - fn drop(&mut self) { - if !self.0.is_null() { - unsafe { - self.as_unknown().Release(); - } - } - } -} - -impl Deref for ComPtr { - type Target = T; - fn deref(&self) -> &T { - debug_assert!(!self.is_null()); - unsafe { &*self.0 } - } -} - -impl fmt::Debug for ComPtr { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "ComPtr( ptr: {:?} )", self.0) - } -} - -impl PartialEq<*mut T> for ComPtr { - fn eq(&self, other: &*mut T) -> bool { - self.0 == *other - } -} - -impl PartialEq for ComPtr { - fn eq(&self, other: &Self) -> bool { - self.0 == other.0 - } -} - -impl Hash for ComPtr { - fn hash(&self, state: &mut H) { - self.0.hash(state); - } -} - -/// Macro that allows generation of an easy to use enum for dealing with many different possible versions of a COM object. -/// -/// 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 (`ComPtr -> Self`) -/// - the as function (`&self -> Option>`) -/// - the unwrap function (`&self -> ComPtr` panicking on failure to cast) -/// -/// ```rust -/// # pub use d3d12::weak_com_inheritance_chain; -/// # mod actual { -/// # pub struct ComObject; impl winapi::Interface for ComObject { fn uuidof() -> winapi::shared::guiddef::GUID { todo!() } } -/// # pub struct ComObject1; impl winapi::Interface for ComObject1 { fn uuidof() -> winapi::shared::guiddef::GUID { todo!() } } -/// # pub struct ComObject2; impl winapi::Interface for ComObject2 { fn uuidof() -> winapi::shared::guiddef::GUID { todo!() } } -/// # } -/// weak_com_inheritance_chain! { -/// pub enum MyComObject { -/// MyComObject(actual::ComObject), from_my_com_object, as_my_com_object, my_com_object; // First variant doesn't use "unwrap" as it can never fail -/// MyComObject1(actual::ComObject1), from_my_com_object1, as_my_com_object1, unwrap_my_com_object1; -/// MyComObject2(actual::ComObject2), from_my_com_object2, as_my_com_object2, unwrap_my_com_object2; -/// } -/// } -/// ``` -#[macro_export] -macro_rules! weak_com_inheritance_chain { - // We first match a human readable enum style, before going into the recursive section. - // - // Internal calls to the macro have either the prefix - // - @recursion_logic for the recursion and termination - // - @render_members for the actual call to fill in the members. - ( - $(#[$meta:meta])* - $vis:vis enum $name:ident { - $first_variant:ident($first_type:ty), $first_from_name:ident, $first_as_name:ident, $first_unwrap_name:ident $(;)? - $($variant:ident($type:ty), $from_name:ident, $as_name:ident, $unwrap_name:ident);* $(;)? - } - ) => { - $(#[$meta])* - $vis enum $name { - $first_variant($crate::ComPtr<$first_type>), - $( - $variant($crate::ComPtr<$type>) - ),+ - } - impl $name { - $crate::weak_com_inheritance_chain! { - @recursion_logic, - $vis, - ; - $first_variant($first_type), $first_from_name, $first_as_name, $first_unwrap_name; - $($variant($type), $from_name, $as_name, $unwrap_name);* - } - } - - impl std::ops::Deref for $name { - type Target = $crate::ComPtr<$first_type>; - fn deref(&self) -> &Self::Target { - self.$first_unwrap_name() - } - } - }; - - // This is the iteration case of the recursion. We instantiate the member functions for the variant we - // are currently at, recursing on ourself for the next variant. Note we only keep track of the previous - // variant name, not the functions names, as those are not needed. - ( - @recursion_logic, - $vis:vis, - $(,)? $($prev_variant:ident),* $(,)?; - $this_variant:ident($this_type:ty), $this_from_name:ident, $this_as_name:ident, $this_unwrap_name:ident $(;)? - $($next_variant:ident($next_type:ty), $next_from_name:ident, $next_as_name:ident, $next_unwrap_name:ident);* - ) => { - // Actually generate the members for this variant. Needs the previous and future variant names. - $crate::weak_com_inheritance_chain! { - @render_members, - $vis, - $this_from_name, $this_as_name, $this_unwrap_name; - $($prev_variant),*; - $this_variant($this_type); - $($next_variant),*; - } - - // Recurse on ourselves. If there is no future variants left, we'll hit the base case as the final expansion returns no tokens. - $crate::weak_com_inheritance_chain! { - @recursion_logic, - $vis, - $($prev_variant),* , $this_variant; - $($next_variant($next_type), $next_from_name, $next_as_name, $next_unwrap_name);* - } - }; - // Base case for recursion. There are no more variants left - ( - @recursion_logic, - $vis:vis, - $($prev_variant:ident),*; - ) => {}; - - - // This is where we generate the members using the given names. - ( - @render_members, - $vis:vis, - $from_name:ident, $as_name:ident, $unwrap_name:ident; - $($prev_variant:ident),*; - $variant:ident($type:ty); - $($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::ComPtr<$type>) -> Self { - Self::$variant(value) - } - - // Returns Some if the value implements the interface otherwise returns None. - $vis fn $as_name(&self) -> Option<&$crate::ComPtr<$type>> { - match *self { - $( - Self::$prev_variant(_) => None, - )* - Self::$variant(ref v) => Some(v), - $( - Self::$next_variant(ref v) => { - // v is &ComPtr and se cast to &ComPtr - Some(unsafe { std::mem::transmute(v) }) - } - )* - } - } - - // Returns the interface if the value implements it, otherwise panics. - #[track_caller] - $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))), - )* - Self::$variant(ref v) => &*v, - $( - Self::$next_variant(ref v) => { - // v is &ComPtr and se cast to &ComPtr - unsafe { std::mem::transmute(v) } - } - )* - } - } - }; -} diff --git a/d3d12/src/command_allocator.rs b/d3d12/src/command_allocator.rs deleted file mode 100644 index b50ec00d4..000000000 --- a/d3d12/src/command_allocator.rs +++ /dev/null @@ -1,14 +0,0 @@ -//! Command Allocator - -use crate::com::ComPtr; -use winapi::um::d3d12; - -pub type CommandAllocator = ComPtr; - -impl CommandAllocator { - pub fn reset(&self) { - unsafe { - self.Reset(); - } - } -} diff --git a/d3d12/src/command_list.rs b/d3d12/src/command_list.rs deleted file mode 100644 index 1f8c0d53c..000000000 --- a/d3d12/src/command_list.rs +++ /dev/null @@ -1,406 +0,0 @@ -//! Graphics command list - -use crate::{ - com::ComPtr, resource::DiscardRegion, CommandAllocator, CpuDescriptor, DescriptorHeap, Format, - GpuAddress, GpuDescriptor, IndexCount, InstanceCount, PipelineState, Rect, Resource, RootIndex, - RootSignature, Subresource, VertexCount, VertexOffset, WorkGroupCount, HRESULT, -}; -use std::{mem, ptr}; -use winapi::um::d3d12; - -#[repr(u32)] -#[derive(Clone, Copy)] -pub enum CmdListType { - Direct = d3d12::D3D12_COMMAND_LIST_TYPE_DIRECT, - Bundle = d3d12::D3D12_COMMAND_LIST_TYPE_BUNDLE, - Compute = d3d12::D3D12_COMMAND_LIST_TYPE_COMPUTE, - Copy = d3d12::D3D12_COMMAND_LIST_TYPE_COPY, - // VideoDecode = d3d12::D3D12_COMMAND_LIST_TYPE_VIDEO_DECODE, - // VideoProcess = d3d12::D3D12_COMMAND_LIST_TYPE_VIDEO_PROCESS, -} - -bitflags::bitflags! { - #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] - pub struct ClearFlags: u32 { - const DEPTH = d3d12::D3D12_CLEAR_FLAG_DEPTH; - const STENCIL = d3d12::D3D12_CLEAR_FLAG_STENCIL; - } -} - -#[repr(transparent)] -pub struct IndirectArgument(d3d12::D3D12_INDIRECT_ARGUMENT_DESC); - -impl IndirectArgument { - pub fn draw() -> Self { - IndirectArgument(d3d12::D3D12_INDIRECT_ARGUMENT_DESC { - Type: d3d12::D3D12_INDIRECT_ARGUMENT_TYPE_DRAW, - ..unsafe { mem::zeroed() } - }) - } - - pub fn draw_indexed() -> Self { - IndirectArgument(d3d12::D3D12_INDIRECT_ARGUMENT_DESC { - Type: d3d12::D3D12_INDIRECT_ARGUMENT_TYPE_DRAW_INDEXED, - ..unsafe { mem::zeroed() } - }) - } - - pub fn dispatch() -> Self { - IndirectArgument(d3d12::D3D12_INDIRECT_ARGUMENT_DESC { - Type: d3d12::D3D12_INDIRECT_ARGUMENT_TYPE_DISPATCH, - ..unsafe { mem::zeroed() } - }) - } - - pub fn vertex_buffer(slot: u32) -> Self { - let mut desc = d3d12::D3D12_INDIRECT_ARGUMENT_DESC { - Type: d3d12::D3D12_INDIRECT_ARGUMENT_TYPE_VERTEX_BUFFER_VIEW, - ..unsafe { mem::zeroed() } - }; - *unsafe { desc.u.VertexBuffer_mut() } = - d3d12::D3D12_INDIRECT_ARGUMENT_DESC_VertexBuffer { Slot: slot }; - IndirectArgument(desc) - } - - pub fn constant(root_index: RootIndex, dest_offset_words: u32, count: u32) -> Self { - let mut desc = d3d12::D3D12_INDIRECT_ARGUMENT_DESC { - Type: d3d12::D3D12_INDIRECT_ARGUMENT_TYPE_CONSTANT, - ..unsafe { mem::zeroed() } - }; - *unsafe { desc.u.Constant_mut() } = d3d12::D3D12_INDIRECT_ARGUMENT_DESC_Constant { - RootParameterIndex: root_index, - DestOffsetIn32BitValues: dest_offset_words, - Num32BitValuesToSet: count, - }; - IndirectArgument(desc) - } - - pub fn constant_buffer_view(root_index: RootIndex) -> Self { - let mut desc = d3d12::D3D12_INDIRECT_ARGUMENT_DESC { - Type: d3d12::D3D12_INDIRECT_ARGUMENT_TYPE_CONSTANT_BUFFER_VIEW, - ..unsafe { mem::zeroed() } - }; - *unsafe { desc.u.ConstantBufferView_mut() } = - d3d12::D3D12_INDIRECT_ARGUMENT_DESC_ConstantBufferView { - RootParameterIndex: root_index, - }; - IndirectArgument(desc) - } - - pub fn shader_resource_view(root_index: RootIndex) -> Self { - let mut desc = d3d12::D3D12_INDIRECT_ARGUMENT_DESC { - Type: d3d12::D3D12_INDIRECT_ARGUMENT_TYPE_SHADER_RESOURCE_VIEW, - ..unsafe { mem::zeroed() } - }; - *unsafe { desc.u.ShaderResourceView_mut() } = - d3d12::D3D12_INDIRECT_ARGUMENT_DESC_ShaderResourceView { - RootParameterIndex: root_index, - }; - IndirectArgument(desc) - } - - pub fn unordered_access_view(root_index: RootIndex) -> Self { - let mut desc = d3d12::D3D12_INDIRECT_ARGUMENT_DESC { - Type: d3d12::D3D12_INDIRECT_ARGUMENT_TYPE_UNORDERED_ACCESS_VIEW, - ..unsafe { mem::zeroed() } - }; - *unsafe { desc.u.UnorderedAccessView_mut() } = - d3d12::D3D12_INDIRECT_ARGUMENT_DESC_UnorderedAccessView { - RootParameterIndex: root_index, - }; - IndirectArgument(desc) - } -} - -#[repr(transparent)] -pub struct ResourceBarrier(d3d12::D3D12_RESOURCE_BARRIER); - -impl ResourceBarrier { - pub fn transition( - resource: Resource, - subresource: Subresource, - state_before: d3d12::D3D12_RESOURCE_STATES, - state_after: d3d12::D3D12_RESOURCE_STATES, - flags: d3d12::D3D12_RESOURCE_BARRIER_FLAGS, - ) -> Self { - let mut barrier = d3d12::D3D12_RESOURCE_BARRIER { - Type: d3d12::D3D12_RESOURCE_BARRIER_TYPE_TRANSITION, - Flags: flags, - ..unsafe { mem::zeroed() } - }; - unsafe { - *barrier.u.Transition_mut() = d3d12::D3D12_RESOURCE_TRANSITION_BARRIER { - pResource: resource.as_mut_ptr(), - Subresource: subresource, - StateBefore: state_before, - StateAfter: state_after, - }; - } - ResourceBarrier(barrier) - } -} - -pub type CommandSignature = ComPtr; -pub type CommandList = ComPtr; -pub type GraphicsCommandList = ComPtr; - -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() } - } - - pub fn reset(&self, allocator: &CommandAllocator, initial_pso: PipelineState) -> HRESULT { - unsafe { self.Reset(allocator.as_mut_ptr(), initial_pso.as_mut_ptr()) } - } - - pub fn discard_resource(&self, resource: Resource, region: DiscardRegion) { - debug_assert!(region.subregions.start < region.subregions.end); - unsafe { - self.DiscardResource( - resource.as_mut_ptr(), - &d3d12::D3D12_DISCARD_REGION { - NumRects: region.rects.len() as _, - pRects: region.rects.as_ptr(), - FirstSubresource: region.subregions.start, - NumSubresources: region.subregions.end - region.subregions.start - 1, - }, - ); - } - } - - pub fn clear_depth_stencil_view( - &self, - dsv: CpuDescriptor, - flags: ClearFlags, - depth: f32, - stencil: u8, - rects: &[Rect], - ) { - let num_rects = rects.len() as _; - let rects = if num_rects > 0 { - rects.as_ptr() - } else { - ptr::null() - }; - unsafe { - self.ClearDepthStencilView(dsv, flags.bits(), depth, stencil, num_rects, rects); - } - } - - pub fn clear_render_target_view(&self, rtv: CpuDescriptor, color: [f32; 4], rects: &[Rect]) { - let num_rects = rects.len() as _; - let rects = if num_rects > 0 { - rects.as_ptr() - } else { - ptr::null() - }; - unsafe { - self.ClearRenderTargetView(rtv, &color, num_rects, rects); - } - } - - pub fn dispatch(&self, count: WorkGroupCount) { - unsafe { - self.Dispatch(count[0], count[1], count[2]); - } - } - - pub fn draw( - &self, - num_vertices: VertexCount, - num_instances: InstanceCount, - first_vertex: VertexCount, - first_instance: InstanceCount, - ) { - unsafe { - self.DrawInstanced(num_vertices, num_instances, first_vertex, first_instance); - } - } - - pub fn draw_indexed( - &self, - num_indices: IndexCount, - num_instances: InstanceCount, - first_index: IndexCount, - base_vertex: VertexOffset, - first_instance: InstanceCount, - ) { - unsafe { - self.DrawIndexedInstanced( - num_indices, - num_instances, - first_index, - base_vertex, - first_instance, - ); - } - } - - pub fn set_index_buffer(&self, gpu_address: GpuAddress, size: u32, format: Format) { - let ibv = d3d12::D3D12_INDEX_BUFFER_VIEW { - BufferLocation: gpu_address, - SizeInBytes: size, - Format: format, - }; - unsafe { - self.IASetIndexBuffer(&ibv); - } - } - - pub fn set_blend_factor(&self, factor: [f32; 4]) { - unsafe { - self.OMSetBlendFactor(&factor); - } - } - - pub fn set_stencil_reference(&self, reference: u32) { - unsafe { - self.OMSetStencilRef(reference); - } - } - - pub fn set_pipeline_state(&self, pso: &PipelineState) { - unsafe { - self.SetPipelineState(pso.as_mut_ptr()); - } - } - - pub fn execute_bundle(&self, bundle: GraphicsCommandList) { - unsafe { - self.ExecuteBundle(bundle.as_mut_ptr()); - } - } - - pub fn set_descriptor_heaps(&self, heaps: &[DescriptorHeap]) { - unsafe { - self.SetDescriptorHeaps( - heaps.len() as _, - heaps.as_ptr() as *mut &DescriptorHeap as *mut _, - ); - } - } - - 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) { - unsafe { - self.SetGraphicsRootSignature(signature.as_mut_ptr()); - } - } - - pub fn set_compute_root_descriptor_table( - &self, - root_index: RootIndex, - base_descriptor: GpuDescriptor, - ) { - unsafe { - self.SetComputeRootDescriptorTable(root_index, base_descriptor); - } - } - - pub fn set_compute_root_constant_buffer_view( - &self, - root_index: RootIndex, - buffer_location: GpuAddress, - ) { - unsafe { - self.SetComputeRootConstantBufferView(root_index, buffer_location); - } - } - - pub fn set_compute_root_shader_resource_view( - &self, - root_index: RootIndex, - buffer_location: GpuAddress, - ) { - unsafe { - self.SetComputeRootShaderResourceView(root_index, buffer_location); - } - } - - pub fn set_compute_root_unordered_access_view( - &self, - root_index: RootIndex, - buffer_location: GpuAddress, - ) { - unsafe { - self.SetComputeRootUnorderedAccessView(root_index, buffer_location); - } - } - - pub fn set_compute_root_constant( - &self, - root_index: RootIndex, - value: u32, - dest_offset_words: u32, - ) { - unsafe { - self.SetComputeRoot32BitConstant(root_index, value, dest_offset_words); - } - } - - pub fn set_graphics_root_descriptor_table( - &self, - root_index: RootIndex, - base_descriptor: GpuDescriptor, - ) { - unsafe { - self.SetGraphicsRootDescriptorTable(root_index, base_descriptor); - } - } - - pub fn set_graphics_root_constant_buffer_view( - &self, - root_index: RootIndex, - buffer_location: GpuAddress, - ) { - unsafe { - self.SetGraphicsRootConstantBufferView(root_index, buffer_location); - } - } - - pub fn set_graphics_root_shader_resource_view( - &self, - root_index: RootIndex, - buffer_location: GpuAddress, - ) { - unsafe { - self.SetGraphicsRootShaderResourceView(root_index, buffer_location); - } - } - - pub fn set_graphics_root_unordered_access_view( - &self, - root_index: RootIndex, - buffer_location: GpuAddress, - ) { - unsafe { - self.SetGraphicsRootUnorderedAccessView(root_index, buffer_location); - } - } - - pub fn set_graphics_root_constant( - &self, - root_index: RootIndex, - value: u32, - dest_offset_words: u32, - ) { - unsafe { - self.SetGraphicsRoot32BitConstant(root_index, value, dest_offset_words); - } - } - - pub fn resource_barrier(&self, barriers: &[ResourceBarrier]) { - unsafe { - self.ResourceBarrier(barriers.len() as _, barriers.as_ptr() as _) // matches representation - } - } -} diff --git a/d3d12/src/debug.rs b/d3d12/src/debug.rs deleted file mode 100644 index f321d878d..000000000 --- a/d3d12/src/debug.rs +++ /dev/null @@ -1,56 +0,0 @@ -use crate::com::ComPtr; -#[cfg(any(feature = "libloading", feature = "implicit-link"))] -use winapi::Interface as _; -use winapi::{ - shared::{minwindef::TRUE, winerror::S_OK}, - um::d3d12sdklayers, -}; - -pub type Debug = ComPtr; - -#[cfg(feature = "libloading")] -impl crate::D3D12Lib { - pub fn get_debug_interface(&self) -> Result, libloading::Error> { - type Fun = extern "system" fn( - winapi::shared::guiddef::REFIID, - *mut *mut winapi::ctypes::c_void, - ) -> crate::HRESULT; - - let mut debug = Debug::null(); - let hr = unsafe { - let func: libloading::Symbol = self.lib.get(b"D3D12GetDebugInterface")?; - func(&d3d12sdklayers::ID3D12Debug::uuidof(), debug.mut_void()) - }; - - Ok((debug, hr)) - } -} - -impl Debug { - #[cfg(feature = "implicit-link")] - pub fn get_interface() -> crate::D3DResult { - let mut debug = Debug::null(); - let hr = unsafe { - winapi::um::d3d12::D3D12GetDebugInterface( - &d3d12sdklayers::ID3D12Debug::uuidof(), - debug.mut_void(), - ) - }; - - (debug, hr) - } - - pub fn enable_layer(&self) { - unsafe { self.EnableDebugLayer() } - } - - pub fn enable_gpu_based_validation(&self) -> bool { - let (ptr, hr) = unsafe { self.cast::() }; - if hr == S_OK { - unsafe { ptr.SetEnableGPUBasedValidation(TRUE) }; - true - } else { - false - } - } -} diff --git a/d3d12/src/descriptor.rs b/d3d12/src/descriptor.rs deleted file mode 100644 index b2c3ab23b..000000000 --- a/d3d12/src/descriptor.rs +++ /dev/null @@ -1,362 +0,0 @@ -use crate::{com::ComPtr, Blob, D3DResult, Error, TextureAddressMode}; -use std::{fmt, mem, ops::Range}; -use winapi::{shared::dxgiformat, um::d3d12}; - -pub type CpuDescriptor = d3d12::D3D12_CPU_DESCRIPTOR_HANDLE; -pub type GpuDescriptor = d3d12::D3D12_GPU_DESCRIPTOR_HANDLE; - -#[derive(Clone, Copy, Debug)] -pub struct Binding { - pub space: u32, - pub register: u32, -} - -#[repr(u32)] -#[derive(Clone, Copy, Debug)] -pub enum DescriptorHeapType { - CbvSrvUav = d3d12::D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, - Sampler = d3d12::D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, - Rtv = d3d12::D3D12_DESCRIPTOR_HEAP_TYPE_RTV, - Dsv = d3d12::D3D12_DESCRIPTOR_HEAP_TYPE_DSV, -} - -bitflags::bitflags! { - #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] - pub struct DescriptorHeapFlags: u32 { - const SHADER_VISIBLE = d3d12::D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE; - } -} - -pub type DescriptorHeap = ComPtr; - -impl DescriptorHeap { - pub fn start_cpu_descriptor(&self) -> CpuDescriptor { - unsafe { self.GetCPUDescriptorHandleForHeapStart() } - } - - pub fn start_gpu_descriptor(&self) -> GpuDescriptor { - unsafe { self.GetGPUDescriptorHandleForHeapStart() } - } -} - -#[repr(u32)] -#[derive(Clone, Copy, Debug)] -pub enum ShaderVisibility { - All = d3d12::D3D12_SHADER_VISIBILITY_ALL, - VS = d3d12::D3D12_SHADER_VISIBILITY_VERTEX, - HS = d3d12::D3D12_SHADER_VISIBILITY_HULL, - DS = d3d12::D3D12_SHADER_VISIBILITY_DOMAIN, - GS = d3d12::D3D12_SHADER_VISIBILITY_GEOMETRY, - PS = d3d12::D3D12_SHADER_VISIBILITY_PIXEL, -} - -#[repr(u32)] -#[derive(Clone, Copy, Debug)] -pub enum DescriptorRangeType { - SRV = d3d12::D3D12_DESCRIPTOR_RANGE_TYPE_SRV, - UAV = d3d12::D3D12_DESCRIPTOR_RANGE_TYPE_UAV, - CBV = d3d12::D3D12_DESCRIPTOR_RANGE_TYPE_CBV, - Sampler = d3d12::D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER, -} - -#[repr(transparent)] -pub struct DescriptorRange(d3d12::D3D12_DESCRIPTOR_RANGE); -impl DescriptorRange { - pub fn new(ty: DescriptorRangeType, count: u32, base_binding: Binding, offset: u32) -> Self { - DescriptorRange(d3d12::D3D12_DESCRIPTOR_RANGE { - RangeType: ty as _, - NumDescriptors: count, - BaseShaderRegister: base_binding.register, - RegisterSpace: base_binding.space, - OffsetInDescriptorsFromTableStart: offset, - }) - } -} - -impl fmt::Debug for DescriptorRange { - fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - formatter - .debug_struct("DescriptorRange") - .field("range_type", &self.0.RangeType) - .field("num", &self.0.NumDescriptors) - .field("register_space", &self.0.RegisterSpace) - .field("base_register", &self.0.BaseShaderRegister) - .field("table_offset", &self.0.OffsetInDescriptorsFromTableStart) - .finish() - } -} - -#[repr(transparent)] -pub struct RootParameter(d3d12::D3D12_ROOT_PARAMETER); -impl RootParameter { - // TODO: DescriptorRange must outlive Self - pub fn descriptor_table(visibility: ShaderVisibility, ranges: &[DescriptorRange]) -> Self { - let mut param = d3d12::D3D12_ROOT_PARAMETER { - ParameterType: d3d12::D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE, - ShaderVisibility: visibility as _, - ..unsafe { mem::zeroed() } - }; - - *unsafe { param.u.DescriptorTable_mut() } = d3d12::D3D12_ROOT_DESCRIPTOR_TABLE { - NumDescriptorRanges: ranges.len() as _, - pDescriptorRanges: ranges.as_ptr() as *const _, - }; - - RootParameter(param) - } - - pub fn constants(visibility: ShaderVisibility, binding: Binding, num: u32) -> Self { - let mut param = d3d12::D3D12_ROOT_PARAMETER { - ParameterType: d3d12::D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS, - ShaderVisibility: visibility as _, - ..unsafe { mem::zeroed() } - }; - - *unsafe { param.u.Constants_mut() } = d3d12::D3D12_ROOT_CONSTANTS { - ShaderRegister: binding.register, - RegisterSpace: binding.space, - Num32BitValues: num, - }; - - RootParameter(param) - } - - //TODO: should this be unsafe? - pub fn descriptor( - ty: d3d12::D3D12_ROOT_PARAMETER_TYPE, - visibility: ShaderVisibility, - binding: Binding, - ) -> Self { - let mut param = d3d12::D3D12_ROOT_PARAMETER { - ParameterType: ty, - ShaderVisibility: visibility as _, - ..unsafe { mem::zeroed() } - }; - - *unsafe { param.u.Descriptor_mut() } = d3d12::D3D12_ROOT_DESCRIPTOR { - ShaderRegister: binding.register, - RegisterSpace: binding.space, - }; - - RootParameter(param) - } - - pub fn cbv_descriptor(visibility: ShaderVisibility, binding: Binding) -> Self { - Self::descriptor(d3d12::D3D12_ROOT_PARAMETER_TYPE_CBV, visibility, binding) - } - - pub fn srv_descriptor(visibility: ShaderVisibility, binding: Binding) -> Self { - Self::descriptor(d3d12::D3D12_ROOT_PARAMETER_TYPE_SRV, visibility, binding) - } - - pub fn uav_descriptor(visibility: ShaderVisibility, binding: Binding) -> Self { - Self::descriptor(d3d12::D3D12_ROOT_PARAMETER_TYPE_UAV, visibility, binding) - } -} - -impl fmt::Debug for RootParameter { - fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - #[derive(Debug)] - #[allow(dead_code)] // False-positive - enum Inner<'a> { - Table(&'a [DescriptorRange]), - Constants { binding: Binding, num: u32 }, - SingleCbv(Binding), - SingleSrv(Binding), - SingleUav(Binding), - } - let kind = match self.0.ParameterType { - d3d12::D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE => unsafe { - let raw = self.0.u.DescriptorTable(); - Inner::Table(std::slice::from_raw_parts( - raw.pDescriptorRanges as *const _, - raw.NumDescriptorRanges as usize, - )) - }, - d3d12::D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS => unsafe { - let raw = self.0.u.Constants(); - Inner::Constants { - binding: Binding { - space: raw.RegisterSpace, - register: raw.ShaderRegister, - }, - num: raw.Num32BitValues, - } - }, - _ => unsafe { - let raw = self.0.u.Descriptor(); - let binding = Binding { - space: raw.RegisterSpace, - register: raw.ShaderRegister, - }; - match self.0.ParameterType { - d3d12::D3D12_ROOT_PARAMETER_TYPE_CBV => Inner::SingleCbv(binding), - d3d12::D3D12_ROOT_PARAMETER_TYPE_SRV => Inner::SingleSrv(binding), - d3d12::D3D12_ROOT_PARAMETER_TYPE_UAV => Inner::SingleUav(binding), - other => panic!("Unexpected type {:?}", other), - } - }, - }; - - formatter - .debug_struct("RootParameter") - .field("visibility", &self.0.ShaderVisibility) - .field("kind", &kind) - .finish() - } -} - -#[repr(u32)] -#[derive(Copy, Clone, Debug)] -pub enum StaticBorderColor { - TransparentBlack = d3d12::D3D12_STATIC_BORDER_COLOR_TRANSPARENT_BLACK, - OpaqueBlack = d3d12::D3D12_STATIC_BORDER_COLOR_OPAQUE_BLACK, - OpaqueWhite = d3d12::D3D12_STATIC_BORDER_COLOR_OPAQUE_WHITE, -} - -#[repr(transparent)] -pub struct StaticSampler(d3d12::D3D12_STATIC_SAMPLER_DESC); -impl StaticSampler { - pub fn new( - visibility: ShaderVisibility, - binding: Binding, - filter: d3d12::D3D12_FILTER, - address_mode: TextureAddressMode, - mip_lod_bias: f32, - max_anisotropy: u32, - comparison_op: d3d12::D3D12_COMPARISON_FUNC, - border_color: StaticBorderColor, - lod: Range, - ) -> Self { - StaticSampler(d3d12::D3D12_STATIC_SAMPLER_DESC { - Filter: filter, - AddressU: address_mode[0], - AddressV: address_mode[1], - AddressW: address_mode[2], - MipLODBias: mip_lod_bias, - MaxAnisotropy: max_anisotropy, - ComparisonFunc: comparison_op, - BorderColor: border_color as _, - MinLOD: lod.start, - MaxLOD: lod.end, - ShaderRegister: binding.register, - RegisterSpace: binding.space, - ShaderVisibility: visibility as _, - }) - } -} - -#[repr(u32)] -#[derive(Copy, Clone, Debug)] -pub enum RootSignatureVersion { - V1_0 = d3d12::D3D_ROOT_SIGNATURE_VERSION_1_0, - V1_1 = d3d12::D3D_ROOT_SIGNATURE_VERSION_1_1, -} - -bitflags::bitflags! { - #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] - pub struct RootSignatureFlags: u32 { - const ALLOW_IA_INPUT_LAYOUT = d3d12::D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT; - const DENY_VS_ROOT_ACCESS = d3d12::D3D12_ROOT_SIGNATURE_FLAG_DENY_VERTEX_SHADER_ROOT_ACCESS; - const DENY_HS_ROOT_ACCESS = d3d12::D3D12_ROOT_SIGNATURE_FLAG_DENY_HULL_SHADER_ROOT_ACCESS; - const DENY_DS_ROOT_ACCESS = d3d12::D3D12_ROOT_SIGNATURE_FLAG_DENY_DOMAIN_SHADER_ROOT_ACCESS; - const DENY_GS_ROOT_ACCESS = d3d12::D3D12_ROOT_SIGNATURE_FLAG_DENY_GEOMETRY_SHADER_ROOT_ACCESS; - const DENY_PS_ROOT_ACCESS = d3d12::D3D12_ROOT_SIGNATURE_FLAG_DENY_PIXEL_SHADER_ROOT_ACCESS; - } -} - -pub type RootSignature = ComPtr; -pub type BlobResult = D3DResult<(Blob, Error)>; - -#[cfg(feature = "libloading")] -impl crate::D3D12Lib { - pub fn serialize_root_signature( - &self, - version: RootSignatureVersion, - parameters: &[RootParameter], - static_samplers: &[StaticSampler], - flags: RootSignatureFlags, - ) -> Result { - use winapi::um::d3dcommon::ID3DBlob; - type Fun = extern "system" fn( - *const d3d12::D3D12_ROOT_SIGNATURE_DESC, - d3d12::D3D_ROOT_SIGNATURE_VERSION, - *mut *mut ID3DBlob, - *mut *mut ID3DBlob, - ) -> crate::HRESULT; - - let desc = d3d12::D3D12_ROOT_SIGNATURE_DESC { - NumParameters: parameters.len() as _, - pParameters: parameters.as_ptr() as *const _, - NumStaticSamplers: static_samplers.len() as _, - pStaticSamplers: static_samplers.as_ptr() as _, - Flags: flags.bits(), - }; - - let mut blob = Blob::null(); - let mut error = Error::null(); - let hr = unsafe { - let func: libloading::Symbol = self.lib.get(b"D3D12SerializeRootSignature")?; - func( - &desc, - version as _, - blob.mut_void() as *mut *mut _, - error.mut_void() as *mut *mut _, - ) - }; - - Ok(((blob, error), hr)) - } -} - -impl RootSignature { - #[cfg(feature = "implicit-link")] - pub fn serialize( - version: RootSignatureVersion, - parameters: &[RootParameter], - static_samplers: &[StaticSampler], - flags: RootSignatureFlags, - ) -> BlobResult { - let mut blob = Blob::null(); - let mut error = Error::null(); - - let desc = d3d12::D3D12_ROOT_SIGNATURE_DESC { - NumParameters: parameters.len() as _, - pParameters: parameters.as_ptr() as *const _, - NumStaticSamplers: static_samplers.len() as _, - pStaticSamplers: static_samplers.as_ptr() as _, - Flags: flags.bits(), - }; - - let hr = unsafe { - d3d12::D3D12SerializeRootSignature( - &desc, - version as _, - blob.mut_void() as *mut *mut _, - error.mut_void() as *mut *mut _, - ) - }; - - ((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/d3d12/src/device.rs b/d3d12/src/device.rs deleted file mode 100644 index 475fa22b5..000000000 --- a/d3d12/src/device.rs +++ /dev/null @@ -1,344 +0,0 @@ -//! Device - -use crate::{ - com::ComPtr, - command_list::{CmdListType, CommandSignature, IndirectArgument}, - descriptor::{CpuDescriptor, DescriptorHeapFlags, DescriptorHeapType, RenderTargetViewDesc}, - heap::{Heap, HeapFlags, HeapProperties}, - pso, query, queue, Blob, CachedPSO, CommandAllocator, CommandQueue, D3DResult, DescriptorHeap, - Fence, GraphicsCommandList, NodeMask, PipelineState, QueryHeap, Resource, RootSignature, - Shader, TextureAddressMode, -}; -use std::ops::Range; -use winapi::{um::d3d12, Interface}; - -pub type Device = ComPtr; - -#[cfg(feature = "libloading")] -impl crate::D3D12Lib { - pub fn create_device( - &self, - adapter: &ComPtr, - feature_level: crate::FeatureLevel, - ) -> Result, libloading::Error> { - type Fun = extern "system" fn( - *mut winapi::um::unknwnbase::IUnknown, - winapi::um::d3dcommon::D3D_FEATURE_LEVEL, - winapi::shared::guiddef::REFGUID, - *mut *mut winapi::ctypes::c_void, - ) -> crate::HRESULT; - - let mut device = Device::null(); - let hr = unsafe { - let func: libloading::Symbol = self.lib.get(b"D3D12CreateDevice")?; - func( - adapter.as_unknown() as *const _ as *mut _, - feature_level as _, - &d3d12::ID3D12Device::uuidof(), - device.mut_void(), - ) - }; - - Ok((device, hr)) - } -} - -impl Device { - #[cfg(feature = "implicit-link")] - pub fn create( - adapter: ComPtr, - feature_level: crate::FeatureLevel, - ) -> D3DResult { - let mut device = Device::null(); - let hr = unsafe { - d3d12::D3D12CreateDevice( - adapter.as_unknown() as *const _ as *mut _, - feature_level as _, - &d3d12::ID3D12Device::uuidof(), - device.mut_void(), - ) - }; - - (device, hr) - } - - pub fn create_heap( - &self, - size_in_bytes: u64, - properties: HeapProperties, - alignment: u64, - flags: HeapFlags, - ) -> D3DResult { - let mut heap = Heap::null(); - - let desc = d3d12::D3D12_HEAP_DESC { - SizeInBytes: size_in_bytes, - Properties: properties.0, - Alignment: alignment, - Flags: flags.bits(), - }; - - let hr = unsafe { self.CreateHeap(&desc, &d3d12::ID3D12Heap::uuidof(), heap.mut_void()) }; - - (heap, hr) - } - - pub fn create_command_allocator(&self, list_type: CmdListType) -> D3DResult { - let mut allocator = CommandAllocator::null(); - let hr = unsafe { - self.CreateCommandAllocator( - list_type as _, - &d3d12::ID3D12CommandAllocator::uuidof(), - allocator.mut_void(), - ) - }; - - (allocator, hr) - } - - pub fn create_command_queue( - &self, - list_type: CmdListType, - priority: queue::Priority, - flags: queue::CommandQueueFlags, - node_mask: NodeMask, - ) -> D3DResult { - let desc = d3d12::D3D12_COMMAND_QUEUE_DESC { - Type: list_type as _, - Priority: priority as _, - Flags: flags.bits(), - NodeMask: node_mask, - }; - - let mut queue = CommandQueue::null(); - let hr = unsafe { - self.CreateCommandQueue( - &desc, - &d3d12::ID3D12CommandQueue::uuidof(), - queue.mut_void(), - ) - }; - - (queue, hr) - } - - pub fn create_descriptor_heap( - &self, - num_descriptors: u32, - heap_type: DescriptorHeapType, - flags: DescriptorHeapFlags, - node_mask: NodeMask, - ) -> D3DResult { - let desc = d3d12::D3D12_DESCRIPTOR_HEAP_DESC { - Type: heap_type as _, - NumDescriptors: num_descriptors, - Flags: flags.bits(), - NodeMask: node_mask, - }; - - let mut heap = DescriptorHeap::null(); - let hr = unsafe { - self.CreateDescriptorHeap( - &desc, - &d3d12::ID3D12DescriptorHeap::uuidof(), - heap.mut_void(), - ) - }; - - (heap, hr) - } - - pub fn get_descriptor_increment_size(&self, heap_type: DescriptorHeapType) -> u32 { - unsafe { self.GetDescriptorHandleIncrementSize(heap_type as _) } - } - - pub fn create_graphics_command_list( - &self, - list_type: CmdListType, - allocator: &CommandAllocator, - initial: PipelineState, - node_mask: NodeMask, - ) -> D3DResult { - let mut command_list = GraphicsCommandList::null(); - let hr = unsafe { - self.CreateCommandList( - node_mask, - list_type as _, - allocator.as_mut_ptr(), - initial.as_mut_ptr(), - &d3d12::ID3D12GraphicsCommandList::uuidof(), - command_list.mut_void(), - ) - }; - - (command_list, hr) - } - - pub fn create_query_heap( - &self, - heap_ty: query::QueryHeapType, - count: u32, - node_mask: NodeMask, - ) -> D3DResult { - let desc = d3d12::D3D12_QUERY_HEAP_DESC { - Type: heap_ty as _, - Count: count, - NodeMask: node_mask, - }; - - let mut query_heap = QueryHeap::null(); - let hr = unsafe { - self.CreateQueryHeap( - &desc, - &d3d12::ID3D12QueryHeap::uuidof(), - query_heap.mut_void(), - ) - }; - - (query_heap, hr) - } - - pub fn create_graphics_pipeline_state( - &self, - _root_signature: RootSignature, - _vs: Shader, - _ps: Shader, - _gs: Shader, - _hs: Shader, - _ds: Shader, - _node_mask: NodeMask, - _cached_pso: CachedPSO, - _flags: pso::PipelineStateFlags, - ) -> D3DResult { - unimplemented!() - } - - pub fn create_compute_pipeline_state( - &self, - root_signature: &RootSignature, - cs: Shader, - node_mask: NodeMask, - cached_pso: CachedPSO, - flags: pso::PipelineStateFlags, - ) -> D3DResult { - let mut pipeline = PipelineState::null(); - let desc = d3d12::D3D12_COMPUTE_PIPELINE_STATE_DESC { - pRootSignature: root_signature.as_mut_ptr(), - CS: *cs, - NodeMask: node_mask, - CachedPSO: *cached_pso, - Flags: flags.bits(), - }; - - let hr = unsafe { - self.CreateComputePipelineState( - &desc, - &d3d12::ID3D12PipelineState::uuidof(), - pipeline.mut_void(), - ) - }; - - (pipeline, hr) - } - - pub fn create_sampler( - &self, - sampler: CpuDescriptor, - filter: d3d12::D3D12_FILTER, - address_mode: TextureAddressMode, - mip_lod_bias: f32, - max_anisotropy: u32, - comparison_op: d3d12::D3D12_COMPARISON_FUNC, - border_color: [f32; 4], - lod: Range, - ) { - let desc = d3d12::D3D12_SAMPLER_DESC { - Filter: filter, - AddressU: address_mode[0], - AddressV: address_mode[1], - AddressW: address_mode[2], - MipLODBias: mip_lod_bias, - MaxAnisotropy: max_anisotropy, - ComparisonFunc: comparison_op, - BorderColor: border_color, - MinLOD: lod.start, - MaxLOD: lod.end, - }; - - unsafe { - self.CreateSampler(&desc, sampler); - } - } - - pub fn create_root_signature( - &self, - blob: Blob, - node_mask: NodeMask, - ) -> D3DResult { - let mut signature = RootSignature::null(); - let hr = unsafe { - self.CreateRootSignature( - node_mask, - blob.GetBufferPointer(), - blob.GetBufferSize(), - &d3d12::ID3D12RootSignature::uuidof(), - signature.mut_void(), - ) - }; - - (signature, hr) - } - - pub fn create_command_signature( - &self, - root_signature: RootSignature, - arguments: &[IndirectArgument], - stride: u32, - node_mask: NodeMask, - ) -> D3DResult { - let mut signature = CommandSignature::null(); - let desc = d3d12::D3D12_COMMAND_SIGNATURE_DESC { - ByteStride: stride, - NumArgumentDescs: arguments.len() as _, - pArgumentDescs: arguments.as_ptr() as *const _, - NodeMask: node_mask, - }; - - let hr = unsafe { - self.CreateCommandSignature( - &desc, - root_signature.as_mut_ptr(), - &d3d12::ID3D12CommandSignature::uuidof(), - signature.mut_void(), - ) - }; - - (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); - } - } - - // 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/d3d12/src/dxgi.rs b/d3d12/src/dxgi.rs deleted file mode 100644 index 0cbb5bb63..000000000 --- a/d3d12/src/dxgi.rs +++ /dev/null @@ -1,377 +0,0 @@ -use crate::{com::ComPtr, 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::bitflags! { - #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] - 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 = ComPtr; - -pub type Adapter1 = ComPtr; -pub type Adapter2 = ComPtr; -pub type Adapter3 = ComPtr; -pub type Adapter4 = ComPtr; -crate::weak_com_inheritance_chain! { - #[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; - Adapter3(dxgi1_4::IDXGIAdapter3), from_adapter3, as_adapter3, unwrap_adapter3; - Adapter4(dxgi1_6::IDXGIAdapter4), from_adapter4, as_adapter4, unwrap_adapter4; - } -} - -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, 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 = ComPtr; - -pub type SwapChain = ComPtr; -pub type SwapChain1 = ComPtr; -pub type SwapChain2 = ComPtr; -pub type SwapChain3 = ComPtr; -crate::weak_com_inheritance_chain! { - #[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; - 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 { - unsafe { libloading::Library::new("dxgi.dll").map(|lib| DxgiLib { lib }) } - } - - pub fn create_factory2( - &self, - flags: FactoryCreationFlags, - ) -> Result, 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 = self.lib.get(b"CreateDXGIFactory2")?; - func( - flags.bits(), - &dxgi1_4::IDXGIFactory4::uuidof(), - factory.mut_void(), - ) - }; - - Ok((factory, hr)) - } - - pub fn create_factory1(&self) -> Result, 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 = self.lib.get(b"CreateDXGIFactory1")?; - func(&dxgi::IDXGIFactory1::uuidof(), factory.mut_void()) - }; - - Ok((factory, hr)) - } - - pub fn create_factory_media(&self) -> Result, 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 = self.lib.get(b"CreateDXGIFactory1")?; - func(&dxgi1_3::IDXGIFactoryMedia::uuidof(), factory.mut_void()) - }; - - Ok((factory, hr)) - } - - pub fn get_debug_interface1(&self) -> Result, 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 = 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 { - 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 { - 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 { - 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 { - 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) - } -} - -impl FactoryMedia { - pub fn create_swapchain_for_composition_surface_handle( - &self, - queue: *mut IUnknown, - surface_handle: HANDLE, - desc: &SwapchainDesc, - ) -> D3DResult { - 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::bitflags! { - #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] - 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 { - 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() } - } -} diff --git a/d3d12/src/heap.rs b/d3d12/src/heap.rs deleted file mode 100644 index 074de56d7..000000000 --- a/d3d12/src/heap.rs +++ /dev/null @@ -1,87 +0,0 @@ -use crate::com::ComPtr; -use winapi::um::d3d12; - -pub type Heap = ComPtr; - -#[repr(u32)] -#[derive(Clone, Copy)] -pub enum HeapType { - Default = d3d12::D3D12_HEAP_TYPE_DEFAULT, - Upload = d3d12::D3D12_HEAP_TYPE_UPLOAD, - Readback = d3d12::D3D12_HEAP_TYPE_READBACK, - Custom = d3d12::D3D12_HEAP_TYPE_CUSTOM, -} - -#[repr(u32)] -#[derive(Clone, Copy)] -pub enum CpuPageProperty { - Unknown = d3d12::D3D12_CPU_PAGE_PROPERTY_UNKNOWN, - NotAvailable = d3d12::D3D12_CPU_PAGE_PROPERTY_NOT_AVAILABLE, - WriteCombine = d3d12::D3D12_CPU_PAGE_PROPERTY_WRITE_COMBINE, - WriteBack = d3d12::D3D12_CPU_PAGE_PROPERTY_WRITE_BACK, -} - -#[repr(u32)] -#[derive(Clone, Copy)] -pub enum MemoryPool { - Unknown = d3d12::D3D12_CPU_PAGE_PROPERTY_UNKNOWN, - L0 = d3d12::D3D12_MEMORY_POOL_L0, - L1 = d3d12::D3D12_MEMORY_POOL_L1, -} - -bitflags::bitflags! { - #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] - pub struct HeapFlags: u32 { - const NONE = d3d12::D3D12_HEAP_FLAG_NONE; - const SHARED = d3d12::D3D12_HEAP_FLAG_SHARED; - const DENY_BUFFERS = d3d12::D3D12_HEAP_FLAG_DENY_BUFFERS; - const ALLOW_DISPLAY = d3d12::D3D12_HEAP_FLAG_ALLOW_DISPLAY; - const SHARED_CROSS_ADAPTER = d3d12::D3D12_HEAP_FLAG_SHARED_CROSS_ADAPTER; - const DENT_RT_DS_TEXTURES = d3d12::D3D12_HEAP_FLAG_DENY_RT_DS_TEXTURES; - const DENY_NON_RT_DS_TEXTURES = d3d12::D3D12_HEAP_FLAG_DENY_NON_RT_DS_TEXTURES; - const HARDWARE_PROTECTED = d3d12::D3D12_HEAP_FLAG_HARDWARE_PROTECTED; - const ALLOW_WRITE_WATCH = d3d12::D3D12_HEAP_FLAG_ALLOW_WRITE_WATCH; - const ALLOW_ALL_BUFFERS_AND_TEXTURES = d3d12::D3D12_HEAP_FLAG_ALLOW_ALL_BUFFERS_AND_TEXTURES; - const ALLOW_ONLY_BUFFERS = d3d12::D3D12_HEAP_FLAG_ALLOW_ONLY_BUFFERS; - const ALLOW_ONLY_NON_RT_DS_TEXTURES = d3d12::D3D12_HEAP_FLAG_ALLOW_ONLY_NON_RT_DS_TEXTURES; - const ALLOW_ONLY_RT_DS_TEXTURES = d3d12::D3D12_HEAP_FLAG_ALLOW_ONLY_RT_DS_TEXTURES; - } -} - -#[repr(transparent)] -pub struct HeapProperties(pub d3d12::D3D12_HEAP_PROPERTIES); -impl HeapProperties { - pub fn new( - heap_type: HeapType, - cpu_page_property: CpuPageProperty, - memory_pool_preference: MemoryPool, - creation_node_mask: u32, - visible_node_mask: u32, - ) -> Self { - HeapProperties(d3d12::D3D12_HEAP_PROPERTIES { - Type: heap_type as _, - CPUPageProperty: cpu_page_property as _, - MemoryPoolPreference: memory_pool_preference as _, - CreationNodeMask: creation_node_mask, - VisibleNodeMask: visible_node_mask, - }) - } -} - -#[repr(transparent)] -pub struct HeapDesc(d3d12::D3D12_HEAP_DESC); -impl HeapDesc { - pub fn new( - size_in_bytes: u64, - properties: HeapProperties, - alignment: u64, - flags: HeapFlags, - ) -> Self { - HeapDesc(d3d12::D3D12_HEAP_DESC { - SizeInBytes: size_in_bytes, - Properties: properties.0, - Alignment: alignment, - Flags: flags.bits(), - }) - } -} diff --git a/d3d12/src/lib.rs b/d3d12/src/lib.rs deleted file mode 100644 index 13f022689..000000000 --- a/d3d12/src/lib.rs +++ /dev/null @@ -1,125 +0,0 @@ -#![cfg(windows)] -#![allow( - clippy::missing_safety_doc, - clippy::too_many_arguments, - clippy::not_unsafe_ptr_arg_deref -)] - -use std::{convert::TryFrom, ffi::CStr}; -use winapi::{ - shared::dxgiformat, - um::{d3d12, d3dcommon}, -}; - -mod com; -mod command_allocator; -mod command_list; -mod debug; -mod descriptor; -mod device; -mod dxgi; -mod heap; -mod pso; -mod query; -mod queue; -mod resource; -mod sync; - -pub use crate::com::*; -pub use crate::command_allocator::*; -pub use crate::command_list::*; -pub use crate::debug::*; -pub use crate::descriptor::*; -pub use crate::device::*; -pub use crate::dxgi::*; -pub use crate::heap::*; -pub use crate::pso::*; -pub use crate::query::*; -pub use crate::queue::*; -pub use crate::resource::*; -pub use crate::sync::*; - -pub use winapi::shared::winerror::HRESULT; - -pub type D3DResult = (T, HRESULT); -pub type GpuAddress = d3d12::D3D12_GPU_VIRTUAL_ADDRESS; -pub type Format = dxgiformat::DXGI_FORMAT; -pub type Rect = d3d12::D3D12_RECT; -pub type NodeMask = u32; - -/// Index into the root signature. -pub type RootIndex = u32; -/// Draw vertex count. -pub type VertexCount = u32; -/// Draw vertex base offset. -pub type VertexOffset = i32; -/// Draw number of indices. -pub type IndexCount = u32; -/// Draw number of instances. -pub type InstanceCount = u32; -/// Number of work groups. -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)] -#[non_exhaustive] -pub enum FeatureLevel { - L9_1 = d3dcommon::D3D_FEATURE_LEVEL_9_1, - L9_2 = d3dcommon::D3D_FEATURE_LEVEL_9_2, - L9_3 = d3dcommon::D3D_FEATURE_LEVEL_9_3, - L10_0 = d3dcommon::D3D_FEATURE_LEVEL_10_0, - L10_1 = d3dcommon::D3D_FEATURE_LEVEL_10_1, - L11_0 = d3dcommon::D3D_FEATURE_LEVEL_11_0, - L11_1 = d3dcommon::D3D_FEATURE_LEVEL_11_1, - L12_0 = d3dcommon::D3D_FEATURE_LEVEL_12_0, - L12_1 = d3dcommon::D3D_FEATURE_LEVEL_12_1, -} - -impl TryFrom for FeatureLevel { - type Error = (); - - fn try_from(value: u32) -> Result { - Ok(match value { - d3dcommon::D3D_FEATURE_LEVEL_9_1 => Self::L9_1, - d3dcommon::D3D_FEATURE_LEVEL_9_2 => Self::L9_2, - d3dcommon::D3D_FEATURE_LEVEL_9_3 => Self::L9_3, - d3dcommon::D3D_FEATURE_LEVEL_10_0 => Self::L10_0, - d3dcommon::D3D_FEATURE_LEVEL_10_1 => Self::L10_1, - d3dcommon::D3D_FEATURE_LEVEL_11_0 => Self::L11_0, - d3dcommon::D3D_FEATURE_LEVEL_11_1 => Self::L11_1, - d3dcommon::D3D_FEATURE_LEVEL_12_0 => Self::L12_0, - d3dcommon::D3D_FEATURE_LEVEL_12_1 => Self::L12_1, - _ => return Err(()), - }) - } -} - -pub type Blob = ComPtr; - -pub type Error = ComPtr; -impl Error { - pub unsafe fn as_c_str(&self) -> &CStr { - debug_assert!(!self.is_null()); - let data = self.GetBufferPointer(); - CStr::from_ptr(data as *const _ as *const _) - } -} - -#[cfg(feature = "libloading")] -#[derive(Debug)] -pub struct D3D12Lib { - lib: libloading::Library, -} - -#[cfg(feature = "libloading")] -impl D3D12Lib { - pub fn new() -> Result { - unsafe { libloading::Library::new("d3d12.dll").map(|lib| D3D12Lib { lib }) } - } -} diff --git a/d3d12/src/pso.rs b/d3d12/src/pso.rs deleted file mode 100644 index 83a549621..000000000 --- a/d3d12/src/pso.rs +++ /dev/null @@ -1,182 +0,0 @@ -//! Pipeline state - -use crate::{com::ComPtr, Blob, D3DResult, Error}; -use std::{ - ffi::{self, c_void}, - marker::PhantomData, - ops::Deref, - ptr, -}; -use winapi::um::{d3d12, d3dcompiler}; - -bitflags::bitflags! { - #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] - pub struct PipelineStateFlags: u32 { - const TOOL_DEBUG = d3d12::D3D12_PIPELINE_STATE_FLAG_TOOL_DEBUG; - } -} - -bitflags::bitflags! { - #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] - pub struct ShaderCompileFlags: u32 { - const DEBUG = d3dcompiler::D3DCOMPILE_DEBUG; - const SKIP_VALIDATION = d3dcompiler::D3DCOMPILE_SKIP_VALIDATION; - const SKIP_OPTIMIZATION = d3dcompiler::D3DCOMPILE_SKIP_OPTIMIZATION; - const PACK_MATRIX_ROW_MAJOR = d3dcompiler::D3DCOMPILE_PACK_MATRIX_ROW_MAJOR; - const PACK_MATRIX_COLUMN_MAJOR = d3dcompiler::D3DCOMPILE_PACK_MATRIX_COLUMN_MAJOR; - const PARTIAL_PRECISION = d3dcompiler::D3DCOMPILE_PARTIAL_PRECISION; - // TODO: add missing flags - } -} - -#[derive(Copy, Clone)] -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: &'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: &'a Blob) -> Self { - Shader( - d3d12::D3D12_SHADER_BYTECODE { - BytecodeLength: unsafe { blob.GetBufferSize() }, - pShaderBytecode: unsafe { blob.GetBufferPointer() }, - }, - PhantomData, - ) - } - - /// Compile a shader from raw HLSL. - /// - /// * `target`: example format: `ps_5_1`. - pub fn compile( - code: &[u8], - target: &ffi::CStr, - entry: &ffi::CStr, - flags: ShaderCompileFlags, - ) -> D3DResult<(Blob, Error)> { - let mut shader = Blob::null(); - let mut error = Error::null(); - - let hr = unsafe { - d3dcompiler::D3DCompile( - code.as_ptr() as *const _, - code.len(), - ptr::null(), // defines - ptr::null(), // include - ptr::null_mut(), - entry.as_ptr() as *const _, - target.as_ptr() as *const _, - flags.bits(), - 0, - shader.mut_void() as *mut *mut _, - error.mut_void() as *mut *mut _, - ) - }; - - ((shader, error), hr) - } -} - -impl<'a> Deref for Shader<'a> { - type Target = d3d12::D3D12_SHADER_BYTECODE; - fn deref(&self) -> &Self::Target { - &self.0 - } -} - -#[derive(Copy, Clone)] -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: &'a Blob) -> Self { - CachedPSO( - d3d12::D3D12_CACHED_PIPELINE_STATE { - CachedBlobSizeInBytes: unsafe { blob.GetBufferSize() }, - pCachedBlob: unsafe { blob.GetBufferPointer() }, - }, - PhantomData, - ) - } -} - -impl<'a> Deref for CachedPSO<'a> { - type Target = d3d12::D3D12_CACHED_PIPELINE_STATE; - fn deref(&self) -> &Self::Target { - &self.0 - } -} - -pub type PipelineState = ComPtr; - -#[repr(u32)] -pub enum Subobject { - RootSignature = d3d12::D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_ROOT_SIGNATURE, - VS = d3d12::D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_VS, - PS = d3d12::D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_PS, - DS = d3d12::D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_DS, - HS = d3d12::D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_HS, - GS = d3d12::D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_GS, - CS = d3d12::D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_CS, - StreamOutput = d3d12::D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_STREAM_OUTPUT, - Blend = d3d12::D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_BLEND, - SampleMask = d3d12::D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_SAMPLE_MASK, - Rasterizer = d3d12::D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_RASTERIZER, - DepthStencil = d3d12::D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_DEPTH_STENCIL, - InputLayout = d3d12::D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_INPUT_LAYOUT, - IBStripCut = d3d12::D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_IB_STRIP_CUT_VALUE, - PrimitiveTopology = d3d12::D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_PRIMITIVE_TOPOLOGY, - RTFormats = d3d12::D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_RENDER_TARGET_FORMATS, - DSFormat = d3d12::D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_DEPTH_STENCIL_FORMAT, - SampleDesc = d3d12::D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_SAMPLE_DESC, - NodeMask = d3d12::D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_NODE_MASK, - CachedPSO = d3d12::D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_CACHED_PSO, - Flags = d3d12::D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_FLAGS, - DepthStencil1 = d3d12::D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_DEPTH_STENCIL1, - // ViewInstancing = d3d12::D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_VIEW_INSTANCING, -} - -/// Subobject of a pipeline stream description -#[repr(C)] -pub struct PipelineStateSubobject { - subobject_align: [usize; 0], // Subobjects must have the same alignment as pointers. - subobject_type: d3d12::D3D12_PIPELINE_STATE_SUBOBJECT_TYPE, - subobject: T, -} - -impl PipelineStateSubobject { - pub fn new(subobject_type: Subobject, subobject: T) -> Self { - PipelineStateSubobject { - subobject_align: [], - subobject_type: subobject_type as _, - subobject, - } - } -} diff --git a/d3d12/src/query.rs b/d3d12/src/query.rs deleted file mode 100644 index 68901de94..000000000 --- a/d3d12/src/query.rs +++ /dev/null @@ -1,15 +0,0 @@ -use crate::com::ComPtr; -use winapi::um::d3d12; - -#[repr(u32)] -#[derive(Debug, Copy, Clone)] -pub enum QueryHeapType { - Occlusion = d3d12::D3D12_QUERY_HEAP_TYPE_OCCLUSION, - Timestamp = d3d12::D3D12_QUERY_HEAP_TYPE_TIMESTAMP, - PipelineStatistics = d3d12::D3D12_QUERY_HEAP_TYPE_PIPELINE_STATISTICS, - SOStatistics = d3d12::D3D12_QUERY_HEAP_TYPE_SO_STATISTICS, - // VideoDecodeStatistics = d3d12::D3D12_QUERY_HEAP_TYPE_VIDEO_DECODE_STATISTICS, - // CopyQueueTimestamp = d3d12::D3D12_QUERY_HEAP_TYPE_COPY_QUEUE_TIMESTAMP, -} - -pub type QueryHeap = ComPtr; diff --git a/d3d12/src/queue.rs b/d3d12/src/queue.rs deleted file mode 100644 index a569344f3..000000000 --- a/d3d12/src/queue.rs +++ /dev/null @@ -1,32 +0,0 @@ -use crate::{com::ComPtr, sync::Fence, CommandList, HRESULT}; -use winapi::um::d3d12; - -#[repr(u32)] -pub enum Priority { - Normal = d3d12::D3D12_COMMAND_QUEUE_PRIORITY_NORMAL, - High = d3d12::D3D12_COMMAND_QUEUE_PRIORITY_HIGH, - GlobalRealtime = d3d12::D3D12_COMMAND_QUEUE_PRIORITY_GLOBAL_REALTIME, -} - -bitflags::bitflags! { - #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] - pub struct CommandQueueFlags: u32 { - const DISABLE_GPU_TIMEOUT = d3d12::D3D12_COMMAND_QUEUE_FLAG_DISABLE_GPU_TIMEOUT; - } -} - -pub type CommandQueue = ComPtr; - -impl CommandQueue { - pub fn execute_command_lists(&self, command_lists: &[CommandList]) { - let command_lists = command_lists - .iter() - .map(CommandList::as_mut_ptr) - .collect::>(); - unsafe { self.ExecuteCommandLists(command_lists.len() as _, command_lists.as_ptr()) } - } - - pub fn signal(&self, fence: &Fence, value: u64) -> HRESULT { - unsafe { self.Signal(fence.as_mut_ptr(), value) } - } -} diff --git a/d3d12/src/resource.rs b/d3d12/src/resource.rs deleted file mode 100644 index def01f414..000000000 --- a/d3d12/src/resource.rs +++ /dev/null @@ -1,52 +0,0 @@ -//! GPU Resource - -use crate::{com::ComPtr, D3DResult, Rect}; -use std::{ops::Range, ptr}; -use winapi::um::d3d12; - -pub type Subresource = u32; - -pub struct DiscardRegion<'a> { - pub rects: &'a [Rect], - pub subregions: Range, -} - -pub type Resource = ComPtr; - -impl Resource { - pub fn map( - &self, - subresource: Subresource, - read_range: Option>, - ) -> D3DResult<*mut ()> { - let mut ptr = ptr::null_mut(); - let read_range = read_range.map(|r| d3d12::D3D12_RANGE { - Begin: r.start, - End: r.end, - }); - let read = match read_range { - Some(ref r) => r as *const _, - None => ptr::null(), - }; - let hr = unsafe { self.Map(subresource, read, &mut ptr) }; - - (ptr as _, hr) - } - - pub fn unmap(&self, subresource: Subresource, write_range: Option>) { - let write_range = write_range.map(|r| d3d12::D3D12_RANGE { - Begin: r.start, - End: r.end, - }); - let write = match write_range { - Some(ref r) => r as *const _, - None => ptr::null(), - }; - - unsafe { self.Unmap(subresource, write) }; - } - - pub fn gpu_virtual_address(&self) -> u64 { - unsafe { self.GetGPUVirtualAddress() } - } -} diff --git a/d3d12/src/sync.rs b/d3d12/src/sync.rs deleted file mode 100644 index fa5f09040..000000000 --- a/d3d12/src/sync.rs +++ /dev/null @@ -1,39 +0,0 @@ -use crate::{com::ComPtr, HRESULT}; -use std::ptr; -use winapi::um::{d3d12, synchapi, winnt}; - -#[derive(Copy, Clone)] -#[repr(transparent)] -pub struct Event(pub 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 = ComPtr; -impl Fence { - pub fn set_event_on_completion(&self, event: Event, value: u64) -> HRESULT { - unsafe { self.SetEventOnCompletion(value, event.0) } - } - - pub fn get_value(&self) -> u64 { - unsafe { self.GetCompletedValue() } - } - - pub fn signal(&self, value: u64) -> HRESULT { - unsafe { self.Signal(value) } - } -} diff --git a/wgpu-core/src/instance.rs b/wgpu-core/src/instance.rs index d23c6a65e..16a5b69c4 100644 --- a/wgpu-core/src/instance.rs +++ b/wgpu-core/src/instance.rs @@ -585,7 +585,7 @@ impl Global { ) -> Result { profiling::scope!("Instance::instance_create_surface_from_visual"); self.instance_create_surface_dx12(id_in, |inst| unsafe { - inst.create_surface_from_visual(visual.cast()) + inst.create_surface_from_visual(visual) }) } @@ -615,7 +615,7 @@ impl Global { ) -> Result { profiling::scope!("Instance::instance_create_surface_from_swap_chain_panel"); self.instance_create_surface_dx12(id_in, |inst| unsafe { - inst.create_surface_from_swap_chain_panel(swap_chain_panel.cast()) + inst.create_surface_from_swap_chain_panel(swap_chain_panel) }) } diff --git a/wgpu-hal/Cargo.toml b/wgpu-hal/Cargo.toml index eedd027bf..ee2808b19 100644 --- a/wgpu-hal/Cargo.toml +++ b/wgpu-hal/Cargo.toml @@ -71,21 +71,24 @@ gles = [ ## Has no effect if not targeting Windows. dx12 = [ # DX12 is only available on Windows, therefore request HLSL output also only if we target Windows. - "naga/hlsl-out-if-target-windows", - "dep:d3d12", "dep:bit-set", "dep:libloading", "dep:range-alloc", - "winapi/std", - "winapi/winbase", - "winapi/d3d12", - "winapi/d3d12shader", - "winapi/d3d12sdklayers", - "winapi/dxgi1_6", - "winapi/errhandlingapi", + "dep:windows-core", + "gpu-allocator/d3d12", + "naga/hlsl-out-if-target-windows", + "windows/Win32_Graphics_Direct3D_Fxc", + "windows/Win32_Graphics_Direct3D", + "windows/Win32_Graphics_Direct3D12", + "windows/Win32_Graphics_DirectComposition", + "windows/Win32_Graphics_Dxgi_Common", + "windows/Win32_Security", + "windows/Win32_System_Diagnostics_Debug", + "windows/Win32_System_Kernel", + "windows/Win32_System_Performance", + "windows/Win32_System_Threading", + "windows/Win32_UI_WindowsAndMessaging", ] -# TODO: This is a separate feature until Mozilla okays windows-rs, see https://github.com/gfx-rs/wgpu/issues/3207 for the tracking issue. -windows_rs = ["dep:gpu-allocator"] dxc_shader_compiler = ["dep:hassle-rs"] renderdoc = ["dep:libloading", "dep:renderdoc-sys"] fragile-send-sync-non-atomic-wasm = ["wgt/fragile-send-sync-non-atomic-wasm"] @@ -154,20 +157,12 @@ bit-set = { workspace = true, optional = true } range-alloc = { workspace = true, optional = true } gpu-allocator = { workspace = true, optional = true } hassle-rs = { workspace = true, optional = true } +# For core macros. This crate is also reexported as windows::core. +windows-core = { workspace = true, optional = true } # backend: Gles glutin_wgl_sys = { workspace = true, optional = true } -winapi = { version = "0.3", features = [ - "profileapi", - "windef", - "winuser", - "dcomp", -] } -d3d12 = { path = "../d3d12/", version = "22.0.0", optional = true, features = [ - "libloading", -] } - [target.'cfg(any(target_os="macos", target_os="ios"))'.dependencies] # backend: Metal block = { workspace = true, optional = true } diff --git a/wgpu-hal/src/auxil/dxgi/conv.rs b/wgpu-hal/src/auxil/dxgi/conv.rs index d84e082df..09843f011 100644 --- a/wgpu-hal/src/auxil/dxgi/conv.rs +++ b/wgpu-hal/src/auxil/dxgi/conv.rs @@ -1,5 +1,6 @@ use std::{ffi::OsString, os::windows::ffi::OsStringExt}; -use winapi::shared::dxgiformat; + +use windows::Win32::Graphics::Dxgi; // Helper to convert DXGI adapter name to a normal string pub fn map_adapter_name(name: [u16; 128]) -> String { @@ -8,9 +9,11 @@ pub fn map_adapter_name(name: [u16; 128]) -> String { name.to_string_lossy().into_owned() } -pub fn map_texture_format_failable(format: wgt::TextureFormat) -> Option { +pub fn map_texture_format_failable( + format: wgt::TextureFormat, +) -> Option { use wgt::TextureFormat as Tf; - use winapi::shared::dxgiformat::*; + use Dxgi::Common::*; Some(match format { Tf::R8Unorm => DXGI_FORMAT_R8_UNORM, @@ -94,7 +97,7 @@ pub fn map_texture_format_failable(format: wgt::TextureFormat) -> Option dxgiformat::DXGI_FORMAT { +pub fn map_texture_format(format: wgt::TextureFormat) -> Dxgi::Common::DXGI_FORMAT { match map_texture_format_failable(format) { Some(f) => f, None => unreachable!(), @@ -103,10 +106,10 @@ pub fn map_texture_format(format: wgt::TextureFormat) -> dxgiformat::DXGI_FORMAT // Note: DXGI doesn't allow sRGB format on the swapchain, // but creating RTV of swapchain buffers with sRGB works. -pub fn map_texture_format_nosrgb(format: wgt::TextureFormat) -> dxgiformat::DXGI_FORMAT { +pub fn map_texture_format_nosrgb(format: wgt::TextureFormat) -> Dxgi::Common::DXGI_FORMAT { match format { - wgt::TextureFormat::Bgra8UnormSrgb => dxgiformat::DXGI_FORMAT_B8G8R8A8_UNORM, - wgt::TextureFormat::Rgba8UnormSrgb => dxgiformat::DXGI_FORMAT_R8G8B8A8_UNORM, + wgt::TextureFormat::Bgra8UnormSrgb => Dxgi::Common::DXGI_FORMAT_B8G8R8A8_UNORM, + wgt::TextureFormat::Rgba8UnormSrgb => Dxgi::Common::DXGI_FORMAT_R8G8B8A8_UNORM, _ => map_texture_format(format), } } @@ -116,29 +119,29 @@ pub fn map_texture_format_nosrgb(format: wgt::TextureFormat) -> dxgiformat::DXGI pub fn map_texture_format_for_srv_uav( format: wgt::TextureFormat, aspect: crate::FormatAspects, -) -> Option { +) -> Option { Some(match (format, aspect) { (wgt::TextureFormat::Depth16Unorm, crate::FormatAspects::DEPTH) => { - dxgiformat::DXGI_FORMAT_R16_UNORM + Dxgi::Common::DXGI_FORMAT_R16_UNORM } (wgt::TextureFormat::Depth32Float, crate::FormatAspects::DEPTH) => { - dxgiformat::DXGI_FORMAT_R32_FLOAT + Dxgi::Common::DXGI_FORMAT_R32_FLOAT } (wgt::TextureFormat::Depth32FloatStencil8, crate::FormatAspects::DEPTH) => { - dxgiformat::DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS + Dxgi::Common::DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS } ( wgt::TextureFormat::Depth24Plus | wgt::TextureFormat::Depth24PlusStencil8, crate::FormatAspects::DEPTH, - ) => dxgiformat::DXGI_FORMAT_R24_UNORM_X8_TYPELESS, + ) => Dxgi::Common::DXGI_FORMAT_R24_UNORM_X8_TYPELESS, (wgt::TextureFormat::Depth32FloatStencil8, crate::FormatAspects::STENCIL) => { - dxgiformat::DXGI_FORMAT_X32_TYPELESS_G8X24_UINT + Dxgi::Common::DXGI_FORMAT_X32_TYPELESS_G8X24_UINT } ( wgt::TextureFormat::Stencil8 | wgt::TextureFormat::Depth24PlusStencil8, crate::FormatAspects::STENCIL, - ) => dxgiformat::DXGI_FORMAT_X24_TYPELESS_G8_UINT, + ) => Dxgi::Common::DXGI_FORMAT_X24_TYPELESS_G8_UINT, (_, crate::FormatAspects::DEPTH) | (_, crate::FormatAspects::STENCIL) @@ -152,22 +155,22 @@ pub fn map_texture_format_for_srv_uav( pub fn map_texture_format_for_copy( format: wgt::TextureFormat, aspect: crate::FormatAspects, -) -> Option { +) -> Option { Some(match (format, aspect) { (wgt::TextureFormat::Depth16Unorm, crate::FormatAspects::DEPTH) => { - dxgiformat::DXGI_FORMAT_R16_UNORM + Dxgi::Common::DXGI_FORMAT_R16_UNORM } ( wgt::TextureFormat::Depth32Float | wgt::TextureFormat::Depth32FloatStencil8, crate::FormatAspects::DEPTH, - ) => dxgiformat::DXGI_FORMAT_R32_FLOAT, + ) => Dxgi::Common::DXGI_FORMAT_R32_FLOAT, ( wgt::TextureFormat::Stencil8 | wgt::TextureFormat::Depth24PlusStencil8 | wgt::TextureFormat::Depth32FloatStencil8, crate::FormatAspects::STENCIL, - ) => dxgiformat::DXGI_FORMAT_R8_UINT, + ) => Dxgi::Common::DXGI_FORMAT_R8_UINT, (format, crate::FormatAspects::COLOR) => map_texture_format(format), @@ -180,9 +183,9 @@ pub fn map_texture_format_for_resource( usage: crate::TextureUses, has_view_formats: bool, casting_fully_typed_format_supported: bool, -) -> dxgiformat::DXGI_FORMAT { +) -> Dxgi::Common::DXGI_FORMAT { use wgt::TextureFormat as Tf; - use winapi::shared::dxgiformat::*; + use Dxgi::Common::*; if casting_fully_typed_format_supported { map_texture_format(format) @@ -219,16 +222,16 @@ pub fn map_texture_format_for_resource( } } -pub fn map_index_format(format: wgt::IndexFormat) -> dxgiformat::DXGI_FORMAT { +pub fn map_index_format(format: wgt::IndexFormat) -> Dxgi::Common::DXGI_FORMAT { match format { - wgt::IndexFormat::Uint16 => dxgiformat::DXGI_FORMAT_R16_UINT, - wgt::IndexFormat::Uint32 => dxgiformat::DXGI_FORMAT_R32_UINT, + wgt::IndexFormat::Uint16 => Dxgi::Common::DXGI_FORMAT_R16_UINT, + wgt::IndexFormat::Uint32 => Dxgi::Common::DXGI_FORMAT_R32_UINT, } } -pub fn map_vertex_format(format: wgt::VertexFormat) -> dxgiformat::DXGI_FORMAT { +pub fn map_vertex_format(format: wgt::VertexFormat) -> Dxgi::Common::DXGI_FORMAT { use wgt::VertexFormat as Vf; - use winapi::shared::dxgiformat::*; + use Dxgi::Common::*; match format { Vf::Unorm8x2 => DXGI_FORMAT_R8G8_UNORM, @@ -266,6 +269,6 @@ pub fn map_vertex_format(format: wgt::VertexFormat) -> dxgiformat::DXGI_FORMAT { } } -pub fn map_acomposite_alpha_mode(_mode: wgt::CompositeAlphaMode) -> d3d12::AlphaMode { - d3d12::AlphaMode::Ignore +pub fn map_acomposite_alpha_mode(_mode: wgt::CompositeAlphaMode) -> Dxgi::Common::DXGI_ALPHA_MODE { + Dxgi::Common::DXGI_ALPHA_MODE_IGNORE } diff --git a/wgpu-hal/src/auxil/dxgi/exception.rs b/wgpu-hal/src/auxil/dxgi/exception.rs index 70db8b2d0..c3d655c6e 100644 --- a/wgpu-hal/src/auxil/dxgi/exception.rs +++ b/wgpu-hal/src/auxil/dxgi/exception.rs @@ -1,10 +1,7 @@ use std::{borrow::Cow, slice}; use parking_lot::{lock_api::RawMutex, Mutex}; -use winapi::{ - um::{errhandlingapi, winnt}, - vc::excpt, -}; +use windows::Win32::{Foundation, System::Diagnostics::Debug}; // This is a mutex as opposed to an atomic as we need to completely // lock everyone out until we have registered or unregistered the @@ -17,9 +14,7 @@ static EXCEPTION_HANDLER_COUNT: Mutex = Mutex::const_new(parking_lot::Raw pub fn register_exception_handler() { let mut count_guard = EXCEPTION_HANDLER_COUNT.lock(); if *count_guard == 0 { - unsafe { - errhandlingapi::AddVectoredExceptionHandler(0, Some(output_debug_string_handler)) - }; + unsafe { Debug::AddVectoredExceptionHandler(0, Some(output_debug_string_handler)) }; } *count_guard += 1; } @@ -27,9 +22,7 @@ pub fn register_exception_handler() { pub fn unregister_exception_handler() { let mut count_guard = EXCEPTION_HANDLER_COUNT.lock(); if *count_guard == 1 { - unsafe { - errhandlingapi::RemoveVectoredExceptionHandler(output_debug_string_handler as *mut _) - }; + unsafe { Debug::RemoveVectoredExceptionHandler(output_debug_string_handler as *mut _) }; } *count_guard -= 1; } @@ -43,34 +36,34 @@ const MESSAGE_PREFIXES: &[(&str, log::Level)] = &[ ]; unsafe extern "system" fn output_debug_string_handler( - exception_info: *mut winnt::EXCEPTION_POINTERS, + exception_info: *mut Debug::EXCEPTION_POINTERS, ) -> i32 { // See https://stackoverflow.com/a/41480827 let record = unsafe { &*(*exception_info).ExceptionRecord }; if record.NumberParameters != 2 { - return excpt::EXCEPTION_CONTINUE_SEARCH; + return Debug::EXCEPTION_CONTINUE_SEARCH; } let message = match record.ExceptionCode { - winnt::DBG_PRINTEXCEPTION_C => String::from_utf8_lossy(unsafe { + Foundation::DBG_PRINTEXCEPTION_C => String::from_utf8_lossy(unsafe { slice::from_raw_parts( record.ExceptionInformation[1] as *const u8, record.ExceptionInformation[0], ) }), - winnt::DBG_PRINTEXCEPTION_WIDE_C => Cow::Owned(String::from_utf16_lossy(unsafe { + Foundation::DBG_PRINTEXCEPTION_WIDE_C => Cow::Owned(String::from_utf16_lossy(unsafe { slice::from_raw_parts( record.ExceptionInformation[1] as *const u16, record.ExceptionInformation[0], ) })), - _ => return excpt::EXCEPTION_CONTINUE_SEARCH, + _ => return Debug::EXCEPTION_CONTINUE_SEARCH, }; let message = match message.strip_prefix("D3D12 ") { Some(msg) => msg .trim_end_matches("\n\0") .trim_end_matches("[ STATE_CREATION WARNING #0: UNKNOWN]"), - None => return excpt::EXCEPTION_CONTINUE_SEARCH, + None => return Debug::EXCEPTION_CONTINUE_SEARCH, }; let (message, level) = match MESSAGE_PREFIXES @@ -84,12 +77,12 @@ unsafe extern "system" fn output_debug_string_handler( if level == log::Level::Warn && message.contains("#82") { // This is are useless spammy warnings (#820, #821): // "The application did not pass any clear value to resource creation" - return excpt::EXCEPTION_CONTINUE_SEARCH; + return Debug::EXCEPTION_CONTINUE_SEARCH; } if level == log::Level::Warn && message.contains("DRAW_EMPTY_SCISSOR_RECTANGLE") { // This is normal, WebGPU allows passing empty scissor rectangles. - return excpt::EXCEPTION_CONTINUE_SEARCH; + return Debug::EXCEPTION_CONTINUE_SEARCH; } let _ = std::panic::catch_unwind(|| { @@ -101,5 +94,5 @@ unsafe extern "system" fn output_debug_string_handler( crate::VALIDATION_CANARY.add(message.to_string()); } - excpt::EXCEPTION_CONTINUE_EXECUTION + Debug::EXCEPTION_CONTINUE_EXECUTION } diff --git a/wgpu-hal/src/auxil/dxgi/factory.rs b/wgpu-hal/src/auxil/dxgi/factory.rs index 38fdd17c8..6c68ffeea 100644 --- a/wgpu-hal/src/auxil/dxgi/factory.rs +++ b/wgpu-hal/src/auxil/dxgi/factory.rs @@ -1,9 +1,8 @@ -use winapi::{ - shared::{dxgi, dxgi1_2, dxgi1_4, dxgi1_6, winerror}, - Interface, -}; +use std::ops::Deref; -use super::result::HResult as _; +use windows::{core::Interface as _, Win32::Graphics::Dxgi}; + +use crate::dx12::DxgiLib; #[derive(Debug, PartialEq, Eq, PartialOrd, Ord)] pub enum DxgiFactoryType { @@ -12,9 +11,8 @@ pub enum DxgiFactoryType { Factory6, } -fn should_keep_adapter(adapter: &dxgi::IDXGIAdapter1) -> bool { - let mut desc = unsafe { std::mem::zeroed() }; - unsafe { adapter.GetDesc1(&mut desc) }; +fn should_keep_adapter(adapter: &Dxgi::IDXGIAdapter1) -> bool { + let desc = unsafe { adapter.GetDesc1() }.unwrap(); // The Intel Haswell family of iGPUs had support for the D3D12 API but it was later // removed due to a security vulnerability. @@ -40,8 +38,10 @@ fn should_keep_adapter(adapter: &dxgi::IDXGIAdapter1) -> bool { // which is lying about being an integrated card. This is so that programs // that ignore software adapters will actually run on headless/gpu-less machines. // - // We don't want that and discorage that kind of filtering anyway, so we skip the integrated WARP. - if desc.VendorId == 5140 && (desc.Flags & dxgi::DXGI_ADAPTER_FLAG_SOFTWARE) == 0 { + // We don't want that and discourage that kind of filtering anyway, so we skip the integrated WARP. + if desc.VendorId == 5140 + && Dxgi::DXGI_ADAPTER_FLAG(desc.Flags as i32).contains(Dxgi::DXGI_ADAPTER_FLAG_SOFTWARE) + { let adapter_name = super::conv::map_adapter_name(desc.Description); if adapter_name.contains("Microsoft Basic Render Driver") { return false; @@ -51,50 +51,85 @@ fn should_keep_adapter(adapter: &dxgi::IDXGIAdapter1) -> bool { true } -pub fn enumerate_adapters(factory: d3d12::DxgiFactory) -> Vec { +pub enum DxgiAdapter { + Adapter1(Dxgi::IDXGIAdapter1), + Adapter2(Dxgi::IDXGIAdapter2), + Adapter3(Dxgi::IDXGIAdapter3), + Adapter4(Dxgi::IDXGIAdapter4), +} + +impl windows::core::Param for &DxgiAdapter { + unsafe fn param(self) -> windows::core::ParamValue { + unsafe { self.deref().param() } + } +} + +impl Deref for DxgiAdapter { + type Target = Dxgi::IDXGIAdapter; + + fn deref(&self) -> &Self::Target { + match self { + DxgiAdapter::Adapter1(a) => a, + DxgiAdapter::Adapter2(a) => a, + DxgiAdapter::Adapter3(a) => a, + DxgiAdapter::Adapter4(a) => a, + } + } +} + +impl DxgiAdapter { + pub fn as_adapter2(&self) -> Option<&Dxgi::IDXGIAdapter2> { + match self { + Self::Adapter1(_) => None, + Self::Adapter2(f) => Some(f), + Self::Adapter3(f) => Some(f), + Self::Adapter4(f) => Some(f), + } + } + + pub fn unwrap_adapter2(&self) -> &Dxgi::IDXGIAdapter2 { + self.as_adapter2().unwrap() + } +} + +pub fn enumerate_adapters(factory: DxgiFactory) -> Vec { let mut adapters = Vec::with_capacity(8); for cur_index in 0.. { - if let Some(factory6) = factory.as_factory6() { + if let DxgiFactory::Factory6(ref factory6) = factory { profiling::scope!("IDXGIFactory6::EnumAdapterByGpuPreference"); // We're already at dxgi1.6, we can grab IDXGIAdapter4 directly - let mut adapter4 = d3d12::ComPtr::::null(); - let hr = unsafe { + let adapter4: Dxgi::IDXGIAdapter4 = match unsafe { factory6.EnumAdapterByGpuPreference( cur_index, - dxgi1_6::DXGI_GPU_PREFERENCE_HIGH_PERFORMANCE, - &dxgi1_6::IDXGIAdapter4::uuidof(), - adapter4.mut_void(), + Dxgi::DXGI_GPU_PREFERENCE_HIGH_PERFORMANCE, ) + } { + Ok(a) => a, + Err(e) if e.code() == Dxgi::DXGI_ERROR_NOT_FOUND => break, + Err(e) => { + log::error!("Failed enumerating adapters: {}", e); + break; + } }; - if hr == winerror::DXGI_ERROR_NOT_FOUND { - break; - } - if let Err(err) = hr.into_result() { - log::error!("Failed enumerating adapters: {}", err); - break; - } - if !should_keep_adapter(&adapter4) { continue; } - adapters.push(d3d12::DxgiAdapter::Adapter4(adapter4)); + adapters.push(DxgiAdapter::Adapter4(adapter4)); continue; } profiling::scope!("IDXGIFactory1::EnumAdapters1"); - let mut adapter1 = d3d12::ComPtr::::null(); - let hr = unsafe { factory.EnumAdapters1(cur_index, adapter1.mut_self()) }; - - if hr == winerror::DXGI_ERROR_NOT_FOUND { - break; - } - if let Err(err) = hr.into_result() { - log::error!("Failed enumerating adapters: {}", err); - break; - } + let adapter1: Dxgi::IDXGIAdapter1 = match unsafe { factory.EnumAdapters1(cur_index) } { + Ok(a) => a, + Err(e) if e.code() == Dxgi::DXGI_ERROR_NOT_FOUND => break, + Err(e) => { + log::error!("Failed enumerating adapters: {}", e); + break; + } + }; if !should_keep_adapter(&adapter1) { continue; @@ -103,58 +138,97 @@ pub fn enumerate_adapters(factory: d3d12::DxgiFactory) -> Vec Adapter3 - unsafe { - match adapter1.cast::().into_result() { - Ok(adapter3) => { - adapters.push(d3d12::DxgiAdapter::Adapter3(adapter3)); - continue; - } - Err(err) => { - log::warn!("Failed casting Adapter1 to Adapter3: {}", err); - } + match adapter1.cast::() { + Ok(adapter3) => { + adapters.push(DxgiAdapter::Adapter3(adapter3)); + continue; + } + Err(err) => { + log::warn!("Failed casting Adapter1 to Adapter3: {}", err); } } // Adapter1 -> Adapter2 - unsafe { - match adapter1.cast::().into_result() { - Ok(adapter2) => { - adapters.push(d3d12::DxgiAdapter::Adapter2(adapter2)); - continue; - } - Err(err) => { - log::warn!("Failed casting Adapter1 to Adapter2: {}", err); - } + match adapter1.cast::() { + Ok(adapter2) => { + adapters.push(DxgiAdapter::Adapter2(adapter2)); + continue; + } + Err(err) => { + log::warn!("Failed casting Adapter1 to Adapter2: {}", err); } } - adapters.push(d3d12::DxgiAdapter::Adapter1(adapter1)); + adapters.push(DxgiAdapter::Adapter1(adapter1)); } adapters } -/// Tries to create a IDXGIFactory6, then a IDXGIFactory4, then a IDXGIFactory2, then a IDXGIFactory1, +#[derive(Clone, Debug)] +pub enum DxgiFactory { + Factory1(Dxgi::IDXGIFactory1), + Factory2(Dxgi::IDXGIFactory2), + Factory4(Dxgi::IDXGIFactory4), + Factory6(Dxgi::IDXGIFactory6), +} + +impl Deref for DxgiFactory { + type Target = Dxgi::IDXGIFactory1; + + fn deref(&self) -> &Self::Target { + match self { + DxgiFactory::Factory1(f) => f, + DxgiFactory::Factory2(f) => f, + DxgiFactory::Factory4(f) => f, + DxgiFactory::Factory6(f) => f, + } + } +} + +impl DxgiFactory { + pub fn as_factory2(&self) -> Option<&Dxgi::IDXGIFactory2> { + match self { + Self::Factory1(_) => None, + Self::Factory2(f) => Some(f), + Self::Factory4(f) => Some(f), + Self::Factory6(f) => Some(f), + } + } + + pub fn unwrap_factory2(&self) -> &Dxgi::IDXGIFactory2 { + self.as_factory2().unwrap() + } + + pub fn as_factory5(&self) -> Option<&Dxgi::IDXGIFactory5> { + match self { + Self::Factory1(_) | Self::Factory2(_) | Self::Factory4(_) => None, + Self::Factory6(f) => Some(f), + } + } +} + +/// Tries to create a [`Dxgi::IDXGIFactory6`], then a [`Dxgi::IDXGIFactory4`], then a [`Dxgi::IDXGIFactory2`], then a [`Dxgi::IDXGIFactory1`], /// returning the one that succeeds, or if the required_factory_type fails to be /// created. pub fn create_factory( required_factory_type: DxgiFactoryType, instance_flags: wgt::InstanceFlags, -) -> Result<(d3d12::DxgiLib, d3d12::DxgiFactory), crate::InstanceError> { - let lib_dxgi = d3d12::DxgiLib::new().map_err(|e| { +) -> Result<(DxgiLib, DxgiFactory), crate::InstanceError> { + let lib_dxgi = DxgiLib::new().map_err(|e| { crate::InstanceError::with_source(String::from("failed to load dxgi.dll"), e) })?; - let mut factory_flags = d3d12::FactoryCreationFlags::empty(); + let mut factory_flags = Dxgi::DXGI_CREATE_FACTORY_FLAGS::default(); if instance_flags.contains(wgt::InstanceFlags::VALIDATION) { // The `DXGI_CREATE_FACTORY_DEBUG` flag is only allowed to be passed to // `CreateDXGIFactory2` if the debug interface is actually available. So // we check for whether it exists first. - match lib_dxgi.get_debug_interface1() { - Ok(pair) => match pair.into_result() { + match lib_dxgi.debug_interface1() { + Ok(pair) => match pair { Ok(_debug_controller) => { - factory_flags |= d3d12::FactoryCreationFlags::DEBUG; + factory_flags |= Dxgi::DXGI_CREATE_FACTORY_DEBUG; } Err(err) => { log::warn!("Unable to enable DXGI debug interface: {}", err); @@ -171,7 +245,7 @@ pub fn create_factory( // Try to create IDXGIFactory4 let factory4 = match lib_dxgi.create_factory2(factory_flags) { - Ok(pair) => match pair.into_result() { + Ok(pair) => match pair { Ok(factory) => Some(factory), // We hard error here as we _should have_ been able to make a factory4 but couldn't. Err(err) => { @@ -197,10 +271,10 @@ pub fn create_factory( if let Some(factory4) = factory4 { // Try to cast the IDXGIFactory4 into IDXGIFactory6 - let factory6 = unsafe { factory4.cast::().into_result() }; + let factory6 = factory4.cast::(); match factory6 { Ok(factory6) => { - return Ok((lib_dxgi, d3d12::DxgiFactory::Factory6(factory6))); + return Ok((lib_dxgi, DxgiFactory::Factory6(factory6))); } // If we require factory6, hard error. Err(err) if required_factory_type == DxgiFactoryType::Factory6 => { @@ -212,14 +286,14 @@ pub fn create_factory( // If we don't print it to warn. Err(err) => { log::warn!("Failed to cast IDXGIFactory4 to IDXGIFactory6: {:?}", err); - return Ok((lib_dxgi, d3d12::DxgiFactory::Factory4(factory4))); + return Ok((lib_dxgi, DxgiFactory::Factory4(factory4))); } } } // Try to create IDXGIFactory1 let factory1 = match lib_dxgi.create_factory1() { - Ok(pair) => match pair.into_result() { + Ok(pair) => match pair { Ok(factory) => factory, Err(err) => { // err is a Cow, not an Error implementor @@ -238,10 +312,10 @@ pub fn create_factory( }; // Try to cast the IDXGIFactory1 into IDXGIFactory2 - let factory2 = unsafe { factory1.cast::().into_result() }; + let factory2 = factory1.cast::(); match factory2 { Ok(factory2) => { - return Ok((lib_dxgi, d3d12::DxgiFactory::Factory2(factory2))); + return Ok((lib_dxgi, DxgiFactory::Factory2(factory2))); } // If we require factory2, hard error. Err(err) if required_factory_type == DxgiFactoryType::Factory2 => { @@ -257,5 +331,5 @@ pub fn create_factory( } // We tried to create 4 and 2, but only succeeded with 1. - Ok((lib_dxgi, d3d12::DxgiFactory::Factory1(factory1))) + Ok((lib_dxgi, DxgiFactory::Factory1(factory1))) } diff --git a/wgpu-hal/src/auxil/dxgi/result.rs b/wgpu-hal/src/auxil/dxgi/result.rs index 2ac446456..3bb88b5bf 100644 --- a/wgpu-hal/src/auxil/dxgi/result.rs +++ b/wgpu-hal/src/auxil/dxgi/result.rs @@ -1,37 +1,46 @@ use std::borrow::Cow; -use winapi::shared::winerror; +use windows::Win32::{Foundation, Graphics::Dxgi}; pub(crate) trait HResult { fn into_result(self) -> Result>; fn into_device_result(self, description: &str) -> Result; } -impl HResult<()> for i32 { - fn into_result(self) -> Result<(), Cow<'static, str>> { - if self >= 0 { - return Ok(()); - } +impl HResult for windows::core::Result { + fn into_result(self) -> Result> { + // TODO: use windows-rs built-in error formatting? let description = match self { - winerror::E_UNEXPECTED => "unexpected", - winerror::E_NOTIMPL => "not implemented", - winerror::E_OUTOFMEMORY => "out of memory", - winerror::E_INVALIDARG => "invalid argument", - _ => return Err(Cow::Owned(format!("0x{:X}", self as u32))), + Ok(t) => return Ok(t), + Err(e) if e.code() == Foundation::E_UNEXPECTED => "unexpected", + Err(e) if e.code() == Foundation::E_NOTIMPL => "not implemented", + Err(e) if e.code() == Foundation::E_OUTOFMEMORY => "out of memory", + Err(e) if e.code() == Foundation::E_INVALIDARG => "invalid argument", + Err(e) => return Err(Cow::Owned(format!("{e:?}"))), }; Err(Cow::Borrowed(description)) } - fn into_device_result(self, description: &str) -> Result<(), crate::DeviceError> { + fn into_device_result(self, description: &str) -> Result { #![allow(unreachable_code)] + let err_code = if let Err(err) = &self { + Some(err.code()) + } else { + None + }; self.into_result().map_err(|err| { log::error!("{} failed: {}", description, err); - match self { - winerror::E_OUTOFMEMORY => { + let Some(err_code) = err_code else { + unreachable!() + }; + + match err_code { + Foundation::E_OUTOFMEMORY => { #[cfg(feature = "oom_panic")] panic!("{description} failed: Out of memory"); + return crate::DeviceError::OutOfMemory; } - winerror::DXGI_ERROR_DEVICE_RESET | winerror::DXGI_ERROR_DEVICE_REMOVED => { + Dxgi::DXGI_ERROR_DEVICE_RESET | Dxgi::DXGI_ERROR_DEVICE_REMOVED => { #[cfg(feature = "device_lost_panic")] panic!("{description} failed: Device lost ({err})"); } @@ -41,20 +50,7 @@ impl HResult<()> for i32 { } } - if self == winerror::E_OUTOFMEMORY { - crate::DeviceError::OutOfMemory - } else { - crate::DeviceError::Lost - } + crate::DeviceError::Lost }) } } - -impl HResult for (T, i32) { - fn into_result(self) -> Result> { - self.1.into_result().map(|()| self.0) - } - fn into_device_result(self, description: &str) -> Result { - self.1.into_device_result(description).map(|()| self.0) - } -} diff --git a/wgpu-hal/src/auxil/dxgi/time.rs b/wgpu-hal/src/auxil/dxgi/time.rs index fd99c097d..08bc3cee0 100644 --- a/wgpu-hal/src/auxil/dxgi/time.rs +++ b/wgpu-hal/src/auxil/dxgi/time.rs @@ -1,22 +1,20 @@ #![allow(dead_code)] // IPresentationManager is unused currently -use std::mem; - -use winapi::um::{ - profileapi::{QueryPerformanceCounter, QueryPerformanceFrequency}, - winnt::LARGE_INTEGER, -}; +use windows::Win32::System::Performance::{QueryPerformanceCounter, QueryPerformanceFrequency}; pub enum PresentationTimer { - /// DXGI uses QueryPerformanceCounter + /// DXGI uses [`QueryPerformanceCounter()`] Dxgi { /// How many ticks of QPC per second frequency: u64, }, - /// IPresentationManager uses QueryInterruptTimePrecise + /// [`IPresentationManager`] uses [`QueryInterruptTimePrecise()`] + /// + /// [`IPresentationManager`]: https://microsoft.github.io/windows-docs-rs/doc/windows/Win32/Graphics/CompositionSwapchain/struct.IPresentationManager.html + /// [`QueryInterruptTimePrecise()`]: https://microsoft.github.io/windows-docs-rs/doc/windows/Win32/System/WindowsProgramming/fn.QueryInterruptTimePrecise.html #[allow(non_snake_case)] IPresentationManager { - fnQueryInterruptTimePrecise: unsafe extern "system" fn(*mut winapi::ctypes::c_ulonglong), + fnQueryInterruptTimePrecise: unsafe extern "system" fn(*mut u64), }, } @@ -43,12 +41,13 @@ impl std::fmt::Debug for PresentationTimer { impl PresentationTimer { /// Create a presentation timer using QueryPerformanceFrequency (what DXGI uses for presentation times) pub fn new_dxgi() -> Self { - let mut frequency: LARGE_INTEGER = unsafe { mem::zeroed() }; - let success = unsafe { QueryPerformanceFrequency(&mut frequency) }; - assert_ne!(success, 0); + let mut frequency = 0; + unsafe { QueryPerformanceFrequency(&mut frequency) }.unwrap(); Self::Dxgi { - frequency: unsafe { *frequency.QuadPart() } as u64, + frequency: frequency + .try_into() + .expect("Frequency should not be negative"), } } @@ -59,6 +58,7 @@ impl PresentationTimer { // We need to load this explicitly, as QueryInterruptTimePrecise is only available on Windows 10+ // // Docs say it's in kernel32.dll, but it's actually in kernelbase.dll. + // api-ms-win-core-realtime-l1-1-1.dll let kernelbase = libloading::os::windows::Library::open_already_loaded("kernelbase.dll").unwrap(); // No concerns about lifetimes here as kernelbase is always there. @@ -73,12 +73,11 @@ impl PresentationTimer { // Always do u128 math _after_ hitting the timing function. match *self { PresentationTimer::Dxgi { frequency } => { - let mut counter: LARGE_INTEGER = unsafe { mem::zeroed() }; - let success = unsafe { QueryPerformanceCounter(&mut counter) }; - assert_ne!(success, 0); + let mut counter = 0; + unsafe { QueryPerformanceCounter(&mut counter) }.unwrap(); // counter * (1_000_000_000 / freq) but re-ordered to make more precise - (unsafe { *counter.QuadPart() } as u128 * 1_000_000_000) / frequency as u128 + (counter as u128 * 1_000_000_000) / frequency as u128 } PresentationTimer::IPresentationManager { fnQueryInterruptTimePrecise, diff --git a/wgpu-hal/src/auxil/renderdoc.rs b/wgpu-hal/src/auxil/renderdoc.rs index 240d9dda2..3b08955fa 100644 --- a/wgpu-hal/src/auxil/renderdoc.rs +++ b/wgpu-hal/src/auxil/renderdoc.rs @@ -106,7 +106,7 @@ impl Default for RenderDoc { unsafe { Self::new() } } } -/// A implementation specific handle +/// An implementation specific handle pub type Handle = *mut os::raw::c_void; impl RenderDoc { diff --git a/wgpu-hal/src/dx12/adapter.rs b/wgpu-hal/src/dx12/adapter.rs index f77c238d7..00930024a 100644 --- a/wgpu-hal/src/dx12/adapter.rs +++ b/wgpu-hal/src/dx12/adapter.rs @@ -1,15 +1,21 @@ -use crate::{ - auxil::{self, dxgi::result::HResult as _}, - dx12::{shader_compilation, SurfaceTarget}, -}; -use parking_lot::Mutex; use std::{mem, ptr, sync::Arc, thread}; -use winapi::{ - shared::{ - dxgi, dxgi1_2, dxgiformat::DXGI_FORMAT_B8G8R8A8_UNORM, minwindef::DWORD, windef, winerror, + +use parking_lot::Mutex; +use windows::{ + core::Interface as _, + Win32::{ + Graphics::{Direct3D, Direct3D12, Dxgi}, + UI::WindowsAndMessaging, }, - um::{d3d12 as d3d12_ty, d3d12sdklayers, winnt, winuser}, - Interface, +}; + +use super::D3D12Lib; +use crate::{ + auxil::{ + self, + dxgi::{factory::DxgiAdapter, result::HResult}, + }, + dx12::{shader_compilation, SurfaceTarget}, }; impl Drop for super::Adapter { @@ -30,34 +36,31 @@ impl Drop for super::Adapter { impl super::Adapter { pub unsafe fn report_live_objects(&self) { - if let Ok(debug_device) = unsafe { - self.raw - .cast::() - .into_result() - } { + if let Ok(debug_device) = self.raw.cast::() { unsafe { debug_device.ReportLiveDeviceObjects( - d3d12sdklayers::D3D12_RLDO_SUMMARY | d3d12sdklayers::D3D12_RLDO_IGNORE_INTERNAL, + Direct3D12::D3D12_RLDO_SUMMARY | Direct3D12::D3D12_RLDO_IGNORE_INTERNAL, ) - }; + } + .unwrap() } } - pub fn raw_adapter(&self) -> &d3d12::DxgiAdapter { + pub fn raw_adapter(&self) -> &DxgiAdapter { &self.raw } pub(super) fn expose( - adapter: d3d12::DxgiAdapter, - library: &Arc, + adapter: DxgiAdapter, + library: &Arc, instance_flags: wgt::InstanceFlags, dxc_container: Option>, ) -> Option> { // Create the device so that we can get the capabilities. let device = { profiling::scope!("ID3D12Device::create_device"); - match library.create_device(&adapter, d3d12::FeatureLevel::L11_0) { - Ok(pair) => match pair.into_result() { + match library.create_device(&adapter, Direct3D::D3D_FEATURE_LEVEL_11_0) { + Ok(pair) => match pair { Ok(device) => device, Err(err) => { log::warn!("Device creation failed: {}", err); @@ -75,45 +78,42 @@ impl super::Adapter { // Detect the highest supported feature level. let d3d_feature_level = [ - d3d12::FeatureLevel::L12_1, - d3d12::FeatureLevel::L12_0, - d3d12::FeatureLevel::L11_1, - d3d12::FeatureLevel::L11_0, + Direct3D::D3D_FEATURE_LEVEL_12_1, + Direct3D::D3D_FEATURE_LEVEL_12_0, + Direct3D::D3D_FEATURE_LEVEL_11_1, + Direct3D::D3D_FEATURE_LEVEL_11_0, ]; - let mut device_levels: d3d12_ty::D3D12_FEATURE_DATA_FEATURE_LEVELS = - unsafe { mem::zeroed() }; - device_levels.NumFeatureLevels = d3d_feature_level.len() as u32; - device_levels.pFeatureLevelsRequested = d3d_feature_level.as_ptr().cast(); + let mut device_levels = Direct3D12::D3D12_FEATURE_DATA_FEATURE_LEVELS { + NumFeatureLevels: d3d_feature_level.len() as u32, + pFeatureLevelsRequested: d3d_feature_level.as_ptr().cast(), + MaxSupportedFeatureLevel: Default::default(), + }; unsafe { device.CheckFeatureSupport( - d3d12_ty::D3D12_FEATURE_FEATURE_LEVELS, - ptr::from_mut(&mut device_levels).cast(), - mem::size_of::() as _, + Direct3D12::D3D12_FEATURE_FEATURE_LEVELS, + <*mut _>::cast(&mut device_levels), + mem::size_of_val(&device_levels) as u32, ) - }; - // This cast should never fail because we only requested feature levels that are already in the enum. - let max_feature_level = - d3d12::FeatureLevel::try_from(device_levels.MaxSupportedFeatureLevel) - .expect("Unexpected feature level"); + } + .unwrap(); + let max_feature_level = device_levels.MaxSupportedFeatureLevel; // We have found a possible adapter. // Acquire the device information. - let mut desc: dxgi1_2::DXGI_ADAPTER_DESC2 = unsafe { mem::zeroed() }; - unsafe { - adapter.unwrap_adapter2().GetDesc2(&mut desc); - } + let desc = unsafe { adapter.unwrap_adapter2().GetDesc2() }.unwrap(); let device_name = auxil::dxgi::conv::map_adapter_name(desc.Description); - let mut features_architecture: d3d12_ty::D3D12_FEATURE_DATA_ARCHITECTURE = - unsafe { mem::zeroed() }; - assert_eq!(0, unsafe { + let mut features_architecture = Direct3D12::D3D12_FEATURE_DATA_ARCHITECTURE::default(); + + unsafe { device.CheckFeatureSupport( - d3d12_ty::D3D12_FEATURE_ARCHITECTURE, - ptr::from_mut(&mut features_architecture).cast(), - mem::size_of::() as _, + Direct3D12::D3D12_FEATURE_ARCHITECTURE, + <*mut _>::cast(&mut features_architecture), + mem::size_of_val(&features_architecture) as u32, ) - }); + } + .unwrap(); let mut workarounds = super::Workarounds::default(); @@ -122,27 +122,25 @@ impl super::Adapter { name: device_name, vendor: desc.VendorId, device: desc.DeviceId, - device_type: if (desc.Flags & dxgi::DXGI_ADAPTER_FLAG_SOFTWARE) != 0 { + device_type: if Dxgi::DXGI_ADAPTER_FLAG(desc.Flags as i32) + .contains(Dxgi::DXGI_ADAPTER_FLAG_SOFTWARE) + { workarounds.avoid_cpu_descriptor_overwrites = true; wgt::DeviceType::Cpu - } else if features_architecture.UMA != 0 { + } else if features_architecture.UMA.as_bool() { wgt::DeviceType::IntegratedGpu } else { wgt::DeviceType::DiscreteGpu }, driver: { - let mut i: winnt::LARGE_INTEGER = unsafe { mem::zeroed() }; - if 0 == unsafe { - adapter.CheckInterfaceSupport(&dxgi::IDXGIDevice::uuidof(), &mut i) - } { - let quad_part = unsafe { *i.QuadPart() }; + if let Ok(i) = unsafe { adapter.CheckInterfaceSupport(&Dxgi::IDXGIDevice::IID) } { const MASK: i64 = 0xFFFF; format!( "{}.{}.{}.{}", - quad_part >> 48, - (quad_part >> 32) & MASK, - (quad_part >> 16) & MASK, - quad_part & MASK + i >> 48, + (i >> 32) & MASK, + (i >> 16) & MASK, + i & MASK ) } else { String::new() @@ -151,84 +149,101 @@ impl super::Adapter { driver_info: String::new(), }; - let mut options: d3d12_ty::D3D12_FEATURE_DATA_D3D12_OPTIONS = unsafe { mem::zeroed() }; - assert_eq!(0, unsafe { + let mut options = Direct3D12::D3D12_FEATURE_DATA_D3D12_OPTIONS::default(); + unsafe { device.CheckFeatureSupport( - d3d12_ty::D3D12_FEATURE_D3D12_OPTIONS, - ptr::from_mut(&mut options).cast(), - mem::size_of::() as _, + Direct3D12::D3D12_FEATURE_D3D12_OPTIONS, + <*mut _>::cast(&mut options), + mem::size_of_val(&options) as u32, ) - }); + } + .unwrap(); let _depth_bounds_test_supported = { - let mut features2: d3d12_ty::D3D12_FEATURE_DATA_D3D12_OPTIONS2 = - unsafe { mem::zeroed() }; - let hr = unsafe { + let mut features2 = Direct3D12::D3D12_FEATURE_DATA_D3D12_OPTIONS2::default(); + unsafe { device.CheckFeatureSupport( - d3d12_ty::D3D12_FEATURE_D3D12_OPTIONS2, - ptr::from_mut(&mut features2).cast(), - mem::size_of::() as _, + Direct3D12::D3D12_FEATURE_D3D12_OPTIONS2, + <*mut _>::cast(&mut features2), + mem::size_of_val(&features2) as u32, ) - }; - hr == 0 && features2.DepthBoundsTestSupported != 0 + } + .is_ok() + && features2.DepthBoundsTestSupported.as_bool() }; let casting_fully_typed_format_supported = { - let mut features3: crate::dx12::types::D3D12_FEATURE_DATA_D3D12_OPTIONS3 = - unsafe { mem::zeroed() }; - let hr = unsafe { + let mut features3 = Direct3D12::D3D12_FEATURE_DATA_D3D12_OPTIONS3::default(); + unsafe { device.CheckFeatureSupport( - 21, // D3D12_FEATURE_D3D12_OPTIONS3 - ptr::from_mut(&mut features3).cast(), - mem::size_of::() as _, + Direct3D12::D3D12_FEATURE_D3D12_OPTIONS3, + <*mut _>::cast(&mut features3), + mem::size_of_val(&features3) as u32, ) - }; - hr == 0 && features3.CastingFullyTypedFormatSupported != 0 + } + .is_ok() + && features3.CastingFullyTypedFormatSupported.as_bool() + }; + + let heap_create_not_zeroed = { + // For D3D12_HEAP_FLAG_CREATE_NOT_ZEROED we just need to + // make sure that options7 can be queried. See also: + // https://devblogs.microsoft.com/directx/coming-to-directx-12-more-control-over-memory-allocation/ + let mut features7 = Direct3D12::D3D12_FEATURE_DATA_D3D12_OPTIONS7::default(); + unsafe { + device.CheckFeatureSupport( + Direct3D12::D3D12_FEATURE_D3D12_OPTIONS7, + <*mut _>::cast(&mut features7), + mem::size_of_val(&features7) as u32, + ) + } + .is_ok() }; let shader_model = if dxc_container.is_none() { naga::back::hlsl::ShaderModel::V5_1 } else { let mut versions = [ - crate::dx12::types::D3D_SHADER_MODEL_6_7, - crate::dx12::types::D3D_SHADER_MODEL_6_6, - crate::dx12::types::D3D_SHADER_MODEL_6_5, - crate::dx12::types::D3D_SHADER_MODEL_6_4, - crate::dx12::types::D3D_SHADER_MODEL_6_3, - crate::dx12::types::D3D_SHADER_MODEL_6_2, - crate::dx12::types::D3D_SHADER_MODEL_6_1, - crate::dx12::types::D3D_SHADER_MODEL_6_0, - crate::dx12::types::D3D_SHADER_MODEL_5_1, + Direct3D12::D3D_SHADER_MODEL_6_7, + Direct3D12::D3D_SHADER_MODEL_6_6, + Direct3D12::D3D_SHADER_MODEL_6_5, + Direct3D12::D3D_SHADER_MODEL_6_4, + Direct3D12::D3D_SHADER_MODEL_6_3, + Direct3D12::D3D_SHADER_MODEL_6_2, + Direct3D12::D3D_SHADER_MODEL_6_1, + Direct3D12::D3D_SHADER_MODEL_6_0, + Direct3D12::D3D_SHADER_MODEL_5_1, ] .iter(); match loop { if let Some(&sm) = versions.next() { - let mut sm = crate::dx12::types::D3D12_FEATURE_DATA_SHADER_MODEL { + let mut sm = Direct3D12::D3D12_FEATURE_DATA_SHADER_MODEL { HighestShaderModel: sm, }; - if 0 == unsafe { + if unsafe { device.CheckFeatureSupport( - 7, // D3D12_FEATURE_SHADER_MODEL - ptr::from_mut(&mut sm).cast(), - mem::size_of::() - as _, + Direct3D12::D3D12_FEATURE_SHADER_MODEL, + <*mut _>::cast(&mut sm), + mem::size_of_val(&sm) as u32, ) - } { + } + .is_ok() + { break sm.HighestShaderModel; } } else { - break crate::dx12::types::D3D_SHADER_MODEL_5_1; + break Direct3D12::D3D_SHADER_MODEL_5_1; } } { - crate::dx12::types::D3D_SHADER_MODEL_5_1 => naga::back::hlsl::ShaderModel::V5_1, - crate::dx12::types::D3D_SHADER_MODEL_6_0 => naga::back::hlsl::ShaderModel::V6_0, - crate::dx12::types::D3D_SHADER_MODEL_6_1 => naga::back::hlsl::ShaderModel::V6_1, - crate::dx12::types::D3D_SHADER_MODEL_6_2 => naga::back::hlsl::ShaderModel::V6_2, - crate::dx12::types::D3D_SHADER_MODEL_6_3 => naga::back::hlsl::ShaderModel::V6_3, - crate::dx12::types::D3D_SHADER_MODEL_6_4 => naga::back::hlsl::ShaderModel::V6_4, - crate::dx12::types::D3D_SHADER_MODEL_6_5 => naga::back::hlsl::ShaderModel::V6_5, - crate::dx12::types::D3D_SHADER_MODEL_6_6 => naga::back::hlsl::ShaderModel::V6_6, - crate::dx12::types::D3D_SHADER_MODEL_6_7 => naga::back::hlsl::ShaderModel::V6_7, + Direct3D12::D3D_SHADER_MODEL_5_1 => naga::back::hlsl::ShaderModel::V5_1, + Direct3D12::D3D_SHADER_MODEL_6_0 => naga::back::hlsl::ShaderModel::V6_0, + Direct3D12::D3D_SHADER_MODEL_6_1 => naga::back::hlsl::ShaderModel::V6_1, + Direct3D12::D3D_SHADER_MODEL_6_2 => naga::back::hlsl::ShaderModel::V6_2, + Direct3D12::D3D_SHADER_MODEL_6_3 => naga::back::hlsl::ShaderModel::V6_3, + Direct3D12::D3D_SHADER_MODEL_6_4 => naga::back::hlsl::ShaderModel::V6_4, + Direct3D12::D3D_SHADER_MODEL_6_5 => naga::back::hlsl::ShaderModel::V6_5, + Direct3D12::D3D_SHADER_MODEL_6_6 => naga::back::hlsl::ShaderModel::V6_6, + Direct3D12::D3D_SHADER_MODEL_6_7 => naga::back::hlsl::ShaderModel::V6_7, _ => unreachable!(), } }; @@ -236,15 +251,15 @@ impl super::Adapter { let private_caps = super::PrivateCapabilities { instance_flags, heterogeneous_resource_heaps: options.ResourceHeapTier - != d3d12_ty::D3D12_RESOURCE_HEAP_TIER_1, - memory_architecture: if features_architecture.UMA != 0 { + != Direct3D12::D3D12_RESOURCE_HEAP_TIER_1, + memory_architecture: if features_architecture.UMA.as_bool() { super::MemoryArchitecture::Unified { - cache_coherent: features_architecture.CacheCoherentUMA != 0, + cache_coherent: features_architecture.CacheCoherentUMA.as_bool(), } } else { super::MemoryArchitecture::NonUnified }, - heap_create_not_zeroed: false, //TODO: winapi support for Options7 + heap_create_not_zeroed, casting_fully_typed_format_supported, // See https://github.com/gfx-rs/wgpu/issues/3552 suballocation_supported: !info.name.contains("Iris(R) Xe"), @@ -255,29 +270,29 @@ impl super::Adapter { let tier3_practical_descriptor_limit = 1 << 20; let (full_heap_count, uav_count) = match options.ResourceBindingTier { - d3d12_ty::D3D12_RESOURCE_BINDING_TIER_1 => { + Direct3D12::D3D12_RESOURCE_BINDING_TIER_1 => { let uav_count = match max_feature_level { - d3d12::FeatureLevel::L11_0 => 8, + Direct3D::D3D_FEATURE_LEVEL_11_0 => 8, _ => 64, }; ( - d3d12_ty::D3D12_MAX_SHADER_VISIBLE_DESCRIPTOR_HEAP_SIZE_TIER_1, + Direct3D12::D3D12_MAX_SHADER_VISIBLE_DESCRIPTOR_HEAP_SIZE_TIER_1, uav_count, ) } - d3d12_ty::D3D12_RESOURCE_BINDING_TIER_2 => ( - d3d12_ty::D3D12_MAX_SHADER_VISIBLE_DESCRIPTOR_HEAP_SIZE_TIER_2, + Direct3D12::D3D12_RESOURCE_BINDING_TIER_2 => ( + Direct3D12::D3D12_MAX_SHADER_VISIBLE_DESCRIPTOR_HEAP_SIZE_TIER_2, 64, ), - d3d12_ty::D3D12_RESOURCE_BINDING_TIER_3 => ( + Direct3D12::D3D12_RESOURCE_BINDING_TIER_3 => ( tier3_practical_descriptor_limit, tier3_practical_descriptor_limit, ), other => { - log::warn!("Unknown resource binding tier {}", other); + log::warn!("Unknown resource binding tier {:?}", other); ( - d3d12_ty::D3D12_MAX_SHADER_VISIBLE_DESCRIPTOR_HEAP_SIZE_TIER_1, + Direct3D12::D3D12_MAX_SHADER_VISIBLE_DESCRIPTOR_HEAP_SIZE_TIER_1, 8, ) } @@ -313,14 +328,14 @@ impl super::Adapter { // write the results there, and issue a bunch of copy commands. //| wgt::Features::PIPELINE_STATISTICS_QUERY - if max_feature_level as u32 >= d3d12::FeatureLevel::L11_1 as u32 { + if max_feature_level.0 >= Direct3D::D3D_FEATURE_LEVEL_11_1.0 { features |= wgt::Features::VERTEX_WRITABLE_STORAGE; } features.set( wgt::Features::CONSERVATIVE_RASTERIZATION, options.ConservativeRasterizationTier - != d3d12_ty::D3D12_CONSERVATIVE_RASTERIZATION_TIER_NOT_SUPPORTED, + != Direct3D12::D3D12_CONSERVATIVE_RASTERIZATION_TIER_NOT_SUPPORTED, ); features.set( @@ -331,60 +346,62 @@ impl super::Adapter { ); let bgra8unorm_storage_supported = { - let mut bgra8unorm_info: d3d12_ty::D3D12_FEATURE_DATA_FORMAT_SUPPORT = - unsafe { mem::zeroed() }; - bgra8unorm_info.Format = DXGI_FORMAT_B8G8R8A8_UNORM; + let mut bgra8unorm_info = Direct3D12::D3D12_FEATURE_DATA_FORMAT_SUPPORT { + Format: Dxgi::Common::DXGI_FORMAT_B8G8R8A8_UNORM, + ..Default::default() + }; let hr = unsafe { device.CheckFeatureSupport( - d3d12_ty::D3D12_FEATURE_FORMAT_SUPPORT, - ptr::from_mut(&mut bgra8unorm_info).cast(), - mem::size_of::() as _, + Direct3D12::D3D12_FEATURE_FORMAT_SUPPORT, + <*mut _>::cast(&mut bgra8unorm_info), + mem::size_of_val(&bgra8unorm_info) as u32, ) }; - hr == 0 - && (bgra8unorm_info.Support2 & d3d12_ty::D3D12_FORMAT_SUPPORT2_UAV_TYPED_STORE != 0) + hr.is_ok() + && bgra8unorm_info + .Support2 + .contains(Direct3D12::D3D12_FORMAT_SUPPORT2_UAV_TYPED_STORE) }; features.set( wgt::Features::BGRA8UNORM_STORAGE, bgra8unorm_storage_supported, ); - let mut features1: d3d12_ty::D3D12_FEATURE_DATA_D3D12_OPTIONS1 = unsafe { mem::zeroed() }; + let mut features1 = Direct3D12::D3D12_FEATURE_DATA_D3D12_OPTIONS1::default(); let hr = unsafe { device.CheckFeatureSupport( - d3d12_ty::D3D12_FEATURE_D3D12_OPTIONS1, - ptr::from_mut(&mut features1).cast(), - mem::size_of::() as _, + Direct3D12::D3D12_FEATURE_D3D12_OPTIONS1, + <*mut _>::cast(&mut features1), + mem::size_of_val(&features1) as u32, ) }; features.set( wgt::Features::SHADER_INT64, shader_model >= naga::back::hlsl::ShaderModel::V6_0 - && hr == 0 - && features1.Int64ShaderOps != 0, + && hr.is_ok() + && features1.Int64ShaderOps.as_bool(), ); features.set( wgt::Features::SUBGROUP, shader_model >= naga::back::hlsl::ShaderModel::V6_0 - && hr == 0 - && features1.WaveOps != 0, + && hr.is_ok() + && features1.WaveOps.as_bool(), ); let atomic_int64_on_typed_resource_supported = { - let mut features9: crate::dx12::types::D3D12_FEATURE_DATA_D3D12_OPTIONS9 = - unsafe { mem::zeroed() }; - let hr = unsafe { + let mut features9 = Direct3D12::D3D12_FEATURE_DATA_D3D12_OPTIONS9::default(); + unsafe { device.CheckFeatureSupport( - 37, // D3D12_FEATURE_D3D12_OPTIONS9 - ptr::from_mut(&mut features9).cast(), - mem::size_of::() as _, + Direct3D12::D3D12_FEATURE_D3D12_OPTIONS9, + <*mut _>::cast(&mut features9), + mem::size_of_val(&features9) as u32, ) - }; - hr == 0 - && features9.AtomicInt64OnGroupSharedSupported != 0 - && features9.AtomicInt64OnTypedResourceSupported != 0 + } + .is_ok() + && features9.AtomicInt64OnGroupSharedSupported.as_bool() + && features9.AtomicInt64OnTypedResourceSupported.as_bool() }; features.set( wgt::Features::SHADER_INT64_ATOMIC_ALL_OPS | wgt::Features::SHADER_INT64_ATOMIC_MIN_MAX, @@ -424,11 +441,11 @@ impl super::Adapter { features, capabilities: crate::Capabilities { limits: wgt::Limits { - max_texture_dimension_1d: d3d12_ty::D3D12_REQ_TEXTURE1D_U_DIMENSION, - max_texture_dimension_2d: d3d12_ty::D3D12_REQ_TEXTURE2D_U_OR_V_DIMENSION - .min(d3d12_ty::D3D12_REQ_TEXTURECUBE_DIMENSION), - max_texture_dimension_3d: d3d12_ty::D3D12_REQ_TEXTURE3D_U_V_OR_W_DIMENSION, - max_texture_array_layers: d3d12_ty::D3D12_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION, + max_texture_dimension_1d: Direct3D12::D3D12_REQ_TEXTURE1D_U_DIMENSION, + max_texture_dimension_2d: Direct3D12::D3D12_REQ_TEXTURE2D_U_OR_V_DIMENSION + .min(Direct3D12::D3D12_REQ_TEXTURECUBE_DIMENSION), + max_texture_dimension_3d: Direct3D12::D3D12_REQ_TEXTURE3D_U_V_OR_W_DIMENSION, + max_texture_array_layers: Direct3D12::D3D12_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION, max_bind_groups: crate::MAX_BIND_GROUPS as u32, max_bindings_per_bind_group: 65535, // dynamic offsets take a root constant, so we expose the minimum here @@ -437,12 +454,12 @@ impl super::Adapter { max_dynamic_storage_buffers_per_pipeline_layout: base .max_dynamic_storage_buffers_per_pipeline_layout, max_sampled_textures_per_shader_stage: match options.ResourceBindingTier { - d3d12_ty::D3D12_RESOURCE_BINDING_TIER_1 => 128, + Direct3D12::D3D12_RESOURCE_BINDING_TIER_1 => 128, _ => full_heap_count, }, max_samplers_per_shader_stage: match options.ResourceBindingTier { - d3d12_ty::D3D12_RESOURCE_BINDING_TIER_1 => 16, - _ => d3d12_ty::D3D12_MAX_SHADER_VISIBLE_SAMPLER_HEAP_SIZE, + Direct3D12::D3D12_RESOURCE_BINDING_TIER_1 => 16, + _ => Direct3D12::D3D12_MAX_SHADER_VISIBLE_SAMPLER_HEAP_SIZE, }, // these both account towards `uav_count`, but we can't express the limit as as sum // of the two, so we divide it by 4 to account for the worst case scenario @@ -451,12 +468,12 @@ impl super::Adapter { max_storage_textures_per_shader_stage: uav_count / 4, max_uniform_buffers_per_shader_stage: full_heap_count, max_uniform_buffer_binding_size: - d3d12_ty::D3D12_REQ_CONSTANT_BUFFER_ELEMENT_COUNT * 16, + Direct3D12::D3D12_REQ_CONSTANT_BUFFER_ELEMENT_COUNT * 16, max_storage_buffer_binding_size: auxil::MAX_I32_BINDING_SIZE, - max_vertex_buffers: d3d12_ty::D3D12_VS_INPUT_REGISTER_COUNT + max_vertex_buffers: Direct3D12::D3D12_VS_INPUT_REGISTER_COUNT .min(crate::MAX_VERTEX_BUFFERS as u32), - max_vertex_attributes: d3d12_ty::D3D12_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT, - max_vertex_buffer_array_stride: d3d12_ty::D3D12_SO_BUFFER_MAX_STRIDE_IN_BYTES, + max_vertex_attributes: Direct3D12::D3D12_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT, + max_vertex_buffer_array_stride: Direct3D12::D3D12_SO_BUFFER_MAX_STRIDE_IN_BYTES, min_subgroup_size: 4, // Not using `features1.WaveLaneCountMin` as it is unreliable max_subgroup_size: 128, // The push constants are part of the root signature which @@ -479,19 +496,19 @@ impl super::Adapter { // Source: https://learn.microsoft.com/en-us/windows/win32/direct3d12/root-signature-limits#memory-limits-and-costs max_push_constant_size: 128, min_uniform_buffer_offset_alignment: - d3d12_ty::D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT, + Direct3D12::D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT, min_storage_buffer_offset_alignment: 4, max_inter_stage_shader_components: base.max_inter_stage_shader_components, max_color_attachments, max_color_attachment_bytes_per_sample, max_compute_workgroup_storage_size: base.max_compute_workgroup_storage_size, //TODO? max_compute_invocations_per_workgroup: - d3d12_ty::D3D12_CS_4_X_THREAD_GROUP_MAX_THREADS_PER_GROUP, - max_compute_workgroup_size_x: d3d12_ty::D3D12_CS_THREAD_GROUP_MAX_X, - max_compute_workgroup_size_y: d3d12_ty::D3D12_CS_THREAD_GROUP_MAX_Y, - max_compute_workgroup_size_z: d3d12_ty::D3D12_CS_THREAD_GROUP_MAX_Z, + Direct3D12::D3D12_CS_4_X_THREAD_GROUP_MAX_THREADS_PER_GROUP, + max_compute_workgroup_size_x: Direct3D12::D3D12_CS_THREAD_GROUP_MAX_X, + max_compute_workgroup_size_y: Direct3D12::D3D12_CS_THREAD_GROUP_MAX_Y, + max_compute_workgroup_size_z: Direct3D12::D3D12_CS_THREAD_GROUP_MAX_Z, max_compute_workgroups_per_dimension: - d3d12_ty::D3D12_CS_DISPATCH_MAX_THREAD_GROUPS_PER_DIMENSION, + Direct3D12::D3D12_CS_DISPATCH_MAX_THREAD_GROUPS_PER_DIMENSION, // Dx12 does not expose a maximum buffer size in the API. // This limit is chosen to avoid potential issues with drivers should they internally // store buffer sizes using 32 bit ints (a situation we have already encountered with vulkan). @@ -500,11 +517,11 @@ impl super::Adapter { }, alignments: crate::Alignments { buffer_copy_offset: wgt::BufferSize::new( - d3d12_ty::D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT as u64, + Direct3D12::D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT as u64, ) .unwrap(), buffer_copy_pitch: wgt::BufferSize::new( - d3d12_ty::D3D12_TEXTURE_DATA_PITCH_ALIGNMENT as u64, + Direct3D12::D3D12_TEXTURE_DATA_PITCH_ALIGNMENT as u64, ) .unwrap(), }, @@ -523,16 +540,18 @@ impl crate::Adapter for super::Adapter { limits: &wgt::Limits, memory_hints: &wgt::MemoryHints, ) -> Result, crate::DeviceError> { - let queue = { + let queue: Direct3D12::ID3D12CommandQueue = { profiling::scope!("ID3D12Device::CreateCommandQueue"); - self.device - .create_command_queue( - d3d12::CmdListType::Direct, - d3d12::Priority::Normal, - d3d12::CommandQueueFlags::empty(), - 0, - ) - .into_device_result("Queue creation")? + unsafe { + self.device + .CreateCommandQueue(&Direct3D12::D3D12_COMMAND_QUEUE_DESC { + Type: Direct3D12::D3D12_COMMAND_LIST_TYPE_DIRECT, + Priority: Direct3D12::D3D12_COMMAND_QUEUE_PRIORITY_NORMAL.0, + Flags: Direct3D12::D3D12_COMMAND_QUEUE_FLAG_NONE, + NodeMask: 0, + }) + } + .into_device_result("Queue creation")? }; let device = super::Device::new( @@ -577,99 +596,118 @@ impl crate::Adapter for super::Adapter { } .unwrap(); - let mut data = d3d12_ty::D3D12_FEATURE_DATA_FORMAT_SUPPORT { + let mut data = Direct3D12::D3D12_FEATURE_DATA_FORMAT_SUPPORT { Format: raw_format, - Support1: unsafe { mem::zeroed() }, - Support2: unsafe { mem::zeroed() }, + ..Default::default() }; - assert_eq!(winerror::S_OK, unsafe { + unsafe { self.device.CheckFeatureSupport( - d3d12_ty::D3D12_FEATURE_FORMAT_SUPPORT, - ptr::from_mut(&mut data).cast(), - mem::size_of::() as _, + Direct3D12::D3D12_FEATURE_FORMAT_SUPPORT, + <*mut _>::cast(&mut data), + mem::size_of_val(&data) as u32, ) - }); + } + .unwrap(); // Because we use a different format for SRV and UAV views of depth textures, we need to check // the features that use SRV/UAVs using the no-depth format. - let mut data_srv_uav = d3d12_ty::D3D12_FEATURE_DATA_FORMAT_SUPPORT { + let mut data_srv_uav = Direct3D12::D3D12_FEATURE_DATA_FORMAT_SUPPORT { Format: srv_uav_format, - Support1: d3d12_ty::D3D12_FORMAT_SUPPORT1_NONE, - Support2: d3d12_ty::D3D12_FORMAT_SUPPORT2_NONE, + Support1: Direct3D12::D3D12_FORMAT_SUPPORT1_NONE, + Support2: Direct3D12::D3D12_FORMAT_SUPPORT2_NONE, }; if raw_format != srv_uav_format { // Only-recheck if we're using a different format - assert_eq!(winerror::S_OK, unsafe { + unsafe { self.device.CheckFeatureSupport( - d3d12_ty::D3D12_FEATURE_FORMAT_SUPPORT, + Direct3D12::D3D12_FEATURE_FORMAT_SUPPORT, ptr::addr_of_mut!(data_srv_uav).cast(), - DWORD::try_from(mem::size_of::()) - .unwrap(), + mem::size_of::() as u32, ) - }); + } + .unwrap(); } else { // Same format, just copy over. data_srv_uav = data; } let mut caps = Tfc::COPY_SRC | Tfc::COPY_DST; - let is_texture = data.Support1 - & (d3d12_ty::D3D12_FORMAT_SUPPORT1_TEXTURE1D - | d3d12_ty::D3D12_FORMAT_SUPPORT1_TEXTURE2D - | d3d12_ty::D3D12_FORMAT_SUPPORT1_TEXTURE3D - | d3d12_ty::D3D12_FORMAT_SUPPORT1_TEXTURECUBE) + // Cannot use the contains() helper, and windows-rs doesn't provide a .intersect() helper + let is_texture = (data.Support1 + & (Direct3D12::D3D12_FORMAT_SUPPORT1_TEXTURE1D + | Direct3D12::D3D12_FORMAT_SUPPORT1_TEXTURE2D + | Direct3D12::D3D12_FORMAT_SUPPORT1_TEXTURE3D + | Direct3D12::D3D12_FORMAT_SUPPORT1_TEXTURECUBE)) + .0 != 0; // SRVs use srv_uav_format caps.set( Tfc::SAMPLED, - is_texture && data_srv_uav.Support1 & d3d12_ty::D3D12_FORMAT_SUPPORT1_SHADER_LOAD != 0, + is_texture + && data_srv_uav + .Support1 + .contains(Direct3D12::D3D12_FORMAT_SUPPORT1_SHADER_LOAD), ); caps.set( Tfc::SAMPLED_LINEAR, - data_srv_uav.Support1 & d3d12_ty::D3D12_FORMAT_SUPPORT1_SHADER_SAMPLE != 0, + data_srv_uav + .Support1 + .contains(Direct3D12::D3D12_FORMAT_SUPPORT1_SHADER_SAMPLE), ); caps.set( Tfc::COLOR_ATTACHMENT, - data.Support1 & d3d12_ty::D3D12_FORMAT_SUPPORT1_RENDER_TARGET != 0, + data.Support1 + .contains(Direct3D12::D3D12_FORMAT_SUPPORT1_RENDER_TARGET), ); caps.set( Tfc::COLOR_ATTACHMENT_BLEND, - data.Support1 & d3d12_ty::D3D12_FORMAT_SUPPORT1_BLENDABLE != 0, + data.Support1 + .contains(Direct3D12::D3D12_FORMAT_SUPPORT1_BLENDABLE), ); caps.set( Tfc::DEPTH_STENCIL_ATTACHMENT, - data.Support1 & d3d12_ty::D3D12_FORMAT_SUPPORT1_DEPTH_STENCIL != 0, + data.Support1 + .contains(Direct3D12::D3D12_FORMAT_SUPPORT1_DEPTH_STENCIL), ); // UAVs use srv_uav_format caps.set( Tfc::STORAGE, - data_srv_uav.Support1 & d3d12_ty::D3D12_FORMAT_SUPPORT1_TYPED_UNORDERED_ACCESS_VIEW - != 0, + data_srv_uav + .Support1 + .contains(Direct3D12::D3D12_FORMAT_SUPPORT1_TYPED_UNORDERED_ACCESS_VIEW), ); caps.set( Tfc::STORAGE_READ_WRITE, - data_srv_uav.Support2 & d3d12_ty::D3D12_FORMAT_SUPPORT2_UAV_TYPED_LOAD != 0, + data_srv_uav + .Support2 + .contains(Direct3D12::D3D12_FORMAT_SUPPORT2_UAV_TYPED_LOAD), ); // We load via UAV/SRV so use srv_uav_format let no_msaa_load = caps.contains(Tfc::SAMPLED) - && data_srv_uav.Support1 & d3d12_ty::D3D12_FORMAT_SUPPORT1_MULTISAMPLE_LOAD == 0; + && !data_srv_uav + .Support1 + .contains(Direct3D12::D3D12_FORMAT_SUPPORT1_MULTISAMPLE_LOAD); - let no_msaa_target = data.Support1 - & (d3d12_ty::D3D12_FORMAT_SUPPORT1_RENDER_TARGET - | d3d12_ty::D3D12_FORMAT_SUPPORT1_DEPTH_STENCIL) + let no_msaa_target = (data.Support1 + & (Direct3D12::D3D12_FORMAT_SUPPORT1_RENDER_TARGET + | Direct3D12::D3D12_FORMAT_SUPPORT1_DEPTH_STENCIL)) + .0 != 0 - && data.Support1 & d3d12_ty::D3D12_FORMAT_SUPPORT1_MULTISAMPLE_RENDERTARGET == 0; + && !data + .Support1 + .contains(Direct3D12::D3D12_FORMAT_SUPPORT1_MULTISAMPLE_RENDERTARGET); caps.set( Tfc::MULTISAMPLE_RESOLVE, - data.Support1 & d3d12_ty::D3D12_FORMAT_SUPPORT1_MULTISAMPLE_RESOLVE != 0, + data.Support1 + .contains(Direct3D12::D3D12_FORMAT_SUPPORT1_MULTISAMPLE_RESOLVE), ); - let mut ms_levels = d3d12_ty::D3D12_FEATURE_DATA_MULTISAMPLE_QUALITY_LEVELS { + let mut ms_levels = Direct3D12::D3D12_FEATURE_DATA_MULTISAMPLE_QUALITY_LEVELS { Format: raw_format, SampleCount: 0, - Flags: d3d12_ty::D3D12_MULTISAMPLE_QUALITY_LEVELS_FLAG_NONE, + Flags: Direct3D12::D3D12_MULTISAMPLE_QUALITY_LEVELS_FLAG_NONE, NumQualityLevels: 0, }; @@ -678,11 +716,12 @@ impl crate::Adapter for super::Adapter { if unsafe { self.device.CheckFeatureSupport( - d3d12_ty::D3D12_FEATURE_MULTISAMPLE_QUALITY_LEVELS, + Direct3D12::D3D12_FEATURE_MULTISAMPLE_QUALITY_LEVELS, <*mut _>::cast(&mut ms_levels), - mem::size_of::() as _, + mem::size_of_val(&ms_levels) as u32, ) - } == winerror::S_OK + } + .is_ok() && ms_levels.NumQualityLevels != 0 { caps.set(tfc, !no_msaa_load && !no_msaa_target); @@ -704,8 +743,9 @@ impl crate::Adapter for super::Adapter { let current_extent = { match surface.target { SurfaceTarget::WndHandle(wnd_handle) => { - let mut rect: windef::RECT = unsafe { mem::zeroed() }; - if unsafe { winuser::GetClientRect(wnd_handle, &mut rect) } != 0 { + let mut rect = Default::default(); + if unsafe { WindowsAndMessaging::GetClientRect(wnd_handle, &mut rect) }.is_ok() + { Some(wgt::Extent3d { width: (rect.right - rect.left) as u32, height: (rect.bottom - rect.top) as u32, diff --git a/wgpu-hal/src/dx12/command.rs b/wgpu-hal/src/dx12/command.rs index 0356b9197..5f32480fd 100644 --- a/wgpu-hal/src/dx12/command.rs +++ b/wgpu-hal/src/dx12/command.rs @@ -1,11 +1,15 @@ -use crate::auxil::{self, dxgi::result::HResult as _}; +use std::{mem, ops::Range}; + +use windows::Win32::{Foundation, Graphics::Direct3D12}; use super::conv; -use std::{mem, ops::Range, ptr}; -use winapi::um::d3d12 as d3d12_ty; +use crate::{ + auxil::{self, dxgi::result::HResult as _}, + dx12::borrow_interface_temporarily, +}; -fn make_box(origin: &wgt::Origin3d, size: &crate::CopyExtent) -> d3d12_ty::D3D12_BOX { - d3d12_ty::D3D12_BOX { +fn make_box(origin: &wgt::Origin3d, size: &crate::CopyExtent) -> Direct3D12::D3D12_BOX { + Direct3D12::D3D12_BOX { left: origin.x, top: origin.y, right: origin.x + size.width, @@ -19,11 +23,11 @@ impl crate::BufferTextureCopy { fn to_subresource_footprint( &self, format: wgt::TextureFormat, - ) -> d3d12_ty::D3D12_PLACED_SUBRESOURCE_FOOTPRINT { + ) -> Direct3D12::D3D12_PLACED_SUBRESOURCE_FOOTPRINT { let (block_width, _) = format.block_dimensions(); - d3d12_ty::D3D12_PLACED_SUBRESOURCE_FOOTPRINT { + Direct3D12::D3D12_PLACED_SUBRESOURCE_FOOTPRINT { Offset: self.buffer_layout.offset, - Footprint: d3d12_ty::D3D12_SUBRESOURCE_FOOTPRINT { + Footprint: Direct3D12::D3D12_SUBRESOURCE_FOOTPRINT { Format: auxil::dxgi::conv::map_texture_format_for_copy( format, self.texture_base.aspect, @@ -40,7 +44,7 @@ impl crate::BufferTextureCopy { .unwrap(); (self.size.width / block_width) * block_size }); - wgt::math::align_to(actual, d3d12_ty::D3D12_TEXTURE_DATA_PITCH_ALIGNMENT) + wgt::math::align_to(actual, Direct3D12::D3D12_TEXTURE_DATA_PITCH_ALIGNMENT) }, }, } @@ -49,6 +53,7 @@ impl crate::BufferTextureCopy { impl super::Temp { fn prepare_marker(&mut self, marker: &str) -> (&[u16], u32) { + // TODO: Store in HSTRING self.marker.clear(); self.marker.extend(marker.encode_utf16()); self.marker.push(0); @@ -69,20 +74,22 @@ impl super::CommandEncoder { self.pass.kind = kind; if let Some(label) = label { let (wide_label, size) = self.temp.prepare_marker(label); - unsafe { list.BeginEvent(0, wide_label.as_ptr().cast(), size) }; + unsafe { list.BeginEvent(0, Some(wide_label.as_ptr().cast()), size) }; self.pass.has_label = true; } self.pass.dirty_root_elements = 0; self.pass.dirty_vertex_buffers = 0; - list.set_descriptor_heaps(&[ - self.shared.heap_views.raw.clone(), - self.shared.heap_samplers.raw.clone(), - ]); + unsafe { + list.SetDescriptorHeaps(&[ + Some(self.shared.heap_views.raw.clone()), + Some(self.shared.heap_samplers.raw.clone()), + ]) + }; } unsafe fn end_pass(&mut self) { let list = self.list.as_ref().unwrap(); - list.set_descriptor_heaps(&[]); + unsafe { list.SetDescriptorHeaps(&[]) }; if self.pass.has_label { unsafe { list.EndEvent() }; } @@ -97,8 +104,7 @@ impl super::CommandEncoder { unsafe { list.IASetVertexBuffers( index, - 1, - self.pass.vertex_buffers.as_ptr().offset(index as isize), + Some(&self.pass.vertex_buffers[index as usize..][..1]), ); } } @@ -165,8 +171,12 @@ impl super::CommandEncoder { for offset in info.range.clone() { let val = self.pass.constant_data[offset as usize]; match self.pass.kind { - Pk::Render => list.set_graphics_root_constant(index, val, offset), - Pk::Compute => list.set_compute_root_constant(index, val, offset), + Pk::Render => unsafe { + list.SetGraphicsRoot32BitConstant(index, val, offset) + }, + Pk::Compute => unsafe { + list.SetComputeRoot32BitConstant(index, val, offset) + }, Pk::Transfer => (), } } @@ -177,41 +187,42 @@ impl super::CommandEncoder { other, } => match self.pass.kind { Pk::Render => { - list.set_graphics_root_constant(index, first_vertex as u32, 0); - list.set_graphics_root_constant(index, first_instance, 1); + unsafe { list.SetGraphicsRoot32BitConstant(index, first_vertex as u32, 0) }; + unsafe { list.SetGraphicsRoot32BitConstant(index, first_instance, 1) }; } Pk::Compute => { - list.set_compute_root_constant(index, first_vertex as u32, 0); - list.set_compute_root_constant(index, first_instance, 1); - list.set_compute_root_constant(index, other, 2); + unsafe { list.SetComputeRoot32BitConstant(index, first_vertex as u32, 0) }; + unsafe { list.SetComputeRoot32BitConstant(index, first_instance, 1) }; + unsafe { list.SetComputeRoot32BitConstant(index, other, 2) }; } Pk::Transfer => (), }, super::RootElement::Table(descriptor) => match self.pass.kind { - Pk::Render => list.set_graphics_root_descriptor_table(index, descriptor), - Pk::Compute => list.set_compute_root_descriptor_table(index, descriptor), + Pk::Render => unsafe { list.SetGraphicsRootDescriptorTable(index, descriptor) }, + Pk::Compute => unsafe { list.SetComputeRootDescriptorTable(index, descriptor) }, Pk::Transfer => (), }, super::RootElement::DynamicOffsetBuffer { kind, address } => { + let address = address.ptr; match (self.pass.kind, kind) { - (Pk::Render, Bvk::Constant) => { - list.set_graphics_root_constant_buffer_view(index, address) - } - (Pk::Compute, Bvk::Constant) => { - list.set_compute_root_constant_buffer_view(index, address) - } - (Pk::Render, Bvk::ShaderResource) => { - list.set_graphics_root_shader_resource_view(index, address) - } - (Pk::Compute, Bvk::ShaderResource) => { - list.set_compute_root_shader_resource_view(index, address) - } - (Pk::Render, Bvk::UnorderedAccess) => { - list.set_graphics_root_unordered_access_view(index, address) - } - (Pk::Compute, Bvk::UnorderedAccess) => { - list.set_compute_root_unordered_access_view(index, address) - } + (Pk::Render, Bvk::Constant) => unsafe { + list.SetGraphicsRootConstantBufferView(index, address) + }, + (Pk::Compute, Bvk::Constant) => unsafe { + list.SetComputeRootConstantBufferView(index, address) + }, + (Pk::Render, Bvk::ShaderResource) => unsafe { + list.SetGraphicsRootShaderResourceView(index, address) + }, + (Pk::Compute, Bvk::ShaderResource) => unsafe { + list.SetComputeRootShaderResourceView(index, address) + }, + (Pk::Render, Bvk::UnorderedAccess) => unsafe { + list.SetGraphicsRootUnorderedAccessView(index, address) + }, + (Pk::Compute, Bvk::UnorderedAccess) => unsafe { + list.SetComputeRootUnorderedAccessView(index, address) + }, (Pk::Transfer, _) => (), } } @@ -239,7 +250,7 @@ impl super::CommandEncoder { self.write_timestamp( &crate::dx12::QuerySet { raw: query_set_raw, - raw_ty: d3d12_ty::D3D12_QUERY_TYPE_TIMESTAMP, + raw_ty: Direct3D12::D3D12_QUERY_TYPE_TIMESTAMP, }, index, ); @@ -254,9 +265,7 @@ impl crate::CommandEncoder for super::CommandEncoder { unsafe fn begin_encoding(&mut self, label: crate::Label) -> Result<(), crate::DeviceError> { let list = loop { if let Some(list) = self.free_lists.pop() { - let reset_result = list - .reset(&self.allocator, d3d12::PipelineState::null()) - .into_result(); + let reset_result = unsafe { list.Reset(&self.allocator, None) }.into_result(); if reset_result.is_ok() { break Some(list); } @@ -268,19 +277,20 @@ impl crate::CommandEncoder for super::CommandEncoder { let list = if let Some(list) = list { list } else { - self.device - .create_graphics_command_list( - d3d12::CmdListType::Direct, - &self.allocator, - d3d12::PipelineState::null(), + unsafe { + self.device.CreateCommandList( 0, + Direct3D12::D3D12_COMMAND_LIST_TYPE_DIRECT, + &self.allocator, + None, ) - .into_device_result("Create command list")? + } + .into_device_result("Create command list")? }; if let Some(label) = label { - let cwstr = conv::map_label(label); - unsafe { list.SetName(cwstr.as_ptr()) }; + unsafe { list.SetName(&windows::core::HSTRING::from(label)) } + .into_device_result("SetName")?; } self.list = Some(list); @@ -290,22 +300,21 @@ impl crate::CommandEncoder for super::CommandEncoder { } unsafe fn discard_encoding(&mut self) { if let Some(list) = self.list.take() { - if list.close().into_result().is_ok() { + if unsafe { list.Close() }.is_ok() { self.free_lists.push(list); } } } unsafe fn end_encoding(&mut self) -> Result { let raw = self.list.take().unwrap(); - raw.close() - .into_device_result("GraphicsCommandList::close")?; + unsafe { raw.Close() }.into_device_result("GraphicsCommandList::close")?; Ok(super::CommandBuffer { raw }) } unsafe fn reset_all>(&mut self, command_buffers: I) { for cmd_buf in command_buffers { self.free_lists.push(cmd_buf.raw); } - self.allocator.reset(); + let _todo_handle_error = unsafe { self.allocator.Reset() }; } unsafe fn transition_buffers<'a, T>(&mut self, barriers: T) @@ -318,30 +327,34 @@ impl crate::CommandEncoder for super::CommandEncoder { let s0 = conv::map_buffer_usage_to_state(barrier.usage.start); let s1 = conv::map_buffer_usage_to_state(barrier.usage.end); if s0 != s1 { - let mut raw = d3d12_ty::D3D12_RESOURCE_BARRIER { - Type: d3d12_ty::D3D12_RESOURCE_BARRIER_TYPE_TRANSITION, - Flags: d3d12_ty::D3D12_RESOURCE_BARRIER_FLAG_NONE, - u: unsafe { mem::zeroed() }, - }; - unsafe { - *raw.u.Transition_mut() = d3d12_ty::D3D12_RESOURCE_TRANSITION_BARRIER { - pResource: barrier.buffer.resource.as_mut_ptr(), - Subresource: d3d12_ty::D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES, - StateBefore: s0, - StateAfter: s1, - } + let raw = Direct3D12::D3D12_RESOURCE_BARRIER { + Type: Direct3D12::D3D12_RESOURCE_BARRIER_TYPE_TRANSITION, + Flags: Direct3D12::D3D12_RESOURCE_BARRIER_FLAG_NONE, + Anonymous: Direct3D12::D3D12_RESOURCE_BARRIER_0 { + Transition: mem::ManuallyDrop::new( + Direct3D12::D3D12_RESOURCE_TRANSITION_BARRIER { + pResource: unsafe { + borrow_interface_temporarily(&barrier.buffer.resource) + }, + Subresource: Direct3D12::D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES, + StateBefore: s0, + StateAfter: s1, + }, + ), + }, }; self.temp.barriers.push(raw); } else if barrier.usage.start == crate::BufferUses::STORAGE_READ_WRITE { - let mut raw = d3d12_ty::D3D12_RESOURCE_BARRIER { - Type: d3d12_ty::D3D12_RESOURCE_BARRIER_TYPE_UAV, - Flags: d3d12_ty::D3D12_RESOURCE_BARRIER_FLAG_NONE, - u: unsafe { mem::zeroed() }, - }; - unsafe { - *raw.u.UAV_mut() = d3d12_ty::D3D12_RESOURCE_UAV_BARRIER { - pResource: barrier.buffer.resource.as_mut_ptr(), - } + let raw = Direct3D12::D3D12_RESOURCE_BARRIER { + Type: Direct3D12::D3D12_RESOURCE_BARRIER_TYPE_UAV, + Flags: Direct3D12::D3D12_RESOURCE_BARRIER_FLAG_NONE, + Anonymous: Direct3D12::D3D12_RESOURCE_BARRIER_0 { + UAV: mem::ManuallyDrop::new(Direct3D12::D3D12_RESOURCE_UAV_BARRIER { + pResource: unsafe { + borrow_interface_temporarily(&barrier.buffer.resource) + }, + }), + }, }; self.temp.barriers.push(raw); } @@ -352,7 +365,7 @@ impl crate::CommandEncoder for super::CommandEncoder { self.list .as_ref() .unwrap() - .ResourceBarrier(self.temp.barriers.len() as u32, self.temp.barriers.as_ptr()) + .ResourceBarrier(&self.temp.barriers) }; } } @@ -367,18 +380,21 @@ impl crate::CommandEncoder for super::CommandEncoder { let s0 = conv::map_texture_usage_to_state(barrier.usage.start); let s1 = conv::map_texture_usage_to_state(barrier.usage.end); if s0 != s1 { - let mut raw = d3d12_ty::D3D12_RESOURCE_BARRIER { - Type: d3d12_ty::D3D12_RESOURCE_BARRIER_TYPE_TRANSITION, - Flags: d3d12_ty::D3D12_RESOURCE_BARRIER_FLAG_NONE, - u: unsafe { mem::zeroed() }, - }; - unsafe { - *raw.u.Transition_mut() = d3d12_ty::D3D12_RESOURCE_TRANSITION_BARRIER { - pResource: barrier.texture.resource.as_mut_ptr(), - Subresource: d3d12_ty::D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES, - StateBefore: s0, - StateAfter: s1, - } + let mut raw = Direct3D12::D3D12_RESOURCE_BARRIER { + Type: Direct3D12::D3D12_RESOURCE_BARRIER_TYPE_TRANSITION, + Flags: Direct3D12::D3D12_RESOURCE_BARRIER_FLAG_NONE, + Anonymous: Direct3D12::D3D12_RESOURCE_BARRIER_0 { + Transition: mem::ManuallyDrop::new( + Direct3D12::D3D12_RESOURCE_TRANSITION_BARRIER { + pResource: unsafe { + borrow_interface_temporarily(&barrier.texture.resource) + }, + Subresource: Direct3D12::D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES, + StateBefore: s0, + StateAfter: s1, + }, + ), + }, }; let tex_mip_level_count = barrier.texture.mip_level_count; @@ -419,26 +435,25 @@ impl crate::CommandEncoder for super::CommandEncoder { for mip_level in barrier.range.mip_range(tex_mip_level_count) { for array_layer in barrier.range.layer_range(tex_array_layer_count) { for plane in planes.clone() { - unsafe { - raw.u.Transition_mut().Subresource = barrier - .texture - .calc_subresource(mip_level, array_layer, plane); - }; - self.temp.barriers.push(raw); + unsafe { &mut *raw.Anonymous.Transition }.Subresource = barrier + .texture + .calc_subresource(mip_level, array_layer, plane); + self.temp.barriers.push(raw.clone()); } } } } } else if barrier.usage.start == crate::TextureUses::STORAGE_READ_WRITE { - let mut raw = d3d12_ty::D3D12_RESOURCE_BARRIER { - Type: d3d12_ty::D3D12_RESOURCE_BARRIER_TYPE_UAV, - Flags: d3d12_ty::D3D12_RESOURCE_BARRIER_FLAG_NONE, - u: unsafe { mem::zeroed() }, - }; - unsafe { - *raw.u.UAV_mut() = d3d12_ty::D3D12_RESOURCE_UAV_BARRIER { - pResource: barrier.texture.resource.as_mut_ptr(), - } + let raw = Direct3D12::D3D12_RESOURCE_BARRIER { + Type: Direct3D12::D3D12_RESOURCE_BARRIER_TYPE_UAV, + Flags: Direct3D12::D3D12_RESOURCE_BARRIER_FLAG_NONE, + Anonymous: Direct3D12::D3D12_RESOURCE_BARRIER_0 { + UAV: mem::ManuallyDrop::new(Direct3D12::D3D12_RESOURCE_UAV_BARRIER { + pResource: unsafe { + borrow_interface_temporarily(&barrier.texture.resource) + }, + }), + }, }; self.temp.barriers.push(raw); } @@ -449,7 +464,7 @@ impl crate::CommandEncoder for super::CommandEncoder { self.list .as_ref() .unwrap() - .ResourceBarrier(self.temp.barriers.len() as u32, self.temp.barriers.as_ptr()) + .ResourceBarrier(&self.temp.barriers) }; } } @@ -460,13 +475,7 @@ impl crate::CommandEncoder for super::CommandEncoder { while offset < range.end { let size = super::ZERO_BUFFER_SIZE.min(range.end - offset); unsafe { - list.CopyBufferRegion( - buffer.resource.as_mut_ptr(), - offset, - self.shared.zero_buffer.as_mut_ptr(), - 0, - size, - ) + list.CopyBufferRegion(&buffer.resource, offset, &self.shared.zero_buffer, 0, size) }; offset += size; } @@ -484,9 +493,9 @@ impl crate::CommandEncoder for super::CommandEncoder { for r in regions { unsafe { list.CopyBufferRegion( - dst.resource.as_mut_ptr(), + &dst.resource, r.dst_offset, - src.resource.as_mut_ptr(), + &src.resource, r.src_offset, r.size.get(), ) @@ -504,25 +513,24 @@ impl crate::CommandEncoder for super::CommandEncoder { T: Iterator, { let list = self.list.as_ref().unwrap(); - let mut src_location = d3d12_ty::D3D12_TEXTURE_COPY_LOCATION { - pResource: src.resource.as_mut_ptr(), - Type: d3d12_ty::D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX, - u: unsafe { mem::zeroed() }, - }; - let mut dst_location = d3d12_ty::D3D12_TEXTURE_COPY_LOCATION { - pResource: dst.resource.as_mut_ptr(), - Type: d3d12_ty::D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX, - u: unsafe { mem::zeroed() }, - }; for r in regions { + let src_location = Direct3D12::D3D12_TEXTURE_COPY_LOCATION { + pResource: unsafe { borrow_interface_temporarily(&src.resource) }, + Type: Direct3D12::D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX, + Anonymous: Direct3D12::D3D12_TEXTURE_COPY_LOCATION_0 { + SubresourceIndex: src.calc_subresource_for_copy(&r.src_base), + }, + }; + let dst_location = Direct3D12::D3D12_TEXTURE_COPY_LOCATION { + pResource: unsafe { borrow_interface_temporarily(&dst.resource) }, + Type: Direct3D12::D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX, + Anonymous: Direct3D12::D3D12_TEXTURE_COPY_LOCATION_0 { + SubresourceIndex: dst.calc_subresource_for_copy(&r.dst_base), + }, + }; + let src_box = make_box(&r.src_base.origin, &r.size); - unsafe { - *src_location.u.SubresourceIndex_mut() = src.calc_subresource_for_copy(&r.src_base) - }; - unsafe { - *dst_location.u.SubresourceIndex_mut() = dst.calc_subresource_for_copy(&r.dst_base) - }; unsafe { list.CopyTextureRegion( @@ -531,7 +539,7 @@ impl crate::CommandEncoder for super::CommandEncoder { r.dst_base.origin.y, r.dst_base.origin.z, &src_location, - &src_box, + Some(&src_box), ) }; } @@ -546,25 +554,23 @@ impl crate::CommandEncoder for super::CommandEncoder { T: Iterator, { let list = self.list.as_ref().unwrap(); - let mut src_location = d3d12_ty::D3D12_TEXTURE_COPY_LOCATION { - pResource: src.resource.as_mut_ptr(), - Type: d3d12_ty::D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT, - u: unsafe { mem::zeroed() }, - }; - let mut dst_location = d3d12_ty::D3D12_TEXTURE_COPY_LOCATION { - pResource: dst.resource.as_mut_ptr(), - Type: d3d12_ty::D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX, - u: unsafe { mem::zeroed() }, - }; for r in regions { + let src_location = Direct3D12::D3D12_TEXTURE_COPY_LOCATION { + pResource: unsafe { borrow_interface_temporarily(&src.resource) }, + Type: Direct3D12::D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT, + Anonymous: Direct3D12::D3D12_TEXTURE_COPY_LOCATION_0 { + PlacedFootprint: r.to_subresource_footprint(dst.format), + }, + }; + let dst_location = Direct3D12::D3D12_TEXTURE_COPY_LOCATION { + pResource: unsafe { borrow_interface_temporarily(&dst.resource) }, + Type: Direct3D12::D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX, + Anonymous: Direct3D12::D3D12_TEXTURE_COPY_LOCATION_0 { + SubresourceIndex: dst.calc_subresource_for_copy(&r.texture_base), + }, + }; + let src_box = make_box(&wgt::Origin3d::ZERO, &r.size); - unsafe { - *src_location.u.PlacedFootprint_mut() = r.to_subresource_footprint(dst.format) - }; - unsafe { - *dst_location.u.SubresourceIndex_mut() = - dst.calc_subresource_for_copy(&r.texture_base) - }; unsafe { list.CopyTextureRegion( &dst_location, @@ -572,7 +578,7 @@ impl crate::CommandEncoder for super::CommandEncoder { r.texture_base.origin.y, r.texture_base.origin.z, &src_location, - &src_box, + Some(&src_box), ) }; } @@ -588,26 +594,26 @@ impl crate::CommandEncoder for super::CommandEncoder { T: Iterator, { let list = self.list.as_ref().unwrap(); - let mut src_location = d3d12_ty::D3D12_TEXTURE_COPY_LOCATION { - pResource: src.resource.as_mut_ptr(), - Type: d3d12_ty::D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX, - u: unsafe { mem::zeroed() }, - }; - let mut dst_location = d3d12_ty::D3D12_TEXTURE_COPY_LOCATION { - pResource: dst.resource.as_mut_ptr(), - Type: d3d12_ty::D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT, - u: unsafe { mem::zeroed() }, - }; for r in regions { + let src_location = Direct3D12::D3D12_TEXTURE_COPY_LOCATION { + pResource: unsafe { borrow_interface_temporarily(&src.resource) }, + Type: Direct3D12::D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX, + Anonymous: Direct3D12::D3D12_TEXTURE_COPY_LOCATION_0 { + SubresourceIndex: src.calc_subresource_for_copy(&r.texture_base), + }, + }; + let dst_location = Direct3D12::D3D12_TEXTURE_COPY_LOCATION { + pResource: unsafe { borrow_interface_temporarily(&dst.resource) }, + Type: Direct3D12::D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT, + Anonymous: Direct3D12::D3D12_TEXTURE_COPY_LOCATION_0 { + PlacedFootprint: r.to_subresource_footprint(src.format), + }, + }; + let src_box = make_box(&r.texture_base.origin, &r.size); unsafe { - *src_location.u.SubresourceIndex_mut() = - src.calc_subresource_for_copy(&r.texture_base) + list.CopyTextureRegion(&dst_location, 0, 0, 0, &src_location, Some(&src_box)) }; - unsafe { - *dst_location.u.PlacedFootprint_mut() = r.to_subresource_footprint(src.format) - }; - unsafe { list.CopyTextureRegion(&dst_location, 0, 0, 0, &src_location, &src_box) }; } } @@ -616,7 +622,7 @@ impl crate::CommandEncoder for super::CommandEncoder { self.list .as_ref() .unwrap() - .BeginQuery(set.raw.as_mut_ptr(), set.raw_ty, index) + .BeginQuery(&set.raw, set.raw_ty, index) }; } unsafe fn end_query(&mut self, set: &super::QuerySet, index: u32) { @@ -624,14 +630,14 @@ impl crate::CommandEncoder for super::CommandEncoder { self.list .as_ref() .unwrap() - .EndQuery(set.raw.as_mut_ptr(), set.raw_ty, index) + .EndQuery(&set.raw, set.raw_ty, index) }; } unsafe fn write_timestamp(&mut self, set: &super::QuerySet, index: u32) { unsafe { self.list.as_ref().unwrap().EndQuery( - set.raw.as_mut_ptr(), - d3d12_ty::D3D12_QUERY_TYPE_TIMESTAMP, + &set.raw, + Direct3D12::D3D12_QUERY_TYPE_TIMESTAMP, index, ) }; @@ -649,11 +655,11 @@ impl crate::CommandEncoder for super::CommandEncoder { ) { unsafe { self.list.as_ref().unwrap().ResolveQueryData( - set.raw.as_mut_ptr(), + &set.raw, set.raw_ty, range.start, range.end - range.start, - buffer.resource.as_mut_ptr(), + &buffer.resource, offset, ) }; @@ -679,7 +685,8 @@ impl crate::CommandEncoder for super::CommandEncoder { .map(|index| (timestamp_writes.query_set.raw.clone(), index)); } - let mut color_views = [d3d12::CpuDescriptor { ptr: 0 }; crate::MAX_COLOR_ATTACHMENTS]; + let mut color_views = + [Direct3D12::D3D12_CPU_DESCRIPTOR_HANDLE { ptr: 0 }; crate::MAX_COLOR_ATTACHMENTS]; for (rtv, cat) in color_views.iter_mut().zip(desc.color_attachments.iter()) { if let Some(cat) = cat.as_ref() { *rtv = cat.target.view.handle_rtv.unwrap().raw; @@ -688,24 +695,22 @@ impl crate::CommandEncoder for super::CommandEncoder { } } - let ds_view = match desc.depth_stencil_attachment { - None => ptr::null(), - Some(ref ds) => { - if ds.target.usage == crate::TextureUses::DEPTH_STENCIL_WRITE { - &ds.target.view.handle_dsv_rw.as_ref().unwrap().raw - } else { - &ds.target.view.handle_dsv_ro.as_ref().unwrap().raw - } + let ds_view = desc.depth_stencil_attachment.as_ref().map(|ds| { + if ds.target.usage == crate::TextureUses::DEPTH_STENCIL_WRITE { + ds.target.view.handle_dsv_rw.as_ref().unwrap().raw + } else { + ds.target.view.handle_dsv_ro.as_ref().unwrap().raw } - }; + }); let list = self.list.as_ref().unwrap(); + #[allow(trivial_casts)] // No other clean way to write the coercion inside .map() below? unsafe { list.OMSetRenderTargets( desc.color_attachments.len() as u32, - color_views.as_ptr(), - 0, - ds_view, + Some(color_views.as_ptr()), + false, + ds_view.as_ref().map(std::ptr::from_ref), ) }; @@ -719,7 +724,8 @@ impl crate::CommandEncoder for super::CommandEncoder { cat.clear_value.b as f32, cat.clear_value.a as f32, ]; - list.clear_render_target_view(*rtv, value, &[]); + // TODO: Empty slice vs None? + unsafe { list.ClearRenderTargetView(*rtv, &value, Some(&[])) }; } if let Some(ref target) = cat.resolve_target { self.pass.resolves.push(super::PassResolve { @@ -732,31 +738,35 @@ impl crate::CommandEncoder for super::CommandEncoder { } if let Some(ref ds) = desc.depth_stencil_attachment { - let mut flags = d3d12::ClearFlags::empty(); + let mut flags = Direct3D12::D3D12_CLEAR_FLAGS::default(); let aspects = ds.target.view.aspects; if !ds.depth_ops.contains(crate::AttachmentOps::LOAD) && aspects.contains(crate::FormatAspects::DEPTH) { - flags |= d3d12::ClearFlags::DEPTH; + flags |= Direct3D12::D3D12_CLEAR_FLAG_DEPTH; } if !ds.stencil_ops.contains(crate::AttachmentOps::LOAD) && aspects.contains(crate::FormatAspects::STENCIL) { - flags |= d3d12::ClearFlags::STENCIL; + flags |= Direct3D12::D3D12_CLEAR_FLAG_STENCIL; } - if !ds_view.is_null() && !flags.is_empty() { - list.clear_depth_stencil_view( - unsafe { *ds_view }, - flags, - ds.clear_value.0, - ds.clear_value.1 as u8, - &[], - ); + if let Some(ds_view) = ds_view { + if flags != Direct3D12::D3D12_CLEAR_FLAGS::default() { + unsafe { + list.ClearDepthStencilView( + ds_view, + flags, + ds.clear_value.0, + ds.clear_value.1 as u8, + &[], + ) + } + } } } - let raw_vp = d3d12_ty::D3D12_VIEWPORT { + let raw_vp = Direct3D12::D3D12_VIEWPORT { TopLeftX: 0.0, TopLeftY: 0.0, Width: desc.extent.width as f32, @@ -764,14 +774,14 @@ impl crate::CommandEncoder for super::CommandEncoder { MinDepth: 0.0, MaxDepth: 1.0, }; - let raw_rect = d3d12_ty::D3D12_RECT { + let raw_rect = Foundation::RECT { left: 0, top: 0, right: desc.extent.width as i32, bottom: desc.extent.height as i32, }; - unsafe { list.RSSetViewports(1, &raw_vp) }; - unsafe { list.RSSetScissorRects(1, &raw_rect) }; + unsafe { list.RSSetViewports(std::slice::from_ref(&raw_vp)) }; + unsafe { list.RSSetScissorRects(std::slice::from_ref(&raw_rect)) }; } unsafe fn end_render_pass(&mut self) { @@ -782,50 +792,54 @@ impl crate::CommandEncoder for super::CommandEncoder { // All the targets are expected to be in `COLOR_TARGET` state, // but D3D12 has special source/destination states for the resolves. for resolve in self.pass.resolves.iter() { - let mut barrier = d3d12_ty::D3D12_RESOURCE_BARRIER { - Type: d3d12_ty::D3D12_RESOURCE_BARRIER_TYPE_TRANSITION, - Flags: d3d12_ty::D3D12_RESOURCE_BARRIER_FLAG_NONE, - u: unsafe { mem::zeroed() }, - }; - //Note: this assumes `D3D12_RESOURCE_STATE_RENDER_TARGET`. - // If it's not the case, we can include the `TextureUses` in `PassResove`. - unsafe { - *barrier.u.Transition_mut() = d3d12_ty::D3D12_RESOURCE_TRANSITION_BARRIER { - pResource: resolve.src.0.as_mut_ptr(), - Subresource: resolve.src.1, - StateBefore: d3d12_ty::D3D12_RESOURCE_STATE_RENDER_TARGET, - StateAfter: d3d12_ty::D3D12_RESOURCE_STATE_RESOLVE_SOURCE, - } + let barrier = Direct3D12::D3D12_RESOURCE_BARRIER { + Type: Direct3D12::D3D12_RESOURCE_BARRIER_TYPE_TRANSITION, + Flags: Direct3D12::D3D12_RESOURCE_BARRIER_FLAG_NONE, + Anonymous: Direct3D12::D3D12_RESOURCE_BARRIER_0 { + //Note: this assumes `D3D12_RESOURCE_STATE_RENDER_TARGET`. + // If it's not the case, we can include the `TextureUses` in `PassResove`. + Transition: mem::ManuallyDrop::new( + Direct3D12::D3D12_RESOURCE_TRANSITION_BARRIER { + pResource: unsafe { borrow_interface_temporarily(&resolve.src.0) }, + Subresource: resolve.src.1, + StateBefore: Direct3D12::D3D12_RESOURCE_STATE_RENDER_TARGET, + StateAfter: Direct3D12::D3D12_RESOURCE_STATE_RESOLVE_SOURCE, + }, + ), + }, }; self.temp.barriers.push(barrier); - unsafe { - *barrier.u.Transition_mut() = d3d12_ty::D3D12_RESOURCE_TRANSITION_BARRIER { - pResource: resolve.dst.0.as_mut_ptr(), - Subresource: resolve.dst.1, - StateBefore: d3d12_ty::D3D12_RESOURCE_STATE_RENDER_TARGET, - StateAfter: d3d12_ty::D3D12_RESOURCE_STATE_RESOLVE_DEST, - } + let barrier = Direct3D12::D3D12_RESOURCE_BARRIER { + Type: Direct3D12::D3D12_RESOURCE_BARRIER_TYPE_TRANSITION, + Flags: Direct3D12::D3D12_RESOURCE_BARRIER_FLAG_NONE, + Anonymous: Direct3D12::D3D12_RESOURCE_BARRIER_0 { + //Note: this assumes `D3D12_RESOURCE_STATE_RENDER_TARGET`. + // If it's not the case, we can include the `TextureUses` in `PassResolve`. + Transition: mem::ManuallyDrop::new( + Direct3D12::D3D12_RESOURCE_TRANSITION_BARRIER { + pResource: unsafe { borrow_interface_temporarily(&resolve.dst.0) }, + Subresource: resolve.dst.1, + StateBefore: Direct3D12::D3D12_RESOURCE_STATE_RENDER_TARGET, + StateAfter: Direct3D12::D3D12_RESOURCE_STATE_RESOLVE_DEST, + }, + ), + }, }; self.temp.barriers.push(barrier); } if !self.temp.barriers.is_empty() { profiling::scope!("ID3D12GraphicsCommandList::ResourceBarrier"); - unsafe { - list.ResourceBarrier( - self.temp.barriers.len() as u32, - self.temp.barriers.as_ptr(), - ) - }; + unsafe { list.ResourceBarrier(&self.temp.barriers) }; } for resolve in self.pass.resolves.iter() { profiling::scope!("ID3D12GraphicsCommandList::ResolveSubresource"); unsafe { list.ResolveSubresource( - resolve.dst.0.as_mut_ptr(), + &resolve.dst.0, resolve.dst.1, - resolve.src.0.as_mut_ptr(), + &resolve.src.0, resolve.src.1, resolve.format, ) @@ -834,17 +848,12 @@ impl crate::CommandEncoder for super::CommandEncoder { // Flip all the barriers to reverse, back into `COLOR_TARGET`. for barrier in self.temp.barriers.iter_mut() { - let transition = unsafe { barrier.u.Transition_mut() }; + let transition = unsafe { &mut *barrier.Anonymous.Transition }; mem::swap(&mut transition.StateBefore, &mut transition.StateAfter); } if !self.temp.barriers.is_empty() { profiling::scope!("ID3D12GraphicsCommandList::ResourceBarrier"); - unsafe { - list.ResourceBarrier( - self.temp.barriers.len() as u32, - self.temp.barriers.as_ptr(), - ) - }; + unsafe { list.ResourceBarrier(&self.temp.barriers) }; } } @@ -886,7 +895,9 @@ impl crate::CommandEncoder for super::CommandEncoder { { self.pass.root_elements[root_index] = super::RootElement::DynamicOffsetBuffer { kind, - address: gpu_base + offset as d3d12::GpuAddress, + address: Direct3D12::D3D12_GPU_DESCRIPTOR_HANDLE { + ptr: gpu_base.ptr + offset as u64, + }, }; root_index += 1; } @@ -927,7 +938,7 @@ impl crate::CommandEncoder for super::CommandEncoder { self.list .as_ref() .unwrap() - .SetMarker(0, wide_label.as_ptr().cast(), size) + .SetMarker(0, Some(wide_label.as_ptr().cast()), size) }; } unsafe fn begin_debug_marker(&mut self, group_label: &str) { @@ -936,7 +947,7 @@ impl crate::CommandEncoder for super::CommandEncoder { self.list .as_ref() .unwrap() - .BeginEvent(0, wide_label.as_ptr().cast(), size) + .BeginEvent(0, Some(wide_label.as_ptr().cast()), size) }; } unsafe fn end_debug_marker(&mut self) { @@ -944,15 +955,15 @@ impl crate::CommandEncoder for super::CommandEncoder { } unsafe fn set_render_pipeline(&mut self, pipeline: &super::RenderPipeline) { - let list = self.list.as_ref().unwrap().clone(); + let list = self.list.clone().unwrap(); if self.pass.layout.signature != pipeline.layout.signature { // D3D12 requires full reset on signature change - list.set_graphics_root_signature(&pipeline.layout.signature); + unsafe { list.SetGraphicsRootSignature(pipeline.layout.signature.as_ref()) }; self.reset_signature(&pipeline.layout); }; - list.set_pipeline_state(&pipeline.raw); + unsafe { list.SetPipelineState(&pipeline.raw) }; unsafe { list.IASetPrimitiveTopology(pipeline.topology) }; for (index, (vb, &stride)) in self @@ -976,11 +987,13 @@ impl crate::CommandEncoder for super::CommandEncoder { binding: crate::BufferBinding<'a, super::Buffer>, format: wgt::IndexFormat, ) { - self.list.as_ref().unwrap().set_index_buffer( - binding.resolve_address(), - binding.resolve_size() as u32, - auxil::dxgi::conv::map_index_format(format), - ); + let ibv = Direct3D12::D3D12_INDEX_BUFFER_VIEW { + BufferLocation: binding.resolve_address(), + SizeInBytes: binding.resolve_size() as u32, + Format: auxil::dxgi::conv::map_index_format(format), + }; + + unsafe { self.list.as_ref().unwrap().IASetIndexBuffer(Some(&ibv)) } } unsafe fn set_vertex_buffer<'a>( &mut self, @@ -994,7 +1007,7 @@ impl crate::CommandEncoder for super::CommandEncoder { } unsafe fn set_viewport(&mut self, rect: &crate::Rect, depth_range: Range) { - let raw_vp = d3d12_ty::D3D12_VIEWPORT { + let raw_vp = Direct3D12::D3D12_VIEWPORT { TopLeftX: rect.x, TopLeftY: rect.y, Width: rect.w, @@ -1002,22 +1015,32 @@ impl crate::CommandEncoder for super::CommandEncoder { MinDepth: depth_range.start, MaxDepth: depth_range.end, }; - unsafe { self.list.as_ref().unwrap().RSSetViewports(1, &raw_vp) }; + unsafe { + self.list + .as_ref() + .unwrap() + .RSSetViewports(std::slice::from_ref(&raw_vp)) + } } unsafe fn set_scissor_rect(&mut self, rect: &crate::Rect) { - let raw_rect = d3d12_ty::D3D12_RECT { + let raw_rect = Foundation::RECT { left: rect.x as i32, top: rect.y as i32, right: (rect.x + rect.w) as i32, bottom: (rect.y + rect.h) as i32, }; - unsafe { self.list.as_ref().unwrap().RSSetScissorRects(1, &raw_rect) }; + unsafe { + self.list + .as_ref() + .unwrap() + .RSSetScissorRects(std::slice::from_ref(&raw_rect)) + } } unsafe fn set_stencil_reference(&mut self, value: u32) { - self.list.as_ref().unwrap().set_stencil_reference(value); + unsafe { self.list.as_ref().unwrap().OMSetStencilRef(value) } } unsafe fn set_blend_constants(&mut self, color: &[f32; 4]) { - self.list.as_ref().unwrap().set_blend_factor(*color); + unsafe { self.list.as_ref().unwrap().OMSetBlendFactor(Some(color)) } } unsafe fn draw( @@ -1028,12 +1051,14 @@ impl crate::CommandEncoder for super::CommandEncoder { instance_count: u32, ) { unsafe { self.prepare_draw(first_vertex as i32, first_instance) }; - self.list.as_ref().unwrap().draw( - vertex_count, - instance_count, - first_vertex, - first_instance, - ); + unsafe { + self.list.as_ref().unwrap().DrawInstanced( + vertex_count, + instance_count, + first_vertex, + first_instance, + ) + } } unsafe fn draw_indexed( &mut self, @@ -1044,13 +1069,15 @@ impl crate::CommandEncoder for super::CommandEncoder { instance_count: u32, ) { unsafe { self.prepare_draw(base_vertex, first_instance) }; - self.list.as_ref().unwrap().draw_indexed( - index_count, - instance_count, - first_index, - base_vertex, - first_instance, - ); + unsafe { + self.list.as_ref().unwrap().DrawIndexedInstanced( + index_count, + instance_count, + first_index, + base_vertex, + first_instance, + ) + } } unsafe fn draw_indirect( &mut self, @@ -1061,14 +1088,14 @@ impl crate::CommandEncoder for super::CommandEncoder { unsafe { self.prepare_draw(0, 0) }; unsafe { self.list.as_ref().unwrap().ExecuteIndirect( - self.shared.cmd_signatures.draw.as_mut_ptr(), + &self.shared.cmd_signatures.draw, draw_count, - buffer.resource.as_mut_ptr(), + &buffer.resource, offset, - ptr::null_mut(), + None, 0, ) - }; + } } unsafe fn draw_indexed_indirect( &mut self, @@ -1079,14 +1106,14 @@ impl crate::CommandEncoder for super::CommandEncoder { unsafe { self.prepare_draw(0, 0) }; unsafe { self.list.as_ref().unwrap().ExecuteIndirect( - self.shared.cmd_signatures.draw_indexed.as_mut_ptr(), + &self.shared.cmd_signatures.draw_indexed, draw_count, - buffer.resource.as_mut_ptr(), + &buffer.resource, offset, - ptr::null_mut(), + None, 0, ) - }; + } } unsafe fn draw_indirect_count( &mut self, @@ -1099,14 +1126,14 @@ impl crate::CommandEncoder for super::CommandEncoder { unsafe { self.prepare_draw(0, 0) }; unsafe { self.list.as_ref().unwrap().ExecuteIndirect( - self.shared.cmd_signatures.draw.as_mut_ptr(), + &self.shared.cmd_signatures.draw, max_count, - buffer.resource.as_mut_ptr(), + &buffer.resource, offset, - count_buffer.resource.as_mut_ptr(), + &count_buffer.resource, count_offset, ) - }; + } } unsafe fn draw_indexed_indirect_count( &mut self, @@ -1119,14 +1146,14 @@ impl crate::CommandEncoder for super::CommandEncoder { unsafe { self.prepare_draw(0, 0) }; unsafe { self.list.as_ref().unwrap().ExecuteIndirect( - self.shared.cmd_signatures.draw_indexed.as_mut_ptr(), + &self.shared.cmd_signatures.draw_indexed, max_count, - buffer.resource.as_mut_ptr(), + &buffer.resource, offset, - count_buffer.resource.as_mut_ptr(), + &count_buffer.resource, count_offset, ) - }; + } } // compute @@ -1154,34 +1181,35 @@ impl crate::CommandEncoder for super::CommandEncoder { } unsafe fn set_compute_pipeline(&mut self, pipeline: &super::ComputePipeline) { - let list = self.list.as_ref().unwrap().clone(); + let list = self.list.clone().unwrap(); if self.pass.layout.signature != pipeline.layout.signature { // D3D12 requires full reset on signature change - list.set_compute_root_signature(&pipeline.layout.signature); + unsafe { list.SetComputeRootSignature(pipeline.layout.signature.as_ref()) }; self.reset_signature(&pipeline.layout); }; - list.set_pipeline_state(&pipeline.raw); + unsafe { list.SetPipelineState(&pipeline.raw) } } - unsafe fn dispatch(&mut self, count: [u32; 3]) { + unsafe fn dispatch(&mut self, count @ [x, y, z]: [u32; 3]) { self.prepare_dispatch(count); - self.list.as_ref().unwrap().dispatch(count); + unsafe { self.list.as_ref().unwrap().Dispatch(x, y, z) } } + unsafe fn dispatch_indirect(&mut self, buffer: &super::Buffer, offset: wgt::BufferAddress) { self.prepare_dispatch([0; 3]); //TODO: update special constants indirectly unsafe { self.list.as_ref().unwrap().ExecuteIndirect( - self.shared.cmd_signatures.dispatch.as_mut_ptr(), + &self.shared.cmd_signatures.dispatch, 1, - buffer.resource.as_mut_ptr(), + &buffer.resource, offset, - ptr::null_mut(), + None, 0, ) - }; + } } unsafe fn build_acceleration_structures<'a, T>( diff --git a/wgpu-hal/src/dx12/conv.rs b/wgpu-hal/src/dx12/conv.rs index b09ea7608..8e60f6e06 100644 --- a/wgpu-hal/src/dx12/conv.rs +++ b/wgpu-hal/src/dx12/conv.rs @@ -1,79 +1,75 @@ -use std::iter; -use winapi::{ - shared::minwindef::BOOL, - um::{d3d12 as d3d12_ty, d3dcommon}, -}; +use windows::Win32::Graphics::{Direct3D, Direct3D12}; pub fn map_buffer_usage_to_resource_flags( usage: crate::BufferUses, -) -> d3d12_ty::D3D12_RESOURCE_FLAGS { - let mut flags = 0; +) -> Direct3D12::D3D12_RESOURCE_FLAGS { + let mut flags = Direct3D12::D3D12_RESOURCE_FLAG_NONE; if usage.contains(crate::BufferUses::STORAGE_READ_WRITE) { - flags |= d3d12_ty::D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS; + flags |= Direct3D12::D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS; } flags } -pub fn map_texture_dimension(dim: wgt::TextureDimension) -> d3d12_ty::D3D12_RESOURCE_DIMENSION { +pub fn map_texture_dimension(dim: wgt::TextureDimension) -> Direct3D12::D3D12_RESOURCE_DIMENSION { match dim { - wgt::TextureDimension::D1 => d3d12_ty::D3D12_RESOURCE_DIMENSION_TEXTURE1D, - wgt::TextureDimension::D2 => d3d12_ty::D3D12_RESOURCE_DIMENSION_TEXTURE2D, - wgt::TextureDimension::D3 => d3d12_ty::D3D12_RESOURCE_DIMENSION_TEXTURE3D, + wgt::TextureDimension::D1 => Direct3D12::D3D12_RESOURCE_DIMENSION_TEXTURE1D, + wgt::TextureDimension::D2 => Direct3D12::D3D12_RESOURCE_DIMENSION_TEXTURE2D, + wgt::TextureDimension::D3 => Direct3D12::D3D12_RESOURCE_DIMENSION_TEXTURE3D, } } pub fn map_texture_usage_to_resource_flags( usage: crate::TextureUses, -) -> d3d12_ty::D3D12_RESOURCE_FLAGS { - let mut flags = 0; +) -> Direct3D12::D3D12_RESOURCE_FLAGS { + let mut flags = Direct3D12::D3D12_RESOURCE_FLAG_NONE; if usage.contains(crate::TextureUses::COLOR_TARGET) { - flags |= d3d12_ty::D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET; + flags |= Direct3D12::D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET; } if usage.intersects( crate::TextureUses::DEPTH_STENCIL_READ | crate::TextureUses::DEPTH_STENCIL_WRITE, ) { - flags |= d3d12_ty::D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL; + flags |= Direct3D12::D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL; if !usage.contains(crate::TextureUses::RESOURCE) { - flags |= d3d12_ty::D3D12_RESOURCE_FLAG_DENY_SHADER_RESOURCE; + flags |= Direct3D12::D3D12_RESOURCE_FLAG_DENY_SHADER_RESOURCE; } } if usage.contains(crate::TextureUses::STORAGE_READ_WRITE) { - flags |= d3d12_ty::D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS; + flags |= Direct3D12::D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS; } flags } -pub fn map_address_mode(mode: wgt::AddressMode) -> d3d12_ty::D3D12_TEXTURE_ADDRESS_MODE { +pub fn map_address_mode(mode: wgt::AddressMode) -> Direct3D12::D3D12_TEXTURE_ADDRESS_MODE { use wgt::AddressMode as Am; match mode { - Am::Repeat => d3d12_ty::D3D12_TEXTURE_ADDRESS_MODE_WRAP, - Am::MirrorRepeat => d3d12_ty::D3D12_TEXTURE_ADDRESS_MODE_MIRROR, - Am::ClampToEdge => d3d12_ty::D3D12_TEXTURE_ADDRESS_MODE_CLAMP, - Am::ClampToBorder => d3d12_ty::D3D12_TEXTURE_ADDRESS_MODE_BORDER, - //Am::MirrorClamp => d3d12_ty::D3D12_TEXTURE_ADDRESS_MODE_MIRROR_ONCE, + Am::Repeat => Direct3D12::D3D12_TEXTURE_ADDRESS_MODE_WRAP, + Am::MirrorRepeat => Direct3D12::D3D12_TEXTURE_ADDRESS_MODE_MIRROR, + Am::ClampToEdge => Direct3D12::D3D12_TEXTURE_ADDRESS_MODE_CLAMP, + Am::ClampToBorder => Direct3D12::D3D12_TEXTURE_ADDRESS_MODE_BORDER, + //Am::MirrorClamp => Direct3D12::D3D12_TEXTURE_ADDRESS_MODE_MIRROR_ONCE, } } -pub fn map_filter_mode(mode: wgt::FilterMode) -> d3d12_ty::D3D12_FILTER_TYPE { +pub fn map_filter_mode(mode: wgt::FilterMode) -> Direct3D12::D3D12_FILTER_TYPE { match mode { - wgt::FilterMode::Nearest => d3d12_ty::D3D12_FILTER_TYPE_POINT, - wgt::FilterMode::Linear => d3d12_ty::D3D12_FILTER_TYPE_LINEAR, + wgt::FilterMode::Nearest => Direct3D12::D3D12_FILTER_TYPE_POINT, + wgt::FilterMode::Linear => Direct3D12::D3D12_FILTER_TYPE_LINEAR, } } -pub fn map_comparison(func: wgt::CompareFunction) -> d3d12_ty::D3D12_COMPARISON_FUNC { +pub fn map_comparison(func: wgt::CompareFunction) -> Direct3D12::D3D12_COMPARISON_FUNC { use wgt::CompareFunction as Cf; match func { - Cf::Never => d3d12_ty::D3D12_COMPARISON_FUNC_NEVER, - Cf::Less => d3d12_ty::D3D12_COMPARISON_FUNC_LESS, - Cf::LessEqual => d3d12_ty::D3D12_COMPARISON_FUNC_LESS_EQUAL, - Cf::Equal => d3d12_ty::D3D12_COMPARISON_FUNC_EQUAL, - Cf::GreaterEqual => d3d12_ty::D3D12_COMPARISON_FUNC_GREATER_EQUAL, - Cf::Greater => d3d12_ty::D3D12_COMPARISON_FUNC_GREATER, - Cf::NotEqual => d3d12_ty::D3D12_COMPARISON_FUNC_NOT_EQUAL, - Cf::Always => d3d12_ty::D3D12_COMPARISON_FUNC_ALWAYS, + Cf::Never => Direct3D12::D3D12_COMPARISON_FUNC_NEVER, + Cf::Less => Direct3D12::D3D12_COMPARISON_FUNC_LESS, + Cf::LessEqual => Direct3D12::D3D12_COMPARISON_FUNC_LESS_EQUAL, + Cf::Equal => Direct3D12::D3D12_COMPARISON_FUNC_EQUAL, + Cf::GreaterEqual => Direct3D12::D3D12_COMPARISON_FUNC_GREATER_EQUAL, + Cf::Greater => Direct3D12::D3D12_COMPARISON_FUNC_GREATER, + Cf::NotEqual => Direct3D12::D3D12_COMPARISON_FUNC_NOT_EQUAL, + Cf::Always => Direct3D12::D3D12_COMPARISON_FUNC_ALWAYS, } } @@ -86,71 +82,67 @@ pub fn map_border_color(border_color: Option) -> [f32; } } -pub fn map_visibility(visibility: wgt::ShaderStages) -> d3d12::ShaderVisibility { +pub fn map_visibility(visibility: wgt::ShaderStages) -> Direct3D12::D3D12_SHADER_VISIBILITY { match visibility { - wgt::ShaderStages::VERTEX => d3d12::ShaderVisibility::VS, - wgt::ShaderStages::FRAGMENT => d3d12::ShaderVisibility::PS, - _ => d3d12::ShaderVisibility::All, + wgt::ShaderStages::VERTEX => Direct3D12::D3D12_SHADER_VISIBILITY_VERTEX, + wgt::ShaderStages::FRAGMENT => Direct3D12::D3D12_SHADER_VISIBILITY_PIXEL, + _ => Direct3D12::D3D12_SHADER_VISIBILITY_ALL, } } -pub fn map_binding_type(ty: &wgt::BindingType) -> d3d12::DescriptorRangeType { +pub fn map_binding_type(ty: &wgt::BindingType) -> Direct3D12::D3D12_DESCRIPTOR_RANGE_TYPE { use wgt::BindingType as Bt; match *ty { - Bt::Sampler { .. } => d3d12::DescriptorRangeType::Sampler, + Bt::Sampler { .. } => Direct3D12::D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER, Bt::Buffer { ty: wgt::BufferBindingType::Uniform, .. - } => d3d12::DescriptorRangeType::CBV, + } => Direct3D12::D3D12_DESCRIPTOR_RANGE_TYPE_CBV, Bt::Buffer { ty: wgt::BufferBindingType::Storage { read_only: true }, .. } - | Bt::Texture { .. } => d3d12::DescriptorRangeType::SRV, + | Bt::Texture { .. } => Direct3D12::D3D12_DESCRIPTOR_RANGE_TYPE_SRV, Bt::Buffer { ty: wgt::BufferBindingType::Storage { read_only: false }, .. } - | Bt::StorageTexture { .. } => d3d12::DescriptorRangeType::UAV, + | Bt::StorageTexture { .. } => Direct3D12::D3D12_DESCRIPTOR_RANGE_TYPE_UAV, Bt::AccelerationStructure => todo!(), } } -pub fn map_label(name: &str) -> Vec { - name.encode_utf16().chain(iter::once(0)).collect() -} - -pub fn map_buffer_usage_to_state(usage: crate::BufferUses) -> d3d12_ty::D3D12_RESOURCE_STATES { +pub fn map_buffer_usage_to_state(usage: crate::BufferUses) -> Direct3D12::D3D12_RESOURCE_STATES { use crate::BufferUses as Bu; - let mut state = d3d12_ty::D3D12_RESOURCE_STATE_COMMON; + let mut state = Direct3D12::D3D12_RESOURCE_STATE_COMMON; if usage.intersects(Bu::COPY_SRC) { - state |= d3d12_ty::D3D12_RESOURCE_STATE_COPY_SOURCE; + state |= Direct3D12::D3D12_RESOURCE_STATE_COPY_SOURCE; } if usage.intersects(Bu::COPY_DST) { - state |= d3d12_ty::D3D12_RESOURCE_STATE_COPY_DEST; + state |= Direct3D12::D3D12_RESOURCE_STATE_COPY_DEST; } if usage.intersects(Bu::INDEX) { - state |= d3d12_ty::D3D12_RESOURCE_STATE_INDEX_BUFFER; + state |= Direct3D12::D3D12_RESOURCE_STATE_INDEX_BUFFER; } if usage.intersects(Bu::VERTEX | Bu::UNIFORM) { - state |= d3d12_ty::D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER; + state |= Direct3D12::D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER; } if usage.intersects(Bu::STORAGE_READ_WRITE) { - state |= d3d12_ty::D3D12_RESOURCE_STATE_UNORDERED_ACCESS; + state |= Direct3D12::D3D12_RESOURCE_STATE_UNORDERED_ACCESS; } else if usage.intersects(Bu::STORAGE_READ) { - state |= d3d12_ty::D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE - | d3d12_ty::D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE; + state |= Direct3D12::D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE + | Direct3D12::D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE; } if usage.intersects(Bu::INDIRECT) { - state |= d3d12_ty::D3D12_RESOURCE_STATE_INDIRECT_ARGUMENT; + state |= Direct3D12::D3D12_RESOURCE_STATE_INDIRECT_ARGUMENT; } state } -pub fn map_texture_usage_to_state(usage: crate::TextureUses) -> d3d12_ty::D3D12_RESOURCE_STATES { +pub fn map_texture_usage_to_state(usage: crate::TextureUses) -> Direct3D12::D3D12_RESOURCE_STATES { use crate::TextureUses as Tu; - let mut state = d3d12_ty::D3D12_RESOURCE_STATE_COMMON; + let mut state = Direct3D12::D3D12_RESOURCE_STATE_COMMON; //Note: `RESOLVE_SOURCE` and `RESOLVE_DEST` are not used here //Note: `PRESENT` is the same as `COMMON` if usage == crate::TextureUses::UNINITIALIZED { @@ -158,26 +150,26 @@ pub fn map_texture_usage_to_state(usage: crate::TextureUses) -> d3d12_ty::D3D12_ } if usage.intersects(Tu::COPY_SRC) { - state |= d3d12_ty::D3D12_RESOURCE_STATE_COPY_SOURCE; + state |= Direct3D12::D3D12_RESOURCE_STATE_COPY_SOURCE; } if usage.intersects(Tu::COPY_DST) { - state |= d3d12_ty::D3D12_RESOURCE_STATE_COPY_DEST; + state |= Direct3D12::D3D12_RESOURCE_STATE_COPY_DEST; } if usage.intersects(Tu::RESOURCE) { - state |= d3d12_ty::D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE - | d3d12_ty::D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE; + state |= Direct3D12::D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE + | Direct3D12::D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE; } if usage.intersects(Tu::COLOR_TARGET) { - state |= d3d12_ty::D3D12_RESOURCE_STATE_RENDER_TARGET; + state |= Direct3D12::D3D12_RESOURCE_STATE_RENDER_TARGET; } if usage.intersects(Tu::DEPTH_STENCIL_READ) { - state |= d3d12_ty::D3D12_RESOURCE_STATE_DEPTH_READ; + state |= Direct3D12::D3D12_RESOURCE_STATE_DEPTH_READ; } if usage.intersects(Tu::DEPTH_STENCIL_WRITE) { - state |= d3d12_ty::D3D12_RESOURCE_STATE_DEPTH_WRITE; + state |= Direct3D12::D3D12_RESOURCE_STATE_DEPTH_WRITE; } if usage.intersects(Tu::STORAGE_READ | Tu::STORAGE_READ_WRITE) { - state |= d3d12_ty::D3D12_RESOURCE_STATE_UNORDERED_ACCESS; + state |= Direct3D12::D3D12_RESOURCE_STATE_UNORDERED_ACCESS; } state } @@ -185,37 +177,37 @@ pub fn map_texture_usage_to_state(usage: crate::TextureUses) -> d3d12_ty::D3D12_ pub fn map_topology( topology: wgt::PrimitiveTopology, ) -> ( - d3d12_ty::D3D12_PRIMITIVE_TOPOLOGY_TYPE, - d3d12_ty::D3D12_PRIMITIVE_TOPOLOGY, + Direct3D12::D3D12_PRIMITIVE_TOPOLOGY_TYPE, + Direct3D::D3D_PRIMITIVE_TOPOLOGY, ) { match topology { wgt::PrimitiveTopology::PointList => ( - d3d12_ty::D3D12_PRIMITIVE_TOPOLOGY_TYPE_POINT, - d3dcommon::D3D_PRIMITIVE_TOPOLOGY_POINTLIST, + Direct3D12::D3D12_PRIMITIVE_TOPOLOGY_TYPE_POINT, + Direct3D::D3D_PRIMITIVE_TOPOLOGY_POINTLIST, ), wgt::PrimitiveTopology::LineList => ( - d3d12_ty::D3D12_PRIMITIVE_TOPOLOGY_TYPE_LINE, - d3dcommon::D3D_PRIMITIVE_TOPOLOGY_LINELIST, + Direct3D12::D3D12_PRIMITIVE_TOPOLOGY_TYPE_LINE, + Direct3D::D3D_PRIMITIVE_TOPOLOGY_LINELIST, ), wgt::PrimitiveTopology::LineStrip => ( - d3d12_ty::D3D12_PRIMITIVE_TOPOLOGY_TYPE_LINE, - d3dcommon::D3D_PRIMITIVE_TOPOLOGY_LINESTRIP, + Direct3D12::D3D12_PRIMITIVE_TOPOLOGY_TYPE_LINE, + Direct3D::D3D_PRIMITIVE_TOPOLOGY_LINESTRIP, ), wgt::PrimitiveTopology::TriangleList => ( - d3d12_ty::D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE, - d3dcommon::D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST, + Direct3D12::D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE, + Direct3D::D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST, ), wgt::PrimitiveTopology::TriangleStrip => ( - d3d12_ty::D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE, - d3dcommon::D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP, + Direct3D12::D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE, + Direct3D::D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP, ), } } -pub fn map_polygon_mode(mode: wgt::PolygonMode) -> d3d12_ty::D3D12_FILL_MODE { +pub fn map_polygon_mode(mode: wgt::PolygonMode) -> Direct3D12::D3D12_FILL_MODE { match mode { - wgt::PolygonMode::Fill => d3d12_ty::D3D12_FILL_MODE_SOLID, - wgt::PolygonMode::Line => d3d12_ty::D3D12_FILL_MODE_WIREFRAME, + wgt::PolygonMode::Fill => Direct3D12::D3D12_FILL_MODE_SOLID, + wgt::PolygonMode::Line => Direct3D12::D3D12_FILL_MODE_WIREFRAME, wgt::PolygonMode::Point => panic!( "{:?} is not enabled for this backend", wgt::Features::POLYGON_MODE_POINT @@ -227,32 +219,32 @@ pub fn map_polygon_mode(mode: wgt::PolygonMode) -> d3d12_ty::D3D12_FILL_MODE { /// (see ). /// Therefore this function takes an additional `is_alpha` argument /// which if set will return an equivalent `_ALPHA` factor. -fn map_blend_factor(factor: wgt::BlendFactor, is_alpha: bool) -> d3d12_ty::D3D12_BLEND { +fn map_blend_factor(factor: wgt::BlendFactor, is_alpha: bool) -> Direct3D12::D3D12_BLEND { use wgt::BlendFactor as Bf; match factor { - Bf::Zero => d3d12_ty::D3D12_BLEND_ZERO, - Bf::One => d3d12_ty::D3D12_BLEND_ONE, - Bf::Src if is_alpha => d3d12_ty::D3D12_BLEND_SRC_ALPHA, - Bf::Src => d3d12_ty::D3D12_BLEND_SRC_COLOR, - Bf::OneMinusSrc if is_alpha => d3d12_ty::D3D12_BLEND_INV_SRC_ALPHA, - Bf::OneMinusSrc => d3d12_ty::D3D12_BLEND_INV_SRC_COLOR, - Bf::Dst if is_alpha => d3d12_ty::D3D12_BLEND_DEST_ALPHA, - Bf::Dst => d3d12_ty::D3D12_BLEND_DEST_COLOR, - Bf::OneMinusDst if is_alpha => d3d12_ty::D3D12_BLEND_INV_DEST_ALPHA, - Bf::OneMinusDst => d3d12_ty::D3D12_BLEND_INV_DEST_COLOR, - Bf::SrcAlpha => d3d12_ty::D3D12_BLEND_SRC_ALPHA, - Bf::OneMinusSrcAlpha => d3d12_ty::D3D12_BLEND_INV_SRC_ALPHA, - Bf::DstAlpha => d3d12_ty::D3D12_BLEND_DEST_ALPHA, - Bf::OneMinusDstAlpha => d3d12_ty::D3D12_BLEND_INV_DEST_ALPHA, - Bf::Constant => d3d12_ty::D3D12_BLEND_BLEND_FACTOR, - Bf::OneMinusConstant => d3d12_ty::D3D12_BLEND_INV_BLEND_FACTOR, - Bf::SrcAlphaSaturated => d3d12_ty::D3D12_BLEND_SRC_ALPHA_SAT, - Bf::Src1 if is_alpha => d3d12_ty::D3D12_BLEND_SRC1_ALPHA, - Bf::Src1 => d3d12_ty::D3D12_BLEND_SRC1_COLOR, - Bf::OneMinusSrc1 if is_alpha => d3d12_ty::D3D12_BLEND_INV_SRC1_ALPHA, - Bf::OneMinusSrc1 => d3d12_ty::D3D12_BLEND_INV_SRC1_COLOR, - Bf::Src1Alpha => d3d12_ty::D3D12_BLEND_SRC1_ALPHA, - Bf::OneMinusSrc1Alpha => d3d12_ty::D3D12_BLEND_INV_SRC1_ALPHA, + Bf::Zero => Direct3D12::D3D12_BLEND_ZERO, + Bf::One => Direct3D12::D3D12_BLEND_ONE, + Bf::Src if is_alpha => Direct3D12::D3D12_BLEND_SRC_ALPHA, + Bf::Src => Direct3D12::D3D12_BLEND_SRC_COLOR, + Bf::OneMinusSrc if is_alpha => Direct3D12::D3D12_BLEND_INV_SRC_ALPHA, + Bf::OneMinusSrc => Direct3D12::D3D12_BLEND_INV_SRC_COLOR, + Bf::Dst if is_alpha => Direct3D12::D3D12_BLEND_DEST_ALPHA, + Bf::Dst => Direct3D12::D3D12_BLEND_DEST_COLOR, + Bf::OneMinusDst if is_alpha => Direct3D12::D3D12_BLEND_INV_DEST_ALPHA, + Bf::OneMinusDst => Direct3D12::D3D12_BLEND_INV_DEST_COLOR, + Bf::SrcAlpha => Direct3D12::D3D12_BLEND_SRC_ALPHA, + Bf::OneMinusSrcAlpha => Direct3D12::D3D12_BLEND_INV_SRC_ALPHA, + Bf::DstAlpha => Direct3D12::D3D12_BLEND_DEST_ALPHA, + Bf::OneMinusDstAlpha => Direct3D12::D3D12_BLEND_INV_DEST_ALPHA, + Bf::Constant => Direct3D12::D3D12_BLEND_BLEND_FACTOR, + Bf::OneMinusConstant => Direct3D12::D3D12_BLEND_INV_BLEND_FACTOR, + Bf::SrcAlphaSaturated => Direct3D12::D3D12_BLEND_SRC_ALPHA_SAT, + Bf::Src1 if is_alpha => Direct3D12::D3D12_BLEND_SRC1_ALPHA, + Bf::Src1 => Direct3D12::D3D12_BLEND_SRC1_COLOR, + Bf::OneMinusSrc1 if is_alpha => Direct3D12::D3D12_BLEND_INV_SRC1_ALPHA, + Bf::OneMinusSrc1 => Direct3D12::D3D12_BLEND_INV_SRC1_COLOR, + Bf::Src1Alpha => Direct3D12::D3D12_BLEND_SRC1_ALPHA, + Bf::OneMinusSrc1Alpha => Direct3D12::D3D12_BLEND_INV_SRC1_ALPHA, } } @@ -260,16 +252,16 @@ fn map_blend_component( component: &wgt::BlendComponent, is_alpha: bool, ) -> ( - d3d12_ty::D3D12_BLEND_OP, - d3d12_ty::D3D12_BLEND, - d3d12_ty::D3D12_BLEND, + Direct3D12::D3D12_BLEND_OP, + Direct3D12::D3D12_BLEND, + Direct3D12::D3D12_BLEND, ) { let raw_op = match component.operation { - wgt::BlendOperation::Add => d3d12_ty::D3D12_BLEND_OP_ADD, - wgt::BlendOperation::Subtract => d3d12_ty::D3D12_BLEND_OP_SUBTRACT, - wgt::BlendOperation::ReverseSubtract => d3d12_ty::D3D12_BLEND_OP_REV_SUBTRACT, - wgt::BlendOperation::Min => d3d12_ty::D3D12_BLEND_OP_MIN, - wgt::BlendOperation::Max => d3d12_ty::D3D12_BLEND_OP_MAX, + wgt::BlendOperation::Add => Direct3D12::D3D12_BLEND_OP_ADD, + wgt::BlendOperation::Subtract => Direct3D12::D3D12_BLEND_OP_SUBTRACT, + wgt::BlendOperation::ReverseSubtract => Direct3D12::D3D12_BLEND_OP_REV_SUBTRACT, + wgt::BlendOperation::Min => Direct3D12::D3D12_BLEND_OP_MIN, + wgt::BlendOperation::Max => Direct3D12::D3D12_BLEND_OP_MAX, }; let raw_src = map_blend_factor(component.src_factor, is_alpha); let raw_dst = map_blend_factor(component.dst_factor, is_alpha); @@ -278,21 +270,22 @@ fn map_blend_component( pub fn map_render_targets( color_targets: &[Option], -) -> [d3d12_ty::D3D12_RENDER_TARGET_BLEND_DESC; - d3d12_ty::D3D12_SIMULTANEOUS_RENDER_TARGET_COUNT as usize] { - let dummy_target = d3d12_ty::D3D12_RENDER_TARGET_BLEND_DESC { - BlendEnable: 0, - LogicOpEnable: 0, - SrcBlend: d3d12_ty::D3D12_BLEND_ZERO, - DestBlend: d3d12_ty::D3D12_BLEND_ZERO, - BlendOp: d3d12_ty::D3D12_BLEND_OP_ADD, - SrcBlendAlpha: d3d12_ty::D3D12_BLEND_ZERO, - DestBlendAlpha: d3d12_ty::D3D12_BLEND_ZERO, - BlendOpAlpha: d3d12_ty::D3D12_BLEND_OP_ADD, - LogicOp: d3d12_ty::D3D12_LOGIC_OP_CLEAR, +) -> [Direct3D12::D3D12_RENDER_TARGET_BLEND_DESC; + Direct3D12::D3D12_SIMULTANEOUS_RENDER_TARGET_COUNT as usize] { + let dummy_target = Direct3D12::D3D12_RENDER_TARGET_BLEND_DESC { + BlendEnable: false.into(), + LogicOpEnable: false.into(), + SrcBlend: Direct3D12::D3D12_BLEND_ZERO, + DestBlend: Direct3D12::D3D12_BLEND_ZERO, + BlendOp: Direct3D12::D3D12_BLEND_OP_ADD, + SrcBlendAlpha: Direct3D12::D3D12_BLEND_ZERO, + DestBlendAlpha: Direct3D12::D3D12_BLEND_ZERO, + BlendOpAlpha: Direct3D12::D3D12_BLEND_OP_ADD, + LogicOp: Direct3D12::D3D12_LOGIC_OP_CLEAR, RenderTargetWriteMask: 0, }; - let mut raw_targets = [dummy_target; d3d12_ty::D3D12_SIMULTANEOUS_RENDER_TARGET_COUNT as usize]; + let mut raw_targets = + [dummy_target; Direct3D12::D3D12_SIMULTANEOUS_RENDER_TARGET_COUNT as usize]; for (raw, ct) in raw_targets.iter_mut().zip(color_targets.iter()) { if let Some(ct) = ct.as_ref() { @@ -300,7 +293,7 @@ pub fn map_render_targets( if let Some(ref blend) = ct.blend { let (color_op, color_src, color_dst) = map_blend_component(&blend.color, false); let (alpha_op, alpha_src, alpha_dst) = map_blend_component(&blend.alpha, true); - raw.BlendEnable = 1; + raw.BlendEnable = true.into(); raw.BlendOp = color_op; raw.SrcBlend = color_src; raw.DestBlend = color_dst; @@ -314,22 +307,22 @@ pub fn map_render_targets( raw_targets } -fn map_stencil_op(op: wgt::StencilOperation) -> d3d12_ty::D3D12_STENCIL_OP { +fn map_stencil_op(op: wgt::StencilOperation) -> Direct3D12::D3D12_STENCIL_OP { use wgt::StencilOperation as So; match op { - So::Keep => d3d12_ty::D3D12_STENCIL_OP_KEEP, - So::Zero => d3d12_ty::D3D12_STENCIL_OP_ZERO, - So::Replace => d3d12_ty::D3D12_STENCIL_OP_REPLACE, - So::IncrementClamp => d3d12_ty::D3D12_STENCIL_OP_INCR_SAT, - So::IncrementWrap => d3d12_ty::D3D12_STENCIL_OP_INCR, - So::DecrementClamp => d3d12_ty::D3D12_STENCIL_OP_DECR_SAT, - So::DecrementWrap => d3d12_ty::D3D12_STENCIL_OP_DECR, - So::Invert => d3d12_ty::D3D12_STENCIL_OP_INVERT, + So::Keep => Direct3D12::D3D12_STENCIL_OP_KEEP, + So::Zero => Direct3D12::D3D12_STENCIL_OP_ZERO, + So::Replace => Direct3D12::D3D12_STENCIL_OP_REPLACE, + So::IncrementClamp => Direct3D12::D3D12_STENCIL_OP_INCR_SAT, + So::IncrementWrap => Direct3D12::D3D12_STENCIL_OP_INCR, + So::DecrementClamp => Direct3D12::D3D12_STENCIL_OP_DECR_SAT, + So::DecrementWrap => Direct3D12::D3D12_STENCIL_OP_DECR, + So::Invert => Direct3D12::D3D12_STENCIL_OP_INVERT, } } -fn map_stencil_face(face: &wgt::StencilFaceState) -> d3d12_ty::D3D12_DEPTH_STENCILOP_DESC { - d3d12_ty::D3D12_DEPTH_STENCILOP_DESC { +fn map_stencil_face(face: &wgt::StencilFaceState) -> Direct3D12::D3D12_DEPTH_STENCILOP_DESC { + Direct3D12::D3D12_DEPTH_STENCILOP_DESC { StencilFailOp: map_stencil_op(face.fail_op), StencilDepthFailOp: map_stencil_op(face.depth_fail_op), StencilPassOp: map_stencil_op(face.pass_op), @@ -337,16 +330,16 @@ fn map_stencil_face(face: &wgt::StencilFaceState) -> d3d12_ty::D3D12_DEPTH_STENC } } -pub fn map_depth_stencil(ds: &wgt::DepthStencilState) -> d3d12_ty::D3D12_DEPTH_STENCIL_DESC { - d3d12_ty::D3D12_DEPTH_STENCIL_DESC { - DepthEnable: BOOL::from(ds.is_depth_enabled()), +pub fn map_depth_stencil(ds: &wgt::DepthStencilState) -> Direct3D12::D3D12_DEPTH_STENCIL_DESC { + Direct3D12::D3D12_DEPTH_STENCIL_DESC { + DepthEnable: ds.is_depth_enabled().into(), DepthWriteMask: if ds.depth_write_enabled { - d3d12_ty::D3D12_DEPTH_WRITE_MASK_ALL + Direct3D12::D3D12_DEPTH_WRITE_MASK_ALL } else { - d3d12_ty::D3D12_DEPTH_WRITE_MASK_ZERO + Direct3D12::D3D12_DEPTH_WRITE_MASK_ZERO }, DepthFunc: map_comparison(ds.depth_compare), - StencilEnable: BOOL::from(ds.stencil.is_enabled()), + StencilEnable: ds.stencil.is_enabled().into(), StencilReadMask: ds.stencil.read_mask as u8, StencilWriteMask: ds.stencil.write_mask as u8, FrontFace: map_stencil_face(&ds.stencil.front), diff --git a/wgpu-hal/src/dx12/descriptor.rs b/wgpu-hal/src/dx12/descriptor.rs index 6f7afe807..ebb42ddcd 100644 --- a/wgpu-hal/src/dx12/descriptor.rs +++ b/wgpu-hal/src/dx12/descriptor.rs @@ -1,16 +1,18 @@ -use super::null_comptr_check; -use crate::auxil::dxgi::result::HResult as _; +use std::fmt; + use bit_set::BitSet; use parking_lot::Mutex; use range_alloc::RangeAllocator; -use std::fmt; +use windows::Win32::Graphics::Direct3D12; + +use crate::auxil::dxgi::result::HResult as _; const HEAP_SIZE_FIXED: usize = 64; #[derive(Copy, Clone)] pub(super) struct DualHandle { - cpu: d3d12::CpuDescriptor, - pub gpu: d3d12::GpuDescriptor, + cpu: Direct3D12::D3D12_CPU_DESCRIPTOR_HANDLE, + pub gpu: Direct3D12::D3D12_GPU_DESCRIPTOR_HANDLE, /// How large the block allocated to this handle is. count: u64, } @@ -28,8 +30,8 @@ impl fmt::Debug for DualHandle { type DescriptorIndex = u64; pub(super) struct GeneralHeap { - pub raw: d3d12::DescriptorHeap, - ty: d3d12::DescriptorHeapType, + pub raw: Direct3D12::ID3D12DescriptorHeap, + ty: Direct3D12::D3D12_DESCRIPTOR_HEAP_TYPE, handle_size: u64, total_handles: u64, start: DualHandle, @@ -38,32 +40,30 @@ pub(super) struct GeneralHeap { impl GeneralHeap { pub(super) fn new( - device: d3d12::Device, - ty: d3d12::DescriptorHeapType, + device: &Direct3D12::ID3D12Device, + ty: Direct3D12::D3D12_DESCRIPTOR_HEAP_TYPE, total_handles: u64, ) -> Result { let raw = { profiling::scope!("ID3D12Device::CreateDescriptorHeap"); - device - .create_descriptor_heap( - total_handles as u32, - ty, - d3d12::DescriptorHeapFlags::SHADER_VISIBLE, - 0, - ) + let desc = Direct3D12::D3D12_DESCRIPTOR_HEAP_DESC { + Type: ty, + NumDescriptors: total_handles as u32, + Flags: Direct3D12::D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE, + NodeMask: 0, + }; + unsafe { device.CreateDescriptorHeap::(&desc) } .into_device_result("Descriptor heap creation")? }; - null_comptr_check(&raw)?; - Ok(Self { raw: raw.clone(), ty, - handle_size: device.get_descriptor_increment_size(ty) as u64, + handle_size: unsafe { device.GetDescriptorHandleIncrementSize(ty) } as u64, total_handles, start: DualHandle { - cpu: raw.start_cpu_descriptor(), - gpu: raw.start_gpu_descriptor(), + cpu: unsafe { raw.GetCPUDescriptorHandleForHeapStart() }, + gpu: unsafe { raw.GetGPUDescriptorHandleForHeapStart() }, count: 0, }, ranges: Mutex::new(RangeAllocator::new(0..total_handles)), @@ -79,14 +79,14 @@ impl GeneralHeap { } } - fn cpu_descriptor_at(&self, index: u64) -> d3d12::CpuDescriptor { - d3d12::CpuDescriptor { + fn cpu_descriptor_at(&self, index: u64) -> Direct3D12::D3D12_CPU_DESCRIPTOR_HANDLE { + Direct3D12::D3D12_CPU_DESCRIPTOR_HANDLE { ptr: self.start.cpu.ptr + (self.handle_size * index) as usize, } } - fn gpu_descriptor_at(&self, index: u64) -> d3d12::GpuDescriptor { - d3d12::GpuDescriptor { + fn gpu_descriptor_at(&self, index: u64) -> Direct3D12::D3D12_GPU_DESCRIPTOR_HANDLE { + Direct3D12::D3D12_GPU_DESCRIPTOR_HANDLE { ptr: self.start.gpu.ptr + self.handle_size * index, } } @@ -109,41 +109,42 @@ impl GeneralHeap { /// Fixed-size free-list allocator for CPU descriptors. struct FixedSizeHeap { - _raw: d3d12::DescriptorHeap, + _raw: Direct3D12::ID3D12DescriptorHeap, /// Bit flag representation of available handles in the heap. /// /// 0 - Occupied /// 1 - free availability: u64, handle_size: usize, - start: d3d12::CpuDescriptor, + start: Direct3D12::D3D12_CPU_DESCRIPTOR_HANDLE, } impl FixedSizeHeap { fn new( - device: &d3d12::Device, - ty: d3d12::DescriptorHeapType, + device: &Direct3D12::ID3D12Device, + ty: Direct3D12::D3D12_DESCRIPTOR_HEAP_TYPE, ) -> Result { - let heap = device - .create_descriptor_heap( - HEAP_SIZE_FIXED as _, - ty, - d3d12::DescriptorHeapFlags::empty(), - 0, - ) - .into_device_result("Descriptor heap creation")?; - - null_comptr_check(&heap)?; + let desc = Direct3D12::D3D12_DESCRIPTOR_HEAP_DESC { + Type: ty, + NumDescriptors: HEAP_SIZE_FIXED as u32, + Flags: Direct3D12::D3D12_DESCRIPTOR_HEAP_FLAG_NONE, + NodeMask: 0, + }; + let heap = + unsafe { device.CreateDescriptorHeap::(&desc) } + .into_device_result("Descriptor heap creation")?; Ok(Self { - handle_size: device.get_descriptor_increment_size(ty) as _, + handle_size: unsafe { device.GetDescriptorHandleIncrementSize(ty) } as usize, availability: !0, // all free! - start: heap.start_cpu_descriptor(), + start: unsafe { heap.GetCPUDescriptorHandleForHeapStart() }, _raw: heap, }) } - fn alloc_handle(&mut self) -> Result { + fn alloc_handle( + &mut self, + ) -> Result { // Find first free slot. let slot = self.availability.trailing_zeros() as usize; if slot >= HEAP_SIZE_FIXED { @@ -153,12 +154,12 @@ impl FixedSizeHeap { // Set the slot as occupied. self.availability ^= 1 << slot; - Ok(d3d12::CpuDescriptor { + Ok(Direct3D12::D3D12_CPU_DESCRIPTOR_HANDLE { ptr: self.start.ptr + self.handle_size * slot, }) } - fn free_handle(&mut self, handle: d3d12::CpuDescriptor) { + fn free_handle(&mut self, handle: Direct3D12::D3D12_CPU_DESCRIPTOR_HANDLE) { let slot = (handle.ptr - self.start.ptr) / self.handle_size; assert!(slot < HEAP_SIZE_FIXED); assert_eq!(self.availability & (1 << slot), 0); @@ -172,7 +173,7 @@ impl FixedSizeHeap { #[derive(Clone, Copy)] pub(super) struct Handle { - pub raw: d3d12::CpuDescriptor, + pub raw: Direct3D12::D3D12_CPU_DESCRIPTOR_HANDLE, heap_index: usize, } @@ -186,14 +187,17 @@ impl fmt::Debug for Handle { } pub(super) struct CpuPool { - device: d3d12::Device, - ty: d3d12::DescriptorHeapType, + device: Direct3D12::ID3D12Device, + ty: Direct3D12::D3D12_DESCRIPTOR_HEAP_TYPE, heaps: Vec, available_heap_indices: BitSet, } impl CpuPool { - pub(super) fn new(device: d3d12::Device, ty: d3d12::DescriptorHeapType) -> Self { + pub(super) fn new( + device: Direct3D12::ID3D12Device, + ty: Direct3D12::D3D12_DESCRIPTOR_HEAP_TYPE, + ) -> Self { Self { device, ty, @@ -234,13 +238,13 @@ impl CpuPool { } pub(super) struct CpuHeapInner { - pub _raw: d3d12::DescriptorHeap, - pub stage: Vec, + pub _raw: Direct3D12::ID3D12DescriptorHeap, + pub stage: Vec, } pub(super) struct CpuHeap { pub inner: Mutex, - start: d3d12::CpuDescriptor, + start: Direct3D12::D3D12_CPU_DESCRIPTOR_HANDLE, handle_size: u32, total: u32, } @@ -250,30 +254,33 @@ unsafe impl Sync for CpuHeap {} impl CpuHeap { pub(super) fn new( - device: d3d12::Device, - ty: d3d12::DescriptorHeapType, + device: &Direct3D12::ID3D12Device, + ty: Direct3D12::D3D12_DESCRIPTOR_HEAP_TYPE, total: u32, ) -> Result { - let handle_size = device.get_descriptor_increment_size(ty); - let raw = device - .create_descriptor_heap(total, ty, d3d12::DescriptorHeapFlags::empty(), 0) + let handle_size = unsafe { device.GetDescriptorHandleIncrementSize(ty) }; + let desc = Direct3D12::D3D12_DESCRIPTOR_HEAP_DESC { + Type: ty, + NumDescriptors: total, + Flags: Direct3D12::D3D12_DESCRIPTOR_HEAP_FLAG_NONE, + NodeMask: 0, + }; + let raw = unsafe { device.CreateDescriptorHeap::(&desc) } .into_device_result("CPU descriptor heap creation")?; - null_comptr_check(&raw)?; - Ok(Self { inner: Mutex::new(CpuHeapInner { _raw: raw.clone(), stage: Vec::new(), }), - start: raw.start_cpu_descriptor(), + start: unsafe { raw.GetCPUDescriptorHandleForHeapStart() }, handle_size, total, }) } - pub(super) fn at(&self, index: u32) -> d3d12::CpuDescriptor { - d3d12::CpuDescriptor { + pub(super) fn at(&self, index: u32) -> Direct3D12::D3D12_CPU_DESCRIPTOR_HANDLE { + Direct3D12::D3D12_CPU_DESCRIPTOR_HANDLE { ptr: self.start.ptr + (self.handle_size * index) as usize, } } @@ -290,7 +297,7 @@ impl fmt::Debug for CpuHeap { } pub(super) unsafe fn upload( - device: d3d12::Device, + device: Direct3D12::ID3D12Device, src: &CpuHeapInner, dst: &GeneralHeap, dummy_copy_counts: &[u32], @@ -301,11 +308,11 @@ pub(super) unsafe fn upload( device.CopyDescriptors( 1, &dst.cpu_descriptor_at(index), - &count, + Some(&count), count, src.stage.as_ptr(), - dummy_copy_counts.as_ptr(), - dst.ty as u32, + Some(dummy_copy_counts.as_ptr()), + dst.ty, ) }; Ok(dst.at(index, count as u64)) diff --git a/wgpu-hal/src/dx12/device.rs b/wgpu-hal/src/dx12/device.rs index 8cfd8deae..dd6816031 100644 --- a/wgpu-hal/src/dx12/device.rs +++ b/wgpu-hal/src/dx12/device.rs @@ -1,12 +1,3 @@ -use crate::{ - auxil::{self, dxgi::result::HResult as _}, - dx12::shader_compilation, - DeviceError, -}; -use d3d12::ComPtr; - -use super::{conv, descriptor, null_comptr_check, view}; -use parking_lot::Mutex; use std::{ ffi, mem, num::NonZeroU32, @@ -14,10 +5,21 @@ use std::{ sync::Arc, time::{Duration, Instant}, }; -use winapi::{ - shared::{dxgiformat, dxgitype, minwindef::BOOL, winerror}, - um::{d3d12 as d3d12_ty, synchapi, winbase}, - Interface, + +use parking_lot::Mutex; +use windows::{ + core::Interface as _, + Win32::{ + Foundation, + Graphics::{Direct3D12, Dxgi}, + System::Threading, + }, +}; + +use super::{conv, descriptor, D3D12Lib}; +use crate::{ + auxil::{self, dxgi::result::HResult}, + dx12::{borrow_optional_interface_temporarily, shader_compilation, Event}, }; // this has to match Naga's HLSL backend, and also needs to be null-terminated @@ -25,156 +27,181 @@ const NAGA_LOCATION_SEMANTIC: &[u8] = b"LOC\0"; impl super::Device { pub(super) fn new( - raw: d3d12::Device, - present_queue: d3d12::CommandQueue, + raw: Direct3D12::ID3D12Device, + present_queue: Direct3D12::ID3D12CommandQueue, limits: &wgt::Limits, memory_hints: &wgt::MemoryHints, private_caps: super::PrivateCapabilities, - library: &Arc, + library: &Arc, dxc_container: Option>, - ) -> Result { - let mem_allocator = if private_caps.suballocation_supported { - super::suballocation::create_allocator_wrapper(&raw, memory_hints)? - } else { - None - }; + ) -> Result { + let mem_allocator = super::suballocation::create_allocator_wrapper(&raw, memory_hints)?; - let mut idle_fence = d3d12::Fence::null(); - let hr = unsafe { + let idle_fence: Direct3D12::ID3D12Fence = unsafe { profiling::scope!("ID3D12Device::CreateFence"); - raw.CreateFence( - 0, - d3d12_ty::D3D12_FENCE_FLAG_NONE, - &d3d12_ty::ID3D12Fence::uuidof(), - idle_fence.mut_void(), - ) + raw.CreateFence(0, Direct3D12::D3D12_FENCE_FLAG_NONE) + } + .into_device_result("Idle fence creation")?; + + let raw_desc = Direct3D12::D3D12_RESOURCE_DESC { + Dimension: Direct3D12::D3D12_RESOURCE_DIMENSION_BUFFER, + Alignment: 0, + Width: super::ZERO_BUFFER_SIZE, + Height: 1, + DepthOrArraySize: 1, + MipLevels: 1, + Format: Dxgi::Common::DXGI_FORMAT_UNKNOWN, + SampleDesc: Dxgi::Common::DXGI_SAMPLE_DESC { + Count: 1, + Quality: 0, + }, + Layout: Direct3D12::D3D12_TEXTURE_LAYOUT_ROW_MAJOR, + Flags: Direct3D12::D3D12_RESOURCE_FLAG_NONE, }; - hr.into_device_result("Idle fence creation")?; - null_comptr_check(&idle_fence)?; + let heap_properties = Direct3D12::D3D12_HEAP_PROPERTIES { + Type: Direct3D12::D3D12_HEAP_TYPE_CUSTOM, + CPUPageProperty: Direct3D12::D3D12_CPU_PAGE_PROPERTY_NOT_AVAILABLE, + MemoryPoolPreference: match private_caps.memory_architecture { + super::MemoryArchitecture::Unified { .. } => Direct3D12::D3D12_MEMORY_POOL_L0, + super::MemoryArchitecture::NonUnified => Direct3D12::D3D12_MEMORY_POOL_L1, + }, + CreationNodeMask: 0, + VisibleNodeMask: 0, + }; - let mut zero_buffer = d3d12::Resource::null(); + profiling::scope!("Zero Buffer Allocation"); + let mut zero_buffer = None::; unsafe { - let raw_desc = d3d12_ty::D3D12_RESOURCE_DESC { - Dimension: d3d12_ty::D3D12_RESOURCE_DIMENSION_BUFFER, - Alignment: 0, - Width: super::ZERO_BUFFER_SIZE, - Height: 1, - DepthOrArraySize: 1, - MipLevels: 1, - Format: dxgiformat::DXGI_FORMAT_UNKNOWN, - SampleDesc: dxgitype::DXGI_SAMPLE_DESC { - Count: 1, - Quality: 0, - }, - Layout: d3d12_ty::D3D12_TEXTURE_LAYOUT_ROW_MAJOR, - Flags: d3d12_ty::D3D12_RESOURCE_FLAG_NONE, - }; - - let heap_properties = d3d12_ty::D3D12_HEAP_PROPERTIES { - Type: d3d12_ty::D3D12_HEAP_TYPE_CUSTOM, - CPUPageProperty: d3d12_ty::D3D12_CPU_PAGE_PROPERTY_NOT_AVAILABLE, - MemoryPoolPreference: match private_caps.memory_architecture { - super::MemoryArchitecture::Unified { .. } => d3d12_ty::D3D12_MEMORY_POOL_L0, - super::MemoryArchitecture::NonUnified => d3d12_ty::D3D12_MEMORY_POOL_L1, - }, - CreationNodeMask: 0, - VisibleNodeMask: 0, - }; - - profiling::scope!("Zero Buffer Allocation"); raw.CreateCommittedResource( &heap_properties, - d3d12_ty::D3D12_HEAP_FLAG_NONE, + Direct3D12::D3D12_HEAP_FLAG_NONE, &raw_desc, - d3d12_ty::D3D12_RESOURCE_STATE_COMMON, - ptr::null(), - &d3d12_ty::ID3D12Resource::uuidof(), - zero_buffer.mut_void(), + Direct3D12::D3D12_RESOURCE_STATE_COMMON, + None, + &mut zero_buffer, ) - .into_device_result("Zero buffer creation")?; + } + .into_device_result("Zero buffer creation")?; - null_comptr_check(&zero_buffer)?; + let zero_buffer = zero_buffer.ok_or(crate::DeviceError::ResourceCreationFailed)?; - // Note: without `D3D12_HEAP_FLAG_CREATE_NOT_ZEROED` - // this resource is zeroed by default. - }; + // Note: without `D3D12_HEAP_FLAG_CREATE_NOT_ZEROED` + // this resource is zeroed by default. // maximum number of CBV/SRV/UAV descriptors in heap for Tier 1 let capacity_views = limits.max_non_sampler_bindings as u64; let capacity_samplers = 2_048; + fn create_command_signature( + raw: &Direct3D12::ID3D12Device, + byte_stride: usize, + arguments: &[Direct3D12::D3D12_INDIRECT_ARGUMENT_DESC], + node_mask: u32, + ) -> Result { + let mut signature = None; + unsafe { + raw.CreateCommandSignature( + &Direct3D12::D3D12_COMMAND_SIGNATURE_DESC { + ByteStride: byte_stride as u32, + NumArgumentDescs: arguments.len() as u32, + pArgumentDescs: arguments.as_ptr(), + NodeMask: node_mask, + }, + None, + &mut signature, + ) + } + .into_device_result("Command signature creation")?; + signature.ok_or(crate::DeviceError::ResourceCreationFailed) + } + let shared = super::DeviceShared { zero_buffer, cmd_signatures: super::CommandSignatures { - draw: raw - .create_command_signature( - d3d12::RootSignature::null(), - &[d3d12::IndirectArgument::draw()], - mem::size_of::() as u32, - 0, - ) - .into_device_result("Command (draw) signature creation")?, - draw_indexed: raw - .create_command_signature( - d3d12::RootSignature::null(), - &[d3d12::IndirectArgument::draw_indexed()], - mem::size_of::() as u32, - 0, - ) - .into_device_result("Command (draw_indexed) signature creation")?, - dispatch: raw - .create_command_signature( - d3d12::RootSignature::null(), - &[d3d12::IndirectArgument::dispatch()], - mem::size_of::() as u32, - 0, - ) - .into_device_result("Command (dispatch) signature creation")?, + draw: create_command_signature( + &raw, + mem::size_of::(), + &[Direct3D12::D3D12_INDIRECT_ARGUMENT_DESC { + Type: Direct3D12::D3D12_INDIRECT_ARGUMENT_TYPE_DRAW, + ..Default::default() + }], + 0, + )?, + draw_indexed: create_command_signature( + &raw, + mem::size_of::(), + &[Direct3D12::D3D12_INDIRECT_ARGUMENT_DESC { + Type: Direct3D12::D3D12_INDIRECT_ARGUMENT_TYPE_DRAW_INDEXED, + ..Default::default() + }], + 0, + )?, + dispatch: create_command_signature( + &raw, + mem::size_of::(), + &[Direct3D12::D3D12_INDIRECT_ARGUMENT_DESC { + Type: Direct3D12::D3D12_INDIRECT_ARGUMENT_TYPE_DISPATCH, + ..Default::default() + }], + 0, + )?, }, heap_views: descriptor::GeneralHeap::new( - raw.clone(), - d3d12::DescriptorHeapType::CbvSrvUav, + &raw, + Direct3D12::D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, capacity_views, )?, heap_samplers: descriptor::GeneralHeap::new( - raw.clone(), - d3d12::DescriptorHeapType::Sampler, + &raw, + Direct3D12::D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, capacity_samplers, )?, }; - let mut rtv_pool = descriptor::CpuPool::new(raw.clone(), d3d12::DescriptorHeapType::Rtv); + let mut rtv_pool = + descriptor::CpuPool::new(raw.clone(), Direct3D12::D3D12_DESCRIPTOR_HEAP_TYPE_RTV); let null_rtv_handle = rtv_pool.alloc_handle()?; // A null pResource is used to initialize a null descriptor, // which guarantees D3D11-like null binding behavior (reading 0s, writes are discarded) - raw.create_render_target_view( - ComPtr::null(), - &d3d12::RenderTargetViewDesc::texture_2d(dxgiformat::DXGI_FORMAT_R8G8B8A8_UNORM, 0, 0), - null_rtv_handle.raw, - ); + unsafe { + raw.CreateRenderTargetView( + None, + Some(&Direct3D12::D3D12_RENDER_TARGET_VIEW_DESC { + Format: Dxgi::Common::DXGI_FORMAT_R8G8B8A8_UNORM, + ViewDimension: Direct3D12::D3D12_RTV_DIMENSION_TEXTURE2D, + Anonymous: Direct3D12::D3D12_RENDER_TARGET_VIEW_DESC_0 { + Texture2D: Direct3D12::D3D12_TEX2D_RTV { + MipSlice: 0, + PlaneSlice: 0, + }, + }, + }), + null_rtv_handle.raw, + ) + }; Ok(super::Device { raw: raw.clone(), present_queue, idler: super::Idler { fence: idle_fence, - event: d3d12::Event::create(false, false), + event: Event::create(false, false)?, }, private_caps, shared: Arc::new(shared), rtv_pool: Mutex::new(rtv_pool), dsv_pool: Mutex::new(descriptor::CpuPool::new( raw.clone(), - d3d12::DescriptorHeapType::Dsv, + Direct3D12::D3D12_DESCRIPTOR_HEAP_TYPE_DSV, )), srv_uav_pool: Mutex::new(descriptor::CpuPool::new( raw.clone(), - d3d12::DescriptorHeapType::CbvSrvUav, + Direct3D12::D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, )), sampler_pool: Mutex::new(descriptor::CpuPool::new( raw, - d3d12::DescriptorHeapType::Sampler, + Direct3D12::D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, )), library: Arc::clone(library), #[cfg(feature = "renderdoc")] @@ -189,20 +216,22 @@ impl super::Device { // Blocks until the dedicated present queue is finished with all of its work. // // Once this method completes, the surface is able to be resized or deleted. - pub(super) unsafe fn wait_for_present_queue_idle(&self) -> Result<(), DeviceError> { - let cur_value = self.idler.fence.get_value(); + pub(super) unsafe fn wait_for_present_queue_idle(&self) -> Result<(), crate::DeviceError> { + let cur_value = unsafe { self.idler.fence.GetCompletedValue() }; if cur_value == !0 { - return Err(DeviceError::Lost); + return Err(crate::DeviceError::Lost); } let value = cur_value + 1; - self.present_queue.signal(&self.idler.fence, value); - let hr = self - .idler - .fence - .set_event_on_completion(self.idler.event, value); + unsafe { self.present_queue.Signal(&self.idler.fence, value) } + .into_device_result("Signal")?; + let hr = unsafe { + self.idler + .fence + .SetEventOnCompletion(value, self.idler.event.0) + }; hr.into_device_result("Set event")?; - unsafe { synchapi::WaitForSingleObject(self.idler.event.0, winbase::INFINITE) }; + unsafe { Threading::WaitForSingleObject(self.idler.event.0, Threading::INFINITE) }; Ok(()) } @@ -308,16 +337,16 @@ impl super::Device { result } - pub fn raw_device(&self) -> &d3d12::Device { + pub fn raw_device(&self) -> &Direct3D12::ID3D12Device { &self.raw } - pub fn raw_queue(&self) -> &d3d12::CommandQueue { + pub fn raw_queue(&self) -> &Direct3D12::ID3D12CommandQueue { &self.present_queue } pub unsafe fn texture_from_raw( - resource: d3d12::Resource, + resource: Direct3D12::ID3D12Resource, format: wgt::TextureFormat, dimension: wgt::TextureDimension, size: wgt::Extent3d, @@ -336,7 +365,7 @@ impl super::Device { } pub unsafe fn buffer_from_raw( - resource: d3d12::Resource, + resource: Direct3D12::ID3D12Resource, size: wgt::BufferAddress, ) -> super::Buffer { super::Buffer { @@ -350,45 +379,45 @@ impl super::Device { impl crate::Device for super::Device { type A = super::Api; - unsafe fn exit(mut self, _queue: super::Queue) { + unsafe fn exit(self, _queue: super::Queue) { self.rtv_pool.lock().free_handle(self.null_rtv_handle); - self.mem_allocator = None; } unsafe fn create_buffer( &self, desc: &crate::BufferDescriptor, - ) -> Result { - let mut resource = d3d12::Resource::null(); + ) -> Result { + let mut resource = None; let mut size = desc.size; if desc.usage.contains(crate::BufferUses::UNIFORM) { - let align_mask = d3d12_ty::D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT as u64 - 1; + let align_mask = Direct3D12::D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT as u64 - 1; size = ((size - 1) | align_mask) + 1; } - let raw_desc = d3d12_ty::D3D12_RESOURCE_DESC { - Dimension: d3d12_ty::D3D12_RESOURCE_DIMENSION_BUFFER, + let raw_desc = Direct3D12::D3D12_RESOURCE_DESC { + Dimension: Direct3D12::D3D12_RESOURCE_DIMENSION_BUFFER, Alignment: 0, Width: size, Height: 1, DepthOrArraySize: 1, MipLevels: 1, - Format: dxgiformat::DXGI_FORMAT_UNKNOWN, - SampleDesc: dxgitype::DXGI_SAMPLE_DESC { + Format: Dxgi::Common::DXGI_FORMAT_UNKNOWN, + SampleDesc: Dxgi::Common::DXGI_SAMPLE_DESC { Count: 1, Quality: 0, }, - Layout: d3d12_ty::D3D12_TEXTURE_LAYOUT_ROW_MAJOR, + Layout: Direct3D12::D3D12_TEXTURE_LAYOUT_ROW_MAJOR, Flags: conv::map_buffer_usage_to_resource_flags(desc.usage), }; - let (hr, allocation) = + let allocation = super::suballocation::create_buffer_resource(self, desc, raw_desc, &mut resource)?; - hr.into_device_result("Buffer creation")?; + let resource = resource.ok_or(crate::DeviceError::ResourceCreationFailed)?; + if let Some(label) = desc.label { - let cwstr = conv::map_label(label); - unsafe { resource.SetName(cwstr.as_ptr()) }; + unsafe { resource.SetName(&windows::core::HSTRING::from(label)) } + .into_device_result("SetName")?; } self.counters.buffers.add(1); @@ -401,17 +430,12 @@ impl crate::Device for super::Device { } unsafe fn destroy_buffer(&self, mut buffer: super::Buffer) { - // Only happens when it's using the windows_rs feature and there's an allocation + // Always Some except on Intel Xe: https://github.com/gfx-rs/wgpu/issues/3552 if let Some(alloc) = buffer.allocation.take() { // Resource should be dropped before free suballocation drop(buffer); - super::suballocation::free_buffer_allocation( - self, - alloc, - // SAFETY: for allocations to exist, the allocator must exist - unsafe { self.mem_allocator.as_ref().unwrap_unchecked() }, - ); + super::suballocation::free_buffer_allocation(self, alloc, &self.mem_allocator); } self.counters.buffers.sub(1); @@ -421,11 +445,10 @@ impl crate::Device for super::Device { &self, buffer: &super::Buffer, range: crate::MemoryRange, - ) -> Result { + ) -> Result { let mut ptr = ptr::null_mut(); // TODO: 0 for subresource should be fine here until map and unmap buffer is subresource aware? - let hr = unsafe { (*buffer.resource).Map(0, ptr::null(), &mut ptr) }; - hr.into_device_result("Map buffer")?; + unsafe { buffer.resource.Map(0, None, Some(&mut ptr)) }.into_device_result("Map buffer")?; Ok(crate::BufferMapping { ptr: ptr::NonNull::new(unsafe { ptr.offset(range.start as isize).cast::() }) @@ -437,7 +460,7 @@ impl crate::Device for super::Device { } unsafe fn unmap_buffer(&self, buffer: &super::Buffer) { - unsafe { (*buffer.resource).Unmap(0, ptr::null()) }; + unsafe { buffer.resource.Unmap(0, None) }; } unsafe fn flush_mapped_ranges(&self, _buffer: &super::Buffer, _ranges: I) {} @@ -446,12 +469,12 @@ impl crate::Device for super::Device { unsafe fn create_texture( &self, desc: &crate::TextureDescriptor, - ) -> Result { + ) -> Result { use super::suballocation::create_texture_resource; - let mut resource = d3d12::Resource::null(); + let mut resource = None; - let raw_desc = d3d12_ty::D3D12_RESOURCE_DESC { + let raw_desc = Direct3D12::D3D12_RESOURCE_DESC { Dimension: conv::map_texture_dimension(desc.dimension), Alignment: 0, Width: desc.size.width as u64, @@ -464,20 +487,20 @@ impl crate::Device for super::Device { !desc.view_formats.is_empty(), self.private_caps.casting_fully_typed_format_supported, ), - SampleDesc: dxgitype::DXGI_SAMPLE_DESC { + SampleDesc: Dxgi::Common::DXGI_SAMPLE_DESC { Count: desc.sample_count, Quality: 0, }, - Layout: d3d12_ty::D3D12_TEXTURE_LAYOUT_UNKNOWN, + Layout: Direct3D12::D3D12_TEXTURE_LAYOUT_UNKNOWN, Flags: conv::map_texture_usage_to_resource_flags(desc.usage), }; - let (hr, allocation) = create_texture_resource(self, desc, raw_desc, &mut resource)?; + let allocation = create_texture_resource(self, desc, raw_desc, &mut resource)?; - hr.into_device_result("Texture creation")?; + let resource = resource.ok_or(crate::DeviceError::ResourceCreationFailed)?; if let Some(label) = desc.label { - let cwstr = conv::map_label(label); - unsafe { resource.SetName(cwstr.as_ptr()) }; + unsafe { resource.SetName(&windows::core::HSTRING::from(label)) } + .into_device_result("SetName")?; } self.counters.textures.add(1); @@ -502,7 +525,7 @@ impl crate::Device for super::Device { self, alloc, // SAFETY: for allocations to exist, the allocator must exist - unsafe { self.mem_allocator.as_ref().unwrap_unchecked() }, + &self.mem_allocator, ); } @@ -513,7 +536,7 @@ impl crate::Device for super::Device { &self, texture: &super::Texture, desc: &crate::TextureViewDescriptor, - ) -> Result { + ) -> Result { let view_desc = desc.to_internal(texture); self.counters.texture_views.add(1); @@ -531,8 +554,8 @@ impl crate::Device for super::Device { let handle = self.srv_uav_pool.lock().alloc_handle()?; unsafe { self.raw.CreateShaderResourceView( - texture.resource.as_mut_ptr(), - &raw_desc, + &texture.resource, + Some(&raw_desc), handle.raw, ) }; @@ -551,9 +574,9 @@ impl crate::Device for super::Device { let handle = self.srv_uav_pool.lock().alloc_handle()?; unsafe { self.raw.CreateUnorderedAccessView( - texture.resource.as_mut_ptr(), - ptr::null_mut(), - &raw_desc, + &texture.resource, + None, + Some(&raw_desc), handle.raw, ); } @@ -568,11 +591,8 @@ impl crate::Device for super::Device { let raw_desc = unsafe { view_desc.to_rtv() }; let handle = self.rtv_pool.lock().alloc_handle()?; unsafe { - self.raw.CreateRenderTargetView( - texture.resource.as_mut_ptr(), - &raw_desc, - handle.raw, - ) + self.raw + .CreateRenderTargetView(&texture.resource, Some(&raw_desc), handle.raw) }; Some(handle) } else { @@ -585,11 +605,8 @@ impl crate::Device for super::Device { let raw_desc = unsafe { view_desc.to_dsv(true) }; let handle = self.dsv_pool.lock().alloc_handle()?; unsafe { - self.raw.CreateDepthStencilView( - texture.resource.as_mut_ptr(), - &raw_desc, - handle.raw, - ) + self.raw + .CreateDepthStencilView(&texture.resource, Some(&raw_desc), handle.raw) }; Some(handle) } else { @@ -602,11 +619,8 @@ impl crate::Device for super::Device { let raw_desc = unsafe { view_desc.to_dsv(false) }; let handle = self.dsv_pool.lock().alloc_handle()?; unsafe { - self.raw.CreateDepthStencilView( - texture.resource.as_mut_ptr(), - &raw_desc, - handle.raw, - ) + self.raw + .CreateDepthStencilView(&texture.resource, Some(&raw_desc), handle.raw) }; Some(handle) } else { @@ -644,38 +658,46 @@ impl crate::Device for super::Device { unsafe fn create_sampler( &self, desc: &crate::SamplerDescriptor, - ) -> Result { + ) -> Result { let handle = self.sampler_pool.lock().alloc_handle()?; let reduction = match desc.compare { - Some(_) => d3d12_ty::D3D12_FILTER_REDUCTION_TYPE_COMPARISON, - None => d3d12_ty::D3D12_FILTER_REDUCTION_TYPE_STANDARD, + Some(_) => Direct3D12::D3D12_FILTER_REDUCTION_TYPE_COMPARISON, + None => Direct3D12::D3D12_FILTER_REDUCTION_TYPE_STANDARD, }; - let mut filter = conv::map_filter_mode(desc.min_filter) << d3d12_ty::D3D12_MIN_FILTER_SHIFT - | conv::map_filter_mode(desc.mag_filter) << d3d12_ty::D3D12_MAG_FILTER_SHIFT - | conv::map_filter_mode(desc.mipmap_filter) << d3d12_ty::D3D12_MIP_FILTER_SHIFT - | reduction << d3d12_ty::D3D12_FILTER_REDUCTION_TYPE_SHIFT; + let mut filter = Direct3D12::D3D12_FILTER( + conv::map_filter_mode(desc.min_filter).0 << Direct3D12::D3D12_MIN_FILTER_SHIFT + | conv::map_filter_mode(desc.mag_filter).0 << Direct3D12::D3D12_MAG_FILTER_SHIFT + | conv::map_filter_mode(desc.mipmap_filter).0 << Direct3D12::D3D12_MIP_FILTER_SHIFT + | reduction.0 << Direct3D12::D3D12_FILTER_REDUCTION_TYPE_SHIFT, + ); if desc.anisotropy_clamp != 1 { - filter |= d3d12_ty::D3D12_FILTER_ANISOTROPIC; + filter.0 |= Direct3D12::D3D12_FILTER_ANISOTROPIC.0; }; let border_color = conv::map_border_color(desc.border_color); - self.raw.create_sampler( - handle.raw, - filter, - [ - conv::map_address_mode(desc.address_modes[0]), - conv::map_address_mode(desc.address_modes[1]), - conv::map_address_mode(desc.address_modes[2]), - ], - 0.0, - desc.anisotropy_clamp as u32, - conv::map_comparison(desc.compare.unwrap_or(wgt::CompareFunction::Always)), - border_color, - desc.lod_clamp.clone(), - ); + unsafe { + self.raw.CreateSampler( + &Direct3D12::D3D12_SAMPLER_DESC { + Filter: filter, + AddressU: conv::map_address_mode(desc.address_modes[0]), + AddressV: conv::map_address_mode(desc.address_modes[1]), + AddressW: conv::map_address_mode(desc.address_modes[2]), + MipLODBias: 0f32, + MaxAnisotropy: desc.anisotropy_clamp as u32, + + ComparisonFunc: conv::map_comparison( + desc.compare.unwrap_or(wgt::CompareFunction::Always), + ), + BorderColor: border_color, + MinLOD: desc.lod_clamp.start, + MaxLOD: desc.lod_clamp.end, + }, + handle.raw, + ) + }; self.counters.samplers.add(1); @@ -690,15 +712,16 @@ impl crate::Device for super::Device { unsafe fn create_command_encoder( &self, desc: &crate::CommandEncoderDescriptor, - ) -> Result { - let allocator = self - .raw - .create_command_allocator(d3d12::CmdListType::Direct) - .into_device_result("Command allocator creation")?; + ) -> Result { + let allocator: Direct3D12::ID3D12CommandAllocator = unsafe { + self.raw + .CreateCommandAllocator(Direct3D12::D3D12_COMMAND_LIST_TYPE_DIRECT) + } + .into_device_result("Command allocator creation")?; if let Some(label) = desc.label { - let cwstr = conv::map_label(label); - unsafe { allocator.SetName(cwstr.as_ptr()) }; + unsafe { allocator.SetName(&windows::core::HSTRING::from(label)) } + .into_device_result("SetName")?; } self.counters.command_encoders.add(1); @@ -723,7 +746,7 @@ impl crate::Device for super::Device { unsafe fn create_bind_group_layout( &self, desc: &crate::BindGroupLayoutDescriptor, - ) -> Result { + ) -> Result { let (mut num_buffer_views, mut num_samplers, mut num_texture_views) = (0, 0, 0); for entry in desc.entries.iter() { let count = entry.count.map_or(1, NonZeroU32::get); @@ -748,8 +771,8 @@ impl crate::Device for super::Device { entries: desc.entries.to_vec(), cpu_heap_views: if num_views != 0 { let heap = descriptor::CpuHeap::new( - self.raw.clone(), - d3d12::DescriptorHeapType::CbvSrvUav, + &self.raw, + Direct3D12::D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, num_views, )?; Some(heap) @@ -758,8 +781,8 @@ impl crate::Device for super::Device { }, cpu_heap_samplers: if num_samplers != 0 { let heap = descriptor::CpuHeap::new( - self.raw.clone(), - d3d12::DescriptorHeapType::Sampler, + &self.raw, + Direct3D12::D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, num_samplers, )?; Some(heap) @@ -777,7 +800,7 @@ impl crate::Device for super::Device { unsafe fn create_pipeline_layout( &self, desc: &crate::PipelineLayoutDescriptor, - ) -> Result { + ) -> Result { use naga::back::hlsl; // Pipeline layouts are implemented as RootSignature for D3D12. // @@ -809,13 +832,6 @@ impl crate::Device for super::Device { // Currently impossible because wgpu-core only re-binds the descriptor sets based // on Vulkan-like layout compatibility rules. - fn native_binding(bt: &hlsl::BindTarget) -> d3d12::Binding { - d3d12::Binding { - space: bt.space as u32, - register: bt.register, - } - } - let mut binding_map = hlsl::BindingMap::default(); let (mut bind_cbv, mut bind_srv, mut bind_uav, mut bind_sampler) = ( hlsl::BindTarget::default(), @@ -838,11 +854,17 @@ impl crate::Device for super::Device { if pc_start != u32::MAX && pc_end != u32::MIN { let parameter_index = parameters.len(); let size = (pc_end - pc_start) / 4; - parameters.push(d3d12::RootParameter::constants( - d3d12::ShaderVisibility::All, - native_binding(&bind_cbv), - size, - )); + parameters.push(Direct3D12::D3D12_ROOT_PARAMETER { + ParameterType: Direct3D12::D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS, + Anonymous: Direct3D12::D3D12_ROOT_PARAMETER_0 { + Constants: Direct3D12::D3D12_ROOT_CONSTANTS { + ShaderRegister: bind_cbv.register, + RegisterSpace: bind_cbv.space as u32, + Num32BitValues: size, + }, + }, + ShaderVisibility: Direct3D12::D3D12_SHADER_VISIBILITY_ALL, + }); let binding = bind_cbv.clone(); bind_cbv.register += 1; root_constant_info = Some(super::RootConstantInfo { @@ -906,10 +928,11 @@ impl crate::Device for super::Device { ref other => conv::map_binding_type(other), }; let bt = match range_ty { - d3d12::DescriptorRangeType::CBV => &mut bind_cbv, - d3d12::DescriptorRangeType::SRV => &mut bind_srv, - d3d12::DescriptorRangeType::UAV => &mut bind_uav, - d3d12::DescriptorRangeType::Sampler => continue, + Direct3D12::D3D12_DESCRIPTOR_RANGE_TYPE_CBV => &mut bind_cbv, + Direct3D12::D3D12_DESCRIPTOR_RANGE_TYPE_SRV => &mut bind_srv, + Direct3D12::D3D12_DESCRIPTOR_RANGE_TYPE_UAV => &mut bind_uav, + Direct3D12::D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER => continue, + _ => todo!(), }; binding_map.insert( @@ -922,19 +945,28 @@ impl crate::Device for super::Device { ..bt.clone() }, ); - ranges.push(d3d12::DescriptorRange::new( - range_ty, - entry.count.map_or(1, |count| count.get()), - native_binding(bt), - d3d12_ty::D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND, - )); + ranges.push(Direct3D12::D3D12_DESCRIPTOR_RANGE { + RangeType: range_ty, + NumDescriptors: entry.count.map_or(1, |count| count.get()), + BaseShaderRegister: bt.register, + RegisterSpace: bt.space as u32, + OffsetInDescriptorsFromTableStart: + Direct3D12::D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND, + }); bt.register += entry.count.map(NonZeroU32::get).unwrap_or(1); } if ranges.len() > range_base { - parameters.push(d3d12::RootParameter::descriptor_table( - conv::map_visibility(visibility_view_static), - &ranges[range_base..], - )); + let range = &ranges[range_base..]; + parameters.push(Direct3D12::D3D12_ROOT_PARAMETER { + ParameterType: Direct3D12::D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE, + Anonymous: Direct3D12::D3D12_ROOT_PARAMETER_0 { + DescriptorTable: Direct3D12::D3D12_ROOT_DESCRIPTOR_TABLE { + NumDescriptorRanges: range.len() as u32, + pDescriptorRanges: range.as_ptr(), + }, + }, + ShaderVisibility: conv::map_visibility(visibility_view_static), + }); info.tables |= super::TableTypes::SRV_CBV_UAV; } @@ -942,7 +974,9 @@ impl crate::Device for super::Device { range_base = ranges.len(); for entry in bgl.entries.iter() { let range_ty = match entry.ty { - wgt::BindingType::Sampler { .. } => d3d12::DescriptorRangeType::Sampler, + wgt::BindingType::Sampler { .. } => { + Direct3D12::D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER + } _ => continue, }; binding_map.insert( @@ -955,19 +989,28 @@ impl crate::Device for super::Device { ..bind_sampler.clone() }, ); - ranges.push(d3d12::DescriptorRange::new( - range_ty, - entry.count.map_or(1, |count| count.get()), - native_binding(&bind_sampler), - d3d12_ty::D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND, - )); + ranges.push(Direct3D12::D3D12_DESCRIPTOR_RANGE { + RangeType: range_ty, + NumDescriptors: entry.count.map_or(1, |count| count.get()), + BaseShaderRegister: bind_sampler.register, + RegisterSpace: bind_sampler.space as u32, + OffsetInDescriptorsFromTableStart: + Direct3D12::D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND, + }); bind_sampler.register += entry.count.map(NonZeroU32::get).unwrap_or(1); } if ranges.len() > range_base { - parameters.push(d3d12::RootParameter::descriptor_table( - conv::map_visibility(visibility_sampler), - &ranges[range_base..], - )); + let range = &ranges[range_base..]; + parameters.push(Direct3D12::D3D12_ROOT_PARAMETER { + ParameterType: Direct3D12::D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE, + Anonymous: Direct3D12::D3D12_ROOT_PARAMETER_0 { + DescriptorTable: Direct3D12::D3D12_ROOT_DESCRIPTOR_TABLE { + NumDescriptorRanges: range.len() as u32, + pDescriptorRanges: range.as_ptr(), + }, + }, + ShaderVisibility: conv::map_visibility(visibility_sampler), + }); info.tables |= super::TableTypes::SAMPLERS; } @@ -986,17 +1029,17 @@ impl crate::Device for super::Device { let (kind, parameter_ty, bt) = match buffer_ty { wgt::BufferBindingType::Uniform => ( super::BufferViewKind::Constant, - d3d12_ty::D3D12_ROOT_PARAMETER_TYPE_CBV, + Direct3D12::D3D12_ROOT_PARAMETER_TYPE_CBV, &mut bind_cbv, ), wgt::BufferBindingType::Storage { read_only: true } => ( super::BufferViewKind::ShaderResource, - d3d12_ty::D3D12_ROOT_PARAMETER_TYPE_SRV, + Direct3D12::D3D12_ROOT_PARAMETER_TYPE_SRV, &mut bind_srv, ), wgt::BufferBindingType::Storage { read_only: false } => ( super::BufferViewKind::UnorderedAccess, - d3d12_ty::D3D12_ROOT_PARAMETER_TYPE_UAV, + Direct3D12::D3D12_ROOT_PARAMETER_TYPE_UAV, &mut bind_uav, ), }; @@ -1013,11 +1056,16 @@ impl crate::Device for super::Device { ); info.dynamic_buffers.push(kind); - parameters.push(d3d12::RootParameter::descriptor( - parameter_ty, - dynamic_buffers_visibility, - native_binding(bt), - )); + parameters.push(Direct3D12::D3D12_ROOT_PARAMETER { + ParameterType: parameter_ty, + Anonymous: Direct3D12::D3D12_ROOT_PARAMETER_0 { + Descriptor: Direct3D12::D3D12_ROOT_DESCRIPTOR { + ShaderRegister: bt.register, + RegisterSpace: bt.space as u32, + }, + }, + ShaderVisibility: dynamic_buffers_visibility, + }); bt.register += entry.count.map_or(1, NonZeroU32::get); } @@ -1033,11 +1081,17 @@ impl crate::Device for super::Device { | crate::PipelineLayoutFlags::NUM_WORK_GROUPS, ) { let parameter_index = parameters.len(); - parameters.push(d3d12::RootParameter::constants( - d3d12::ShaderVisibility::All, // really needed for VS and CS only - native_binding(&bind_cbv), - 3, // 0 = first_vertex, 1 = first_instance, 2 = other - )); + parameters.push(Direct3D12::D3D12_ROOT_PARAMETER { + ParameterType: Direct3D12::D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS, + Anonymous: Direct3D12::D3D12_ROOT_PARAMETER_0 { + Constants: Direct3D12::D3D12_ROOT_CONSTANTS { + ShaderRegister: bind_cbv.register, + RegisterSpace: bind_cbv.space as u32, + Num32BitValues: 3, // 0 = first_vertex, 1 = first_instance, 2 = other + }, + }, + ShaderVisibility: Direct3D12::D3D12_SHADER_VISIBILITY_ALL, // really needed for VS and CS only, + }); let binding = bind_cbv.clone(); bind_cbv.register += 1; (Some(parameter_index as u32), Some(binding)) @@ -1045,43 +1099,29 @@ impl crate::Device for super::Device { (None, None) }; - let (blob, error) = self - .library - .serialize_root_signature( - d3d12::RootSignatureVersion::V1_0, - ¶meters, - &[], - d3d12::RootSignatureFlags::ALLOW_IA_INPUT_LAYOUT, - ) - .map_err(|e| { - log::error!("Unable to find serialization function: {:?}", e); - DeviceError::Lost - })? - .into_device_result("Root signature serialization")?; + let blob = self.library.serialize_root_signature( + Direct3D12::D3D_ROOT_SIGNATURE_VERSION_1_0, + ¶meters, + &[], + Direct3D12::D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT, + )?; - if !error.is_null() { - log::error!( - "Root signature serialization error: {:?}", - unsafe { error.as_c_str() }.to_str().unwrap() - ); - return Err(DeviceError::Lost); + let raw = unsafe { + self.raw + .CreateRootSignature::(0, blob.as_slice()) } - - let raw = self - .raw - .create_root_signature(blob, 0) - .into_device_result("Root signature creation")?; + .into_device_result("Root signature creation")?; if let Some(label) = desc.label { - let cwstr = conv::map_label(label); - unsafe { raw.SetName(cwstr.as_ptr()) }; + unsafe { raw.SetName(&windows::core::HSTRING::from(label)) } + .into_device_result("SetName")?; } self.counters.pipeline_layouts.add(1); Ok(super::PipelineLayout { shared: super::PipelineLayoutShared { - signature: raw, + signature: Some(raw), total_root_elements: parameters.len() as super::RootIndex, special_constants_root_index, root_constant_info, @@ -1111,7 +1151,7 @@ impl crate::Device for super::Device { super::TextureView, super::AccelerationStructure, >, - ) -> Result { + ) -> Result { let mut cpu_views = desc .layout .cpu_heap_views @@ -1148,7 +1188,9 @@ impl crate::Device for super::Device { let start = entry.resource_index as usize; let end = start + entry.count as usize; for data in &desc.buffers[start..end] { - dynamic_buffers.push(data.resolve_address()); + dynamic_buffers.push(Direct3D12::D3D12_GPU_DESCRIPTOR_HANDLE { + ptr: data.resolve_address(), + }); } } wgt::BindingType::Buffer { ty, .. } => { @@ -1163,57 +1205,57 @@ impl crate::Device for super::Device { match ty { wgt::BufferBindingType::Uniform => { let size_mask = - d3d12_ty::D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT - 1; - let raw_desc = d3d12_ty::D3D12_CONSTANT_BUFFER_VIEW_DESC { + Direct3D12::D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT - 1; + let raw_desc = Direct3D12::D3D12_CONSTANT_BUFFER_VIEW_DESC { BufferLocation: gpu_address, SizeInBytes: ((size - 1) | size_mask) + 1, }; - unsafe { self.raw.CreateConstantBufferView(&raw_desc, handle) }; + unsafe { + self.raw.CreateConstantBufferView(Some(&raw_desc), handle) + }; } wgt::BufferBindingType::Storage { read_only: true } => { - let mut raw_desc = d3d12_ty::D3D12_SHADER_RESOURCE_VIEW_DESC { - Format: dxgiformat::DXGI_FORMAT_R32_TYPELESS, + let raw_desc = Direct3D12::D3D12_SHADER_RESOURCE_VIEW_DESC { + Format: Dxgi::Common::DXGI_FORMAT_R32_TYPELESS, Shader4ComponentMapping: - view::D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING, - ViewDimension: d3d12_ty::D3D12_SRV_DIMENSION_BUFFER, - u: unsafe { mem::zeroed() }, - }; - unsafe { - *raw_desc.u.Buffer_mut() = d3d12_ty::D3D12_BUFFER_SRV { - FirstElement: data.offset / 4, - NumElements: size / 4, - StructureByteStride: 0, - Flags: d3d12_ty::D3D12_BUFFER_SRV_FLAG_RAW, - } + Direct3D12::D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING, + ViewDimension: Direct3D12::D3D12_SRV_DIMENSION_BUFFER, + Anonymous: Direct3D12::D3D12_SHADER_RESOURCE_VIEW_DESC_0 { + Buffer: Direct3D12::D3D12_BUFFER_SRV { + FirstElement: data.offset / 4, + NumElements: size / 4, + StructureByteStride: 0, + Flags: Direct3D12::D3D12_BUFFER_SRV_FLAG_RAW, + }, + }, }; unsafe { self.raw.CreateShaderResourceView( - data.buffer.resource.as_mut_ptr(), - &raw_desc, + &data.buffer.resource, + Some(&raw_desc), handle, ) }; } wgt::BufferBindingType::Storage { read_only: false } => { - let mut raw_desc = d3d12_ty::D3D12_UNORDERED_ACCESS_VIEW_DESC { - Format: dxgiformat::DXGI_FORMAT_R32_TYPELESS, - ViewDimension: d3d12_ty::D3D12_UAV_DIMENSION_BUFFER, - u: unsafe { mem::zeroed() }, - }; - unsafe { - *raw_desc.u.Buffer_mut() = d3d12_ty::D3D12_BUFFER_UAV { - FirstElement: data.offset / 4, - NumElements: size / 4, - StructureByteStride: 0, - CounterOffsetInBytes: 0, - Flags: d3d12_ty::D3D12_BUFFER_UAV_FLAG_RAW, - } + let raw_desc = Direct3D12::D3D12_UNORDERED_ACCESS_VIEW_DESC { + Format: Dxgi::Common::DXGI_FORMAT_R32_TYPELESS, + ViewDimension: Direct3D12::D3D12_UAV_DIMENSION_BUFFER, + Anonymous: Direct3D12::D3D12_UNORDERED_ACCESS_VIEW_DESC_0 { + Buffer: Direct3D12::D3D12_BUFFER_UAV { + FirstElement: data.offset / 4, + NumElements: size / 4, + StructureByteStride: 0, + CounterOffsetInBytes: 0, + Flags: Direct3D12::D3D12_BUFFER_UAV_FLAG_RAW, + }, + }, }; unsafe { self.raw.CreateUnorderedAccessView( - data.buffer.resource.as_mut_ptr(), - ptr::null_mut(), - &raw_desc, + &data.buffer.resource, + None, + Some(&raw_desc), handle, ) }; @@ -1353,15 +1395,15 @@ impl crate::Device for super::Device { *stride = NonZeroU32::new(vbuf.array_stride as u32); let (slot_class, step_rate) = match vbuf.step_mode { wgt::VertexStepMode::Vertex => { - (d3d12_ty::D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0) + (Direct3D12::D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0) } wgt::VertexStepMode::Instance => { - (d3d12_ty::D3D12_INPUT_CLASSIFICATION_PER_INSTANCE_DATA, 1) + (Direct3D12::D3D12_INPUT_CLASSIFICATION_PER_INSTANCE_DATA, 1) } }; for attribute in vbuf.attributes { - input_element_descs.push(d3d12_ty::D3D12_INPUT_ELEMENT_DESC { - SemanticName: NAGA_LOCATION_SEMANTIC.as_ptr().cast(), + input_element_descs.push(Direct3D12::D3D12_INPUT_ELEMENT_DESC { + SemanticName: windows::core::PCSTR(NAGA_LOCATION_SEMANTIC.as_ptr()), SemanticIndex: attribute.shader_location, Format: auxil::dxgi::conv::map_vertex_format(attribute.format), InputSlot: i as u32, @@ -1372,8 +1414,8 @@ impl crate::Device for super::Device { } } - let mut rtv_formats = [dxgiformat::DXGI_FORMAT_UNKNOWN; - d3d12_ty::D3D12_SIMULTANEOUS_RENDER_TARGET_COUNT as usize]; + let mut rtv_formats = [Dxgi::Common::DXGI_FORMAT_UNKNOWN; + Direct3D12::D3D12_SIMULTANEOUS_RENDER_TARGET_COUNT as usize]; for (rtv_format, ct) in rtv_formats.iter_mut().zip(desc.color_targets) { if let Some(ct) = ct.as_ref() { *rtv_format = auxil::dxgi::conv::map_texture_format(ct.format); @@ -1386,60 +1428,64 @@ impl crate::Device for super::Device { .map(|ds| ds.bias) .unwrap_or_default(); - let raw_rasterizer = d3d12_ty::D3D12_RASTERIZER_DESC { + let raw_rasterizer = Direct3D12::D3D12_RASTERIZER_DESC { FillMode: conv::map_polygon_mode(desc.primitive.polygon_mode), CullMode: match desc.primitive.cull_mode { - None => d3d12_ty::D3D12_CULL_MODE_NONE, - Some(wgt::Face::Front) => d3d12_ty::D3D12_CULL_MODE_FRONT, - Some(wgt::Face::Back) => d3d12_ty::D3D12_CULL_MODE_BACK, + None => Direct3D12::D3D12_CULL_MODE_NONE, + Some(wgt::Face::Front) => Direct3D12::D3D12_CULL_MODE_FRONT, + Some(wgt::Face::Back) => Direct3D12::D3D12_CULL_MODE_BACK, }, FrontCounterClockwise: match desc.primitive.front_face { - wgt::FrontFace::Cw => 0, - wgt::FrontFace::Ccw => 1, + wgt::FrontFace::Cw => Foundation::FALSE, + wgt::FrontFace::Ccw => Foundation::TRUE, }, DepthBias: bias.constant, DepthBiasClamp: bias.clamp, SlopeScaledDepthBias: bias.slope_scale, - DepthClipEnable: BOOL::from(!desc.primitive.unclipped_depth), - MultisampleEnable: BOOL::from(desc.multisample.count > 1), + DepthClipEnable: Foundation::BOOL::from(!desc.primitive.unclipped_depth), + MultisampleEnable: Foundation::BOOL::from(desc.multisample.count > 1), ForcedSampleCount: 0, - AntialiasedLineEnable: 0, + AntialiasedLineEnable: false.into(), ConservativeRaster: if desc.primitive.conservative { - d3d12_ty::D3D12_CONSERVATIVE_RASTERIZATION_MODE_ON + Direct3D12::D3D12_CONSERVATIVE_RASTERIZATION_MODE_ON } else { - d3d12_ty::D3D12_CONSERVATIVE_RASTERIZATION_MODE_OFF + Direct3D12::D3D12_CONSERVATIVE_RASTERIZATION_MODE_OFF }, }; - let raw_desc = d3d12_ty::D3D12_GRAPHICS_PIPELINE_STATE_DESC { - pRootSignature: desc.layout.shared.signature.as_mut_ptr(), - VS: *blob_vs.create_native_shader(), - PS: match blob_fs { - Some(ref shader) => *shader.create_native_shader(), - None => *d3d12::Shader::null(), + let raw_desc = Direct3D12::D3D12_GRAPHICS_PIPELINE_STATE_DESC { + pRootSignature: unsafe { + borrow_optional_interface_temporarily(&desc.layout.shared.signature) }, - GS: *d3d12::Shader::null(), - DS: *d3d12::Shader::null(), - HS: *d3d12::Shader::null(), - StreamOutput: d3d12_ty::D3D12_STREAM_OUTPUT_DESC { + VS: blob_vs.create_native_shader(), + PS: match &blob_fs { + Some(shader) => shader.create_native_shader(), + None => Direct3D12::D3D12_SHADER_BYTECODE::default(), + }, + GS: Direct3D12::D3D12_SHADER_BYTECODE::default(), + DS: Direct3D12::D3D12_SHADER_BYTECODE::default(), + HS: Direct3D12::D3D12_SHADER_BYTECODE::default(), + StreamOutput: Direct3D12::D3D12_STREAM_OUTPUT_DESC { pSODeclaration: ptr::null(), NumEntries: 0, pBufferStrides: ptr::null(), NumStrides: 0, RasterizedStream: 0, }, - BlendState: d3d12_ty::D3D12_BLEND_DESC { - AlphaToCoverageEnable: BOOL::from(desc.multisample.alpha_to_coverage_enabled), - IndependentBlendEnable: 1, + BlendState: Direct3D12::D3D12_BLEND_DESC { + AlphaToCoverageEnable: Foundation::BOOL::from( + desc.multisample.alpha_to_coverage_enabled, + ), + IndependentBlendEnable: true.into(), RenderTarget: conv::map_render_targets(desc.color_targets), }, SampleMask: desc.multisample.mask as u32, RasterizerState: raw_rasterizer, DepthStencilState: match desc.depth_stencil { Some(ref ds) => conv::map_depth_stencil(ds), - None => unsafe { mem::zeroed() }, + None => Default::default(), }, - InputLayout: d3d12_ty::D3D12_INPUT_LAYOUT_DESC { + InputLayout: Direct3D12::D3D12_INPUT_LAYOUT_DESC { pInputElementDescs: if input_element_descs.is_empty() { ptr::null() } else { @@ -1449,12 +1495,12 @@ impl crate::Device for super::Device { }, IBStripCutValue: match desc.primitive.strip_index_format { Some(wgt::IndexFormat::Uint16) => { - d3d12_ty::D3D12_INDEX_BUFFER_STRIP_CUT_VALUE_0xFFFF + Direct3D12::D3D12_INDEX_BUFFER_STRIP_CUT_VALUE_0xFFFF } Some(wgt::IndexFormat::Uint32) => { - d3d12_ty::D3D12_INDEX_BUFFER_STRIP_CUT_VALUE_0xFFFFFFFF + Direct3D12::D3D12_INDEX_BUFFER_STRIP_CUT_VALUE_0xFFFFFFFF } - None => d3d12_ty::D3D12_INDEX_BUFFER_STRIP_CUT_VALUE_DISABLED, + None => Direct3D12::D3D12_INDEX_BUFFER_STRIP_CUT_VALUE_DISABLED, }, PrimitiveTopologyType: topology_class, NumRenderTargets: desc.color_targets.len() as u32, @@ -1462,46 +1508,35 @@ impl crate::Device for super::Device { DSVFormat: desc .depth_stencil .as_ref() - .map_or(dxgiformat::DXGI_FORMAT_UNKNOWN, |ds| { + .map_or(Dxgi::Common::DXGI_FORMAT_UNKNOWN, |ds| { auxil::dxgi::conv::map_texture_format(ds.format) }), - SampleDesc: dxgitype::DXGI_SAMPLE_DESC { + SampleDesc: Dxgi::Common::DXGI_SAMPLE_DESC { Count: desc.multisample.count, Quality: 0, }, NodeMask: 0, - CachedPSO: d3d12_ty::D3D12_CACHED_PIPELINE_STATE { + CachedPSO: Direct3D12::D3D12_CACHED_PIPELINE_STATE { pCachedBlob: ptr::null(), CachedBlobSizeInBytes: 0, }, - Flags: d3d12_ty::D3D12_PIPELINE_STATE_FLAG_NONE, + Flags: Direct3D12::D3D12_PIPELINE_STATE_FLAG_NONE, }; - let mut raw = d3d12::PipelineState::null(); - let hr = { + let raw: Direct3D12::ID3D12PipelineState = { profiling::scope!("ID3D12Device::CreateGraphicsPipelineState"); - unsafe { - self.raw.CreateGraphicsPipelineState( - &raw_desc, - &d3d12_ty::ID3D12PipelineState::uuidof(), - raw.mut_void(), - ) - } - }; + unsafe { self.raw.CreateGraphicsPipelineState(&raw_desc) } + } + .map_err(|err| crate::PipelineError::Linkage(shader_stages, err.to_string()))?; unsafe { blob_vs.destroy() }; if let Some(blob_fs) = blob_fs { unsafe { blob_fs.destroy() }; }; - hr.into_result() - .map_err(|err| crate::PipelineError::Linkage(shader_stages, err.into_owned()))?; - - null_comptr_check(&raw)?; - - if let Some(name) = desc.label { - let cwstr = conv::map_label(name); - unsafe { raw.SetName(cwstr.as_ptr()) }; + if let Some(label) = desc.label { + unsafe { raw.SetName(&windows::core::HSTRING::from(label)) } + .into_device_result("SetName")?; } self.counters.render_pipelines.add(1); @@ -1530,26 +1565,30 @@ impl crate::Device for super::Device { let pair = { profiling::scope!("ID3D12Device::CreateComputePipelineState"); - self.raw.create_compute_pipeline_state( - &desc.layout.shared.signature, - blob_cs.create_native_shader(), - 0, - d3d12::CachedPSO::null(), - d3d12::PipelineStateFlags::empty(), - ) + unsafe { + self.raw.CreateComputePipelineState( + &Direct3D12::D3D12_COMPUTE_PIPELINE_STATE_DESC { + pRootSignature: borrow_optional_interface_temporarily( + &desc.layout.shared.signature, + ), + CS: blob_cs.create_native_shader(), + NodeMask: 0, + CachedPSO: Direct3D12::D3D12_CACHED_PIPELINE_STATE::default(), + Flags: Direct3D12::D3D12_PIPELINE_STATE_FLAG_NONE, + }, + ) + } }; unsafe { blob_cs.destroy() }; - let raw = pair.into_result().map_err(|err| { - crate::PipelineError::Linkage(wgt::ShaderStages::COMPUTE, err.into_owned()) + let raw: Direct3D12::ID3D12PipelineState = pair.map_err(|err| { + crate::PipelineError::Linkage(wgt::ShaderStages::COMPUTE, err.to_string()) })?; - null_comptr_check(&raw)?; - - if let Some(name) = desc.label { - let cwstr = conv::map_label(name); - unsafe { raw.SetName(cwstr.as_ptr()) }; + if let Some(label) = desc.label { + unsafe { raw.SetName(&windows::core::HSTRING::from(label)) } + .into_device_result("SetName")?; } self.counters.compute_pipelines.add(1); @@ -1575,32 +1614,40 @@ impl crate::Device for super::Device { unsafe fn create_query_set( &self, desc: &wgt::QuerySetDescriptor, - ) -> Result { + ) -> Result { let (heap_ty, raw_ty) = match desc.ty { wgt::QueryType::Occlusion => ( - d3d12::QueryHeapType::Occlusion, - d3d12_ty::D3D12_QUERY_TYPE_BINARY_OCCLUSION, + Direct3D12::D3D12_QUERY_HEAP_TYPE_OCCLUSION, + Direct3D12::D3D12_QUERY_TYPE_BINARY_OCCLUSION, ), wgt::QueryType::PipelineStatistics(_) => ( - d3d12::QueryHeapType::PipelineStatistics, - d3d12_ty::D3D12_QUERY_TYPE_PIPELINE_STATISTICS, + Direct3D12::D3D12_QUERY_HEAP_TYPE_PIPELINE_STATISTICS, + Direct3D12::D3D12_QUERY_TYPE_PIPELINE_STATISTICS, ), wgt::QueryType::Timestamp => ( - d3d12::QueryHeapType::Timestamp, - d3d12_ty::D3D12_QUERY_TYPE_TIMESTAMP, + Direct3D12::D3D12_QUERY_HEAP_TYPE_TIMESTAMP, + Direct3D12::D3D12_QUERY_TYPE_TIMESTAMP, ), }; - let raw = self - .raw - .create_query_heap(heap_ty, desc.count, 0) - .into_device_result("Query heap creation")?; + let mut raw = None::; + unsafe { + self.raw.CreateQueryHeap( + &Direct3D12::D3D12_QUERY_HEAP_DESC { + Type: heap_ty, + Count: desc.count, + NodeMask: 0, + }, + &mut raw, + ) + } + .into_device_result("Query heap creation")?; - null_comptr_check(&raw)?; + let raw = raw.ok_or(crate::DeviceError::ResourceCreationFailed)?; if let Some(label) = desc.label { - let cwstr = conv::map_label(label); - unsafe { raw.SetName(cwstr.as_ptr()) }; + unsafe { raw.SetName(&windows::core::HSTRING::from(label)) } + .into_device_result("SetName")?; } self.counters.query_sets.add(1); @@ -1612,18 +1659,10 @@ impl crate::Device for super::Device { self.counters.query_sets.sub(1); } - unsafe fn create_fence(&self) -> Result { - let mut raw = d3d12::Fence::null(); - let hr = unsafe { - self.raw.CreateFence( - 0, - d3d12_ty::D3D12_FENCE_FLAG_SHARED, - &d3d12_ty::ID3D12Fence::uuidof(), - raw.mut_void(), - ) - }; - hr.into_device_result("Fence creation")?; - null_comptr_check(&raw)?; + unsafe fn create_fence(&self) -> Result { + let raw: Direct3D12::ID3D12Fence = + unsafe { self.raw.CreateFence(0, Direct3D12::D3D12_FENCE_FLAG_SHARED) } + .into_device_result("Fence creation")?; self.counters.fences.add(1); @@ -1636,7 +1675,7 @@ impl crate::Device for super::Device { unsafe fn get_fence_value( &self, fence: &super::Fence, - ) -> Result { + ) -> Result { Ok(unsafe { fence.raw.GetCompletedValue() }) } unsafe fn wait( @@ -1644,7 +1683,7 @@ impl crate::Device for super::Device { fence: &super::Fence, value: crate::FenceValue, timeout_ms: u32, - ) -> Result { + ) -> Result { let timeout_duration = Duration::from_millis(timeout_ms as u64); // We first check if the fence has already reached the value we're waiting for. @@ -1653,9 +1692,7 @@ impl crate::Device for super::Device { return Ok(true); } - fence - .raw - .set_event_on_completion(self.idler.event, value) + unsafe { fence.raw.SetEventOnCompletion(value, self.idler.event.0) } .into_device_result("Set event")?; let start_time = Instant::now(); @@ -1682,7 +1719,7 @@ impl crate::Device for super::Device { let remaining_wait_duration = match timeout_duration.checked_sub(elapsed) { Some(remaining) => remaining, None => { - log::trace!("Timeout elapsed inbetween waits!"); + log::trace!("Timeout elapsed in between waits!"); break Ok(false); } }; @@ -1694,23 +1731,23 @@ impl crate::Device for super::Device { ); match unsafe { - synchapi::WaitForSingleObject( + Threading::WaitForSingleObject( self.idler.event.0, remaining_wait_duration.as_millis().try_into().unwrap(), ) } { - winbase::WAIT_OBJECT_0 => {} - winbase::WAIT_ABANDONED | winbase::WAIT_FAILED => { + Foundation::WAIT_OBJECT_0 => {} + Foundation::WAIT_ABANDONED | Foundation::WAIT_FAILED => { log::error!("Wait failed!"); - break Err(DeviceError::Lost); + break Err(crate::DeviceError::Lost); } - winerror::WAIT_TIMEOUT => { + Foundation::WAIT_TIMEOUT => { log::trace!("Wait timed out!"); break Ok(false); } other => { - log::error!("Unexpected wait status: 0x{:x}", other); - break Err(DeviceError::Lost); + log::error!("Unexpected wait status: 0x{:?}", other); + break Err(crate::DeviceError::Lost); } }; @@ -1728,7 +1765,7 @@ impl crate::Device for super::Device { { unsafe { self.render_doc - .start_frame_capture(self.raw.as_mut_ptr().cast(), ptr::null_mut()) + .start_frame_capture(self.raw.as_raw(), ptr::null_mut()) } } #[cfg(not(feature = "renderdoc"))] @@ -1739,7 +1776,7 @@ impl crate::Device for super::Device { #[cfg(feature = "renderdoc")] unsafe { self.render_doc - .end_frame_capture(self.raw.as_mut_ptr().cast(), ptr::null_mut()) + .end_frame_capture(self.raw.as_raw(), ptr::null_mut()) } } @@ -1764,7 +1801,7 @@ impl crate::Device for super::Device { unsafe fn create_acceleration_structure( &self, _desc: &crate::AccelerationStructureDescriptor, - ) -> Result { + ) -> Result { // Create a D3D12 resource as per-usual. todo!() } @@ -1781,15 +1818,8 @@ impl crate::Device for super::Device { self.counters.clone() } - #[cfg(feature = "windows_rs")] fn generate_allocator_report(&self) -> Option { - let mut upstream = { - self.mem_allocator - .as_ref()? - .lock() - .allocator - .generate_report() - }; + let mut upstream = self.mem_allocator.lock().allocator.generate_report(); let allocations = upstream .allocations diff --git a/wgpu-hal/src/dx12/instance.rs b/wgpu-hal/src/dx12/instance.rs index 880c56774..036561619 100644 --- a/wgpu-hal/src/dx12/instance.rs +++ b/wgpu-hal/src/dx12/instance.rs @@ -1,9 +1,19 @@ +use std::sync::Arc; + use parking_lot::RwLock; -use winapi::shared::{dxgi1_5, minwindef}; +use windows::{ + core::Interface as _, + Win32::{ + Foundation, + Graphics::{Direct3D12, Dxgi}, + }, +}; use super::SurfaceTarget; -use crate::auxil::{self, dxgi::result::HResult as _}; -use std::{mem, sync::Arc}; +use crate::{ + auxil::{self, dxgi::result::HResult as _}, + dx12::D3D12Lib, +}; impl Drop for super::Instance { fn drop(&mut self) { @@ -18,7 +28,7 @@ impl crate::Instance for super::Instance { unsafe fn init(desc: &crate::InstanceDescriptor) -> Result { profiling::scope!("Init DX12 Backend"); - let lib_main = d3d12::D3D12Lib::new().map_err(|e| { + let lib_main = D3D12Lib::new().map_err(|e| { crate::InstanceError::with_source(String::from("failed to load d3d12.dll"), e) })?; @@ -27,18 +37,21 @@ impl crate::Instance for super::Instance { .intersects(wgt::InstanceFlags::VALIDATION | wgt::InstanceFlags::GPU_BASED_VALIDATION) { // Enable debug layer - match lib_main.get_debug_interface() { - Ok(pair) => match pair.into_result() { + match lib_main.debug_interface() { + Ok(pair) => match pair { Ok(debug_controller) => { if desc.flags.intersects(wgt::InstanceFlags::VALIDATION) { - debug_controller.enable_layer(); + unsafe { debug_controller.EnableDebugLayer() } } if desc .flags .intersects(wgt::InstanceFlags::GPU_BASED_VALIDATION) { #[allow(clippy::collapsible_if)] - if !debug_controller.enable_gpu_based_validation() { + if let Ok(debug1) = debug_controller.cast::() + { + unsafe { debug1.SetEnableGPUBasedValidation(true) } + } else { log::warn!("Failed to enable GPU-based validation"); } } @@ -61,7 +74,7 @@ impl crate::Instance for super::Instance { // Create IDXGIFactoryMedia let factory_media = match lib_dxgi.create_factory_media() { - Ok(pair) => match pair.into_result() { + Ok(pair) => match pair { Ok(factory_media) => Some(factory_media), Err(err) => { log::error!("Failed to create IDXGIFactoryMedia: {}", err); @@ -76,12 +89,12 @@ impl crate::Instance for super::Instance { let mut supports_allow_tearing = false; if let Some(factory5) = factory.as_factory5() { - let mut allow_tearing: minwindef::BOOL = minwindef::FALSE; + let mut allow_tearing = Foundation::FALSE; let hr = unsafe { factory5.CheckFeatureSupport( - dxgi1_5::DXGI_FEATURE_PRESENT_ALLOW_TEARING, - std::ptr::from_mut(&mut allow_tearing).cast(), - mem::size_of::() as _, + Dxgi::DXGI_FEATURE_PRESENT_ALLOW_TEARING, + <*mut _>::cast(&mut allow_tearing), + std::mem::size_of_val(&allow_tearing) as u32, ) }; @@ -133,7 +146,8 @@ impl crate::Instance for super::Instance { raw_window_handle::RawWindowHandle::Win32(handle) => Ok(super::Surface { factory: self.factory.clone(), factory_media: self.factory_media.clone(), - target: SurfaceTarget::WndHandle(handle.hwnd.get() as *mut _), + // https://github.com/rust-windowing/raw-window-handle/issues/171 + target: SurfaceTarget::WndHandle(Foundation::HWND(handle.hwnd.get() as *mut _)), supports_allow_tearing: self.supports_allow_tearing, swap_chain: RwLock::new(None), }), diff --git a/wgpu-hal/src/dx12/mod.rs b/wgpu-hal/src/dx12/mod.rs index 8401bbe1e..e4b9e7463 100644 --- a/wgpu-hal/src/dx12/mod.rs +++ b/wgpu-hal/src/dx12/mod.rs @@ -44,16 +44,258 @@ mod suballocation; mod types; mod view; -use crate::auxil::{self, dxgi::result::HResult as _}; +use std::{ffi, fmt, mem, num::NonZeroU32, ops::Deref, sync::Arc}; use arrayvec::ArrayVec; use parking_lot::{Mutex, RwLock}; -use std::{ffi, fmt, mem, num::NonZeroU32, sync::Arc}; -use winapi::{ - shared::{dxgi, dxgi1_4, dxgitype, windef, winerror}, - um::{d3d12 as d3d12_ty, dcomp, synchapi, winbase, winnt}, - Interface as _, +use windows::{ + core::{Interface, Param as _}, + Win32::{ + Foundation, + Graphics::{Direct3D, Direct3D12, DirectComposition, Dxgi}, + System::Threading, + }, }; +use windows_core::Free; + +use crate::auxil::{ + self, + dxgi::{ + factory::{DxgiAdapter, DxgiFactory}, + result::HResult, + }, +}; + +#[derive(Debug)] +struct D3D12Lib { + lib: libloading::Library, +} + +impl D3D12Lib { + fn new() -> Result { + unsafe { libloading::Library::new("d3d12.dll").map(|lib| D3D12Lib { lib }) } + } + + fn create_device( + &self, + adapter: &DxgiAdapter, + feature_level: Direct3D::D3D_FEATURE_LEVEL, + ) -> Result, libloading::Error> { + // Calls windows::Win32::Graphics::Direct3D12::D3D12CreateDevice on d3d12.dll + type Fun = extern "system" fn( + padapter: *mut core::ffi::c_void, + minimumfeaturelevel: Direct3D::D3D_FEATURE_LEVEL, + riid: *const windows_core::GUID, + ppdevice: *mut *mut core::ffi::c_void, + ) -> windows_core::HRESULT; + let func: libloading::Symbol = unsafe { self.lib.get(b"D3D12CreateDevice") }?; + + let mut result__ = None; + Ok((func)( + unsafe { adapter.param().abi() }, + feature_level, + // TODO: Generic? + &Direct3D12::ID3D12Device::IID, + <*mut _>::cast(&mut result__), + ) + .map(|| result__.expect("D3D12CreateDevice succeeded but result is NULL?"))) + } + + fn serialize_root_signature( + &self, + version: Direct3D12::D3D_ROOT_SIGNATURE_VERSION, + parameters: &[Direct3D12::D3D12_ROOT_PARAMETER], + static_samplers: &[Direct3D12::D3D12_STATIC_SAMPLER_DESC], + flags: Direct3D12::D3D12_ROOT_SIGNATURE_FLAGS, + ) -> Result { + // Calls windows::Win32::Graphics::Direct3D12::D3D12SerializeRootSignature on d3d12.dll + type Fun = extern "system" fn( + prootsignature: *const Direct3D12::D3D12_ROOT_SIGNATURE_DESC, + version: Direct3D12::D3D_ROOT_SIGNATURE_VERSION, + ppblob: *mut *mut core::ffi::c_void, + pperrorblob: *mut *mut core::ffi::c_void, + ) -> windows_core::HRESULT; + let func: libloading::Symbol = unsafe { self.lib.get(b"D3D12SerializeRootSignature") } + .map_err(|e| { + log::error!("Unable to find serialization function: {:?}", e); + crate::DeviceError::Lost + })?; + + let desc = Direct3D12::D3D12_ROOT_SIGNATURE_DESC { + NumParameters: parameters.len() as _, + pParameters: parameters.as_ptr(), + NumStaticSamplers: static_samplers.len() as _, + pStaticSamplers: static_samplers.as_ptr(), + Flags: flags, + }; + + let mut blob = None; + let mut error = None::; + (func)( + &desc, + version, + <*mut _>::cast(&mut blob), + <*mut _>::cast(&mut error), + ) + .ok() + // TODO: If there's a HRESULT, error may still be non-null and + // contain info. + .into_device_result("Root signature serialization")?; + + if let Some(error) = error { + let error = D3DBlob(error); + log::error!( + "Root signature serialization error: {:?}", + unsafe { error.as_c_str() }.unwrap().to_str().unwrap() + ); + return Err(crate::DeviceError::Lost); + } + + Ok(D3DBlob(blob.expect( + "D3D12SerializeRootSignature succeeded but result is NULL?", + ))) + } + + fn debug_interface( + &self, + ) -> Result, libloading::Error> { + // Calls windows::Win32::Graphics::Direct3D12::D3D12GetDebugInterface on d3d12.dll + type Fun = extern "system" fn( + riid: *const windows_core::GUID, + ppvdebug: *mut *mut core::ffi::c_void, + ) -> windows_core::HRESULT; + let func: libloading::Symbol = unsafe { self.lib.get(b"D3D12GetDebugInterface") }?; + + let mut result__ = core::ptr::null_mut(); + Ok((func)(&Direct3D12::ID3D12Debug::IID, &mut result__) + .and_then(|| unsafe { windows_core::Type::from_abi(result__) })) + } +} + +#[derive(Debug)] +pub(super) struct DxgiLib { + lib: libloading::Library, +} + +impl DxgiLib { + pub fn new() -> Result { + unsafe { libloading::Library::new("dxgi.dll").map(|lib| DxgiLib { lib }) } + } + + pub fn debug_interface1( + &self, + ) -> Result, libloading::Error> { + // Calls windows::Win32::Graphics::Dxgi::DXGIGetDebugInterface1 on dxgi.dll + type Fun = extern "system" fn( + flags: u32, + riid: *const windows_core::GUID, + pdebug: *mut *mut core::ffi::c_void, + ) -> windows_core::HRESULT; + let func: libloading::Symbol = unsafe { self.lib.get(b"DXGIGetDebugInterface1") }?; + + let mut result__ = core::ptr::null_mut(); + Ok((func)(0, &Dxgi::IDXGIInfoQueue::IID, &mut result__) + .and_then(|| unsafe { windows_core::Type::from_abi(result__) })) + } + + pub fn create_factory1( + &self, + ) -> Result, libloading::Error> { + // Calls windows::Win32::Graphics::Dxgi::CreateDXGIFactory1 on dxgi.dll + type Fun = extern "system" fn( + riid: *const windows_core::GUID, + ppfactory: *mut *mut core::ffi::c_void, + ) -> windows_core::HRESULT; + let func: libloading::Symbol = unsafe { self.lib.get(b"CreateDXGIFactory1") }?; + + let mut result__ = core::ptr::null_mut(); + Ok((func)(&Dxgi::IDXGIFactory1::IID, &mut result__) + .and_then(|| unsafe { windows_core::Type::from_abi(result__) })) + } + + pub fn create_factory2( + &self, + factory_flags: Dxgi::DXGI_CREATE_FACTORY_FLAGS, + ) -> Result, libloading::Error> { + // Calls windows::Win32::Graphics::Dxgi::CreateDXGIFactory2 on dxgi.dll + type Fun = extern "system" fn( + flags: Dxgi::DXGI_CREATE_FACTORY_FLAGS, + riid: *const windows_core::GUID, + ppfactory: *mut *mut core::ffi::c_void, + ) -> windows_core::HRESULT; + let func: libloading::Symbol = unsafe { self.lib.get(b"CreateDXGIFactory2") }?; + + let mut result__ = core::ptr::null_mut(); + Ok( + (func)(factory_flags, &Dxgi::IDXGIFactory4::IID, &mut result__) + .and_then(|| unsafe { windows_core::Type::from_abi(result__) }), + ) + } + + pub fn create_factory_media( + &self, + ) -> Result, libloading::Error> { + // Calls windows::Win32::Graphics::Dxgi::CreateDXGIFactory1 on dxgi.dll + type Fun = extern "system" fn( + riid: *const windows_core::GUID, + ppfactory: *mut *mut core::ffi::c_void, + ) -> windows_core::HRESULT; + let func: libloading::Symbol = unsafe { self.lib.get(b"CreateDXGIFactory1") }?; + + let mut result__ = core::ptr::null_mut(); + // https://learn.microsoft.com/en-us/windows/win32/api/dxgi1_3/nn-dxgi1_3-idxgifactorymedia + Ok((func)(&Dxgi::IDXGIFactoryMedia::IID, &mut result__) + .and_then(|| unsafe { windows_core::Type::from_abi(result__) })) + } +} + +/// Create a temporary "owned" copy inside a [`mem::ManuallyDrop`] without increasing the refcount or +/// moving away the source variable. +/// +/// This is a common pattern when needing to pass interface pointers ("borrows") into Windows +/// structs. Moving/cloning ownership is impossible/inconvenient because: +/// +/// - The caller does _not_ assume ownership (and decrement the refcount at a later time); +/// - Unnecessarily increasing and decrementing the refcount; +/// - [`Drop`] destructors cannot run inside `union` structures (when the created structure is +/// implicitly dropped after a call). +/// +/// See also and +/// . +/// +/// # Safety +/// Performs a [`mem::transmute_copy()`] on a refcounted [`Interface`] type. The returned +/// [`mem::ManuallyDrop`] should _not_ be dropped. +pub unsafe fn borrow_interface_temporarily(src: &I) -> mem::ManuallyDrop> { + unsafe { mem::transmute_copy(src) } +} + +/// See [`borrow_interface_temporarily()`] +pub unsafe fn borrow_optional_interface_temporarily( + src: &Option, +) -> mem::ManuallyDrop> { + unsafe { mem::transmute_copy(src) } +} + +struct D3DBlob(Direct3D::ID3DBlob); + +impl Deref for D3DBlob { + type Target = Direct3D::ID3DBlob; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl D3DBlob { + unsafe fn as_slice(&self) -> &[u8] { + unsafe { std::slice::from_raw_parts(self.GetBufferPointer().cast(), self.GetBufferSize()) } + } + + unsafe fn as_c_str(&self) -> Result<&ffi::CStr, ffi::FromBytesUntilNulError> { + ffi::CStr::from_bytes_until_nul(unsafe { self.as_slice() }) + } +} #[derive(Clone, Debug)] pub struct Api; @@ -116,24 +358,23 @@ const MAX_ROOT_ELEMENTS: usize = 64; const ZERO_BUFFER_SIZE: wgt::BufferAddress = 256 << 10; pub struct Instance { - factory: d3d12::DxgiFactory, - factory_media: Option, - library: Arc, + factory: DxgiFactory, + factory_media: Option, + library: Arc, supports_allow_tearing: bool, - _lib_dxgi: d3d12::DxgiLib, + _lib_dxgi: DxgiLib, flags: wgt::InstanceFlags, dxc_container: Option>, } impl Instance { - pub unsafe fn create_surface_from_visual( - &self, - visual: *mut dcomp::IDCompositionVisual, - ) -> Surface { + pub unsafe fn create_surface_from_visual(&self, visual: *mut std::ffi::c_void) -> Surface { + let visual = unsafe { DirectComposition::IDCompositionVisual::from_raw_borrowed(&visual) } + .expect("COM pointer should not be NULL"); Surface { factory: self.factory.clone(), factory_media: self.factory_media.clone(), - target: SurfaceTarget::Visual(unsafe { d3d12::ComPtr::from_raw(visual) }), + target: SurfaceTarget::Visual(visual.to_owned()), supports_allow_tearing: self.supports_allow_tearing, swap_chain: RwLock::new(None), } @@ -141,8 +382,12 @@ impl Instance { pub unsafe fn create_surface_from_surface_handle( &self, - surface_handle: winnt::HANDLE, + surface_handle: *mut std::ffi::c_void, ) -> Surface { + // TODO: We're not given ownership, so we shouldn't call HANDLE::free(). This puts an extra burden on the caller to keep it alive. + // https://learn.microsoft.com/en-us/windows/win32/api/handleapi/nf-handleapi-duplicatehandle could help us, even though DirectComposition is not in the list? + // Or we make all these types owned, require an ownership transition, and replace SurfaceTargetUnsafe with SurfaceTarget. + let surface_handle = Foundation::HANDLE(surface_handle); Surface { factory: self.factory.clone(), factory_media: self.factory_media.clone(), @@ -154,14 +399,15 @@ impl Instance { pub unsafe fn create_surface_from_swap_chain_panel( &self, - swap_chain_panel: *mut types::ISwapChainPanelNative, + swap_chain_panel: *mut std::ffi::c_void, ) -> Surface { + let swap_chain_panel = + unsafe { types::ISwapChainPanelNative::from_raw_borrowed(&swap_chain_panel) } + .expect("COM pointer should not be NULL"); Surface { factory: self.factory.clone(), factory_media: self.factory_media.clone(), - target: SurfaceTarget::SwapChainPanel(unsafe { - d3d12::ComPtr::from_raw(swap_chain_panel) - }), + target: SurfaceTarget::SwapChainPanel(swap_chain_panel.to_owned()), supports_allow_tearing: self.supports_allow_tearing, swap_chain: RwLock::new(None), } @@ -172,11 +418,13 @@ unsafe impl Send for Instance {} unsafe impl Sync for Instance {} struct SwapChain { - raw: d3d12::ComPtr, + // TODO: Drop order frees the SWC before the raw image pointers...? + raw: Dxgi::IDXGISwapChain3, // need to associate raw image pointers with the swapchain so they can be properly released // when the swapchain is destroyed - resources: Vec, - waitable: winnt::HANDLE, + resources: Vec, + /// Handle is freed in [`Self::release_resources()`] + waitable: Foundation::HANDLE, acquired_count: usize, present_mode: wgt::PresentMode, format: wgt::TextureFormat, @@ -184,15 +432,17 @@ struct SwapChain { } enum SurfaceTarget { - WndHandle(windef::HWND), - Visual(d3d12::ComPtr), - SurfaceHandle(winnt::HANDLE), - SwapChainPanel(d3d12::ComPtr), + /// Borrowed, lifetime externally managed + WndHandle(Foundation::HWND), + Visual(DirectComposition::IDCompositionVisual), + /// Borrowed, lifetime externally managed + SurfaceHandle(Foundation::HANDLE), + SwapChainPanel(types::ISwapChainPanelNative), } pub struct Surface { - factory: d3d12::DxgiFactory, - factory_media: Option, + factory: DxgiFactory, + factory_media: Option, target: SurfaceTarget, supports_allow_tearing: bool, swap_chain: RwLock>, @@ -216,7 +466,6 @@ struct PrivateCapabilities { #[allow(unused)] heterogeneous_resource_heaps: bool, memory_architecture: MemoryArchitecture, - #[allow(unused)] // TODO: Exists until windows-rs is standard, then it can probably be removed? heap_create_not_zeroed: bool, casting_fully_typed_format_supported: bool, suballocation_supported: bool, @@ -231,12 +480,12 @@ struct Workarounds { } pub struct Adapter { - raw: d3d12::DxgiAdapter, - device: d3d12::Device, - library: Arc, + raw: DxgiAdapter, + device: Direct3D12::ID3D12Device, + library: Arc, private_caps: PrivateCapabilities, presentation_timer: auxil::dxgi::time::PresentationTimer, - //Note: this isn't used right now, but we'll need it later. + // Note: this isn't used right now, but we'll need it later. #[allow(unused)] workarounds: Workarounds, dxc_container: Option>, @@ -245,20 +494,36 @@ pub struct Adapter { unsafe impl Send for Adapter {} unsafe impl Sync for Adapter {} +struct Event(pub Foundation::HANDLE); +impl Event { + pub fn create(manual_reset: bool, initial_state: bool) -> Result { + Ok(Self( + unsafe { Threading::CreateEventA(None, manual_reset, initial_state, None) } + .into_device_result("CreateEventA")?, + )) + } +} + +impl Drop for Event { + fn drop(&mut self) { + unsafe { Foundation::HANDLE::free(&mut self.0) } + } +} + /// Helper structure for waiting for GPU. struct Idler { - fence: d3d12::Fence, - event: d3d12::Event, + fence: Direct3D12::ID3D12Fence, + event: Event, } struct CommandSignatures { - draw: d3d12::CommandSignature, - draw_indexed: d3d12::CommandSignature, - dispatch: d3d12::CommandSignature, + draw: Direct3D12::ID3D12CommandSignature, + draw_indexed: Direct3D12::ID3D12CommandSignature, + dispatch: Direct3D12::ID3D12CommandSignature, } struct DeviceShared { - zero_buffer: d3d12::Resource, + zero_buffer: Direct3D12::ID3D12Resource, cmd_signatures: CommandSignatures, heap_views: descriptor::GeneralHeap, heap_samplers: descriptor::GeneralHeap, @@ -268,8 +533,8 @@ unsafe impl Send for DeviceShared {} unsafe impl Sync for DeviceShared {} pub struct Device { - raw: d3d12::Device, - present_queue: d3d12::CommandQueue, + raw: Direct3D12::ID3D12Device, + present_queue: Direct3D12::ID3D12CommandQueue, idler: Idler, private_caps: PrivateCapabilities, shared: Arc, @@ -279,11 +544,11 @@ pub struct Device { srv_uav_pool: Mutex, sampler_pool: Mutex, // library - library: Arc, + library: Arc, #[cfg(feature = "renderdoc")] render_doc: auxil::renderdoc::RenderDoc, null_rtv_handle: descriptor::Handle, - mem_allocator: Option>, + mem_allocator: Mutex, dxc_container: Option>, counters: wgt::HalCounters, } @@ -292,8 +557,8 @@ unsafe impl Send for Device {} unsafe impl Sync for Device {} pub struct Queue { - raw: d3d12::CommandQueue, - temp_lists: Mutex>, + raw: Direct3D12::ID3D12CommandQueue, + temp_lists: Mutex>>, } unsafe impl Send for Queue {} @@ -302,7 +567,7 @@ unsafe impl Sync for Queue {} #[derive(Default)] struct Temp { marker: Vec, - barriers: Vec, + barriers: Vec, } impl Temp { @@ -313,9 +578,9 @@ impl Temp { } struct PassResolve { - src: (d3d12::Resource, u32), - dst: (d3d12::Resource, u32), - format: d3d12::Format, + src: (Direct3D12::ID3D12Resource, u32), + dst: (Direct3D12::ID3D12Resource, u32), + format: Dxgi::Common::DXGI_FORMAT, } #[derive(Clone, Copy)] @@ -328,11 +593,11 @@ enum RootElement { other: u32, }, /// Descriptor table. - Table(d3d12::GpuDescriptor), + Table(Direct3D12::D3D12_GPU_DESCRIPTOR_HANDLE), /// Descriptor for a buffer that has dynamic offset. DynamicOffsetBuffer { kind: BufferViewKind, - address: d3d12::GpuAddress, + address: Direct3D12::D3D12_GPU_DESCRIPTOR_HANDLE, }, } @@ -350,7 +615,7 @@ struct PassState { root_elements: [RootElement; MAX_ROOT_ELEMENTS], constant_data: [u32; MAX_ROOT_ELEMENTS], dirty_root_elements: u64, - vertex_buffers: [d3d12_ty::D3D12_VERTEX_BUFFER_VIEW; crate::MAX_VERTEX_BUFFERS], + vertex_buffers: [Direct3D12::D3D12_VERTEX_BUFFER_VIEW; crate::MAX_VERTEX_BUFFERS], dirty_vertex_buffers: usize, kind: PassKind, } @@ -366,7 +631,7 @@ impl PassState { has_label: false, resolves: ArrayVec::new(), layout: PipelineLayoutShared { - signature: d3d12::RootSignature::null(), + signature: None, total_root_elements: 0, special_constants_root_index: None, root_constant_info: None, @@ -374,7 +639,7 @@ impl PassState { root_elements: [RootElement::Empty; MAX_ROOT_ELEMENTS], constant_data: [0; MAX_ROOT_ELEMENTS], dirty_root_elements: 0, - vertex_buffers: [unsafe { mem::zeroed() }; crate::MAX_VERTEX_BUFFERS], + vertex_buffers: [Default::default(); crate::MAX_VERTEX_BUFFERS], dirty_vertex_buffers: 0, kind: PassKind::Transfer, } @@ -387,18 +652,18 @@ impl PassState { } pub struct CommandEncoder { - allocator: d3d12::CommandAllocator, - device: d3d12::Device, + allocator: Direct3D12::ID3D12CommandAllocator, + device: Direct3D12::ID3D12Device, shared: Arc, null_rtv_handle: descriptor::Handle, - list: Option, - free_lists: Vec, + list: Option, + free_lists: Vec, pass: PassState, temp: Temp, /// If set, the end of the next render/compute pass will write a timestamp at /// the given pool & location. - end_of_pass_timer_query: Option<(d3d12::QueryHeap, u32)>, + end_of_pass_timer_query: Option<(Direct3D12::ID3D12QueryHeap, u32)>, } unsafe impl Send for CommandEncoder {} @@ -415,7 +680,7 @@ impl fmt::Debug for CommandEncoder { #[derive(Debug)] pub struct CommandBuffer { - raw: d3d12::GraphicsCommandList, + raw: Direct3D12::ID3D12GraphicsCommandList, } impl crate::DynCommandBuffer for CommandBuffer {} @@ -425,7 +690,7 @@ unsafe impl Sync for CommandBuffer {} #[derive(Debug)] pub struct Buffer { - resource: d3d12::Resource, + resource: Direct3D12::ID3D12Resource, size: wgt::BufferAddress, allocation: Option, } @@ -443,14 +708,15 @@ impl crate::BufferBinding<'_, Buffer> { } } + // TODO: Return GPU handle directly? fn resolve_address(&self) -> wgt::BufferAddress { - self.buffer.resource.gpu_virtual_address() + self.offset + (unsafe { self.buffer.resource.GetGPUVirtualAddress() }) + self.offset } } #[derive(Debug)] pub struct Texture { - resource: d3d12::Resource, + resource: Direct3D12::ID3D12Resource, format: wgt::TextureFormat, dimension: wgt::TextureDimension, size: wgt::Extent3d, @@ -496,10 +762,10 @@ impl Texture { #[derive(Debug)] pub struct TextureView { - raw_format: d3d12::Format, + raw_format: Dxgi::Common::DXGI_FORMAT, aspects: crate::FormatAspects, /// only used by resolve - target_base: (d3d12::Resource, u32), + target_base: (Direct3D12::ID3D12Resource, u32), handle_srv: Option, handle_uav: Option, handle_rtv: Option, @@ -524,8 +790,8 @@ unsafe impl Sync for Sampler {} #[derive(Debug)] pub struct QuerySet { - raw: d3d12::QueryHeap, - raw_ty: d3d12_ty::D3D12_QUERY_TYPE, + raw: Direct3D12::ID3D12QueryHeap, + raw_ty: Direct3D12::D3D12_QUERY_TYPE, } impl crate::DynQuerySet for QuerySet {} @@ -535,7 +801,7 @@ unsafe impl Sync for QuerySet {} #[derive(Debug)] pub struct Fence { - raw: d3d12::Fence, + raw: Direct3D12::ID3D12Fence, } impl crate::DynFence for Fence {} @@ -544,7 +810,7 @@ unsafe impl Send for Fence {} unsafe impl Sync for Fence {} impl Fence { - pub fn raw_fence(&self) -> &d3d12::Fence { + pub fn raw_fence(&self) -> &Direct3D12::ID3D12Fence { &self.raw } } @@ -571,7 +837,7 @@ enum BufferViewKind { pub struct BindGroup { handle_views: Option, handle_samplers: Option, - dynamic_buffers: Vec, + dynamic_buffers: Vec, } impl crate::DynBindGroup for BindGroup {} @@ -602,7 +868,7 @@ struct RootConstantInfo { #[derive(Debug, Clone)] struct PipelineLayoutShared { - signature: d3d12::RootSignature, + signature: Option, total_root_elements: RootIndex, special_constants_root_index: Option, root_constant_info: Option, @@ -633,14 +899,20 @@ impl crate::DynShaderModule for ShaderModule {} pub(super) enum CompiledShader { #[allow(unused)] Dxc(Vec), - Fxc(d3d12::Blob), + Fxc(Direct3D::ID3DBlob), } impl CompiledShader { - fn create_native_shader(&self) -> d3d12::Shader { - match *self { - CompiledShader::Dxc(ref shader) => d3d12::Shader::from_raw(shader), - CompiledShader::Fxc(ref shader) => d3d12::Shader::from_blob(shader), + fn create_native_shader(&self) -> Direct3D12::D3D12_SHADER_BYTECODE { + match self { + CompiledShader::Dxc(shader) => Direct3D12::D3D12_SHADER_BYTECODE { + pShaderBytecode: shader.as_ptr().cast(), + BytecodeLength: shader.len(), + }, + CompiledShader::Fxc(shader) => Direct3D12::D3D12_SHADER_BYTECODE { + pShaderBytecode: unsafe { shader.GetBufferPointer() }, + BytecodeLength: unsafe { shader.GetBufferSize() }, + }, } } @@ -649,9 +921,9 @@ impl CompiledShader { #[derive(Debug)] pub struct RenderPipeline { - raw: d3d12::PipelineState, + raw: Direct3D12::ID3D12PipelineState, layout: PipelineLayoutShared, - topology: d3d12_ty::D3D12_PRIMITIVE_TOPOLOGY, + topology: Direct3D::D3D_PRIMITIVE_TOPOLOGY, vertex_strides: [Option; crate::MAX_VERTEX_BUFFERS], } @@ -662,7 +934,7 @@ unsafe impl Sync for RenderPipeline {} #[derive(Debug)] pub struct ComputePipeline { - raw: d3d12::PipelineState, + raw: Direct3D12::ID3D12PipelineState, layout: PipelineLayoutShared, } @@ -682,7 +954,8 @@ pub struct AccelerationStructure {} impl crate::DynAccelerationStructure for AccelerationStructure {} impl SwapChain { - unsafe fn release_resources(self) -> d3d12::ComPtr { + unsafe fn release_resources(mut self) -> Dxgi::IDXGISwapChain3 { + unsafe { Foundation::HANDLE::free(&mut self.waitable) }; self.raw } @@ -692,14 +965,14 @@ impl SwapChain { ) -> Result { let timeout_ms = match timeout { Some(duration) => duration.as_millis() as u32, - None => winbase::INFINITE, + None => Threading::INFINITE, }; - match unsafe { synchapi::WaitForSingleObject(self.waitable, timeout_ms) } { - winbase::WAIT_ABANDONED | winbase::WAIT_FAILED => Err(crate::SurfaceError::Lost), - winbase::WAIT_OBJECT_0 => Ok(true), - winerror::WAIT_TIMEOUT => Ok(false), + match unsafe { Threading::WaitForSingleObject(self.waitable, timeout_ms) } { + Foundation::WAIT_ABANDONED | Foundation::WAIT_FAILED => Err(crate::SurfaceError::Lost), + Foundation::WAIT_OBJECT_0 => Ok(true), + Foundation::WAIT_TIMEOUT => Ok(false), other => { - log::error!("Unexpected wait status: 0x{:x}", other); + log::error!("Unexpected wait status: 0x{:x?}", other); Err(crate::SurfaceError::Lost) } } @@ -714,7 +987,7 @@ impl crate::Surface for Surface { device: &Device, config: &crate::SurfaceConfiguration, ) -> Result<(), crate::SurfaceError> { - let mut flags = dxgi::DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT; + let mut flags = Dxgi::DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT; // We always set ALLOW_TEARING on the swapchain no matter // what kind of swapchain we want because ResizeBuffers // cannot change the swapchain's ALLOW_TEARING flag. @@ -722,7 +995,7 @@ impl crate::Surface for Surface { // This does not change the behavior of the swapchain, just // allow present calls to use tearing. if self.supports_allow_tearing { - flags |= dxgi::DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING; + flags |= Dxgi::DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING; } // While `configure`s contract ensures that no work on the GPU's main queues @@ -760,77 +1033,72 @@ impl crate::Surface for Surface { raw } None => { - let desc = d3d12::SwapchainDesc { - alpha_mode: auxil::dxgi::conv::map_acomposite_alpha_mode( + let desc = Dxgi::DXGI_SWAP_CHAIN_DESC1 { + AlphaMode: auxil::dxgi::conv::map_acomposite_alpha_mode( config.composite_alpha_mode, ), - width: config.extent.width, - height: config.extent.height, - format: non_srgb_format, - stereo: false, - sample: d3d12::SampleDesc { - count: 1, - quality: 0, + Width: config.extent.width, + Height: config.extent.height, + Format: non_srgb_format, + Stereo: false.into(), + SampleDesc: Dxgi::Common::DXGI_SAMPLE_DESC { + Count: 1, + Quality: 0, }, - buffer_usage: dxgitype::DXGI_USAGE_RENDER_TARGET_OUTPUT, - buffer_count: swap_chain_buffer, - scaling: d3d12::Scaling::Stretch, - swap_effect: d3d12::SwapEffect::FlipDiscard, - flags, + BufferUsage: Dxgi::DXGI_USAGE_RENDER_TARGET_OUTPUT, + BufferCount: swap_chain_buffer, + Scaling: Dxgi::DXGI_SCALING_STRETCH, + SwapEffect: Dxgi::DXGI_SWAP_EFFECT_FLIP_DISCARD, + Flags: flags.0 as u32, }; let swap_chain1 = match self.target { SurfaceTarget::Visual(_) | SurfaceTarget::SwapChainPanel(_) => { profiling::scope!("IDXGIFactory4::CreateSwapChainForComposition"); - self.factory - .unwrap_factory2() - .create_swapchain_for_composition( - device.present_queue.as_mut_ptr().cast(), - &desc, - ) - .into_result() + unsafe { + self.factory + .unwrap_factory2() + .CreateSwapChainForComposition(&device.present_queue, &desc, None) + } } SurfaceTarget::SurfaceHandle(handle) => { profiling::scope!( "IDXGIFactoryMedia::CreateSwapChainForCompositionSurfaceHandle" ); - self.factory_media - .clone() - .ok_or(crate::SurfaceError::Other("IDXGIFactoryMedia not found"))? - .create_swapchain_for_composition_surface_handle( - device.present_queue.as_mut_ptr().cast(), - handle, - &desc, - ) - .into_result() + unsafe { + self.factory_media + .as_ref() + .ok_or(crate::SurfaceError::Other("IDXGIFactoryMedia not found"))? + .CreateSwapChainForCompositionSurfaceHandle( + &device.present_queue, + handle, + &desc, + None, + ) + } } SurfaceTarget::WndHandle(hwnd) => { profiling::scope!("IDXGIFactory4::CreateSwapChainForHwnd"); - self.factory - .as_factory2() - .unwrap() - .create_swapchain_for_hwnd( - device.present_queue.as_mut_ptr().cast(), + unsafe { + self.factory.unwrap_factory2().CreateSwapChainForHwnd( + &device.present_queue, hwnd, &desc, + None, + None, ) - .into_result() + } } }; - let swap_chain1 = match swap_chain1 { - Ok(s) => s, - Err(err) => { - log::error!("SwapChain creation error: {}", err); - return Err(crate::SurfaceError::Other("swap chain creation")); - } - }; + let swap_chain1 = swap_chain1.map_err(|err| { + log::error!("SwapChain creation error: {}", err); + crate::SurfaceError::Other("swap chain creation") + })?; match &self.target { - SurfaceTarget::WndHandle(_) | &SurfaceTarget::SurfaceHandle(_) => {} + SurfaceTarget::WndHandle(_) | SurfaceTarget::SurfaceHandle(_) => {} SurfaceTarget::Visual(visual) => { - if let Err(err) = - unsafe { visual.SetContent(swap_chain1.as_unknown()) }.into_result() - { + if let Err(err) = unsafe { visual.SetContent(&swap_chain1) }.into_result() { log::error!("Unable to SetContent: {}", err); return Err(crate::SurfaceError::Other( "IDCompositionVisual::SetContent", @@ -839,8 +1107,7 @@ impl crate::Surface for Surface { } SurfaceTarget::SwapChainPanel(swap_chain_panel) => { if let Err(err) = - unsafe { swap_chain_panel.SetSwapChain(swap_chain1.as_ptr()) } - .into_result() + unsafe { swap_chain_panel.SetSwapChain(&swap_chain1) }.into_result() { log::error!("Unable to SetSwapChain: {}", err); return Err(crate::SurfaceError::Other( @@ -850,7 +1117,7 @@ impl crate::Surface for Surface { } } - match unsafe { swap_chain1.cast::() }.into_result() { + match swap_chain1.cast::() { Ok(swap_chain3) => swap_chain3, Err(err) => { log::error!("Unable to cast swap chain: {}", err); @@ -863,29 +1130,27 @@ impl crate::Surface for Surface { match self.target { SurfaceTarget::WndHandle(wnd_handle) => { // Disable automatic Alt+Enter handling by DXGI. - const DXGI_MWA_NO_WINDOW_CHANGES: u32 = 1; - const DXGI_MWA_NO_ALT_ENTER: u32 = 2; unsafe { self.factory.MakeWindowAssociation( wnd_handle, - DXGI_MWA_NO_WINDOW_CHANGES | DXGI_MWA_NO_ALT_ENTER, + Dxgi::DXGI_MWA_NO_WINDOW_CHANGES | Dxgi::DXGI_MWA_NO_ALT_ENTER, ) - }; + } + .into_device_result("MakeWindowAssociation")?; } SurfaceTarget::Visual(_) | SurfaceTarget::SurfaceHandle(_) | SurfaceTarget::SwapChainPanel(_) => {} } - unsafe { swap_chain.SetMaximumFrameLatency(config.maximum_frame_latency) }; + unsafe { swap_chain.SetMaximumFrameLatency(config.maximum_frame_latency) } + .into_device_result("SetMaximumFrameLatency")?; let waitable = unsafe { swap_chain.GetFrameLatencyWaitableObject() }; let mut resources = Vec::with_capacity(swap_chain_buffer as usize); for i in 0..swap_chain_buffer { - let mut resource = d3d12::Resource::null(); - unsafe { - swap_chain.GetBuffer(i, &d3d12_ty::ID3D12Resource::uuidof(), resource.mut_void()) - }; + let resource = unsafe { swap_chain.GetBuffer(i) } + .into_device_result("Failed to get swapchain buffer")?; resources.push(resource); } @@ -966,16 +1231,15 @@ impl crate::Queue for Queue { let mut temp_lists = self.temp_lists.lock(); temp_lists.clear(); for cmd_buf in command_buffers { - temp_lists.push(cmd_buf.raw.as_list()); + temp_lists.push(Some(cmd_buf.raw.clone().into())); } { profiling::scope!("ID3D12CommandQueue::ExecuteCommandLists"); - self.raw.execute_command_lists(&temp_lists); + unsafe { self.raw.ExecuteCommandLists(&temp_lists) } } - self.raw - .signal(&signal_fence.raw, signal_value) + unsafe { self.raw.Signal(&signal_fence.raw, signal_value) } .into_device_result("Signal fence")?; // Note the lack of synchronization here between the main Direct queue @@ -997,33 +1261,22 @@ impl crate::Queue for Queue { let (interval, flags) = match sc.present_mode { // We only allow immediate if ALLOW_TEARING is valid. - wgt::PresentMode::Immediate => (0, dxgi::DXGI_PRESENT_ALLOW_TEARING), - wgt::PresentMode::Mailbox => (0, 0), - wgt::PresentMode::Fifo => (1, 0), + wgt::PresentMode::Immediate => (0, Dxgi::DXGI_PRESENT_ALLOW_TEARING), + wgt::PresentMode::Mailbox => (0, Dxgi::DXGI_PRESENT::default()), + wgt::PresentMode::Fifo => (1, Dxgi::DXGI_PRESENT::default()), m => unreachable!("Cannot make surface with present mode {m:?}"), }; profiling::scope!("IDXGISwapchain3::Present"); - unsafe { sc.raw.Present(interval, flags) }; + unsafe { sc.raw.Present(interval, flags) } + .ok() + .into_device_result("Present")?; Ok(()) } unsafe fn get_timestamp_period(&self) -> f32 { - let mut frequency = 0u64; - unsafe { self.raw.GetTimestampFrequency(&mut frequency) }; + let frequency = unsafe { self.raw.GetTimestampFrequency() }.expect("GetTimestampFrequency"); (1_000_000_000.0 / frequency as f64) as f32 } } - -/// A shorthand for producing a `ResourceCreationFailed` error if a ComPtr is null. -#[inline] -pub fn null_comptr_check( - ptr: &d3d12::ComPtr, -) -> Result<(), crate::DeviceError> { - if d3d12::ComPtr::is_null(ptr) { - return Err(crate::DeviceError::ResourceCreationFailed); - } - - Ok(()) -} diff --git a/wgpu-hal/src/dx12/shader_compilation.rs b/wgpu-hal/src/dx12/shader_compilation.rs index f290861d3..8385082e3 100644 --- a/wgpu-hal/src/dx12/shader_compilation.rs +++ b/wgpu-hal/src/dx12/shader_compilation.rs @@ -2,7 +2,7 @@ use std::ffi::CStr; use std::ptr; pub(super) use dxc::{compile_dxc, get_dxc_container, DxcContainer}; -use winapi::um::d3dcompiler; +use windows::Win32::Graphics::Direct3D; use crate::auxil::dxgi::result::HResult; @@ -16,7 +16,7 @@ pub(super) fn compile_fxc( device: &super::Device, source: &str, source_name: Option<&CStr>, - raw_ep: &std::ffi::CString, + raw_ep: &CStr, stage_bit: wgt::ShaderStages, full_stage: &CStr, ) -> ( @@ -24,49 +24,54 @@ pub(super) fn compile_fxc( log::Level, ) { profiling::scope!("compile_fxc"); - let mut shader_data = d3d12::Blob::null(); - let mut compile_flags = d3dcompiler::D3DCOMPILE_ENABLE_STRICTNESS; + let mut shader_data = None; + let mut compile_flags = Direct3D::Fxc::D3DCOMPILE_ENABLE_STRICTNESS; if device .private_caps .instance_flags .contains(wgt::InstanceFlags::DEBUG) { - compile_flags |= d3dcompiler::D3DCOMPILE_DEBUG | d3dcompiler::D3DCOMPILE_SKIP_OPTIMIZATION; + compile_flags |= + Direct3D::Fxc::D3DCOMPILE_DEBUG | Direct3D::Fxc::D3DCOMPILE_SKIP_OPTIMIZATION; } // If no name has been set, D3DCompile wants the null pointer. let source_name = source_name.map(|cstr| cstr.as_ptr()).unwrap_or(ptr::null()); - let mut error = d3d12::Blob::null(); + let mut error = None; let hr = unsafe { - profiling::scope!("d3dcompiler::D3DCompile"); - d3dcompiler::D3DCompile( + profiling::scope!("Direct3D::Fxc::D3DCompile"); + Direct3D::Fxc::D3DCompile( + // TODO: Update low-level bindings to accept a slice here source.as_ptr().cast(), source.len(), - source_name.cast(), - ptr::null(), - ptr::null_mut(), - raw_ep.as_ptr(), - full_stage.as_ptr().cast(), + windows::core::PCSTR(source_name.cast()), + None, + None, + windows::core::PCSTR(raw_ep.as_ptr().cast()), + windows::core::PCSTR(full_stage.as_ptr().cast()), compile_flags, 0, - shader_data.mut_void().cast(), - error.mut_void().cast(), + &mut shader_data, + Some(&mut error), ) }; match hr.into_result() { - Ok(()) => ( - Ok(super::CompiledShader::Fxc(shader_data)), - log::Level::Info, - ), + Ok(()) => { + let shader_data = shader_data.unwrap(); + ( + Ok(super::CompiledShader::Fxc(shader_data)), + log::Level::Info, + ) + } Err(e) => { let mut full_msg = format!("FXC D3DCompile error ({e})"); - if !error.is_null() { + if let Some(error) = error { use std::fmt::Write as _; let message = unsafe { std::slice::from_raw_parts( - error.GetBufferPointer() as *const u8, + error.GetBufferPointer().cast(), error.GetBufferSize(), ) }; @@ -149,7 +154,7 @@ mod dxc { ) { profiling::scope!("compile_dxc"); let mut compile_flags = arrayvec::ArrayVec::<&str, 6>::new_const(); - compile_flags.push("-Ges"); // d3dcompiler::D3DCOMPILE_ENABLE_STRICTNESS + compile_flags.push("-Ges"); // Direct3D::Fxc::D3DCOMPILE_ENABLE_STRICTNESS compile_flags.push("-Vd"); // Disable implicit validation to work around bugs when dxil.dll isn't in the local directory. compile_flags.push("-HV"); // Use HLSL 2018, Naga doesn't supported 2021 yet. compile_flags.push("2018"); @@ -159,8 +164,8 @@ mod dxc { .instance_flags .contains(wgt::InstanceFlags::DEBUG) { - compile_flags.push("-Zi"); // d3dcompiler::D3DCOMPILE_SKIP_OPTIMIZATION - compile_flags.push("-Od"); // d3dcompiler::D3DCOMPILE_DEBUG + compile_flags.push("-Zi"); // Direct3D::Fxc::D3DCOMPILE_SKIP_OPTIMIZATION + compile_flags.push("-Od"); // Direct3D::Fxc::D3DCOMPILE_DEBUG } let blob = match dxc_container diff --git a/wgpu-hal/src/dx12/suballocation.rs b/wgpu-hal/src/dx12/suballocation.rs index b7ddbaf0b..d840e118f 100644 --- a/wgpu-hal/src/dx12/suballocation.rs +++ b/wgpu-hal/src/dx12/suballocation.rs @@ -1,409 +1,314 @@ -pub(crate) use allocation::{ - create_allocator_wrapper, create_buffer_resource, create_texture_resource, - free_buffer_allocation, free_texture_allocation, AllocationWrapper, GpuAllocatorWrapper, -}; +use gpu_allocator::{d3d12::AllocationCreateDesc, MemoryLocation}; +use parking_lot::Mutex; +use windows::Win32::Graphics::Direct3D12; -#[cfg(not(feature = "windows_rs"))] -use committed as allocation; -#[cfg(feature = "windows_rs")] -use placed as allocation; +use crate::auxil::dxgi::result::HResult as _; -// This exists to work around https://github.com/gfx-rs/wgpu/issues/3207 -// Currently this will work the older, slower way if the windows_rs feature is disabled, -// and will use the fast path of suballocating buffers and textures using gpu_allocator if -// the windows_rs feature is enabled. +#[derive(Debug)] +pub(crate) struct GpuAllocatorWrapper { + pub(crate) allocator: gpu_allocator::d3d12::Allocator, +} -// This is the fast path using gpu_allocator to suballocate buffers and textures. -#[cfg(feature = "windows_rs")] -mod placed { - use crate::dx12::null_comptr_check; - use d3d12::ComPtr; - use parking_lot::Mutex; - use std::ptr; - use wgt::assertions::StrictAssertUnwrapExt; - use winapi::{ - um::{ - d3d12::{self as d3d12_ty, ID3D12Resource}, - winnt::HRESULT, - }, - Interface, +#[derive(Debug)] +pub(crate) struct AllocationWrapper { + pub(crate) allocation: gpu_allocator::d3d12::Allocation, +} + +pub(crate) fn create_allocator_wrapper( + raw: &Direct3D12::ID3D12Device, + memory_hints: &wgt::MemoryHints, +) -> Result, crate::DeviceError> { + // TODO: the allocator's configuration should take hardware capability into + // account. + let mb = 1024 * 1024; + let allocation_sizes = match memory_hints { + wgt::MemoryHints::Performance => gpu_allocator::AllocationSizes::default(), + wgt::MemoryHints::MemoryUsage => gpu_allocator::AllocationSizes::new(8 * mb, 4 * mb), + wgt::MemoryHints::Manual { + suballocated_device_memory_block_size, + } => { + // TODO: Would it be useful to expose the host size in memory hints + // instead of always using half of the device size? + let device_size = suballocated_device_memory_block_size.start; + let host_size = device_size / 2; + gpu_allocator::AllocationSizes::new(device_size, host_size) + } }; - use gpu_allocator::{ - d3d12::{AllocationCreateDesc, ToWinapi, ToWindows}, - MemoryLocation, + match gpu_allocator::d3d12::Allocator::new(&gpu_allocator::d3d12::AllocatorCreateDesc { + device: gpu_allocator::d3d12::ID3D12DeviceVersion::Device(raw.clone()), + debug_settings: Default::default(), + allocation_sizes, + }) { + Ok(allocator) => Ok(Mutex::new(GpuAllocatorWrapper { allocator })), + Err(e) => { + log::error!("Failed to create d3d12 allocator, error: {}", e); + Err(e)? + } + } +} + +pub(crate) fn create_buffer_resource( + device: &crate::dx12::Device, + desc: &crate::BufferDescriptor, + raw_desc: Direct3D12::D3D12_RESOURCE_DESC, + resource: &mut Option, +) -> Result, crate::DeviceError> { + let is_cpu_read = desc.usage.contains(crate::BufferUses::MAP_READ); + let is_cpu_write = desc.usage.contains(crate::BufferUses::MAP_WRITE); + + // Workaround for Intel Xe drivers + if !device.private_caps.suballocation_supported { + return create_committed_buffer_resource(device, desc, raw_desc, resource).map(|()| None); + } + + let location = match (is_cpu_read, is_cpu_write) { + (true, true) => MemoryLocation::CpuToGpu, + (true, false) => MemoryLocation::GpuToCpu, + (false, true) => MemoryLocation::CpuToGpu, + (false, false) => MemoryLocation::GpuOnly, }; - #[derive(Debug)] - pub(crate) struct GpuAllocatorWrapper { - pub(crate) allocator: gpu_allocator::d3d12::Allocator, - } + let name = desc.label.unwrap_or("Unlabeled buffer"); - #[derive(Debug)] - pub(crate) struct AllocationWrapper { - pub(crate) allocation: gpu_allocator::d3d12::Allocation, - } + let mut allocator = device.mem_allocator.lock(); - pub(crate) fn create_allocator_wrapper( - raw: &d3d12::Device, - memory_hints: &wgt::MemoryHints, - ) -> Result>, crate::DeviceError> { - let device = raw.as_ptr(); + let allocation_desc = AllocationCreateDesc::from_d3d12_resource_desc( + allocator.allocator.device(), + &raw_desc, + name, + location, + ); + let allocation = allocator.allocator.allocate(&allocation_desc)?; - // TODO: the allocator's configuration should take hardware capability into - // account. - let mb = 1024 * 1024; - let allocation_sizes = match memory_hints { - wgt::MemoryHints::Performance => gpu_allocator::AllocationSizes::default(), - wgt::MemoryHints::MemoryUsage => gpu_allocator::AllocationSizes::new(8 * mb, 4 * mb), - wgt::MemoryHints::Manual { - suballocated_device_memory_block_size, - } => { - // TODO: Would it be useful to expose the host size in memory hints - // instead of always using half of the device size? - let device_size = suballocated_device_memory_block_size.start; - let host_size = device_size / 2; - gpu_allocator::AllocationSizes::new(device_size, host_size) - } - }; - - match gpu_allocator::d3d12::Allocator::new(&gpu_allocator::d3d12::AllocatorCreateDesc { - device: gpu_allocator::d3d12::ID3D12DeviceVersion::Device(device.as_windows().clone()), - debug_settings: Default::default(), - allocation_sizes, - }) { - Ok(allocator) => Ok(Some(Mutex::new(GpuAllocatorWrapper { allocator }))), - Err(e) => { - log::error!("Failed to create d3d12 allocator, error: {}", e); - Err(e)? - } - } - } - - pub(crate) fn create_buffer_resource( - device: &crate::dx12::Device, - desc: &crate::BufferDescriptor, - raw_desc: d3d12_ty::D3D12_RESOURCE_DESC, - resource: &mut ComPtr, - ) -> Result<(HRESULT, Option), crate::DeviceError> { - let is_cpu_read = desc.usage.contains(crate::BufferUses::MAP_READ); - let is_cpu_write = desc.usage.contains(crate::BufferUses::MAP_WRITE); - - // It's a workaround for Intel Xe drivers. - if !device.private_caps.suballocation_supported { - return super::committed::create_buffer_resource(device, desc, raw_desc, resource) - .map(|(hr, _)| (hr, None)); - } - - let location = match (is_cpu_read, is_cpu_write) { - (true, true) => MemoryLocation::CpuToGpu, - (true, false) => MemoryLocation::GpuToCpu, - (false, true) => MemoryLocation::CpuToGpu, - (false, false) => MemoryLocation::GpuOnly, - }; - - let name = desc.label.unwrap_or("Unlabeled buffer"); - - // SAFETY: allocator exists when the windows_rs feature is enabled - let mut allocator = unsafe { - device - .mem_allocator - .as_ref() - .strict_unwrap_unchecked() - .lock() - }; - - // let mut allocator = unsafe { device.mem_allocator.as_ref().unwrap_unchecked().lock() }; - let allocation_desc = AllocationCreateDesc::from_winapi_d3d12_resource_desc( - allocator.allocator.device().as_winapi(), + unsafe { + device.raw.CreatePlacedResource( + allocation.heap(), + allocation.offset(), &raw_desc, - name, - location, - ); - let allocation = allocator.allocator.allocate(&allocation_desc)?; + Direct3D12::D3D12_RESOURCE_STATE_COMMON, + None, + resource, + ) + } + .into_device_result("Placed buffer creation")?; - let hr = unsafe { - device.raw.CreatePlacedResource( - allocation.heap().as_winapi() as *mut _, - allocation.offset(), - &raw_desc, - d3d12_ty::D3D12_RESOURCE_STATE_COMMON, - ptr::null(), - &ID3D12Resource::uuidof(), - resource.mut_void(), - ) - }; - - null_comptr_check(resource)?; - - device - .counters - .buffer_memory - .add(allocation.size() as isize); - - Ok((hr, Some(AllocationWrapper { allocation }))) + if resource.is_none() { + return Err(crate::DeviceError::ResourceCreationFailed); } - pub(crate) fn create_texture_resource( - device: &crate::dx12::Device, - desc: &crate::TextureDescriptor, - raw_desc: d3d12_ty::D3D12_RESOURCE_DESC, - resource: &mut ComPtr, - ) -> Result<(HRESULT, Option), crate::DeviceError> { - // It's a workaround for Intel Xe drivers. - if !device.private_caps.suballocation_supported { - return super::committed::create_texture_resource(device, desc, raw_desc, resource) - .map(|(hr, _)| (hr, None)); - } + device + .counters + .buffer_memory + .add(allocation.size() as isize); - let location = MemoryLocation::GpuOnly; + Ok(Some(AllocationWrapper { allocation })) +} - let name = desc.label.unwrap_or("Unlabeled texture"); +pub(crate) fn create_texture_resource( + device: &crate::dx12::Device, + desc: &crate::TextureDescriptor, + raw_desc: Direct3D12::D3D12_RESOURCE_DESC, + resource: &mut Option, +) -> Result, crate::DeviceError> { + // Workaround for Intel Xe drivers + if !device.private_caps.suballocation_supported { + return create_committed_texture_resource(device, desc, raw_desc, resource).map(|()| None); + } - // SAFETY: allocator exists when the windows_rs feature is enabled - let mut allocator = unsafe { - device - .mem_allocator - .as_ref() - .strict_unwrap_unchecked() - .lock() - }; - let allocation_desc = AllocationCreateDesc::from_winapi_d3d12_resource_desc( - allocator.allocator.device().as_winapi(), + let location = MemoryLocation::GpuOnly; + + let name = desc.label.unwrap_or("Unlabeled texture"); + + let mut allocator = device.mem_allocator.lock(); + let allocation_desc = AllocationCreateDesc::from_d3d12_resource_desc( + allocator.allocator.device(), + &raw_desc, + name, + location, + ); + let allocation = allocator.allocator.allocate(&allocation_desc)?; + + unsafe { + device.raw.CreatePlacedResource( + allocation.heap(), + allocation.offset(), &raw_desc, - name, - location, - ); - let allocation = allocator.allocator.allocate(&allocation_desc)?; + Direct3D12::D3D12_RESOURCE_STATE_COMMON, + None, // clear value + resource, + ) + } + .into_device_result("Placed texture creation")?; - let hr = unsafe { - device.raw.CreatePlacedResource( - allocation.heap().as_winapi() as *mut _, - allocation.offset(), - &raw_desc, - d3d12_ty::D3D12_RESOURCE_STATE_COMMON, - ptr::null(), // clear value - &ID3D12Resource::uuidof(), - resource.mut_void(), - ) - }; - - null_comptr_check(resource)?; - - device - .counters - .texture_memory - .add(allocation.size() as isize); - - Ok((hr, Some(AllocationWrapper { allocation }))) + if resource.is_none() { + return Err(crate::DeviceError::ResourceCreationFailed); } - pub(crate) fn free_buffer_allocation( - device: &crate::dx12::Device, - allocation: AllocationWrapper, - allocator: &Mutex, - ) { - device - .counters - .buffer_memory - .sub(allocation.allocation.size() as isize); - match allocator.lock().allocator.free(allocation.allocation) { - Ok(_) => (), - // TODO: Don't panic here - Err(e) => panic!("Failed to destroy dx12 buffer, {e}"), - }; - } + device + .counters + .texture_memory + .add(allocation.size() as isize); - pub(crate) fn free_texture_allocation( - device: &crate::dx12::Device, - allocation: AllocationWrapper, - allocator: &Mutex, - ) { - device - .counters - .texture_memory - .sub(allocation.allocation.size() as isize); - match allocator.lock().allocator.free(allocation.allocation) { - Ok(_) => (), - // TODO: Don't panic here - Err(e) => panic!("Failed to destroy dx12 texture, {e}"), - }; - } + Ok(Some(AllocationWrapper { allocation })) +} - impl From for crate::DeviceError { - fn from(result: gpu_allocator::AllocationError) -> Self { - match result { - gpu_allocator::AllocationError::OutOfMemory => Self::OutOfMemory, - gpu_allocator::AllocationError::FailedToMap(e) => { - log::error!("DX12 gpu-allocator: Failed to map: {}", e); - Self::Lost - } - gpu_allocator::AllocationError::NoCompatibleMemoryTypeFound => { - log::error!("DX12 gpu-allocator: No Compatible Memory Type Found"); - Self::Lost - } - gpu_allocator::AllocationError::InvalidAllocationCreateDesc => { - log::error!("DX12 gpu-allocator: Invalid Allocation Creation Description"); - Self::Lost - } - gpu_allocator::AllocationError::InvalidAllocatorCreateDesc(e) => { - log::error!( - "DX12 gpu-allocator: Invalid Allocator Creation Description: {}", - e - ); - Self::Lost - } +pub(crate) fn free_buffer_allocation( + device: &crate::dx12::Device, + allocation: AllocationWrapper, + allocator: &Mutex, +) { + device + .counters + .buffer_memory + .sub(allocation.allocation.size() as isize); + match allocator.lock().allocator.free(allocation.allocation) { + Ok(_) => (), + // TODO: Don't panic here + Err(e) => panic!("Failed to destroy dx12 buffer, {e}"), + }; +} - gpu_allocator::AllocationError::Internal(e) => { - log::error!("DX12 gpu-allocator: Internal Error: {}", e); - Self::Lost - } - gpu_allocator::AllocationError::BarrierLayoutNeedsDevice10 - | gpu_allocator::AllocationError::CastableFormatsRequiresEnhancedBarriers - | gpu_allocator::AllocationError::CastableFormatsRequiresAtLeastDevice12 => { - unreachable!() - } +pub(crate) fn free_texture_allocation( + device: &crate::dx12::Device, + allocation: AllocationWrapper, + allocator: &Mutex, +) { + device + .counters + .texture_memory + .sub(allocation.allocation.size() as isize); + match allocator.lock().allocator.free(allocation.allocation) { + Ok(_) => (), + // TODO: Don't panic here + Err(e) => panic!("Failed to destroy dx12 texture, {e}"), + }; +} + +impl From for crate::DeviceError { + fn from(result: gpu_allocator::AllocationError) -> Self { + match result { + gpu_allocator::AllocationError::OutOfMemory => Self::OutOfMemory, + gpu_allocator::AllocationError::FailedToMap(e) => { + log::error!("DX12 gpu-allocator: Failed to map: {}", e); + Self::Lost + } + gpu_allocator::AllocationError::NoCompatibleMemoryTypeFound => { + log::error!("DX12 gpu-allocator: No Compatible Memory Type Found"); + Self::Lost + } + gpu_allocator::AllocationError::InvalidAllocationCreateDesc => { + log::error!("DX12 gpu-allocator: Invalid Allocation Creation Description"); + Self::Lost + } + gpu_allocator::AllocationError::InvalidAllocatorCreateDesc(e) => { + log::error!( + "DX12 gpu-allocator: Invalid Allocator Creation Description: {}", + e + ); + Self::Lost + } + + gpu_allocator::AllocationError::Internal(e) => { + log::error!("DX12 gpu-allocator: Internal Error: {}", e); + Self::Lost + } + gpu_allocator::AllocationError::BarrierLayoutNeedsDevice10 + | gpu_allocator::AllocationError::CastableFormatsRequiresEnhancedBarriers + | gpu_allocator::AllocationError::CastableFormatsRequiresAtLeastDevice12 => { + unreachable!() } } } } -// This is the older, slower path where it doesn't suballocate buffers. -// Tracking issue for when it can be removed: https://github.com/gfx-rs/wgpu/issues/3207 -mod committed { - use crate::dx12::null_comptr_check; - use d3d12::ComPtr; - use parking_lot::Mutex; - use std::ptr; - use winapi::{ - um::{ - d3d12::{self as d3d12_ty, ID3D12Resource}, - winnt::HRESULT, +pub(crate) fn create_committed_buffer_resource( + device: &crate::dx12::Device, + desc: &crate::BufferDescriptor, + raw_desc: Direct3D12::D3D12_RESOURCE_DESC, + resource: &mut Option, +) -> Result<(), crate::DeviceError> { + let is_cpu_read = desc.usage.contains(crate::BufferUses::MAP_READ); + let is_cpu_write = desc.usage.contains(crate::BufferUses::MAP_WRITE); + + let heap_properties = Direct3D12::D3D12_HEAP_PROPERTIES { + Type: Direct3D12::D3D12_HEAP_TYPE_CUSTOM, + CPUPageProperty: if is_cpu_read { + Direct3D12::D3D12_CPU_PAGE_PROPERTY_WRITE_BACK + } else if is_cpu_write { + Direct3D12::D3D12_CPU_PAGE_PROPERTY_WRITE_COMBINE + } else { + Direct3D12::D3D12_CPU_PAGE_PROPERTY_NOT_AVAILABLE }, - Interface, + MemoryPoolPreference: match device.private_caps.memory_architecture { + crate::dx12::MemoryArchitecture::NonUnified if !is_cpu_read && !is_cpu_write => { + Direct3D12::D3D12_MEMORY_POOL_L1 + } + _ => Direct3D12::D3D12_MEMORY_POOL_L0, + }, + CreationNodeMask: 0, + VisibleNodeMask: 0, }; - // https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ne-d3d12-d3d12_heap_flags - const D3D12_HEAP_FLAG_CREATE_NOT_ZEROED: d3d12_ty::D3D12_HEAP_FLAGS = 0x1000; - - // Allocator isn't needed when not suballocating with gpu_allocator - #[derive(Debug)] - pub(crate) struct GpuAllocatorWrapper {} - - // Allocations aren't needed when not suballocating with gpu_allocator - #[derive(Debug)] - pub(crate) struct AllocationWrapper {} - - #[allow(unused)] - pub(crate) fn create_allocator_wrapper( - _raw: &d3d12::Device, - _memory_hints: &wgt::MemoryHints, - ) -> Result>, crate::DeviceError> { - Ok(None) - } - - pub(crate) fn create_buffer_resource( - device: &crate::dx12::Device, - desc: &crate::BufferDescriptor, - raw_desc: d3d12_ty::D3D12_RESOURCE_DESC, - resource: &mut ComPtr, - ) -> Result<(HRESULT, Option), crate::DeviceError> { - let is_cpu_read = desc.usage.contains(crate::BufferUses::MAP_READ); - let is_cpu_write = desc.usage.contains(crate::BufferUses::MAP_WRITE); - - let heap_properties = d3d12_ty::D3D12_HEAP_PROPERTIES { - Type: d3d12_ty::D3D12_HEAP_TYPE_CUSTOM, - CPUPageProperty: if is_cpu_read { - d3d12_ty::D3D12_CPU_PAGE_PROPERTY_WRITE_BACK - } else if is_cpu_write { - d3d12_ty::D3D12_CPU_PAGE_PROPERTY_WRITE_COMBINE + unsafe { + device.raw.CreateCommittedResource( + &heap_properties, + if device.private_caps.heap_create_not_zeroed { + Direct3D12::D3D12_HEAP_FLAG_CREATE_NOT_ZEROED } else { - d3d12_ty::D3D12_CPU_PAGE_PROPERTY_NOT_AVAILABLE + Direct3D12::D3D12_HEAP_FLAG_NONE }, - MemoryPoolPreference: match device.private_caps.memory_architecture { - crate::dx12::MemoryArchitecture::NonUnified if !is_cpu_read && !is_cpu_write => { - d3d12_ty::D3D12_MEMORY_POOL_L1 - } - _ => d3d12_ty::D3D12_MEMORY_POOL_L0, - }, - CreationNodeMask: 0, - VisibleNodeMask: 0, - }; + &raw_desc, + Direct3D12::D3D12_RESOURCE_STATE_COMMON, + None, + resource, + ) + } + .into_device_result("Committed buffer creation")?; - let hr = unsafe { - device.raw.CreateCommittedResource( - &heap_properties, - if device.private_caps.heap_create_not_zeroed { - D3D12_HEAP_FLAG_CREATE_NOT_ZEROED - } else { - d3d12_ty::D3D12_HEAP_FLAG_NONE - }, - &raw_desc, - d3d12_ty::D3D12_RESOURCE_STATE_COMMON, - ptr::null(), - &ID3D12Resource::uuidof(), - resource.mut_void(), - ) - }; - - null_comptr_check(resource)?; - - Ok((hr, None)) + if resource.is_none() { + return Err(crate::DeviceError::ResourceCreationFailed); } - pub(crate) fn create_texture_resource( - device: &crate::dx12::Device, - _desc: &crate::TextureDescriptor, - raw_desc: d3d12_ty::D3D12_RESOURCE_DESC, - resource: &mut ComPtr, - ) -> Result<(HRESULT, Option), crate::DeviceError> { - let heap_properties = d3d12_ty::D3D12_HEAP_PROPERTIES { - Type: d3d12_ty::D3D12_HEAP_TYPE_CUSTOM, - CPUPageProperty: d3d12_ty::D3D12_CPU_PAGE_PROPERTY_NOT_AVAILABLE, - MemoryPoolPreference: match device.private_caps.memory_architecture { - crate::dx12::MemoryArchitecture::NonUnified => d3d12_ty::D3D12_MEMORY_POOL_L1, - crate::dx12::MemoryArchitecture::Unified { .. } => d3d12_ty::D3D12_MEMORY_POOL_L0, - }, - CreationNodeMask: 0, - VisibleNodeMask: 0, - }; - - let hr = unsafe { - device.raw.CreateCommittedResource( - &heap_properties, - if device.private_caps.heap_create_not_zeroed { - D3D12_HEAP_FLAG_CREATE_NOT_ZEROED - } else { - d3d12_ty::D3D12_HEAP_FLAG_NONE - }, - &raw_desc, - d3d12_ty::D3D12_RESOURCE_STATE_COMMON, - ptr::null(), // clear value - &ID3D12Resource::uuidof(), - resource.mut_void(), - ) - }; - - null_comptr_check(resource)?; - - Ok((hr, None)) - } - - #[allow(unused)] - pub(crate) fn free_buffer_allocation( - _device: &crate::dx12::Device, - _allocation: AllocationWrapper, - _allocator: &Mutex, - ) { - // No-op when not using gpu-allocator - } - - #[allow(unused)] - pub(crate) fn free_texture_allocation( - _device: &crate::dx12::Device, - _allocation: AllocationWrapper, - _allocator: &Mutex, - ) { - // No-op when not using gpu-allocator - } + Ok(()) +} + +pub(crate) fn create_committed_texture_resource( + device: &crate::dx12::Device, + _desc: &crate::TextureDescriptor, + raw_desc: Direct3D12::D3D12_RESOURCE_DESC, + resource: &mut Option, +) -> Result<(), crate::DeviceError> { + let heap_properties = Direct3D12::D3D12_HEAP_PROPERTIES { + Type: Direct3D12::D3D12_HEAP_TYPE_CUSTOM, + CPUPageProperty: Direct3D12::D3D12_CPU_PAGE_PROPERTY_NOT_AVAILABLE, + MemoryPoolPreference: match device.private_caps.memory_architecture { + crate::dx12::MemoryArchitecture::NonUnified => Direct3D12::D3D12_MEMORY_POOL_L1, + crate::dx12::MemoryArchitecture::Unified { .. } => Direct3D12::D3D12_MEMORY_POOL_L0, + }, + CreationNodeMask: 0, + VisibleNodeMask: 0, + }; + + unsafe { + device.raw.CreateCommittedResource( + &heap_properties, + if device.private_caps.heap_create_not_zeroed { + Direct3D12::D3D12_HEAP_FLAG_CREATE_NOT_ZEROED + } else { + Direct3D12::D3D12_HEAP_FLAG_NONE + }, + &raw_desc, + Direct3D12::D3D12_RESOURCE_STATE_COMMON, + None, // clear value + resource, + ) + } + .into_device_result("Committed texture creation")?; + + if resource.is_none() { + return Err(crate::DeviceError::ResourceCreationFailed); + } + + Ok(()) } diff --git a/wgpu-hal/src/dx12/types.rs b/wgpu-hal/src/dx12/types.rs index 57a0d94a8..5270c6ca8 100644 --- a/wgpu-hal/src/dx12/types.rs +++ b/wgpu-hal/src/dx12/types.rs @@ -1,83 +1,39 @@ #![allow(non_camel_case_types)] #![allow(non_snake_case)] -// use here so that the recursive RIDL macro can find the crate -use winapi::um::unknwnbase::{IUnknown, IUnknownVtbl}; -use winapi::RIDL; +use windows::Win32::Graphics::Dxgi; -RIDL! {#[uuid(0x63aad0b8, 0x7c24, 0x40ff, 0x85, 0xa8, 0x64, 0x0d, 0x94, 0x4c, 0xc3, 0x25)] -interface ISwapChainPanelNative(ISwapChainPanelNativeVtbl): IUnknown(IUnknownVtbl) { - fn SetSwapChain(swapChain: *const winapi::shared::dxgi1_2::IDXGISwapChain1,) -> winapi::um::winnt::HRESULT, -}} - -winapi::ENUM! { - enum D3D12_VIEW_INSTANCING_TIER { - D3D12_VIEW_INSTANCING_TIER_NOT_SUPPORTED = 0, - D3D12_VIEW_INSTANCING_TIER_1 = 1, - D3D12_VIEW_INSTANCING_TIER_2 = 2, - D3D12_VIEW_INSTANCING_TIER_3 = 3, +windows_core::imp::define_interface!( + ISwapChainPanelNative, + ISwapChainPanelNative_Vtbl, + 0x63aad0b8_7c24_40ff_85a8_640d944cc325 +); +impl core::ops::Deref for ISwapChainPanelNative { + type Target = windows_core::IUnknown; + fn deref(&self) -> &Self::Target { + unsafe { core::mem::transmute(self) } } } - -winapi::ENUM! { - enum D3D12_COMMAND_LIST_SUPPORT_FLAGS { - D3D12_COMMAND_LIST_SUPPORT_FLAG_NONE = 0, - // D3D12_COMMAND_LIST_SUPPORT_FLAG_DIRECT, - // D3D12_COMMAND_LIST_SUPPORT_FLAG_BUNDLE, - // D3D12_COMMAND_LIST_SUPPORT_FLAG_COMPUTE, - // D3D12_COMMAND_LIST_SUPPORT_FLAG_COPY, - // D3D12_COMMAND_LIST_SUPPORT_FLAG_VIDEO_DECODE, - // D3D12_COMMAND_LIST_SUPPORT_FLAG_VIDEO_PROCESS, - // D3D12_COMMAND_LIST_SUPPORT_FLAG_VIDEO_ENCODE, +windows_core::imp::interface_hierarchy!(ISwapChainPanelNative, windows_core::IUnknown); +impl ISwapChainPanelNative { + pub unsafe fn SetSwapChain(&self, swap_chain: P0) -> windows_core::Result<()> + where + P0: windows_core::Param, + { + unsafe { + (windows_core::Interface::vtable(self).SetSwapChain)( + windows_core::Interface::as_raw(self), + swap_chain.param().abi(), + ) + } + .ok() } } - -winapi::STRUCT! { - struct D3D12_FEATURE_DATA_D3D12_OPTIONS3 { - CopyQueueTimestampQueriesSupported: winapi::shared::minwindef::BOOL, - CastingFullyTypedFormatSupported: winapi::shared::minwindef::BOOL, - WriteBufferImmediateSupportFlags: D3D12_COMMAND_LIST_SUPPORT_FLAGS, - ViewInstancingTier: D3D12_VIEW_INSTANCING_TIER, - BarycentricsSupported: winapi::shared::minwindef::BOOL, - } -} - -winapi::ENUM! { - enum D3D12_WAVE_MMA_TIER { - D3D12_WAVE_MMA_TIER_NOT_SUPPORTED = 0, - D3D12_WAVE_MMA_TIER_1_0 = 10, - } -} - -winapi::STRUCT! { - struct D3D12_FEATURE_DATA_D3D12_OPTIONS9 { - MeshShaderPipelineStatsSupported: winapi::shared::minwindef::BOOL, - MeshShaderSupportsFullRangeRenderTargetArrayIndex: winapi::shared::minwindef::BOOL, - AtomicInt64OnTypedResourceSupported: winapi::shared::minwindef::BOOL, - AtomicInt64OnGroupSharedSupported: winapi::shared::minwindef::BOOL, - DerivativesInMeshAndAmplificationShadersSupported: winapi::shared::minwindef::BOOL, - WaveMMATier: D3D12_WAVE_MMA_TIER, - } -} - -winapi::ENUM! { - enum D3D_SHADER_MODEL { - D3D_SHADER_MODEL_NONE = 0, - D3D_SHADER_MODEL_5_1 = 0x51, - D3D_SHADER_MODEL_6_0 = 0x60, - D3D_SHADER_MODEL_6_1 = 0x61, - D3D_SHADER_MODEL_6_2 = 0x62, - D3D_SHADER_MODEL_6_3 = 0x63, - D3D_SHADER_MODEL_6_4 = 0x64, - D3D_SHADER_MODEL_6_5 = 0x65, - D3D_SHADER_MODEL_6_6 = 0x66, - D3D_SHADER_MODEL_6_7 = 0x67, - D3D_HIGHEST_SHADER_MODEL = 0x67, - } -} - -winapi::STRUCT! { - struct D3D12_FEATURE_DATA_SHADER_MODEL { - HighestShaderModel: D3D_SHADER_MODEL, - } +#[repr(C)] +pub struct ISwapChainPanelNative_Vtbl { + pub base__: windows_core::IUnknown_Vtbl, + pub SetSwapChain: unsafe extern "system" fn( + swap_chain_panel_native: *mut core::ffi::c_void, + swap_chain: *mut core::ffi::c_void, + ) -> windows_core::HRESULT, } diff --git a/wgpu-hal/src/dx12/view.rs b/wgpu-hal/src/dx12/view.rs index ae8e5814a..8162b012a 100644 --- a/wgpu-hal/src/dx12/view.rs +++ b/wgpu-hal/src/dx12/view.rs @@ -1,14 +1,12 @@ -use crate::auxil; -use std::mem; -use winapi::um::d3d12 as d3d12_ty; +use windows::Win32::Graphics::{Direct3D12, Dxgi}; -pub(crate) const D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING: u32 = 0x1688; +use crate::auxil; pub(super) struct ViewDescriptor { dimension: wgt::TextureViewDimension, pub aspects: crate::FormatAspects, - pub rtv_dsv_format: d3d12::Format, - srv_uav_format: Option, + pub rtv_dsv_format: Dxgi::Common::DXGI_FORMAT, + srv_uav_format: Option, multisampled: bool, array_layer_base: u32, array_layer_count: u32, @@ -44,113 +42,98 @@ fn aspects_to_plane(aspects: crate::FormatAspects) -> u32 { } impl ViewDescriptor { - pub(crate) unsafe fn to_srv(&self) -> Option { - let mut desc = d3d12_ty::D3D12_SHADER_RESOURCE_VIEW_DESC { + pub(crate) unsafe fn to_srv(&self) -> Option { + let mut desc = Direct3D12::D3D12_SHADER_RESOURCE_VIEW_DESC { Format: self.srv_uav_format?, - ViewDimension: 0, - Shader4ComponentMapping: D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING, - u: unsafe { mem::zeroed() }, + ViewDimension: Direct3D12::D3D12_SRV_DIMENSION_UNKNOWN, + Shader4ComponentMapping: Direct3D12::D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING, + Anonymous: Default::default(), }; match self.dimension { wgt::TextureViewDimension::D1 => { - desc.ViewDimension = d3d12_ty::D3D12_SRV_DIMENSION_TEXTURE1D; - unsafe { - *desc.u.Texture1D_mut() = d3d12_ty::D3D12_TEX1D_SRV { - MostDetailedMip: self.mip_level_base, - MipLevels: self.mip_level_count, - ResourceMinLODClamp: 0.0, - } + desc.ViewDimension = Direct3D12::D3D12_SRV_DIMENSION_TEXTURE1D; + desc.Anonymous.Texture1D = Direct3D12::D3D12_TEX1D_SRV { + MostDetailedMip: self.mip_level_base, + MipLevels: self.mip_level_count, + ResourceMinLODClamp: 0.0, } } /* wgt::TextureViewDimension::D1Array => { - desc.ViewDimension = d3d12_ty::D3D12_SRV_DIMENSION_TEXTURE1DARRAY; - *desc.u.Texture1DArray_mut() = d3d12_ty::D3D12_TEX1D_ARRAY_SRV { + desc.ViewDimension = Direct3D12::D3D12_SRV_DIMENSION_TEXTURE1DARRAY; + desc.Anonymous.Texture1DArray = Direct3D12::D3D12_TEX1D_ARRAY_SRV { MostDetailedMip: self.mip_level_base, MipLevels: self.mip_level_count, FirstArraySlice: self.array_layer_base, ArraySize: self.array_layer_count, ResourceMinLODClamp: 0.0, } - }*/ + } + */ wgt::TextureViewDimension::D2 if self.multisampled && self.array_layer_base == 0 => { - desc.ViewDimension = d3d12_ty::D3D12_SRV_DIMENSION_TEXTURE2DMS; - unsafe { - *desc.u.Texture2DMS_mut() = d3d12_ty::D3D12_TEX2DMS_SRV { - UnusedField_NothingToDefine: 0, - } + desc.ViewDimension = Direct3D12::D3D12_SRV_DIMENSION_TEXTURE2DMS; + desc.Anonymous.Texture2DMS = Direct3D12::D3D12_TEX2DMS_SRV { + UnusedField_NothingToDefine: 0, } } wgt::TextureViewDimension::D2 if self.array_layer_base == 0 => { - desc.ViewDimension = d3d12_ty::D3D12_SRV_DIMENSION_TEXTURE2D; - unsafe { - *desc.u.Texture2D_mut() = d3d12_ty::D3D12_TEX2D_SRV { - MostDetailedMip: self.mip_level_base, - MipLevels: self.mip_level_count, - PlaneSlice: aspects_to_plane(self.aspects), - ResourceMinLODClamp: 0.0, - } + desc.ViewDimension = Direct3D12::D3D12_SRV_DIMENSION_TEXTURE2D; + desc.Anonymous.Texture2D = Direct3D12::D3D12_TEX2D_SRV { + MostDetailedMip: self.mip_level_base, + MipLevels: self.mip_level_count, + PlaneSlice: aspects_to_plane(self.aspects), + ResourceMinLODClamp: 0.0, } } wgt::TextureViewDimension::D2 | wgt::TextureViewDimension::D2Array if self.multisampled => { - desc.ViewDimension = d3d12_ty::D3D12_SRV_DIMENSION_TEXTURE2DMSARRAY; - unsafe { - *desc.u.Texture2DMSArray_mut() = d3d12_ty::D3D12_TEX2DMS_ARRAY_SRV { - FirstArraySlice: self.array_layer_base, - ArraySize: self.array_layer_count, - } + desc.ViewDimension = Direct3D12::D3D12_SRV_DIMENSION_TEXTURE2DMSARRAY; + desc.Anonymous.Texture2DMSArray = Direct3D12::D3D12_TEX2DMS_ARRAY_SRV { + FirstArraySlice: self.array_layer_base, + ArraySize: self.array_layer_count, } } wgt::TextureViewDimension::D2 | wgt::TextureViewDimension::D2Array => { - desc.ViewDimension = d3d12_ty::D3D12_SRV_DIMENSION_TEXTURE2DARRAY; - unsafe { - *desc.u.Texture2DArray_mut() = d3d12_ty::D3D12_TEX2D_ARRAY_SRV { - MostDetailedMip: self.mip_level_base, - MipLevels: self.mip_level_count, - FirstArraySlice: self.array_layer_base, - ArraySize: self.array_layer_count, - PlaneSlice: aspects_to_plane(self.aspects), - ResourceMinLODClamp: 0.0, - } + desc.ViewDimension = Direct3D12::D3D12_SRV_DIMENSION_TEXTURE2DARRAY; + desc.Anonymous.Texture2DArray = Direct3D12::D3D12_TEX2D_ARRAY_SRV { + MostDetailedMip: self.mip_level_base, + MipLevels: self.mip_level_count, + FirstArraySlice: self.array_layer_base, + ArraySize: self.array_layer_count, + PlaneSlice: aspects_to_plane(self.aspects), + ResourceMinLODClamp: 0.0, } } wgt::TextureViewDimension::D3 => { - desc.ViewDimension = d3d12_ty::D3D12_SRV_DIMENSION_TEXTURE3D; - unsafe { - *desc.u.Texture3D_mut() = d3d12_ty::D3D12_TEX3D_SRV { - MostDetailedMip: self.mip_level_base, - MipLevels: self.mip_level_count, - ResourceMinLODClamp: 0.0, - } + desc.ViewDimension = Direct3D12::D3D12_SRV_DIMENSION_TEXTURE3D; + desc.Anonymous.Texture3D = Direct3D12::D3D12_TEX3D_SRV { + MostDetailedMip: self.mip_level_base, + MipLevels: self.mip_level_count, + ResourceMinLODClamp: 0.0, } } wgt::TextureViewDimension::Cube if self.array_layer_base == 0 => { - desc.ViewDimension = d3d12_ty::D3D12_SRV_DIMENSION_TEXTURECUBE; - unsafe { - *desc.u.TextureCube_mut() = d3d12_ty::D3D12_TEXCUBE_SRV { - MostDetailedMip: self.mip_level_base, - MipLevels: self.mip_level_count, - ResourceMinLODClamp: 0.0, - } + desc.ViewDimension = Direct3D12::D3D12_SRV_DIMENSION_TEXTURECUBE; + desc.Anonymous.TextureCube = Direct3D12::D3D12_TEXCUBE_SRV { + MostDetailedMip: self.mip_level_base, + MipLevels: self.mip_level_count, + ResourceMinLODClamp: 0.0, } } wgt::TextureViewDimension::Cube | wgt::TextureViewDimension::CubeArray => { - desc.ViewDimension = d3d12_ty::D3D12_SRV_DIMENSION_TEXTURECUBEARRAY; - unsafe { - *desc.u.TextureCubeArray_mut() = d3d12_ty::D3D12_TEXCUBE_ARRAY_SRV { - MostDetailedMip: self.mip_level_base, - MipLevels: self.mip_level_count, - First2DArrayFace: self.array_layer_base, - NumCubes: if self.array_layer_count == !0 { - !0 - } else { - self.array_layer_count / 6 - }, - ResourceMinLODClamp: 0.0, - } + desc.ViewDimension = Direct3D12::D3D12_SRV_DIMENSION_TEXTURECUBEARRAY; + desc.Anonymous.TextureCubeArray = Direct3D12::D3D12_TEXCUBE_ARRAY_SRV { + MostDetailedMip: self.mip_level_base, + MipLevels: self.mip_level_count, + First2DArrayFace: self.array_layer_base, + NumCubes: if self.array_layer_count == !0 { + !0 + } else { + self.array_layer_count / 6 + }, + ResourceMinLODClamp: 0.0, } } } @@ -158,59 +141,51 @@ impl ViewDescriptor { Some(desc) } - pub(crate) unsafe fn to_uav(&self) -> Option { - let mut desc = d3d12_ty::D3D12_UNORDERED_ACCESS_VIEW_DESC { + pub(crate) unsafe fn to_uav(&self) -> Option { + let mut desc = Direct3D12::D3D12_UNORDERED_ACCESS_VIEW_DESC { Format: self.srv_uav_format?, - ViewDimension: 0, - u: unsafe { mem::zeroed() }, + ViewDimension: Direct3D12::D3D12_UAV_DIMENSION_UNKNOWN, + Anonymous: Default::default(), }; match self.dimension { wgt::TextureViewDimension::D1 => { - desc.ViewDimension = d3d12_ty::D3D12_UAV_DIMENSION_TEXTURE1D; - unsafe { - *desc.u.Texture1D_mut() = d3d12_ty::D3D12_TEX1D_UAV { - MipSlice: self.mip_level_base, - } + desc.ViewDimension = Direct3D12::D3D12_UAV_DIMENSION_TEXTURE1D; + desc.Anonymous.Texture1D = Direct3D12::D3D12_TEX1D_UAV { + MipSlice: self.mip_level_base, } } /* wgt::TextureViewDimension::D1Array => { - desc.ViewDimension = d3d12_ty::D3D12_UAV_DIMENSION_TEXTURE1DARRAY; - *desc.u.Texture1DArray_mut() = d3d12_ty::D3D12_TEX1D_ARRAY_UAV { + desc.ViewDimension = Direct3D12::D3D12_UAV_DIMENSION_TEXTURE1DARRAY; + desc.Anonymous.Texture1DArray = Direct3D12::D3D12_TEX1D_ARRAY_UAV { MipSlice: self.mip_level_base, FirstArraySlice: self.array_layer_base, ArraySize, } }*/ wgt::TextureViewDimension::D2 if self.array_layer_base == 0 => { - desc.ViewDimension = d3d12_ty::D3D12_UAV_DIMENSION_TEXTURE2D; - unsafe { - *desc.u.Texture2D_mut() = d3d12_ty::D3D12_TEX2D_UAV { - MipSlice: self.mip_level_base, - PlaneSlice: aspects_to_plane(self.aspects), - } + desc.ViewDimension = Direct3D12::D3D12_UAV_DIMENSION_TEXTURE2D; + desc.Anonymous.Texture2D = Direct3D12::D3D12_TEX2D_UAV { + MipSlice: self.mip_level_base, + PlaneSlice: aspects_to_plane(self.aspects), } } wgt::TextureViewDimension::D2 | wgt::TextureViewDimension::D2Array => { - desc.ViewDimension = d3d12_ty::D3D12_UAV_DIMENSION_TEXTURE2DARRAY; - unsafe { - *desc.u.Texture2DArray_mut() = d3d12_ty::D3D12_TEX2D_ARRAY_UAV { - MipSlice: self.mip_level_base, - FirstArraySlice: self.array_layer_base, - ArraySize: self.array_layer_count, - PlaneSlice: aspects_to_plane(self.aspects), - } + desc.ViewDimension = Direct3D12::D3D12_UAV_DIMENSION_TEXTURE2DARRAY; + desc.Anonymous.Texture2DArray = Direct3D12::D3D12_TEX2D_ARRAY_UAV { + MipSlice: self.mip_level_base, + FirstArraySlice: self.array_layer_base, + ArraySize: self.array_layer_count, + PlaneSlice: aspects_to_plane(self.aspects), } } wgt::TextureViewDimension::D3 => { - desc.ViewDimension = d3d12_ty::D3D12_UAV_DIMENSION_TEXTURE3D; - unsafe { - *desc.u.Texture3D_mut() = d3d12_ty::D3D12_TEX3D_UAV { - MipSlice: self.mip_level_base, - FirstWSlice: self.array_layer_base, - WSize: self.array_layer_count, - } + desc.ViewDimension = Direct3D12::D3D12_UAV_DIMENSION_TEXTURE3D; + desc.Anonymous.Texture3D = Direct3D12::D3D12_TEX3D_UAV { + MipSlice: self.mip_level_base, + FirstWSlice: self.array_layer_base, + WSize: self.array_layer_count, } } wgt::TextureViewDimension::Cube | wgt::TextureViewDimension::CubeArray => { @@ -221,78 +196,66 @@ impl ViewDescriptor { Some(desc) } - pub(crate) unsafe fn to_rtv(&self) -> d3d12_ty::D3D12_RENDER_TARGET_VIEW_DESC { - let mut desc = d3d12_ty::D3D12_RENDER_TARGET_VIEW_DESC { + pub(crate) unsafe fn to_rtv(&self) -> Direct3D12::D3D12_RENDER_TARGET_VIEW_DESC { + let mut desc = Direct3D12::D3D12_RENDER_TARGET_VIEW_DESC { Format: self.rtv_dsv_format, - ViewDimension: 0, - u: unsafe { mem::zeroed() }, + ViewDimension: Direct3D12::D3D12_RTV_DIMENSION_UNKNOWN, + Anonymous: Default::default(), }; match self.dimension { wgt::TextureViewDimension::D1 => { - desc.ViewDimension = d3d12_ty::D3D12_RTV_DIMENSION_TEXTURE1D; - unsafe { - *desc.u.Texture1D_mut() = d3d12_ty::D3D12_TEX1D_RTV { - MipSlice: self.mip_level_base, - } + desc.ViewDimension = Direct3D12::D3D12_RTV_DIMENSION_TEXTURE1D; + desc.Anonymous.Texture1D = Direct3D12::D3D12_TEX1D_RTV { + MipSlice: self.mip_level_base, } } /* wgt::TextureViewDimension::D1Array => { - desc.ViewDimension = d3d12_ty::D3D12_RTV_DIMENSION_TEXTURE1DARRAY; - *desc.u.Texture1DArray_mut() = d3d12_ty::D3D12_TEX1D_ARRAY_RTV { + desc.ViewDimension = Direct3D12::D3D12_RTV_DIMENSION_TEXTURE1DARRAY; + desc.Anonymous.Texture1DArray = Direct3D12::D3D12_TEX1D_ARRAY_RTV { MipSlice: self.mip_level_base, FirstArraySlice: self.array_layer_base, ArraySize, } }*/ wgt::TextureViewDimension::D2 if self.multisampled && self.array_layer_base == 0 => { - desc.ViewDimension = d3d12_ty::D3D12_RTV_DIMENSION_TEXTURE2DMS; - unsafe { - *desc.u.Texture2DMS_mut() = d3d12_ty::D3D12_TEX2DMS_RTV { - UnusedField_NothingToDefine: 0, - } + desc.ViewDimension = Direct3D12::D3D12_RTV_DIMENSION_TEXTURE2DMS; + desc.Anonymous.Texture2DMS = Direct3D12::D3D12_TEX2DMS_RTV { + UnusedField_NothingToDefine: 0, } } wgt::TextureViewDimension::D2 if self.array_layer_base == 0 => { - desc.ViewDimension = d3d12_ty::D3D12_RTV_DIMENSION_TEXTURE2D; - unsafe { - *desc.u.Texture2D_mut() = d3d12_ty::D3D12_TEX2D_RTV { - MipSlice: self.mip_level_base, - PlaneSlice: aspects_to_plane(self.aspects), - } + desc.ViewDimension = Direct3D12::D3D12_RTV_DIMENSION_TEXTURE2D; + desc.Anonymous.Texture2D = Direct3D12::D3D12_TEX2D_RTV { + MipSlice: self.mip_level_base, + PlaneSlice: aspects_to_plane(self.aspects), } } wgt::TextureViewDimension::D2 | wgt::TextureViewDimension::D2Array if self.multisampled => { - desc.ViewDimension = d3d12_ty::D3D12_RTV_DIMENSION_TEXTURE2DMSARRAY; - unsafe { - *desc.u.Texture2DMSArray_mut() = d3d12_ty::D3D12_TEX2DMS_ARRAY_RTV { - FirstArraySlice: self.array_layer_base, - ArraySize: self.array_layer_count, - } + desc.ViewDimension = Direct3D12::D3D12_RTV_DIMENSION_TEXTURE2DMSARRAY; + desc.Anonymous.Texture2DMSArray = Direct3D12::D3D12_TEX2DMS_ARRAY_RTV { + FirstArraySlice: self.array_layer_base, + ArraySize: self.array_layer_count, } } wgt::TextureViewDimension::D2 | wgt::TextureViewDimension::D2Array => { - desc.ViewDimension = d3d12_ty::D3D12_RTV_DIMENSION_TEXTURE2DARRAY; - unsafe { - *desc.u.Texture2DArray_mut() = d3d12_ty::D3D12_TEX2D_ARRAY_RTV { - MipSlice: self.mip_level_base, - FirstArraySlice: self.array_layer_base, - ArraySize: self.array_layer_count, - PlaneSlice: aspects_to_plane(self.aspects), - } + desc.ViewDimension = Direct3D12::D3D12_RTV_DIMENSION_TEXTURE2DARRAY; + desc.Anonymous.Texture2DArray = Direct3D12::D3D12_TEX2D_ARRAY_RTV { + MipSlice: self.mip_level_base, + FirstArraySlice: self.array_layer_base, + ArraySize: self.array_layer_count, + PlaneSlice: aspects_to_plane(self.aspects), } } wgt::TextureViewDimension::D3 => { - desc.ViewDimension = d3d12_ty::D3D12_RTV_DIMENSION_TEXTURE3D; - unsafe { - *desc.u.Texture3D_mut() = d3d12_ty::D3D12_TEX3D_RTV { - MipSlice: self.mip_level_base, - FirstWSlice: self.array_layer_base, - WSize: self.array_layer_count, - } + desc.ViewDimension = Direct3D12::D3D12_RTV_DIMENSION_TEXTURE3D; + desc.Anonymous.Texture3D = Direct3D12::D3D12_TEX3D_RTV { + MipSlice: self.mip_level_base, + FirstWSlice: self.array_layer_base, + WSize: self.array_layer_count, } } wgt::TextureViewDimension::Cube | wgt::TextureViewDimension::CubeArray => { @@ -303,78 +266,72 @@ impl ViewDescriptor { desc } - pub(crate) unsafe fn to_dsv(&self, read_only: bool) -> d3d12_ty::D3D12_DEPTH_STENCIL_VIEW_DESC { - let mut desc = d3d12_ty::D3D12_DEPTH_STENCIL_VIEW_DESC { + pub(crate) unsafe fn to_dsv( + &self, + read_only: bool, + ) -> Direct3D12::D3D12_DEPTH_STENCIL_VIEW_DESC { + let mut desc = Direct3D12::D3D12_DEPTH_STENCIL_VIEW_DESC { Format: self.rtv_dsv_format, - ViewDimension: 0, + ViewDimension: Direct3D12::D3D12_DSV_DIMENSION_UNKNOWN, Flags: { - let mut flags = d3d12_ty::D3D12_DSV_FLAG_NONE; + let mut flags = Direct3D12::D3D12_DSV_FLAG_NONE; if read_only { if self.aspects.contains(crate::FormatAspects::DEPTH) { - flags |= d3d12_ty::D3D12_DSV_FLAG_READ_ONLY_DEPTH; + flags |= Direct3D12::D3D12_DSV_FLAG_READ_ONLY_DEPTH; } if self.aspects.contains(crate::FormatAspects::STENCIL) { - flags |= d3d12_ty::D3D12_DSV_FLAG_READ_ONLY_STENCIL; + flags |= Direct3D12::D3D12_DSV_FLAG_READ_ONLY_STENCIL; } } flags }, - u: unsafe { mem::zeroed() }, + Anonymous: Default::default(), }; match self.dimension { wgt::TextureViewDimension::D1 => { - desc.ViewDimension = d3d12_ty::D3D12_DSV_DIMENSION_TEXTURE1D; - unsafe { - *desc.u.Texture1D_mut() = d3d12_ty::D3D12_TEX1D_DSV { - MipSlice: self.mip_level_base, - } + desc.ViewDimension = Direct3D12::D3D12_DSV_DIMENSION_TEXTURE1D; + desc.Anonymous.Texture1D = Direct3D12::D3D12_TEX1D_DSV { + MipSlice: self.mip_level_base, } } /* wgt::TextureViewDimension::D1Array => { - desc.ViewDimension = d3d12_ty::D3D12_DSV_DIMENSION_TEXTURE1DARRAY; - *desc.u.Texture1DArray_mut() = d3d12_ty::D3D12_TEX1D_ARRAY_DSV { + desc.ViewDimension = Direct3D12::D3D12_DSV_DIMENSION_TEXTURE1DARRAY; + desc.Anonymous.Texture1DArray = Direct3D12::D3D12_TEX1D_ARRAY_DSV { MipSlice: self.mip_level_base, FirstArraySlice: self.array_layer_base, ArraySize, } }*/ wgt::TextureViewDimension::D2 if self.multisampled && self.array_layer_base == 0 => { - desc.ViewDimension = d3d12_ty::D3D12_DSV_DIMENSION_TEXTURE2DMS; - unsafe { - *desc.u.Texture2DMS_mut() = d3d12_ty::D3D12_TEX2DMS_DSV { - UnusedField_NothingToDefine: 0, - } + desc.ViewDimension = Direct3D12::D3D12_DSV_DIMENSION_TEXTURE2DMS; + desc.Anonymous.Texture2DMS = Direct3D12::D3D12_TEX2DMS_DSV { + UnusedField_NothingToDefine: 0, } } wgt::TextureViewDimension::D2 if self.array_layer_base == 0 => { - desc.ViewDimension = d3d12_ty::D3D12_DSV_DIMENSION_TEXTURE2D; - unsafe { - *desc.u.Texture2D_mut() = d3d12_ty::D3D12_TEX2D_DSV { - MipSlice: self.mip_level_base, - } + desc.ViewDimension = Direct3D12::D3D12_DSV_DIMENSION_TEXTURE2D; + + desc.Anonymous.Texture2D = Direct3D12::D3D12_TEX2D_DSV { + MipSlice: self.mip_level_base, } } wgt::TextureViewDimension::D2 | wgt::TextureViewDimension::D2Array if self.multisampled => { - desc.ViewDimension = d3d12_ty::D3D12_DSV_DIMENSION_TEXTURE2DMSARRAY; - unsafe { - *desc.u.Texture2DMSArray_mut() = d3d12_ty::D3D12_TEX2DMS_ARRAY_DSV { - FirstArraySlice: self.array_layer_base, - ArraySize: self.array_layer_count, - } + desc.ViewDimension = Direct3D12::D3D12_DSV_DIMENSION_TEXTURE2DMSARRAY; + desc.Anonymous.Texture2DMSArray = Direct3D12::D3D12_TEX2DMS_ARRAY_DSV { + FirstArraySlice: self.array_layer_base, + ArraySize: self.array_layer_count, } } wgt::TextureViewDimension::D2 | wgt::TextureViewDimension::D2Array => { - desc.ViewDimension = d3d12_ty::D3D12_DSV_DIMENSION_TEXTURE2DARRAY; - unsafe { - *desc.u.Texture2DArray_mut() = d3d12_ty::D3D12_TEX2D_ARRAY_DSV { - MipSlice: self.mip_level_base, - FirstArraySlice: self.array_layer_base, - ArraySize: self.array_layer_count, - } + desc.ViewDimension = Direct3D12::D3D12_DSV_DIMENSION_TEXTURE2DARRAY; + desc.Anonymous.Texture2DArray = Direct3D12::D3D12_TEX2D_ARRAY_DSV { + MipSlice: self.mip_level_base, + FirstArraySlice: self.array_layer_base, + ArraySize: self.array_layer_count, } } wgt::TextureViewDimension::D3 diff --git a/wgpu-types/src/assertions.rs b/wgpu-types/src/assertions.rs index ee10bfd56..a36b2e826 100644 --- a/wgpu-types/src/assertions.rs +++ b/wgpu-types/src/assertions.rs @@ -64,29 +64,3 @@ macro_rules! strict_assert_ne { debug_assert_ne!( $( $arg )* ) }; } - -/// Unwrapping using strict_asserts -pub trait StrictAssertUnwrapExt { - /// Unchecked unwrap, with a [`strict_assert`] backed assertion of validitly. - /// - /// # Safety - /// - /// It _must_ be valid to call unwrap_unchecked on this value. - unsafe fn strict_unwrap_unchecked(self) -> T; -} - -impl StrictAssertUnwrapExt for Option { - unsafe fn strict_unwrap_unchecked(self) -> T { - strict_assert!(self.is_some(), "Called strict_unwrap_unchecked on None"); - // SAFETY: Checked by above assert, or by assertion by unsafe. - unsafe { self.unwrap_unchecked() } - } -} - -impl StrictAssertUnwrapExt for Result { - unsafe fn strict_unwrap_unchecked(self) -> T { - strict_assert!(self.is_ok(), "Called strict_unwrap_unchecked on Err"); - // SAFETY: Checked by above assert, or by assertion by unsafe. - unsafe { self.unwrap_unchecked() } - } -} diff --git a/wgpu/Cargo.toml b/wgpu/Cargo.toml index cd73f5dc9..2512840a6 100644 --- a/wgpu/Cargo.toml +++ b/wgpu/Cargo.toml @@ -164,7 +164,6 @@ hal = { workspace = true, features = ["renderdoc"] } hal = { workspace = true, features = [ "dxc_shader_compiler", "renderdoc", - "windows_rs", ] } [target.'cfg(target_arch = "wasm32")'.dependencies.hal] diff --git a/wgpu/src/api/surface.rs b/wgpu/src/api/surface.rs index 9c7e056aa..de140a9dc 100644 --- a/wgpu/src/api/surface.rs +++ b/wgpu/src/api/surface.rs @@ -332,15 +332,18 @@ pub enum SurfaceTargetUnsafe { /// /// # Safety /// - /// - visual must be a valid IDCompositionVisual to create a surface upon. + /// - visual must be a valid `IDCompositionVisual` to create a surface upon. Its refcount will be incremented internally and kept live as long as the resulting [`Surface`] is live. #[cfg(dx12)] CompositionVisual(*mut std::ffi::c_void), - /// Surface from DX12 `SurfaceHandle`. + /// Surface from DX12 `DirectComposition` handle. + /// + /// /// /// # Safety /// - /// - surface_handle must be a valid SurfaceHandle to create a surface upon. + /// - surface_handle must be a valid `DirectComposition` handle to create a surface upon. Its lifetime **will not** be internally managed: this handle **should not** be freed before + /// the resulting [`Surface`] is destroyed. #[cfg(dx12)] SurfaceHandle(*mut std::ffi::c_void), @@ -348,7 +351,7 @@ pub enum SurfaceTargetUnsafe { /// /// # Safety /// - /// - visual must be a valid SwapChainPanel to create a surface upon. + /// - visual must be a valid SwapChainPanel to create a surface upon. Its refcount will be incremented internally and kept live as long as the resulting [`Surface`] is live. #[cfg(dx12)] SwapChainPanel(*mut std::ffi::c_void), }