mirror of
https://github.com/gfx-rs/wgpu.git
synced 2024-11-25 16:24:24 +00:00
playtest: move the actions together with expectations
This commit is contained in:
parent
acef9206a6
commit
eb7bdcd012
@ -12,11 +12,6 @@ keywords = ["graphics"]
|
||||
license = "MPL-2.0"
|
||||
publish = false
|
||||
|
||||
[lib]
|
||||
|
||||
[[bin]]
|
||||
name = "play"
|
||||
|
||||
[features]
|
||||
|
||||
[dependencies]
|
||||
|
@ -1,17 +1,6 @@
|
||||
(
|
||||
backends: (bits: 0x7),
|
||||
tests: [
|
||||
(
|
||||
path: "buffer-copy.ron",
|
||||
features: (bits: 0x0),
|
||||
expectations: [
|
||||
(
|
||||
name: "basic",
|
||||
buffer: (index: 0, epoch: 1),
|
||||
offset: 0,
|
||||
data: [0x00, 0x00, 0x80, 0xBF],
|
||||
)
|
||||
],
|
||||
),
|
||||
"buffer-copy.ron",
|
||||
],
|
||||
)
|
@ -1,23 +1,34 @@
|
||||
[
|
||||
CreateBuffer(
|
||||
id: Id(0, 1, Empty),
|
||||
desc: (
|
||||
label: "",
|
||||
size: 16,
|
||||
usage: (
|
||||
bits: 41,
|
||||
(
|
||||
features: (bits: 0x0),
|
||||
expectations: [
|
||||
(
|
||||
name: "basic",
|
||||
buffer: (index: 0, epoch: 1),
|
||||
offset: 0,
|
||||
data: [0x00, 0x00, 0x80, 0xBF],
|
||||
)
|
||||
],
|
||||
actions: [
|
||||
CreateBuffer(
|
||||
id: Id(0, 1, Empty),
|
||||
desc: (
|
||||
label: "",
|
||||
size: 16,
|
||||
usage: (
|
||||
bits: 41,
|
||||
),
|
||||
mapped_at_creation: false,
|
||||
),
|
||||
mapped_at_creation: false,
|
||||
),
|
||||
),
|
||||
WriteBuffer(
|
||||
id: Id(0, 1, Empty),
|
||||
data: "data1.bin",
|
||||
range: (
|
||||
start: 0,
|
||||
end: 16,
|
||||
WriteBuffer(
|
||||
id: Id(0, 1, Empty),
|
||||
data: "data1.bin",
|
||||
range: (
|
||||
start: 0,
|
||||
end: 16,
|
||||
),
|
||||
queued: true,
|
||||
),
|
||||
queued: true,
|
||||
),
|
||||
Submit(1, []),
|
||||
]
|
||||
Submit(1, []),
|
||||
],
|
||||
)
|
@ -10,6 +10,7 @@
|
||||
* - all IDs have the backend `Empty`
|
||||
* - all expected buffers have `MAP_READ` usage
|
||||
* - last action is `Submit`
|
||||
* - no swapchain use
|
||||
!*/
|
||||
|
||||
use player::{gfx_select, GlobalPlay, IdentityPassThroughFactory};
|
||||
@ -35,15 +36,88 @@ struct Expectation {
|
||||
|
||||
#[derive(serde::Deserialize)]
|
||||
struct Test {
|
||||
path: String,
|
||||
features: wgt::Features,
|
||||
expectations: Vec<Expectation>,
|
||||
actions: Vec<wgc::device::trace::Action>,
|
||||
}
|
||||
|
||||
extern "C" fn map_callback(status: wgc::resource::BufferMapAsyncStatus, _user_data: *mut u8) {
|
||||
match status {
|
||||
wgc::resource::BufferMapAsyncStatus::Success => (),
|
||||
_ => panic!("Unable to map"),
|
||||
}
|
||||
}
|
||||
|
||||
impl Test {
|
||||
fn load(path: PathBuf, backend: wgt::Backend) -> Self {
|
||||
let backend_name = match backend {
|
||||
wgt::Backend::Vulkan => "Vulkan",
|
||||
wgt::Backend::Metal => "Metal",
|
||||
wgt::Backend::Dx12 => "Dx12",
|
||||
wgt::Backend::Dx11 => "Dx11",
|
||||
wgt::Backend::Gl => "Gl",
|
||||
_ => unreachable!(),
|
||||
};
|
||||
let string = read_to_string(path).unwrap().replace("Empty", backend_name);
|
||||
ron::de::from_str(&string).unwrap()
|
||||
}
|
||||
|
||||
fn run(
|
||||
self,
|
||||
dir: &Path,
|
||||
global: &wgc::hub::Global<IdentityPassThroughFactory>,
|
||||
adapter: wgc::id::AdapterId,
|
||||
) {
|
||||
let backend = adapter.backend();
|
||||
let device = gfx_select!(adapter => global.adapter_request_device(
|
||||
adapter,
|
||||
&wgt::DeviceDescriptor {
|
||||
features: self.features | wgt::Features::MAPPABLE_PRIMARY_BUFFERS,
|
||||
limits: wgt::Limits::default(),
|
||||
shader_validation: true,
|
||||
},
|
||||
None,
|
||||
wgc::id::TypedId::zip(1, 0, backend)
|
||||
))
|
||||
.unwrap();
|
||||
|
||||
let mut command_buffer_id_manager = wgc::hub::IdentityManager::default();
|
||||
println!("\t\t\tRunning...");
|
||||
for action in self.actions {
|
||||
gfx_select!(device => global.process(device, action, dir, &mut command_buffer_id_manager));
|
||||
}
|
||||
println!("\t\t\tMapping...");
|
||||
for expect in &self.expectations {
|
||||
let buffer = wgc::id::TypedId::zip(expect.buffer.index, expect.buffer.epoch, backend);
|
||||
gfx_select!(device => global.buffer_map_async(
|
||||
buffer,
|
||||
expect.offset .. expect.offset+expect.data.len() as wgt::BufferAddress,
|
||||
wgc::resource::BufferMapOperation {
|
||||
host: wgc::device::HostMap::Read,
|
||||
callback: map_callback,
|
||||
user_data: ptr::null_mut(),
|
||||
}
|
||||
));
|
||||
}
|
||||
|
||||
println!("\t\t\tWaiting...");
|
||||
gfx_select!(device => global.device_poll(device, true));
|
||||
|
||||
for expect in self.expectations {
|
||||
println!("\t\t\tChecking {}", expect.name);
|
||||
let buffer = wgc::id::TypedId::zip(expect.buffer.index, expect.buffer.epoch, backend);
|
||||
let ptr =
|
||||
gfx_select!(device => global.buffer_get_mapped_range(buffer, expect.offset, None));
|
||||
let contents = unsafe { slice::from_raw_parts(ptr, expect.data.len()) };
|
||||
assert_eq!(&expect.data[..], contents);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(serde::Deserialize)]
|
||||
struct Corpus {
|
||||
backends: wgt::BackendBit,
|
||||
tests: Vec<Test>,
|
||||
tests: Vec<String>,
|
||||
}
|
||||
|
||||
const BACKENDS: &[wgt::Backend] = &[
|
||||
@ -54,116 +128,50 @@ const BACKENDS: &[wgt::Backend] = &[
|
||||
wgt::Backend::Gl,
|
||||
];
|
||||
|
||||
extern "C" fn map_callback(status: wgc::resource::BufferMapAsyncStatus, _user_data: *mut u8) {
|
||||
match status {
|
||||
wgc::resource::BufferMapAsyncStatus::Success => (),
|
||||
_ => panic!("Unable to map"),
|
||||
}
|
||||
}
|
||||
impl Corpus {
|
||||
fn run_from(path: PathBuf) {
|
||||
println!("Corpus {:?}", path);
|
||||
let dir = path.parent().unwrap();
|
||||
let corpus: Corpus = ron::de::from_reader(File::open(&path).unwrap()).unwrap();
|
||||
|
||||
fn run_test(
|
||||
test: Test,
|
||||
dir: &Path,
|
||||
global: &wgc::hub::Global<IdentityPassThroughFactory>,
|
||||
adapter: wgc::id::AdapterId,
|
||||
) {
|
||||
println!("\t\tTest '{:?}'", test.path);
|
||||
let device = gfx_select!(adapter => global.adapter_request_device(
|
||||
adapter,
|
||||
&wgt::DeviceDescriptor {
|
||||
features: test.features | wgt::Features::MAPPABLE_PRIMARY_BUFFERS,
|
||||
limits: wgt::Limits::default(),
|
||||
shader_validation: true,
|
||||
},
|
||||
None,
|
||||
wgc::id::TypedId::zip(1, 0, adapter.backend())
|
||||
))
|
||||
.unwrap();
|
||||
|
||||
let backend = device.backend();
|
||||
let backend_name = match backend {
|
||||
wgt::Backend::Vulkan => "Vulkan",
|
||||
wgt::Backend::Metal => "Metal",
|
||||
wgt::Backend::Dx12 => "Dx12",
|
||||
wgt::Backend::Dx11 => "Dx11",
|
||||
wgt::Backend::Gl => "Gl",
|
||||
_ => unreachable!(),
|
||||
};
|
||||
let string = read_to_string(dir.join(test.path))
|
||||
.unwrap()
|
||||
.replace("Empty", backend_name);
|
||||
let actions: Vec<wgc::device::trace::Action> = ron::de::from_str(&string).unwrap();
|
||||
|
||||
let mut command_buffer_id_manager = wgc::hub::IdentityManager::default();
|
||||
println!("\t\t\tRunning...");
|
||||
for action in actions {
|
||||
gfx_select!(device => global.process(device, action, dir, &mut command_buffer_id_manager));
|
||||
}
|
||||
println!("\t\t\tMapping...");
|
||||
for expect in &test.expectations {
|
||||
let buffer = wgc::id::TypedId::zip(expect.buffer.index, expect.buffer.epoch, backend);
|
||||
gfx_select!(device => global.buffer_map_async(
|
||||
buffer,
|
||||
expect.offset .. expect.offset+expect.data.len() as wgt::BufferAddress,
|
||||
wgc::resource::BufferMapOperation {
|
||||
host: wgc::device::HostMap::Read,
|
||||
callback: map_callback,
|
||||
user_data: ptr::null_mut(),
|
||||
}
|
||||
));
|
||||
}
|
||||
|
||||
println!("\t\t\tWaiting...");
|
||||
gfx_select!(device => global.device_poll(device, true));
|
||||
|
||||
for expect in test.expectations {
|
||||
println!("\t\t\tChecking {}", expect.name);
|
||||
let buffer = wgc::id::TypedId::zip(expect.buffer.index, expect.buffer.epoch, backend);
|
||||
let ptr =
|
||||
gfx_select!(device => global.buffer_get_mapped_range(buffer, expect.offset, None));
|
||||
let contents = unsafe { slice::from_raw_parts(ptr, expect.data.len()) };
|
||||
assert_eq!(&expect.data[..], contents);
|
||||
}
|
||||
}
|
||||
|
||||
fn run_corpus(path: PathBuf) {
|
||||
println!("Corpus {:?}", path);
|
||||
let mut corpus: Corpus = ron::de::from_reader(File::open(&path).unwrap()).unwrap();
|
||||
|
||||
let global = wgc::hub::Global::new("test", IdentityPassThroughFactory, corpus.backends);
|
||||
for &backend in BACKENDS {
|
||||
if !corpus.backends.contains(backend.into()) {
|
||||
continue;
|
||||
}
|
||||
let adapter = match global.pick_adapter(
|
||||
&wgc::instance::RequestAdapterOptions {
|
||||
power_preference: wgt::PowerPreference::Default,
|
||||
compatible_surface: None,
|
||||
},
|
||||
wgc::instance::AdapterInputs::IdSet(&[wgc::id::TypedId::zip(0, 0, backend)], |id| {
|
||||
id.backend()
|
||||
}),
|
||||
) {
|
||||
Some(adapter) => adapter,
|
||||
None => continue,
|
||||
};
|
||||
|
||||
println!("\tBackend {:?}", backend);
|
||||
let supported_features = gfx_select!(adapter => global.adapter_features(adapter));
|
||||
for test in corpus.tests.drain(..) {
|
||||
if !supported_features.contains(test.features) {
|
||||
println!(
|
||||
"\t\tSkipped due to missing features {:?}",
|
||||
test.features - supported_features
|
||||
);
|
||||
let global = wgc::hub::Global::new("test", IdentityPassThroughFactory, corpus.backends);
|
||||
for &backend in BACKENDS {
|
||||
if !corpus.backends.contains(backend.into()) {
|
||||
continue;
|
||||
}
|
||||
run_test(test, path.parent().unwrap(), &global, adapter);
|
||||
let adapter = match global.pick_adapter(
|
||||
&wgc::instance::RequestAdapterOptions {
|
||||
power_preference: wgt::PowerPreference::Default,
|
||||
compatible_surface: None,
|
||||
},
|
||||
wgc::instance::AdapterInputs::IdSet(
|
||||
&[wgc::id::TypedId::zip(0, 0, backend)],
|
||||
|id| id.backend(),
|
||||
),
|
||||
) {
|
||||
Some(adapter) => adapter,
|
||||
None => continue,
|
||||
};
|
||||
|
||||
println!("\tBackend {:?}", backend);
|
||||
let supported_features = gfx_select!(adapter => global.adapter_features(adapter));
|
||||
for test_path in &corpus.tests {
|
||||
println!("\t\tTest '{:?}'", test_path);
|
||||
let test = Test::load(dir.join(test_path), adapter.backend());
|
||||
if !supported_features.contains(test.features) {
|
||||
println!(
|
||||
"\t\tSkipped due to missing features {:?}",
|
||||
test.features - supported_features
|
||||
);
|
||||
continue;
|
||||
}
|
||||
test.run(dir, &global, adapter);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_api() {
|
||||
run_corpus(PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("tests/data/all.ron"))
|
||||
Corpus::run_from(PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("tests/data/all.ron"))
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user