Texture format MSAA capabilities

This commit is contained in:
Dzmitry Malyshau 2022-01-10 20:46:08 -05:00
parent 01f62baad2
commit dbec075cdc
16 changed files with 462 additions and 189 deletions

3
Cargo.lock generated
View File

@ -995,8 +995,7 @@ dependencies = [
[[package]]
name = "metal"
version = "0.23.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e0514f491f4cc03632ab399ee01e2c1c1b12d3e1cf2d667c1ff5f87d6dcd2084"
source = "git+https://github.com/gfx-rs/metal-rs?rev=140c8f4#140c8f4e39001ae154f153ffc767da6c0c9d7f06"
dependencies = [
"bitflags",
"block",

View File

@ -94,6 +94,8 @@ impl RenderBundleEncoder {
parent_id: id::DeviceId,
base: Option<BasePass<RenderCommand>>,
) -> Result<Self, CreateRenderBundleError> {
//TODO: validate that attachment formats are renderable,
// have expected aspects, support multisampling.
Ok(Self {
base: base.unwrap_or_else(|| BasePass::new(&desc.label)),
parent_id,

View File

@ -409,6 +409,8 @@ pub enum RenderPassErrorInner {
InvalidColorAttachmentFormat(wgt::TextureFormat),
#[error("attachment format {0:?} is not a depth-stencil format")]
InvalidDepthStencilAttachmentFormat(wgt::TextureFormat),
#[error("attachment format {0:?} can not be resolved")]
UnsupportedResolveTargetFormat(wgt::TextureFormat),
#[error("necessary attachments are missing")]
MissingAttachments,
#[error("attachments have differing sizes: {previous:?} is followed by {mismatch:?}")]
@ -418,10 +420,15 @@ pub enum RenderPassErrorInner {
},
#[error("attachment's sample count {0} is invalid")]
InvalidSampleCount(u32),
#[error("attachment with resolve target must be multi-sampled")]
InvalidResolveSourceSampleCount,
#[error("resolve target must have a sample count of 1")]
InvalidResolveTargetSampleCount,
#[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(
"resource source format ({src:?}) must match the resolve destination format ({dst:?})"
)]
MismatchedResolveTextureFormat {
src: wgt::TextureFormat,
dst: wgt::TextureFormat,
},
#[error("surface texture is dropped before the render pass is finished")]
SurfaceTextureDropped,
#[error("not enough memory left")]
@ -438,7 +445,8 @@ pub enum RenderPassErrorInner {
MissingFeatures(#[from] MissingFeatures),
#[error(transparent)]
MissingDownlevelFlags(#[from] MissingDownlevelFlags),
#[error("indirect draw uses bytes {offset}..{end_offset} {} which overruns indirect buffer of size {buffer_size}", count.map_or_else(String::new, |v| format!("(using count {})", v)))]
#[error("indirect draw uses bytes {offset}..{end_offset} {} which overruns indirect buffer of size {buffer_size}",
count.map_or_else(String::new, |v| format!("(using count {})", v)))]
IndirectBufferOverrun {
count: Option<NonZeroU32>,
offset: u64,
@ -823,6 +831,7 @@ impl<'a, A: HalApi> RenderPassInfo<'a, A> {
.views
.use_extend(&*view_guard, resolve_target, (), ())
.map_err(|_| RenderPassErrorInner::InvalidAttachment(resolve_target))?;
check_multiview(resolve_view)?;
if color_view.extent != resolve_view.extent {
return Err(RenderPassErrorInner::AttachmentsDimensionMismatch {
@ -830,11 +839,26 @@ impl<'a, A: HalApi> RenderPassInfo<'a, A> {
mismatch: ("resolve", resolve_view.extent),
});
}
if color_view.samples == 1 {
return Err(RenderPassErrorInner::InvalidResolveSourceSampleCount);
if color_view.samples == 1 || resolve_view.samples != 1 {
return Err(RenderPassErrorInner::InvalidResolveSampleCounts {
src: color_view.samples,
dst: resolve_view.samples,
});
}
if resolve_view.samples != 1 {
return Err(RenderPassErrorInner::InvalidResolveTargetSampleCount);
if color_view.desc.format != resolve_view.desc.format {
return Err(RenderPassErrorInner::MismatchedResolveTextureFormat {
src: color_view.desc.format,
dst: resolve_view.desc.format,
});
}
if !resolve_view
.format_features
.flags
.contains(wgt::TextureFormatFeatureFlags::MULTISAMPLE_RESOLVE)
{
return Err(RenderPassErrorInner::UnsupportedResolveTargetFormat(
resolve_view.desc.format,
));
}
cmd_buf.texture_memory_actions.register_implicit_init(

View File

@ -1890,19 +1890,19 @@ impl<A: HalApi> Device<A> {
view_samples: view.samples,
});
}
match (sample_type, format_info.sample_type, view.format_features.filterable) {
(Tst::Uint, Tst::Uint, ..) |
(Tst::Sint, Tst::Sint, ..) |
(Tst::Depth, Tst::Depth, ..) |
match (sample_type, format_info.sample_type) {
(Tst::Uint, Tst::Uint) |
(Tst::Sint, Tst::Sint) |
(Tst::Depth, Tst::Depth) |
// if we expect non-filterable, accept anything float
(Tst::Float { filterable: false }, Tst::Float { .. }, ..) |
(Tst::Float { filterable: false }, Tst::Float { .. }) |
// if we expect filterable, require it
(Tst::Float { filterable: true }, Tst::Float { filterable: true }, ..) |
// if we expect filterable, also accept Float that is defined as unfilterable if filterable feature is explicitly enabled
// (only hit if wgt::Features::TEXTURE_ADAPTER_SPECIFIC_FORMAT_FEATURES is enabled)
(Tst::Float { filterable: true }, Tst::Float { .. }, true) |
(Tst::Float { filterable: true }, Tst::Float { filterable: true }) |
// if we expect float, also accept depth
(Tst::Float { .. }, Tst::Depth, ..) => {}
// if we expect filterable, also accept Float that is defined as unfilterable if filterable feature is explicitly enabled
// (only hit if wgt::Features::TEXTURE_ADAPTER_SPECIFIC_FORMAT_FEATURES is enabled)
(Tst::Float { filterable: true }, Tst::Float { .. }) if view.format_features.flags.contains(wgt::TextureFormatFeatureFlags::FILTERABLE) => {}
_ => {
return Err(Error::InvalidTextureSampleType {
binding,
@ -2268,6 +2268,8 @@ impl<A: HalApi> Device<A> {
hub: &Hub<A, G>,
token: &mut Token<Self>,
) -> Result<pipeline::RenderPipeline<A>, pipeline::CreateRenderPipelineError> {
use wgt::TextureFormatFeatureFlags as Tfff;
//TODO: only lock mutable if the layout is derived
let (mut pipeline_layout_guard, mut token) = hub.pipeline_layouts.write(token);
let (mut bgl_guard, mut token) = hub.bind_group_layouts.write(&mut token);
@ -2413,12 +2415,16 @@ impl<A: HalApi> Device<A> {
{
break Some(pipeline::ColorStateError::FormatNotRenderable(cs.format));
}
if cs.blend.is_some() && !format_features.filterable {
if cs.blend.is_some() && !format_features.flags.contains(Tfff::FILTERABLE) {
break Some(pipeline::ColorStateError::FormatNotBlendable(cs.format));
}
if !hal::FormatAspects::from(cs.format).contains(hal::FormatAspects::COLOR) {
break Some(pipeline::ColorStateError::FormatNotColor(cs.format));
}
if desc.multisample.count > 1 && !format_features.flags.contains(Tfff::MULTISAMPLE)
{
break Some(pipeline::ColorStateError::FormatNotMultisampled(cs.format));
}
break None;
};
@ -2429,8 +2435,8 @@ impl<A: HalApi> Device<A> {
if let Some(ds) = depth_stencil_state {
let error = loop {
if !self
.describe_format_features(adapter, ds.format)?
let format_features = self.describe_format_features(adapter, ds.format)?;
if !format_features
.allowed_usages
.contains(wgt::TextureUsages::RENDER_ATTACHMENT)
{
@ -2438,6 +2444,7 @@ impl<A: HalApi> Device<A> {
ds.format,
));
}
let aspect = hal::FormatAspects::from(ds.format);
if ds.is_depth_enabled() && !aspect.contains(hal::FormatAspects::DEPTH) {
break Some(pipeline::DepthStencilStateError::FormatNotDepth(ds.format));
@ -2447,6 +2454,13 @@ impl<A: HalApi> Device<A> {
ds.format,
));
}
if desc.multisample.count > 1 && !format_features.flags.contains(Tfff::MULTISAMPLE)
{
break Some(pipeline::DepthStencilStateError::FormatNotMultisampled(
ds.format,
));
}
break None;
};
if let Some(e) = error {

View File

@ -270,14 +270,25 @@ impl<A: HalApi> Adapter<A> {
// We are currently taking the filtering and blending together,
// but we may reconsider this in the future if there are formats
// in the wild for which these two capabilities do not match.
let filterable = caps.contains(Tfc::SAMPLED_LINEAR)
&& (!caps.contains(Tfc::COLOR_ATTACHMENT)
|| caps.contains(Tfc::COLOR_ATTACHMENT_BLEND));
flags.set(
wgt::TextureFormatFeatureFlags::FILTERABLE,
caps.contains(Tfc::SAMPLED_LINEAR)
&& (!caps.contains(Tfc::COLOR_ATTACHMENT)
|| caps.contains(Tfc::COLOR_ATTACHMENT_BLEND)),
);
flags.set(
wgt::TextureFormatFeatureFlags::MULTISAMPLE,
caps.contains(Tfc::MULTISAMPLE),
);
flags.set(
wgt::TextureFormatFeatureFlags::MULTISAMPLE_RESOLVE,
caps.contains(Tfc::MULTISAMPLE_RESOLVE),
);
wgt::TextureFormatFeatures {
allowed_usages,
flags,
filterable,
}
}

View File

@ -270,6 +270,8 @@ pub enum ColorStateError {
FormatNotBlendable(wgt::TextureFormat),
#[error("format {0:?} does not have a color aspect")]
FormatNotColor(wgt::TextureFormat),
#[error("format {0:?} can't be multisampled")]
FormatNotMultisampled(wgt::TextureFormat),
#[error("output format {pipeline} is incompatible with the shader {shader}")]
IncompatibleFormat {
pipeline: validation::NumericType,
@ -287,6 +289,8 @@ pub enum DepthStencilStateError {
FormatNotDepth(wgt::TextureFormat),
#[error("format {0:?} does not have a stencil aspect, but stencil test/write is enabled")]
FormatNotStencil(wgt::TextureFormat),
#[error("format {0:?} can't be multisampled")]
FormatNotMultisampled(wgt::TextureFormat),
}
#[derive(Clone, Debug, Error)]

View File

@ -170,8 +170,8 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
hal_usage: conv::map_texture_usage(config.usage, config.format.into()),
format_features: wgt::TextureFormatFeatures {
allowed_usages: wgt::TextureUsages::RENDER_ATTACHMENT,
flags: wgt::TextureFormatFeatureFlags::empty(),
filterable: false,
flags: wgt::TextureFormatFeatureFlags::MULTISAMPLE
| wgt::TextureFormatFeatureFlags::MULTISAMPLE_RESOLVE,
},
initialization_status: TextureInitTracker::new(1, 1),
full_range: TextureSelector {

View File

@ -71,7 +71,7 @@ winapi = { version = "0.3", features = ["libloaderapi", "windef", "winuser"] }
native = { package = "d3d12", version = "0.4.1", features = ["libloading"], optional = true }
[target.'cfg(any(target_os="macos", target_os="ios"))'.dependencies]
mtl = { package = "metal", version = "0.23.1" }
mtl = { package = "metal", git = "https://github.com/gfx-rs/metal-rs", rev = "140c8f4" }
objc = "0.2.5"
core-graphics-types = "0.1"

View File

@ -332,13 +332,16 @@ impl crate::Adapter<super::Api> for super::Adapter {
);
let mut caps = Tfc::COPY_SRC | Tfc::COPY_DST;
let can_image = 0
!= data.Support1
& (d3d12::D3D12_FORMAT_SUPPORT1_TEXTURE1D
| d3d12::D3D12_FORMAT_SUPPORT1_TEXTURE2D
| d3d12::D3D12_FORMAT_SUPPORT1_TEXTURE3D
| d3d12::D3D12_FORMAT_SUPPORT1_TEXTURECUBE);
caps.set(Tfc::SAMPLED, can_image);
let is_texture = data.Support1
& (d3d12::D3D12_FORMAT_SUPPORT1_TEXTURE1D
| d3d12::D3D12_FORMAT_SUPPORT1_TEXTURE2D
| d3d12::D3D12_FORMAT_SUPPORT1_TEXTURE3D
| d3d12::D3D12_FORMAT_SUPPORT1_TEXTURECUBE)
!= 0;
caps.set(
Tfc::SAMPLED,
is_texture && data.Support1 & d3d12::D3D12_FORMAT_SUPPORT1_SHADER_LOAD != 0,
);
caps.set(
Tfc::SAMPLED_LINEAR,
data.Support1 & d3d12::D3D12_FORMAT_SUPPORT1_SHADER_SAMPLE != 0,
@ -364,6 +367,19 @@ impl crate::Adapter<super::Api> for super::Adapter {
data.Support2 & d3d12::D3D12_FORMAT_SUPPORT2_UAV_TYPED_LOAD != 0,
);
let no_msaa_load = caps.contains(Tfc::SAMPLED)
&& data.Support1 & d3d12::D3D12_FORMAT_SUPPORT1_MULTISAMPLE_LOAD == 0;
let no_msaa_target = data.Support1
& (d3d12::D3D12_FORMAT_SUPPORT1_RENDER_TARGET
| d3d12::D3D12_FORMAT_SUPPORT1_DEPTH_STENCIL)
!= 0
&& data.Support1 & d3d12::D3D12_FORMAT_SUPPORT1_MULTISAMPLE_RENDERTARGET == 0;
caps.set(Tfc::MULTISAMPLE, !no_msaa_load && !no_msaa_target);
caps.set(
Tfc::MULTISAMPLE_RESOLVE,
data.Support1 & d3d12::D3D12_FORMAT_SUPPORT1_MULTISAMPLE_RESOLVE != 0,
);
caps
}

View File

@ -576,9 +576,11 @@ impl crate::Adapter<super::Api> for super::Adapter {
) -> crate::TextureFormatCapabilities {
use crate::TextureFormatCapabilities as Tfc;
use wgt::TextureFormat as Tf;
// The storage types are sprinkled based on section
// "TEXTURE IMAGE LOADS AND STORES" of GLES-3.2 spec.
let unfiltered_color = Tfc::SAMPLED | Tfc::COLOR_ATTACHMENT;
let unfiltered_color =
Tfc::SAMPLED | Tfc::COLOR_ATTACHMENT | Tfc::MULTISAMPLE | Tfc::MULTISAMPLE_RESOLVE;
let filtered_color = unfiltered_color | Tfc::SAMPLED_LINEAR | Tfc::COLOR_ATTACHMENT_BLEND;
match format {
Tf::R8Unorm | Tf::R8Snorm => filtered_color,

View File

@ -373,7 +373,7 @@ impl super::Queue {
gl.pixel_store_i32(glow::UNPACK_ROW_LENGTH, row_texels as i32);
gl.pixel_store_i32(glow::UNPACK_IMAGE_HEIGHT, column_texels as i32);
let mut unbind_unpack_buffer = false;
if format_info.block_dimensions == (1, 1) {
if !format_info.is_compressed() {
let buffer_data;
let unpack_data = match src.raw {
Some(buffer) => {
@ -540,7 +540,7 @@ impl super::Queue {
ref copy,
} => {
let format_info = src_format.describe();
if format_info.block_dimensions != (1, 1) {
if format_info.is_compressed() {
log::error!("Not implemented yet: compressed texture copy to buffer");
return;
}

View File

@ -562,10 +562,15 @@ bitflags!(
/// Format can be used as depth-stencil and input attachment.
const DEPTH_STENCIL_ATTACHMENT = 1 << 8;
/// Format can be multisampled.
const MULTISAMPLE = 1 << 9;
/// Format can be used for render pass resolve targets.
const MULTISAMPLE_RESOLVE = 1 << 10;
/// Format can be copied from.
const COPY_SRC = 1 << 9;
const COPY_SRC = 1 << 11;
/// Format can be copied to.
const COPY_DST = 1 << 10;
const COPY_DST = 1 << 12;
}
);

View File

@ -55,6 +55,26 @@ impl crate::Adapter<super::Api> for super::Adapter {
(Tfc::STORAGE_READ_WRITE, Tfc::STORAGE_READ_WRITE)
}
};
let msaa_desktop_if = if pc.msaa_desktop {
Tfc::MULTISAMPLE
} else {
Tfc::empty()
};
let msaa_apple7x_if = if pc.msaa_desktop | pc.msaa_apple7 {
Tfc::MULTISAMPLE
} else {
Tfc::empty()
};
let msaa_resolve_desktop_if = if pc.msaa_desktop {
Tfc::MULTISAMPLE_RESOLVE
} else {
Tfc::empty()
};
let msaa_resolve_apple3x_if = if pc.msaa_desktop | pc.msaa_apple3 {
Tfc::MULTISAMPLE_RESOLVE
} else {
Tfc::empty()
};
let extra = match format {
Tf::R8Unorm => {
@ -63,59 +83,77 @@ impl crate::Adapter<super::Api> for super::Adapter {
| Tfc::STORAGE
| Tfc::COLOR_ATTACHMENT
| Tfc::COLOR_ATTACHMENT_BLEND
| Tfc::MULTISAMPLE
| Tfc::MULTISAMPLE_RESOLVE
}
Tf::R8Snorm => {
Tfc::SAMPLED_LINEAR
| Tfc::STORAGE
| Tfc::COLOR_ATTACHMENT
| Tfc::COLOR_ATTACHMENT_BLEND
| Tfc::MULTISAMPLE
| Tfc::MULTISAMPLE_RESOLVE
}
Tf::R8Uint | Tf::R8Sint | Tf::R16Uint | Tf::R16Sint => {
read_write_tier2_if | Tfc::STORAGE | Tfc::COLOR_ATTACHMENT
read_write_tier2_if | Tfc::STORAGE | Tfc::COLOR_ATTACHMENT | Tfc::MULTISAMPLE
}
Tf::R16Float => {
read_write_tier2_if
| Tfc::STORAGE
| Tfc::COLOR_ATTACHMENT
| Tfc::COLOR_ATTACHMENT_BLEND
| Tfc::MULTISAMPLE
| Tfc::MULTISAMPLE_RESOLVE
}
Tf::R16Unorm | Tf::R16Snorm => {
Tfc::SAMPLED_LINEAR
| Tfc::STORAGE
| Tfc::COLOR_ATTACHMENT
| Tfc::COLOR_ATTACHMENT_BLEND
| Tfc::MULTISAMPLE
| msaa_resolve_desktop_if
}
Tf::Rg8Unorm | Tf::Rg8Snorm => {
Tfc::SAMPLED_LINEAR
| Tfc::STORAGE
| Tfc::COLOR_ATTACHMENT
| Tfc::COLOR_ATTACHMENT_BLEND
| Tfc::MULTISAMPLE
| Tfc::MULTISAMPLE_RESOLVE
}
Tf::Rg8Uint | Tf::Rg8Sint => Tfc::COLOR_ATTACHMENT,
Tf::Rg8Uint | Tf::Rg8Sint => Tfc::COLOR_ATTACHMENT | Tfc::MULTISAMPLE,
Tf::R32Uint | Tf::R32Sint => {
if pc.format_r32_all {
read_write_tier1_if | Tfc::STORAGE | Tfc::COLOR_ATTACHMENT
let storage = if pc.format_r32_all {
read_write_tier1_if | Tfc::STORAGE
} else {
Tfc::COLOR_ATTACHMENT
}
Tfc::empty()
};
Tfc::COLOR_ATTACHMENT | storage | msaa_desktop_if
}
Tf::R32Float => {
let mut flags = Tfc::COLOR_ATTACHMENT | Tfc::COLOR_ATTACHMENT_BLEND;
if pc.format_r32float_all {
flags |= read_write_tier1_if | Tfc::STORAGE | Tfc::SAMPLED_LINEAR;
let flags = Tfc::COLOR_ATTACHMENT
| Tfc::COLOR_ATTACHMENT_BLEND
| Tfc::MULTISAMPLE
| msaa_resolve_desktop_if;
let extra = if pc.format_r32float_all {
read_write_tier1_if | Tfc::STORAGE | Tfc::SAMPLED_LINEAR
} else if pc.format_r32float_no_filter {
flags |= Tfc::SAMPLED_LINEAR;
}
flags
Tfc::SAMPLED_LINEAR
} else {
Tfc::empty()
};
flags | extra
}
Tf::Rg16Uint | Tf::Rg16Sint => {
read_write_tier2_if | Tfc::STORAGE | Tfc::COLOR_ATTACHMENT
read_write_tier2_if | Tfc::STORAGE | Tfc::COLOR_ATTACHMENT | Tfc::MULTISAMPLE
}
Tf::Rg16Unorm | Tf::Rg16Snorm => {
Tfc::SAMPLED_LINEAR
| Tfc::STORAGE
| Tfc::COLOR_ATTACHMENT
| Tfc::COLOR_ATTACHMENT_BLEND
| Tfc::MULTISAMPLE
| msaa_resolve_desktop_if
}
Tf::Rg16Float => {
read_write_tier2_if
@ -123,6 +161,8 @@ impl crate::Adapter<super::Api> for super::Adapter {
| Tfc::STORAGE
| Tfc::COLOR_ATTACHMENT
| Tfc::COLOR_ATTACHMENT_BLEND
| Tfc::MULTISAMPLE
| Tfc::MULTISAMPLE_RESOLVE
}
Tf::Rgba8Unorm => {
read_write_tier2_if
@ -130,10 +170,15 @@ impl crate::Adapter<super::Api> for super::Adapter {
| Tfc::STORAGE
| Tfc::COLOR_ATTACHMENT
| Tfc::COLOR_ATTACHMENT_BLEND
| Tfc::MULTISAMPLE
| Tfc::MULTISAMPLE_RESOLVE
}
Tf::Rgba8UnormSrgb | Tf::Bgra8UnormSrgb => {
let mut flags =
Tfc::SAMPLED_LINEAR | Tfc::COLOR_ATTACHMENT | Tfc::COLOR_ATTACHMENT_BLEND;
let mut flags = Tfc::SAMPLED_LINEAR
| Tfc::COLOR_ATTACHMENT
| Tfc::COLOR_ATTACHMENT_BLEND
| Tfc::MULTISAMPLE
| Tfc::MULTISAMPLE_RESOLVE;
flags.set(Tfc::STORAGE, pc.format_rgba8_srgb_all);
flags
}
@ -142,25 +187,34 @@ impl crate::Adapter<super::Api> for super::Adapter {
| Tfc::STORAGE
| Tfc::COLOR_ATTACHMENT
| Tfc::COLOR_ATTACHMENT_BLEND
| Tfc::MULTISAMPLE
| Tfc::MULTISAMPLE_RESOLVE
}
Tf::Rgba8Uint | Tf::Rgba8Sint => {
read_write_tier2_if | Tfc::STORAGE | Tfc::COLOR_ATTACHMENT
read_write_tier2_if | Tfc::STORAGE | Tfc::COLOR_ATTACHMENT | Tfc::MULTISAMPLE
}
Tf::Rgb10a2Unorm => {
let mut flags =
Tfc::SAMPLED_LINEAR | Tfc::COLOR_ATTACHMENT | Tfc::COLOR_ATTACHMENT_BLEND;
let mut flags = Tfc::SAMPLED_LINEAR
| Tfc::COLOR_ATTACHMENT
| Tfc::COLOR_ATTACHMENT_BLEND
| Tfc::MULTISAMPLE
| Tfc::MULTISAMPLE_RESOLVE;
flags.set(Tfc::STORAGE, pc.format_rgb10a2_unorm_all);
flags
}
Tf::Rg11b10Float => {
let mut flags =
Tfc::SAMPLED_LINEAR | Tfc::COLOR_ATTACHMENT | Tfc::COLOR_ATTACHMENT_BLEND;
let mut flags = Tfc::SAMPLED_LINEAR
| Tfc::COLOR_ATTACHMENT
| Tfc::COLOR_ATTACHMENT_BLEND
| Tfc::MULTISAMPLE
| Tfc::MULTISAMPLE_RESOLVE;
flags.set(Tfc::STORAGE, pc.format_rg11b10_all);
flags
}
Tf::Rg32Uint | Tf::Rg32Sint => Tfc::COLOR_ATTACHMENT | Tfc::STORAGE,
Tf::Rg32Uint | Tf::Rg32Sint => Tfc::COLOR_ATTACHMENT | Tfc::STORAGE | msaa_apple7x_if,
Tf::Rg32Float => {
let mut flags = Tfc::COLOR_ATTACHMENT | Tfc::COLOR_ATTACHMENT_BLEND;
let mut flags =
Tfc::COLOR_ATTACHMENT | Tfc::COLOR_ATTACHMENT_BLEND | msaa_apple7x_if;
if pc.format_rg32float_all {
flags |= Tfc::STORAGE | Tfc::SAMPLED_LINEAR;
} else if pc.format_rg32float_color_blend {
@ -169,13 +223,15 @@ impl crate::Adapter<super::Api> for super::Adapter {
flags
}
Tf::Rgba16Uint | Tf::Rgba16Sint => {
read_write_tier2_if | Tfc::STORAGE | Tfc::COLOR_ATTACHMENT
read_write_tier2_if | Tfc::STORAGE | Tfc::COLOR_ATTACHMENT | Tfc::MULTISAMPLE
}
Tf::Rgba16Unorm | Tf::Rgba16Snorm => {
Tfc::SAMPLED_LINEAR
| Tfc::STORAGE
| Tfc::COLOR_ATTACHMENT
| Tfc::COLOR_ATTACHMENT_BLEND
| Tfc::MULTISAMPLE
| msaa_resolve_desktop_if
}
Tf::Rgba16Float => {
read_write_tier2_if
@ -183,38 +239,52 @@ impl crate::Adapter<super::Api> for super::Adapter {
| Tfc::STORAGE
| Tfc::COLOR_ATTACHMENT
| Tfc::COLOR_ATTACHMENT_BLEND
| Tfc::MULTISAMPLE
| Tfc::MULTISAMPLE_RESOLVE
}
Tf::Rgba32Uint | Tf::Rgba32Sint => {
if pc.format_rgba32int_color_write {
read_write_tier2_if | Tfc::COLOR_ATTACHMENT | Tfc::STORAGE
let storage = if pc.format_rgba32int_color_write {
read_write_tier2_if | Tfc::STORAGE
} else {
Tfc::COLOR_ATTACHMENT
}
Tfc::empty()
};
storage | Tfc::COLOR_ATTACHMENT | msaa_desktop_if
}
Tf::Rgba32Float => {
if pc.format_rgba32float_all {
let extra = if pc.format_rgba32float_all {
read_write_tier2_if
| Tfc::SAMPLED_LINEAR
| Tfc::STORAGE
| Tfc::COLOR_ATTACHMENT
| Tfc::COLOR_ATTACHMENT_BLEND
} else if pc.format_rgba32float_color_write {
read_write_tier2_if | Tfc::COLOR_ATTACHMENT | Tfc::STORAGE
read_write_tier2_if | Tfc::STORAGE
} else {
Tfc::COLOR_ATTACHMENT
}
Tfc::empty()
};
extra | Tfc::COLOR_ATTACHMENT | msaa_apple7x_if | msaa_resolve_desktop_if
}
Tf::Depth32Float => {
if pc.format_depth32float_filter {
Tfc::DEPTH_STENCIL_ATTACHMENT | Tfc::SAMPLED_LINEAR
let linear = if pc.format_depth32float_filter {
Tfc::SAMPLED_LINEAR
} else {
Tfc::DEPTH_STENCIL_ATTACHMENT
}
Tfc::empty()
};
linear | Tfc::DEPTH_STENCIL_ATTACHMENT | Tfc::MULTISAMPLE | msaa_resolve_apple3x_if
}
Tf::Depth24Plus | Tf::Depth24PlusStencil8 => {
Tfc::DEPTH_STENCIL_ATTACHMENT | Tfc::SAMPLED_LINEAR
Tfc::DEPTH_STENCIL_ATTACHMENT
| Tfc::SAMPLED_LINEAR
| Tfc::MULTISAMPLE
| msaa_resolve_apple3x_if
}
Tf::Rgb9e5Ufloat => {
let msaa = if msaa_desktop_if.is_empty() {
Tfc::MULTISAMPLE | Tfc::MULTISAMPLE_RESOLVE
} else {
Tfc::empty()
};
Tfc::SAMPLED_LINEAR | msaa
}
Tf::Rgb9e5Ufloat => Tfc::SAMPLED_LINEAR,
Tf::Bc1RgbaUnorm
| Tf::Bc1RgbaUnormSrgb
| Tf::Bc2RgbaUnorm
@ -613,6 +683,9 @@ impl super::PrivateCapabilities {
} else {
mtl::MTLReadWriteTextureTier::TierNone
},
msaa_desktop: os_is_mac,
msaa_apple3: family_check && device.supports_family(MTLGPUFamily::Apple3),
msaa_apple7: family_check && device.supports_family(MTLGPUFamily::Apple7),
resource_heaps: Self::supports_any(device, RESOURCE_HEAP_SUPPORT),
argument_buffers: Self::supports_any(device, ARGUMENT_BUFFER_SUPPORT),
shared_textures: !os_is_mac,

View File

@ -144,6 +144,9 @@ struct PrivateCapabilities {
msl_version: mtl::MTLLanguageVersion,
fragment_rw_storage: bool,
read_write_texture_tier: mtl::MTLReadWriteTextureTier,
msaa_desktop: bool,
msaa_apple3: bool,
msaa_apple7: bool,
resource_heaps: bool,
argument_buffers: bool,
shared_textures: bool,

View File

@ -1332,6 +1332,7 @@ impl crate::Adapter<super::Api> for super::Adapter {
format: wgt::TextureFormat,
) -> crate::TextureFormatCapabilities {
use crate::TextureFormatCapabilities as Tfc;
let vk_format = self.private_caps.map_texture_format(format);
let properties = self
.phd_capabilities
@ -1385,6 +1386,11 @@ impl crate::Adapter<super::Api> for super::Adapter {
vk::FormatFeatureFlags::TRANSFER_DST | vk::FormatFeatureFlags::BLIT_DST,
),
);
// Vulkan is very permissive about MSAA
flags.set(
Tfc::MULTISAMPLE | Tfc::MULTISAMPLE_RESOLVE,
!format.describe().is_compressed(),
);
flags
}

View File

@ -1410,12 +1410,20 @@ bitflags::bitflags! {
/// Feature flags for a texture format.
#[repr(transparent)]
pub struct TextureFormatFeatureFlags: u32 {
/// If not present, the texture can't be sampled with a filtering sampler.
/// This may overwrite TextureSampleType::Float.filterable
const FILTERABLE = 1 << 0;
/// Allows [`TextureDescriptor::sample_count`] greater than `1`.
const MULTISAMPLE = 1 << 1;
/// Allows a texture of this format to back a view passed as `resolve_target`
/// to a render pass for an automatic driver-implemented resolve.
const MULTISAMPLE_RESOLVE = 1 << 2;
/// When used as a STORAGE texture, then a texture with this format can be bound with
/// [`StorageTextureAccess::ReadOnly`] or [`StorageTextureAccess::ReadWrite`].
const STORAGE_READ_WRITE = 1 << 0;
const STORAGE_READ_WRITE = 1 << 3;
/// When used as a STORAGE texture, then a texture with this format can be written to with atomics.
// TODO: No access flag exposed as of writing
const STORAGE_ATOMICS = 1 << 1;
const STORAGE_ATOMICS = 1 << 4;
}
}
@ -1431,9 +1439,6 @@ pub struct TextureFormatFeatures {
pub allowed_usages: TextureUsages,
/// Additional property flags for the format.
pub flags: TextureFormatFeatureFlags,
/// If `filterable` is false, the texture can't be sampled with a filtering sampler.
/// This may overwrite TextureSampleType::Float.filterable
pub filterable: bool,
}
/// Information about a texture format.
@ -1455,6 +1460,13 @@ pub struct TextureFormatInfo {
pub guaranteed_format_features: TextureFormatFeatures,
}
impl TextureFormatInfo {
/// Return `true` for compressed formats.
pub fn is_compressed(&self) -> bool {
self.block_dimensions != (1, 1)
}
}
/// Underlying texture data format.
///
/// If there is a conversion in the format (such as srgb -> linear), The conversion listed is for
@ -1984,9 +1996,18 @@ impl TextureFormat {
let float = TextureSampleType::Float { filterable: true };
let depth = TextureSampleType::Depth;
// Color spaces
let linear = false;
let srgb = true;
enum ColorSpace {
Linear,
Corrected,
}
let linear = ColorSpace::Linear;
let corrected = ColorSpace::Corrected;
// Multisampling
let noaa = TextureFormatFeatureFlags::empty();
let msaa = TextureFormatFeatureFlags::MULTISAMPLE;
let msaa_resolve =
TextureFormatFeatureFlags::MULTISAMPLE | TextureFormatFeatureFlags::MULTISAMPLE_RESOLVE;
// Flags
let basic =
@ -1999,145 +2020,238 @@ impl TextureFormat {
let (
required_features,
sample_type,
srgb,
color_space,
msaa_flags,
block_dimensions,
block_size,
allowed_usages,
components,
) = match self {
// Normal 8 bit textures
Self::R8Unorm => (native, float, linear, (1, 1), 1, attachment, 1),
Self::R8Snorm => (native, float, linear, (1, 1), 1, basic, 1),
Self::R8Uint => (native, uint, linear, (1, 1), 1, attachment, 1),
Self::R8Sint => (native, sint, linear, (1, 1), 1, attachment, 1),
Self::R8Unorm => (
native,
float,
linear,
msaa_resolve,
(1, 1),
1,
attachment,
1,
),
Self::R8Snorm => (native, float, linear, msaa, (1, 1), 1, basic, 1),
Self::R8Uint => (native, uint, linear, msaa, (1, 1), 1, attachment, 1),
Self::R8Sint => (native, sint, linear, msaa, (1, 1), 1, attachment, 1),
// Normal 16 bit textures
Self::R16Uint => (native, uint, linear, (1, 1), 2, attachment, 1),
Self::R16Sint => (native, sint, linear, (1, 1), 2, attachment, 1),
Self::R16Float => (native, float, linear, (1, 1), 2, attachment, 1),
Self::Rg8Unorm => (native, float, linear, (1, 1), 2, attachment, 2),
Self::Rg8Snorm => (native, float, linear, (1, 1), 2, attachment, 2),
Self::Rg8Uint => (native, uint, linear, (1, 1), 2, attachment, 2),
Self::Rg8Sint => (native, sint, linear, (1, 1), 2, basic, 2),
Self::R16Uint => (native, uint, linear, msaa, (1, 1), 2, attachment, 1),
Self::R16Sint => (native, sint, linear, msaa, (1, 1), 2, attachment, 1),
Self::R16Float => (
native,
float,
linear,
msaa_resolve,
(1, 1),
2,
attachment,
1,
),
Self::Rg8Unorm => (
native,
float,
linear,
msaa_resolve,
(1, 1),
2,
attachment,
2,
),
Self::Rg8Snorm => (native, float, linear, msaa, (1, 1), 2, attachment, 2),
Self::Rg8Uint => (native, uint, linear, msaa, (1, 1), 2, attachment, 2),
Self::Rg8Sint => (native, sint, linear, msaa, (1, 1), 2, basic, 2),
// Normal 32 bit textures
Self::R32Uint => (native, uint, linear, (1, 1), 4, all_flags, 1),
Self::R32Sint => (native, sint, linear, (1, 1), 4, all_flags, 1),
Self::R32Float => (native, nearest, linear, (1, 1), 4, all_flags, 1),
Self::Rg16Uint => (native, uint, linear, (1, 1), 4, attachment, 2),
Self::Rg16Sint => (native, sint, linear, (1, 1), 4, attachment, 2),
Self::Rg16Float => (native, float, linear, (1, 1), 4, attachment, 2),
Self::Rgba8Unorm => (native, float, linear, (1, 1), 4, all_flags, 4),
Self::Rgba8UnormSrgb => (native, float, srgb, (1, 1), 4, attachment, 4),
Self::Rgba8Snorm => (native, float, linear, (1, 1), 4, storage, 4),
Self::Rgba8Uint => (native, uint, linear, (1, 1), 4, all_flags, 4),
Self::Rgba8Sint => (native, sint, linear, (1, 1), 4, all_flags, 4),
Self::Bgra8Unorm => (native, float, linear, (1, 1), 4, attachment, 4),
Self::Bgra8UnormSrgb => (native, float, srgb, (1, 1), 4, attachment, 4),
Self::R32Uint => (native, uint, linear, noaa, (1, 1), 4, all_flags, 1),
Self::R32Sint => (native, sint, linear, noaa, (1, 1), 4, all_flags, 1),
Self::R32Float => (native, nearest, linear, msaa, (1, 1), 4, all_flags, 1),
Self::Rg16Uint => (native, uint, linear, msaa, (1, 1), 4, attachment, 2),
Self::Rg16Sint => (native, sint, linear, msaa, (1, 1), 4, attachment, 2),
Self::Rg16Float => (
native,
float,
linear,
msaa_resolve,
(1, 1),
4,
attachment,
2,
),
Self::Rgba8Unorm => (native, float, linear, msaa_resolve, (1, 1), 4, all_flags, 4),
Self::Rgba8UnormSrgb => (
native,
float,
corrected,
msaa_resolve,
(1, 1),
4,
attachment,
4,
),
Self::Rgba8Snorm => (native, float, linear, msaa, (1, 1), 4, storage, 4),
Self::Rgba8Uint => (native, uint, linear, msaa, (1, 1), 4, all_flags, 4),
Self::Rgba8Sint => (native, sint, linear, msaa, (1, 1), 4, all_flags, 4),
Self::Bgra8Unorm => (
native,
float,
linear,
msaa_resolve,
(1, 1),
4,
attachment,
4,
),
Self::Bgra8UnormSrgb => (
native,
float,
corrected,
msaa_resolve,
(1, 1),
4,
attachment,
4,
),
// Packed 32 bit textures
Self::Rgb10a2Unorm => (native, float, linear, (1, 1), 4, attachment, 4),
Self::Rg11b10Float => (native, float, linear, (1, 1), 4, basic, 3),
Self::Rgb10a2Unorm => (
native,
float,
linear,
msaa_resolve,
(1, 1),
4,
attachment,
4,
),
Self::Rg11b10Float => (native, float, linear, msaa, (1, 1), 4, basic, 3),
// Packed 32 bit textures
Self::Rg32Uint => (native, uint, linear, (1, 1), 8, all_flags, 2),
Self::Rg32Sint => (native, sint, linear, (1, 1), 8, all_flags, 2),
Self::Rg32Float => (native, nearest, linear, (1, 1), 8, all_flags, 2),
Self::Rgba16Uint => (native, uint, linear, (1, 1), 8, all_flags, 4),
Self::Rgba16Sint => (native, sint, linear, (1, 1), 8, all_flags, 4),
Self::Rgba16Float => (native, float, linear, (1, 1), 8, all_flags, 4),
Self::Rg32Uint => (native, uint, linear, noaa, (1, 1), 8, all_flags, 2),
Self::Rg32Sint => (native, sint, linear, noaa, (1, 1), 8, all_flags, 2),
Self::Rg32Float => (native, nearest, linear, noaa, (1, 1), 8, all_flags, 2),
Self::Rgba16Uint => (native, uint, linear, msaa, (1, 1), 8, all_flags, 4),
Self::Rgba16Sint => (native, sint, linear, msaa, (1, 1), 8, all_flags, 4),
Self::Rgba16Float => (native, float, linear, msaa_resolve, (1, 1), 8, all_flags, 4),
// Packed 32 bit textures
Self::Rgba32Uint => (native, uint, linear, (1, 1), 16, all_flags, 4),
Self::Rgba32Sint => (native, sint, linear, (1, 1), 16, all_flags, 4),
Self::Rgba32Float => (native, nearest, linear, (1, 1), 16, all_flags, 4),
Self::Rgba32Uint => (native, uint, linear, noaa, (1, 1), 16, all_flags, 4),
Self::Rgba32Sint => (native, sint, linear, noaa, (1, 1), 16, all_flags, 4),
Self::Rgba32Float => (native, nearest, linear, noaa, (1, 1), 16, all_flags, 4),
// Depth-stencil textures
Self::Depth32Float => (native, depth, linear, (1, 1), 4, attachment, 1),
Self::Depth24Plus => (native, depth, linear, (1, 1), 4, attachment, 1),
Self::Depth24PlusStencil8 => (native, depth, linear, (1, 1), 4, attachment, 2),
Self::Depth32Float => (native, depth, linear, msaa, (1, 1), 4, attachment, 1),
Self::Depth24Plus => (native, depth, linear, msaa, (1, 1), 4, attachment, 1),
Self::Depth24PlusStencil8 => (native, depth, linear, msaa, (1, 1), 4, attachment, 2),
// Packed uncompressed
Self::Rgb9e5Ufloat => (native, float, linear, (1, 1), 4, basic, 3),
Self::Rgb9e5Ufloat => (native, float, linear, noaa, (1, 1), 4, basic, 3),
// BCn compressed textures
Self::Bc1RgbaUnorm => (bc, float, linear, (4, 4), 8, basic, 4),
Self::Bc1RgbaUnormSrgb => (bc, float, srgb, (4, 4), 8, basic, 4),
Self::Bc2RgbaUnorm => (bc, float, linear, (4, 4), 16, basic, 4),
Self::Bc2RgbaUnormSrgb => (bc, float, srgb, (4, 4), 16, basic, 4),
Self::Bc3RgbaUnorm => (bc, float, linear, (4, 4), 16, basic, 4),
Self::Bc3RgbaUnormSrgb => (bc, float, srgb, (4, 4), 16, basic, 4),
Self::Bc4RUnorm => (bc, float, linear, (4, 4), 8, basic, 1),
Self::Bc4RSnorm => (bc, float, linear, (4, 4), 8, basic, 1),
Self::Bc5RgUnorm => (bc, float, linear, (4, 4), 16, basic, 2),
Self::Bc5RgSnorm => (bc, float, linear, (4, 4), 16, basic, 2),
Self::Bc6hRgbUfloat => (bc, float, linear, (4, 4), 16, basic, 3),
Self::Bc6hRgbSfloat => (bc, float, linear, (4, 4), 16, basic, 3),
Self::Bc7RgbaUnorm => (bc, float, linear, (4, 4), 16, basic, 4),
Self::Bc7RgbaUnormSrgb => (bc, float, srgb, (4, 4), 16, basic, 4),
Self::Bc1RgbaUnorm => (bc, float, linear, noaa, (4, 4), 8, basic, 4),
Self::Bc1RgbaUnormSrgb => (bc, float, corrected, noaa, (4, 4), 8, basic, 4),
Self::Bc2RgbaUnorm => (bc, float, linear, noaa, (4, 4), 16, basic, 4),
Self::Bc2RgbaUnormSrgb => (bc, float, corrected, noaa, (4, 4), 16, basic, 4),
Self::Bc3RgbaUnorm => (bc, float, linear, noaa, (4, 4), 16, basic, 4),
Self::Bc3RgbaUnormSrgb => (bc, float, corrected, noaa, (4, 4), 16, basic, 4),
Self::Bc4RUnorm => (bc, float, linear, noaa, (4, 4), 8, basic, 1),
Self::Bc4RSnorm => (bc, float, linear, noaa, (4, 4), 8, basic, 1),
Self::Bc5RgUnorm => (bc, float, linear, noaa, (4, 4), 16, basic, 2),
Self::Bc5RgSnorm => (bc, float, linear, noaa, (4, 4), 16, basic, 2),
Self::Bc6hRgbUfloat => (bc, float, linear, noaa, (4, 4), 16, basic, 3),
Self::Bc6hRgbSfloat => (bc, float, linear, noaa, (4, 4), 16, basic, 3),
Self::Bc7RgbaUnorm => (bc, float, linear, noaa, (4, 4), 16, basic, 4),
Self::Bc7RgbaUnormSrgb => (bc, float, corrected, noaa, (4, 4), 16, basic, 4),
// ETC compressed textures
Self::Etc2Rgb8Unorm => (etc2, float, linear, (4, 4), 8, basic, 3),
Self::Etc2Rgb8UnormSrgb => (etc2, float, srgb, (4, 4), 8, basic, 3),
Self::Etc2Rgb8A1Unorm => (etc2, float, linear, (4, 4), 8, basic, 4),
Self::Etc2Rgb8A1UnormSrgb => (etc2, float, srgb, (4, 4), 8, basic, 4),
Self::Etc2Rgba8Unorm => (etc2, float, linear, (4, 4), 16, basic, 4),
Self::Etc2Rgba8UnormSrgb => (etc2, float, srgb, (4, 4), 16, basic, 4),
Self::EacR11Unorm => (etc2, float, linear, (4, 4), 8, basic, 1),
Self::EacR11Snorm => (etc2, float, linear, (4, 4), 8, basic, 1),
Self::EacRg11Unorm => (etc2, float, linear, (4, 4), 16, basic, 2),
Self::EacRg11Snorm => (etc2, float, linear, (4, 4), 16, basic, 2),
Self::Etc2Rgb8Unorm => (etc2, float, linear, noaa, (4, 4), 8, basic, 3),
Self::Etc2Rgb8UnormSrgb => (etc2, float, corrected, noaa, (4, 4), 8, basic, 3),
Self::Etc2Rgb8A1Unorm => (etc2, float, linear, noaa, (4, 4), 8, basic, 4),
Self::Etc2Rgb8A1UnormSrgb => (etc2, float, corrected, noaa, (4, 4), 8, basic, 4),
Self::Etc2Rgba8Unorm => (etc2, float, linear, noaa, (4, 4), 16, basic, 4),
Self::Etc2Rgba8UnormSrgb => (etc2, float, corrected, noaa, (4, 4), 16, basic, 4),
Self::EacR11Unorm => (etc2, float, linear, noaa, (4, 4), 8, basic, 1),
Self::EacR11Snorm => (etc2, float, linear, noaa, (4, 4), 8, basic, 1),
Self::EacRg11Unorm => (etc2, float, linear, noaa, (4, 4), 16, basic, 2),
Self::EacRg11Snorm => (etc2, float, linear, noaa, (4, 4), 16, basic, 2),
// ASTC compressed textures
Self::Astc4x4RgbaUnorm => (astc_ldr, float, linear, (4, 4), 16, basic, 4),
Self::Astc4x4RgbaUnormSrgb => (astc_ldr, float, srgb, (4, 4), 16, basic, 4),
Self::Astc5x4RgbaUnorm => (astc_ldr, float, linear, (5, 4), 16, basic, 4),
Self::Astc5x4RgbaUnormSrgb => (astc_ldr, float, srgb, (5, 4), 16, basic, 4),
Self::Astc5x5RgbaUnorm => (astc_ldr, float, linear, (5, 5), 16, basic, 4),
Self::Astc5x5RgbaUnormSrgb => (astc_ldr, float, srgb, (5, 5), 16, basic, 4),
Self::Astc6x5RgbaUnorm => (astc_ldr, float, linear, (6, 5), 16, basic, 4),
Self::Astc6x5RgbaUnormSrgb => (astc_ldr, float, srgb, (6, 5), 16, basic, 4),
Self::Astc6x6RgbaUnorm => (astc_ldr, float, linear, (6, 6), 16, basic, 4),
Self::Astc6x6RgbaUnormSrgb => (astc_ldr, float, srgb, (6, 6), 16, basic, 4),
Self::Astc8x5RgbaUnorm => (astc_ldr, float, linear, (8, 5), 16, basic, 4),
Self::Astc8x5RgbaUnormSrgb => (astc_ldr, float, srgb, (8, 5), 16, basic, 4),
Self::Astc8x6RgbaUnorm => (astc_ldr, float, linear, (8, 6), 16, basic, 4),
Self::Astc8x6RgbaUnormSrgb => (astc_ldr, float, srgb, (8, 6), 16, basic, 4),
Self::Astc10x5RgbaUnorm => (astc_ldr, float, linear, (10, 5), 16, basic, 4),
Self::Astc10x5RgbaUnormSrgb => (astc_ldr, float, srgb, (10, 5), 16, basic, 4),
Self::Astc10x6RgbaUnorm => (astc_ldr, float, linear, (10, 6), 16, basic, 4),
Self::Astc10x6RgbaUnormSrgb => (astc_ldr, float, srgb, (10, 6), 16, basic, 4),
Self::Astc8x8RgbaUnorm => (astc_ldr, float, linear, (8, 8), 16, basic, 4),
Self::Astc8x8RgbaUnormSrgb => (astc_ldr, float, srgb, (8, 8), 16, basic, 4),
Self::Astc10x8RgbaUnorm => (astc_ldr, float, linear, (10, 8), 16, basic, 4),
Self::Astc10x8RgbaUnormSrgb => (astc_ldr, float, srgb, (10, 8), 16, basic, 4),
Self::Astc10x10RgbaUnorm => (astc_ldr, float, linear, (10, 10), 16, basic, 4),
Self::Astc10x10RgbaUnormSrgb => (astc_ldr, float, srgb, (10, 10), 16, basic, 4),
Self::Astc12x10RgbaUnorm => (astc_ldr, float, linear, (12, 10), 16, basic, 4),
Self::Astc12x10RgbaUnormSrgb => (astc_ldr, float, srgb, (12, 10), 16, basic, 4),
Self::Astc12x12RgbaUnorm => (astc_ldr, float, linear, (12, 12), 16, basic, 4),
Self::Astc12x12RgbaUnormSrgb => (astc_ldr, float, srgb, (12, 12), 16, basic, 4),
Self::Astc4x4RgbaUnorm => (astc_ldr, float, linear, noaa, (4, 4), 16, basic, 4),
Self::Astc4x4RgbaUnormSrgb => (astc_ldr, float, corrected, noaa, (4, 4), 16, basic, 4),
Self::Astc5x4RgbaUnorm => (astc_ldr, float, linear, noaa, (5, 4), 16, basic, 4),
Self::Astc5x4RgbaUnormSrgb => (astc_ldr, float, corrected, noaa, (5, 4), 16, basic, 4),
Self::Astc5x5RgbaUnorm => (astc_ldr, float, linear, noaa, (5, 5), 16, basic, 4),
Self::Astc5x5RgbaUnormSrgb => (astc_ldr, float, corrected, noaa, (5, 5), 16, basic, 4),
Self::Astc6x5RgbaUnorm => (astc_ldr, float, linear, noaa, (6, 5), 16, basic, 4),
Self::Astc6x5RgbaUnormSrgb => (astc_ldr, float, corrected, noaa, (6, 5), 16, basic, 4),
Self::Astc6x6RgbaUnorm => (astc_ldr, float, linear, noaa, (6, 6), 16, basic, 4),
Self::Astc6x6RgbaUnormSrgb => (astc_ldr, float, corrected, noaa, (6, 6), 16, basic, 4),
Self::Astc8x5RgbaUnorm => (astc_ldr, float, linear, noaa, (8, 5), 16, basic, 4),
Self::Astc8x5RgbaUnormSrgb => (astc_ldr, float, corrected, noaa, (8, 5), 16, basic, 4),
Self::Astc8x6RgbaUnorm => (astc_ldr, float, linear, noaa, (8, 6), 16, basic, 4),
Self::Astc8x6RgbaUnormSrgb => (astc_ldr, float, corrected, noaa, (8, 6), 16, basic, 4),
Self::Astc10x5RgbaUnorm => (astc_ldr, float, linear, noaa, (10, 5), 16, basic, 4),
Self::Astc10x5RgbaUnormSrgb => {
(astc_ldr, float, corrected, noaa, (10, 5), 16, basic, 4)
}
Self::Astc10x6RgbaUnorm => (astc_ldr, float, linear, noaa, (10, 6), 16, basic, 4),
Self::Astc10x6RgbaUnormSrgb => {
(astc_ldr, float, corrected, noaa, (10, 6), 16, basic, 4)
}
Self::Astc8x8RgbaUnorm => (astc_ldr, float, linear, noaa, (8, 8), 16, basic, 4),
Self::Astc8x8RgbaUnormSrgb => (astc_ldr, float, corrected, noaa, (8, 8), 16, basic, 4),
Self::Astc10x8RgbaUnorm => (astc_ldr, float, linear, noaa, (10, 8), 16, basic, 4),
Self::Astc10x8RgbaUnormSrgb => {
(astc_ldr, float, corrected, noaa, (10, 8), 16, basic, 4)
}
Self::Astc10x10RgbaUnorm => (astc_ldr, float, linear, noaa, (10, 10), 16, basic, 4),
Self::Astc10x10RgbaUnormSrgb => {
(astc_ldr, float, corrected, noaa, (10, 10), 16, basic, 4)
}
Self::Astc12x10RgbaUnorm => (astc_ldr, float, linear, noaa, (12, 10), 16, basic, 4),
Self::Astc12x10RgbaUnormSrgb => {
(astc_ldr, float, corrected, noaa, (12, 10), 16, basic, 4)
}
Self::Astc12x12RgbaUnorm => (astc_ldr, float, linear, noaa, (12, 12), 16, basic, 4),
Self::Astc12x12RgbaUnormSrgb => {
(astc_ldr, float, corrected, noaa, (12, 12), 16, basic, 4)
}
// Optional normalized 16-bit-per-channel formats
Self::R16Unorm => (norm16bit, float, linear, (1, 1), 2, storage, 1),
Self::R16Snorm => (norm16bit, float, linear, (1, 1), 2, storage, 1),
Self::Rg16Unorm => (norm16bit, float, linear, (1, 1), 4, storage, 2),
Self::Rg16Snorm => (norm16bit, float, linear, (1, 1), 4, storage, 2),
Self::Rgba16Unorm => (norm16bit, float, linear, (1, 1), 8, storage, 4),
Self::Rgba16Snorm => (norm16bit, float, linear, (1, 1), 8, storage, 4),
Self::R16Unorm => (norm16bit, float, linear, msaa, (1, 1), 2, storage, 1),
Self::R16Snorm => (norm16bit, float, linear, msaa, (1, 1), 2, storage, 1),
Self::Rg16Unorm => (norm16bit, float, linear, msaa, (1, 1), 4, storage, 2),
Self::Rg16Snorm => (norm16bit, float, linear, msaa, (1, 1), 4, storage, 2),
Self::Rgba16Unorm => (norm16bit, float, linear, msaa, (1, 1), 8, storage, 4),
Self::Rgba16Snorm => (norm16bit, float, linear, msaa, (1, 1), 8, storage, 4),
};
let mut flags = msaa_flags;
flags.set(
TextureFormatFeatureFlags::FILTERABLE,
sample_type == TextureSampleType::Float { filterable: true },
);
TextureFormatInfo {
required_features,
sample_type,
block_dimensions,
block_size,
components,
srgb,
srgb: match color_space {
ColorSpace::Linear => false,
ColorSpace::Corrected => true,
},
guaranteed_format_features: TextureFormatFeatures {
allowed_usages,
flags: TextureFormatFeatureFlags::empty(),
filterable: sample_type == TextureSampleType::Float { filterable: true },
flags,
},
}
}