job refactor progress
This commit is contained in:
parent
0d8531e740
commit
632f12dd63
@ -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;
|
||||
TempArena scratch = BeginScratchNoConflict();
|
||||
SharedAppState *g = &shared_app_state;
|
||||
|
||||
String args_str = Lit("");
|
||||
AppArgList args = ParseAppArgs(scratch.arena, args_str);
|
||||
String logfile_name = Lit("log.log");
|
||||
String settings_file_name = Lit("settings.txt");
|
||||
@ -217,7 +218,7 @@ void P_AppStartup(String args_str)
|
||||
),
|
||||
FmtString(settings_path),
|
||||
FmtString(error));
|
||||
P_Panic(msg);
|
||||
Panic(msg);
|
||||
}
|
||||
P_LogInfoF("Settings file loaded successfully");
|
||||
window_settings = *deser;
|
||||
|
||||
@ -119,7 +119,7 @@ AC_Asset *AC_TouchCache(String key, u64 hash, b32 *is_first_touch)
|
||||
{
|
||||
if (g->num_assets >= AC_MaxAssets)
|
||||
{
|
||||
P_Panic(Lit("Max assets reached"));
|
||||
Panic(Lit("Max assets reached"));
|
||||
}
|
||||
String key_stored = ZI;
|
||||
{
|
||||
|
||||
@ -30,6 +30,7 @@ inline void StartupBaseDeps(void)
|
||||
# include "base_rand.h"
|
||||
# include "base_util.h"
|
||||
# include "base_incbin.h"
|
||||
# include "base_entry.h"
|
||||
#if PlatformIsWindows
|
||||
# include "win32/base_win32.h"
|
||||
#endif
|
||||
|
||||
@ -18,7 +18,7 @@ Arena *AllocArena(u64 reserve)
|
||||
{
|
||||
/* Hard fail on memory reserve failure for now */
|
||||
/* FIXME: Enable this */
|
||||
//P_Panic(Lit("Failed to reserve memory"));
|
||||
//Panic(Lit("Failed to reserve memory"));
|
||||
(*(volatile int *)0) = 0;
|
||||
}
|
||||
u64 reserved = reserve;
|
||||
@ -30,7 +30,7 @@ Arena *AllocArena(u64 reserve)
|
||||
{
|
||||
/* Hard fail on commit failure */
|
||||
/* 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;
|
||||
}
|
||||
|
||||
@ -89,7 +89,7 @@ void *PushBytesNoZero(Arena *arena, u64 size, u64 align)
|
||||
{
|
||||
/* Hard fail if we overflow reserved memory for now */
|
||||
/* 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;
|
||||
}
|
||||
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 */
|
||||
/* 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;
|
||||
}
|
||||
arena->committed += commit_bytes;
|
||||
|
||||
17
src/base/base_entry.h
Normal file
17
src/base/base_entry.h
Normal 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);
|
||||
@ -55,7 +55,7 @@ String StringFromIncbinRcResource(IncbinRcResource *inc)
|
||||
if (!params.found)
|
||||
{
|
||||
/* FIXME: enable this */
|
||||
//P_Panic(StringFormat(scratch.arena,
|
||||
//Panic(StringFormat(scratch.arena,
|
||||
// Lit("INCBIN include not found in RC file: \"%F\""),
|
||||
// FmtString(inc->rc_name)));
|
||||
(*(volatile int *)0) = 0;
|
||||
|
||||
@ -93,7 +93,6 @@ void RunJobEx(GenericJobDesc *desc);
|
||||
//~ @hookdecl Helpers
|
||||
|
||||
i64 TimeNs(void);
|
||||
|
||||
u32 GetLogicalProcessorCount(void);
|
||||
u32 ThreadId(void);
|
||||
u32 GetLogicalProcessorCount(void);
|
||||
i64 GetCurrentSchedulerPeriodNs(void);
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
#include "base_win32.h"
|
||||
|
||||
#include "base_win32_job.c"
|
||||
#include "base_win32_entry.c"
|
||||
|
||||
@ -4,5 +4,6 @@
|
||||
#include "../base.h"
|
||||
|
||||
#include "base_win32_job.h"
|
||||
#include "base_win32_entry.h"
|
||||
|
||||
#endif
|
||||
|
||||
292
src/base/win32/base_win32_entry.c
Normal file
292
src/base/win32/base_win32_entry.c
Normal 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 */
|
||||
33
src/base/win32/base_win32_entry.h
Normal file
33
src/base/win32/base_win32_entry.h
Normal 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);
|
||||
@ -1,4 +1,4 @@
|
||||
W32_SharedCtx W32_shared_ctx = ZI;
|
||||
W32_SharedJobCtx W32_shared_job_ctx = ZI;
|
||||
|
||||
/* FIXME: Enable logs, panic, shutdown */
|
||||
|
||||
@ -21,7 +21,7 @@ W32_SharedCtx W32_shared_ctx = ZI;
|
||||
|
||||
void StartupBaseJobs(void)
|
||||
{
|
||||
W32_SharedCtx *g = &W32_shared_ctx;
|
||||
W32_SharedJobCtx *g = &W32_shared_job_ctx;
|
||||
|
||||
/* Init timer */
|
||||
{
|
||||
@ -133,7 +133,7 @@ void StartupBaseJobs(void)
|
||||
}
|
||||
}
|
||||
|
||||
//P_OnExit(ShutdownJobs);
|
||||
//OnExit(ShutdownJobs);
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
@ -195,7 +195,7 @@ void ShutdownJobs(void)
|
||||
++num_dangling_threads;
|
||||
}
|
||||
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);
|
||||
}
|
||||
UnlockTicketMutex(&g->threads_tm);
|
||||
@ -237,7 +237,7 @@ W32_Thread *W32_AllocThread(W32_ThreadFunc *entry_point, void *thread_data, Stri
|
||||
{
|
||||
__prof;
|
||||
TempArena scratch = BeginScratchNoConflict();
|
||||
W32_SharedCtx *g = &W32_shared_ctx;
|
||||
W32_SharedJobCtx *g = &W32_shared_job_ctx;
|
||||
Assert(entry_point != 0);
|
||||
//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)
|
||||
{
|
||||
//P_Panic(Lit("Failed to create thread"));
|
||||
//Panic(Lit("Failed to create thread"));
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
__prof;
|
||||
W32_SharedCtx *g = &W32_shared_ctx;
|
||||
W32_SharedJobCtx *g = &W32_shared_job_ctx;
|
||||
b32 success = 0;
|
||||
W32_Thread *t = (W32_Thread *)thread;
|
||||
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 */
|
||||
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 */
|
||||
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)
|
||||
{
|
||||
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;
|
||||
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)
|
||||
{
|
||||
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;
|
||||
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 */
|
||||
W32_Fiber *W32_AllocFiber(W32_JobPool *pool)
|
||||
{
|
||||
W32_SharedCtx *g = &W32_shared_ctx;
|
||||
W32_SharedJobCtx *g = &W32_shared_job_ctx;
|
||||
i16 fiber_id = 0;
|
||||
W32_Fiber *fiber = 0;
|
||||
char *new_name_cstr = 0;
|
||||
@ -730,7 +730,7 @@ W32_Fiber *W32_AllocFiber(W32_JobPool *pool)
|
||||
fiber_id = g->num_fibers++;
|
||||
if (fiber_id >= MaxFibers)
|
||||
{
|
||||
//P_Panic(Lit("Max fibers reached"));
|
||||
//Panic(Lit("Max fibers reached"));
|
||||
}
|
||||
fiber = &g->fibers[fiber_id];
|
||||
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
|
||||
ForceInline W32_Fiber *W32_FiberFromId(i16 id)
|
||||
{
|
||||
W32_SharedCtx *g = &W32_shared_ctx;
|
||||
W32_SharedJobCtx *g = &W32_shared_job_ctx;
|
||||
if (id <= 0)
|
||||
{
|
||||
return 0;
|
||||
@ -898,7 +898,7 @@ void W32_FiberEntryPoint(void *id_ptr)
|
||||
|
||||
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;
|
||||
JobPool pool_kind = ctx->pool_kind;
|
||||
W32_JobPool *pool = &g->job_pools[pool_kind];
|
||||
@ -1066,7 +1066,7 @@ W32_ThreadDef(W32_JobWorkerEntryFunc, worker_ctx_arg)
|
||||
{
|
||||
/* Invalid yield kind */
|
||||
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);
|
||||
} break;
|
||||
|
||||
@ -1280,7 +1280,7 @@ W32_ThreadDef(W32_JobWorkerEntryFunc, worker_ctx_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;
|
||||
@ -1293,7 +1293,7 @@ W32_ThreadDef(W32_JobSchedulerEntryFunc, UNUSED arg)
|
||||
HANDLE timer = CreateWaitableTimerExW(0, 0, CREATE_WAITABLE_TIMER_HIGH_RESOLUTION, TIMER_ALL_ACCESS);
|
||||
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 */
|
||||
@ -1419,7 +1419,7 @@ GenericJobDesc *PushJobDesc_(u64 sig_size, u64 sig_align, GenericJobFunc *func,
|
||||
void RunJobEx(GenericJobDesc *desc)
|
||||
{
|
||||
__prof;
|
||||
struct W32_SharedCtx *g = &W32_shared_ctx;
|
||||
struct W32_SharedJobCtx *g = &W32_shared_job_ctx;
|
||||
i32 count = desc->count;
|
||||
Counter *counter = desc->counter;
|
||||
JobPool pool_kind = desc->pool;
|
||||
@ -1496,25 +1496,25 @@ void RunJobEx(GenericJobDesc *desc)
|
||||
|
||||
i64 TimeNs(void)
|
||||
{
|
||||
struct W32_SharedCtx *g = &W32_shared_ctx;
|
||||
struct W32_SharedJobCtx *g = &W32_shared_job_ctx;
|
||||
LARGE_INTEGER qpc;
|
||||
QueryPerformanceCounter(&qpc);
|
||||
i64 result = (qpc.QuadPart - g->timer_start_qpc) * g->ns_per_qpc;
|
||||
return result;
|
||||
}
|
||||
|
||||
u32 GetLogicalProcessorCount(void)
|
||||
{
|
||||
return GetActiveProcessorCount(ALL_PROCESSOR_GROUPS);
|
||||
}
|
||||
|
||||
u32 ThreadId(void)
|
||||
{
|
||||
return GetCurrentThreadId();
|
||||
}
|
||||
|
||||
u32 GetLogicalProcessorCount(void)
|
||||
{
|
||||
return GetActiveProcessorCount(ALL_PROCESSOR_GROUPS);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@ -213,7 +213,7 @@ AlignedStruct(W32_JobPool, 64)
|
||||
/* Arbitrary threshold for determining when to fall back from a looped WakeByAddressSingle to WakeByAddressAll */
|
||||
#define W32_WakeAllThreshold 16
|
||||
|
||||
Struct(W32_SharedCtx)
|
||||
Struct(W32_SharedJobCtx)
|
||||
{
|
||||
i64 timer_start_qpc;
|
||||
i64 ns_per_qpc;
|
||||
@ -249,7 +249,7 @@ Struct(W32_SharedCtx)
|
||||
W32_JobPool job_pools[JobPool_Count];
|
||||
};
|
||||
|
||||
extern W32_SharedCtx W32_shared_ctx;
|
||||
extern W32_SharedJobCtx W32_shared_job_ctx;
|
||||
|
||||
////////////////////////////////
|
||||
//~ Startup
|
||||
|
||||
@ -40,7 +40,7 @@ JobDef(F_LoadJob, sig, _)
|
||||
if (!RES_ResourceExists(&res))
|
||||
{
|
||||
/* FIME: Load baked font instead of panicking */
|
||||
P_Panic(StringFormat(scratch.arena,
|
||||
Panic(StringFormat(scratch.arena,
|
||||
Lit("Font \"%F\" not found"),
|
||||
FmtString(path)));
|
||||
}
|
||||
@ -70,7 +70,7 @@ JobDef(F_LoadJob, sig, _)
|
||||
/* FIXME: Load baked font instead of panicking */
|
||||
if (font->glyphs_count <= 0)
|
||||
{
|
||||
P_Panic(StringFormat(scratch.arena,
|
||||
Panic(StringFormat(scratch.arena,
|
||||
Lit("Parsed 0 glyphs from font \"%F\"!"),
|
||||
FmtString(path)));
|
||||
}
|
||||
|
||||
@ -24,7 +24,7 @@ void GPU_StartupCore(void)
|
||||
GPU_D12_SharedState *g = &GPU_D12_shared_state;
|
||||
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 */
|
||||
@ -53,7 +53,7 @@ void GPU_StartupCore(void)
|
||||
String embedded_data = INC_GetDxcTar();
|
||||
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(""));
|
||||
|
||||
@ -68,13 +68,13 @@ void GPU_StartupCore(void)
|
||||
#if RESOURCE_RELOADING
|
||||
W_RegisterCallback(GPU_D12_WatchPipelineCallback);
|
||||
#endif
|
||||
P_OnExit(GPU_D12_Shutdown);
|
||||
OnExit(GPU_D12_Shutdown);
|
||||
|
||||
/* Start evictor job */
|
||||
RunJob(1, GPU_D12_EvictorJob, JobPool_Background, JobPriority_Low, &g->evictor_job_counter, 0);
|
||||
}
|
||||
|
||||
P_ExitFuncDef(GPU_D12_Shutdown)
|
||||
ExitFuncDef(GPU_D12_Shutdown)
|
||||
{
|
||||
__prof;
|
||||
GPU_D12_SharedState *g = &GPU_D12_shared_state;
|
||||
@ -108,7 +108,7 @@ void GPU_D12_PushInitError(String error)
|
||||
{
|
||||
TempArena scratch = BeginScratchNoConflict();
|
||||
String msg = StringFormat(scratch.arena, Lit("Failed to initialize DirectX 12.\n\n%F"), FmtString(error));
|
||||
P_Panic(msg);
|
||||
Panic(msg);
|
||||
EndScratch(scratch);
|
||||
}
|
||||
|
||||
@ -464,7 +464,7 @@ void GPU_D12_InitNoise(void)
|
||||
String data = RES_GetResourceData(&noise_res);
|
||||
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)"),
|
||||
FmtUint(K_BLUE_NOISE_TEX_WIDTH), FmtUint(K_BLUE_NOISE_TEX_HEIGHT), FmtUint(K_BLUE_NOISE_TEX_DEPTH),
|
||||
FmtUint(expected_size), FmtUint(data.len)));
|
||||
@ -503,7 +503,7 @@ void GPU_D12_InitNoise(void)
|
||||
}
|
||||
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);
|
||||
}
|
||||
@ -1237,7 +1237,7 @@ GPU_D12_Descriptor *GPU_D12_AllocDescriptor(GPU_D12_CpuDescriptorHeap *dh)
|
||||
{
|
||||
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);
|
||||
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)
|
||||
{
|
||||
P_Panic(Lit("Unsupported CPU descriptor type"));
|
||||
Panic(Lit("Unsupported CPU descriptor type"));
|
||||
}
|
||||
dh->num_descriptors_capacity = num_descriptors;
|
||||
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);
|
||||
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);
|
||||
|
||||
@ -1388,7 +1388,7 @@ GPU_D12_Resource *GPU_D12_AllocResource(D3D12_HEAP_PROPERTIES heap_props, D3D12_
|
||||
if (FAILED(hr))
|
||||
{
|
||||
/* TODO: Don't panic */
|
||||
P_Panic(Lit("Failed to create resource"));
|
||||
Panic(Lit("Failed to create resource"));
|
||||
}
|
||||
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
@ -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);
|
||||
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);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
P_Panic(Lit("Failed to create command list"));
|
||||
Panic(Lit("Failed to create command list"));
|
||||
}
|
||||
|
||||
hr = ID3D12GraphicsCommandList_Close(cl->cl);
|
||||
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);
|
||||
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);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
P_Panic(Lit("Failed to reset command list"));
|
||||
Panic(Lit("Failed to reset command list"));
|
||||
}
|
||||
|
||||
return cl;
|
||||
@ -1677,7 +1677,7 @@ u64 GPU_D12_EndCommandList(GPU_D12_CommandList *cl)
|
||||
if (FAILED(hr))
|
||||
{
|
||||
/* 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);
|
||||
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_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)
|
||||
{
|
||||
/* 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);
|
||||
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;
|
||||
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[] = {
|
||||
[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)
|
||||
{
|
||||
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 };
|
||||
@ -2158,7 +2158,7 @@ JobDef(GPU_D12_UploadJob, sig, UNUSED id)
|
||||
if (FAILED(hr) || !mapped)
|
||||
{
|
||||
/* 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 *src = data;
|
||||
@ -2998,7 +2998,7 @@ void GPU_D12_InitSwapchainResources(GPU_D12_Swapchain *swapchain)
|
||||
if (FAILED(hr))
|
||||
{
|
||||
/* 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];
|
||||
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);
|
||||
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);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
P_Panic(Lit("Failed to create IDXGISwapChain3"));
|
||||
Panic(Lit("Failed to create IDXGISwapChain3"));
|
||||
}
|
||||
|
||||
/* Create waitable object */
|
||||
@ -3137,7 +3137,7 @@ GPU_D12_SwapchainBuffer *GPU_D12_UpdateSwapchain(GPU_D12_Swapchain *swapchain, V
|
||||
if (FAILED(hr))
|
||||
{
|
||||
/* TODO: Don't panic */
|
||||
P_Panic(Lit("Failed to resize swapchain"));
|
||||
Panic(Lit("Failed to resize swapchain"));
|
||||
}
|
||||
}
|
||||
Unlock(&lock);
|
||||
|
||||
@ -425,7 +425,7 @@ extern GPU_D12_SharedState GPU_D12_shared_state;
|
||||
* Startup
|
||||
* ========================== */
|
||||
|
||||
P_ExitFuncDef(GPU_D12_Shutdown);
|
||||
ExitFuncDef(GPU_D12_Shutdown);
|
||||
|
||||
/* ========================== *
|
||||
* Dx12 device initialization
|
||||
|
||||
@ -11,6 +11,7 @@ void P_Main(void)
|
||||
{
|
||||
RunOnce();
|
||||
P_StartupDeps();
|
||||
P_StartupCore();
|
||||
/* FIXME: Logfile path */
|
||||
P_StartupLog(Lit("log.log"));
|
||||
}
|
||||
|
||||
@ -302,10 +302,9 @@ typedef i32 P_MessageBoxKind; enum
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ Exit callback types
|
||||
//~ @hookdecl Startup
|
||||
|
||||
#define P_ExitFuncDef(name) void name(void)
|
||||
typedef P_ExitFuncDef(P_ExitFunc);
|
||||
void P_StartupCore(void);
|
||||
|
||||
////////////////////////////////
|
||||
//~ @hookdecl Time helper operations
|
||||
@ -412,9 +411,9 @@ void P_SleepFrame(i64 last_frame_time_ns, i64 target_dt_ns);
|
||||
////////////////////////////////
|
||||
//~ @hookdecl Program exit
|
||||
|
||||
void P_OnExit(P_ExitFunc *func);
|
||||
void P_Exit(void);
|
||||
void P_Panic(String msg);
|
||||
void OnExit(ExitFunc *func);
|
||||
void Exit(void);
|
||||
void Panic(String msg);
|
||||
|
||||
////////////////////////////////
|
||||
//~ @hookdecl Entry point (implemented per application)
|
||||
|
||||
@ -145,7 +145,7 @@ void P_Log_(i32 level, String msg)
|
||||
P_LogLevelSettings settings = P_log_settings[level];
|
||||
if (level < 0 || level >= P_LogLevel_Count)
|
||||
{
|
||||
P_Panic(Lit("Invalid log level"));
|
||||
Panic(Lit("Invalid log level"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -122,8 +122,6 @@ void P_StartupLog(String logfile_path);
|
||||
////////////////////////////////
|
||||
//~ Logging macros
|
||||
|
||||
#define log_panic(msg) P_LogPanic_(msg)
|
||||
|
||||
#if P_LogLevel(P_LogLevel_Critical)
|
||||
# if P_IncludeLogSourceLocation
|
||||
# define P_LogCritical(msg) P_Log_(P_LogLevel_Critical, Lit(__FILE__), __LINE__, msg)
|
||||
|
||||
@ -14,6 +14,107 @@ P_W32_SharedCtx P_W32_shared_ctx = ZI;
|
||||
#pragma comment(lib, "avrt")
|
||||
#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
|
||||
|
||||
@ -864,7 +965,7 @@ void P_MkDir(String path)
|
||||
Lit("Failed to create directory \"%F\": %F"),
|
||||
FmtString(path),
|
||||
FmtString(err));
|
||||
P_Panic(msg);
|
||||
Panic(msg);
|
||||
}
|
||||
EndScratch(scratch);
|
||||
}
|
||||
@ -1018,7 +1119,7 @@ void P_WriteFile(P_File file, String data)
|
||||
if (data.len >= 0x7FFF)
|
||||
{
|
||||
TempArena scratch = BeginScratchNoConflict();
|
||||
P_Panic(StringFormat(scratch.arena,
|
||||
Panic(StringFormat(scratch.arena,
|
||||
Lit("Tried to write too many bytes to disk (%F)"),
|
||||
FmtUint(data.len)));
|
||||
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 */
|
||||
|
||||
@ -108,24 +108,8 @@ Struct(P_W32_Sock)
|
||||
|
||||
#define P_W32_WindowClassName L"power_play_window_class"
|
||||
|
||||
#define P_W32_MaxOnExitFuncs 1024
|
||||
|
||||
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
|
||||
P_Btn vk_btn_table[256];
|
||||
|
||||
@ -145,10 +129,6 @@ Struct(P_W32_SharedCtx)
|
||||
Arena *socks_arena;
|
||||
Mutex socks_mutex;
|
||||
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;
|
||||
@ -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_ConvertAnyaddrToLocalhost(P_W32_Address 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);
|
||||
|
||||
@ -16,10 +16,10 @@ void PB_StartupCore(void)
|
||||
PB_WSP_InitializeWasapi();
|
||||
/* Start playback job */
|
||||
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;
|
||||
PB_WSP_SharedState *g = &PB_WSP_shared_state;
|
||||
|
||||
@ -48,7 +48,7 @@ extern PB_WSP_SharedState PB_WSP_shared_state;
|
||||
//~ Wasapi startup
|
||||
|
||||
void PB_WSP_InitializeWasapi(void);
|
||||
P_ExitFuncDef(PB_WSP_Shutdown);
|
||||
ExitFuncDef(PB_WSP_Shutdown);
|
||||
|
||||
////////////////////////////////
|
||||
//~ Playback update
|
||||
|
||||
@ -46,13 +46,13 @@ void StartupUser(void)
|
||||
/* Start jobs */
|
||||
RunJob(1, UpdateUserJob, 0, JobPool_User, JobPriority_High, &g->shutdown_job_counters);
|
||||
RunJob(1, SimJob, 0, JobPool_Sim, JobPriority_High, &g->shutdown_job_counters);
|
||||
P_OnExit(&ShutdownUser);
|
||||
OnExit(&ShutdownUser);
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
//~ Shutdown
|
||||
|
||||
P_ExitFuncDef(ShutdownUser)
|
||||
ExitFuncDef(ShutdownUser)
|
||||
{
|
||||
__prof;
|
||||
SharedUserState *g = &shared_user_state;
|
||||
@ -553,7 +553,7 @@ void UpdateUser(P_Window *window)
|
||||
P_WindowEvent *event = &events.events[ent_index];
|
||||
if (event->kind == P_WindowEventKind_Quit)
|
||||
{
|
||||
P_Exit();
|
||||
Exit();
|
||||
}
|
||||
|
||||
if (event->kind == P_WindowEventKind_ButtonUp)
|
||||
@ -561,7 +561,7 @@ void UpdateUser(P_Window *window)
|
||||
/* Escape quit */
|
||||
if (event->button == P_Btn_ESC)
|
||||
{
|
||||
P_Exit();
|
||||
Exit();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -257,7 +257,7 @@ void StartupUser(void);
|
||||
////////////////////////////////
|
||||
//~ Shutdown
|
||||
|
||||
P_ExitFuncDef(ShutdownUser);
|
||||
ExitFuncDef(ShutdownUser);
|
||||
|
||||
////////////////////////////////
|
||||
//~ Debug draw operations
|
||||
|
||||
@ -13,14 +13,14 @@ void RES_StartupCore(void)
|
||||
String embedded_data = INC_GetResTar();
|
||||
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(""));
|
||||
#else
|
||||
/* Ensure we have the right working directory */
|
||||
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
|
||||
}
|
||||
|
||||
@ -44,7 +44,7 @@ void S_StartupCore(void)
|
||||
|
||||
RunJob(1, S_EvictorJob, JobPool_Background, JobPriority_Low, &g->shutdown_counter, 0);
|
||||
|
||||
P_OnExit(&S_Shutdown);
|
||||
OnExit(&S_Shutdown);
|
||||
#if RESOURCE_RELOADING
|
||||
W_RegisterCallback(&S_WatchSpriteCallback);
|
||||
#endif
|
||||
@ -53,7 +53,7 @@ void S_StartupCore(void)
|
||||
////////////////////////////////
|
||||
//~ Shutdown
|
||||
|
||||
P_ExitFuncDef(S_Shutdown)
|
||||
ExitFuncDef(S_Shutdown)
|
||||
{
|
||||
__prof;
|
||||
S_SharedState *g = &S_shared_state;
|
||||
@ -433,7 +433,7 @@ JobDef(S_LoadSpriteJob, sig, UNUSED id)
|
||||
{
|
||||
S_LoadCacheEntrySheet(ref, tag);
|
||||
} break;
|
||||
default: { P_Panic(Lit("Unknown sprite cache node kind")); } break;
|
||||
default: { Panic(Lit("Unknown sprite cache node kind")); } break;
|
||||
}
|
||||
S_EndScope(scope);
|
||||
}
|
||||
@ -665,7 +665,7 @@ S_ScopeCacheEntryRef *S_EnsureRefUnsafely(S_Scope *scope, S_CacheEntry *e)
|
||||
{
|
||||
if (scope->num_references >= S_MaxScopeReferences)
|
||||
{
|
||||
P_Panic(Lit("Max sprite scope references reached"));
|
||||
Panic(Lit("Max sprite scope references reached"));
|
||||
}
|
||||
|
||||
/* 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_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);
|
||||
@ -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_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)
|
||||
@ -944,7 +944,7 @@ void *S_DataFromTag(S_Scope *scope, S_Tag tag, S_CacheEntryKind kind, b32 await)
|
||||
S_LoadCacheEntrySheet(ref, tag);
|
||||
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
|
||||
|
||||
@ -260,7 +260,7 @@ void S_StartupCore(void);
|
||||
////////////////////////////////
|
||||
//~ Shutdown
|
||||
|
||||
P_ExitFuncDef(S_Shutdown);
|
||||
ExitFuncDef(S_Shutdown);
|
||||
|
||||
////////////////////////////////
|
||||
//~ Purple-black image
|
||||
|
||||
@ -45,7 +45,7 @@ void TTF_StartupCore(void)
|
||||
if (error != S_OK)
|
||||
{
|
||||
/* FIXME: Enable this */
|
||||
//P_Panic(Lit("Error creating DWrite factory"));
|
||||
//Panic(Lit("Error creating DWrite factory"));
|
||||
(*(volatile int *)0) = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -12,10 +12,10 @@ void W_StartupCore(void)
|
||||
|
||||
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);
|
||||
P_OnExit(&W_Shutdown);
|
||||
OnExit(&W_Shutdown);
|
||||
}
|
||||
|
||||
P_ExitFuncDef(W_Shutdown)
|
||||
ExitFuncDef(W_Shutdown)
|
||||
{
|
||||
__prof;
|
||||
W_SharedState *g = &W_shared_state;
|
||||
@ -43,7 +43,7 @@ void W_RegisterCallback(W_CallbackFunc *callback)
|
||||
}
|
||||
else
|
||||
{
|
||||
P_Panic(Lit("Max resource watch callbacks reached"));
|
||||
Panic(Lit("Max resource watch callbacks reached"));
|
||||
}
|
||||
}
|
||||
Unlock(&lock);
|
||||
|
||||
@ -42,7 +42,7 @@ extern W_SharedState W_shared_state;
|
||||
//~ Startup
|
||||
|
||||
void W_StartupCore(void);
|
||||
P_ExitFuncDef(W_Shutdown);
|
||||
ExitFuncDef(W_Shutdown);
|
||||
|
||||
////////////////////////////////
|
||||
//~ Watch operations
|
||||
|
||||
Loading…
Reference in New Issue
Block a user