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;
|
__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;
|
||||||
|
|||||||
@ -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;
|
||||||
{
|
{
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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
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)
|
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;
|
||||||
|
|||||||
@ -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);
|
||||||
|
|||||||
@ -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"
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
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 */
|
/* 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);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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)));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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);
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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"));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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)
|
||||||
|
|||||||
@ -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"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -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)
|
||||||
|
|||||||
@ -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 */
|
|
||||||
|
|||||||
@ -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);
|
|
||||||
|
|||||||
@ -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;
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -257,7 +257,7 @@ void StartupUser(void);
|
|||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ Shutdown
|
//~ Shutdown
|
||||||
|
|
||||||
P_ExitFuncDef(ShutdownUser);
|
ExitFuncDef(ShutdownUser);
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ Debug draw operations
|
//~ Debug draw operations
|
||||||
|
|||||||
@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -260,7 +260,7 @@ void S_StartupCore(void);
|
|||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ Shutdown
|
//~ Shutdown
|
||||||
|
|
||||||
P_ExitFuncDef(S_Shutdown);
|
ExitFuncDef(S_Shutdown);
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ Purple-black image
|
//~ Purple-black image
|
||||||
|
|||||||
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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);
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user