Skip to content

Commit d7fb2d2

Browse files
committed
Deploying to master from @ gfx-rs/wgpu@2f50426 🚀
1 parent 702a738 commit d7fb2d2

File tree

18 files changed

+319
-115
lines changed

18 files changed

+319
-115
lines changed

doc/search-index.js

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

doc/search.desc/wgpu/wgpu-desc-1-.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

doc/src/wgpu/util/belt.rs.html

Lines changed: 195 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -197,56 +197,107 @@
197197
<a href="#196" id="196">196</a>
198198
<a href="#197" id="197">197</a>
199199
<a href="#198" id="198">198</a>
200-
<a href="#199" id="199">199</a></pre></div><pre class="rust"><code><span class="kw">use crate</span>::{
200+
<a href="#199" id="199">199</a>
201+
<a href="#200" id="200">200</a>
202+
<a href="#201" id="201">201</a>
203+
<a href="#202" id="202">202</a>
204+
<a href="#203" id="203">203</a>
205+
<a href="#204" id="204">204</a>
206+
<a href="#205" id="205">205</a>
207+
<a href="#206" id="206">206</a>
208+
<a href="#207" id="207">207</a>
209+
<a href="#208" id="208">208</a>
210+
<a href="#209" id="209">209</a>
211+
<a href="#210" id="210">210</a>
212+
<a href="#211" id="211">211</a>
213+
<a href="#212" id="212">212</a>
214+
<a href="#213" id="213">213</a>
215+
<a href="#214" id="214">214</a>
216+
<a href="#215" id="215">215</a>
217+
<a href="#216" id="216">216</a>
218+
<a href="#217" id="217">217</a>
219+
<a href="#218" id="218">218</a>
220+
<a href="#219" id="219">219</a>
221+
<a href="#220" id="220">220</a>
222+
<a href="#221" id="221">221</a>
223+
<a href="#222" id="222">222</a>
224+
<a href="#223" id="223">223</a>
225+
<a href="#224" id="224">224</a>
226+
<a href="#225" id="225">225</a>
227+
<a href="#226" id="226">226</a>
228+
<a href="#227" id="227">227</a>
229+
<a href="#228" id="228">228</a>
230+
<a href="#229" id="229">229</a>
231+
<a href="#230" id="230">230</a>
232+
<a href="#231" id="231">231</a>
233+
<a href="#232" id="232">232</a>
234+
<a href="#233" id="233">233</a>
235+
<a href="#234" id="234">234</a>
236+
<a href="#235" id="235">235</a>
237+
<a href="#236" id="236">236</a>
238+
<a href="#237" id="237">237</a>
239+
<a href="#238" id="238">238</a>
240+
<a href="#239" id="239">239</a>
241+
<a href="#240" id="240">240</a>
242+
<a href="#241" id="241">241</a>
243+
<a href="#242" id="242">242</a>
244+
<a href="#243" id="243">243</a>
245+
<a href="#244" id="244">244</a>
246+
<a href="#245" id="245">245</a>
247+
<a href="#246" id="246">246</a>
248+
<a href="#247" id="247">247</a>
249+
<a href="#248" id="248">248</a>
250+
<a href="#249" id="249">249</a>
251+
<a href="#250" id="250">250</a>
252+
<a href="#251" id="251">251</a>
253+
<a href="#252" id="252">252</a>
254+
<a href="#253" id="253">253</a>
255+
<a href="#254" id="254">254</a>
256+
<a href="#255" id="255">255</a>
257+
<a href="#256" id="256">256</a>
258+
<a href="#257" id="257">257</a>
259+
<a href="#258" id="258">258</a>
260+
<a href="#259" id="259">259</a>
261+
<a href="#260" id="260">260</a>
262+
<a href="#261" id="261">261</a>
263+
<a href="#262" id="262">262</a>
264+
<a href="#263" id="263">263</a>
265+
<a href="#264" id="264">264</a>
266+
<a href="#265" id="265">265</a>
267+
<a href="#266" id="266">266</a>
268+
<a href="#267" id="267">267</a>
269+
<a href="#268" id="268">268</a>
270+
<a href="#269" id="269">269</a>
271+
<a href="#270" id="270">270</a>
272+
<a href="#271" id="271">271</a>
273+
<a href="#272" id="272">272</a></pre></div><pre class="rust"><code><span class="kw">use crate</span>::{
201274
util::align_to, Buffer, BufferAddress, BufferDescriptor, BufferSize, BufferUsages,
202275
BufferViewMut, CommandEncoder, Device, MapMode,
203276
};
204277
<span class="kw">use </span>std::fmt;
205-
<span class="kw">use </span>std::sync::{mpsc, Arc};
206-
207-
<span class="kw">struct </span>Chunk {
208-
buffer: Arc&lt;Buffer&gt;,
209-
size: BufferAddress,
210-
offset: BufferAddress,
211-
}
212-
213-
<span class="doccomment">/// `Sync` wrapper that works by providing only exclusive access.
214-
///
215-
/// See https://doc.rust-lang.org/nightly/std/sync/struct.Exclusive.html
216-
</span><span class="kw">struct </span>Exclusive&lt;T&gt;(T);
217-
218-
<span class="kw">unsafe impl</span>&lt;T&gt; Sync <span class="kw">for </span>Exclusive&lt;T&gt; {}
219-
220-
<span class="kw">impl</span>&lt;T&gt; Exclusive&lt;T&gt; {
221-
<span class="kw">fn </span>new(value: T) -&gt; <span class="self">Self </span>{
222-
<span class="self">Self</span>(value)
223-
}
224-
225-
<span class="kw">fn </span>get_mut(<span class="kw-2">&amp;mut </span><span class="self">self</span>) -&gt; <span class="kw-2">&amp;mut </span>T {
226-
<span class="kw-2">&amp;mut </span><span class="self">self</span>.<span class="number">0
227-
</span>}
228-
}
278+
<span class="kw">use </span>std::sync::mpsc;
229279

230280
<span class="doccomment">/// Efficiently performs many buffer writes by sharing and reusing temporary buffers.
231281
///
232282
/// Internally it uses a ring-buffer of staging buffers that are sub-allocated.
233-
/// It has an advantage over [`Queue::write_buffer()`] in a way that it returns a mutable slice,
234-
/// which you can fill to avoid an extra data copy.
283+
/// Its advantage over [`Queue::write_buffer_with()`] is that the individual allocations
284+
/// are cheaper; `StagingBelt` is most useful when you are writing very many small pieces
285+
/// of data. It can be understood as a sort of arena allocator.
235286
///
236287
/// Using a staging belt is slightly complicated, and generally goes as follows:
237-
/// 1. Write to buffers that need writing to using [`StagingBelt::write_buffer()`].
288+
/// 1. Use [`StagingBelt::write_buffer()`] or [`StagingBelt::allocate()`] to allocate
289+
/// buffer slices, then write your data to them.
238290
/// 2. Call [`StagingBelt::finish()`].
239291
/// 3. Submit all command encoders that were used in step 1.
240292
/// 4. Call [`StagingBelt::recall()`].
241293
///
242-
/// [`Queue::write_buffer()`]: crate::Queue::write_buffer
294+
/// [`Queue::write_buffer_with()`]: crate::Queue::write_buffer_with
243295
</span><span class="kw">pub struct </span>StagingBelt {
244296
chunk_size: BufferAddress,
245297
<span class="doccomment">/// Chunks into which we are accumulating data to be transferred.
246298
</span>active_chunks: Vec&lt;Chunk&gt;,
247299
<span class="doccomment">/// Chunks that have scheduled transfers already; they are unmapped and some
248-
/// command encoder has one or more `copy_buffer_to_buffer` commands with them
249-
/// as source.
300+
/// command encoder has one or more commands with them as source.
250301
</span>closed_chunks: Vec&lt;Chunk&gt;,
251302
<span class="doccomment">/// Chunks that are back from the GPU and ready to be mapped for write and put
252303
/// into `active_chunks`.
@@ -269,7 +320,7 @@
269320
/// (per [`StagingBelt::finish()`]); and
270321
/// * bigger is better, within these bounds.
271322
</span><span class="kw">pub fn </span>new(chunk_size: BufferAddress) -&gt; <span class="self">Self </span>{
272-
<span class="kw">let </span>(sender, receiver) = std::sync::mpsc::channel();
323+
<span class="kw">let </span>(sender, receiver) = mpsc::channel();
273324
StagingBelt {
274325
chunk_size,
275326
active_chunks: Vec::new(),
@@ -280,7 +331,7 @@
280331
}
281332
}
282333

283-
<span class="doccomment">/// Allocate the staging belt slice of `size` to be uploaded into the `target` buffer
334+
<span class="doccomment">/// Allocate a staging belt slice of `size` to be copied into the `target` buffer
284335
/// at the specified offset.
285336
///
286337
/// The upload will be placed into the provided command encoder. This encoder
@@ -298,10 +349,61 @@
298349
size: BufferSize,
299350
device: <span class="kw-2">&amp;</span>Device,
300351
) -&gt; BufferViewMut&lt;<span class="lifetime">'_</span>&gt; {
352+
<span class="kw">let </span>(mapped, belt_buffer, offset_in_belt_buffer) = <span class="self">self</span>.allocate(
353+
size,
354+
<span class="kw">const </span>{ BufferSize::new(<span class="kw">crate</span>::COPY_BUFFER_ALIGNMENT).unwrap() },
355+
device,
356+
);
357+
encoder.copy_buffer_to_buffer(
358+
belt_buffer,
359+
offset_in_belt_buffer,
360+
target,
361+
offset,
362+
size.get(),
363+
);
364+
mapped
365+
}
366+
367+
<span class="doccomment">/// Allocate a staging belt slice with the given `size` and `alignment` and return it.
368+
///
369+
/// This allows you to do whatever you want with the slice after, such as
370+
/// copying it to a texture or executing a compute shader that reads it, whereas
371+
/// [`StagingBelt::write_buffer()`] can only write to other buffers.
372+
///
373+
/// If the `size` is greater than the space available in any free internal buffer, a new buffer
374+
/// will be allocated for it. Therefore, the `chunk_size` passed to [`StagingBelt::new()`]
375+
/// should ideally be larger than every such size.
376+
///
377+
/// The chosen slice will be positioned within the buffer at a multiple of `alignment`,
378+
/// which may be used to meet alignment requirements for the operation you wish to perform
379+
/// with the slice. This does not necessarily affect the alignment of the mapping.
380+
///
381+
/// Three values are returned:
382+
///
383+
/// * The mapped buffer view which you should write into from the CPU side (Rust code).
384+
/// * The buffer containing the slice, for you to use in GPU commands.
385+
/// All commands involving this slice must be submitted after
386+
/// [`StagingBelt::finish()`] is called and before [`StagingBelt::recall()`] is called.
387+
/// * The offset within the buffer at which the slice starts.
388+
/// This offset should be used for all GPU commands, and should not be used with
389+
/// the mapped buffer view.
390+
</span><span class="kw">pub fn </span>allocate(
391+
<span class="kw-2">&amp;mut </span><span class="self">self</span>,
392+
size: BufferSize,
393+
alignment: BufferSize,
394+
device: <span class="kw-2">&amp;</span>Device,
395+
) -&gt; (BufferViewMut&lt;<span class="lifetime">'_</span>&gt;, <span class="kw-2">&amp;</span>Buffer, BufferAddress) {
396+
<span class="macro">assert!</span>(
397+
alignment.get().is_power_of_two(),
398+
<span class="string">"alignment must be a power of two, not {alignment}"
399+
</span>);
400+
<span class="comment">// At minimum, we must have alignment sufficient to map the buffer.
401+
</span><span class="kw">let </span>alignment = alignment.get().max(<span class="kw">crate</span>::MAP_ALIGNMENT);
402+
301403
<span class="kw">let </span><span class="kw-2">mut </span>chunk = <span class="kw">if let </span><span class="prelude-val">Some</span>(index) = <span class="self">self
302404
</span>.active_chunks
303405
.iter()
304-
.position(|chunk| chunk.offset + size.get() &lt;= chunk.size)
406+
.position(|chunk| chunk.can_allocate(size, alignment))
305407
{
306408
<span class="self">self</span>.active_chunks.swap_remove(index)
307409
} <span class="kw">else </span>{
@@ -310,35 +412,35 @@
310412
</span><span class="kw">if let </span><span class="prelude-val">Some</span>(index) = <span class="self">self
311413
</span>.free_chunks
312414
.iter()
313-
.position(|chunk| size.get() &lt;= chunk.size)
415+
.position(|chunk| chunk.can_allocate(size, alignment))
314416
{
315417
<span class="self">self</span>.free_chunks.swap_remove(index)
316418
} <span class="kw">else </span>{
317-
<span class="kw">let </span>size = <span class="self">self</span>.chunk_size.max(size.get());
318419
Chunk {
319-
buffer: Arc::new(device.create_buffer(<span class="kw-2">&amp;</span>BufferDescriptor {
420+
buffer: device.create_buffer(<span class="kw-2">&amp;</span>BufferDescriptor {
320421
label: <span class="prelude-val">Some</span>(<span class="string">"(wgpu internal) StagingBelt staging buffer"</span>),
321-
size,
422+
size: <span class="self">self</span>.chunk_size.max(size.get()),
322423
usage: BufferUsages::MAP_WRITE | BufferUsages::COPY_SRC,
323424
mapped_at_creation: <span class="bool-val">true</span>,
324-
})),
325-
size,
425+
}),
326426
offset: <span class="number">0</span>,
327427
}
328428
}
329429
};
330430

331-
encoder.copy_buffer_to_buffer(<span class="kw-2">&amp;</span>chunk.buffer, chunk.offset, target, offset, size.get());
332-
<span class="kw">let </span>old_offset = chunk.offset;
333-
chunk.offset = align_to(chunk.offset + size.get(), <span class="kw">crate</span>::MAP_ALIGNMENT);
431+
<span class="kw">let </span>allocation_offset = chunk.allocate(size, alignment);
334432

335433
<span class="self">self</span>.active_chunks.push(chunk);
336-
<span class="self">self</span>.active_chunks
337-
.last()
338-
.unwrap()
339-
.buffer
340-
.slice(old_offset..old_offset + size.get())
341-
.get_mapped_range_mut()
434+
<span class="kw">let </span>chunk = <span class="self">self</span>.active_chunks.last().unwrap();
435+
436+
(
437+
chunk
438+
.buffer
439+
.slice(allocation_offset..allocation_offset + size.get())
440+
.get_mapped_range_mut(),
441+
<span class="kw-2">&amp;</span>chunk.buffer,
442+
allocation_offset,
443+
)
342444
}
343445

