WIP: Untested more process runtime bootstrapping, some decisions on how grime is setup..
This commit is contained in:
21
code2/sectr/config_compile_time.odin
Normal file
21
code2/sectr/config_compile_time.odin
Normal file
@@ -0,0 +1,21 @@
|
||||
package sectr
|
||||
|
||||
Path_Assets :: "../assets/"
|
||||
Path_Shaders :: "../shaders/"
|
||||
Path_Input_Replay :: "input.sectr_replay"
|
||||
|
||||
|
||||
Path_Logs :: "../logs"
|
||||
when ODIN_OS == .Windows
|
||||
{
|
||||
Path_Module :: "sectr.dll"
|
||||
Path_Live_Module :: "sectr_live.dll"
|
||||
Path_Debug_Symbols :: "sectr.pdb"
|
||||
Path_Spall_Record :: "sectr.spall"
|
||||
}
|
||||
|
||||
DISABLE_CLIENT_PROFILING :: false
|
||||
DISABLE_HOST_PROFILING :: false
|
||||
|
||||
// TODO(Ed): We can technically hot-reload this (spin up or down lanes on reloads)
|
||||
THREAD_TICK_LANES :: 2
|
||||
@@ -1,14 +1,18 @@
|
||||
package sectr
|
||||
|
||||
import "core:dynlib"
|
||||
import "core:sync"
|
||||
// Sokol should only be used here and in the client_api_sokol_callbacks.odin
|
||||
|
||||
Path_Assets :: "../assets/"
|
||||
Path_Shaders :: "../shaders/"
|
||||
Path_Input_Replay :: "input.sectr_replay"
|
||||
import sokol_app "thirdparty:sokol/app"
|
||||
import sokol_gfx "thirdparty:sokol/gfx"
|
||||
import sokol_glue "thirdparty:sokol/glue"
|
||||
import sokol_gp "thirdparty:sokol/gp"
|
||||
|
||||
/*
|
||||
This definies the client interface for the host process to call into
|
||||
*/
|
||||
|
||||
ModuleAPI :: struct {
|
||||
lib: dynlib.Library,
|
||||
lib: DynLibrary,
|
||||
write_time: FileTime,
|
||||
lib_version : int,
|
||||
|
||||
@@ -19,8 +23,6 @@ ModuleAPI :: struct {
|
||||
clean_frame: type_of( clean_frame),
|
||||
}
|
||||
|
||||
StartupContext :: struct {}
|
||||
|
||||
/*
|
||||
Called by host.main when it completes its setup.
|
||||
|
||||
@@ -34,44 +36,63 @@ startup :: proc(host_mem: ^ProcessMemory, thread_mem: ^ThreadMemory)
|
||||
}
|
||||
|
||||
/*
|
||||
Called by sync_client_api when the client module has be reloaded.
|
||||
Called by host.sync_client_api when the client module has be reloaded.
|
||||
Threads will eventually return to their tick_lane upon completion.
|
||||
*/
|
||||
@export
|
||||
hot_reload :: proc(host_mem: ^ProcessMemory, thread_mem: ^ThreadMemory)
|
||||
{
|
||||
thread_ctx = thread_mem
|
||||
if thread_ctx.id == .Master_Prepper {
|
||||
cache_coherent_store(& memory, host_mem, .Release)
|
||||
thread = thread_mem
|
||||
if thread.id == .Master_Prepper {
|
||||
sync_store(& memory, host_mem, .Release)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Called by host_tick_lane_startup
|
||||
Used for lane specific startup operations
|
||||
|
||||
The lane tick cannot be handled it, its call must be done by the host module.
|
||||
(We need threads to not be within a client callstack in the even of a hot-reload)
|
||||
Called by host_tick_lane_startup
|
||||
Used for lane specific startup operations
|
||||
|
||||
The lane tick cannot be handled it, its call must be done by the host module.
|
||||
(We need threads to not be within a client callstack in the even of a hot-reload)
|
||||
*/
|
||||
@export
|
||||
tick_lane_startup :: proc(thread_mem: ^ThreadMemory)
|
||||
{
|
||||
thread_ctx = thread_mem
|
||||
thread_ctx.live_lanes = THREAD_TICK_LANES
|
||||
thread = thread_mem
|
||||
thread.live_lanes = THREAD_TICK_LANES
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
*/
|
||||
@export
|
||||
tick_lane :: proc(host_delta_time_ms: f64, host_delta_ns: Duration) -> (should_close: b64)
|
||||
{
|
||||
@thread_local dummy: int = 0;
|
||||
dummy += 2
|
||||
profile_begin("sokol_app: pre_client_tick")
|
||||
// should_close |= cast(b64) sokol_app.pre_client_frame()
|
||||
profile_end()
|
||||
|
||||
profile_begin("Client Tick")
|
||||
profile_end()
|
||||
|
||||
profile_begin("sokol_app: post_client_tick")
|
||||
profile_end()
|
||||
|
||||
tick_lane_frametime()
|
||||
return true
|
||||
}
|
||||
|
||||
tick_lane_frametime :: proc()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
@export
|
||||
clean_frame :: proc()
|
||||
{
|
||||
@thread_local dummy: int = 0;
|
||||
dummy += 1
|
||||
if thread.id == .Master_Prepper
|
||||
{
|
||||
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@@ -5,6 +5,12 @@ import "core:sync"
|
||||
/*
|
||||
Everything defined for the host module within the client module
|
||||
so that the client module has full awareness of relevant host definitions
|
||||
|
||||
Client interaction with host is very minimal,
|
||||
host will only provide the base runtime for client's tick lanes and job system workers.
|
||||
|
||||
Host is has all statically (data/bss) defined memory for the application, it will not mess with
|
||||
client_memory however.
|
||||
*/
|
||||
|
||||
ProcessMemory :: struct {
|
||||
@@ -19,8 +25,7 @@ ProcessMemory :: struct {
|
||||
logger: Logger,
|
||||
|
||||
// Profiling
|
||||
spall_profiler: SpallProfiler,
|
||||
// TODO(Ed): Try Superluminal!
|
||||
spall_profiler: ^SpallProfiler,
|
||||
|
||||
// Multi-threading
|
||||
threads: [MAX_THREADS](SysThread),
|
||||
@@ -34,12 +39,8 @@ ProcessMemory :: struct {
|
||||
}
|
||||
|
||||
Host_API :: struct {
|
||||
launch_tick_lane_thread: #type proc(WorkerID),
|
||||
|
||||
request_virtual_memory: #type proc(),
|
||||
request_virtual_mapped_io: #type proc(),
|
||||
|
||||
sync_client_module : #type proc(),
|
||||
}
|
||||
|
||||
ThreadMemory :: struct {
|
||||
|
||||
@@ -1,14 +1,36 @@
|
||||
package sectr
|
||||
|
||||
/*
|
||||
All direct non-codebase package symbols should do zero allocations.
|
||||
Any symbol that does must be mapped from the Grime package to properly tirage its allocator to odin's ideomatic interface.
|
||||
|
||||
|
||||
*/
|
||||
|
||||
import "base:intrinsics"
|
||||
debug_trap :: intrinsics.debug_trap
|
||||
|
||||
import "core:dynlib"
|
||||
// Only referenced in ModuleAPI
|
||||
DynLibrary :: dynlib.Library
|
||||
|
||||
import "core:log"
|
||||
LoggerLevel :: log.Level
|
||||
|
||||
import "core:mem"
|
||||
Odin_Arena :: mem.Arena
|
||||
// Used strickly for the logger
|
||||
Odin_Arena :: mem.Arena
|
||||
odin_arena_allocator :: mem.arena_allocator
|
||||
|
||||
import "core:os"
|
||||
FileTime :: os.File_Time
|
||||
FileTime :: os.File_Time
|
||||
process_exit :: os.exit
|
||||
|
||||
import "core:prof/spall"
|
||||
|
||||
import "core:sync"
|
||||
AtomicMutex :: sync.Atomic_Mutex
|
||||
cache_coherent_store :: sync.atomic_store_explicit
|
||||
sync_store :: sync.atomic_store_explicit
|
||||
|
||||
import "core:thread"
|
||||
SysThread :: thread.Thread
|
||||
@@ -17,10 +39,44 @@ import "core:time"
|
||||
Duration :: time.Duration
|
||||
|
||||
import "codebase:grime"
|
||||
Logger :: grime.Logger
|
||||
SpallProfiler :: grime.SpallProfiler
|
||||
Logger :: grime.Logger
|
||||
SpallProfiler :: grime.SpallProfiler
|
||||
|
||||
Kilo :: 1024
|
||||
Mega :: Kilo * 1024
|
||||
Giga :: Mega * 1024
|
||||
Tera :: Giga * 1024
|
||||
|
||||
ensure :: #force_inline proc( condition : b32, msg : string, location := #caller_location ) {
|
||||
if condition do return
|
||||
log_print( msg, LoggerLevel.Warning, location )
|
||||
debug_trap()
|
||||
}
|
||||
// TODO(Ed) : Setup exit codes!
|
||||
fatal :: #force_inline proc( msg : string, exit_code : int = -1, location := #caller_location ) {
|
||||
log_print( msg, LoggerLevel.Fatal, location )
|
||||
debug_trap()
|
||||
process_exit( exit_code )
|
||||
}
|
||||
// TODO(Ed) : Setup exit codes!
|
||||
verify :: #force_inline proc( condition : b32, msg : string, exit_code : int = -1, location := #caller_location ) {
|
||||
if condition do return
|
||||
log_print( msg, LoggerLevel.Fatal, location )
|
||||
debug_trap()
|
||||
process_exit( exit_code )
|
||||
}
|
||||
|
||||
log_print :: proc( msg : string, level := LoggerLevel.Info, loc := #caller_location ) {
|
||||
context.allocator = odin_arena_allocator(& memory.host_scratch)
|
||||
context.temp_allocator = odin_arena_allocator(& memory.host_scratch)
|
||||
log.log( level, msg, location = loc )
|
||||
}
|
||||
log_print_fmt :: proc( fmt : string, args : ..any, level := LoggerLevel.Info, loc := #caller_location ) {
|
||||
context.allocator = odin_arena_allocator(& memory.host_scratch)
|
||||
context.temp_allocator = odin_arena_allocator(& memory.host_scratch)
|
||||
log.logf( level, fmt, ..args, location = loc )
|
||||
}
|
||||
|
||||
@(deferred_none = profile_end, disabled = DISABLE_CLIENT_PROFILING) profile :: #force_inline proc "contextless" ( name : string, loc := #caller_location ) { spall._buffer_begin( & memory.spall_profiler.ctx, & memory.spall_profiler.buffer, name, "", loc ) }
|
||||
@( disabled = DISABLE_CLIENT_PROFILING) profile_begin :: #force_inline proc "contextless" ( name : string, loc := #caller_location ) { spall._buffer_begin( & memory.spall_profiler.ctx, & memory.spall_profiler.buffer, name, "", loc ) }
|
||||
@( disabled = DISABLE_CLIENT_PROFILING) profile_end :: #force_inline proc "contextless" () { spall._buffer_end ( & memory.spall_profiler.ctx, & memory.spall_profiler.buffer) }
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
package sectr
|
||||
|
||||
//region STATIC MEMORY
|
||||
// This should be the only global on client module side.
|
||||
memory: ^ProcessMemory
|
||||
|
||||
@(thread_local)
|
||||
thread_ctx: ^ThreadMemory
|
||||
|
||||
THREAD_TICK_LANES :: 2
|
||||
memory: ^ProcessMemory
|
||||
@(thread_local) thread: ^ThreadMemory
|
||||
//endregion STATIC MEMORy
|
||||
|
||||
State :: struct {
|
||||
job_system: JobSystemContext,
|
||||
|
||||
Reference in New Issue
Block a user