|
1762 | 1762 | <a href="#1761" id="1761">1761</a> |
1763 | 1763 | <a href="#1762" id="1762">1762</a> |
1764 | 1764 | <a href="#1763" id="1763">1763</a> |
1765 | | -<a href="#1764" id="1764">1764</a></pre></div><pre class="rust"><code><span class="doccomment">/*! Render Bundles |
| 1765 | +<a href="#1764" id="1764">1764</a> |
| 1766 | +<a href="#1765" id="1765">1765</a> |
| 1767 | +<a href="#1766" id="1766">1766</a> |
| 1768 | +<a href="#1767" id="1767">1767</a> |
| 1769 | +<a href="#1768" id="1768">1768</a> |
| 1770 | +<a href="#1769" id="1769">1769</a> |
| 1771 | +<a href="#1770" id="1770">1770</a> |
| 1772 | +<a href="#1771" id="1771">1771</a> |
| 1773 | +<a href="#1772" id="1772">1772</a> |
| 1774 | +<a href="#1773" id="1773">1773</a> |
| 1775 | +<a href="#1774" id="1774">1774</a> |
| 1776 | +<a href="#1775" id="1775">1775</a> |
| 1777 | +<a href="#1776" id="1776">1776</a> |
| 1778 | +<a href="#1777" id="1777">1777</a> |
| 1779 | +<a href="#1778" id="1778">1778</a> |
| 1780 | +<a href="#1779" id="1779">1779</a> |
| 1781 | +<a href="#1780" id="1780">1780</a> |
| 1782 | +<a href="#1781" id="1781">1781</a> |
| 1783 | +<a href="#1782" id="1782">1782</a> |
| 1784 | +<a href="#1783" id="1783">1783</a></pre></div><pre class="rust"><code><span class="doccomment">/*! Render Bundles |
1766 | 1785 |
|
1767 | 1786 | A render bundle is a prerecorded sequence of commands that can be replayed on a |
1768 | 1787 | command encoder with a single call. A single bundle can replayed any number of |
|
1857 | 1876 | <span class="kw">use </span>arrayvec::ArrayVec; |
1858 | 1877 | <span class="kw">use </span>thiserror::Error; |
1859 | 1878 |
|
| 1879 | +<span class="kw">use </span>wgpu_hal::ShouldBeNonZeroExt; |
1860 | 1880 | <span class="kw">use </span>wgt::error::{ErrorType, WebGpuError}; |
1861 | 1881 |
|
1862 | 1882 | <span class="kw">use crate</span>::{ |
|
2366 | 2386 | <span class="prelude-val">Ok</span>(()) |
2367 | 2387 | } |
2368 | 2388 |
|
2369 | | -<span class="kw">fn </span>set_index_buffer( |
| 2389 | +<span class="comment">// This function is duplicative of `render::set_index_buffer`. |
| 2390 | +</span><span class="kw">fn </span>set_index_buffer( |
2370 | 2391 | state: <span class="kw-2">&mut </span>State, |
2371 | 2392 | buffer_guard: <span class="kw-2">&</span><span class="kw">crate</span>::storage::Storage<Fallible<Buffer>>, |
2372 | 2393 | buffer_id: id::Id<id::markers::Buffer>, |
|
2384 | 2405 | buffer.same_device(<span class="kw-2">&</span>state.device)<span class="question-mark">?</span>; |
2385 | 2406 | buffer.check_usage(wgt::BufferUsages::INDEX)<span class="question-mark">?</span>; |
2386 | 2407 |
|
2387 | | - <span class="kw">let </span>end = <span class="kw">match </span>size { |
2388 | | - <span class="prelude-val">Some</span>(s) => offset + s.get(), |
2389 | | - <span class="prelude-val">None </span>=> buffer.size, |
2390 | | - }; |
| 2408 | + <span class="kw">let </span>end = offset + buffer.resolve_binding_size(offset, size)<span class="question-mark">?</span>; |
| 2409 | + |
2391 | 2410 | state |
2392 | 2411 | .buffer_memory_init_actions |
2393 | 2412 | .extend(buffer.initialization_status.read().create_action( |
2394 | 2413 | <span class="kw-2">&</span>buffer, |
2395 | | - offset..end, |
| 2414 | + offset..end.get(), |
2396 | 2415 | MemoryInitKind::NeedsInitializedMemory, |
2397 | 2416 | )); |
2398 | | - state.set_index_buffer(buffer, index_format, offset..end); |
| 2417 | + state.set_index_buffer(buffer, index_format, offset..end.get()); |
2399 | 2418 | <span class="prelude-val">Ok</span>(()) |
2400 | 2419 | } |
2401 | 2420 |
|
2402 | | -<span class="kw">fn </span>set_vertex_buffer( |
| 2421 | +<span class="comment">// This function is duplicative of `render::set_vertex_buffer`. |
| 2422 | +</span><span class="kw">fn </span>set_vertex_buffer( |
2403 | 2423 | state: <span class="kw-2">&mut </span>State, |
2404 | 2424 | buffer_guard: <span class="kw-2">&</span><span class="kw">crate</span>::storage::Storage<Fallible<Buffer>>, |
2405 | 2425 | slot: u32, |
|
2426 | 2446 | buffer.same_device(<span class="kw-2">&</span>state.device)<span class="question-mark">?</span>; |
2427 | 2447 | buffer.check_usage(wgt::BufferUsages::VERTEX)<span class="question-mark">?</span>; |
2428 | 2448 |
|
2429 | | - <span class="kw">let </span>end = <span class="kw">match </span>size { |
2430 | | - <span class="prelude-val">Some</span>(s) => offset + s.get(), |
2431 | | - <span class="prelude-val">None </span>=> buffer.size, |
2432 | | - }; |
| 2449 | + <span class="kw">let </span>end = offset + buffer.resolve_binding_size(offset, size)<span class="question-mark">?</span>; |
| 2450 | + |
2433 | 2451 | state |
2434 | 2452 | .buffer_memory_init_actions |
2435 | 2453 | .extend(buffer.initialization_status.read().create_action( |
2436 | 2454 | <span class="kw-2">&</span>buffer, |
2437 | | - offset..end, |
| 2455 | + offset..end.get(), |
2438 | 2456 | MemoryInitKind::NeedsInitializedMemory, |
2439 | 2457 | )); |
2440 | | - state.vertex[slot <span class="kw">as </span>usize] = <span class="prelude-val">Some</span>(VertexState::new(buffer, offset..end)); |
| 2458 | + state.vertex[slot <span class="kw">as </span>usize] = <span class="prelude-val">Some</span>(VertexState::new(buffer, offset..end.get())); |
2441 | 2459 | <span class="prelude-val">Ok</span>(()) |
2442 | 2460 | } |
2443 | 2461 |
|
|
2729 | 2747 | size, |
2730 | 2748 | } => { |
2731 | 2749 | <span class="kw">let </span>buffer = buffer.try_raw(snatch_guard)<span class="question-mark">?</span>; |
2732 | | - <span class="kw">let </span>bb = hal::BufferBinding { |
2733 | | - buffer, |
2734 | | - offset: <span class="kw-2">*</span>offset, |
2735 | | - size: <span class="kw-2">*</span>size, |
2736 | | - }; |
| 2750 | + <span class="comment">// SAFETY: The binding size was checked against the buffer size |
| 2751 | + // in `set_index_buffer` and again in `IndexState::flush`. |
| 2752 | + </span><span class="kw">let </span>bb = hal::BufferBinding::new_unchecked(buffer, <span class="kw-2">*</span>offset, <span class="kw-2">*</span>size); |
2737 | 2753 | <span class="kw">unsafe </span>{ raw.set_index_buffer(bb, <span class="kw-2">*</span>index_format) }; |
2738 | 2754 | } |
2739 | 2755 | Cmd::SetVertexBuffer { |
|
2743 | 2759 | size, |
2744 | 2760 | } => { |
2745 | 2761 | <span class="kw">let </span>buffer = buffer.try_raw(snatch_guard)<span class="question-mark">?</span>; |
2746 | | - <span class="kw">let </span>bb = hal::BufferBinding { |
2747 | | - buffer, |
2748 | | - offset: <span class="kw-2">*</span>offset, |
2749 | | - size: <span class="kw-2">*</span>size, |
2750 | | - }; |
| 2762 | + <span class="comment">// SAFETY: The binding size was checked against the buffer size |
| 2763 | + // in `set_vertex_buffer` and again in `VertexState::flush`. |
| 2764 | + </span><span class="kw">let </span>bb = hal::BufferBinding::new_unchecked(buffer, <span class="kw-2">*</span>offset, <span class="kw-2">*</span>size); |
2751 | 2765 | <span class="kw">unsafe </span>{ raw.set_vertex_buffer(<span class="kw-2">*</span>slot, bb) }; |
2752 | 2766 | } |
2753 | 2767 | Cmd::SetPushConstant { |
|
2895 | 2909 | /// [`RenderBundleEncoder::finish`] records the currently set index buffer here, |
2896 | 2910 | /// and calls [`State::flush_index`] before any indexed draw command to produce |
2897 | 2911 | /// a `SetIndexBuffer` command if one is necessary. |
| 2912 | +/// |
| 2913 | +/// Binding ranges must be validated against the size of the buffer before |
| 2914 | +/// being stored in `IndexState`. |
2898 | 2915 | </span><span class="attr">#[derive(Debug)] |
2899 | 2916 | </span><span class="kw">struct </span>IndexState { |
2900 | 2917 | buffer: Arc<Buffer>, |
|
2916 | 2933 | <span class="doccomment">/// Generate a `SetIndexBuffer` command to prepare for an indexed draw |
2917 | 2934 | /// command, if needed. |
2918 | 2935 | </span><span class="kw">fn </span>flush(<span class="kw-2">&mut </span><span class="self">self</span>) -> <span class="prelude-ty">Option</span><ArcRenderCommand> { |
| 2936 | + <span class="comment">// This was all checked before, but let's check again just in case. |
| 2937 | + </span><span class="kw">let </span>binding_size = <span class="self">self |
| 2938 | + </span>.range |
| 2939 | + .end |
| 2940 | + .checked_sub(<span class="self">self</span>.range.start) |
| 2941 | + .filter(|<span class="kw">_</span>| <span class="self">self</span>.range.end <= <span class="self">self</span>.buffer.size) |
| 2942 | + .expect(<span class="string">"index range must be contained in buffer"</span>); |
| 2943 | + |
2919 | 2944 | <span class="kw">if </span><span class="self">self</span>.is_dirty { |
2920 | 2945 | <span class="self">self</span>.is_dirty = <span class="bool-val">false</span>; |
2921 | 2946 | <span class="prelude-val">Some</span>(ArcRenderCommand::SetIndexBuffer { |
2922 | 2947 | buffer: <span class="self">self</span>.buffer.clone(), |
2923 | 2948 | index_format: <span class="self">self</span>.format, |
2924 | 2949 | offset: <span class="self">self</span>.range.start, |
2925 | | - size: wgt::BufferSize::new(<span class="self">self</span>.range.end - <span class="self">self</span>.range.start), |
| 2950 | + size: NonZeroU64::new(binding_size), |
2926 | 2951 | }) |
2927 | 2952 | } <span class="kw">else </span>{ |
2928 | 2953 | <span class="prelude-val">None |
|
2938 | 2963 | /// calls this type's [`flush`] method just before any draw command to |
2939 | 2964 | /// produce a `SetVertexBuffer` commands if one is necessary. |
2940 | 2965 | /// |
| 2966 | +/// Binding ranges must be validated against the size of the buffer before |
| 2967 | +/// being stored in `VertexState`. |
| 2968 | +/// |
2941 | 2969 | /// [`flush`]: IndexState::flush |
2942 | 2970 | </span><span class="attr">#[derive(Debug)] |
2943 | 2971 | </span><span class="kw">struct </span>VertexState { |
|
2947 | 2975 | } |
2948 | 2976 |
|
2949 | 2977 | <span class="kw">impl </span>VertexState { |
2950 | | - <span class="kw">fn </span>new(buffer: Arc<Buffer>, range: Range<wgt::BufferAddress>) -> <span class="self">Self </span>{ |
| 2978 | + <span class="doccomment">/// Create a new `VertexState`. |
| 2979 | + /// |
| 2980 | + /// The `range` must be contained within `buffer`. |
| 2981 | + </span><span class="kw">fn </span>new(buffer: Arc<Buffer>, range: Range<wgt::BufferAddress>) -> <span class="self">Self </span>{ |
2951 | 2982 | <span class="self">Self </span>{ |
2952 | 2983 | buffer, |
2953 | 2984 | range, |
|
2959 | 2990 | /// |
2960 | 2991 | /// `slot` is the index of the vertex buffer slot that `self` tracks. |
2961 | 2992 | </span><span class="kw">fn </span>flush(<span class="kw-2">&mut </span><span class="self">self</span>, slot: u32) -> <span class="prelude-ty">Option</span><ArcRenderCommand> { |
| 2993 | + <span class="kw">let </span>binding_size = <span class="self">self |
| 2994 | + </span>.range |
| 2995 | + .end |
| 2996 | + .checked_sub(<span class="self">self</span>.range.start) |
| 2997 | + .filter(|<span class="kw">_</span>| <span class="self">self</span>.range.end <= <span class="self">self</span>.buffer.size) |
| 2998 | + .expect(<span class="string">"vertex range must be contained in buffer"</span>); |
| 2999 | + |
2962 | 3000 | <span class="kw">if </span><span class="self">self</span>.is_dirty { |
2963 | 3001 | <span class="self">self</span>.is_dirty = <span class="bool-val">false</span>; |
2964 | 3002 | <span class="prelude-val">Some</span>(ArcRenderCommand::SetVertexBuffer { |
2965 | 3003 | slot, |
2966 | 3004 | buffer: <span class="self">self</span>.buffer.clone(), |
2967 | 3005 | offset: <span class="self">self</span>.range.start, |
2968 | | - size: wgt::BufferSize::new(<span class="self">self</span>.range.end - <span class="self">self</span>.range.start), |
| 3006 | + size: NonZeroU64::new(binding_size), |
2969 | 3007 | }) |
2970 | 3008 | } <span class="kw">else </span>{ |
2971 | 3009 | <span class="prelude-val">None |
|
0 commit comments