11use alloc:: { boxed:: Box , sync:: Arc , vec:: Vec } ;
22use core:: {
33 error, fmt,
4- ops:: { Bound , Deref , DerefMut , Range , RangeBounds } ,
4+ ops:: { Bound , Deref , Range , RangeBounds } ,
55} ;
66
77use crate :: util:: Mutex ;
@@ -140,8 +140,8 @@ use crate::*;
140140/// buffer.map_async(wgpu::MapMode::Write, .., move |result| {
141141/// if result.is_ok() {
142142/// let mut view = capturable.get_mapped_range_mut(..);
143- /// let floats: &mut [f32] = bytemuck::cast_slice_mut(&mut view) ;
144- /// floats.fill(42.0 );
143+ /// let mut floats: wgpu::WriteOnly<[[u8; 4]]> = view.slice(..).into_chunks::<4>().0 ;
144+ /// floats.fill(42.0f32.to_ne_bytes() );
145145/// drop(view);
146146/// capturable.unmap();
147147/// }
@@ -613,7 +613,7 @@ impl<'a> BufferSlice<'a> {
613613 }
614614 }
615615
616- /// Gain write access to the bytes of a [mapped] [`Buffer`].
616+ /// Gain write-only access to the bytes of a [mapped] [`Buffer`].
617617 ///
618618 /// Returns a [`BufferViewMut`] referring to the buffer range represented by
619619 /// `self`. See the documentation for [`BufferViewMut`] for more details.
@@ -825,7 +825,7 @@ impl MapContext {
825825 ///
826826 /// This panics if the given range does not exactly match one previously
827827 /// passed to [`MapContext::validate_and_add`].
828- fn remove ( & mut self , offset : BufferAddress , size : BufferSize ) {
828+ pub ( crate ) fn remove ( & mut self , offset : BufferAddress , size : BufferSize ) {
829829 let end = offset + size. get ( ) ;
830830
831831 let index = self
@@ -894,43 +894,16 @@ pub struct BufferView {
894894 inner : dispatch:: DispatchBufferMappedRange ,
895895}
896896
897- #[ cfg( webgpu) ]
898- impl BufferView {
899- /// Provides the same data as dereferencing the view, but as a `Uint8Array` in js.
900- /// This can be MUCH faster than dereferencing the view which copies the data into
901- /// the Rust / wasm heap.
902- pub fn as_uint8array ( & self ) -> & js_sys:: Uint8Array {
903- self . inner . as_uint8array ( )
904- }
905- }
906-
907- impl core:: ops:: Deref for BufferView {
908- type Target = [ u8 ] ;
909-
910- #[ inline]
911- fn deref ( & self ) -> & [ u8 ] {
912- self . inner . slice ( )
913- }
914- }
915-
916- impl AsRef < [ u8 ] > for BufferView {
917- #[ inline]
918- fn as_ref ( & self ) -> & [ u8 ] {
919- self . inner . slice ( )
920- }
921- }
922-
923897/// A write-only view of a mapped buffer's bytes.
924898///
925899/// To get a `BufferViewMut`, first [map] the buffer, and then
926900/// call `buffer.slice(range).get_mapped_range_mut()`.
927901///
928- /// `BufferViewMut` dereferences to `&mut [u8]`, so you can use all the usual
929- /// Rust slice methods to access the buffer's contents. It also implements
930- /// `AsMut<[u8]>`, if that's more convenient.
931- ///
932- /// It is possible to read the buffer using this view, but doing so is not
933- /// recommended, as it is likely to be slow.
902+ /// Because Rust has no write-only reference type
903+ /// (`&[u8]` is read-only and `&mut [u8]` is read-write),
904+ /// this type does not dereference to a slice in the way that [`BufferView`] does.
905+ /// Instead, [`.slice()`][BufferViewMut::slice] returns a special [`WriteOnly`] pointer type,
906+ /// and there are also a few convenience methods such as [`BufferViewMut::copy_from_slice()`].
934907///
935908/// Before the buffer can be unmapped, all `BufferViewMut`s observing it
936909/// must be dropped. Otherwise, the call to [`Buffer::unmap`] will panic.
@@ -947,24 +920,25 @@ pub struct BufferViewMut {
947920 inner : dispatch:: DispatchBufferMappedRange ,
948921}
949922
950- impl AsMut < [ u8 ] > for BufferViewMut {
951- #[ inline]
952- fn as_mut ( & mut self ) -> & mut [ u8 ] {
953- self . inner . slice_mut ( )
954- }
955- }
923+ // `BufferView` simply dereferences. `BufferViewMut` cannot, because mapped memory may be
924+ // write-combining memory <https://en.wikipedia.org/wiki/Write_combining>,
925+ // and not support the expected behavior of atomic accesses.
926+ // Further context: <https://github.com/gfx-rs/wgpu/issues/8897>
956927
957- impl Deref for BufferViewMut {
928+ impl core :: ops :: Deref for BufferView {
958929 type Target = [ u8 ] ;
959930
960- fn deref ( & self ) -> & Self :: Target {
961- self . inner . slice ( )
931+ #[ inline]
932+ fn deref ( & self ) -> & [ u8 ] {
933+ // SAFETY: this is a read mapping
934+ unsafe { self . inner . read_slice ( ) }
962935 }
963936}
964937
965- impl DerefMut for BufferViewMut {
966- fn deref_mut ( & mut self ) -> & mut Self :: Target {
967- self . inner . slice_mut ( )
938+ impl AsRef < [ u8 ] > for BufferView {
939+ #[ inline]
940+ fn as_ref ( & self ) -> & [ u8 ] {
941+ self
968942 }
969943}
970944
@@ -986,6 +960,50 @@ impl Drop for BufferViewMut {
986960 }
987961}
988962
963+ #[ cfg( webgpu) ]
964+ impl BufferView {
965+ /// Provides the same data as dereferencing the view, but as a `Uint8Array` in js.
966+ /// This can be MUCH faster than dereferencing the view which copies the data into
967+ /// the Rust / wasm heap.
968+ pub fn as_uint8array ( & self ) -> & js_sys:: Uint8Array {
969+ self . inner . as_uint8array ( )
970+ }
971+ }
972+
973+ /// These methods are equivalent to the methods of the same names on [`WriteOnly`].
974+ impl BufferViewMut {
975+ /// Returns the length of this view; the number of bytes to be written.
976+ pub fn len ( & self ) -> usize {
977+ // cannot fail because we can't actually map more than isize::MAX bytes
978+ usize:: try_from ( self . size . get ( ) ) . unwrap ( )
979+ }
980+
981+ /// Returns `true` if the view has a length of 0.
982+ ///
983+ /// Note that this is currently impossible.
984+ pub fn is_empty ( & self ) -> bool {
985+ self . len ( ) == 0
986+ }
987+
988+ /// Returns a [`WriteOnly`] reference to a portion of this.
989+ ///
990+ /// `.slice(..)` can be used to access the whole data.
991+ pub fn slice < ' a , S : RangeBounds < usize > > ( & ' a mut self , bounds : S ) -> WriteOnly < ' a , [ u8 ] > {
992+ // SAFETY: this is a write mapping
993+ unsafe { self . inner . write_slice ( ) } . into_slice ( bounds)
994+ }
995+
996+ /// Copies all elements from src into `self`.
997+ ///
998+ /// The length of `src` must be the same as `self`.
999+ ///
1000+ /// This method is equivalent to
1001+ /// [`self.slice(..).copy_from_slice(src)`][WriteOnly::copy_from_slice].
1002+ pub fn copy_from_slice ( & mut self , src : & [ u8 ] ) {
1003+ self . slice ( ..) . copy_from_slice ( src)
1004+ }
1005+ }
1006+
9891007#[ track_caller]
9901008fn check_buffer_bounds (
9911009 buffer_size : BufferAddress ,
0 commit comments