Files
wgpu/tests/gpu-tests/clear_texture.rs
2025-02-23 14:06:34 -05:00

431 lines
14 KiB
Rust

use wgpu_test::{
gpu_test, image::ReadbackBuffers, FailureCase, GpuTestConfiguration, TestParameters,
TestingContext,
};
static TEXTURE_FORMATS_UNCOMPRESSED_GLES_COMPAT: &[wgpu::TextureFormat] = &[
wgpu::TextureFormat::R8Unorm,
wgpu::TextureFormat::R8Snorm,
wgpu::TextureFormat::R8Uint,
wgpu::TextureFormat::R8Sint,
wgpu::TextureFormat::R16Uint,
wgpu::TextureFormat::R16Sint,
wgpu::TextureFormat::R16Float,
wgpu::TextureFormat::R32Uint,
wgpu::TextureFormat::R32Sint,
wgpu::TextureFormat::R32Float,
wgpu::TextureFormat::Rg16Uint,
wgpu::TextureFormat::Rg16Sint,
wgpu::TextureFormat::Rg16Float,
wgpu::TextureFormat::Rgba8Unorm,
wgpu::TextureFormat::Rgba8UnormSrgb,
wgpu::TextureFormat::Rgba8Snorm,
wgpu::TextureFormat::Rgba8Uint,
wgpu::TextureFormat::Rgba8Sint,
wgpu::TextureFormat::Bgra8Unorm,
wgpu::TextureFormat::Bgra8UnormSrgb,
wgpu::TextureFormat::Rgb10a2Uint,
wgpu::TextureFormat::Rgb10a2Unorm,
wgpu::TextureFormat::Rg11b10Ufloat,
wgpu::TextureFormat::Rg32Uint,
wgpu::TextureFormat::Rg32Sint,
wgpu::TextureFormat::Rg32Float,
wgpu::TextureFormat::Rgba16Uint,
wgpu::TextureFormat::Rgba16Sint,
wgpu::TextureFormat::Rgba16Float,
wgpu::TextureFormat::Rgba32Uint,
wgpu::TextureFormat::Rgba32Sint,
wgpu::TextureFormat::Rgba32Float,
];
static TEXTURE_FORMATS_UNCOMPRESSED: &[wgpu::TextureFormat] = &[
wgpu::TextureFormat::Rg8Unorm,
wgpu::TextureFormat::Rg8Snorm,
wgpu::TextureFormat::Rg8Uint,
wgpu::TextureFormat::Rg8Sint,
wgpu::TextureFormat::Rgb9e5Ufloat,
];
static TEXTURE_FORMATS_DEPTH: &[wgpu::TextureFormat] = &[
wgpu::TextureFormat::Stencil8,
wgpu::TextureFormat::Depth16Unorm,
wgpu::TextureFormat::Depth24Plus,
wgpu::TextureFormat::Depth24PlusStencil8,
wgpu::TextureFormat::Depth32Float,
];
// needs TEXTURE_COMPRESSION_BC
static TEXTURE_FORMATS_BC: &[wgpu::TextureFormat] = &[
wgpu::TextureFormat::Bc1RgbaUnorm,
wgpu::TextureFormat::Bc1RgbaUnormSrgb,
wgpu::TextureFormat::Bc2RgbaUnorm,
wgpu::TextureFormat::Bc2RgbaUnormSrgb,
wgpu::TextureFormat::Bc3RgbaUnorm,
wgpu::TextureFormat::Bc3RgbaUnormSrgb,
wgpu::TextureFormat::Bc4RUnorm,
wgpu::TextureFormat::Bc4RSnorm,
wgpu::TextureFormat::Bc5RgUnorm,
wgpu::TextureFormat::Bc5RgSnorm,
wgpu::TextureFormat::Bc6hRgbUfloat,
wgpu::TextureFormat::Bc6hRgbFloat,
wgpu::TextureFormat::Bc7RgbaUnorm,
wgpu::TextureFormat::Bc7RgbaUnormSrgb,
];
// needs TEXTURE_COMPRESSION_ETC2
static TEXTURE_FORMATS_ETC2: &[wgpu::TextureFormat] = &[
wgpu::TextureFormat::Etc2Rgb8Unorm,
wgpu::TextureFormat::Etc2Rgb8UnormSrgb,
wgpu::TextureFormat::Etc2Rgb8A1Unorm,
wgpu::TextureFormat::Etc2Rgb8A1UnormSrgb,
wgpu::TextureFormat::Etc2Rgba8Unorm,
wgpu::TextureFormat::Etc2Rgba8UnormSrgb,
wgpu::TextureFormat::EacR11Unorm,
wgpu::TextureFormat::EacR11Snorm,
wgpu::TextureFormat::EacRg11Unorm,
wgpu::TextureFormat::EacRg11Snorm,
];
// needs TEXTURE_COMPRESSION_ASTC
use wgpu::{AstcBlock, AstcChannel};
static TEXTURE_FORMATS_ASTC: &[wgpu::TextureFormat] = &[
wgpu::TextureFormat::Astc {
block: AstcBlock::B4x4,
channel: AstcChannel::Unorm,
},
wgpu::TextureFormat::Astc {
block: AstcBlock::B5x4,
channel: AstcChannel::Unorm,
},
wgpu::TextureFormat::Astc {
block: AstcBlock::B5x5,
channel: AstcChannel::Unorm,
},
wgpu::TextureFormat::Astc {
block: AstcBlock::B6x5,
channel: AstcChannel::Unorm,
},
wgpu::TextureFormat::Astc {
block: AstcBlock::B6x6,
channel: AstcChannel::Unorm,
},
wgpu::TextureFormat::Astc {
block: AstcBlock::B8x5,
channel: AstcChannel::Unorm,
},
wgpu::TextureFormat::Astc {
block: AstcBlock::B8x6,
channel: AstcChannel::Unorm,
},
wgpu::TextureFormat::Astc {
block: AstcBlock::B8x8,
channel: AstcChannel::Unorm,
},
wgpu::TextureFormat::Astc {
block: AstcBlock::B10x5,
channel: AstcChannel::Unorm,
},
wgpu::TextureFormat::Astc {
block: AstcBlock::B10x6,
channel: AstcChannel::Unorm,
},
wgpu::TextureFormat::Astc {
block: AstcBlock::B10x8,
channel: AstcChannel::Unorm,
},
wgpu::TextureFormat::Astc {
block: AstcBlock::B10x10,
channel: AstcChannel::Unorm,
},
wgpu::TextureFormat::Astc {
block: AstcBlock::B12x10,
channel: AstcChannel::Unorm,
},
wgpu::TextureFormat::Astc {
block: AstcBlock::B12x12,
channel: AstcChannel::Unorm,
},
wgpu::TextureFormat::Astc {
block: AstcBlock::B4x4,
channel: AstcChannel::UnormSrgb,
},
wgpu::TextureFormat::Astc {
block: AstcBlock::B5x4,
channel: AstcChannel::UnormSrgb,
},
wgpu::TextureFormat::Astc {
block: AstcBlock::B5x5,
channel: AstcChannel::UnormSrgb,
},
wgpu::TextureFormat::Astc {
block: AstcBlock::B6x5,
channel: AstcChannel::UnormSrgb,
},
wgpu::TextureFormat::Astc {
block: AstcBlock::B6x6,
channel: AstcChannel::UnormSrgb,
},
wgpu::TextureFormat::Astc {
block: AstcBlock::B8x5,
channel: AstcChannel::UnormSrgb,
},
wgpu::TextureFormat::Astc {
block: AstcBlock::B8x6,
channel: AstcChannel::UnormSrgb,
},
wgpu::TextureFormat::Astc {
block: AstcBlock::B8x8,
channel: AstcChannel::UnormSrgb,
},
wgpu::TextureFormat::Astc {
block: AstcBlock::B10x5,
channel: AstcChannel::UnormSrgb,
},
wgpu::TextureFormat::Astc {
block: AstcBlock::B10x6,
channel: AstcChannel::UnormSrgb,
},
wgpu::TextureFormat::Astc {
block: AstcBlock::B10x8,
channel: AstcChannel::UnormSrgb,
},
wgpu::TextureFormat::Astc {
block: AstcBlock::B10x10,
channel: AstcChannel::UnormSrgb,
},
wgpu::TextureFormat::Astc {
block: AstcBlock::B12x10,
channel: AstcChannel::UnormSrgb,
},
wgpu::TextureFormat::Astc {
block: AstcBlock::B12x12,
channel: AstcChannel::UnormSrgb,
},
];
async fn single_texture_clear_test(
ctx: &TestingContext,
format: wgpu::TextureFormat,
size: wgpu::Extent3d,
dimension: wgpu::TextureDimension,
) {
log::info!(
"clearing texture with {:?}, dimension {:?}, size {:?}",
format,
dimension,
size
);
let extra_usages = match format {
wgpu::TextureFormat::Depth24Plus | wgpu::TextureFormat::Depth24PlusStencil8 => {
wgpu::TextureUsages::TEXTURE_BINDING
}
_ => wgpu::TextureUsages::empty(),
};
let texture = ctx.device.create_texture(&wgpu::TextureDescriptor {
label: Some(&format!("texture {format:?}")),
size,
mip_level_count: if dimension == wgpu::TextureDimension::D1 {
1
} else {
// arbitrary value between 2 and max
3
},
sample_count: 1, // multisampling is not supported for clear
dimension,
format,
usage: wgpu::TextureUsages::COPY_SRC | extra_usages,
view_formats: &[],
});
let mut encoder = ctx
.device
.create_command_encoder(&wgpu::CommandEncoderDescriptor::default());
encoder.clear_texture(
&texture,
&wgpu::ImageSubresourceRange {
aspect: wgpu::TextureAspect::All,
base_mip_level: 0,
mip_level_count: None,
base_array_layer: 0,
array_layer_count: None,
},
);
let readback_buffers = ReadbackBuffers::new(&ctx.device, &texture);
readback_buffers.copy_from(&ctx.device, &mut encoder, &texture);
ctx.queue.submit([encoder.finish()]);
assert!(
readback_buffers.are_zero(ctx).await,
"texture with format {format:?} was not fully cleared"
);
}
async fn clear_texture_tests(ctx: TestingContext, formats: &'static [wgpu::TextureFormat]) {
for &format in formats {
let (block_width, block_height) = format.block_dimensions();
let rounded_width = block_width * wgpu::COPY_BYTES_PER_ROW_ALIGNMENT;
let rounded_height = block_height * wgpu::COPY_BYTES_PER_ROW_ALIGNMENT;
let is_compressed_or_depth_stencil_format =
format.is_compressed() || format.is_depth_stencil_format();
let supports_1d = !is_compressed_or_depth_stencil_format;
let supports_3d = format.is_bcn() || !is_compressed_or_depth_stencil_format;
// 1D texture
if supports_1d {
single_texture_clear_test(
&ctx,
format,
wgpu::Extent3d {
width: rounded_width,
height: 1,
depth_or_array_layers: 1,
},
wgpu::TextureDimension::D1,
)
.await;
}
// 2D texture
single_texture_clear_test(
&ctx,
format,
wgpu::Extent3d {
width: rounded_width,
height: rounded_height,
depth_or_array_layers: 1,
},
wgpu::TextureDimension::D2,
)
.await;
// 2D array texture
single_texture_clear_test(
&ctx,
format,
wgpu::Extent3d {
width: rounded_width,
height: rounded_height,
depth_or_array_layers: 4,
},
wgpu::TextureDimension::D2,
)
.await;
if supports_3d {
// volume texture
single_texture_clear_test(
&ctx,
format,
wgpu::Extent3d {
width: rounded_width,
height: rounded_height,
depth_or_array_layers: 16,
},
wgpu::TextureDimension::D3,
)
.await;
}
}
}
#[gpu_test]
static CLEAR_TEXTURE_UNCOMPRESSED_GLES: GpuTestConfiguration = GpuTestConfiguration::new()
.parameters(
TestParameters::default()
.features(wgpu::Features::CLEAR_TEXTURE)
.skip(FailureCase::webgl2()),
)
.run_async(|ctx| clear_texture_tests(ctx, TEXTURE_FORMATS_UNCOMPRESSED_GLES_COMPAT));
#[gpu_test]
static CLEAR_TEXTURE_UNCOMPRESSED: GpuTestConfiguration = GpuTestConfiguration::new()
.parameters(
TestParameters::default()
.expect_fail(
FailureCase::backend(wgpu::Backends::GL)
.panic("texture with format Rg8Snorm was not fully cleared")
.panic("texture with format Rgb9e5Ufloat was not fully cleared")
.validation_error("GL_INVALID_FRAMEBUFFER_OPERATION")
.validation_error("GL_INVALID_OPERATION"),
)
.features(wgpu::Features::CLEAR_TEXTURE),
)
.run_async(|ctx| clear_texture_tests(ctx, TEXTURE_FORMATS_UNCOMPRESSED));
#[gpu_test]
static CLEAR_TEXTURE_DEPTH: GpuTestConfiguration = GpuTestConfiguration::new()
.parameters(
TestParameters::default()
.downlevel_flags(
wgpu::DownlevelFlags::DEPTH_TEXTURE_AND_BUFFER_COPIES
| wgpu::DownlevelFlags::COMPUTE_SHADERS,
)
// https://github.com/gfx-rs/wgpu/issues/5016
.skip(FailureCase::adapter("Apple Paravirtual device"))
.skip(FailureCase::webgl2())
.limits(wgpu::Limits::downlevel_defaults())
.features(wgpu::Features::CLEAR_TEXTURE),
)
.run_async(|ctx| clear_texture_tests(ctx, TEXTURE_FORMATS_DEPTH));
#[gpu_test]
static CLEAR_TEXTURE_DEPTH32_STENCIL8: GpuTestConfiguration = GpuTestConfiguration::new()
.parameters(
TestParameters::default()
.features(wgpu::Features::CLEAR_TEXTURE | wgpu::Features::DEPTH32FLOAT_STENCIL8)
.downlevel_flags(wgpu::DownlevelFlags::DEPTH_TEXTURE_AND_BUFFER_COPIES)
// https://github.com/gfx-rs/wgpu/issues/5016
.skip(FailureCase::adapter("Apple Paravirtual device")),
)
.run_async(|ctx| clear_texture_tests(ctx, &[wgpu::TextureFormat::Depth32FloatStencil8]));
#[gpu_test]
static CLEAR_TEXTURE_COMPRESSED_BCN: GpuTestConfiguration = GpuTestConfiguration::new()
.parameters(
TestParameters::default()
.features(
wgpu::Features::CLEAR_TEXTURE
| wgpu::Features::TEXTURE_COMPRESSION_BC
| wgpu::Features::TEXTURE_COMPRESSION_BC_SLICED_3D,
)
.limits(wgpu::Limits {
max_texture_dimension_3d: 1024,
..wgpu::Limits::downlevel_defaults()
})
// https://bugs.chromium.org/p/angleproject/issues/detail?id=7056
.expect_fail(FailureCase::backend_adapter(wgpu::Backends::GL, "ANGLE"))
// compressed texture copy to buffer not yet implemented
.expect_fail(FailureCase::backend(wgpu::Backends::GL)),
)
.run_async(|ctx| clear_texture_tests(ctx, TEXTURE_FORMATS_BC));
#[gpu_test]
static CLEAR_TEXTURE_COMPRESSED_ASTC: GpuTestConfiguration = GpuTestConfiguration::new()
.parameters(
TestParameters::default()
.features(wgpu::Features::CLEAR_TEXTURE | wgpu::Features::TEXTURE_COMPRESSION_ASTC)
.limits(wgpu::Limits {
max_texture_dimension_2d: wgpu::COPY_BYTES_PER_ROW_ALIGNMENT * 12,
..wgpu::Limits::downlevel_defaults()
})
// https://bugs.chromium.org/p/angleproject/issues/detail?id=7056
.expect_fail(FailureCase::backend_adapter(wgpu::Backends::GL, "ANGLE"))
// compressed texture copy to buffer not yet implemented
.expect_fail(FailureCase::backend(wgpu::Backends::GL)),
)
.run_async(|ctx| clear_texture_tests(ctx, TEXTURE_FORMATS_ASTC));
#[gpu_test]
static CLEAR_TEXTURE_COMPRESSED_ETC2: GpuTestConfiguration = GpuTestConfiguration::new()
.parameters(
TestParameters::default()
.features(wgpu::Features::CLEAR_TEXTURE | wgpu::Features::TEXTURE_COMPRESSION_ETC2)
// https://bugs.chromium.org/p/angleproject/issues/detail?id=7056
.expect_fail(FailureCase::backend_adapter(wgpu::Backends::GL, "ANGLE"))
// compressed texture copy to buffer not yet implemented
.expect_fail(FailureCase::backend(wgpu::Backends::GL)),
)
.run_async(|ctx| clear_texture_tests(ctx, TEXTURE_FORMATS_ETC2));