/* Ċ Ġ* ĠCopyright Ġ( c ) Ġ 2 0 1 9 , ĠC uch az ĠInteractive , ĠLLC . ĠAll Ġrights Ġreserved . Ċ Ġ* ĠLicense Ġterms Ġare Ġat Ġlicense . txt Ġin Ġthe Ġproject Ġroot Ċ Ġ*/ Ċ Ċ package Ġc uch az . kl udge . v ulkan Ċ Ċ import Ġc uch az . kl udge . tools . Auto Closer Ċ import Ġc uch az . kl udge . tools . Int Flags Ċ import Ġc uch az . kl udge . tools . at Least Ċ import Ġjava . nio . ByteBuffer ĊĊ Ċ /** Ċ Ġ* ĠMan ages Ġtransfer Ġbuffers Ġfor Ġcopying Ġdata Ġbetween Ġhost Ġand Ġdevice . Ċ Ġ* Ċ Ġ* ĠA Ġsingle Ġstaging Ġbuffer Ġis Ġmaintained Ġfor Ġthis Ġdevice . Ċ Ġ* ĠEach Ġtime Ġa Ġtransfer Ġis Ġrequested , Ġthe Ġsame Ġstaging Ġbuffer Ġis Ġused , Ġso ĠMemory St ager Ġis Ġnot Ġthead - safe . Ċ Ġ* ĠIf Ġthe Ġexisting Ġstaging Ġbuffer Ġis Ġtoo Ġsmall Ġfor Ġthe Ġrequest , Ċ Ġ* Ġthen Ġthat Ġbuffer Ġis Ġreplaced Ġwith Ġa Ġnew Ġone Ġthat 's Ġbig Ġenough Ġfor Ġthe Ġtransfer . Ċ Ġ*/ Ċ class ĠMemory St ager Ġinternal Ġconstructor ( Ċ ĉ val Ġdevice : ĠDevice Ċ ) Ġ: ĠAuto Closeable Ġ{ ĊĊ ĉ private Ġval Ġcloser Ġ= ĠAuto Closer () Ċ ĉ private Ġfun Ġ< R : Auto Closeable > ĠR . auto Close ( replace : ĠR ? Ġ= Ġnull ) Ġ= Ġapply Ġ{ Ġcloser . add ( this , Ġreplace ) Ġ} Ċ ĉ override Ġfun Ġclose () Ġ{ Ċĉ ĉ clo ser . close () Ċ ĉ } ĊĊ ĉ // Ġget Ġthe Ġqueue Ġfor Ġmemory Ġtransfers Ċ ĉ val Ġqueue Family Ġ= Ġdevice . physical Device . find Queue Family ( Int Flags . of ( Ċĉ ĉ PhysicalDevice . Queue Family . Flags . Transfer Ċ ĉ )) Ċ ĉ val Ġqueues Ġ= Ġdevice . queues [ queue Family ] Ċĉ ĉ ?: Ġthrow ĠNoSuch ElementException (" no Ġmemory Ġtransfer Ġqueues Ġdefined Ġfor Ġdevice , Ġcan 't Ġuse ĠMemory St ager ") Ċ ĉ val Ġqueue Ġ= Ġqueues . first OrNull () Ġ?: Ġthrow ĠNoSuch ElementException (" no Ġmemory Ġtransfer Ġqueue Ġdefined Ġfor Ġdevice , Ġcan 't Ġuse ĠMemory St ager ") ĊĊ ĉ // Ġmake Ġa Ġcommand Ġbuffer Ċ ĉ val Ġcommand Pool Ġ= Ġdevice Ċĉ ĉ . command Pool ( Ċĉĉ ĉ queue Family , Ċĉĉ ĉ flags Ġ= ĠInt Flags . of ( Command Pool . Create . Reset CommandBuffer ) Ċĉ ĉ ) Ċĉ ĉ . auto Close () ĊĊ ĉ // Ġstart Ġwith Ġinitial Ġbuffers Ċ ĉ private Ġvar Ġbuf : ĠBuffer . Allocated ? Ġ= Ġnull ĊĊ ĉ fun Ġget Buffer ( size : ĠLong ): ĠBuffer . Allocated Ġ{ ĊĊĉ ĉ // Ġif Ġthe Ġexisting Ġbuffer Ġis Ġbig Ġenough , Ġuse Ġthat Ċĉ ĉ val Ġexisting Buf Ġ= Ġbuf Ċĉ ĉ if Ġ( existing Buf Ġ!= Ġnull Ġ&& Ġexisting Buf . memory . size Ġ>= Ġsize ) Ġ{ Ċĉĉ ĉ return Ġexisting Buf Ċĉ ĉ } ĊĊĉ ĉ // Ġotherwise , Ġallocate Ġa Ġnew Ġone Ġ( at Ġleast Ġ 1 ĠK iB ) Ċĉ ĉ var Ġnew Size Ġ= Ġ( buf ?. memory ?. size Ġ?: Ġ 0 ). at Least ( 1 0 2 4 ) Ċĉ ĉ while Ġ( new Size Ġ< Ġsize ) Ġ{ Ċĉĉ ĉ new Size Ġ*= Ġ 2 Ċĉ ĉ } ĊĊĉ ĉ // Ġallocate Ġthe Ġnew Ġbuffer Ċĉ ĉ val Ġbuf Ġ= Ġdevice Ċĉĉ ĉ . buffer ( Ċĉĉĉ ĉ size , Ċĉĉĉ ĉ Int Flags . of ( Buffer . Usage . Transfer Src , ĠBuffer . Usage . Transfer Dst ) Ċĉĉ ĉ ) Ċĉĉ ĉ . auto Close ( replace Ġ= Ġbuf ?. buffer ) Ċĉĉ ĉ . allocate Ġ{ Ġmem Type Ġ-> Ċĉĉĉ ĉ mem Type . flags . has All ( Int Flags . of ( Ċĉĉĉĉ ĉ Memory Type . Flags . Host Visible , Ċĉĉĉĉ ĉ Memory Type . Flags . Host Co herent Ċĉĉĉ ĉ )) Ċĉĉ ĉ } Ċĉĉ ĉ . auto Close ( replace Ġ= Ġbuf ) ĊĊĉ ĉ this . buf Ġ= Ġbuf ĊĊĉ ĉ return Ġbuf Ċ ĉ } ĊĊ ĉ fun Ġcommand ( block : ĠCommand Buffer . () Ġ-> ĠUnit ) Ġ{ Ċĉ ĉ queue . submit ( command Pool . buffer (). apply Ġ{ Ċĉĉ ĉ begin ( Int Flags . of ( CommandBuffer . Usage . One Time Submit )) Ċĉĉ ĉ block () Ċĉĉ ĉ end () Ċĉ ĉ }) Ċĉ ĉ queue . waitFor Idle () Ċ ĉ } Ċ } ĊĊ Ċ fun ĠBuffer . allocate Host (): ĠBuffer . Allocated Ġ= Ċ ĉ allocate Ġ{ Ġmem Type Ġ-> Ċĉ ĉ mem Type . flags . has All ( Int Flags . of ( Ċĉĉ ĉ Memory Type . Flags . Host Visible , Ċĉĉ ĉ Memory Type . Flags . Host Co herent Ċĉ ĉ )) Ċ ĉ } Ċ Ċ fun ĠBuffer . allocate Device (): ĠBuffer . Allocated Ġ= Ċ ĉ allocate Ġ{ Ġmem Type Ġ-> Ċĉ ĉ mem Type . flags . has All ( Int Flags . of ( Ċĉĉ ĉ Memory Type . Flags . Device Local Ċĉ ĉ )) Ċ ĉ } Ċ Ċ inline Ġfun Ġ< T > ĠBuffer . Allocated . transfer H to D ( Ċ ĉ offset : ĠLong Ġ= Ġ 0 L , Ċ ĉ size : ĠInt Ġ= Ġmemory . size As Int , Ċ ĉ block : Ġ( buf : ĠByteBuffer ) Ġ-> ĠT Ċ ): ĠT Ġ{ Ċ ĉ if Ġ( memory . type . flags . has ( Memory Type . Flags . Host Visible )) Ġ{ ĊĊĉ ĉ // Ġmemory Ġis Ġhost - visible , Ġso Ġmap Ġit Ġdirectly Ċĉ ĉ return Ġmemory . map ( offset , Ġsize , Ġblock ) ĊĊ ĉ } Ġelse Ġ{ ĊĊĉ ĉ // Ġmemory Ġis Ġnot Ġhost - visible , Ġso Ġupload Ġusing Ġa Ġstaging Ġbuffer Ċĉ ĉ val Ġhost Buf Ġ= Ġmemory . device . memory St ager . get Buffer ( size . to Long ()) Ċĉ ĉ val Ġdevice Buf Ġ= Ġthis Ċĉ ĉ val Ġresult Ġ= Ġhost Buf . memory . map ( 0 , Ġsize , Ġblock ) Ċĉ ĉ memory . device . memory St ager . command Ġ{ Ċĉĉ ĉ copy Buffer ( host Buf . buffer , Ġdevice Buf . buffer , Ġ 0 , Ġoffset , Ġsize . to Long ()) Ċĉ ĉ } Ċĉ ĉ return Ġresult Ċ ĉ } Ċ } Ċ Ċ inline Ġfun Ġ< T > ĠBuffer . Allocated . transfer Dto H ( Ċ ĉ offset : ĠLong Ġ= Ġ 0 L , Ċ ĉ size : ĠInt Ġ= Ġmemory . size As Int , Ċ ĉ block : Ġ( buf : ĠByteBuffer ) Ġ-> ĠT Ċ ): ĠT Ġ{ Ċ ĉ if Ġ( memory . type . flags . has ( Memory Type . Flags . Host Visible )) Ġ{ ĊĊĉ ĉ // Ġmemory Ġis Ġhost - visible , Ġso Ġmap Ġit Ġdirectly Ċĉ ĉ return Ġmemory . map ( offset , Ġsize , Ġblock ) ĊĊ ĉ } Ġelse Ġ{ ĊĊĉ ĉ // Ġmemory Ġis Ġnot Ġhost - visible , Ġso Ġdownload Ġusing Ġa Ġstaging Ġbuffer Ċĉ ĉ val Ġhost Buf Ġ= Ġmemory . device . memory St ager . get Buffer ( size . to Long ()) Ċĉ ĉ val Ġdevice Buf Ġ= Ġthis Ċĉ ĉ memory . device . memory St ager . command Ġ{ Ċĉĉ ĉ copy Buffer ( device Buf . buffer , Ġhost Buf . buffer , Ġoffset , Ġ 0 , Ġsize . to Long ()) Ċĉ ĉ } Ċĉ ĉ return Ġhost Buf . memory . map ( 0 , Ġsize , Ġblock ) Ċ ĉ } Ċ } ĊĊ Ċ fun ĠImage . allocate Device (): ĠImage . Allocated Ġ= Ċ ĉ allocate Ġ{ Ġmem Type Ġ-> Ċĉ ĉ mem Type . flags . has All ( Int Flags . of ( Ċĉĉ ĉ Memory Type . Flags . Device Local Ċĉ ĉ )) Ċ ĉ } Ċ Ċ inline Ġfun Ġ< T > ĠImage . Allocated . transfer H to D ( Ċ ĉ layout : ĠImage . Layout Ġ= ĠImage . Layout . Transfer Dst Opt imal , Ċ ĉ block : Ġ( buf : ĠByteBuffer ) Ġ-> ĠT Ċ ): ĠT Ġ{ Ċ ĉ if Ġ( image . til ing Ġ== ĠImage . T iling . Linear Ġ&& Ġmemory . type . flags . has ( Memory Type . Flags . Host Visible )) Ġ{ ĊĊĉ ĉ // Ġmap Ġit Ġdirectly Ċĉ ĉ return Ġmemory . map ( 0 , Ġmemory . size . toInt (), Ġblock ) ĊĊ ĉ } Ġelse Ġ{ ĊĊĉ ĉ // Ġupload Ġusing Ġa Ġstaging Ġbuffer Ċĉ ĉ val Ġhost Buf Ġ= Ġmemory . device . memory St ager . get Buffer ( memory . size ) Ċĉ ĉ val Ġdevice Img Ġ= Ġthis Ċĉ ĉ val Ġresult Ġ= Ġhost Buf . memory . map ( 0 , Ġmemory . size . toInt (), Ġblock ) Ċĉ ĉ memory . device . memory St ager . command Ġ{ ĊĊĉĉ ĉ // Ġtransition Ġimage Ġinto Ġa Ġtransfer Ġdestination Ċĉĉ ĉ pipeline Barrier ( Ċĉĉĉ ĉ src Stage Ġ= ĠInt Flags . of ( Pipeline Stage . Top Of Pipe ), Ċĉĉĉ ĉ dst Stage Ġ= ĠInt Flags . of ( Pipeline Stage . Transfer ), Ċĉĉĉ ĉ images Ġ= ĠlistOf ( Ċĉĉĉĉ ĉ image . barrier ( Ċĉĉĉĉĉ ĉ dst Access Ġ= ĠInt Flags . of ( Access . Transfer Write ), Ċĉĉĉĉĉ ĉ new Layout Ġ= Ġlayout Ċĉĉĉĉ ĉ ) Ċĉĉĉ ĉ ) Ċĉĉ ĉ ) ĊĊĉĉ ĉ // ĠTODO : Ġexpose Ġother Ġimage Ġcopy Ġoptions ? Ġ( need Ġto Ġem ulate Ġfor Ġhost - visible Ġmem Ġth o ) Ċĉĉ ĉ copy Buffer To Image ( host Buf . buffer , Ġdevice Img . image , Ġlayout ) Ċĉ ĉ } Ċĉ ĉ return Ġresult Ċ ĉ } Ċ } Ċ Ċ inline Ġfun Ġ< T > ĠImage . Allocated . transfer Dto H ( Ċ ĉ layout : ĠImage . Layout Ġ= ĠImage . Layout . Transfer Src Opt imal , Ċ ĉ block : Ġ( buf : ĠByteBuffer ) Ġ-> ĠT Ċ ): ĠT Ġ{ Ċ ĉ if Ġ( image . til ing Ġ== ĠImage . T iling . Linear Ġ&& Ġmemory . type . flags . has ( Memory Type . Flags . Host Visible )) Ġ{ ĊĊĉ ĉ // Ġmap Ġit Ġdirectly Ċĉ ĉ return Ġmemory . map ( 0 , Ġmemory . size . toInt (), Ġblock ) ĊĊ ĉ } Ġelse Ġ{ ĊĊĉ ĉ // Ġdownload Ġusing Ġa Ġstaging Ġbuffer Ċĉ ĉ val Ġhost Buf Ġ= Ġmemory . device . memory St ager . get Buffer ( memory . size ) Ċĉ ĉ val Ġdevice Img Ġ= Ġthis Ċĉ ĉ memory . device . memory St ager . command Ġ{ ĊĊĉĉ ĉ // Ġtransition Ġimage Ġinto Ġa Ġtransfer Ġsrc Ċĉĉ ĉ pipeline Barrier ( Ċĉĉĉ ĉ src Stage Ġ= ĠInt Flags . of ( Pipeline Stage . Top Of Pipe ), Ċĉĉĉ ĉ dst Stage Ġ= ĠInt Flags . of ( Pipeline Stage . Transfer ), Ċĉĉĉ ĉ images Ġ= ĠlistOf ( Ċĉĉĉĉ ĉ image . barrier ( Ċĉĉĉĉĉ ĉ dst Access Ġ= ĠInt Flags . of ( Access . Transfer Read ), Ċĉĉĉĉĉ ĉ new Layout Ġ= Ġlayout Ċĉĉĉĉ ĉ ) Ċĉĉĉ ĉ ) Ċĉĉ ĉ ) ĊĊĉĉ ĉ // ĠTODO : Ġexpose Ġother Ġimage Ġcopy Ġoptions ? Ġ( need Ġto Ġem ulate Ġfor Ġhost - visible Ġmem Ġth o ) Ċĉĉ ĉ copy Image To Buffer ( device Img . image , Ġhost Buf . buffer , Ġlayout ) Ċĉ ĉ } Ċĉ ĉ return Ġhost Buf . memory . map ( 0 , Ġmemory . size . toInt (), Ġblock ) Ċ ĉ } Ċ } Ċ