Skip to content

Commit 910143d

Browse files
Check for more cases of unbalanced debug groups (#8048)
Fixes #3911
1 parent 7cb642e commit 910143d

File tree

6 files changed

+78
-30
lines changed

6 files changed

+78
-30
lines changed

cts_runner/test.lst

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,13 @@ webgpu:api,validation,encoding,cmds,clearBuffer:*
2525
webgpu:api,validation,encoding,cmds,compute_pass:set_pipeline:*
2626
webgpu:api,validation,encoding,cmds,compute_pass:dispatch_sizes:*
2727
webgpu:api,validation,encoding,cmds,copyTextureToTexture:*
28+
webgpu:api,validation,encoding,cmds,debug:debug_group_balanced:encoderType="non-pass"
29+
webgpu:api,validation,encoding,cmds,debug:debug_group_balanced:encoderType="compute%20pass"
30+
webgpu:api,validation,encoding,cmds,debug:debug_group_balanced:encoderType="render%20pass"
31+
//FAIL: webgpu:api,validation,encoding,cmds,debug:debug_group_balanced:encoderType="render%20bundle"
32+
// https://github.com/gfx-rs/wgpu/issues/8039
33+
webgpu:api,validation,encoding,cmds,debug:debug_group:*
34+
webgpu:api,validation,encoding,cmds,debug:debug_marker:*
2835
webgpu:api,validation,encoding,cmds,index_access:*
2936
//FAIL: webgpu:api,validation,encoding,cmds,render,draw:*
3037
webgpu:api,validation,encoding,cmds,render,draw:index_buffer_OOB:*
@@ -75,11 +82,7 @@ webgpu:api,validation,image_copy,layout_related:copy_end_overflows_u64:*
7582
// Fails with OOM in CI.
7683
fails-if(dx12) webgpu:api,validation,image_copy,layout_related:offset_alignment:*
7784
webgpu:api,validation,image_copy,texture_related:format:dimension="1d";*
78-
webgpu:api,validation,queue,submit:command_buffer,device_mismatch:*
79-
webgpu:api,validation,queue,submit:command_buffer,duplicate_buffers:*
80-
webgpu:api,validation,queue,submit:command_buffer,submit_invalidates:*
81-
//FAIL: webgpu:api,validation,queue,submit:command_buffer,invalid_submit_invalidates:*
82-
// https://github.com/gfx-rs/wgpu/issues/3911#issuecomment-2972995675
85+
webgpu:api,validation,queue,submit:command_buffer,*
8386
webgpu:api,validation,render_pass,render_pass_descriptor:attachments,*
8487
webgpu:api,validation,render_pass,render_pass_descriptor:resolveTarget,*
8588
webgpu:api,validation,texture,rg11b10ufloat_renderable:*
@@ -93,6 +96,7 @@ webgpu:api,operation,rendering,color_target_state:blend_constant,setting:*
9396
webgpu:api,operation,rendering,depth:*
9497
webgpu:api,operation,rendering,draw:*
9598
webgpu:api,operation,shader_module,compilation_info:*
99+
// Likely due to https://github.com/gfx-rs/wgpu/issues/7357.
96100
fails-if(metal) webgpu:api,operation,uncapturederror:iff_uncaptured:*
97101
//FAIL: webgpu:shader,execution,expression,call,builtin,select:*
98102
// - Fails with `const`/abstract int cases on all platforms because of <https://github.com/gfx-rs/wgpu/issues/4507>.

deno_webgpu/render_bundle.rs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,13 @@ use crate::buffer::GPUBuffer;
2020
use crate::texture::GPUTextureFormat;
2121
use crate::Instance;
2222

23+
fn c_string_truncated_at_first_nul<T: Into<Vec<u8>>>(src: T) -> std::ffi::CString {
24+
std::ffi::CString::new(src).unwrap_or_else(|err| {
25+
let nul_pos = err.nul_position();
26+
std::ffi::CString::new(err.into_vec().split_at(nul_pos).0).unwrap()
27+
})
28+
}
29+
2330
pub struct GPURenderBundleEncoder {
2431
pub instance: Instance,
2532
pub error_handler: super::error::ErrorHandler,
@@ -70,7 +77,7 @@ impl GPURenderBundleEncoder {
7077
.as_mut()
7178
.ok_or_else(|| JsErrorBox::generic("Encoder has already been finished"))?;
7279

73-
let label = std::ffi::CString::new(group_label).unwrap();
80+
let label = c_string_truncated_at_first_nul(group_label);
7481
// SAFETY: the string the raw pointer points to lives longer than the below
7582
// function invocation.
7683
unsafe {
@@ -99,8 +106,7 @@ impl GPURenderBundleEncoder {
99106
.as_mut()
100107
.ok_or_else(|| JsErrorBox::generic("Encoder has already been finished"))?;
101108

102-
let label = std::ffi::CString::new(marker_label).unwrap();
103-
109+
let label = c_string_truncated_at_first_nul(marker_label);
104110
// SAFETY: the string the raw pointer points to lives longer than the below
105111
// function invocation.
106112
unsafe {

wgpu-core/src/command/compute.rs

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use alloc::{borrow::Cow, boxed::Box, sync::Arc, vec::Vec};
88
use core::{fmt, str};
99

1010
use crate::command::{
11-
pass, CommandEncoder, EncoderStateError, PassStateError, TimestampWritesError,
11+
pass, CommandEncoder, DebugGroupError, EncoderStateError, PassStateError, TimestampWritesError,
1212
};
1313
use crate::resource::DestroyedResourceError;
1414
use crate::{binding_model::BindError, resource::RawResourceAccess};
@@ -146,6 +146,8 @@ pub enum ComputePassErrorInner {
146146
#[error("Parent encoder is invalid")]
147147
InvalidParentEncoder,
148148
#[error(transparent)]
149+
DebugGroupError(#[from] DebugGroupError),
150+
#[error(transparent)]
149151
BindGroupIndexOutOfRange(#[from] pass::BindGroupIndexOutOfRange),
150152
#[error(transparent)]
151153
DestroyedResource(#[from] DestroyedResourceError),
@@ -162,8 +164,6 @@ pub enum ComputePassErrorInner {
162164
#[error(transparent)]
163165
MissingBufferUsage(#[from] MissingBufferUsageError),
164166
#[error(transparent)]
165-
InvalidPopDebugGroup(#[from] pass::InvalidPopDebugGroup),
166-
#[error(transparent)]
167167
Dispatch(#[from] DispatchError),
168168
#[error(transparent)]
169169
Bind(#[from] BindError),
@@ -226,6 +226,7 @@ impl WebGpuError for ComputePassError {
226226
let e: &dyn WebGpuError = match inner {
227227
ComputePassErrorInner::Device(e) => e,
228228
ComputePassErrorInner::EncoderState(e) => e,
229+
ComputePassErrorInner::DebugGroupError(e) => e,
229230
ComputePassErrorInner::DestroyedResource(e) => e,
230231
ComputePassErrorInner::ResourceUsageCompatibility(e) => e,
231232
ComputePassErrorInner::MissingBufferUsage(e) => e,
@@ -238,7 +239,6 @@ impl WebGpuError for ComputePassError {
238239
ComputePassErrorInner::InvalidResource(e) => e,
239240
ComputePassErrorInner::TimestampWrites(e) => e,
240241
ComputePassErrorInner::InvalidValuesOffset(e) => e,
241-
ComputePassErrorInner::InvalidPopDebugGroup(e) => e,
242242

243243
ComputePassErrorInner::InvalidParentEncoder
244244
| ComputePassErrorInner::BindGroupIndexOutOfRange { .. }
@@ -734,6 +734,13 @@ impl Global {
734734
}
735735
}
736736

737+
if state.general.debug_scope_depth > 0 {
738+
Err(
739+
ComputePassErrorInner::DebugGroupError(DebugGroupError::MissingPop)
740+
.map_pass_err(pass_scope),
741+
)?;
742+
}
743+
737744
unsafe {
738745
state.general.raw_encoder.end_compute_pass();
739746
}

wgpu-core/src/command/mod.rs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,10 @@ impl CommandEncoderStatus {
284284
Self::Recording(mut inner) => {
285285
if let Err(err) = inner.encoder.close_if_open() {
286286
Self::Error(err.into())
287+
} else if inner.debug_scope_depth > 0 {
288+
Self::Error(CommandEncoderError::DebugGroupError(
289+
DebugGroupError::MissingPop,
290+
))
287291
} else {
288292
// Note: if we want to stop tracking the swapchain texture view,
289293
// this is the place to do it.
@@ -648,6 +652,8 @@ pub struct CommandBufferMutable {
648652

649653
indirect_draw_validation_resources: crate::indirect_validation::DrawResources,
650654

655+
debug_scope_depth: u32,
656+
651657
#[cfg(feature = "trace")]
652658
pub(crate) commands: Option<Vec<TraceCommand>>,
653659
}
@@ -721,6 +727,7 @@ impl CommandEncoder {
721727
temp_resources: Default::default(),
722728
indirect_draw_validation_resources:
723729
crate::indirect_validation::DrawResources::new(device.clone()),
730+
debug_scope_depth: 0,
724731
#[cfg(feature = "trace")]
725732
commands: if device.trace.lock().is_some() {
726733
Some(Vec::new())
@@ -1041,6 +1048,8 @@ pub enum CommandEncoderError {
10411048
#[error(transparent)]
10421049
ResourceUsage(#[from] ResourceUsageCompatibilityError),
10431050
#[error(transparent)]
1051+
DebugGroupError(#[from] DebugGroupError),
1052+
#[error(transparent)]
10441053
MissingFeatures(#[from] MissingFeatures),
10451054
#[error(transparent)]
10461055
Transfer(#[from] TransferError),
@@ -1094,6 +1103,7 @@ impl WebGpuError for CommandEncoderError {
10941103
let e: &dyn WebGpuError = match self {
10951104
Self::Device(e) => e,
10961105
Self::InvalidResource(e) => e,
1106+
Self::DebugGroupError(e) => e,
10971107
Self::MissingFeatures(e) => e,
10981108
Self::State(e) => e,
10991109
Self::DestroyedResource(e) => e,
@@ -1110,6 +1120,23 @@ impl WebGpuError for CommandEncoderError {
11101120
}
11111121
}
11121122

1123+
#[derive(Clone, Debug, Error)]
1124+
#[non_exhaustive]
1125+
pub enum DebugGroupError {
1126+
#[error("Cannot pop debug group, because number of pushed debug groups is zero")]
1127+
InvalidPop,
1128+
#[error("A debug group was not popped before the encoder was finished")]
1129+
MissingPop,
1130+
}
1131+
1132+
impl WebGpuError for DebugGroupError {
1133+
fn webgpu_error_type(&self) -> ErrorType {
1134+
match self {
1135+
Self::InvalidPop | Self::MissingPop => ErrorType::Validation,
1136+
}
1137+
}
1138+
}
1139+
11131140
#[derive(Clone, Debug, Error)]
11141141
#[non_exhaustive]
11151142
pub enum TimestampWritesError {
@@ -1175,6 +1202,8 @@ impl Global {
11751202
let cmd_enc = hub.command_encoders.get(encoder_id);
11761203
let mut cmd_buf_data = cmd_enc.data.lock();
11771204
cmd_buf_data.record_with(|cmd_buf_data| -> Result<(), CommandEncoderError> {
1205+
cmd_buf_data.debug_scope_depth += 1;
1206+
11781207
#[cfg(feature = "trace")]
11791208
if let Some(ref mut list) = cmd_buf_data.commands {
11801209
list.push(TraceCommand::PushDebugGroup(label.to_owned()));
@@ -1244,6 +1273,11 @@ impl Global {
12441273
let cmd_enc = hub.command_encoders.get(encoder_id);
12451274
let mut cmd_buf_data = cmd_enc.data.lock();
12461275
cmd_buf_data.record_with(|cmd_buf_data| -> Result<(), CommandEncoderError> {
1276+
if cmd_buf_data.debug_scope_depth == 0 {
1277+
return Err(DebugGroupError::InvalidPop.into());
1278+
}
1279+
cmd_buf_data.debug_scope_depth -= 1;
1280+
12471281
#[cfg(feature = "trace")]
12481282
if let Some(ref mut list) = cmd_buf_data.commands {
12491283
list.push(TraceCommand::PopDebugGroup);

wgpu-core/src/command/pass.rs

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
use crate::binding_model::{BindError, BindGroup, PushConstantUploadError};
44
use crate::command::bind::Binder;
55
use crate::command::memory_init::{CommandBufferTextureMemoryActions, SurfacesInDiscardState};
6-
use crate::command::{CommandEncoder, QueryResetMap, QueryUseError};
6+
use crate::command::{CommandEncoder, DebugGroupError, QueryResetMap, QueryUseError};
77
use crate::device::{Device, DeviceError, MissingFeatures};
88
use crate::init_tracker::BufferInitTrackerAction;
99
use crate::pipeline::LateSizedBufferGroup;
@@ -42,16 +42,6 @@ impl WebGpuError for InvalidValuesOffset {
4242
}
4343
}
4444

45-
#[derive(Clone, Debug, Error)]
46-
#[error("Cannot pop debug group, because number of pushed debug groups is zero")]
47-
pub struct InvalidPopDebugGroup;
48-
49-
impl WebGpuError for InvalidPopDebugGroup {
50-
fn webgpu_error_type(&self) -> ErrorType {
51-
ErrorType::Validation
52-
}
53-
}
54-
5545
pub(crate) struct BaseState<'scope, 'snatch_guard, 'cmd_enc, 'raw_encoder> {
5646
pub(crate) device: &'cmd_enc Arc<Device>,
5747

@@ -332,12 +322,12 @@ pub(crate) fn push_debug_group(state: &mut BaseState, string_data: &[u8], len: u
332322

333323
pub(crate) fn pop_debug_group<E>(state: &mut BaseState) -> Result<(), E>
334324
where
335-
E: From<InvalidPopDebugGroup>,
325+
E: From<DebugGroupError>,
336326
{
337327
api_log!("Pass::pop_debug_group");
338328

339329
if state.debug_scope_depth == 0 {
340-
return Err(InvalidPopDebugGroup.into());
330+
return Err(DebugGroupError::InvalidPop.into());
341331
}
342332
state.debug_scope_depth -= 1;
343333
if !state

wgpu-core/src/command/render.rs

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ use wgt::{
1111

1212
use crate::command::{
1313
pass, pass_base, pass_try, validate_and_begin_occlusion_query,
14-
validate_and_begin_pipeline_statistics_query, EncoderStateError, InnerCommandEncoder,
15-
PassStateError, TimestampWritesError,
14+
validate_and_begin_pipeline_statistics_query, DebugGroupError, EncoderStateError,
15+
InnerCommandEncoder, PassStateError, TimestampWritesError,
1616
};
1717
use crate::pipeline::{RenderPipeline, VertexStep};
1818
use crate::resource::RawResourceAccess;
@@ -671,6 +671,8 @@ pub enum RenderPassErrorInner {
671671
EncoderState(#[from] EncoderStateError),
672672
#[error("Parent encoder is invalid")]
673673
InvalidParentEncoder,
674+
#[error(transparent)]
675+
DebugGroupError(#[from] DebugGroupError),
674676
#[error("The format of the {location} ({format:?}) is not resolvable")]
675677
UnsupportedResolveTargetFormat {
676678
location: AttachmentErrorLocation,
@@ -738,8 +740,6 @@ pub enum RenderPassErrorInner {
738740
count_buffer_size: u64,
739741
},
740742
#[error(transparent)]
741-
InvalidPopDebugGroup(#[from] pass::InvalidPopDebugGroup),
742-
#[error(transparent)]
743743
ResourceUsageCompatibility(#[from] ResourceUsageCompatibilityError),
744744
#[error("Render bundle has incompatible targets, {0}")]
745745
IncompatibleBundleTargets(#[from] RenderPassCompatibilityError),
@@ -842,6 +842,7 @@ impl WebGpuError for RenderPassError {
842842
RenderPassErrorInner::Device(e) => e,
843843
RenderPassErrorInner::ColorAttachment(e) => e,
844844
RenderPassErrorInner::EncoderState(e) => e,
845+
RenderPassErrorInner::DebugGroupError(e) => e,
845846
RenderPassErrorInner::MissingFeatures(e) => e,
846847
RenderPassErrorInner::MissingDownlevelFlags(e) => e,
847848
RenderPassErrorInner::RenderCommand(e) => e,
@@ -854,7 +855,6 @@ impl WebGpuError for RenderPassError {
854855
RenderPassErrorInner::InvalidAttachment(e) => e,
855856
RenderPassErrorInner::TimestampWrites(e) => e,
856857
RenderPassErrorInner::InvalidValuesOffset(e) => e,
857-
RenderPassErrorInner::InvalidPopDebugGroup(e) => e,
858858

859859
RenderPassErrorInner::InvalidParentEncoder
860860
| RenderPassErrorInner::UnsupportedResolveTargetFormat { .. }
@@ -2220,6 +2220,13 @@ impl Global {
22202220
}
22212221
}
22222222

2223+
if state.general.debug_scope_depth > 0 {
2224+
Err(
2225+
RenderPassErrorInner::DebugGroupError(DebugGroupError::MissingPop)
2226+
.map_pass_err(pass_scope),
2227+
)?;
2228+
}
2229+
22232230
state
22242231
.info
22252232
.finish(

0 commit comments

Comments
 (0)