Skip to content

Commit

Permalink
Stick gpu-allocator behind a feature until gfx-rs#3207 lands
Browse files Browse the repository at this point in the history
  • Loading branch information
Elabajaba committed Nov 26, 2022
1 parent a782dfc commit 2ee1a41
Show file tree
Hide file tree
Showing 4 changed files with 220 additions and 5 deletions.
4 changes: 3 additions & 1 deletion wgpu-hal/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,9 @@ metal = ["naga/msl-out", "block", "foreign-types"]
vulkan = ["naga/spv-out", "ash", "gpu-alloc", "gpu-descriptor", "libloading", "smallvec"]
gles = ["naga/glsl-out", "glow", "egl", "libloading"]
dx11 = ["naga/hlsl-out", "native", "libloading", "winapi/d3d11", "winapi/d3d11_1", "winapi/d3d11_2", "winapi/d3d11sdklayers", "winapi/dxgi1_6"]
dx12 = ["naga/hlsl-out", "native", "bit-set", "range-alloc", "winapi/d3d12", "winapi/d3d12shader", "winapi/d3d12sdklayers", "winapi/dxgi1_6", "gpu-allocator"]
dx12 = ["naga/hlsl-out", "native", "bit-set", "range-alloc", "winapi/d3d12", "winapi/d3d12shader", "winapi/d3d12sdklayers", "winapi/dxgi1_6"]
# 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 = ["gpu-allocator"]
renderdoc = ["libloading", "renderdoc-sys"]
emscripten = ["gles"]

Expand Down
2 changes: 1 addition & 1 deletion wgpu-hal/src/dx12/adapter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ impl super::Adapter {
} else {
super::MemoryArchitecture::NonUnified
},
_heap_create_not_zeroed: false, //TODO: winapi support for Options7
heap_create_not_zeroed: false, //TODO: winapi support for Options7
};

// Theoretically vram limited, but in practice 2^20 is the limit
Expand Down
208 changes: 207 additions & 1 deletion wgpu-hal/src/dx12/device.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ use winapi::{
Interface,
};

#[cfg(not(feature = "windows_rs"))]
use winapi::um::d3d12::D3D12_RESOURCE_DESC;

