@@ -639,7 +639,7 @@ impl TextureCache {
639
639
// - We have freed an item that will definitely allow us to
640
640
// fit the currently requested allocation.
641
641
let needed_slab_size =
642
- SlabSize :: new ( required_alloc. width , required_alloc. height ) . get_size ( ) ;
642
+ SlabSize :: new ( required_alloc. width , required_alloc. height ) ;
643
643
let mut found_matching_slab = false ;
644
644
let mut freed_complete_page = false ;
645
645
let mut evicted_items = 0 ;
@@ -765,11 +765,12 @@ impl TextureCache {
765
765
allowed_in_shared_cache = false ;
766
766
}
767
767
768
- // Anything larger than 512 goes in a standalone texture.
768
+ // Anything larger than TEXTURE_REGION_DIMENSIONS goes in a standalone texture.
769
769
// TODO(gw): If we find pages that suffer from batch breaks in this
770
770
// case, add support for storing these in a standalone
771
771
// texture array.
772
- if descriptor. width > 512 || descriptor. height > 512 {
772
+ if descriptor. width > TEXTURE_REGION_DIMENSIONS ||
773
+ descriptor. height > TEXTURE_REGION_DIMENSIONS {
773
774
allowed_in_shared_cache = false ;
774
775
}
775
776
@@ -900,43 +901,48 @@ impl TextureCache {
900
901
}
901
902
}
902
903
903
- // A list of the block sizes that a region can be initialized with.
904
+ #[ cfg_attr( feature = "capture" , derive( Serialize ) ) ]
905
+ #[ cfg_attr( feature = "replay" , derive( Deserialize ) ) ]
904
906
#[ derive( Copy , Clone , PartialEq ) ]
905
- enum SlabSize {
906
- Size16x16 ,
907
- Size32x32 ,
908
- Size64x64 ,
909
- Size128x128 ,
910
- Size256x256 ,
911
- Size512x512 ,
907
+ struct SlabSize {
908
+ width : u32 ,
909
+ height : u32 ,
912
910
}
913
911
914
912
impl SlabSize {
915
913
fn new ( width : u32 , height : u32 ) -> SlabSize {
916
- // TODO(gw): Consider supporting non-square
917
- // allocator sizes here.
918
- let max_dim = cmp:: max ( width, height) ;
919
-
920
- match max_dim {
921
- 0 => unreachable ! ( ) ,
922
- 1 ...16 => SlabSize :: Size16x16 ,
923
- 17 ...32 => SlabSize :: Size32x32 ,
924
- 33 ...64 => SlabSize :: Size64x64 ,
925
- 65 ...128 => SlabSize :: Size128x128 ,
926
- 129 ...256 => SlabSize :: Size256x256 ,
927
- 257 ...512 => SlabSize :: Size512x512 ,
928
- _ => panic ! ( "Invalid dimensions for cache!" ) ,
914
+ let x_size = quantize_dimension ( width) ;
915
+ let y_size = quantize_dimension ( height) ;
916
+
917
+ assert ! ( x_size > 0 && x_size <= TEXTURE_REGION_DIMENSIONS ) ;
918
+ assert ! ( y_size > 0 && y_size <= TEXTURE_REGION_DIMENSIONS ) ;
919
+
920
+ let ( width, height) = match ( x_size, y_size) {
921
+ // Special cased rectangular slab pages.
922
+ ( 512 , 256 ) => ( 512 , 256 ) ,
923
+ ( 512 , 128 ) => ( 512 , 128 ) ,
924
+ ( 512 , 64 ) => ( 512 , 64 ) ,
925
+ ( 256 , 512 ) => ( 256 , 512 ) ,
926
+ ( 128 , 512 ) => ( 128 , 512 ) ,
927
+ ( 64 , 512 ) => ( 64 , 512 ) ,
928
+
929
+ // If none of those fit, use a square slab size.
930
+ ( x_size, y_size) => {
931
+ let square_size = cmp:: max ( x_size, y_size) ;
932
+ ( square_size, square_size)
933
+ }
934
+ } ;
935
+
936
+ SlabSize {
937
+ width,
938
+ height,
929
939
}
930
940
}
931
941
932
- fn get_size ( & self ) -> u32 {
933
- match * self {
934
- SlabSize :: Size16x16 => 16 ,
935
- SlabSize :: Size32x32 => 32 ,
936
- SlabSize :: Size64x64 => 64 ,
937
- SlabSize :: Size128x128 => 128 ,
938
- SlabSize :: Size256x256 => 256 ,
939
- SlabSize :: Size512x512 => 512 ,
942
+ fn invalid ( ) -> SlabSize {
943
+ SlabSize {
944
+ width : 0 ,
945
+ height : 0 ,
940
946
}
941
947
}
942
948
}
@@ -960,9 +966,8 @@ impl TextureLocation {
960
966
struct TextureRegion {
961
967
layer_index : i32 ,
962
968
region_size : u32 ,
963
- slab_size : u32 ,
969
+ slab_size : SlabSize ,
964
970
free_slots : Vec < TextureLocation > ,
965
- slots_per_axis : u32 ,
966
971
total_slot_count : usize ,
967
972
origin : DeviceUintPoint ,
968
973
}
@@ -972,25 +977,25 @@ impl TextureRegion {
972
977
TextureRegion {
973
978
layer_index,
974
979
region_size,
975
- slab_size : 0 ,
980
+ slab_size : SlabSize :: invalid ( ) ,
976
981
free_slots : Vec :: new ( ) ,
977
- slots_per_axis : 0 ,
978
982
total_slot_count : 0 ,
979
983
origin,
980
984
}
981
985
}
982
986
983
987
// Initialize a region to be an allocator for a specific slab size.
984
988
fn init ( & mut self , slab_size : SlabSize ) {
985
- debug_assert ! ( self . slab_size == 0 ) ;
989
+ debug_assert ! ( self . slab_size == SlabSize :: invalid ( ) ) ;
986
990
debug_assert ! ( self . free_slots. is_empty( ) ) ;
987
991
988
- self . slab_size = slab_size. get_size ( ) ;
989
- self . slots_per_axis = self . region_size / self . slab_size ;
992
+ self . slab_size = slab_size;
993
+ let slots_per_x_axis = self . region_size / self . slab_size . width ;
994
+ let slots_per_y_axis = self . region_size / self . slab_size . height ;
990
995
991
996
// Add each block to a freelist.
992
- for y in 0 .. self . slots_per_axis {
993
- for x in 0 .. self . slots_per_axis {
997
+ for y in 0 .. slots_per_y_axis {
998
+ for x in 0 .. slots_per_x_axis {
994
999
self . free_slots . push ( TextureLocation :: new ( x, y) ) ;
995
1000
}
996
1001
}
@@ -1001,30 +1006,31 @@ impl TextureRegion {
1001
1006
// Deinit a region, allowing it to become a region with
1002
1007
// a different allocator size.
1003
1008
fn deinit ( & mut self ) {
1004
- self . slab_size = 0 ;
1009
+ self . slab_size = SlabSize :: invalid ( ) ;
1005
1010
self . free_slots . clear ( ) ;
1006
- self . slots_per_axis = 0 ;
1007
1011
self . total_slot_count = 0 ;
1008
1012
}
1009
1013
1010
1014
fn is_empty ( & self ) -> bool {
1011
- self . slab_size == 0
1015
+ self . slab_size == SlabSize :: invalid ( )
1012
1016
}
1013
1017
1014
1018
// Attempt to allocate a fixed size block from this region.
1015
1019
fn alloc ( & mut self ) -> Option < DeviceUintPoint > {
1020
+ debug_assert ! ( self . slab_size != SlabSize :: invalid( ) ) ;
1021
+
1016
1022
self . free_slots . pop ( ) . map ( |location| {
1017
1023
DeviceUintPoint :: new (
1018
- self . origin . x + self . slab_size * location. 0 as u32 ,
1019
- self . origin . y + self . slab_size * location. 1 as u32 ,
1024
+ self . origin . x + self . slab_size . width * location. 0 as u32 ,
1025
+ self . origin . y + self . slab_size . height * location. 1 as u32 ,
1020
1026
)
1021
1027
} )
1022
1028
}
1023
1029
1024
1030
// Free a block in this region.
1025
1031
fn free ( & mut self , point : DeviceUintPoint ) {
1026
- let x = ( point. x - self . origin . x ) / self . slab_size ;
1027
- let y = ( point. y - self . origin . y ) / self . slab_size ;
1032
+ let x = ( point. x - self . origin . x ) / self . slab_size . width ;
1033
+ let y = ( point. y - self . origin . y ) / self . slab_size . height ;
1028
1034
self . free_slots . push ( TextureLocation :: new ( x, y) ) ;
1029
1035
1030
1036
// If this region is completely unused, deinit it
@@ -1118,7 +1124,6 @@ impl TextureArray {
1118
1124
// Quantize the size of the allocation to select a region to
1119
1125
// allocate from.
1120
1126
let slab_size = SlabSize :: new ( width, height) ;
1121
- let slab_size_dim = slab_size. get_size ( ) ;
1122
1127
1123
1128
// TODO(gw): For simplicity, the initial implementation just
1124
1129
// has a single vec<> of regions. We could easily
@@ -1134,9 +1139,9 @@ impl TextureArray {
1134
1139
// Run through the existing regions of this size, and see if
1135
1140
// we can find a free block in any of them.
1136
1141
for ( i, region) in self . regions . iter_mut ( ) . enumerate ( ) {
1137
- if region. slab_size == 0 {
1142
+ if region. is_empty ( ) {
1138
1143
empty_region_index = Some ( i) ;
1139
- } else if region. slab_size == slab_size_dim {
1144
+ } else if region. slab_size == slab_size {
1140
1145
if let Some ( location) = region. alloc ( ) {
1141
1146
entry_kind = Some ( EntryKind :: Cache {
1142
1147
layer_index : region. layer_index as u16 ,
@@ -1244,3 +1249,16 @@ impl TextureUpdate {
1244
1249
}
1245
1250
}
1246
1251
}
1252
+
1253
+ fn quantize_dimension ( size : u32 ) -> u32 {
1254
+ match size {
1255
+ 0 => unreachable ! ( ) ,
1256
+ 1 ...16 => 16 ,
1257
+ 17 ...32 => 32 ,
1258
+ 33 ...64 => 64 ,
1259
+ 65 ...128 => 128 ,
1260
+ 129 ...256 => 256 ,
1261
+ 257 ...512 => 512 ,
1262
+ _ => panic ! ( "Invalid dimensions for cache!" ) ,
1263
+ }
1264
+ }
0 commit comments