More offloading to shaper, seeing if its better todo some math in loop...
This commit is contained in:
parent
18d8735c54
commit
ce84652417
@ -54,6 +54,7 @@ Atlas :: struct {
|
||||
}
|
||||
|
||||
// Hahser for the atlas.
|
||||
@(optimization_mode="favor_size")
|
||||
atlas_glyph_lru_code :: #force_inline proc "contextless" ( font : Font_ID, px_size : f32, glyph_index : Glyph ) -> (lru_code : Atlas_Key) {
|
||||
// lru_code = u32(glyph_index) + ( ( 0x10000 * u32(font) ) & 0xFFFF0000 )
|
||||
font := font
|
||||
@ -131,7 +132,7 @@ atlas_decide_region_branchless :: #force_inline proc "contextless" (
|
||||
which_ab := min(score_a, score_b)
|
||||
which_cd := min(score_c, score_d)
|
||||
which_region := min(which_ab, which_cd)
|
||||
resolved := min(which_region, score_buffer) + 6
|
||||
resolved := min(which_region, score_buffer) + 6
|
||||
return Atlas_Region_Kind(resolved)
|
||||
}
|
||||
|
||||
|
@ -21,15 +21,6 @@ Vertex :: struct {
|
||||
u, v : f32,
|
||||
}
|
||||
|
||||
Transform :: struct {
|
||||
pos : Vec2,
|
||||
scale : Vec2,
|
||||
}
|
||||
|
||||
Range2 :: struct {
|
||||
p0, p1 : Vec2,
|
||||
}
|
||||
|
||||
Glyph_Bounds_Mat :: matrix[2, 2] f32
|
||||
|
||||
Glyph_Draw_Quad :: struct {
|
||||
@ -44,21 +35,21 @@ Glyph_Draw_Quad :: struct {
|
||||
Glyph_Pack_Entry :: struct #packed {
|
||||
position : Vec2,
|
||||
|
||||
index : Glyph,
|
||||
lru_code : Atlas_Key,
|
||||
// index : Glyph,
|
||||
// lru_code : Atlas_Key,
|
||||
atlas_index : i32,
|
||||
in_atlas : b8,
|
||||
should_cache : b8,
|
||||
region_kind : Atlas_Region_Kind,
|
||||
// region_kind : Atlas_Region_Kind,
|
||||
region_pos : Vec2,
|
||||
region_size : Vec2,
|
||||
|
||||
bounds : Range2,
|
||||
bounds_scaled : Range2,
|
||||
bounds_size : Vec2,
|
||||
bounds_size_scaled : Vec2,
|
||||
// bounds : Range2,
|
||||
// bounds_scaled : Range2,
|
||||
// bounds_size : Vec2,
|
||||
// bounds_size_scaled : Vec2,
|
||||
over_sample : Vec2,
|
||||
scale : Vec2,
|
||||
// scale : Vec2,
|
||||
|
||||
shape : Parser_Glyph_Shape,
|
||||
draw_transform : Transform,
|
||||
@ -358,41 +349,12 @@ generate_shape_draw_list :: proc( draw_list : ^Draw_List, shape : Shaped_Text,
|
||||
}
|
||||
sub_slice :: #force_inline proc "contextless" ( pack : ^[dynamic]i32) -> []i32 { return pack[:] }
|
||||
|
||||
profile_begin("index")
|
||||
for & glyph, index in glyph_pack
|
||||
{
|
||||
glyph.index = shape.glyph_id[ index ]
|
||||
glyph.lru_code = atlas_glyph_lru_code(entry.id, px_size, glyph.index)
|
||||
}
|
||||
profile_end()
|
||||
|
||||
profile_begin("translate")
|
||||
for & glyph, index in glyph_pack
|
||||
{
|
||||
for & glyph, index in glyph_pack {
|
||||
glyph.position = target_position + (shape.position[index]) * target_scale
|
||||
}
|
||||
profile_end()
|
||||
|
||||
profile_begin("bounds")
|
||||
for & glyph, index in glyph_pack
|
||||
{
|
||||
glyph.bounds = parser_get_bounds( entry.parser_info, glyph.index )
|
||||
glyph.bounds_scaled = { glyph.bounds.p0 * font_scale, glyph.bounds.p1 * font_scale }
|
||||
glyph.bounds_size = glyph.bounds.p1 - glyph.bounds.p0
|
||||
glyph.bounds_size_scaled = glyph.bounds_size * font_scale
|
||||
glyph.scale = glyph.bounds_size_scaled + atlas.glyph_padding
|
||||
}
|
||||
profile_end()
|
||||
|
||||
glyph_padding_dbl := atlas.glyph_padding * 2
|
||||
|
||||
profile_begin("region")
|
||||
for & glyph, index in glyph_pack
|
||||
{
|
||||
glyph.region_kind = atlas_decide_region( atlas ^, glyph_buffer_size, glyph.bounds_size_scaled )
|
||||
}
|
||||
profile_end()
|
||||
|
||||
profile_begin("batching")
|
||||
clear(oversized)
|
||||
clear(to_cache)
|
||||
@ -401,15 +363,20 @@ generate_shape_draw_list :: proc( draw_list : ^Draw_List, shape : Shaped_Text,
|
||||
|
||||
for & glyph, index in glyph_pack
|
||||
{
|
||||
if glyph.region_kind == .None {
|
||||
atlas_key := shape.atlas_lru_code[index]
|
||||
region_kind := shape.region_kind[index]
|
||||
bounds := shape.bounds[index]
|
||||
bounds_size_scaled := size(bounds) * font_scale
|
||||
|
||||
if region_kind == .None {
|
||||
assert(false, "FAILED TO ASSGIN REGION")
|
||||
continue
|
||||
}
|
||||
if glyph.region_kind == .E
|
||||
if region_kind == .E
|
||||
{
|
||||
glyph.over_sample = \
|
||||
glyph.bounds_size_scaled.x <= glyph_buffer_size.x / 2 &&
|
||||
glyph.bounds_size_scaled.y <= glyph_buffer_size.y / 2 ? \
|
||||
bounds_size_scaled.x <= glyph_buffer_size.x / 2 &&
|
||||
bounds_size_scaled.y <= glyph_buffer_size.y / 2 ? \
|
||||
{2.0, 2.0} \
|
||||
: {1.0, 1.0}
|
||||
append_sub_pack(oversized, cast(i32) index)
|
||||
@ -417,8 +384,8 @@ generate_shape_draw_list :: proc( draw_list : ^Draw_List, shape : Shaped_Text,
|
||||
}
|
||||
|
||||
glyph.over_sample = glyph_buffer.over_sample
|
||||
region := atlas.regions[glyph.region_kind]
|
||||
glyph.atlas_index = lru_get( & region.state, glyph.lru_code )
|
||||
region := atlas.regions[region_kind]
|
||||
glyph.atlas_index = lru_get( & region.state, atlas_key )
|
||||
|
||||
// Glyphs are prepared in batches based on the capacity of the batch cache.
|
||||
Prepare_For_Batch:
|
||||
@ -441,22 +408,22 @@ generate_shape_draw_list :: proc( draw_list : ^Draw_List, shape : Shaped_Text,
|
||||
}
|
||||
|
||||
profile("append to_cache")
|
||||
glyph.atlas_index = atlas_reserve_slot(region, glyph.lru_code)
|
||||
glyph.atlas_index = atlas_reserve_slot(region, atlas_key)
|
||||
glyph.region_pos, glyph.region_size = atlas_region_bbox(region ^, glyph.atlas_index)
|
||||
append_sub_pack(to_cache, cast(i32) index)
|
||||
mark_glyph_seen(& glyph_buffer.batch_cache, glyph.lru_code)
|
||||
mark_glyph_seen(& glyph_buffer.batch_cache, atlas_key)
|
||||
continue
|
||||
}
|
||||
|
||||
profile("append cached")
|
||||
glyph.region_pos, glyph.region_size = atlas_region_bbox(region ^, glyph.atlas_index)
|
||||
append_sub_pack(cached, cast(i32) index)
|
||||
mark_glyph_seen(& glyph_buffer.batch_cache, glyph.lru_code)
|
||||
mark_glyph_seen(& glyph_buffer.batch_cache, atlas_key)
|
||||
continue
|
||||
}
|
||||
|
||||
// Batch has been prepared for a set of glyphs time to generate glyphs.
|
||||
batch_generate_glyphs_draw_list( draw_list, glyph_pack, sub_slice(cached), sub_slice(to_cache), sub_slice(oversized),
|
||||
batch_generate_glyphs_draw_list( draw_list, shape, glyph_pack, sub_slice(cached), sub_slice(to_cache), sub_slice(oversized),
|
||||
atlas,
|
||||
glyph_buffer,
|
||||
atlas_size,
|
||||
@ -478,7 +445,7 @@ generate_shape_draw_list :: proc( draw_list : ^Draw_List, shape : Shaped_Text,
|
||||
if len(oversized) > 0 || glyph_buffer.batch_cache.num > 0
|
||||
{
|
||||
// Last batch pass
|
||||
batch_generate_glyphs_draw_list( draw_list, glyph_pack, sub_slice(cached), sub_slice(to_cache), sub_slice(oversized),
|
||||
batch_generate_glyphs_draw_list( draw_list, shape, glyph_pack, sub_slice(cached), sub_slice(to_cache), sub_slice(oversized),
|
||||
atlas,
|
||||
glyph_buffer,
|
||||
atlas_size,
|
||||
@ -508,7 +475,9 @@ generate_shape_draw_list :: proc( draw_list : ^Draw_List, shape : Shaped_Text,
|
||||
* Oversized will have a draw call setup to blit directly from the glyph buffer to the target.
|
||||
* to_cache will blit the glyphs rendered to the buffer to the atlas.
|
||||
*/
|
||||
@(optimization_mode = "favor_size")
|
||||
batch_generate_glyphs_draw_list :: proc ( draw_list : ^Draw_List,
|
||||
shape : Shaped_Text,
|
||||
glyph_pack : ^#soa[dynamic]Glyph_Pack_Entry,
|
||||
cached : []i32,
|
||||
to_cache : []i32,
|
||||
@ -533,22 +502,29 @@ batch_generate_glyphs_draw_list :: proc ( draw_list : ^Draw_List,
|
||||
for id, index in cached
|
||||
{
|
||||
// Quad to for drawing atlas slot to target
|
||||
glyph := & glyph_pack[id]
|
||||
glyph := & glyph_pack[id]
|
||||
bounds := shape.bounds[id]
|
||||
bounds_scaled := mul(bounds, font_scale)
|
||||
glyph_scale := size(bounds_scaled) + atlas.glyph_padding
|
||||
|
||||
quad := & glyph.draw_quad
|
||||
quad.dst_pos = glyph.position + (glyph.bounds_scaled.p0) * target_scale
|
||||
quad.dst_scale = (glyph.scale) * target_scale
|
||||
quad.src_scale = (glyph.scale)
|
||||
quad.dst_pos = glyph.position + (bounds_scaled.p0) * target_scale
|
||||
quad.dst_scale = (glyph_scale) * target_scale
|
||||
quad.src_scale = (glyph_scale)
|
||||
quad.src_pos = (glyph.region_pos)
|
||||
to_target_space( & quad.src_pos, & quad.src_scale, atlas_size )
|
||||
}
|
||||
for id, index in to_cache
|
||||
{
|
||||
glyph := & glyph_pack[id]
|
||||
glyph := & glyph_pack[id]
|
||||
bounds := shape.bounds[id]
|
||||
bounds_scaled := mul(bounds, font_scale)
|
||||
glyph_scale := size(bounds_scaled) + glyph_buffer.draw_padding
|
||||
|
||||
f32_allocated_x := cast(f32) glyph_buffer.allocated_x
|
||||
|
||||
// Resolve how much space this glyph will allocate in the buffer
|
||||
buffer_size := (glyph.bounds_size_scaled + glyph_buffer.draw_padding) * glyph_buffer.over_sample
|
||||
buffer_size := glyph_scale * glyph_buffer.over_sample
|
||||
// Allocate a glyph glyph render target region (FBO)
|
||||
to_allocate_x := buffer_size.x + 2.0
|
||||
|
||||
@ -559,7 +535,7 @@ batch_generate_glyphs_draw_list :: proc ( draw_list : ^Draw_List,
|
||||
// The glyph buffer space transform for generate_glyph_pass_draw_list
|
||||
draw_transform := & glyph.draw_transform
|
||||
draw_transform.scale = font_scale * glyph_buffer.over_sample
|
||||
draw_transform.pos = -1 * (glyph.bounds.p0) * draw_transform.scale + glyph_buffer.draw_padding
|
||||
draw_transform.pos = -1 * (bounds.p0) * draw_transform.scale + glyph_buffer.draw_padding
|
||||
draw_transform.pos.x += glyph.buffer_x
|
||||
to_glyph_buffer_space( & draw_transform.pos, & draw_transform.scale, glyph_buffer_size )
|
||||
|
||||
@ -570,21 +546,25 @@ batch_generate_glyphs_draw_list :: proc ( draw_list : ^Draw_List,
|
||||
draw_quad := & glyph.draw_quad
|
||||
|
||||
// Destination (draw_list's target image)
|
||||
draw_quad.dst_pos = glyph.position + (glyph.bounds_scaled.p0) * target_scale
|
||||
draw_quad.dst_scale = (glyph.scale) * target_scale
|
||||
draw_quad.dst_pos = glyph.position + (bounds_scaled.p0) * target_scale
|
||||
draw_quad.dst_scale = (glyph_scale) * target_scale
|
||||
|
||||
// UV Coordinates for sampling the atlas
|
||||
draw_quad.src_scale = (glyph.scale)
|
||||
draw_quad.src_scale = (glyph_scale)
|
||||
draw_quad.src_pos = (glyph.region_pos)
|
||||
to_target_space( & draw_quad.src_pos, & draw_quad.src_scale, atlas_size )
|
||||
}
|
||||
for id, index in oversized
|
||||
when ENABLE_OVERSIZED_GLYPHS do for id, index in oversized
|
||||
{
|
||||
glyph := & glyph_pack[id]
|
||||
glyph_padding := vec2(glyph_buffer.draw_padding)
|
||||
glyph := & glyph_pack[id]
|
||||
bounds := shape.bounds[id]
|
||||
bounds_scaled := mul(bounds, font_scale)
|
||||
bounds_size_scaled := size(bounds_scaled)
|
||||
|
||||
f32_allocated_x := cast(f32) glyph_buffer.allocated_x
|
||||
// Resolve how much space this glyph will allocate in the buffer
|
||||
buffer_size := (glyph.bounds_size_scaled + glyph_buffer.draw_padding) * glyph.over_sample
|
||||
buffer_size := (bounds_size_scaled + glyph_padding) * glyph.over_sample
|
||||
|
||||
// Allocate a glyph glyph render target region (FBO)
|
||||
to_allocate_x := buffer_size.x + 2.0
|
||||
@ -597,40 +577,40 @@ batch_generate_glyphs_draw_list :: proc ( draw_list : ^Draw_List,
|
||||
// Quad to for drawing atlas slot to target
|
||||
draw_quad := & glyph.draw_quad
|
||||
|
||||
glyph_padding := vec2(glyph_buffer.draw_padding)
|
||||
|
||||
// Target position (draw_list's target image)
|
||||
draw_quad.dst_pos = glyph.position + (glyph.bounds_scaled.p0 - glyph_padding) * target_scale
|
||||
draw_quad.dst_scale = (glyph.bounds_size_scaled + glyph_padding) * target_scale
|
||||
draw_quad.dst_pos = glyph.position + (bounds_scaled.p0 - glyph_padding) * target_scale
|
||||
draw_quad.dst_scale = (bounds_size_scaled + glyph_padding) * target_scale
|
||||
|
||||
// The glyph buffer space transform for generate_glyph_pass_draw_list
|
||||
draw_transform := & glyph.draw_transform
|
||||
draw_transform.scale = font_scale * glyph.over_sample
|
||||
draw_transform.pos = -1 * glyph.bounds.p0 * draw_transform.scale + vec2(atlas.glyph_padding)
|
||||
draw_transform.pos = -1 * bounds.p0 * draw_transform.scale + vec2(atlas.glyph_padding)
|
||||
draw_transform.pos.x += glyph.buffer_x
|
||||
to_glyph_buffer_space( & draw_transform.pos, & draw_transform.scale, glyph_buffer_size )
|
||||
|
||||
|
||||
draw_quad.src_pos = Vec2 { glyph.buffer_x, 0 }
|
||||
draw_quad.src_scale = glyph.bounds_size_scaled * glyph.over_sample + glyph_padding
|
||||
draw_quad.src_scale = bounds_size_scaled * glyph.over_sample + glyph_padding
|
||||
to_target_space( & draw_quad.src_pos, & draw_quad.src_scale, glyph_buffer_size )
|
||||
}
|
||||
profile_end()
|
||||
|
||||
profile_begin("generate oversized glyphs draw_list")
|
||||
if len(oversized) > 0
|
||||
when ENABLE_OVERSIZED_GLYPHS do if len(oversized) > 0
|
||||
{
|
||||
// colour.r = max(colour.a, enable_debug_vis_type)
|
||||
// colour.g = max(colour.g, enable_debug_vis_type)
|
||||
// colour.b = colour.b * f32(cast(i32) ! b32(cast(i32) enable_debug_vis_type))
|
||||
for id, index in oversized {
|
||||
for pack_id, index in oversized {
|
||||
error : Allocator_Error
|
||||
glyph_pack[id].shape, error = parser_get_glyph_shape(entry.parser_info, glyph_pack[id].index)
|
||||
glyph_pack[pack_id].shape, error = parser_get_glyph_shape(entry.parser_info, shape.glyph_id[pack_id])
|
||||
assert(error == .None)
|
||||
}
|
||||
for id, index in oversized
|
||||
{
|
||||
glyph := & glyph_pack[id]
|
||||
glyph := & glyph_pack[id]
|
||||
bounds := shape.bounds[id]
|
||||
if glyph.flush_glyph_buffer do flush_glyph_buffer_draw_list(draw_list,
|
||||
& glyph_buffer.draw_list,
|
||||
& glyph_buffer.clear_draw_list,
|
||||
@ -640,7 +620,7 @@ batch_generate_glyphs_draw_list :: proc ( draw_list : ^Draw_List,
|
||||
generate_glyph_pass_draw_list( draw_list, & glyph_buffer.shape_gen_scratch,
|
||||
glyph_pack[id].shape,
|
||||
entry.curve_quality,
|
||||
glyph_pack[id].bounds,
|
||||
bounds,
|
||||
glyph_pack[id].draw_transform.pos,
|
||||
glyph_pack[id].draw_transform.scale
|
||||
)
|
||||
@ -691,16 +671,19 @@ batch_generate_glyphs_draw_list :: proc ( draw_list : ^Draw_List,
|
||||
profile_begin("to_cache: caching to atlas")
|
||||
if len(to_cache) > 0
|
||||
{
|
||||
for id, index in to_cache {
|
||||
for pack_id, index in to_cache {
|
||||
error : Allocator_Error
|
||||
glyph_pack[id].shape, error = parser_get_glyph_shape(entry.parser_info, glyph_pack[id].index)
|
||||
glyph_pack[pack_id].shape, error = parser_get_glyph_shape(entry.parser_info, shape.glyph_id[pack_id])
|
||||
assert(error == .None)
|
||||
}
|
||||
|
||||
for id, index in to_cache
|
||||
{
|
||||
profile("glyph")
|
||||
glyph := & glyph_pack[id]
|
||||
glyph := & glyph_pack[id]
|
||||
bounds := shape.bounds[id]
|
||||
bounds_scaled := mul(bounds, font_scale)
|
||||
bounds_size_scaled := size(bounds_scaled)
|
||||
|
||||
if glyph.flush_glyph_buffer do flush_glyph_buffer_draw_list( draw_list,
|
||||
& glyph_buffer.draw_list,
|
||||
@ -723,12 +706,12 @@ batch_generate_glyphs_draw_list :: proc ( draw_list : ^Draw_List,
|
||||
clear_target_region.end_index = cast(u32) len(glyph_buffer.clear_draw_list.indices)
|
||||
|
||||
dst_glyph_pos := glyph.region_pos
|
||||
dst_glyph_size := glyph.bounds_size_scaled + atlas.glyph_padding
|
||||
dst_glyph_size := bounds_size_scaled + atlas.glyph_padding
|
||||
dst_glyph_size.y = max(dst_glyph_size.y, ceil(dst_glyph_size.y) * glyph_buffer.snap_glyph_height) // 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 := (bounds_size_scaled + atlas.glyph_padding) * glyph_buffer.over_sample
|
||||
src_size.y = max(src_size.y, ceil(src_size.y) * glyph_buffer.snap_glyph_height) // Note(Ed): Seems to improve hinting
|
||||
to_target_space( & src_position, & src_size, glyph_buffer_size )
|
||||
|
||||
@ -748,7 +731,7 @@ batch_generate_glyphs_draw_list :: proc ( draw_list : ^Draw_List,
|
||||
generate_glyph_pass_draw_list( draw_list, & glyph_buffer.shape_gen_scratch,
|
||||
glyph.shape,
|
||||
entry.curve_quality,
|
||||
glyph.bounds,
|
||||
bounds,
|
||||
glyph.draw_transform.pos,
|
||||
glyph.draw_transform.scale
|
||||
)
|
||||
|
@ -58,6 +58,18 @@ Vec2 :: [2]f32
|
||||
Vec2i :: [2]i32
|
||||
Vec2_64 :: [2]f64
|
||||
|
||||
Transform :: struct {
|
||||
pos : Vec2,
|
||||
scale : Vec2,
|
||||
}
|
||||
|
||||
Range2 :: struct {
|
||||
p0, p1 : Vec2,
|
||||
}
|
||||
|
||||
mul_range2_vec2 :: #force_inline proc "contextless" ( range : Range2, v : Vec2 ) -> Range2 { return { range.p0 * v, range.p1 * v } }
|
||||
size_range2 :: #force_inline proc "contextless" ( range : Range2 ) -> Vec2 { return range.p1 - range.p0 }
|
||||
|
||||
vec2_from_scalar :: #force_inline proc "contextless" ( scalar : f32 ) -> Vec2 { return { scalar, scalar }}
|
||||
vec2_64_from_vec2 :: #force_inline proc "contextless" ( v2 : Vec2 ) -> Vec2_64 { return { f64(v2.x), f64(v2.y) }}
|
||||
vec2_from_vec2i :: #force_inline proc "contextless" ( v2i : Vec2i ) -> Vec2 { return { f32(v2i.x), f32(v2i.y) }}
|
||||
|
@ -102,6 +102,10 @@ make_soa :: proc {
|
||||
builtin.make_soa_slice,
|
||||
}
|
||||
|
||||
mul :: proc {
|
||||
mul_range2_vec2,
|
||||
}
|
||||
|
||||
peek :: proc {
|
||||
peek_array,
|
||||
}
|
||||
@ -110,6 +114,10 @@ resize :: proc {
|
||||
builtin.resize_dynamic_array,
|
||||
}
|
||||
|
||||
size :: proc {
|
||||
size_range2,
|
||||
}
|
||||
|
||||
vec2 :: proc {
|
||||
vec2_from_scalar,
|
||||
vec2_from_vec2i,
|
||||
|
@ -25,12 +25,15 @@ Shape_Key :: u32
|
||||
If your doing something heavy though (where there is thousands, or tens-of thousands)
|
||||
your not going to be satisfied with keeping that in the iteration).
|
||||
*/
|
||||
Shaped_Text :: struct {
|
||||
Shaped_Text :: struct #packed {
|
||||
glyph_id : [dynamic]Glyph,
|
||||
position : [dynamic]Vec2,
|
||||
atlas_lru_code : [dynamic]Atlas_Key,
|
||||
region_kind : [dynamic]Atlas_Region_Kind,
|
||||
bound : [dynamic]Range2,
|
||||
bounds : [dynamic]Range2,
|
||||
// bounds_scaled : [dynamic]Range2,
|
||||
// bounds_size : [dynamic]Vec2,
|
||||
// bounds_size_Scaled : [dynamic]Vec2,
|
||||
end_cursor_pos : Vec2,
|
||||
size : Vec2,
|
||||
}
|
||||
@ -281,28 +284,41 @@ shaper_shape_text_uncached_advanced :: #force_inline proc( ctx : ^Shaper_Context
|
||||
|
||||
// Resolve each glyphs: bounds, atlas lru, and the atlas region as we have everything we need now.
|
||||
|
||||
resize( & output.atlas_lru_code, len(output.glyph_id) )
|
||||
resize( & output.region_kind, len(output.glyph_id) )
|
||||
resize( & output.bounds, len(output.glyph_id) )
|
||||
// resize( & output.bounds_scaled, len(output.glyph_id) )
|
||||
|
||||
profile_begin("bounds")
|
||||
for id, index in output.glyph_id
|
||||
{
|
||||
// glyph.bounds = parser_get_bounds( entry.parser_info, glyph.index )
|
||||
// glyph.bounds_scaled = { glyph.bounds.p0 * font_scale, glyph.bounds.p1 * font_scale }
|
||||
// glyph.bounds_size = glyph.bounds.p1 - glyph.bounds.p0
|
||||
// glyph.bounds_size_scaled = glyph.bounds_size * font_scale
|
||||
// glyph.scale = glyph.bounds_size_scaled + atlas.glyph_padding
|
||||
bounds := & output.bounds[index]
|
||||
// bounds_scaled := & output.bounds_scaled[index]
|
||||
// bounds_size := & output.bounds_size[index]
|
||||
// bounds_size_scaled := & output.bounds_size_scaled[index]
|
||||
// scale := & output.scale[index]
|
||||
(bounds ^) = parser_get_bounds( entry.parser_info, id )
|
||||
// (bounds_scaled ^) = { bounds.p0 * font_scale, bounds.p1 * font_scale }
|
||||
// bounds_size = bounds.p1 - bounds.p0
|
||||
// bounds_size_scaled = bounds_size * font_scale
|
||||
// scale = glyph.bounds_size_scaled + atlas.glyph_padding
|
||||
}
|
||||
profile_end()
|
||||
|
||||
profile_begin("index")
|
||||
profile_begin("atlas_lru_code")
|
||||
for id, index in output.glyph_id
|
||||
{
|
||||
// output.atlas_lru_code[index] = atlas_glyph_lru_code(entry.id, px_size, glyph.index)
|
||||
output.atlas_lru_code[index] = atlas_glyph_lru_code(entry.id, font_px_size, id)
|
||||
}
|
||||
profile_end()
|
||||
|
||||
profile_begin("region")
|
||||
for id, index in output.glyph_id
|
||||
{
|
||||
// output.region_kind[index] = atlas_decide_region_branchless( atlas ^, glyph_buffer_size, glyph.bounds_size_scaled )
|
||||
bounds := & output.bounds[index]
|
||||
bounds_size_scaled := (bounds.p1 - bounds.p0) * font_scale
|
||||
|
||||
output.region_kind[index] = atlas_decide_region( atlas, glyph_buffer_size, bounds_size_scaled )
|
||||
}
|
||||
profile_end()
|
||||
}
|
||||
|
@ -8,7 +8,8 @@ package vetext
|
||||
import "base:runtime"
|
||||
|
||||
// See: mappings.odin for profiling hookup
|
||||
DISABLE_PROFILING :: false
|
||||
DISABLE_PROFILING :: false
|
||||
ENABLE_OVERSIZED_GLYPHS :: true
|
||||
|
||||
Font_ID :: distinct i32
|
||||
Glyph :: distinct i32
|
||||
@ -158,13 +159,14 @@ Init_Shaper_Params_Default :: Init_Shaper_Params {
|
||||
Init_Shape_Cache_Params :: struct {
|
||||
// Note(Ed): This should mostly just be given the worst-case capacity and reserve at the same time.
|
||||
// If memory is a concern it can easily be 256 - 2k if not much text is going to be rendered often.
|
||||
// Shapes should really not exceed 1024 glyphs..
|
||||
capacity : u32,
|
||||
reserve : u32,
|
||||
}
|
||||
|
||||
Init_Shape_Cache_Params_Default :: Init_Shape_Cache_Params {
|
||||
capacity = 10 * 1024,
|
||||
reserve = 10 * 1024,
|
||||
reserve = 1024,
|
||||
}
|
||||
|
||||
//#region("lifetime")
|
||||
@ -268,7 +270,8 @@ startup :: proc( ctx : ^Context, parser_kind : Parser_Kind = .STB_TrueType,
|
||||
shape_cache.storage, error = make( [dynamic]Shaped_Text, shape_cache_params.capacity )
|
||||
assert(error == .None, "VEFontCache.init : Failed to allocate shape_cache.storage")
|
||||
|
||||
for idx : u32 = 0; idx < shape_cache_params.capacity; idx += 1 {
|
||||
for idx : u32 = 0; idx < shape_cache_params.capacity; idx += 1
|
||||
{
|
||||
stroage_entry := & shape_cache.storage[idx]
|
||||
|
||||
stroage_entry.glyph_id, error = make( [dynamic]Glyph, len = 0, cap = shape_cache_params.reserve )
|
||||
@ -276,6 +279,18 @@ startup :: proc( ctx : ^Context, parser_kind : Parser_Kind = .STB_TrueType,
|
||||
|
||||
stroage_entry.position, error = make( [dynamic]Vec2, len = 0, cap = shape_cache_params.reserve )
|
||||
assert( error == .None, "VEFontCache.init : Failed to allocate positions array for shape cache storage" )
|
||||
|
||||
stroage_entry.atlas_lru_code, error = make( [dynamic]Atlas_Key, len = 0, cap = shape_cache_params.reserve )
|
||||
assert( error == .None, "VEFontCache.init : Failed to allocate atlas_lru_code array for shape cache storage" )
|
||||
|
||||
stroage_entry.region_kind, error = make( [dynamic]Atlas_Region_Kind, len = 0, cap = shape_cache_params.reserve )
|
||||
assert( error == .None, "VEFontCache.init : Failed to allocate region_kind array for shape cache storage" )
|
||||
|
||||
stroage_entry.bounds, error = make( [dynamic]Range2, len = 0, cap = shape_cache_params.reserve )
|
||||
assert( error == .None, "VEFontCache.init : Failed to allocate bounds array for shape cache storage" )
|
||||
|
||||
// stroage_entry.bounds_scaled, error = make( [dynamic]Range2, len = 0, cap = shape_cache_params.reserve )
|
||||
// assert( error == .None, "VEFontCache.init : Failed to allocate bounds_scaled array for shape cache storage" )
|
||||
}
|
||||
}
|
||||
|
||||
@ -365,8 +380,12 @@ hot_reload :: proc( ctx : ^Context, allocator : Allocator )
|
||||
lru_reload( & shape_cache.state, allocator )
|
||||
for idx : i32 = 0; idx < i32(len(shape_cache.storage)); idx += 1 {
|
||||
storage_entry := & shape_cache.storage[idx]
|
||||
reload_array( & storage_entry.glyph_id, allocator )
|
||||
reload_array( & storage_entry.position, allocator )
|
||||
reload_array( & storage_entry.glyph_id, allocator)
|
||||
reload_array( & storage_entry.position, allocator)
|
||||
reload_array( & storage_entry.atlas_lru_code, allocator)
|
||||
reload_array( & storage_entry.region_kind, allocator)
|
||||
reload_array( & storage_entry.bounds, allocator)
|
||||
// reload_array( & storage_entry.bounds_scaled, allocator)
|
||||
}
|
||||
reload_array( & shape_cache.storage, allocator )
|
||||
|
||||
@ -415,6 +434,10 @@ shutdown :: proc( ctx : ^Context )
|
||||
storage_entry := & shape_cache.storage[idx]
|
||||
delete( storage_entry.glyph_id )
|
||||
delete( storage_entry.position )
|
||||
delete( storage_entry.atlas_lru_code)
|
||||
delete( storage_entry.region_kind)
|
||||
delete( storage_entry.bounds)
|
||||
// delete( storage_entry.bounds_scaled)
|
||||
}
|
||||
lru_free( & shape_cache.state )
|
||||
|
||||
|
@ -15,7 +15,7 @@ set_profiler_module_context :: #force_inline proc "contextless" ( ctx : ^SpallPr
|
||||
Module_Context = ctx
|
||||
}
|
||||
|
||||
DISABLE_PROFILING :: false
|
||||
DISABLE_PROFILING :: true
|
||||
|
||||
@(deferred_none = profile_end, disabled = DISABLE_PROFILING)
|
||||
profile :: #force_inline proc "contextless" ( name : string, loc := #caller_location ) {
|
||||
|
@ -205,11 +205,11 @@ push-location $path_root
|
||||
# $build_args += $flag_micro_architecture_native
|
||||
$build_args += $flag_use_separate_modules
|
||||
$build_args += $flag_thread_count + $CoreCount_Physical
|
||||
$build_args += $flag_optimize_none
|
||||
# $build_args += $flag_optimize_none
|
||||
# $build_args += $flag_optimize_minimal
|
||||
# $build_args += $flag_optimize_speed
|
||||
# $build_args += $falg_optimize_aggressive
|
||||
$build_args += $flag_debug
|
||||
$build_args += $falg_optimize_aggressive
|
||||
# $build_args += $flag_debug
|
||||
$build_args += $flag_pdb_name + $pdb
|
||||
$build_args += $flag_subsystem + 'windows'
|
||||
# $build_args += $flag_show_system_calls
|
||||
|
Loading…
x
Reference in New Issue
Block a user