#[cfg(feature = "windows_rs")]
use gpu_allocator::{
d3d12::{winapi_d3d12::D3D12_RESOURCE_DESC, AllocationCreateDesc, ToWinapi, ToWindows},
MemoryLocation,
Expand All @@ -21,7 +25,8 @@ use gpu_allocator::{
const NAGA_LOCATION_SEMANTIC: &[u8] = b"LOC\0";
// TODO: find the exact value
// TODO: figure out if this is even needed?
const _D3D12_HEAP_FLAG_CREATE_NOT_ZEROED: u32 = d3d12::D3D12_HEAP_FLAG_NONE;
#[allow(unused)] // TODO: Exists until windows-rs is standard, then it can probably be removed?
const D3D12_HEAP_FLAG_CREATE_NOT_ZEROED: u32 = d3d12::D3D12_HEAP_FLAG_NONE;

impl super::Device {
pub(super) fn new(
Expand All @@ -30,6 +35,7 @@ impl super::Device {
private_caps: super::PrivateCapabilities,
library: &Arc<native::D3D12Lib>,
) -> Result<Self, crate::DeviceError> {
#[cfg(feature = "windows_rs")]
let mem_allocator = {
let device = raw.as_ptr();

Expand Down Expand Up @@ -183,6 +189,7 @@ impl super::Device {
#[cfg(feature = "renderdoc")]
render_doc: Default::default(),
null_rtv_handle,
#[cfg(feature = "windows_rs")]
mem_allocator: Mutex::new(mem_allocator),
})
}
Expand Down Expand Up @@ -331,6 +338,7 @@ impl super::Device {
size,
mip_level_count,
sample_count,
#[cfg(feature = "windows_rs")]
allocation: None,
}
}
Expand All @@ -348,6 +356,7 @@ impl crate::Device<super::Api> for super::Device {
unsafe { queue.raw.destroy() };
}

#[cfg(feature = "windows_rs")]
unsafe fn create_buffer(
&self,
desc: &crate::BufferDescriptor,
Expand Down Expand Up @@ -419,6 +428,83 @@ impl crate::Device<super::Api> for super::Device {
allocation: Some(allocation),
})
}

#[cfg(not(feature = "windows_rs"))]
unsafe fn create_buffer(
&self,
desc: &crate::BufferDescriptor,
) -> Result<super::Buffer, crate::DeviceError> {
let mut resource = native::Resource::null();
let mut size = desc.size;
if desc.usage.contains(crate::BufferUses::UNIFORM) {
let align_mask = d3d12::D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT as u64 - 1;
size = ((size - 1) | align_mask) + 1;
}

let raw_desc = D3D12_RESOURCE_DESC {
Dimension: d3d12::D3D12_RESOURCE_DIMENSION_BUFFER,
Alignment: 0,
Width: 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: conv::map_buffer_usage_to_resource_flags(desc.usage),
};

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::D3D12_HEAP_PROPERTIES {
Type: d3d12::D3D12_HEAP_TYPE_CUSTOM,
CPUPageProperty: if is_cpu_read {
d3d12::D3D12_CPU_PAGE_PROPERTY_WRITE_BACK
} else if is_cpu_write {
d3d12::D3D12_CPU_PAGE_PROPERTY_WRITE_COMBINE
} else {
d3d12::D3D12_CPU_PAGE_PROPERTY_NOT_AVAILABLE
},
MemoryPoolPreference: match self.private_caps.memory_architecture {
super::MemoryArchitecture::NonUnified if !is_cpu_read && !is_cpu_write => {
d3d12::D3D12_MEMORY_POOL_L1
}
_ => d3d12::D3D12_MEMORY_POOL_L0,
},
CreationNodeMask: 0,
VisibleNodeMask: 0,
};

let hr = unsafe {
self.raw.CreateCommittedResource(
&heap_properties,
if self.private_caps.heap_create_not_zeroed {
D3D12_HEAP_FLAG_CREATE_NOT_ZEROED
} else {
d3d12::D3D12_HEAP_FLAG_NONE
},
&raw_desc,
d3d12::D3D12_RESOURCE_STATE_COMMON,
ptr::null(),
&d3d12::ID3D12Resource::uuidof(),
resource.mut_void(),
)
};

hr.into_device_result("Buffer creation")?;
if let Some(label) = desc.label {
let cwstr = conv::map_label(label);
unsafe { resource.SetName(cwstr.as_ptr()) };
}

Ok(super::Buffer { resource, size })
}

#[cfg(feature = "windows_rs")]
unsafe fn destroy_buffer(&self, mut buffer: super::Buffer) {
// TODO: Destroy or Release here?
unsafe { buffer.resource.destroy() };
Expand All @@ -430,6 +516,13 @@ impl crate::Device<super::Api> for super::Device {
};
}
}

#[cfg(not(feature = "windows_rs"))]
unsafe fn destroy_buffer(&self, buffer: super::Buffer) {
unsafe { buffer.resource.destroy() };
}

#[cfg(feature = "windows_rs")]
unsafe fn map_buffer(
&self,
buffer: &super::Buffer,
Expand All @@ -447,13 +540,41 @@ impl crate::Device<super::Api> for super::Device {
is_coherent: true,
})
}

