mirror of
https://github.com/gfx-rs/wgpu.git
synced 2025-12-08 21:26:17 +00:00
[dx12,vulkan] Add support for P010 texture format (#8086)
P010 is a 4:2:0 chroma subsampled planar format, similar to NV12. Each component uses 16 bits of storage, of which only the high 10 bits are used. On DX12 this maps to DXGI_FORMAT_P010, and on Vulkan this maps to G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16. The existing "nv12" gpu test module has been renamed to "planar_texture", and a new test P010_TEXTURE_CREATION_SAMPLING has been added similar to the existing NV12_TEXTURE_CREATION_SAMPLING. The remaining tests in this module have been converted to validation tests, and now test both NV12 and P010 formats.
This commit is contained in:
parent
01b3204e7f
commit
486c151772
@ -37,7 +37,7 @@ pub use wgpu_macros::gpu_test;
|
||||
pub fn fail<T>(
|
||||
device: &wgpu::Device,
|
||||
callback: impl FnOnce() -> T,
|
||||
expected_msg_substring: Option<&'static str>,
|
||||
expected_msg_substring: Option<&str>,
|
||||
) -> T {
|
||||
device.push_error_scope(wgpu::ErrorFilter::Validation);
|
||||
let result = callback();
|
||||
|
||||
@ -36,12 +36,12 @@ mod instance;
|
||||
mod life_cycle;
|
||||
mod mem_leaks;
|
||||
mod mesh_shader;
|
||||
mod nv12_texture;
|
||||
mod occlusion_query;
|
||||
mod oob_indexing;
|
||||
mod oom;
|
||||
mod pipeline;
|
||||
mod pipeline_cache;
|
||||
mod planar_texture;
|
||||
mod poll;
|
||||
mod push_constants;
|
||||
mod query_set;
|
||||
@ -96,12 +96,12 @@ fn all_tests() -> Vec<wgpu_test::GpuTestInitializer> {
|
||||
life_cycle::all_tests(&mut tests);
|
||||
mem_leaks::all_tests(&mut tests);
|
||||
mesh_shader::all_tests(&mut tests);
|
||||
nv12_texture::all_tests(&mut tests);
|
||||
occlusion_query::all_tests(&mut tests);
|
||||
oob_indexing::all_tests(&mut tests);
|
||||
oom::all_tests(&mut tests);
|
||||
pipeline_cache::all_tests(&mut tests);
|
||||
pipeline::all_tests(&mut tests);
|
||||
planar_texture::all_tests(&mut tests);
|
||||
poll::all_tests(&mut tests);
|
||||
push_constants::all_tests(&mut tests);
|
||||
query_set::all_tests(&mut tests);
|
||||
|
||||
@ -1,277 +0,0 @@
|
||||
//! Tests for nv12 texture creation and sampling.
|
||||
|
||||
use wgpu_test::{fail, gpu_test, GpuTestConfiguration, GpuTestInitializer, TestParameters};
|
||||
|
||||
pub fn all_tests(tests: &mut Vec<GpuTestInitializer>) {
|
||||
tests.extend([
|
||||
NV12_TEXTURE_CREATION_SAMPLING,
|
||||
NV12_TEXTURE_VIEW_PLANE_ON_NON_PLANAR_FORMAT,
|
||||
NV12_TEXTURE_VIEW_PLANE_OUT_OF_BOUNDS,
|
||||
NV12_TEXTURE_BAD_FORMAT_VIEW_PLANE,
|
||||
NV12_TEXTURE_BAD_SIZE,
|
||||
]);
|
||||
}
|
||||
|
||||
#[gpu_test]
|
||||
static NV12_TEXTURE_CREATION_SAMPLING: GpuTestConfiguration = GpuTestConfiguration::new()
|
||||
.parameters(
|
||||
TestParameters::default()
|
||||
.features(wgpu::Features::TEXTURE_FORMAT_NV12)
|
||||
.enable_noop(),
|
||||
)
|
||||
.run_sync(|ctx| {
|
||||
let size = wgpu::Extent3d {
|
||||
width: 256,
|
||||
height: 256,
|
||||
depth_or_array_layers: 1,
|
||||
};
|
||||
let target_format = wgpu::TextureFormat::Bgra8UnormSrgb;
|
||||
|
||||
let shader = ctx
|
||||
.device
|
||||
.create_shader_module(wgpu::include_wgsl!("nv12_texture.wgsl"));
|
||||
let pipeline = ctx
|
||||
.device
|
||||
.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
|
||||
label: Some("nv12 pipeline"),
|
||||
layout: None,
|
||||
vertex: wgpu::VertexState {
|
||||
module: &shader,
|
||||
entry_point: Some("vs_main"),
|
||||
compilation_options: Default::default(),
|
||||
buffers: &[],
|
||||
},
|
||||
fragment: Some(wgpu::FragmentState {
|
||||
module: &shader,
|
||||
entry_point: Some("fs_main"),
|
||||
compilation_options: Default::default(),
|
||||
targets: &[Some(target_format.into())],
|
||||
}),
|
||||
primitive: wgpu::PrimitiveState {
|
||||
topology: wgpu::PrimitiveTopology::TriangleStrip,
|
||||
strip_index_format: Some(wgpu::IndexFormat::Uint32),
|
||||
..Default::default()
|
||||
},
|
||||
depth_stencil: None,
|
||||
multisample: wgpu::MultisampleState::default(),
|
||||
multiview: None,
|
||||
cache: None,
|
||||
});
|
||||
|
||||
let tex = ctx.device.create_texture(&wgpu::TextureDescriptor {
|
||||
label: None,
|
||||
dimension: wgpu::TextureDimension::D2,
|
||||
size,
|
||||
format: wgpu::TextureFormat::NV12,
|
||||
usage: wgpu::TextureUsages::TEXTURE_BINDING,
|
||||
mip_level_count: 1,
|
||||
sample_count: 1,
|
||||
view_formats: &[],
|
||||
});
|
||||
let y_view = tex.create_view(&wgpu::TextureViewDescriptor {
|
||||
format: Some(wgpu::TextureFormat::R8Unorm),
|
||||
aspect: wgpu::TextureAspect::Plane0,
|
||||
..Default::default()
|
||||
});
|
||||
let uv_view = tex.create_view(&wgpu::TextureViewDescriptor {
|
||||
format: Some(wgpu::TextureFormat::Rg8Unorm),
|
||||
aspect: wgpu::TextureAspect::Plane1,
|
||||
..Default::default()
|
||||
});
|
||||
let sampler = ctx.device.create_sampler(&wgpu::SamplerDescriptor {
|
||||
min_filter: wgpu::FilterMode::Linear,
|
||||
mag_filter: wgpu::FilterMode::Linear,
|
||||
..Default::default()
|
||||
});
|
||||
let bind_group = ctx.device.create_bind_group(&wgpu::BindGroupDescriptor {
|
||||
label: None,
|
||||
layout: &pipeline.get_bind_group_layout(0),
|
||||
entries: &[
|
||||
wgpu::BindGroupEntry {
|
||||
binding: 0,
|
||||
resource: wgpu::BindingResource::Sampler(&sampler),
|
||||
},
|
||||
wgpu::BindGroupEntry {
|
||||
binding: 1,
|
||||
resource: wgpu::BindingResource::TextureView(&y_view),
|
||||
},
|
||||
wgpu::BindGroupEntry {
|
||||
binding: 2,
|
||||
resource: wgpu::BindingResource::TextureView(&uv_view),
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
let target_tex = ctx.device.create_texture(&wgpu::TextureDescriptor {
|
||||
label: None,
|
||||
size,
|
||||
mip_level_count: 1,
|
||||
sample_count: 1,
|
||||
dimension: wgpu::TextureDimension::D2,
|
||||
format: target_format,
|
||||
usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
|
||||
view_formats: &[],
|
||||
});
|
||||
let target_view = target_tex.create_view(&wgpu::TextureViewDescriptor::default());
|
||||
|
||||
let mut encoder = ctx
|
||||
.device
|
||||
.create_command_encoder(&wgpu::CommandEncoderDescriptor::default());
|
||||
let mut rpass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
|
||||
label: None,
|
||||
color_attachments: &[Some(wgpu::RenderPassColorAttachment {
|
||||
ops: wgpu::Operations::default(),
|
||||
resolve_target: None,
|
||||
view: &target_view,
|
||||
depth_slice: None,
|
||||
})],
|
||||
depth_stencil_attachment: None,
|
||||
timestamp_writes: None,
|
||||
occlusion_query_set: None,
|
||||
});
|
||||
rpass.set_pipeline(&pipeline);
|
||||
rpass.set_bind_group(0, &bind_group, &[]);
|
||||
rpass.draw(0..4, 0..1);
|
||||
drop(rpass);
|
||||
ctx.queue.submit(Some(encoder.finish()));
|
||||
});
|
||||
|
||||
#[gpu_test]
|
||||
static NV12_TEXTURE_VIEW_PLANE_ON_NON_PLANAR_FORMAT: GpuTestConfiguration =
|
||||
GpuTestConfiguration::new()
|
||||
.parameters(
|
||||
TestParameters::default()
|
||||
.features(wgpu::Features::TEXTURE_FORMAT_NV12)
|
||||
.enable_noop(),
|
||||
)
|
||||
.run_sync(|ctx| {
|
||||
let size = wgpu::Extent3d {
|
||||
width: 256,
|
||||
height: 256,
|
||||
depth_or_array_layers: 1,
|
||||
};
|
||||
let tex = ctx.device.create_texture(&wgpu::TextureDescriptor {
|
||||
label: None,
|
||||
dimension: wgpu::TextureDimension::D2,
|
||||
size,
|
||||
format: wgpu::TextureFormat::R8Unorm,
|
||||
usage: wgpu::TextureUsages::TEXTURE_BINDING,
|
||||
mip_level_count: 1,
|
||||
sample_count: 1,
|
||||
view_formats: &[],
|
||||
});
|
||||
fail(
|
||||
&ctx.device,
|
||||
|| {
|
||||
let _ = tex.create_view(&wgpu::TextureViewDescriptor {
|
||||
aspect: wgpu::TextureAspect::Plane0,
|
||||
..Default::default()
|
||||
});
|
||||
},
|
||||
Some("aspect plane0 is not in the source texture format r8unorm"),
|
||||
);
|
||||
});
|
||||
|
||||
#[gpu_test]
|
||||
static NV12_TEXTURE_VIEW_PLANE_OUT_OF_BOUNDS: GpuTestConfiguration = GpuTestConfiguration::new()
|
||||
.parameters(
|
||||
TestParameters::default()
|
||||
.features(wgpu::Features::TEXTURE_FORMAT_NV12)
|
||||
.enable_noop(),
|
||||
)
|
||||
.run_sync(|ctx| {
|
||||
let size = wgpu::Extent3d {
|
||||
width: 256,
|
||||
height: 256,
|
||||
depth_or_array_layers: 1,
|
||||
};
|
||||
let tex = ctx.device.create_texture(&wgpu::TextureDescriptor {
|
||||
label: None,
|
||||
dimension: wgpu::TextureDimension::D2,
|
||||
size,
|
||||
format: wgpu::TextureFormat::NV12,
|
||||
usage: wgpu::TextureUsages::TEXTURE_BINDING,
|
||||
mip_level_count: 1,
|
||||
sample_count: 1,
|
||||
view_formats: &[],
|
||||
});
|
||||
fail(
|
||||
&ctx.device,
|
||||
|| {
|
||||
let _ = tex.create_view(&wgpu::TextureViewDescriptor {
|
||||
format: Some(wgpu::TextureFormat::R8Unorm),
|
||||
aspect: wgpu::TextureAspect::Plane2,
|
||||
..Default::default()
|
||||
});
|
||||
},
|
||||
Some("aspect plane2 is not in the source texture format nv12"),
|
||||
);
|
||||
});
|
||||
|
||||
#[gpu_test]
|
||||
static NV12_TEXTURE_BAD_FORMAT_VIEW_PLANE: GpuTestConfiguration = GpuTestConfiguration::new()
|
||||
.parameters(
|
||||
TestParameters::default()
|
||||
.features(wgpu::Features::TEXTURE_FORMAT_NV12)
|
||||
.enable_noop(),
|
||||
)
|
||||
.run_sync(|ctx| {
|
||||
let size = wgpu::Extent3d {
|
||||
width: 256,
|
||||
height: 256,
|
||||
depth_or_array_layers: 1,
|
||||
};
|
||||
let tex = ctx.device.create_texture(&wgpu::TextureDescriptor {
|
||||
label: None,
|
||||
dimension: wgpu::TextureDimension::D2,
|
||||
size,
|
||||
format: wgpu::TextureFormat::NV12,
|
||||
usage: wgpu::TextureUsages::TEXTURE_BINDING,
|
||||
mip_level_count: 1,
|
||||
sample_count: 1,
|
||||
view_formats: &[],
|
||||
});
|
||||
fail(
|
||||
&ctx.device,
|
||||
|| {
|
||||
let _ = tex.create_view(&wgpu::TextureViewDescriptor {
|
||||
format: Some(wgpu::TextureFormat::Rg8Unorm),
|
||||
aspect: wgpu::TextureAspect::Plane0,
|
||||
..Default::default()
|
||||
});
|
||||
},
|
||||
Some("unable to view texture nv12 as rg8unorm"),
|
||||
);
|
||||
});
|
||||
|
||||
#[gpu_test]
|
||||
static NV12_TEXTURE_BAD_SIZE: GpuTestConfiguration = GpuTestConfiguration::new()
|
||||
.parameters(
|
||||
TestParameters::default()
|
||||
.features(wgpu::Features::TEXTURE_FORMAT_NV12)
|
||||
.enable_noop(),
|
||||
)
|
||||
.run_sync(|ctx| {
|
||||
let size = wgpu::Extent3d {
|
||||
width: 255,
|
||||
height: 255,
|
||||
depth_or_array_layers: 1,
|
||||
};
|
||||
|
||||
fail(
|
||||
&ctx.device,
|
||||
|| {
|
||||
let _ = ctx.device.create_texture(&wgpu::TextureDescriptor {
|
||||
label: None,
|
||||
dimension: wgpu::TextureDimension::D2,
|
||||
size,
|
||||
format: wgpu::TextureFormat::NV12,
|
||||
usage: wgpu::TextureUsages::TEXTURE_BINDING,
|
||||
mip_level_count: 1,
|
||||
sample_count: 1,
|
||||
view_formats: &[],
|
||||
});
|
||||
},
|
||||
Some("width 255 is not a multiple of nv12's width multiple requirement"),
|
||||
);
|
||||
});
|
||||
189
tests/tests/wgpu-gpu/planar_texture/mod.rs
Normal file
189
tests/tests/wgpu-gpu/planar_texture/mod.rs
Normal file
@ -0,0 +1,189 @@
|
||||
//! Tests for nv12 texture creation and sampling.
|
||||
|
||||
use wgpu_test::{
|
||||
gpu_test, GpuTestConfiguration, GpuTestInitializer, TestParameters, TestingContext,
|
||||
};
|
||||
|
||||
pub fn all_tests(tests: &mut Vec<GpuTestInitializer>) {
|
||||
tests.extend([
|
||||
NV12_TEXTURE_CREATION_SAMPLING,
|
||||
P010_TEXTURE_CREATION_SAMPLING,
|
||||
]);
|
||||
}
|
||||
|
||||
// Helper function to test planar texture creation and sampling.
|
||||
fn test_planar_texture_creation_sampling(
|
||||
ctx: &TestingContext,
|
||||
y_view: &wgpu::TextureView,
|
||||
uv_view: &wgpu::TextureView,
|
||||
) {
|
||||
let target_format = wgpu::TextureFormat::Bgra8UnormSrgb;
|
||||
|
||||
let shader = ctx
|
||||
.device
|
||||
.create_shader_module(wgpu::include_wgsl!("planar_texture.wgsl"));
|
||||
let pipeline = ctx
|
||||
.device
|
||||
.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
|
||||
label: Some("planar texture pipeline"),
|
||||
layout: None,
|
||||
vertex: wgpu::VertexState {
|
||||
module: &shader,
|
||||
entry_point: Some("vs_main"),
|
||||
compilation_options: Default::default(),
|
||||
buffers: &[],
|
||||
},
|
||||
fragment: Some(wgpu::FragmentState {
|
||||
module: &shader,
|
||||
entry_point: Some("fs_main"),
|
||||
compilation_options: Default::default(),
|
||||
targets: &[Some(target_format.into())],
|
||||
}),
|
||||
primitive: wgpu::PrimitiveState {
|
||||
topology: wgpu::PrimitiveTopology::TriangleStrip,
|
||||
strip_index_format: Some(wgpu::IndexFormat::Uint32),
|
||||
..Default::default()
|
||||
},
|
||||
depth_stencil: None,
|
||||
multisample: wgpu::MultisampleState::default(),
|
||||
multiview: None,
|
||||
cache: None,
|
||||
});
|
||||
|
||||
let sampler = ctx.device.create_sampler(&wgpu::SamplerDescriptor {
|
||||
min_filter: wgpu::FilterMode::Linear,
|
||||
mag_filter: wgpu::FilterMode::Linear,
|
||||
..Default::default()
|
||||
});
|
||||
let bind_group = ctx.device.create_bind_group(&wgpu::BindGroupDescriptor {
|
||||
label: None,
|
||||
layout: &pipeline.get_bind_group_layout(0),
|
||||
entries: &[
|
||||
wgpu::BindGroupEntry {
|
||||
binding: 0,
|
||||
resource: wgpu::BindingResource::Sampler(&sampler),
|
||||
},
|
||||
wgpu::BindGroupEntry {
|
||||
binding: 1,
|
||||
resource: wgpu::BindingResource::TextureView(y_view),
|
||||
},
|
||||
wgpu::BindGroupEntry {
|
||||
binding: 2,
|
||||
resource: wgpu::BindingResource::TextureView(uv_view),
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
let target_tex = ctx.device.create_texture(&wgpu::TextureDescriptor {
|
||||
label: None,
|
||||
size: y_view.texture().size(),
|
||||
mip_level_count: 1,
|
||||
sample_count: 1,
|
||||
dimension: wgpu::TextureDimension::D2,
|
||||
format: target_format,
|
||||
usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
|
||||
view_formats: &[],
|
||||
});
|
||||
let target_view = target_tex.create_view(&wgpu::TextureViewDescriptor::default());
|
||||
|
||||
let mut encoder = ctx
|
||||
.device
|
||||
.create_command_encoder(&wgpu::CommandEncoderDescriptor::default());
|
||||
let mut rpass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
|
||||
label: None,
|
||||
color_attachments: &[Some(wgpu::RenderPassColorAttachment {
|
||||
ops: wgpu::Operations::default(),
|
||||
resolve_target: None,
|
||||
view: &target_view,
|
||||
depth_slice: None,
|
||||
})],
|
||||
depth_stencil_attachment: None,
|
||||
timestamp_writes: None,
|
||||
occlusion_query_set: None,
|
||||
});
|
||||
rpass.set_pipeline(&pipeline);
|
||||
rpass.set_bind_group(0, &bind_group, &[]);
|
||||
rpass.draw(0..4, 0..1);
|
||||
drop(rpass);
|
||||
ctx.queue.submit(Some(encoder.finish()));
|
||||
}
|
||||
|
||||
/// Ensures that creation and sampling of an NV12 format texture works as
|
||||
/// expected.
|
||||
#[gpu_test]
|
||||
static NV12_TEXTURE_CREATION_SAMPLING: GpuTestConfiguration = GpuTestConfiguration::new()
|
||||
.parameters(
|
||||
TestParameters::default()
|
||||
.features(wgpu::Features::TEXTURE_FORMAT_NV12)
|
||||
.enable_noop(),
|
||||
)
|
||||
.run_sync(|ctx| {
|
||||
let size = wgpu::Extent3d {
|
||||
width: 256,
|
||||
height: 256,
|
||||
depth_or_array_layers: 1,
|
||||
};
|
||||
let tex = ctx.device.create_texture(&wgpu::TextureDescriptor {
|
||||
label: None,
|
||||
dimension: wgpu::TextureDimension::D2,
|
||||
size,
|
||||
format: wgpu::TextureFormat::NV12,
|
||||
usage: wgpu::TextureUsages::TEXTURE_BINDING,
|
||||
mip_level_count: 1,
|
||||
sample_count: 1,
|
||||
view_formats: &[],
|
||||
});
|
||||
let y_view = tex.create_view(&wgpu::TextureViewDescriptor {
|
||||
format: Some(wgpu::TextureFormat::R8Unorm),
|
||||
aspect: wgpu::TextureAspect::Plane0,
|
||||
..Default::default()
|
||||
});
|
||||
let uv_view = tex.create_view(&wgpu::TextureViewDescriptor {
|
||||
format: Some(wgpu::TextureFormat::Rg8Unorm),
|
||||
aspect: wgpu::TextureAspect::Plane1,
|
||||
..Default::default()
|
||||
});
|
||||
|
||||
test_planar_texture_creation_sampling(&ctx, &y_view, &uv_view);
|
||||
});
|
||||
|
||||
/// Ensures that creation and sampling of a P010 format texture works as
|
||||
/// expected.
|
||||
#[gpu_test]
|
||||
static P010_TEXTURE_CREATION_SAMPLING: GpuTestConfiguration = GpuTestConfiguration::new()
|
||||
.parameters(
|
||||
TestParameters::default()
|
||||
.features(
|
||||
wgpu::Features::TEXTURE_FORMAT_P010 | wgpu::Features::TEXTURE_FORMAT_16BIT_NORM,
|
||||
)
|
||||
.enable_noop(),
|
||||
)
|
||||
.run_sync(|ctx| {
|
||||
let size = wgpu::Extent3d {
|
||||
width: 256,
|
||||
height: 256,
|
||||
depth_or_array_layers: 1,
|
||||
};
|
||||
let tex = ctx.device.create_texture(&wgpu::TextureDescriptor {
|
||||
label: None,
|
||||
dimension: wgpu::TextureDimension::D2,
|
||||
size,
|
||||
format: wgpu::TextureFormat::P010,
|
||||
usage: wgpu::TextureUsages::TEXTURE_BINDING,
|
||||
mip_level_count: 1,
|
||||
sample_count: 1,
|
||||
view_formats: &[],
|
||||
});
|
||||
let y_view = tex.create_view(&wgpu::TextureViewDescriptor {
|
||||
format: Some(wgpu::TextureFormat::R16Unorm),
|
||||
aspect: wgpu::TextureAspect::Plane0,
|
||||
..Default::default()
|
||||
});
|
||||
let uv_view = tex.create_view(&wgpu::TextureViewDescriptor {
|
||||
format: Some(wgpu::TextureFormat::Rg16Unorm),
|
||||
aspect: wgpu::TextureAspect::Plane1,
|
||||
..Default::default()
|
||||
});
|
||||
|
||||
test_planar_texture_creation_sampling(&ctx, &y_view, &uv_view);
|
||||
});
|
||||
@ -1,5 +1,7 @@
|
||||
//! Tests of [`wgpu::Texture`] and related.
|
||||
|
||||
use wgpu_test::{fail, valid};
|
||||
|
||||
/// Ensures that submitting a command buffer referencing an already destroyed texture
|
||||
/// results in an error.
|
||||
#[test]
|
||||
@ -54,3 +56,245 @@ fn destroyed_texture() {
|
||||
|
||||
queue.submit([encoder.finish()]);
|
||||
}
|
||||
|
||||
/// Ensures that creating a texture view from a specific plane of a planar
|
||||
/// texture works as expected.
|
||||
#[test]
|
||||
fn planar_texture_view_plane() {
|
||||
let required_features = wgpu::Features::TEXTURE_FORMAT_NV12
|
||||
| wgpu::Features::TEXTURE_FORMAT_P010
|
||||
| wgpu::Features::TEXTURE_FORMAT_16BIT_NORM;
|
||||
let device_desc = wgpu::DeviceDescriptor {
|
||||
required_features,
|
||||
..Default::default()
|
||||
};
|
||||
let (device, _queue) = wgpu::Device::noop(&device_desc);
|
||||
let size = wgpu::Extent3d {
|
||||
width: 256,
|
||||
height: 256,
|
||||
depth_or_array_layers: 1,
|
||||
};
|
||||
|
||||
for (tex_format, view_format, view_aspect) in [
|
||||
(
|
||||
wgpu::TextureFormat::NV12,
|
||||
wgpu::TextureFormat::R8Unorm,
|
||||
wgpu::TextureAspect::Plane0,
|
||||
),
|
||||
(
|
||||
wgpu::TextureFormat::NV12,
|
||||
wgpu::TextureFormat::Rg8Unorm,
|
||||
wgpu::TextureAspect::Plane1,
|
||||
),
|
||||
(
|
||||
wgpu::TextureFormat::P010,
|
||||
wgpu::TextureFormat::R16Unorm,
|
||||
wgpu::TextureAspect::Plane0,
|
||||
),
|
||||
(
|
||||
wgpu::TextureFormat::P010,
|
||||
wgpu::TextureFormat::Rg16Unorm,
|
||||
wgpu::TextureAspect::Plane1,
|
||||
),
|
||||
] {
|
||||
let tex = device.create_texture(&wgpu::TextureDescriptor {
|
||||
label: None,
|
||||
dimension: wgpu::TextureDimension::D2,
|
||||
size,
|
||||
format: tex_format,
|
||||
usage: wgpu::TextureUsages::TEXTURE_BINDING,
|
||||
mip_level_count: 1,
|
||||
sample_count: 1,
|
||||
view_formats: &[],
|
||||
});
|
||||
valid(&device, || {
|
||||
let _ = tex.create_view(&wgpu::TextureViewDescriptor {
|
||||
format: Some(view_format),
|
||||
aspect: view_aspect,
|
||||
..Default::default()
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// Ensures that attempting to create a texture view from a specific plane of a
|
||||
/// non-planar texture fails validation.
|
||||
#[test]
|
||||
fn non_planar_texture_view_plane() {
|
||||
let (device, _queue) = wgpu::Device::noop(&wgpu::DeviceDescriptor::default());
|
||||
let size = wgpu::Extent3d {
|
||||
width: 256,
|
||||
height: 256,
|
||||
depth_or_array_layers: 1,
|
||||
};
|
||||
let tex = device.create_texture(&wgpu::TextureDescriptor {
|
||||
label: None,
|
||||
dimension: wgpu::TextureDimension::D2,
|
||||
size,
|
||||
format: wgpu::TextureFormat::R8Unorm,
|
||||
usage: wgpu::TextureUsages::TEXTURE_BINDING,
|
||||
mip_level_count: 1,
|
||||
sample_count: 1,
|
||||
view_formats: &[],
|
||||
});
|
||||
fail(
|
||||
&device,
|
||||
|| {
|
||||
let _ = tex.create_view(&wgpu::TextureViewDescriptor {
|
||||
aspect: wgpu::TextureAspect::Plane0,
|
||||
..Default::default()
|
||||
});
|
||||
},
|
||||
Some("Aspect Plane0 is not in the source texture format R8Unorm"),
|
||||
);
|
||||
}
|
||||
|
||||
/// Ensures that attempting to create a texture view from an invalid plane of a
|
||||
/// planar texture fails validation.
|
||||
#[test]
|
||||
fn planar_texture_view_plane_out_of_bounds() {
|
||||
let required_features = wgpu::Features::TEXTURE_FORMAT_NV12
|
||||
| wgpu::Features::TEXTURE_FORMAT_P010
|
||||
| wgpu::Features::TEXTURE_FORMAT_16BIT_NORM;
|
||||
let device_desc = wgpu::DeviceDescriptor {
|
||||
required_features,
|
||||
..Default::default()
|
||||
};
|
||||
let (device, _queue) = wgpu::Device::noop(&device_desc);
|
||||
let size = wgpu::Extent3d {
|
||||
width: 256,
|
||||
height: 256,
|
||||
depth_or_array_layers: 1,
|
||||
};
|
||||
|
||||
for (tex_format, view_format, view_aspect) in [
|
||||
(
|
||||
wgpu::TextureFormat::NV12,
|
||||
wgpu::TextureFormat::R8Unorm,
|
||||
wgpu::TextureAspect::Plane2,
|
||||
),
|
||||
(
|
||||
wgpu::TextureFormat::P010,
|
||||
wgpu::TextureFormat::R16Unorm,
|
||||
wgpu::TextureAspect::Plane2,
|
||||
),
|
||||
] {
|
||||
let tex = device.create_texture(&wgpu::TextureDescriptor {
|
||||
label: None,
|
||||
dimension: wgpu::TextureDimension::D2,
|
||||
size,
|
||||
format: tex_format,
|
||||
usage: wgpu::TextureUsages::TEXTURE_BINDING,
|
||||
mip_level_count: 1,
|
||||
sample_count: 1,
|
||||
view_formats: &[],
|
||||
});
|
||||
fail(
|
||||
&device,
|
||||
|| {
|
||||
let _ = tex.create_view(&wgpu::TextureViewDescriptor {
|
||||
format: Some(view_format),
|
||||
aspect: view_aspect,
|
||||
..Default::default()
|
||||
});
|
||||
},
|
||||
Some(&format!(
|
||||
"Aspect {view_aspect:?} is not in the source texture format {tex_format:?}"
|
||||
)),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// Ensures that attempting to create a texture view from a specific plane of a
|
||||
/// planar texture with an invalid format fails validation.
|
||||
#[test]
|
||||
fn planar_texture_view_plane_bad_format() {
|
||||
let required_features = wgpu::Features::TEXTURE_FORMAT_NV12
|
||||
| wgpu::Features::TEXTURE_FORMAT_P010
|
||||
| wgpu::Features::TEXTURE_FORMAT_16BIT_NORM;
|
||||
let device_desc = wgpu::DeviceDescriptor {
|
||||
required_features,
|
||||
..Default::default()
|
||||
};
|
||||
let (device, _queue) = wgpu::Device::noop(&device_desc);
|
||||
let size = wgpu::Extent3d {
|
||||
width: 256,
|
||||
height: 256,
|
||||
depth_or_array_layers: 1,
|
||||
};
|
||||
for (tex_format, view_format, view_aspect) in [
|
||||
(
|
||||
wgpu::TextureFormat::NV12,
|
||||
wgpu::TextureFormat::Rg8Unorm,
|
||||
wgpu::TextureAspect::Plane0,
|
||||
),
|
||||
(
|
||||
wgpu::TextureFormat::P010,
|
||||
wgpu::TextureFormat::Rg16Unorm,
|
||||
wgpu::TextureAspect::Plane0,
|
||||
),
|
||||
] {
|
||||
let tex = device.create_texture(&wgpu::TextureDescriptor {
|
||||
label: None,
|
||||
dimension: wgpu::TextureDimension::D2,
|
||||
size,
|
||||
format: tex_format,
|
||||
usage: wgpu::TextureUsages::TEXTURE_BINDING,
|
||||
mip_level_count: 1,
|
||||
sample_count: 1,
|
||||
view_formats: &[],
|
||||
});
|
||||
fail(
|
||||
&device,
|
||||
|| {
|
||||
let _ = tex.create_view(&wgpu::TextureViewDescriptor {
|
||||
format: Some(view_format),
|
||||
aspect: view_aspect,
|
||||
..Default::default()
|
||||
});
|
||||
},
|
||||
Some(&format!(
|
||||
"unable to view texture {tex_format:?} as {view_format:?}"
|
||||
)),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// Ensures that attempting to create a planar texture with an invalid size
|
||||
/// fails validation.
|
||||
#[test]
|
||||
fn planar_texture_bad_size() {
|
||||
let required_features =
|
||||
wgpu::Features::TEXTURE_FORMAT_NV12 | wgpu::Features::TEXTURE_FORMAT_P010;
|
||||
let device_desc = wgpu::DeviceDescriptor {
|
||||
required_features,
|
||||
..Default::default()
|
||||
};
|
||||
let (device, _queue) = wgpu::Device::noop(&device_desc);
|
||||
let size = wgpu::Extent3d {
|
||||
width: 255,
|
||||
height: 255,
|
||||
depth_or_array_layers: 1,
|
||||
};
|
||||
for format in [wgpu::TextureFormat::NV12, wgpu::TextureFormat::P010] {
|
||||
fail(
|
||||
&device,
|
||||
|| {
|
||||
let _ = device.create_texture(&wgpu::TextureDescriptor {
|
||||
label: None,
|
||||
dimension: wgpu::TextureDimension::D2,
|
||||
size,
|
||||
format,
|
||||
usage: wgpu::TextureUsages::TEXTURE_BINDING,
|
||||
mip_level_count: 1,
|
||||
sample_count: 1,
|
||||
view_formats: &[],
|
||||
});
|
||||
},
|
||||
Some(&format!(
|
||||
"width {} is not a multiple of {format:?}'s width multiple requirement",
|
||||
size.width
|
||||
)),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -373,8 +373,10 @@ fn clear_texture_via_buffer_copies(
|
||||
) {
|
||||
assert!(!texture_desc.format.is_depth_stencil_format());
|
||||
|
||||
if texture_desc.format == wgt::TextureFormat::NV12 {
|
||||
// TODO: Currently COPY_DST for NV12 textures is unsupported.
|
||||
if texture_desc.format == wgt::TextureFormat::NV12
|
||||
|| texture_desc.format == wgt::TextureFormat::P010
|
||||
{
|
||||
// TODO: Currently COPY_DST for NV12 and P010 textures is unsupported.
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@ -817,6 +817,7 @@ impl NumericType {
|
||||
panic!("Unexpected depth format")
|
||||
}
|
||||
Tf::NV12 => panic!("Unexpected nv12 format"),
|
||||
Tf::P010 => panic!("Unexpected p010 format"),
|
||||
Tf::Rgb9e5Ufloat => (NumericDimension::Vector(Vs::Tri), Scalar::F32),
|
||||
Tf::Bc1RgbaUnorm
|
||||
| Tf::Bc1RgbaUnormSrgb
|
||||
|
||||
@ -68,6 +68,7 @@ pub fn map_texture_format_failable(
|
||||
Tf::Depth32Float => DXGI_FORMAT_D32_FLOAT,
|
||||
Tf::Depth32FloatStencil8 => DXGI_FORMAT_D32_FLOAT_S8X24_UINT,
|
||||
Tf::NV12 => DXGI_FORMAT_NV12,
|
||||
Tf::P010 => DXGI_FORMAT_P010,
|
||||
Tf::Bc1RgbaUnorm => DXGI_FORMAT_BC1_UNORM,
|
||||
Tf::Bc1RgbaUnormSrgb => DXGI_FORMAT_BC1_UNORM_SRGB,
|
||||
Tf::Bc2RgbaUnorm => DXGI_FORMAT_BC2_UNORM,
|
||||
|
||||
@ -414,6 +414,35 @@ impl super::Adapter {
|
||||
bgra8unorm_storage_supported,
|
||||
);
|
||||
|
||||
let p010_format_supported = {
|
||||
let mut p010_info = Direct3D12::D3D12_FEATURE_DATA_FORMAT_SUPPORT {
|
||||
Format: Dxgi::Common::DXGI_FORMAT_P010,
|
||||
..Default::default()
|
||||
};
|
||||
let hr = unsafe {
|
||||
device.CheckFeatureSupport(
|
||||
Direct3D12::D3D12_FEATURE_FORMAT_SUPPORT,
|
||||
<*mut _>::cast(&mut p010_info),
|
||||
size_of_val(&p010_info) as u32,
|
||||
)
|
||||
};
|
||||
if hr.is_ok() {
|
||||
let supports_texture2d = p010_info
|
||||
.Support1
|
||||
.contains(Direct3D12::D3D12_FORMAT_SUPPORT1_TEXTURE2D);
|
||||
let supports_shader_load = p010_info
|
||||
.Support1
|
||||
.contains(Direct3D12::D3D12_FORMAT_SUPPORT1_SHADER_LOAD);
|
||||
let supports_shader_sample = p010_info
|
||||
.Support1
|
||||
.contains(Direct3D12::D3D12_FORMAT_SUPPORT1_SHADER_SAMPLE);
|
||||
supports_texture2d && supports_shader_load && supports_shader_sample
|
||||
} else {
|
||||
false
|
||||
}
|
||||
};
|
||||
features.set(wgt::Features::TEXTURE_FORMAT_P010, p010_format_supported);
|
||||
|
||||
let mut features1 = Direct3D12::D3D12_FEATURE_DATA_D3D12_OPTIONS1::default();
|
||||
let hr = unsafe {
|
||||
device.CheckFeatureSupport(
|
||||
|
||||
@ -1165,6 +1165,7 @@ impl crate::Adapter for super::Adapter {
|
||||
| Tf::Depth24Plus
|
||||
| Tf::Depth24PlusStencil8 => depth,
|
||||
Tf::NV12 => empty,
|
||||
Tf::P010 => empty,
|
||||
Tf::Rgb9e5Ufloat => filterable,
|
||||
Tf::Bc1RgbaUnorm
|
||||
| Tf::Bc1RgbaUnormSrgb
|
||||
|
||||
@ -89,6 +89,7 @@ impl super::AdapterShared {
|
||||
glow::UNSIGNED_INT_24_8,
|
||||
),
|
||||
Tf::NV12 => unreachable!(),
|
||||
Tf::P010 => unreachable!(),
|
||||
Tf::Rgb9e5Ufloat => (glow::RGB9_E5, glow::RGB, glow::UNSIGNED_INT_5_9_9_9_REV),
|
||||
Tf::Bc1RgbaUnorm => (glow::COMPRESSED_RGBA_S3TC_DXT1_EXT, glow::RGBA, 0),
|
||||
Tf::Bc1RgbaUnormSrgb => (glow::COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT, glow::RGBA, 0),
|
||||
|
||||
@ -1734,7 +1734,7 @@ impl From<wgt::TextureFormat> for FormatAspects {
|
||||
wgt::TextureFormat::Depth32FloatStencil8 | wgt::TextureFormat::Depth24PlusStencil8 => {
|
||||
Self::DEPTH_STENCIL
|
||||
}
|
||||
wgt::TextureFormat::NV12 => Self::PLANE_0 | Self::PLANE_1,
|
||||
wgt::TextureFormat::NV12 | wgt::TextureFormat::P010 => Self::PLANE_0 | Self::PLANE_1,
|
||||
_ => Self::COLOR,
|
||||
}
|
||||
}
|
||||
|
||||
@ -290,6 +290,7 @@ impl crate::Adapter for super::Adapter {
|
||||
flags
|
||||
}
|
||||
Tf::NV12 => return Tfc::empty(),
|
||||
Tf::P010 => return Tfc::empty(),
|
||||
Tf::Rgb9e5Ufloat => {
|
||||
if pc.msaa_apple3 {
|
||||
all_caps
|
||||
@ -1175,6 +1176,7 @@ impl super::PrivateCapabilities {
|
||||
}
|
||||
}
|
||||
Tf::NV12 => unreachable!(),
|
||||
Tf::P010 => unreachable!(),
|
||||
Tf::Rgb9e5Ufloat => MTL::RGB9E5Float,
|
||||
Tf::Bc1RgbaUnorm => MTL::BC1_RGBA,
|
||||
Tf::Bc1RgbaUnormSrgb => MTL::BC1_RGBA_sRGB,
|
||||
|
||||
@ -850,6 +850,24 @@ impl PhysicalDeviceFeatures {
|
||||
);
|
||||
}
|
||||
|
||||
if let Some(ref _sampler_ycbcr_conversion) = self.sampler_ycbcr_conversion {
|
||||
features.set(
|
||||
F::TEXTURE_FORMAT_P010,
|
||||
supports_format(
|
||||
instance,
|
||||
phd,
|
||||
vk::Format::G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16,
|
||||
vk::ImageTiling::OPTIMAL,
|
||||
vk::FormatFeatureFlags::SAMPLED_IMAGE
|
||||
| vk::FormatFeatureFlags::TRANSFER_SRC
|
||||
| vk::FormatFeatureFlags::TRANSFER_DST,
|
||||
) && !caps
|
||||
.driver
|
||||
.map(|driver| driver.driver_id == vk::DriverId::MOLTENVK)
|
||||
.unwrap_or_default(),
|
||||
);
|
||||
}
|
||||
|
||||
features.set(
|
||||
F::VULKAN_GOOGLE_DISPLAY_TIMING,
|
||||
caps.supports_extension(google::display_timing::NAME),
|
||||
|
||||
@ -78,6 +78,7 @@ impl super::PrivateCapabilities {
|
||||
}
|
||||
Tf::Depth16Unorm => F::D16_UNORM,
|
||||
Tf::NV12 => F::G8_B8R8_2PLANE_420_UNORM,
|
||||
Tf::P010 => F::G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16,
|
||||
Tf::Rgb9e5Ufloat => F::E5B9G9R9_UFLOAT_PACK32,
|
||||
Tf::Bc1RgbaUnorm => F::BC1_RGBA_UNORM_BLOCK,
|
||||
Tf::Bc1RgbaUnormSrgb => F::BC1_RGBA_SRGB_BLOCK,
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
// Lets keep these on one line
|
||||
#[rustfmt::skip]
|
||||
pub const TEXTURE_FORMAT_LIST: [wgpu::TextureFormat; 117] = [
|
||||
pub const TEXTURE_FORMAT_LIST: [wgpu::TextureFormat; 118] = [
|
||||
wgpu::TextureFormat::R8Unorm,
|
||||
wgpu::TextureFormat::R8Snorm,
|
||||
wgpu::TextureFormat::R8Uint,
|
||||
@ -52,6 +52,7 @@ pub const TEXTURE_FORMAT_LIST: [wgpu::TextureFormat; 117] = [
|
||||
wgpu::TextureFormat::Depth32Float,
|
||||
wgpu::TextureFormat::Depth32FloatStencil8,
|
||||
wgpu::TextureFormat::NV12,
|
||||
wgpu::TextureFormat::P010,
|
||||
wgpu::TextureFormat::Bc1RgbaUnorm,
|
||||
wgpu::TextureFormat::Bc1RgbaUnormSrgb,
|
||||
wgpu::TextureFormat::Bc2RgbaUnorm,
|
||||
|
||||
@ -984,6 +984,16 @@ bitflags_array! {
|
||||
///
|
||||
/// [`TextureFormat::NV12`]: super::TextureFormat::NV12
|
||||
const TEXTURE_FORMAT_NV12 = 1 << 29;
|
||||
/// Allows for creation of textures of format [`TextureFormat::P010`]
|
||||
///
|
||||
/// Supported platforms:
|
||||
/// - DX12
|
||||
/// - Vulkan
|
||||
///
|
||||
/// This is a native only feature.
|
||||
///
|
||||
/// [`TextureFormat::P010`]: super::TextureFormat::P010
|
||||
const TEXTURE_FORMAT_P010 = 1 << 30;
|
||||
|
||||
/// Allows for the creation and usage of `ExternalTexture`s, and bind
|
||||
/// group layouts containing external texture `BindingType`s.
|
||||
@ -998,7 +1008,7 @@ bitflags_array! {
|
||||
///
|
||||
/// Supported platforms:
|
||||
/// - DX12
|
||||
const EXTERNAL_TEXTURE = 1 << 30;
|
||||
const EXTERNAL_TEXTURE = 1 << 31;
|
||||
|
||||
// Shader:
|
||||
|
||||
@ -1012,7 +1022,7 @@ bitflags_array! {
|
||||
/// - Vulkan
|
||||
///
|
||||
/// This is a native-only feature.
|
||||
const EXPERIMENTAL_RAY_QUERY = 1 << 31;
|
||||
const EXPERIMENTAL_RAY_QUERY = 1 << 32;
|
||||
/// Enables 64-bit floating point types in SPIR-V shaders.
|
||||
///
|
||||
/// Note: even when supported by GPU hardware, 64-bit floating point operations are
|
||||
@ -1022,14 +1032,14 @@ bitflags_array! {
|
||||
/// - Vulkan
|
||||
///
|
||||
/// This is a native only feature.
|
||||
const SHADER_F64 = 1 << 32;
|
||||
const SHADER_F64 = 1 << 33;
|
||||
/// Allows shaders to use i16. Not currently supported in `naga`, only available through `spirv-passthrough`.
|
||||
///
|
||||
/// Supported platforms:
|
||||
/// - Vulkan
|
||||
///
|
||||
/// This is a native only feature.
|
||||
const SHADER_I16 = 1 << 33;
|
||||
const SHADER_I16 = 1 << 34;
|
||||
/// Enables `builtin(primitive_index)` in fragment shaders.
|
||||
///
|
||||
/// Note: enables geometry processing for pipelines using the builtin.
|
||||
@ -1043,7 +1053,7 @@ bitflags_array! {
|
||||
/// - OpenGL (some)
|
||||
///
|
||||
/// This is a native only feature.
|
||||
const SHADER_PRIMITIVE_INDEX = 1 << 34;
|
||||
const SHADER_PRIMITIVE_INDEX = 1 << 35;
|
||||
/// Allows shaders to use the `early_depth_test` attribute.
|
||||
///
|
||||
/// The attribute is applied to the fragment shader entry point. It can be used in two
|
||||
@ -1071,7 +1081,7 @@ bitflags_array! {
|
||||
/// This is a native only feature.
|
||||
///
|
||||
/// [`EarlyDepthTest`]: https://docs.rs/naga/latest/naga/ir/enum.EarlyDepthTest.html
|
||||
const SHADER_EARLY_DEPTH_TEST = 1 << 35;
|
||||
const SHADER_EARLY_DEPTH_TEST = 1 << 36;
|
||||
/// Allows shaders to use i64 and u64.
|
||||
///
|
||||
/// Supported platforms:
|
||||
@ -1080,7 +1090,7 @@ bitflags_array! {
|
||||
/// - Metal (with MSL 2.3+)
|
||||
///
|
||||
/// This is a native only feature.
|
||||
const SHADER_INT64 = 1 << 36;
|
||||
const SHADER_INT64 = 1 << 37;
|
||||
/// Allows compute and fragment shaders to use the subgroup operation built-ins
|
||||
///
|
||||
/// Supported Platforms:
|
||||
@ -1089,14 +1099,14 @@ bitflags_array! {
|
||||
/// - Metal
|
||||
///
|
||||
/// This is a native only feature.
|
||||
const SUBGROUP = 1 << 37;
|
||||
const SUBGROUP = 1 << 38;
|
||||
/// Allows vertex shaders to use the subgroup operation built-ins
|
||||
///
|
||||
/// Supported Platforms:
|
||||
/// - Vulkan
|
||||
///
|
||||
/// This is a native only feature.
|
||||
const SUBGROUP_VERTEX = 1 << 38;
|
||||
const SUBGROUP_VERTEX = 1 << 39;
|
||||
/// Allows shaders to use the subgroup barrier
|
||||
///
|
||||
/// Supported Platforms:
|
||||
@ -1104,7 +1114,7 @@ bitflags_array! {
|
||||
/// - Metal
|
||||
///
|
||||
/// This is a native only feature.
|
||||
const SUBGROUP_BARRIER = 1 << 39;
|
||||
const SUBGROUP_BARRIER = 1 << 40;
|
||||
/// Allows the use of pipeline cache objects
|
||||
///
|
||||
/// Supported platforms:
|
||||
@ -1113,7 +1123,7 @@ bitflags_array! {
|
||||
/// Unimplemented Platforms:
|
||||
/// - DX12
|
||||
/// - Metal
|
||||
const PIPELINE_CACHE = 1 << 40;
|
||||
const PIPELINE_CACHE = 1 << 41;
|
||||
/// Allows shaders to use i64 and u64 atomic min and max.
|
||||
///
|
||||
/// Supported platforms:
|
||||
@ -1122,7 +1132,7 @@ bitflags_array! {
|
||||
/// - Metal (with MSL 2.4+)
|
||||
///
|
||||
/// This is a native only feature.
|
||||
const SHADER_INT64_ATOMIC_MIN_MAX = 1 << 41;
|
||||
const SHADER_INT64_ATOMIC_MIN_MAX = 1 << 42;
|
||||
/// Allows shaders to use all i64 and u64 atomic operations.
|
||||
///
|
||||
/// Supported platforms:
|
||||
@ -1130,7 +1140,7 @@ bitflags_array! {
|
||||
/// - DX12 (with SM 6.6+)
|
||||
///
|
||||
/// This is a native only feature.
|
||||
const SHADER_INT64_ATOMIC_ALL_OPS = 1 << 42;
|
||||
const SHADER_INT64_ATOMIC_ALL_OPS = 1 << 43;
|
||||
/// Allows using the [VK_GOOGLE_display_timing] Vulkan extension.
|
||||
///
|
||||
/// This is used for frame pacing to reduce latency, and is generally only available on Android.
|
||||
@ -1146,7 +1156,7 @@ bitflags_array! {
|
||||
///
|
||||
/// [VK_GOOGLE_display_timing]: https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VK_GOOGLE_display_timing.html
|
||||
/// [`Surface::as_hal()`]: https://docs.rs/wgpu/latest/wgpu/struct.Surface.html#method.as_hal
|
||||
const VULKAN_GOOGLE_DISPLAY_TIMING = 1 << 43;
|
||||
const VULKAN_GOOGLE_DISPLAY_TIMING = 1 << 44;
|
||||
|
||||
/// Allows using the [VK_KHR_external_memory_win32] Vulkan extension.
|
||||
///
|
||||
@ -1156,7 +1166,7 @@ bitflags_array! {
|
||||
/// This is a native only feature.
|
||||
///
|
||||
/// [VK_KHR_external_memory_win32]: https://registry.khronos.org/vulkan/specs/latest/man/html/VK_KHR_external_memory_win32.html
|
||||
const VULKAN_EXTERNAL_MEMORY_WIN32 = 1 << 44;
|
||||
const VULKAN_EXTERNAL_MEMORY_WIN32 = 1 << 45;
|
||||
|
||||
/// Enables R64Uint image atomic min and max.
|
||||
///
|
||||
@ -1166,7 +1176,7 @@ bitflags_array! {
|
||||
/// - Metal (with MSL 3.1+)
|
||||
///
|
||||
/// This is a native only feature.
|
||||
const TEXTURE_INT64_ATOMIC = 1 << 45;
|
||||
const TEXTURE_INT64_ATOMIC = 1 << 46;
|
||||
|
||||
/// Allows uniform buffers to be bound as binding arrays.
|
||||
///
|
||||
@ -1183,7 +1193,7 @@ bitflags_array! {
|
||||
/// - Vulkan 1.2+ (or VK_EXT_descriptor_indexing)'s `shaderUniformBufferArrayNonUniformIndexing` feature)
|
||||
///
|
||||
/// This is a native only feature.
|
||||
const UNIFORM_BUFFER_BINDING_ARRAYS = 1 << 46;
|
||||
const UNIFORM_BUFFER_BINDING_ARRAYS = 1 << 47;
|
||||
|
||||
/// Enables mesh shaders and task shaders in mesh shader pipelines.
|
||||
///
|
||||
@ -1195,7 +1205,7 @@ bitflags_array! {
|
||||
/// - Metal
|
||||
///
|
||||
/// This is a native only feature.
|
||||
const EXPERIMENTAL_MESH_SHADER = 1 << 47;
|
||||
const EXPERIMENTAL_MESH_SHADER = 1 << 48;
|
||||
|
||||
/// ***THIS IS EXPERIMENTAL:*** Features enabled by this may have
|
||||
/// major bugs in them and are expected to be subject to breaking changes, suggestions
|
||||
@ -1210,7 +1220,7 @@ bitflags_array! {
|
||||
/// This is a native only feature
|
||||
///
|
||||
/// [`AccelerationStructureFlags::ALLOW_RAY_HIT_VERTEX_RETURN`]: super::AccelerationStructureFlags::ALLOW_RAY_HIT_VERTEX_RETURN
|
||||
const EXPERIMENTAL_RAY_HIT_VERTEX_RETURN = 1 << 48;
|
||||
const EXPERIMENTAL_RAY_HIT_VERTEX_RETURN = 1 << 49;
|
||||
|
||||
/// Enables multiview in mesh shader pipelines
|
||||
///
|
||||
@ -1222,7 +1232,7 @@ bitflags_array! {
|
||||
/// - Metal
|
||||
///
|
||||
/// This is a native only feature.
|
||||
const EXPERIMENTAL_MESH_SHADER_MULTIVIEW = 1 << 49;
|
||||
const EXPERIMENTAL_MESH_SHADER_MULTIVIEW = 1 << 50;
|
||||
|
||||
/// Allows usage of additional vertex formats in [BlasTriangleGeometrySizeDescriptor::vertex_format]
|
||||
///
|
||||
@ -1231,7 +1241,7 @@ bitflags_array! {
|
||||
/// - DX12
|
||||
///
|
||||
/// [BlasTriangleGeometrySizeDescriptor::vertex_format]: super::BlasTriangleGeometrySizeDescriptor
|
||||
const EXTENDED_ACCELERATION_STRUCTURE_VERTEX_FORMATS = 1 << 50;
|
||||
const EXTENDED_ACCELERATION_STRUCTURE_VERTEX_FORMATS = 1 << 51;
|
||||
|
||||
/// Enables creating shader modules from DirectX HLSL or DXIL shaders (unsafe)
|
||||
///
|
||||
@ -1241,7 +1251,7 @@ bitflags_array! {
|
||||
/// - DX12
|
||||
///
|
||||
/// This is a native only feature.
|
||||
const HLSL_DXIL_SHADER_PASSTHROUGH = 1 << 51;
|
||||
const HLSL_DXIL_SHADER_PASSTHROUGH = 1 << 52;
|
||||
}
|
||||
|
||||
/// Features that are not guaranteed to be supported.
|
||||
|
||||
@ -2230,6 +2230,23 @@ pub enum TextureFormat {
|
||||
/// [`Features::TEXTURE_FORMAT_NV12`] must be enabled to use this texture format.
|
||||
NV12,
|
||||
|
||||
/// YUV 4:2:0 chroma subsampled format.
|
||||
///
|
||||
/// Contains two planes:
|
||||
/// - 0: Single 16 bit channel luminance, of which only the high 10 bits
|
||||
/// are used.
|
||||
/// - 1: Dual 16 bit channel chrominance at half width and half height, of
|
||||
/// which only the high 10 bits are used.
|
||||
///
|
||||
/// Valid view formats for luminance are [`TextureFormat::R16Unorm`].
|
||||
///
|
||||
/// Valid view formats for chrominance are [`TextureFormat::Rg16Unorm`].
|
||||
///
|
||||
/// Width and height must be even.
|
||||
///
|
||||
/// [`Features::TEXTURE_FORMAT_P010`] must be enabled to use this texture format.
|
||||
P010,
|
||||
|
||||
// Compressed textures usable with `TEXTURE_COMPRESSION_BC` feature. `TEXTURE_COMPRESSION_SLICED_3D` is required to use with 3D textures.
|
||||
/// 4x4 block compressed texture. 8 bytes per block (4 bit/px). 4 color + alpha pallet. 5 bit R + 6 bit G + 5 bit B + 1 bit alpha.
|
||||
/// [0, 63] ([0, 1] for alpha) converted to/from float [0, 1] in shader.
|
||||
@ -2475,6 +2492,7 @@ impl<'de> Deserialize<'de> for TextureFormat {
|
||||
"depth24plus" => TextureFormat::Depth24Plus,
|
||||
"depth24plus-stencil8" => TextureFormat::Depth24PlusStencil8,
|
||||
"nv12" => TextureFormat::NV12,
|
||||
"p010" => TextureFormat::P010,
|
||||
"rgb9e5ufloat" => TextureFormat::Rgb9e5Ufloat,
|
||||
"bc1-rgba-unorm" => TextureFormat::Bc1RgbaUnorm,
|
||||
"bc1-rgba-unorm-srgb" => TextureFormat::Bc1RgbaUnormSrgb,
|
||||
@ -2604,6 +2622,7 @@ impl Serialize for TextureFormat {
|
||||
TextureFormat::Depth24Plus => "depth24plus",
|
||||
TextureFormat::Depth24PlusStencil8 => "depth24plus-stencil8",
|
||||
TextureFormat::NV12 => "nv12",
|
||||
TextureFormat::P010 => "p010",
|
||||
TextureFormat::Rgb9e5Ufloat => "rgb9e5ufloat",
|
||||
TextureFormat::Bc1RgbaUnorm => "bc1-rgba-unorm",
|
||||
TextureFormat::Bc1RgbaUnormSrgb => "bc1-rgba-unorm-srgb",
|
||||
@ -2696,6 +2715,8 @@ impl TextureFormat {
|
||||
(Self::Depth32FloatStencil8, TextureAspect::DepthOnly) => Some(Self::Depth32Float),
|
||||
(Self::NV12, TextureAspect::Plane0) => Some(Self::R8Unorm),
|
||||
(Self::NV12, TextureAspect::Plane1) => Some(Self::Rg8Unorm),
|
||||
(Self::P010, TextureAspect::Plane0) => Some(Self::R16Unorm),
|
||||
(Self::P010, TextureAspect::Plane1) => Some(Self::Rg16Unorm),
|
||||
// views to multi-planar formats must specify the plane
|
||||
(format, TextureAspect::All) if !format.is_multi_planar_format() => Some(format),
|
||||
_ => None,
|
||||
@ -2751,6 +2772,7 @@ impl TextureFormat {
|
||||
pub fn planes(&self) -> Option<u32> {
|
||||
match *self {
|
||||
Self::NV12 => Some(2),
|
||||
Self::P010 => Some(2),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
@ -2788,6 +2810,7 @@ impl TextureFormat {
|
||||
pub fn size_multiple_requirement(&self) -> (u32, u32) {
|
||||
match *self {
|
||||
Self::NV12 => (2, 2),
|
||||
Self::P010 => (2, 2),
|
||||
_ => self.block_dimensions(),
|
||||
}
|
||||
}
|
||||
@ -2848,7 +2871,8 @@ impl TextureFormat {
|
||||
| Self::Depth24PlusStencil8
|
||||
| Self::Depth32Float
|
||||
| Self::Depth32FloatStencil8
|
||||
| Self::NV12 => (1, 1),
|
||||
| Self::NV12
|
||||
| Self::P010 => (1, 1),
|
||||
|
||||
Self::Bc1RgbaUnorm
|
||||
| Self::Bc1RgbaUnormSrgb
|
||||
@ -2966,6 +2990,7 @@ impl TextureFormat {
|
||||
Self::Depth32FloatStencil8 => Features::DEPTH32FLOAT_STENCIL8,
|
||||
|
||||
Self::NV12 => Features::TEXTURE_FORMAT_NV12,
|
||||
Self::P010 => Features::TEXTURE_FORMAT_P010,
|
||||
|
||||
Self::R16Unorm
|
||||
| Self::R16Snorm
|
||||
@ -3099,8 +3124,10 @@ impl TextureFormat {
|
||||
Self::Depth32Float => ( msaa, attachment),
|
||||
Self::Depth32FloatStencil8 => ( msaa, attachment),
|
||||
|
||||
// We only support sampling nv12 textures until we implement transfer plane data.
|
||||
// We only support sampling nv12 and p010 textures until we
|
||||
// implement transfer plane data.
|
||||
Self::NV12 => ( none, binding),
|
||||
Self::P010 => ( none, binding),
|
||||
|
||||
Self::R16Unorm => ( msaa | s_ro_wo, storage),
|
||||
Self::R16Snorm => ( msaa | s_ro_wo, storage),
|
||||
@ -3230,7 +3257,7 @@ impl TextureFormat {
|
||||
_ => None,
|
||||
},
|
||||
|
||||
Self::NV12 => match aspect {
|
||||
Self::NV12 | Self::P010 => match aspect {
|
||||
Some(TextureAspect::Plane0) | Some(TextureAspect::Plane1) => {
|
||||
Some(unfilterable_float)
|
||||
}
|
||||
@ -3363,6 +3390,12 @@ impl TextureFormat {
|
||||
_ => None,
|
||||
},
|
||||
|
||||
Self::P010 => match aspect {
|
||||
Some(TextureAspect::Plane0) => Some(2),
|
||||
Some(TextureAspect::Plane1) => Some(4),
|
||||
_ => None,
|
||||
},
|
||||
|
||||
Self::Bc1RgbaUnorm | Self::Bc1RgbaUnormSrgb | Self::Bc4RUnorm | Self::Bc4RSnorm => {
|
||||
Some(8)
|
||||
}
|
||||
@ -3448,6 +3481,7 @@ impl TextureFormat {
|
||||
| Self::Depth32Float
|
||||
| Self::Depth32FloatStencil8
|
||||
| Self::NV12
|
||||
| Self::P010
|
||||
| Self::Rgb9e5Ufloat
|
||||
| Self::Bc1RgbaUnorm
|
||||
| Self::Bc1RgbaUnormSrgb
|
||||
@ -3531,6 +3565,7 @@ impl TextureFormat {
|
||||
| Self::Depth32Float
|
||||
| Self::Depth32FloatStencil8
|
||||
| Self::NV12
|
||||
| Self::P010
|
||||
| Self::Rgb9e5Ufloat
|
||||
| Self::Bc1RgbaUnorm
|
||||
| Self::Bc1RgbaUnormSrgb
|
||||
@ -3625,7 +3660,7 @@ impl TextureFormat {
|
||||
_ => 2,
|
||||
},
|
||||
|
||||
Self::NV12 => match aspect {
|
||||
Self::NV12 | Self::P010 => match aspect {
|
||||
TextureAspect::Plane0 => 1,
|
||||
TextureAspect::Plane1 => 2,
|
||||
_ => 3,
|
||||
@ -3735,6 +3770,8 @@ impl TextureFormat {
|
||||
Self::Stencil8 => 1,
|
||||
// Two chroma bytes per block, one luma byte per block
|
||||
Self::NV12 => 3,
|
||||
// Two chroma u16s and one luma u16 per block
|
||||
Self::P010 => 6,
|
||||
f => {
|
||||
log::warn!("Memory footprint for format {f:?} is not implemented");
|
||||
0
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user