diff --git a/wgpu-hal/src/dx12/command.rs b/wgpu-hal/src/dx12/command.rs index ecd3a89ead..64e5c0e57a 100644 --- a/wgpu-hal/src/dx12/command.rs +++ b/wgpu-hal/src/dx12/command.rs @@ -170,13 +170,21 @@ impl crate::CommandEncoder for super::CommandEncoder { } } - unsafe fn fill_buffer( - &mut self, - _buffer: &super::Buffer, - _range: crate::MemoryRange, - _value: u8, - ) { - //TODO + unsafe fn fill_buffer(&mut self, buffer: &super::Buffer, range: crate::MemoryRange, value: u8) { + assert_eq!(value, 0, "Only zero is supported!"); + let list = self.list.unwrap(); + let mut offset = range.start; + while offset < range.end { + let size = super::ZERO_BUFFER_SIZE.min(range.end - offset); + list.CopyBufferRegion( + buffer.resource.as_mut_ptr(), + offset, + self.zero_buffer.as_mut_ptr(), + 0, + size, + ); + offset += size; + } } unsafe fn copy_buffer_to_buffer( diff --git a/wgpu-hal/src/dx12/device.rs b/wgpu-hal/src/dx12/device.rs index ab3b97671d..cebf587262 100644 --- a/wgpu-hal/src/dx12/device.rs +++ b/wgpu-hal/src/dx12/device.rs @@ -1,6 +1,6 @@ use super::{conv, descriptor, HResult as _}; use parking_lot::Mutex; -use std::{mem, ptr, sync::Arc}; +use std::{mem, ptr, slice, sync::Arc}; use winapi::{ shared::{dxgiformat, dxgitype, winerror}, um::{d3d12, d3d12sdklayers, synchapi, winbase}, @@ -30,6 +30,53 @@ impl super::Device { }; hr.into_device_result("Idle fence creation")?; + let mut zero_buffer = native::Resource::null(); + unsafe { + let raw_desc = d3d12::D3D12_RESOURCE_DESC { + Dimension: d3d12::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::D3D12_TEXTURE_LAYOUT_ROW_MAJOR, + Flags: d3d12::D3D12_RESOURCE_FLAG_DENY_SHADER_RESOURCE, + }; + + let heap_properties = d3d12::D3D12_HEAP_PROPERTIES { + Type: d3d12::D3D12_HEAP_TYPE_CUSTOM, + CPUPageProperty: d3d12::D3D12_CPU_PAGE_PROPERTY_WRITE_COMBINE, + MemoryPoolPreference: d3d12::D3D12_MEMORY_POOL_L0, + CreationNodeMask: 0, + VisibleNodeMask: 0, + }; + + let hr = raw.CreateCommittedResource( + &heap_properties, + d3d12::D3D12_HEAP_FLAG_NONE, + &raw_desc, + d3d12::D3D12_RESOURCE_STATE_COMMON, + ptr::null(), + &d3d12::ID3D12Resource::uuidof(), + zero_buffer.mut_void(), + ); + + hr.into_device_result("Zero buffer creation")?; + + let range = d3d12::D3D12_RANGE { Begin: 0, End: 0 }; + let mut ptr = std::ptr::null_mut(); + (*zero_buffer) + .Map(0, &range, &mut ptr) + .into_device_result("Map zero buffer")?; + slice::from_raw_parts_mut(ptr as *mut u8, super::ZERO_BUFFER_SIZE as usize).fill(0); + (*zero_buffer).Unmap(0, &range); + }; + Ok(super::Device { raw, present_queue, @@ -54,6 +101,7 @@ impl super::Device { raw, native::DescriptorHeapType::Sampler, )), + zero_buffer, library: Arc::clone(library), }) } @@ -424,6 +472,7 @@ impl crate::Device for super::Device { self.dsv_pool.into_inner().destroy(); self.srv_uav_pool.into_inner().destroy(); self.sampler_pool.into_inner().destroy(); + self.zero_buffer.destroy(); //self.descriptor_updater.lock().destroy(); @@ -701,6 +750,7 @@ impl crate::Device for super::Device { Ok(super::CommandEncoder { allocator, device: self.raw, + zero_buffer: self.zero_buffer, list: None, free_lists: Vec::new(), temp: super::Temp::default(), diff --git a/wgpu-hal/src/dx12/mod.rs b/wgpu-hal/src/dx12/mod.rs index 99764062a1..1db9aebdb3 100644 --- a/wgpu-hal/src/dx12/mod.rs +++ b/wgpu-hal/src/dx12/mod.rs @@ -93,6 +93,8 @@ impl HResult for (T, i32) { } } +const ZERO_BUFFER_SIZE: wgt::BufferAddress = 256 << 10; + pub struct Instance { factory: native::Factory4, library: Arc, @@ -166,6 +168,8 @@ pub struct Device { dsv_pool: Mutex, srv_uav_pool: Mutex, sampler_pool: Mutex, + // aux resources + zero_buffer: native::Resource, // library library: Arc, } @@ -194,6 +198,7 @@ impl Temp { pub struct CommandEncoder { allocator: native::CommandAllocator, device: native::Device, + zero_buffer: native::Resource, list: Option, free_lists: Vec, temp: Temp,