From 2aa4a82499d4becd2284cdb482213d541b8804dd Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 28 Apr 2024 16:29:10 +0200 Subject: Adding upstream version 86.0.1. Signed-off-by: Daniel Baumann --- third_party/rust/d3d12/src/com.rs | 102 +++++++ third_party/rust/d3d12/src/command_allocator.rs | 14 + third_party/rust/d3d12/src/command_list.rs | 328 ++++++++++++++++++++++ third_party/rust/d3d12/src/debug.rs | 46 ++++ third_party/rust/d3d12/src/descriptor.rs | 297 ++++++++++++++++++++ third_party/rust/d3d12/src/device.rs | 346 ++++++++++++++++++++++++ third_party/rust/d3d12/src/dxgi.rs | 219 +++++++++++++++ third_party/rust/d3d12/src/heap.rs | 86 ++++++ third_party/rust/d3d12/src/lib.rs | 101 +++++++ third_party/rust/d3d12/src/pso.rs | 164 +++++++++++ third_party/rust/d3d12/src/query.rs | 15 + third_party/rust/d3d12/src/queue.rs | 34 +++ third_party/rust/d3d12/src/resource.rs | 55 ++++ third_party/rust/d3d12/src/sync.rs | 41 +++ 14 files changed, 1848 insertions(+) create mode 100644 third_party/rust/d3d12/src/com.rs create mode 100644 third_party/rust/d3d12/src/command_allocator.rs create mode 100644 third_party/rust/d3d12/src/command_list.rs create mode 100644 third_party/rust/d3d12/src/debug.rs create mode 100644 third_party/rust/d3d12/src/descriptor.rs create mode 100644 third_party/rust/d3d12/src/device.rs create mode 100644 third_party/rust/d3d12/src/dxgi.rs create mode 100644 third_party/rust/d3d12/src/heap.rs create mode 100644 third_party/rust/d3d12/src/lib.rs create mode 100644 third_party/rust/d3d12/src/pso.rs create mode 100644 third_party/rust/d3d12/src/query.rs create mode 100644 third_party/rust/d3d12/src/queue.rs create mode 100644 third_party/rust/d3d12/src/resource.rs create mode 100644 third_party/rust/d3d12/src/sync.rs (limited to 'third_party/rust/d3d12/src') diff --git a/third_party/rust/d3d12/src/com.rs b/third_party/rust/d3d12/src/com.rs new file mode 100644 index 0000000000..f68349e6c5 --- /dev/null +++ b/third_party/rust/d3d12/src/com.rs @@ -0,0 +1,102 @@ +use std::fmt; +use std::hash::{Hash, Hasher}; +use std::ops::Deref; +use std::ptr; +use winapi::ctypes::c_void; +use winapi::um::unknwnbase::IUnknown; +use winapi::Interface; +use D3DResult; + +#[repr(transparent)] +pub struct WeakPtr(*mut T); + +impl WeakPtr { + pub fn null() -> Self { + WeakPtr(ptr::null_mut()) + } + + pub unsafe fn from_raw(raw: *mut T) -> Self { + WeakPtr(raw) + } + + pub fn is_null(&self) -> bool { + self.0.is_null() + } + + pub fn as_ptr(&self) -> *const T { + self.0 + } + + pub fn as_mut_ptr(&self) -> *mut T { + self.0 + } + + pub unsafe fn mut_void(&mut self) -> *mut *mut c_void { + &mut self.0 as *mut *mut _ as *mut *mut _ + } +} + +impl WeakPtr { + pub unsafe fn as_unknown(&self) -> &IUnknown { + debug_assert!(!self.is_null()); + &*(self.0 as *mut IUnknown) + } + + // Cast creates a new WeakPtr requiring explicit destroy call. + pub unsafe fn cast(&self) -> D3DResult> + where + U: Interface, + { + let mut obj = WeakPtr::::null(); + let hr = self + .as_unknown() + .QueryInterface(&U::uuidof(), obj.mut_void()); + (obj, hr) + } + + // Destroying one instance of the WeakPtr will invalidate all + // copies and clones. + pub unsafe fn destroy(&self) { + self.as_unknown().Release(); + } +} + +impl Clone for WeakPtr { + fn clone(&self) -> Self { + WeakPtr(self.0) + } +} + +impl Copy for WeakPtr {} + +impl Deref for WeakPtr { + type Target = T; + fn deref(&self) -> &T { + debug_assert!(!self.is_null()); + unsafe { &*self.0 } + } +} + +impl fmt::Debug for WeakPtr { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "WeakPtr( ptr: {:?} )", self.0) + } +} + +impl PartialEq<*mut T> for WeakPtr { + fn eq(&self, other: &*mut T) -> bool { + self.0 == *other + } +} + +impl PartialEq for WeakPtr { + fn eq(&self, other: &Self) -> bool { + self.0 == other.0 + } +} + +impl Hash for WeakPtr { + fn hash(&self, state: &mut H) { + self.0.hash(state); + } +} diff --git a/third_party/rust/d3d12/src/command_allocator.rs b/third_party/rust/d3d12/src/command_allocator.rs new file mode 100644 index 0000000000..fc2730b8ad --- /dev/null +++ b/third_party/rust/d3d12/src/command_allocator.rs @@ -0,0 +1,14 @@ +//! Command Allocator + +use com::WeakPtr; +use winapi::um::d3d12; + +pub type CommandAllocator = WeakPtr; + +impl CommandAllocator { + pub fn reset(&self) { + unsafe { + self.Reset(); + } + } +} diff --git a/third_party/rust/d3d12/src/command_list.rs b/third_party/rust/d3d12/src/command_list.rs new file mode 100644 index 0000000000..b5a9437cee --- /dev/null +++ b/third_party/rust/d3d12/src/command_list.rs @@ -0,0 +1,328 @@ +//! Graphics command list + +use com::WeakPtr; +use resource::DiscardRegion; +use std::{mem, ptr}; +use winapi::um::d3d12; +use { + CommandAllocator, CpuDescriptor, DescriptorHeap, Format, GpuAddress, GpuDescriptor, IndexCount, + InstanceCount, PipelineState, Rect, Resource, RootSignature, VertexCount, VertexOffset, + WorkGroupCount, HRESULT, +}; + +#[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! { + 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() } + }) + } + + // TODO: missing variants +} + +#[repr(transparent)] +pub struct ResourceBarrier(d3d12::D3D12_RESOURCE_BARRIER); + +impl ResourceBarrier { + pub fn transition( + resource: Resource, + subresource: u32, + 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 = WeakPtr; +pub type CommandList = WeakPtr; +pub type GraphicsCommandList = WeakPtr; + +impl GraphicsCommandList { + pub fn as_list(&self) -> CommandList { + unsafe { CommandList::from_raw(self.as_mut_ptr() as *mut _) } + } + + pub fn close(&self) -> HRESULT { + unsafe { self.Close() } + } + + 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, + start_vertex: VertexCount, + start_instance: InstanceCount, + ) { + unsafe { + self.DrawInstanced(num_vertices, num_instances, start_vertex, start_instance); + } + } + + pub fn draw_indexed( + &self, + num_indices: IndexCount, + num_instances: InstanceCount, + start_index: IndexCount, + base_vertex: VertexOffset, + start_instance: InstanceCount, + ) { + unsafe { + self.DrawIndexedInstanced( + num_indices, + num_instances, + start_index, + base_vertex, + start_instance, + ); + } + } + + pub fn set_index_buffer(&self, gpu_address: GpuAddress, size: u32, format: Format) { + let mut ibv = d3d12::D3D12_INDEX_BUFFER_VIEW { + BufferLocation: gpu_address, + SizeInBytes: size, + Format: format, + }; + unsafe { + self.IASetIndexBuffer(&mut 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: u32, + base_descriptor: GpuDescriptor, + ) { + unsafe { + self.SetComputeRootDescriptorTable(root_index, base_descriptor); + } + } + + pub fn set_compute_root_constant_buffer_view( + &self, + root_index: u32, + buffer_location: GpuAddress, + ) { + unsafe { + self.SetComputeRootConstantBufferView(root_index, buffer_location); + } + } + + pub fn set_compute_root_shader_resource_view( + &self, + root_index: u32, + buffer_location: GpuAddress, + ) { + unsafe { + self.SetComputeRootShaderResourceView(root_index, buffer_location); + } + } + + pub fn set_compute_root_unordered_access_view( + &self, + root_index: u32, + buffer_location: GpuAddress, + ) { + unsafe { + self.SetComputeRootUnorderedAccessView(root_index, buffer_location); + } + } + + pub fn set_graphics_root_descriptor_table( + &self, + root_index: u32, + base_descriptor: GpuDescriptor, + ) { + unsafe { + self.SetGraphicsRootDescriptorTable(root_index, base_descriptor); + } + } + + pub fn set_graphics_root_constant_buffer_view( + &self, + root_index: u32, + buffer_location: GpuAddress, + ) { + unsafe { + self.SetGraphicsRootConstantBufferView(root_index, buffer_location); + } + } + + pub fn set_graphics_root_shader_resource_view( + &self, + root_index: u32, + buffer_location: GpuAddress, + ) { + unsafe { + self.SetGraphicsRootShaderResourceView(root_index, buffer_location); + } + } + + pub fn set_graphics_root_unordered_access_view( + &self, + root_index: u32, + buffer_location: GpuAddress, + ) { + unsafe { + self.SetGraphicsRootUnorderedAccessView(root_index, buffer_location); + } + } + + pub fn resource_barrier(&self, barriers: &[ResourceBarrier]) { + unsafe { + self.ResourceBarrier(barriers.len() as _, barriers.as_ptr() as _) // matches representation + } + } +} diff --git a/third_party/rust/d3d12/src/debug.rs b/third_party/rust/d3d12/src/debug.rs new file mode 100644 index 0000000000..822b8fbf91 --- /dev/null +++ b/third_party/rust/d3d12/src/debug.rs @@ -0,0 +1,46 @@ +use com::WeakPtr; +#[cfg(any(feature = "libloading", feature = "implicit-link"))] +use winapi::Interface as _; +use winapi::um::d3d12sdklayers; + +pub type Debug = WeakPtr; + +#[cfg(feature = "libloading")] +impl crate::D3D12Lib { + pub fn get_debug_interface(&self) -> libloading::Result> { + 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() } + } +} diff --git a/third_party/rust/d3d12/src/descriptor.rs b/third_party/rust/d3d12/src/descriptor.rs new file mode 100644 index 0000000000..23dd1a17cc --- /dev/null +++ b/third_party/rust/d3d12/src/descriptor.rs @@ -0,0 +1,297 @@ +use com::WeakPtr; +use std::mem; +use std::ops::Range; +use winapi::shared::dxgiformat; +use winapi::um::d3d12; +use {Blob, D3DResult, Error, TextureAddressMode}; + +pub type CpuDescriptor = d3d12::D3D12_CPU_DESCRIPTOR_HANDLE; +pub type GpuDescriptor = d3d12::D3D12_GPU_DESCRIPTOR_HANDLE; + +#[derive(Clone, Copy, Debug)] +pub struct Binding { + pub register: u32, + pub space: 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! { + pub struct DescriptorHeapFlags: u32 { + const SHADER_VISIBLE = d3d12::D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE; + } +} + +pub type DescriptorHeap = WeakPtr; + +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, + }) + } +} + +#[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) + } + + 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) + } +} + +#[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! { + 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 = WeakPtr; +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, + ) -> libloading::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/third_party/rust/d3d12/src/device.rs b/third_party/rust/d3d12/src/device.rs new file mode 100644 index 0000000000..6180d846ce --- /dev/null +++ b/third_party/rust/d3d12/src/device.rs @@ -0,0 +1,346 @@ +//! Device + +use com::WeakPtr; +use command_list::{CmdListType, CommandSignature, IndirectArgument}; +use descriptor::{CpuDescriptor, DescriptorHeapFlags, DescriptorHeapType, RenderTargetViewDesc}; +use heap::{Heap, HeapFlags, HeapProperties}; +use std::ops::Range; +use winapi::um::d3d12; +use winapi::Interface; +use {pso, query, queue}; +use { + Blob, CachedPSO, CommandAllocator, CommandQueue, D3DResult, DescriptorHeap, + Fence, GraphicsCommandList, NodeMask, PipelineState, QueryHeap, Resource, RootSignature, + Shader, TextureAddressMode, +}; + +pub type Device = WeakPtr; + +#[cfg(feature = "libloading")] +impl crate::D3D12Lib { + pub fn create_device( + &self, + adapter: WeakPtr, + feature_level: crate::FeatureLevel, + ) -> libloading::Result> { + 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: WeakPtr, + 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/third_party/rust/d3d12/src/dxgi.rs b/third_party/rust/d3d12/src/dxgi.rs new file mode 100644 index 0000000000..991d1d0db4 --- /dev/null +++ b/third_party/rust/d3d12/src/dxgi.rs @@ -0,0 +1,219 @@ +use com::WeakPtr; +use std::ptr; +use winapi::shared::windef::HWND; +use winapi::shared::{dxgi, dxgi1_2, dxgi1_3, dxgi1_4, dxgiformat, dxgitype}; +use winapi::um::{dxgidebug, d3d12}; +use winapi::Interface; +use {CommandQueue, D3DResult, Resource, SampleDesc, HRESULT}; + +bitflags! { + pub struct FactoryCreationFlags: u32 { + const DEBUG = dxgi1_3::DXGI_CREATE_FACTORY_DEBUG; + } +} + +#[repr(u32)] +#[derive(Debug, Copy, Clone)] +pub enum Scaling { + Stretch = dxgi1_2::DXGI_SCALING_STRETCH, + Identity = dxgi1_2::DXGI_SCALING_NONE, + Aspect = dxgi1_2::DXGI_SCALING_ASPECT_RATIO_STRETCH, +} + +#[repr(u32)] +#[derive(Debug, Copy, Clone)] +pub enum SwapEffect { + Discard = dxgi::DXGI_SWAP_EFFECT_DISCARD, + Sequential = dxgi::DXGI_SWAP_EFFECT_SEQUENTIAL, + FlipDiscard = dxgi::DXGI_SWAP_EFFECT_FLIP_DISCARD, + FlipSequential = dxgi::DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL, +} + +#[repr(u32)] +#[derive(Debug, Copy, Clone)] +pub enum AlphaMode { + Unspecified = dxgi1_2::DXGI_ALPHA_MODE_UNSPECIFIED, + Premultiplied = dxgi1_2::DXGI_ALPHA_MODE_PREMULTIPLIED, + Straight = dxgi1_2::DXGI_ALPHA_MODE_STRAIGHT, + Ignore = dxgi1_2::DXGI_ALPHA_MODE_IGNORE, + ForceDword = dxgi1_2::DXGI_ALPHA_MODE_FORCE_DWORD, +} + +pub type Adapter1 = WeakPtr; +pub type Factory2 = WeakPtr; +pub type Factory4 = WeakPtr; +pub type InfoQueue = WeakPtr; +pub type SwapChain = WeakPtr; +pub type SwapChain1 = WeakPtr; +pub type SwapChain3 = WeakPtr; + +#[cfg(feature = "libloading")] +#[derive(Debug)] +pub struct DxgiLib { + lib: libloading::Library, +} + +#[cfg(feature = "libloading")] +impl DxgiLib { + pub fn new() -> libloading::Result { + libloading::Library::new("dxgi.dll") + .map(|lib| DxgiLib { + lib, + }) + } + + pub fn create_factory2( + &self, flags: FactoryCreationFlags + ) -> libloading::Result> { + 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 get_debug_interface1(&self) -> libloading::Result> { + 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 Factory2 { + // TODO: interface not complete + pub fn create_swapchain_for_hwnd( + &self, + queue: CommandQueue, + hwnd: HWND, + desc: &SwapchainDesc, + ) -> D3DResult { + let desc = dxgi1_2::DXGI_SWAP_CHAIN_DESC1 { + AlphaMode: desc.alpha_mode as _, + BufferCount: desc.buffer_count, + Width: desc.width, + Height: desc.height, + Format: desc.format, + Flags: desc.flags, + BufferUsage: desc.buffer_usage, + SampleDesc: dxgitype::DXGI_SAMPLE_DESC { + Count: desc.sample.count, + Quality: desc.sample.quality, + }, + Scaling: desc.scaling as _, + Stereo: desc.stereo as _, + SwapEffect: desc.swap_effect as _, + }; + + let mut swap_chain = SwapChain1::null(); + let hr = unsafe { + self.CreateSwapChainForHwnd( + queue.as_mut_ptr() as *mut _, + hwnd, + &desc, + ptr::null(), + ptr::null_mut(), + swap_chain.mut_void() as *mut *mut _, + ) + }; + + (swap_chain, hr) + } +} + +impl Factory4 { + #[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 as_factory2(&self) -> Factory2 { + unsafe { Factory2::from_raw(self.as_mut_ptr() as *mut _) } + } + + pub fn enumerate_adapters(&self, id: u32) -> D3DResult { + let mut adapter = Adapter1::null(); + let hr = unsafe { self.EnumAdapters1(id, adapter.mut_void() as *mut *mut _) }; + + (adapter, hr) + } +} + +impl SwapChain { + pub fn get_buffer(&self, id: u32) -> D3DResult { + let mut resource = Resource::null(); + let hr = + unsafe { self.GetBuffer(id, &d3d12::ID3D12Resource::uuidof(), resource.mut_void()) }; + + (resource, hr) + } + + // TODO: present flags + pub fn present(&self, interval: u32, flags: u32) -> HRESULT { + unsafe { self.Present(interval, flags) } + } +} + +impl SwapChain1 { + pub fn as_swapchain0(&self) -> SwapChain { + unsafe { SwapChain::from_raw(self.as_mut_ptr() as *mut _) } + } +} + +impl SwapChain3 { + pub fn as_swapchain0(&self) -> SwapChain { + unsafe { SwapChain::from_raw(self.as_mut_ptr() as *mut _) } + } + + pub fn get_current_back_buffer_index(&self) -> u32 { + unsafe { self.GetCurrentBackBufferIndex() } + } +} diff --git a/third_party/rust/d3d12/src/heap.rs b/third_party/rust/d3d12/src/heap.rs new file mode 100644 index 0000000000..acf0aead11 --- /dev/null +++ b/third_party/rust/d3d12/src/heap.rs @@ -0,0 +1,86 @@ +use com::WeakPtr; +use winapi::um::d3d12; + +pub type Heap = WeakPtr; + +#[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! { + 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/third_party/rust/d3d12/src/lib.rs b/third_party/rust/d3d12/src/lib.rs new file mode 100644 index 0000000000..97691ee2eb --- /dev/null +++ b/third_party/rust/d3d12/src/lib.rs @@ -0,0 +1,101 @@ +extern crate winapi; +#[macro_use] +extern crate bitflags; + +use std::ffi::CStr; +use winapi::shared::dxgiformat; +use winapi::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; + +/// 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)] +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, +} + +pub type Blob = self::com::WeakPtr; + +pub type Error = self::com::WeakPtr; +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() -> libloading::Result { + libloading::Library::new("d3d12.dll") + .map(|lib| D3D12Lib { + lib, + }) + } +} diff --git a/third_party/rust/d3d12/src/pso.rs b/third_party/rust/d3d12/src/pso.rs new file mode 100644 index 0000000000..cab647a73f --- /dev/null +++ b/third_party/rust/d3d12/src/pso.rs @@ -0,0 +1,164 @@ +//! Pipeline state + +use com::WeakPtr; +use std::ops::Deref; +use std::{ffi, ptr}; +use winapi::um::{d3d12, d3dcompiler}; +use {Blob, D3DResult, Error}; + +bitflags! { + pub struct PipelineStateFlags: u32 { + const TOOL_DEBUG = d3d12::D3D12_PIPELINE_STATE_FLAG_TOOL_DEBUG; + } +} + +bitflags! { + 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(d3d12::D3D12_SHADER_BYTECODE); +impl Shader { + pub fn null() -> Self { + Shader(d3d12::D3D12_SHADER_BYTECODE { + BytecodeLength: 0, + pShaderBytecode: ptr::null(), + }) + } + + // `blob` may not be null. + pub fn from_blob(blob: Blob) -> Self { + Shader(d3d12::D3D12_SHADER_BYTECODE { + BytecodeLength: unsafe { blob.GetBufferSize() }, + pShaderBytecode: unsafe { blob.GetBufferPointer() }, + }) + } + + /// 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 Deref for Shader { + type Target = d3d12::D3D12_SHADER_BYTECODE; + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl From> for Shader { + fn from(blob: Option) -> Self { + match blob { + Some(b) => Shader::from_blob(b), + None => Shader::null(), + } + } +} + +#[derive(Copy, Clone)] +pub struct CachedPSO(d3d12::D3D12_CACHED_PIPELINE_STATE); +impl CachedPSO { + pub fn null() -> Self { + CachedPSO(d3d12::D3D12_CACHED_PIPELINE_STATE { + CachedBlobSizeInBytes: 0, + pCachedBlob: ptr::null(), + }) + } + + // `blob` may not be null. + pub fn from_blob(blob: Blob) -> Self { + CachedPSO(d3d12::D3D12_CACHED_PIPELINE_STATE { + CachedBlobSizeInBytes: unsafe { blob.GetBufferSize() }, + pCachedBlob: unsafe { blob.GetBufferPointer() }, + }) + } +} + +impl Deref for CachedPSO { + type Target = d3d12::D3D12_CACHED_PIPELINE_STATE; + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +pub type PipelineState = WeakPtr; + +#[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/third_party/rust/d3d12/src/query.rs b/third_party/rust/d3d12/src/query.rs new file mode 100644 index 0000000000..662fc8084a --- /dev/null +++ b/third_party/rust/d3d12/src/query.rs @@ -0,0 +1,15 @@ +use com::WeakPtr; +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, + // VideoDecodeStatistcs = d3d12::D3D12_QUERY_HEAP_TYPE_VIDEO_DECODE_STATISTICS, + // CopyQueueTimestamp = d3d12::D3D12_QUERY_HEAP_TYPE_COPY_QUEUE_TIMESTAMP, +} + +pub type QueryHeap = WeakPtr; diff --git a/third_party/rust/d3d12/src/queue.rs b/third_party/rust/d3d12/src/queue.rs new file mode 100644 index 0000000000..346b9af6ca --- /dev/null +++ b/third_party/rust/d3d12/src/queue.rs @@ -0,0 +1,34 @@ +use crate::CommandList; +use com::WeakPtr; +use sync::Fence; +use winapi::um::d3d12; +use HRESULT; + +#[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! { + pub struct CommandQueueFlags: u32 { + const DISABLE_GPU_TIMEOUT = d3d12::D3D12_COMMAND_QUEUE_FLAG_DISABLE_GPU_TIMEOUT; + } +} + +pub type CommandQueue = WeakPtr; + +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/third_party/rust/d3d12/src/resource.rs b/third_party/rust/d3d12/src/resource.rs new file mode 100644 index 0000000000..c314e5a7c2 --- /dev/null +++ b/third_party/rust/d3d12/src/resource.rs @@ -0,0 +1,55 @@ +//! GPU Resource + +use com::WeakPtr; +use std::ops::Range; +use std::ptr; +use winapi::um::d3d12; +use {D3DResult, Rect}; + +pub type Subresource = u32; + +pub struct DiscardRegion<'a> { + pub rects: &'a [Rect], + pub subregions: Range, +} + +pub type Resource = WeakPtr; + +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/third_party/rust/d3d12/src/sync.rs b/third_party/rust/d3d12/src/sync.rs new file mode 100644 index 0000000000..75a4b26710 --- /dev/null +++ b/third_party/rust/d3d12/src/sync.rs @@ -0,0 +1,41 @@ +use com::WeakPtr; +use std::ptr; +use winapi::um::d3d12; +use winapi::um::{synchapi, winnt}; +use HRESULT; + +#[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 = WeakPtr; +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) } + } +} -- cgit v1.2.3