Improve RenderPass/RenderBundle compatibility errors

This commit is contained in:
Connor Fitzgerald
2023-03-01 16:14:49 -05:00
parent de695fca0b
commit 38f1f0ede0
3 changed files with 77 additions and 30 deletions

View File

@@ -86,8 +86,8 @@ use crate::{
},
conv,
device::{
AttachmentData, Device, DeviceError, MissingDownlevelFlags, RenderPassContext,
SHADER_STAGE_COUNT,
AttachmentData, Device, DeviceError, MissingDownlevelFlags,
RenderPassCompatibilityCheckType, RenderPassContext, SHADER_STAGE_COUNT,
},
error::{ErrorFormatter, PrettyError},
hub::{GlobalIdentityHandlerFactory, HalApi, Hub, Resource, Storage, Token},
@@ -367,7 +367,7 @@ impl RenderBundleEncoder {
.map_pass_err(scope)?;
self.context
.check_compatible(&pipeline.pass_context)
.check_compatible(&pipeline.pass_context, RenderPassCompatibilityCheckType::RenderPipeline)
.map_err(RenderCommandError::IncompatiblePipelineTargets)
.map_pass_err(scope)?;

View File

@@ -11,7 +11,7 @@ use crate::{
},
device::{
AttachmentData, Device, MissingDownlevelFlags, MissingFeatures,
RenderPassCompatibilityError, RenderPassContext,
RenderPassCompatibilityCheckType, RenderPassCompatibilityError, RenderPassContext,
},
error::{ErrorFormatter, PrettyError},
hub::{Global, GlobalIdentityHandlerFactory, HalApi, Storage, Token},
@@ -1320,7 +1320,10 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
.map_pass_err(scope)?;
info.context
.check_compatible(&pipeline.pass_context)
.check_compatible(
&pipeline.pass_context,
RenderPassCompatibilityCheckType::RenderPipeline,
)
.map_err(RenderCommandError::IncompatiblePipelineTargets)
.map_pass_err(scope)?;
@@ -1986,7 +1989,10 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
.map_pass_err(scope)?;
info.context
.check_compatible(&bundle.context)
.check_compatible(
&bundle.context,
RenderPassCompatibilityCheckType::RenderBundle,
)
.map_err(RenderPassErrorInner::IncompatibleBundleTargets)
.map_pass_err(scope)?;

View File

@@ -70,6 +70,12 @@ impl<T> AttachmentData<T> {
}
}
#[derive(Debug, Copy, Clone)]
pub enum RenderPassCompatibilityCheckType {
RenderPipeline,
RenderBundle,
}
#[derive(Clone, Debug, Hash, PartialEq)]
#[cfg_attr(feature = "serial-pass", derive(serde::Deserialize, serde::Serialize))]
pub(crate) struct RenderPassContext {
@@ -79,16 +85,37 @@ pub(crate) struct RenderPassContext {
}
#[derive(Clone, Debug, Error)]
pub enum RenderPassCompatibilityError {
#[error("Incompatible color attachment: the renderpass expected {0:?} but was given {1:?}")]
IncompatibleColorAttachment(Vec<Option<TextureFormat>>, Vec<Option<TextureFormat>>),
#[error(
"Incompatible depth-stencil attachment: the renderpass expected {0:?} but was given {1:?}"
"Incompatible color attachments at indices {indices:?}: the RenderPass uses textures with formats {expected:?} but the {ty:?} uses attachments with formats {actual:?}",
)]
IncompatibleDepthStencilAttachment(Option<TextureFormat>, Option<TextureFormat>),
#[error("Incompatible sample count: the renderpass expected {0:?} but was given {1:?}")]
IncompatibleSampleCount(u32, u32),
#[error("Incompatible multiview: the renderpass expected {0:?} but was given {1:?}")]
IncompatibleMultiview(Option<NonZeroU32>, Option<NonZeroU32>),
IncompatibleColorAttachment {
indices: Vec<usize>,
expected: Vec<Option<TextureFormat>>,
actual: Vec<Option<TextureFormat>>,
ty: RenderPassCompatibilityCheckType,
},
#[error(
"Incompatible depth-stencil attachment format: the RenderPass uses a texture with format {expected:?} but the {ty:?} uses an attachment with format {actual:?}",
)]
IncompatibleDepthStencilAttachment {
expected: Option<TextureFormat>,
actual: Option<TextureFormat>,
ty: RenderPassCompatibilityCheckType,
},
#[error(
"Incompatible sample count: the RenderPass uses textures with sample count {expected:?} but the {ty:?} uses attachments with format {actual:?}",
)]
IncompatibleSampleCount {
expected: u32,
actual: u32,
ty: RenderPassCompatibilityCheckType,
},
#[error("Incompatible multiview setting: the RenderPass uses setting {expected:?} but the {ty:?} uses setting {actual:?}")]
IncompatibleMultiview {
expected: Option<NonZeroU32>,
actual: Option<NonZeroU32>,
ty: RenderPassCompatibilityCheckType,
},
}
impl RenderPassContext {
@@ -96,32 +123,46 @@ impl RenderPassContext {
pub(crate) fn check_compatible(
&self,
other: &Self,
ty: RenderPassCompatibilityCheckType,
) -> Result<(), RenderPassCompatibilityError> {
if self.attachments.colors != other.attachments.colors {
return Err(RenderPassCompatibilityError::IncompatibleColorAttachment(
self.attachments.colors.iter().cloned().collect(),
other.attachments.colors.iter().cloned().collect(),
));
let indices = self
.attachments
.colors
.iter()
.zip(&other.attachments.colors)
.enumerate()
.filter_map(|(idx, (left, right))| (left != right).then_some(idx))
.collect();
return Err(RenderPassCompatibilityError::IncompatibleColorAttachment {
indices,
expected: self.attachments.colors.iter().cloned().collect(),
actual: other.attachments.colors.iter().cloned().collect(),
ty,
});
}
if self.attachments.depth_stencil != other.attachments.depth_stencil {
return Err(
RenderPassCompatibilityError::IncompatibleDepthStencilAttachment(
self.attachments.depth_stencil,
other.attachments.depth_stencil,
),
RenderPassCompatibilityError::IncompatibleDepthStencilAttachment {
expected: self.attachments.depth_stencil,
actual: other.attachments.depth_stencil,
ty,
},
);
}
if self.sample_count != other.sample_count {
return Err(RenderPassCompatibilityError::IncompatibleSampleCount(
self.sample_count,
other.sample_count,
));
return Err(RenderPassCompatibilityError::IncompatibleSampleCount {
expected: self.sample_count,
actual: other.sample_count,
ty,
});
}
if self.multiview != other.multiview {
return Err(RenderPassCompatibilityError::IncompatibleMultiview(
self.multiview,
other.multiview,
));
return Err(RenderPassCompatibilityError::IncompatibleMultiview {
expected: self.multiview,
actual: other.multiview,
ty,
});
}
Ok(())
}