1144: Fix and simplify attachment dimension mismatch check r=kvark a=DasEtwas

This also improves error messages with detailed dimension and attachment type name info which developers can hopefully recognize.

**Connections**
None

**Description**
Before this commit, depth/stencil attachments are not considered when evaluating the renderpasses' dimension, which will result in a "NoAttachment" error with a confusing display message.

**Testing**
Tested by running an application making use of color-only and depth/stencil-only attachment renderpasses.

Tested by running boids, hello-triangle and shadow examples.


Co-authored-by: DasEtwas <18222134+DasEtwas@users.noreply.github.com>
This commit is contained in:
bors[bot] 2021-01-11 23:05:10 +00:00 committed by GitHub
commit 09ba19b265
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -387,10 +387,18 @@ pub enum RenderPassErrorInner {
Encoder(#[from] CommandEncoderError), Encoder(#[from] CommandEncoderError),
#[error("attachment texture view {0:?} is invalid")] #[error("attachment texture view {0:?} is invalid")]
InvalidAttachment(id::TextureViewId), InvalidAttachment(id::TextureViewId),
#[error("there are attachments")] #[error("necessary attachments are missing")]
NoAttachments, MissingAttachments,
#[error("attachments have different sizes")] #[error("color and/or depth attachments have differing sizes: a {mismatching_attachment_type_name} attachment of size {mismatching_dimensions:?} is not compatible with a {previous_attachment_type_name} attachment's size {previous_dimensions:?}",
MismatchAttachments, )]
AttachmentsDimensionMismatch {
/// depth or color
previous_attachment_type_name: &'static str,
/// depth or color
mismatching_attachment_type_name: &'static str,
previous_dimensions: (u32, u32),
mismatching_dimensions: (u32, u32),
},
#[error("attachment's sample count {0} is invalid")] #[error("attachment's sample count {0} is invalid")]
InvalidSampleCount(u8), InvalidSampleCount(u8),
#[error("attachment with resolve target must be multi-sampled")] #[error("attachment with resolve target must be multi-sampled")]
@ -528,7 +536,9 @@ impl<'a, B: GfxBackend> RenderPassInfo<'a, B> {
let mut attachment_width = None; let mut attachment_width = None;
let mut attachment_height = None; let mut attachment_height = None;
let mut valid_attachment = true; let mut attachment_type_name = "";
let mut mismatching_dimensions = None;
let mut extent = None; let mut extent = None;
let mut sample_count = 0; let mut sample_count = 0;
@ -567,6 +577,25 @@ impl<'a, B: GfxBackend> RenderPassInfo<'a, B> {
.use_extend(&*view_guard, at.attachment, (), ()) .use_extend(&*view_guard, at.attachment, (), ())
.map_err(|_| RenderPassErrorInner::InvalidAttachment(at.attachment))?; .map_err(|_| RenderPassErrorInner::InvalidAttachment(at.attachment))?;
add_view(view)?; add_view(view)?;
// get the width and height set by another attachment, then check if it matches
let (previous_width, previous_height) = (
*attachment_width.get_or_insert(view.extent.width),
*attachment_height.get_or_insert(view.extent.height),
);
if previous_width != view.extent.width || previous_height != view.extent.height
{
mismatching_dimensions = Some((
"depth",
(view.extent.width, view.extent.height),
(previous_width, previous_height),
));
} else {
// this attachment's size was successfully inserted into `attachment_width` and `attachment_height`
attachment_type_name = "depth";
}
depth_stencil_aspects = view.aspects; depth_stencil_aspects = view.aspects;
let source_id = match view.inner { let source_id = match view.inner {
@ -625,9 +654,22 @@ impl<'a, B: GfxBackend> RenderPassInfo<'a, B> {
.map_err(|_| RenderPassErrorInner::InvalidAttachment(at.attachment))?; .map_err(|_| RenderPassErrorInner::InvalidAttachment(at.attachment))?;
add_view(view)?; add_view(view)?;
valid_attachment &= *attachment_width.get_or_insert(view.extent.width) // get the width and height set by another attachment, then check if it matches
== view.extent.width let (previous_width, previous_height) = (
&& *attachment_height.get_or_insert(view.extent.height) == view.extent.height; *attachment_width.get_or_insert(view.extent.width),
*attachment_height.get_or_insert(view.extent.height),
);
if previous_width != view.extent.width || previous_height != view.extent.height {
mismatching_dimensions = Some((
"color",
(view.extent.width, view.extent.height),
(previous_width, previous_height),
));
} else {
// this attachment's size was successfully inserted into `attachment_width` and `attachment_height`
attachment_type_name = "color";
}
let layouts = match view.inner { let layouts = match view.inner {
TextureViewInner::Native { ref source_id, .. } => { TextureViewInner::Native { ref source_id, .. } => {
@ -685,8 +727,20 @@ impl<'a, B: GfxBackend> RenderPassInfo<'a, B> {
colors.push((color_at, hal::image::Layout::ColorAttachmentOptimal)); colors.push((color_at, hal::image::Layout::ColorAttachmentOptimal));
} }
if !valid_attachment { if let Some((
return Err(RenderPassErrorInner::MismatchAttachments); mismatching_attachment_type_name,
previous_dimensions,
mismatching_dimensions,
)) = mismatching_dimensions
{
return Err(RenderPassErrorInner::AttachmentsDimensionMismatch {
// okay to unwrap: for `mismatching_dimensions` to be set, `attachment_{width/height}` must have been
// set, which includes `attachment_type_name` being set in a later `else` block
previous_attachment_type_name: attachment_type_name,
mismatching_attachment_type_name,
previous_dimensions,
mismatching_dimensions,
});
} }
for resolve_target in color_attachments.iter().flat_map(|at| at.resolve_target) { for resolve_target in color_attachments.iter().flat_map(|at| at.resolve_target) {
@ -994,8 +1048,8 @@ impl<'a, B: GfxBackend> RenderPassInfo<'a, B> {
used_swapchain_with_framebuffer, used_swapchain_with_framebuffer,
is_ds_read_only, is_ds_read_only,
extent: wgt::Extent3d { extent: wgt::Extent3d {
width: attachment_width.ok_or(RenderPassErrorInner::NoAttachments)?, width: attachment_width.ok_or(RenderPassErrorInner::MissingAttachments)?,
height: attachment_height.ok_or(RenderPassErrorInner::NoAttachments)?, height: attachment_height.ok_or(RenderPassErrorInner::MissingAttachments)?,
depth: 1, depth: 1,
}, },
}) })