Segregated host/api better. Memory setup is problably solid now.
This commit is contained in:
parent
2f6d3636e1
commit
2e6ca2d0fd
105
code/api.odin
105
code/api.odin
@ -3,7 +3,9 @@ package sectr
|
||||
import "core:dynlib"
|
||||
import "core:fmt"
|
||||
import "core:mem"
|
||||
import "core:mem/virtual"
|
||||
import "core:os"
|
||||
import "core:slice"
|
||||
import "core:strings"
|
||||
import rl "vendor:raylib"
|
||||
|
||||
@ -14,30 +16,60 @@ ModuleAPI :: struct {
|
||||
write_time : os.File_Time,
|
||||
lib_version : i32,
|
||||
|
||||
startup : type_of( startup ),
|
||||
shutdown : type_of( sectr_shutdown),
|
||||
reload : type_of( reload ),
|
||||
update : type_of( update ),
|
||||
render : type_of( render )
|
||||
startup : type_of( startup ),
|
||||
shutdown : type_of( sectr_shutdown),
|
||||
reload : type_of( reload ),
|
||||
update : type_of( update ),
|
||||
render : type_of( render ),
|
||||
clean_temp : type_of( clean_temp ),
|
||||
}
|
||||
|
||||
memory_chunk_size :: 2 * Gigabyte
|
||||
memory_persistent_size :: 128 * Megabyte
|
||||
memory_trans_temp_size :: (memory_chunk_size - memory_persistent_size ) / 2
|
||||
|
||||
Memory :: struct {
|
||||
persistent : ^ mem.Arena,
|
||||
transient : ^ mem.Arena,
|
||||
temp : ^ mem.Arena
|
||||
live : ^ virtual.Arena,
|
||||
snapshot : ^ virtual.Arena,
|
||||
persistent : ^ TrackedAllocator,
|
||||
transient : ^ TrackedAllocator,
|
||||
temp : ^ TrackedAllocator
|
||||
}
|
||||
|
||||
memory : Memory
|
||||
|
||||
@export
|
||||
startup :: proc( persistent, transient, temp : ^ mem.Arena )
|
||||
startup :: proc( live_mem, snapshot_mem : ^ virtual.Arena )
|
||||
{
|
||||
memory.persistent = persistent
|
||||
state := cast(^State) memory.persistent; using state
|
||||
// Setup memory for the first time
|
||||
{
|
||||
Arena :: mem.Arena
|
||||
Tracking_Allocator :: mem.Tracking_Allocator
|
||||
arena_allocator :: mem.arena_allocator
|
||||
arena_init :: mem.arena_init
|
||||
slice_ptr :: mem.slice_ptr
|
||||
|
||||
// Anything allocated by default is considered transient.
|
||||
// context.allocator = mem.arena_allocator( transient )
|
||||
// context.temp_allocator = mem.arena_allocator( temp )
|
||||
arena_size :: size_of( mem.Arena)
|
||||
internals_size :: 4 * Megabyte
|
||||
|
||||
using memory;
|
||||
block := live_mem.curr_block
|
||||
|
||||
persistent_slice := slice_ptr( block.base, memory_persistent_size )
|
||||
transient_slice := slice_ptr( memory_after( persistent_slice), memory_trans_temp_size )
|
||||
temp_slice := slice_ptr( memory_after( transient_slice), memory_trans_temp_size )
|
||||
|
||||
// We assign the beginning of the block to be the host's persistent memory's arena.
|
||||
// Then we offset past the arena and determine its slice to be the amount left after for the size of host's persistent.
|
||||
persistent = tracked_allocator_init_vmem( persistent_slice, internals_size )
|
||||
transient = tracked_allocator_init_vmem( transient_slice, internals_size )
|
||||
temp = tracked_allocator_init_vmem( temp_slice , internals_size )
|
||||
|
||||
// context.allocator = tracked_allocator( transient )
|
||||
// context.temp_allocator = tracked_allocator( temp )
|
||||
}
|
||||
state := new( State, tracked_allocator( memory.persistent ) )
|
||||
using state
|
||||
|
||||
// Rough setup of window with rl stuff
|
||||
screen_width = 1280
|
||||
@ -70,25 +102,35 @@ sectr_shutdown :: proc()
|
||||
if memory.persistent == nil {
|
||||
return
|
||||
}
|
||||
state := cast( ^ State ) memory.persistent
|
||||
state := get_state()
|
||||
rl.UnloadFont( state.font_rec_mono_semicasual_reg )
|
||||
rl.CloseWindow()
|
||||
}
|
||||
|
||||
@export
|
||||
reload :: proc( persistent, transient, temp : ^ mem.Arena )
|
||||
reload :: proc( live_mem, snapshot_mem : ^ virtual.Arena )
|
||||
{
|
||||
memory.persistent = persistent
|
||||
memory.transient = transient
|
||||
memory.temp = temp
|
||||
context.allocator = mem.arena_allocator( transient )
|
||||
context.temp_allocator = mem.arena_allocator( temp )
|
||||
Arena :: mem.Arena
|
||||
Tracking_Allocator :: mem.Tracking_Allocator
|
||||
arena_allocator :: mem.arena_allocator
|
||||
slice_ptr :: mem.slice_ptr
|
||||
|
||||
using memory;
|
||||
block := live_mem.curr_block
|
||||
|
||||
persistent_slice := slice_ptr( block.base, memory_persistent_size )
|
||||
transient_slice := slice_ptr( memory_after( persistent_slice), memory_trans_temp_size )
|
||||
temp_slice := slice_ptr( memory_after( transient_slice), memory_trans_temp_size )
|
||||
|
||||
persistent = cast( ^TrackedAllocator ) & persistent_slice[0]
|
||||
transient = cast( ^TrackedAllocator ) & transient_slice[0]
|
||||
temp = cast( ^TrackedAllocator ) & temp_slice[0]
|
||||
}
|
||||
|
||||
@export
|
||||
update :: proc() -> b32
|
||||
{
|
||||
state := cast( ^ State ) memory.persistent
|
||||
state := get_state(); using state
|
||||
|
||||
should_shutdown : b32 = ! cast(b32) rl.WindowShouldClose()
|
||||
return should_shutdown
|
||||
@ -97,7 +139,7 @@ update :: proc() -> b32
|
||||
@export
|
||||
render :: proc()
|
||||
{
|
||||
state := cast( ^ State ) memory.persistent; using state
|
||||
state := get_state(); using state
|
||||
|
||||
rl.BeginDrawing()
|
||||
rl.ClearBackground( Color_BG )
|
||||
@ -111,7 +153,7 @@ render :: proc()
|
||||
{
|
||||
@static draw_text_scratch : [Kilobyte * 64]u8
|
||||
|
||||
state := cast( ^ State ) memory.persistent; using state
|
||||
state := get_state(); using state
|
||||
if ( draw_debug_text_y > 800 ) {
|
||||
draw_debug_text_y = 50
|
||||
}
|
||||
@ -122,10 +164,21 @@ render :: proc()
|
||||
draw_debug_text_y += 16
|
||||
}
|
||||
|
||||
draw_text( "Monitor : %v", rl.GetMonitorName(0) )
|
||||
// draw_text( "Hot-Reload Count : %v", -1 )
|
||||
|
||||
draw_text( "Screen Width : %v", rl.GetScreenWidth() )
|
||||
draw_text( "Screen Height: %v", rl.GetScreenHeight() )
|
||||
// draw_text( "HOT RELOAD BITCHES" )
|
||||
|
||||
draw_debug_text_y = 50
|
||||
}
|
||||
|
||||
@export
|
||||
clean_temp :: proc()
|
||||
{
|
||||
mem.tracking_allocator_clear( & memory.temp.tracker )
|
||||
}
|
||||
|
||||
get_state :: proc() -> (^ State)
|
||||
{
|
||||
return cast(^ State) raw_data( memory.persistent.backing.data )
|
||||
}
|
||||
|
@ -20,7 +20,17 @@ import "core:time"
|
||||
import rl "vendor:raylib"
|
||||
import sectr "../."
|
||||
|
||||
TrackedAllocator :: sectr.TrackedAllocator
|
||||
tracked_allocator :: sectr.tracked_allocator
|
||||
tracked_allocator_init :: sectr.tracked_allocator_init
|
||||
|
||||
path_snapshot :: "VMemChunk_1.snapshot"
|
||||
when ODIN_OS == runtime.Odin_OS_Type.Windows
|
||||
{
|
||||
path_sectr_module :: "sectr.dll"
|
||||
path_sectr_live_module :: "sectr_live.dll"
|
||||
path_sectr_debug_symbols :: "sectr.pdb"
|
||||
}
|
||||
|
||||
RuntimeState :: struct {
|
||||
running : b32,
|
||||
@ -29,77 +39,46 @@ RuntimeState :: struct {
|
||||
}
|
||||
|
||||
VMemChunk :: struct {
|
||||
sarena : virtual.Arena,
|
||||
host_persistent : ^ mem.Arena,
|
||||
host_transient : ^ mem.Arena,
|
||||
sectr_persistent : ^ mem.Arena,
|
||||
sectr_transient : ^ mem.Arena,
|
||||
sectr_temp : ^ mem.Arena,
|
||||
|
||||
// snapshot :
|
||||
og_allocator : mem.Allocator,
|
||||
og_temp_allocator : mem.Allocator,
|
||||
host_persistent : TrackedAllocator,
|
||||
host_transient : TrackedAllocator,
|
||||
sectr_live : virtual.Arena,
|
||||
sectr_snapshot : virtual.Arena
|
||||
}
|
||||
|
||||
setup_engine_memory :: proc () -> VMemChunk
|
||||
setup_memory :: proc () -> VMemChunk
|
||||
{
|
||||
Arena :: mem.Arena
|
||||
Tracking_Allocator :: mem.Tracking_Allocator
|
||||
memory : VMemChunk; using memory
|
||||
|
||||
Arena :: mem.Arena
|
||||
arena_init :: mem.arena_init
|
||||
ptr_offset :: mem.ptr_offset
|
||||
slice_ptr :: mem.slice_ptr
|
||||
host_persistent_size :: 32 * Megabyte
|
||||
host_transient_size :: 96 * Megabyte
|
||||
internals_size :: 4 * Megabyte
|
||||
|
||||
chunk_size :: 2 * Gigabyte
|
||||
host_persistent = tracked_allocator_init( host_persistent_size, internals_size )
|
||||
host_transient = tracked_allocator_init( host_transient_size, internals_size )
|
||||
|
||||
// Setup the static arena for the entire application
|
||||
if result := virtual.arena_init_static( & sarena, chunk_size, chunk_size );
|
||||
result != runtime.Allocator_Error.None
|
||||
if result := virtual.arena_init_static( & sectr_live, sectr.memory_chunk_size, sectr.memory_chunk_size );
|
||||
result != runtime.Allocator_Error.None
|
||||
{
|
||||
// TODO(Ed) : Setup a proper logging interface
|
||||
fmt. printf( "Failed to allocate memory for the engine" )
|
||||
fmt. printf( "Failed to allocate memory for the sectr module" )
|
||||
runtime.debug_trap()
|
||||
os. exit( -1 )
|
||||
// TODO(Ed) : Figure out the error code enums..
|
||||
}
|
||||
|
||||
arena_size :: size_of( Arena)
|
||||
|
||||
persistent_size :: Megabyte * 128 * 2
|
||||
transient_size :: (chunk_size - persistent_size * 2) / 2
|
||||
host_persistent_size :: persistent_size / 4 - arena_size
|
||||
host_transient_size :: transient_size / 4 - arena_size
|
||||
sectr_persistent_size :: persistent_size - host_persistent_size - arena_size
|
||||
sectr_trans_temp_size :: (transient_size - host_transient_size) / 2 - arena_size
|
||||
|
||||
block := memory.sarena.curr_block
|
||||
|
||||
// We assign the beginning of the block to be the host's persistent memory's arena.
|
||||
// Then we offset past the arena and determine its slice to be the amount left after for the size of host's persistent.
|
||||
host_persistent = cast( ^ Arena ) block.base
|
||||
host_persistent_slice := slice_ptr( ptr_offset( block.base, arena_size), host_persistent_size)
|
||||
arena_init( host_persistent, host_persistent_slice )
|
||||
|
||||
// Initialize a sub-section of our virtual memory as a sub-arena
|
||||
sub_arena_init :: proc( address : ^ byte, size : int ) -> ( ^ Arena) {
|
||||
sub_arena := cast( ^ Arena ) address
|
||||
mem_slice := slice_ptr( ptr_offset( address, arena_size), size )
|
||||
arena_init( sub_arena, mem_slice )
|
||||
return sub_arena
|
||||
}
|
||||
|
||||
// Helper to get the the beginning of memory after a slice
|
||||
next :: proc( slice : []byte ) -> ( ^ byte) {
|
||||
return ptr_offset( & slice[0], len(slice) )
|
||||
}
|
||||
|
||||
host_transient = sub_arena_init( next( host_persistent.data), host_transient_size)
|
||||
sectr_persistent = sub_arena_init( next( host_transient.data), sectr_persistent_size)
|
||||
sectr_transient = sub_arena_init( next( sectr_persistent.data), sectr_trans_temp_size)
|
||||
sectr_temp = sub_arena_init( next( sectr_transient.data), sectr_trans_temp_size)
|
||||
// Reassign default allocators for host
|
||||
memory.og_allocator = context.allocator
|
||||
memory.og_temp_allocator = context.temp_allocator
|
||||
context.allocator = tracked_allocator( & memory.host_persistent )
|
||||
context.temp_allocator = tracked_allocator( & memory.host_transient )
|
||||
return memory;
|
||||
}
|
||||
|
||||
setup_snapshot_memory :: proc ()
|
||||
|
||||
load_sectr_api :: proc ( version_id : i32 ) -> sectr.ModuleAPI
|
||||
{
|
||||
loaded_module : sectr.ModuleAPI
|
||||
@ -112,28 +91,31 @@ load_sectr_api :: proc ( version_id : i32 ) -> sectr.ModuleAPI
|
||||
return {}
|
||||
}
|
||||
|
||||
lock_file := fmt.tprintf( "sectr_{0}_locked.dll", version_id )
|
||||
sectr.copy_file_sync( "sectr.dll", lock_file )
|
||||
live_file := path_sectr_live_module
|
||||
sectr.copy_file_sync( path_sectr_module, live_file )
|
||||
|
||||
lib, load_result := dynlib.load_library( lock_file )
|
||||
lib, load_result := dynlib.load_library( live_file )
|
||||
if ! load_result {
|
||||
// TODO(Ed) : Setup a proper logging interface
|
||||
fmt. println( "Failed to load the sectr module." )
|
||||
runtime.debug_trap()
|
||||
return {}
|
||||
}
|
||||
|
||||
startup := cast( type_of( sectr.startup )) dynlib.symbol_address( lib, "startup" )
|
||||
shutdown := cast( type_of( sectr.sectr_shutdown )) dynlib.symbol_address( lib, "sectr_shutdown" )
|
||||
reload := cast( type_of( sectr.reload )) dynlib.symbol_address( lib, "reload" )
|
||||
update := cast( type_of( sectr.update )) dynlib.symbol_address( lib, "update" )
|
||||
render := cast( type_of( sectr.render )) dynlib.symbol_address( lib, "render" )
|
||||
startup := cast( type_of( sectr.startup )) dynlib.symbol_address( lib, "startup" )
|
||||
shutdown := cast( type_of( sectr.sectr_shutdown )) dynlib.symbol_address( lib, "sectr_shutdown" )
|
||||
reload := cast( type_of( sectr.reload )) dynlib.symbol_address( lib, "reload" )
|
||||
update := cast( type_of( sectr.update )) dynlib.symbol_address( lib, "update" )
|
||||
render := cast( type_of( sectr.render )) dynlib.symbol_address( lib, "render" )
|
||||
clean_temp := cast( type_of( sectr.clean_temp )) dynlib.symbol_address( lib, "clean_temp" )
|
||||
|
||||
missing_symbol : b32 = false
|
||||
if startup == nil do fmt.println("Failed to load sectr.startup symbol")
|
||||
if shutdown == nil do fmt.println("Failed to load sectr.shutdown symbol")
|
||||
if reload == nil do fmt.println("Failed to load sectr.reload symbol")
|
||||
if update == nil do fmt.println("Failed to load sectr.update symbol")
|
||||
if render == nil do fmt.println("Failed to load sectr.render symbol")
|
||||
if startup == nil do fmt.println("Failed to load sectr.startup symbol")
|
||||
if shutdown == nil do fmt.println("Failed to load sectr.shutdown symbol")
|
||||
if reload == nil do fmt.println("Failed to load sectr.reload symbol")
|
||||
if update == nil do fmt.println("Failed to load sectr.update symbol")
|
||||
if render == nil do fmt.println("Failed to load sectr.render symbol")
|
||||
if clean_temp == nil do fmt.println("Failed to load sector.clean_temp symbol")
|
||||
if missing_symbol {
|
||||
runtime.debug_trap()
|
||||
return {}
|
||||
@ -144,23 +126,46 @@ load_sectr_api :: proc ( version_id : i32 ) -> sectr.ModuleAPI
|
||||
write_time = write_time,
|
||||
lib_version = version_id,
|
||||
|
||||
startup = startup,
|
||||
shutdown = shutdown,
|
||||
reload = reload,
|
||||
update = update,
|
||||
render = render,
|
||||
startup = startup,
|
||||
shutdown = shutdown,
|
||||
reload = reload,
|
||||
update = update,
|
||||
render = render,
|
||||
clean_temp = clean_temp,
|
||||
}
|
||||
return loaded_module
|
||||
}
|
||||
|
||||
unload_sectr_api :: proc ( module : ^ sectr.ModuleAPI )
|
||||
{
|
||||
lock_file := fmt.tprintf( "sectr_{0}_locked.dll", module.lib_version )
|
||||
dynlib.unload_library( module.lib )
|
||||
// os.remove( lock_file )
|
||||
os.remove( path_sectr_live_module )
|
||||
module^ = {}
|
||||
}
|
||||
|
||||
sync_sectr_api :: proc ( sectr_api : ^ sectr.ModuleAPI, memory : ^ VMemChunk )
|
||||
{
|
||||
if write_time, result := os.last_write_time_by_name( path_sectr_module );
|
||||
result == os.ERROR_NONE && sectr_api.write_time != write_time
|
||||
{
|
||||
version_id := sectr_api.lib_version + 1
|
||||
unload_sectr_api( sectr_api )
|
||||
|
||||
// Wait for pdb to unlock (linker may still be writting)
|
||||
for ; sectr.is_file_locked( path_sectr_debug_symbols ) && sectr.is_file_locked( path_sectr_live_module ); {}
|
||||
time.sleep( time.Millisecond )
|
||||
|
||||
sectr_api ^ = load_sectr_api( version_id )
|
||||
if sectr_api.lib_version == 0 {
|
||||
fmt.println("Failed to hot-reload the sectr module")
|
||||
runtime.debug_trap()
|
||||
os.exit(-1)
|
||||
// TODO(Ed) : Figure out the error code enums..
|
||||
}
|
||||
sectr_api.reload( & memory.sectr_live, & memory.sectr_snapshot )
|
||||
}
|
||||
}
|
||||
|
||||
main :: proc()
|
||||
{
|
||||
fmt.println("Hellope!")
|
||||
@ -174,55 +179,35 @@ main :: proc()
|
||||
// We're going to make it static for the prototype and separate it from the 'project' memory.
|
||||
// Then shove the context allocator for the engine to it.
|
||||
// The project's context will use its own subsection arena allocator.
|
||||
memory = setup_engine_memory()
|
||||
context.allocator = mem.arena_allocator( memory.host_persistent )
|
||||
context.temp_allocator = mem.arena_allocator( memory.host_transient )
|
||||
memory = setup_memory()
|
||||
}
|
||||
|
||||
// Load the Enviornment API for the first-time
|
||||
{
|
||||
sectr_api = load_sectr_api( 1 )
|
||||
if sectr_api.lib_version == 0 {
|
||||
// TODO(Ed) : Setup a proper logging interface
|
||||
fmt. println( "Failed to initially load the sectr module" )
|
||||
runtime.debug_trap()
|
||||
os. exit( -1 )
|
||||
// TODO(Ed) : Figure out the error code enums..
|
||||
}
|
||||
}
|
||||
|
||||
running = true;
|
||||
memory = memory
|
||||
sectr_api = sectr_api
|
||||
sectr_api.startup( memory.sectr_persistent, memory.sectr_transient, memory.sectr_temp )
|
||||
sectr_api.startup( & memory.sectr_live, & memory.sectr_snapshot )
|
||||
|
||||
// TODO(Ed) : This should have an end status so that we know the reason the engine stopped.
|
||||
for ; running ;
|
||||
{
|
||||
// Hot-Reload
|
||||
if write_time, result := os.last_write_time_by_name("sectr.dll");
|
||||
result == os.ERROR_NONE && sectr_api.write_time != write_time
|
||||
{
|
||||
version_id := sectr_api.lib_version + 1
|
||||
unload_sectr_api( & sectr_api )
|
||||
|
||||
// Wait for pdb to unlock (linker may still be writting)
|
||||
for ; sectr.is_file_locked( "sectr.pdb" ); {
|
||||
}
|
||||
time.sleep( time.Millisecond )
|
||||
|
||||
sectr_api = load_sectr_api( version_id )
|
||||
if sectr_api.lib_version == 0 {
|
||||
fmt.println("Failed to hot-reload the sectr module")
|
||||
runtime.debug_trap()
|
||||
os.exit(-1)
|
||||
}
|
||||
sectr_api.reload( memory.sectr_persistent, memory.sectr_transient, memory.sectr_temp )
|
||||
}
|
||||
sync_sectr_api( & sectr_api, & memory )
|
||||
|
||||
running = sectr_api.update()
|
||||
sectr_api.render()
|
||||
|
||||
free_all( mem.arena_allocator( memory.sectr_temp ) )
|
||||
// free_all( mem.arena_allocator( & memory.env_transient ) )
|
||||
sectr_api.render()
|
||||
sectr_api.clean_temp()
|
||||
}
|
||||
|
||||
// Determine how the run_cyle completed, if it failed due to an error,
|
||||
|
111
code/memory.odin
111
code/memory.odin
@ -4,6 +4,7 @@ import "core:fmt"
|
||||
import "core:mem"
|
||||
import "core:mem/virtual"
|
||||
import "core:runtime"
|
||||
import "core:os"
|
||||
|
||||
Byte :: 1
|
||||
Kilobyte :: 1024 * Byte
|
||||
@ -14,8 +15,112 @@ Petabyte :: 1024 * Terabyte
|
||||
Exabyte :: 1024 * Petabyte
|
||||
|
||||
kilobytes :: proc ( kb : $ integer_type ) -> integer_type {
|
||||
return kb * 1024
|
||||
return kb * Kilobyte
|
||||
}
|
||||
megabytes :: proc ( kb : $ integer_type ) -> integer_type {
|
||||
return kb * 1024 * 1024
|
||||
megabytes :: proc ( mb : $ integer_type ) -> integer_type {
|
||||
return mb * Megabyte
|
||||
}
|
||||
gigabyte :: proc ( gb : $ integer_type ) -> integer_type {
|
||||
return gb * Gigabyte
|
||||
}
|
||||
terabyte :: proc ( tb : $ integer_type ) -> integer_type {
|
||||
return tb * Terabyte
|
||||
}
|
||||
|
||||
// Initialize a sub-section of our virtual memory as a sub-arena
|
||||
sub_arena_init :: proc( address : ^ byte, size : int ) -> ( ^ mem.Arena) {
|
||||
Arena :: mem.Arena
|
||||
|
||||
arena_size :: size_of( Arena)
|
||||
sub_arena := cast( ^ Arena ) address
|
||||
mem_slice := mem.slice_ptr( mem.ptr_offset( address, arena_size), size )
|
||||
mem.arena_init( sub_arena, mem_slice )
|
||||
return sub_arena
|
||||
}
|
||||
|
||||
// Helper to get the the beginning of memory after a slice
|
||||
memory_after :: proc( slice : []byte ) -> ( ^ byte) {
|
||||
return mem.ptr_offset( & slice[0], len(slice) )
|
||||
}
|
||||
|
||||
// Since this is a prototype, all memory is always tracked. No arena is is interfaced directly.
|
||||
TrackedAllocator :: struct {
|
||||
backing : mem.Arena,
|
||||
internals : mem.Arena,
|
||||
tracker : mem.Tracking_Allocator,
|
||||
}
|
||||
|
||||
tracked_allocator :: proc ( self : ^ TrackedAllocator ) -> mem.Allocator {
|
||||
return mem.tracking_allocator( & self.tracker )
|
||||
}
|
||||
|
||||
tracked_allocator_init :: proc( size, internals_size : int ) -> TrackedAllocator
|
||||
{
|
||||
result : TrackedAllocator
|
||||
|
||||
Arena :: mem.Arena
|
||||
Tracking_Allocator :: mem.Tracking_Allocator
|
||||
arena_allocator :: mem.arena_allocator
|
||||
arena_init :: mem.arena_init
|
||||
slice_ptr :: mem.slice_ptr
|
||||
|
||||
arena_size :: size_of( Arena)
|
||||
backing_size := size + arena_size
|
||||
internals_size := internals_size + arena_size
|
||||
raw_size := backing_size + internals_size
|
||||
|
||||
raw_mem, raw_mem_code := mem.alloc( raw_size )
|
||||
if ( raw_mem_code != mem.Allocator_Error.None )
|
||||
{
|
||||
// TODO(Ed) : Setup a proper logging interface
|
||||
fmt. printf( "Failed to allocate memory for the TrackingAllocator" )
|
||||
runtime.debug_trap()
|
||||
os. exit( -1 )
|
||||
// TODO(Ed) : Figure out the error code enums..
|
||||
}
|
||||
arena_init( & result.backing, slice_ptr( cast( ^ byte) raw_mem, backing_size ) )
|
||||
arena_init( & result.internals, slice_ptr( memory_after( result.backing.data), internals_size ) )
|
||||
|
||||
backing_allocator := arena_allocator( & result.backing )
|
||||
internals_allocator := arena_allocator( & result.internals )
|
||||
mem.tracking_allocator_init( & result.tracker, backing_allocator, internals_allocator )
|
||||
return result
|
||||
}
|
||||
|
||||
tracked_allocator_init_vmem :: proc( vmem : [] byte, internals_size : int ) -> ^ TrackedAllocator
|
||||
{
|
||||
Arena :: mem.Arena
|
||||
Tracking_Allocator :: mem.Tracking_Allocator
|
||||
arena_allocator :: mem.arena_allocator
|
||||
arena_init :: mem.arena_init
|
||||
tracking_alloator_init :: mem.tracking_allocator_init
|
||||
ptr_offset :: mem.ptr_offset
|
||||
slice_ptr :: mem.slice_ptr
|
||||
|
||||
arena_size :: size_of( Arena)
|
||||
tracking_allocator_size :: size_of( Tracking_Allocator )
|
||||
backing_size := len(vmem) - internals_size
|
||||
raw_size := backing_size + internals_size
|
||||
|
||||
if backing_size < 0 || len(vmem) < raw_size
|
||||
{
|
||||
// TODO(Ed) : Setup a proper logging interface
|
||||
fmt. printf( "Provided virtual memory slice is not large enough to hold the TrackedAllocator" )
|
||||
runtime.debug_trap()
|
||||
os. exit( -1 )
|
||||
// TODO(Ed) : Figure out the error code enums..
|
||||
}
|
||||
|
||||
result := cast( ^ TrackedAllocator) & vmem[0]
|
||||
result_slice := slice_ptr( & vmem[0], tracking_allocator_size )
|
||||
|
||||
backing_slice := slice_ptr( memory_after( result_slice ), backing_size )
|
||||
internals_slice := slice_ptr( memory_after( backing_slice), internals_size )
|
||||
backing := & result.backing
|
||||
internals := & result.internals
|
||||
arena_init( backing, backing_slice )
|
||||
arena_init( internals, internals_slice )
|
||||
|
||||
tracking_alloator_init( & result.tracker, arena_allocator( backing ), arena_allocator( internals ) )
|
||||
return result
|
||||
}
|
||||
|
@ -12,7 +12,7 @@ debug_text :: proc( content : string, x, y : f32, size : f32 = 16.0, color : rl.
|
||||
|
||||
font := font
|
||||
if ( font.chars == nil ) {
|
||||
font = ( cast( ^ State) memory.persistent ).default_font
|
||||
font = get_state().default_font
|
||||
}
|
||||
|
||||
rl.DrawTextCodepoints( font,
|
||||
|
Loading…
Reference in New Issue
Block a user