mirror of
https://github.com/gfx-rs/wgpu.git
synced 2025-12-08 21:26:17 +00:00
Remove MULTI_DRAW_INDIRECT feature (#8162)
This commit is contained in:
parent
97ba77d668
commit
2ff46cd7cd
10
CHANGELOG.md
10
CHANGELOG.md
@ -74,6 +74,16 @@ Difference for SPIR-V passthrough:
|
||||
This allows using precompiled shaders without manually checking which backend's code to pass, for example if you have shaders precompiled for both DXIL and SPIR-V.
|
||||
|
||||
|
||||
#### Multi-draw indirect is now unconditionally supported when indirect draws are supported
|
||||
|
||||
We have removed `Features::MULTI_DRAW_INDIRECT` as it was unconditionally available on all platforms.
|
||||
`RenderPass::multi_draw_indirect` is now available if the device supports downlevel flag `DownlevelFlags::INDIRECT_EXECUTION`.
|
||||
|
||||
If you are using spirv-passthrough with multi-draw indirect and `gl_DrawID`, you can know if `MULTI_DRAW_INDIRECT` is being emulated
|
||||
by if the `Feature::MULTI_DRAW_INDIRECT_COUNT` feature is available on the device, this feature cannot be emulated efficicently.
|
||||
|
||||
By @cwfitzgerald in [#8162](https://github.com/gfx-rs/wgpu/pull/8162).
|
||||
|
||||
### New Features
|
||||
|
||||
#### General
|
||||
|
||||
@ -399,8 +399,6 @@ pub enum GPUFeatureName {
|
||||
UniformBufferBindingArrays,
|
||||
#[webidl(rename = "partially-bound-binding-array")]
|
||||
PartiallyBoundBindingArray,
|
||||
#[webidl(rename = "multi-draw-indirect")]
|
||||
MultiDrawIndirect,
|
||||
#[webidl(rename = "multi-draw-indirect-count")]
|
||||
MultiDrawIndirectCount,
|
||||
#[webidl(rename = "push-constants")]
|
||||
@ -470,7 +468,6 @@ pub fn feature_names_to_features(names: Vec<GPUFeatureName>) -> wgpu_types::Feat
|
||||
GPUFeatureName::StorageTextureArrayNonUniformIndexing => Features::STORAGE_TEXTURE_ARRAY_NON_UNIFORM_INDEXING,
|
||||
GPUFeatureName::UniformBufferBindingArrays => Features::UNIFORM_BUFFER_BINDING_ARRAYS,
|
||||
GPUFeatureName::PartiallyBoundBindingArray => Features::PARTIALLY_BOUND_BINDING_ARRAY,
|
||||
GPUFeatureName::MultiDrawIndirect => Features::MULTI_DRAW_INDIRECT,
|
||||
GPUFeatureName::MultiDrawIndirectCount => Features::MULTI_DRAW_INDIRECT_COUNT,
|
||||
GPUFeatureName::PushConstants => Features::PUSH_CONSTANTS,
|
||||
GPUFeatureName::AddressModeClampToZero => Features::ADDRESS_MODE_CLAMP_TO_ZERO,
|
||||
@ -593,9 +590,6 @@ pub fn features_to_feature_names(features: wgpu_types::Features) -> HashSet<GPUF
|
||||
if features.contains(wgpu_types::Features::PARTIALLY_BOUND_BINDING_ARRAY) {
|
||||
return_features.insert(PartiallyBoundBindingArray);
|
||||
}
|
||||
if features.contains(wgpu_types::Features::MULTI_DRAW_INDIRECT) {
|
||||
return_features.insert(MultiDrawIndirect);
|
||||
}
|
||||
if features.contains(wgpu_types::Features::MULTI_DRAW_INDIRECT_COUNT) {
|
||||
return_features.insert(MultiDrawIndirectCount);
|
||||
}
|
||||
|
||||
@ -269,8 +269,9 @@ fn default_gpu_test_config(draw_type: DrawType) -> GpuTestConfiguration {
|
||||
wgpu::Features::EXPERIMENTAL_MESH_SHADER
|
||||
| wgpu::Features::EXPERIMENTAL_PASSTHROUGH_SHADERS
|
||||
| match draw_type {
|
||||
DrawType::Standard | DrawType::Indirect => wgpu::Features::empty(),
|
||||
DrawType::MultiIndirect => wgpu::Features::MULTI_DRAW_INDIRECT,
|
||||
DrawType::Standard | DrawType::Indirect | DrawType::MultiIndirect => {
|
||||
wgpu::Features::empty()
|
||||
}
|
||||
DrawType::MultiIndirectCount => wgpu::Features::MULTI_DRAW_INDIRECT_COUNT,
|
||||
},
|
||||
)
|
||||
|
||||
@ -2696,13 +2696,6 @@ fn multi_draw_indirect(
|
||||
|
||||
state.is_ready(family)?;
|
||||
|
||||
if count != 1 {
|
||||
state
|
||||
.general
|
||||
.device
|
||||
.require_features(wgt::Features::MULTI_DRAW_INDIRECT)?;
|
||||
}
|
||||
|
||||
state
|
||||
.general
|
||||
.device
|
||||
|
||||
@ -343,7 +343,6 @@ impl super::Adapter {
|
||||
| wgt::Features::DEPTH32FLOAT_STENCIL8
|
||||
| wgt::Features::INDIRECT_FIRST_INSTANCE
|
||||
| wgt::Features::MAPPABLE_PRIMARY_BUFFERS
|
||||
| wgt::Features::MULTI_DRAW_INDIRECT
|
||||
| wgt::Features::MULTI_DRAW_INDIRECT_COUNT
|
||||
| wgt::Features::ADDRESS_MODE_CLAMP_TO_BORDER
|
||||
| wgt::Features::ADDRESS_MODE_CLAMP_TO_ZERO
|
||||
|
||||
@ -479,8 +479,6 @@ impl super::Adapter {
|
||||
wgt::Features::SHADER_EARLY_DEPTH_TEST,
|
||||
supported((3, 1), (4, 2)) || extensions.contains("GL_ARB_shader_image_load_store"),
|
||||
);
|
||||
// We emulate MDI with a loop of draw calls.
|
||||
features.set(wgt::Features::MULTI_DRAW_INDIRECT, indirect_execution);
|
||||
if extensions.contains("GL_ARB_timer_query") {
|
||||
features.set(wgt::Features::TIMESTAMP_QUERY, true);
|
||||
features.set(wgt::Features::TIMESTAMP_QUERY_INSIDE_ENCODERS, true);
|
||||
|
||||
@ -931,10 +931,7 @@ impl super::PrivateCapabilities {
|
||||
| F::EXTERNAL_TEXTURE;
|
||||
|
||||
features.set(F::FLOAT32_FILTERABLE, self.supports_float_filtering);
|
||||
features.set(
|
||||
F::INDIRECT_FIRST_INSTANCE | F::MULTI_DRAW_INDIRECT,
|
||||
self.indirect_draw_dispatch,
|
||||
);
|
||||
features.set(F::INDIRECT_FIRST_INSTANCE, self.indirect_draw_dispatch);
|
||||
features.set(
|
||||
F::TIMESTAMP_QUERY | F::TIMESTAMP_QUERY_INSIDE_ENCODERS,
|
||||
self.timestamp_query_support
|
||||
|
||||
@ -266,9 +266,7 @@ impl PhysicalDeviceFeatures {
|
||||
requested_features.contains(wgt::Features::INDIRECT_FIRST_INSTANCE),
|
||||
)
|
||||
//.dual_src_blend(requested_features.contains(wgt::Features::DUAL_SRC_BLENDING))
|
||||
.multi_draw_indirect(
|
||||
requested_features.contains(wgt::Features::MULTI_DRAW_INDIRECT),
|
||||
)
|
||||
.multi_draw_indirect(phd_features.core.multi_draw_indirect != 0)
|
||||
.fill_mode_non_solid(requested_features.intersects(
|
||||
wgt::Features::POLYGON_MODE_LINE | wgt::Features::POLYGON_MODE_POINT,
|
||||
))
|
||||
@ -602,7 +600,6 @@ impl PhysicalDeviceFeatures {
|
||||
self.core.draw_indirect_first_instance != 0,
|
||||
);
|
||||
//if self.core.dual_src_blend != 0
|
||||
features.set(F::MULTI_DRAW_INDIRECT, self.core.multi_draw_indirect != 0);
|
||||
features.set(F::POLYGON_MODE_LINE, self.core.fill_mode_non_solid != 0);
|
||||
features.set(F::POLYGON_MODE_POINT, self.core.fill_mode_non_solid != 0);
|
||||
//if self.core.depth_bounds != 0 {
|
||||
@ -1775,6 +1772,7 @@ impl super::Instance {
|
||||
vk::ImageTiling::OPTIMAL,
|
||||
depth_stencil_required_flags(),
|
||||
),
|
||||
multi_draw_indirect: phd_features.core.multi_draw_indirect != 0,
|
||||
non_coherent_map_mask: phd_capabilities.properties.limits.non_coherent_atom_size - 1,
|
||||
can_present: true,
|
||||
//TODO: make configurable
|
||||
|
||||
@ -1146,15 +1146,29 @@ impl crate::CommandEncoder for super::CommandEncoder {
|
||||
offset: wgt::BufferAddress,
|
||||
draw_count: u32,
|
||||
) {
|
||||
unsafe {
|
||||
self.device.raw.cmd_draw_indexed_indirect(
|
||||
self.active,
|
||||
buffer.raw,
|
||||
offset,
|
||||
draw_count,
|
||||
size_of::<wgt::DrawIndexedIndirectArgs>() as u32,
|
||||
)
|
||||
};
|
||||
if draw_count >= 1 && self.device.private_caps.multi_draw_indirect {
|
||||
unsafe {
|
||||
self.device.raw.cmd_draw_indexed_indirect(
|
||||
self.active,
|
||||
buffer.raw,
|
||||
offset,
|
||||
draw_count,
|
||||
size_of::<wgt::DrawIndexedIndirectArgs>() as u32,
|
||||
)
|
||||
};
|
||||
} else {
|
||||
for _ in 0..draw_count {
|
||||
unsafe {
|
||||
self.device.raw.cmd_draw_indexed_indirect(
|
||||
self.active,
|
||||
buffer.raw,
|
||||
offset,
|
||||
1,
|
||||
size_of::<wgt::DrawIndexedIndirectArgs>() as u32,
|
||||
)
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
unsafe fn draw_mesh_tasks_indirect(
|
||||
&mut self,
|
||||
|
||||
@ -575,6 +575,7 @@ struct PrivateCapabilities {
|
||||
/// Ability to present contents to any screen. Only needed to work around broken platform configurations.
|
||||
can_present: bool,
|
||||
non_coherent_map_mask: wgt::BufferAddress,
|
||||
multi_draw_indirect: bool,
|
||||
|
||||
/// True if this adapter advertises the [`robustBufferAccess`][vrba] feature.
|
||||
///
|
||||
|
||||
@ -784,28 +784,11 @@ bitflags_array! {
|
||||
///
|
||||
/// This is a native only feature.
|
||||
const PARTIALLY_BOUND_BINDING_ARRAY = 1 << 13;
|
||||
/// Allows the user to call [`RenderPass::multi_draw_indirect`] and [`RenderPass::multi_draw_indexed_indirect`].
|
||||
///
|
||||
/// Allows multiple indirect calls to be dispatched from a single buffer.
|
||||
///
|
||||
/// Natively Supported Platforms:
|
||||
/// - DX12
|
||||
/// - Vulkan
|
||||
///
|
||||
/// Emulated Platforms:
|
||||
/// - Metal
|
||||
/// - OpenGL
|
||||
/// - WebGPU
|
||||
///
|
||||
/// Emulation is preformed by looping over the individual indirect draw calls in the backend. This is still significantly
|
||||
/// faster than enulating it yourself, as wgpu only does draw call validation once.
|
||||
///
|
||||
/// [`RenderPass::multi_draw_indirect`]: ../wgpu/struct.RenderPass.html#method.multi_draw_indirect
|
||||
/// [`RenderPass::multi_draw_indexed_indirect`]: ../wgpu/struct.RenderPass.html#method.multi_draw_indexed_indirect
|
||||
const MULTI_DRAW_INDIRECT = 1 << 14;
|
||||
/// Allows the user to call [`RenderPass::multi_draw_indirect_count`] and [`RenderPass::multi_draw_indexed_indirect_count`].
|
||||
///
|
||||
/// This allows the use of a buffer containing the actual number of draw calls.
|
||||
/// This allows the use of a buffer containing the actual number of draw calls. This feature being present also implies
|
||||
/// that all calls to [`RenderPass::multi_draw_indirect`] and [`RenderPass::multi_draw_indexed_indirect`] are not being emulated
|
||||
/// with a series of `draw_indirect` calls.
|
||||
///
|
||||
/// Supported platforms:
|
||||
/// - DX12
|
||||
@ -813,6 +796,8 @@ bitflags_array! {
|
||||
///
|
||||
/// This is a native only feature.
|
||||
///
|
||||
/// [`RenderPass::multi_draw_indirect`]: ../wgpu/struct.RenderPass.html#method.multi_draw_indirect
|
||||
/// [`RenderPass::multi_draw_indexed_indirect`]: ../wgpu/struct.RenderPass.html#method.multi_draw_indexed_indirect
|
||||
/// [`RenderPass::multi_draw_indirect_count`]: ../wgpu/struct.RenderPass.html#method.multi_draw_indirect_count
|
||||
/// [`RenderPass::multi_draw_indexed_indirect_count`]: ../wgpu/struct.RenderPass.html#method.multi_draw_indexed_indirect_count
|
||||
const MULTI_DRAW_INDIRECT_COUNT = 1 << 15;
|
||||
|
||||
@ -236,6 +236,8 @@ impl RenderPass<'_> {
|
||||
///
|
||||
/// This is like calling [`RenderPass::draw`] but the contents of the call are specified in the `indirect_buffer`.
|
||||
/// The structure expected in `indirect_buffer` must conform to [`DrawIndirectArgs`](crate::util::DrawIndirectArgs).
|
||||
///
|
||||
/// Calling this requires the device support [`DownlevelFlags::INDIRECT_EXECUTION`].
|
||||
pub fn draw_indirect(&mut self, indirect_buffer: &Buffer, indirect_offset: BufferAddress) {
|
||||
self.inner
|
||||
.draw_indirect(&indirect_buffer.inner, indirect_offset);
|
||||
@ -246,6 +248,8 @@ impl RenderPass<'_> {
|
||||
///
|
||||
/// This is like calling [`RenderPass::draw_indexed`] but the contents of the call are specified in the `indirect_buffer`.
|
||||
/// The structure expected in `indirect_buffer` must conform to [`DrawIndexedIndirectArgs`](crate::util::DrawIndexedIndirectArgs).
|
||||
///
|
||||
/// Calling this requires the device support [`DownlevelFlags::INDIRECT_EXECUTION`].
|
||||
pub fn draw_indexed_indirect(
|
||||
&mut self,
|
||||
indirect_buffer: &Buffer,
|
||||
@ -287,10 +291,7 @@ impl RenderPass<'_> {
|
||||
|
||||
self.inner.execute_bundles(&mut render_bundles);
|
||||
}
|
||||
}
|
||||
|
||||
/// [`Features::MULTI_DRAW_INDIRECT`] must be enabled on the device in order to call these functions.
|
||||
impl RenderPass<'_> {
|
||||
/// Dispatches multiple draw calls from the active vertex buffer(s) based on the contents of the `indirect_buffer`.
|
||||
/// `count` draw calls are issued.
|
||||
///
|
||||
@ -299,6 +300,8 @@ impl RenderPass<'_> {
|
||||
/// The structure expected in `indirect_buffer` must conform to [`DrawIndirectArgs`](crate::util::DrawIndirectArgs).
|
||||
/// These draw structures are expected to be tightly packed.
|
||||
///
|
||||
/// Calling this requires the device support [`DownlevelFlags::INDIRECT_EXECUTION`].
|
||||
///
|
||||
/// This drawing command uses the current render state, as set by preceding `set_*()` methods.
|
||||
/// It is not affected by changes to the state that are performed after it is called.
|
||||
pub fn multi_draw_indirect(
|
||||
@ -320,6 +323,8 @@ impl RenderPass<'_> {
|
||||
/// The structure expected in `indirect_buffer` must conform to [`DrawIndexedIndirectArgs`](crate::util::DrawIndexedIndirectArgs).
|
||||
/// These draw structures are expected to be tightly packed.
|
||||
///
|
||||
/// Calling this requires the device support [`DownlevelFlags::INDIRECT_EXECUTION`].
|
||||
///
|
||||
/// This drawing command uses the current render state, as set by preceding `set_*()` methods.
|
||||
/// It is not affected by changes to the state that are performed after it is called.
|
||||
pub fn multi_draw_indexed_indirect(
|
||||
|
||||
@ -772,8 +772,7 @@ const FEATURES_MAPPING: [(wgt::Features, webgpu_sys::GpuFeatureName); 15] = [
|
||||
];
|
||||
|
||||
fn map_wgt_features(supported_features: webgpu_sys::GpuSupportedFeatures) -> wgt::Features {
|
||||
// We emulate MDI.
|
||||
let mut features = wgt::Features::MULTI_DRAW_INDIRECT;
|
||||
let mut features = wgt::Features::empty();
|
||||
for (wgpu_feat, web_feat) in FEATURES_MAPPING {
|
||||
match wasm_bindgen::JsValue::from(web_feat).as_string() {
|
||||
Some(value) if supported_features.has(&value) => features |= wgpu_feat,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user