Add out multiple tests of vertex pulling

This commit is contained in:
Connor Fitzgerald 2021-06-19 17:58:29 -04:00
parent 528a311dd1
commit 3d8a4baeb8
3 changed files with 186 additions and 135 deletions

View File

@ -2,9 +2,7 @@
use std::panic::{catch_unwind, AssertUnwindSafe};
use wgt::{
BackendBit, DeviceDescriptor, DownlevelProperties, Features, Limits,
};
use wgt::{BackendBit, DeviceDescriptor, DownlevelProperties, Features, Limits};
use wgpu::{util, Adapter, Device, Instance, Queue};
@ -101,28 +99,38 @@ impl Default for TestParameters {
// Builder pattern to make it easier
#[allow(dead_code)]
impl TestParameters {
/// Set of common features that most tests require.
pub fn test_features(self) -> Self {
self.features(Features::MAPPABLE_PRIMARY_BUFFERS | Features::VERTEX_WRITABLE_STORAGE)
}
pub fn features(mut self, features: Features) -> Self {
self.required_features |= features;
self
}
pub fn backend_failures(mut self, backends: BackendBit) -> Self {
self.backend_failures |= backends;
self
}
pub fn failure(mut self) -> Self {
self.always_failure = true;
self
}
}
pub fn initialize_test(
parameters: TestParameters,
test_function: impl FnOnce(TestingContext),
) {
// We don't actually care if it fails
let _ = env_logger::try_init();
pub fn initialize_test(parameters: TestParameters, test_function: impl FnOnce(TestingContext)) {
// We don't actually care if it fails
let _ = env_logger::try_init();
let backend_bits = util::backend_bits_from_env().unwrap_or(BackendBit::all());
let instance = Instance::new(backend_bits);
let adapter = pollster::block_on(util::initialize_adapter_from_env_or_default(&instance, backend_bits))
.expect("could not find sutable adapter on the system");
let adapter = pollster::block_on(util::initialize_adapter_from_env_or_default(
&instance,
backend_bits,
))
.expect("could not find sutable adapter on the system");
let adapter_info = adapter.get_info();
let adapter_lowercase_name = adapter_info.name.to_lowercase();

View File

@ -8,7 +8,8 @@ var<storage> indices: [[access(read_write)]] Indices;
[[stage(vertex)]]
fn vs_main([[builtin(instance_index)]] instance: u32, [[builtin(vertex_index)]] index: u32) -> [[builtin(position)]] vec4<f32> {
indices.arr[index] = instance;
let idx = instance * 3u + index;
indices.arr[idx] = idx;
return vec4<f32>(0.0, 0.0, 0.0, 1.0);
}

View File

@ -2,135 +2,177 @@ use std::num::NonZeroU64;
use wgpu::util::DeviceExt;
use crate::common::{initialize_test, TestParameters};
use crate::common::{initialize_test, TestParameters, TestingContext};
fn pulling_common(
ctx: TestingContext,
expected: &[u32],
function: impl FnOnce(&mut wgpu::RenderPass<'_>),
) {
let shader = ctx
.device
.create_shader_module(&wgpu::include_wgsl!("draw.vert.wgsl"));
let bgl = ctx
.device
.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
label: None,
entries: &[wgpu::BindGroupLayoutEntry {
binding: 0,
ty: wgpu::BindingType::Buffer {
ty: wgpu::BufferBindingType::Storage { read_only: false },
has_dynamic_offset: false,
min_binding_size: NonZeroU64::new(4),
},
visibility: wgpu::ShaderStage::VERTEX,
count: None,
}],
});
let buffer = ctx.device.create_buffer(&wgpu::BufferDescriptor {
label: None,
size: 4 * expected.len() as u64,
usage: wgpu::BufferUsage::COPY_SRC
| wgpu::BufferUsage::STORAGE
| wgpu::BufferUsage::MAP_READ,
mapped_at_creation: false,
});
let bg = ctx.device.create_bind_group(&wgpu::BindGroupDescriptor {
label: None,
layout: &bgl,
entries: &[wgpu::BindGroupEntry {
binding: 0,
resource: buffer.as_entire_binding(),
}],
});
let ppl = ctx
.device
.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
label: None,
bind_group_layouts: &[&bgl],
push_constant_ranges: &[],
});
let pipeline = ctx
.device
.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
label: None,
layout: Some(&ppl),
vertex: wgpu::VertexState {
buffers: &[],
entry_point: "vs_main",
module: &shader,
},
primitive: wgpu::PrimitiveState::default(),
depth_stencil: None,
multisample: wgpu::MultisampleState::default(),
fragment: Some(wgpu::FragmentState {
entry_point: "fs_main",
module: &shader,
targets: &[wgpu::ColorTargetState {
format: wgpu::TextureFormat::Rgba8Unorm,
blend: None,
write_mask: wgpu::ColorWrite::ALL,
}],
}),
});
let dummy = ctx
.device
.create_texture_with_data(
&ctx.queue,
&wgpu::TextureDescriptor {
label: Some("dummy"),
size: wgpu::Extent3d {
width: 1,
height: 1,
depth_or_array_layers: 1,
},
mip_level_count: 1,
sample_count: 1,
dimension: wgpu::TextureDimension::D2,
format: wgpu::TextureFormat::Rgba8Unorm,
usage: wgpu::TextureUsage::RENDER_ATTACHMENT | wgpu::TextureUsage::COPY_DST,
},
&[0, 0, 0, 1],
)
.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 {
color_attachments: &[wgpu::RenderPassColorAttachment {
ops: wgpu::Operations::default(),
resolve_target: None,
view: &dummy,
}],
depth_stencil_attachment: None,
label: None,
});
rpass.set_pipeline(&pipeline);
rpass.set_bind_group(0, &bg, &[]);
function(&mut rpass);
drop(rpass);
ctx.queue.submit(Some(encoder.finish()));
let slice = buffer.slice(..);
let _ = slice.map_async(wgpu::MapMode::Read);
ctx.device.poll(wgpu::Maintain::Wait);
let data: Vec<u32> = bytemuck::cast_slice(&*slice.get_mapped_range()).to_vec();
assert_eq!(data, expected);
}
#[test]
fn draw() {
initialize_test(TestParameters::default().test_features(), |ctx| {
pulling_common(ctx, &[0, 1, 2, 3, 4, 5], |cmb| {
cmb.draw(0..6, 0..1);
})
})
}
#[test]
fn draw_vertex_offset() {
initialize_test(
TestParameters::default()
.features(
wgpu::Features::VERTEX_WRITABLE_STORAGE | wgpu::Features::MAPPABLE_PRIMARY_BUFFERS,
)
.failure(),
.test_features()
.backend_failures(wgpu::BackendBit::DX12 | wgpu::BackendBit::DX11),
|ctx| {
let shader = ctx
.device
.create_shader_module(&wgpu::include_wgsl!("draw.vert.wgsl"));
let bgl = ctx
.device
.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
label: None,
entries: &[wgpu::BindGroupLayoutEntry {
binding: 0,
ty: wgpu::BindingType::Buffer {
ty: wgpu::BufferBindingType::Storage { read_only: false },
has_dynamic_offset: false,
min_binding_size: NonZeroU64::new(4),
},
visibility: wgpu::ShaderStage::VERTEX,
count: None,
}],
});
let buffer = ctx.device.create_buffer(&wgpu::BufferDescriptor {
label: None,
size: 4 * 6,
usage: wgpu::BufferUsage::COPY_SRC
| wgpu::BufferUsage::STORAGE
| wgpu::BufferUsage::MAP_READ,
mapped_at_creation: false,
});
let bg = ctx.device.create_bind_group(&wgpu::BindGroupDescriptor {
label: None,
layout: &bgl,
entries: &[wgpu::BindGroupEntry {
binding: 0,
resource: buffer.as_entire_binding(),
}],
});
let ppl = ctx
.device
.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
label: None,
bind_group_layouts: &[&bgl],
push_constant_ranges: &[],
});
let pipeline = ctx
.device
.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
label: None,
layout: Some(&ppl),
vertex: wgpu::VertexState {
buffers: &[],
entry_point: "vs_main",
module: &shader,
},
primitive: wgpu::PrimitiveState::default(),
depth_stencil: None,
multisample: wgpu::MultisampleState::default(),
fragment: Some(wgpu::FragmentState {
entry_point: "fs_main",
module: &shader,
targets: &[wgpu::ColorTargetState {
format: wgpu::TextureFormat::Rgba8Unorm,
blend: None,
write_mask: wgpu::ColorWrite::ALL,
}],
}),
});
let dummy = ctx
.device
.create_texture_with_data(
&ctx.queue,
&wgpu::TextureDescriptor {
label: Some("dummy"),
size: wgpu::Extent3d {
width: 1,
height: 1,
depth_or_array_layers: 1,
},
mip_level_count: 1,
sample_count: 1,
dimension: wgpu::TextureDimension::D2,
format: wgpu::TextureFormat::Rgba8Unorm,
usage: wgpu::TextureUsage::RENDER_ATTACHMENT | wgpu::TextureUsage::COPY_DST,
},
&[0, 0, 0, 1],
)
.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 {
color_attachments: &[wgpu::RenderPassColorAttachment {
ops: wgpu::Operations::default(),
resolve_target: None,
view: &dummy,
}],
depth_stencil_attachment: None,
label: None,
});
rpass.set_pipeline(&pipeline);
rpass.set_bind_group(0, &bg, &[]);
rpass.draw(0..6, 0..1);
drop(rpass);
ctx.queue.submit(Some(encoder.finish()));
let slice = buffer.slice(..);
let _ = slice.map_async(wgpu::MapMode::Read);
ctx.device.poll(wgpu::Maintain::Wait);
let data: Vec<u32> = bytemuck::cast_slice(&*slice.get_mapped_range()).to_vec();
assert_eq!(data, [0, 1, 2, 3, 4, 5]);
pulling_common(ctx, &[0, 1, 2, 3, 4, 5], |cmb| {
cmb.draw(0..3, 0..1);
cmb.draw(3..6, 0..1);
})
},
)
}
#[test]
fn draw_instanced() {
initialize_test(TestParameters::default().test_features(), |ctx| {
pulling_common(ctx, &[0, 1, 2, 3, 4, 5], |cmb| {
cmb.draw(0..3, 0..2);
})
})
}
#[test]
fn draw_instanced_offset() {
initialize_test(
TestParameters::default()
.test_features()
.backend_failures(wgpu::BackendBit::DX12 | wgpu::BackendBit::DX11),
|ctx| {
pulling_common(ctx, &[0, 1, 2, 3, 4, 5], |cmb| {
cmb.draw(0..3, 0..1);
cmb.draw(0..3, 1..2);
})
},
)
}