@@ -86,6 +86,8 @@ pub(crate) enum CommandEncoderStatus {
8686 /// <https://www.w3.org/TR/webgpu/#encoder-state-locked>
8787 Locked ( CommandBufferMutable ) ,
8888
89+ Consumed ,
90+
8991 /// Command recording is complete, and the buffer is ready for submission.
9092 ///
9193 /// [`Global::command_encoder_finish`] transitions a
@@ -145,9 +147,7 @@ impl CommandEncoderStatus {
145147 // Encoder is ended. Invalidate the encoder, do not record anything,
146148 // and return an immediate validation error.
147149 Self :: Finished ( _) => Err ( self . invalidate ( EncoderStateError :: Ended ) ) ,
148- Self :: Error ( CommandEncoderError :: State ( EncoderStateError :: Ended ) ) => {
149- Err ( EncoderStateError :: Ended )
150- }
150+ Self :: Consumed => Err ( EncoderStateError :: Ended ) ,
151151 // Encoder is already invalid. Do not record anything, but do not
152152 // return an immediate validation error.
153153 Self :: Error ( _) => Ok ( ( ) ) ,
@@ -176,7 +176,7 @@ impl CommandEncoderStatus {
176176 self . invalidate ( EncoderStateError :: Ended ) ;
177177 f ( None )
178178 }
179- Self :: Error ( CommandEncoderError :: State ( EncoderStateError :: Ended ) ) => f ( None ) ,
179+ Self :: Consumed => f ( None ) ,
180180 Self :: Error ( _) => f ( None ) ,
181181 Self :: Transitioning => unreachable ! ( ) ,
182182 }
@@ -190,6 +190,7 @@ impl CommandEncoderStatus {
190190 // playing back a recorded trace. If only to avoid having to
191191 // implement serialization for all the error types, we don't support
192192 // storing the errors in a trace.
193+ Self :: Consumed => unreachable ! ( "command encoder is consumed" ) ,
193194 Self :: Error ( _) => unreachable ! ( "passes in a trace do not store errors" ) ,
194195 Self :: Transitioning => unreachable ! ( ) ,
195196 }
@@ -214,7 +215,7 @@ impl CommandEncoderStatus {
214215 Err ( EncoderStateError :: Ended )
215216 }
216217 Self :: Locked ( _) => Err ( self . invalidate ( EncoderStateError :: Locked ) ) ,
217- st @ Self :: Error ( CommandEncoderError :: State ( EncoderStateError :: Ended ) ) => {
218+ st @ Self :: Consumed => {
218219 * self = st;
219220 Err ( EncoderStateError :: Ended )
220221 }
@@ -262,7 +263,7 @@ impl CommandEncoderStatus {
262263 * self = Self :: Error ( EncoderStateError :: Unlocked . into ( ) ) ;
263264 Err ( EncoderStateError :: Unlocked )
264265 }
265- st @ Self :: Error ( CommandEncoderError :: State ( EncoderStateError :: Ended ) ) => {
266+ st @ Self :: Consumed => {
266267 * self = st;
267268 Err ( EncoderStateError :: Ended )
268269 }
@@ -276,21 +277,22 @@ impl CommandEncoderStatus {
276277 }
277278 }
278279
279- fn finish ( & mut self ) -> Result < ( ) , CommandEncoderError > {
280- match mem:: replace ( self , Self :: Transitioning ) {
280+ fn finish ( & mut self ) -> Self {
281+ // Replace our state with `Consumed`, and return either the inner
282+ // state or an error, to be transferred to the command buffer.
283+ match mem:: replace ( self , Self :: Consumed ) {
281284 Self :: Recording ( mut inner) => {
282- if let Err ( e ) = inner. encoder . close_if_open ( ) {
283- Err ( self . invalidate ( e . into ( ) ) )
285+ if let Err ( err ) = inner. encoder . close_if_open ( ) {
286+ Self :: Error ( err . into ( ) )
284287 } else {
285- * self = Self :: Finished ( inner) ;
286288 // Note: if we want to stop tracking the swapchain texture view,
287289 // this is the place to do it.
288- Ok ( ( ) )
290+ Self :: Finished ( inner )
289291 }
290292 }
291- Self :: Finished ( _) => Err ( self . invalidate ( EncoderStateError :: Ended . into ( ) ) ) ,
292- Self :: Locked ( _) => Err ( self . invalidate ( EncoderStateError :: Locked . into ( ) ) ) ,
293- Self :: Error ( err ) => Err ( self . invalidate ( err ) ) ,
293+ Self :: Consumed | Self :: Finished ( _) => Self :: Error ( EncoderStateError :: Ended . into ( ) ) ,
294+ Self :: Locked ( _) => Self :: Error ( EncoderStateError :: Locked . into ( ) ) ,
295+ st @ Self :: Error ( _ ) => st ,
294296 Self :: Transitioning => unreachable ! ( ) ,
295297 }
296298 }
@@ -828,10 +830,7 @@ impl CommandBuffer {
828830 ) {
829831 St :: Finished ( command_buffer_mutable) => Ok ( command_buffer_mutable) ,
830832 St :: Error ( err) => Err ( err) ,
831- St :: Recording ( _) | St :: Locked ( _) => {
832- Err ( InvalidResourceError ( self . error_ident ( ) ) . into ( ) )
833- }
834- St :: Transitioning => unreachable ! ( ) ,
833+ St :: Recording ( _) | St :: Locked ( _) | St :: Consumed | St :: Transitioning => unreachable ! ( ) ,
835834 }
836835 }
837836}
@@ -1143,22 +1142,15 @@ impl Global {
11431142
11441143 let cmd_enc = hub. command_encoders . get ( encoder_id) ;
11451144
1146- let mut data_guard = cmd_enc. data . lock ( ) ;
1145+ let data = cmd_enc. data . lock ( ) . finish ( ) ;
11471146
11481147 // Errors related to destroyed resources are not reported until the
11491148 // command buffer is submitted.
1150- let error = match data_guard . finish ( ) {
1151- Err ( e) if !e. is_destroyed_error ( ) => Some ( e) ,
1149+ let error = match data {
1150+ CommandEncoderStatus :: Error ( ref e) if !e. is_destroyed_error ( ) => Some ( e. clone ( ) ) ,
11521151 _ => None ,
11531152 } ;
11541153
1155- let data = mem:: replace (
1156- & mut * data_guard,
1157- CommandEncoderStatus :: Error ( EncoderStateError :: Ended . into ( ) ) ,
1158- ) ;
1159-
1160- drop ( data_guard) ;
1161-
11621154 let cmd_buf = CommandBuffer {
11631155 device : cmd_enc. device . clone ( ) ,
11641156 label : desc. label . to_string ( ) ,
0 commit comments