job refactor progress

This commit is contained in:
jacob 2025-08-05 13:48:49 -05:00
parent 0d8531e740
commit 632f12dd63
32 changed files with 547 additions and 513 deletions

View File

@ -126,14 +126,15 @@ AppArgList ParseAppArgs(Arena *arena, String args_str)
} }
//////////////////////////////// ////////////////////////////////
//~ Entry point //~ @hookdef Entry point
void P_AppStartup(String args_str) void EntryPoint(void)
{ {
__prof; __prof;
TempArena scratch = BeginScratchNoConflict(); TempArena scratch = BeginScratchNoConflict();
SharedAppState *g = &shared_app_state; SharedAppState *g = &shared_app_state;
String args_str = Lit("");
AppArgList args = ParseAppArgs(scratch.arena, args_str); AppArgList args = ParseAppArgs(scratch.arena, args_str);
String logfile_name = Lit("log.log"); String logfile_name = Lit("log.log");
String settings_file_name = Lit("settings.txt"); String settings_file_name = Lit("settings.txt");
@ -217,7 +218,7 @@ void P_AppStartup(String args_str)
), ),
FmtString(settings_path), FmtString(settings_path),
FmtString(error)); FmtString(error));
P_Panic(msg); Panic(msg);
} }
P_LogInfoF("Settings file loaded successfully"); P_LogInfoF("Settings file loaded successfully");
window_settings = *deser; window_settings = *deser;

View File

