@@ -177,6 +177,7 @@ impl CommandEncoderStatus {
177177 ) -> Result < ( ) , EncoderStateError > {
178178 match self {
179179 Self :: Recording ( cmd_buf_data) => {
180+ cmd_buf_data. encoder . api . set ( EncodingApi :: Wgpu ) ;
180181 match f ( ) {
181182 Ok ( cmd) => cmd_buf_data. commands . push ( cmd) ,
182183 Err ( err) => {
@@ -220,10 +221,12 @@ impl CommandEncoderStatus {
220221 E : Clone + Into < CommandEncoderError > ,
221222 > (
222223 & mut self ,
224+ api : EncodingApi ,
223225 f : F ,
224226 ) -> Result < ( ) , EncoderStateError > {
225227 match self {
226- Self :: Recording ( _) => {
228+ Self :: Recording ( inner) => {
229+ inner. encoder . api . set ( api) ;
227230 RecordingGuard { inner : self } . record ( f) ;
228231 Ok ( ( ) )
229232 }
@@ -256,7 +259,10 @@ impl CommandEncoderStatus {
256259 f : F ,
257260 ) -> T {
258261 match self {
259- Self :: Recording ( _) => RecordingGuard { inner : self } . record_as_hal_mut ( f) ,
262+ Self :: Recording ( inner) => {
263+ inner. encoder . api . set ( EncodingApi :: Raw ) ;
264+ RecordingGuard { inner : self } . record_as_hal_mut ( f)
265+ }
260266 Self :: Locked ( _) => {
261267 self . invalidate ( EncoderStateError :: Locked ) ;
262268 f ( None )
@@ -358,8 +364,11 @@ impl CommandEncoderStatus {
358364 // state or an error, to be transferred to the command buffer.
359365 match mem:: replace ( self , Self :: Consumed ) {
360366 Self :: Recording ( inner) => {
361- // Nothing should have opened the encoder yet.
362- assert ! ( !inner. encoder. is_open) ;
367+ // Raw encoding leaves the encoder open in `command_encoder_as_hal_mut`.
368+ // Otherwise, nothing should have opened it yet.
369+ if inner. encoder . api != EncodingApi :: Raw {
370+ assert ! ( !inner. encoder. is_open) ;
371+ }
363372 Self :: Finished ( inner)
364373 }
365374 Self :: Consumed | Self :: Finished ( _) => Self :: Error ( EncoderStateError :: Ended . into ( ) ) ,
@@ -480,6 +489,38 @@ impl Drop for CommandEncoder {
480489 }
481490}
482491
492+ /// The encoding API being used with a `CommandEncoder`.
493+ ///
494+ /// Mixing APIs on the same encoder is not allowed.
495+ #[ derive( Copy , Clone , Debug , Eq , PartialEq ) ]
496+ pub enum EncodingApi {
497+ // The regular wgpu encoding APIs are being used.
498+ Wgpu ,
499+
500+ // The raw hal encoding API is being used.
501+ Raw ,
502+
503+ // Neither encoding API has been called yet.
504+ Undecided ,
505+
506+ // The encoder is used internally by wgpu.
507+ InternalUse ,
508+ }
509+
510+ impl EncodingApi {
511+ pub ( crate ) fn set ( & mut self , api : EncodingApi ) {
512+ match * self {
513+ EncodingApi :: Undecided => {
514+ * self = api;
515+ }
516+ self_api if self_api != api => {
517+ panic ! ( "Mixing the wgpu encoding API with the raw encoding API is not permitted" ) ;
518+ }
519+ _ => { }
520+ }
521+ }
522+ }
523+
483524/// A raw [`CommandEncoder`][rce], and the raw [`CommandBuffer`][rcb]s built from it.
484525///
485526/// Each wgpu-core [`CommandBuffer`] owns an instance of this type, which is
@@ -528,6 +569,13 @@ pub(crate) struct InnerCommandEncoder {
528569 /// [`wgpu_hal::CommandEncoder`]: hal::CommandEncoder
529570 pub ( crate ) is_open : bool ,
530571
572+ /// Tracks which API is being used to encode commands.
573+ ///
574+ /// Mixing the wgpu encoding API with access to the raw hal encoder via
575+ /// `as_hal_mut` is not supported. this field tracks which API is being used
576+ /// in order to detect and reject invalid usage.
577+ pub ( crate ) api : EncodingApi ,
578+
531579 pub ( crate ) label : String ,
532580}
533581
@@ -790,6 +838,7 @@ impl CommandEncoder {
790838 list : Vec :: new ( ) ,
791839 device : device. clone ( ) ,
792840 is_open : false ,
841+ api : EncodingApi :: Undecided ,
793842 label : label. to_string ( ) ,
794843 } ,
795844 trackers : Tracker :: new ( ) ,
@@ -916,6 +965,12 @@ impl CommandEncoder {
916965 let snatch_guard = self . device . snatchable_lock . read ( ) ;
917966 let mut debug_scope_depth = 0 ;
918967
968+ if cmd_buf_data. encoder . api == EncodingApi :: Raw {
969+ // Should have panicked on the first call that switched APIs,
970+ // but lets be sure.
971+ assert ! ( cmd_buf_data. commands. is_empty( ) ) ;
972+ }
973+
919974 let mut commands = mem:: take ( & mut cmd_buf_data. commands ) ;
920975 for command in commands. drain ( ..) {
921976 if matches ! (
0 commit comments