mirror of
https://github.com/gfx-rs/wgpu.git
synced 2024-11-25 16:24:24 +00:00
Refactor the stencil state descriptor a bit
This commit is contained in:
parent
d07d8503a0
commit
2473c25971
@ -94,10 +94,18 @@ pub enum CreateBindGroupError {
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Error)]
|
||||
#[error("too many bindings of type {kind:?} in stage {stage:?}, limit is {count}")]
|
||||
pub enum BindingZone {
|
||||
#[error("stage {0:?}")]
|
||||
Stage(wgt::ShaderStage),
|
||||
#[error("whole pipeline")]
|
||||
Pipeline,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Error)]
|
||||
#[error("too many bindings of type {kind:?} in {zone}, limit is {count}")]
|
||||
pub struct BindingTypeMaxCountError {
|
||||
pub kind: BindingTypeMaxCountErrorKind,
|
||||
pub stage: wgt::ShaderStage,
|
||||
pub zone: BindingZone,
|
||||
pub count: u32,
|
||||
}
|
||||
|
||||
@ -132,7 +140,7 @@ impl PerStageBindingTypeCounter {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn max(&self) -> (wgt::ShaderStage, u32) {
|
||||
pub(crate) fn max(&self) -> (BindingZone, u32) {
|
||||
let max_value = self.vertex.max(self.fragment.max(self.compute));
|
||||
let mut stage = wgt::ShaderStage::NONE;
|
||||
if max_value == self.vertex {
|
||||
@ -144,7 +152,7 @@ impl PerStageBindingTypeCounter {
|
||||
if max_value == self.compute {
|
||||
stage |= wgt::ShaderStage::COMPUTE
|
||||
}
|
||||
(stage, max_value)
|
||||
(BindingZone::Stage(stage), max_value)
|
||||
}
|
||||
|
||||
pub(crate) fn merge(&mut self, other: &Self) {
|
||||
@ -158,9 +166,9 @@ impl PerStageBindingTypeCounter {
|
||||
limit: u32,
|
||||
kind: BindingTypeMaxCountErrorKind,
|
||||
) -> Result<(), BindingTypeMaxCountError> {
|
||||
let (stage, count) = self.max();
|
||||
let (zone, count) = self.max();
|
||||
if limit < count {
|
||||
Err(BindingTypeMaxCountError { kind, stage, count })
|
||||
Err(BindingTypeMaxCountError { kind, zone, count })
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
@ -220,14 +228,14 @@ impl BindingTypeMaxCountValidator {
|
||||
if limits.max_dynamic_uniform_buffers_per_pipeline_layout < self.dynamic_uniform_buffers {
|
||||
return Err(BindingTypeMaxCountError {
|
||||
kind: BindingTypeMaxCountErrorKind::DynamicUniformBuffers,
|
||||
stage: wgt::ShaderStage::NONE,
|
||||
zone: BindingZone::Pipeline,
|
||||
count: self.dynamic_uniform_buffers,
|
||||
});
|
||||
}
|
||||
if limits.max_dynamic_storage_buffers_per_pipeline_layout < self.dynamic_storage_buffers {
|
||||
return Err(BindingTypeMaxCountError {
|
||||
kind: BindingTypeMaxCountErrorKind::DynamicStorageBuffers,
|
||||
stage: wgt::ShaderStage::NONE,
|
||||
zone: BindingZone::Pipeline,
|
||||
count: self.dynamic_storage_buffers,
|
||||
});
|
||||
}
|
||||
|
@ -242,7 +242,7 @@ pub fn map_depth_stencil_state_descriptor(
|
||||
desc: &wgt::DepthStencilStateDescriptor,
|
||||
) -> hal::pso::DepthStencilDesc {
|
||||
hal::pso::DepthStencilDesc {
|
||||
depth: if desc.depth_write_enabled || desc.depth_compare != wgt::CompareFunction::Always {
|
||||
depth: if desc.is_depth_enabled() {
|
||||
Some(hal::pso::DepthTest {
|
||||
fun: map_compare_function(desc.depth_compare),
|
||||
write: desc.depth_write_enabled,
|
||||
@ -251,19 +251,24 @@ pub fn map_depth_stencil_state_descriptor(
|
||||
None
|
||||
},
|
||||
depth_bounds: false, // TODO
|
||||
stencil: desc.stencil.as_ref().map(|stencil| hal::pso::StencilTest {
|
||||
faces: hal::pso::Sided {
|
||||
front: map_stencil_face(&stencil.front),
|
||||
back: map_stencil_face(&stencil.back),
|
||||
},
|
||||
read_masks: hal::pso::State::Static(hal::pso::Sided::new(stencil.read_mask)),
|
||||
write_masks: hal::pso::State::Static(hal::pso::Sided::new(stencil.write_mask)),
|
||||
reference_values: if stencil.needs_ref_value() {
|
||||
hal::pso::State::Dynamic
|
||||
} else {
|
||||
hal::pso::State::Static(hal::pso::Sided::new(0))
|
||||
},
|
||||
}),
|
||||
stencil: if desc.stencil.is_enabled() {
|
||||
let s = &desc.stencil;
|
||||
Some(hal::pso::StencilTest {
|
||||
faces: hal::pso::Sided {
|
||||
front: map_stencil_face(&s.front),
|
||||
back: map_stencil_face(&s.back),
|
||||
},
|
||||
read_masks: hal::pso::State::Static(hal::pso::Sided::new(s.read_mask)),
|
||||
write_masks: hal::pso::State::Static(hal::pso::Sided::new(s.write_mask)),
|
||||
reference_values: if s.needs_ref_value() {
|
||||
hal::pso::State::Dynamic
|
||||
} else {
|
||||
hal::pso::State::Static(hal::pso::Sided::new(0))
|
||||
},
|
||||
})
|
||||
} else {
|
||||
None
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2914,7 +2914,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||
}
|
||||
}
|
||||
if let Some(ds) = depth_stencil_state.as_ref() {
|
||||
if ds.stencil.as_ref().map_or(false, |s| s.needs_ref_value()) {
|
||||
if ds.stencil.needs_ref_value() {
|
||||
flags |= pipeline::PipelineFlags::STENCIL_REFERENCE;
|
||||
}
|
||||
if !ds.is_read_only() {
|
||||
|
@ -505,6 +505,17 @@ pub struct ColorStateDescriptor {
|
||||
pub write_mask: ColorWrite,
|
||||
}
|
||||
|
||||
impl From<TextureFormat> for ColorStateDescriptor {
|
||||
fn from(format: TextureFormat) -> Self {
|
||||
ColorStateDescriptor {
|
||||
format,
|
||||
alpha_blend: BlendDescriptor::REPLACE,
|
||||
color_blend: BlendDescriptor::REPLACE,
|
||||
write_mask: ColorWrite::ALL,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Primitive type the input mesh is composed of.
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
|
||||
@ -830,12 +841,17 @@ pub struct StencilStateDescriptor {
|
||||
}
|
||||
|
||||
impl StencilStateDescriptor {
|
||||
pub fn needs_ref_value(&self) -> bool {
|
||||
!self.front.compare.is_trivial() || !self.back.compare.is_trivial()
|
||||
pub fn is_enabled(&self) -> bool {
|
||||
(self.front != StencilStateFaceDescriptor::IGNORE
|
||||
|| self.back != StencilStateFaceDescriptor::IGNORE)
|
||||
&& self.read_mask != 0
|
||||
}
|
||||
pub fn is_read_only(&self) -> bool {
|
||||
self.write_mask == 0
|
||||
}
|
||||
pub fn needs_ref_value(&self) -> bool {
|
||||
self.front.compare.needs_ref_value() || self.back.compare.needs_ref_value()
|
||||
}
|
||||
}
|
||||
|
||||
/// Describes the depth/stencil state in a render pipeline.
|
||||
@ -851,16 +867,15 @@ pub struct DepthStencilStateDescriptor {
|
||||
pub depth_write_enabled: bool,
|
||||
/// Comparison function used to compare depth values in the depth test.
|
||||
pub depth_compare: CompareFunction,
|
||||
pub stencil: Option<StencilStateDescriptor>,
|
||||
pub stencil: StencilStateDescriptor,
|
||||
}
|
||||
|
||||
impl DepthStencilStateDescriptor {
|
||||
pub fn is_depth_enabled(&self) -> bool {
|
||||
self.depth_compare != CompareFunction::Always || self.depth_write_enabled
|
||||
}
|
||||
pub fn is_read_only(&self) -> bool {
|
||||
!self.depth_write_enabled
|
||||
&& self
|
||||
.stencil
|
||||
.as_ref()
|
||||
.map_or(true, StencilStateDescriptor::is_read_only)
|
||||
!self.depth_write_enabled && self.stencil.is_read_only()
|
||||
}
|
||||
}
|
||||
|
||||
@ -970,10 +985,10 @@ pub enum CompareFunction {
|
||||
}
|
||||
|
||||
impl CompareFunction {
|
||||
pub fn is_trivial(self) -> bool {
|
||||
pub fn needs_ref_value(self) -> bool {
|
||||
match self {
|
||||
CompareFunction::Never | CompareFunction::Always => true,
|
||||
_ => false,
|
||||
CompareFunction::Never | CompareFunction::Always => false,
|
||||
_ => true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user