#[cfg(not(feature = "windows_rs"))]
unsafe fn map_buffer(
&self,
buffer: &super::Buffer,
range: crate::MemoryRange,
) -> Result<crate::BufferMapping, crate::DeviceError> {
let mut ptr = ptr::null_mut();
let hr = unsafe { (*buffer.resource).Map(0, ptr::null(), &mut ptr) };
hr.into_device_result("Map buffer")?;
Ok(crate::BufferMapping {
ptr: ptr::NonNull::new(unsafe { ptr.offset(range.start as isize).cast::<u8>() })
.unwrap(),
//TODO: double-check this. Documentation is a bit misleading -
// it implies that Map/Unmap is needed to invalidate/flush memory.
is_coherent: true,
})
}

#[cfg(feature = "windows_rs")]
unsafe fn unmap_buffer(&self, buffer: &super::Buffer) -> Result<(), crate::DeviceError> {
unsafe { (*buffer.resource).Unmap(0, ptr::null()) };
Ok(())
}

#[cfg(not(feature = "windows_rs"))]
unsafe fn unmap_buffer(&self, buffer: &super::Buffer) -> Result<(), crate::DeviceError> {
unsafe { (*buffer.resource).Unmap(0, ptr::null()) };
Ok(())
}

unsafe fn flush_mapped_ranges<I>(&self, _buffer: &super::Buffer, _ranges: I) {}
unsafe fn invalidate_mapped_ranges<I>(&self, _buffer: &super::Buffer, _ranges: I) {}

#[cfg(feature = "windows_rs")]
unsafe fn create_texture(
&self,
desc: &crate::TextureDescriptor,
Expand Down Expand Up @@ -529,6 +650,86 @@ impl crate::Device<super::Api> for super::Device {
})
}

#[cfg(not(feature = "windows_rs"))]
unsafe fn create_texture(
&self,
desc: &crate::TextureDescriptor,
) -> Result<super::Texture, crate::DeviceError> {
let mut resource = native::Resource::null();

let raw_desc = D3D12_RESOURCE_DESC {
Dimension: conv::map_texture_dimension(desc.dimension),
Alignment: 0,
Width: desc.size.width as u64,
Height: desc.size.height,
DepthOrArraySize: desc.size.depth_or_array_layers as u16,
MipLevels: desc.mip_level_count as u16,
Format: if crate::FormatAspects::from(desc.format).contains(crate::FormatAspects::COLOR)
|| !desc.usage.intersects(
crate::TextureUses::RESOURCE
| crate::TextureUses::STORAGE_READ
| crate::TextureUses::STORAGE_READ_WRITE,
) {
auxil::dxgi::conv::map_texture_format(desc.format)
} else {
// This branch is needed if it's a depth texture, and it's ever needed to be viewed as SRV or UAV,
// because then we'd create a non-depth format view of it.
// Note: we can skip this branch if
// `D3D12_FEATURE_D3D12_OPTIONS3::CastingFullyTypedFormatSupported`
auxil::dxgi::conv::map_texture_format_depth_typeless(desc.format)
},
SampleDesc: dxgitype::DXGI_SAMPLE_DESC {
Count: desc.sample_count,
Quality: 0,
},
Layout: d3d12::D3D12_TEXTURE_LAYOUT_UNKNOWN,
Flags: conv::map_texture_usage_to_resource_flags(desc.usage),
};

let heap_properties = d3d12::D3D12_HEAP_PROPERTIES {
Type: d3d12::D3D12_HEAP_TYPE_CUSTOM,
CPUPageProperty: d3d12::D3D12_CPU_PAGE_PROPERTY_NOT_AVAILABLE,
MemoryPoolPreference: match self.private_caps.memory_architecture {
super::MemoryArchitecture::NonUnified => d3d12::D3D12_MEMORY_POOL_L1,
super::MemoryArchitecture::Unified { .. } => d3d12::D3D12_MEMORY_POOL_L0,
},
CreationNodeMask: 0,
VisibleNodeMask: 0,
};

let hr = unsafe {
self.raw.CreateCommittedResource(
&heap_properties,
if self.private_caps.heap_create_not_zeroed {
D3D12_HEAP_FLAG_CREATE_NOT_ZEROED
} else {
d3d12::D3D12_HEAP_FLAG_NONE
},
&raw_desc,
d3d12::D3D12_RESOURCE_STATE_COMMON,
ptr::null(), // clear value
&d3d12::ID3D12Resource::uuidof(),
resource.mut_void(),
)
};

hr.into_device_result("Texture creation")?;
if let Some(label) = desc.label {
let cwstr = conv::map_label(label);
unsafe { resource.SetName(cwstr.as_ptr()) };
}

Ok(super::Texture {
resource,
format: desc.format,
dimension: desc.dimension,
size: desc.size,
mip_level_count: desc.mip_level_count,
sample_count: desc.sample_count,
})
}

