Remove rune tracking for string cache, + vecache deharcoding atlas...

Shapers as well
This commit is contained in:
2025-01-06 17:21:16 -05:00
parent 0350a0c282
commit bf38087d8e
13 changed files with 395 additions and 377 deletions

View File

@ -17,8 +17,7 @@ Atlas_Region :: struct {
capacity : Vec2i,
offset : Vec2i,
width : i32,
height : i32,
slot_size : Vec2i,
next_idx : i32,
}
@ -31,20 +30,18 @@ Atlas :: struct {
regions : [5] ^Atlas_Region,
glyph_padding : f32, // Padding to add to bounds_<width/height>_scaled for choosing which atlas region.
glyph_over_scalar : f32, // Scalar to apply to bounds_<width/height>_scaled for choosing which atlas region.
glyph_padding : f32, // Padding to add to bounds_<width/height>_scaled for choosing which atlas region.
size_multiplier : f32, // Grows all text by this multiple.
width : i32,
height : i32,
size : Vec2i,
}
atlas_region_bbox :: proc( region : Atlas_Region, local_idx : i32 ) -> (position, size: Vec2)
{
size.x = f32(region.width)
size.y = f32(region.height)
size = vec2(region.slot_size.x)
position.x = cast(f32) (( local_idx % region.capacity.x ) * region.width)
position.y = cast(f32) (( local_idx / region.capacity.x ) * region.height)
position.x = cast(f32) (( local_idx % region.capacity.x ) * region.slot_size.x)
position.y = cast(f32) (( local_idx / region.capacity.x ) * region.slot_size.y)
position.x += f32(region.offset.x)
position.y += f32(region.offset.y)
@ -57,7 +54,7 @@ atlas_decide_region :: #force_inline proc "contextless" (atlas : Atlas, glyph_bu
glyph_padding_dbl := atlas.glyph_padding * 2
padded_bounds := bounds_size_scaled + glyph_padding_dbl
for kind in 1 ..= 4 do if padded_bounds.x <= f32( atlas.regions[kind].width) && padded_bounds.y <= f32(atlas.regions[kind].height) {
for kind in 1 ..= 4 do if padded_bounds.x <= f32( atlas.regions[kind].slot_size.x) && padded_bounds.y <= f32(atlas.regions[kind].slot_size.y) {
return cast(Atlas_Region_Kind) kind
}

View File

@ -99,8 +99,7 @@ Glyph_Batch_Cache :: struct {
Glyph_Draw_Buffer :: struct{
over_sample : Vec2,
width : i32,
height : i32,
size : Vec2i,
draw_padding : f32,
allocated_x : i32, // Space used (horizontally) within the glyph buffer
@ -254,7 +253,7 @@ generate_shapes_draw_list :: proc ( ctx : ^Context, font : Font_ID, colour : Col
assert(len(shapes) > 0)
for shape in shapes {
ctx.cursor_pos = {}
ctx.cursor_pos = generate_shape_draw_list( & ctx.draw_list, shape, & ctx.atlas, & ctx.glyph_buffer,
ctx.cursor_pos = generate_shape_draw_list( & ctx.draw_list, shape, & ctx.atlas, & ctx.glyph_buffer, ctx.px_scalar,
colour,
entry,
font_scale,
@ -269,6 +268,7 @@ generate_shapes_draw_list :: proc ( ctx : ^Context, font : Font_ID, colour : Col
generate_shape_draw_list :: #force_no_inline proc( draw_list : ^Draw_List, shape : Shaped_Text,
atlas : ^Atlas,
glyph_buffer : ^Glyph_Draw_Buffer,
px_scalar : f32,
colour : Colour,
entry : Entry,
@ -282,6 +282,9 @@ generate_shape_draw_list :: #force_no_inline proc( draw_list : ^Draw_List, shape
{
profile(#procedure)
font_scale := font_scale * px_scalar
target_scale := target_scale / px_scalar
mark_glyph_seen :: #force_inline proc "contextless" ( cache : ^Glyph_Batch_Cache, lru_code : u32 ) {
cache.table[lru_code] = true
cache.num += 1
@ -292,8 +295,8 @@ generate_shape_draw_list :: #force_no_inline proc( draw_list : ^Draw_List, shape
}
atlas_glyph_pad := atlas.glyph_padding
atlas_size := Vec2 { f32(atlas.width), f32(atlas.height) }
glyph_buffer_size := Vec2 { f32(glyph_buffer.width), f32(glyph_buffer.height) }
atlas_size := vec2(atlas.size)
glyph_buffer_size := vec2(glyph_buffer.size)
// Make sure the packs are large enough for the shape
glyph_pack := & glyph_buffer.glyph_pack
@ -477,7 +480,7 @@ batch_generate_glyphs_draw_list :: proc ( draw_list : ^Draw_List,
quad.dst_pos = glyph.position + (glyph.bounds_scaled.p0) * target_scale
quad.dst_scale = (glyph.scale) * target_scale
quad.src_scale = (glyph.scale)
quad.src_pos = (glyph.region_pos)
quad.src_pos = (glyph.region_pos)
to_target_space( & quad.src_pos, & quad.src_scale, atlas_size )
}
for id, index in to_cache
@ -643,12 +646,12 @@ batch_generate_glyphs_draw_list :: proc ( draw_list : ^Draw_List,
dst_glyph_pos := glyph.region_pos
dst_glyph_size := glyph.bounds_size_scaled + atlas.glyph_padding
dst_glyph_size.y = ceil(dst_glyph_size.y) // Note(Ed): Seems to improve hinting
// dst_glyph_size.y = ceil(dst_glyph_size.y) // Note(Ed): Seems to improve hinting
to_glyph_buffer_space( & dst_glyph_pos, & dst_glyph_size, atlas_size )
src_position := Vec2 { glyph.buffer_x, 0 }
src_size := (glyph.bounds_size_scaled + atlas.glyph_padding) * glyph_buffer.over_sample
src_size.y = ceil(src_size.y) // Note(Ed): Seems to improve hinting
// src_size.y = ceil(src_size.y) // Note(Ed): Seems to improve hinting
to_target_space( & src_position, & src_size, glyph_buffer_size )
blit_to_atlas : Draw_Call

View File

@ -81,49 +81,18 @@ Context :: struct {
default_curve_quality : i32,
}
Init_Atlas_Region_Params :: struct {
width : u32,
height : u32,
}
Init_Atlas_Params :: struct {
width : u32,
height : u32,
glyph_padding : u32, // Padding to add to bounds_<width/height>_scaled for choosing which atlas region.
glyph_over_scalar : f32, // Scalar to apply to bounds_<width/height>_scaled for choosing which atlas region.
region_a : Init_Atlas_Region_Params,
region_b : Init_Atlas_Region_Params,
region_c : Init_Atlas_Region_Params,
region_d : Init_Atlas_Region_Params,
size_multiplier : u32, // How much to scale the the atlas size to. (Affects everything, the base is 4096 x 2048 and everything follows from there)
glyph_padding : u32, // Padding to add to bounds_<width/height>_scaled for choosing which atlas region.
}
Init_Atlas_Params_Default :: Init_Atlas_Params {
width = 4096 * 2,
height = 2048 * 2,
glyph_padding = 1,
glyph_over_scalar = 1,
region_a = {
width = 32 * 2,
height = 32 * 2,
},
region_b = {
width = 32 * 2,
height = 64 * 2,
},
region_c = {
width = 64 * 2,
height = 64 * 2,
},
region_d = {
width = 128 * 2,
height = 128 * 2,
}
size_multiplier = 2,
glyph_padding = 1,
}
Init_Glyph_Draw_Params :: struct {
over_sample : Vec2,
over_sample : u32,
draw_padding : u32,
shape_gen_scratch_reserve : u32,
buffer_glyph_limit : u32, // How many region.D glyphs can be drawn to the glyph render target buffer at once (worst case scenario)
@ -131,7 +100,7 @@ Init_Glyph_Draw_Params :: struct {
}
Init_Glyph_Draw_Params_Default :: Init_Glyph_Draw_Params {
over_sample = Vec2 { 4, 4 },
over_sample = 4,
draw_padding = Init_Atlas_Params_Default.glyph_padding,
shape_gen_scratch_reserve = 10 * 1024,
buffer_glyph_limit = 4,
@ -203,44 +172,42 @@ startup :: proc( ctx : ^Context, parser_kind : Parser_Kind = .STB_TrueType,
ctx.draw_list.calls, error = make( [dynamic]Draw_Call, len = 0, cap = Kilobyte )
assert(error == .None, "VEFontCache.init : Failed to allocate draw_list.calls")
atlas := & ctx.atlas
Atlas_Setup:
{
init_atlas_region :: proc( region : ^Atlas_Region, params : Init_Atlas_Params, region_params : Init_Atlas_Region_Params, factor : Vec2i, expected_cap : i32 )
atlas.size_multiplier = f32(atlas_params.size_multiplier)
atlas_size := Vec2i { 4096, 2048 } * i32(atlas.size_multiplier)
slot_region_a := Vec2i { 32, 32 } * i32(atlas.size_multiplier)
slot_region_c := Vec2i { 64, 64 } * i32(atlas.size_multiplier)
slot_region_b := Vec2i { 32, 64 } * i32(atlas.size_multiplier)
slot_region_d := Vec2i { 128, 128 } * i32(atlas.size_multiplier)
init_atlas_region :: proc( region : ^Atlas_Region, atlas_size, slot_size : Vec2i, factor : Vec2i )
{
region.next_idx = 0;
region.width = i32(region_params.width)
region.height = i32(region_params.height)
region.size = {
i32(params.width) / factor.x,
i32(params.height) / factor.y,
}
region.capacity = {
region.size.x / i32(region.width),
region.size.y / i32(region.height),
}
assert( region.capacity.x * region.capacity.y == expected_cap )
region.next_idx = 0;
region.slot_size = slot_size
region.size = atlas_size / factor
region.capacity = region.size / region.slot_size
error : Allocator_Error
lru_init( & region.state, region.capacity.x * region.capacity.y )
}
init_atlas_region( & atlas.region_a, atlas_params, atlas_params.region_a, { 4, 2}, 1024 * 4 )
init_atlas_region( & atlas.region_b, atlas_params, atlas_params.region_b, { 4, 2}, 512 * 4 )
init_atlas_region( & atlas.region_c, atlas_params, atlas_params.region_c, { 4, 1}, 512 * 4 )
init_atlas_region( & atlas.region_d, atlas_params, atlas_params.region_d, { 2, 1}, 256 * 4 )
init_atlas_region( & atlas.region_a, atlas_size, slot_region_a, { 4, 2})
init_atlas_region( & atlas.region_b, atlas_size, slot_region_b, { 4, 2})
init_atlas_region( & atlas.region_c, atlas_size, slot_region_c, { 4, 1})
init_atlas_region( & atlas.region_d, atlas_size, slot_region_d, { 2, 1})
atlas.width = i32(atlas_params.width)
atlas.height = i32(atlas_params.height)
atlas.glyph_padding = f32(atlas_params.glyph_padding)
atlas.glyph_over_scalar = atlas_params.glyph_over_scalar
atlas.size = atlas_size
atlas.glyph_padding = f32(atlas_params.glyph_padding)
atlas.region_a.offset = {0, 0}
atlas.region_b.offset.x = 0
atlas.region_b.offset.y = atlas.region_a.size.y
atlas.region_c.offset.x = atlas.region_a.size.x
atlas.region_c.offset.y = 0
atlas.region_d.offset.x = atlas.width / 2
atlas.region_d.offset.x = atlas.size.x / 2
atlas.region_d.offset.y = 0
atlas.regions = {
@ -274,9 +241,9 @@ startup :: proc( ctx : ^Context, parser_kind : Parser_Kind = .STB_TrueType,
Glyph_Buffer_Setup:
{
glyph_buffer := & ctx.glyph_buffer
glyph_buffer.over_sample = glyph_draw_params.over_sample
glyph_buffer.width = atlas.region_d.width * i32(glyph_buffer.over_sample.x) * i32(glyph_draw_params.buffer_glyph_limit)
glyph_buffer.height = atlas.region_d.height * i32(glyph_buffer.over_sample.y)
glyph_buffer.over_sample = { f32(glyph_draw_params.over_sample), f32(glyph_draw_params.over_sample) }
glyph_buffer.size.x = atlas.region_d.slot_size.x * i32(glyph_buffer.over_sample.x) * i32(glyph_draw_params.buffer_glyph_limit)
glyph_buffer.size.y = atlas.region_d.slot_size.y * i32(glyph_buffer.over_sample.y)
glyph_buffer.draw_padding = cast(f32) glyph_draw_params.draw_padding
buffer_limit := glyph_draw_params.buffer_glyph_limit
@ -532,16 +499,16 @@ draw_text :: #force_inline proc( ctx : ^Context, font : Font_ID, px_size : f32,
shape := shaper_shape_text_cached( text_utf8, & ctx.shaper_ctx, & ctx.shape_cache,
font,
entry,
px_upscale,
font_scale_upscale,
px_size,
font_scale,
shaper_shape_text_uncached_advanced
)
ctx.cursor_pos = generate_shape_draw_list( & ctx.draw_list, shape, & ctx.atlas, & ctx.glyph_buffer,
ctx.cursor_pos = generate_shape_draw_list( & ctx.draw_list, shape, & ctx.atlas, & ctx.glyph_buffer, ctx.px_scalar,
colour,
entry,
font_scale_upscale,
font_scale,
position,
downscale,
scale,
ctx.snap_width,
ctx.snap_height
)
@ -578,12 +545,12 @@ draw_text_slice :: #force_inline proc( ctx : ^Context, font : Font_ID, px_size :
font,
entry,
px_upscale,
font_scale_upscale,
font_scale,
shaper_shape_text_uncached_advanced
)
shapes[id] = shape
}
generate_shapes_draw_list(ctx, font, colour, entry, font_scale_upscale, position, scale, shapes )
generate_shapes_draw_list(ctx, font, colour, entry, font_scale, position, scale, shapes )
}
@ -631,12 +598,12 @@ draw_text_shape :: #force_inline proc( ctx : ^Context, font : Font_ID, px_size :
downscale := scale * (1 / ctx.px_scalar)
font_scale_upscale := parser_scale( entry.parser_info, px_upscale )
ctx.cursor_pos = generate_shape_draw_list( & ctx.draw_list, shape, & ctx.atlas, & ctx.glyph_buffer,
ctx.cursor_pos = generate_shape_draw_list( & ctx.draw_list, shape, & ctx.atlas, & ctx.glyph_buffer, ctx.px_scalar,
colour,
entry,
font_scale_upscale,
font_scale,
position,
downscale,
scale,
ctx.snap_width,
ctx.snap_height
)