@@ -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