package sectr import "base:runtime" import "core:fmt" import "core:mem" import "core:mem/virtual" import "core:os" import rl "vendor:raylib" Memory_App : Memory Memory_Base_Address_Persistent :: Terabyte * 1 Memory_Base_Address_Frame :: Memory_Base_Address_Persistent + Memory_Reserve_Persistent * 2 Memory_Base_Address_Transient :: Memory_Base_Address_Frame + Memory_Reserve_Frame * 2 Memory_Base_Address_Files_Buffer :: Memory_Base_Address_Transient + Memory_Reserve_Transient * 2 // This reserve goes beyond the typical amount of ram the user has, // TODO(Ed): Setup warnings when the amount is heading toward half the ram size Memory_Reserve_Persistent :: 32 * Gigabyte Memory_Reserve_Frame :: 16 * Gigabyte Memory_Reserve_Transient :: 16 * Gigabyte Memory_Reserve_FilesBuffer :: 64 * Gigabyte Memory_Commit_Initial_Persistent :: 4 * Kilobyte Memory_Commit_Initial_Frame :: 4 * Kilobyte Memory_Commit_Initial_Transient :: 4 * Kilobyte Memory_Commit_Initial_Filebuffer :: 4 * Kilobyte MemorySnapshot :: struct { persistent : []u8, frame : []u8, transient : []u8, // files_buffer cannot be restored from snapshot } Memory :: struct { persistent : ^VArena, frame : ^VArena, transient : ^VArena, files_buffer : ^VArena, // Should only be used for small memory allocation iterations // Not for large memory env states snapshot : MemorySnapshot, replay : ReplayState, logger : Logger, profiler : ^SpallProfiler } persistent_allocator :: proc() -> Allocator { result := varena_allocator( Memory_App.persistent ) return result } frame_allocator :: proc() -> Allocator { result := varena_allocator( Memory_App.frame ) return result } transient_allocator :: proc() -> Allocator { result := varena_allocator( Memory_App.transient ) return result } files_buffer_allocator :: proc() -> Allocator { result := varena_allocator( Memory_App.files_buffer ) return result } persistent_slab_allocator :: proc() -> Allocator { state := get_state() result := slab_allocator( state.persistent_slab ) return result } frame_slab_allocator :: proc() -> Allocator { result := slab_allocator( get_state().frame_slab ) return result } transient_slab_allocator :: proc() -> Allocator { result := slab_allocator( get_state().transient_slab ) return result } // TODO(Ed) : Implment host memory mapping api save_snapshot :: proc( snapshot : ^MemorySnapshot ) { // Make sure the snapshot size is able to hold the current size of the arenas // Grow the files & mapping otherwise { // TODO(Ed) : Implement eventually } persistent := Memory_App.persistent mem.copy_non_overlapping( & snapshot.persistent[0], persistent.reserve_start, int(persistent.commit_used) ) frame := Memory_App.frame mem.copy_non_overlapping( & snapshot.frame[0], frame.reserve_start, int(frame.commit_used) ) transient := Memory_App.transient mem.copy_non_overlapping( & snapshot.transient[0], transient.reserve_start, int(transient.commit_used) ) } // TODO(Ed) : Implment host memory mapping api load_snapshot :: proc( snapshot : ^MemorySnapshot ) { persistent := Memory_App.persistent mem.copy_non_overlapping( persistent.reserve_start, & snapshot.persistent[0], int(persistent.commit_used) ) frame := Memory_App.frame mem.copy_non_overlapping( frame.reserve_start, & snapshot.frame[0], int(frame.commit_used) ) transient := Memory_App.transient mem.copy_non_overlapping( transient.reserve_start, & snapshot.transient[0], int(transient.commit_used) ) } // TODO(Ed) : Implement usage of this MemoryConfig :: struct { reserve_persistent : uint, reserve_frame : uint, reserve_transient : uint, reserve_filebuffer : uint, commit_initial_persistent : uint, commit_initial_frame : uint, commit_initial_transient : uint, commit_initial_filebuffer : uint, } AppConfig :: struct { using memory : MemoryConfig, resolution_width : uint, resolution_height : uint, refresh_rate : uint, cam_min_zoom : f32, cam_max_zoom : f32, cam_zoom_mode : CameraZoomMode, cam_zoom_smooth_snappiness : f32, cam_zoom_sensitivity_smooth : f32, cam_zoom_sensitivity_digital : f32, engine_refresh_hz : uint, timing_fps_moving_avg_alpha : f32, ui_resize_border_width : f32, } State :: struct { default_slab_policy : SlabPolicy, persistent_slab : Slab, frame_slab : Slab, transient_slab : Slab, // TODO(Ed): This needs to be recreated per transient wipe transinet_clear_lock : b32, // Pravents auto-free of transient at designated intervals transient_clear_time : f32, // Time in seconds for the usual period to clear transient transient_clear_elapsed : f32, // Time since last clear string_cache : StringCache, font_provider_data : FontProviderData, input_data : [2]InputState, input_prev : ^InputState, input : ^InputState, debug : DebugData, project : Project, config : AppConfig, app_window : AppWindow, monitor_id : i32, monitor_refresh_hz : i32, sleep_is_granular : b32, frametime_delta_seconds : f64, frametime_delta_ms : f64, frametime_delta_ns : Duration, frametime_target_ms : f64, frametime_elapsed_ms : f64, frametime_avg_ms : f64, fps_avg : f64, font_firacode : FontID, font_squidgy_slimes : FontID, font_rec_mono_semicasual_reg : FontID, default_font : FontID, // There are two potential UI contextes for this prototype so far, // the screen-space UI and the current workspace UI. // This is used so that the ui api doesn't need to have the user pass the context every single time. ui_context : ^UI_State, } get_state :: proc "contextless" () -> ^ State { return cast( ^ State ) Memory_App.persistent.reserve_start } AppWindow :: struct { extent : Extents2, // Window half-size dpi_scale : f32, // Dots per inch scale (provided by raylib via glfw) ppcm : f32, // Dots per centimetre } // PMDB CodeBase :: struct { placeholder : int, } ProjectConfig :: struct { placeholder : int, } Project :: struct { path : StringCached, name : StringCached, config : ProjectConfig, codebase : CodeBase, // TODO(Ed) : Support multiple workspaces workspace : Workspace, } Frame :: struct { pos : Vec2, size : Vec2, ui : ^UI_Box, } Workspace :: struct { name : StringCached, cam : Camera, zoom_target : f32, frames : Array(Frame), test_frame : Frame, // TODO(Ed) : The workspace is mainly a 'UI' conceptually... ui : UI_State, } DebugData :: struct { square_size : i32, square_pos : rl.Vector2, draw_debug_text_y : f32, cursor_locked : b32, cursor_unlock_pos : Vec2, // Raylib changes the mose position on lock, we want restore the position the user would be in on screen mouse_vis : b32, last_mouse_pos : Vec2, // UI Vis draw_ui_box_bounds_points : bool, draw_ui_margin_bounds : bool, draw_ui_anchor_bounds : bool, draw_UI_padding_bounds : bool, draw_ui_content_bounds : bool, // Test First frame_2_created : b32, // Test Draggable draggable_box_pos : Vec2, draggable_box_size : Vec2, box_original_size : Vec2, // Test parsing path_lorem : string, lorem_content : []byte, lorem_parse : PWS_ParseResult, // Test 3d Viewport cam_vp : rl.Camera3D, viewport_rt : rl.RenderTexture, }