mirror of
https://github.com/gfx-rs/wgpu.git
synced 2024-11-26 08:44:08 +00:00
Merge #1731
1731: hal/dx12: support base vertex/instance r=cwfitzgerald a=kvark **Connections** Fixes #1725 Depends on https://github.com/gfx-rs/naga/pull/1141, https://github.com/gfx-rs/d3d12-rs/pull/34, and https://github.com/gfx-rs/d3d12-rs/pull/35 (thanks `@msiglreith` for quick reviews!). **Description** We allocate one root parameter covering the special constant buffer view with root constants. We set the root constants for each draw, but only on change. This PR does *not* handle the indirect case. I'll follow-up with this. **Testing** Not thoroughly tested, but `@cwfitzgerald` already implemented a test for this, and this PR enables it on DX12. Also, examples still seem to work :) Co-authored-by: Dzmitry Malyshau <kvarkus@gmail.com>
This commit is contained in:
commit
2940347ba3
5
Cargo.lock
generated
5
Cargo.lock
generated
@ -459,8 +459,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "d3d12"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "091ed1b25fe47c7ff129fc440c23650b6114f36aa00bc7212cc8041879294428"
|
||||
source = "git+https://github.com/gfx-rs/d3d12-rs?rev=79f29c8#79f29c8809d3dc4f97785815567e5efda20e639a"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"libloading 0.7.0",
|
||||
@ -965,7 +964,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "naga"
|
||||
version = "0.5.0"
|
||||
source = "git+https://github.com/gfx-rs/naga?rev=e97c8f9#e97c8f944121a58bbc908ecb64bdf97d4ada039d"
|
||||
source = "git+https://github.com/gfx-rs/naga?rev=a7ac13a#a7ac13a61d63620b8a0821db9176ed467fc282f7"
|
||||
dependencies = [
|
||||
"bit-set",
|
||||
"bitflags",
|
||||
|
@ -36,7 +36,7 @@ thiserror = "1"
|
||||
|
||||
[dependencies.naga]
|
||||
git = "https://github.com/gfx-rs/naga"
|
||||
rev = "e97c8f9"
|
||||
rev = "a7ac13a"
|
||||
features = ["wgsl-in"]
|
||||
|
||||
[dependencies.wgt]
|
||||
|
@ -1723,6 +1723,7 @@ impl<A: HalApi> Device<A> {
|
||||
.collect::<Vec<_>>();
|
||||
let hal_desc = hal::PipelineLayoutDescriptor {
|
||||
label: desc.label.borrow_option(),
|
||||
flags: hal::PipelineLayoutFlags::BASE_VERTEX_INSTANCE,
|
||||
bind_group_layouts: &bgl_vec,
|
||||
push_constant_ranges: desc.push_constant_ranges.as_ref(),
|
||||
};
|
||||
|
@ -47,7 +47,7 @@ glow = { git = "https://github.com/grovesNL/glow", rev = "0864897a28bbdd43f89f4f
|
||||
|
||||
# backend: Dx12
|
||||
bit-set = { version = "0.5", optional = true }
|
||||
native = { package = "d3d12", version = "0.4", features = ["libloading"], optional = true }
|
||||
native = { package = "d3d12", git = "https://github.com/gfx-rs/d3d12-rs", rev = "79f29c8", features = ["libloading"], optional = true }
|
||||
range-alloc = { version = "0.1", optional = true }
|
||||
|
||||
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
|
||||
@ -65,11 +65,11 @@ core-graphics-types = "0.1"
|
||||
|
||||
[dependencies.naga]
|
||||
git = "https://github.com/gfx-rs/naga"
|
||||
rev = "e97c8f9"
|
||||
rev = "a7ac13a"
|
||||
|
||||
[dev-dependencies.naga]
|
||||
git = "https://github.com/gfx-rs/naga"
|
||||
rev = "e97c8f9"
|
||||
rev = "a7ac13a"
|
||||
features = ["wgsl-in"]
|
||||
|
||||
[dev-dependencies]
|
||||
|
@ -199,6 +199,7 @@ impl<A: hal::Api> Example<A> {
|
||||
|
||||
let pipeline_layout_desc = hal::PipelineLayoutDescriptor {
|
||||
label: None,
|
||||
flags: hal::PipelineLayoutFlags::empty(),
|
||||
bind_group_layouts: &[&global_group_layout, &local_group_layout],
|
||||
push_constant_ranges: &[],
|
||||
};
|
||||
|
@ -43,7 +43,7 @@ impl super::CommandEncoder {
|
||||
self.pass.clear();
|
||||
}
|
||||
|
||||
unsafe fn prepare_draw(&mut self) {
|
||||
unsafe fn prepare_draw(&mut self, base_vertex: i32, base_instance: u32) {
|
||||
let list = self.list.unwrap();
|
||||
while self.pass.dirty_vertex_buffers != 0 {
|
||||
let index = self.pass.dirty_vertex_buffers.trailing_zeros();
|
||||
@ -54,6 +54,24 @@ impl super::CommandEncoder {
|
||||
self.pass.vertex_buffers.as_ptr().offset(index as isize),
|
||||
);
|
||||
}
|
||||
if let Some(root_index) = self.pass.layout.special_constants_root_index {
|
||||
let needs_update = match self.pass.root_elements[root_index as usize] {
|
||||
super::RootElement::SpecialConstantBuffer {
|
||||
base_vertex: other_vertex,
|
||||
base_instance: other_instance,
|
||||
} => base_vertex != other_vertex || base_instance != other_instance,
|
||||
_ => true,
|
||||
};
|
||||
if needs_update {
|
||||
self.pass.root_elements[root_index as usize] =
|
||||
super::RootElement::SpecialConstantBuffer {
|
||||
base_vertex,
|
||||
base_instance,
|
||||
};
|
||||
list.set_graphics_root_constant(root_index, base_vertex as u32, 0);
|
||||
list.set_graphics_root_constant(root_index, base_instance, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn update_root_elements(&self, range: Range<super::RootIndex>) {
|
||||
@ -63,6 +81,17 @@ impl super::CommandEncoder {
|
||||
for index in range {
|
||||
match self.pass.root_elements[index as usize] {
|
||||
super::RootElement::Empty => {}
|
||||
super::RootElement::SpecialConstantBuffer {
|
||||
base_vertex,
|
||||
base_instance,
|
||||
} => match self.pass.kind {
|
||||
Pk::Render => {
|
||||
list.set_graphics_root_constant(index, base_vertex as u32, 0);
|
||||
list.set_graphics_root_constant(index, base_instance, 1);
|
||||
}
|
||||
Pk::Compute => (),
|
||||
Pk::Transfer => (),
|
||||
},
|
||||
super::RootElement::Table(descriptor) => match self.pass.kind {
|
||||
Pk::Render => list.set_graphics_root_descriptor_table(index, descriptor),
|
||||
Pk::Compute => list.set_compute_root_descriptor_table(index, descriptor),
|
||||
@ -94,6 +123,18 @@ impl super::CommandEncoder {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn reset_signature(&mut self, layout: &super::PipelineLayoutShared) {
|
||||
if let Some(root_index) = layout.special_constants_root_index {
|
||||
self.pass.root_elements[root_index as usize] =
|
||||
super::RootElement::SpecialConstantBuffer {
|
||||
base_vertex: 0,
|
||||
base_instance: 0,
|
||||
};
|
||||
}
|
||||
self.pass.layout = layout.clone();
|
||||
self.update_root_elements(0..layout.total_root_elements);
|
||||
}
|
||||
}
|
||||
|
||||
impl crate::CommandEncoder<super::Api> for super::CommandEncoder {
|
||||
@ -653,14 +694,13 @@ impl crate::CommandEncoder<super::Api> for super::CommandEncoder {
|
||||
root_index += 1;
|
||||
}
|
||||
|
||||
let update_range = if self.pass.signature == layout.raw {
|
||||
info.base_root_index..root_index as super::RootIndex
|
||||
if self.pass.layout.signature == layout.shared.signature {
|
||||
let update_range = info.base_root_index..root_index as super::RootIndex;
|
||||
self.update_root_elements(update_range);
|
||||
} else {
|
||||
// D3D12 requires full reset on signature change
|
||||
self.pass.signature = layout.raw;
|
||||
0..layout.total_root_elements
|
||||
self.reset_signature(&layout.shared);
|
||||
};
|
||||
self.update_root_elements(update_range);
|
||||
}
|
||||
unsafe fn set_push_constants(
|
||||
&mut self,
|
||||
@ -690,11 +730,10 @@ impl crate::CommandEncoder<super::Api> for super::CommandEncoder {
|
||||
unsafe fn set_render_pipeline(&mut self, pipeline: &super::RenderPipeline) {
|
||||
let list = self.list.unwrap();
|
||||
|
||||
if self.pass.signature != pipeline.signature {
|
||||
if self.pass.layout.signature != pipeline.layout.signature {
|
||||
// D3D12 requires full reset on signature change
|
||||
list.set_graphics_root_signature(pipeline.signature);
|
||||
self.pass.signature = pipeline.signature;
|
||||
self.update_root_elements(0..pipeline.total_root_elements);
|
||||
list.set_graphics_root_signature(pipeline.layout.signature);
|
||||
self.reset_signature(&pipeline.layout);
|
||||
};
|
||||
|
||||
list.set_pipeline_state(pipeline.raw);
|
||||
@ -772,7 +811,7 @@ impl crate::CommandEncoder<super::Api> for super::CommandEncoder {
|
||||
start_instance: u32,
|
||||
instance_count: u32,
|
||||
) {
|
||||
self.prepare_draw();
|
||||
self.prepare_draw(start_vertex as i32, start_instance);
|
||||
self.list
|
||||
.unwrap()
|
||||
.draw(vertex_count, instance_count, start_vertex, start_instance);
|
||||
@ -785,7 +824,7 @@ impl crate::CommandEncoder<super::Api> for super::CommandEncoder {
|
||||
start_instance: u32,
|
||||
instance_count: u32,
|
||||
) {
|
||||
self.prepare_draw();
|
||||
self.prepare_draw(base_vertex, start_instance);
|
||||
self.list.unwrap().draw_indexed(
|
||||
index_count,
|
||||
instance_count,
|
||||
@ -800,7 +839,7 @@ impl crate::CommandEncoder<super::Api> for super::CommandEncoder {
|
||||
offset: wgt::BufferAddress,
|
||||
draw_count: u32,
|
||||
) {
|
||||
self.prepare_draw();
|
||||
self.prepare_draw(0, 0);
|
||||
self.list.unwrap().ExecuteIndirect(
|
||||
self.shared.cmd_signatures.draw.as_mut_ptr(),
|
||||
draw_count,
|
||||
@ -816,7 +855,7 @@ impl crate::CommandEncoder<super::Api> for super::CommandEncoder {
|
||||
offset: wgt::BufferAddress,
|
||||
draw_count: u32,
|
||||
) {
|
||||
self.prepare_draw();
|
||||
self.prepare_draw(0, 0);
|
||||
self.list.unwrap().ExecuteIndirect(
|
||||
self.shared.cmd_signatures.draw_indexed.as_mut_ptr(),
|
||||
draw_count,
|
||||
@ -834,7 +873,7 @@ impl crate::CommandEncoder<super::Api> for super::CommandEncoder {
|
||||
count_offset: wgt::BufferAddress,
|
||||
max_count: u32,
|
||||
) {
|
||||
self.prepare_draw();
|
||||
self.prepare_draw(0, 0);
|
||||
self.list.unwrap().ExecuteIndirect(
|
||||
self.shared.cmd_signatures.draw.as_mut_ptr(),
|
||||
max_count,
|
||||
@ -852,7 +891,7 @@ impl crate::CommandEncoder<super::Api> for super::CommandEncoder {
|
||||
count_offset: wgt::BufferAddress,
|
||||
max_count: u32,
|
||||
) {
|
||||
self.prepare_draw();
|
||||
self.prepare_draw(0, 0);
|
||||
self.list.unwrap().ExecuteIndirect(
|
||||
self.shared.cmd_signatures.draw_indexed.as_mut_ptr(),
|
||||
max_count,
|
||||
@ -875,11 +914,10 @@ impl crate::CommandEncoder<super::Api> for super::CommandEncoder {
|
||||
unsafe fn set_compute_pipeline(&mut self, pipeline: &super::ComputePipeline) {
|
||||
let list = self.list.unwrap();
|
||||
|
||||
if self.pass.signature != pipeline.signature {
|
||||
if self.pass.layout.signature != pipeline.layout.signature {
|
||||
// D3D12 requires full reset on signature change
|
||||
list.set_compute_root_signature(pipeline.signature);
|
||||
self.pass.signature = pipeline.signature;
|
||||
self.update_root_elements(0..pipeline.total_root_elements);
|
||||
list.set_compute_root_signature(pipeline.layout.signature);
|
||||
self.reset_signature(&pipeline.layout);
|
||||
};
|
||||
|
||||
list.set_pipeline_state(pipeline.raw);
|
||||
|
@ -703,28 +703,53 @@ impl crate::Device<super::Api> for super::Device {
|
||||
// This is easier than trying to patch up the offset on the shader side.
|
||||
//
|
||||
// Root signature layout:
|
||||
// Root Constants: Register: Offset/4, Space: 0
|
||||
// Root Constants: Parameter=0, Space=0
|
||||
// Special constant buffer: Space=0
|
||||
// ...
|
||||
// (bind group [3]) - Space: 1
|
||||
// (bind group [3]) - Space=0
|
||||
// View descriptor table, if any
|
||||
// Sampler descriptor table, if any
|
||||
// Root descriptors (for dynamic offset buffers)
|
||||
// (bind group [2]) - Space: 2
|
||||
// (bind group [2]) - Space=0
|
||||
// ...
|
||||
// (bind group [0]) - Space: 4
|
||||
// (bind group [0]) - Space=0
|
||||
|
||||
//Note: lower bind group indices are put futher down the root signature. See:
|
||||
// https://microsoft.github.io/DirectX-Specs/d3d/ResourceBinding.html#binding-model
|
||||
|
||||
fn native_binding(bt: &hlsl::BindTarget) -> native::Binding {
|
||||
native::Binding {
|
||||
space: bt.space as u32,
|
||||
register: bt.register,
|
||||
}
|
||||
}
|
||||
|
||||
let mut binding_map = hlsl::BindingMap::default();
|
||||
let root_constants: &[()] = &[];
|
||||
let (mut bind_cbv, mut bind_srv, mut bind_uav, mut bind_sampler) = (
|
||||
hlsl::BindTarget::default(),
|
||||
hlsl::BindTarget::default(),
|
||||
hlsl::BindTarget::default(),
|
||||
hlsl::BindTarget::default(),
|
||||
);
|
||||
let mut parameters = Vec::new();
|
||||
|
||||
// Number of elements in the root signature.
|
||||
let total_parameters = root_constants.len() + desc.bind_group_layouts.len() * 2;
|
||||
// Guarantees that no re-allocation is done, and our pointers are valid
|
||||
let mut parameters = Vec::with_capacity(total_parameters);
|
||||
let (special_constants_root_index, special_constants_binding) = if desc
|
||||
.flags
|
||||
.contains(crate::PipelineLayoutFlags::BASE_VERTEX_INSTANCE)
|
||||
{
|
||||
let parameter_index = parameters.len();
|
||||
parameters.push(native::RootParameter::constants(
|
||||
native::ShaderVisibility::VS,
|
||||
native_binding(&bind_cbv),
|
||||
2, // 0 = base vertex, 1 = base instance
|
||||
));
|
||||
let binding = bind_cbv.clone();
|
||||
bind_cbv.register += 1;
|
||||
(Some(parameter_index as u32), Some(binding))
|
||||
} else {
|
||||
(None, None)
|
||||
};
|
||||
|
||||
let root_space_offset = if !root_constants.is_empty() { 1 } else { 0 };
|
||||
// Collect the whole number of bindings we will create upfront.
|
||||
// It allows us to preallocate enough storage to avoid reallocation,
|
||||
// which could cause invalid pointers.
|
||||
@ -745,8 +770,7 @@ impl crate::Device<super::Api> for super::Device {
|
||||
|
||||
let mut bind_group_infos =
|
||||
arrayvec::ArrayVec::<super::BindGroupInfo, { crate::MAX_BIND_GROUPS }>::default();
|
||||
for (index, bgl) in desc.bind_group_layouts.iter().enumerate() {
|
||||
let space = root_space_offset + (desc.bind_group_layouts.len() - 1 - index) as u32;
|
||||
for (index, bgl) in desc.bind_group_layouts.iter().enumerate().rev() {
|
||||
let mut info = super::BindGroupInfo {
|
||||
tables: super::TableTypes::empty(),
|
||||
base_root_index: parameters.len() as u32,
|
||||
@ -767,8 +791,6 @@ impl crate::Device<super::Api> for super::Device {
|
||||
}
|
||||
}
|
||||
|
||||
let (mut num_cbv, mut num_srv, mut num_uav) = (0, 0, 0);
|
||||
|
||||
// SRV/CBV/UAV descriptor tables
|
||||
let mut range_base = ranges.len();
|
||||
for entry in bgl.entries.iter() {
|
||||
@ -780,31 +802,27 @@ impl crate::Device<super::Api> for super::Device {
|
||||
| wgt::BindingType::Sampler { .. } => continue,
|
||||
ref other => conv::map_binding_type(other),
|
||||
};
|
||||
let reg_ref = match range_ty {
|
||||
native::DescriptorRangeType::CBV => &mut num_cbv,
|
||||
native::DescriptorRangeType::SRV => &mut num_srv,
|
||||
native::DescriptorRangeType::UAV => &mut num_uav,
|
||||
let bt = match range_ty {
|
||||
native::DescriptorRangeType::CBV => &mut bind_cbv,
|
||||
native::DescriptorRangeType::SRV => &mut bind_srv,
|
||||
native::DescriptorRangeType::UAV => &mut bind_uav,
|
||||
native::DescriptorRangeType::Sampler => unreachable!(),
|
||||
};
|
||||
let register = *reg_ref;
|
||||
*reg_ref += 1;
|
||||
|
||||
binding_map.insert(
|
||||
naga::ResourceBinding {
|
||||
group: index as u32,
|
||||
binding: entry.binding,
|
||||
},
|
||||
hlsl::BindTarget {
|
||||
space: space as u8,
|
||||
register,
|
||||
},
|
||||
bt.clone(),
|
||||
);
|
||||
ranges.push(native::DescriptorRange::new(
|
||||
range_ty,
|
||||
entry.count.map_or(1, |count| count.get()),
|
||||
native::Binding { space, register },
|
||||
native_binding(bt),
|
||||
d3d12::D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND,
|
||||
));
|
||||
bt.register += 1;
|
||||
}
|
||||
if ranges.len() > range_base {
|
||||
parameters.push(native::RootParameter::descriptor_table(
|
||||
@ -821,23 +839,20 @@ impl crate::Device<super::Api> for super::Device {
|
||||
wgt::BindingType::Sampler { .. } => native::DescriptorRangeType::Sampler,
|
||||
_ => continue,
|
||||
};
|
||||
let register = (ranges.len() - range_base) as u32;
|
||||
binding_map.insert(
|
||||
naga::ResourceBinding {
|
||||
group: index as u32,
|
||||
binding: entry.binding,
|
||||
},
|
||||
hlsl::BindTarget {
|
||||
space: space as u8,
|
||||
register,
|
||||
},
|
||||
bind_sampler.clone(),
|
||||
);
|
||||
ranges.push(native::DescriptorRange::new(
|
||||
range_ty,
|
||||
entry.count.map_or(1, |count| count.get()),
|
||||
native::Binding { space, register },
|
||||
native_binding(&bind_sampler),
|
||||
d3d12::D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND,
|
||||
));
|
||||
bind_sampler.register += 1;
|
||||
}
|
||||
if ranges.len() > range_base {
|
||||
parameters.push(native::RootParameter::descriptor_table(
|
||||
@ -859,49 +874,22 @@ impl crate::Device<super::Api> for super::Device {
|
||||
_ => continue,
|
||||
};
|
||||
|
||||
let (kind, param, register) = match buffer_ty {
|
||||
wgt::BufferBindingType::Uniform => {
|
||||
let binding = native::Binding {
|
||||
space,
|
||||
register: num_cbv,
|
||||
};
|
||||
(
|
||||
super::BufferViewKind::Constant,
|
||||
native::RootParameter::cbv_descriptor(
|
||||
dynamic_buffers_visibility,
|
||||
binding,
|
||||
),
|
||||
&mut num_cbv,
|
||||
)
|
||||
}
|
||||
wgt::BufferBindingType::Storage { read_only: true } => {
|
||||
let binding = native::Binding {
|
||||
space,
|
||||
register: num_srv,
|
||||
};
|
||||
(
|
||||
super::BufferViewKind::ShaderResource,
|
||||
native::RootParameter::srv_descriptor(
|
||||
dynamic_buffers_visibility,
|
||||
binding,
|
||||
),
|
||||
&mut num_srv,
|
||||
)
|
||||
}
|
||||
wgt::BufferBindingType::Storage { read_only: false } => {
|
||||
let binding = native::Binding {
|
||||
space,
|
||||
register: num_uav,
|
||||
};
|
||||
(
|
||||
super::BufferViewKind::UnorderedAccess,
|
||||
native::RootParameter::uav_descriptor(
|
||||
dynamic_buffers_visibility,
|
||||
binding,
|
||||
),
|
||||
&mut num_uav,
|
||||
)
|
||||
}
|
||||
let (kind, parameter_ty, bt) = match buffer_ty {
|
||||
wgt::BufferBindingType::Uniform => (
|
||||
super::BufferViewKind::Constant,
|
||||
d3d12::D3D12_ROOT_PARAMETER_TYPE_CBV,
|
||||
&mut bind_cbv,
|
||||
),
|
||||
wgt::BufferBindingType::Storage { read_only: true } => (
|
||||
super::BufferViewKind::ShaderResource,
|
||||
d3d12::D3D12_ROOT_PARAMETER_TYPE_SRV,
|
||||
&mut bind_srv,
|
||||
),
|
||||
wgt::BufferBindingType::Storage { read_only: false } => (
|
||||
super::BufferViewKind::UnorderedAccess,
|
||||
d3d12::D3D12_ROOT_PARAMETER_TYPE_UAV,
|
||||
&mut bind_uav,
|
||||
),
|
||||
};
|
||||
|
||||
binding_map.insert(
|
||||
@ -909,15 +897,16 @@ impl crate::Device<super::Api> for super::Device {
|
||||
group: index as u32,
|
||||
binding: entry.binding,
|
||||
},
|
||||
hlsl::BindTarget {
|
||||
space: space as u8,
|
||||
register: *register,
|
||||
},
|
||||
bt.clone(),
|
||||
);
|
||||
*register += 1;
|
||||
|
||||
info.dynamic_buffers.push(kind);
|
||||
parameters.push(param);
|
||||
parameters.push(native::RootParameter::descriptor(
|
||||
parameter_ty,
|
||||
dynamic_buffers_visibility,
|
||||
native_binding(bt),
|
||||
));
|
||||
|
||||
bt.register += 1;
|
||||
}
|
||||
|
||||
bind_group_infos.push(info);
|
||||
@ -961,18 +950,22 @@ impl crate::Device<super::Api> for super::Device {
|
||||
}
|
||||
|
||||
Ok(super::PipelineLayout {
|
||||
raw,
|
||||
shared: super::PipelineLayoutShared {
|
||||
signature: raw,
|
||||
total_root_elements: parameters.len() as super::RootIndex,
|
||||
special_constants_root_index,
|
||||
},
|
||||
bind_group_infos,
|
||||
total_root_elements: total_parameters as super::RootIndex,
|
||||
naga_options: hlsl::Options {
|
||||
shader_model: hlsl::ShaderModel::V5_1,
|
||||
binding_map,
|
||||
fake_missing_bindings: false,
|
||||
special_constants_binding,
|
||||
},
|
||||
})
|
||||
}
|
||||
unsafe fn destroy_pipeline_layout(&self, pipeline_layout: super::PipelineLayout) {
|
||||
pipeline_layout.raw.destroy();
|
||||
pipeline_layout.shared.signature.destroy();
|
||||
}
|
||||
|
||||
unsafe fn create_bind_group(
|
||||
@ -1224,7 +1217,7 @@ impl crate::Device<super::Api> for super::Device {
|
||||
};
|
||||
|
||||
let raw_desc = d3d12::D3D12_GRAPHICS_PIPELINE_STATE_DESC {
|
||||
pRootSignature: desc.layout.raw.as_mut_ptr(),
|
||||
pRootSignature: desc.layout.shared.signature.as_mut_ptr(),
|
||||
VS: *native::Shader::from_blob(blob_vs),
|
||||
PS: if blob_fs.is_null() {
|
||||
*native::Shader::null()
|
||||
@ -1314,8 +1307,7 @@ impl crate::Device<super::Api> for super::Device {
|
||||
|
||||
Ok(super::RenderPipeline {
|
||||
raw,
|
||||
signature: desc.layout.raw,
|
||||
total_root_elements: desc.layout.total_root_elements,
|
||||
layout: desc.layout.shared.clone(),
|
||||
topology,
|
||||
vertex_strides,
|
||||
})
|
||||
@ -1331,7 +1323,7 @@ impl crate::Device<super::Api> for super::Device {
|
||||
let blob_cs = self.load_shader(&desc.stage, desc.layout, naga::ShaderStage::Compute)?;
|
||||
|
||||
let pair = self.raw.create_compute_pipeline_state(
|
||||
desc.layout.raw,
|
||||
desc.layout.shared.signature,
|
||||
native::Shader::from_blob(blob_cs),
|
||||
0,
|
||||
native::CachedPSO::null(),
|
||||
@ -1351,8 +1343,7 @@ impl crate::Device<super::Api> for super::Device {
|
||||
|
||||
Ok(super::ComputePipeline {
|
||||
raw,
|
||||
signature: desc.layout.raw,
|
||||
total_root_elements: desc.layout.total_root_elements,
|
||||
layout: desc.layout.shared.clone(),
|
||||
})
|
||||
}
|
||||
unsafe fn destroy_compute_pipeline(&self, pipeline: super::ComputePipeline) {
|
||||
|
@ -280,7 +280,10 @@ struct PassResolve {
|
||||
#[derive(Clone, Copy)]
|
||||
enum RootElement {
|
||||
Empty,
|
||||
//Constant(u32),
|
||||
SpecialConstantBuffer {
|
||||
base_vertex: i32,
|
||||
base_instance: u32,
|
||||
},
|
||||
/// Descriptor table.
|
||||
Table(native::GpuDescriptor),
|
||||
/// Descriptor for a buffer that has dynamic offset.
|
||||
@ -300,7 +303,7 @@ enum PassKind {
|
||||
struct PassState {
|
||||
has_label: bool,
|
||||
resolves: ArrayVec<PassResolve, { crate::MAX_COLOR_TARGETS }>,
|
||||
signature: native::RootSignature,
|
||||
layout: PipelineLayoutShared,
|
||||
root_elements: [RootElement; MAX_ROOT_ELEMENTS],
|
||||
vertex_buffers: [d3d12::D3D12_VERTEX_BUFFER_VIEW; crate::MAX_VERTEX_BUFFERS],
|
||||
dirty_vertex_buffers: usize,
|
||||
@ -312,7 +315,11 @@ impl PassState {
|
||||
PassState {
|
||||
has_label: false,
|
||||
resolves: ArrayVec::new(),
|
||||
signature: native::RootSignature::null(),
|
||||
layout: PipelineLayoutShared {
|
||||
signature: native::RootSignature::null(),
|
||||
total_root_elements: 0,
|
||||
special_constants_root_index: None,
|
||||
},
|
||||
root_elements: [RootElement::Empty; MAX_ROOT_ELEMENTS],
|
||||
vertex_buffers: [unsafe { mem::zeroed() }; crate::MAX_VERTEX_BUFFERS],
|
||||
dirty_vertex_buffers: 0,
|
||||
@ -468,7 +475,7 @@ bitflags::bitflags! {
|
||||
}
|
||||
}
|
||||
|
||||
// Index into the root signature.
|
||||
// Element (also known as parameter) index into the root signature.
|
||||
type RootIndex = u32;
|
||||
|
||||
struct BindGroupInfo {
|
||||
@ -477,18 +484,24 @@ struct BindGroupInfo {
|
||||
dynamic_buffers: Vec<BufferViewKind>,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
struct PipelineLayoutShared {
|
||||
signature: native::RootSignature,
|
||||
total_root_elements: RootIndex,
|
||||
special_constants_root_index: Option<RootIndex>,
|
||||
}
|
||||
|
||||
unsafe impl Send for PipelineLayoutShared {}
|
||||
unsafe impl Sync for PipelineLayoutShared {}
|
||||
|
||||
pub struct PipelineLayout {
|
||||
raw: native::RootSignature,
|
||||
shared: PipelineLayoutShared,
|
||||
// Storing for each associated bind group, which tables we created
|
||||
// in the root signature. This is required for binding descriptor sets.
|
||||
bind_group_infos: ArrayVec<BindGroupInfo, { crate::MAX_BIND_GROUPS }>,
|
||||
total_root_elements: RootIndex,
|
||||
naga_options: naga::back::hlsl::Options,
|
||||
}
|
||||
|
||||
unsafe impl Send for PipelineLayout {}
|
||||
unsafe impl Sync for PipelineLayout {}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ShaderModule {
|
||||
naga: crate::NagaShader,
|
||||
@ -497,8 +510,7 @@ pub struct ShaderModule {
|
||||
|
||||
pub struct RenderPipeline {
|
||||
raw: native::PipelineState,
|
||||
signature: native::RootSignature,
|
||||
total_root_elements: RootIndex,
|
||||
layout: PipelineLayoutShared,
|
||||
topology: d3d12::D3D12_PRIMITIVE_TOPOLOGY,
|
||||
vertex_strides: [Option<NonZeroU32>; crate::MAX_VERTEX_BUFFERS],
|
||||
}
|
||||
@ -508,8 +520,7 @@ unsafe impl Sync for RenderPipeline {}
|
||||
|
||||
pub struct ComputePipeline {
|
||||
raw: native::PipelineState,
|
||||
signature: native::RootSignature,
|
||||
total_root_elements: RootIndex,
|
||||
layout: PipelineLayoutShared,
|
||||
}
|
||||
|
||||
unsafe impl Send for ComputePipeline {}
|
||||
|
@ -505,6 +505,14 @@ bitflags!(
|
||||
}
|
||||
);
|
||||
|
||||
bitflags!(
|
||||
/// Pipeline layout creation flags.
|
||||
pub struct PipelineLayoutFlags: u32 {
|
||||
/// Include support for base vertex/instance drawing.
|
||||
const BASE_VERTEX_INSTANCE = 0x1;
|
||||
}
|
||||
);
|
||||
|
||||
bitflags!(
|
||||
/// Texture format capability flags.
|
||||
pub struct TextureFormatCapabilities: u32 {
|
||||
@ -785,6 +793,7 @@ pub struct BindGroupLayoutDescriptor<'a> {
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct PipelineLayoutDescriptor<'a, A: Api> {
|
||||
pub label: Label<'a>,
|
||||
pub flags: PipelineLayoutFlags,
|
||||
pub bind_group_layouts: &'a [&'a A::BindGroupLayout],
|
||||
pub push_constant_ranges: &'a [wgt::PushConstantRange],
|
||||
}
|
||||
|
@ -75,13 +75,13 @@ env_logger = "0.8"
|
||||
|
||||
[dependencies.naga]
|
||||
git = "https://github.com/gfx-rs/naga"
|
||||
rev = "e97c8f9"
|
||||
rev = "a7ac13a"
|
||||
optional = true
|
||||
|
||||
# used to test all the example shaders
|
||||
[dev-dependencies.naga]
|
||||
git = "https://github.com/gfx-rs/naga"
|
||||
rev = "e97c8f9"
|
||||
rev = "a7ac13a"
|
||||
features = ["wgsl-in"]
|
||||
|
||||
[[example]]
|
||||
|
@ -472,8 +472,8 @@ fn skybox() {
|
||||
height: 768,
|
||||
optional_features: wgpu::Features::default(),
|
||||
base_test_parameters: framework::test_common::TestParameters::default()
|
||||
.backend_failure(wgpu::Backends::VULKAN | wgpu::Backends::GL),
|
||||
tolerance: 2,
|
||||
.backend_failure(wgpu::Backends::GL),
|
||||
tolerance: 3,
|
||||
max_outliers: 3,
|
||||
});
|
||||
}
|
||||
|
@ -143,7 +143,7 @@ fn draw_vertex_offset() {
|
||||
initialize_test(
|
||||
TestParameters::default()
|
||||
.test_features()
|
||||
.backend_failure(wgpu::Backends::DX12 | wgpu::Backends::DX11),
|
||||
.backend_failure(wgpu::Backends::DX11),
|
||||
|ctx| {
|
||||
pulling_common(ctx, &[0, 1, 2, 3, 4, 5], |cmb| {
|
||||
cmb.draw(0..3, 0..1);
|
||||
@ -167,7 +167,7 @@ fn draw_instanced_offset() {
|
||||
initialize_test(
|
||||
TestParameters::default()
|
||||
.test_features()
|
||||
.backend_failure(wgpu::Backends::DX12 | wgpu::Backends::DX11),
|
||||
.backend_failure(wgpu::Backends::DX11),
|
||||
|ctx| {
|
||||
pulling_common(ctx, &[0, 1, 2, 3, 4, 5], |cmb| {
|
||||
cmb.draw(0..3, 0..1);
|
||||
|
Loading…
Reference in New Issue
Block a user