11use crate :: sys:: TexturePixelFormat ;
22use crate :: sys:: { sceGeEdramGetAddr, sceGeEdramGetSize} ;
3+ use core:: marker:: PhantomData ;
34use core:: mem:: size_of;
45use core:: ptr:: null_mut;
6+ use core:: sync:: atomic:: { AtomicU32 , Ordering } ;
57
68type VramAllocator = SimpleVramAllocator ;
79
@@ -27,14 +29,20 @@ impl VramAllocatorSingleton {
2729 }
2830}
2931
30- pub struct VramMemChunk {
32+ pub struct VramMemChunk < ' a > {
3133 start : u32 ,
3234 len : u32 ,
35+ // This makes the VRAM chunk act like it has a mutable reference
36+ vram : PhantomData < & ' a mut ( ) > ,
3337}
3438
35- impl VramMemChunk {
39+ impl VramMemChunk < ' _ > {
3640 fn new ( start : u32 , len : u32 ) -> Self {
37- Self { start, len }
41+ Self {
42+ start,
43+ len,
44+ vram : PhantomData ,
45+ }
3846 }
3947
4048 pub fn as_mut_ptr_from_zero ( & self ) -> * mut u8 {
@@ -54,38 +62,55 @@ impl VramMemChunk {
5462// TODO: pin?
5563#[ derive( Debug ) ]
5664pub struct SimpleVramAllocator {
57- offset : u32 ,
65+ offset : AtomicU32 ,
5866}
5967
6068impl SimpleVramAllocator {
6169 const fn new ( ) -> Self {
62- Self { offset : 0 }
70+ Self {
71+ offset : AtomicU32 :: new ( 0 ) ,
72+ }
6373 }
6474
65- // TODO: return a Result instead of panicking
66- pub fn alloc ( & mut self , size : u32 ) -> VramMemChunk {
67- let old_offset = self . offset ;
68- self . offset += size;
75+ /// Frees all previously allocated VRAM chunks.
76+ ///
77+ /// This resets the allocator's counter, but does not change the contents of
78+ /// VRAM. Since this method requires `&mut Self`, it cannot overlap with any
79+ /// previously allocated `VramMemChunk`s since they have the lifetime of the
80+ /// `&Self` that allocated them.
81+ pub fn free_all ( & mut self ) {
82+ self . offset . store ( 0 , Ordering :: Relaxed ) ;
83+ }
6984
70- if self . offset > self . total_mem ( ) {
85+ // TODO: return a Result instead of panicking
86+ /// Allocates a `size` bytes of VRAM
87+ ///
88+ /// The returned VRAM chunk has the same lifetime as the
89+ /// `SimpleVramAllocator` borrow (i.e. `&self`) that allocated it.
90+ pub fn alloc < ' a > ( & ' a self , size : u32 ) -> VramMemChunk < ' a > {
91+ let old_offset = self . offset . load ( Ordering :: Relaxed ) ;
92+ let new_offset = old_offset + size;
93+ self . offset . store ( new_offset, Ordering :: Relaxed ) ;
94+
95+ if new_offset > self . total_mem ( ) {
7196 panic ! ( "Total VRAM size exceeded!" ) ;
7297 }
7398
7499 VramMemChunk :: new ( old_offset, size)
75100 }
76101
77102 // TODO: ensure 16-bit alignment?
78- pub fn alloc_sized < T : Sized > ( & mut self , count : u32 ) -> VramMemChunk {
103+ pub fn alloc_sized < ' a , T : Sized > ( & ' a self , count : u32 ) -> VramMemChunk < ' a > {
79104 let size = size_of :: < T > ( ) as u32 ;
80105 self . alloc ( count * size)
81106 }
82107
83- pub fn alloc_texture_pixels (
84- & mut self ,
108+ pub fn alloc_texture_pixels < ' a > (
109+ & ' a self ,
85110 width : u32 ,
86111 height : u32 ,
87112 psm : TexturePixelFormat ,
88- ) -> VramMemChunk {
113+ ) -> VramMemChunk < ' a > {
89114 let size = get_memory_size ( width, height, psm) ;
90115 self . alloc ( size)
91116 }
0 commit comments