mirror of
https://github.com/gfx-rs/wgpu.git
synced 2026-04-22 03:02:01 -04:00
302 lines
8.0 KiB
Rust
302 lines
8.0 KiB
Rust
use wgpu::{DownlevelFlags, Limits};
|
|
|
|
use crate::shader::{shader_input_output_test, InputStorageType, ShaderTest};
|
|
use wgpu_test::{gpu_test, GpuTestConfiguration, TestParameters};
|
|
|
|
fn create_numeric_builtin_test() -> Vec<ShaderTest> {
|
|
let mut tests = Vec::new();
|
|
|
|
#[rustfmt::skip]
|
|
let clamp_values: &[(f32, f32, f32, &[f32])] = &[
|
|
// value - low - high - valid outputs
|
|
|
|
// normal clamps
|
|
( 20.0, 0.0, 10.0, &[10.0]),
|
|
( -10.0, 0.0, 10.0, &[0.0]),
|
|
( 5.0, 0.0, 10.0, &[5.0]),
|
|
|
|
// med-of-three or min/max
|
|
( 3.0, 2.0, 1.0, &[1.0, 2.0]),
|
|
];
|
|
|
|
for &(input, low, high, output) in clamp_values {
|
|
let mut test = ShaderTest::new(
|
|
format!("clamp({input}, {low}, {high}) == {output:?}"),
|
|
String::from("value: f32, low: f32, high: f32"),
|
|
String::from("output[0] = bitcast<u32>(clamp(input.value, input.low, input.high));"),
|
|
&[input, low, high],
|
|
&[output[0]],
|
|
);
|
|
for &extra in &output[1..] {
|
|
test = test.extra_output_values(&[extra]);
|
|
}
|
|
|
|
tests.push(test);
|
|
}
|
|
|
|
tests
|
|
}
|
|
|
|
#[gpu_test]
|
|
static NUMERIC_BUILTINS: GpuTestConfiguration = GpuTestConfiguration::new()
|
|
.parameters(
|
|
TestParameters::default()
|
|
.downlevel_flags(DownlevelFlags::COMPUTE_SHADERS)
|
|
.limits(Limits::downlevel_defaults()),
|
|
)
|
|
.run_async(|ctx| {
|
|
shader_input_output_test(
|
|
ctx,
|
|
InputStorageType::Storage,
|
|
create_numeric_builtin_test(),
|
|
)
|
|
});
|
|
|
|
fn create_int64_atomic_min_max_test() -> Vec<ShaderTest> {
|
|
let mut tests = Vec::new();
|
|
|
|
let test = ShaderTest::new(
|
|
"atomicMax".into(),
|
|
"value: u64".into(),
|
|
"atomicMin(&output, 0lu); atomicMax(&output, 2lu);".into(),
|
|
&[0],
|
|
&[2],
|
|
)
|
|
.output_type("atomic<u64>".into());
|
|
|
|
tests.push(test);
|
|
|
|
let test = ShaderTest::new(
|
|
"atomicMin".into(),
|
|
"value: u64".into(),
|
|
"atomicMax(&output, 100lu); atomicMin(&output, 4lu);".into(),
|
|
&[0],
|
|
&[4],
|
|
)
|
|
.output_type("atomic<u64>".into());
|
|
|
|
tests.push(test);
|
|
|
|
tests
|
|
}
|
|
|
|
#[gpu_test]
|
|
static INT64_ATOMIC_MIN_MAX: GpuTestConfiguration = GpuTestConfiguration::new()
|
|
.parameters(
|
|
TestParameters::default()
|
|
.features(wgpu::Features::SHADER_INT64 | wgpu::Features::SHADER_INT64_ATOMIC_MIN_MAX)
|
|
.downlevel_flags(DownlevelFlags::COMPUTE_SHADERS)
|
|
.limits(Limits::downlevel_defaults()),
|
|
)
|
|
.run_async(|ctx| {
|
|
shader_input_output_test(
|
|
ctx,
|
|
InputStorageType::Storage,
|
|
create_int64_atomic_min_max_test(),
|
|
)
|
|
});
|
|
|
|
fn create_int64_atomic_all_ops_test() -> Vec<ShaderTest> {
|
|
let mut tests = Vec::new();
|
|
|
|
let test = ShaderTest::new(
|
|
"atomicAdd".into(),
|
|
"value: u64".into(),
|
|
"atomicStore(&output, 0lu); atomicAdd(&output, 1lu); atomicAdd(&output, 1lu);".into(),
|
|
&[0],
|
|
&[2],
|
|
)
|
|
.output_type("atomic<u64>".into());
|
|
|
|
tests.push(test);
|
|
|
|
let test = ShaderTest::new(
|
|
"atomicAnd".into(),
|
|
"value: u64".into(),
|
|
"atomicStore(&output, 31lu); atomicAnd(&output, 30lu); atomicAnd(&output, 3lu);".into(),
|
|
&[0],
|
|
&[2],
|
|
)
|
|
.output_type("atomic<u64>".into());
|
|
|
|
tests.push(test);
|
|
|
|
let test = ShaderTest::new(
|
|
"atomicOr".into(),
|
|
"value: u64".into(),
|
|
"atomicStore(&output, 0lu); atomicOr(&output, 3lu); atomicOr(&output, 6lu);".into(),
|
|
&[0],
|
|
&[7],
|
|
)
|
|
.output_type("atomic<u64>".into());
|
|
|
|
tests.push(test);
|
|
|
|
tests
|
|
}
|
|
|
|
#[gpu_test]
|
|
static INT64_ATOMIC_ALL_OPS: GpuTestConfiguration = GpuTestConfiguration::new()
|
|
.parameters(
|
|
TestParameters::default()
|
|
.features(wgpu::Features::SHADER_INT64 | wgpu::Features::SHADER_INT64_ATOMIC_ALL_OPS)
|
|
.downlevel_flags(DownlevelFlags::COMPUTE_SHADERS)
|
|
.limits(Limits::downlevel_defaults()),
|
|
)
|
|
.run_async(|ctx| {
|
|
shader_input_output_test(
|
|
ctx,
|
|
InputStorageType::Storage,
|
|
create_int64_atomic_all_ops_test(),
|
|
)
|
|
});
|
|
|
|
fn create_float32_atomic_test() -> Vec<ShaderTest> {
|
|
let mut tests = Vec::new();
|
|
|
|
let test = ShaderTest::new(
|
|
"atomicAdd".into(),
|
|
"value: f32".into(),
|
|
"atomicStore(&output, 0.0); atomicAdd(&output, -0.50); atomicAdd(&output, 1.75);".into(),
|
|
&[0_f32],
|
|
&[1.25_f32],
|
|
)
|
|
.output_type("atomic<f32>".into());
|
|
|
|
tests.push(test);
|
|
|
|
let test = ShaderTest::new(
|
|
"atomicAdd".into(),
|
|
"value: f32".into(),
|
|
"atomicStore(&output, 0.0); atomicSub(&output, -2.5); atomicSub(&output, 3.0);".into(),
|
|
&[0_f32],
|
|
&[-0.5_f32],
|
|
)
|
|
.output_type("atomic<f32>".into());
|
|
|
|
tests.push(test);
|
|
|
|
tests
|
|
}
|
|
|
|
#[gpu_test]
|
|
static FLOAT32_ATOMIC: GpuTestConfiguration = GpuTestConfiguration::new()
|
|
.parameters(
|
|
TestParameters::default()
|
|
.features(wgpu::Features::SHADER_FLOAT32_ATOMIC)
|
|
.downlevel_flags(DownlevelFlags::COMPUTE_SHADERS)
|
|
.limits(Limits::downlevel_defaults()),
|
|
)
|
|
.run_async(|ctx| {
|
|
shader_input_output_test(ctx, InputStorageType::Storage, create_float32_atomic_test())
|
|
});
|
|
|
|
// See https://github.com/gfx-rs/wgpu/issues/5276
|
|
/*
|
|
fn create_int64_polyfill_test() -> Vec<ShaderTest> {
|
|
let mut tests = Vec::new();
|
|
|
|
let u64_clz_values: &[(u64, u32)] = &[
|
|
(u64::MAX, 0),
|
|
(1, 63),
|
|
(2, 62),
|
|
(3, 62),
|
|
(1 << 63, 0),
|
|
(1 << 62, 1),
|
|
(0, 64),
|
|
];
|
|
|
|
for &(input, output) in u64_clz_values {
|
|
let test = ShaderTest::new(
|
|
format!("countLeadingZeros({input}lu) == {output:?}"),
|
|
String::from("value: u64"),
|
|
String::from("output[0] = u32(countLeadingZeros(input.value));"),
|
|
&[input],
|
|
&[output],
|
|
);
|
|
|
|
tests.push(test);
|
|
}
|
|
|
|
let i64_clz_values: &[(i64, u32)] = &[
|
|
(i64::MAX, 1),
|
|
(i64::MIN, 0),
|
|
(1, 63),
|
|
(1 << 62, 1),
|
|
(-1 << 62, 0),
|
|
(0, 64),
|
|
(-1, 0),
|
|
];
|
|
|
|
for &(input, output) in i64_clz_values {
|
|
let test = ShaderTest::new(
|
|
format!("countLeadingZeros({input}li) == {output:?}"),
|
|
String::from("value: i64"),
|
|
String::from("output[0] = u32(countLeadingZeros(input.value));"),
|
|
&[input],
|
|
&[output],
|
|
);
|
|
|
|
tests.push(test);
|
|
}
|
|
|
|
let u64_flb_values: &[(u64, u32)] = &[
|
|
(u64::MAX, 63),
|
|
(1, 0),
|
|
(2, 1),
|
|
(3, 1),
|
|
(1 << 63, 63),
|
|
(1 << 62, 62),
|
|
(0, u32::MAX),
|
|
];
|
|
|
|
for &(input, output) in u64_flb_values {
|
|
let test = ShaderTest::new(
|
|
format!("firstLeadingBit({input}lu) == {output:?}"),
|
|
String::from("value: u64"),
|
|
String::from("output[0] = u32(firstLeadingBit(input.value));"),
|
|
&[input],
|
|
&[output],
|
|
);
|
|
|
|
tests.push(test);
|
|
}
|
|
|
|
let i64_flb_values: &[(i64, u32)] = &[
|
|
(i64::MAX, 62),
|
|
(i64::MIN, 62),
|
|
(1, 0),
|
|
(1 << 62, 62),
|
|
(-1 << 62, 61),
|
|
(0, u32::MAX),
|
|
(-1, u32::MAX),
|
|
];
|
|
|
|
for &(input, output) in i64_flb_values {
|
|
let test = ShaderTest::new(
|
|
format!("firstLeadingBit({input}li) == {output:?}"),
|
|
String::from("value: i64"),
|
|
String::from("output[0] = u32(firstLeadingBit(input.value));"),
|
|
&[input],
|
|
&[output],
|
|
);
|
|
|
|
tests.push(test);
|
|
}
|
|
|
|
tests
|
|
}
|
|
|
|
#[gpu_test]
|
|
static INT64_POLYFILL: GpuTestConfiguration = GpuTestConfiguration::new()
|
|
.parameters(
|
|
TestParameters::default()
|
|
.features(Features::SHADER_INT64)
|
|
.downlevel_flags(DownlevelFlags::COMPUTE_SHADERS)
|
|
.limits(Limits::downlevel_defaults()),
|
|
)
|
|
.run_async(|ctx| {
|
|
shader_input_output_test(ctx, InputStorageType::Storage, create_int64_polyfill_test())
|
|
});
|
|
*/
|