Skip to content

Commit 73ab877

Browse files
committed
difftest runner: eddyb's suggestions, cleanup wgpu AI code
1 parent f1250b9 commit 73ab877

3 files changed

Lines changed: 98 additions & 118 deletions

File tree

tests/difftests/tests/arch/push_constants/push_constants-rust/src/main.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,7 @@ fn main() {
4545
},
4646
],
4747
)
48-
.with_feature(Features::IMMEDIATES)
49-
.with_push_constant(&push_constants);
48+
.with_immediates(&push_constants);
5049

5150
test.run_test(&config).unwrap();
5251
}

tests/difftests/tests/arch/push_constants/push_constants-wgsl/src/main.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,7 @@ fn main() {
4545
},
4646
],
4747
)
48-
.with_feature(Features::IMMEDIATES)
49-
.with_push_constant(&push_constants);
48+
.with_immediates(&push_constants);
5049

5150
test.run_test(&config).unwrap();
5251
}

tests/difftests/tests/lib/src/scaffold/compute/wgpu_runner.rs

Lines changed: 96 additions & 114 deletions
Original file line numberDiff line numberDiff line change
@@ -48,14 +48,15 @@ where
4848
}
4949
}
5050

51-
pub fn with_push_constant<T: NoUninit>(self, data: &T) -> Self {
51+
pub fn with_immediates<T: NoUninit>(self, data: &T) -> Self {
5252
Self {
5353
push_constant: Some(bytemuck::bytes_of(data).to_vec()),
54+
features: self.features | wgpu::Features::IMMEDIATES,
5455
..self
5556
}
5657
}
5758

58-
pub fn run(self) -> anyhow::Result<Vec<Vec<u8>>> {
59+
pub fn run(&self) -> anyhow::Result<Vec<Option<Vec<u8>>>> {
5960
let instance = wgpu::Instance::new(wgpu::InstanceDescriptor::new_without_display_handle());
6061
let adapter = block_on(instance.request_adapter(&wgpu::RequestAdapterOptions {
6162
power_preference: wgpu::PowerPreference::HighPerformance,
@@ -90,22 +91,18 @@ where
9091
.map(|(i, buffer_config)| wgpu::BindGroupLayoutEntry {
9192
binding: i as u32,
9293
visibility: wgpu::ShaderStages::COMPUTE,
93-
ty: match buffer_config.usage {
94-
BufferUsage::Storage => wgpu::BindingType::Buffer {
95-
ty: wgpu::BufferBindingType::Storage { read_only: false },
96-
has_dynamic_offset: false,
97-
min_binding_size: None,
98-
},
99-
BufferUsage::StorageReadOnly => wgpu::BindingType::Buffer {
100-
ty: wgpu::BufferBindingType::Storage { read_only: true },
101-
has_dynamic_offset: false,
102-
min_binding_size: None,
103-
},
104-
BufferUsage::Uniform => wgpu::BindingType::Buffer {
105-
ty: wgpu::BufferBindingType::Uniform,
106-
has_dynamic_offset: false,
107-
min_binding_size: None,
94+
ty: wgpu::BindingType::Buffer {
95+
ty: match buffer_config.usage {
96+
BufferUsage::Storage => {
97+
wgpu::BufferBindingType::Storage { read_only: false }
98+
}
99+
BufferUsage::StorageReadOnly => {
100+
wgpu::BufferBindingType::Storage { read_only: true }
101+
}
102+
BufferUsage::Uniform => wgpu::BufferBindingType::Uniform,
108103
},
104+
has_dynamic_offset: false,
105+
min_binding_size: None,
109106
},
110107
count: None,
111108
})
@@ -121,59 +118,55 @@ where
121118
)?;
122119

123120
// Create buffers.
124-
let mut gpu_buffers = Vec::new();
125-
126-
for (i, buffer_config) in self.buffers.iter().enumerate() {
127-
let usage = match buffer_config.usage {
128-
BufferUsage::Storage => wgpu::BufferUsages::STORAGE | wgpu::BufferUsages::COPY_SRC,
129-
BufferUsage::StorageReadOnly => {
130-
wgpu::BufferUsages::STORAGE | wgpu::BufferUsages::COPY_SRC
131-
}
132-
BufferUsage::Uniform => wgpu::BufferUsages::UNIFORM,
133-
};
134-
135-
let buffer = if let Some(initial_data) = &buffer_config.initial_data {
136-
device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
137-
label: Some(&format!("Buffer {i}")),
138-
contents: initial_data,
139-
usage,
140-
})
141-
} else {
142-
let buffer = device.create_buffer(&wgpu::BufferDescriptor {
143-
label: Some(&format!("Buffer {i}")),
144-
size: buffer_config.size,
145-
usage,
146-
mapped_at_creation: true,
147-
});
148-
{
149-
// Zero the buffer.
150-
let initial_data = vec![0u8; buffer_config.size as usize];
151-
let mut mapping = buffer.slice(..).get_mapped_range_mut();
152-
mapping.copy_from_slice(&initial_data);
153-
}
154-
buffer.unmap();
155-
buffer
156-
};
157-
158-
gpu_buffers.push(buffer);
159-
}
160-
161-
// Create bind entries after all buffers are created
162-
let bind_entries: Vec<_> = gpu_buffers
121+
let gpu_buffers = self
122+
.buffers
163123
.iter()
164124
.enumerate()
165-
.map(|(i, buffer)| wgpu::BindGroupEntry {
166-
binding: i as u32,
167-
resource: buffer.as_entire_binding(),
125+
.map(|(i, buffer_config)| {
126+
let usage = match buffer_config.usage {
127+
BufferUsage::Storage => {
128+
wgpu::BufferUsages::STORAGE | wgpu::BufferUsages::COPY_SRC
129+
}
130+
BufferUsage::StorageReadOnly => {
131+
wgpu::BufferUsages::STORAGE | wgpu::BufferUsages::COPY_SRC
132+
}
133+
BufferUsage::Uniform => wgpu::BufferUsages::UNIFORM,
134+
};
135+
136+
let buffer = if let Some(initial_data) = &buffer_config.initial_data {
137+
device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
138+
label: Some(&format!("Buffer {i}")),
139+
contents: initial_data,
140+
usage,
141+
})
142+
} else {
143+
device.create_buffer(&wgpu::BufferDescriptor {
144+
label: Some(&format!("Buffer {i}")),
145+
size: buffer_config.size,
146+
usage,
147+
mapped_at_creation: false,
148+
})
149+
};
150+
151+
(buffer_config, buffer)
168152
})
169-
.collect();
153+
.collect::<Vec<_>>();
170154

155+
// Create bind entries after all buffers are created
171156
let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
172157
layout: &pipeline.get_bind_group_layout(0),
173-
entries: &bind_entries,
158+
entries: &gpu_buffers
159+
.iter()
160+
.enumerate()
161+
.map(|(i, (_, buffer))| wgpu::BindGroupEntry {
162+
binding: i as u32,
163+
resource: buffer.as_entire_binding(),
164+
})
165+
.collect::<Vec<_>>(),
174166
label: Some("Compute Bind Group"),
175167
});
176168

169+
// record command encoder
177170
let mut encoder = device.create_command_encoder(&wgpu::CommandEncoderDescriptor {
178171
label: Some("Compute Encoder"),
179172
});
@@ -184,72 +177,61 @@ where
184177
});
185178
pass.set_pipeline(&pipeline);
186179
pass.set_bind_group(0, &bind_group, &[]);
187-
if let Some(push_constant) = self.push_constant {
180+
if let Some(push_constant) = &self.push_constant {
188181
pass.set_immediates(0, &push_constant);
189182
}
190183
pass.dispatch_workgroups(self.dispatch[0], self.dispatch[1], self.dispatch[2]);
191184
}
192185

193-
// Create staging buffers and copy results.
194-
let mut staging_buffers = Vec::new();
195-
for (i, buffer_config) in self.buffers.iter().enumerate() {
196-
if matches!(
197-
buffer_config.usage,
198-
BufferUsage::Storage | BufferUsage::StorageReadOnly
199-
) {
200-
let staging_buffer = device.create_buffer(&wgpu::BufferDescriptor {
201-
label: Some(&format!("Staging Buffer {i}")),
202-
size: buffer_config.size,
203-
usage: wgpu::BufferUsages::MAP_READ | wgpu::BufferUsages::COPY_DST,
204-
mapped_at_creation: false,
205-
});
206-
encoder.copy_buffer_to_buffer(
207-
&gpu_buffers[i],
208-
0,
209-
&staging_buffer,
210-
0,
211-
buffer_config.size,
212-
);
213-
staging_buffers.push(Some(staging_buffer));
214-
} else {
215-
staging_buffers.push(None);
216-
}
217-
}
218-
186+
// Create staging buffers, copy results and initiate mapping.
187+
let download_buffers = gpu_buffers
188+
.iter()
189+
.enumerate()
190+
.map(|(i, (buffer_config, buffer))| {
191+
matches!(buffer_config.usage, BufferUsage::Storage).then(|| {
192+
let staging_buffer = device.create_buffer(&wgpu::BufferDescriptor {
193+
label: Some(&format!("Staging Buffer {i}")),
194+
size: buffer_config.size,
195+
usage: wgpu::BufferUsages::MAP_READ | wgpu::BufferUsages::COPY_DST,
196+
mapped_at_creation: false,
197+
});
198+
encoder.copy_buffer_to_buffer(
199+
&buffer,
200+
0,
201+
&staging_buffer,
202+
0,
203+
buffer_config.size,
204+
);
205+
encoder.map_buffer_on_submit(
206+
&staging_buffer,
207+
wgpu::MapMode::Read,
208+
..,
209+
move |r| r.unwrap(),
210+
);
211+
staging_buffer
212+
})
213+
})
214+
.collect::<Vec<_>>();
219215
queue.submit(Some(encoder.finish()));
216+
device.poll(wgpu::PollType::wait_indefinitely())?;
220217

221-
// Read back results.
222-
let mut results = Vec::new();
223-
for staging_buffer in staging_buffers {
224-
if let Some(buffer) = staging_buffer {
225-
let buffer_slice = buffer.slice(..);
226-
let (sender, receiver) = futures::channel::oneshot::channel();
227-
buffer_slice.map_async(wgpu::MapMode::Read, move |res| {
228-
let _ = sender.send(res);
229-
});
230-
device.poll(wgpu::PollType::wait_indefinitely())?;
231-
block_on(receiver)
232-
.context("mapping canceled")?
233-
.context("mapping failed")?;
234-
let data = buffer_slice.get_mapped_range().to_vec();
235-
buffer.unmap();
236-
results.push(data);
237-
} else {
238-
results.push(Vec::new());
239-
}
240-
}
241-
218+
// copy data from buffers into Vecs
219+
let results = download_buffers
220+
.into_iter()
221+
.map(|buffer| buffer.map(|buffer| buffer.get_mapped_range(..).to_vec()))
222+
.collect::<Vec<_>>();
242223
Ok(results)
243224
}
244225

245226
pub fn run_test(self, config: &Config) -> anyhow::Result<()> {
246-
let buffers = self.buffers.clone();
247227
let outputs = self.run()?;
248228
// Write the first storage buffer output to the file.
249-
for (output, buffer_config) in outputs.iter().zip(&buffers) {
250-
if matches!(buffer_config.usage, BufferUsage::Storage) && !output.is_empty() {
251-
config.write_result(output)?;
252-
return Ok(());
229+
for output in &outputs {
230+
if let Some(output) = output {
231+
if !output.is_empty() {
232+
config.write_result(output)?;
233+
return Ok(());
234+
}
253235
}
254236
}
255237
anyhow::bail!("No storage buffer output found")

0 commit comments

Comments
 (0)