From c42c02e8013eaa0c8695aa7e2352d70488f1bb6f Mon Sep 17 00:00:00 2001 From: teoxoy <28601907+teoxoy@users.noreply.github.com> Date: Tue, 25 Jun 2024 16:29:49 +0200 Subject: [PATCH] extract `multi_draw_indirect_count` from `render_pass_end_impl` --- wgpu-core/src/command/render.rs | 222 +++++++++++++++++--------------- 1 file changed, 115 insertions(+), 107 deletions(-) diff --git a/wgpu-core/src/command/render.rs b/wgpu-core/src/command/render.rs index ced425b7a0..f82b5275ac 100644 --- a/wgpu-core/src/command/render.rs +++ b/wgpu-core/src/command/render.rs @@ -1652,124 +1652,28 @@ impl Global { .map_pass_err(scope)?; } ArcRenderCommand::MultiDrawIndirectCount { - buffer: indirect_buffer, + buffer, offset, count_buffer, count_buffer_offset, max_count, indexed, } => { - api_log!( - "RenderPass::multi_draw_indirect_count (indexed:{indexed}) {} {offset} {} {count_buffer_offset:?} {max_count:?}", - indirect_buffer.error_ident(), - count_buffer.error_ident() - ); - let scope = PassErrorScope::Draw { kind: DrawKind::MultiDrawIndirectCount, indexed, pipeline: state.pipeline, }; - state.is_ready(indexed).map_pass_err(scope)?; - - let stride = match indexed { - false => mem::size_of::(), - true => mem::size_of::(), - } as u64; - - state - .device - .require_features(wgt::Features::MULTI_DRAW_INDIRECT_COUNT) - .map_pass_err(scope)?; - state - .device - .require_downlevel_flags(wgt::DownlevelFlags::INDIRECT_EXECUTION) - .map_pass_err(scope)?; - - state - .info - .usage_scope - .buffers - .merge_single(&indirect_buffer, hal::BufferUses::INDIRECT) - .map_pass_err(scope)?; - - indirect_buffer - .check_usage(BufferUsages::INDIRECT) - .map_pass_err(scope)?; - let indirect_raw = indirect_buffer - .try_raw(state.snatch_guard) - .map_pass_err(scope)?; - - state - .info - .usage_scope - .buffers - .merge_single(&count_buffer, hal::BufferUses::INDIRECT) - .map_pass_err(scope)?; - - count_buffer - .check_usage(BufferUsages::INDIRECT) - .map_pass_err(scope)?; - let count_raw = count_buffer - .try_raw(state.snatch_guard) - .map_pass_err(scope)?; - - let end_offset = offset + stride * max_count as u64; - if end_offset > indirect_buffer.size { - return Err(RenderPassErrorInner::IndirectBufferOverrun { - count: None, - offset, - end_offset, - buffer_size: indirect_buffer.size, - }) - .map_pass_err(scope); - } - state.buffer_memory_init_actions.extend( - indirect_buffer.initialization_status.read().create_action( - &indirect_buffer, - offset..end_offset, - MemoryInitKind::NeedsInitializedMemory, - ), - ); - - let begin_count_offset = count_buffer_offset; - let end_count_offset = count_buffer_offset + 4; - if end_count_offset > count_buffer.size { - return Err(RenderPassErrorInner::IndirectCountBufferOverrun { - begin_count_offset, - end_count_offset, - count_buffer_size: count_buffer.size, - }) - .map_pass_err(scope); - } - state.buffer_memory_init_actions.extend( - count_buffer.initialization_status.read().create_action( - &count_buffer, - count_buffer_offset..end_count_offset, - MemoryInitKind::NeedsInitializedMemory, - ), - ); - - match indexed { - false => unsafe { - state.raw_encoder.draw_indirect_count( - indirect_raw, - offset, - count_raw, - count_buffer_offset, - max_count, - ); - }, - true => unsafe { - state.raw_encoder.draw_indexed_indirect_count( - indirect_raw, - offset, - count_raw, - count_buffer_offset, - max_count, - ); - }, - } + multi_draw_indirect_count( + &mut state, + buffer, + offset, + count_buffer, + count_buffer_offset, + max_count, + indexed, + ) + .map_pass_err(scope)?; } ArcRenderCommand::PushDebugGroup { color: _, len } => { state.debug_scope_depth += 1; @@ -2617,6 +2521,110 @@ fn multi_draw_indirect( Ok(()) } +fn multi_draw_indirect_count( + state: &mut State, + indirect_buffer: Arc>, + offset: u64, + count_buffer: Arc>, + count_buffer_offset: u64, + max_count: u32, + indexed: bool, +) -> Result<(), RenderPassErrorInner> { + api_log!( + "RenderPass::multi_draw_indirect_count (indexed:{indexed}) {} {offset} {} {count_buffer_offset:?} {max_count:?}", + indirect_buffer.error_ident(), + count_buffer.error_ident() + ); + + state.is_ready(indexed)?; + + let stride = match indexed { + false => mem::size_of::(), + true => mem::size_of::(), + } as u64; + + state + .device + .require_features(wgt::Features::MULTI_DRAW_INDIRECT_COUNT)?; + state + .device + .require_downlevel_flags(wgt::DownlevelFlags::INDIRECT_EXECUTION)?; + + state + .info + .usage_scope + .buffers + .merge_single(&indirect_buffer, hal::BufferUses::INDIRECT)?; + + indirect_buffer.check_usage(BufferUsages::INDIRECT)?; + let indirect_raw = indirect_buffer.try_raw(state.snatch_guard)?; + + state + .info + .usage_scope + .buffers + .merge_single(&count_buffer, hal::BufferUses::INDIRECT)?; + + count_buffer.check_usage(BufferUsages::INDIRECT)?; + let count_raw = count_buffer.try_raw(state.snatch_guard)?; + + let end_offset = offset + stride * max_count as u64; + if end_offset > indirect_buffer.size { + return Err(RenderPassErrorInner::IndirectBufferOverrun { + count: None, + offset, + end_offset, + buffer_size: indirect_buffer.size, + }); + } + state.buffer_memory_init_actions.extend( + indirect_buffer.initialization_status.read().create_action( + &indirect_buffer, + offset..end_offset, + MemoryInitKind::NeedsInitializedMemory, + ), + ); + + let begin_count_offset = count_buffer_offset; + let end_count_offset = count_buffer_offset + 4; + if end_count_offset > count_buffer.size { + return Err(RenderPassErrorInner::IndirectCountBufferOverrun { + begin_count_offset, + end_count_offset, + count_buffer_size: count_buffer.size, + }); + } + state.buffer_memory_init_actions.extend( + count_buffer.initialization_status.read().create_action( + &count_buffer, + count_buffer_offset..end_count_offset, + MemoryInitKind::NeedsInitializedMemory, + ), + ); + + match indexed { + false => unsafe { + state.raw_encoder.draw_indirect_count( + indirect_raw, + offset, + count_raw, + count_buffer_offset, + max_count, + ); + }, + true => unsafe { + state.raw_encoder.draw_indexed_indirect_count( + indirect_raw, + offset, + count_raw, + count_buffer_offset, + max_count, + ); + }, + } + Ok(()) +} + impl Global { pub fn render_pass_set_bind_group( &self,