More bug fixing, All latin characters don't look corrupt anymore

HMapChained causes memory corruption in VEFontCache (not sure why yet), so I switched temporarily over to HMapZPL.

Fixed bug with parser_get_glyph_shape from me tracking vertices as u16s instead of i16s.

Currently a bug with the frametime example:
text_test_str := str_fmt("frametime: %0.2f", frametime_avg_ms)

It doesn't handle per-frame updates properly compared to C++ source
This commit is contained in:
2024-06-15 14:53:26 -04:00
parent 13f24b4ae9
commit 65be3eae03
14 changed files with 107 additions and 64 deletions

View File

@ -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
})

View File

@ -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

View File

@ -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
}

View File

@ -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

View File

@ -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 {

View File

@ -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,
})
}