Skip to content

Commit

Permalink
[dx12] introduce the workarounds, move the descriptor updater
Browse files Browse the repository at this point in the history
  • Loading branch information
kvark committed Oct 25, 2020
1 parent 58f8dcf commit 2186b1c
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 65 deletions.
57 changes: 57 additions & 0 deletions src/backend/dx12/src/descriptors_cpu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -246,3 +246,60 @@ impl MultiCopyAccumulator {
}
}
}

pub struct DescriptorUpdater {
heaps: Vec<HeapLinear>,
heap_index: usize,
reset_heap_index: usize,
avoid_overwrite: bool,
}

impl DescriptorUpdater {
pub fn new(device: native::Device, avoid_overwrite: bool) -> Self {
DescriptorUpdater {
heaps: vec![Self::create_heap(device)],
heap_index: 0,
reset_heap_index: 0,
avoid_overwrite,
}
}

pub unsafe fn destroy(&mut self) {
for heap in self.heaps.drain(..) {
heap.destroy();
}
}

pub fn reset(&mut self) {
if self.avoid_overwrite {
self.reset_heap_index = self.heap_index;
} else {
self.heap_index = 0;
for heap in self.heaps.iter_mut() {
heap.clear();
}
}
}

fn create_heap(device: native::Device) -> HeapLinear {
let size = 1 << 12; //arbitrary
HeapLinear::new(device, native::DescriptorHeapType::CbvSrvUav, size)
}

pub fn alloc_handle(&mut self, device: native::Device) -> CpuDescriptor {
if self.heaps[self.heap_index].is_full() {
self.heap_index += 1;
if self.heap_index == self.heaps.len() {
self.heap_index = 0;
}
if self.heap_index == self.reset_heap_index {
let heap = Self::create_heap(device);
self.heaps.insert(self.heap_index, heap);
self.reset_heap_index += 1;
} else {
self.heaps[self.heap_index].clear();
}
}
self.heaps[self.heap_index].alloc_handle()
}
}
11 changes: 7 additions & 4 deletions src/backend/dx12/src/device.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2290,7 +2290,10 @@ impl d::Device<B> for Device {
let buffer = buffer.expect_bound();
let buffer_features = {
let idx = format.map(|fmt| fmt as usize).unwrap_or(0);
self.format_properties.get(idx).properties.buffer_features
self.format_properties
.resolve(idx)
.properties
.buffer_features
};
let (format, format_desc) = match format.and_then(conv::map_format) {
Some(fmt) => (fmt, format.unwrap().surface_desc()),
Expand Down Expand Up @@ -2385,7 +2388,7 @@ impl d::Device<B> for Device {
let view_format = conv::map_format(format);
let extent = kind.extent();

let format_info = self.format_properties.get(format as usize);
let format_info = self.format_properties.resolve(format as usize);
let (layout, features) = match tiling {
image::Tiling::Optimal => (
d3d12::D3D12_TEXTURE_LAYOUT_UNKNOWN,
Expand Down Expand Up @@ -2568,7 +2571,7 @@ impl d::Device<B> for Device {
// if the format supports being rendered into, allowing us to create clear_Xv
let format_properties = self
.format_properties
.get(image_unbound.format as usize)
.resolve(image_unbound.format as usize)
.properties;
let props = match image_unbound.tiling {
image::Tiling::Optimal => format_properties.optimal_tiling,
Expand Down Expand Up @@ -2898,7 +2901,7 @@ impl d::Device<B> for Device {
J: IntoIterator,
J::Item: Borrow<pso::Descriptor<'a, B>>,
{
let mut descriptor_updater = self.descriptor_updater.lock().unwrap();
let mut descriptor_updater = self.descriptor_updater.lock();
descriptor_updater.reset();

let mut accum = descriptors_cpu::MultiCopyAccumulator::default();
Expand Down
84 changes: 23 additions & 61 deletions src/backend/dx12/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,13 @@ static QUEUE_FAMILIES: [QueueFamily; 4] = [
QueueFamily::Normal(q::QueueType::Transfer),
];

#[derive(Default)]
struct Workarounds {
// On WARP, temporary CPU descriptors are still used by the runtime
// after we call `CopyDescriptors`.
avoid_cpu_descriptor_overwrites: bool,
}

//Note: fields are dropped in the order of declaration, so we put the
// most owning fields last.
pub struct PhysicalDevice {
Expand All @@ -187,6 +194,7 @@ pub struct PhysicalDevice {
limits: Limits,
format_properties: Arc<FormatProperties>,
private_caps: Capabilities,
workarounds: Workarounds,
heap_properties: &'static [HeapProperties; NUM_HEAP_PROPERTIES],
memory_properties: adapter::MemoryProperties,
// Indicates that there is currently an active logical device.
Expand Down Expand Up @@ -306,7 +314,7 @@ impl adapter::PhysicalDevice<Backend> for PhysicalDevice {

fn format_properties(&self, fmt: Option<f::Format>) -> f::Properties {
let idx = fmt.map(|fmt| fmt as usize).unwrap_or(0);
self.format_properties.get(idx).properties
self.format_properties.resolve(idx).properties
}

fn image_format_properties(
Expand All @@ -318,7 +326,7 @@ impl adapter::PhysicalDevice<Backend> for PhysicalDevice {
view_caps: image::ViewCapabilities,
) -> Option<image::FormatProperties> {
conv::map_format(format)?; //filter out unknown formats
let format_info = self.format_properties.get(format as usize);
let format_info = self.format_properties.resolve(format as usize);

let supported_usage = {
use hal::image::Usage as U;
Expand Down Expand Up @@ -566,61 +574,6 @@ impl SamplerStorage {
}
}

struct DescriptorUpdater {
heaps: Vec<descriptors_cpu::HeapLinear>,
heap_index: usize,
reset_heap_index: usize,
}

impl DescriptorUpdater {
fn new(device: native::Device) -> Self {
DescriptorUpdater {
heaps: vec![Self::create_heap(device)],
heap_index: 0,
reset_heap_index: 0,
}
}

unsafe fn destroy(&mut self) {
for heap in self.heaps.drain(..) {
heap.destroy();
}
}

fn reset(&mut self) {
self.reset_heap_index = self.heap_index;
// Note: this could clear all the heaps, but WARP has an issue with that
if false {
for heap in self.heaps.iter_mut() {
heap.clear();
}
}
}

fn create_heap(device: native::Device) -> descriptors_cpu::HeapLinear {
let size = 1 << 12; //arbitrary
descriptors_cpu::HeapLinear::new(device, native::DescriptorHeapType::CbvSrvUav, size)
}

fn alloc_handle(&mut self, device: native::Device) -> native::CpuDescriptor {
if self.heaps[self.heap_index].is_full() {
self.heap_index += 1;
if self.heap_index == self.heaps.len() {
self.heap_index = 0;
}
if self.heap_index == self.reset_heap_index {
let heap = Self::create_heap(device);
self.heaps.insert(self.heap_index, heap);
self.reset_heap_index += 1;
} else {
self.heaps[self.heap_index].clear();
}
}
self.heaps[self.heap_index].alloc_handle()
}
}


pub struct Device {
raw: native::Device,
private_caps: Capabilities,
Expand All @@ -631,7 +584,7 @@ pub struct Device {
rtv_pool: Mutex<DescriptorCpuPool>,
dsv_pool: Mutex<DescriptorCpuPool>,
srv_uav_pool: Mutex<DescriptorCpuPool>,
descriptor_updater: Mutex<DescriptorUpdater>,
descriptor_updater: Mutex<descriptors_cpu::DescriptorUpdater>,
// CPU/GPU descriptor heaps
heap_srv_cbv_uav: (
resource::DescriptorHeap,
Expand Down Expand Up @@ -689,6 +642,11 @@ impl Device {
2_048,
);

let descriptor_updater = descriptors_cpu::DescriptorUpdater::new(
device,
physical_device.workarounds.avoid_cpu_descriptor_overwrites,
);

let draw_signature = Self::create_command_signature(device, device::CommandSignature::Draw);
let draw_indexed_signature =
Self::create_command_signature(device, device::CommandSignature::DrawIndexed);
Expand Down Expand Up @@ -717,7 +675,7 @@ impl Device {
rtv_pool: Mutex::new(rtv_pool),
dsv_pool: Mutex::new(dsv_pool),
srv_uav_pool: Mutex::new(srv_uav_pool),
descriptor_updater: Mutex::new(DescriptorUpdater::new(device)),
descriptor_updater: Mutex::new(descriptor_updater),
heap_srv_cbv_uav: (heap_srv_cbv_uav, Mutex::new(view_range_allocator)),
samplers: SamplerStorage {
map: Mutex::default(),
Expand Down Expand Up @@ -762,7 +720,7 @@ impl Drop for Device {
self.dsv_pool.lock().destroy();
self.srv_uav_pool.lock().destroy();

self.descriptor_updater.lock().unwrap().destroy();
self.descriptor_updater.lock().destroy();

// Debug tracking alive objects
let (debug_device, hr_debug) = self.raw.cast::<d3d12sdklayers::ID3D12DebugDevice>();
Expand Down Expand Up @@ -941,11 +899,14 @@ impl hal::Instance<Backend> for Instance {
)
});

let mut workarounds = Workarounds::default();

let info = adapter::AdapterInfo {
name: device_name,
vendor: desc.VendorId as usize,
device: desc.DeviceId as usize,
device_type: if (desc.Flags & dxgi::DXGI_ADAPTER_FLAG_SOFTWARE) != 0 {
workarounds.avoid_cpu_descriptor_overwrites = true;
adapter::DeviceType::VirtualGpu
} else if features_architecture.CacheCoherentUMA == TRUE {
adapter::DeviceType::IntegratedGpu
Expand Down Expand Up @@ -1274,6 +1235,7 @@ impl hal::Instance<Backend> for Instance {
heterogeneous_resource_heaps,
memory_architecture,
},
workarounds,
heap_properties,
memory_properties: adapter::MemoryProperties {
memory_types,
Expand Down Expand Up @@ -1389,7 +1351,7 @@ impl FormatProperties {
}
}

fn get(&self, idx: usize) -> FormatInfo {
fn resolve(&self, idx: usize) -> FormatInfo {
let mut guard = self.info[idx].lock();
if let Some(info) = *guard {
return info;
Expand Down

0 comments on commit 2186b1c

Please sign in to comment.