11use gfx_hal:: {
2- memory:: SparseFlags ,
2+ memory:: {
3+ Segment ,
4+ SparseFlags ,
5+ } ,
36 Backend ,
47} ;
58
@@ -11,11 +14,14 @@ pub type Properties = gfx_hal::memory::Properties;
1114
1215/// A buffer is a block of memory that can be used to store data that can be
1316/// accessed by the GPU.
17+ #[ derive( Debug , Clone , Copy ) ]
1418pub struct Buffer < RenderBackend : super :: internal:: Backend > {
1519 buffer : RenderBackend :: Buffer ,
1620 memory : RenderBackend :: Memory ,
1721}
1822
23+ impl < RenderBackend : super :: internal:: Backend > Buffer < RenderBackend > { }
24+
1925pub struct BufferBuilder {
2026 buffer_length : usize ,
2127 usage : Usage ,
@@ -47,9 +53,12 @@ impl BufferBuilder {
4753
4854 /// Builds & binds a buffer of memory to the GPU. If the buffer cannot be
4955 /// bound to the GPU, the buffer memory is freed before the error is returned.
50- pub fn build < RenderBackend : super :: internal:: Backend > (
51- self ,
56+ /// Data must represent the data that will be stored in the buffer, meaning
57+ /// it must repr C and be the same size as the buffer length.
58+ pub fn build < RenderBackend : super :: internal:: Backend , Data : Sized > (
59+ & self ,
5260 gpu : & mut Gpu < RenderBackend > ,
61+ data : Vec < Data > ,
5362 ) -> Result < Buffer < RenderBackend > , & ' static str > {
5463 use gfx_hal:: {
5564 adapter:: PhysicalDevice ,
@@ -98,7 +107,7 @@ impl BufferBuilder {
98107 return Err ( "Failed to allocate memory for buffer." ) ;
99108 }
100109
101- let buffer_memory = buffer_memory_allocation. unwrap ( ) ;
110+ let mut buffer_memory = buffer_memory_allocation. unwrap ( ) ;
102111
103112 // Bind the buffer to the GPU memory
104113 let buffer_binding = unsafe {
@@ -111,6 +120,43 @@ impl BufferBuilder {
111120 return Err ( "Failed to bind buffer memory." ) ;
112121 }
113122
123+ // Get address of the buffer memory on the GPU so that we can write to it.
124+ let get_mapping_to_memory =
125+ unsafe { logical_device. map_memory ( & mut buffer_memory, Segment :: ALL ) } ;
126+
127+ if get_mapping_to_memory. is_err ( ) {
128+ unsafe { logical_device. destroy_buffer ( buffer) } ;
129+ return Err ( "Failed to map memory." ) ;
130+ }
131+ let mapped_memory = get_mapping_to_memory. unwrap ( ) ;
132+
133+ // Copy the data to the GPU memory.
134+ unsafe {
135+ std:: ptr:: copy_nonoverlapping (
136+ data. as_ptr ( ) as * const u8 ,
137+ mapped_memory,
138+ self . buffer_length ,
139+ ) ;
140+ } ;
141+
142+ // Flush the data to ensure it is written to the GPU memory.
143+ let memory_flush = unsafe {
144+ logical_device
145+ . flush_mapped_memory_ranges ( std:: iter:: once ( (
146+ & buffer_memory,
147+ Segment :: ALL ,
148+ ) ) )
149+ . map_err ( |_| "Failed to flush memory." )
150+ } ;
151+
152+ if memory_flush. is_err ( ) {
153+ unsafe { logical_device. destroy_buffer ( buffer) } ;
154+ return Err ( "No memory available on the GPU." ) ;
155+ }
156+
157+ // Unmap the memory now that it's no longer needed by the CPU.
158+ unsafe { logical_device. unmap_memory ( & mut buffer_memory) } ;
159+
114160 return Ok ( Buffer {
115161 buffer,
116162 memory : buffer_memory,
0 commit comments