diff --git a/assets/Arial Unicode MS.ttf b/assets/Arial Unicode MS.ttf new file mode 100644 index 0000000..51a18bc Binary files /dev/null and b/assets/Arial Unicode MS.ttf differ diff --git a/assets/NotoSans-Regular.ttf b/assets/NotoSans-Regular.ttf new file mode 100644 index 0000000..fa4cff5 Binary files /dev/null and b/assets/NotoSans-Regular.ttf differ diff --git a/code/font/VEFontCache/LRU.odin b/code/font/VEFontCache/LRU.odin index 4583364..bf1b1de 100644 --- a/code/font/VEFontCache/LRU.odin +++ b/code/font/VEFontCache/LRU.odin @@ -110,14 +110,14 @@ LRU_Link :: struct { LRU_Cache :: struct { capacity : u32, num : u32, - table : HMapChained(LRU_Link), + table : HMapZPL(LRU_Link), key_queue : PoolList, } LRU_init :: proc( cache : ^LRU_Cache, capacity : u32 ) { error : AllocatorError cache.capacity = capacity - cache.table, error = make( HMapChained(LRU_Link), hmap_closest_prime( uint(capacity)) ) + cache.table, error = hmap_zpl_init( HMapZPL(LRU_Link), u64( hmap_closest_prime( uint(capacity))) ) assert( error == .None, "VEFontCache.LRU_init : Failed to allocate cache's table") pool_list_init( & cache.key_queue, capacity ) @@ -126,7 +126,7 @@ LRU_init :: proc( cache : ^LRU_Cache, capacity : u32 ) { LRU_find :: proc( cache : ^LRU_Cache, value : u64 ) -> ^LRU_Link { bytes := transmute( [8]byte ) value key := fnv64a( bytes[:] ) - link := get( cache.table, key ) + link := get( & cache.table, key ) return link } @@ -167,7 +167,8 @@ LRU_put :: proc( cache : ^LRU_Cache, key : u64, value : i32 ) -> u64 { evict := key if cache.key_queue.size >= cache.capacity { evict = pool_list_pop_back( & cache.key_queue ) - hmap_chained_remove( cache.table, evict ) + // hmap_chained_remove( cache.table, evict ) + hmap_zpl_remove( & cache.table, evict ) cache.num -= 1 } @@ -175,7 +176,8 @@ LRU_put :: proc( cache : ^LRU_Cache, key : u64, value : i32 ) -> u64 { bytes := transmute( [8]byte ) key hash_key := fnv64a( bytes[:] ) - hmap_chained_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 }) diff --git a/code/font/VEFontCache/VEFontCache.odin b/code/font/VEFontCache/VEFontCache.odin index 1b39fa9..12164e3 100644 --- a/code/font/VEFontCache/VEFontCache.odin +++ b/code/font/VEFontCache/VEFontCache.odin @@ -80,7 +80,7 @@ Context :: struct { entries : Array(Entry), temp_path : Array(Vec2), - temp_codepoint_seen : HMapChained(bool), + temp_codepoint_seen : HMapZPL(bool), temp_codepoint_seen_num : u32, snap_width : u32, @@ -258,7 +258,7 @@ init :: proc( ctx : ^Context, parser_kind : ParserKind, temp_path, error = make( Array(Vec2), u64(temp_path_reserve) ) assert(error == .None, "VEFontCache.init : Failed to allocate temp_path") - temp_codepoint_seen, error = make( HMapChained(bool), hmap_closest_prime( uint(temp_codepoint_seen_reserve)) ) + temp_codepoint_seen, error = make( HMapZPL(bool), u64(hmap_closest_prime( uint(temp_codepoint_seen_reserve))) ) assert(error == .None, "VEFontCache.init : Failed to allocate temp_path") draw_list.vertices, error = make( Array(Vertex), 4 * Kilobyte ) @@ -500,6 +500,7 @@ cache_glyph :: proc( ctx : ^Context, font : FontID, glyph_index : Glyph, scale, for edge in shape do switch edge.type { case .Move: + path_slice := array_to_slice(path) if path.num > 0 { draw_filled_path( & ctx.draw_list, outside, array_to_slice(path), scale, translate, ctx.debug_print_verbose ) } @@ -679,17 +680,17 @@ is_empty :: proc( ctx : ^Context, entry : ^Entry, glyph_index : Glyph ) -> b32 } reset_batch_codepoint_state :: proc( ctx : ^Context ) { - clear( ctx.temp_codepoint_seen ) + clear( & ctx.temp_codepoint_seen ) ctx.temp_codepoint_seen_num = 0 } shape_text_cached :: proc( ctx : ^Context, font : FontID, text_utf8 : string ) -> ^ShapedText { - ELFhash64 :: proc( hash : ^u64, ptr : ^( $Type), count := 1 ) + ELFhash64 :: proc( hash : ^u64, ptr : ^( $Type), count : i32 = 1 ) { x := u64(0) bytes := transmute( [^]byte) ptr - for index : i32 = 0; index < i32( size_of(Type)); index += 1 { + for index : i32 = 0; index < i32( size_of(Type)) * count; index += 1 { (hash^) = ((hash^) << 4 ) + u64(bytes[index]) x = (hash^) & 0xF000000000000000 if x != 0 { @@ -701,9 +702,10 @@ shape_text_cached :: proc( ctx : ^Context, font : FontID, text_utf8 : string ) - font := font - hash := cast(u64) 0x9f8e00d51d263c24; - ELFhash64( & hash, raw_data(transmute([]u8) text_utf8), len(text_utf8) ) + hash := cast(u64) 0x9f8e00d51d263c24; + ELFhash64( & hash, raw_data(transmute([]u8) text_utf8), cast(i32) len(text_utf8) ) ELFhash64( & hash, & font ) + // hash := cast(u64) crc32( transmute([]u8) text_utf8 ) shape_cache := & ctx.shape_cache state := & ctx.shape_cache.state diff --git a/code/font/VEFontCache/atlas.odin b/code/font/VEFontCache/atlas.odin index 67584ad..ac2b0bb 100644 --- a/code/font/VEFontCache/atlas.odin +++ b/code/font/VEFontCache/atlas.odin @@ -101,7 +101,7 @@ can_batch_glyph :: proc( ctx : ^Context, font : FontID, entry : ^Entry, glyph_in if region.next_idx >= u32( region.state.capacity) { // We will evict LRU. We must predict which LRU will get evicted, and if it's something we've seen then we need to take slowpath and flush batch. next_evict_codepoint := LRU_get_next_evicted( & region.state ) - seen := get( ctx.temp_codepoint_seen, next_evict_codepoint ) + seen := get( & ctx.temp_codepoint_seen, next_evict_codepoint ) assert(seen != nil) if (seen^) { @@ -113,7 +113,7 @@ can_batch_glyph :: proc( ctx : ^Context, font : FontID, entry : ^Entry, glyph_in } assert( LRU_get( & region.state, lru_code ) != -1 ) - set( ctx.temp_codepoint_seen, lru_code, true ) + set( & ctx.temp_codepoint_seen, lru_code, true ) ctx.temp_codepoint_seen_num += 1 return true } diff --git a/code/font/VEFontCache/draw.odin b/code/font/VEFontCache/draw.odin index f43576e..c102ae0 100644 --- a/code/font/VEFontCache/draw.odin +++ b/code/font/VEFontCache/draw.odin @@ -309,7 +309,7 @@ draw_text :: proc( ctx : ^Context, font : FontID, text_utf8 : string, position : cache_glyph_to_atlas( ctx, font, glyph_index ) lru_code := font_glyph_lru_code(font, glyph_index) - set( ctx.temp_codepoint_seen, lru_code, true ) + set( & ctx.temp_codepoint_seen, lru_code, true ) ctx.temp_codepoint_seen_num += 1 batch_start_idx = index diff --git a/code/font/VEFontCache/mappings.odin b/code/font/VEFontCache/mappings.odin index 5d10453..0ba7ac6 100644 --- a/code/font/VEFontCache/mappings.odin +++ b/code/font/VEFontCache/mappings.odin @@ -1,6 +1,7 @@ package VEFontCache import "core:hash" + crc32 :: hash.crc32 fnv64a :: hash.fnv64a import "core:mem" @@ -48,6 +49,15 @@ hmap_chained_remove :: grime.hmap_chained_remove hmap_chained_set :: grime.hmap_chained_set hmap_closest_prime :: grime.hmap_closest_prime +HMapZPL :: grime.HMapZPL + +hmap_zpl_clear :: grime.hmap_zpl_clear +hmap_zpl_init :: grime.hmap_zpl_init +hmap_zpl_get :: grime.hmap_zpl_get +hmap_zpl_reload :: grime.hmap_zpl_reload +hmap_zpl_remove :: grime.hmap_zpl_remove +hmap_zpl_set :: grime.hmap_zpl_set + // Pool :: grime.Pool StackFixed :: grime.StackFixed @@ -79,6 +89,7 @@ append_at :: proc { clear :: proc { array_clear, hmap_chained_clear, + hmap_zpl_clear, } delete :: proc { @@ -88,11 +99,13 @@ delete :: proc { get :: proc { hmap_chained_get, + hmap_zpl_get, } make :: proc { array_init, hmap_chained_init, + hmap_zpl_init, } remove_at :: proc { @@ -105,6 +118,7 @@ resize :: proc { set :: proc { hmap_chained_set, + hmap_zpl_set, } to_slice :: proc { diff --git a/code/font/VEFontCache/parser.odin b/code/font/VEFontCache/parser.odin index 0ceae88..7cc670f 100644 --- a/code/font/VEFontCache/parser.odin +++ b/code/font/VEFontCache/parser.odin @@ -38,9 +38,9 @@ GlyphVertType :: enum u8 { // Based directly off of stb_truetype's vertex ParserGlyphVertex :: struct { - x, y : u16, - contour_x0, contour_y0 : u16, - contour_x1, contour_y1 : u16, + x, y : i16, + contour_x0, contour_y0 : i16, + contour_x1, contour_y1 : i16, type : GlyphVertType, padding : u8, } @@ -277,17 +277,17 @@ parser_get_glyph_shape :: proc( font : ^ParserFontInfo, glyph_index : Glyph ) -> { // Close the previous contour if needed append(& vertices, ParserGlyphVertex { type = .Line, - x = u16(points[start].x), y = u16(points[start].y), - contour_x0 = u16(0), contour_y0 = u16(0), - contour_x1 = u16(0), contour_y1 = u16(0), + x = i16(points[start].x), y = i16(points[start].y), + contour_x0 = i16(0), contour_y0 = i16(0), + contour_x1 = i16(0), contour_y1 = i16(0), padding = 0, }) } append(& vertices, ParserGlyphVertex { type = .Move, - x = u16(point.x), y = u16(point.y), - contour_x0 = u16(0), contour_y0 = u16(0), - contour_x1 = u16(0), contour_y1 = u16(0), + x = i16(point.x), y = i16(point.y), + contour_x0 = i16(0), contour_y0 = i16(0), + contour_x1 = i16(0), contour_y1 = i16(0), padding = 0, }) } @@ -296,9 +296,9 @@ parser_get_glyph_shape :: proc( font : ^ParserFontInfo, glyph_index : Glyph ) -> point1 := points[ index + 1 ] point2 := points[ index + 2 ] append(& vertices, ParserGlyphVertex { type = .Cubic, - x = u16(point2.x), y = u16(point2.y), - contour_x0 = u16(point.x), contour_y0 = u16(point.y), - contour_x1 = u16(point1.x), contour_y1 = u16(point1.y), + x = i16(point2.x), y = i16(point2.y), + contour_x0 = i16(point.x), contour_y0 = i16(point.y), + contour_x1 = i16(point1.x), contour_y1 = i16(point1.y), padding = 0, }) index += 2 @@ -324,9 +324,9 @@ parser_get_glyph_shape :: proc( font : ^ParserFontInfo, glyph_index : Glyph ) -> point1.y + freetype.Pos( (fp.y - fp1.y) * control_conv * 64.0 ), } append(& vertices, ParserGlyphVertex { type = .Cubic, - x = u16(point1.x), y = u16(point1.y), - contour_x0 = u16(control1.x), contour_y0 = u16(control1.y), - contour_x1 = u16(control2.x), contour_y1 = u16(control2.y), + x = i16(point1.x), y = i16(point1.y), + contour_x0 = i16(control1.x), contour_y0 = i16(control1.y), + contour_x1 = i16(control2.x), contour_y1 = i16(control2.y), padding = 0, }) index += 1 @@ -334,9 +334,9 @@ parser_get_glyph_shape :: proc( font : ^ParserFontInfo, glyph_index : Glyph ) -> else { append(& vertices, ParserGlyphVertex { type = .Line, - x = u16(point.x), y = u16(point.y), - contour_x0 = u16(0), contour_y0 = u16(0), - contour_x1 = u16(0), contour_y1 = u16(0), + x = i16(point.x), y = i16(point.y), + contour_x0 = i16(0), contour_y0 = i16(0), + contour_x1 = i16(0), contour_y1 = i16(0), padding = 0, }) } @@ -344,9 +344,9 @@ parser_get_glyph_shape :: proc( font : ^ParserFontInfo, glyph_index : Glyph ) -> // Close contour append(& vertices, ParserGlyphVertex { type = .Line, - x = u16(points[start].x), y = u16(points[start].y), - contour_x0 = u16(0), contour_y0 = u16(0), - contour_x1 = u16(0), contour_y1 = u16(0), + x = i16(points[start].x), y = i16(points[start].y), + contour_x0 = i16(0), contour_y0 = i16(0), + contour_x1 = i16(0), contour_y1 = i16(0), padding = 0, }) } diff --git a/code/grime/hashmap_chained.odin b/code/grime/hashmap_chained.odin index 6dfe156..2bab34b 100644 --- a/code/grime/hashmap_chained.odin +++ b/code/grime/hashmap_chained.odin @@ -183,8 +183,9 @@ hmap_chained_set :: proc( self : HMapChained($Type), key : u64, value : Type ) - error := AllocatorError.None if slot.next == nil { block : []byte - block, error = pool_grab(pool, true) + block, error = pool_grab(pool, false) next := transmute( ^HMapChainedSlot(Type)) & block[0] + next^ = {} slot.next = next next.prev = slot } @@ -195,8 +196,9 @@ hmap_chained_set :: proc( self : HMapChained($Type), key : u64, value : Type ) - } if surface_slot == nil { - block, error := pool_grab(pool, true) + block, error := pool_grab(pool, false) surface_slot := transmute( ^HMapChainedSlot(Type)) & block[0] + surface_slot^ = {} surface_slot.key = key surface_slot.value = value surface_slot.occupied = true @@ -206,8 +208,9 @@ hmap_chained_set :: proc( self : HMapChained($Type), key : u64, value : Type ) - } lookup[hash_index] = surface_slot - block, error = pool_grab(pool, true) + block, error = pool_grab(pool, false) next := transmute( ^HMapChainedSlot(Type)) & block[0] + next^ = {} surface_slot.next = next next.prev = surface_slot return & surface_slot.value, error diff --git a/code/grime/hashmap_zpl.odin b/code/grime/hashmap_zpl.odin index 7117c3c..302b3ed 100644 --- a/code/grime/hashmap_zpl.odin +++ b/code/grime/hashmap_zpl.odin @@ -70,11 +70,11 @@ hmap_zpl_init :: proc } hmap_zpl_clear :: proc( using self : ^ HMapZPL( $ Type ) ) { - for id := 0; id < table.num; id += 1 { - table[id] = -1 + for id := 0; id < int(table.num); id += 1 { + table.data[id] = -1 } - array_clear( table ) + // array_clear( table ) array_clear( entries ) } @@ -154,21 +154,21 @@ hmap_zpl_rehash :: proc( ht : ^ HMapZPL( $ Type ), new_num : u64 ) -> AllocatorE hmap_zpl_rehash_fast :: proc( using self : ^ HMapZPL( $ Type ) ) { - for id := 0; id < entries.num; id += 1 { - entries[id].Next = -1; + for id : i64 = 0; id < i64(entries.num); id += 1 { + entries.data[id].next = -1; } - for id := 0; id < table.num; id += 1 { - table[id] = -1 + for id : i64 = 0; id < i64(table.num); id += 1 { + table.data[id] = -1 } - for id := 0; id < entries.num; id += 1 { - entry := & entries[id] - find_result := hmap_zpl_find( entry.key ) + for id : i64 = 0; id < i64(entries.num); id += 1 { + entry := & entries.data[id] + find_result := hmap_zpl_find( self, entry.key ) if find_result.prev_index < 0 { - table[ find_result.hash_index ] = id + table.data[ find_result.hash_index ] = id } else { - entries[ find_result.prev_index ].next = id + entries.data[ find_result.prev_index ].next = id } } } @@ -180,10 +180,10 @@ hmap_zpl_reload :: proc( using self : ^HMapZPL($Type), new_backing : Allocator ) } hmap_zpl_remove :: proc( self : ^ HMapZPL( $ Type ), key : u64 ) { - find_result := hmap_zpl_find( key ) + find_result := hmap_zpl_find( self, key ) if find_result.entry_index >= 0 { - array_remove_at( & entries, find_result.entry_index ) + array_remove_at( self.entries, u64(find_result.entry_index) ) hmap_zpl_rehash_fast( self ) } } diff --git a/code/grime/memory_tracker.odin b/code/grime/memory_tracker.odin index df096ff..04b46ea 100644 --- a/code/grime/memory_tracker.odin +++ b/code/grime/memory_tracker.odin @@ -17,7 +17,7 @@ MemoryTracker :: struct { entries : Array(MemoryTrackerEntry), } -Track_Memory :: false +Track_Memory :: true memtracker_clear :: proc ( tracker : MemoryTracker ) { when ! Track_Memory { @@ -51,6 +51,10 @@ memtracker_register :: proc( tracker : ^MemoryTracker, new_entry : MemoryTracker } profile(#procedure) + temp_arena : Arena; arena_init(& temp_arena, Logger_Allocator_Buffer[:]) + context.allocator = arena_allocator(& temp_arena) + context.temp_allocator = arena_allocator(& temp_arena) + if tracker.entries.num == tracker.entries.capacity { ensure(false, "Memory tracker entries array full, can no longer register any more allocations") return @@ -70,12 +74,12 @@ memtracker_register :: proc( tracker : ^MemoryTracker, new_entry : MemoryTracker memtracker_dump_entries(tracker ^) } array_append_at( & tracker.entries, new_entry, idx ) - log(str_fmt("%v : Registered: %v", tracker.name, new_entry) ) + logf("%v : Registered: %v", tracker.name, new_entry) return } array_append( & tracker.entries, new_entry ) - log(str_fmt("%v : Registered: %v", tracker.name, new_entry) ) + logf("%v : Registered: %v", tracker.name, new_entry) } memtracker_register_auto_name :: proc( tracker : ^MemoryTracker, start, end : rawptr ) @@ -103,13 +107,17 @@ memtracker_unregister :: proc( tracker : MemoryTracker, to_remove : MemoryTracke } profile(#procedure) + temp_arena : Arena; arena_init(& temp_arena, Logger_Allocator_Buffer[:]) + context.allocator = arena_allocator(& temp_arena) + context.temp_allocator = arena_allocator(& temp_arena) + entries := array_to_slice(tracker.entries) for idx in 0..< tracker.entries.num { entry := & entries[idx] if entry.start == to_remove.start { if (entry.end == to_remove.end || to_remove.end == nil) { - log(str_fmt("%v: Unregistered: %v", tracker.name, to_remove)); + logf("%v: Unregistered: %v", tracker.name, to_remove); array_remove_at(tracker.entries, idx) return } @@ -130,6 +138,10 @@ memtracker_check_for_collisions :: proc ( tracker : MemoryTracker ) } profile(#procedure) + temp_arena : Arena; arena_init(& temp_arena, Logger_Allocator_Buffer[:]) + context.allocator = arena_allocator(& temp_arena) + context.temp_allocator = arena_allocator(& temp_arena) + entries := array_to_slice(tracker.entries) for idx in 1 ..< tracker.entries.num { // Check to make sure each allocations adjacent entries do not intersect @@ -153,6 +165,6 @@ memtracker_dump_entries :: proc( tracker : MemoryTracker ) log( "Dumping Memory Tracker:") for idx in 0 ..< tracker.entries.num { entry := & tracker.entries.data[idx] - log( str_fmt("%v", entry) ) + logf("%v", entry) } } diff --git a/code/sectr/app/state.odin b/code/sectr/app/state.odin index 5290a01..e1451a6 100644 --- a/code/sectr/app/state.odin +++ b/code/sectr/app/state.odin @@ -237,7 +237,9 @@ State :: struct { // fonts : FontData, font_provider_data : FontProviderData, + font_arial_unicode_ms : FontID, font_firacode : FontID, + font_noto_sans : FontID, font_open_sans : FontID, font_squidgy_slimes : FontID, font_rec_mono_semicasual_reg : FontID, diff --git a/code/sectr/engine/client_api.odin b/code/sectr/engine/client_api.odin index b61f425..a6d495a 100644 --- a/code/sectr/engine/client_api.odin +++ b/code/sectr/engine/client_api.odin @@ -284,9 +284,16 @@ startup :: proc( prof : ^SpallProfiler, persistent_mem, frame_mem, transient_mem // 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" ) - default_font = font_open_sans + // 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_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_arial_unicode_ms log( "Default font loaded" ) } diff --git a/code/sectr/engine/render_vefc.odin b/code/sectr/engine/render_vefc.odin index 61bf153..677ec9d 100644 --- a/code/sectr/engine/render_vefc.odin +++ b/code/sectr/engine/render_vefc.odin @@ -79,9 +79,10 @@ render :: proc() // "Draw text" using immediate mode api { - // text_test_str := str_fmt("frametime: %v", frametime_avg_ms) - // text_test_str := str_fmt("HELLO VE FONT CACHE!!!!!") - text_test_str := str_fmt("C") + text_test_str := str_fmt("frametime: %0.2f", frametime_avg_ms) + // log(text_test_str) + // text_test_str := str_fmt("HELLO VE FONT CACHE!") + // text_test_str := str_fmt("C") // font_provider := & state.font_provider_data fdef := hmap_chained_get( font_cache, default_font.key )