diff --git a/CHANGELOG.md b/CHANGELOG.md index 99d97564f..2cddec8cf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,8 @@ # Change Log +## v0.5.6 (2020-07-09) + - add debug markers support + ## v0.5.5 (2020-05-20) - fix destruction of adapters, swap chains, and bind group layouts - fix command pool leak with temporary threads diff --git a/wgpu-core/Cargo.toml b/wgpu-core/Cargo.toml index 95d5d3275..d65fb16e6 100644 --- a/wgpu-core/Cargo.toml +++ b/wgpu-core/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wgpu-core" -version = "0.5.5" +version = "0.5.6" authors = [ "Dzmitry Malyshau ", "Joshua Groves ", diff --git a/wgpu-core/src/command/compute.rs b/wgpu-core/src/command/compute.rs index 1a545f1ff..e894dab5d 100644 --- a/wgpu-core/src/command/compute.rs +++ b/wgpu-core/src/command/compute.rs @@ -16,7 +16,7 @@ use hal::command::CommandBuffer as _; use peek_poke::{Peek, PeekPoke, Poke}; use wgt::{BufferAddress, BufferUsage, DynamicOffset, BIND_BUFFER_ALIGNMENT}; -use std::iter; +use std::{iter, str}; #[derive(Debug, PartialEq)] enum PipelineState { @@ -38,9 +38,28 @@ enum ComputeCommand { buffer_id: id::BufferId, offset: BufferAddress, }, + PushDebugGroup { + color: u32, + len: usize, + #[cfg_attr(any(feature = "trace", feature = "replay"), serde(skip))] + phantom_marker: PhantomSlice, + }, + PopDebugGroup, + InsertDebugMarker { + color: u32, + len: usize, + #[cfg_attr(any(feature = "trace", feature = "replay"), serde(skip))] + phantom_marker: PhantomSlice, + }, End, } +#[derive(Debug)] +struct State { + binder: Binder, + debug_scope_depth: u32, +} + impl Default for ComputeCommand { fn default() -> Self { ComputeCommand::End @@ -78,7 +97,6 @@ impl Global { let (mut cmb_guard, mut token) = hub.command_buffers.write(&mut token); let cmb = &mut cmb_guard[encoder_id]; let raw = cmb.raw.last_mut().unwrap(); - let mut binder = Binder::new(cmb.limits.max_bind_groups); let (pipeline_layout_guard, mut token) = hub.pipeline_layouts.read(&mut token); let (bind_group_guard, mut token) = hub.bind_groups.read(&mut token); @@ -88,6 +106,11 @@ impl Global { let mut pipeline_state = PipelineState::Required; + let mut state = State { + binder: Binder::new(cmb.limits.max_bind_groups), + debug_scope_depth: 0, + }; + let mut peeker = raw_data.as_ptr(); let raw_data_end = unsafe { raw_data.as_ptr().add(raw_data.len()) }; let mut command = ComputeCommand::Dispatch([0; 3]); // dummy @@ -142,9 +165,12 @@ impl Global { &*texture_guard, ); - if let Some((pipeline_layout_id, follow_ups)) = - binder.provide_entry(index as usize, bind_group_id, bind_group, offsets) - { + if let Some((pipeline_layout_id, follow_ups)) = state.binder.provide_entry( + index as usize, + bind_group_id, + bind_group, + offsets, + ) { let bind_groups = iter::once(bind_group.raw.raw()).chain( follow_ups .clone() @@ -176,13 +202,16 @@ impl Global { } // Rebind resources - if binder.pipeline_layout_id != Some(pipeline.layout_id.value) { + if state.binder.pipeline_layout_id != Some(pipeline.layout_id.value) { let pipeline_layout = &pipeline_layout_guard[pipeline.layout_id.value]; - binder.pipeline_layout_id = Some(pipeline.layout_id.value); - binder.reset_expectations(pipeline_layout.bind_group_layout_ids.len()); + state.binder.pipeline_layout_id = Some(pipeline.layout_id.value); + state + .binder + .reset_expectations(pipeline_layout.bind_group_layout_ids.len()); let mut is_compatible = true; - for (index, (entry, bgl_id)) in binder + for (index, (entry, bgl_id)) in state + .binder .entries .iter_mut() .zip(&pipeline_layout.bind_group_layout_ids) @@ -243,6 +272,39 @@ impl Global { raw.dispatch_indirect(&src_buffer.raw, offset); } } + ComputeCommand::PushDebugGroup { + color, + len, + phantom_marker, + } => unsafe { + state.debug_scope_depth += 1; + + let (new_peeker, label) = + { phantom_marker.decode_unaligned(peeker, len, raw_data_end) }; + peeker = new_peeker; + + raw.begin_debug_marker(str::from_utf8(label).unwrap(), color) + }, + ComputeCommand::PopDebugGroup => unsafe { + assert_ne!( + state.debug_scope_depth, 0, + "Can't pop debug group, because number of pushed debug groups is zero!" + ); + state.debug_scope_depth -= 1; + + raw.end_debug_marker() + }, + ComputeCommand::InsertDebugMarker { + color, + len, + phantom_marker, + } => unsafe { + let (new_peeker, label) = + { phantom_marker.decode_unaligned(peeker, len, raw_data_end) }; + peeker = new_peeker; + + raw.insert_debug_marker(str::from_utf8(label).unwrap(), color) + }, ComputeCommand::End => break, } } @@ -255,7 +317,7 @@ pub mod compute_ffi { ComputeCommand, }; use crate::{id, RawString}; - use std::{convert::TryInto, slice}; + use std::{convert::TryInto, ffi, slice}; use wgt::{BufferAddress, DynamicOffset}; /// # Safety @@ -309,21 +371,40 @@ pub mod compute_ffi { } #[no_mangle] - pub extern "C" fn wgpu_compute_pass_push_debug_group(_pass: &mut RawPass, _label: RawString) { - //TODO - } - - #[no_mangle] - pub extern "C" fn wgpu_compute_pass_pop_debug_group(_pass: &mut RawPass) { - //TODO - } - - #[no_mangle] - pub extern "C" fn wgpu_compute_pass_insert_debug_marker( - _pass: &mut RawPass, - _label: RawString, + pub unsafe extern "C" fn wgpu_compute_pass_push_debug_group( + pass: &mut RawPass, + label: RawString, + color: u32, ) { - //TODO + let bytes = ffi::CStr::from_ptr(label).to_bytes(); + + pass.encode(&ComputeCommand::PushDebugGroup { + color, + len: bytes.len(), + phantom_marker: PhantomSlice::default(), + }); + pass.encode_slice(bytes); + } + + #[no_mangle] + pub unsafe extern "C" fn wgpu_compute_pass_pop_debug_group(pass: &mut RawPass) { + pass.encode(&ComputeCommand::PopDebugGroup); + } + + #[no_mangle] + pub unsafe extern "C" fn wgpu_compute_pass_insert_debug_marker( + pass: &mut RawPass, + label: RawString, + color: u32, + ) { + let bytes = ffi::CStr::from_ptr(label).to_bytes(); + + pass.encode(&ComputeCommand::InsertDebugMarker { + color, + len: bytes.len(), + phantom_marker: PhantomSlice::default(), + }); + pass.encode_slice(bytes); } #[no_mangle] diff --git a/wgpu-core/src/command/mod.rs b/wgpu-core/src/command/mod.rs index 8716eddda..adddf6c40 100644 --- a/wgpu-core/src/command/mod.rs +++ b/wgpu-core/src/command/mod.rs @@ -22,6 +22,8 @@ use crate::{ LifeGuard, PrivateFeatures, Stored, }; +use hal::command::CommandBuffer as _; + use peek_poke::PeekPoke; use std::{marker::PhantomData, mem, ptr, slice, thread::ThreadId}; @@ -259,4 +261,51 @@ impl Global { log::debug!("Command buffer {:?} {:#?}", encoder_id, comb.trackers); encoder_id } + + pub fn command_encoder_push_debug_group( + &self, + encoder_id: id::CommandEncoderId, + label: &str, + ) { + let hub = B::hub(self); + let mut token = Token::root(); + + let (mut cmb_guard, _) = hub.command_buffers.write(&mut token); + let cmb = &mut cmb_guard[encoder_id]; + let cmb_raw = cmb.raw.last_mut().unwrap(); + + unsafe { + cmb_raw.begin_debug_marker(label, 0); + } + } + + pub fn command_encoder_insert_debug_marker( + &self, + encoder_id: id::CommandEncoderId, + label: &str, + ) { + let hub = B::hub(self); + let mut token = Token::root(); + + let (mut cmb_guard, _) = hub.command_buffers.write(&mut token); + let cmb = &mut cmb_guard[encoder_id]; + let cmb_raw = cmb.raw.last_mut().unwrap(); + + unsafe { + cmb_raw.insert_debug_marker(label, 0); + } + } + + pub fn command_encoder_pop_debug_group(&self, encoder_id: id::CommandEncoderId) { + let hub = B::hub(self); + let mut token = Token::root(); + + let (mut cmb_guard, _) = hub.command_buffers.write(&mut token); + let cmb = &mut cmb_guard[encoder_id]; + let cmb_raw = cmb.raw.last_mut().unwrap(); + + unsafe { + cmb_raw.end_debug_marker(); + } + } } diff --git a/wgpu-core/src/command/render.rs b/wgpu-core/src/command/render.rs index 7f53f4831..0b889dcc9 100644 --- a/wgpu-core/src/command/render.rs +++ b/wgpu-core/src/command/render.rs @@ -29,7 +29,7 @@ use wgt::{ TextureUsage, BIND_BUFFER_ALIGNMENT, }; -use std::{borrow::Borrow, collections::hash_map::Entry, fmt, iter, mem, ops::Range, slice}; +use std::{borrow::Borrow, collections::hash_map::Entry, fmt, iter, mem, ops::Range, slice, str}; pub type RenderPassColorAttachmentDescriptor = RenderPassColorAttachmentDescriptorBase; @@ -102,6 +102,19 @@ enum RenderCommand { buffer_id: id::BufferId, offset: BufferAddress, }, + PushDebugGroup { + color: u32, + len: usize, + #[cfg_attr(any(feature = "trace", feature = "replay"), serde(skip))] + phantom_marker: PhantomSlice, + }, + PopDebugGroup, + InsertDebugMarker { + color: u32, + len: usize, + #[cfg_attr(any(feature = "trace", feature = "replay"), serde(skip))] + phantom_marker: PhantomSlice, + }, End, } @@ -266,6 +279,7 @@ struct State { pipeline: OptionalState, index: IndexState, vertex: VertexState, + debug_scope_depth: u32, } impl State { @@ -832,6 +846,7 @@ impl Global { vertex_limit: 0, instance_limit: 0, }, + debug_scope_depth: 0, }; let mut command = RenderCommand::Draw { @@ -1197,6 +1212,39 @@ impl Global { raw.draw_indexed_indirect(&buffer.raw, offset, 1, 0); } } + RenderCommand::PushDebugGroup { + color, + len, + phantom_marker, + } => unsafe { + state.debug_scope_depth += 1; + + let (new_peeker, label) = + { phantom_marker.decode_unaligned(peeker, len, raw_data_end) }; + peeker = new_peeker; + + raw.begin_debug_marker(str::from_utf8(label).unwrap(), color) + }, + RenderCommand::PopDebugGroup => unsafe { + assert_ne!( + state.debug_scope_depth, 0, + "Can't pop debug group, because number of pushed debug groups is zero!" + ); + state.debug_scope_depth -= 1; + + raw.end_debug_marker() + }, + RenderCommand::InsertDebugMarker { + color, + len, + phantom_marker, + } => unsafe { + let (new_peeker, label) = + { phantom_marker.decode_unaligned(peeker, len, raw_data_end) }; + peeker = new_peeker; + + raw.insert_debug_marker(str::from_utf8(label).unwrap(), color) + }, RenderCommand::End => break, } } @@ -1225,7 +1273,7 @@ pub mod render_ffi { RenderCommand, }; use crate::{id, RawString}; - use std::{convert::TryInto, slice}; + use std::{convert::TryInto, ffi, slice}; use wgt::{BufferAddress, Color, DynamicOffset}; /// # Safety @@ -1392,18 +1440,40 @@ pub mod render_ffi { } #[no_mangle] - pub extern "C" fn wgpu_render_pass_push_debug_group(_pass: &mut RawPass, _label: RawString) { - //TODO + pub unsafe extern "C" fn wgpu_render_pass_push_debug_group( + pass: &mut RawPass, + label: RawString, + color: u32, + ) { + let bytes = ffi::CStr::from_ptr(label).to_bytes(); + + pass.encode(&RenderCommand::PushDebugGroup { + color, + len: bytes.len(), + phantom_marker: PhantomSlice::default(), + }); + pass.encode_slice(bytes); } #[no_mangle] - pub extern "C" fn wgpu_render_pass_pop_debug_group(_pass: &mut RawPass) { - //TODO + pub unsafe extern "C" fn wgpu_render_pass_pop_debug_group(pass: &mut RawPass) { + pass.encode(&RenderCommand::PopDebugGroup); } #[no_mangle] - pub extern "C" fn wgpu_render_pass_insert_debug_marker(_pass: &mut RawPass, _label: RawString) { - //TODO + pub unsafe extern "C" fn wgpu_render_pass_insert_debug_marker( + pass: &mut RawPass, + label: RawString, + color: u32, + ) { + let bytes = ffi::CStr::from_ptr(label).to_bytes(); + + pass.encode(&RenderCommand::InsertDebugMarker { + color, + len: bytes.len(), + phantom_marker: PhantomSlice::default(), + }); + pass.encode_slice(bytes); } #[no_mangle]