Validate pipeline state formats

This commit is contained in:
Dzmitry Malyshau 2021-06-03 10:30:35 -04:00
parent c7576553ba
commit cfc6792c82
2 changed files with 78 additions and 3 deletions

View File

@ -2255,11 +2255,68 @@ impl<B: GfxBackend> Device<B> {
targets: Vec::with_capacity(color_states.len()),
};
for (i, cs) in color_states.iter().enumerate() {
let bt = conv::map_color_target_state(cs)
.map_err(|error| pipeline::CreateRenderPipelineError::ColorState(i as u8, error))?;
blender.targets.push(bt);
let error = loop {
let format_desc = cs.format.describe();
self.require_features(format_desc.required_features)?;
if !format_desc
.guaranteed_format_features
.allowed_usages
.contains(wgt::TextureUsage::RENDER_ATTACHMENT)
{
break Some(pipeline::ColorStateError::FormatNotRenderable(cs.format));
}
if cs.blend.is_some() && !format_desc.guaranteed_format_features.filterable {
break Some(pipeline::ColorStateError::FormatNotBlendable(cs.format));
}
let hal_format = conv::map_texture_format(cs.format, self.private_features);
if !hal_format
.surface_desc()
.aspects
.contains(hal::format::Aspects::COLOR)
{
break Some(pipeline::ColorStateError::FormatNotColor(cs.format));
}
match conv::map_color_target_state(cs) {
Ok(bt) => blender.targets.push(bt),
Err(e) => break Some(e),
}
break None;
};
if let Some(e) = error {
return Err(pipeline::CreateRenderPipelineError::ColorState(i as u8, e));
}
}
if let Some(ds) = depth_stencil_state {
let error = loop {
let format_desc = ds.format.describe();
self.require_features(format_desc.required_features)?;
if !format_desc
.guaranteed_format_features
.allowed_usages
.contains(wgt::TextureUsage::RENDER_ATTACHMENT)
{
break Some(pipeline::DepthStencilStateError::FormatNotRenderable(
ds.format,
));
}
let hal_format = conv::map_texture_format(ds.format, self.private_features);
let aspects = hal_format.surface_desc().aspects;
if ds.is_depth_enabled() && !aspects.contains(hal::format::Aspects::DEPTH) {
break Some(pipeline::DepthStencilStateError::FormatNotDepth(ds.format));
}
if ds.stencil.is_enabled() && !aspects.contains(hal::format::Aspects::STENCIL) {
break Some(pipeline::DepthStencilStateError::FormatNotStencil(
ds.format,
));
}
break None;
};
if let Some(e) = error {
return Err(pipeline::CreateRenderPipelineError::DepthStencilState(e));
}
}
let depth_stencil = depth_stencil_state
.map(conv::map_depth_stencil_state)
.unwrap_or_default();

View File

@ -202,6 +202,12 @@ pub struct RenderPipelineDescriptor<'a> {
pub enum ColorStateError {
#[error("output is missing")]
Missing,
#[error("format {0:?} is not renderable")]
FormatNotRenderable(wgt::TextureFormat),
#[error("format {0:?} is not blendable")]
FormatNotBlendable(wgt::TextureFormat),
#[error("format {0:?} does not have a color aspect")]
FormatNotColor(wgt::TextureFormat),
#[error("output format {pipeline} is incompatible with the shader {shader}")]
IncompatibleFormat {
pipeline: validation::NumericType,
@ -211,6 +217,16 @@ pub enum ColorStateError {
InvalidMinMaxBlendFactors(wgt::BlendComponent),
}
#[derive(Clone, Debug, Error)]
pub enum DepthStencilStateError {
#[error("format {0:?} is not renderable")]
FormatNotRenderable(wgt::TextureFormat),
#[error("format {0:?} does not have a depth aspect, but depth test/write is enabled")]
FormatNotDepth(wgt::TextureFormat),
#[error("format {0:?} does not have a stencil aspect, but stencil test/write is enabled")]
FormatNotStencil(wgt::TextureFormat),
}
#[derive(Clone, Debug, Error)]
pub enum CreateRenderPipelineError {
#[error(transparent)]
@ -221,6 +237,8 @@ pub enum CreateRenderPipelineError {
Implicit(#[from] ImplicitLayoutError),
#[error("color state [{0}] is invalid")]
ColorState(u8, #[source] ColorStateError),
#[error("depth/stencil state is invalid")]
DepthStencilState(#[from] DepthStencilStateError),
#[error("invalid sample count {0}")]
InvalidSampleCount(u32),
#[error("the number of vertex buffers {given} exceeds the limit {limit}")]