Began to reduce direct referencing of mutable state struct

This commit is contained in:
Edward R. Gonzalez 2024-12-30 12:22:26 -05:00
parent 9da86c1f4b
commit 57d51fc7b1
8 changed files with 90 additions and 66 deletions

View File

@ -23,7 +23,11 @@ The dependencies are:
* I added support for 'monlithic packages' or 'uniform-across-subdirectories packages'. It allows me to organize the main package with sub-directories.
* Odin repo's base, core, and vendor(raylib) libaries
* An ini parser
* backtrace
* backtrace (not used yet)
* freetype (not used yet)
* harfbuzz
* sokol
* sokol-tools
* Powershell (if you want to use my build scripts)
Major 'codebase modules':

View File

@ -271,11 +271,11 @@ startup :: proc( prof : ^SpallProfiler, persistent_mem, frame_mem, transient_mem
// path_squidgy_slimes := strings.concatenate( { Path_Assets, "Squidgy Slimes.ttf" } )
// font_squidgy_slimes = font_load( path_squidgy_slimes, 32.0, "Squidgy_Slime" )
// path_firacode := strings.concatenate( { Path_Assets, "FiraCode-Regular.ttf" } )
// font_firacode = font_load( path_firacode, 16.0, "FiraCode" )
path_fira_cousine := strings.concatenate( { Path_Assets, "FiraCousine-Regular.ttf" } )
font_fira_cousine = font_load( path_fira_cousine, 16.0, "Fira Cousine" )
path_firacode := strings.concatenate( { Path_Assets, "FiraCode-Regular.ttf" } )
font_firacode = font_load( path_firacode, 16.0, "FiraCode" )
// path_fira_cousine := strings.concatenate( { Path_Assets, "FiraCousine-Regular.ttf" } )
// font_fira_cousine = font_load( path_fira_cousine, 16.0, "Fira Cousine" )
// path_open_sans := strings.concatenate( { Path_Assets, "OpenSans-Regular.ttf" } )
// font_open_sans = font_load( path_open_sans, 16.0, "OpenSans" )
@ -298,7 +298,7 @@ startup :: proc( prof : ^SpallProfiler, persistent_mem, frame_mem, transient_mem
// path_arial_unicode_ms := strings.concatenate( { Path_Assets, "Arial Unicode MS.ttf" } )
// font_arial_unicode_ms = font_load( path_arial_unicode_ms, 16.0, "Arial_Unicode_MS" )
default_font = font_fira_cousine
default_font = font_firacode
log( "Default font loaded" )
}
@ -319,7 +319,7 @@ startup :: proc( prof : ^SpallProfiler, persistent_mem, frame_mem, transient_mem
}
// Demo project setup
// TODO(Ed): This will eventually have to occur when the user either creates or loads a workspace. I don't know
// TODO(Ed): This will eventually have to occur when the user either creates or loads a workspace.
if true
{
profile("project setup")
@ -499,21 +499,17 @@ tick :: proc( host_delta_time_ms : f64, host_delta_ns : Duration ) -> b32
// Lifted out of tick so that sokol_app_frame_callback can do it as well.
tick_work_frame :: #force_inline proc( host_delta_time_ms : f64 ) -> b32
{
context.logger = to_odin_logger( & Memory_App.logger )
state := get_state(); using state
profile("Work frame")
context.logger = to_odin_logger( & Memory_App.logger )
should_close : b32
// Setup Frame Slab
{
alloc_error : AllocatorError
frame_slab, alloc_error = slab_init( & default_slab_policy, bucket_reserve_num = 0,
allocator = frame_allocator(),
dbg_name = Frame_Slab_DBG_Name,
should_zero_buckets = true )
verify( alloc_error == .None, "Failed to allocate frame slab" )
}
alloc_error : AllocatorError
get_state().frame_slab, alloc_error = slab_init( & get_state().default_slab_policy, bucket_reserve_num = 0,
allocator = frame_allocator(),
dbg_name = Frame_Slab_DBG_Name,
should_zero_buckets = true )
verify( alloc_error == .None, "Failed to allocate frame slab" )
// The policy for the work tick is that the default allocator is the frame's slab.
// Transient's is the temp allocator.
@ -522,6 +518,9 @@ tick_work_frame :: #force_inline proc( host_delta_time_ms : f64 ) -> b32
// rl.PollInputEvents()
config := app_config()
debug := & get_state().debug
debug.draw_ui_box_bounds_points = false
debug.draw_ui_padding_bounds = false
debug.draw_ui_content_bounds = false
@ -535,7 +534,7 @@ tick_work_frame :: #force_inline proc( host_delta_time_ms : f64 ) -> b32
sokol_width := sokol_app.widthf()
sokol_height := sokol_app.heightf()
window := & state.app_window
window := & get_state().app_window
// if int(window.extent.x) != int(sokol_width) || int(window.extent.y) != int(sokol_height) {
window.resized = true
window.extent.x = sokol_width * 0.5
@ -554,23 +553,24 @@ tick_work_frame :: #force_inline proc( host_delta_time_ms : f64 ) -> b32
tick_frametime :: #force_inline proc( client_tick : ^time.Tick, host_delta_time_ms : f64, host_delta_ns : Duration, can_sleep := true )
{
profile(#procedure)
state := get_state(); using state
config := app_config()
frametime := & get_state().frametime
context.allocator = frame_slab_allocator()
context.temp_allocator = transient_allocator()
// profile("Client tick timing processing")
frametime_target_ms = 1.0 / f64(config.engine_refresh_hz) * S_To_MS
sub_ms_granularity_required := frametime_target_ms <= Frametime_High_Perf_Threshold_MS
frametime.target_ms = 1.0 / f64(config.engine_refresh_hz) * S_To_MS
sub_ms_granularity_required := frametime.target_ms <= Frametime_High_Perf_Threshold_MS
frametime_delta_ns = time.tick_lap_time( client_tick )
frametime_delta_ms = duration_ms( frametime_delta_ns )
frametime_delta_seconds = duration_seconds( host_delta_ns )
frametime_elapsed_ms = frametime_delta_ms + host_delta_time_ms
frametime.delta_ns = time.tick_lap_time( client_tick )
frametime.delta_ms = duration_ms( frametime.delta_ns )
frametime.delta_seconds = duration_seconds( host_delta_ns )
frametime.elapsed_ms = frametime.delta_ms + host_delta_time_ms
if frametime_elapsed_ms < frametime_target_ms
if frametime.elapsed_ms < frametime.target_ms
{
sleep_ms := frametime_target_ms - frametime_elapsed_ms
sleep_ms := frametime.target_ms - frametime.elapsed_ms
pre_sleep_tick := time.tick_now()
if can_sleep && sleep_ms > 0 {
@ -585,24 +585,24 @@ tick_frametime :: #force_inline proc( client_tick : ^time.Tick, host_delta_time_
// log( str_fmt_tmp("frametime sleep was off by: %v ms", sleep_delta_ms - sleep_ms ))
}
frametime_elapsed_ms += sleep_delta_ms
for ; frametime_elapsed_ms < frametime_target_ms; {
frametime.elapsed_ms += sleep_delta_ms
for ; frametime.elapsed_ms < frametime.target_ms; {
sleep_delta_ns = time.tick_lap_time( & pre_sleep_tick)
sleep_delta_ms = duration_ms( sleep_delta_ns )
frametime_elapsed_ms += sleep_delta_ms
frametime.elapsed_ms += sleep_delta_ms
}
}
config.timing_fps_moving_avg_alpha = 0.99
frametime_avg_ms = mov_avg_exp( f64(config.timing_fps_moving_avg_alpha), frametime_elapsed_ms, frametime_avg_ms )
fps_avg = 1 / (frametime_avg_ms * MS_To_S)
frametime.avg_ms = mov_avg_exp( f64(config.timing_fps_moving_avg_alpha), frametime.elapsed_ms, frametime.avg_ms )
frametime.fps_avg = 1 / (frametime.avg_ms * MS_To_S)
if frametime_elapsed_ms > 60.0 {
log( str_fmt("Big tick! %v ms", frametime_elapsed_ms), LogLevel.Warning )
if frametime.elapsed_ms > 60.0 {
log( str_fmt("Big tick! %v ms", frametime.elapsed_ms), LogLevel.Warning )
}
frame += 1
frametime.current_frame += 1
}
@export

View File

@ -17,8 +17,8 @@ sokol_app_init_callback :: proc "c" () {
// So this will only get called during window pan or resize events (on Win32 at least)
sokol_app_frame_callback :: proc "c" ()
{
context = get_state().sokol_context
profile(#procedure)
context = get_state().sokol_context
state := get_state()
should_close : b32
@ -99,14 +99,13 @@ sokol_app_log_callback :: proc "c" (
// TODO(Ed): Does this need to be queued to a separate thread?
sokol_app_event_callback :: proc "c" (sokol_event : ^sokol_app.Event)
{
state := get_state(); using state
context = sokol_context
context = get_state().sokol_context
event : InputEvent
using event
_sokol_frame_id = sokol_event.frame_count
frame_id = frame
frame_id = get_frametime().current_frame
mouse.pos = { sokol_event.mouse_x, sokol_event.mouse_y }
mouse.delta = { sokol_event.mouse_dx, sokol_event.mouse_dy }

View File

@ -22,7 +22,7 @@ RenderState :: struct {
render :: proc()
{
profile(#procedure)
state := get_state(); using state // TODO(Ed): Prefer passing static context to through the callstack
state := get_state(); using state // TODO(Ed): Remove mutable access to to entire state.
screen_extent := app_window.extent
screen_size := app_window.extent * 2
@ -152,7 +152,7 @@ render_mode_screenspace :: proc( screen_extent : Extents2, screen_ui : ^UI_State
debug_draw_text :: proc( content : string, pos : Vec2, size : f32, color := Color_White, font : FontID = Font_Default )
{
state := get_state(); using state
state := get_state(); using state // TODO(Ed): Remove this state getter. Get default font properly.
if len( content ) == 0 do return
font := font
@ -187,11 +187,12 @@ render_mode_screenspace :: proc( screen_extent : Extents2, screen_ui : ^UI_State
}
if true {
frametime := get_frametime()
debug_text( "Screen Width : %v", screen_size.x )
debug_text( "Screen Height: %v", screen_size.y )
debug_text( "frametime_target_ms : %f ms", frametime_target_ms )
debug_text( "frametime (work) : %0.3f ms", frametime_delta_ms )
debug_text( "frametime_last_elapsed_ms : %f ms", frametime_elapsed_ms )
debug_text( "frametime_target_ms : %f ms", frametime.target_ms )
debug_text( "frametime (work) : %0.3f ms", frametime.delta_ms )
debug_text( "frametime_last_elapsed_ms : %f ms", frametime.elapsed_ms )
}
if replay.mode == ReplayMode.Record {
debug_text( "Recording Input")
@ -450,6 +451,7 @@ render_text_layer :: proc( screen_extent : Vec2, ve_ctx : ^ve.Context, render :
render_ui_via_box_tree :: proc( ui : ^UI_State, screen_extent : Vec2, ve_ctx : ^ve.Context, ve_render : VE_RenderData, cam : ^Camera = nil )
{
// TODO(Ed): Make a debug getter.
debug := get_state().debug
default_font := get_state().default_font
@ -801,8 +803,6 @@ draw_text_string_pos_norm :: proc( content : string, id : FontID, size : f32, po
width := app_window.extent.x * 2
height := app_window.extent.y * 2
// TODO(Ed): Review doing double scaling on the text...
ve_id, resolved_size := font_provider_resolve_draw_id( id, size * config.font_size_screen_scalar )
color_norm := normalize_rgba8(color)
@ -825,7 +825,7 @@ draw_text_string_pos_extent :: proc( content : string, id : FontID, size : f32,
draw_text_string_pos_extent_zoomed :: proc( content : string, id : FontID, size : f32, pos : Vec2, cam : Camera, color := Color_White )
{
profile(#procedure)
state := get_state(); using state
state := get_state(); using state // TODO(Ed): Remove usage of direct access to entire mutable state.
cam_offset := Vec2 {
cam.position.x,
@ -871,6 +871,7 @@ draw_text_string_pos_extent_zoomed :: proc( content : string, id : FontID, size
render_flush_gp :: #force_inline proc()
{
profile(#procedure)
// TODO(Ed): Perfer a non-mutable get to the pass.
gfx.begin_pass( gfx.Pass { action = get_state().render_data.pass_actions.empty_action, swapchain = sokol_glue.swapchain() })
gp.flush()
gfx.end_pass()

View File

@ -56,14 +56,11 @@ poll_debug_actions :: proc( actions : ^ DebugActions, input : ^ InputState )
cam_mouse_pan = mouse.right.ended_down && ! pressed(mouse.right)
}
frametime_delta32 :: #force_inline proc "contextless" () -> f32 {
return cast(f32) get_state().frametime_avg_ms
}
//TODO(Ed): Just use avg delta not this.
update :: proc( delta_time : f64 ) -> b32
{
profile(#procedure)
// TODO(Ed): Remove usage of mutable reference to state here.
state := get_state(); using state
replay := & Memory_App.replay
workspace := & project.workspace
@ -259,7 +256,7 @@ update :: proc( delta_time : f64 ) -> b32
if zoom_delta != 0 {
current_index := find_closest_zoom_index(cam.zoom, Digial_Zoom_Snap_Levels)
scroll_speed := max(1, abs(zoom_delta) * config.cam_zoom_scroll_delta_scale) // Adjust this factor to control sensitivity
scroll_speed := max( cast(f32) 1, abs(zoom_delta) * config.cam_zoom_scroll_delta_scale) // Adjust this factor to control sensitivity
target_index := current_index
if zoom_delta > 0 {

View File

@ -428,9 +428,17 @@ make :: proc {
make_multi_pointer,
}
// measure_text_size :: proc {
// measure_text_size_raylib,
// }
max :: proc {
linalg.max_single,
linalg.max_double,
linalg.max_triple,
}
min :: proc {
linalg.min_single,
linalg.min_double,
linalg.min_triple,
}
mov_avg_exp :: proc {
mov_avg_exp_f32,

View File

@ -285,3 +285,19 @@ poll_input_events :: proc( input, prev_input : ^InputState, input_events : Input
prev_frame = last_frame
}
input_event_iter :: #force_inline proc () -> RingBufferFixedIterator(InputEvent) {
return iterator_ringbuf_fixed( & get_state().input_events.events )
}
input_key_event_iter :: #force_inline proc() -> RingBufferFixedIterator(InputKeyEvent) {
return iterator_ringbuf_fixed( & get_state().input_events.key_events )
}
input_mouse_event_iter :: #force_inline proc() -> RingBufferFixedIterator(InputMouseEvent) {
return iterator_ringbuf_fixed( & get_state().input_events.mouse_events )
}
input_codes_pressed_slice :: #force_inline proc() -> []rune {
return to_slice( get_state().input_events.codes_pressed )
}

View File

@ -587,10 +587,9 @@ ui_text_input_box :: proc( text_input_box : ^UI_TextInputBox, label : string,
policy : UI_TextInput_Policy = {}
)
{
state := get_state()
// state := get_state()
iter_next :: next
input := state.input
input_events := & get_state().input_events
input := get_input_state()
ui := ui_context()
text_input_box.box = ui_box_make( flags, label )
@ -621,7 +620,7 @@ ui_text_input_box :: proc( text_input_box : ^UI_TextInputBox, label : string,
// TODO(Ed): Abstract this to navigation bindings
if btn_pressed(input.keyboard.left) {
editor_cursor_pos.x = max(0, editor_cursor_pos.x - 1)
editor_cursor_pos.x = max(editor_cursor_pos.x - 1, 0)
}
if btn_pressed(input.keyboard.right) {
editor_cursor_pos.x = min(i32(input_str.num), editor_cursor_pos.x + 1)
@ -638,14 +637,14 @@ ui_text_input_box :: proc( text_input_box : ^UI_TextInputBox, label : string,
// screen_ui.active = 0
// }
iter_obj := iterator( & input_events.key_events ); iter := & iter_obj
iter_obj := input_key_event_iter(); iter := & iter_obj
for event := iter_next( iter ); event != nil; event = iter_next( iter )
{
if event.frame_id != state.frame do break
if event.frame_id != get_frametime().current_frame do break
if event.key == .backspace && event.type == .Key_Pressed {
if input_str.num > 0 {
editor_cursor_pos.x = max(0, editor_cursor_pos.x - 1)
editor_cursor_pos.x = max(editor_cursor_pos.x - 1, 0)
remove_at( input_str, u64(editor_cursor_pos.x) )
break
}
@ -657,7 +656,7 @@ ui_text_input_box :: proc( text_input_box : ^UI_TextInputBox, label : string,
}
decimal_detected := false
for code in to_slice(input_events.codes_pressed)
for code in input_codes_pressed_slice()
{
accept_digits := ! digits_only || '0' <= code && code <= '9'
accept_decimal := ! disallow_decimal || ! decimal_detected && code =='.'
@ -680,7 +679,7 @@ ui_text_input_box :: proc( text_input_box : ^UI_TextInputBox, label : string,
continue
}
}
clear( input_events.codes_pressed )
clear( get_state().input_events.codes_pressed )
invalid_color := RGBA8 { 70, 40, 40, 255}