wgpu: Don't create depth buffers, or use any depth testing, if we aren't expecting masks
This commit is contained in:
parent
05f49dd487
commit
cb2b27ba03
|
@ -17,7 +17,7 @@ pub struct CommandTarget<'pass> {
|
|||
frame_buffer: FrameBuffer,
|
||||
blend_buffer: OnceCell<BlendBuffer>,
|
||||
resolve_buffer: Option<ResolveBuffer>,
|
||||
depth: DepthBuffer,
|
||||
depth: OnceCell<DepthBuffer>,
|
||||
globals: &'pass Globals,
|
||||
size: wgpu::Extent3d,
|
||||
format: wgpu::TextureFormat,
|
||||
|
@ -97,18 +97,11 @@ impl<'pass> CommandTarget<'pass> {
|
|||
None
|
||||
};
|
||||
|
||||
let depth = DepthBuffer::new(
|
||||
&descriptors.device,
|
||||
create_debug_label!("Depth buffer"),
|
||||
sample_count,
|
||||
size,
|
||||
);
|
||||
|
||||
Self {
|
||||
frame_buffer,
|
||||
blend_buffer: OnceCell::new(),
|
||||
resolve_buffer,
|
||||
depth,
|
||||
depth: OnceCell::new(),
|
||||
globals,
|
||||
size,
|
||||
format,
|
||||
|
@ -160,9 +153,21 @@ impl<'pass> CommandTarget<'pass> {
|
|||
})
|
||||
}
|
||||
|
||||
pub fn depth_attachment(&self, clear: bool) -> Option<wgpu::RenderPassDepthStencilAttachment> {
|
||||
pub fn depth_attachment(
|
||||
&self,
|
||||
descriptors: &Descriptors,
|
||||
clear: bool,
|
||||
) -> Option<wgpu::RenderPassDepthStencilAttachment> {
|
||||
let depth = self.depth.get_or_init(|| {
|
||||
DepthBuffer::new(
|
||||
&descriptors.device,
|
||||
create_debug_label!("Depth buffer"),
|
||||
self.sample_count,
|
||||
self.size,
|
||||
)
|
||||
});
|
||||
Some(wgpu::RenderPassDepthStencilAttachment {
|
||||
view: self.depth.view(),
|
||||
view: depth.view(),
|
||||
depth_ops: Some(wgpu::Operations {
|
||||
load: if clear {
|
||||
wgpu::LoadOp::Clear(0.0)
|
||||
|
@ -231,6 +236,7 @@ pub struct CommandRenderer<'pass, 'frame: 'pass, 'global: 'frame> {
|
|||
render_pass: wgpu::RenderPass<'pass>,
|
||||
uniform_buffers: &'frame mut UniformBuffer<'global, Transforms>,
|
||||
uniform_encoder: &'frame mut wgpu::CommandEncoder,
|
||||
needs_depth: bool,
|
||||
}
|
||||
|
||||
impl<'pass, 'frame: 'pass, 'global: 'frame> CommandRenderer<'pass, 'frame, 'global> {
|
||||
|
@ -244,6 +250,7 @@ impl<'pass, 'frame: 'pass, 'global: 'frame> CommandRenderer<'pass, 'frame, 'glob
|
|||
render_pass: wgpu::RenderPass<'pass>,
|
||||
num_masks: u32,
|
||||
mask_state: MaskState,
|
||||
needs_depth: bool,
|
||||
) -> Self {
|
||||
Self {
|
||||
pipelines,
|
||||
|
@ -254,6 +261,7 @@ impl<'pass, 'frame: 'pass, 'global: 'frame> CommandRenderer<'pass, 'frame, 'glob
|
|||
descriptors,
|
||||
uniform_buffers,
|
||||
uniform_encoder,
|
||||
needs_depth,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -284,12 +292,16 @@ impl<'pass, 'frame: 'pass, 'global: 'frame> CommandRenderer<'pass, 'frame, 'glob
|
|||
|
||||
for chunk in chunk_blends(commands.0) {
|
||||
match chunk {
|
||||
Chunk::Draw(chunk) => {
|
||||
Chunk::Draw(chunk, needs_depth) => {
|
||||
let mut render_pass =
|
||||
draw_encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
|
||||
label: None,
|
||||
color_attachments: &[target.color_attachments(clear_color.take())],
|
||||
depth_stencil_attachment: target.depth_attachment(first && clear_depth),
|
||||
depth_stencil_attachment: if needs_depth {
|
||||
target.depth_attachment(&descriptors, first && clear_depth)
|
||||
} else {
|
||||
None
|
||||
},
|
||||
});
|
||||
render_pass.set_bind_group(0, target.globals.bind_group(), &[]);
|
||||
let mut renderer = CommandRenderer::new(
|
||||
|
@ -301,6 +313,7 @@ impl<'pass, 'frame: 'pass, 'global: 'frame> CommandRenderer<'pass, 'frame, 'glob
|
|||
render_pass,
|
||||
num_masks,
|
||||
mask_state,
|
||||
needs_depth,
|
||||
);
|
||||
|
||||
for command in &chunk {
|
||||
|
@ -348,7 +361,7 @@ impl<'pass, 'frame: 'pass, 'global: 'frame> CommandRenderer<'pass, 'frame, 'glob
|
|||
num_masks = renderer.num_masks;
|
||||
mask_state = renderer.mask_state;
|
||||
}
|
||||
Chunk::Blend(commands, blend_mode) => {
|
||||
Chunk::Blend(commands, blend_mode, needs_depth) => {
|
||||
let parent = match blend_mode {
|
||||
BlendMode::Alpha | BlendMode::Erase => nearest_layer,
|
||||
_ => target,
|
||||
|
@ -434,7 +447,11 @@ impl<'pass, 'frame: 'pass, 'global: 'frame> CommandRenderer<'pass, 'frame, 'glob
|
|||
color_attachments: &[
|
||||
target.color_attachments(clear_color.take())
|
||||
],
|
||||
depth_stencil_attachment: target.depth_attachment(false),
|
||||
depth_stencil_attachment: if needs_depth {
|
||||
target.depth_attachment(descriptors, false)
|
||||
} else {
|
||||
None
|
||||
},
|
||||
});
|
||||
render_pass.set_bind_group(0, target.globals.bind_group(), &[]);
|
||||
|
||||
|
@ -451,8 +468,13 @@ impl<'pass, 'frame: 'pass, 'global: 'frame> CommandRenderer<'pass, 'frame, 'glob
|
|||
}
|
||||
}
|
||||
|
||||
render_pass
|
||||
.set_pipeline(pipelines.bitmap[blend].pipeline_for(mask_state));
|
||||
if needs_depth {
|
||||
render_pass
|
||||
.set_pipeline(pipelines.bitmap[blend].pipeline_for(mask_state));
|
||||
} else {
|
||||
render_pass
|
||||
.set_pipeline(pipelines.bitmap[blend].depthless_pipeline());
|
||||
}
|
||||
|
||||
render_pass.set_bind_group(1, target.whole_frame_bind_group(), &[0]);
|
||||
render_pass.set_bind_group(2, &bitmap_bind_group, &[]);
|
||||
|
@ -512,7 +534,11 @@ impl<'pass, 'frame: 'pass, 'global: 'frame> CommandRenderer<'pass, 'frame, 'glob
|
|||
color_attachments: &[
|
||||
target.color_attachments(clear_color.take())
|
||||
],
|
||||
depth_stencil_attachment: target.depth_attachment(false),
|
||||
depth_stencil_attachment: if needs_depth {
|
||||
target.depth_attachment(descriptors, false)
|
||||
} else {
|
||||
None
|
||||
},
|
||||
});
|
||||
render_pass.set_bind_group(0, target.globals.bind_group(), &[]);
|
||||
|
||||
|
@ -529,8 +555,13 @@ impl<'pass, 'frame: 'pass, 'global: 'frame> CommandRenderer<'pass, 'frame, 'glob
|
|||
}
|
||||
}
|
||||
|
||||
render_pass
|
||||
.set_pipeline(pipelines.complex_blend.pipeline_for(mask_state));
|
||||
if needs_depth {
|
||||
render_pass
|
||||
.set_pipeline(pipelines.complex_blend.pipeline_for(mask_state));
|
||||
} else {
|
||||
render_pass
|
||||
.set_pipeline(pipelines.complex_blend.depthless_pipeline());
|
||||
}
|
||||
|
||||
render_pass.set_bind_group(1, target.whole_frame_bind_group(), &[0]);
|
||||
render_pass.set_bind_group(2, &blend_bind_group, &[]);
|
||||
|
@ -554,21 +585,36 @@ impl<'pass, 'frame: 'pass, 'global: 'frame> CommandRenderer<'pass, 'frame, 'glob
|
|||
}
|
||||
|
||||
pub fn prep_color(&mut self) {
|
||||
self.render_pass
|
||||
.set_pipeline(self.pipelines.color.pipeline_for(self.mask_state));
|
||||
if self.needs_depth {
|
||||
self.render_pass
|
||||
.set_pipeline(self.pipelines.color.pipeline_for(self.mask_state));
|
||||
} else {
|
||||
self.render_pass
|
||||
.set_pipeline(self.pipelines.color.depthless_pipeline());
|
||||
}
|
||||
}
|
||||
|
||||
pub fn prep_gradient(&mut self, bind_group: &'pass wgpu::BindGroup) {
|
||||
self.render_pass
|
||||
.set_pipeline(self.pipelines.gradient.pipeline_for(self.mask_state));
|
||||
if self.needs_depth {
|
||||
self.render_pass
|
||||
.set_pipeline(self.pipelines.gradient.pipeline_for(self.mask_state));
|
||||
} else {
|
||||
self.render_pass
|
||||
.set_pipeline(self.pipelines.gradient.depthless_pipeline());
|
||||
}
|
||||
|
||||
self.render_pass.set_bind_group(2, bind_group, &[]);
|
||||
}
|
||||
|
||||
pub fn prep_bitmap(&mut self, bind_group: &'pass wgpu::BindGroup) {
|
||||
self.render_pass.set_pipeline(
|
||||
self.pipelines.bitmap[TrivialBlend::Normal].pipeline_for(self.mask_state),
|
||||
);
|
||||
if self.needs_depth {
|
||||
self.render_pass.set_pipeline(
|
||||
self.pipelines.bitmap[TrivialBlend::Normal].pipeline_for(self.mask_state),
|
||||
);
|
||||
} else {
|
||||
self.render_pass
|
||||
.set_pipeline(self.pipelines.bitmap[TrivialBlend::Normal].depthless_pipeline());
|
||||
}
|
||||
|
||||
self.render_pass.set_bind_group(2, bind_group, &[]);
|
||||
}
|
||||
|
@ -749,22 +795,30 @@ impl<'pass, 'frame: 'pass, 'global: 'frame> CommandRenderer<'pass, 'frame, 'glob
|
|||
|
||||
#[derive(Debug)]
|
||||
pub enum Chunk {
|
||||
Draw(Vec<Command>),
|
||||
Blend(CommandList, BlendMode),
|
||||
Draw(Vec<Command>, bool),
|
||||
Blend(CommandList, BlendMode, bool),
|
||||
}
|
||||
|
||||
/// Chunk the commands such that every Blend is separated out
|
||||
fn chunk_blends(commands: Vec<Command>) -> Vec<Chunk> {
|
||||
let mut result = vec![];
|
||||
let mut current = vec![];
|
||||
let mut needs_depth = false;
|
||||
|
||||
for command in commands {
|
||||
match command {
|
||||
Command::Blend(commands, blend_mode) => {
|
||||
if !current.is_empty() {
|
||||
result.push(Chunk::Draw(std::mem::take(&mut current)));
|
||||
result.push(Chunk::Draw(std::mem::take(&mut current), needs_depth));
|
||||
}
|
||||
result.push(Chunk::Blend(commands, blend_mode));
|
||||
result.push(Chunk::Blend(commands, blend_mode, needs_depth));
|
||||
}
|
||||
Command::PushMask
|
||||
| Command::ActivateMask
|
||||
| Command::PopMask
|
||||
| Command::DeactivateMask => {
|
||||
needs_depth = true;
|
||||
current.push(command);
|
||||
}
|
||||
_ => {
|
||||
current.push(command);
|
||||
|
@ -773,7 +827,7 @@ fn chunk_blends(commands: Vec<Command>) -> Vec<Chunk> {
|
|||
}
|
||||
|
||||
if !current.is_empty() {
|
||||
result.push(Chunk::Draw(current));
|
||||
result.push(Chunk::Draw(current, needs_depth));
|
||||
}
|
||||
|
||||
result
|
||||
|
|
|
@ -17,6 +17,7 @@ pub const VERTEX_BUFFERS_DESCRIPTION: [wgpu::VertexBufferLayout; 1] = [wgpu::Ver
|
|||
#[derive(Debug)]
|
||||
pub struct ShapePipeline {
|
||||
pub pipelines: EnumMap<MaskState, wgpu::RenderPipeline>,
|
||||
depthless: wgpu::RenderPipeline,
|
||||
}
|
||||
|
||||
#[derive(Enum, Debug)]
|
||||
|
@ -99,10 +100,17 @@ impl ShapePipeline {
|
|||
&self.pipelines[mask_state]
|
||||
}
|
||||
|
||||
pub fn depthless_pipeline(&self) -> &wgpu::RenderPipeline {
|
||||
&self.depthless
|
||||
}
|
||||
|
||||
/// Builds of a nested `EnumMap` that maps a `MaskState` to
|
||||
/// a `RenderPipeline`. The provided callback is used to construct the `RenderPipeline`
|
||||
/// for each possible `MaskState`.
|
||||
fn build(mut f: impl FnMut(MaskState) -> wgpu::RenderPipeline) -> Self {
|
||||
fn build(
|
||||
depthless: wgpu::RenderPipeline,
|
||||
mut f: impl FnMut(MaskState) -> wgpu::RenderPipeline,
|
||||
) -> Self {
|
||||
let mask_array: [wgpu::RenderPipeline; MaskState::LENGTH] = (0..MaskState::LENGTH)
|
||||
.map(|mask_enum| {
|
||||
let mask_state = MaskState::from_usize(mask_enum);
|
||||
|
@ -113,6 +121,7 @@ impl ShapePipeline {
|
|||
.unwrap();
|
||||
ShapePipeline {
|
||||
pipelines: EnumMap::from_array(mask_array),
|
||||
depthless,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -289,46 +298,62 @@ fn create_shape_pipeline(
|
|||
))
|
||||
};
|
||||
|
||||
ShapePipeline::build(|mask_state| match mask_state {
|
||||
MaskState::NoMask => mask_render_state(
|
||||
"no mask",
|
||||
wgpu::StencilFaceState {
|
||||
compare: wgpu::CompareFunction::Always,
|
||||
fail_op: wgpu::StencilOperation::Keep,
|
||||
depth_fail_op: wgpu::StencilOperation::Keep,
|
||||
pass_op: wgpu::StencilOperation::Keep,
|
||||
},
|
||||
wgpu::ColorWrites::ALL,
|
||||
),
|
||||
MaskState::DrawMaskStencil => mask_render_state(
|
||||
"draw mask stencil",
|
||||
wgpu::StencilFaceState {
|
||||
compare: wgpu::CompareFunction::Equal,
|
||||
fail_op: wgpu::StencilOperation::Keep,
|
||||
depth_fail_op: wgpu::StencilOperation::Keep,
|
||||
pass_op: wgpu::StencilOperation::IncrementClamp,
|
||||
},
|
||||
wgpu::ColorWrites::empty(),
|
||||
),
|
||||
MaskState::DrawMaskedContent => mask_render_state(
|
||||
"draw masked content",
|
||||
wgpu::StencilFaceState {
|
||||
compare: wgpu::CompareFunction::Equal,
|
||||
fail_op: wgpu::StencilOperation::Keep,
|
||||
depth_fail_op: wgpu::StencilOperation::Keep,
|
||||
pass_op: wgpu::StencilOperation::Keep,
|
||||
},
|
||||
wgpu::ColorWrites::ALL,
|
||||
),
|
||||
MaskState::ClearMaskStencil => mask_render_state(
|
||||
"clear mask stencil",
|
||||
wgpu::StencilFaceState {
|
||||
compare: wgpu::CompareFunction::Equal,
|
||||
fail_op: wgpu::StencilOperation::Keep,
|
||||
depth_fail_op: wgpu::StencilOperation::Keep,
|
||||
pass_op: wgpu::StencilOperation::DecrementClamp,
|
||||
},
|
||||
wgpu::ColorWrites::empty(),
|
||||
),
|
||||
})
|
||||
ShapePipeline::build(
|
||||
device.create_render_pipeline(&create_pipeline_descriptor(
|
||||
create_debug_label!("{} depthless pipeline", name).as_deref(),
|
||||
shader,
|
||||
shader,
|
||||
&pipeline_layout,
|
||||
None,
|
||||
&[Some(wgpu::ColorTargetState {
|
||||
format,
|
||||
blend: Some(blend),
|
||||
write_mask: wgpu::ColorWrites::ALL,
|
||||
})],
|
||||
vertex_buffers_layout,
|
||||
msaa_sample_count,
|
||||
)),
|
||||
|mask_state| match mask_state {
|
||||
MaskState::NoMask => mask_render_state(
|
||||
"no mask",
|
||||
wgpu::StencilFaceState {
|
||||
compare: wgpu::CompareFunction::Always,
|
||||
fail_op: wgpu::StencilOperation::Keep,
|
||||
depth_fail_op: wgpu::StencilOperation::Keep,
|
||||
pass_op: wgpu::StencilOperation::Keep,
|
||||
},
|
||||
wgpu::ColorWrites::ALL,
|
||||
),
|
||||
MaskState::DrawMaskStencil => mask_render_state(
|
||||
"draw mask stencil",
|
||||
wgpu::StencilFaceState {
|
||||
compare: wgpu::CompareFunction::Equal,
|
||||
fail_op: wgpu::StencilOperation::Keep,
|
||||
depth_fail_op: wgpu::StencilOperation::Keep,
|
||||
pass_op: wgpu::StencilOperation::IncrementClamp,
|
||||
},
|
||||
wgpu::ColorWrites::empty(),
|
||||
),
|
||||
MaskState::DrawMaskedContent => mask_render_state(
|
||||
"draw masked content",
|
||||
wgpu::StencilFaceState {
|
||||
compare: wgpu::CompareFunction::Equal,
|
||||
fail_op: wgpu::StencilOperation::Keep,
|
||||
depth_fail_op: wgpu::StencilOperation::Keep,
|
||||
pass_op: wgpu::StencilOperation::Keep,
|
||||
},
|
||||
wgpu::ColorWrites::ALL,
|
||||
),
|
||||
MaskState::ClearMaskStencil => mask_render_state(
|
||||
"clear mask stencil",
|
||||
wgpu::StencilFaceState {
|
||||
compare: wgpu::CompareFunction::Equal,
|
||||
fail_op: wgpu::StencilOperation::Keep,
|
||||
depth_fail_op: wgpu::StencilOperation::Keep,
|
||||
pass_op: wgpu::StencilOperation::DecrementClamp,
|
||||
},
|
||||
wgpu::ColorWrites::empty(),
|
||||
),
|
||||
},
|
||||
)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue