From 6e01c398999a7b6f3ed1a071d35bd3403ec9b31a Mon Sep 17 00:00:00 2001 From: Ed_ Date: Tue, 7 Jan 2025 10:17:46 -0500 Subject: [PATCH] Builds again has on text rendering (makes sense) --- code/font/vefontcache/draw.odin | 24 ++-- code/font/vefontcache/pkg_mapping.odin | 6 +- code/font/vefontcache/vefontcache.odin | 176 +++++++++++++++---------- code/sectr/engine/client_api.odin | 2 +- code/sectr/engine/render.odin | 19 ++- scripts/build.ps1 | 4 +- 6 files changed, 132 insertions(+), 99 deletions(-) diff --git a/code/font/vefontcache/draw.odin b/code/font/vefontcache/draw.odin index e637d69..360588f 100644 --- a/code/font/vefontcache/draw.odin +++ b/code/font/vefontcache/draw.odin @@ -286,8 +286,8 @@ generate_shapes_draw_list :: #force_inline proc ( ctx : ^Context, font : Font_ID /* Core generator pipeline for shapes - If you'd like to make a custom draw procedure, this may either be directly used, or - should be straight forward to make an augmented derivative for a specific codepath. + If you'd like to make a custom draw procedure, this can either be used directly or + modified to create an augmented derivative for a specific code path. This procedure has no awareness of layers. That should be handled by a higher-order codepath. For this level of codepaths what matters is maximizing memory locality for: @@ -348,7 +348,7 @@ generate_shape_draw_list :: proc( draw_list : ^Draw_List, shape : Shaped_Text, oversized := & glyph_buffer.oversized to_cache := & glyph_buffer.to_cache cached := & glyph_buffer.cached - non_zero_resize_soa(glyph_pack, len(shape.glyphs)) + resize_soa_non_zero(glyph_pack, len(shape.glyphs)) append_sub_pack :: #force_inline proc ( pack : ^[dynamic]i32, entry : i32 ) { @@ -754,12 +754,10 @@ batch_generate_glyphs_draw_list :: proc ( draw_list : ^Draw_List, ) } - profile_begin("generate_cached_draw_list: to_cache") - if enable_debug_vis_tyeps { - colour.r = 1.0 - colour.g = 1.0 - colour.b = 1.0 - } + profile_begin("generate_cached_draw_list: cached") + colour.r = max(colour.r, 1.0 * enable_debug_vis_type) + colour.g = max(colour.g, 1.0 * enable_debug_vis_type) + colour.b = max(colour.b, 1.0 * enable_debug_vis_type) generate_cached_draw_list( draw_list, glyph_pack[:], cached, colour ) profile_end() @@ -769,11 +767,9 @@ batch_generate_glyphs_draw_list :: proc ( draw_list : ^Draw_List, profile_end() profile_begin("generate_cached_draw_list: to_cache") - if enable_debug_vis_tyeps { - colour.r = 0.80 - colour.g = 0.25 - colour.b = 0.25 - } + colour.r = max(colour.r, 0.80 * enable_debug_vis_type) + colour.g = max(colour.g, 0.25 * enable_debug_vis_type) + colour.b = max(colour.b, 0.25 * enable_debug_vis_type) generate_cached_draw_list( draw_list, glyph_pack[:], to_cache, colour ) profile_end() } diff --git a/code/font/vefontcache/pkg_mapping.odin b/code/font/vefontcache/pkg_mapping.odin index 111b211..5b20913 100644 --- a/code/font/vefontcache/pkg_mapping.odin +++ b/code/font/vefontcache/pkg_mapping.odin @@ -1,6 +1,7 @@ package vetext import "base:builtin" + resize_soa_non_zero :: non_zero_resize_soa import "base:runtime" import "core:hash" ginger16 :: hash.ginger16 @@ -105,11 +106,6 @@ peek :: proc { peek_array, } -pop_array :: proc { - builtin.pop, - // pop_safe, -} - resize :: proc { builtin.resize_dynamic_array, } diff --git a/code/font/vefontcache/vefontcache.odin b/code/font/vefontcache/vefontcache.odin index 04a7f1a..bbe423f 100644 --- a/code/font/vefontcache/vefontcache.odin +++ b/code/font/vefontcache/vefontcache.odin @@ -37,10 +37,10 @@ Entry_Default :: Entry { } // Ease of use encapsulation of common fields for a canvas space -Camera :: struct { - view : [dynamic]Vec2, - position : [dynamic]Vec2, - zoom : [dynamic]f32, +VPZ_Transform :: struct { + view : Vec2, + position : Vec2, + zoom : f32, } Scope_Stack :: struct { @@ -539,63 +539,74 @@ Used with snap_to_view_extent to enforce position snapping. Position: Used with a draw procedure that uses relative positioning will offset the incoming position by the given amount. Scale : Used with a draw procedure that uses relative scaling, will scale the procedures incoming scale by the given amount. Zoom : Used with a draw procedure that uses scaling via zoom, will scale the procedure's incoming font size & scale based on an 'canvas' camera's notion of it. - -The pkg_mapping.odin provides an explicit set of overloads for these: -scope() -push() -pop() */ -@(deferred_none = pop_font) -scope_font :: #force_inline proc( ctx : ^Context, font : Font_ID ) { assert(ctx != nil); append(& ctx.stack.font, font ) } -push_font :: #force_inline proc( ctx : ^Context, font : Font_ID ) { assert(ctx != nil); append(& ctx.stack.font, font ) } -pop_font :: #force_inline proc( ctx : ^Context, font : Font_ID ) { assert(ctx != nil); pop_array(& ctx.stack.font) } +@(deferred_in = auto_pop_font) +scope_font :: #force_inline proc( ctx : ^Context, font : Font_ID ) { assert(ctx != nil); append(& ctx.stack.font, font ) } +push_font :: #force_inline proc( ctx : ^Context, font : Font_ID ) { assert(ctx != nil); append(& ctx.stack.font, font ) } +pop_font :: #force_inline proc( ctx : ^Context ) { assert(ctx != nil); pop(& ctx.stack.font) } +auto_pop_font :: #force_inline proc( ctx : ^Context, font : Font_ID ) { assert(ctx != nil); pop(& ctx.stack.font) } -@(deferred_none = pop_font_size) -scope_font_size :: #force_inline proc( ctx : ^Context, px_size : f32 ) { assert(ctx != nil); append(& ctx.stack.font_size, px_size) } -push_font_size :: #force_inline proc( ctx : ^Context, px_size : f32 ) { assert(ctx != nil); append(& ctx.stack.font_size, px_size) } -pop_font_size :: #force_inline proc( ctx : ^Context, px_size : f32 ) { assert(ctx != nil); pop_array(& ctx.stack.font_size) } +@(deferred_in = auto_pop_font_size) +scope_font_size :: #force_inline proc( ctx : ^Context, px_size : f32 ) { assert(ctx != nil); append(& ctx.stack.font_size, px_size) } +push_font_size :: #force_inline proc( ctx : ^Context, px_size : f32 ) { assert(ctx != nil); append(& ctx.stack.font_size, px_size) } +pop_font_size :: #force_inline proc( ctx : ^Context ) { assert(ctx != nil); pop(& ctx.stack.font_size) } +auto_pop_font_size :: #force_inline proc( ctx : ^Context, px_size : f32 ) { assert(ctx != nil); pop(& ctx.stack.font_size) } -@(deferred_none = pop_colour ) -scope_colour :: #force_inline proc( ctx : ^Context, colour : RGBAN ) { assert(ctx != nil); append(& ctx.stack.colour, colour) } -push_colour :: #force_inline proc( ctx : ^Context, colour : RGBAN ) { assert(ctx != nil); append(& ctx.stack.colour, colour) } -pop_colour :: #force_inline proc( ctx : ^Context ) { assert(ctx != nil); pop_array(& ctx.stack.colour) } +@(deferred_in = auto_pop_colour ) +scope_colour :: #force_inline proc( ctx : ^Context, colour : RGBAN ) { assert(ctx != nil); append(& ctx.stack.colour, colour) } +push_colour :: #force_inline proc( ctx : ^Context, colour : RGBAN ) { assert(ctx != nil); append(& ctx.stack.colour, colour) } +pop_colour :: #force_inline proc( ctx : ^Context ) { assert(ctx != nil); pop(& ctx.stack.colour) } +auto_pop_colour :: #force_inline proc( ctx : ^Context, colour : RGBAN ) { assert(ctx != nil); pop(& ctx.stack.colour) } -@(deferred_none = pop_view) -scope_view :: #force_inline proc( ctx : ^Context, view : Vec2 ) { assert(ctx != nil); append(& ctx.stack.view, view) } -push_view :: #force_inline proc( ctx : ^Context, view : Vec2 ) { assert(ctx != nil); append(& ctx.stack.view, view) } -pop_view :: #force_inline proc( ctx : ^Context ) { assert(ctx != nil); pop_array(& ctx.stack.view) } +@(deferred_in = auto_pop_view) +scope_view :: #force_inline proc( ctx : ^Context, view : Vec2 ) { assert(ctx != nil); append(& ctx.stack.view, view) } +push_view :: #force_inline proc( ctx : ^Context, view : Vec2 ) { assert(ctx != nil); append(& ctx.stack.view, view) } +pop_view :: #force_inline proc( ctx : ^Context ) { assert(ctx != nil); pop(& ctx.stack.view) } +auto_pop_view :: #force_inline proc( ctx : ^Context, view : Vec2 ) { assert(ctx != nil); pop(& ctx.stack.view) } -@(deferred_none = pop_position) -scope_position :: #force_inline proc( ctx : ^Context, position : Vec2 ) { assert(ctx != nil); append(& ctx.stack.position, position ) } -push_position :: #force_inline proc( ctx : ^Context, position : Vec2 ) { assert(ctx != nil); append(& ctx.stack.position, position ) } -pop_position :: #force_inline proc( ctx : ^Context ) { assert(ctx != nil); pop_array( & ctx.stack.position) } +@(deferred_in = auto_pop_position) +scope_position :: #force_inline proc( ctx : ^Context, position : Vec2 ) { assert(ctx != nil); append(& ctx.stack.position, position ) } +push_position :: #force_inline proc( ctx : ^Context, position : Vec2 ) { assert(ctx != nil); append(& ctx.stack.position, position ) } +pop_position :: #force_inline proc( ctx : ^Context ) { assert(ctx != nil); pop( & ctx.stack.position) } +auto_pop_position :: #force_inline proc( ctx : ^Context, view : Vec2 ) { assert(ctx != nil); pop( & ctx.stack.position) } -@(deferred_none = pop_scale) -scope_scale :: #force_inline proc( ctx : ^Context, scale : Vec2 ) { append(& ctx.stack.scale, scale ) } -push_scale :: #force_inline proc( ctx : ^Context, scale : Vec2 ) { append(& ctx.stack.scale, scale ) } -pop_scale :: #force_inline proc( ctx : ^Context, scale : Vec2 ) { pop_array(& ctx.stack.scale) } +@(deferred_in = auto_pop_scale) +scope_scale :: #force_inline proc( ctx : ^Context, scale : Vec2 ) { assert(ctx != nil); append(& ctx.stack.scale, scale ) } +push_scale :: #force_inline proc( ctx : ^Context, scale : Vec2 ) { assert(ctx != nil); append(& ctx.stack.scale, scale ) } +pop_scale :: #force_inline proc( ctx : ^Context, scale : Vec2 ) { assert(ctx != nil); pop(& ctx.stack.scale) } +auto_pop_scale :: #force_inline proc( ctx : ^Context, scale : Vec2 ) { assert(ctx != nil); pop(& ctx.stack.scale) } -@(deferred_none = pop_zoom ) -scope_zoom :: #force_inline proc( ctx : ^Context, zoom : f32 ) { append(& ctx.stack.zoom, zoom ) } -push_zoom :: #force_inline proc( ctx : ^Context, zoom : f32 ) { append(& ctx.stack.zoom, zoom) } -pop_zoom :: #force_inline proc( ctx : ^Context ) { pop_array(& ctx.stack.zoom) } +@(deferred_in = auto_pop_zoom ) +scope_zoom :: #force_inline proc( ctx : ^Context, zoom : f32 ) { append(& ctx.stack.zoom, zoom ) } +push_zoom :: #force_inline proc( ctx : ^Context, zoom : f32 ) { append(& ctx.stack.zoom, zoom) } +pop_zoom :: #force_inline proc( ctx : ^Context ) { pop(& ctx.stack.zoom) } +auto_pop_zoom :: #force_inline proc( ctx : ^Context, zoom : f32 ) { pop(& ctx.stack.zoom) } -@(deferred_none = pop_camera) -scope_camera :: #force_inline proc( ctx : ^Context, camera : Camera ) { +@(deferred_in = auto_pop_vpz) +scope_vpz :: #force_inline proc( ctx : ^Context, camera : VPZ_Transform ) { + assert(ctx != nil) append(& ctx.stack.view, camera.view ) append(& ctx.stack.position, camera.position ) append(& ctx.stack.zoom, camera.zoom ) } -push_camera :: #force_inline proc( ctx : ^Context, camera : Camera ) { +push_vpz :: #force_inline proc( ctx : ^Context, camera : VPZ_Transform ) { + assert(ctx != nil) append(& ctx.stack.view, camera.view ) append(& ctx.stack.position, camera.position ) append(& ctx.stack.zoom, camera.zoom ) } -pop_camera :: #force_inline proc( ctx : ^Context ) { - pop_array(& ctx.stack.view ) - pop_array(& ctx.stack.position) - pop_array(& ctx.stack.zoom ) +pop_vpz :: #force_inline proc( ctx : ^Context ) { + assert(ctx != nil) + pop(& ctx.stack.view ) + pop(& ctx.stack.position) + pop(& ctx.stack.zoom ) +} +auto_pop_vpz :: #force_inline proc( ctx : ^Context, camera : VPZ_Transform ) { + assert(ctx != nil) + pop(& ctx.stack.view ) + pop(& ctx.stack.position) + pop(& ctx.stack.zoom ) } //#endregion("scoping") @@ -644,7 +655,7 @@ draw_text_shape_normalized_space :: #force_inline proc( ctx : ^Context, assert( ctx != nil ) assert( font >= 0 && int(font) < len(ctx.entries) ) - adjusted_position := get_snapped_position( ctx, position ) + adjusted_position := get_snapped_position( ctx^, position ) entry := ctx.entries[ font ] @@ -658,6 +669,7 @@ draw_text_shape_normalized_space :: #force_inline proc( ctx : ^Context, font_scale_upscale := parser_scale( entry.parser_info, px_upscale ) ctx.cursor_pos = generate_shape_draw_list( & ctx.draw_list, shape, & ctx.atlas, & ctx.glyph_buffer, ctx.px_scalar, + ctx.enable_draw_type_visualization, adjusted_colour, entry, px_upscale, @@ -690,7 +702,7 @@ draw_text_normalized_space :: #force_inline proc( ctx : ^Context, ctx.cursor_pos = {} entry := ctx.entries[ font ] - adjusted_position := get_snapped_position( ctx, position ) + adjusted_position := get_snapped_position( ctx^, position ) colour := ctx.colour colour.a = 1.0 + ctx.alpha_sharpen @@ -698,7 +710,7 @@ draw_text_normalized_space :: #force_inline proc( ctx : ^Context, // Does nothing when px_scalar is 1.0 target_px_size := px_size * ctx.px_scalar target_scale := scale * (1 / ctx.px_scalar) - target_font_scale := parser_scale( entry.parser_info, px_upscale ) + target_font_scale := parser_scale( entry.parser_info, target_px_size ) shape := shaper_shape_text_cached( text_utf8, & ctx.shaper_ctx, & ctx.shape_cache, font, @@ -708,6 +720,7 @@ draw_text_normalized_space :: #force_inline proc( ctx : ^Context, shaper_shape_text_uncached_advanced ) ctx.cursor_pos = generate_shape_draw_list( & ctx.draw_list, shape, & ctx.atlas, & ctx.glyph_buffer, ctx.px_scalar, + ctx.enable_draw_type_visualization, colour, entry, target_px_size, @@ -734,7 +747,7 @@ Text_Layer_Elem :: struct { font : Font_ID, px_size : f32, zoom : f32, - colour : Colour, + colour : RGBAN, } // Batch a layer of text. Use get_draw_list_layer to process the layer immediately after. @@ -742,41 +755,59 @@ draw_text_layer :: #force_inline proc( ctx : ^Context, layer : []Text_Layer_Elem { profile(#procedure) assert( ctx != nil ) - assert( font >= 0 && int(font) < len(ctx.entries) ) - assert( len(texts) > 0 ) + assert( len(layer) > 0 ) for elem in layer { - entry := ctx.entries[ elem.font ] + assert( elem.font >= 0 && int(elem.font) < len(ctx.entries) ) - ctx.cursor_pos = {} - - adjusted_position := get_snapped_position( ctx, position ) - - colour := ctx.colour - colour.a = 1.0 + ctx.alpha_sharpen - - font_scale := parser_scale( entry.parser_info, px_size ) - - px_upscale := px_size * ctx.px_scalar - downscale := scale * (1 / ctx.px_scalar) - font_scale_upscale := parser_scale( entry.parser_info, px_upscale ) - - shapes := make( []Shaped_Text, len(texts) ) - for str, id in texts + shapes := make( []Shaped_Text, len(layer) ) + for elem, id in layer { - assert( len(str) > 0 ) - shape := shaper_shape_text_cached( str, & ctx.shaper_ctx, & ctx.shape_cache, - font, + entry := ctx.entries[ elem.font ] + + ctx.cursor_pos = {} + + // colour := ctx.colour + // colour.a = 1.0 + ctx.alpha_sharpen + + // adjusted_position := get_snapped_position( ctx^, elem.position ) + + // font_scale := parser_scale( entry.parser_info, elem.px_size ) + + target_px_size := elem.px_size * ctx.px_scalar + // target_scale := elem.scale * (1 / ctx.px_scalar) + target_font_scale := parser_scale( entry.parser_info, target_px_size ) + + assert( len(elem.text) > 0 ) + shape := shaper_shape_text_cached( elem.text, & ctx.shaper_ctx, & ctx.shape_cache, + elem.font, entry, - px_upscale, - font_scale_upscale, + target_px_size, + target_font_scale, shaper_shape_text_uncached_advanced ) shapes[id] = shape } - generate_shapes_draw_list(ctx, font, colour, entry, px_upscale, font_scale_upscale, position, downscale, shapes ) + for elem, id in layer { + entry := ctx.entries[ elem.font ] + + ctx.cursor_pos = {} + + colour := ctx.colour + colour.a = 1.0 + ctx.alpha_sharpen + + adjusted_position := get_snapped_position( ctx^, elem.position ) + + // font_scale := parser_scale( entry.parser_info, elem.px_size ) + + target_px_size := elem.px_size * ctx.px_scalar + target_scale := elem.scale * (1 / ctx.px_scalar) + target_font_scale := parser_scale( entry.parser_info, target_px_size ) + + generate_shapes_draw_list(ctx, elem.font, elem.colour, entry, target_px_size, target_font_scale, adjusted_position, target_scale, shapes ) + } } } @@ -803,6 +834,7 @@ flush_draw_list :: #force_inline proc( ctx : ^Context ) { ctx.draw_layer.calls_offset = 0 } + flush_draw_list_layer :: #force_inline proc( ctx : ^Context ) { assert( ctx != nil ) ctx.draw_layer.vertices_offset = len(ctx.draw_list.vertices) diff --git a/code/sectr/engine/client_api.odin b/code/sectr/engine/client_api.odin index ea4c00d..c691df3 100644 --- a/code/sectr/engine/client_api.odin +++ b/code/sectr/engine/client_api.odin @@ -356,7 +356,7 @@ startup :: proc( prof : ^SpallProfiler, persistent_mem, frame_mem, transient_mem // debug.path_lorem = str_fmt("C:/projects/SectrPrototype/examples/Lorem Ipsum (197).txt", allocator = persistent_slab_allocator()) // debug.path_lorem = str_fmt("C:/projects/SectrPrototype/examples/Lorem Ipsum (1022).txt", allocator = persistent_slab_allocator()) - // debug.path_lorem = str_fmt("C:/projects/SectrPrototype/examples/sokol_gp.h", allocator = persistent_slab_allocator()) + debug.path_lorem = str_fmt("C:/projects/SectrPrototype/examples/sokol_gp.h", allocator = persistent_slab_allocator()) // debug.path_lorem = str_fmt("C:/projects/SectrPrototype/examples/ve_fontcache.h", allocator = persistent_slab_allocator()) alloc_error : AllocatorError; success : bool diff --git a/code/sectr/engine/render.odin b/code/sectr/engine/render.odin index 4d42095..16f93a8 100644 --- a/code/sectr/engine/render.odin +++ b/code/sectr/engine/render.odin @@ -927,7 +927,7 @@ draw_text_string_pos_norm :: #force_inline proc( text : string, id : FontID, fon // ve.set_px_scalar( & font_provider_ctx.ve_ctx, config.font_size_screen_scalar ) ve.set_colour( & font_provider_ctx.ve_ctx, color_norm ) - ve.draw_text( & font_provider_ctx.ve_ctx, ve_id, f32(resolved_size), pos, draw_scale, text ) + ve.draw_text_normalized_space( & font_provider_ctx.ve_ctx, ve_id, f32(resolved_size), color_norm, {}, pos, draw_scale, 1.0, text ) return } @@ -957,7 +957,7 @@ draw_text_shape_pos_norm :: #force_inline proc( shape : ShapedText, id : FontID, // ve.set_px_scalar( & font_provider_ctx.ve_ctx, config.font_size_screen_scalar ) ve.set_colour( & font_provider_ctx.ve_ctx, color_norm ) - ve.draw_text_shape( & font_provider_ctx.ve_ctx, ve_id, f32(resolved_size), pos, screen_size_norm * scale, shape ) + ve.draw_text_shape_normalized_space( & font_provider_ctx.ve_ctx, ve_id, f32(resolved_size), color_norm, {}, pos, screen_size_norm * scale, 1.0, shape ) return } @@ -998,7 +998,16 @@ draw_text_string_pos_extent_zoomed :: #force_inline proc( text : string, id : Fo color_norm := normalize_rgba8(color) ve.set_colour( & get_state().font_provider_ctx.ve_ctx, color_norm ) - ve.draw_text( & get_state().font_provider_ctx.ve_ctx, ve_id, f32(resolved_size), normalized_pos, text_scale, text ) + ve.draw_text_normalized_space( & get_state().font_provider_ctx.ve_ctx, + ve_id, + f32(resolved_size), + color_norm, + {}, + normalized_pos, + text_scale, + 1.0, + text + ) } draw_text_shape_pos_extent_zoomed :: #force_inline proc( shape : ShapedText, id : FontID, size : f32, pos, cam_offset, screen_size, screen_size_norm : Vec2, zoom : f32, color := Color_White ) @@ -1009,7 +1018,7 @@ draw_text_shape_pos_extent_zoomed :: #force_inline proc( shape : ShapedText, id zoom_adjust_size := size * zoom // Over-sample font-size for any render under a camera - over_sample : f32 = f32(state.config.font_size_canvas_scalar) + over_sample : f32 = f32(app_config().text_size_canvas_scalar) // zoom_adjust_size *= over_sample pos_offset := (pos + cam_offset) @@ -1034,7 +1043,7 @@ draw_text_shape_pos_extent_zoomed :: #force_inline proc( shape : ShapedText, id color_norm := normalize_rgba8(color) // ve.set_px_scalar( & get_state().font_provider_ctx.ve_ctx, config.font_size_canvas_scalar ) ve.set_colour( & font_provider_ctx.ve_ctx, color_norm ) - ve.draw_text_shape( & font_provider_ctx.ve_ctx, ve_id, f32_resolved_size, normalized_pos, text_scale, shape ) + ve.draw_text_shape_normalized_space( & font_provider_ctx.ve_ctx, ve_id, f32_resolved_size, color_norm, {}, normalized_pos, text_scale, 1.0, shape ) } // TODO(Ed): Eventually the workspace will need a viewport for drawing text diff --git a/scripts/build.ps1 b/scripts/build.ps1 index 5d7a531..c84e564 100644 --- a/scripts/build.ps1 +++ b/scripts/build.ps1 @@ -205,9 +205,9 @@ 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 += $flag_optimize_speed # $build_args += $falg_optimize_aggressive $build_args += $flag_debug $build_args += $flag_pdb_name + $pdb