Skip to content

Commit 429db8a

Browse files
committed
fix(core): Fix resource usage for R/O depth w/o TEXTURE_BINDING
1 parent be1a711 commit 429db8a

3 files changed

Lines changed: 212 additions & 1 deletion

File tree

tests/tests/wgpu-gpu/main.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ mod regression {
99
pub mod issue_6317;
1010
pub mod issue_6467;
1111
pub mod issue_6827;
12+
pub mod issue_9343;
1213
}
1314

1415
mod bgra8unorm_storage;
@@ -133,6 +134,7 @@ fn all_tests() -> Vec<wgpu_test::GpuTestInitializer> {
133134
regression::issue_6317::all_tests(&mut tests);
134135
regression::issue_6467::all_tests(&mut tests);
135136
regression::issue_6827::all_tests(&mut tests);
137+
regression::issue_9343::all_tests(&mut tests);
136138
render_pass_ownership::all_tests(&mut tests);
137139
render_target::all_tests(&mut tests);
138140
resource_descriptor_accessor::all_tests(&mut tests);
Lines changed: 201 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,201 @@
1+
use wgpu::*;
2+
use wgpu_macros::gpu_test;
3+
use wgpu_test::{GpuTestConfiguration, GpuTestInitializer, TestParameters};
4+
5+
pub fn all_tests(vec: &mut Vec<GpuTestInitializer>) {
6+
vec.push(READ_ONLY_DEPTH_WITHOUT_TEXTURE_BINDING);
7+
}
8+
9+
/// Regression test for <https://github.com/gfx-rs/wgpu/issues/9343>, a dx12 crash when
10+
/// using a texture created without `TEXTURE_BINDING` as a read-only depth attachment.
11+
///
12+
/// When both depth and stencil were read-only, wgpu-core transitioned the depth
13+
/// texture to `DEPTH_STENCIL_READ | RESOURCE`. The `RESOURCE` usage maps to
14+
/// `D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE | NON_PIXEL_SHADER_RESOURCE` on
15+
/// dx12. However, a depth texture created without `TEXTURE_BINDING` cannot
16+
/// be transitioned to these states on dx12.
17+
#[gpu_test]
18+
static READ_ONLY_DEPTH_WITHOUT_TEXTURE_BINDING: GpuTestConfiguration = GpuTestConfiguration::new()
19+
.parameters(
20+
TestParameters::default()
21+
.downlevel_flags(DownlevelFlags::READ_ONLY_DEPTH_STENCIL)
22+
.enable_noop(),
23+
)
24+
.run_sync(|ctx| {
25+
let size = Extent3d {
26+
width: 64,
27+
height: 64,
28+
depth_or_array_layers: 1,
29+
};
30+
let color_texture = ctx.device.create_texture(&TextureDescriptor {
31+
label: Some("color"),
32+
size,
33+
mip_level_count: 1,
34+
sample_count: 1,
35+
dimension: TextureDimension::D2,
36+
format: TextureFormat::Rgba8Unorm,
37+
usage: TextureUsages::RENDER_ATTACHMENT,
38+
view_formats: &[],
39+
});
40+
let color_view = color_texture.create_view(&TextureViewDescriptor::default());
41+
42+
// Depth texture with _only_ `RENDER_ATTACHMENT` (no `TEXTURE_BINDING`).
43+
let depth_texture = ctx.device.create_texture(&TextureDescriptor {
44+
label: Some("depth"),
45+
size,
46+
mip_level_count: 1,
47+
sample_count: 1,
48+
dimension: TextureDimension::D2,
49+
format: TextureFormat::Depth32Float,
50+
usage: TextureUsages::RENDER_ATTACHMENT,
51+
view_formats: &[],
52+
});
53+
let depth_view = depth_texture.create_view(&TextureViewDescriptor::default());
54+
55+
let shader = ctx.device.create_shader_module(ShaderModuleDescriptor {
56+
label: None,
57+
source: ShaderSource::Wgsl(
58+
concat!(
59+
"@vertex fn vs() -> @builtin(position) vec4f {\n",
60+
" return vec4f(0.0, 0.0, 0.5, 1.0);\n",
61+
"}\n",
62+
"@fragment fn fs() -> @location(0) vec4f {\n",
63+
" return vec4f(1.0);\n",
64+
"}\n",
65+
)
66+
.into(),
67+
),
68+
});
69+
70+
let pipeline_layout = ctx
71+
.device
72+
.create_pipeline_layout(&PipelineLayoutDescriptor {
73+
label: None,
74+
bind_group_layouts: &[],
75+
immediate_size: 0,
76+
});
77+
78+
let vertex = VertexState {
79+
module: &shader,
80+
entry_point: Some("vs"),
81+
compilation_options: Default::default(),
82+
buffers: &[],
83+
};
84+
85+
let fragment = FragmentState {
86+
module: &shader,
87+
entry_point: Some("fs"),
88+
compilation_options: Default::default(),
89+
targets: &[Some(ColorTargetState {
90+
format: TextureFormat::Rgba8Unorm,
91+
blend: None,
92+
write_mask: ColorWrites::all(),
93+
})],
94+
};
95+
96+
// Write pipeline: depth_write_enabled = true
97+
let write_pipeline = ctx
98+
.device
99+
.create_render_pipeline(&RenderPipelineDescriptor {
100+
label: Some("depth write pipeline"),
101+
layout: Some(&pipeline_layout),
102+
vertex: vertex.clone(),
103+
primitive: PrimitiveState::default(),
104+
depth_stencil: Some(DepthStencilState {
105+
format: TextureFormat::Depth32Float,
106+
depth_write_enabled: Some(true),
107+
depth_compare: Some(CompareFunction::Always),
108+
stencil: StencilState::default(),
109+
bias: DepthBiasState::default(),
110+
}),
111+
multisample: MultisampleState::default(),
112+
fragment: Some(fragment.clone()),
113+
multiview_mask: None,
114+
cache: None,
115+
});
116+
117+
// Read-only pipeline: depth_write_enabled = false
118+
let readonly_pipeline = ctx
119+
.device
120+
.create_render_pipeline(&RenderPipelineDescriptor {
121+
label: Some("depth read pipeline"),
122+
layout: Some(&pipeline_layout),
123+
vertex,
124+
primitive: PrimitiveState::default(),
125+
depth_stencil: Some(DepthStencilState {
126+
format: TextureFormat::Depth32Float,
127+
depth_write_enabled: Some(false),
128+
depth_compare: None,
129+
stencil: StencilState::default(),
130+
bias: DepthBiasState::default(),
131+
}),
132+
multisample: MultisampleState::default(),
133+
fragment: Some(fragment),
134+
multiview_mask: None,
135+
cache: None,
136+
});
137+
138+
let mut encoder = ctx
139+
.device
140+
.create_command_encoder(&CommandEncoderDescriptor::default());
141+
142+
// First pass: writable depth, puts the depth texture in `DEPTH_STENCIL_WRITE` state.
143+
{
144+
let mut rpass = encoder.begin_render_pass(&RenderPassDescriptor {
145+
label: Some("depth write pass"),
146+
color_attachments: &[Some(RenderPassColorAttachment {
147+
view: &color_view,
148+
depth_slice: None,
149+
resolve_target: None,
150+
ops: Operations {
151+
load: LoadOp::Clear(Color::BLACK),
152+
store: StoreOp::Store,
153+
},
154+
})],
155+
depth_stencil_attachment: Some(RenderPassDepthStencilAttachment {
156+
view: &depth_view,
157+
depth_ops: Some(Operations {
158+
load: LoadOp::Clear(0.0),
159+
store: StoreOp::Store,
160+
}),
161+
stencil_ops: None,
162+
}),
163+
timestamp_writes: None,
164+
occlusion_query_set: None,
165+
multiview_mask: None,
166+
});
167+
rpass.set_pipeline(&write_pipeline);
168+
rpass.draw(0..1, 0..1);
169+
}
170+
171+
// Second pass: read-only depth, triggers the `DEPTH_STENCIL_WRITE` ->
172+
// `DEPTH_STENCIL_READ` transition. Before the fix, this would include
173+
// `RESOURCE` usage, even though the texture does not have
174+
// `TEXTURE_BINDING`
175+
{
176+
let mut rpass = encoder.begin_render_pass(&RenderPassDescriptor {
177+
label: Some("depth read pass"),
178+
color_attachments: &[Some(RenderPassColorAttachment {
179+
view: &color_view,
180+
depth_slice: None,
181+
resolve_target: None,
182+
ops: Operations {
183+
load: LoadOp::Load,
184+
store: StoreOp::Store,
185+
},
186+
})],
187+
depth_stencil_attachment: Some(RenderPassDepthStencilAttachment {
188+
view: &depth_view,
189+
depth_ops: None, // read-only depth
190+
stencil_ops: None, // read-only stencil
191+
}),
192+
timestamp_writes: None,
193+
occlusion_query_set: None,
194+
multiview_mask: None,
195+
});
196+
rpass.set_pipeline(&readonly_pipeline);
197+
rpass.draw(0..1, 0..1);
198+
}
199+
200+
ctx.queue.submit([encoder.finish()]);
201+
});

wgpu-core/src/command/render.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1189,7 +1189,15 @@ impl RenderPassInfo {
11891189
.flags
11901190
.contains(wgt::DownlevelFlags::READ_ONLY_DEPTH_STENCIL)
11911191
{
1192-
wgt::TextureUses::DEPTH_STENCIL_READ | wgt::TextureUses::RESOURCE
1192+
// If the texture supports TEXTURE_BINDING, it can be used as a shader
1193+
// resource and a read-only depth attachment simultaneously. But if it
1194+
// doesn't support TEXTURE_BINDING, don't attempt to transition it to a
1195+
// shader resource state, because DX12 will raise an error.
1196+
if view.desc.usage.contains(TextureUsages::TEXTURE_BINDING) {
1197+
wgt::TextureUses::DEPTH_STENCIL_READ | wgt::TextureUses::RESOURCE
1198+
} else {
1199+
wgt::TextureUses::DEPTH_STENCIL_READ
1200+
}
11931201
} else {
11941202
wgt::TextureUses::DEPTH_STENCIL_WRITE
11951203
};

0 commit comments

Comments
 (0)