@@ -273,62 +273,138 @@ impl Default for AllocatorDebugSettings {
273273
274274/// The sizes of the memory blocks that the allocator will create. 
275275/// 
276- /// Useful for tuning the allocator to your application's needs. For example most games will be fine with the default  
276+ /// Useful for tuning the allocator to your application's needs. For example most games will be fine with the defaultsize  
277277/// values, but eg. an app might want to use smaller block sizes to reduce the amount of memory used. 
278278/// 
279279/// Clamped between 4MB and 256MB, and rounds up to the nearest multiple of 4MB for alignment reasons. 
280+ /// 
281+ /// # Fixed or growable block size 
282+ /// 
283+ /// This structure represents ranges of allowed sizes for shared memory blocks. 
284+ /// By default, If the bounds of a given range are equal, the allocator will 
285+ /// be configured to used a fixed memory block size for shared allocations. 
286+ /// 
287+ /// Otherwise, the allocator will pick a memory block size within the specifed 
288+ /// range, dependending on the number of existing allocations for the memory 
289+ /// type. 
290+ /// As a rule of thumb, the allocator will start with the minimum block size 
291+ /// and double the size with each new allocation, up to the specified maximum 
292+ /// block size. This growth is tracked independently for each memory type. 
293+ /// The block size also decreases when blocks are deallocated. 
294+ /// 
295+ /// # Example 
296+ /// 
297+ /// ``` 
298+ /// use gpu_allocator::AllocationSizes; 
299+ /// const MB: u64 = 1024 * 1024; 
300+ /// // This configuration uses fixed memory block sizes. 
301+ /// let fixed = AllocationSizes::new(256 * MB, 64 * MB); 
302+ /// 
303+ /// // This configuration starts with 8MB memory blocks 
304+ /// // and grows the block size of a given memory type each 
305+ /// // time a new allocation is needed, up to a limit of 
306+ /// // 256MB for device memory and 64MB for host memory. 
307+ /// let growing = AllocationSizes::new(8 * MB, 8 * MB) 
308+ ///     .with_max_device_memblock_size(256 * MB) 
309+ ///     .with_max_host_memblock_size(64 * MB); 
310+ /// ``` 
280311#[ derive( Clone ,  Copy ,  Debug ) ]  
281312pub  struct  AllocationSizes  { 
282-     /// The size of the memory blocks that will be created for the GPU only memory type. 
313+     /// The initial  size of the memory blocks that will be created for the GPU only memory type. 
283314     /// 
284315     /// Defaults to 256MB. 
285-      device_memblock_size :  u64 , 
316+      min_device_memblock_size :  u64 , 
317+     /// The size of device memory blocks doubles each time a new allocation is needed, up to 
318+      /// `device_maximum_memblock_size`. 
319+      max_device_memblock_size :  u64 , 
286320    /// The size of the memory blocks that will be created for the CPU visible memory types. 
287321     /// 
288322     /// Defaults to 64MB. 
289-      host_memblock_size :  u64 , 
323+      min_host_memblock_size :  u64 , 
324+     /// The size of host memory blocks doubles each time a new allocation is needed, up to 
325+      /// `host_maximum_memblock_size`. 
326+      max_host_memblock_size :  u64 , 
290327} 
291328
292329impl  AllocationSizes  { 
330+     /// Sets the minimum device and host memory block sizes. 
331+      /// 
332+      /// The maximum block sizes are initialized to the minimum sizes and 
333+      /// can be changed using `with_max_device_memblock_size` and 
334+      /// `with_max_host_memblock_size`. 
293335     pub  fn  new ( device_memblock_size :  u64 ,  host_memblock_size :  u64 )  -> Self  { 
294-         const  FOUR_MB :  u64  = 4  *  1024  *  1024 ; 
295-         const  TWO_HUNDRED_AND_FIFTY_SIX_MB :  u64  = 256  *  1024  *  1024 ; 
296- 
297-         let  mut  device_memblock_size =
298-             device_memblock_size. clamp ( FOUR_MB ,  TWO_HUNDRED_AND_FIFTY_SIX_MB ) ; 
299-         let  mut  host_memblock_size =
300-             host_memblock_size. clamp ( FOUR_MB ,  TWO_HUNDRED_AND_FIFTY_SIX_MB ) ; 
336+         let  device_memblock_size = Self :: adjust_memblock_size ( device_memblock_size,  "Device" ) ; 
337+         let  host_memblock_size = Self :: adjust_memblock_size ( host_memblock_size,  "Host" ) ; 
301338
302-         if  device_memblock_size % FOUR_MB  != 0  { 
303-             let  val = device_memblock_size / FOUR_MB  + 1 ; 
304-             device_memblock_size = val *  FOUR_MB ; 
305-             log:: warn!( 
306-                 "Device memory block size must be a multiple of 4MB, clamping to {}MB" , 
307-                 device_memblock_size / 1024  / 1024 
308-             ) 
339+         Self  { 
340+             min_device_memblock_size :  device_memblock_size, 
341+             max_device_memblock_size :  device_memblock_size, 
342+             min_host_memblock_size :  host_memblock_size, 
343+             max_host_memblock_size :  host_memblock_size, 
309344        } 
345+     } 
310346
311-         if  host_memblock_size % FOUR_MB  != 0  { 
312-             let  val = host_memblock_size / FOUR_MB  + 1 ; 
313-             host_memblock_size = val *  FOUR_MB ; 
314-             log:: warn!( 
315-                 "Host memory block size must be a multiple of 4MB, clamping to {}MB" , 
316-                 host_memblock_size / 1024  / 1024 
317-             ) 
318-         } 
347+     /// Sets the maximum device memblock size, in bytes. 
348+      pub  fn  with_max_device_memblock_size ( mut  self ,  size :  u64 )  -> Self  { 
349+         self . max_device_memblock_size  =
350+             Self :: adjust_memblock_size ( size,  "Device" ) . max ( self . min_device_memblock_size ) ; 
319351
320-         Self  { 
321-             device_memblock_size, 
322-             host_memblock_size, 
352+         self 
353+     } 
354+ 
355+     /// Sets the maximum host memblock size, in bytes. 
356+      pub  fn  with_max_host_memblock_size ( mut  self ,  size :  u64 )  -> Self  { 
357+         self . max_host_memblock_size  =
358+             Self :: adjust_memblock_size ( size,  "Host" ) . max ( self . min_host_memblock_size ) ; 
359+ 
360+         self 
361+     } 
362+ 
363+     fn  adjust_memblock_size ( size :  u64 ,  kind :  & str )  -> u64  { 
364+         const  MB :  u64  = 1024  *  1024 ; 
365+ 
366+         let  size = size. clamp ( 4  *  MB ,  256  *  MB ) ; 
367+ 
368+         if  size % ( 4  *  MB )  == 0  { 
369+             return  size; 
323370        } 
371+ 
372+         let  val = size / ( 4  *  MB )  + 1 ; 
373+         let  new_size = val *  4  *  MB ; 
374+         log:: warn!( 
375+             "{kind} memory block size must be a multiple of 4MB, clamping to {}MB" , 
376+             new_size / MB 
377+         ) ; 
378+ 
379+         new_size
380+     } 
381+ 
382+     /// Used internally to decide the size of a shared memory block 
383+      /// based withing the allowed range, based on the number of 
384+      /// existing allocations 
385+      pub ( crate )  fn  get_memblock_size ( & self ,  is_host :  bool ,  count :  usize )  -> u64  { 
386+         let  ( min_size,  max_size)  = if  is_host { 
387+             ( self . min_host_memblock_size ,  self . max_host_memblock_size ) 
388+         }  else  { 
389+             ( self . min_device_memblock_size ,  self . max_device_memblock_size ) 
390+         } ; 
391+ 
392+         // The ranges are clamped to 4MB..256MB so we never need to 
393+         // shift by more than 7 bits. Clamping here to avoid having 
394+         // to worry about overflows. 
395+         let  shift = count. min ( 7 )  as  u64 ; 
396+         ( min_size << shift) . min ( max_size) 
324397    } 
325398} 
326399
327400impl  Default  for  AllocationSizes  { 
328401    fn  default ( )  -> Self  { 
402+         const  MB :  u64  = 1024  *  1024 ; 
329403        Self  { 
330-             device_memblock_size :  256  *  1024  *  1024 , 
331-             host_memblock_size :  64  *  1024  *  1024 , 
404+             min_device_memblock_size :  256  *  MB , 
405+             max_device_memblock_size :  256  *  MB , 
406+             min_host_memblock_size :  64  *  MB , 
407+             max_host_memblock_size :  64  *  MB , 
332408        } 
333409    } 
334410} 
0 commit comments