@ -119,7 +119,7 @@ AC_Asset *AC_TouchCache(String key, u64 hash, b32 *is_first_touch)
{ {
if (g->num_assets >= AC_MaxAssets) if (g->num_assets >= AC_MaxAssets)
{ {
P_Panic(Lit("Max assets reached")); Panic(Lit("Max assets reached"));
} }
String key_stored = ZI; String key_stored = ZI;
{ {

View File

@ -30,6 +30,7 @@ inline void StartupBaseDeps(void)
# include "base_rand.h" # include "base_rand.h"
# include "base_util.h" # include "base_util.h"
# include "base_incbin.h" # include "base_incbin.h"
# include "base_entry.h"
#if PlatformIsWindows #if PlatformIsWindows
# include "win32/base_win32.h" # include "win32/base_win32.h"
#endif #endif

View File

@ -18,7 +18,7 @@ Arena *AllocArena(u64 reserve)
{ {
/* Hard fail on memory reserve failure for now */ /* Hard fail on memory reserve failure for now */
/* FIXME: Enable this */ /* FIXME: Enable this */
//P_Panic(Lit("Failed to reserve memory")); //Panic(Lit("Failed to reserve memory"));
(*(volatile int *)0) = 0; (*(volatile int *)0) = 0;
} }
u64 reserved = reserve; u64 reserved = reserve;
@ -30,7 +30,7 @@ Arena *AllocArena(u64 reserve)
{ {
/* Hard fail on commit failure */ /* Hard fail on commit failure */
/* FIXME: Enable this */ /* FIXME: Enable this */
//P_Panic(Lit("Failed to commit initial memory block: System may be out of memory")); //Panic(Lit("Failed to commit initial memory block: System may be out of memory"));
(*(volatile int *)0) = 0; (*(volatile int *)0) = 0;
} }
@ -89,7 +89,7 @@ void *PushBytesNoZero(Arena *arena, u64 size, u64 align)
{ {
/* Hard fail if we overflow reserved memory for now */ /* Hard fail if we overflow reserved memory for now */
/* FIXME: Enable this */ /* FIXME: Enable this */
//P_Panic(Lit("Failed to commit new memory block: Overflow of reserved memory")); //Panic(Lit("Failed to commit new memory block: Overflow of reserved memory"));
(*(volatile int *)0) = 0; (*(volatile int *)0) = 0;
} }
void *commit_address = base + arena->committed; void *commit_address = base + arena->committed;
@ -97,7 +97,7 @@ void *PushBytesNoZero(Arena *arena, u64 size, u64 align)
{ {
/* Hard fail on memory allocation failure for now */ /* Hard fail on memory allocation failure for now */
/* FIXME: Enable this */ /* FIXME: Enable this */
//P_Panic(Lit("Failed to commit new memory block: System may be out of memory")); //Panic(Lit("Failed to commit new memory block: System may be out of memory"));
(*(volatile int *)0) = 0; (*(volatile int *)0) = 0;
} }
arena->committed += commit_bytes; arena->committed += commit_bytes;

17
src/base/base_entry.h Normal file
View File

@ -0,0 +1,17 @@
////////////////////////////////
//~ Exit callback types
#define ExitFuncDef(name) void name(void)
typedef ExitFuncDef(ExitFunc);
////////////////////////////////
//~ @hookdecl Exit operations
void OnExit(ExitFunc *func);
void Exit(void);
void Panic(String msg);
////////////////////////////////
//~ @hookdecl Application defined entry point
void EntryPoint(void);

View File

@ -55,7 +55,7 @@ String StringFromIncbinRcResource(IncbinRcResource *inc)
if (!params.found) if (!params.found)
{ {
/* FIXME: enable this */ /* FIXME: enable this */
//P_Panic(StringFormat(scratch.arena, //Panic(StringFormat(scratch.arena,
// Lit("INCBIN include not found in RC file: \"%F\""), // Lit("INCBIN include not found in RC file: \"%F\""),
// FmtString(inc->rc_name))); // FmtString(inc->rc_name)));
(*(volatile int *)0) = 0; (*(volatile int *)0) = 0;

View File

@ -93,7 +93,6 @@ void RunJobEx(GenericJobDesc *desc);
//~ @hookdecl Helpers //~ @hookdecl Helpers
i64 TimeNs(void); i64 TimeNs(void);
u32 GetLogicalProcessorCount(void);
u32 ThreadId(void); u32 ThreadId(void);
u32 GetLogicalProcessorCount(void);
i64 GetCurrentSchedulerPeriodNs(void); i64 GetCurrentSchedulerPeriodNs(void);

View File

@ -1,3 +1,4 @@
#include "base_win32.h" #include "base_win32.h"
#include "base_win32_job.c" #include "base_win32_job.c"
#include "base_win32_entry.c"

View File

@ -4,5 +4,6 @@
#include "../base.h" #include "../base.h"
#include "base_win32_job.h" #include "base_win32_job.h"
#include "base_win32_entry.h"
#endif #endif

View File

@ -0,0 +1,292 @@
W32_SharedEntryCtx W32_shared_entry_ctx = ZI;
////////////////////////////////
//~ Startup / shutdown jobs
JobDef(W32_AppStartupJob, UNUSED sig, UNUSED id)
{
W32_SharedEntryCtx *g = &W32_shared_entry_ctx;
TempArena scratch = BeginScratchNoConflict();
{
EntryPoint();
SetEvent(g->startup_end_event);
}
EndScratch(scratch);
}
JobDef(W32_AppShutdownJob, UNUSED sig, UNUSED id)
{
__prof;
W32_SharedEntryCtx *g = &W32_shared_entry_ctx;
i32 num_funcs = Atomic32Fetch(&g->num_exit_funcs);
for (i32 i = num_funcs - 1; i >= 0; --i)
{
ExitFunc *func = g->exit_funcs[i];
func();
}
SetEvent(g->exit_end_event);
}
////////////////////////////////
//~ @hookdef Exit hooks
void OnExit(ExitFunc *func)
{
W32_SharedEntryCtx *g = &W32_shared_entry_ctx;
i32 index = Atomic32FetchAdd(&g->num_exit_funcs, 1);
if (index >= W32_MaxOnExitFuncs)
{
Panic(Lit("Maximum on exit functions registered"));
}
g->exit_funcs[index] = func;
}
void Exit(void)
{
W32_SharedEntryCtx *g = &W32_shared_entry_ctx;
SetEvent(g->exit_begin_event);
}
void Panic(String msg)
{
W32_SharedEntryCtx *g = &W32_shared_entry_ctx;
if (Atomic32FetchTestSet(&g->panicking, 0, 1) == 0)
{
//LogPanic(msg);
wchar_t *wstr = g->panic_wstr;
u64 WstrLen = 0;
wchar_t prefix[] = L"A fatal error has occured and the application needs to exit:\n\n";
CopyBytes(wstr, prefix, MinU64(countof(g->panic_wstr), (countof(prefix) << 1)));
WstrLen += countof(prefix) - 1;
/* Perform manual string encode to avoid any implicit memory
* allocation (in case allocation is unreliable) */
String str8 = msg;
u64 pos8 = 0;
while (pos8 < str8.len)
{
String str8_remaining = { .len = (str8.len - pos8), .text = str8.text + pos8 };
Utf8DecodeResult decoded = DecodeUtf8(str8_remaining);
Utf16EncodeResult encoded = EncodeUtf16(decoded.codepoint);
u64 wstr_new_len = WstrLen + encoded.count16;
if (wstr_new_len < (countof(g->panic_wstr) - 1))
{
u16 *dest = wstr + WstrLen;
CopyBytes(dest, encoded.chars16, (encoded.count16 << 1));
WstrLen = wstr_new_len;
pos8 += decoded.advance8;
}
else
{
break;
}
}
wstr[WstrLen] = 0;
#if RtcIsEnabled
MessageBoxExW(0, wstr, L"Fatal error", MB_ICONSTOP | MB_SETFOREGROUND | MB_TOPMOST, 0);
Assert(0);
#endif
SetEvent(g->panic_event);
/* Wait for process termination */
if (GetCurrentThreadId() != g->main_thread_id)
{
Sleep(INFINITE);
}
}
}
////////////////////////////////
//~ Winmain
int CALLBACK wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev_instance, _In_ LPWSTR cmdline_wstr, _In_ int show_code)
{
LAX instance;
LAX prev_instance;
LAX cmdline_wstr;
LAX show_code;
__profthread("Main thread", PROF_THREAD_GROUP_MAIN);
W32_SharedEntryCtx *g = &W32_shared_entry_ctx;
#if ProfilingIsEnabled
/* Start profiler */
{
__profn("Launch profiler");
STARTUPINFO si = ZI;
si.cb = sizeof(si);
PROCESS_INFORMATION pi = ZI;
wchar_t cmd[sizeof(ProfilingCmdWstr)] = ZI;
CopyBytes(cmd, ProfilingCmdWstr, sizeof(ProfilingCmdWstr));
DeleteFileW(ProfilingOutFileWstr);
b32 success = CreateProcessW(0, cmd, 0, 0, 0, DETACHED_PROCESS, 0, 0, &si, &pi);
if (!success)
{
MessageBoxExW(0, L"Failed to launch profiler using command '" ProfilingCmdWstr L"'.", L"Error", MB_ICONSTOP | MB_SETFOREGROUND | MB_TOPMOST, 0);
}
}
/* Set internal profiler thread affinities */
{
__profn("Set profiler thread affinities");
wchar_t *prefix_name_wstr = ProfilerThreadPrefixWstr;
u64 prefix_name_wstr_len = ((i32)sizeof(ProfilerThreadPrefixWstr) >> 1) - 1;
if (prefix_name_wstr_len > 0 && ProfilerThreadAffinityMask != 0)
{
DWORD proc_id = GetCurrentProcessId();
HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
if (snapshot != INVALID_HANDLE_VALUE)
{
THREADENTRY32 te = ZI;
te.dwSize = sizeof(THREADENTRY32);
if (Thread32First(snapshot, &te))
{
do
{
if (te.th32OwnerProcessID == proc_id)
{
i32 thread_id = te.th32ThreadID;
HANDLE thread = OpenThread(THREAD_ALL_ACCESS, FALSE, thread_id);
if (thread)
{
wchar_t *thread_name_wstr = 0;
HRESULT hr = GetThreadDescription(thread, &thread_name_wstr);
if (SUCCEEDED(hr))
{
u64 thread_name_len = WstrLenNoLimit(thread_name_wstr);
if (thread_name_len >= prefix_name_wstr_len && EqBytes(thread_name_wstr, prefix_name_wstr, prefix_name_wstr_len))
{
__profn("Set profiler thread affinity");
b32 success = SetThreadAffinityMask(thread, ProfilerThreadAffinityMask) != 0;
{
/* Retry until external tools can set correct process affinity */
i32 delay_ms = 16;
while (!success && delay_ms <= 1024)
{
__profn("Profiler thread affinity retry");
Sleep(delay_ms);
success = SetThreadAffinityMask(thread, ProfilerThreadAffinityMask) != 0;
delay_ms *= 2;
}
}
Assert(success);
LAX success;
}
}
CloseHandle(thread);
}
}
} while (Thread32Next(snapshot, &te));
}
}
CloseHandle(snapshot);
}
}
#endif
/* Set up exit events */
g->panic_event = CreateEventW(0, 1, 0, 0);
g->startup_end_event = CreateEventW(0, 1, 0, 0);
g->exit_begin_event = CreateEventW(0, 1, 0, 0);
g->exit_end_event = CreateEventW(0, 1, 0, 0);
u64 cmdline_len = WstrLen(cmdline_wstr, countof(g->cmdline_args_wstr) - 1);
CopyBytes(g->cmdline_args_wstr, cmdline_wstr, cmdline_len * sizeof(*cmdline_wstr));
g->cmdline_args_wstr[cmdline_len] = 0;
g->main_thread_id = GetCurrentThreadId();
SetThreadDescription(GetCurrentThread(), L"Main thread");
/* Query system info */
GetSystemInfo(&g->info);
/* Initialize base layer */
BaseMain();
//- App startup
/* Run app start job */
if (!Atomic32Fetch(&g->panicking))
{
RunJob(1, W32_AppStartupJob, 0, JobPool_Floating, JobPriority_High, 0);
}
/* Wait for startup end or panic */
if (!Atomic32Fetch(&g->panicking))
{
HANDLE handles[] = {
g->startup_end_event,
g->panic_event
};
WaitForMultipleObjects(countof(handles), handles, 0, INFINITE);
}
/* Wait for exit start or panic */
if (!Atomic32Fetch(&g->panicking))
{
HANDLE handles[] = {
g->exit_begin_event,
g->panic_event
};
WaitForMultipleObjects(countof(handles), handles, 0, INFINITE);
}
//- App shutdown
/* Run exit callbacks job */
if (!Atomic32Fetch(&g->panicking))
{
RunJob(1, W32_AppShutdownJob, 0, JobPool_Floating, JobPriority_High, 0);
}
/* Wait for exit end or panic */
if (!Atomic32Fetch(&g->panicking))
{
HANDLE handles[] = {
g->exit_end_event,
g->panic_event
};
WaitForMultipleObjects(countof(handles), handles, 0, INFINITE);
}
/* Exit */
i32 exit_code = 0;
if (Atomic32Fetch(&g->panicking))
{
WaitForSingleObject(g->panic_event, INFINITE);
MessageBoxExW(0, g->panic_wstr, L"Fatal error", MB_ICONSTOP | MB_SETFOREGROUND | MB_TOPMOST, 0);
exit_code = 1;
}
return exit_code;
}
////////////////////////////////
//~ Crt stub
#if !CrtlibIsEnabled
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wmissing-variable-declarations"
#pragma clang diagnostic ignored "-Wmissing-prototypes"
/* Enable floating point */
__attribute((used))
int _fltused;
__attribute((used))
void __stdcall wWinMainCRTStartup(void)
{
int result = wWinMain(GetModuleHandle(0), 0, GetCommandLineW(), 0);
ExitProcess(result);
}
#pragma clang diagnostic pop
#endif /* !CrtlibIsEnabled */

View File

@ -0,0 +1,33 @@
////////////////////////////////
//~ Shared state
#define W32_MaxOnExitFuncs 1024
Struct(W32_SharedEntryCtx)
{
SYSTEM_INFO info;
u32 main_thread_id;
Atomic32 shutdown;
wchar_t cmdline_args_wstr[8192];
//- Application control flow
Atomic32 panicking;
wchar_t panic_wstr[4096];
HANDLE panic_event;
HANDLE startup_end_event;
HANDLE exit_begin_event;
HANDLE exit_end_event;
//- Exit funcs
Atomic32 num_exit_funcs;
ExitFunc *exit_funcs[W32_MaxOnExitFuncs];
};
extern W32_SharedEntryCtx W32_shared_entry_ctx;
////////////////////////////////
//~ Startup / shutdown jobs
JobDecl(W32_AppStartupJob, EmptySig);
JobDecl(W32_AppShutdownJob, EmptySig);

View File

@ -1,4 +1,4 @@
W32_SharedCtx W32_shared_ctx = ZI; W32_SharedJobCtx W32_shared_job_ctx = ZI;
/* FIXME: Enable logs, panic, shutdown */ /* FIXME: Enable logs, panic, shutdown */
@ -21,7 +21,7 @@ W32_SharedCtx W32_shared_ctx = ZI;
void StartupBaseJobs(void) void StartupBaseJobs(void)
{ {
W32_SharedCtx *g = &W32_shared_ctx; W32_SharedJobCtx *g = &W32_shared_job_ctx;
/* Init timer */ /* Init timer */
{ {
@ -133,7 +133,7 @@ void StartupBaseJobs(void)
} }
} }
//P_OnExit(ShutdownJobs); //OnExit(ShutdownJobs);
} }
//////////////////////////////// ////////////////////////////////
@ -195,7 +195,7 @@ void ShutdownJobs(void)
++num_dangling_threads; ++num_dangling_threads;
} }
threads_msg = StringFormat(scratch.arena, Lit("%F dangling thread(s):\n%F"), FmtUint(num_dangling_threads), FmtString(threads_msg)); threads_msg = StringFormat(scratch.arena, Lit("%F dangling thread(s):\n%F"), FmtUint(num_dangling_threads), FmtString(threads_msg));
//P_Panic(threads_msg); //Panic(threads_msg);
EndScratch(scratch); EndScratch(scratch);
} }
UnlockTicketMutex(&g->threads_tm); UnlockTicketMutex(&g->threads_tm);
@ -237,7 +237,7 @@ W32_Thread *W32_AllocThread(W32_ThreadFunc *entry_point, void *thread_data, Stri
{ {
__prof; __prof;
TempArena scratch = BeginScratchNoConflict(); TempArena scratch = BeginScratchNoConflict();
W32_SharedCtx *g = &W32_shared_ctx; W32_SharedJobCtx *g = &W32_shared_job_ctx;
Assert(entry_point != 0); Assert(entry_point != 0);
//P_LogInfoF("Creating thread \"%F\"", FmtString(thread_name)); //P_LogInfoF("Creating thread \"%F\"", FmtString(thread_name));
@ -296,7 +296,7 @@ W32_Thread *W32_AllocThread(W32_ThreadFunc *entry_point, void *thread_data, Stri
if (!t->handle) if (!t->handle)
{ {
//P_Panic(Lit("Failed to create thread")); //Panic(Lit("Failed to create thread"));
} }
EndScratch(scratch); EndScratch(scratch);
@ -307,7 +307,7 @@ W32_Thread *W32_AllocThread(W32_ThreadFunc *entry_point, void *thread_data, Stri
b32 W32_TryReleaseThread(W32_Thread *thread, f32 timeout_seconds) b32 W32_TryReleaseThread(W32_Thread *thread, f32 timeout_seconds)
{ {
__prof; __prof;
W32_SharedCtx *g = &W32_shared_ctx; W32_SharedJobCtx *g = &W32_shared_job_ctx;
b32 success = 0; b32 success = 0;
W32_Thread *t = (W32_Thread *)thread; W32_Thread *t = (W32_Thread *)thread;
HANDLE handle = t->handle; HANDLE handle = t->handle;
@ -366,7 +366,7 @@ void W32_WaitReleaseThread(W32_Thread *thread)
/* REQUIRED: Caller must have acquired `wake_lock` for each fiber in array */ /* REQUIRED: Caller must have acquired `wake_lock` for each fiber in array */
void W32_WakeLockedFibers(i32 num_fibers, W32_Fiber **fibers) void W32_WakeLockedFibers(i32 num_fibers, W32_Fiber **fibers)
{ {
W32_SharedCtx *g = &W32_shared_ctx; W32_SharedJobCtx *g = &W32_shared_job_ctx;
/* Update wait lists */ /* Update wait lists */
for (i32 i = 0; i < num_fibers; ++i) for (i32 i = 0; i < num_fibers; ++i)
@ -593,7 +593,7 @@ void W32_WakeLockedFibers(i32 num_fibers, W32_Fiber **fibers)
void W32_WakeByAddress(void *addr, i32 count) void W32_WakeByAddress(void *addr, i32 count)
{ {
TempArena scratch = BeginScratchNoConflict(); TempArena scratch = BeginScratchNoConflict();
W32_SharedCtx *g = &W32_shared_ctx; W32_SharedJobCtx *g = &W32_shared_job_ctx;
u64 wait_addr_bin_index = (u64)addr % W32_NumWaitAddrBins; u64 wait_addr_bin_index = (u64)addr % W32_NumWaitAddrBins;
W32_WaitBin *wait_addr_bin = &g->wait_addr_bins[wait_addr_bin_index]; W32_WaitBin *wait_addr_bin = &g->wait_addr_bins[wait_addr_bin_index];
@ -655,7 +655,7 @@ void W32_WakeByAddress(void *addr, i32 count)
void W32_WakeByTime(u64 time) void W32_WakeByTime(u64 time)
{ {
TempArena scratch = BeginScratchNoConflict(); TempArena scratch = BeginScratchNoConflict();
W32_SharedCtx *g = &W32_shared_ctx; W32_SharedJobCtx *g = &W32_shared_job_ctx;
u64 wait_time_bin_index = (u64)time % W32_NumWaitTimeBins; u64 wait_time_bin_index = (u64)time % W32_NumWaitTimeBins;
W32_WaitBin *wait_time_bin = &g->wait_time_bins[wait_time_bin_index]; W32_WaitBin *wait_time_bin = &g->wait_time_bins[wait_time_bin_index];
@ -706,7 +706,7 @@ void W32_WakeByTime(u64 time)
/* If `pool` is 0, then the currently running thread will be converted into a fiber */ /* If `pool` is 0, then the currently running thread will be converted into a fiber */
W32_Fiber *W32_AllocFiber(W32_JobPool *pool) W32_Fiber *W32_AllocFiber(W32_JobPool *pool)
{ {
W32_SharedCtx *g = &W32_shared_ctx; W32_SharedJobCtx *g = &W32_shared_job_ctx;
i16 fiber_id = 0; i16 fiber_id = 0;
W32_Fiber *fiber = 0; W32_Fiber *fiber = 0;
char *new_name_cstr = 0; char *new_name_cstr = 0;
@ -730,7 +730,7 @@ W32_Fiber *W32_AllocFiber(W32_JobPool *pool)
fiber_id = g->num_fibers++; fiber_id = g->num_fibers++;
if (fiber_id >= MaxFibers) if (fiber_id >= MaxFibers)
{ {
//P_Panic(Lit("Max fibers reached")); //Panic(Lit("Max fibers reached"));
} }
fiber = &g->fibers[fiber_id]; fiber = &g->fibers[fiber_id];
new_name_cstr = PushStructs(g->fiber_names_arena, char, W32_FiberNameMaxSize); new_name_cstr = PushStructs(g->fiber_names_arena, char, W32_FiberNameMaxSize);
@ -825,7 +825,7 @@ void W32_ReleaseFiber(W32_JobPool *pool, W32_Fiber *fiber)
//- Fiber id //- Fiber id
ForceInline W32_Fiber *W32_FiberFromId(i16 id) ForceInline W32_Fiber *W32_FiberFromId(i16 id)
{ {
W32_SharedCtx *g = &W32_shared_ctx; W32_SharedJobCtx *g = &W32_shared_job_ctx;
if (id <= 0) if (id <= 0)
{ {
return 0; return 0;
@ -898,7 +898,7 @@ void W32_FiberEntryPoint(void *id_ptr)
W32_ThreadDef(W32_JobWorkerEntryFunc, worker_ctx_arg) W32_ThreadDef(W32_JobWorkerEntryFunc, worker_ctx_arg)
{ {
W32_SharedCtx *g = &W32_shared_ctx; W32_SharedJobCtx *g = &W32_shared_job_ctx;
W32_WorkerCtx *ctx = worker_ctx_arg; W32_WorkerCtx *ctx = worker_ctx_arg;
JobPool pool_kind = ctx->pool_kind; JobPool pool_kind = ctx->pool_kind;
W32_JobPool *pool = &g->job_pools[pool_kind]; W32_JobPool *pool = &g->job_pools[pool_kind];
@ -1066,7 +1066,7 @@ W32_ThreadDef(W32_JobWorkerEntryFunc, worker_ctx_arg)
{ {
/* Invalid yield kind */ /* Invalid yield kind */
TempArena scratch = BeginScratchNoConflict(); TempArena scratch = BeginScratchNoConflict();
//P_Panic(StringFormat(scratch.arena, Lit("Invalid fiber yield kind \"%F\""), FmtSint(yield.kind))); //Panic(StringFormat(scratch.arena, Lit("Invalid fiber yield kind \"%F\""), FmtSint(yield.kind)));
EndScratch(scratch); EndScratch(scratch);
} break; } break;
@ -1280,7 +1280,7 @@ W32_ThreadDef(W32_JobWorkerEntryFunc, worker_ctx_arg)
W32_ThreadDef(W32_JobSchedulerEntryFunc, UNUSED arg) W32_ThreadDef(W32_JobSchedulerEntryFunc, UNUSED arg)
{ {
struct W32_SharedCtx *g = &W32_shared_ctx; struct W32_SharedJobCtx *g = &W32_shared_job_ctx;
{ {
i32 priority = THREAD_PRIORITY_TIME_CRITICAL; i32 priority = THREAD_PRIORITY_TIME_CRITICAL;
@ -1293,7 +1293,7 @@ W32_ThreadDef(W32_JobSchedulerEntryFunc, UNUSED arg)
HANDLE timer = CreateWaitableTimerExW(0, 0, CREATE_WAITABLE_TIMER_HIGH_RESOLUTION, TIMER_ALL_ACCESS); HANDLE timer = CreateWaitableTimerExW(0, 0, CREATE_WAITABLE_TIMER_HIGH_RESOLUTION, TIMER_ALL_ACCESS);
if (!timer) if (!timer)
{ {
//P_Panic(Lit("Failed to create high resolution timer")); //Panic(Lit("Failed to create high resolution timer"));
} }
/* Create rolling buffer of scheduler cycles initialized to default value */ /* Create rolling buffer of scheduler cycles initialized to default value */
@ -1419,7 +1419,7 @@ GenericJobDesc *PushJobDesc_(u64 sig_size, u64 sig_align, GenericJobFunc *func,
void RunJobEx(GenericJobDesc *desc) void RunJobEx(GenericJobDesc *desc)
{ {
__prof; __prof;
struct W32_SharedCtx *g = &W32_shared_ctx; struct W32_SharedJobCtx *g = &W32_shared_job_ctx;
i32 count = desc->count; i32 count = desc->count;
Counter *counter = desc->counter; Counter *counter = desc->counter;
JobPool pool_kind = desc->pool; JobPool pool_kind = desc->pool;
@ -1496,25 +1496,25 @@ void RunJobEx(GenericJobDesc *desc)
i64 TimeNs(void) i64 TimeNs(void)
{ {
struct W32_SharedCtx *g = &W32_shared_ctx; struct W32_SharedJobCtx *g = &W32_shared_job_ctx;
LARGE_INTEGER qpc; LARGE_INTEGER qpc;
QueryPerformanceCounter(&qpc); QueryPerformanceCounter(&qpc);
i64 result = (qpc.QuadPart - g->timer_start_qpc) * g->ns_per_qpc; i64 result = (qpc.QuadPart - g->timer_start_qpc) * g->ns_per_qpc;
return result; return result;
} }
u32 GetLogicalProcessorCount(void)
{
return GetActiveProcessorCount(ALL_PROCESSOR_GROUPS);
}
u32 ThreadId(void) u32 ThreadId(void)
{ {
return GetCurrentThreadId(); return GetCurrentThreadId();
} }
u32 GetLogicalProcessorCount(void)
{
return GetActiveProcessorCount(ALL_PROCESSOR_GROUPS);
}
i64 GetCurrentSchedulerPeriodNs(void) i64 GetCurrentSchedulerPeriodNs(void)
{ {
W32_SharedCtx *g = &W32_shared_ctx; W32_SharedJobCtx *g = &W32_shared_job_ctx;
return Atomic64Fetch(&g->current_scheduler_cycle_period_ns.v); return Atomic64Fetch(&g->current_scheduler_cycle_period_ns.v);
} }

View File

@ -213,7 +213,7 @@ AlignedStruct(W32_JobPool, 64)
/* Arbitrary threshold for determining when to fall back from a looped WakeByAddressSingle to WakeByAddressAll */ /* Arbitrary threshold for determining when to fall back from a looped WakeByAddressSingle to WakeByAddressAll */
#define W32_WakeAllThreshold 16 #define W32_WakeAllThreshold 16
Struct(W32_SharedCtx) Struct(W32_SharedJobCtx)
{ {
i64 timer_start_qpc; i64 timer_start_qpc;
i64 ns_per_qpc; i64 ns_per_qpc;
@ -249,7 +249,7 @@ Struct(W32_SharedCtx)
W32_JobPool job_pools[JobPool_Count]; W32_JobPool job_pools[JobPool_Count];
}; };
extern W32_SharedCtx W32_shared_ctx; extern W32_SharedJobCtx W32_shared_job_ctx;
//////////////////////////////// ////////////////////////////////
//~ Startup //~ Startup

View File

@ -40,7 +40,7 @@ JobDef(F_LoadJob, sig, _)
if (!RES_ResourceExists(&res)) if (!RES_ResourceExists(&res))
{ {
/* FIME: Load baked font instead of panicking */ /* FIME: Load baked font instead of panicking */
P_Panic(StringFormat(scratch.arena, Panic(StringFormat(scratch.arena,
Lit("Font \"%F\" not found"), Lit("Font \"%F\" not found"),
FmtString(path))); FmtString(path)));
} }
@ -70,7 +70,7 @@ JobDef(F_LoadJob, sig, _)
/* FIXME: Load baked font instead of panicking */ /* FIXME: Load baked font instead of panicking */
if (font->glyphs_count <= 0) if (font->glyphs_count <= 0)
{ {
P_Panic(StringFormat(scratch.arena, Panic(StringFormat(scratch.arena,
Lit("Parsed 0 glyphs from font \"%F\"!"), Lit("Parsed 0 glyphs from font \"%F\"!"),
FmtString(path))); FmtString(path)));
} }

View File

@ -24,7 +24,7 @@ void GPU_StartupCore(void)
GPU_D12_SharedState *g = &GPU_D12_shared_state; GPU_D12_SharedState *g = &GPU_D12_shared_state;
if (Atomic32FetchTestSet(&g->initialized, 0, 1) != 0) if (Atomic32FetchTestSet(&g->initialized, 0, 1) != 0)
{ {
P_Panic(Lit("GP layer already initialized")); Panic(Lit("GP layer already initialized"));
} }
/* Initialize command descriptor heaps pool */ /* Initialize command descriptor heaps pool */
@ -53,7 +53,7 @@ void GPU_StartupCore(void)
String embedded_data = INC_GetDxcTar(); String embedded_data = INC_GetDxcTar();
if (embedded_data.len <= 0) if (embedded_data.len <= 0)
{ {
P_Panic(Lit("No embedded shaders found")); Panic(Lit("No embedded shaders found"));
} }
g->dxc_archive = TAR_ArchiveFromString(g->pipelines_arena, embedded_data, Lit("")); g->dxc_archive = TAR_ArchiveFromString(g->pipelines_arena, embedded_data, Lit(""));
@ -68,13 +68,13 @@ void GPU_StartupCore(void)
#if RESOURCE_RELOADING #if RESOURCE_RELOADING
W_RegisterCallback(GPU_D12_WatchPipelineCallback); W_RegisterCallback(GPU_D12_WatchPipelineCallback);
#endif #endif
P_OnExit(GPU_D12_Shutdown); OnExit(GPU_D12_Shutdown);
/* Start evictor job */ /* Start evictor job */
RunJob(1, GPU_D12_EvictorJob, JobPool_Background, JobPriority_Low, &g->evictor_job_counter, 0); RunJob(1, GPU_D12_EvictorJob, JobPool_Background, JobPriority_Low, &g->evictor_job_counter, 0);
} }
P_ExitFuncDef(GPU_D12_Shutdown) ExitFuncDef(GPU_D12_Shutdown)
{ {
__prof; __prof;
GPU_D12_SharedState *g = &GPU_D12_shared_state; GPU_D12_SharedState *g = &GPU_D12_shared_state;
@ -108,7 +108,7 @@ void GPU_D12_PushInitError(String error)
{ {
TempArena scratch = BeginScratchNoConflict(); TempArena scratch = BeginScratchNoConflict();
String msg = StringFormat(scratch.arena, Lit("Failed to initialize DirectX 12.\n\n%F"), FmtString(error)); String msg = StringFormat(scratch.arena, Lit("Failed to initialize DirectX 12.\n\n%F"), FmtString(error));
P_Panic(msg); Panic(msg);
EndScratch(scratch); EndScratch(scratch);
} }
@ -464,7 +464,7 @@ void GPU_D12_InitNoise(void)
String data = RES_GetResourceData(&noise_res); String data = RES_GetResourceData(&noise_res);
if (data.len != expected_size) if (data.len != expected_size)
{ {
P_Panic(StringFormat(scratch.arena, Panic(StringFormat(scratch.arena,
Lit("Noise texture has unexpected size for a %Fx%Fx%F texture (expected %F, got %F)"), Lit("Noise texture has unexpected size for a %Fx%Fx%F texture (expected %F, got %F)"),
FmtUint(K_BLUE_NOISE_TEX_WIDTH), FmtUint(K_BLUE_NOISE_TEX_HEIGHT), FmtUint(K_BLUE_NOISE_TEX_DEPTH), FmtUint(K_BLUE_NOISE_TEX_WIDTH), FmtUint(K_BLUE_NOISE_TEX_HEIGHT), FmtUint(K_BLUE_NOISE_TEX_DEPTH),
FmtUint(expected_size), FmtUint(data.len))); FmtUint(expected_size), FmtUint(data.len)));
@ -503,7 +503,7 @@ void GPU_D12_InitNoise(void)
} }
else else
{ {
P_Panic(StringFormat(scratch.arena, Lit("Noise resource \"%F\" not found"), FmtString(noise_res_name))); Panic(StringFormat(scratch.arena, Lit("Noise resource \"%F\" not found"), FmtString(noise_res_name)));
} }
RES_CloseResource(&noise_res); RES_CloseResource(&noise_res);
} }
@ -1237,7 +1237,7 @@ GPU_D12_Descriptor *GPU_D12_AllocDescriptor(GPU_D12_CpuDescriptorHeap *dh)
{ {
if (dh->num_descriptors_reserved >= dh->num_descriptors_capacity) if (dh->num_descriptors_reserved >= dh->num_descriptors_capacity)
{ {
P_Panic(Lit("Max descriptors reached in heap")); Panic(Lit("Max descriptors reached in heap"));
} }
d = PushStructNoZero(dh->arena, GPU_D12_Descriptor); d = PushStructNoZero(dh->arena, GPU_D12_Descriptor);
index = dh->num_descriptors_reserved++; index = dh->num_descriptors_reserved++;
@ -1287,7 +1287,7 @@ GPU_D12_CpuDescriptorHeap *GPU_D12_AllocCpuDescriptorHeap(enum D3D12_DESCRIPTOR_
} }
if (num_descriptors == 0 || descriptor_size == 0) if (num_descriptors == 0 || descriptor_size == 0)
{ {
P_Panic(Lit("Unsupported CPU descriptor type")); Panic(Lit("Unsupported CPU descriptor type"));
} }
dh->num_descriptors_capacity = num_descriptors; dh->num_descriptors_capacity = num_descriptors;
dh->descriptor_size = descriptor_size; dh->descriptor_size = descriptor_size;
@ -1298,7 +1298,7 @@ GPU_D12_CpuDescriptorHeap *GPU_D12_AllocCpuDescriptorHeap(enum D3D12_DESCRIPTOR_
HRESULT hr = ID3D12Device_CreateDescriptorHeap(g->device, &desc, &IID_ID3D12DescriptorHeap, (void **)&dh->heap); HRESULT hr = ID3D12Device_CreateDescriptorHeap(g->device, &desc, &IID_ID3D12DescriptorHeap, (void **)&dh->heap);
if (FAILED(hr)) if (FAILED(hr))
{ {
P_Panic(Lit("Failed to create CPU descriptor heap")); Panic(Lit("Failed to create CPU descriptor heap"));
} }
ID3D12DescriptorHeap_GetCPUDescriptorHandleForHeapStart(dh->heap, &dh->handle); ID3D12DescriptorHeap_GetCPUDescriptorHandleForHeapStart(dh->heap, &dh->handle);
@ -1388,7 +1388,7 @@ GPU_D12_Resource *GPU_D12_AllocResource(D3D12_HEAP_PROPERTIES heap_props, D3D12_
if (FAILED(hr)) if (FAILED(hr))
{ {
/* TODO: Don't panic */ /* TODO: Don't panic */
P_Panic(Lit("Failed to create resource")); Panic(Lit("Failed to create resource"));
} }
r->state = initial_state; r->state = initial_state;
@ -1524,13 +1524,13 @@ JobDef(GPU_D12_AllocCommandQueueJob, sig, id)
HRESULT hr = ID3D12Device_CreateCommandQueue(g->device, &dx12_desc, &IID_ID3D12CommandQueue, (void **)&cq->cq); HRESULT hr = ID3D12Device_CreateCommandQueue(g->device, &dx12_desc, &IID_ID3D12CommandQueue, (void **)&cq->cq);
if (FAILED(hr)) if (FAILED(hr))
{ {
P_Panic(Lit("Failed to create command queue")); Panic(Lit("Failed to create command queue"));
} }
hr = ID3D12Device_CreateFence(g->device, 0, 0, &IID_ID3D12Fence, (void **)&cq->submit_fence); hr = ID3D12Device_CreateFence(g->device, 0, 0, &IID_ID3D12Fence, (void **)&cq->submit_fence);
if (FAILED(hr)) if (FAILED(hr))
{ {
P_Panic(Lit("Failed to create command queue fence")); Panic(Lit("Failed to create command queue fence"));
} }
cq->cl_pool = GPU_D12_AllocCommandListPool(cq); cq->cl_pool = GPU_D12_AllocCommandListPool(cq);
@ -1630,19 +1630,19 @@ GPU_D12_CommandList *GPU_D12_BeginCommandList(GPU_D12_CommandListPool *pool)
hr = ID3D12Device_CreateCommandAllocator(g->device, cq->desc.type, &IID_ID3D12CommandAllocator, (void **)&cl->ca); hr = ID3D12Device_CreateCommandAllocator(g->device, cq->desc.type, &IID_ID3D12CommandAllocator, (void **)&cl->ca);
if (FAILED(hr)) if (FAILED(hr))
{ {
P_Panic(Lit("Failed to create command allocator")); Panic(Lit("Failed to create command allocator"));
} }
hr = ID3D12Device_CreateCommandList(g->device, 0, cq->desc.type, cl->ca, 0, &IID_ID3D12GraphicsCommandList, (void **)&cl->cl); hr = ID3D12Device_CreateCommandList(g->device, 0, cq->desc.type, cl->ca, 0, &IID_ID3D12GraphicsCommandList, (void **)&cl->cl);
if (FAILED(hr)) if (FAILED(hr))
{ {
P_Panic(Lit("Failed to create command list")); Panic(Lit("Failed to create command list"));
} }
hr = ID3D12GraphicsCommandList_Close(cl->cl); hr = ID3D12GraphicsCommandList_Close(cl->cl);
if (FAILED(hr)) if (FAILED(hr))
{ {
P_Panic(Lit("Failed to close command list during initialization")); Panic(Lit("Failed to close command list during initialization"));
} }
} }
@ -1650,13 +1650,13 @@ GPU_D12_CommandList *GPU_D12_BeginCommandList(GPU_D12_CommandListPool *pool)
hr = ID3D12CommandAllocator_Reset(cl->ca); hr = ID3D12CommandAllocator_Reset(cl->ca);
if (FAILED(hr)) if (FAILED(hr))
{ {
P_Panic(Lit("Failed to reset command allocator")); Panic(Lit("Failed to reset command allocator"));
} }
hr = ID3D12GraphicsCommandList_Reset(cl->cl, cl->ca, 0); hr = ID3D12GraphicsCommandList_Reset(cl->cl, cl->ca, 0);
if (FAILED(hr)) if (FAILED(hr))
{ {
P_Panic(Lit("Failed to reset command list")); Panic(Lit("Failed to reset command list"));
} }
return cl; return cl;
@ -1677,7 +1677,7 @@ u64 GPU_D12_EndCommandList(GPU_D12_CommandList *cl)
if (FAILED(hr)) if (FAILED(hr))
{ {
/* TODO: Don't panic */ /* TODO: Don't panic */
P_Panic(Lit("Failed to close command list before execution")); Panic(Lit("Failed to close command list before execution"));
} }
} }
@ -1834,7 +1834,7 @@ GPU_D12_CommandDescriptorHeap *GPU_D12_PushDescriptorHeap(GPU_D12_CommandList *c
HRESULT hr = ID3D12Device_CreateDescriptorHeap(g->device, &desc, &IID_ID3D12DescriptorHeap, (void **)&cdh->heap); HRESULT hr = ID3D12Device_CreateDescriptorHeap(g->device, &desc, &IID_ID3D12DescriptorHeap, (void **)&cdh->heap);
if (FAILED(hr)) if (FAILED(hr))
{ {
P_Panic(Lit("Failed to create GPU descriptor heap")); Panic(Lit("Failed to create GPU descriptor heap"));
} }
ID3D12DescriptorHeap_GetCPUDescriptorHandleForHeapStart(cdh->heap, &cdh->start_cpu_handle); ID3D12DescriptorHeap_GetCPUDescriptorHandleForHeapStart(cdh->heap, &cdh->start_cpu_handle);
ID3D12DescriptorHeap_GetGPUDescriptorHandleForHeapStart(cdh->heap, &cdh->start_gpu_handle); ID3D12DescriptorHeap_GetGPUDescriptorHandleForHeapStart(cdh->heap, &cdh->start_gpu_handle);
@ -1987,7 +1987,7 @@ GPU_D12_CommandBuffer *GPU_D12__PushCommandBuffer(GPU_D12_CommandList *cl, u64 d
if (FAILED(hr) || !dst) if (FAILED(hr) || !dst)
{ {
/* TODO: Don't panic */ /* TODO: Don't panic */
P_Panic(Lit("Failed to map command buffer resource")); Panic(Lit("Failed to map command buffer resource"));
} }
CopyBytes(dst, data, data_len); CopyBytes(dst, data, data_len);
ID3D12Resource_Unmap(cb->resource->resource, 0, 0); ID3D12Resource_Unmap(cb->resource->resource, 0, 0);
@ -2029,7 +2029,7 @@ GPU_Resource *GPU_AllocTexture(GPU_TextureFormat format, u32 flags, Vec2I32 size
GPU_D12_SharedState *g = &GPU_D12_shared_state; GPU_D12_SharedState *g = &GPU_D12_shared_state;
if (size.x <= 0 || size.y <= 0) if (size.x <= 0 || size.y <= 0)
{ {
P_Panic(Lit("Tried to create texture with dimension <= 0")); Panic(Lit("Tried to create texture with dimension <= 0"));
} }
LocalPersist const DXGI_FORMAT formats[] = { LocalPersist const DXGI_FORMAT formats[] = {
[GP_TEXTURE_FORMAT_R8_UNORM] = DXGI_FORMAT_R8_UNORM, [GP_TEXTURE_FORMAT_R8_UNORM] = DXGI_FORMAT_R8_UNORM,
@ -2045,7 +2045,7 @@ GPU_Resource *GPU_AllocTexture(GPU_TextureFormat format, u32 flags, Vec2I32 size
} }
if (format == 0) if (format == 0)
{ {
P_Panic(Lit("Tried to create texture with unknown format")); Panic(Lit("Tried to create texture with unknown format"));
} }
D3D12_HEAP_PROPERTIES heap_props = { .Type = D3D12_HEAP_TYPE_DEFAULT }; D3D12_HEAP_PROPERTIES heap_props = { .Type = D3D12_HEAP_TYPE_DEFAULT };
@ -2158,7 +2158,7 @@ JobDef(GPU_D12_UploadJob, sig, UNUSED id)
if (FAILED(hr) || !mapped) if (FAILED(hr) || !mapped)
{ {
/* TODO: Don't panic */ /* TODO: Don't panic */
P_Panic(Lit("Failed to map texture upload resource")); Panic(Lit("Failed to map texture upload resource"));
} }
u8 *dst = (u8 *)mapped + placed_footprint.Offset; u8 *dst = (u8 *)mapped + placed_footprint.Offset;
u8 *src = data; u8 *src = data;
@ -2998,7 +2998,7 @@ void GPU_D12_InitSwapchainResources(GPU_D12_Swapchain *swapchain)
if (FAILED(hr)) if (FAILED(hr))
{ {
/* TODO: Don't panic */ /* TODO: Don't panic */
P_Panic(Lit("Failed to get swapchain buffer")); Panic(Lit("Failed to get swapchain buffer"));
} }
GPU_D12_SwapchainBuffer *sb = &swapchain->buffers[i]; GPU_D12_SwapchainBuffer *sb = &swapchain->buffers[i];
ZeroStruct(sb); ZeroStruct(sb);
@ -3050,7 +3050,7 @@ GPU_Swapchain *GPU_AllocSwapchain(P_Window *window, Vec2I32 resolution)
hr = IDXGIFactory2_CreateSwapChainForHwnd(g->factory, (IUnknown *)cq->cq, hwnd, &desc, 0, 0, &swapchain1); hr = IDXGIFactory2_CreateSwapChainForHwnd(g->factory, (IUnknown *)cq->cq, hwnd, &desc, 0, 0, &swapchain1);
if (FAILED(hr)) if (FAILED(hr))
{ {
P_Panic(Lit("Failed to create IDXGISwapChain1")); Panic(Lit("Failed to create IDXGISwapChain1"));
} }
} }
@ -3058,7 +3058,7 @@ GPU_Swapchain *GPU_AllocSwapchain(P_Window *window, Vec2I32 resolution)
hr = IDXGISwapChain1_QueryInterface(swapchain1, &IID_IDXGISwapChain3, (void **)&swapchain->swapchain); hr = IDXGISwapChain1_QueryInterface(swapchain1, &IID_IDXGISwapChain3, (void **)&swapchain->swapchain);
if (FAILED(hr)) if (FAILED(hr))
{ {
P_Panic(Lit("Failed to create IDXGISwapChain3")); Panic(Lit("Failed to create IDXGISwapChain3"));
} }
/* Create waitable object */ /* Create waitable object */
@ -3137,7 +3137,7 @@ GPU_D12_SwapchainBuffer *GPU_D12_UpdateSwapchain(GPU_D12_Swapchain *swapchain, V
if (FAILED(hr)) if (FAILED(hr))
{ {
/* TODO: Don't panic */ /* TODO: Don't panic */
P_Panic(Lit("Failed to resize swapchain")); Panic(Lit("Failed to resize swapchain"));
} }
} }
Unlock(&lock); Unlock(&lock);

View File

@ -425,7 +425,7 @@ extern GPU_D12_SharedState GPU_D12_shared_state;
* Startup * Startup
* ========================== */ * ========================== */
P_ExitFuncDef(GPU_D12_Shutdown); ExitFuncDef(GPU_D12_Shutdown);
/* ========================== * /* ========================== *
* Dx12 device initialization * Dx12 device initialization

View File

@ -11,6 +11,7 @@ void P_Main(void)
{ {
RunOnce(); RunOnce();
P_StartupDeps(); P_StartupDeps();
P_StartupCore();
/* FIXME: Logfile path */ /* FIXME: Logfile path */
P_StartupLog(Lit("log.log")); P_StartupLog(Lit("log.log"));
} }

View File

@ -302,10 +302,9 @@ typedef i32 P_MessageBoxKind; enum
}; };
//////////////////////////////// ////////////////////////////////
//~ Exit callback types //~ @hookdecl Startup
#define P_ExitFuncDef(name) void name(void) void P_StartupCore(void);
typedef P_ExitFuncDef(P_ExitFunc);
//////////////////////////////// ////////////////////////////////
//~ @hookdecl Time helper operations //~ @hookdecl Time helper operations
@ -412,9 +411,9 @@ void P_SleepFrame(i64 last_frame_time_ns, i64 target_dt_ns);
//////////////////////////////// ////////////////////////////////
//~ @hookdecl Program exit //~ @hookdecl Program exit
void P_OnExit(P_ExitFunc *func); void OnExit(ExitFunc *func);
void P_Exit(void); void Exit(void);
void P_Panic(String msg); void Panic(String msg);
//////////////////////////////// ////////////////////////////////
//~ @hookdecl Entry point (implemented per application) //~ @hookdecl Entry point (implemented per application)

View File

@ -145,7 +145,7 @@ void P_Log_(i32 level, String msg)
P_LogLevelSettings settings = P_log_settings[level]; P_LogLevelSettings settings = P_log_settings[level];
if (level < 0 || level >= P_LogLevel_Count) if (level < 0 || level >= P_LogLevel_Count)
{ {
P_Panic(Lit("Invalid log level")); Panic(Lit("Invalid log level"));
} }

View File

@ -122,8 +122,6 @@ void P_StartupLog(String logfile_path);
//////////////////////////////// ////////////////////////////////
//~ Logging macros //~ Logging macros
#define log_panic(msg) P_LogPanic_(msg)
#if P_LogLevel(P_LogLevel_Critical) #if P_LogLevel(P_LogLevel_Critical)
# if P_IncludeLogSourceLocation # if P_IncludeLogSourceLocation
# define P_LogCritical(msg) P_Log_(P_LogLevel_Critical, Lit(__FILE__), __LINE__, msg) # define P_LogCritical(msg) P_Log_(P_LogLevel_Critical, Lit(__FILE__), __LINE__, msg)

View File

@ -14,6 +14,107 @@ P_W32_SharedCtx P_W32_shared_ctx = ZI;
#pragma comment(lib, "avrt") #pragma comment(lib, "avrt")
#pragma comment(lib, "ws2_32.lib") #pragma comment(lib, "ws2_32.lib")
////////////////////////////////
//~ @hookdef Startup
void P_StartupCore(void)
{
P_W32_SharedCtx *g = &P_W32_shared_ctx;
//- Initialize btn table
{
ZeroArray(g->vk_btn_table);
for (u32 i = 'A', j = P_Btn_A; i <= 'Z'; ++i, ++j)
{
g->vk_btn_table[i] = (P_Btn)j;
}
for (u32 i = '0', j = P_Btn_0; i <= '9'; ++i, ++j)
{
g->vk_btn_table[i] = (P_Btn)j;
}
for (u32 i = VK_F1, j = P_Btn_F1; i <= VK_F24; ++i, ++j)
{
g->vk_btn_table[i] = (P_Btn)j;
}
g->vk_btn_table[VK_ESCAPE] = P_Btn_ESC;
g->vk_btn_table[VK_OEM_3] = P_Btn_GraveAccent;
g->vk_btn_table[VK_OEM_MINUS] = P_Btn_Minus;
g->vk_btn_table[VK_OEM_PLUS] = P_Btn_Equal;
g->vk_btn_table[VK_BACK] = P_Btn_Backspace;
g->vk_btn_table[VK_TAB] = P_Btn_Tab;
g->vk_btn_table[VK_SPACE] = P_Btn_Space;
g->vk_btn_table[VK_RETURN] = P_Btn_Enter;
g->vk_btn_table[VK_CONTROL] = P_Btn_Ctrl;
g->vk_btn_table[VK_SHIFT] = P_Btn_Shift;
g->vk_btn_table[VK_MENU] = P_Btn_Alt;
g->vk_btn_table[VK_UP] = P_Btn_Up;
g->vk_btn_table[VK_LEFT] = P_Btn_Left;
g->vk_btn_table[VK_DOWN] = P_Btn_Down;
g->vk_btn_table[VK_RIGHT] = P_Btn_Right;
g->vk_btn_table[VK_DELETE] = P_Btn_Delete;
g->vk_btn_table[VK_PRIOR] = P_Btn_PageUp;
g->vk_btn_table[VK_NEXT] = P_Btn_PageDown;
g->vk_btn_table[VK_HOME] = P_Btn_Home;
g->vk_btn_table[VK_END] = P_Btn_End;
g->vk_btn_table[VK_OEM_2] = P_Btn_ForwardSlash;
g->vk_btn_table[VK_OEM_PERIOD] = P_Btn_Period;
g->vk_btn_table[VK_OEM_COMMA] = P_Btn_Comma;
g->vk_btn_table[VK_OEM_7] = P_Btn_Quote;
g->vk_btn_table[VK_OEM_4] = P_Btn_LeftBracket;
g->vk_btn_table[VK_OEM_6] = P_Btn_RightBracket;
g->vk_btn_table[VK_INSERT] = P_Btn_Insert;
g->vk_btn_table[VK_OEM_1] = P_Btn_Semicolon;
}
//- Create window class
{
HMODULE instance = GetModuleHandle(0);
/* Register the window class */
WNDCLASSEXW *wc = &g->window_class;
wc->cbSize = sizeof(WNDCLASSEX);
wc->lpszClassName = P_W32_WindowClassName;
wc->hCursor = LoadCursor(0, IDC_ARROW);
wc->style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
//wc->hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
wc->lpfnWndProc = P_W32_Win32WindowProc;
wc->hInstance = instance;
/* Use first icon resource as window icon (same as explorer) */
wchar_t path[4096] = ZI;
GetModuleFileNameW(instance, path, countof(path));
ExtractIconExW(path, 0, &wc->hIcon, &wc->hIconSm, 1);
if (!RegisterClassExW(wc))
{
Panic(Lit("Failed to register window class"));
}
}
//- Register raw input
{
RAWINPUTDEVICE rid = (RAWINPUTDEVICE) {
.usUsagePage = 0x01, /* HID_USAGE_PAGE_GENERIC */
.usUsage = 0x02, /* HID_USAGE_GENERIC_MOUSE */
//.dwFlags = RIDEV_NOLEGACY /* Adds mouse and also ignores legacy mouse messages */
};
b32 success = RegisterRawInputDevices(&rid, 1, sizeof(rid));
Assert(success);
LAX success;
}
//- Init watches pool
g->watches_arena = AllocArena(Gibi(64));
//- Init windows pool
g->windows_arena = AllocArena(Gibi(64));
//- Init winsock
WSAStartup(MAKEWORD(2, 2), &g->wsa_data);
g->socks_arena = AllocArena(Gibi(64));
}
//////////////////////////////// ////////////////////////////////
//~ Win32 time //~ Win32 time
@ -864,7 +965,7 @@ void P_MkDir(String path)
Lit("Failed to create directory \"%F\": %F"), Lit("Failed to create directory \"%F\": %F"),
FmtString(path), FmtString(path),
FmtString(err)); FmtString(err));
P_Panic(msg); Panic(msg);
} }
EndScratch(scratch); EndScratch(scratch);
} }
@ -1018,7 +1119,7 @@ void P_WriteFile(P_File file, String data)
if (data.len >= 0x7FFF) if (data.len >= 0x7FFF)
{ {
TempArena scratch = BeginScratchNoConflict(); TempArena scratch = BeginScratchNoConflict();
P_Panic(StringFormat(scratch.arena, Panic(StringFormat(scratch.arena,
Lit("Tried to write too many bytes to disk (%F)"), Lit("Tried to write too many bytes to disk (%F)"),
FmtUint(data.len))); FmtUint(data.len)));
EndScratch(scratch); EndScratch(scratch);
@ -1922,386 +2023,3 @@ void P_SleepFrame(i64 last_frame_time_ns, i64 target_dt_ns)
} }
} }
} }
////////////////////////////////
//~ @hookdef Exit hooks
void P_OnExit(P_ExitFunc *func)
{
P_W32_SharedCtx *g = &P_W32_shared_ctx;
i32 index = Atomic32FetchAdd(&g->num_exit_funcs, 1);
if (index >= P_W32_MaxOnExitFuncs)
{
P_Panic(Lit("Maximum on exit functions registered"));
}
g->exit_funcs[index] = func;
}
void P_Exit(void)
{
P_W32_SharedCtx *g = &P_W32_shared_ctx;
SetEvent(g->exit_begin_event);
}
void P_Panic(String msg)
{
P_W32_SharedCtx *g = &P_W32_shared_ctx;
if (Atomic32FetchTestSet(&g->panicking, 0, 1) == 0)
{
log_panic(msg);
wchar_t *wstr = g->panic_wstr;
u64 WstrLen = 0;
wchar_t prefix[] = L"A fatal error has occured and the application needs to exit:\n\n";
CopyBytes(wstr, prefix, MinU64(countof(g->panic_wstr), (countof(prefix) << 1)));
WstrLen += countof(prefix) - 1;
/* Perform manual string encode to avoid any implicit memory
* allocation (in case allocation is unreliable) */
String str8 = msg;
u64 pos8 = 0;
while (pos8 < str8.len)
{
String str8_remaining = { .len = (str8.len - pos8), .text = str8.text + pos8 };
Utf8DecodeResult decoded = DecodeUtf8(str8_remaining);
Utf16EncodeResult encoded = EncodeUtf16(decoded.codepoint);
u64 wstr_new_len = WstrLen + encoded.count16;
if (wstr_new_len < (countof(g->panic_wstr) - 1))
{
u16 *dest = wstr + WstrLen;
CopyBytes(dest, encoded.chars16, (encoded.count16 << 1));
WstrLen = wstr_new_len;
pos8 += decoded.advance8;
}
else
{
break;
}
}
wstr[WstrLen] = 0;
#if RtcIsEnabled
MessageBoxExW(0, wstr, L"Fatal error", MB_ICONSTOP | MB_SETFOREGROUND | MB_TOPMOST, 0);
Assert(0);
#endif
SetEvent(g->panic_event);
/* Wait for process termination */
if (GetCurrentThreadId() != g->main_thread_id)
{
Sleep(INFINITE);
}
}
}
////////////////////////////////
//~ Win32 entry point
void P_W32_InitBtnTable(void)
{
P_W32_SharedCtx *g = &P_W32_shared_ctx;
ZeroArray(g->vk_btn_table);
for (u32 i = 'A', j = P_Btn_A; i <= 'Z'; ++i, ++j)
{
g->vk_btn_table[i] = (P_Btn)j;
}
for (u32 i = '0', j = P_Btn_0; i <= '9'; ++i, ++j)
{
g->vk_btn_table[i] = (P_Btn)j;
}
for (u32 i = VK_F1, j = P_Btn_F1; i <= VK_F24; ++i, ++j)
{
g->vk_btn_table[i] = (P_Btn)j;
}
g->vk_btn_table[VK_ESCAPE] = P_Btn_ESC;
g->vk_btn_table[VK_OEM_3] = P_Btn_GraveAccent;
g->vk_btn_table[VK_OEM_MINUS] = P_Btn_Minus;
g->vk_btn_table[VK_OEM_PLUS] = P_Btn_Equal;
g->vk_btn_table[VK_BACK] = P_Btn_Backspace;
g->vk_btn_table[VK_TAB] = P_Btn_Tab;
g->vk_btn_table[VK_SPACE] = P_Btn_Space;
g->vk_btn_table[VK_RETURN] = P_Btn_Enter;
g->vk_btn_table[VK_CONTROL] = P_Btn_Ctrl;
g->vk_btn_table[VK_SHIFT] = P_Btn_Shift;
g->vk_btn_table[VK_MENU] = P_Btn_Alt;
g->vk_btn_table[VK_UP] = P_Btn_Up;
g->vk_btn_table[VK_LEFT] = P_Btn_Left;
g->vk_btn_table[VK_DOWN] = P_Btn_Down;
g->vk_btn_table[VK_RIGHT] = P_Btn_Right;
g->vk_btn_table[VK_DELETE] = P_Btn_Delete;
g->vk_btn_table[VK_PRIOR] = P_Btn_PageUp;
g->vk_btn_table[VK_NEXT] = P_Btn_PageDown;
g->vk_btn_table[VK_HOME] = P_Btn_Home;
g->vk_btn_table[VK_END] = P_Btn_End;
g->vk_btn_table[VK_OEM_2] = P_Btn_ForwardSlash;
g->vk_btn_table[VK_OEM_PERIOD] = P_Btn_Period;
g->vk_btn_table[VK_OEM_COMMA] = P_Btn_Comma;
g->vk_btn_table[VK_OEM_7] = P_Btn_Quote;
g->vk_btn_table[VK_OEM_4] = P_Btn_LeftBracket;
g->vk_btn_table[VK_OEM_6] = P_Btn_RightBracket;
g->vk_btn_table[VK_INSERT] = P_Btn_Insert;
g->vk_btn_table[VK_OEM_1] = P_Btn_Semicolon;
}
JobDef(P_W32_AppStartupJob, UNUSED sig, UNUSED id)
{
P_W32_SharedCtx *g = &P_W32_shared_ctx;
TempArena scratch = BeginScratchNoConflict();
{
String cmdline_args = StringFromWstr(scratch.arena, g->cmdline_args_wstr, countof(g->cmdline_args_wstr));
P_AppStartup(cmdline_args);
SetEvent(g->startup_end_event);
}
EndScratch(scratch);
}
JobDef(P_W32_AppShutdownJob, UNUSED sig, UNUSED id)
{
__prof;
P_W32_SharedCtx *g = &P_W32_shared_ctx;
i32 num_funcs = Atomic32Fetch(&g->num_exit_funcs);
for (i32 i = num_funcs - 1; i >= 0; --i)
{
P_ExitFunc *func = g->exit_funcs[i];
func();
}
SetEvent(g->exit_end_event);
}
int CALLBACK wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev_instance, _In_ LPWSTR cmdline_wstr, _In_ int show_code)
{
P_Main();
LAX instance;
LAX prev_instance;
LAX cmdline_wstr;
LAX show_code;
__profthread("Main thread", PROF_THREAD_GROUP_MAIN);
P_W32_SharedCtx *g = &P_W32_shared_ctx;
#if ProfilingIsEnabled
/* Start profiler */
{
__profn("Launch profiler");
STARTUPINFO si = ZI;
si.cb = sizeof(si);
PROCESS_INFORMATION pi = ZI;
wchar_t cmd[sizeof(ProfilingCmdWstr)] = ZI;
CopyBytes(cmd, ProfilingCmdWstr, sizeof(ProfilingCmdWstr));
DeleteFileW(ProfilingOutFileWstr);
b32 success = CreateProcessW(0, cmd, 0, 0, 0, DETACHED_PROCESS, 0, 0, &si, &pi);
if (!success)
{
MessageBoxExW(0, L"Failed to launch profiler using command '" ProfilingCmdWstr L"'.", L"Error", MB_ICONSTOP | MB_SETFOREGROUND | MB_TOPMOST, 0);
}
}
/* Set internal profiler thread affinities */
{
__profn("Set profiler thread affinities");
wchar_t *prefix_name_wstr = ProfilerThreadPrefixWstr;
u64 prefix_name_wstr_len = ((i32)sizeof(ProfilerThreadPrefixWstr) >> 1) - 1;
if (prefix_name_wstr_len > 0 && ProfilerThreadAffinityMask != 0)
{
DWORD proc_id = GetCurrentProcessId();
HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
if (snapshot != INVALID_HANDLE_VALUE)
{
THREADENTRY32 te = ZI;
te.dwSize = sizeof(THREADENTRY32);
if (Thread32First(snapshot, &te))
{
do
{
if (te.th32OwnerProcessID == proc_id)
{
i32 thread_id = te.th32ThreadID;
HANDLE thread = OpenThread(THREAD_ALL_ACCESS, FALSE, thread_id);
if (thread)
{
wchar_t *thread_name_wstr = 0;
HRESULT hr = GetThreadDescription(thread, &thread_name_wstr);
if (SUCCEEDED(hr))
{
u64 thread_name_len = WstrLenNoLimit(thread_name_wstr);
if (thread_name_len >= prefix_name_wstr_len && EqBytes(thread_name_wstr, prefix_name_wstr, prefix_name_wstr_len))
{
__profn("Set profiler thread affinity");
b32 success = SetThreadAffinityMask(thread, ProfilerThreadAffinityMask) != 0;
{
/* Retry until external tools can set correct process affinity */
i32 delay_ms = 16;
while (!success && delay_ms <= 1024)
{
__profn("Profiler thread affinity retry");
Sleep(delay_ms);
success = SetThreadAffinityMask(thread, ProfilerThreadAffinityMask) != 0;
delay_ms *= 2;
}
}
Assert(success);
LAX success;
}
}
CloseHandle(thread);
}
}
} while (Thread32Next(snapshot, &te));
}
}
CloseHandle(snapshot);
}
}
#endif
/* Set up exit events */
g->panic_event = CreateEventW(0, 1, 0, 0);
g->startup_end_event = CreateEventW(0, 1, 0, 0);
g->exit_begin_event = CreateEventW(0, 1, 0, 0);
g->exit_end_event = CreateEventW(0, 1, 0, 0);
u64 cmdline_len = WstrLen(cmdline_wstr, countof(g->cmdline_args_wstr) - 1);
CopyBytes(g->cmdline_args_wstr, cmdline_wstr, cmdline_len * sizeof(*cmdline_wstr));
g->cmdline_args_wstr[cmdline_len] = 0;
g->main_thread_id = GetCurrentThreadId();
SetThreadDescription(GetCurrentThread(), L"Main thread");
/* Query system info */
GetSystemInfo(&g->info);
/* Initialize vk table */
P_W32_InitBtnTable();
/* Create window class */
{
/* Register the window class */
WNDCLASSEXW *wc = &g->window_class;
wc->cbSize = sizeof(WNDCLASSEX);
wc->lpszClassName = P_W32_WindowClassName;
wc->hCursor = LoadCursor(0, IDC_ARROW);
wc->style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
//wc->hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
wc->lpfnWndProc = P_W32_Win32WindowProc;
wc->hInstance = instance;
/* Use first icon resource as window icon (same as explorer) */
wchar_t path[4096] = ZI;
GetModuleFileNameW(instance, path, countof(path));
ExtractIconExW(path, 0, &wc->hIcon, &wc->hIconSm, 1);
if (!RegisterClassExW(wc))
{
P_Panic(Lit("Failed to register window class"));
}
}
/* Register raw input */
if (!Atomic32Fetch(&g->panicking))
{
RAWINPUTDEVICE rid = (RAWINPUTDEVICE) {
.usUsagePage = 0x01, /* HID_USAGE_PAGE_GENERIC */
.usUsage = 0x02, /* HID_USAGE_GENERIC_MOUSE */
//.dwFlags = RIDEV_NOLEGACY /* Adds mouse and also ignores legacy mouse messages */
};
b32 success = RegisterRawInputDevices(&rid, 1, sizeof(rid));
Assert(success);
LAX success;
}
/* Init watches pool */
g->watches_arena = AllocArena(Gibi(64));
/* Init windows pool */
g->windows_arena = AllocArena(Gibi(64));
/* Init winsock */
WSAStartup(MAKEWORD(2, 2), &g->wsa_data);
g->socks_arena = AllocArena(Gibi(64));
//- App startup
/* Run app start job */
if (!Atomic32Fetch(&g->panicking))
{
RunJob(1, P_W32_AppStartupJob, 0, JobPool_Floating, JobPriority_High, 0);
}
/* Wait for startup end or panic */
if (!Atomic32Fetch(&g->panicking))
{
HANDLE handles[] = {
g->startup_end_event,
g->panic_event
};
WaitForMultipleObjects(countof(handles), handles, 0, INFINITE);
}
/* Wait for exit start or panic */
if (!Atomic32Fetch(&g->panicking))
{
HANDLE handles[] = {
g->exit_begin_event,
g->panic_event
};
WaitForMultipleObjects(countof(handles), handles, 0, INFINITE);
}
//- App shutdown
/* Run exit callbacks job */
if (!Atomic32Fetch(&g->panicking))
{
RunJob(1, P_W32_AppShutdownJob, 0, JobPool_Floating, JobPriority_High, 0);
}
/* Wait for exit end or panic */
if (!Atomic32Fetch(&g->panicking))
{
HANDLE handles[] = {
g->exit_end_event,
g->panic_event
};
WaitForMultipleObjects(countof(handles), handles, 0, INFINITE);
}
/* Exit */
i32 exit_code = 0;
if (Atomic32Fetch(&g->panicking))
{
WaitForSingleObject(g->panic_event, INFINITE);
MessageBoxExW(0, g->panic_wstr, L"Fatal error", MB_ICONSTOP | MB_SETFOREGROUND | MB_TOPMOST, 0);
exit_code = 1;
}
return exit_code;
}
////////////////////////////////
//~ Crt stub
#if !CrtlibIsEnabled
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wmissing-variable-declarations"
#pragma clang diagnostic ignored "-Wmissing-prototypes"
/* Enable floating point */
__attribute((used))
int _fltused;
__attribute((used))
void __stdcall wWinMainCRTStartup(void)
{
int result = wWinMain(GetModuleHandle(0), 0, GetCommandLineW(), 0);
ExitProcess(result);
}
#pragma clang diagnostic pop
#endif /* !CrtlibIsEnabled */

View File

@ -108,24 +108,8 @@ Struct(P_W32_Sock)
#define P_W32_WindowClassName L"power_play_window_class" #define P_W32_WindowClassName L"power_play_window_class"
#define P_W32_MaxOnExitFuncs 1024
Struct(P_W32_SharedCtx) Struct(P_W32_SharedCtx)
{ {
SYSTEM_INFO info;
u32 main_thread_id;
Atomic32 shutdown;
wchar_t cmdline_args_wstr[8192];
//- Application control flow
Atomic32 panicking;
wchar_t panic_wstr[4096];
HANDLE panic_event;
HANDLE startup_end_event;
HANDLE exit_begin_event;
HANDLE exit_end_event;
//- Key lookup table //- Key lookup table
P_Btn vk_btn_table[256]; P_Btn vk_btn_table[256];
@ -145,10 +129,6 @@ Struct(P_W32_SharedCtx)
Arena *socks_arena; Arena *socks_arena;
Mutex socks_mutex; Mutex socks_mutex;
P_W32_Sock *first_free_sock; P_W32_Sock *first_free_sock;
//- Exit funcs
Atomic32 num_exit_funcs;
P_ExitFunc *exit_funcs[P_W32_MaxOnExitFuncs];
}; };
extern P_W32_SharedCtx P_W32_shared_ctx; extern P_W32_SharedCtx P_W32_shared_ctx;
@ -186,10 +166,3 @@ LRESULT CALLBACK P_W32_Win32WindowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARA
P_W32_Address P_W32_Win32AddressFromPlatformAddress(P_Address addr); P_W32_Address P_W32_Win32AddressFromPlatformAddress(P_Address addr);
P_W32_Address P_W32_ConvertAnyaddrToLocalhost(P_W32_Address addr); P_W32_Address P_W32_ConvertAnyaddrToLocalhost(P_W32_Address addr);
P_Address P_W32_PlatformAddressFromWin32Address(P_W32_Address ws_addr); P_Address P_W32_PlatformAddressFromWin32Address(P_W32_Address ws_addr);
////////////////////////////////
//~ Entry point
void P_W32_InitBtnTable(void);
JobDecl(P_W32_AppStartupJob, EmptySig);
JobDecl(P_W32_AppShutdownJob, EmptySig);

View File

@ -16,10 +16,10 @@ void PB_StartupCore(void)
PB_WSP_InitializeWasapi(); PB_WSP_InitializeWasapi();
/* Start playback job */ /* Start playback job */
RunJob(1, PB_WSP_PlaybackJob, 0, JobPool_Audio, JobPriority_High, &g->PB_WSP_PlaybackJob_counter); RunJob(1, PB_WSP_PlaybackJob, 0, JobPool_Audio, JobPriority_High, &g->PB_WSP_PlaybackJob_counter);
P_OnExit(&PB_WSP_Shutdown); OnExit(&PB_WSP_Shutdown);
} }
P_ExitFuncDef(PB_WSP_Shutdown) ExitFuncDef(PB_WSP_Shutdown)
{ {
__prof; __prof;
PB_WSP_SharedState *g = &PB_WSP_shared_state; PB_WSP_SharedState *g = &PB_WSP_shared_state;

View File

@ -48,7 +48,7 @@ extern PB_WSP_SharedState PB_WSP_shared_state;
//~ Wasapi startup //~ Wasapi startup
void PB_WSP_InitializeWasapi(void); void PB_WSP_InitializeWasapi(void);
P_ExitFuncDef(PB_WSP_Shutdown); ExitFuncDef(PB_WSP_Shutdown);
//////////////////////////////// ////////////////////////////////
//~ Playback update //~ Playback update

View File

@ -46,13 +46,13 @@ void StartupUser(void)
/* Start jobs */ /* Start jobs */
RunJob(1, UpdateUserJob, 0, JobPool_User, JobPriority_High, &g->shutdown_job_counters); RunJob(1, UpdateUserJob, 0, JobPool_User, JobPriority_High, &g->shutdown_job_counters);
RunJob(1, SimJob, 0, JobPool_Sim, JobPriority_High, &g->shutdown_job_counters); RunJob(1, SimJob, 0, JobPool_Sim, JobPriority_High, &g->shutdown_job_counters);
P_OnExit(&ShutdownUser); OnExit(&ShutdownUser);
} }
//////////////////////////////// ////////////////////////////////
//~ Shutdown //~ Shutdown
P_ExitFuncDef(ShutdownUser) ExitFuncDef(ShutdownUser)
{ {
__prof; __prof;
SharedUserState *g = &shared_user_state; SharedUserState *g = &shared_user_state;
@ -553,7 +553,7 @@ void UpdateUser(P_Window *window)
P_WindowEvent *event = &events.events[ent_index]; P_WindowEvent *event = &events.events[ent_index];
if (event->kind == P_WindowEventKind_Quit) if (event->kind == P_WindowEventKind_Quit)
{ {
P_Exit(); Exit();
} }
if (event->kind == P_WindowEventKind_ButtonUp) if (event->kind == P_WindowEventKind_ButtonUp)
@ -561,7 +561,7 @@ void UpdateUser(P_Window *window)
/* Escape quit */ /* Escape quit */
if (event->button == P_Btn_ESC) if (event->button == P_Btn_ESC)
{ {
P_Exit(); Exit();
} }
} }

View File

@ -257,7 +257,7 @@ void StartupUser(void);
//////////////////////////////// ////////////////////////////////
//~ Shutdown //~ Shutdown
P_ExitFuncDef(ShutdownUser); ExitFuncDef(ShutdownUser);
//////////////////////////////// ////////////////////////////////
//~ Debug draw operations //~ Debug draw operations

View File

@ -13,14 +13,14 @@ void RES_StartupCore(void)
String embedded_data = INC_GetResTar(); String embedded_data = INC_GetResTar();
if (embedded_data.len <= 0) if (embedded_data.len <= 0)
{ {
P_Panic(Lit("No embedded resources found")); Panic(Lit("No embedded resources found"));
} }
g->archive = TAR_ArchiveFromString(g->arena, embedded_data, Lit("")); g->archive = TAR_ArchiveFromString(g->arena, embedded_data, Lit(""));
#else #else
/* Ensure we have the right working directory */ /* Ensure we have the right working directory */
if (!P_IsDir(Lit("res"))) if (!P_IsDir(Lit("res")))
{ {
P_Panic(Lit("Resource directory \"res\" not found. Make sure the executable is being launched from the correct working directory.")); Panic(Lit("Resource directory \"res\" not found. Make sure the executable is being launched from the correct working directory."));
} }
#endif #endif
} }

View File

@ -44,7 +44,7 @@ void S_StartupCore(void)
RunJob(1, S_EvictorJob, JobPool_Background, JobPriority_Low, &g->shutdown_counter, 0); RunJob(1, S_EvictorJob, JobPool_Background, JobPriority_Low, &g->shutdown_counter, 0);
P_OnExit(&S_Shutdown); OnExit(&S_Shutdown);
#if RESOURCE_RELOADING #if RESOURCE_RELOADING
W_RegisterCallback(&S_WatchSpriteCallback); W_RegisterCallback(&S_WatchSpriteCallback);
#endif #endif
@ -53,7 +53,7 @@ void S_StartupCore(void)
//////////////////////////////// ////////////////////////////////
//~ Shutdown //~ Shutdown
P_ExitFuncDef(S_Shutdown) ExitFuncDef(S_Shutdown)
{ {
__prof; __prof;
S_SharedState *g = &S_shared_state; S_SharedState *g = &S_shared_state;
@ -433,7 +433,7 @@ JobDef(S_LoadSpriteJob, sig, UNUSED id)
{ {
S_LoadCacheEntrySheet(ref, tag); S_LoadCacheEntrySheet(ref, tag);
} break; } break;
default: { P_Panic(Lit("Unknown sprite cache node kind")); } break; default: { Panic(Lit("Unknown sprite cache node kind")); } break;
} }
S_EndScope(scope); S_EndScope(scope);
} }
@ -665,7 +665,7 @@ S_ScopeCacheEntryRef *S_EnsureRefUnsafely(S_Scope *scope, S_CacheEntry *e)
{ {
if (scope->num_references >= S_MaxScopeReferences) if (scope->num_references >= S_MaxScopeReferences)
{ {
P_Panic(Lit("Max sprite scope references reached")); Panic(Lit("Max sprite scope references reached"));
} }
/* Increment refcount */ /* Increment refcount */
@ -908,7 +908,7 @@ void *S_DataFromTag(S_Scope *scope, S_Tag tag, S_CacheEntryKind kind, b32 await)
{ {
case S_CacheEntryKind_Texture: { result = g->loading_texture; } break; case S_CacheEntryKind_Texture: { result = g->loading_texture; } break;
case S_CacheEntryKind_Sheet: { result = g->loading_sheet; } break; case S_CacheEntryKind_Sheet: { result = g->loading_sheet; } break;
default: { P_Panic(Lit("Unknown sprite cache entry kind")); } break; default: { Panic(Lit("Unknown sprite cache entry kind")); } break;
} }
S_ScopeCacheEntryRef *scope_ref = S_EntryFromTag(scope, tag, kind, 0); S_ScopeCacheEntryRef *scope_ref = S_EntryFromTag(scope, tag, kind, 0);
@ -921,7 +921,7 @@ void *S_DataFromTag(S_Scope *scope, S_Tag tag, S_CacheEntryKind kind, b32 await)
{ {
case S_CacheEntryKind_Texture: { result = ref.e->texture; } break; case S_CacheEntryKind_Texture: { result = ref.e->texture; } break;
case S_CacheEntryKind_Sheet: { result = ref.e->sheet; } break; case S_CacheEntryKind_Sheet: { result = ref.e->sheet; } break;
default: { P_Panic(Lit("Unknown sprite cache entry kind")); } break; default: { Panic(Lit("Unknown sprite cache entry kind")); } break;
} }
} }
else if (state == S_CacheEntryState_None) else if (state == S_CacheEntryState_None)
@ -944,7 +944,7 @@ void *S_DataFromTag(S_Scope *scope, S_Tag tag, S_CacheEntryKind kind, b32 await)
S_LoadCacheEntrySheet(ref, tag); S_LoadCacheEntrySheet(ref, tag);
result = ref.e->sheet; result = ref.e->sheet;
} break; } break;
default: { P_Panic(Lit("Unknown sprite cache entry kind")); } break; default: { Panic(Lit("Unknown sprite cache entry kind")); } break;
} }
} }
else else

