cart_tmp_wgc/command/
mod.rs

1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5mod allocator;
6mod bind;
7mod bundle;
8mod compute;
9mod render;
10mod transfer;
11
12pub(crate) use self::allocator::CommandAllocator;
13pub use self::bundle::*;
14pub use self::compute::*;
15pub use self::render::*;
16pub use self::transfer::*;
17
18use crate::{
19    device::{all_buffer_stages, all_image_stages},
20    hub::{GfxBackend, Global, GlobalIdentityHandlerFactory, Storage, Token},
21    id,
22    resource::{Buffer, Texture},
23    span,
24    track::TrackerSet,
25    PrivateFeatures, Stored,
26};
27
28use hal::command::CommandBuffer as _;
29
30use std::thread::ThreadId;
31
32#[derive(Debug)]
33pub struct CommandBuffer<B: hal::Backend> {
34    pub(crate) raw: Vec<B::CommandBuffer>,
35    is_recording: bool,
36    recorded_thread_id: ThreadId,
37    pub(crate) device_id: Stored<id::DeviceId>,
38    pub(crate) trackers: TrackerSet,
39    pub(crate) used_swap_chain: Option<(Stored<id::SwapChainId>, B::Framebuffer)>,
40    limits: wgt::Limits,
41    private_features: PrivateFeatures,
42    #[cfg(feature = "trace")]
43    pub(crate) commands: Option<Vec<crate::device::trace::Command>>,
44}
45
46impl<B: GfxBackend> CommandBuffer<B> {
47    pub(crate) fn insert_barriers(
48        raw: &mut B::CommandBuffer,
49        base: &mut TrackerSet,
50        head: &TrackerSet,
51        buffer_guard: &Storage<Buffer<B>, id::BufferId>,
52        texture_guard: &Storage<Texture<B>, id::TextureId>,
53    ) {
54        use hal::command::CommandBuffer as _;
55
56        debug_assert_eq!(B::VARIANT, base.backend());
57        debug_assert_eq!(B::VARIANT, head.backend());
58
59        let buffer_barriers = base.buffers.merge_replace(&head.buffers).map(|pending| {
60            let buf = &buffer_guard[pending.id];
61            pending.into_hal(buf)
62        });
63        let texture_barriers = base.textures.merge_replace(&head.textures).map(|pending| {
64            let tex = &texture_guard[pending.id];
65            pending.into_hal(tex)
66        });
67        base.views.merge_extend(&head.views).unwrap();
68        base.bind_groups.merge_extend(&head.bind_groups).unwrap();
69        base.samplers.merge_extend(&head.samplers).unwrap();
70        base.compute_pipes
71            .merge_extend(&head.compute_pipes)
72            .unwrap();
73        base.render_pipes.merge_extend(&head.render_pipes).unwrap();
74        base.bundles.merge_extend(&head.bundles).unwrap();
75
76        let stages = all_buffer_stages() | all_image_stages();
77        unsafe {
78            raw.pipeline_barrier(
79                stages..stages,
80                hal::memory::Dependencies::empty(),
81                buffer_barriers.chain(texture_barriers),
82            );
83        }
84    }
85}
86
87#[derive(Copy, Clone, Debug)]
88pub struct BasePassRef<'a, C> {
89    pub commands: &'a [C],
90    pub dynamic_offsets: &'a [wgt::DynamicOffset],
91    pub string_data: &'a [u8],
92}
93
94#[doc(hidden)]
95#[derive(Debug)]
96#[cfg_attr(
97    any(feature = "serial-pass", feature = "trace"),
98    derive(serde::Serialize)
99)]
100#[cfg_attr(
101    any(feature = "serial-pass", feature = "replay"),
102    derive(serde::Deserialize)
103)]
104pub struct BasePass<C> {
105    pub commands: Vec<C>,
106    pub dynamic_offsets: Vec<wgt::DynamicOffset>,
107    pub string_data: Vec<u8>,
108}
109
110impl<C: Clone> BasePass<C> {
111    fn new() -> Self {
112        BasePass {
113            commands: Vec::new(),
114            dynamic_offsets: Vec::new(),
115            string_data: Vec::new(),
116        }
117    }
118
119    #[cfg(feature = "trace")]
120    fn from_ref(base: BasePassRef<C>) -> Self {
121        BasePass {
122            commands: base.commands.to_vec(),
123            dynamic_offsets: base.dynamic_offsets.to_vec(),
124            string_data: base.string_data.to_vec(),
125        }
126    }
127
128    pub fn as_ref(&self) -> BasePassRef<C> {
129        BasePassRef {
130            commands: &self.commands,
131            dynamic_offsets: &self.dynamic_offsets,
132            string_data: &self.string_data,
133        }
134    }
135}
136
137impl<G: GlobalIdentityHandlerFactory> Global<G> {
138    pub fn command_encoder_finish<B: GfxBackend>(
139        &self,
140        encoder_id: id::CommandEncoderId,
141        _desc: &wgt::CommandBufferDescriptor,
142    ) -> id::CommandBufferId {
143        span!(_guard, INFO, "CommandEncoder::finish");
144
145        let hub = B::hub(self);
146        let mut token = Token::root();
147        let (swap_chain_guard, mut token) = hub.swap_chains.read(&mut token);
148        //TODO: actually close the last recorded command buffer
149        let (mut comb_guard, _) = hub.command_buffers.write(&mut token);
150        let comb = &mut comb_guard[encoder_id];
151        assert!(comb.is_recording, "Command buffer must be recording");
152        comb.is_recording = false;
153        // stop tracking the swapchain image, if used
154        if let Some((ref sc_id, _)) = comb.used_swap_chain {
155            let view_id = swap_chain_guard[sc_id.value]
156                .acquired_view_id
157                .as_ref()
158                .expect("Used swap chain frame has already presented");
159            comb.trackers.views.remove(view_id.value);
160        }
161        log::trace!("Command buffer {:?} {:#?}", encoder_id, comb.trackers);
162        encoder_id
163    }
164
165    pub fn command_encoder_push_debug_group<B: GfxBackend>(
166        &self,
167        encoder_id: id::CommandEncoderId,
168        label: &str,
169    ) {
170        span!(_guard, DEBUG, "CommandEncoder::push_debug_group");
171
172        let hub = B::hub(self);
173        let mut token = Token::root();
174
175        let (mut cmb_guard, _) = hub.command_buffers.write(&mut token);
176        let cmb = &mut cmb_guard[encoder_id];
177        let cmb_raw = cmb.raw.last_mut().unwrap();
178
179        unsafe {
180            cmb_raw.begin_debug_marker(label, 0);
181        }
182    }
183
184    pub fn command_encoder_insert_debug_marker<B: GfxBackend>(
185        &self,
186        encoder_id: id::CommandEncoderId,
187        label: &str,
188    ) {
189        span!(_guard, DEBUG, "CommandEncoder::insert_debug_marker");
190
191        let hub = B::hub(self);
192        let mut token = Token::root();
193
194        let (mut cmb_guard, _) = hub.command_buffers.write(&mut token);
195        let cmb = &mut cmb_guard[encoder_id];
196        let cmb_raw = cmb.raw.last_mut().unwrap();
197
198        unsafe {
199            cmb_raw.insert_debug_marker(label, 0);
200        }
201    }
202
203    pub fn command_encoder_pop_debug_group<B: GfxBackend>(&self, encoder_id: id::CommandEncoderId) {
204        span!(_guard, DEBUG, "CommandEncoder::pop_debug_marker");
205
206        let hub = B::hub(self);
207        let mut token = Token::root();
208
209        let (mut cmb_guard, _) = hub.command_buffers.write(&mut token);
210        let cmb = &mut cmb_guard[encoder_id];
211        let cmb_raw = cmb.raw.last_mut().unwrap();
212
213        unsafe {
214            cmb_raw.end_debug_marker();
215        }
216    }
217}