wgpu_core/command/
transition_resources.rs

1use thiserror::Error;
2
3use crate::{
4    command::CommandBuffer,
5    device::DeviceError,
6    global::Global,
7    id::{BufferId, CommandEncoderId, TextureId},
8    resource::{InvalidResourceError, ParentDevice},
9    track::ResourceUsageCompatibilityError,
10};
11
12use super::CommandEncoderError;
13
14impl Global {
15    pub fn command_encoder_transition_resources(
16        &self,
17        command_encoder_id: CommandEncoderId,
18        buffer_transitions: impl Iterator<Item = wgt::BufferTransition<BufferId>>,
19        texture_transitions: impl Iterator<Item = wgt::TextureTransition<TextureId>>,
20    ) -> Result<(), TransitionResourcesError> {
21        profiling::scope!("CommandEncoder::transition_resources");
22
23        let hub = &self.hub;
24
25        // Lock command encoder for recording
26        let cmd_buf = hub
27            .command_buffers
28            .get(command_encoder_id.into_command_buffer_id());
29        let mut cmd_buf_data = cmd_buf.data.lock();
30        let mut cmd_buf_data_guard = cmd_buf_data.record()?;
31        let cmd_buf_data = &mut *cmd_buf_data_guard;
32
33        // Get and lock device
34        let device = &cmd_buf.device;
35        device.check_is_valid()?;
36        let snatch_guard = &device.snatchable_lock.read();
37
38        let mut usage_scope = device.new_usage_scope();
39        let indices = &device.tracker_indices;
40        usage_scope.buffers.set_size(indices.buffers.size());
41        usage_scope.textures.set_size(indices.textures.size());
42
43        // Process buffer transitions
44        for buffer_transition in buffer_transitions {
45            let buffer = hub.buffers.get(buffer_transition.buffer).get()?;
46            buffer.same_device_as(cmd_buf.as_ref())?;
47
48            usage_scope
49                .buffers
50                .merge_single(&buffer, buffer_transition.state)?;
51        }
52
53        // Process texture transitions
54        for texture_transition in texture_transitions {
55            let texture = hub.textures.get(texture_transition.texture).get()?;
56            texture.same_device_as(cmd_buf.as_ref())?;
57
58            unsafe {
59                usage_scope.textures.merge_single(
60                    &texture,
61                    texture_transition.selector,
62                    texture_transition.state,
63                )
64            }?;
65        }
66
67        // Record any needed barriers based on tracker data
68        let cmd_buf_raw = cmd_buf_data.encoder.open()?;
69        CommandBuffer::insert_barriers_from_scope(
70            cmd_buf_raw,
71            &mut cmd_buf_data.trackers,
72            &usage_scope,
73            snatch_guard,
74        );
75        cmd_buf_data_guard.mark_successful();
76
77        Ok(())
78    }
79}
80
81/// Error encountered while attempting to perform [`Global::command_encoder_transition_resources`].
82#[derive(Clone, Debug, Error)]
83#[non_exhaustive]
84pub enum TransitionResourcesError {
85    #[error(transparent)]
86    Device(#[from] DeviceError),
87    #[error(transparent)]
88    Encoder(#[from] CommandEncoderError),
89    #[error(transparent)]
90    InvalidResource(#[from] InvalidResourceError),
91    #[error(transparent)]
92    ResourceUsage(#[from] ResourceUsageCompatibilityError),
93}