View File

@ -260,7 +260,7 @@ void S_StartupCore(void);
//////////////////////////////// ////////////////////////////////
//~ Shutdown //~ Shutdown
P_ExitFuncDef(S_Shutdown); ExitFuncDef(S_Shutdown);
//////////////////////////////// ////////////////////////////////
//~ Purple-black image //~ Purple-black image

View File

@ -45,7 +45,7 @@ void TTF_StartupCore(void)
if (error != S_OK) if (error != S_OK)
{ {
/* FIXME: Enable this */ /* FIXME: Enable this */
//P_Panic(Lit("Error creating DWrite factory")); //Panic(Lit("Error creating DWrite factory"));
(*(volatile int *)0) = 0; (*(volatile int *)0) = 0;
} }
} }

View File

@ -12,10 +12,10 @@ void W_StartupCore(void)
RunJob(1, W_MonitorJob, JobPool_Floating, JobPriority_Low, &g->watch_jobs_counter, 0); RunJob(1, W_MonitorJob, JobPool_Floating, JobPriority_Low, &g->watch_jobs_counter, 0);
RunJob(1, W_DispatcherJob, JobPool_Floating, JobPriority_Low, &g->watch_jobs_counter, 0); RunJob(1, W_DispatcherJob, JobPool_Floating, JobPriority_Low, &g->watch_jobs_counter, 0);
P_OnExit(&W_Shutdown); OnExit(&W_Shutdown);
} }
P_ExitFuncDef(W_Shutdown) ExitFuncDef(W_Shutdown)
{ {
__prof; __prof;
W_SharedState *g = &W_shared_state; W_SharedState *g = &W_shared_state;
@ -43,7 +43,7 @@ void W_RegisterCallback(W_CallbackFunc *callback)
} }
else else
{ {
P_Panic(Lit("Max resource watch callbacks reached")); Panic(Lit("Max resource watch callbacks reached"));
} }
} }
Unlock(&lock); Unlock(&lock);

View File

@ -42,7 +42,7 @@ extern W_SharedState W_shared_state;
//~ Startup //~ Startup
void W_StartupCore(void); void W_StartupCore(void);
P_ExitFuncDef(W_Shutdown); ExitFuncDef(W_Shutdown);
//////////////////////////////// ////////////////////////////////
//~ Watch operations //~ Watch operations