wgpu_core/command/
transition_resources.rs1use alloc::{sync::Arc, vec::Vec};
2
3use thiserror::Error;
4use wgt::error::{ErrorType, WebGpuError};
5
6use crate::{
7 command::{encoder::EncodingState, ArcCommand, CommandEncoder, EncoderStateError},
8 device::DeviceError,
9 global::Global,
10 id::{BufferId, CommandEncoderId, TextureId},
11 resource::{Buffer, InvalidResourceError, ParentDevice, Texture},
12 track::ResourceUsageCompatibilityError,
13};
14
15impl CommandEncoder {
16 pub fn transition_resources(
17 self: &Arc<Self>,
18 buffer_transitions: impl Iterator<Item = wgt::BufferTransition<Arc<Buffer>>>,
19 texture_transitions: impl Iterator<Item = wgt::TextureTransition<Arc<Texture>>>,
20 ) -> Result<(), EncoderStateError> {
21 profiling::scope!("CommandEncoder::transition_resources");
22
23 let mut cmd_buf_data = self.data.lock();
25 cmd_buf_data.push_with(|| -> Result<_, TransitionResourcesError> {
26 Ok(ArcCommand::TransitionResources {
27 buffer_transitions: buffer_transitions
28 .map(|t| {
29 t.buffer.check_is_valid()?;
30 Ok(wgt::BufferTransition {
31 buffer: t.buffer,
32 state: t.state,
33 })
34 })
35 .collect::<Result<_, TransitionResourcesError>>()?,
36 texture_transitions: texture_transitions
37 .map(|t| {
38 t.texture.check_valid()?;
39 Ok(wgt::TextureTransition {
40 texture: t.texture,
41 selector: t.selector,
42 state: t.state,
43 })
44 })
45 .collect::<Result<_, TransitionResourcesError>>()?,
46 })
47 })
48 }
49}
50
51impl Global {
52 pub fn command_encoder_transition_resources(
53 &self,
54 command_encoder_id: CommandEncoderId,
55 buffer_transitions: impl Iterator<Item = wgt::BufferTransition<BufferId>>,
56 texture_transitions: impl Iterator<Item = wgt::TextureTransition<TextureId>>,
57 ) -> Result<(), EncoderStateError> {
58 let hub = &self.hub;
59
60 let cmd_enc = hub.command_encoders.get(command_encoder_id);
61 let buffer_transitions = buffer_transitions
62 .map(|t| {
63 let buffer = hub.buffers.get(t.buffer);
64 wgt::BufferTransition {
65 buffer,
66 state: t.state,
67 }
68 })
69 .collect::<Vec<_>>();
70 let texture_transitions = texture_transitions
71 .map(|t| {
72 let texture = hub.textures.get(t.texture);
73 wgt::TextureTransition {
74 texture,
75 selector: t.selector,
76 state: t.state,
77 }
78 })
79 .collect::<Vec<_>>();
80 cmd_enc.transition_resources(
81 buffer_transitions.into_iter(),
82 texture_transitions.into_iter(),
83 )
84 }
85}
86
87pub(crate) fn transition_resources(
88 state: &mut EncodingState,
89 buffer_transitions: Vec<wgt::BufferTransition<Arc<Buffer>>>,
90 texture_transitions: Vec<wgt::TextureTransition<Arc<Texture>>>,
91) -> Result<(), TransitionResourcesError> {
92 let mut usage_scope = state.device.new_usage_scope();
93 let indices = &state.device.tracker_indices;
94 usage_scope.buffers.set_size(indices.buffers.size());
95 usage_scope.textures.set_size(indices.textures.size());
96
97 for buffer_transition in buffer_transitions {
99 buffer_transition.buffer.same_device(state.device)?;
100
101 usage_scope
102 .buffers
103 .merge_single(&buffer_transition.buffer, buffer_transition.state)?;
104 }
105
106 for texture_transition in texture_transitions {
108 texture_transition.texture.same_device(state.device)?;
109
110 unsafe {
111 usage_scope.textures.merge_single(
112 &texture_transition.texture,
113 texture_transition.selector,
114 texture_transition.state,
115 )
116 }?;
117 }
118
119 CommandEncoder::insert_barriers_from_scope(
121 state.raw_encoder,
122 state.tracker,
123 &usage_scope,
124 state.snatch_guard,
125 );
126 Ok(())
127}
128
129#[derive(Clone, Debug, Error)]
131#[non_exhaustive]
132pub enum TransitionResourcesError {
133 #[error(transparent)]
134 Device(#[from] DeviceError),
135 #[error(transparent)]
136 EncoderState(#[from] EncoderStateError),
137 #[error(transparent)]
138 InvalidResource(#[from] InvalidResourceError),
139 #[error(transparent)]
140 ResourceUsage(#[from] ResourceUsageCompatibilityError),
141}
142
143impl WebGpuError for TransitionResourcesError {
144 fn webgpu_error_type(&self) -> ErrorType {
145 match self {
146 Self::Device(e) => e.webgpu_error_type(),
147 Self::EncoderState(e) => e.webgpu_error_type(),
148 Self::InvalidResource(e) => e.webgpu_error_type(),
149 Self::ResourceUsage(e) => e.webgpu_error_type(),
150 }
151 }
152}