344446
<span class="doccomment">/// Prepare currently mapped buffers for use in a submission.
@@ -396,4 +498,48 @@
396498
.finish_non_exhaustive()
397499
}
398500
}
501+
502+
<span class="kw">struct </span>Chunk {
503+
buffer: Buffer,
504+
offset: BufferAddress,
505+
}
506+
507+
<span class="kw">impl </span>Chunk {
508+
<span class="kw">fn </span>can_allocate(<span class="kw-2">&amp;</span><span class="self">self</span>, size: BufferSize, alignment: BufferAddress) -&gt; bool {
509+
<span class="kw">let </span>alloc_start = align_to(<span class="self">self</span>.offset, alignment);
510+
<span class="kw">let </span>alloc_end = alloc_start + size.get();
511+
512+
alloc_end &lt;= <span class="self">self</span>.buffer.size()
513+
}
514+
515+
<span class="kw">fn </span>allocate(<span class="kw-2">&amp;mut </span><span class="self">self</span>, size: BufferSize, alignment: BufferAddress) -&gt; BufferAddress {
516+
<span class="kw">let </span>alloc_start = align_to(<span class="self">self</span>.offset, alignment);
517+
<span class="kw">let </span>alloc_end = alloc_start + size.get();
518+
519+
<span class="macro">assert!</span>(alloc_end &lt;= <span class="self">self</span>.buffer.size());
520+
<span class="self">self</span>.offset = alloc_end;
521+
alloc_start
522+
}
523+
}
524+
525+
<span class="kw">use </span>exclusive::Exclusive;
526+
<span class="kw">mod </span>exclusive {
527+
<span class="doccomment">/// `Sync` wrapper that works by providing only exclusive access.
528+
///
529+
/// See &lt;https://doc.rust-lang.org/nightly/std/sync/struct.Exclusive.html&gt;
530+
</span><span class="kw">pub</span>(<span class="kw">super</span>) <span class="kw">struct </span>Exclusive&lt;T&gt;(T);
531+
532+
<span class="doccomment">/// Safety: `&amp;Exclusive` has no operations.
533+
</span><span class="kw">unsafe impl</span>&lt;T&gt; Sync <span class="kw">for </span>Exclusive&lt;T&gt; {}
534+
535+
<span class="kw">impl</span>&lt;T&gt; Exclusive&lt;T&gt; {
536+
<span class="kw">pub fn </span>new(value: T) -&gt; <span class="self">Self </span>{
537+
<span class="self">Self</span>(value)
538+
}
539+
540+
<span class="kw">pub fn </span>get_mut(<span class="kw-2">&amp;mut </span><span class="self">self</span>) -&gt; <span class="kw-2">&amp;mut </span>T {
541+
<span class="kw-2">&amp;mut </span><span class="self">self</span>.<span class="number">0
542+
</span>}
543+
}
544+
}
399545
</code></pre></div></section></main></body></html>

doc/trait.impl/core/marker/trait.Freeze.js

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

doc/trait.impl/core/marker/trait.Send.js

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

doc/trait.impl/core/marker/trait.Sync.js

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

doc/trait.impl/core/marker/trait.Unpin.js

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

doc/trait.impl/core/panic/unwind_safe/trait.RefUnwindSafe.js

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

doc/trait.impl/core/panic/unwind_safe/trait.UnwindSafe.js

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

doc/wgpu/all.html

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)