mirror of
https://github.com/gfx-rs/wgpu.git
synced 2025-12-08 21:26:17 +00:00
[d3d12] get vertex_index & instance_index builtins working for indirect draws
This commit is contained in:
parent
3805768cb4
commit
597114052e
@ -268,6 +268,7 @@ impl Device {
|
||||
raw_device.as_ref(),
|
||||
&desc.required_limits,
|
||||
&desc.required_features,
|
||||
adapter.backend(),
|
||||
)?)
|
||||
} else {
|
||||
None
|
||||
|
||||
@ -62,6 +62,7 @@ impl Draw {
|
||||
pub(super) fn new(
|
||||
device: &dyn hal::DynDevice,
|
||||
required_features: &wgt::Features,
|
||||
backend: wgt::Backend,
|
||||
) -> Result<Self, CreateIndirectValidationPipelineError> {
|
||||
let module = create_validation_module(device)?;
|
||||
|
||||
@ -92,11 +93,13 @@ impl Draw {
|
||||
|
||||
let supports_indirect_first_instance =
|
||||
required_features.contains(wgt::Features::INDIRECT_FIRST_INSTANCE);
|
||||
let write_d3d12_special_constants = backend == wgt::Backend::Dx12;
|
||||
let pipeline = create_validation_pipeline(
|
||||
device,
|
||||
module.as_ref(),
|
||||
pipeline_layout.as_ref(),
|
||||
supports_indirect_first_instance,
|
||||
write_d3d12_special_constants,
|
||||
)?;
|
||||
|
||||
Ok(Self {
|
||||
@ -523,6 +526,7 @@ fn create_validation_pipeline(
|
||||
module: &dyn hal::DynShaderModule,
|
||||
pipeline_layout: &dyn hal::DynPipelineLayout,
|
||||
supports_indirect_first_instance: bool,
|
||||
write_d3d12_special_constants: bool,
|
||||
) -> Result<Box<dyn hal::DynComputePipeline>, CreateIndirectValidationPipelineError> {
|
||||
let pipeline_desc = hal::ComputePipelineDescriptor {
|
||||
label: None,
|
||||
@ -530,10 +534,16 @@ fn create_validation_pipeline(
|
||||
stage: hal::ProgrammableStage {
|
||||
module,
|
||||
entry_point: "main",
|
||||
constants: &hashbrown::HashMap::from([(
|
||||
"supports_indirect_first_instance".to_string(),
|
||||
f64::from(supports_indirect_first_instance),
|
||||
)]),
|
||||
constants: &hashbrown::HashMap::from([
|
||||
(
|
||||
"supports_indirect_first_instance".to_string(),
|
||||
f64::from(supports_indirect_first_instance),
|
||||
),
|
||||
(
|
||||
"write_d3d12_special_constants".to_string(),
|
||||
f64::from(write_d3d12_special_constants),
|
||||
),
|
||||
]),
|
||||
zero_initialize_workgroup_memory: false,
|
||||
},
|
||||
cache: None,
|
||||
@ -913,7 +923,13 @@ impl DrawBatcher {
|
||||
vertex_or_index_limit: u64,
|
||||
instance_limit: u64,
|
||||
) -> Result<(usize, u64), DeviceError> {
|
||||
let stride = crate::command::get_stride_of_indirect_args(indexed);
|
||||
// space for D3D12 special constants
|
||||
let extra = if device.backend() == wgt::Backend::Dx12 {
|
||||
3 * size_of::<u32>() as u64
|
||||
} else {
|
||||
0
|
||||
};
|
||||
let stride = extra + crate::command::get_stride_of_indirect_args(indexed);
|
||||
|
||||
let (dst_resource_index, dst_offset) = indirect_draw_validation_resources
|
||||
.get_dst_subrange(stride, &mut self.current_dst_entry)?;
|
||||
|
||||
@ -33,6 +33,7 @@ impl IndirectValidation {
|
||||
device: &dyn hal::DynDevice,
|
||||
required_limits: &wgt::Limits,
|
||||
required_features: &wgt::Features,
|
||||
backend: wgt::Backend,
|
||||
) -> Result<Self, DeviceError> {
|
||||
let dispatch = match Dispatch::new(device, required_limits) {
|
||||
Ok(dispatch) => dispatch,
|
||||
@ -41,7 +42,7 @@ impl IndirectValidation {
|
||||
return Err(DeviceError::Lost);
|
||||
}
|
||||
};
|
||||
let draw = match Draw::new(device, required_features) {
|
||||
let draw = match Draw::new(device, required_features, backend) {
|
||||
Ok(draw) => draw,
|
||||
Err(e) => {
|
||||
log::error!("indirect-draw-validation error: {e:?}");
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
override supports_indirect_first_instance: bool;
|
||||
override write_d3d12_special_constants: bool;
|
||||
|
||||
struct MetadataEntry {
|
||||
// bits 0..30 are an offset into `src`
|
||||
@ -66,21 +67,32 @@ fn main(@builtin(global_invocation_id) global_invocation_id: vec3u) {
|
||||
failed |= first_instance != 0u;
|
||||
}
|
||||
|
||||
let dst_offset = select(0u, 3u, write_d3d12_special_constants);
|
||||
if failed {
|
||||
dst[dst_base_offset + 0] = 0u;
|
||||
dst[dst_base_offset + 1] = 0u;
|
||||
dst[dst_base_offset + 2] = 0u;
|
||||
dst[dst_base_offset + 3] = 0u;
|
||||
if write_d3d12_special_constants {
|
||||
dst[dst_base_offset + 0] = 0u;
|
||||
dst[dst_base_offset + 1] = 0u;
|
||||
dst[dst_base_offset + 2] = 0u;
|
||||
}
|
||||
dst[dst_base_offset + dst_offset + 0] = 0u;
|
||||
dst[dst_base_offset + dst_offset + 1] = 0u;
|
||||
dst[dst_base_offset + dst_offset + 2] = 0u;
|
||||
dst[dst_base_offset + dst_offset + 3] = 0u;
|
||||
if (is_indexed) {
|
||||
dst[dst_base_offset + 4] = 0u;
|
||||
dst[dst_base_offset + dst_offset + 4] = 0u;
|
||||
}
|
||||
} else {
|
||||
dst[dst_base_offset + 0] = src[src_base_offset + 0];
|
||||
dst[dst_base_offset + 1] = src[src_base_offset + 1];
|
||||
dst[dst_base_offset + 2] = src[src_base_offset + 2];
|
||||
dst[dst_base_offset + 3] = src[src_base_offset + 3];
|
||||
if write_d3d12_special_constants {
|
||||
dst[dst_base_offset + 0] = src[src_base_offset + 2 + u32(is_indexed)];
|
||||
dst[dst_base_offset + 1] = src[src_base_offset + 3 + u32(is_indexed)];
|
||||
dst[dst_base_offset + 2] = 0u;
|
||||
}
|
||||
dst[dst_base_offset + dst_offset + 0] = src[src_base_offset + 0];
|
||||
dst[dst_base_offset + dst_offset + 1] = src[src_base_offset + 1];
|
||||
dst[dst_base_offset + dst_offset + 2] = src[src_base_offset + 2];
|
||||
dst[dst_base_offset + dst_offset + 3] = src[src_base_offset + 3];
|
||||
if (is_indexed) {
|
||||
dst[dst_base_offset + 4] = src[src_base_offset + 4];
|
||||
dst[dst_base_offset + dst_offset + 4] = src[src_base_offset + 4];
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -104,7 +104,7 @@ impl super::CommandEncoder {
|
||||
self.pass.clear();
|
||||
}
|
||||
|
||||
unsafe fn prepare_draw(&mut self, first_vertex: i32, first_instance: u32) {
|
||||
unsafe fn prepare_vertex_buffers(&mut self) {
|
||||
while self.pass.dirty_vertex_buffers != 0 {
|
||||
let list = self.list.as_ref().unwrap();
|
||||
let index = self.pass.dirty_vertex_buffers.trailing_zeros();
|
||||
@ -116,6 +116,12 @@ impl super::CommandEncoder {
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn prepare_draw(&mut self, first_vertex: i32, first_instance: u32) {
|
||||
unsafe {
|
||||
self.prepare_vertex_buffers();
|
||||
}
|
||||
if let Some(root_index) = self
|
||||
.pass
|
||||
.layout
|
||||
@ -1195,10 +1201,31 @@ impl crate::CommandEncoder for super::CommandEncoder {
|
||||
offset: wgt::BufferAddress,
|
||||
draw_count: u32,
|
||||
) {
|
||||
unsafe { self.prepare_draw(0, 0) };
|
||||
if self
|
||||
.pass
|
||||
.layout
|
||||
.special_constants
|
||||
.as_ref()
|
||||
.and_then(|sc| sc.indirect_cmd_signatures.as_ref())
|
||||
.is_some()
|
||||
{
|
||||
unsafe { self.prepare_vertex_buffers() };
|
||||
self.update_root_elements();
|
||||
} else {
|
||||
unsafe { self.prepare_draw(0, 0) };
|
||||
}
|
||||
|
||||
let cmd_signature = &self
|
||||
.pass
|
||||
.layout
|
||||
.special_constants
|
||||
.as_ref()
|
||||
.and_then(|sc| sc.indirect_cmd_signatures.as_ref())
|
||||
.unwrap_or_else(|| &self.shared.cmd_signatures)
|
||||
.draw;
|
||||
unsafe {
|
||||
self.list.as_ref().unwrap().ExecuteIndirect(
|
||||
&self.shared.cmd_signatures.draw,
|
||||
cmd_signature,
|
||||
draw_count,
|
||||
&buffer.resource,
|
||||
offset,
|
||||
@ -1213,10 +1240,31 @@ impl crate::CommandEncoder for super::CommandEncoder {
|
||||
offset: wgt::BufferAddress,
|
||||
draw_count: u32,
|
||||
) {
|
||||
unsafe { self.prepare_draw(0, 0) };
|
||||
if self
|
||||
.pass
|
||||
.layout
|
||||
.special_constants
|
||||
.as_ref()
|
||||
.and_then(|sc| sc.indirect_cmd_signatures.as_ref())
|
||||
.is_some()
|
||||
{
|
||||
unsafe { self.prepare_vertex_buffers() };
|
||||
self.update_root_elements();
|
||||
} else {
|
||||
unsafe { self.prepare_draw(0, 0) };
|
||||
}
|
||||
|
||||
let cmd_signature = &self
|
||||
.pass
|
||||
.layout
|
||||
.special_constants
|
||||
.as_ref()
|
||||
.and_then(|sc| sc.indirect_cmd_signatures.as_ref())
|
||||
.unwrap_or_else(|| &self.shared.cmd_signatures)
|
||||
.draw_indexed;
|
||||
unsafe {
|
||||
self.list.as_ref().unwrap().ExecuteIndirect(
|
||||
&self.shared.cmd_signatures.draw_indexed,
|
||||
cmd_signature,
|
||||
draw_count,
|
||||
&buffer.resource,
|
||||
offset,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user