mirror of
https://github.com/gfx-rs/wgpu.git
synced 2024-11-22 23:04:07 +00:00
Improve RenderPass attachment errors
This commit is contained in:
parent
38f1f0ede0
commit
c98f4ed662
@ -18,7 +18,7 @@ use crate::{
|
|||||||
id,
|
id,
|
||||||
init_tracker::{MemoryInitKind, TextureInitRange, TextureInitTrackerAction},
|
init_tracker::{MemoryInitKind, TextureInitRange, TextureInitTrackerAction},
|
||||||
pipeline::{self, PipelineFlags},
|
pipeline::{self, PipelineFlags},
|
||||||
resource::{self, Buffer, Texture, TextureView},
|
resource::{self, Buffer, Texture, TextureView, TextureViewNotRenderableReason},
|
||||||
track::{TextureSelector, UsageConflict, UsageScope},
|
track::{TextureSelector, UsageConflict, UsageScope},
|
||||||
validation::{
|
validation::{
|
||||||
check_buffer_usage, check_texture_usage, MissingBufferUsageError, MissingTextureUsageError,
|
check_buffer_usage, check_texture_usage, MissingBufferUsageError, MissingTextureUsageError,
|
||||||
@ -436,6 +436,34 @@ impl State {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Describes an attachment location in words.
|
||||||
|
///
|
||||||
|
/// Can be used as "the {loc} has..." or "{loc} has..."
|
||||||
|
#[derive(Debug, Copy, Clone)]
|
||||||
|
pub enum AttachmentErrorLocation {
|
||||||
|
Color { index: usize, resolve: bool },
|
||||||
|
Depth,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for AttachmentErrorLocation {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
match *self {
|
||||||
|
AttachmentErrorLocation::Color {
|
||||||
|
index,
|
||||||
|
resolve: false,
|
||||||
|
} => write!(f, "color attachment at index {index}'s texture view"),
|
||||||
|
AttachmentErrorLocation::Color {
|
||||||
|
index,
|
||||||
|
resolve: true,
|
||||||
|
} => write!(
|
||||||
|
f,
|
||||||
|
"color attachment at index {index}'s resolve texture view"
|
||||||
|
),
|
||||||
|
AttachmentErrorLocation::Depth => write!(f, "depth attachment's texture view"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Error)]
|
#[derive(Clone, Debug, Error)]
|
||||||
pub enum ColorAttachmentError {
|
pub enum ColorAttachmentError {
|
||||||
#[error("attachment format {0:?} is not a color format")]
|
#[error("attachment format {0:?} is not a color format")]
|
||||||
@ -453,27 +481,46 @@ 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("attachment format {0:?} is not a depth-stencil format")]
|
#[error("the format of the depth-stencil attachment ({0:?}) is not a depth-stencil format")]
|
||||||
InvalidDepthStencilAttachmentFormat(wgt::TextureFormat),
|
InvalidDepthStencilAttachmentFormat(wgt::TextureFormat),
|
||||||
#[error("attachment format {0:?} can not be resolved")]
|
#[error("the format of the {location} ({format:?}) is not resolvable")]
|
||||||
UnsupportedResolveTargetFormat(wgt::TextureFormat),
|
UnsupportedResolveTargetFormat {
|
||||||
#[error("missing color or depth_stencil attachments, at least one is required.")]
|
location: AttachmentErrorLocation,
|
||||||
MissingAttachments,
|
format: wgt::TextureFormat,
|
||||||
#[error("attachment texture view is not renderable")]
|
},
|
||||||
TextureViewIsNotRenderable,
|
#[error("no color attachments or depth attachments were provided, at least one attachment of any kind must be provided")]
|
||||||
#[error("attachments have differing sizes: {previous:?} is followed by {mismatch:?}")]
|
MissingAttachments,
|
||||||
AttachmentsDimensionMismatch {
|
#[error("the {location} is not renderable:")]
|
||||||
previous: (&'static str, wgt::Extent3d),
|
TextureViewIsNotRenderable {
|
||||||
mismatch: (&'static str, wgt::Extent3d),
|
location: AttachmentErrorLocation,
|
||||||
|
#[source]
|
||||||
|
reason: TextureViewNotRenderableReason,
|
||||||
|
},
|
||||||
|
#[error("attachments have differing sizes: the {expected_location} has extent {expected_extent:?} but is followed by the {actual_location} which has {actual_extent:?}")]
|
||||||
|
AttachmentsDimensionMismatch {
|
||||||
|
expected_location: AttachmentErrorLocation,
|
||||||
|
expected_extent: wgt::Extent3d,
|
||||||
|
actual_location: AttachmentErrorLocation,
|
||||||
|
actual_extent: wgt::Extent3d,
|
||||||
|
},
|
||||||
|
#[error("attachments have differing sample counts: the {expected_location} has count {expected_samples:?} but is followed by the {actual_location} which has count {actual_samples:?}")]
|
||||||
|
AttachmentSampleCountMismatch {
|
||||||
|
expected_location: AttachmentErrorLocation,
|
||||||
|
expected_samples: u32,
|
||||||
|
actual_location: AttachmentErrorLocation,
|
||||||
|
actual_samples: u32,
|
||||||
|
},
|
||||||
|
#[error("the resolve source, {location}, must be multi-sampled (has {src} samples) while the resolve destination must not be multisampled (has {dst} samples)")]
|
||||||
|
InvalidResolveSampleCounts {
|
||||||
|
location: AttachmentErrorLocation,
|
||||||
|
src: u32,
|
||||||
|
dst: u32,
|
||||||
},
|
},
|
||||||
#[error("attachment's sample count {0} is invalid")]
|
|
||||||
InvalidSampleCount(u32),
|
|
||||||
#[error("resolve source must be multi-sampled (has {src} samples) while the resolve destination must not be multisampled (has {dst} samples)")]
|
|
||||||
InvalidResolveSampleCounts { src: u32, dst: u32 },
|
|
||||||
#[error(
|
#[error(
|
||||||
"resource source format ({src:?}) must match the resolve destination format ({dst:?})"
|
"resource source, {location}, format ({src:?}) must match the resolve destination format ({dst:?})"
|
||||||
)]
|
)]
|
||||||
MismatchedResolveTextureFormat {
|
MismatchedResolveTextureFormat {
|
||||||
|
location: AttachmentErrorLocation,
|
||||||
src: wgt::TextureFormat,
|
src: wgt::TextureFormat,
|
||||||
dst: wgt::TextureFormat,
|
dst: wgt::TextureFormat,
|
||||||
},
|
},
|
||||||
@ -485,8 +532,6 @@ pub enum RenderPassErrorInner {
|
|||||||
InvalidDepthOps,
|
InvalidDepthOps,
|
||||||
#[error("unable to clear non-present/read-only stencil")]
|
#[error("unable to clear non-present/read-only stencil")]
|
||||||
InvalidStencilOps,
|
InvalidStencilOps,
|
||||||
#[error("all attachments must have the same sample count, found {actual} != {expected}")]
|
|
||||||
SampleCountMismatch { actual: u32, expected: u32 },
|
|
||||||
#[error("setting `values_offset` to be `None` is only for internal use in render bundles")]
|
#[error("setting `values_offset` to be `None` is only for internal use in render bundles")]
|
||||||
InvalidValuesOffset,
|
InvalidValuesOffset,
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
@ -519,7 +564,7 @@ pub enum RenderPassErrorInner {
|
|||||||
while the pass has flags depth = {pass_depth} and stencil = {pass_stencil}. \
|
while the pass has flags depth = {pass_depth} and stencil = {pass_stencil}. \
|
||||||
Read-only renderpasses are only compatible with read-only bundles for that aspect."
|
Read-only renderpasses are only compatible with read-only bundles for that aspect."
|
||||||
)]
|
)]
|
||||||
IncompatibleBundleRods {
|
IncompatibleBundleReadOnlyDepthStencil {
|
||||||
pass_depth: bool,
|
pass_depth: bool,
|
||||||
pass_stencil: bool,
|
pass_stencil: bool,
|
||||||
bundle_depth: bool,
|
bundle_depth: bool,
|
||||||
@ -686,7 +731,10 @@ impl<'a, A: HalApi> RenderPassInfo<'a, A> {
|
|||||||
let mut pending_discard_init_fixups = SurfacesInDiscardState::new();
|
let mut pending_discard_init_fixups = SurfacesInDiscardState::new();
|
||||||
let mut divergent_discarded_depth_stencil_aspect = None;
|
let mut divergent_discarded_depth_stencil_aspect = None;
|
||||||
|
|
||||||
let mut attachment_type_name = "";
|
let mut attachment_location = AttachmentErrorLocation::Color {
|
||||||
|
index: usize::MAX,
|
||||||
|
resolve: false,
|
||||||
|
};
|
||||||
let mut extent = None;
|
let mut extent = None;
|
||||||
let mut sample_count = 0;
|
let mut sample_count = 0;
|
||||||
|
|
||||||
@ -723,15 +771,17 @@ impl<'a, A: HalApi> RenderPassInfo<'a, A> {
|
|||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
};
|
};
|
||||||
let mut add_view = |view: &TextureView<A>, type_name| {
|
let mut add_view = |view: &TextureView<A>, location| {
|
||||||
let render_extent = view
|
let render_extent = view.render_extent.map_err(|reason| {
|
||||||
.render_extent
|
RenderPassErrorInner::TextureViewIsNotRenderable { location, reason }
|
||||||
.ok_or(RenderPassErrorInner::TextureViewIsNotRenderable)?;
|
})?;
|
||||||
if let Some(ex) = extent {
|
if let Some(ex) = extent {
|
||||||
if ex != render_extent {
|
if ex != render_extent {
|
||||||
return Err(RenderPassErrorInner::AttachmentsDimensionMismatch {
|
return Err(RenderPassErrorInner::AttachmentsDimensionMismatch {
|
||||||
previous: (attachment_type_name, ex),
|
expected_location: attachment_location,
|
||||||
mismatch: (type_name, render_extent),
|
expected_extent: ex,
|
||||||
|
actual_location: location,
|
||||||
|
actual_extent: render_extent,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -740,12 +790,14 @@ impl<'a, A: HalApi> RenderPassInfo<'a, A> {
|
|||||||
if sample_count == 0 {
|
if sample_count == 0 {
|
||||||
sample_count = view.samples;
|
sample_count = view.samples;
|
||||||
} else if sample_count != view.samples {
|
} else if sample_count != view.samples {
|
||||||
return Err(RenderPassErrorInner::SampleCountMismatch {
|
return Err(RenderPassErrorInner::AttachmentSampleCountMismatch {
|
||||||
actual: view.samples,
|
expected_location: attachment_location,
|
||||||
expected: sample_count,
|
expected_samples: sample_count,
|
||||||
|
actual_location: location,
|
||||||
|
actual_samples: view.samples,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
attachment_type_name = type_name;
|
attachment_location = location;
|
||||||
Ok(())
|
Ok(())
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -760,7 +812,7 @@ impl<'a, A: HalApi> RenderPassInfo<'a, A> {
|
|||||||
.add_single(view_guard, at.view)
|
.add_single(view_guard, at.view)
|
||||||
.ok_or(RenderPassErrorInner::InvalidAttachment(at.view))?;
|
.ok_or(RenderPassErrorInner::InvalidAttachment(at.view))?;
|
||||||
check_multiview(view)?;
|
check_multiview(view)?;
|
||||||
add_view(view, "depth")?;
|
add_view(view, AttachmentErrorLocation::Depth)?;
|
||||||
|
|
||||||
let ds_aspects = view.desc.aspects();
|
let ds_aspects = view.desc.aspects();
|
||||||
if ds_aspects.contains(hal::FormatAspects::COLOR) {
|
if ds_aspects.contains(hal::FormatAspects::COLOR) {
|
||||||
@ -879,8 +931,8 @@ impl<'a, A: HalApi> RenderPassInfo<'a, A> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
for at in color_attachments {
|
for (index, attachment) in color_attachments.iter().enumerate() {
|
||||||
let at = if let Some(attachment) = at.as_ref() {
|
let at = if let Some(attachment) = attachment.as_ref() {
|
||||||
attachment
|
attachment
|
||||||
} else {
|
} else {
|
||||||
colors.push(None);
|
colors.push(None);
|
||||||
@ -892,7 +944,13 @@ impl<'a, A: HalApi> RenderPassInfo<'a, A> {
|
|||||||
.add_single(view_guard, at.view)
|
.add_single(view_guard, at.view)
|
||||||
.ok_or(RenderPassErrorInner::InvalidAttachment(at.view))?;
|
.ok_or(RenderPassErrorInner::InvalidAttachment(at.view))?;
|
||||||
check_multiview(color_view)?;
|
check_multiview(color_view)?;
|
||||||
add_view(color_view, "color")?;
|
add_view(
|
||||||
|
color_view,
|
||||||
|
AttachmentErrorLocation::Color {
|
||||||
|
index,
|
||||||
|
resolve: false,
|
||||||
|
},
|
||||||
|
)?;
|
||||||
|
|
||||||
if !color_view
|
if !color_view
|
||||||
.desc
|
.desc
|
||||||
@ -924,23 +982,35 @@ impl<'a, A: HalApi> RenderPassInfo<'a, A> {
|
|||||||
|
|
||||||
check_multiview(resolve_view)?;
|
check_multiview(resolve_view)?;
|
||||||
|
|
||||||
let render_extent = resolve_view
|
let resolve_location = AttachmentErrorLocation::Color {
|
||||||
.render_extent
|
index,
|
||||||
.ok_or(RenderPassErrorInner::TextureViewIsNotRenderable)?;
|
resolve: true,
|
||||||
|
};
|
||||||
|
|
||||||
|
let render_extent = resolve_view.render_extent.map_err(|reason| {
|
||||||
|
RenderPassErrorInner::TextureViewIsNotRenderable {
|
||||||
|
location: resolve_location,
|
||||||
|
reason,
|
||||||
|
}
|
||||||
|
})?;
|
||||||
if color_view.render_extent.unwrap() != render_extent {
|
if color_view.render_extent.unwrap() != render_extent {
|
||||||
return Err(RenderPassErrorInner::AttachmentsDimensionMismatch {
|
return Err(RenderPassErrorInner::AttachmentsDimensionMismatch {
|
||||||
previous: (attachment_type_name, extent.unwrap_or_default()),
|
expected_location: attachment_location,
|
||||||
mismatch: ("resolve", render_extent),
|
expected_extent: extent.unwrap_or_default(),
|
||||||
|
actual_location: resolve_location,
|
||||||
|
actual_extent: render_extent,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if color_view.samples == 1 || resolve_view.samples != 1 {
|
if color_view.samples == 1 || resolve_view.samples != 1 {
|
||||||
return Err(RenderPassErrorInner::InvalidResolveSampleCounts {
|
return Err(RenderPassErrorInner::InvalidResolveSampleCounts {
|
||||||
|
location: resolve_location,
|
||||||
src: color_view.samples,
|
src: color_view.samples,
|
||||||
dst: resolve_view.samples,
|
dst: resolve_view.samples,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if color_view.desc.format != resolve_view.desc.format {
|
if color_view.desc.format != resolve_view.desc.format {
|
||||||
return Err(RenderPassErrorInner::MismatchedResolveTextureFormat {
|
return Err(RenderPassErrorInner::MismatchedResolveTextureFormat {
|
||||||
|
location: resolve_location,
|
||||||
src: color_view.desc.format,
|
src: color_view.desc.format,
|
||||||
dst: resolve_view.desc.format,
|
dst: resolve_view.desc.format,
|
||||||
});
|
});
|
||||||
@ -950,9 +1020,10 @@ impl<'a, A: HalApi> RenderPassInfo<'a, A> {
|
|||||||
.flags
|
.flags
|
||||||
.contains(wgt::TextureFormatFeatureFlags::MULTISAMPLE_RESOLVE)
|
.contains(wgt::TextureFormatFeatureFlags::MULTISAMPLE_RESOLVE)
|
||||||
{
|
{
|
||||||
return Err(RenderPassErrorInner::UnsupportedResolveTargetFormat(
|
return Err(RenderPassErrorInner::UnsupportedResolveTargetFormat {
|
||||||
resolve_view.desc.format,
|
location: resolve_location,
|
||||||
));
|
format: resolve_view.desc.format,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd_buf.texture_memory_actions.register_implicit_init(
|
cmd_buf.texture_memory_actions.register_implicit_init(
|
||||||
@ -1999,12 +2070,14 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
|||||||
if (info.is_depth_read_only && !bundle.is_depth_read_only)
|
if (info.is_depth_read_only && !bundle.is_depth_read_only)
|
||||||
|| (info.is_stencil_read_only && !bundle.is_stencil_read_only)
|
|| (info.is_stencil_read_only && !bundle.is_stencil_read_only)
|
||||||
{
|
{
|
||||||
return Err(RenderPassErrorInner::IncompatibleBundleRods {
|
return Err(
|
||||||
pass_depth: info.is_depth_read_only,
|
RenderPassErrorInner::IncompatibleBundleReadOnlyDepthStencil {
|
||||||
pass_stencil: info.is_stencil_read_only,
|
pass_depth: info.is_depth_read_only,
|
||||||
bundle_depth: bundle.is_depth_read_only,
|
pass_stencil: info.is_stencil_read_only,
|
||||||
bundle_stencil: bundle.is_stencil_read_only,
|
bundle_depth: bundle.is_depth_read_only,
|
||||||
})
|
bundle_stencil: bundle.is_stencil_read_only,
|
||||||
|
},
|
||||||
|
)
|
||||||
.map_pass_err(scope);
|
.map_pass_err(scope);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@ use crate::{
|
|||||||
},
|
},
|
||||||
instance::{self, Adapter, Surface},
|
instance::{self, Adapter, Surface},
|
||||||
pipeline, present,
|
pipeline, present,
|
||||||
resource::{self, BufferAccessResult, BufferMapState},
|
resource::{self, BufferAccessResult, BufferMapState, TextureViewNotRenderableReason},
|
||||||
resource::{BufferAccessError, BufferMapOperation},
|
resource::{BufferAccessError, BufferMapOperation},
|
||||||
track::{BindGroupStates, TextureSelector, Tracker},
|
track::{BindGroupStates, TextureSelector, Tracker},
|
||||||
validation::{self, check_buffer_usage, check_texture_usage},
|
validation::{self, check_buffer_usage, check_texture_usage},
|
||||||
@ -1175,20 +1175,41 @@ impl<A: HalApi> Device<A> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// https://gpuweb.github.io/gpuweb/#abstract-opdef-renderable-texture-view
|
// https://gpuweb.github.io/gpuweb/#abstract-opdef-renderable-texture-view
|
||||||
let is_renderable = texture
|
let render_extent = 'b: loop {
|
||||||
.desc
|
if !texture
|
||||||
.usage
|
|
||||||
.contains(wgt::TextureUsages::RENDER_ATTACHMENT)
|
|
||||||
&& resolved_dimension == TextureViewDimension::D2
|
|
||||||
&& resolved_mip_level_count == 1
|
|
||||||
&& resolved_array_layer_count == 1
|
|
||||||
&& aspects == hal::FormatAspects::from(texture.desc.format);
|
|
||||||
|
|
||||||
let render_extent = is_renderable.then(|| {
|
|
||||||
texture
|
|
||||||
.desc
|
.desc
|
||||||
.compute_render_extent(desc.range.base_mip_level)
|
.usage
|
||||||
});
|
.contains(wgt::TextureUsages::RENDER_ATTACHMENT)
|
||||||
|
{
|
||||||
|
break 'b Err(TextureViewNotRenderableReason::Usage(texture.desc.usage));
|
||||||
|
}
|
||||||
|
|
||||||
|
if resolved_dimension != TextureViewDimension::D2 {
|
||||||
|
break 'b Err(TextureViewNotRenderableReason::Dimension(
|
||||||
|
resolved_dimension,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
if resolved_mip_level_count != 1 {
|
||||||
|
break 'b Err(TextureViewNotRenderableReason::MipLevelCount(
|
||||||
|
resolved_mip_level_count,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
if resolved_array_layer_count != 1 {
|
||||||
|
break 'b Err(TextureViewNotRenderableReason::ArrayLayerCount(
|
||||||
|
resolved_array_layer_count,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
if aspects != hal::FormatAspects::from(texture.desc.format) {
|
||||||
|
break 'b Err(TextureViewNotRenderableReason::Aspects(aspects));
|
||||||
|
}
|
||||||
|
|
||||||
|
break 'b Ok(texture
|
||||||
|
.desc
|
||||||
|
.compute_render_extent(desc.range.base_mip_level));
|
||||||
|
};
|
||||||
|
|
||||||
// filter the usages based on the other criteria
|
// filter the usages based on the other criteria
|
||||||
let usage = {
|
let usage = {
|
||||||
|
@ -576,6 +576,22 @@ impl HalTextureViewDescriptor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Copy, Clone, Error)]
|
||||||
|
pub enum TextureViewNotRenderableReason {
|
||||||
|
#[error("the texture this view references doesn't include the RENDER_ATTACHMENT usage. Provided usages: {0:?}")]
|
||||||
|
Usage(wgt::TextureUsages),
|
||||||
|
#[error("the dimension of this texture view is not 2D. View dimension: {0:?}")]
|
||||||
|
Dimension(wgt::TextureViewDimension),
|
||||||
|
#[error("this texture view has more than one mipmap level. View mipmap levels: {0:?}")]
|
||||||
|
MipLevelCount(u32),
|
||||||
|
#[error("this texture view has more than one array layer. View array layers: {0:?}")]
|
||||||
|
ArrayLayerCount(u32),
|
||||||
|
#[error(
|
||||||
|
"the aspects of this texture view are a subset of the aspects in the original texture. Aspects: {0:?}"
|
||||||
|
)]
|
||||||
|
Aspects(hal::FormatAspects),
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct TextureView<A: hal::Api> {
|
pub struct TextureView<A: hal::Api> {
|
||||||
pub(crate) raw: A::TextureView,
|
pub(crate) raw: A::TextureView,
|
||||||
@ -586,8 +602,8 @@ pub struct TextureView<A: hal::Api> {
|
|||||||
//TODO: store device_id for quick access?
|
//TODO: store device_id for quick access?
|
||||||
pub(crate) desc: HalTextureViewDescriptor,
|
pub(crate) desc: HalTextureViewDescriptor,
|
||||||
pub(crate) format_features: wgt::TextureFormatFeatures,
|
pub(crate) format_features: wgt::TextureFormatFeatures,
|
||||||
/// This is `None` only if the texture view is not renderable
|
/// This is `Err` only if the texture view is not renderable
|
||||||
pub(crate) render_extent: Option<wgt::Extent3d>,
|
pub(crate) render_extent: Result<wgt::Extent3d, TextureViewNotRenderableReason>,
|
||||||
pub(crate) samples: u32,
|
pub(crate) samples: u32,
|
||||||
pub(crate) selector: TextureSelector,
|
pub(crate) selector: TextureSelector,
|
||||||
pub(crate) life_guard: LifeGuard,
|
pub(crate) life_guard: LifeGuard,
|
||||||
|
Loading…
Reference in New Issue
Block a user