Fixed a long-standing issue with the chained hashmap (finally)
This commit is contained in:
		| @@ -4,6 +4,8 @@ package VEFontCache | ||||
| The choice was made to keep the LRU cache implementation as close to the original as possible. | ||||
| */ | ||||
|  | ||||
| import "base:runtime" | ||||
|  | ||||
| PoolListIter  :: i32 | ||||
| PoolListValue :: u64 | ||||
|  | ||||
| @@ -20,9 +22,10 @@ PoolList :: struct { | ||||
| 	back      : PoolListIter, | ||||
| 	size      : u32, | ||||
| 	capacity  : u32, | ||||
| 	dbg_name  : string, | ||||
| } | ||||
|  | ||||
| pool_list_init :: proc( pool : ^PoolList, capacity : u32 ) | ||||
| pool_list_init :: proc( pool : ^PoolList, capacity : u32, dbg_name : string = "" ) | ||||
| { | ||||
| 	error : AllocatorError | ||||
| 	pool.items, error = make( Array( PoolListItem ), u64(capacity) ) | ||||
| @@ -35,6 +38,7 @@ pool_list_init :: proc( pool : ^PoolList, capacity : u32 ) | ||||
|  | ||||
| 	pool.capacity = capacity | ||||
|  | ||||
| 	pool.dbg_name = dbg_name | ||||
| 	using pool | ||||
|  | ||||
| 	for id in 0 ..< capacity { | ||||
| @@ -72,6 +76,9 @@ pool_list_push_front :: proc( pool : ^PoolList, value : PoolListValue ) | ||||
| 	items.data[ id ].prev  = -1 | ||||
| 	items.data[ id ].next  = front | ||||
| 	items.data[ id ].value = value | ||||
| 	if pool.dbg_name != "" { | ||||
| 		logf("pool_list: pushed %v into id %v", value, id) | ||||
| 	} | ||||
|  | ||||
| 	if front != -1 do items.data[ front ].prev = id | ||||
| 	if back  == -1 do back = id | ||||
| @@ -98,6 +105,9 @@ pool_list_erase :: proc( pool : ^PoolList, iter : PoolListIter ) | ||||
|  | ||||
| 	iter_node.prev  = -1 | ||||
| 	iter_node.next  = -1 | ||||
| 	// if pool.dbg_name != "" { | ||||
| 	// 	logf("pool_list: erased %v, at id %v", iter_node.value, iter) | ||||
| 	// } | ||||
| 	iter_node.value = 0 | ||||
| 	append( & free_list, iter ) | ||||
|  | ||||
| @@ -115,34 +125,35 @@ pool_list_peek_back :: proc ( pool : ^PoolList ) -> PoolListValue { | ||||
| } | ||||
|  | ||||
| pool_list_pop_back :: proc( pool : ^PoolList ) -> PoolListValue { | ||||
| 	using pool | ||||
| 	if size <= 0 do return 0 | ||||
| 	assert( back != -1 ) | ||||
| 	if pool.size <= 0 do return 0 | ||||
| 	assert( pool.back != -1 ) | ||||
|  | ||||
| 	value := items.data[ back ].value | ||||
| 	pool_list_erase( pool, back ) | ||||
| 	value := pool.items.data[ pool.back ].value | ||||
| 	pool_list_erase( pool, pool.back ) | ||||
| 	return value | ||||
| } | ||||
|  | ||||
| LRU_Link :: struct { | ||||
| 	pad_top : u64, | ||||
| 	value : i32, | ||||
| 	ptr   : PoolListIter, | ||||
| 	pad_bottom : u64, | ||||
| } | ||||
|  | ||||
| LRU_Cache :: struct { | ||||
| 	capacity  : u32, | ||||
| 	num       : u32, | ||||
| 	table     : HMapZPL(LRU_Link), | ||||
| 	table     : HMapChained(LRU_Link), | ||||
| 	key_queue : PoolList, | ||||
| } | ||||
|  | ||||
| LRU_init :: proc( cache : ^LRU_Cache, capacity : u32 ) { | ||||
| LRU_init :: proc( cache : ^LRU_Cache, capacity : u32, dbg_name : string = "" ) { | ||||
| 	error : AllocatorError | ||||
| 	cache.capacity     = capacity | ||||
| 	cache.table, error = hmap_zpl_init( HMapZPL(LRU_Link), u64( hmap_closest_prime( uint(capacity))) ) | ||||
| 	cache.table, error = make( HMapChained(LRU_Link), hmap_closest_prime( uint(capacity)) ) | ||||
| 	assert( error == .None, "VEFontCache.LRU_init : Failed to allocate cache's table") | ||||
|  | ||||
| 	pool_list_init( & cache.key_queue, capacity ) | ||||
| 	pool_list_init( & cache.key_queue, capacity, dbg_name = dbg_name ) | ||||
| } | ||||
|  | ||||
| LRU_free :: proc( cache : ^LRU_Cache ) | ||||
| @@ -152,7 +163,7 @@ LRU_free :: proc( cache : ^LRU_Cache ) | ||||
|  | ||||
| LRU_reload :: proc( cache : ^LRU_Cache, allocator : Allocator ) | ||||
| { | ||||
| 	hmap_zpl_reload( & cache.table, allocator ) | ||||
| 	hmap_chained_reload( cache.table, allocator ) | ||||
| 	pool_list_reload( & cache.key_queue, allocator ) | ||||
| } | ||||
|  | ||||
| @@ -162,9 +173,13 @@ LRU_hash_key :: #force_inline proc( key : u64 ) -> ( hash : u64 ) { | ||||
| 	return | ||||
| } | ||||
|  | ||||
| LRU_find :: proc( cache : ^LRU_Cache, key : u64 ) -> ^LRU_Link { | ||||
| LRU_find :: proc( cache : ^LRU_Cache, key : u64, must_find := false ) -> ^LRU_Link { | ||||
| 	hash := LRU_hash_key( key ) | ||||
| 	link := get( & cache.table, hash ) | ||||
| 	link := get( cache.table, hash ) | ||||
| 	// if link == nil && must_find { | ||||
| 	// 	runtime.debug_trap() | ||||
| 	// 	link = get( cache.table, hash ) | ||||
| 	// } | ||||
| 	return link | ||||
| } | ||||
|  | ||||
| @@ -186,8 +201,8 @@ LRU_get_next_evicted :: proc( cache : ^LRU_Cache ) -> u64 | ||||
| 	return 0xFFFFFFFFFFFFFFFF | ||||
| } | ||||
|  | ||||
| LRU_peek :: proc( cache : ^LRU_Cache, key : u64 ) -> i32 { | ||||
| 	iter := LRU_find( cache, key ) | ||||
| LRU_peek :: proc( cache : ^LRU_Cache, key : u64, must_find := false ) -> i32 { | ||||
| 	iter := LRU_find( cache, key, must_find ) | ||||
| 	if iter == nil { | ||||
| 		return -1 | ||||
| 	} | ||||
| @@ -197,7 +212,7 @@ LRU_peek :: proc( cache : ^LRU_Cache, key : u64 ) -> i32 { | ||||
| LRU_put :: proc( cache : ^LRU_Cache, key : u64,  value : i32 ) -> u64 | ||||
| { | ||||
| 	hash_key := LRU_hash_key( key ) | ||||
| 	iter     := get( & cache.table, hash_key ) | ||||
| 	iter     := get( cache.table, hash_key ) | ||||
| 	if iter != nil { | ||||
| 		LRU_refresh( cache, key ) | ||||
| 		iter.value = value | ||||
| @@ -209,14 +224,19 @@ LRU_put :: proc( cache : ^LRU_Cache, key : u64,  value : i32 ) -> u64 | ||||
| 		evict = pool_list_pop_back( & cache.key_queue ) | ||||
|  | ||||
| 		evict_hash := LRU_hash_key( evict ) | ||||
| 		hmap_zpl_remove( & cache.table, evict_hash ) | ||||
| 		// if cache.table.dbg_name != "" { | ||||
| 		// 	logf("%v: Evicted   %v with hash: %v", cache.table.dbg_name, evict, evict_hash) | ||||
| 		// } | ||||
| 		hmap_chained_remove( cache.table, evict_hash ) | ||||
| 		cache.num -= 1 | ||||
| 	} | ||||
|  | ||||
| 	pool_list_push_front( & cache.key_queue, key ) | ||||
| 	// if cache.table.dbg_name != "" { | ||||
| 	// 	logf("%v: Pushed   %v with hash: %v", cache.table.dbg_name, key, hash_key ) | ||||
| 	// } | ||||
|  | ||||
| 	// set( cache.table, hash_key, LRU_Link { | ||||
| 	set( & cache.table, hash_key, LRU_Link { | ||||
| 	set( cache.table, hash_key, LRU_Link { | ||||
| 		value = value, | ||||
| 		ptr   = cache.key_queue.front | ||||
| 	}) | ||||
| @@ -227,6 +247,9 @@ LRU_put :: proc( cache : ^LRU_Cache, key : u64,  value : i32 ) -> u64 | ||||
|  | ||||
| LRU_refresh :: proc( cache : ^LRU_Cache, key : u64 ) { | ||||
| 	link := LRU_find( cache, key ) | ||||
| 	// if cache.table.dbg_name != "" { | ||||
| 	// 	logf("%v: Refreshed %v", cache.table.dbg_name, key) | ||||
| 	// } | ||||
| 	pool_list_erase( & cache.key_queue, link.ptr ) | ||||
| 	pool_list_push_front( & cache.key_queue, key ) | ||||
| 	link.ptr = cache.key_queue.front | ||||
|   | ||||
| @@ -15,6 +15,7 @@ Changes: | ||||
| */ | ||||
| package VEFontCache | ||||
|  | ||||
| import "base:runtime" | ||||
| import "core:math" | ||||
| import "core:mem" | ||||
|  | ||||
| @@ -625,7 +626,7 @@ cache_glyph_to_atlas :: proc( ctx : ^Context, font : FontID, glyph_index : Glyph | ||||
| 			next_evict_codepoint := LRU_get_next_evicted( & region.state ) | ||||
| 			assert( next_evict_codepoint != 0xFFFFFFFFFFFFFFFF ) | ||||
|  | ||||
| 			atlas_index = LRU_peek( & region.state, next_evict_codepoint ) | ||||
| 			atlas_index = LRU_peek( & region.state, next_evict_codepoint, must_find = true ) | ||||
| 			assert( atlas_index != -1 ) | ||||
|  | ||||
| 			evicted := LRU_put( & region.state, lru_code, atlas_index ) | ||||
| @@ -763,16 +764,17 @@ shape_text_cached :: proc( ctx : ^Context, font : FontID, text_utf8 : string ) - | ||||
| 	if shape_cache_idx == -1 | ||||
| 	{ | ||||
| 		if shape_cache.next_cache_id < i32(state.capacity) { | ||||
| 			shape_cache_idx = shape_cache.next_cache_id | ||||
| 			LRU_put( state, hash, shape_cache_idx ) | ||||
| 			shape_cache_idx            = shape_cache.next_cache_id | ||||
| 			shape_cache.next_cache_id += 1 | ||||
| 			evicted := LRU_put( state, hash, shape_cache_idx ) | ||||
| 			assert( evicted == hash ) | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			next_evict_idx := LRU_get_next_evicted( state ) | ||||
| 			assert( next_evict_idx != 0xFFFFFFFFFFFFFFFF ) | ||||
|  | ||||
| 			shape_cache_idx = LRU_peek( state, next_evict_idx ) | ||||
| 			shape_cache_idx = LRU_peek( state, next_evict_idx, must_find = true ) | ||||
| 			assert( shape_cache_idx != - 1 ) | ||||
|  | ||||
| 			LRU_put( state, hash, shape_cache_idx ) | ||||
|   | ||||
| @@ -8,6 +8,8 @@ import "core:mem" | ||||
|  | ||||
| Kilobyte :: mem.Kilobyte | ||||
|  | ||||
| slice_ptr :: mem.slice_ptr | ||||
|  | ||||
| Arena :: mem.Arena | ||||
|  | ||||
| arena_allocator :: mem.arena_allocator | ||||
| @@ -46,6 +48,7 @@ hmap_chained_destroy :: grime.hmap_chained_destroy | ||||
| hmap_chained_init    :: grime.hmap_chained_init | ||||
| hmap_chained_get     :: grime.hmap_chained_get | ||||
| hmap_chained_remove  :: grime.hmap_chained_remove | ||||
| hmap_chained_reload  :: grime.hmap_chained_reload | ||||
| hmap_chained_set     :: grime.hmap_chained_set | ||||
| hmap_closest_prime   :: grime.hmap_closest_prime | ||||
|  | ||||
|   | ||||
| @@ -13,8 +13,8 @@ and direct pointers are kept across the codebase instead of a key to the slot. | ||||
| */ | ||||
| package grime | ||||
|  | ||||
| import "core:mem" | ||||
| import "base:runtime" | ||||
| import "core:mem" | ||||
|  | ||||
| HTable_Minimum_Capacity :: 4 * Kilobyte | ||||
|  | ||||
| @@ -26,6 +26,7 @@ HMapChainedSlot :: struct( $Type : typeid ) { | ||||
| } | ||||
|  | ||||
| HMapChainedHeader :: struct( $ Type : typeid ) { | ||||
| 	tracker  : MemoryTracker, | ||||
| 	pool     : Pool, | ||||
| 	lookup   : [] ^HMapChainedSlot(Type), | ||||
| 	dbg_name : string, | ||||
| @@ -62,7 +63,7 @@ hmap_chained_init :: proc( $HMapChainedType : typeid/HMapChained($Type), lookup_ | ||||
| ) -> (table : HMapChained(Type), error : AllocatorError) | ||||
| { | ||||
| 	header_size := size_of(HMapChainedHeader(Type)) | ||||
| 	size  := header_size + int(lookup_capacity) * size_of( ^HMapChainedSlot(Type)) + size_of(int) | ||||
| 	size  := header_size + int(lookup_capacity) * size_of( ^HMapChainedSlot(Type)) | ||||
|  | ||||
| 	raw_mem : rawptr | ||||
| 	raw_mem, error = alloc( size, allocator = allocator ) | ||||
| @@ -79,9 +80,14 @@ hmap_chained_init :: proc( $HMapChainedType : typeid/HMapChained($Type), lookup_ | ||||
| 		dbg_name            = str_intern(str_fmt("%v: pool", dbg_name)).str, | ||||
| 		enable_mem_tracking = enable_mem_tracking, | ||||
| 	) | ||||
| 	data          := transmute([^] ^HMapChainedSlot(Type)) (transmute( [^]HMapChainedHeader(Type)) table.header)[1:] | ||||
| 	data          := transmute(^^HMapChainedSlot(Type)) memory_after_header(table.header) | ||||
| 	table.lookup   = slice_ptr( data, int(lookup_capacity) ) | ||||
| 	table.dbg_name = dbg_name | ||||
|  | ||||
| 	if Track_Memory && enable_mem_tracking { | ||||
| 		memtracker_init( & table.tracker, allocator, Kilobyte * 16, dbg_name ) | ||||
| 	} | ||||
|  | ||||
| 	return | ||||
| } | ||||
|  | ||||
| @@ -115,9 +121,6 @@ hmap_chained_get :: proc( using self : HMapChained($Type), key : u64) -> ^Type | ||||
| { | ||||
| 	// profile(#procedure) | ||||
| 	hash_index   := hmap_chained_lookup_id(self, key) | ||||
| 	// if hash_index == 565 { | ||||
| 	// 	runtime.debug_trap() | ||||
| 	// } | ||||
| 	surface_slot := lookup[hash_index] | ||||
|  | ||||
| 	if surface_slot == nil { | ||||
| @@ -128,9 +131,13 @@ hmap_chained_get :: proc( using self : HMapChained($Type), key : u64) -> ^Type | ||||
| 		return & surface_slot.value | ||||
| 	} | ||||
|  | ||||
| 	for slot := surface_slot.next; slot != nil; slot = slot.next { | ||||
| 	for slot := surface_slot.next; slot != nil; slot = slot.next | ||||
| 	{ | ||||
| 		if slot.occupied && slot.key == key { | ||||
| 			return & surface_slot.value | ||||
| 			if self.dbg_name != "" && self.tracker.entries.header != nil { | ||||
| 				logf( "%v: Retrieved %v in lookup[%v] which shows key as %v", self.dbg_name, key, hash_index, slot.key ) | ||||
| 			} | ||||
| 			return & slot.value | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| @@ -139,14 +146,15 @@ hmap_chained_get :: proc( using self : HMapChained($Type), key : u64) -> ^Type | ||||
|  | ||||
| hmap_chained_reload :: proc( self : HMapChained($Type), allocator : Allocator ) | ||||
| { | ||||
| 	pool_reload(self.pool, allocator) | ||||
| 	// pool_reload(self.pool, allocator) | ||||
| } | ||||
|  | ||||
| // Returns true if an slot was actually found and marked as vacant | ||||
| // Entries already found to be vacant will not return true | ||||
| hmap_chained_remove :: proc( self : HMapChained($Type), key : u64 ) -> b32 | ||||
| { | ||||
| 	surface_slot := self.lookup[hmap_chained_lookup_id(self, key)] | ||||
| 	hash_index   := hmap_chained_lookup_id(self, key) | ||||
| 	surface_slot := self.lookup[hash_index] | ||||
|  | ||||
| 	if surface_slot == nil { | ||||
| 		return false | ||||
| @@ -154,13 +162,24 @@ hmap_chained_remove :: proc( self : HMapChained($Type), key : u64 ) -> b32 | ||||
|  | ||||
| 	if surface_slot.occupied && surface_slot.key == key { | ||||
| 		surface_slot.occupied = false | ||||
| 		surface_slot.value    = {} | ||||
| 		surface_slot.key      = {} | ||||
| 		if self.dbg_name != "" && self.tracker.entries.header != nil { | ||||
| 			logf( "%v: Removed %v in lookup[%v]", self.dbg_name, key, hash_index ) | ||||
| 		} | ||||
| 		return true | ||||
| 	} | ||||
|  | ||||
| 	for slot := surface_slot.next; slot != nil; slot = slot.next  | ||||
| 	nest_id : i32 = 1 | ||||
| 	for slot := surface_slot.next; slot != nil; slot = slot.next | ||||
| 	{ | ||||
| 		if slot.occupied && slot.key == key { | ||||
| 			slot.occupied = false | ||||
| 			slot.value    = {} | ||||
| 			slot.key      = {} | ||||
| 			if self.dbg_name != "" && self.tracker.entries.header != nil { | ||||
| 				logf( "%v: Removed %v in lookup[%v] nest_id: %v", self.dbg_name, key, hash_index, nest_id ) | ||||
| 			} | ||||
| 			return true | ||||
| 		} | ||||
| 	} | ||||
| @@ -176,62 +195,69 @@ hmap_chained_set :: proc( self : HMapChained($Type), key : u64, value : Type ) - | ||||
| 	using self | ||||
| 	hash_index   := hmap_chained_lookup_id(self, key) | ||||
| 	surface_slot := lookup[hash_index] | ||||
| 	set_slot :: #force_inline proc( using self : HMapChained(Type), | ||||
| 		slot  : ^HMapChainedSlot(Type), | ||||
| 		key   : u64, | ||||
| 		value : Type | ||||
| 	) -> (^ Type, AllocatorError ) | ||||
| 	{ | ||||
| 		error := AllocatorError.None | ||||
| 		if slot.next == nil { | ||||
| 			block        : []byte | ||||
| 			block, error = pool_grab(pool, false) | ||||
| 			next        := transmute( ^HMapChainedSlot(Type)) & block[0] | ||||
| 			next^ = {} | ||||
| 			slot.next    = next | ||||
| 			next.prev    = slot | ||||
| 		} | ||||
| 		slot.key      = key | ||||
| 		slot.value    = value | ||||
| 		slot.occupied = true | ||||
| 		return & slot.value, error | ||||
| 	} | ||||
|  | ||||
| 	if surface_slot == nil { | ||||
| 		block, error         := pool_grab(pool, false) | ||||
| 		surface_slot         := transmute( ^HMapChainedSlot(Type)) & block[0] | ||||
| 	slot_size := size_of(HMapChainedSlot(Type)) | ||||
| 	if surface_slot == nil | ||||
| 	{ | ||||
| 		block, error := pool_grab(pool, false) | ||||
| 		surface_slot := transmute( ^HMapChainedSlot(Type)) raw_data(block) | ||||
| 		surface_slot^ = {} | ||||
|  | ||||
| 		surface_slot.key      = key | ||||
| 		surface_slot.value    = value | ||||
| 		surface_slot.occupied = true | ||||
| 		if error != AllocatorError.None { | ||||
| 			ensure(error != AllocatorError.None, "Allocation failure for chained slot in hash table") | ||||
| 			return nil, error | ||||
| 		} | ||||
|  | ||||
| 		lookup[hash_index] = surface_slot | ||||
|  | ||||
| 		block, error = pool_grab(pool, false) | ||||
| 		next             := transmute( ^HMapChainedSlot(Type)) & block[0] | ||||
| 		next^ = {} | ||||
| 		surface_slot.next = next | ||||
| 		next.prev         = surface_slot | ||||
| 		if Track_Memory && tracker.entries.header != nil { | ||||
| 			memtracker_register_auto_name_slice( & self.tracker, block) | ||||
| 		} | ||||
| 		return & surface_slot.value, error | ||||
| 	} | ||||
|  | ||||
| 	if ! surface_slot.occupied | ||||
| 	{ | ||||
| 		result, error := set_slot( self, surface_slot, key, value) | ||||
| 		return result, error | ||||
| 		surface_slot.key      = key | ||||
| 		surface_slot.value    = value | ||||
| 		surface_slot.occupied = true | ||||
| 		if dbg_name != "" && tracker.entries.header != nil { | ||||
| 			logf( "%v: Set     %v in lookup[%v]", self.dbg_name, key, hash_index ) | ||||
| 		} | ||||
|  | ||||
| 		return & surface_slot.value, .None | ||||
| 	} | ||||
|  | ||||
| 	slot : ^HMapChainedSlot(Type) = surface_slot.next | ||||
| 	for ; slot != nil; slot = slot.next | ||||
| 	slot : ^HMapChainedSlot(Type) = surface_slot | ||||
| 	nest_id : i32 = 1 | ||||
| 	for ;; slot = slot.next | ||||
| 	{ | ||||
| 		if !slot.occupied | ||||
| 		error : AllocatorError | ||||
| 		if slot.next == nil | ||||
| 		{ | ||||
| 			result, error := set_slot( self, slot, key, value) | ||||
| 			return result, error | ||||
| 			block        : []byte | ||||
| 			block, error = pool_grab(pool, false) | ||||
| 			next        := transmute( ^HMapChainedSlot(Type)) raw_data(block) | ||||
|  | ||||
| 			slot.next      = next | ||||
| 			slot.next^     = {} | ||||
| 			slot.next.prev = slot | ||||
| 			if Track_Memory && tracker.entries.header != nil { | ||||
| 				memtracker_register_auto_name_slice( & self.tracker, block) | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		if ! slot.next.occupied | ||||
| 		{ | ||||
| 			slot.next.key      = key | ||||
| 			slot.next.value    = value | ||||
| 			slot.next.occupied = true | ||||
| 			if dbg_name != "" && tracker.entries.header != nil { | ||||
| 				logf( "%v: Set     %v in lookup[%v] nest_id: %v", self.dbg_name, key, hash_index, nest_id ) | ||||
| 			} | ||||
| 			return & slot.next.value, .None | ||||
| 		} | ||||
|  | ||||
| 		nest_id += 1 | ||||
| 	} | ||||
| 	ensure(false, "Somehow got to a null slot that wasn't preemptively allocated from a previus set") | ||||
| 	return nil, AllocatorError.None | ||||
|   | ||||
| @@ -276,7 +276,7 @@ varena_allocator_proc :: proc( | ||||
| 				data = new_region | ||||
| 				// log( str_fmt_tmp("varena resize (new): old: %p %v new: %p %v", old_memory, old_size, (& data[0]), size)) | ||||
|  | ||||
| 				when Track_Memory { | ||||
| 				if Track_Memory && arena.tracker.entries.header != nil { | ||||
| 					memtracker_register_auto_name( & arena.tracker, & data[0], & data[len(data) - 1] ) | ||||
| 				} | ||||
| 				return | ||||
|   | ||||
| @@ -128,9 +128,9 @@ setup_memory :: proc( profiler : ^SpallProfiler ) -> ClientMemory | ||||
| 			sectr.Memory_Reserve_Persistent, | ||||
| 			sectr.Memory_Commit_Initial_Persistent, | ||||
| 			growth_policy    = nil, | ||||
| 			allow_any_resize = false, | ||||
| 			allow_any_resize = true, | ||||
| 			dbg_name         = "persistent", | ||||
| 			enable_mem_tracking = true ) | ||||
| 			enable_mem_tracking = false ) | ||||
| 		verify( alloc_error == .None, "Failed to allocate persistent virtual arena for the sectr module") | ||||
|  | ||||
| 		frame, alloc_error = varena_init( | ||||
|   | ||||
| @@ -92,7 +92,7 @@ startup :: proc( prof : ^SpallProfiler, persistent_mem, frame_mem, transient_mem | ||||
| 		// push( policy_ptr, SlabSizeClass { 512 * Megabyte, 512 * Megabyte, alignment }) | ||||
|  | ||||
| 		alloc_error : AllocatorError | ||||
| 		persistent_slab, alloc_error = slab_init( policy_ptr, allocator = persistent_allocator(), dbg_name = Persistent_Slab_DBG_Name, enable_mem_tracking = true ) | ||||
| 		persistent_slab, alloc_error = slab_init( policy_ptr, allocator = persistent_allocator(), dbg_name = Persistent_Slab_DBG_Name, enable_mem_tracking = false ) | ||||
| 		verify( alloc_error == .None, "Failed to allocate the persistent slab" ) | ||||
|  | ||||
| 		transient_slab, alloc_error = slab_init( & default_slab_policy, allocator = transient_allocator(), dbg_name = Transient_Slab_DBG_Name ) | ||||
| @@ -254,23 +254,23 @@ startup :: proc( prof : ^SpallProfiler, persistent_mem, frame_mem, transient_mem | ||||
| 	if true | ||||
| 	{ | ||||
| 		font_provider_startup() | ||||
| 		// path_rec_mono_semicasual_reg := strings.concatenate( { Path_Assets, "RecMonoSemicasual-Regular-1.084.ttf" }) | ||||
| 		// font_rec_mono_semicasual_reg  = font_load( path_rec_mono_semicasual_reg, 24.0, "RecMonoSemiCasual_Regular" ) | ||||
| 		path_rec_mono_semicasual_reg := strings.concatenate( { Path_Assets, "RecMonoSemicasual-Regular-1.084.ttf" }) | ||||
| 		font_rec_mono_semicasual_reg  = font_load( path_rec_mono_semicasual_reg, 24.0, "RecMonoSemiCasual_Regular" ) | ||||
|  | ||||
| 		// path_squidgy_slimes := strings.concatenate( { Path_Assets, "Squidgy Slimes.ttf" } ) | ||||
| 		// font_squidgy_slimes = font_load( path_squidgy_slimes, 24.0, "Squidgy_Slime" ) | ||||
| 		path_squidgy_slimes := strings.concatenate( { Path_Assets, "Squidgy Slimes.ttf" } ) | ||||
| 		font_squidgy_slimes = font_load( path_squidgy_slimes, 24.0, "Squidgy_Slime" ) | ||||
|  | ||||
| 		path_firacode := strings.concatenate( { Path_Assets, "FiraCode-Regular.ttf" } ) | ||||
| 		font_firacode  = font_load( path_firacode, 24.0, "FiraCode" ) | ||||
|  | ||||
| 		// path_open_sans := strings.concatenate( { Path_Assets, "OpenSans-Regular.ttf" } ) | ||||
| 		// font_open_sans  = font_load( path_open_sans, 24.0, "OpenSans" ) | ||||
| 		path_open_sans := strings.concatenate( { Path_Assets, "OpenSans-Regular.ttf" } ) | ||||
| 		font_open_sans  = font_load( path_open_sans, 24.0, "OpenSans" ) | ||||
|  | ||||
| 		// path_noto_sans := strings.concatenate( { Path_Assets, "NotoSans-Regular.ttf" } ) | ||||
| 		// font_noto_sans  = font_load( path_noto_sans, 24.0, "NotoSans" ) | ||||
| 		path_noto_sans := strings.concatenate( { Path_Assets, "NotoSans-Regular.ttf" } ) | ||||
| 		font_noto_sans  = font_load( path_noto_sans, 24.0, "NotoSans" ) | ||||
|  | ||||
| 		// path_arial_unicode_ms := strings.concatenate( { Path_Assets, "Arial Unicode MS.ttf" } ) | ||||
| 		// font_arial_unicode_ms  = font_load( path_arial_unicode_ms, 24.0, "Arial_Unicode_MS" ) | ||||
| 		path_arial_unicode_ms := strings.concatenate( { Path_Assets, "Arial Unicode MS.ttf" } ) | ||||
| 		font_arial_unicode_ms  = font_load( path_arial_unicode_ms, 24.0, "Arial_Unicode_MS" ) | ||||
|  | ||||
| 		default_font = font_firacode | ||||
| 		log( "Default font loaded" ) | ||||
|   | ||||
| @@ -125,7 +125,7 @@ render_mode_screenspace :: proc() | ||||
| 	debug.debug_text_vis = true | ||||
| 	if debug.debug_text_vis | ||||
| 	{ | ||||
| 		fps_msg       := str_fmt( "FPS: %0.2f", fps_avg) | ||||
| 		fps_msg       := str_fmt( "FPS: %d", frame) | ||||
| 		fps_msg_width := measure_text_size( fps_msg, default_font, 12.0, 0.0 ).x | ||||
| 		fps_msg_pos   := screen_get_corners().top_right - { fps_msg_width, 0 } - { 5, 5 } | ||||
| 		debug_draw_text( fps_msg, fps_msg_pos, 38.0, color = Color_Red ) | ||||
| @@ -133,7 +133,7 @@ render_mode_screenspace :: proc() | ||||
| 		// debug_text( "Screen Width : %v", rl.GetScreenWidth () ) | ||||
| 		// debug_text( "Screen Height: %v", rl.GetScreenHeight() ) | ||||
| 		// debug_text( "frametime_target_ms       : %f ms", frametime_target_ms ) | ||||
| 		debug_text( "frametime                 : %f ms", frametime_delta_ms ) | ||||
| 		debug_text( "frametime                 : %d ms", frame ) | ||||
| 		// debug_text( "frametime_last_elapsed_ms : %f ms", frametime_elapsed_ms ) | ||||
| 		if replay.mode == ReplayMode.Record { | ||||
| 			debug_text( "Recording Input") | ||||
|   | ||||
| @@ -70,10 +70,10 @@ font_provider_startup :: proc() | ||||
| 	provider_data := & state.font_provider_data; using provider_data | ||||
|  | ||||
| 	error : AllocatorError | ||||
| 	font_cache, error = make( HMapChained(FontDef), hmap_closest_prime(1 * Kilo), persistent_allocator() /*dbg_name = "font_cache"*/ ) | ||||
| 	font_cache, error = make( HMapChained(FontDef), hmap_closest_prime(1 * Kilo), persistent_allocator(), dbg_name = "font_cache" ) | ||||
| 	verify( error == AllocatorError.None, "Failed to allocate font_cache" ) | ||||
|  | ||||
| 	ve.init( & provider_data.ve_font_cache, .STB_TrueType, allocator = persistent_slab_allocator() ) | ||||
| 	ve.init( & provider_data.ve_font_cache, .STB_TrueType, allocator = persistent_allocator() ) | ||||
| 	log("VEFontCached initialized") | ||||
|  | ||||
| 	ve.configure_snap( & provider_data.ve_font_cache, u32(state.app_window.extent.x * 2.0), u32(state.app_window.extent.y * 2.0) ) | ||||
| @@ -552,7 +552,7 @@ font_load :: proc(path_file : string, | ||||
|  | ||||
| 	for font_size : i32 = Font_Size_Interval; font_size <= Font_Largest_Px_Size; font_size += Font_Size_Interval | ||||
| 	{ | ||||
| 		logf("Loading at size %v", font_size) | ||||
| 		// logf("Loading at size %v", font_size) | ||||
| 		id    := (font_size / Font_Size_Interval) + (font_size % Font_Size_Interval) | ||||
| 		ve_id := & def.size_table[id - 1] | ||||
| 		ve_id^ = ve.load_font( & provider_data.ve_font_cache, desired_id, font_data, 14.0 ) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user