WIP - VEFontCache: Working on streamlining to_cache codepath
This commit is contained in:
		@@ -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'
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user