WIP - VEFontCache: Working on streamlining to_cache codepath
This commit is contained in:
parent
83b7098ce9
commit
5b59942c1a
@ -55,7 +55,7 @@ atlas_decide_region :: #force_inline proc "contextless" (atlas : Atlas, glyph_bu
|
||||
{
|
||||
profile(#procedure)
|
||||
glyph_padding_dbl := atlas.glyph_padding * 2
|
||||
padded_bounds := bounds_size_scaled + glyph_padding_dbl
|
||||
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) {
|
||||
return cast(Atlas_Region_Kind) kind
|
||||
|
@ -28,7 +28,9 @@ Glyph_Draw_Quad :: struct {
|
||||
src_scale : Vec2,
|
||||
}
|
||||
|
||||
Glyph_Pack_Entry :: struct #packed {
|
||||
// This is used by generate_shape_draw_list & batch_generate_glyphs_draw_list
|
||||
// to track relevant glyph data in soa format for pipelined processing
|
||||
Glyph_Pack_Entry :: struct {
|
||||
position : Vec2,
|
||||
|
||||
index : Glyph,
|
||||
@ -40,8 +42,6 @@ Glyph_Pack_Entry :: struct #packed {
|
||||
region_pos : Vec2,
|
||||
region_size : Vec2,
|
||||
|
||||
shape : Parser_Glyph_Shape,
|
||||
|
||||
bounds : Range2,
|
||||
bounds_scaled : Range2,
|
||||
bounds_size : Vec2,
|
||||
@ -49,11 +49,14 @@ Glyph_Pack_Entry :: struct #packed {
|
||||
over_sample : Vec2,
|
||||
scale : Vec2,
|
||||
|
||||
shape : Parser_Glyph_Shape,
|
||||
draw_transform : Transform,
|
||||
|
||||
draw_quad : Glyph_Draw_Quad,
|
||||
draw_atlas_quad : Glyph_Draw_Quad,
|
||||
draw_quad_clear : Glyph_Draw_Quad,
|
||||
draw_quad : Glyph_Draw_Quad,
|
||||
draw_atlas_quad : Glyph_Draw_Quad,
|
||||
draw_quad_clear : Glyph_Draw_Quad,
|
||||
buffer_x : f32,
|
||||
flush_glyph_buffer : b8,
|
||||
}
|
||||
|
||||
Draw_Call :: struct {
|
||||
@ -80,7 +83,6 @@ Draw_List :: struct {
|
||||
calls : [dynamic]Draw_Call,
|
||||
}
|
||||
|
||||
// TODO(Ed): This was a rough translation of the raw values the orignal was using, need to give better names...
|
||||
Frame_Buffer_Pass :: enum u32 {
|
||||
None = 0,
|
||||
Glyph = 1,
|
||||
@ -97,16 +99,15 @@ Glyph_Batch_Cache :: struct {
|
||||
|
||||
Glyph_Draw_Buffer :: struct{
|
||||
over_sample : Vec2,
|
||||
batch : i32,
|
||||
batch : i32, // TODO(Ed): Review this.
|
||||
width : i32,
|
||||
height : i32,
|
||||
draw_padding : f32,
|
||||
|
||||
batch_x : i32,
|
||||
allocated_x : i32, // Space used (horizontally) within the glyph buffer
|
||||
clear_draw_list : Draw_List,
|
||||
draw_list : Draw_List,
|
||||
|
||||
// TODO(Ed): Get this working properly again.
|
||||
batch_cache : Glyph_Batch_Cache,
|
||||
shape_gen_scratch : [dynamic]Vertex,
|
||||
|
||||
@ -264,26 +265,27 @@ cache_glyph_to_atlas :: #force_no_inline proc (
|
||||
glyph_buffer_size : Vec2,
|
||||
over_sample : Vec2,
|
||||
glyph_padding : f32,
|
||||
buf_transform : Transform,
|
||||
draw_transform : Transform,
|
||||
|
||||
region_pos : Vec2,
|
||||
region_size : Vec2,
|
||||
curve_quality : f32,
|
||||
|
||||
flush_glyph_buffer : b8,
|
||||
glyph_buffer_x : f32,
|
||||
)
|
||||
{
|
||||
profile(#procedure)
|
||||
batch_x := cast(f32) glyph_buf_Batch_x ^
|
||||
buffer_padding_scaled := glyph_padding * over_sample
|
||||
buffer_bounds_scale := (bounds_size_scaled) * over_sample
|
||||
f32_allocated_x := cast(f32) glyph_buf_Batch_x ^
|
||||
|
||||
// Allocate a glyph glyph render target region (FBO)
|
||||
buffer_x_allocation := buffer_bounds_scale.x + buffer_padding_scaled.x + 2.0
|
||||
// Resolve how much space this glyph will allocate in the buffer
|
||||
buffer_size := (bounds_size_scaled + glyph_padding) * over_sample
|
||||
|
||||
// If we exceed the region availbe to draw on the buffer, flush the calls to reset the buffer
|
||||
if i32(batch_x + buffer_x_allocation) >= i32(glyph_buffer_size.x) {
|
||||
flush_glyph_buffer_draw_list( draw_list, glyph_buf_draw_list, glyph_buf_clear_list, glyph_buf_Batch_x )
|
||||
batch_x = cast(f32) glyph_buf_Batch_x ^
|
||||
}
|
||||
// If allocation would exceed buffer's bounds the buffer must be flush before this glyph can be rendered.
|
||||
// flush_glyph_buffer := i32(f32_allocated_x + to_allocate_x) >= i32(glyph_buffer_size.x)
|
||||
// glyph_buffer_x := flush_glyph_buffer ? 0 : f32_allocated_x
|
||||
|
||||
if flush_glyph_buffer do flush_glyph_buffer_draw_list( draw_list, glyph_buf_draw_list, glyph_buf_clear_list, glyph_buf_Batch_x )
|
||||
|
||||
region_pos := region_pos
|
||||
dst_glyph_position := region_pos
|
||||
@ -292,8 +294,8 @@ cache_glyph_to_atlas :: #force_no_inline proc (
|
||||
to_glyph_buffer_space( & dst_glyph_position, & dst_glyph_size, atlas_size )
|
||||
to_glyph_buffer_space( & region_pos, & dst_size, atlas_size )
|
||||
|
||||
src_position := Vec2 { batch_x, 0 }
|
||||
src_size := (buffer_bounds_scale + buffer_padding_scaled)
|
||||
src_position := Vec2 { glyph_buffer_x, 0 }
|
||||
src_size := buffer_size
|
||||
to_target_space( & src_position, & src_size, glyph_buffer_size )
|
||||
|
||||
clear_target_region : Draw_Call
|
||||
@ -327,14 +329,18 @@ cache_glyph_to_atlas :: #force_no_inline proc (
|
||||
append( & glyph_buf_clear_list.calls, clear_target_region )
|
||||
append( & glyph_buf_draw_list.calls, blit_to_atlas )
|
||||
|
||||
// Allocate a glyph glyph render target region (FBO)
|
||||
to_allocate_x := buffer_size.x + 2.0
|
||||
|
||||
// The glyph buffer space transform for generate_glyph_pass_draw_list
|
||||
glyph_transform := buf_transform
|
||||
glyph_transform.pos.x += batch_x
|
||||
(glyph_buf_Batch_x ^) += i32(buffer_x_allocation)
|
||||
to_glyph_buffer_space( & glyph_transform.pos, & glyph_transform.scale, glyph_buffer_size )
|
||||
draw_transform := draw_transform
|
||||
draw_transform.pos.x += glyph_buffer_x
|
||||
to_glyph_buffer_space( & draw_transform.pos, & draw_transform.scale, glyph_buffer_size )
|
||||
|
||||
(glyph_buf_Batch_x ^) += i32(to_allocate_x)
|
||||
|
||||
// Render glyph to glyph render target (FBO)
|
||||
generate_glyph_pass_draw_list( draw_list, temp_path, glyph_shape, curve_quality, bounds, glyph_transform.scale, glyph_transform.pos )
|
||||
generate_glyph_pass_draw_list( draw_list, temp_path, glyph_shape, curve_quality, bounds, draw_transform.scale, draw_transform.pos )
|
||||
}
|
||||
|
||||
generate_shape_draw_list :: #force_no_inline proc( draw_list : ^Draw_List, shape : Shaped_Text,
|
||||
@ -543,7 +549,9 @@ batch_generate_glyphs_draw_list :: proc ( draw_list : ^Draw_List,
|
||||
colour := colour
|
||||
}
|
||||
|
||||
profile_begin("transform & quad compute")
|
||||
flush_glyph_buffer_draw_list(draw_list, & glyph_buffer.draw_list, & glyph_buffer.clear_draw_list, & glyph_buffer.allocated_x)
|
||||
|
||||
profile_begin("glyph buffer transform & draw quads compute")
|
||||
for id, index in cached
|
||||
{
|
||||
// Quad to for drawing atlas slot to target
|
||||
@ -559,24 +567,60 @@ batch_generate_glyphs_draw_list :: proc ( draw_list : ^Draw_List,
|
||||
{
|
||||
glyph := & glyph_pack[id]
|
||||
|
||||
// Quad to for drawing atlas slot to target
|
||||
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.src_pos = (glyph.region_pos)
|
||||
to_target_space( & quad.src_pos, & quad.src_scale, atlas_size )
|
||||
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
|
||||
|
||||
// Allocate a glyph glyph render target region (FBO)
|
||||
to_allocate_x := buffer_size.x + 2.0 // TODO
|
||||
|
||||
// If allocation would exceed buffer's bounds the buffer must be flush before this glyph can be rendered.
|
||||
glyph.flush_glyph_buffer = i32(f32_allocated_x + to_allocate_x) >= i32(glyph_buffer_size.x)
|
||||
glyph.buffer_x = glyph.flush_glyph_buffer ? 0 : f32_allocated_x
|
||||
|
||||
// The glyph buffer space transform for generate_glyph_pass_draw_list
|
||||
transform := & glyph.draw_transform
|
||||
transform.scale = font_scale * glyph_buffer.over_sample
|
||||
transform.pos = -1 * (glyph.bounds.p0) * transform.scale + atlas.glyph_padding
|
||||
// Unlike with oversized, this cannot be finished here as its final value is dependent on glyph_buffer.batch_x allocation
|
||||
draw_transform := & glyph.draw_transform
|
||||
draw_transform.scale = font_scale * glyph_buffer.over_sample
|
||||
draw_transform.pos = -1 * (glyph.bounds.p0) * draw_transform.scale + atlas.glyph_padding
|
||||
// draw_transform.pos += glyph.buffer_x
|
||||
// to_glyph_buffer_space( & draw_transform.pos, & draw_transform.scale, glyph_buffer_size )
|
||||
|
||||
// Allocate the space
|
||||
glyph_buffer.allocated_x += i32(to_allocate_x)
|
||||
|
||||
// Quad to for drawing atlas slot to target (used in generate_cached_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
|
||||
|
||||
// UV Coordinates for sampling the atlas
|
||||
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
|
||||
{
|
||||
glyph := & glyph_pack[id]
|
||||
|
||||
|
||||
glyph_padding := vec2(glyph_buffer.draw_padding)
|
||||
|
||||
// Quad to draw during target pass, every
|
||||
quad := & glyph.draw_quad
|
||||
|
||||
// Target position (draw_list's target image)
|
||||
quad.dst_pos = glyph.position + (glyph.bounds_scaled.p0 - glyph_padding) * target_scale
|
||||
quad.dst_scale = (glyph.bounds_size_scaled + glyph_padding) * target_scale
|
||||
|
||||
// UV coordinates for sampling from glyph buffer
|
||||
buffer_region_pos := Vec2{0, 0} // Where in the buffer we rendered
|
||||
buffer_region_size := glyph.bounds_size_scaled * glyph.over_sample + glyph_padding //* font_scale
|
||||
quad.src_pos = buffer_region_pos
|
||||
quad.src_scale = buffer_region_size
|
||||
to_target_space( & quad.src_pos, & quad.src_scale, glyph_buffer_size )
|
||||
|
||||
// The glyph buffer space transform for generate_glyph_pass_draw_list
|
||||
transform := & glyph.draw_transform
|
||||
transform.scale = font_scale * glyph.over_sample
|
||||
@ -584,21 +628,115 @@ batch_generate_glyphs_draw_list :: proc ( draw_list : ^Draw_List,
|
||||
to_glyph_buffer_space( & transform.pos, & transform.scale, glyph_buffer_size )
|
||||
// Oversized will use a cleared glyph_buffer every time.
|
||||
|
||||
glyph_padding := vec2(glyph_buffer.draw_padding)
|
||||
|
||||
// Quad to draw during target pass, every
|
||||
quad := & glyph.draw_quad
|
||||
quad.dst_pos = glyph.position + (glyph.bounds_scaled.p0 - glyph_padding) * target_scale //- ({0, 0.5}) * target_scale
|
||||
quad.dst_scale = (glyph.bounds_size_scaled + glyph_padding) * target_scale
|
||||
quad.src_pos = {}
|
||||
quad.src_scale = glyph.bounds_size_scaled * glyph.over_sample - glyph_padding
|
||||
to_target_space( & quad.src_pos, & quad.src_scale, glyph_buffer_size )
|
||||
|
||||
dummy := 0
|
||||
dummy += 1
|
||||
}
|
||||
profile_end()
|
||||
|
||||
glyph_buffer.allocated_x = 0
|
||||
|
||||
profile_begin("to_cache: caching to atlas")
|
||||
{
|
||||
for id, index in to_cache {
|
||||
error : Allocator_Error
|
||||
glyph_pack[id].shape, error = parser_get_glyph_shape(entry.parser_info, glyph_pack[id].index)
|
||||
assert(error == .None)
|
||||
}
|
||||
|
||||
for id, index in to_cache
|
||||
{
|
||||
profile("glyph")
|
||||
glyph := & glyph_pack[id]
|
||||
|
||||
cache_glyph_to_atlas(
|
||||
draw_list,
|
||||
& glyph_buffer.draw_list,
|
||||
& glyph_buffer.clear_draw_list,
|
||||
& glyph_buffer.allocated_x,
|
||||
& glyph_buffer.shape_gen_scratch,
|
||||
|
||||
glyph.shape,
|
||||
glyph.bounds_scaled,
|
||||
glyph.bounds_size_scaled,
|
||||
atlas_size,
|
||||
|
||||
glyph_buffer_size,
|
||||
glyph.over_sample,
|
||||
glyph_buffer.draw_padding,
|
||||
glyph.draw_transform,
|
||||
|
||||
glyph.region_pos,
|
||||
glyph.region_size,
|
||||
entry.curve_quality,
|
||||
|
||||
glyph.flush_glyph_buffer,
|
||||
glyph.buffer_x
|
||||
)
|
||||
|
||||
// if glyph.flush_glyph_buffer do flush_glyph_buffer_draw_list( draw_list,
|
||||
// & glyph_buffer.draw_list,
|
||||
// & glyph_buffer.clear_draw_list,
|
||||
// & glyph_buffer.allocated_x
|
||||
// )
|
||||
|
||||
// dst_region_pos := glyph.region_pos
|
||||
// dst_region_size := glyph.region_size
|
||||
// to_glyph_buffer_space( & dst_region_pos, & dst_region_size, atlas_size )
|
||||
|
||||
// clear_target_region : Draw_Call
|
||||
// {
|
||||
// using clear_target_region
|
||||
// pass = .Atlas
|
||||
// region = .Ignore
|
||||
// start_index = cast(u32) len(glyph_buffer.clear_draw_list.indices)
|
||||
|
||||
// blit_quad( & glyph_buffer.clear_draw_list,
|
||||
// dst_region_pos, dst_region_pos + dst_region_size,
|
||||
// { 1.0, 1.0 }, { 1.0, 1.0 } )
|
||||
// // { 0.0, 0.0 }, { 0.0, 0.0 } )
|
||||
|
||||
// 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
|
||||
// to_glyph_buffer_space( & dst_glyph_pos, & dst_glyph_size, atlas_size )
|
||||
|
||||
// src_position := Vec2 { glyph.glyph_buffer_x, 0 }
|
||||
// src_size := (glyph.bounds_size_scaled + atlas.glyph_padding) * glyph_buffer.over_sample
|
||||
// to_target_space( & src_position, & src_size, glyph_buffer_size )
|
||||
|
||||
// blit_to_atlas : Draw_Call
|
||||
// {
|
||||
// using blit_to_atlas
|
||||
// pass = .Atlas
|
||||
// region = .None
|
||||
// start_index = cast(u32) len(glyph_buffer.draw_list.indices)
|
||||
|
||||
// blit_quad( & glyph_buffer.draw_list,
|
||||
// dst_glyph_pos, dst_glyph_pos + dst_glyph_size,
|
||||
// src_position, src_position + src_size )
|
||||
|
||||
// end_index = cast(u32) len(glyph_buffer.draw_list.indices)
|
||||
// }
|
||||
|
||||
// append( & glyph_buffer.clear_draw_list.calls, clear_target_region )
|
||||
// append( & glyph_buffer.draw_list.calls, blit_to_atlas )
|
||||
|
||||
// // Render glyph to glyph render target (FBO)
|
||||
// generate_glyph_pass_draw_list( draw_list, & glyph_buffer.shape_gen_scratch,
|
||||
// glyph.shape,
|
||||
// entry.curve_quality,
|
||||
// glyph.bounds,
|
||||
// glyph.draw_transform.pos,
|
||||
// glyph.draw_transform.scale
|
||||
// )
|
||||
}
|
||||
flush_glyph_buffer_draw_list(draw_list, & glyph_buffer.draw_list, & glyph_buffer.clear_draw_list, & glyph_buffer.allocated_x)
|
||||
for id, index in to_cache do parser_free_shape(entry.parser_info, glyph_pack[id].shape)
|
||||
}
|
||||
profile_end()
|
||||
|
||||
generate_cached_draw_list :: #force_inline proc (draw_list : ^Draw_List, glyph_pack : #soa[]Glyph_Pack_Entry, sub_pack : []i32, colour : Colour )
|
||||
{
|
||||
profile(#procedure)
|
||||
@ -620,49 +758,14 @@ batch_generate_glyphs_draw_list :: proc ( draw_list : ^Draw_List,
|
||||
}
|
||||
}
|
||||
|
||||
profile_begin("to_cache: caching to atlas")
|
||||
for id, index in to_cache {
|
||||
error : Allocator_Error
|
||||
glyph_pack[id].shape, error = parser_get_glyph_shape(entry.parser_info, glyph_pack[id].index)
|
||||
assert(error == .None)
|
||||
profile_begin("generate_cached_draw_list: to_cache")
|
||||
when ENABLE_DRAW_TYPE_VIS {
|
||||
colour.r = 0.80
|
||||
colour.g = 0.25
|
||||
colour.b = 0.25
|
||||
}
|
||||
for id, index in to_cache
|
||||
{
|
||||
profile("glyph")
|
||||
when ENABLE_DRAW_TYPE_VIS {
|
||||
colour.r = 0.80
|
||||
colour.g = 0.25
|
||||
colour.b = 0.25
|
||||
}
|
||||
|
||||
glyph := glyph_pack[id]
|
||||
cache_glyph_to_atlas(
|
||||
draw_list,
|
||||
& glyph_buffer.draw_list,
|
||||
& glyph_buffer.clear_draw_list,
|
||||
& glyph_buffer.batch_x,
|
||||
& glyph_buffer.shape_gen_scratch,
|
||||
|
||||
glyph.shape,
|
||||
glyph.bounds_scaled,
|
||||
glyph.bounds_size_scaled,
|
||||
atlas_size,
|
||||
|
||||
glyph_buffer_size,
|
||||
glyph.over_sample,
|
||||
atlas.glyph_padding,
|
||||
glyph.draw_transform,
|
||||
|
||||
glyph.region_pos,
|
||||
glyph.region_size,
|
||||
entry.curve_quality,
|
||||
)
|
||||
}
|
||||
flush_glyph_buffer_draw_list(draw_list, & glyph_buffer.draw_list, & glyph_buffer.clear_draw_list, & glyph_buffer.batch_x)
|
||||
for id, index in to_cache do parser_free_shape(entry.parser_info, glyph_pack[id].shape)
|
||||
profile_end()
|
||||
|
||||
generate_cached_draw_list( draw_list, glyph_pack[:], to_cache, colour )
|
||||
profile_end()
|
||||
|
||||
profile_begin("generate_cached_draw_list: to_cache")
|
||||
when ENABLE_DRAW_TYPE_VIS {
|
||||
@ -673,64 +776,66 @@ batch_generate_glyphs_draw_list :: proc ( draw_list : ^Draw_List,
|
||||
generate_cached_draw_list( draw_list, glyph_pack[:], cached, colour )
|
||||
profile_end()
|
||||
|
||||
flush_glyph_buffer_draw_list(draw_list, & glyph_buffer.draw_list, & glyph_buffer.clear_draw_list, & glyph_buffer.batch_x)
|
||||
flush_glyph_buffer_draw_list(draw_list, & glyph_buffer.draw_list, & glyph_buffer.clear_draw_list, & glyph_buffer.allocated_x)
|
||||
|
||||
profile_begin("generate oversized glyphs draw_list")
|
||||
for id, index in oversized {
|
||||
error : Allocator_Error
|
||||
glyph_pack[id].shape, error = parser_get_glyph_shape(entry.parser_info, glyph_pack[id].index)
|
||||
assert(error == .None)
|
||||
}
|
||||
for id, index in oversized
|
||||
{
|
||||
flush_glyph_buffer_draw_list(draw_list, & glyph_buffer.draw_list, & glyph_buffer.clear_draw_list, & glyph_buffer.batch_x)
|
||||
|
||||
generate_glyph_pass_draw_list( draw_list, & glyph_buffer.shape_gen_scratch,
|
||||
glyph_pack[id].shape,
|
||||
entry.curve_quality,
|
||||
glyph_pack[id].bounds_scaled,
|
||||
glyph_pack[id].draw_transform.scale,
|
||||
glyph_pack[id].draw_transform.pos
|
||||
)
|
||||
|
||||
when ENABLE_DRAW_TYPE_VIS {
|
||||
colour.r = 1.0
|
||||
colour.g = 1.0
|
||||
colour.b = 0.0
|
||||
}
|
||||
|
||||
target_quad := glyph_pack[id].draw_quad
|
||||
|
||||
calls : [2]Draw_Call
|
||||
draw_to_target := & calls[0]
|
||||
{
|
||||
using draw_to_target
|
||||
pass = .Target_Uncached
|
||||
colour = colour
|
||||
start_index = u32(len(draw_list.indices))
|
||||
|
||||
blit_quad( draw_list,
|
||||
target_quad.dst_pos, target_quad.dst_pos + target_quad.dst_scale,
|
||||
target_quad.src_pos, target_quad.src_pos + target_quad.src_scale )
|
||||
|
||||
end_index = u32(len(draw_list.indices))
|
||||
for id, index in oversized {
|
||||
error : Allocator_Error
|
||||
glyph_pack[id].shape, error = parser_get_glyph_shape(entry.parser_info, glyph_pack[id].index)
|
||||
assert(error == .None)
|
||||
}
|
||||
clear_glyph_update := & calls[1]
|
||||
for id, index in oversized
|
||||
{
|
||||
// Clear glyph render target (FBO)
|
||||
clear_glyph_update.pass = .Glyph
|
||||
clear_glyph_update.start_index = 0
|
||||
clear_glyph_update.end_index = 0
|
||||
clear_glyph_update.clear_before_draw = true
|
||||
flush_glyph_buffer_draw_list(draw_list, & glyph_buffer.draw_list, & glyph_buffer.clear_draw_list, & glyph_buffer.allocated_x)
|
||||
|
||||
generate_glyph_pass_draw_list( draw_list, & glyph_buffer.shape_gen_scratch,
|
||||
glyph_pack[id].shape,
|
||||
entry.curve_quality,
|
||||
glyph_pack[id].bounds,
|
||||
glyph_pack[id].draw_transform.scale,
|
||||
glyph_pack[id].draw_transform.pos
|
||||
)
|
||||
|
||||
target_quad := & glyph_pack[id].draw_quad
|
||||
|
||||
calls : [2]Draw_Call
|
||||
draw_to_target := & calls[0]
|
||||
{
|
||||
using draw_to_target
|
||||
pass = .Target_Uncached
|
||||
colour = colour
|
||||
start_index = u32(len(draw_list.indices))
|
||||
|
||||
blit_quad( draw_list,
|
||||
target_quad.dst_pos, target_quad.dst_pos + target_quad.dst_scale,
|
||||
target_quad.src_pos, target_quad.src_pos + target_quad.src_scale )
|
||||
|
||||
end_index = u32(len(draw_list.indices))
|
||||
}
|
||||
clear_glyph_update := & calls[1]
|
||||
{
|
||||
// Clear glyph render target (FBO)
|
||||
clear_glyph_update.pass = .Glyph
|
||||
clear_glyph_update.start_index = 0
|
||||
clear_glyph_update.end_index = 0
|
||||
clear_glyph_update.clear_before_draw = true
|
||||
}
|
||||
append( & draw_list.calls, calls[0] )
|
||||
append( & draw_list.calls, calls[1] )
|
||||
}
|
||||
append( & draw_list.calls, ..calls[:] )
|
||||
for id, index in oversized do parser_free_shape(entry.parser_info, glyph_pack[id].shape)
|
||||
}
|
||||
for id, index in oversized do parser_free_shape(entry.parser_info, glyph_pack[id].shape)
|
||||
profile_end()
|
||||
}
|
||||
|
||||
// Flush the content of the glyph_buffers draw lists to the main draw list
|
||||
flush_glyph_buffer_draw_list :: #force_inline proc( #no_alias draw_list, glyph_buffer_draw_list, glyph_buffer_clear_draw_list : ^Draw_List, glyph_buffer_batch_x : ^i32 )
|
||||
flush_glyph_buffer_draw_list :: #force_inline proc( #no_alias draw_list, glyph_buffer_draw_list, glyph_buffer_clear_draw_list : ^Draw_List, allocated_x : ^i32 )
|
||||
{
|
||||
profile(#procedure)
|
||||
// Flush Draw_Calls to draw list
|
||||
@ -740,7 +845,7 @@ flush_glyph_buffer_draw_list :: #force_inline proc( #no_alias draw_list, glyph_b
|
||||
clear_draw_list( glyph_buffer_clear_draw_list )
|
||||
|
||||
// Clear glyph render target (FBO)
|
||||
if (glyph_buffer_batch_x ^) != 0
|
||||
if (allocated_x ^) != 0
|
||||
{
|
||||
call := Draw_Call_Default
|
||||
call.pass = .Glyph
|
||||
@ -748,7 +853,7 @@ flush_glyph_buffer_draw_list :: #force_inline proc( #no_alias draw_list, glyph_b
|
||||
call.end_index = 0
|
||||
call.clear_before_draw = true
|
||||
append( & draw_list.calls, call )
|
||||
(glyph_buffer_batch_x ^) = 0
|
||||
(allocated_x ^) = 0
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -117,16 +117,16 @@ Init_Glyph_Draw_Params :: struct {
|
||||
over_sample : Vec2,
|
||||
draw_padding : u32,
|
||||
shape_gen_scratch_reserve : u32,
|
||||
buffer_batch : u32,
|
||||
buffer_batch_glyph_limit : u32, // How many glyphs can at maximimum be proccessed at once by batch_generate_glyphs_draw_list
|
||||
buffer_glyph_limit : u32, // How many region.D glyphs can be drawn to the glyph render target buffer at once (worst case scenario)
|
||||
batch_glyph_limit : u32, // How many glyphs can at maximimum be proccessed at once by batch_generate_glyphs_draw_list
|
||||
}
|
||||
|
||||
Init_Glyph_Draw_Params_Default :: Init_Glyph_Draw_Params {
|
||||
over_sample = Vec2 { 4, 4 },
|
||||
draw_padding = Init_Atlas_Params_Default.glyph_padding,
|
||||
shape_gen_scratch_reserve = 10 * 1024,
|
||||
buffer_batch = 4,
|
||||
buffer_batch_glyph_limit = 512,
|
||||
buffer_glyph_limit = 4,
|
||||
batch_glyph_limit = 512,
|
||||
}
|
||||
|
||||
Init_Shaper_Params :: struct {
|
||||
@ -166,147 +166,146 @@ startup :: proc( ctx : ^Context, parser_kind : Parser_Kind = .STB_TrueType,
|
||||
)
|
||||
{
|
||||
assert( ctx != nil, "Must provide a valid context" )
|
||||
using ctx
|
||||
|
||||
ctx.backing = allocator
|
||||
context.allocator = ctx.backing
|
||||
|
||||
ctx.colour = { 1, 1, 1, 1 }
|
||||
|
||||
shaper_ctx := & ctx.shaper_ctx
|
||||
shaper_ctx.adv_snap_small_font_threshold = f32(shaper_params.adv_snap_small_font_threshold)
|
||||
shaper_ctx.snap_glyph_position = shaper_params.snap_glyph_position
|
||||
|
||||
if default_curve_quality == 0 {
|
||||
default_curve_quality = 3
|
||||
}
|
||||
ctx.default_curve_quality = default_curve_quality
|
||||
ctx.default_curve_quality = default_curve_quality == 0 ? 3 : i32(default_curve_quality)
|
||||
|
||||
error : Allocator_Error
|
||||
entries, error = make( [dynamic]Entry, len = 0, cap = entires_reserve )
|
||||
ctx.entries, error = make( [dynamic]Entry, len = 0, cap = entires_reserve )
|
||||
assert(error == .None, "VEFontCache.init : Failed to allocate entries")
|
||||
|
||||
draw_list.vertices, error = make( [dynamic]Vertex, len = 0, cap = 8 * Kilobyte )
|
||||
ctx.draw_list.vertices, error = make( [dynamic]Vertex, len = 0, cap = 8 * Kilobyte )
|
||||
assert(error == .None, "VEFontCache.init : Failed to allocate draw_list.vertices")
|
||||
|
||||
draw_list.indices, error = make( [dynamic]u32, len = 0, cap = 16 * Kilobyte )
|
||||
ctx.draw_list.indices, error = make( [dynamic]u32, len = 0, cap = 16 * Kilobyte )
|
||||
assert(error == .None, "VEFontCache.init : Failed to allocate draw_list.indices")
|
||||
|
||||
draw_list.calls, error = make( [dynamic]Draw_Call, len = 0, cap = 1024 )
|
||||
ctx.draw_list.calls, error = make( [dynamic]Draw_Call, len = 0, cap = Kilobyte )
|
||||
assert(error == .None, "VEFontCache.init : Failed to allocate draw_list.calls")
|
||||
|
||||
init_atlas_region :: proc( region : ^Atlas_Region, params : Init_Atlas_Params, region_params : Init_Atlas_Region_Params, factor : Vec2i, expected_cap : i32 )
|
||||
atlas := & ctx.atlas
|
||||
Atlas_Setup:
|
||||
{
|
||||
using region
|
||||
init_atlas_region :: proc( region : ^Atlas_Region, params : Init_Atlas_Params, region_params : Init_Atlas_Region_Params, factor : Vec2i, expected_cap : i32 )
|
||||
{
|
||||
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 )
|
||||
|
||||
next_idx = 0;
|
||||
width = i32(region_params.width)
|
||||
height = i32(region_params.height)
|
||||
size = {
|
||||
i32(params.width) / factor.x,
|
||||
i32(params.height) / factor.y,
|
||||
error : Allocator_Error
|
||||
lru_init( & region.state, region.capacity.x * region.capacity.y )
|
||||
}
|
||||
capacity = {
|
||||
size.x / i32(width),
|
||||
size.y / i32(height),
|
||||
init_atlas_region( & atlas.region_a, atlas_params, atlas_params.region_a, { 4, 2}, 1024 )
|
||||
init_atlas_region( & atlas.region_b, atlas_params, atlas_params.region_b, { 4, 2}, 512 )
|
||||
init_atlas_region( & atlas.region_c, atlas_params, atlas_params.region_c, { 4, 1}, 512 )
|
||||
init_atlas_region( & atlas.region_d, atlas_params, atlas_params.region_d, { 2, 1}, 256 )
|
||||
|
||||
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.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.y = 0
|
||||
|
||||
atlas.regions = {
|
||||
nil,
|
||||
& atlas.region_a,
|
||||
& atlas.region_b,
|
||||
& atlas.region_c,
|
||||
& atlas.region_d,
|
||||
}
|
||||
assert( capacity.x * capacity.y == expected_cap )
|
||||
|
||||
error : Allocator_Error
|
||||
lru_init( & state, capacity.x * capacity.y )
|
||||
}
|
||||
init_atlas_region( & atlas.region_a, atlas_params, atlas_params.region_a, { 4, 2}, 1024 )
|
||||
init_atlas_region( & atlas.region_b, atlas_params, atlas_params.region_b, { 4, 2}, 512 )
|
||||
init_atlas_region( & atlas.region_c, atlas_params, atlas_params.region_c, { 4, 1}, 512 )
|
||||
init_atlas_region( & atlas.region_d, atlas_params, atlas_params.region_d, { 2, 1}, 256 )
|
||||
|
||||
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.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.y = 0
|
||||
|
||||
atlas.regions = {
|
||||
nil,
|
||||
& atlas.region_a,
|
||||
& atlas.region_b,
|
||||
& atlas.region_c,
|
||||
& atlas.region_d,
|
||||
}
|
||||
|
||||
lru_init( & shape_cache.state, i32(shape_cache_params.capacity) )
|
||||
Shape_Cache_Setup:
|
||||
{
|
||||
shape_cache := & ctx.shape_cache
|
||||
lru_init( & shape_cache.state, i32(shape_cache_params.capacity) )
|
||||
|
||||
shape_cache.storage, error = make( [dynamic]Shaped_Text, shape_cache_params.capacity )
|
||||
assert(error == .None, "VEFontCache.init : Failed to allocate shape_cache.storage")
|
||||
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 {
|
||||
stroage_entry := & shape_cache.storage[idx]
|
||||
using stroage_entry
|
||||
glyphs, error = make( [dynamic]Glyph, len = 0, cap = shape_cache_params.reserve_length )
|
||||
assert( error == .None, "VEFontCache.init : Failed to allocate glyphs array for shape cache storage" )
|
||||
for idx : u32 = 0; idx < shape_cache_params.capacity; idx += 1 {
|
||||
stroage_entry := & shape_cache.storage[idx]
|
||||
|
||||
positions, error = make( [dynamic]Vec2, len = 0, cap = shape_cache_params.reserve_length )
|
||||
assert( error == .None, "VEFontCache.init : Failed to allocate positions array for shape cache storage" )
|
||||
stroage_entry.glyphs, error = make( [dynamic]Glyph, len = 0, cap = shape_cache_params.reserve_length )
|
||||
assert( error == .None, "VEFontCache.init : Failed to allocate glyphs array for shape cache storage" )
|
||||
|
||||
draw_list.calls, error = make( [dynamic]Draw_Call, len = 0, cap = glyph_draw_params.buffer_batch * 2 )
|
||||
assert( error == .None, "VEFontCache.init : Failed to allocate calls for draw_list" )
|
||||
|
||||
draw_list.indices, error = make( [dynamic]u32, len = 0, cap = glyph_draw_params.buffer_batch * 2 * 6 )
|
||||
assert( error == .None, "VEFontCache.init : Failed to allocate indices array for draw_list" )
|
||||
|
||||
draw_list.vertices, error = make( [dynamic]Vertex, len = 0, cap = glyph_draw_params.buffer_batch * 2 * 4 )
|
||||
assert( error == .None, "VEFontCache.init : Failed to allocate vertices array for draw_list" )
|
||||
stroage_entry.positions, error = make( [dynamic]Vec2, len = 0, cap = shape_cache_params.reserve_length )
|
||||
assert( error == .None, "VEFontCache.init : Failed to allocate positions array for shape cache storage" )
|
||||
}
|
||||
}
|
||||
|
||||
Glyph_Buffer_Setup:
|
||||
{
|
||||
using glyph_buffer
|
||||
over_sample = glyph_draw_params.over_sample
|
||||
batch = cast(i32) glyph_draw_params.buffer_batch
|
||||
width = atlas.region_d.width * i32(over_sample.x) * batch
|
||||
height = atlas.region_d.height * i32(over_sample.y) //* (batch / 2)
|
||||
draw_padding = cast(f32) glyph_draw_params.draw_padding
|
||||
glyph_buffer := & ctx.glyph_buffer
|
||||
|
||||
draw_list.calls, error = make( [dynamic]Draw_Call, len = 0, cap = glyph_draw_params.buffer_batch * 2 )
|
||||
assert( error == .None, "VEFontCache.init : Failed to allocate calls for draw_list" )
|
||||
// using 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.draw_padding = cast(f32) glyph_draw_params.draw_padding
|
||||
|
||||
draw_list.indices, error = make( [dynamic]u32, len = 0, cap = glyph_draw_params.buffer_batch * 2 * 6 )
|
||||
assert( error == .None, "VEFontCache.init : Failed to allocate indices array for draw_list" )
|
||||
buffer_limit := glyph_draw_params.buffer_glyph_limit
|
||||
batch_limit := glyph_draw_params.batch_glyph_limit
|
||||
|
||||
draw_list.vertices, error = make( [dynamic]Vertex, len = 0, cap = glyph_draw_params.buffer_batch * 2 * 4 )
|
||||
assert( error == .None, "VEFontCache.init : Failed to allocate vertices array for draw_list" )
|
||||
glyph_buffer.draw_list.vertices, error = make( [dynamic]Vertex, len = 0, cap = 8 * Kilobyte )
|
||||
assert( error == .None, "VEFontCache.init : Failed to allocate vertices array for glyph_buffer.draw_list" )
|
||||
|
||||
clear_draw_list.calls, error = make( [dynamic]Draw_Call, len = 0, cap = glyph_draw_params.buffer_batch * 2 )
|
||||
assert( error == .None, "VEFontCache.init : Failed to allocate calls for calls for clear_draw_list" )
|
||||
glyph_buffer.draw_list.indices, error = make( [dynamic]u32, len = 0, cap = 16 * Kilobyte )
|
||||
assert( error == .None, "VEFontCache.init : Failed to allocate indices for glyph_buffer.draw_list" )
|
||||
|
||||
clear_draw_list.indices, error = make( [dynamic]u32, len = 0, cap = glyph_draw_params.buffer_batch * 2 * 4 )
|
||||
assert( error == .None, "VEFontCache.init : Failed to allocate calls for indices array for clear_draw_list" )
|
||||
glyph_buffer.draw_list.calls, error = make( [dynamic]Draw_Call, len = 0, cap = Kilobyte )
|
||||
assert( error == .None, "VEFontCache.init : Failed to allocate calls for glyph_buffer.draw_list" )
|
||||
|
||||
clear_draw_list.vertices, error = make( [dynamic]Vertex, len = 0, cap = glyph_draw_params.buffer_batch * 2 * 4 )
|
||||
glyph_buffer.clear_draw_list.vertices, error = make( [dynamic]Vertex, len = 0, cap = 2 * Kilobyte )
|
||||
assert( error == .None, "VEFontCache.init : Failed to allocate vertices array for clear_draw_list" )
|
||||
|
||||
shape_gen_scratch, error = make( [dynamic]Vertex, len = 0, cap = glyph_draw_params.buffer_batch_glyph_limit )
|
||||
glyph_buffer.clear_draw_list.indices, error = make( [dynamic]u32, len = 0, cap = 4 * Kilobyte )
|
||||
assert( error == .None, "VEFontCache.init : Failed to allocate calls for indices array for clear_draw_list" )
|
||||
|
||||
glyph_buffer.clear_draw_list.calls, error = make( [dynamic]Draw_Call, len = 0, cap = Kilobyte )
|
||||
assert( error == .None, "VEFontCache.init : Failed to allocate calls for calls for clear_draw_list" )
|
||||
|
||||
glyph_buffer.shape_gen_scratch, error = make( [dynamic]Vertex, len = 0, cap = 4 * Kilobyte )
|
||||
assert(error == .None, "VEFontCache.init : Failed to allocate shape_gen_scratch")
|
||||
|
||||
batch_cache.cap = i32(glyph_draw_params.buffer_batch_glyph_limit)
|
||||
batch_cache := & glyph_buffer.batch_cache
|
||||
batch_cache.cap = i32(glyph_draw_params.batch_glyph_limit)
|
||||
batch_cache.num = 0
|
||||
batch_cache.table, error = make( map[u32]b8, uint(glyph_draw_params.shape_gen_scratch_reserve) )
|
||||
assert(error == .None, "VEFontCache.init : Failed to allocate batch_cache")
|
||||
|
||||
glyph_pack,error = make_soa( #soa[dynamic]Glyph_Pack_Entry, length = 0, capacity = 1 * Kilobyte )
|
||||
oversized, error = make( [dynamic]i32, len = 0, cap = 1 * Kilobyte )
|
||||
to_cache, error = make( [dynamic]i32, len = 0, cap = 1 * Kilobyte )
|
||||
cached, error = make( [dynamic]i32, len = 0, cap = 1 * Kilobyte )
|
||||
glyph_buffer.glyph_pack,error = make_soa( #soa[dynamic]Glyph_Pack_Entry, length = 0, capacity = 1 * Kilobyte )
|
||||
glyph_buffer.oversized, error = make( [dynamic]i32, len = 0, cap = 1 * Kilobyte )
|
||||
glyph_buffer.to_cache, error = make( [dynamic]i32, len = 0, cap = 1 * Kilobyte )
|
||||
glyph_buffer.cached, error = make( [dynamic]i32, len = 0, cap = 1 * Kilobyte )
|
||||
}
|
||||
|
||||
parser_init( & parser_ctx, parser_kind )
|
||||
shaper_init( & shaper_ctx )
|
||||
parser_init( & ctx.parser_ctx, parser_kind )
|
||||
shaper_init( & ctx.shaper_ctx )
|
||||
}
|
||||
|
||||
hot_reload :: proc( ctx : ^Context, allocator : Allocator )
|
||||
@ -506,8 +505,15 @@ draw_text :: #force_inline proc( ctx : ^Context, font : Font_ID, px_size : f32,
|
||||
entry := ctx.entries[ font ]
|
||||
font_scale := parser_scale( entry.parser_info, px_size )
|
||||
shape := shaper_shape_text_cached( text_utf8, & ctx.shaper_ctx, & ctx.shape_cache, font, entry, 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, colour, entry, font_scale, position, scale, ctx.snap_width, ctx.snap_height )
|
||||
|
||||
ctx.cursor_pos = generate_shape_draw_list( & ctx.draw_list, shape, & ctx.atlas, & ctx.glyph_buffer,
|
||||
colour,
|
||||
entry,
|
||||
font_scale,
|
||||
position,
|
||||
scale,
|
||||
ctx.snap_width,
|
||||
ctx.snap_height
|
||||
)
|
||||
return true
|
||||
}
|
||||
|
||||
|
@ -201,10 +201,10 @@ 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 += $falg_optimize_aggressive
|
||||
$build_args += $flag_debug
|
||||
$build_args += $flag_pdb_name + $pdb
|
||||
$build_args += $flag_subsystem + 'windows'
|
||||
|
Loading…
Reference in New Issue
Block a user