mirror of
https://github.com/gfx-rs/wgpu.git
synced 2025-12-08 21:26:17 +00:00
dx12: switch root parameter updates from eager to lazy
This commit is contained in:
parent
3f42b59ccc
commit
c9fdaef3e1
@ -9,7 +9,7 @@ members = [
|
|||||||
"wgpu-info",
|
"wgpu-info",
|
||||||
"wgpu-types",
|
"wgpu-types",
|
||||||
]
|
]
|
||||||
default-members = ["wgpu", "player", "wgpu-hal", "wgpu-info"]
|
default-members = ["wgpu", "wgpu-hal", "wgpu-info"]
|
||||||
|
|
||||||
[patch."https://github.com/gfx-rs/naga"]
|
[patch."https://github.com/gfx-rs/naga"]
|
||||||
#naga = { path = "../naga" }
|
#naga = { path = "../naga" }
|
||||||
|
|||||||
@ -31,6 +31,8 @@ impl super::CommandEncoder {
|
|||||||
list.BeginEvent(0, wide_label.as_ptr() as *const _, size);
|
list.BeginEvent(0, wide_label.as_ptr() as *const _, size);
|
||||||
self.pass.has_label = true;
|
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, self.shared.heap_samplers.raw]);
|
list.set_descriptor_heaps(&[self.shared.heap_views.raw, self.shared.heap_samplers.raw]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -63,24 +65,33 @@ impl super::CommandEncoder {
|
|||||||
_ => true,
|
_ => true,
|
||||||
};
|
};
|
||||||
if needs_update {
|
if needs_update {
|
||||||
|
self.pass.dirty_root_elements |= 1 << root_index;
|
||||||
self.pass.root_elements[root_index as usize] =
|
self.pass.root_elements[root_index as usize] =
|
||||||
super::RootElement::SpecialConstantBuffer {
|
super::RootElement::SpecialConstantBuffer {
|
||||||
base_vertex,
|
base_vertex,
|
||||||
base_instance,
|
base_instance,
|
||||||
};
|
};
|
||||||
list.set_graphics_root_constant(root_index, base_vertex as u32, 0);
|
|
||||||
list.set_graphics_root_constant(root_index, base_instance, 1);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
self.update_root_elements();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_root_elements(&self, range: Range<super::RootIndex>) {
|
fn prepare_dispatch(&mut self) {
|
||||||
|
self.update_root_elements();
|
||||||
|
}
|
||||||
|
|
||||||
|
//Note: we have to call this lazily before draw calls. Otherwise, D3D complains
|
||||||
|
// about the root parameters being incompatible with root signature.
|
||||||
|
fn update_root_elements(&mut self) {
|
||||||
use super::{BufferViewKind as Bvk, PassKind as Pk};
|
use super::{BufferViewKind as Bvk, PassKind as Pk};
|
||||||
|
|
||||||
|
while self.pass.dirty_root_elements != 0 {
|
||||||
let list = self.list.unwrap();
|
let list = self.list.unwrap();
|
||||||
for index in range {
|
let index = self.pass.dirty_root_elements.trailing_zeros();
|
||||||
|
self.pass.dirty_root_elements ^= 1 << index;
|
||||||
|
|
||||||
match self.pass.root_elements[index as usize] {
|
match self.pass.root_elements[index as usize] {
|
||||||
super::RootElement::Empty => {}
|
super::RootElement::Empty => log::error!("Root index {} is not bound", index),
|
||||||
super::RootElement::SpecialConstantBuffer {
|
super::RootElement::SpecialConstantBuffer {
|
||||||
base_vertex,
|
base_vertex,
|
||||||
base_instance,
|
base_instance,
|
||||||
@ -133,7 +144,7 @@ impl super::CommandEncoder {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
self.pass.layout = layout.clone();
|
self.pass.layout = layout.clone();
|
||||||
self.update_root_elements(0..layout.total_root_elements);
|
self.pass.dirty_root_elements = (1 << layout.total_root_elements) - 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -695,8 +706,7 @@ impl crate::CommandEncoder<super::Api> for super::CommandEncoder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if self.pass.layout.signature == layout.shared.signature {
|
if self.pass.layout.signature == layout.shared.signature {
|
||||||
let update_range = info.base_root_index..root_index as super::RootIndex;
|
self.pass.dirty_root_elements |= (1 << root_index) - (1 << info.base_root_index);
|
||||||
self.update_root_elements(update_range);
|
|
||||||
} else {
|
} else {
|
||||||
// D3D12 requires full reset on signature change
|
// D3D12 requires full reset on signature change
|
||||||
self.reset_signature(&layout.shared);
|
self.reset_signature(&layout.shared);
|
||||||
@ -924,6 +934,7 @@ impl crate::CommandEncoder<super::Api> for super::CommandEncoder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn dispatch(&mut self, count: [u32; 3]) {
|
unsafe fn dispatch(&mut self, count: [u32; 3]) {
|
||||||
|
self.prepare_dispatch();
|
||||||
self.list.unwrap().dispatch(count);
|
self.list.unwrap().dispatch(count);
|
||||||
}
|
}
|
||||||
unsafe fn dispatch_indirect(&mut self, buffer: &super::Buffer, offset: wgt::BufferAddress) {
|
unsafe fn dispatch_indirect(&mut self, buffer: &super::Buffer, offset: wgt::BufferAddress) {
|
||||||
|
|||||||
@ -810,15 +810,14 @@ impl crate::Device<super::Api> for super::Device {
|
|||||||
wgt::BindingType::Buffer {
|
wgt::BindingType::Buffer {
|
||||||
has_dynamic_offset: true,
|
has_dynamic_offset: true,
|
||||||
..
|
..
|
||||||
}
|
} => continue,
|
||||||
| wgt::BindingType::Sampler { .. } => continue,
|
|
||||||
ref other => conv::map_binding_type(other),
|
ref other => conv::map_binding_type(other),
|
||||||
};
|
};
|
||||||
let bt = match range_ty {
|
let bt = match range_ty {
|
||||||
native::DescriptorRangeType::CBV => &mut bind_cbv,
|
native::DescriptorRangeType::CBV => &mut bind_cbv,
|
||||||
native::DescriptorRangeType::SRV => &mut bind_srv,
|
native::DescriptorRangeType::SRV => &mut bind_srv,
|
||||||
native::DescriptorRangeType::UAV => &mut bind_uav,
|
native::DescriptorRangeType::UAV => &mut bind_uav,
|
||||||
native::DescriptorRangeType::Sampler => unreachable!(),
|
native::DescriptorRangeType::Sampler => continue,
|
||||||
};
|
};
|
||||||
|
|
||||||
binding_map.insert(
|
binding_map.insert(
|
||||||
|
|||||||
@ -305,11 +305,17 @@ struct PassState {
|
|||||||
resolves: ArrayVec<PassResolve, { crate::MAX_COLOR_TARGETS }>,
|
resolves: ArrayVec<PassResolve, { crate::MAX_COLOR_TARGETS }>,
|
||||||
layout: PipelineLayoutShared,
|
layout: PipelineLayoutShared,
|
||||||
root_elements: [RootElement; MAX_ROOT_ELEMENTS],
|
root_elements: [RootElement; MAX_ROOT_ELEMENTS],
|
||||||
|
dirty_root_elements: u64,
|
||||||
vertex_buffers: [d3d12::D3D12_VERTEX_BUFFER_VIEW; crate::MAX_VERTEX_BUFFERS],
|
vertex_buffers: [d3d12::D3D12_VERTEX_BUFFER_VIEW; crate::MAX_VERTEX_BUFFERS],
|
||||||
dirty_vertex_buffers: usize,
|
dirty_vertex_buffers: usize,
|
||||||
kind: PassKind,
|
kind: PassKind,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_dirty_mask() {
|
||||||
|
assert_eq!(MAX_ROOT_ELEMENTS, std::mem::size_of::<u64>() * 8);
|
||||||
|
}
|
||||||
|
|
||||||
impl PassState {
|
impl PassState {
|
||||||
fn new() -> Self {
|
fn new() -> Self {
|
||||||
PassState {
|
PassState {
|
||||||
@ -321,6 +327,7 @@ impl PassState {
|
|||||||
special_constants_root_index: None,
|
special_constants_root_index: None,
|
||||||
},
|
},
|
||||||
root_elements: [RootElement::Empty; MAX_ROOT_ELEMENTS],
|
root_elements: [RootElement::Empty; MAX_ROOT_ELEMENTS],
|
||||||
|
dirty_root_elements: 0,
|
||||||
vertex_buffers: [unsafe { mem::zeroed() }; crate::MAX_VERTEX_BUFFERS],
|
vertex_buffers: [unsafe { mem::zeroed() }; crate::MAX_VERTEX_BUFFERS],
|
||||||
dirty_vertex_buffers: 0,
|
dirty_vertex_buffers: 0,
|
||||||
kind: PassKind::Transfer,
|
kind: PassKind::Transfer,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user