@@ -14,7 +14,7 @@ use crate::{
14
14
dxgi:: { name:: ObjectExt , result:: HResult as _} ,
15
15
} ,
16
16
dx12:: borrow_interface_temporarily,
17
- AccelerationStructureEntries ,
17
+ AccelerationStructureEntries , CommandEncoder as _ ,
18
18
} ;
19
19
20
20
fn make_box ( origin : & wgt:: Origin3d , size : & crate :: CopyExtent ) -> Direct3D12 :: D3D12_BOX {
@@ -312,6 +312,78 @@ impl super::CommandEncoder {
312
312
}
313
313
}
314
314
}
315
+
316
+ unsafe fn buf_tex_intermediate < T > (
317
+ & mut self ,
318
+ region : crate :: BufferTextureCopy ,
319
+ tex_fmt : wgt:: TextureFormat ,
320
+ copy_op : impl FnOnce ( & mut Self , & super :: Buffer , wgt:: BufferSize , crate :: BufferTextureCopy ) -> T ,
321
+ ) -> Option < ( T , super :: Buffer ) > {
322
+ let size = {
323
+ let copy_info = region. buffer_layout . get_buffer_texture_copy_info (
324
+ tex_fmt,
325
+ region. texture_base . aspect . map ( ) ,
326
+ & region. size . into ( ) ,
327
+ ) ;
328
+ copy_info. unwrap ( ) . bytes_in_copy
329
+ } ;
330
+
331
+ let size = wgt:: BufferSize :: new ( size) ?;
332
+
333
+ let buffer = {
334
+ let ( resource, allocation) =
335
+ super :: suballocation:: DeviceAllocationContext :: from ( & * self )
336
+ . create_buffer ( & crate :: BufferDescriptor {
337
+ label : None ,
338
+ size : size. get ( ) ,
339
+ usage : wgt:: BufferUses :: COPY_SRC | wgt:: BufferUses :: COPY_DST ,
340
+ memory_flags : crate :: MemoryFlags :: empty ( ) ,
341
+ } )
342
+ . expect ( concat ! (
343
+ "internal error: " ,
344
+ "failed to allocate intermediate buffer " ,
345
+ "for offset alignment"
346
+ ) ) ;
347
+ super :: Buffer {
348
+ resource,
349
+ size : size. get ( ) ,
350
+ allocation,
351
+ }
352
+ } ;
353
+
354
+ let mut region = region;
355
+ region. buffer_layout . offset = 0 ;
356
+
357
+ unsafe {
358
+ self . transition_buffers (
359
+ [ crate :: BufferBarrier {
360
+ buffer : & buffer,
361
+ usage : crate :: StateTransition {
362
+ from : wgt:: BufferUses :: empty ( ) ,
363
+ to : wgt:: BufferUses :: COPY_DST ,
364
+ } ,
365
+ } ]
366
+ . into_iter ( ) ,
367
+ )
368
+ } ;
369
+
370
+ let t = copy_op ( self , & buffer, size, region) ;
371
+
372
+ unsafe {
373
+ self . transition_buffers (
374
+ [ crate :: BufferBarrier {
375
+ buffer : & buffer,
376
+ usage : crate :: StateTransition {
377
+ from : wgt:: BufferUses :: COPY_DST ,
378
+ to : wgt:: BufferUses :: COPY_SRC ,
379
+ } ,
380
+ } ]
381
+ . into_iter ( ) ,
382
+ )
383
+ } ;
384
+
385
+ Some ( ( t, buffer) )
386
+ }
315
387
}
316
388
317
389
impl crate :: CommandEncoder for super :: CommandEncoder {
@@ -363,7 +435,10 @@ impl crate::CommandEncoder for super::CommandEncoder {
363
435
unsafe fn end_encoding ( & mut self ) -> Result < super :: CommandBuffer , crate :: DeviceError > {
364
436
let raw = self . list . take ( ) . unwrap ( ) ;
365
437
unsafe { raw. Close ( ) } . into_device_result ( "GraphicsCommandList::close" ) ?;
366
- Ok ( super :: CommandBuffer { raw } )
438
+ Ok ( super :: CommandBuffer {
439
+ raw,
440
+ intermediate_copy_bufs : mem:: take ( & mut self . intermediate_copy_bufs ) . into ( ) ,
441
+ } )
367
442
}
368
443
unsafe fn reset_all < I : Iterator < Item = super :: CommandBuffer > > ( & mut self , command_buffers : I ) {
369
444
for cmd_buf in command_buffers {
@@ -612,7 +687,32 @@ impl crate::CommandEncoder for super::CommandEncoder {
612
687
) where
613
688
T : Iterator < Item = crate :: BufferTextureCopy > ,
614
689
{
690
+ let offset_alignment = self . shared . private_caps . texture_data_placement_alignment ( ) ;
691
+
615
692
for r in regions {
693
+ let is_offset_aligned = r. buffer_layout . offset % offset_alignment == 0 ;
694
+ let ( r, src) = if is_offset_aligned {
695
+ ( r, src)
696
+ } else {
697
+ let Some ( ( r, src) ) = ( unsafe {
698
+ let src_offset = r. buffer_layout . offset ;
699
+ self . buf_tex_intermediate ( r, dst. format , |this, buf, size, r| {
700
+ let layout = crate :: BufferCopy {
701
+ src_offset,
702
+ dst_offset : 0 ,
703
+ size,
704
+ } ;
705
+ this. copy_buffer_to_buffer ( src, buf, [ layout] . into_iter ( ) ) ;
706
+ r
707
+ } )
708
+ } ) else {
709
+ continue ;
710
+ } ;
711
+ self . intermediate_copy_bufs . push ( src) ;
712
+ let src = self . intermediate_copy_bufs . last ( ) . unwrap ( ) ;
713
+ ( r, src)
714
+ } ;
715
+
616
716
let list = self . list . as_ref ( ) . unwrap ( ) ;
617
717
618
718
let src_location = Direct3D12 :: D3D12_TEXTURE_COPY_LOCATION {
@@ -680,8 +780,33 @@ impl crate::CommandEncoder for super::CommandEncoder {
680
780
} ;
681
781
} ;
682
782
783
+ let offset_alignment = self . shared . private_caps . texture_data_placement_alignment ( ) ;
784
+
683
785
for r in regions {
684
- copy_aligned ( this, src, dst, r) ;
786
+ let is_offset_aligned = r. buffer_layout . offset % offset_alignment == 0 ;
787
+ if is_offset_aligned {
788
+ copy_aligned ( self , src, dst, r)
789
+ } else {
790
+ let orig_offset = r. buffer_layout . offset ;
791
+ let Some ( ( r, src) ) = ( unsafe {
792
+ self . buf_tex_intermediate ( r, src. format , |this, buf, size, r| {
793
+ copy_aligned ( this, src, buf, r) ;
794
+ crate :: BufferCopy {
795
+ src_offset : orig_offset,
796
+ dst_offset : 0 ,
797
+ size,
798
+ }
799
+ } )
800
+ } ) else {
801
+ continue ;
802
+ } ;
803
+
804
+ unsafe {
805
+ self . copy_buffer_to_buffer ( & src, dst, [ r] . into_iter ( ) ) ;
806
+ }
807
+
808
+ self . intermediate_copy_bufs . push ( src) ;
809
+ } ;
685
810
}
686
811
}
687
812
0 commit comments