#[cfg(feature = "windows_rs")]
unsafe fn destroy_texture(&self, mut texture: super::Texture) {
unsafe { texture.resource.destroy() };
if let Some(alloc) = texture.allocation.take() {
Expand All @@ -539,6 +740,11 @@ impl crate::Device<super::Api> for super::Device {
}
}

#[cfg(not(feature = "windows_rs"))]
unsafe fn destroy_texture(&self, texture: super::Texture) {
unsafe { texture.resource.destroy() };
}

unsafe fn create_texture_view(
&self,
texture: &super::Texture,
Expand Down
11 changes: 9 additions & 2 deletions wgpu-hal/src/dx12/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ mod view;
use crate::auxil::{self, dxgi::result::HResult as _};

use arrayvec::ArrayVec;
use log::error;
use parking_lot::Mutex;
use std::{ffi, fmt, mem, num::NonZeroU32, sync::Arc};
use winapi::{
Expand Down Expand Up @@ -153,7 +152,8 @@ struct PrivateCapabilities {
#[allow(unused)]
heterogeneous_resource_heaps: bool,
memory_architecture: MemoryArchitecture,
_heap_create_not_zeroed: bool,
#[allow(unused)] // TODO: Exists until windows-rs is standard, then it can probably be removed?
heap_create_not_zeroed: bool,
}

#[derive(Default)]
Expand Down Expand Up @@ -238,6 +238,7 @@ pub struct Device {
#[cfg(feature = "renderdoc")]
render_doc: crate::auxil::renderdoc::RenderDoc,
null_rtv_handle: descriptor::Handle,
#[cfg(feature = "windows_rs")]
mem_allocator: Mutex<gpu_allocator::d3d12::Allocator>,
}

Expand Down Expand Up @@ -374,6 +375,7 @@ unsafe impl Sync for CommandBuffer {}
pub struct Buffer {
resource: native::Resource,
size: wgt::BufferAddress,
#[cfg(feature = "windows_rs")]
allocation: Option<gpu_allocator::d3d12::Allocation>,
}

Expand Down Expand Up @@ -401,6 +403,7 @@ pub struct Texture {
size: wgt::Extent3d,
mip_level_count: u32,
sample_count: u32,
#[cfg(feature = "windows_rs")]
allocation: Option<gpu_allocator::d3d12::Allocation>,
}

Expand Down Expand Up @@ -768,6 +771,7 @@ impl crate::Surface<Api> for Surface {
size: sc.size,
mip_level_count: 1,
sample_count: 1,
#[cfg(feature = "windows_rs")]
allocation: None,
};
Ok(Some(crate::AcquiredSurfaceTexture {
Expand Down Expand Up @@ -833,8 +837,11 @@ impl crate::Queue<Api> for Queue {
}
}

#[cfg(feature = "windows_rs")]
impl From<gpu_allocator::AllocationError> for crate::DeviceError {
fn from(result: gpu_allocator::AllocationError) -> Self {
use log::error;

match result {
gpu_allocator::AllocationError::OutOfMemory => Self::OutOfMemory,
gpu_allocator::AllocationError::FailedToMap(e) => {
Expand Down

0 comments on commit 2ee1a41

Please sign in to comment.