diff --git a/src/app/app.c b/src/app/app.c index d83134c5..57d92d76 100644 --- a/src/app/app.c +++ b/src/app/app.c @@ -10,7 +10,7 @@ String InitializeAppWriteDirectory(Arena *arena, String write_dir) /* Create write path */ String base_write_dir = P_GetWritePath(scratch.arena); String write_path_fmt = base_write_dir.len > 0 ? Lit("%F/%F/") : Lit("%F%F/"); - String write_path = StringFormat( + String write_path = FormatString( arena, write_path_fmt, FmtString(base_write_dir), @@ -231,16 +231,14 @@ void Startup(void) if (error.len > 0) { P_LogInfoF("Failed to load settings file with error - %F", FmtString(error)); - String msg = StringFormat(temp.arena, - Lit( - "Failed to loading settings file \"%F\":\n" - "------------\n" - "%F\n" - "------------\n" - "To stop this error from appearing, either fix the issue above or delete the file from the system." - ), - FmtString(settings_path), - FmtString(error)); + String msg = StringF(temp.arena, + "Failed to loading settings file \"%F\":\n" + "------------\n" + "%F\n" + "------------\n" + "To stop this error from appearing, either fix the issue above or delete the file from the system.", + FmtString(settings_path), + FmtString(error)); Panic(msg); } P_LogInfoF("Settings file loaded successfully"); diff --git a/src/ase/ase.c b/src/ase/ase.c index 6cc95786..5562c38a 100644 --- a/src/ase/ase.c +++ b/src/ase/ase.c @@ -502,9 +502,9 @@ ASE_DecodedImage ASE_DecodeImage(Arena *arena, String encoded) if (ase_header.color_depth != 32) { - String msg = StringFormat(scratch.arena, - Lit("Only 32 bit rgba color mode is supported (got %F)"), - FmtUint(ase_header.color_depth)); + String msg = StringF(scratch.arena, + "Only 32 bit rgba color mode is supported (got %F)", + FmtUint(ase_header.color_depth)); ASE_PushError(arena, &result.errors, msg); goto abort; } diff --git a/src/base/base.h b/src/base/base.h index 3d0d9d92..4c62990c 100644 --- a/src/base/base.h +++ b/src/base/base.h @@ -37,12 +37,6 @@ # error Missing compile time definition for 'TestsAreEnabled' #endif -#ifndef IncbinRawDir -# error Missing compile time definition for 'IncbinRawDir' -#else -# define IncbinDir Stringize(IncbinRawDir) -#endif - //////////////////////////////// //~ Machine context diff --git a/src/base/base_arena.h b/src/base/base_arena.h index 4f6fa304..b64dfff0 100644 --- a/src/base/base_arena.h +++ b/src/base/base_arena.h @@ -207,7 +207,7 @@ Inline ArenaCtx *ArenaCtxFromFiberId(i16 fiber_id) * scope that could potentially be a scratch arena from another scope. */ Inline TempArena BeginScratch(Arena *potential_conflict) { - /* This function is currently hard-coded to support 2 scratch arenas */ + /* This function is currently hard-coded to search through 2 scratch arenas */ StaticAssert(ScratchArenasPerCtx == 2); /* Use `BeginScratchNoConflict` if no conflicts are present */ @@ -215,7 +215,7 @@ Inline TempArena BeginScratch(Arena *potential_conflict) ArenaCtx *ctx = ArenaCtxFromFiberId(FiberId); Arena *scratch_arena = ctx->scratch_arenas[0]; - if (potential_conflict && scratch_arena == potential_conflict) + if (scratch_arena == potential_conflict) { scratch_arena = ctx->scratch_arenas[1]; } diff --git a/src/base/base_job.h b/src/base/base_job.h index 48330fe0..1c4e0244 100644 --- a/src/base/base_job.h +++ b/src/base/base_job.h @@ -33,9 +33,9 @@ Enum(JobPriority) }; //////////////////////////////// -//~ @hookdecl Startup +//~ @hookdecl Init -void StartupBaseJobs(void); +void InitJobWorkers(void); //////////////////////////////// //~ @hookdecl Futex diff --git a/src/base/base_math.c b/src/base/base_math.c index c1361506..9aea475a 100644 --- a/src/base/base_math.c +++ b/src/base/base_math.c @@ -293,12 +293,12 @@ f32 LnF32(f32 x) if ((x_int & 0x7fffffff) == 0) { /* Return -inf if x is 0 */ - return -two_p25 / 0; + return -F32Infinity; } else if (x_int < 0) { /* Return NaN if x is negative */ - return (x - x) / 0; + return F32Nan; } k -= 25; x *= two_p25; diff --git a/src/base/base_string.c b/src/base/base_string.c index 3e0820ec..f4bdc86d 100644 --- a/src/base/base_string.c +++ b/src/base/base_string.c @@ -493,10 +493,10 @@ String Trim(String s, String pattern) * included in the arguments (instead of w/ the specifier like in printf). * * Example: - * StringFormat(arena, Lit("Hello there %F"), FmtString(Lit("George"))) + * FormatString(arena, Lit("Hello there %F"), FmtString(Lit("George"))) * * NOTE: FmtEnd must be passed as the last arg in the va_list (This is - * done automatically by the `StringFormat` macro). + * done automatically by the `FormatString` macro). * * Format arguments: * FmtChar: Format a single u8 character @@ -515,7 +515,7 @@ String Trim(String s, String pattern) * %e/%E equivalent? (scientific notation of floats) * %o equivalent? (octal representation) */ -String StringFormatV(Arena *arena, String fmt, va_list args) +String FormatStringV(Arena *arena, String fmt, va_list args) { __prof; @@ -633,11 +633,11 @@ String StringFormatV(Arena *arena, String fmt, va_list args) }; } -String StringFormat_(Arena *arena, String fmt, ...) +String FormatString_(Arena *arena, String fmt, ...) { va_list args; va_start(args, fmt); - String new_str = StringFormatV(arena, fmt, args); + String new_str = FormatStringV(arena, fmt, args); va_end(args); return new_str; } diff --git a/src/base/base_string.h b/src/base/base_string.h index de4aa4f3..433c17c8 100644 --- a/src/base/base_string.h +++ b/src/base/base_string.h @@ -112,10 +112,10 @@ String StringFromList(Arena *arena, StringList l, String separator); #define FmtEnd (FmtArg) {.kind = FmtKind_End} //- Format functions -#define StringF(arena, lit, ...) StringFormat_((arena), Lit(lit), __VA_ARGS__, FmtEnd) -#define StringFormat(arena, fmt, ...) StringFormat_((arena), (fmt), __VA_ARGS__, FmtEnd) -String StringFormat_(Arena *arena, String fmt, ...); -String StringFormatV(Arena *arena, String fmt, va_list args); +#define StringF(arena, lit, ...) FormatString_((arena), Lit(lit), __VA_ARGS__, FmtEnd) +#define FormatString(arena, fmt, ...) FormatString_((arena), (fmt), __VA_ARGS__, FmtEnd) +String FormatString_(Arena *arena, String fmt, ...); +String FormatStringV(Arena *arena, String fmt, va_list args); //////////////////////////////// //~ Unicode operations diff --git a/src/base/base_win32/base_win32.c b/src/base/base_win32/base_win32.c index 55909e76..6c77d7ea 100644 --- a/src/base/base_win32/base_win32.c +++ b/src/base/base_win32/base_win32.c @@ -18,7 +18,10 @@ b32 Panic(String msg) MessageBoxExA(0, msg_cstr, "Fatal error", mb_flags, 0); } HANDLE console_handle = GetStdHandle(STD_ERROR_HANDLE); - WriteConsoleA(console_handle, msg.text, msg.len, 0, 0); + if (console_handle != INVALID_HANDLE_VALUE) + { + WriteFile(console_handle, msg.text, msg.len, 0, 0); + } if (IsRunningInDebugger()) { Assert(0); @@ -184,8 +187,8 @@ i32 W32_Main(void) /* Query system info */ GetSystemInfo(&g->info); - //- Startup jobs - StartupBaseJobs(); + //- Startup workers + InitJobWorkers(); /* Startup layers */ if (!Atomic32Fetch(&g->panicking)) diff --git a/src/base/base_win32/base_win32_job.c b/src/base/base_win32/base_win32_job.c index 8bd00ed2..6a8ae985 100644 --- a/src/base/base_win32/base_win32_job.c +++ b/src/base/base_win32/base_win32_job.c @@ -3,7 +3,7 @@ W32_SharedJobCtx W32_shared_job_ctx = ZI; //////////////////////////////// //~ @hookdef Startup -void StartupBaseJobs(void) +void InitJobWorkers(void) { W32_SharedJobCtx *g = &W32_shared_job_ctx; @@ -114,7 +114,7 @@ void StartupBaseJobs(void) W32_WorkerCtx *ctx = &pool->worker_contexts[i]; ctx->pool_kind = pool_kind; ctx->id = i; - String name = StringFormat(pool->worker_threads_arena, name_fmt, FmtSint(i)); + String name = FormatString(pool->worker_threads_arena, name_fmt, FmtSint(i)); pool->worker_threads[i] = W32_AcquireThread(W32_JobWorkerEntryFunc, ctx, name, prof_group + i); } } @@ -179,10 +179,10 @@ void ShutdownJobs(void) for (W32_Thread *t = g->first_thread; t; t = t->next) { String name = StringFromCstr(t->thread_name_cstr, countof(t->thread_name_cstr)); - threads_msg.len += StringFormat(scratch.arena, Lit(" \"%F\"\n"), FmtString(name)).len; + threads_msg.len += StringF(scratch.arena, " \"%F\"\n", FmtString(name)).len; ++num_dangling_threads; } - threads_msg = StringFormat(scratch.arena, Lit("%F dangling thread(s):\n%F"), FmtUint(num_dangling_threads), FmtString(threads_msg)); + threads_msg = FormatString(scratch.arena, Lit("%F dangling thread(s):\n%F"), FmtUint(num_dangling_threads), FmtString(threads_msg)); //Panic(threads_msg); EndScratch(scratch); } @@ -1056,7 +1056,7 @@ W32_ThreadDef(W32_JobWorkerEntryFunc, worker_ctx_arg) { /* Invalid yield kind */ TempArena scratch = BeginScratchNoConflict(); - //Panic(StringFormat(scratch.arena, Lit("Invalid fiber yield kind \"%F\""), FmtSint(yield.kind))); + //Panic(FormatString(scratch.arena, Lit("Invalid fiber yield kind \"%F\""), FmtSint(yield.kind))); EndScratch(scratch); } break; diff --git a/src/font/font.c b/src/font/font.c index 83353763..8d80a85c 100644 --- a/src/font/font.c +++ b/src/font/font.c @@ -41,9 +41,9 @@ JobDef(F_LoadJob, sig, _) if (resource_data.len == 0) { /* FIME: Load baked font instead of panicking */ - Panic(StringFormat(scratch.arena, - Lit("Font \"%F\" not found"), - FmtString(name))); + Panic(StringF(scratch.arena, + "Font \"%F\" not found", + FmtString(name))); } TTF_Result result = TTF_Decode(scratch.arena, resource_data, point_size, font_codes, countof(font_codes)); @@ -78,9 +78,9 @@ JobDef(F_LoadJob, sig, _) /* FIXME: Load baked font instead of panicking */ if (font->glyphs_count <= 0) { - Panic(StringFormat(scratch.arena, - Lit("Parsed 0 glyphs from font \"%F\"!"), - FmtString(name))); + Panic(StringF(scratch.arena, + "Parsed 0 glyphs from font \"%F\"!", + FmtString(name))); } /* Copy glyphs from decode result */ @@ -111,10 +111,10 @@ AC_Asset *F_LoadAsset(R_Tag resource, f32 point_size, b32 wait) String name = R_NameFromTag(resource); /* Concatenate point_size to name for key */ - String key = StringFormat(scratch.arena, - Lit("%F%F_font"), - FmtString(name), - FmtFloatP((f64)point_size, 1)); + String key = StringF(scratch.arena, + "%F%F_font", + FmtString(name), + FmtFloatP((f64)point_size, 1)); u64 hash = AC_HashFromKey(key); b32 is_first_touch; AC_Asset *asset = AC_TouchCache(key, hash, &is_first_touch); diff --git a/src/gpu/gpu.h b/src/gpu/gpu.h index 2f958dbf..3937ccf7 100644 --- a/src/gpu/gpu.h +++ b/src/gpu/gpu.h @@ -293,7 +293,10 @@ Vec2I32 GPU_GetTextureSize(GPU_Resource *resource); GPU_CommandList *GPU_BeginCommandList(void); GPU_Fence GPU_EndCommandList(GPU_CommandList *cl); -void GPU_ProfileDF(GPU_CommandList *cl, String zone_name); +//////////////////////////////// +//~ Profiling helpers + +void GPU_ProfN(GPU_CommandList *cl, String name); //////////////////////////////// //~ Resource transition operations @@ -301,7 +304,7 @@ void GPU_ProfileDF(GPU_CommandList *cl, String zone_name); void GPU_TransitionToSrv(GPU_CommandList *cl, GPU_Resource *resource); void GPU_TransitionToUav(GPU_CommandList *cl, GPU_Resource *resource); void GPU_TransitionToRtv(GPU_CommandList *cl, GPU_Resource *resource); -void GPU_Flush(GPU_CommandList *cl, GPU_Resource *resource); +void GPU_FlushUav(GPU_CommandList *cl, GPU_Resource *resource); //////////////////////////////// //~ Dispatch operations diff --git a/src/gpu/gpu_dx12/gpu_dx12.c b/src/gpu/gpu_dx12/gpu_dx12.c index fff4ac90..19737bae 100644 --- a/src/gpu/gpu_dx12/gpu_dx12.c +++ b/src/gpu/gpu_dx12/gpu_dx12.c @@ -70,10 +70,13 @@ GPU_Fence GPU_EndCommandList(GPU_CommandList *cl) return (GPU_Fence) ZI; } -void GPU_ProfileDF(GPU_CommandList *cl, String zone_name) +//////////////////////////////// +//~ @hookdef Profiling helpers + +void GPU_ProfN(GPU_CommandList *cl, String name) { LAX cl; - LAX zone_name; + LAX name; } //////////////////////////////// @@ -97,7 +100,7 @@ void GPU_TransitionToRtv(GPU_CommandList *cl, GPU_Resource *resource) LAX resource; } -void GPU_Flush(GPU_CommandList *cl, GPU_Resource *resource) +void GPU_FlushUav(GPU_CommandList *cl, GPU_Resource *resource) { LAX cl; LAX resource; diff --git a/src/meta/meta.c b/src/meta/meta.c index d0dfb728..153a38ad 100644 --- a/src/meta/meta.c +++ b/src/meta/meta.c @@ -45,10 +45,6 @@ # define TestsAreEnabled 0 #endif -#ifndef IncbinRawDir -# define IncbinRawDir -#endif - //////////////////////////////// //~ Includes @@ -60,17 +56,14 @@ //////////////////////////////// //~ Util -/* TODO: Remove printf */ -#include - void Echo(String msg) { - TempArena scratch = BeginScratchNoConflict(); - char *msg_cstr = CstrFromString(scratch.arena, msg); - printf(msg_cstr); - printf("\n"); - fflush(stdout); - EndScratch(scratch); + HANDLE console_handle = GetStdHandle(STD_OUTPUT_HANDLE); + if (console_handle != INVALID_HANDLE_VALUE) + { + WriteFile(console_handle, msg.text, msg.len, 0, 0); + WriteFile(console_handle, "\n", 1, 0, 0); + } } Struct(LineCol) @@ -584,11 +577,16 @@ L_Topo L_TopoFromLayerName(Arena *arena, StringList starting_layer_names, String } if (cycle_names_list.count > 1) { - L_PushTopoItem(arena, &result.errors, token_file, token_pos, StringF(arena, "Cyclic dependency detected while processing dependencies for layer '%F' (%F)", FmtString(name), FmtString(cycle_names_str))); + L_PushTopoItem(arena, &result.errors, token_file, token_pos, StringF(arena, + "Cyclic dependency detected while processing dependencies for layer '%F' (%F)", + FmtString(name), + FmtString(cycle_names_str))); } else { - L_PushTopoItem(arena, &result.errors, token_file, token_pos, StringF(arena, "Cyclic dependency detected while processing dependencies for layer '%F'", FmtString(name))); + L_PushTopoItem(arena, &result.errors, token_file, token_pos, StringF(arena, + "Cyclic dependency detected while processing dependencies for layer '%F'", + FmtString(name))); } } else @@ -814,6 +812,7 @@ void StartupMeta(void) } //- Generate C + String c_out_file = F_GetFull(arena, Lit("pp_gen.c")); if (errors.count <= 0) { StringList c_out_lines = ZI; @@ -863,7 +862,7 @@ void StartupMeta(void) } /* Write to file */ String c_out = StringFromList(arena, c_out_lines, Lit("\n")); - F_ClearWrite(Lit("pp_gen.c"), c_out); + F_ClearWrite(c_out_file, c_out); } //- Echo meta errors @@ -905,13 +904,12 @@ void StartupMeta(void) PushStringToList(arena, &shared_compiler_flags, Lit("-DProfilingIsEnabled=0")); PushStringToList(arena, &shared_compiler_flags, Lit("-DUnoptimizedIsEnabled=1")); PushStringToList(arena, &shared_compiler_flags, Lit("-DTestsAreEnabled=0")); - PushStringToList(arena, &shared_compiler_flags, Lit("-DIncbinRawDir=\"bla/\"")); //- Msvc { PushStringToList(arena, &msvc_compiler_flags, Lit("-Z7")); PushStringToList(arena, &msvc_compiler_flags, Lit("-DEBUG:FULL")); - PushStringToList(arena, &msvc_compiler_flags, Lit("-Fo:pp_pp_gen.obj")); + PushStringToList(arena, &msvc_compiler_flags, Lit("-Fo:pp_gen.obj")); PushStringToList(arena, &msvc_compiler_flags, Lit("-Fe:pp.exe")); PushStringToList(arena, &msvc_compiler_flags, Lit("-nologo")); PushStringToList(arena, &msvc_compiler_flags, Lit("-diagnostics:column")); @@ -923,6 +921,7 @@ void StartupMeta(void) PushStringToList(arena, &msvc_compiler_flags, Lit("-wd4201")); /* nonstandard extension used: nameless struct/union */ PushStringToList(arena, &msvc_compiler_flags, Lit("-wd4324")); /* structure was padded due to alignment specifier */ PushStringToList(arena, &msvc_compiler_flags, Lit("-wd4100")); /* unreferenced parameter */ + PushStringToList(arena, &msvc_compiler_flags, Lit("-wd4101")); /* unreferenced local variable */ PushStringToList(arena, &msvc_compiler_flags, Lit("-wd4189")); /* local variable is initialized but not referenced */ PushStringToList(arena, &msvc_compiler_flags, Lit("-wd4200")); /* nonstandard extension used: zero-sized array in struct/union */ } @@ -936,6 +935,7 @@ void StartupMeta(void) PushStringToList(arena, &clang_compiler_flags, Lit("-msse4.2")); /* Enable warnings */ PushStringToList(arena, &clang_compiler_flags, Lit("-Wall")); + PushStringToList(arena, &clang_compiler_flags, Lit("-Werror")); PushStringToList(arena, &clang_compiler_flags, Lit("-Wframe-larger-than=65536")); PushStringToList(arena, &clang_compiler_flags, Lit("-Wmissing-prototypes")); PushStringToList(arena, &clang_compiler_flags, Lit("-Wunused-variable")); @@ -957,7 +957,7 @@ void StartupMeta(void) FmtString(StringFromList(arena, shared_compiler_flags, Lit(" "))), FmtString(StringFromList(arena, msvc_compiler_flags, Lit(" "))) ); - msvc_cmd_str = StringF(arena, "\"cl\" pp_gen.c %F", FmtString(flags_str)); + msvc_cmd_str = StringF(arena, "\"cl\" %F %F", FmtString(c_out_file), FmtString(flags_str)); } /* Clang */ { @@ -966,10 +966,11 @@ void StartupMeta(void) FmtString(StringFromList(arena, shared_compiler_flags, Lit(" "))), FmtString(StringFromList(arena, clang_compiler_flags, Lit(" "))) ); - clang_cmd_str = StringF(arena, "\"clang\" pp_gen.c %F", FmtString(flags_str)); + clang_cmd_str = StringF(arena, "\"clang\" %F %F", FmtString(c_out_file), FmtString(flags_str)); } //- Compile C + Echo(Lit("Compiling...")); i32 ret = errors.count > 0; if (ret == 0) { String cmd_str = msvc_cmd_str; @@ -980,9 +981,14 @@ void StartupMeta(void) output = Trim(output, Lit("\n")); output = Trim(output, Lit("\r")); output = Trim(output, Lit("\n")); - if (result.code != 0) + Echo(output); + if (result.code == 0) { - Echo(output); + Echo(Lit("Compilation succeeded")); + } + else + { + Echo(Lit("Compilation failed")); } ret = result.code; } diff --git a/src/meta/meta_os/meta_os_win32/meta_os_win32.c b/src/meta/meta_os/meta_os_win32/meta_os_win32.c index 733d432b..53882b9c 100644 --- a/src/meta/meta_os/meta_os_win32/meta_os_win32.c +++ b/src/meta/meta_os/meta_os_win32/meta_os_win32.c @@ -102,9 +102,9 @@ String OS_GetFullPath(Arena *arena, String path) { TempArena scratch = BeginScratch(arena); wchar_t *rel_path_wstr = WstrFromString(scratch.arena, path); - wchar_t buff[4096]; - wchar_t *full_path_wstr = _wfullpath(buff, rel_path_wstr, countof(buff)); - String res = StringFromWstrNoLimit(arena, full_path_wstr); + wchar_t full_path_wstr_buff[4096]; + GetFullPathNameW(rel_path_wstr, countof(full_path_wstr_buff), full_path_wstr_buff, 0); + String res = StringFromWstr(arena, full_path_wstr_buff, countof(full_path_wstr_buff)); EndScratch(scratch); return res; } @@ -186,8 +186,6 @@ OS_CommandResult OS_RunCommand(Arena *arena, String cmd) TempArena scratch = BeginScratch(arena); OS_CommandResult result = ZI; - i32 res = -1; - wchar_t *cmd_wstr = WstrFromString(scratch.arena, cmd); SECURITY_ATTRIBUTES sa = ZI; @@ -195,62 +193,84 @@ OS_CommandResult OS_RunCommand(Arena *arena, String cmd) sa.bInheritHandle = 1; HANDLE pipe_read, pipe_write; - if (!CreatePipe(&pipe_read, &pipe_write, &sa, 0)) + if (CreatePipe(&pipe_read, &pipe_write, &sa, 0)) { - /* TODO: error handling */ - Assert(0); - } - SetHandleInformation(pipe_read, HANDLE_FLAG_INHERIT, 0); + SetHandleInformation(pipe_read, HANDLE_FLAG_INHERIT, 0); - STARTUPINFO si = ZI; - si.cb = sizeof(si); - si.dwFlags = STARTF_USESTDHANDLES; - si.hStdInput = GetStdHandle(STD_INPUT_HANDLE); - si.hStdOutput = pipe_write; - si.hStdError = pipe_write; + STARTUPINFO si = ZI; + si.cb = sizeof(si); + si.dwFlags = STARTF_USESTDHANDLES; + si.hStdInput = GetStdHandle(STD_INPUT_HANDLE); + si.hStdOutput = pipe_write; + si.hStdError = pipe_write; - PROCESS_INFORMATION pi = ZI; + PROCESS_INFORMATION pi = ZI; - result.output.text = PushDry(arena, u8); - if (!CreateProcessW(0, cmd_wstr, 0, 0, 1, 0, 0, 0, &si, &pi)) - { - /* TODO: error handling */ - Assert(0); - } else { - CloseHandle(pipe_write); - b32 exit_code_valid = 0; - i32 exit_code = 0; - b32 stdout_finished = 0; - while (!stdout_finished) + result.output.text = PushDry(arena, u8); + if (!CreateProcessW(0, cmd_wstr, 0, 0, 1, 0, 0, 0, &si, &pi)) { - u8 buff[4096] = ZI; - DWORD bytes_read = 0; - if (!ReadFile(pipe_read, buff, countof(buff), &bytes_read, 0)) + DWORD err = GetLastError(); + char *msg_cstr = 0; + i64 len = FormatMessageA( + FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, + 0, + err, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPSTR)&msg_cstr, + 0, + 0); + if (len > 0) { - if (GetLastError() == ERROR_BROKEN_PIPE) - { - GetExitCodeProcess(pi.hProcess, &exit_code); - exit_code_valid = 1; - } - stdout_finished = 1; + result.output = PushString(arena, StringFromCstr(msg_cstr, len)); + LocalFree(msg_cstr); + } + else + { + result.output = Lit("Failed to create process"); } - PushStructsNoZero(arena, u8, bytes_read); - CopyBytes(result.output.text + result.output.len, buff, bytes_read); - result.output.len += bytes_read; - } - - CloseHandle(pi.hThread); - CloseHandle(pi.hProcess); - - if (exit_code_valid) - { - result.code = exit_code; - } else { result.code = -1; + } else { + CloseHandle(pipe_write); + b32 exit_code_valid = 0; + i32 exit_code = 0; + b32 stdout_finished = 0; + while (!stdout_finished) + { + u8 buff[4096] = ZI; + DWORD bytes_read = 0; + if (!ReadFile(pipe_read, buff, countof(buff), &bytes_read, 0)) + { + if (GetLastError() == ERROR_BROKEN_PIPE) + { + GetExitCodeProcess(pi.hProcess, &exit_code); + exit_code_valid = 1; + } + stdout_finished = 1; + } + PushStructsNoZero(arena, u8, bytes_read); + CopyBytes(result.output.text + result.output.len, buff, bytes_read); + result.output.len += bytes_read; + } + + CloseHandle(pi.hThread); + CloseHandle(pi.hProcess); + + if (exit_code_valid) + { + result.code = exit_code; + } else { + result.code = -1; + } } + + CloseHandle(pipe_read); + } + else + { + result.output = Lit("Failed to create pipe"); + result.code = -1; } - CloseHandle(pipe_read); EndScratch(scratch); return result; } diff --git a/src/meta/meta_os/meta_os_win32/meta_os_win32.h b/src/meta/meta_os/meta_os_win32/meta_os_win32.h index 81de9b4f..97a6bdf4 100644 --- a/src/meta/meta_os/meta_os_win32/meta_os_win32.h +++ b/src/meta/meta_os/meta_os_win32/meta_os_win32.h @@ -1,5 +1,3 @@ -#include /* _wfullpath */ - //////////////////////////////// //~ Win32 libs diff --git a/src/platform/platform_log.c b/src/platform/platform_log.c index 3b56e13a..ff515a4c 100644 --- a/src/platform/platform_log.c +++ b/src/platform/platform_log.c @@ -100,7 +100,7 @@ void P_LogFV_(i32 level, String fmt, va_list args) P_SharedLogState *ctx = &P_shared_log_state; if (!Atomic32Fetch(&ctx->initialized)) { return; } TempArena scratch = BeginScratchNoConflict(); - String msg = StringFormatV(scratch.arena, fmt, args); + String msg = FormatStringV(scratch.arena, fmt, args); #if P_IncludeLogSourceLocation P_Log_(level, file, line, msg); #else @@ -150,7 +150,6 @@ void P_Log_(i32 level, String msg) Panic(Lit("Invalid log level")); } - /* FIXME: Log actual thread & fiber id */ // u32 tid = ThreadId(); u32 tid = 0; @@ -161,9 +160,9 @@ void P_Log_(i32 level, String msg) String shorthand = settings.shorthand; #if P_IncludeLogSourceLocation - String msg_formatted = StringFormat( + String msg_formatted = StringF( scratch.arena, - Lit("[%F:%F:%F.%F] |%F| [%F] <%F:%F> %F"), + "[%F:%F:%F.%F] |%F| [%F] <%F:%F> %F", /* Time */ FmtUintZ(datetime.hour, 2), @@ -185,7 +184,7 @@ void P_Log_(i32 level, String msg) FmtString(msg) ); #else - String msg_formatted = StringFormat( + String msg_formatted = FormatString( scratch.arena, Lit("[%F:%F:%F.%F] |%F| [%F] %F"), diff --git a/src/platform/platform_win32/platform_win32.c b/src/platform/platform_win32/platform_win32.c index bcafd968..791d6ed4 100644 --- a/src/platform/platform_win32/platform_win32.c +++ b/src/platform/platform_win32/platform_win32.c @@ -1,11 +1,11 @@ -P_W32_SharedCtx P_W32_shared_ctx = ZI; +P_W32_SharedState P_W32_shared_state = ZI; //////////////////////////////// //~ @hookdef Startup void P_Startup(void) { - P_W32_SharedCtx *g = &P_W32_shared_ctx; + P_W32_SharedState *g = &P_W32_shared_state; //- Initialize btn table { @@ -156,7 +156,7 @@ String P_W32_StringFromWin32Path(Arena *arena, wchar_t *src) P_W32_Window *P_W32_AcquireWindow(void) { - P_W32_SharedCtx *g = &P_W32_shared_ctx; + P_W32_SharedState *g = &P_W32_shared_state; P_W32_Window *window = 0; { Lock lock = LockE(&g->windows_mutex); @@ -191,7 +191,7 @@ void P_W32_ReleaseWindow(P_W32_Window *window) { /* Stop window threads */ Atomic32FetchSet(&window->shutdown, 1); - P_W32_SharedCtx *g = &P_W32_shared_ctx; + P_W32_SharedState *g = &P_W32_shared_state; P_W32_WakeWindow(window); W32_WaitReleaseThread(window->window_thread); @@ -205,7 +205,7 @@ void P_W32_ReleaseWindow(P_W32_Window *window) HWND P_W32_InitWindow(P_W32_Window *window) { - struct P_W32_SharedCtx *g = &P_W32_shared_ctx; + struct P_W32_SharedState *g = &P_W32_shared_state; /* * From martins (https://gist.github.com/mmozeiko/5e727f845db182d468a34d524508ad5f#file-win32_d3d11-c-L66-L70): @@ -438,7 +438,7 @@ void P_W32_WakeWindow(P_W32_Window *window) LRESULT CALLBACK P_W32_Win32WindowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { __prof; - P_W32_SharedCtx *g = &P_W32_shared_ctx; + P_W32_SharedState *g = &P_W32_shared_state; P_W32_Window *window = (P_W32_Window *)GetWindowLongPtrW(hwnd, GWLP_USERDATA); if (!window) @@ -947,10 +947,10 @@ void P_MkDir(String path) } if (err.len > 0) { - String msg = StringFormat(scratch.arena, - Lit("Failed to create directory \"%F\": %F"), - FmtString(path), - FmtString(err)); + String msg = StringF(scratch.arena, + "Failed to create directory \"%F\": %F", + FmtString(path), + FmtString(err)); Panic(msg); } EndScratch(scratch); @@ -1105,9 +1105,9 @@ void P_WriteFile(P_File file, String data) if (data.len >= 0x7FFF) { TempArena scratch = BeginScratchNoConflict(); - Panic(StringFormat(scratch.arena, - Lit("Tried to write too many bytes to disk (%F)"), - FmtUint(data.len))); + Panic(StringF(scratch.arena, + "Tried to write too many bytes to disk (%F)", + FmtUint(data.len))); EndScratch(scratch); } @@ -1569,7 +1569,7 @@ String P_StringFromAddress(Arena *arena, P_Address address) ip[i] = ntohs(address.ipnb[i]); } u16 port = ntohs(address.portnb); - result = StringFormat(arena, Lit("%F.%F.%F.%F:%F"), FmtUint(ip[0]), FmtUint(ip[1]), FmtUint(ip[2]), FmtUint(ip[3]), FmtUint(port)); + result = StringF(arena, "%F.%F.%F.%F:%F", FmtUint(ip[0]), FmtUint(ip[1]), FmtUint(ip[2]), FmtUint(ip[3]), FmtUint(port)); } return result; @@ -1585,7 +1585,7 @@ b32 P_AddressIsEqual(P_Address a, P_Address b) P_Sock *P_AcquireSock(u16 listen_port, u64 sndbuf_size, u64 rcvbuf_size) { - P_W32_SharedCtx *g = &P_W32_shared_ctx; + P_W32_SharedState *g = &P_W32_shared_state; P_W32_Sock *ws = 0; { Lock lock = LockE(&g->socks_mutex); @@ -1620,7 +1620,7 @@ P_Sock *P_AcquireSock(u16 listen_port, u64 sndbuf_size, u64 rcvbuf_size) void P_ReleaseSock(P_Sock *sock) { - P_W32_SharedCtx *g = &P_W32_shared_ctx; + P_W32_SharedState *g = &P_W32_shared_state; P_W32_Sock *ws = (P_W32_Sock *)sock; closesocket(ws->sock); Lock lock = LockE(&g->socks_mutex); diff --git a/src/platform/platform_win32/platform_win32.h b/src/platform/platform_win32/platform_win32.h index 3102cdd9..3a1c8093 100644 --- a/src/platform/platform_win32/platform_win32.h +++ b/src/platform/platform_win32/platform_win32.h @@ -114,7 +114,7 @@ Struct(P_W32_Sock) #define P_W32_WindowClassName L"power_play_window_class" -Struct(P_W32_SharedCtx) +Struct(P_W32_SharedState) { //- Key lookup table P_Btn vk_btn_table[256]; @@ -137,7 +137,7 @@ Struct(P_W32_SharedCtx) P_W32_Sock *first_free_sock; }; -extern P_W32_SharedCtx P_W32_shared_ctx; +extern P_W32_SharedState P_W32_shared_state; //////////////////////////////// //~ Time operations diff --git a/src/pp/pp.c b/src/pp/pp.c index fc0ab703..27cffb70 100644 --- a/src/pp/pp.c +++ b/src/pp/pp.c @@ -146,35 +146,35 @@ String DebugStringFromEntity(Arena *arena, Entity *ent) String result = ZI; result.text = PushDry(arena, u8); - //result.len += StringFormat(arena, Lit("[%F]"), FmtUid(ent->id.uid)).len; + //result.len += StringF(arena, "[%F]", FmtUid(ent->id.uid)).len; { b32 transmitting = HasProp(ent, Prop_SyncSrc); b32 receiving = HasProp(ent, Prop_SyncDst); if (transmitting & receiving) { - result.len += PushString(arena, Lit(" networked (sending & receiving)")).len; + result.len += StringF(arena, " networked (sending & receiving)").len; } else if (transmitting) { - result.len += PushString(arena, Lit(" networked (sending)")).len; + result.len += StringF(arena, " networked (sending)").len; } else if (receiving) { - result.len += PushString(arena, Lit(" networked (receiving)")).len; + result.len += StringF(arena, " networked (receiving)").len; } else { - result.len += PushString(arena, Lit(" local")).len; + result.len += StringF(arena, " local").len; } } - result.len += PushString(arena, Lit("\n")).len; + result.len += StringF(arena, "\n").len; - result.len += StringFormat(arena, Lit("owner: [%F]\n"), FmtUid(ent->owner.uid)).len; + result.len += StringF(arena, "owner: [%F]\n", FmtUid(ent->owner.uid)).len; - result.len += PushString(arena, Lit("\n")).len; + result.len += StringF(arena, "\n").len; { - result.len += PushString(arena, Lit("props: 0x")).len; + result.len += StringF(arena, "props: 0x").len; for (u64 chunk_index = countof(ent->props); chunk_index-- > 0;) { u64 chunk = ent->props[chunk_index]; @@ -189,32 +189,32 @@ String DebugStringFromEntity(Arena *arena, Entity *ent) } } } - result.len += PushString(arena, Lit("\n")).len; + result.len += StringF(arena, "\n").len; } if (!EqId(ent->parent, RootEntityId)) { - result.len += StringFormat(arena, Lit("parent: [%F]\n"), FmtUid(ent->parent.uid)).len; + result.len += StringF(arena, "parent: [%F]\n", FmtUid(ent->parent.uid)).len; } if (!IsNilId(ent->next) || !IsNilId(ent->prev)) { - result.len += StringFormat(arena, Lit("prev: [%F]\n"), FmtUid(ent->prev.uid)).len; - result.len += StringFormat(arena, Lit("next: [%F]\n"), FmtUid(ent->next.uid)).len; + result.len += StringF(arena, "prev: [%F]\n", FmtUid(ent->prev.uid)).len; + result.len += StringF(arena, "next: [%F]\n", FmtUid(ent->next.uid)).len; } - result.len += PushString(arena, Lit("\n")).len; + result.len += StringF(arena, "\n").len; /* Pos */ Xform xf = XformFromEntity(ent); Vec2 linear_velocity = ent->linear_velocity; f32 angular_velocity = ent->angular_velocity; - result.len += StringFormat(arena, Lit("pos: (%F, %F)\n"), FmtFloat(xf.og.x), FmtFloat(xf.og.y)).len; - result.len += StringFormat(arena, Lit("linear velocity: (%F, %F)\n"), FmtFloat(linear_velocity.x), FmtFloat(linear_velocity.y)).len; - result.len += StringFormat(arena, Lit("angular velocity: %F\n"), FmtFloat(angular_velocity)).len; + result.len += StringF(arena, "pos: (%F, %F)\n", FmtFloat(xf.og.x), FmtFloat(xf.og.y)).len; + result.len += StringF(arena, "linear velocity: (%F, %F)\n", FmtFloat(linear_velocity.x), FmtFloat(linear_velocity.y)).len; + result.len += StringF(arena, "angular velocity: %F\n", FmtFloat(angular_velocity)).len; /* Test */ - result.len += StringFormat(arena, Lit("collision dir: (%F, %F)\n"), FmtFloat(ent->collision_dir.x), FmtFloat(ent->collision_dir.y)).len; + result.len += StringF(arena, "collision dir: (%F, %F)\n", FmtFloat(ent->collision_dir.x), FmtFloat(ent->collision_dir.y)).len; /* Children */ if (!IsNilId(ent->first) || !IsNilId(ent->last)) @@ -222,13 +222,13 @@ String DebugStringFromEntity(Arena *arena, Entity *ent) Entity *child = EntityFromId(ss, ent->first); if (!EqId(ent->first, ent->last) || !child->valid) { - result.len += StringFormat(arena, Lit("first child: [%F]\n"), FmtUid(ent->first.uid)).len; - result.len += StringFormat(arena, Lit("last child: [%F]\n"), FmtUid(ent->last.uid)).len; + result.len += StringF(arena, "first child: [%F]\n", FmtUid(ent->first.uid)).len; + result.len += StringF(arena, "last child: [%F]\n", FmtUid(ent->last.uid)).len; } while (child->valid) { - result.len += PushString(arena, Lit("\n---------------------------------\n")).len; - result.len += PushString(arena, Lit("CHILD\n")).len; + result.len += StringF(arena, "\n---------------------------------\n").len; + result.len += StringF(arena, "CHILD\n").len; String child_text = DebugStringFromEntity(scratch.arena, child); result.len += IndentString(arena, child_text, 4).len; child = EntityFromId(ss, child->next); @@ -340,9 +340,9 @@ void DrawDebugConsole(i32 level, b32 minimized) if (!minimized) { P_DateTime datetime = log->datetime; - text = StringFormat( + text = StringF( scratch.arena, - Lit("[%F:%F:%F.%F] %F"), + "[%F:%F:%F.%F] %F", FmtUintZ(datetime.hour, 2), FmtUintZ(datetime.minute, 2), FmtUintZ(datetime.second, 2), @@ -457,8 +457,8 @@ MergesortCompareFuncDef(EntitySortCmp, arg_a, arg_b, _) if (result == 0) { /* Sort by sprite */ - u64 a_cmp = a->sprite.hash; - u64 b_cmp = b->sprite.hash; + u64 a_cmp = a->sprite.r.hash; + u64 b_cmp = b->sprite.r.hash; result = (a_cmp < b_cmp) - (a_cmp > b_cmp); } if (result == 0) @@ -485,7 +485,6 @@ void UpdateUser(P_Window *window) g->real_dt_ns = TimeNs() - g->real_time_ns; g->real_time_ns += g->real_dt_ns; g->screen_size = P_GetWindowSize(window); - S_Scope *sprite_frame_scope = S_BeginScope(); //- Pull latest local sim snapshot @@ -1217,8 +1216,8 @@ void UpdateUser(P_Window *window) /* Draw sprite */ if (!S_IsTagNil(sprite)) { - S_Sheet *sheet = S_SheetFromTagAsync(sprite_frame_scope, sprite); - S_Texture *texture = S_TextureFromTagAsync(sprite_frame_scope, sprite); + S_Sheet *sheet = S_SheetFromTagAsync(sprite); + S_Texture *texture = S_TextureFromTagAsync(sprite); /* TODO: Fade in placeholder if texture isn't loaded */ if (sheet->loaded && texture->loaded) @@ -1245,8 +1244,8 @@ void UpdateUser(P_Window *window) if (HasProp(ent, Prop_TileChunk)) { Vec2I32 chunk_index = ent->tile_chunk_index; - S_Tag tile_sprite = S_TagFromPath(Lit("sprite/tile.ase")); - S_Texture *tile_texture = S_TextureFromTagAsync(sprite_frame_scope, tile_sprite); + S_Tag tile_sprite = S_TagFromName(Lit("sprite/tile.ase")); + S_Texture *tile_texture = S_TextureFromTagAsync(tile_sprite); if (tile_texture->loaded) { f32 tile_size = 1.f / SIM_TILES_PER_UNIT_SQRT; @@ -1312,7 +1311,7 @@ void UpdateUser(P_Window *window) /* Draw focus arrow */ if (ent == local_control || EqId(ent->id, g->debug_following)) { - S_Sheet *sheet = S_SheetFromTagAsync(sprite_frame_scope, ent->sprite); + S_Sheet *sheet = S_SheetFromTagAsync(ent->sprite); S_Slice slice = S_SliceFromNameIndex(sheet, Lit("attach.wep"), ent->animation_frame); Vec2 start = MulXformV2(sprite_xform, slice.center); start = MulXformV2(g->world_to_ui_xf, start); @@ -1326,7 +1325,7 @@ void UpdateUser(P_Window *window) /* Draw slices */ if (!S_IsTagNil(ent->sprite)) { - S_Sheet *sheet = S_SheetFromTagAsync(sprite_frame_scope, sprite); + S_Sheet *sheet = S_SheetFromTagAsync(sprite); u32 quad_color = Rgba32F(1, 0, 0.5, 1); u32 point_color = Rgba32F(1, 0, 0, 1); @@ -1495,16 +1494,15 @@ void UpdateUser(P_Window *window) "normal: (%F, %F)\n" "num contacts: %F" ); - String text = StringFormat(temp.arena, fmt, - FmtUint(e0->handle.idx), - FmtUint(e1->handle.idx), - FmtHex(point.id), - FmtFloat(point.normal_impulse), - FmtFloat(point.tangent_impulse), - FmtFloatP(point.starting_separation, 6), - FmtFloatP(data->normal.x, 6), FmtFloatP(data->normal.y, 6), - FmtUint(data->num_points)); - + String text = StringF(temp.arena, fmt, + FmtUint(e0->handle.idx), + FmtUint(e1->handle.idx), + FmtHex(point.id), + FmtFloat(point.normal_impulse), + FmtFloat(point.tangent_impulse), + FmtFloatP(point.starting_separation, 6), + FmtFloatP(data->normal.x, 6), FmtFloatP(data->normal.y, 6), + FmtUint(data->num_points)); draw_text(g->render_sig, disp_font, AddVec2(RoundVec2(MulXformV2(g->world_to_ui_xf, dbg_pt)), VEC2(0, offset_px)), text); } @@ -1613,12 +1611,11 @@ void UpdateUser(P_Window *window) "e1 pos: (%F, %F)\n" "e1 rot: %F\n" ); - String text = StringFormat(temp.arena, fmt, - FmtFloatP(e0_xf.og.x, 24), FmtFloatP(e0_xf.og.y, 24), - FmtFloatP(RotationFromXform(e0_xf), 24), - FmtFloatP(e1_xf.og.x, 24), FmtFloatP(e1_xf.og.y, 24), - FmtFloatP(RotationFromXform(e1_xf), 24)); - + String text = StringF(temp.arena, fmt, + FmtFloatP(e0_xf.og.x, 24), FmtFloatP(e0_xf.og.y, 24), + FmtFloatP(RotationFromXform(e0_xf), 24), + FmtFloatP(e1_xf.og.x, 24), FmtFloatP(e1_xf.og.y, 24), + FmtFloatP(RotationFromXform(e1_xf), 24)); draw_text(g->render_sig, disp_font, AddVec2(RoundVec2(MulXformV2(g->world_to_ui_xf, VEC2(0, 0))), VEC2(0, offset_px)), text); } @@ -1758,7 +1755,7 @@ void UpdateUser(P_Window *window) __profn("Draw crosshair"); Vec2 crosshair_pos = g->ui_cursor; S_Tag crosshair = S_TagFromPath(Lit("sprite/crosshair.ase")); - S_Texture *t = S_TextureFromTagAsync(sprite_frame_scope, crosshair); + S_Texture *t = S_TextureFromTagAsync(crosshair); Vec2 size = VEC2(t->width, t->height); Xform xf = XformFromTrs(TRS(.t = crosshair_pos, .s = size)); D_DrawUiRect(g->render_sig, D_UIRECTPARAMS(.xf = xf, .texture = t->gpu_resource)); @@ -1776,7 +1773,7 @@ void UpdateUser(P_Window *window) } else { - S_Texture *t = S_TextureFromTagAsync(sprite_frame_scope, S_TagFromPath(Lit("sprite/crosshair.ase"))); + S_Texture *t = S_TextureFromTagAsync(S_TagFromPath(Lit("sprite/crosshair.ase"))); Vec2 size = VEC2(t->width, t->height); Rect cursor_clip = RectFromVec2(g->ui_screen_offset, g->ui_size); cursor_clip.pos = AddVec2(cursor_clip.pos, MulVec2(size, 0.5f)); @@ -2025,97 +2022,97 @@ void UpdateUser(P_Window *window) text.text = PushDry(temp.arena, u8); #if BITBUFF_DEBUG - text.len += PushString(temp.arena, Lit("(bitbuff debug enabled)")).len; - text.len += PushString(temp.arena, Lit("\n")).len; + text.len += StringF(temp.arena, "(bitbuff debug enabled)").len; + text.len += StringF(temp.arena, "\n").len; #endif - text.len += StringFormat(temp.arena, Lit("blended world entities: %F/%F"), FmtUint(g->ss_blended->num_ents_allocated), FmtUint(g->ss_blended->num_ents_reserved)).len; - text.len += PushString(temp.arena, Lit("\n")).len; + text.len += StringF(temp.arena, "blended world entities: %F/%F", FmtUint(g->ss_blended->num_ents_allocated), FmtUint(g->ss_blended->num_ents_reserved)).len; + text.len += StringF(temp.arena, "\n").len; - text.len += StringFormat(temp.arena, Lit("blended world tick: %F"), FmtUint(g->ss_blended->tick)).len; - text.len += PushString(temp.arena, Lit("\n")).len; + text.len += StringF(temp.arena, "blended world tick: %F", FmtUint(g->ss_blended->tick)).len; + text.len += StringF(temp.arena, "\n").len; - text.len += StringFormat(temp.arena, Lit("blended world time: %F"), FmtFloat(SecondsFromNs(g->ss_blended->sim_time_ns))).len; - text.len += PushString(temp.arena, Lit("\n")).len; - text.len += PushString(temp.arena, Lit("\n")).len; + text.len += StringF(temp.arena, "blended world time: %F", FmtFloat(SecondsFromNs(g->ss_blended->sim_time_ns))).len; + text.len += StringF(temp.arena, "\n").len; + text.len += StringF(temp.arena, "\n").len; - text.len += StringFormat(temp.arena, Lit("average local sim publish dt: %F"), FmtFloat(SecondsFromNs(g->average_local_to_user_snapshot_publish_dt_ns))).len; - text.len += PushString(temp.arena, Lit("\n")).len; + text.len += StringF(temp.arena, "average local sim publish dt: %F", FmtFloat(SecondsFromNs(g->average_local_to_user_snapshot_publish_dt_ns))).len; + text.len += StringF(temp.arena, "\n").len; - text.len += StringFormat(temp.arena, Lit("local sim last known tick: %F"), FmtUint(g->local_sim_last_known_tick)).len; - text.len += PushString(temp.arena, Lit("\n")).len; + text.len += StringF(temp.arena, "local sim last known tick: %F", FmtUint(g->local_sim_last_known_tick)).len; + text.len += StringF(temp.arena, "\n").len; - text.len += StringFormat(temp.arena, Lit("local sim last known time: %F"), FmtFloat(SecondsFromNs(g->local_sim_last_known_time_ns))).len; - text.len += PushString(temp.arena, Lit("\n")).len; + text.len += StringF(temp.arena, "local sim last known time: %F", FmtFloat(SecondsFromNs(g->local_sim_last_known_time_ns))).len; + text.len += StringF(temp.arena, "\n").len; - text.len += StringFormat(temp.arena, Lit("local sim predicted time: %F"), FmtFloat(SecondsFromNs(g->local_sim_predicted_time_ns))).len; - text.len += PushString(temp.arena, Lit("\n")).len; + text.len += StringF(temp.arena, "local sim predicted time: %F", FmtFloat(SecondsFromNs(g->local_sim_predicted_time_ns))).len; + text.len += StringF(temp.arena, "\n").len; - text.len += StringFormat(temp.arena, Lit("render time target: %F"), FmtFloat(SecondsFromNs(g->render_time_target_ns))).len; - text.len += PushString(temp.arena, Lit("\n")).len; + text.len += StringF(temp.arena, "render time target: %F", FmtFloat(SecondsFromNs(g->render_time_target_ns))).len; + text.len += StringF(temp.arena, "\n").len; - text.len += StringFormat(temp.arena, Lit("render time: %F"), FmtFloat(SecondsFromNs(g->render_time_ns))).len; - text.len += PushString(temp.arena, Lit("\n")).len; - text.len += PushString(temp.arena, Lit("\n")).len; + text.len += StringF(temp.arena, "render time: %F", FmtFloat(SecondsFromNs(g->render_time_ns))).len; + text.len += StringF(temp.arena, "\n").len; + text.len += StringF(temp.arena, "\n").len; - text.len += StringFormat(temp.arena, Lit("local player: [%F]"), FmtUid(local_player->id.uid)).len; - text.len += PushString(temp.arena, Lit("\n")).len; - text.len += PushString(temp.arena, Lit("\n")).len; + text.len += StringF(temp.arena, "local player: [%F]", FmtUid(local_player->id.uid)).len; + text.len += StringF(temp.arena, "\n").len; + text.len += StringF(temp.arena, "\n").len; Vec2 world_cursor = g->world_cursor; - text.len += StringFormat(temp.arena, Lit("cursor world: %F, %F"), FmtFloat(world_cursor.x), FmtFloat(world_cursor.y)).len; - text.len += PushString(temp.arena, Lit("\n")).len; + text.len += StringF(temp.arena, "cursor world: %F, %F", FmtFloat(world_cursor.x), FmtFloat(world_cursor.y)).len; + text.len += StringF(temp.arena, "\n").len; Vec2I32 world_tile_cursor = WorldTileIndexFromPos(world_cursor); - text.len += StringFormat(temp.arena, Lit("cursor world tile: %F, %F"), FmtSint(world_tile_cursor.x), FmtSint(world_tile_cursor.y)).len; - text.len += PushString(temp.arena, Lit("\n")).len; + text.len += StringF(temp.arena, "cursor world tile: %F, %F", FmtSint(world_tile_cursor.x), FmtSint(world_tile_cursor.y)).len; + text.len += StringF(temp.arena, "\n").len; Vec2I32 local_tile_cursor = LocalTileIndexFromWorldTileIndex(world_tile_cursor); - text.len += StringFormat(temp.arena, Lit("cursor local tile: %F, %F"), FmtSint(local_tile_cursor.x), FmtSint(local_tile_cursor.y)).len; - text.len += PushString(temp.arena, Lit("\n")).len; + text.len += StringF(temp.arena, "cursor local tile: %F, %F", FmtSint(local_tile_cursor.x), FmtSint(local_tile_cursor.y)).len; + text.len += StringF(temp.arena, "\n").len; Vec2I32 tile_chunk_cursor = TileChunkIndexFromWorldTileIndex(world_tile_cursor); - text.len += StringFormat(temp.arena, Lit("cursor tile chunk: %F, %F"), FmtSint(tile_chunk_cursor.x), FmtSint(tile_chunk_cursor.y)).len; - text.len += PushString(temp.arena, Lit("\n")).len; - text.len += PushString(temp.arena, Lit("\n")).len; + text.len += StringF(temp.arena, "cursor tile chunk: %F, %F", FmtSint(tile_chunk_cursor.x), FmtSint(tile_chunk_cursor.y)).len; + text.len += StringF(temp.arena, "\n").len; + text.len += StringF(temp.arena, "\n").len; - text.len += StringFormat(temp.arena, Lit("Network read: %F mbit/s"), FmtFloat((f64)g->net_bytes_read.last_second * 8 / 1000 / 1000)).len; - text.len += PushString(temp.arena, Lit("\n")).len; + text.len += StringF(temp.arena, "Network read: %F mbit/s", FmtFloat((f64)g->net_bytes_read.last_second * 8 / 1000 / 1000)).len; + text.len += StringF(temp.arena, "\n").len; - text.len += StringFormat(temp.arena, Lit("Network write: %F mbit/s"), FmtFloat((f64)g->net_bytes_sent.last_second * 8 / 1000 / 1000)).len; - text.len += PushString(temp.arena, Lit("\n")).len; + text.len += StringF(temp.arena, "Network write: %F mbit/s", FmtFloat((f64)g->net_bytes_sent.last_second * 8 / 1000 / 1000)).len; + text.len += StringF(temp.arena, "\n").len; - text.len += StringFormat(temp.arena, Lit("Ping (real): %F ms"), FmtFloat(SecondsFromNs(local_player->player_last_rtt_ns) * 1000)).len; - text.len += PushString(temp.arena, Lit("\n")).len; + text.len += StringF(temp.arena, "Ping (real): %F ms", FmtFloat(SecondsFromNs(local_player->player_last_rtt_ns) * 1000)).len; + text.len += StringF(temp.arena, "\n").len; - text.len += StringFormat(temp.arena, Lit("Ping (average): %F ms"), FmtFloat(local_player->player_average_rtt_seconds * 1000)).len; - text.len += PushString(temp.arena, Lit("\n")).len; - text.len += PushString(temp.arena, Lit("\n")).len; + text.len += StringF(temp.arena, "Ping (average): %F ms", FmtFloat(local_player->player_average_rtt_seconds * 1000)).len; + text.len += StringF(temp.arena, "\n").len; + text.len += StringF(temp.arena, "\n").len; - text.len += StringFormat(temp.arena, Lit("Memory committed: %F MiB"), FmtFloat((f64)GetGstat(GSTAT_MEMORY_COMMITTED) / 1024 / 1024)).len; - text.len += PushString(temp.arena, Lit("\n")).len; + text.len += StringF(temp.arena, "Memory committed: %F MiB", FmtFloat((f64)GetGstat(GSTAT_MEMORY_COMMITTED) / 1024 / 1024)).len; + text.len += StringF(temp.arena, "\n").len; - text.len += StringFormat(temp.arena, Lit("Virtual memory reserved: %F TiB"), FmtFloat((f64)GetGstat(GSTAT_MEMORY_RESERVED) / 1024 / 1024 / 1024 / 1024)).len; - text.len += PushString(temp.arena, Lit("\n")).len; + text.len += StringF(temp.arena, "Virtual memory reserved: %F TiB", FmtFloat((f64)GetGstat(GSTAT_MEMORY_RESERVED) / 1024 / 1024 / 1024 / 1024)).len; + text.len += StringF(temp.arena, "\n").len; - text.len += StringFormat(temp.arena, Lit("Arenas allocated: %F"), FmtUint(GetGstat(GSTAT_NUM_ARENAS))).len; - text.len += PushString(temp.arena, Lit("\n")).len; - text.len += PushString(temp.arena, Lit("\n")).len; + text.len += StringF(temp.arena, "Arenas allocated: %F", FmtUint(GetGstat(GSTAT_NUM_ARENAS))).len; + text.len += StringF(temp.arena, "\n").len; + text.len += StringF(temp.arena, "\n").len; - text.len += StringFormat(temp.arena, Lit("Video memory (GPU): %F MiB"), FmtFloat((f64)vram.local_used / 1024 / 1024)).len; - text.len += PushString(temp.arena, Lit("\n")).len; - text.len += StringFormat(temp.arena, Lit("Video memory (shared): %F MiB"), FmtFloat((f64)vram.non_local_used / 1024 / 1024)).len; - //text.len += PushString(temp.arena, Lit("\n")).len; - //text.len += PushString(temp.arena, Lit("\n")).len; + text.len += StringF(temp.arena, "Video memory (GPU): %F MiB", FmtFloat((f64)vram.local_used / 1024 / 1024)).len; + text.len += StringF(temp.arena, "\n").len; + text.len += StringF(temp.arena, "Video memory (shared): %F MiB", FmtFloat((f64)vram.non_local_used / 1024 / 1024)).len; + //text.len += StringF(temp.arena, \n")).len; + //text.len += StringF(temp.arena, \n")).len; #if RtcIsEnabled - text.len += PushString(temp.arena, Lit("\n")).len; - text.len += PushString(temp.arena, Lit("\n")).len; - text.len += StringFormat(temp.arena, Lit("Debug steps: %F"), FmtUint(GetGstat(GSTAT_DEBUG_STEPS))).len; - //text.len += PushString(temp.arena, Lit("\n")).len; + text.len += StringF(temp.arena, "\n").len; + text.len += StringF(temp.arena, "\n").len; + text.len += StringF(temp.arena, "Debug steps: %F", FmtUint(GetGstat(GSTAT_DEBUG_STEPS))).len; + //text.len += StringF(temp.arena, \n")).len; #endif - //draw_text(g->render_sig, font, pos, StringFormat(temp.arena, Lit("blended world entities: %F/%F"), FmtUint(g->ss_blended->num_ents_allocated), FmtUint(g->ss_blended->num_ents_reserved))); + //draw_text(g->render_sig, font, pos, StringF(temp.arena, "blended world entities: %F/%F", FmtUint(g->ss_blended->num_ents_allocated), FmtUint(g->ss_blended->num_ents_reserved))); //draw_text(g->render_sig, font, pos, text); Vec2 pos = VEC2(10, g->ui_size.y); @@ -2193,9 +2190,9 @@ void UpdateUser(P_Window *window) GPU_Resource *grids_buffer = AcquireTransferBufferFromArena(g->grids_count, g->grids_arena); GPU_CommandList *cl = GPU_BeginCommandList(); - GPU_ProfileDF(cl, Lit("Run render")); { __profn("Run render"); + GPU_ProfN(cl, Lit("Run render")); Mat4x4 world_to_render_vp_matrix = ProjectMat4x4View(g->world_to_render_xf, render_viewport.width, render_viewport.height); Mat4x4 ui_vp_matrix = ProjectMat4x4View(XformIdentity, ui_viewport.width, ui_viewport.height); Mat4x4 blit_vp_matrix = ZI; @@ -2207,9 +2204,9 @@ void UpdateUser(P_Window *window) } //- Prep material pass - GPU_ProfileDF(cl, Lit("Clear gbuffers")); { __profn("Clear gbuffers"); + GPU_ProfN(cl, Lit("Clear gbuffers")); GPU_TransitionToRtv(cl, g->albedo); GPU_TransitionToRtv(cl, g->emittance); GPU_DispatchClear(cl, g->albedo); @@ -2217,9 +2214,9 @@ void UpdateUser(P_Window *window) } //- Material pass - GPU_ProfileDF(cl, Lit("Material pass")); { __profn("Material pass"); + GPU_ProfN(cl, Lit("Material pass")); GPU_Resource *rts[] = { g->albedo, @@ -2252,9 +2249,9 @@ void UpdateUser(P_Window *window) //- Flood pass if (!effects_disabled) - GPU_ProfileDF(cl, Lit("Flood pass")); { __profn("Flood pass"); + GPU_ProfN(cl, Lit("Flood pass")); i32 step_length = -1; @@ -2262,11 +2259,11 @@ void UpdateUser(P_Window *window) u64 max_steps = GetGstat(GSTAT_DEBUG_STEPS); u64 step = 0; while (step_length != 0 && step < max_steps) - GPU_ProfileDF(cl, Lit("Flood step")); { __profn("Flood step"); + GPU_ProfN(cl, Lit("Flood step")); - GPU_Flush(cl, g->emittance_flood_read); + GPU_FlushUav(cl, g->emittance_flood_read); FloodSig sig = ZI; sig.step_len = step_length; @@ -2296,21 +2293,21 @@ void UpdateUser(P_Window *window) } //- Prep shade pass - GPU_ProfileDF(cl, Lit("Clear shade target")); { __profn("Clear shade target"); + GPU_ProfN(cl, Lit("Clear shade target")); GPU_TransitionToSrv(cl, g->albedo); GPU_TransitionToSrv(cl, g->emittance); GPU_TransitionToUav(cl, g->shade_target); - GPU_Flush(cl, g->emittance_flood_read); - GPU_Flush(cl, g->shade_read); + GPU_FlushUav(cl, g->emittance_flood_read); + GPU_FlushUav(cl, g->shade_read); GPU_DispatchClear(cl, g->shade_target); } //- Shade pass - GPU_ProfileDF(cl, Lit("Shade pass")); { __profn("Shade pass"); + GPU_ProfN(cl, Lit("Shade pass")); u32 shade_flags = K_SHADE_FLAG_NONE; if (effects_disabled) @@ -2341,18 +2338,18 @@ void UpdateUser(P_Window *window) } //- Prep ui pass - GPU_ProfileDF(cl, Lit("Clear ui target")); { __profn("Clear ui target"); + GPU_ProfN(cl, Lit("Clear ui target")); GPU_TransitionToRtv(cl, g->ui_target); - GPU_Flush(cl, g->shade_read); + GPU_FlushUav(cl, g->shade_read); GPU_DispatchClear(cl, g->ui_target); } //- Ui blit pass - GPU_ProfileDF(cl, Lit("UI blit pass")); { __profn("UI blit pass"); + GPU_ProfN(cl, Lit("UI blit pass")); GPU_Viewport viewport = GPU_ViewportFromRect(ui_viewport); GPU_Scissor scissor = GPU_ScissorFromRect(ui_viewport); @@ -2375,9 +2372,9 @@ void UpdateUser(P_Window *window) } //- Ui rect pass - GPU_ProfileDF(cl, Lit("UI rect pass")); { __profn("UI rect pass"); + GPU_ProfN(cl, Lit("UI rect pass")); GPU_Viewport viewport = GPU_ViewportFromRect(ui_viewport); GPU_Scissor scissor = GPU_ScissorFromRect(ui_viewport); @@ -2397,9 +2394,9 @@ void UpdateUser(P_Window *window) } //- Ui shape pass - GPU_ProfileDF(cl, Lit("UI shape pass")); { __profn("UI shape pass"); + GPU_ProfN(cl, Lit("UI shape pass")); GPU_Viewport viewport = GPU_ViewportFromRect(ui_viewport); GPU_Scissor scissor = GPU_ScissorFromRect(ui_viewport); @@ -2441,10 +2438,6 @@ void UpdateUser(P_Window *window) } } - //- End frame cache scopes - - S_EndScope(sprite_frame_scope); - EndScratch(scratch); } diff --git a/src/pp/pp_step.c b/src/pp/pp_step.c index 5730c2b8..95cce2ec 100644 --- a/src/pp/pp_step.c +++ b/src/pp/pp_step.c @@ -36,7 +36,7 @@ void ResetSimAccel(Snapshot *ss, SimAccel *accel) Entity *SpawnTestSmg(Entity *parent) { Entity *e = AcquireSyncSrc(parent); - e->sprite = S_TagFromPath(Lit("sprite/gun.ase")); + e->sprite = S_TagFromName(Lit("sprite/gun.ase")); EnableProp(e, Prop_Attached); e->attach_slice = Lit("attach.wep"); @@ -52,7 +52,7 @@ Entity *SpawnTestSmg(Entity *parent) Entity *SpawnTestLauncher(Entity *parent) { Entity *e = AcquireSyncSrc(parent); - e->sprite = S_TagFromPath(Lit("sprite/gun.ase")); + e->sprite = S_TagFromName(Lit("sprite/gun.ase")); EnableProp(e, Prop_Attached); e->attach_slice = Lit("attach.wep"); @@ -68,7 +68,7 @@ Entity *SpawnTestLauncher(Entity *parent) Entity *SpawnTestChucker(Entity *parent) { Entity *chucker = AcquireSyncSrc(parent); - chucker->sprite = S_TagFromPath(Lit("sprite/gun.ase")); + chucker->sprite = S_TagFromName(Lit("sprite/gun.ase")); EnableProp(chucker, Prop_Attached); chucker->attach_slice = Lit("attach.wep"); @@ -119,12 +119,12 @@ Entity *SpawnTestEmployee(Entity *parent) { EnableProp(e, Prop_Test); - e->sprite = S_TagFromPath(Lit("sprite/tim.ase")); + e->sprite = S_TagFromName(Lit("sprite/tim.ase")); e->mass_unscaled = 10; e->inertia_unscaled = 5; } - //e->sprite = S_TagFromPath(Lit("sprite/box_rounded.ase")); + //e->sprite = S_TagFromName(Lit("sprite/box_rounded.ase")); //e->sprite_span_name = Lit("idle.unarmed"); //e->sprite_span_name = Lit("idle.one_handed"); e->sprite_span_name = Lit("idle.two_handed"); @@ -257,7 +257,7 @@ void SpawnTestEntities2(Entity *parent, Vec2 pos) Xform xf = XformFromTrs(TRS(.t = pos, .r = rot, .s = size)); SetXform(e, xf); - e->sprite = S_TagFromPath(Lit("sprite/tile.ase")); + e->sprite = S_TagFromName(Lit("sprite/tile.ase")); e->layer = Layer_Shoulders; //e->sprite_tint = Alpha32F(ColorBlue, 0.75); @@ -299,7 +299,7 @@ void SpawnTestEntities2(Entity *parent, Vec2 pos) Xform xf = XformFromTrs(.t = pos, .r = r, .s = size); SetXform(e, xf); - e->sprite = S_TagFromPath(Lit("sprite/bullet.ase")); + e->sprite = S_TagFromName(Lit("sprite/bullet.ase")); e->sprite_collider_slice = Lit("shape"); e->layer = Layer_Shoulders; @@ -327,7 +327,7 @@ void SpawnTestEntities3(Entity *parent, Vec2 pos) Xform xf = XformFromTrs(TRS(.t = pos, .r = r, .s = size)); SetXform(e, xf); - e->sprite = S_TagFromPath(Lit("sprite/box.ase")); + e->sprite = S_TagFromName(Lit("sprite/box.ase")); e->layer = Layer_Shoulders; e->sprite_tint = ColorRed; @@ -350,8 +350,8 @@ void SpawnTestEntities4(Entity *parent, Vec2 pos) Xform xf = XformFromTrs(TRS(.t = pos, .r = r, .s = size)); SetXform(e, xf); - //e->sprite = S_TagFromPath(Lit("sprite/box.ase")); - e->sprite = S_TagFromPath(Lit("sprite/tile.ase")); + //e->sprite = S_TagFromName(Lit("sprite/box.ase")); + e->sprite = S_TagFromName(Lit("sprite/tile.ase")); e->layer = Layer_Shoulders; EnableProp(e, Prop_LightTest); @@ -380,15 +380,11 @@ void SpawnTestTile(Snapshot *world, Vec2 world_pos) SetXform(e, xf); e->layer = Layer_Walls; - e->sprite = S_TagFromPath(Lit("sprite/tile.ase")); + e->sprite = S_TagFromName(Lit("sprite/tile.ase")); e->sprite_tint = ColorRed; - { - S_Scope *scope = S_BeginScope(); - S_Sheet *sheet = S_SheetFromTagAwait(scope, e->sprite); - e->sprite_local_xform = XformFromTrs(.s = DivVec2(sheet->frame_size, PIXELS_PER_UNIT)); - S_EndScope(scope); - } + S_Sheet *sheet = S_SheetFromTagAwait(e->sprite); + e->sprite_local_xform = XformFromTrs(.s = DivVec2(sheet->frame_size, PIXELS_PER_UNIT)); EnableProp(e, Prop_Solid); Quad collider_quad = QuadFromRect(RectFromScalar(-tile_size.x / 2, -tile_size.y / 2, tile_size.y, tile_size.y)); @@ -787,7 +783,7 @@ CollisionCallbackFuncDef(OnEntityCollision, data, step_ctx) { Xform xf = XformFromTrs(TRS(.t = point, .r = RandF64FromState(&step_ctx->rand, 0, Tau))); Entity *decal = AcquireSyncSrc(root); - decal->sprite = S_TagFromPath(Lit("sprite/blood.ase")); + decal->sprite = S_TagFromName(Lit("sprite/blood.ase")); decal->sprite_tint = Rgba32F(1, 1, 1, 0.25f); decal->layer = Layer_FloorDecals; SetXform(decal, xf); @@ -901,8 +897,6 @@ void StepSim(SimStepCtx *ctx) world->sim_time_ns += world->sim_dt_ns; f32 sim_dt = SecondsFromNs(world->sim_dt_ns); - S_Scope *sprite_frame_scope = S_BeginScope(); - Entity *root = EntityFromId(world, RootEntityId); root->owner = world->client->player_id; @@ -1257,7 +1251,7 @@ void StepSim(SimStepCtx *ctx) if (!ShouldSimulate(ent)) continue; if (S_IsTagNil(ent->sprite)) continue; - S_Sheet *sheet = S_SheetFromTagAwait(sprite_frame_scope, ent->sprite); + S_Sheet *sheet = S_SheetFromTagAwait(ent->sprite); /* Update animation */ { @@ -1297,16 +1291,16 @@ void StepSim(SimStepCtx *ctx) #if 0 /* Update sprite local xform */ { - S_Slice slice = S_SliceFromNameIndex(sheet, Lit("pivot"), ent->animation_frame); + S_Slice pivot_slice = S_SliceFromName(sheet, Lit("pivot"), ent->animation_frame); Vec2 sprite_size = DivVec2(sheet->frame_size, (f32)PIXELS_PER_UNIT); - Vec2 dir = MulVec2Vec2(sprite_size, slice.dir); + Vec2 dir = MulVec2Vec2(sprite_size, pivot_slice.dir); f32 rot = AngleFromVec2(dir) + Pi / 2; Xform xf = XformIdentity; xf = RotateXform(xf, -rot); xf = ScaleXform(xf, sprite_size); - xf = TranslateXform(xf, NegVec2(slice.center)); + xf = TranslateXform(xf, NegVec2(pivot_slice.center)); ent->sprite_local_xform = xf; } #endif @@ -1315,8 +1309,7 @@ void StepSim(SimStepCtx *ctx) if (ent->sprite_collider_slice.len > 0) { Xform cxf = ent->sprite_local_xform; - - S_Slice slice = S_SliceFromNameIndex(sheet, ent->sprite_collider_slice, ent->animation_frame); + S_Slice slice = S_SliceFromName(sheet, ent->sprite_collider_slice, ent->animation_frame); ent->local_collider = CLD_ShapeFromQuad(MulXformQuad(cxf, QuadFromRect(slice.rect))); } @@ -1367,11 +1360,11 @@ void StepSim(SimStepCtx *ctx) Entity *parent = EntityFromId(world, ent->parent); S_Tag parent_sprite = parent->sprite; - S_Sheet *parent_sheet = S_SheetFromTagAwait(sprite_frame_scope, parent_sprite); + S_Sheet *parent_sheet = S_SheetFromTagAwait(parent_sprite); Xform parent_sprite_xf = parent->sprite_local_xform; - S_Slice attach_slice = S_SliceFromNameIndex(parent_sheet, ent->attach_slice, parent->animation_frame); + S_Slice attach_slice = S_SliceFromName(parent_sheet, ent->attach_slice, parent->animation_frame); Vec2 attach_pos = MulXformV2(parent_sprite_xf, attach_slice.center); Vec2 attach_dir = MulXformBasisV2(parent_sprite_xf, attach_slice.dir); @@ -1459,9 +1452,9 @@ void StepSim(SimStepCtx *ctx) { S_Tag sprite = ent->sprite; u32 animation_frame = ent->animation_frame; - S_Sheet *sheet = S_SheetFromTagAwait(sprite_frame_scope, sprite); + S_Sheet *sheet = S_SheetFromTagAwait(sprite); Xform sprite_local_xform = ent->sprite_local_xform; - S_Slice out_slice = S_SliceFromNameIndex(sheet, Lit("out"), animation_frame); + S_Slice out_slice = S_SliceFromName(sheet, Lit("out"), animation_frame); Vec2 rel_pos = MulXformV2(sprite_local_xform, out_slice.center); Vec2 rel_dir = MulXformBasisV2(sprite_local_xform, out_slice.dir); @@ -1484,7 +1477,7 @@ void StepSim(SimStepCtx *ctx) bullet->local_collider.points[0] = VEC2(0, 0); bullet->local_collider.count = 1; #else - bullet->sprite = S_TagFromPath(Lit("sprite/bullet.ase")); + bullet->sprite = S_TagFromName(Lit("sprite/bullet.ase")); bullet->sprite_collider_slice = Lit("shape"); #endif } @@ -1508,9 +1501,9 @@ void StepSim(SimStepCtx *ctx) { S_Tag sprite = ent->sprite; u32 animation_frame = ent->animation_frame; - S_Sheet *sheet = S_SheetFromTagAwait(sprite_frame_scope, sprite); + S_Sheet *sheet = S_SheetFromTagAwait(sprite); Xform sprite_local_xform = ent->sprite_local_xform; - S_Slice out_slice = S_SliceFromNameIndex(sheet, Lit("out"), animation_frame); + S_Slice out_slice = S_SliceFromName(sheet, Lit("out"), animation_frame); Vec2 rel_pos = MulXformV2(sprite_local_xform, out_slice.center); Vec2 rel_dir = MulXformBasisV2(sprite_local_xform, out_slice.dir); @@ -1680,8 +1673,8 @@ void StepSim(SimStepCtx *ctx) Vec2 sprite_hold_pos; Vec2 sprite_hold_dir; { - S_Sheet *sheet = S_SheetFromTagAwait(sprite_frame_scope, ent->sprite); - S_Slice slice = S_SliceFromNameIndex(sheet, Lit("attach.wep"), ent->animation_frame); + S_Sheet *sheet = S_SheetFromTagAwait(ent->sprite); + S_Slice slice = S_SliceFromName(sheet, Lit("attach.wep"), ent->animation_frame); sprite_hold_pos = slice.center; sprite_hold_dir = slice.dir; } @@ -2073,9 +2066,5 @@ void StepSim(SimStepCtx *ctx) pub_world->local_player = world->local_player; } - //- End frame - - S_EndScope(sprite_frame_scope); - EndScratch(scratch); } diff --git a/src/res/res.c b/src/res/res.c index e69de29b..102d0099 100644 --- a/src/res/res.c +++ b/src/res/res.c @@ -0,0 +1,24 @@ + +//////////////////////////////// +//~ Tag helpers + +R_Tag R_TagFromName(String name) +{ + R_Tag result = ZI; + return result; +} + +//////////////////////////////// +//~ Resource operations + +String R_DataFromTag(R_Tag tag) +{ + String result = ZI; + return result; +} + +String R_NameFromTag(R_Tag tag) +{ + String result = ZI; + return result; +} diff --git a/src/res/res.h b/src/res/res.h index c668b040..bf08da7f 100644 --- a/src/res/res.h +++ b/src/res/res.h @@ -9,5 +9,10 @@ Struct(R_Tag) //////////////////////////////// //~ Tag helpers +R_Tag R_TagFromName(String name); + +//////////////////////////////// +//~ Resource operations + String R_DataFromTag(R_Tag tag); String R_NameFromTag(R_Tag tag); diff --git a/src/settings/settings.c b/src/settings/settings.c index c9218d37..560eea20 100644 --- a/src/settings/settings.c +++ b/src/settings/settings.c @@ -27,7 +27,7 @@ String SETTINGS_StringFromWindowSettings(Arena *arena, const P_WindowSettings *s "}\n" ); - String formatted = StringFormat(arena, + String formatted = FormatString(arena, fmt, FmtString(minimized), FmtString(maximized), @@ -165,11 +165,11 @@ abort: { if (json_error.msg.len > 0) { - *error_out = StringFormat(arena, - Lit("%F\n(%F:%F)"), - FmtString(json_error.msg), - FmtUint(json_error.start), - FmtUint(json_error.end)); + *error_out = StringF(arena, + Lit("%F\n(%F:%F)"), + FmtString(json_error.msg), + FmtUint(json_error.start), + FmtUint(json_error.end)); } else { diff --git a/src/sound/sound.c b/src/sound/sound.c index 242d9dc8..45a6f54d 100644 --- a/src/sound/sound.c +++ b/src/sound/sound.c @@ -87,10 +87,10 @@ AC_Asset *SND_LoadAsset(R_Tag resource, SND_SoundFlag flags, b32 wait) /* Generate and append sound flags to name key */ String name = R_NameFromTag(resource); - String key = StringFormat(scratch.arena, - Lit("%F%F_sound"), - FmtString(name), - FmtUint((u64)flags)); + String key = StringF(scratch.arena, + "%F%F_sound", + FmtString(name), + FmtUint((u64)flags)); u64 hash = AC_HashFromKey(key); b32 is_first_touch; AC_Asset *asset = AC_TouchCache(key, hash, &is_first_touch); diff --git a/src/sprite/sprite.c b/src/sprite/sprite.c index e54c6d91..75d10b59 100644 --- a/src/sprite/sprite.c +++ b/src/sprite/sprite.c @@ -5,1221 +5,72 @@ S_SharedState S_shared_state = ZI; void S_Startup(void) { - __prof; - S_SharedState *g = &S_shared_state; - g->perm_arena = AcquireArena(Mebi(1)); - { - /* Init loading texture */ - g->loading_texture = PushStruct(g->perm_arena, S_Texture); - - /* Init nil texture */ - g->nil_texture = PushStruct(g->perm_arena, S_Texture); - g->nil_texture->loaded = 1; - { - TempArena scratch = BeginScratchNoConflict(); - GPU_ResourceDesc desc = ZI; - desc.kind = GPU_ResourceKind_Texture2D; - desc.texture.format = GPU_Format_R8G8B8A8_Unorm; - desc.texture.size = VEC3I32(64, 64, 1); - g->nil_texture->gpu_resource = GPU_AcquireResource(desc); - u32 *pixels = S_GeneratePurpleBlackImage(scratch.arena, desc.texture.size.x, desc.texture.size.y); - GPU_PushString(0, g->nil_texture->gpu_resource, STRING(desc.texture.size.x * desc.texture.size.y * 4, (u8 *)pixels)); - EndScratch(scratch); - } - - /* Init loading sheet */ - g->loading_sheet = PushStruct(g->perm_arena, S_Sheet); - g->loading_sheet->image_size = VEC2(PIXELS_PER_UNIT, PIXELS_PER_UNIT); - g->loading_sheet->frame_size = VEC2(PIXELS_PER_UNIT, PIXELS_PER_UNIT); - - /* Init nil sheet */ - g->nil_sheet = PushStruct(g->perm_arena, S_Sheet); - g->nil_sheet->image_size = VEC2(PIXELS_PER_UNIT, PIXELS_PER_UNIT); - g->nil_sheet->frame_size = VEC2(PIXELS_PER_UNIT, PIXELS_PER_UNIT); - g->nil_sheet->loaded = 1; - } - SetArenaReadonly(g->perm_arena); - - g->cache.arena = AcquireArena(Gibi(64)); - g->cache.bins = PushStructs(g->cache.arena, S_CacheEntryBin, S_CacheBinsCount); - - g->scopes_arena = AcquireArena(Gibi(64)); - - RunJob(1, S_EvictorJob, JobPool_Background, JobPriority_Low, &g->shutdown_counter, 0); - - OnExit(&S_Shutdown); } //////////////////////////////// -//~ Shutdown - -ExitFuncDef(S_Shutdown) -{ - __prof; - S_SharedState *g = &S_shared_state; - /* Signal evictor shutdown */ - { - Lock lock = LockE(&g->evictor_scheduler_mutex); - g->evictor_scheduler_shutdown = 1; - SignalCv(&g->evictor_scheduler_shutdown_cv, I32Max); - Unlock(&lock); - } - /* Yield for evictor shutdown */ - YieldOnCounter(&g->shutdown_counter); -} - -//////////////////////////////// -//~ Nil purple-black image - -u32 *S_GeneratePurpleBlackImage(Arena *arena, u32 width, u32 height) -{ - u32 *pixels = PushStructsNoZero(arena, u32, width * height); - - /* Create texture containing alternating blocks of purple and black */ - u32 color_size = 4; - u32 color_1 = 0xFFDC00FF; - u32 color_2 = 0xFF000000; - for (u32 x = 0; x < width; ++x) - { - for (u32 y = 0; y < height; ++y) - { - u32 pixel_index = x + width * y; - if ((y / color_size) % 2 == 0) - { - if ((x / color_size) % 2 == 0) - { - pixels[pixel_index] = color_1; - } - else - { - pixels[pixel_index] = color_2; - } - } - else - { - if ((x / color_size) % 2 == 0) - { - pixels[pixel_index] = color_2; - } - else - { - pixels[pixel_index] = color_1; - } - } - } - } - - return pixels; -} - -//////////////////////////////// -//~ Tag - -S_Tag S_TagFromPath(String path) -{ - S_Tag result = ZI; - result.hash = HashFnv64(Fnv64Basis, path); - result.path = path; - return result; -} +//~ Tag helpers b32 S_IsTagNil(S_Tag tag) { - return tag.hash == 0; + return 0; } -b32 S_EqTag(S_Tag t1, S_Tag t2) +S_Tag S_TagFromName(String name) { - return t1.hash == t2.hash; -} - -S_Hash S_CacheEntryFromTagHash(u64 tag_hash, S_CacheEntryKind kind) -{ - return (S_Hash) { .v = RandU64FromSeed(tag_hash + kind) }; -} - - -//////////////////////////////// -//~ Init sheet - -S_Sheet S_SheetFromAseResult(Arena *arena, ASE_DecodedSheet ase) -{ - __prof; - S_Sheet sheet = ZI; - - Assert(ase.num_frames >= 1); - - Vec2 frame_size = ase.frame_size; - Vec2 frame_center = MulVec2(ase.frame_size, 0.5f); - - /* Init frames */ - { - __profn("Init frames"); - sheet.image_size = ase.image_size; - sheet.frame_size = ase.frame_size; - sheet.frames = PushStructs(arena, S_Frame, ase.num_frames); - sheet.frames_count = ase.num_frames; - for (ASE_Frame *ase_frame = ase.frame_head; ase_frame; ase_frame = ase_frame->next) - { - u32 index = ase_frame->index; - - Vec2 clip_p1 = { (f32)ase_frame->x1 / (f32)ase.image_size.x, (f32)ase_frame->y1 / (f32)ase.image_size.y }; - Vec2 clip_p2 = { (f32)ase_frame->x2 / (f32)ase.image_size.x, (f32)ase_frame->y2 / (f32)ase.image_size.y }; - - sheet.frames[index] = (S_Frame) { - .index = index, - .duration = ase_frame->duration, - .clip = (ClipRect) { clip_p1, clip_p2 } - }; - } - } - - /* Init spans */ - sheet.spans_count = ase.num_spans; - if (ase.num_spans > 0) - { - __profn("Init spans"); - sheet.spans = PushStructs(arena, S_Span, sheet.spans_count); - sheet.spans_dict = InitDict(arena, (u64)(ase.num_spans * S_SheetSpanLookupTableBinRatio)); - u64 index = 0; - for (ASE_Span *ase_span = ase.span_head; ase_span; ase_span = ase_span->next) - { - String name = PushString(arena, ase_span->name); - S_Span *span = &sheet.spans[index]; - span->name = name; - span->start = ase_span->start; - span->end = ase_span->end; - u64 hash = HashFnv64(Fnv64Basis, name); - SetDictValue(arena, sheet.spans_dict, hash, (u64)span); - ++index; - } - } - - /* Init slices */ - if (ase.num_slice_keys > 0) - { - __profn("Init slices"); - TempArena scratch = BeginScratch(arena); - - struct temp_ase_slice_key_node - { - ASE_SliceKey *key; - struct temp_ase_slice_key_node *next; - - u32 index_in_frame; - u32 earliest_frame; - }; - - struct temp_slice_group_node - { - String name; - u64 per_frame_count; - struct temp_ase_slice_key_node *temp_ase_slice_key_head; - struct temp_slice_group_node *next; - - S_SheetSliceGroup *final_slice_group; - }; - - /* Group slices by name and find out counts per frame */ - u64 num_temp_slice_group_nodes = 0; - struct temp_slice_group_node *temp_slice_group_head = 0; - { - Dict *temp_slice_dict = InitDict(scratch.arena, (u64)(ase.num_slice_keys * 2)); - for (ASE_SliceKey *ase_slice_key = ase.slice_key_head; ase_slice_key; ase_slice_key = ase_slice_key->next) - { - String name = ase_slice_key->name; - u64 hash = HashFnv64(Fnv64Basis, name); - struct temp_slice_group_node *temp_slice_group_node = (struct temp_slice_group_node *)DictValueFromHash(temp_slice_dict, hash); - if (!temp_slice_group_node) - { - temp_slice_group_node = PushStruct(scratch.arena, struct temp_slice_group_node); - temp_slice_group_node->name = name; - SetDictValue(scratch.arena, temp_slice_dict, hash, (u64)temp_slice_group_node); - - ++num_temp_slice_group_nodes; - temp_slice_group_node->next = temp_slice_group_head; - temp_slice_group_head = temp_slice_group_node; - } - - struct temp_ase_slice_key_node *node = PushStruct(scratch.arena, struct temp_ase_slice_key_node); - node->key = ase_slice_key; - node->next = temp_slice_group_node->temp_ase_slice_key_head; - node->earliest_frame = U32Max; /* To be overwritten later after iterating */ - - temp_slice_group_node->temp_ase_slice_key_head = node; - - ++temp_slice_group_node->per_frame_count; - } - } - - /* Acquire slice groups & fill originals in 2d array */ - sheet.slice_groups_count = num_temp_slice_group_nodes; - sheet.slice_groups = PushStructs(arena, S_SheetSliceGroup, sheet.slice_groups_count); - sheet.slice_groups_dict = InitDict(arena, (u64)(num_temp_slice_group_nodes * S_SliceLookupTableBinRatio)); - - u64 index = 0; - for (struct temp_slice_group_node *temp_slice_group_node = temp_slice_group_head; temp_slice_group_node; temp_slice_group_node = temp_slice_group_node->next) - { - S_SheetSliceGroup *slice_group = &sheet.slice_groups[index]; - slice_group->name = PushString(arena, temp_slice_group_node->name); - slice_group->per_frame_count = temp_slice_group_node->per_frame_count; - - slice_group->frame_slices = PushStructs(arena, S_Slice, ase.num_frames * slice_group->per_frame_count); - - u64 index_in_frame = 0; - for (struct temp_ase_slice_key_node *node = temp_slice_group_node->temp_ase_slice_key_head; node; node = node->next) - { - ASE_SliceKey *key = node->key; - - for (ASE_Slice *ase_slice = key->slice_head; ase_slice; ase_slice = ase_slice->next) - { - u32 start = ase_slice->start; - - S_Slice *slice = &slice_group->frame_slices[(start * slice_group->per_frame_count) + index_in_frame]; - slice->original = 1; - - f32 x1_px = ase_slice->x1; - f32 y1_px = ase_slice->y1; - f32 x2_px = ase_slice->x2; - f32 y2_px = ase_slice->y2; - f32 width_px = x2_px - x1_px; - f32 height_px = y2_px - y1_px; - - f32 x1 = (x1_px - frame_center.x) / frame_size.x; - f32 y1 = (y1_px - frame_center.y) / frame_size.y; - f32 x2 = (x2_px - frame_center.x) / frame_size.x; - f32 y2 = (y2_px - frame_center.y) / frame_size.y; - f32 width = x2 - x1; - f32 height = y2 - y1; - - /* Rect */ - Rect rect_px = RectFromScalar(x1_px, y1_px, width_px, height_px); - Rect rect = RectFromScalar(x1, y1, width, height); - /* Center */ - Vec2 center_px = VEC2(x1_px + (width_px * 0.5f), y1_px + (height_px * 0.5f)); - Vec2 center = VEC2(x1 + (width * 0.5f), y1 + (height * 0.5f)); - /* Dir */ - Vec2 dir_px = VEC2(center_px.x, -1); - Vec2 dir = VEC2(0, -1); - - slice->rect_px = rect_px; - slice->center_px = center_px; - slice->dir_px = dir_px; - - slice->rect = rect; - slice->center = center; - slice->dir = dir; - - node->index_in_frame = index_in_frame; - if (start < node->earliest_frame) - { - node->earliest_frame = start; - } - } - - ++index_in_frame; - } - - temp_slice_group_node->final_slice_group = slice_group; - u64 hash = HashFnv64(Fnv64Basis, slice_group->name); - SetDictValue(arena, sheet.slice_groups_dict, hash, (u64)slice_group); - ++index; - } - - /* Propagate original slices into next frames (and first slices into previous frames) */ - for (struct temp_slice_group_node *temp_slice_group_node = temp_slice_group_head; temp_slice_group_node; temp_slice_group_node = temp_slice_group_node->next) - { - S_SheetSliceGroup *slice_group = temp_slice_group_node->final_slice_group; - - for (struct temp_ase_slice_key_node *node = temp_slice_group_node->temp_ase_slice_key_head; node; node = node->next) - { - ASE_SliceKey *key = node->key; - u32 index_in_frame = node->index_in_frame; - for (ASE_Slice *ase_slice = key->slice_head; ase_slice; ase_slice = ase_slice->next) - { - u32 start = ase_slice->start; - - S_Slice *slice = &slice_group->frame_slices[(start * slice_group->per_frame_count) + index_in_frame]; - - /* Propagate earliest slice to all previous frames */ - if (start == node->earliest_frame && start > 0) - { - for (u32 i = start; i-- > 0;) - { - S_Slice *target = &slice_group->frame_slices[(i * slice_group->per_frame_count) + index_in_frame]; - *target = *slice; - target->original = 0; - } - } - - /* Propagate slice to forward frames until original is found */ - for (u32 i = start + 1; i < ase.num_frames; ++i) - { - S_Slice *target = &slice_group->frame_slices[(i * slice_group->per_frame_count) + index_in_frame]; - if (target->original) - { - break; - } - else - { - *target = *slice; - target->original = 0; - } - } - } - } - } - - /* Calculate direction vectors */ - for (struct temp_slice_group_node *temp_slice_group_node = temp_slice_group_head; temp_slice_group_node; temp_slice_group_node = temp_slice_group_node->next) - { - String ray_suffix = Lit(".ray"); - - S_SheetSliceGroup *ray_slice_group = temp_slice_group_node->final_slice_group; - String ray_slice_name = ray_slice_group->name; - if (StringEndsWith(ray_slice_name, ray_suffix)) - { - String point_slice_name = ray_slice_name; - point_slice_name.len -= ray_suffix.len; - u64 hash = HashFnv64(Fnv64Basis, point_slice_name); - S_SheetSliceGroup *point_slice_group = (S_SheetSliceGroup *)DictValueFromHash(sheet.slice_groups_dict, hash); - if (point_slice_group) - { - u32 point_slices_per_frame = point_slice_group->per_frame_count; - - for (u32 i = 0; i < ase.num_frames; ++i) - { - /* Use ray slice in ray group */ - S_Slice *ray_slice = &ray_slice_group->frame_slices[i * point_slices_per_frame]; - Vec2 ray_end = ray_slice->center_px; - Vec2 ray_end_norm = ray_slice->center; - - /* Apply to each point slice in point group */ - for (u32 j = 0; j < point_slices_per_frame; ++j) - { - S_Slice *point_slice = &point_slice_group->frame_slices[(i * point_slices_per_frame) + j]; - point_slice->dir_px = SubVec2(ray_end, point_slice->center_px); - point_slice->dir = SubVec2(ray_end_norm, point_slice->center); - point_slice->has_ray = 1; - } - } - - } - } - } - - EndScratch(scratch); - } - - return sheet; -} - -//////////////////////////////// -//~ Load job - -JobDef(S_LoadSpriteJob, sig, UNUSED id) -{ - __prof; - S_CacheEntryRef ref = sig->ref; - S_Tag tag = sig->tag; - S_Scope *scope = sig->scope; - switch (ref.e->kind) - { - case S_CacheEntryKind_Texture: - { - S_LoadCacheEntryTexture(ref, tag); - } break; - case S_CacheEntryKind_Sheet: - { - S_LoadCacheEntrySheet(ref, tag); - } break; - default: { Panic(Lit("Unknown sprite cache node kind")); } break; - } - S_EndScope(scope); -} - -void S_PushLoadJob(S_CacheEntryRef ref, S_Tag tag) -{ - S_LoadSpriteJob_Desc *desc = PushJobDesc(S_LoadSpriteJob, .pool = JobPool_Background, .priority = JobPriority_Inherit); - desc->sig->scope = S_BeginScope(); /* Scope ended by job */ - desc->sig->ref = S_EnsureRefFromRef(desc->sig->scope, ref)->ref; - desc->sig->tag = tag; - tag.path = PushString(desc->arena, tag.path); - RunJobEx((GenericJobDesc *)desc); -} - -//////////////////////////////// -//~ Cache load operations - -void S_LoadCacheEntryTexture(S_CacheEntryRef ref, S_Tag tag) -{ - __prof; - S_SharedState *g = &S_shared_state; - TempArena scratch = BeginScratchNoConflict(); - S_CacheEntry *e = ref.e; - - Atomic32FetchSet(&e->state, S_CacheEntryState_Working); - String path = tag.path; - - P_LogInfoF("Loading sprite texture [%F] \"%F\"", FmtHex(e->hash.v), FmtString(path)); - b32 success = 0; - i64 start_ns = TimeNs(); - - Assert(StringEndsWith(path, Lit(".ase"))); - Assert(e->kind == S_CacheEntryKind_Texture); - - /* TODO: Replace arena allocs w/ buddy allocator */ - /* TODO: Arena probably overkill. Just using it to store texture struct. */ - e->arena = AcquireArena(S_TextureArenaReserve); - u64 memory_size = 0; - { - /* Decode */ - ASE_DecodedImage decoded = ZI; - { - RES_Resource texture_rs = RES_OpenResource(path); - if (RES_ResourceExists(&texture_rs)) - { - decoded = ASE_DecodeImage(scratch.arena, RES_GetResourceData(&texture_rs)); - } - else - { - P_LogErrorF("Sprite texture for \"%F\" not found", FmtString(path)); - } - RES_CloseResource(&texture_rs); - } - - if (decoded.success) - { - /* Initialize */ - GPU_ResourceDesc gpu_desc = ZI; - gpu_desc.kind = GPU_ResourceKind_Texture2D; - gpu_desc.texture.size = VEC3I32(decoded.width, decoded.height, 1); - gpu_desc.texture.format = GPU_Format_R8G8B8A8_Unorm_Srgb; - e->texture = PushStruct(e->arena, S_Texture); - e->texture->width = decoded.width; - e->texture->height = decoded.height; - e->texture->valid = 1; - e->texture->loaded = 1; - e->texture->gpu_resource = GPU_AcquireResource(gpu_desc); - { - u64 size = decoded.width * decoded.height * 4; - GPU_PushString(0, e->texture->gpu_resource, STRING(size, (u8 *)decoded.pixels)); - } - /* TODO: Query gpu for more accurate texture size in VRAM */ - memory_size += (decoded.width * decoded.height) * sizeof(*decoded.pixels); - success = 1; - } - } - SetArenaReadonly(e->arena); - e->memory_usage = e->arena->committed + memory_size; - Atomic64FetchAdd(&g->cache.memory_usage.v, e->memory_usage); - - if (success) - { - P_LogSuccessF("Loaded sprite texture [%F] \"%F\" in %F seconds (cache size: %F bytes).", - FmtHex(e->hash.v), - FmtString(path), - FmtFloat(SecondsFromNs(TimeNs() - start_ns)), - FmtUint(e->memory_usage)); - } - - Atomic32FetchSet(&e->state, S_CacheEntryState_Loaded); - - EndScratch(scratch); -} - -void S_LoadCacheEntrySheet(S_CacheEntryRef ref, S_Tag tag) -{ - __prof; - S_SharedState *g = &S_shared_state; - TempArena scratch = BeginScratchNoConflict(); - S_CacheEntry *e = ref.e; - - Atomic32FetchSet(&e->state, S_CacheEntryState_Working); - String path = tag.path; - - P_LogInfoF("Loading sprite sheet [%F] \"%F\"", FmtHex(e->hash.v), FmtString(path)); - b32 success = 0; - i64 start_ns = TimeNs(); - - Assert(e->kind == S_CacheEntryKind_Sheet); - - /* TODO: Replace arena allocs w/ buddy allocator */ - e->arena = AcquireArena(S_SheetArenaReserve); - { - /* Decode */ - ASE_DecodedSheet decoded = ZI; - { - RES_Resource sheet_rs = RES_OpenResource(path); - if (RES_ResourceExists(&sheet_rs)) - { - decoded = ASE_DecodeSheet(scratch.arena, RES_GetResourceData(&sheet_rs)); - } - else - { - P_LogErrorF("Sprite sheet for \"%F\" not found", FmtString(path)); - } - RES_CloseResource(&sheet_rs); - } - - if (decoded.success) - { - RES_Resource sheet_rs = RES_OpenResource(path); - decoded = ASE_DecodeSheet(scratch.arena, RES_GetResourceData(&sheet_rs)); - RES_CloseResource(&sheet_rs); - - /* Initialize */ - e->sheet = PushStructNoZero(e->arena, S_Sheet); - *e->sheet = S_SheetFromAseResult(e->arena, decoded); - e->sheet->loaded = 1; - e->sheet->valid = 1; - - success = 1; - } - } - SetArenaReadonly(e->arena); - e->memory_usage = e->arena->committed; - Atomic64FetchAdd(&g->cache.memory_usage.v, e->memory_usage); - - if (success) - { - P_LogSuccessF("Loaded sprite sheet [%F] \"%F\" in %F seconds (cache size: %F bytes).", - FmtHex(e->hash.v), - FmtString(path), - FmtFloat(SecondsFromNs(TimeNs() - start_ns)), - FmtUint(e->memory_usage)); - } - - Atomic32FetchSet(&e->state, S_CacheEntryState_Loaded); - - EndScratch(scratch); -} - -//////////////////////////////// -//~ Ref - -void S_AddRef(S_CacheEntry *e, i32 amount) -{ - S_SharedState *g = &S_shared_state; - i32 evictor_cycle = Atomic32Fetch(&g->evictor_cycle.v); - Atomic64 *refcount_atomic = &e->refcount_struct.v; - u64 old_refcount_uncast = Atomic64Fetch(refcount_atomic); - for (;;) - { - S_Refcount new_refcount = *(S_Refcount *)&old_refcount_uncast; - new_refcount.count += amount; - new_refcount.last_ref_cycle = evictor_cycle; - u64 v = Atomic64FetchTestSet(refcount_atomic, old_refcount_uncast, *(u64 *)&new_refcount); - if (v == old_refcount_uncast) - { - Assert(new_refcount.count >= 0); - break; - } - old_refcount_uncast = v; - } -} - -S_ScopeCacheEntryRef *S_EnsureRefUnsafely(S_Scope *scope, S_CacheEntry *e) -{ - u64 bin_index = e->hash.v % S_CacheBinsCount; - - S_ScopeCacheEntryRef **slot = &scope->ref_node_bins[bin_index]; - while (*slot) - { - if ((*slot)->ref.e == e) - { - /* Found reference in scope */ - break; - } - else - { - slot = &(*slot)->next_in_bin; - } - } - - if (*slot == 0) - { - if (scope->num_references >= S_MaxScopeReferences) - { - Panic(Lit("Max sprite scope references reached")); - } - - /* Increment refcount */ - S_AddRef(e, 1); - - /* Grab node from pool */ - S_ScopeCacheEntryRef *scope_ref = &scope->ref_node_pool[scope->num_references++]; - ZeroStruct(scope_ref); - scope_ref->ref.e = e; - - *slot = scope_ref; - } - - return *slot; -} - -S_ScopeCacheEntryRef *S_EnsureRefFromEntryLocked(S_Scope *scope, S_CacheEntry *e, Lock *bin_lock) -{ - S_SharedState *g = &S_shared_state; - LAX g; - /* Guaranteed safe if caller has lock on entry's bin, since entry may not have an existing reference and could otherwise be evicted while ensuring this reference */ - AssertLockedES(bin_lock, &g->cache.bins[e->hash.v % S_CacheBinsCount].mutex); - return S_EnsureRefUnsafely(scope, e); -} - -S_ScopeCacheEntryRef *S_EnsureRefFromRef(S_Scope *scope, S_CacheEntryRef ref) -{ - /* Safe since caller has ref */ - return S_EnsureRefUnsafely(scope, ref.e); -} - -//////////////////////////////// -//~ Scope - -S_Scope *S_BeginScope(void) -{ - S_SharedState *g = &S_shared_state; - /* Acquire scope */ - S_Scope *result = 0; - S_ScopeCacheEntryRef **bins = 0; - S_ScopeCacheEntryRef *pool = 0; - { - Lock lock = LockE(&g->scopes_mutex); - { - if (g->first_free_scope) - { - result = g->first_free_scope; - g->first_free_scope = result->next_free; - bins = result->ref_node_bins; - pool = result->ref_node_pool; - } - else - { - result = PushStructNoZero(g->scopes_arena, S_Scope); - bins = PushStructsNoZero(g->scopes_arena, S_ScopeCacheEntryRef *, S_CacheBinsCount); - pool = PushStructsNoZero(g->scopes_arena, S_ScopeCacheEntryRef, S_MaxScopeReferences); - } - } - Unlock(&lock); - } - ZeroStruct(result); - ZeroBytes(bins, sizeof(*bins) * S_CacheBinsCount); - result->ref_node_bins = bins; - result->ref_node_pool = pool; + S_Tag result = ZI; return result; } -void S_EndScope(S_Scope *scope) +S_Tag S_TagFromResource(R_Tag resource) { - S_SharedState *g = &S_shared_state; - /* Dereference entries */ - u64 num_references = scope->num_references; - for (u64 i = 0; i < num_references; ++i) - { - S_ScopeCacheEntryRef *n = &scope->ref_node_pool[i]; - S_AddRef(n->ref.e, -1); - } - - /* Release scope */ - Lock lock = LockE(&g->scopes_mutex); - { - scope->next_free = g->first_free_scope; - g->first_free_scope = scope; - } - Unlock(&lock); -} - -//////////////////////////////// -//~ Cache lookup - -//- Locked lookup - -S_ScopeCacheEntryRef *S_EntryFromHashLocked(S_Scope *scope, S_Hash hash, Lock *bin_lock) -{ - S_SharedState *g = &S_shared_state; - S_ScopeCacheEntryRef *scope_ref = 0; - - S_CacheEntryBin *bin = &g->cache.bins[hash.v % S_CacheBinsCount]; - AssertLockedES(bin_lock, &bin->mutex); /* Lock required for iterating bin */ - - for (S_CacheEntry *entry = bin->first; entry; entry = entry->next_in_bin) - { - if (entry->hash.v == hash.v) - { - scope_ref = S_EnsureRefFromEntryLocked(scope, entry, bin_lock); - break; - } - } - - return scope_ref; -} - -//- Unlocked lookup - -S_ScopeCacheEntryRef *S_EntryFromTag(S_Scope *scope, S_Tag tag, S_CacheEntryKind kind, b32 force_new) -{ - S_SharedState *g = &S_shared_state; - S_Hash hash = S_CacheEntryFromTagHash(tag.hash, kind); - u64 bin_index = hash.v % S_CacheBinsCount; - S_ScopeCacheEntryRef *scope_ref = 0; - - /* Search for entry in scope */ - if (!force_new) - { - scope_ref = scope->ref_node_bins[bin_index]; - while (scope_ref) - { - if (scope_ref->ref.e->hash.v == hash.v) - { - break; - } - scope_ref = scope_ref->next_in_bin; - } - } - - /* If not in scope, search for entry in cache */ - if (!scope_ref) - { - S_CacheEntryBin *bin = &g->cache.bins[bin_index]; - - /* Search in cache */ - if (!force_new) - { - Lock bin_lock = LockS(&bin->mutex); - { - scope_ref = S_EntryFromHashLocked(scope, hash, &bin_lock); - } - Unlock(&bin_lock); - } - - /* If not in cache, allocate new entry */ - if (!scope_ref) - { - Lock bin_lock = LockE(&bin->mutex); - { - /* Search cache one more time in case an entry was allocated between locks */ - if (!force_new) - { - scope_ref = S_EntryFromHashLocked(scope, hash, &bin_lock); - } - - if (!scope_ref) - { - /* Cache entry still absent, allocate new entry */ - S_CacheEntry *entry = 0; - { - Lock pool_lock = LockE(&g->cache.entry_pool_mutex); - if (g->cache.entry_pool_first_free) - { - entry = g->cache.entry_pool_first_free; - g->cache.entry_pool_first_free = entry->next_free; - } - else - { - entry = PushStructNoZero(g->cache.arena, S_CacheEntry); - } - Unlock(&pool_lock); - } - ZeroStruct(entry); - - /* Init entry and add to bin */ - { - if (bin->last) - { - bin->last->next_in_bin = entry; - entry->prev_in_bin = bin->last; - } - else - { - bin->first = entry; - } - bin->last = entry; - } - entry->hash = S_CacheEntryFromTagHash(tag.hash, kind); - entry->kind = kind; - entry->texture = g->nil_texture; - entry->sheet = g->nil_sheet; - - scope_ref = S_EnsureRefFromEntryLocked(scope, entry, &bin_lock); - } - } - Unlock(&bin_lock); - } - } - - return scope_ref; -} - -//- Data from tag - -void *S_DataFromTag(S_Scope *scope, S_Tag tag, S_CacheEntryKind kind, b32 await) -{ - S_SharedState *g = &S_shared_state; - /* TODO: Replace switch statements */ - void *result = 0; - switch (kind) - { - case S_CacheEntryKind_Texture: { result = g->loading_texture; } break; - case S_CacheEntryKind_Sheet: { result = g->loading_sheet; } break; - default: { Panic(Lit("Unknown sprite cache entry kind")); } break; - } - - S_ScopeCacheEntryRef *scope_ref = S_EntryFromTag(scope, tag, kind, 0); - S_CacheEntryRef ref = scope_ref->ref; - - S_CacheEntryState state = Atomic32Fetch(&ref.e->state); - if (state == S_CacheEntryState_Loaded) - { - switch (kind) - { - case S_CacheEntryKind_Texture: { result = ref.e->texture; } break; - case S_CacheEntryKind_Sheet: { result = ref.e->sheet; } break; - default: { Panic(Lit("Unknown sprite cache entry kind")); } break; - } - } - else if (state == S_CacheEntryState_None) - { - /* If entry is new, load texture */ - if (Atomic32FetchTestSet(&ref.e->state, S_CacheEntryState_None, S_CacheEntryState_Queued) == S_CacheEntryState_None) - { - /* If caller is awaiting result then just load now on the calling thread. Otherwise spawn a work task. */ - if (await) - { - switch (kind) - { - case S_CacheEntryKind_Texture: - { - S_LoadCacheEntryTexture(ref, tag); - result = ref.e->texture; - } break; - case S_CacheEntryKind_Sheet: - { - S_LoadCacheEntrySheet(ref, tag); - result = ref.e->sheet; - } break; - default: { Panic(Lit("Unknown sprite cache entry kind")); } break; - } - } - else - { - /* Acquire cmd */ - S_PushLoadJob(ref, tag); - } - } - } - - /* Spinlock until result is ready */ - if (await && state != S_CacheEntryState_Loaded) - { - while (Atomic32Fetch(&ref.e->state) != S_CacheEntryState_Loaded) - { - _mm_pause(); - } - } - + S_Tag result = ZI; return result; } //////////////////////////////// -//~ Texture retrieval +//~ Texture operations -S_Texture *S_TextureFromTagAwait(S_Scope *scope, S_Tag tag) +S_Texture *S_TextureFromTagAwait(S_Tag tag) { - return (S_Texture *)S_DataFromTag(scope, tag, S_CacheEntryKind_Texture, 1); + S_Texture *result = ZI; + return result; } -S_Texture *S_TextureFromTagAsync(S_Scope *scope, S_Tag tag) +S_Texture *S_TextureFromTagAsync(S_Tag tag) { - return (S_Texture *)S_DataFromTag(scope, tag, S_CacheEntryKind_Texture, 0); -} - - -void S_PrefetchTextureFromTag(S_Scope *scope, S_Tag tag) -{ - S_DataFromTag(scope, tag, S_CacheEntryKind_Texture, 0); + S_Texture *result = ZI; + return result; } //////////////////////////////// -//~ Sheet retrieval +//~ Sheet operations -S_Sheet *S_SheetFromTagAwait(S_Scope *scope, S_Tag tag) +S_Sheet *S_SheetFromTagAwait(S_Tag tag) { - return (S_Sheet *)S_DataFromTag(scope, tag, S_CacheEntryKind_Sheet, 1); + S_Sheet *result = ZI; + return result; } -S_Sheet *S_SheetFromTagAsync(S_Scope *scope, S_Tag tag) +S_Sheet *S_SheetFromTagAsync(S_Tag tag) { - return (S_Sheet *)S_DataFromTag(scope, tag, S_CacheEntryKind_Sheet, 0); -} - -void S_PrefetchSheetFromTag(S_Scope *scope, S_Tag tag) -{ - S_DataFromTag(scope, tag, S_CacheEntryKind_Sheet, 0); -} - -//////////////////////////////// -//~ Sheet data - -S_Frame S_FrameFromIndex(S_Sheet *sheet, u32 index) -{ - if (index < sheet->frames_count) - { - return sheet->frames[index]; - } - S_Frame result = ZI; - result.index = 0; - result.duration = 0.1; - result.clip = AllClipped; + S_Sheet *result = ZI; return result; } S_Span S_SpanFromName(S_Sheet *sheet, String name) { S_Span result = ZI; - if (sheet->spans_count > 0) - { - u64 hash = HashFnv64(Fnv64Basis, name); - S_Span *entry = (S_Span *)DictValueFromHash(sheet->spans_dict, hash); - if (entry) - { - result = *entry; - } - } return result; } -/* Returns first slice with name in frame */ -S_Slice S_SliceFromNameIndex(S_Sheet *sheet, String name, u32 frame_index) +S_Frame S_FrameFromIndex(S_Sheet *sheet, u64 index) { - if (sheet->slice_groups_count > 0) - { - u64 hash = HashFnv64(Fnv64Basis, name); - S_SheetSliceGroup *group = (S_SheetSliceGroup *)DictValueFromHash(sheet->slice_groups_dict, hash); - if (group) - { - return group->frame_slices[frame_index * group->per_frame_count]; - } - } + S_Frame result = ZI; + return result; +} - /* Return 'pivot' by default */ +S_Slice S_SliceFromName(S_Sheet *sheet, String name, u64 frame_index) +{ S_Slice result = ZI; - if (EqString(name, Lit("pivot"))) - { - /* 'pivot' slice does not exist, return center */ - result.center = VEC2(0, 0); - result.center_px = MulVec2(sheet->frame_size, 0.5f); - result.dir_px = VEC2(result.center_px.x, 0); - result.dir = VEC2(0, -0.5); - } - else - { - result = S_SliceFromNameIndex(sheet, Lit("pivot"), frame_index); - } - return result; } - -/* Returns all slices with name in frame */ -S_SliceArray S_SlicesFromNameIndex(S_Sheet *sheet, String name, u32 frame_index) -{ - S_SliceArray result = ZI; - if (sheet->slice_groups_count > 0) - { - u64 hash = HashFnv64(Fnv64Basis, name); - S_SheetSliceGroup *group = (S_SheetSliceGroup *)DictValueFromHash(sheet->slice_groups_dict, hash); - if (group) - { - result.count = group->per_frame_count; - result.slices = &group->frame_slices[frame_index * group->per_frame_count]; - } - } - return result; -} - -//////////////////////////////// -//~ Evictor - -MergesortCompareFuncDef(S_EvictorSortCmp, arg_a, arg_b, _) -{ - S_EvictorNode *a = arg_a; - S_EvictorNode *b = arg_b; - i32 a_cycle = a->last_ref_cycle; - i32 b_cycle = b->last_ref_cycle; - return (b_cycle > a_cycle) - (a_cycle > b_cycle); -} - -/* NOTE: - * A cache node is safe from eviction as long as: - * - Its bin mutex is locked - * - Any references are held to the node (its refcount > 0) - * - * An attempt to evict a cache node will occur when: - * - Its refcount = 0 and - * - The cache is over its memory budget and the node's last reference is longer ago than the grace period - */ -JobDef(S_EvictorJob, UNUSED sig, UNUSED job_id) -{ - S_SharedState *g = &S_shared_state; - b32 shutdown = 0; - while (!shutdown) - { - { - __profn("Sprite evictor cycle"); - TempArena scratch = BeginScratchNoConflict(); - u64 evict_array_count = 0; - S_EvictorNode *evict_array = PushDry(scratch.arena, S_EvictorNode); - { - i32 cur_cycle = Atomic32Fetch(&g->evictor_cycle.v); - - /* Scan for evictable nodes */ - b32 cache_over_budget_threshold = Atomic64Fetch(&g->cache.memory_usage.v) > (i64)S_CacheMemoryBudgetThreshold; - if (cache_over_budget_threshold) - { - __profn("Evictor scan"); - for (u64 i = 0; i < S_CacheBinsCount; ++i) - { - S_CacheEntryBin *bin = &g->cache.bins[i]; - Lock bin_lock = LockS(&bin->mutex); - { - S_CacheEntry *n = bin->first; - while (n) - { - u64 refcount_uncast = Atomic64Fetch(&n->refcount_struct.v); - S_Refcount refcount = *(S_Refcount *)&refcount_uncast; - if (refcount.count <= 0) - { - /* Add node to evict list */ - b32 is_old = cache_over_budget_threshold && ((cur_cycle - refcount.last_ref_cycle) > S_EvictorGracePeriodCycles); - if (is_old) - { - S_EvictorNode *en = PushStruct(scratch.arena, S_EvictorNode); - en->cache_entry = n; - en->cache_bin = bin; - en->last_ref_cycle = refcount.last_ref_cycle; - ++evict_array_count; - } - } - - n = n->next_in_bin; - } - } - Unlock(&bin_lock); - } - } - - /* Scratch arena should only contain evict array at this point */ - Assert(((ArenaBase(scratch.arena) + scratch.arena->pos) - (sizeof(*evict_array) * evict_array_count)) == (u8 *)evict_array); - - /* Sort evict nodes */ - { - __profn("Evictor sort"); - Mergesort(evict_array, evict_array_count, sizeof(*evict_array), S_EvictorSortCmp, 0); - } - - /* Remove evictable nodes from cache until under budget */ - S_EvictorNode *first_evicted = 0; - { - __profn("Evictor cache removal"); - b32 stop_evicting = 0; - for (u64 i = 0; i < evict_array_count && !stop_evicting; ++i) - { - S_EvictorNode *en = &evict_array[i]; - S_CacheEntryBin *bin = en->cache_bin; - S_CacheEntry *entry = en->cache_entry; - i32 last_ref_cycle = en->last_ref_cycle; - b32 cache_over_budget_target = Atomic64Fetch(&g->cache.memory_usage.v) > (i64)S_CacheMemoryBudgetTarget; - Lock bin_lock = LockE(&bin->mutex); - { - u64 refcount_uncast = Atomic64Fetch(&entry->refcount_struct.v); - S_Refcount refcount = *(S_Refcount *)&refcount_uncast; - if (refcount.count > 0 || (last_ref_cycle >= 0 && refcount.last_ref_cycle != en->last_ref_cycle)) - { - /* Cache node has been referenced since scan, skip node. */ - } - else if (cache_over_budget_target || last_ref_cycle < 0) - { - /* Remove from cache bin */ - S_CacheEntry *prev = entry->prev_in_bin; - S_CacheEntry *next = entry->next_in_bin; - if (prev) - { - prev->next_in_bin = next; - } - else - { - bin->first = next; - } - if (next) - { - next->prev_in_bin = prev; - } - else - { - bin->last = prev; - } - - Atomic64FetchAdd(&g->cache.memory_usage.v, -((i64)entry->memory_usage)); - - /* Add to evicted list */ - en->next_evicted = first_evicted; - first_evicted = en; - } - else - { - /* Cache is no longer over budget or force evicting, stop iteration */ - stop_evicting = 1; - } - } - Unlock(&bin_lock); - } - } - - if (first_evicted) - { - /* Release evicted node memory */ - { - __profn("Evictor memory release"); - GPU_Fence gpu_fence = GPU_GetGlobalFence(); - for (S_EvictorNode *en = first_evicted; en; en = en->next_evicted) - { - S_CacheEntry *n = en->cache_entry; - if (n->kind == S_CacheEntryKind_Texture && n->texture->valid) - { - GPU_ReleaseResource(n->texture->gpu_resource, gpu_fence, GPU_ReleaseFlag_None); - } - ReleaseArena(n->arena); - } - } - - /* Add evicted nodes to free list */ - { - __profn("Evictor free list append"); - Lock pool_lock = LockE(&g->cache.entry_pool_mutex); - for (S_EvictorNode *en = first_evicted; en; en = en->next_evicted) - { - S_CacheEntry *n = en->cache_entry; - n->next_free = g->cache.entry_pool_first_free; - g->cache.entry_pool_first_free = n; - } - Unlock(&pool_lock); - } - } - } - Atomic32FetchAdd(&g->evictor_cycle.v, 1); - EndScratch(scratch); - } - - /* Evictor sleep */ - { - Lock lock = LockE(&g->evictor_scheduler_mutex); - { - if (!g->evictor_scheduler_shutdown) - { - YieldOnCvTime(&g->evictor_scheduler_shutdown_cv, &lock, S_EvictorCycleIntervalNs); - } - shutdown = g->evictor_scheduler_shutdown; - } - Unlock(&lock); - } - } -} diff --git a/src/sprite/sprite.h b/src/sprite/sprite.h index d2b4978b..74ef792e 100644 --- a/src/sprite/sprite.h +++ b/src/sprite/sprite.h @@ -1,14 +1,13 @@ //////////////////////////////// -//~ Tag +//~ Tag types Struct(S_Tag) { - u64 hash; - String path; + R_Tag r; }; //////////////////////////////// -//~ Texture +//~ Texture types Struct(S_Texture) { @@ -90,160 +89,12 @@ Struct(S_Sheet) Dict *slice_groups_dict; }; -//////////////////////////////// -//~ Cache types - -Enum(S_CacheEntryKind) -{ - S_CacheEntryKind_Texture, - S_CacheEntryKind_Sheet, - - S_CacheEntryKind_Count -}; - -Enum(S_CacheEntryState) -{ - S_CacheEntryState_None, - S_CacheEntryState_Queued, - S_CacheEntryState_Working, - S_CacheEntryState_Loaded -}; - -Struct(S_Refcount) -{ - i32 count; /* Number of scopes currently holding a reference to this entry */ - i32 last_ref_cycle; /* Last evictor cycle that the refcount was modified */ -}; -StaticAssert(sizeof(S_Refcount) == 8); /* Must fit into 64 bit atomic */ - -Struct(S_Hash) -{ - u64 v; -}; - -Struct(S_CacheEntry) -{ - S_CacheEntryKind kind; - S_Hash hash; - Atomic32 state; - Atomic64Padded refcount_struct; /* Cast fetched result to `cache_refcount` */ - - /* Acquired data */ - /* NOTE: This data is finalized once entry state = loaded */ - i64 load_time_ns; - u64 memory_usage; - Arena *arena; - S_Texture *texture; - S_Sheet *sheet; - - /* Hash list */ - S_CacheEntry *next_in_bin; - S_CacheEntry *prev_in_bin; - - /* Free list */ - S_CacheEntry *next_free; -}; - -Struct(S_CacheEntryBin) -{ - Mutex mutex; - S_CacheEntry *first; - S_CacheEntry *last; -}; - -Struct(S_Cache) -{ - Atomic64Padded memory_usage; - Arena *arena; - S_CacheEntryBin *bins; - Mutex entry_pool_mutex; - S_CacheEntry *entry_pool_first_free; -}; - -/* Represents a reference that can be used to safely access cache entry without it becoming evicted during the reference's lifetime */ -Struct(S_CacheEntryRef) -{ - S_CacheEntry *e; -}; - -//////////////////////////////// -//~ Scope types - -/* A cache reference whose lifetime is bound to the scope it was retrieved from */ -Struct(S_ScopeCacheEntryRef) -{ - S_CacheEntryRef ref; - S_ScopeCacheEntryRef *next_in_bin; -}; - -Struct(S_Scope) -{ - S_ScopeCacheEntryRef **ref_node_bins; - S_ScopeCacheEntryRef *ref_node_pool; - u64 num_references; - S_Scope *next_free; -}; - -//////////////////////////////// -//~ Evictor types - -Struct(S_EvictorNode) -{ - i32 last_ref_cycle; - S_CacheEntry *cache_entry; - S_CacheEntryBin *cache_bin; - S_EvictorNode *next_evicted; -}; - -//////////////////////////////// -//~ Cache constants - -/* Texture arena only used to store texture struct at the moment. Actual image data is allocated on GPU. */ -#define S_TextureArenaReserve Mebi(1) - -#define S_CacheBinsCount 1024 -#define S_MaxScopeReferences 1024 -#define S_SheetArenaReserve Mebi(64) -#define S_SheetSpanLookupTableBinRatio 2.0 -#define S_SliceLookupTableBinRatio 2.0 - -/* How long between evictor cycles */ -#define S_EvictorCycleIntervalNs NsFromSeconds(0.500) - -/* How many cycles a cache entry spends unused until it's considered evictable */ -#define S_EvictorGracePeriodCycles (NsFromSeconds(10.000) / S_EvictorCycleIntervalNs) - -/* The evictor will begin evicting once cache usage is > threshold. - * It will entries until the budget has shrunk < target. */ -#define S_CacheMemoryBudgetThreshold (Mebi(256)) -#define S_CacheMemoryBudgetTarget (Mebi(128)) -StaticAssert(S_CacheMemoryBudgetThreshold >= S_CacheMemoryBudgetTarget); - //////////////////////////////// //~ Shared state Struct(S_SharedState) { - Arena *perm_arena; - S_Texture *nil_texture; - S_Texture *loading_texture; - S_Sheet *nil_sheet; - S_Sheet *loading_sheet; - - /* Cache */ - S_Cache cache; - - /* Scopes */ - Mutex scopes_mutex; - Arena *scopes_arena; - S_Scope *first_free_scope; - - /* Evictor */ - Atomic32Padded evictor_cycle; - Counter shutdown_counter; - b32 evictor_scheduler_shutdown; - Mutex evictor_scheduler_mutex; - Cv evictor_scheduler_shutdown_cv; + i32 _; }; extern S_SharedState S_shared_state; @@ -254,85 +105,24 @@ extern S_SharedState S_shared_state; void S_Startup(void); //////////////////////////////// -//~ Shutdown +//~ Tag helpers -ExitFuncDef(S_Shutdown); - -//////////////////////////////// -//~ Purple-black image - -u32 *S_GeneratePurpleBlackImage(Arena *arena, u32 width, u32 height); - -//////////////////////////////// -//~ Tag operations - -S_Tag S_TagFromPath(String path); b32 S_IsTagNil(S_Tag tag); -b32 S_EqTag(S_Tag t1, S_Tag t2); -S_Hash S_CacheEntryFromTagHash(u64 tag_hash, S_CacheEntryKind kind); +S_Tag S_TagFromName(String name); +S_Tag S_TagFromResource(R_Tag resource); //////////////////////////////// -//~ Sheet init +//~ Texture operations -S_Sheet S_SheetFromAseResult(Arena *arena, ASE_DecodedSheet ase); +S_Texture *S_TextureFromTagAwait(S_Tag tag); +S_Texture *S_TextureFromTagAsync(S_Tag tag); //////////////////////////////// -//~ Load job +//~ Sheet operations -void S_PushLoadJob(S_CacheEntryRef ref, S_Tag tag); -JobDecl(S_LoadSpriteJob, { S_Scope *scope; S_CacheEntryRef ref; S_Tag tag; }); +S_Sheet *S_SheetFromTagAwait(S_Tag tag); +S_Sheet *S_SheetFromTagAsync(S_Tag tag); -//////////////////////////////// -//~ Cache load operations - -void S_LoadCacheEntryTexture(S_CacheEntryRef ref, S_Tag tag); -void S_LoadCacheEntrySheet(S_CacheEntryRef ref, S_Tag tag); - -//////////////////////////////// -//~ Ref operations - -void S_AddRef(S_CacheEntry *e, i32 amount); -S_ScopeCacheEntryRef *S_EnsureRefUnsafely(S_Scope *scope, S_CacheEntry *e); -S_ScopeCacheEntryRef *S_EnsureRefFromEntryLocked(S_Scope *scope, S_CacheEntry *e, Lock *bin_lock); -S_ScopeCacheEntryRef *S_EnsureRefFromRef(S_Scope *scope, S_CacheEntryRef ref); - -//////////////////////////////// -//~ Scope operations - -S_Scope *S_BeginScope(void); -void S_EndScope(S_Scope *scope); - -//////////////////////////////// -//~ Cache lookup operations - -S_ScopeCacheEntryRef *S_EntryFromHashLocked(S_Scope *scope, S_Hash hash, Lock *bin_lock); -S_ScopeCacheEntryRef *S_EntryFromTag(S_Scope *scope, S_Tag tag, S_CacheEntryKind kind, b32 force_new); -void *S_DataFromTag(S_Scope *scope, S_Tag tag, S_CacheEntryKind kind, b32 await); - -//////////////////////////////// -//~ Texture retrieval operations - -S_Texture *S_TextureFromTagAwait(S_Scope *scope, S_Tag tag); -S_Texture *S_TextureFromTagAsync(S_Scope *scope, S_Tag tag); -void S_PrefetchTextureFromTag(S_Scope *scope, S_Tag tag); - -//////////////////////////////// -//~ Sheet retrieval operations - -S_Sheet *S_SheetFromTagAwait(S_Scope *scope, S_Tag tag); -S_Sheet *S_SheetFromTagAsync(S_Scope *scope, S_Tag tag); -void S_PrefetchSheetFromTag(S_Scope *scope, S_Tag tag); - -//////////////////////////////// -//~ Sheet data operations - -S_Frame S_FrameFromIndex(S_Sheet *sheet, u32 index); S_Span S_SpanFromName(S_Sheet *sheet, String name); -S_Slice S_SliceFromNameIndex(S_Sheet *sheet, String name, u32 frame_index); -S_SliceArray S_SlicesFromNameIndex(S_Sheet *sheet, String name, u32 frame_index); - -//////////////////////////////// -//~ Evictor job - -MergesortCompareFuncDef(S_EvictorSortCmp, arg_a, arg_b, udata); -JobDecl(S_EvictorJob, EmptySig); +S_Frame S_FrameFromIndex(S_Sheet *sheet, u64 index); +S_Slice S_SliceFromName(S_Sheet *sheet, String name, u64 frame_index); diff --git a/src/sprite/sprite.lay b/src/sprite/sprite.lay index 420daca4..e92eb40c 100644 --- a/src/sprite/sprite.lay +++ b/src/sprite/sprite.lay @@ -1,7 +1,6 @@ @Layer sprite //- Dependencies -@Dep platform @Dep gpu @Dep ase