Refactor the stencil state descriptor a bit

This commit is contained in:
Dzmitry Malyshau 2020-08-12 19:55:59 -04:00
parent d07d8503a0
commit 2473c25971
4 changed files with 62 additions and 34 deletions

View File

@ -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,
});
}

View File

@ -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
},
}
}

View File

@ -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() {

View File

@ -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,
}
}
}