From a8d79cee4c7f79003f288252fbd9013aaef0b08b Mon Sep 17 00:00:00 2001 From: jacob Date: Sat, 6 Dec 2025 04:27:19 -0600 Subject: [PATCH] wave-enabled meta build --- src/base/base.h | 17 +- src/base/base_wave.c | 53 +- src/base/base_wave.h | 27 +- src/base/base_win32/base_win32.c | 66 +- src/base/base_win32/base_win32_wave.c | 19 +- src/meta/meta.c | 1721 +++++++------------------ 6 files changed, 629 insertions(+), 1274 deletions(-) diff --git a/src/base/base.h b/src/base/base.h index f5611598..a4968377 100644 --- a/src/base/base.h +++ b/src/base/base.h @@ -693,6 +693,19 @@ }; #endif +//////////////////////////////////////////////////////////// +//~ Cpu topology types + +#if IsLanguageC + Struct(CpuTopologyInfo) + { + i32 num_logical_cores; /* Includes P cores, Non-P cores, SMT siblings */ + i32 num_physical_cores; /* Includes P Cores, Non-P Cores */ + i32 num_physical_performance_cores; /* Includes P Cores */ + i32 num_physical_non_performance_cores; /* Includes Non-P cores */ + }; +#endif + //////////////////////////////////////////////////////////// //~ C <-> Shader interop types @@ -750,9 +763,10 @@ Struct(SamplerStateHandle) { u32 v; }; #endif //////////////////////////////////////////////////////////// -//~ @hookdecl Api hooks +//~ @hookdecl Core api hooks #if IsLanguageC + //- Core hooks StringList GetRawCommandline(void); void Echo(String msg); @@ -765,6 +779,7 @@ Struct(SamplerStateHandle) { u32 v; }; void SignalExit(i32 code); void ExitNow(i32 code); + //- Meta hooks void StartupLayers(void); #endif diff --git a/src/base/base_wave.c b/src/base/base_wave.c index 672529b6..76e3e712 100644 --- a/src/base/base_wave.c +++ b/src/base/base_wave.c @@ -1,7 +1,56 @@ //////////////////////////////////////////////////////////// //~ Wave sync ops -void WaveSyncBroadcast_(WaveLaneCtx *lane_ctx, i32 broadcast_lane_idx, void *broadcast_ptr, u64 broadcast_size) +void WaveSyncEx(WaveLaneCtx *lane, u64 spin_count) { - /* FIXME: Impl */ + WaveCtx *wave = lane->wave; + i32 lanes_count = wave->lanes_count; + if (lanes_count > 0) + { + i64 barrier_gen = Atomic64Fetch(&wave->barrier_gen.v); + i32 blocked_count = Atomic32FetchAdd(&wave->barrier_blocked_count, 1) + 1; + if (blocked_count == lanes_count) + { + Atomic32Set(&wave->barrier_blocked_count, 0); + Atomic64FetchAdd(&wave->barrier_gen.v, barrier_gen + 1); + FutexWakeNeq(&wave->barrier_gen.v); + } + else + { + u64 remaining_spins = spin_count; + while (Atomic64Fetch(&wave->barrier_gen.v) == barrier_gen) + { + if (remaining_spins > 0) + { + --remaining_spins; + _mm_pause(); + } + else + { + FutexYieldNeq(&wave->barrier_gen.v, &barrier_gen, sizeof(barrier_gen)); + } + } + } + } +} + +void WaveSyncBroadcastEx_(WaveLaneCtx *lane, u32 broadcast_lane_idx, void *broadcast_ptr, u64 broadcast_size, u64 spin_count) +{ + WaveCtx *wave = lane->wave; + u32 lane_idx = lane->idx; + if (lane_idx == broadcast_lane_idx) + { + wave->barrier_broadcast_data = broadcast_ptr; + } + WaveSyncEx(lane, spin_count); + if (lane_idx != broadcast_lane_idx) + { + CopyBytes(broadcast_ptr, wave->barrier_broadcast_data, broadcast_size); + } + WaveSyncEx(lane, spin_count); +} + +void SetWaveLaneDefaultSpin(WaveLaneCtx *lane, u64 n) +{ + lane->default_spin_count = n; } diff --git a/src/base/base_wave.h b/src/base/base_wave.h index 916923b4..afdfff39 100644 --- a/src/base/base_wave.h +++ b/src/base/base_wave.h @@ -1,15 +1,23 @@ //////////////////////////////////////////////////////////// //~ Wave types +#define DefaultWaveLaneSpinCount 500 + Struct(WaveCtx) { - u32 lanes_count; + i32 lanes_count; + + /* Barrier */ + void *barrier_broadcast_data; + Atomic32 barrier_blocked_count; + Atomic64Padded barrier_gen; }; Struct(WaveLaneCtx) { - u32 idx; + i32 idx; WaveCtx *wave; + u64 default_spin_count; }; typedef void WaveLaneEntryFunc(WaveLaneCtx *lane, void *udata); @@ -17,13 +25,22 @@ typedef void WaveLaneEntryFunc(WaveLaneCtx *lane, void *udata); //////////////////////////////////////////////////////////// //~ Wave sync ops -#define WaveSyncBroadcast(lane_ctx, broadcast_lane_idx, broadcast_ptr) WaveSyncBroadcast_((lane_ctx), (broadcast_lane_idx), (broadcast_ptr), sizeof(*(broadcast_ptr))) -void WaveSyncBroadcast_(WaveLaneCtx *lane_ctx, i32 broadcast_lane_idx, void *broadcast_ptr, u64 broadcast_size); +void WaveSyncEx(WaveLaneCtx *lane, u64 spin_count); +#define WaveSync(lane) \ + WaveSyncEx((lane), (lane)->default_spin_count) + +void WaveSyncBroadcastEx_(WaveLaneCtx *lane, u32 broadcast_lane_idx, void *broadcast_ptr, u64 broadcast_size, u64 spin_count); +#define WaveSyncBroadcastEx(lane, broadcast_lane_idx, broadcast_ptr, spin_count) \ + WaveSyncBroadcastEx_((lane), (broadcast_lane_idx), (broadcast_ptr), sizeof(*(broadcast_ptr)), (spin_count)) +#define WaveSyncBroadcast(lane, broadcast_lane_idx, broadcast_ptr) \ + WaveSyncBroadcastEx_((lane), (broadcast_lane_idx), (broadcast_ptr), sizeof(*(broadcast_ptr)), (lane)->default_spin_count) + +void SetWaveLaneDefaultSpin(WaveLaneCtx *lane, u64 n); //////////////////////////////////////////////////////////// //~ @hookdecl Dispatch -void DispatchWave(u32 num_lanes, WaveLaneEntryFunc *entry, void *udata); +void DispatchWave(String name, u32 num_lanes, WaveLaneEntryFunc *entry, void *udata); //////////////////////////////////////////////////////////// //~ @hookdecl Thread diff --git a/src/base/base_win32/base_win32.c b/src/base/base_win32/base_win32.c index d121c3ca..1e3381c0 100644 --- a/src/base/base_win32/base_win32.c +++ b/src/base/base_win32/base_win32.c @@ -36,7 +36,7 @@ BOOL W32_FindEmbeddedRcData(HMODULE module, LPCWSTR type, LPWSTR wstr_entry_name } //////////////////////////////////////////////////////////// -//~ @hookimpl Core hooks +//~ @hookimpl Core api hooks StringList GetRawCommandline(void) { @@ -109,6 +109,67 @@ void TrueRand(String buffer) BCryptGenRandom(BCRYPT_RNG_ALG_HANDLE, (u8 *)buffer.text, buffer.len, 0); } +CpuTopologyInfo GetCpuTopologyInfo(void) +{ + TempArena scratch = BeginScratchNoConflict(); + CpuTopologyInfo res = ZI; + { + DWORD infos_buff_size = 0; + u8 *infos_buff = 0; + b32 ok = 0; + { + GetLogicalProcessorInformationEx(RelationProcessorCore, 0, &infos_buff_size); + infos_buff = PushStructsNoZero(scratch.arena, u8, infos_buff_size); + ok = GetLogicalProcessorInformationEx(RelationProcessorCore, (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *)infos_buff, &infos_buff_size); + } + if (ok) + { + /* Determine max efficiency class */ + i32 max_efficiency_class = 0; + { + DWORD pos = 0; + while (pos < infos_buff_size) + { + SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *info = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *)&infos_buff[pos]; + max_efficiency_class = MaxI32(max_efficiency_class, info->Processor.EfficiencyClass); + pos += info->Size; + } + } + /* Generate physical core info */ + { + DWORD pos = 0; + while (pos < infos_buff_size) + { + SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *info = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *)&infos_buff[pos]; + ++res.num_physical_cores; + ++res.num_logical_cores; + if (info->Processor.Flags & LTP_PC_SMT) + { + /* Core has SMT sibling */ + ++res.num_logical_cores; + } + if (info->Processor.EfficiencyClass == max_efficiency_class) + { + /* Core is P-core */ + ++res.num_physical_performance_cores; + } + else + { + /* Core is not a P-core */ + ++res.num_physical_non_performance_cores; + } + pos += info->Size; + } + } + } + } + res.num_logical_cores = MaxI32(res.num_logical_cores, 1); + res.num_physical_cores = MaxI32(res.num_physical_cores, 1); + res.num_physical_performance_cores = MaxI32(res.num_physical_performance_cores, 1); + EndScratch(scratch); + return res; +} + //////////////////////////////////////////////////////////// //~ @hookimpl Swap hooks @@ -226,7 +287,7 @@ i32 W32_Main(void) GetSystemInfo(&g->info); /* Init main thread */ - W32_InitCurrentThread(Lit("Main thread")); + W32_InitCurrentThread(Lit("Main")); /* Get raw args from command line */ { @@ -252,6 +313,7 @@ i32 W32_Main(void) /* Init log system */ /* FIXME: Remove hardcoded log path */ InitLogSystem(Lit("log.log")); + LogInfoF("Main thread ID: %F", FmtUint(ThreadId())); /* Init resources */ { diff --git a/src/base/base_win32/base_win32_wave.c b/src/base/base_win32/base_win32_wave.c index dff950e1..cbcc6e9b 100644 --- a/src/base/base_win32/base_win32_wave.c +++ b/src/base/base_win32/base_win32_wave.c @@ -16,8 +16,8 @@ void W32_InitCurrentThread(String name) Arena *perm = PermArena(); /* Fixme: Set thread name */ - // SetThreadDescription(GetCurrentThread(), thread_name_wstr); - //LogInfoF("New thread \"%F\" created with ID %F", FmtString(StringFromCstrNoLimit(t->thread_name_cstr)), FmtUint(ThreadId())); + wchar_t *thread_name_wstr = WstrFromString(perm, name); + SetThreadDescription(GetCurrentThread(), thread_name_wstr); /* Initialize COM */ CoInitializeEx(0, COINIT_MULTITHREADED); @@ -27,6 +27,7 @@ DWORD WINAPI W32_ThreadProc(LPVOID thread_args_vp) { W32_ThreadArgs *thread_args = (W32_ThreadArgs *)thread_args_vp; W32_InitCurrentThread(thread_args->name); + LogInfoF("New thread \"%F\" created with ID %F", FmtString(thread_args->name), FmtUint(ThreadId())); thread_args->entry(thread_args->lane, thread_args->udata); return 0; } @@ -34,7 +35,7 @@ DWORD WINAPI W32_ThreadProc(LPVOID thread_args_vp) //////////////////////////////////////////////////////////// //~ @hookimpl Dispatch -void DispatchWave(u32 num_lanes, WaveLaneEntryFunc *entry, void *udata) +void DispatchWave(String name, u32 num_lanes, WaveLaneEntryFunc *entry, void *udata) { /* FIXME: Impl */ @@ -56,11 +57,23 @@ void DispatchWave(u32 num_lanes, WaveLaneEntryFunc *entry, void *udata) lane_ctx->idx = lane_idx; lane_ctx->wave = wave_ctx; + lane_ctx->default_spin_count = DefaultWaveLaneSpinCount; + + String thread_name = ZI; + if (num_lanes > 1) + { + thread_name = StringF(perm, "%F:%F", FmtString(name), FmtUint(lane_idx)); + } + else + { + thread_name = PushString(perm, name); + } W32_ThreadArgs *thread_args = PushStruct(perm, W32_ThreadArgs); thread_args->lane = lane_ctx; thread_args->udata = udata; thread_args->entry = entry; + thread_args->name = thread_name; HANDLE handle = CreateThread(0, Mebi(4), W32_ThreadProc, thread_args, 0, 0); if (!handle) diff --git a/src/meta/meta.c b/src/meta/meta.c index 1fb6c6a7..18562a7c 100644 --- a/src/meta/meta.c +++ b/src/meta/meta.c @@ -58,21 +58,26 @@ //- Source files #include "meta_lay.c" -//////////////////////////////////////////////////////////// -//~ Global command line args - -Struct(CmdLineArgs) -{ - String leaf_layer_name; -} cmdline = ZI; - //////////////////////////////////////////////////////////// //~ Util void EchoLine(String msg) { - Echo(msg); - Echo(Lit("\n")); + TempArena scratch = BeginScratchNoConflict(); + { + String msg_w_newline = StringF(scratch.arena, "%F\n", FmtString(msg)); + Echo(msg_w_newline); + } + EndScratch(scratch); +} + +void EchoLineOrNothing(String msg) +{ + String trimmed_msg = TrimWhitespace(msg); + if (trimmed_msg.len > 0) + { + EchoLine(trimmed_msg); + } } Struct(LineCol) @@ -103,769 +108,50 @@ LineCol LineColFromPos(String data, i64 pos) return result; } -//////////////////////////////////////////////////////////// -//~ Compiler params - -Struct(CompilerParams) +String StringFromMetaErrors(Arena *arena, M_ErrorList errors) { - StringList defs; - - StringList warnings_msvc; - StringList warnings_clang; - StringList warnings_dxc; - - StringList flags_msvc; - StringList flags_clang; - StringList flags_dxc; - - StringList compiler_only_flags_msvc; - StringList compiler_only_flags_clang; - - StringList linker_only_flags_msvc; - StringList linker_only_flags_clang; -}; - -//////////////////////////////////////////////////////////// -//~ Build step job - -#if 0 - -Enum(StepParamsFlag) -{ - StepParamsFlag_None = 0, - StepParamsFlag_CompileProgram = (1 << 0), - StepParamsFlag_CompileShaders = (1 << 1), - StepParamsFlag_CompileEmbeddedDirs = (1 << 2), - StepParamsFlag_CompileArc = (1 << 3), - StepParamsFlag_RunCommand = (1 << 4), -}; - -Struct(StepParams) -{ - StepParamsFlag flags; - - M_Layer flattened; - CompilerParams compiler_params; - - String arc_store; - String arc_dir; - - String cmd; -}; - -Struct(StepResult) -{ - StringList obj_files; - StringList output_lines; - M_ErrorList meta_errors; - OS_CommandResult cmd_result; - i32 return_code; - i64 elapsed_ns; -}; - -void InheritStepResults(Arena *arena, StepResult *dst, u64 srcs_count, StepResult *srcs) -{ - for (i32 i = 0; i < srcs_count; ++i) + String result = ZI; + for (M_Error *e = errors.first; e; e = e->next) { - StepResult *src = &srcs[i]; - if (dst->return_code == 0) + M_Token *token = e->token; + String token_file = token->file->name; + String token_file_data = token->file->data; + if (token_file.len > 0) { - dst->return_code = src->return_code; - } - for (StringListNode *n = src->output_lines.first; n; n = n->next) - { - PushStringToList(arena, &dst->output_lines, n->s); - } - for (StringListNode *n = src->obj_files.first; n; n = n->next) - { - PushStringToList(arena, &dst->obj_files, n->s); - } - M_AppendErrors(arena, &dst->meta_errors, src->meta_errors); - } -} - -void Step(void) -{ - StepParams *params = &sig->params[id]; - StepParamsFlag flags = params->flags; - CompilerParams cp = params->compiler_params; - Arena *arena = PermArena(); - - StepResult *result = &sig->results[id]; - M_ErrorList *errors = &result->meta_errors; - StringList *output = &result->output_lines; - i64 start_ns = TimeNs(); - - String shader_store_name = Lit("ShadersStore"); - - ////////////////////////////// - //- Build C - - if (flags & StepParamsFlag_CompileProgram) - { - //- Generate C file - String c_out_file = F_GetFull(arena, StringF(arena, "%F_gen_c.c", FmtString(cmdline.leaf_layer_name))); - { - StringList c_store_lines = ZI; - StringList c_shader_lines = ZI; - StringList c_include_lines = ZI; - StringList c_startup_lines = ZI; + i64 token_pos = -1; + if (token->s.len > 0 + && token_file_data.len > 0 + && token->s.text > token_file_data.text + && token->s.text < (token_file_data.text + token_file_data.len)) { - for (M_Entry *entry = params->flattened.first; entry->valid; entry = entry->next) - { - M_EntryKind kind = entry->kind; - M_Token *entry_tok = entry->name_token; - M_Token *arg0_tok = entry->arg_tokens[0]; - M_Token *arg1_tok = entry->arg_tokens[1]; - switch (kind) - { - default: break; - case M_EntryKind_EmbedDir: - { - if (arg0_tok->valid && arg1_tok->valid) - { - String store_name = arg0_tok->s; - String token_file = arg1_tok->file->name; - String token_parent_dir = F_GetParentDir(token_file); - String arg_dir = arg1_tok->s; - String full = F_GetFullCrossPlatform(arena, StringF(arena, "%F/%F", FmtString(token_parent_dir), FmtString(arg_dir))); - if (F_IsDir(full)) - { - u64 hash = HashFnv64(Fnv64Basis, StringF(arena, "%F/", FmtString(store_name))); - String line = StringF(arena, "ResourceStore %F = { 0x%F };", FmtString(store_name), FmtHex(hash)); - PushStringToList(arena, &c_store_lines, line); - } - else - { - String err = StringF(arena, "Directory '%F' not found", FmtString(full)); - M_PushError(arena, errors, arg1_tok, err); - } - } - else - { - M_PushError(arena, errors, entry_tok, Lit("Expected resource store & directory name")); - } - } break; - case M_EntryKind_VertexShader: - case M_EntryKind_PixelShader: - case M_EntryKind_ComputeShader: - { - if (arg0_tok->valid) - { - String shader_type = kind == M_EntryKind_VertexShader ? Lit("VertexShader") - : kind == M_EntryKind_PixelShader ? Lit("PixelShader") - : kind == M_EntryKind_ComputeShader ? Lit("ComputeShader") - : Lit(""); - String shader_name = arg0_tok->s; - u64 hash = HashFnv64(Fnv64Basis, StringF(arena, "%F/%F", FmtString(shader_store_name), FmtString(shader_name))); - String line = StringF(arena, "%F %F = { 0x%F };", FmtString(shader_type), FmtString(shader_name), FmtHex(hash)); - PushStringToList(arena, &c_shader_lines, line); - } - else - { - M_PushError(arena, errors, entry_tok, Lit("Expected shader name")); - } - } break; - case M_EntryKind_IncludeC: - { - if (arg0_tok->valid) - { - String token_file = arg0_tok->file->name; - String token_parent_dir = F_GetParentDir(token_file); - String arg_file = arg0_tok->s; - String full = F_GetFull(arena, StringF(arena, "%F/%F", FmtString(token_parent_dir), FmtString(arg_file))); - if (F_IsFile(full)) - { - String line = StringF(arena, "#include \"%F\"", FmtString(full)); - PushStringToList(arena, &c_include_lines, line); - } - else - { - String err = StringF(arena, "File '%F' not found", FmtString(full)); - M_PushError(arena, errors, arg0_tok, err); - } - } - else - { - M_PushError(arena, errors, entry_tok, Lit("Expected file name")); - } - } break; - case M_EntryKind_Startup: - { - if (arg0_tok->valid) - { - String startup = arg0_tok->s; - String line = StringF(arena, " %F();", FmtString(startup)); - PushStringToList(arena, &c_startup_lines, line); - } - else - { - M_PushError(arena, errors, entry_tok, Lit("Expected startup function name")); - } - } break; - } - } + token_pos = token->s.text - token_file_data.text; } - if (errors->count == 0) + LineCol line_col = ZI; + if (token_pos >= 0) { - StringList c_out_lines = ZI; - PushStringToList(arena, &c_out_lines, Lit("// Auto generated file")); - /* Include base layer */ - { - String base_inc_path = F_GetFull(arena, Lit("../src/base/base_inc.h")); - PushStringToList(arena, &c_out_lines, Lit("")); - PushStringToList(arena, &c_out_lines, Lit("//- Base layer includes")); - PushStringToList(arena, &c_out_lines, StringF(arena, "#include \"%F\"", FmtString(base_inc_path))); - } - /* Define resource stores */ - if (c_store_lines.count > 0) - { - PushStringToList(arena, &c_out_lines, Lit("")); - PushStringToList(arena, &c_out_lines, Lit("//- Resource stores")); - for (StringListNode *n = c_store_lines.first; n; n = n->next) - { - PushStringToList(arena, &c_out_lines, n->s); - } - } - /* Define shaders */ - if (c_shader_lines.count > 0) - { - PushStringToList(arena, &c_out_lines, Lit("")); - PushStringToList(arena, &c_out_lines, Lit("//- Shaders")); - for (StringListNode *n = c_shader_lines.first; n; n = n->next) - { - PushStringToList(arena, &c_out_lines, n->s); - } - } - /* Include dependency layers */ - if (c_include_lines.count > 0) - { - PushStringToList(arena, &c_out_lines, Lit("")); - PushStringToList(arena, &c_out_lines, Lit("//- Dependency graph includes")); - for (StringListNode *n = c_include_lines.first; n; n = n->next) - { - PushStringToList(arena, &c_out_lines, n->s); - } - } - /* Define StartupLayers */ - { - PushStringToList(arena, &c_out_lines, Lit("")); - PushStringToList(arena, &c_out_lines, Lit("//- Startup")); - PushStringToList(arena, &c_out_lines, Lit("void StartupLayers(void)")); - PushStringToList(arena, &c_out_lines, Lit("{")); - for (StringListNode *n = c_startup_lines.first; n; n = n->next) - { - PushStringToList(arena, &c_out_lines, n->s); - } - PushStringToList(arena, &c_out_lines, Lit("}")); - } - /* Write to file */ - PushStringToList(arena, &c_out_lines, Lit("")); - String c_out = StringFromList(arena, c_out_lines, Lit("\n")); - F_ClearWrite(c_out_file, c_out); - } - } - - //- Compile C - String c_out_obj_file = StringF(arena, "%F_gen_c.obj", FmtString(cmdline.leaf_layer_name)); - PushStringToList(arena, &result->obj_files, c_out_obj_file); - if (errors->count == 0) - { - String cmd = StringF(arena, - "cmd /c cl.exe /c %F -Fo:%F %F %F %F %F", - FmtString(c_out_file), - FmtString(c_out_obj_file), - FmtString(StringFromList(arena, cp.flags_msvc, Lit(" "))), - FmtString(StringFromList(arena, cp.compiler_only_flags_msvc, Lit(" "))), - FmtString(StringFromList(arena, cp.warnings_msvc, Lit(" "))), - FmtString(StringFromList(arena, cp.defs, Lit(" ")))); - OS_CommandResult cmd_result = OS_RunCommand(arena, cmd); - String cmd_output = TrimWhitespace(cmd_result.output); - if (cmd_output.len > 0) - { - PushStringToList(arena, output, cmd_output); - } - result->return_code = cmd_result.code; - } - } - - ////////////////////////////// - //- Build shaders - - if (flags & StepParamsFlag_CompileShaders) - { - String shader_store_name = shader_store_name; - OS_Mkdir(shader_store_name); - { - /* Remove all old shaders */ - StringList files = ZI; - F_FilesFromDir(arena, &files, shader_store_name, F_IterFlag_None); - for (StringListNode *n = files.first; n; n = n->next) - { - String file = n->s; - /* Safety check to prevent non-shader files from being removed */ - if (StringEndsWith(file, Lit("VS")) || StringEndsWith(file, Lit("CS")) || StringEndsWith(file, Lit("PS"))) - { - OS_Rm(n->s); - } - } - } - - //- Generate GPU file & shader entries - String gpu_out_file = F_GetFull(arena, StringF(arena, "%F_gen_gpu.hlsl", FmtString(cmdline.leaf_layer_name))); - Enum(ShaderEntryKind) { ShaderEntryKind_VS, ShaderEntryKind_PS, ShaderEntryKind_CS, }; - Struct(ShaderEntry) { ShaderEntry *next; ShaderEntryKind kind; String name; }; - ShaderEntry *first_shader_entry = 0; - ShaderEntry *last_shader_entry = 0; - u64 shader_entries_count = 0; - { - StringList gpu_include_lines = ZI; - { - for (M_Entry *entry = params->flattened.first; entry->valid; entry = entry->next) - { - M_EntryKind kind = entry->kind; - M_Token *entry_tok = entry->name_token; - M_Token *arg0_tok = entry->arg_tokens[0]; - M_Token *arg1_tok = entry->arg_tokens[1]; - switch (kind) - { - default: break; - case M_EntryKind_IncludeGpu: - { - if (arg0_tok->valid) - { - String token_file = arg0_tok->file->name; - String token_parent_dir = F_GetParentDir(token_file); - String arg_file = arg0_tok->s; - String full = F_GetFull(arena, StringF(arena, "%F/%F", FmtString(token_parent_dir), FmtString(arg_file))); - if (F_IsFile(full)) - { - String line = StringF(arena, "#include \"%F\"", FmtString(full)); - PushStringToList(arena, &gpu_include_lines, line); - } - else - { - String err = StringF(arena, "File '%F' not found", FmtString(full)); - M_PushError(arena, errors, arg0_tok, err); - } - } - else - { - M_PushError(arena, errors, entry_tok, Lit("Expected file name")); - } - } break; - case M_EntryKind_VertexShader: - case M_EntryKind_PixelShader: - case M_EntryKind_ComputeShader: - { - if (arg0_tok->valid) - { - ShaderEntryKind shader_kind = kind == M_EntryKind_VertexShader ? ShaderEntryKind_VS - : kind == M_EntryKind_PixelShader ? ShaderEntryKind_PS - : kind == M_EntryKind_ComputeShader ? ShaderEntryKind_CS - : ShaderEntryKind_VS; - String shader_name = arg0_tok->s; - ShaderEntry *e = PushStruct(arena, ShaderEntry); - e->kind = shader_kind; - e->name = shader_name; - SllQueuePush(first_shader_entry, last_shader_entry, e); - ++shader_entries_count; - } - else - { - M_PushError(arena, errors, entry_tok, Lit("Expected shader name")); - } - } break; - } - } - } - if (errors->count == 0) - { - StringList gpu_out_lines = ZI; - PushStringToList(arena, &gpu_out_lines, Lit("// Auto generated file")); - /* Include base layer */ - { - String base_inc_path = F_GetFull(arena, Lit("../src/base/base_inc.h")); - PushStringToList(arena, &gpu_out_lines, Lit("")); - PushStringToList(arena, &gpu_out_lines, Lit("//- Base layer includes")); - PushStringToList(arena, &gpu_out_lines, StringF(arena, "#include \"%F\"", FmtString(base_inc_path))); - } - /* Include dependency layers */ - if (gpu_out_lines.count > 0) - { - PushStringToList(arena, &gpu_out_lines, Lit("")); - PushStringToList(arena, &gpu_out_lines, Lit("//- Dependency graph includes")); - for (StringListNode *n = gpu_include_lines.first; n; n = n->next) - { - PushStringToList(arena, &gpu_out_lines, n->s); - } - } - /* Write to file */ - PushStringToList(arena, &gpu_out_lines, Lit("")); - String c_out = StringFromList(arena, gpu_out_lines, Lit("\n")); - F_ClearWrite(gpu_out_file, c_out); - } - } - - //- Compile shaders - String *compile_cmds = PushStructs(arena, String, shader_entries_count); - RunCommandResult *compile_results = PushStructs(arena, RunCommandResult, shader_entries_count); - { - i32 i = 0; - for (ShaderEntry *e = first_shader_entry; e; e = e->next) - { - String target = e->kind == ShaderEntryKind_VS ? Lit("vs_6_6") - : e->kind == ShaderEntryKind_PS ? Lit("ps_6_6") - : e->kind == ShaderEntryKind_CS ? Lit("cs_6_6") - : Lit("vs_6_6"); - String *compile_cmd = &compile_cmds[i]; - *compile_cmd = StringF(arena, - "cmd /c dxc.exe -T %F -E %F -Fo %F/%F %F %F %F", - FmtString(target), - FmtString(e->name), - FmtString(shader_store_name), - FmtString(e->name), - FmtString(gpu_out_file), - FmtString(StringFromList(arena, cp.defs, Lit(" "))), - FmtString(StringFromList(arena, cp.flags_dxc, Lit(" ")))); - ++i; - } - } - - u32 job_count = 0; Fence job_fence = ZI; - job_count += RunJob(RunCommand, - .count = shader_entries_count, - .fence = &job_fence, - .sig = { .cmds = compile_cmds, .results = compile_results }); - YieldOnFence(&job_fence, job_count); - - //- Process shader compilation results - { - i32 i = 0; - for (ShaderEntry *e = first_shader_entry; e; e = e->next) - { - RunCommandResult compile_result = compile_results[i]; - OS_CommandResult cmd_result = compile_result.cmd_result; - if (result->return_code == 0) - { - PushStringToList(arena, output, StringF(arena, "%F:%F %Fs", FmtString(F_GetFileName(gpu_out_file)), FmtString(e->name), FmtFloat(SecondsFromNs(compile_result.elapsed_ns)))); - if (cmd_result.output.len > 0) - { - PushStringToList(arena, output, cmd_result.output); - } - result->return_code = cmd_result.code; - } - ++i; - } - } - - //- Build embedded shader archive - if (result->return_code == 0) - { - StepParams arc_params = *params; - StepResult arc_results = ZI; - - arc_params.flags = StepParamsFlag_CompileArc; - arc_params.arc_store = shader_store_name; - arc_params.arc_dir = shader_store_name; - - u32 job_count = 0; Fence job_fence = ZI; - job_count += RunJob(Step, .fence = &job_fence, .sig.params = &arc_params, .sig.results = &arc_results); - YieldOnFence(&job_fence, job_count); - InheritStepResults(arena, result, 1, &arc_results); - } - } - - ////////////////////////////// - //- Build embedded dirs - - if (flags & StepParamsFlag_CompileEmbeddedDirs) - { - //- Assemble embed dirs - String arc_out_file = F_GetFull(arena, Lit("resources.arc")); - { - Struct(EmbeddedDir) { EmbeddedDir *next; String store_name; String dir_name; }; - EmbeddedDir *first_dir_embed = 0; - EmbeddedDir *last_dir_embed = 0; - u64 dir_embeds_count = 0; - { - for (M_Entry *entry = params->flattened.first; entry->valid; entry = entry->next) - { - M_EntryKind kind = entry->kind; - M_Token *entry_tok = entry->name_token; - M_Token *arg0_tok = entry->arg_tokens[0]; - M_Token *arg1_tok = entry->arg_tokens[1]; - switch (kind) - { - default: break; - case M_EntryKind_EmbedDir: - { - if (arg0_tok->valid && arg1_tok->valid) - { - String store_name = arg0_tok->s; - String token_file = arg1_tok->file->name; - String token_parent_dir = F_GetParentDir(token_file); - String arg_dir = arg1_tok->s; - String full = F_GetFullCrossPlatform(arena, StringF(arena, "%F/%F", FmtString(token_parent_dir), FmtString(arg_dir))); - if (F_IsDir(full)) - { - EmbeddedDir *ed = PushStruct(arena, EmbeddedDir); - ed->store_name = store_name; - ed->dir_name = full; - SllQueuePush(first_dir_embed, last_dir_embed, ed); - ++dir_embeds_count; - } - else - { - String err = StringF(arena, "Directory '%F' not found", FmtString(full)); - M_PushError(arena, errors, arg1_tok, err); - } - } - else - { - M_PushError(arena, errors, entry_tok, Lit("Expected resource store & directory name")); - } - } break; - } - } - } - if (errors->count == 0) - { - StepParams *arc_params_array = PushStructs(arena, StepParams, dir_embeds_count); - StepResult *arc_results_array = PushStructs(arena, StepResult, dir_embeds_count); - { - i32 i = 0; - for (EmbeddedDir *ed = first_dir_embed; ed; ed = ed->next) - { - StepParams *arc_params = &arc_params_array[i]; - *arc_params = *params; - arc_params->flags = StepParamsFlag_CompileArc; - arc_params->arc_store = ed->store_name; - arc_params->arc_dir = ed->dir_name; - ++i; - } - } - u32 job_count = 0; Fence job_fence = ZI; - job_count += RunJob(Step, - .fence = &job_fence, - .count = dir_embeds_count, - .sig.params = arc_params_array, - .sig.results = arc_results_array); - YieldOnFence(&job_fence, job_count); - InheritStepResults(arena, result, dir_embeds_count, arc_results_array); - } - } - } - - ////////////////////////////// - //- Build arc file - - if (flags & StepParamsFlag_CompileArc) - { - String store = params->arc_store; - String dir_path = params->arc_dir; - - Struct(EntryNode) - { - EntryNode *next; - String entry_name; - String file_name; - }; - - EntryNode *first_entry = 0; - EntryNode *last_entry = 0; - u64 entries_count = 0; - - StringList files = ZI; - F_FilesFromDir(arena, &files, dir_path, F_IterFlag_Recurse); - for (StringListNode *file_node = files.first; file_node; file_node = file_node->next) - { - String file_name = file_node->s; - if (F_IsFile(file_name)) - { - String entry_name = file_name; - if (entry_name.len > (dir_path.len + 1)) - { - entry_name.len -= dir_path.len + 1; - entry_name.text += dir_path.len + 1; - } - entry_name = StringF(arena, "%F/%F", FmtString(store), FmtString(entry_name)); - for (u64 i = 0; i < entry_name.len; ++i) - { - if (entry_name.text[i] == '\\') - { - entry_name.text[i] = '/'; - } - } - - EntryNode *en = PushStruct(arena, EntryNode); - en->entry_name = entry_name; - en->file_name = file_name; - SllQueuePush(first_entry, last_entry, en); - ++entries_count; - } - } - - String arc_out_file = StringF(arena, "%F.arc", FmtString(store)); - String arc_contents = ZI; - { - BB_Buff bb = BB_AcquireBuff(Gibi(2)); - BB_Writer bw = BB_WriterFromBuff(&bb); - - /* Write magic */ - BB_WriteUBits(&bw, ResourceEmbeddedMagic, 64); - - /* Write header */ - BB_WriteUBits(&bw, entries_count, 64); - - /* Reserve entries space */ - u64 entry_size = 8 /* Name start */ - + 8 /* Name end */ - + 8 /* Data start */ - + 8; /* Data end */ - u8 *entries_start = BB_GetWrittenRaw(&bw) + BB_GetNumBytesWritten(&bw); - u64 entries_size = entry_size * entries_count; - String entries_str = STRING(entries_size, entries_start); - BB_WriteSeekBytes(&bw, entries_size); - BB_Buff entries_bb = BB_BuffFromString(entries_str); - BB_Writer entries_bw = BB_WriterFromBuff(&entries_bb); - - /* Write entries */ - for (EntryNode *en = first_entry; en; en = en->next) - { - /* TODO: Copy file data directly into archive file */ - String file_data = F_DataFromFile(arena, en->file_name); - - /* Write name */ - BB_WriteAlignBytes(&bw, 64); - u64 name_start = BB_GetNumBytesWritten(&bw) + 1; - BB_WriteString(&bw, en->entry_name); - u64 name_len = BB_GetNumBytesWritten(&bw) - name_start; - - /* Write data */ - BB_WriteAlignBytes(&bw, 64); - /* FIXME: Why no +1 here? */ - u64 data_start = BB_GetNumBytesWritten(&bw); - BB_WriteBytes(&bw, file_data); - u64 data_len = BB_GetNumBytesWritten(&bw) - data_start; - - /* Write entry */ - BB_WriteUBits(&entries_bw, name_start, 64); - BB_WriteUBits(&entries_bw, name_len, 64); - BB_WriteUBits(&entries_bw, data_start, 64); - BB_WriteUBits(&entries_bw, data_len, 64); - } - - arc_contents.len = BB_GetNumBytesWritten(&bw); - arc_contents.text = BB_GetWrittenRaw(&bw); - } - - /* Write arc file */ - F_ClearWrite(arc_out_file, arc_contents); - PushStringToList(arena, output, StringF(arena, "%F (%F mb)", FmtString(F_GetFileName(arc_out_file)), FmtFloatP((f32)arc_contents.len / 1024 / 1024, 3))); - - if (IsPlatformWindows) - { - //- Generate rc file - String rc_out_file = StringF(arena, "%F.rc", FmtString(store)); - { - RandState rs = ZI; - StringList rc_out_lines = ZI; - String arc_file_cp = F_GetFullCrossPlatform(arena, arc_out_file); - String line = StringF(arena, "%F_%F RCDATA \"%F\"", FmtString(Lit(Stringize(W32_EmbeddedDataPrefix))), FmtHex(RandU64FromState(&rs)), FmtString(arc_file_cp)); - PushStringToList(arena, &rc_out_lines, line); - /* Write to file */ - String rc_out = StringFromList(arena, rc_out_lines, Lit("\n")); - F_ClearWrite(rc_out_file, rc_out); - } - - //- Compile RC - String res_out_file = StringF(arena, "%F.res", FmtString(store)); - PushStringToList(arena, &result->obj_files, res_out_file); - if (errors->count == 0) - { - String cmd = StringF(arena, "cmd /c rc.exe -nologo -fo %F %F", FmtString(res_out_file), FmtString(F_GetFull(arena, rc_out_file))); - OS_CommandResult cmd_result = OS_RunCommand(arena, cmd); - String cmd_output = TrimWhitespace(cmd_result.output); - PushStringToList(arena, output, rc_out_file); - if (cmd_output.len > 0) - { - PushStringToList(arena, output, cmd_output); - } - result->return_code = cmd_result.code; + line_col = LineColFromPos(token_file_data, token_pos); } + result = StringF(arena, + "%F:%F:%F: error: %F", + FmtString(token_file), + FmtSint(line_col.line), + FmtSint(line_col.col), + FmtString(e->msg)); } else { - /* TODO: Compile object files using .incbin on non-windows platforms */ - Panic(Lit("Non-windows embedded format not implemented")); + result = StringF(arena, "error: %F", FmtString(e->msg)); } } - - ////////////////////////////// - //- Run command - - if (flags & StepParamsFlag_RunCommand) - { - result->cmd_result = OS_RunCommand(arena, cmd); - } - - result->elapsed_ns = TimeNs() - start_ns; + return result; } -#endif - - - - - - - - -//////////////////////////////////////////////////////////// -//~ Stub funcs - - -/* FIXME: Move and implement these */ - - - - - - - - - - - - - - - - -Struct(CpuTopologyInfo) -{ - i32 num_logical_cores; -}; - -CpuTopologyInfo GetCpuTopologyInfo(void) -{ - /* FIXME: Implement this */ - CpuTopologyInfo res = ZI; - res.num_logical_cores = 8; - return res; -} - - - //////////////////////////////////////////////////////////// //~ Startup void BuildEntryPoint(WaveLaneCtx *lane, void *udata) { - Arena *arena = PermArena(); - M_ErrorList meta_parse_errors = ZI; - i32 ret = 0; + Arena *perm = PermArena(); ////////////////////////////// //- Dirty check @@ -877,7 +163,7 @@ void BuildEntryPoint(WaveLaneCtx *lane, void *udata) u64 old_metahash = 0; if (F_IsFile(Lit("metahash.dat"))) { - String hashes_str = F_DataFromFile(arena, Lit("metahash.dat")); + String hashes_str = F_DataFromFile(perm, Lit("metahash.dat")); if (hashes_str.len == sizeof(old_metahash)) { CopyBytes(&old_metahash, hashes_str.text, sizeof(old_metahash)); @@ -889,9 +175,9 @@ void BuildEntryPoint(WaveLaneCtx *lane, void *udata) u64 new_metahash = 0; { StringList check_files = ZI; - F_FilesFromDir(arena, &check_files, Lit("../src/base"), F_IterFlag_Recurse); - F_FilesFromDir(arena, &check_files, Lit("../src/meta"), F_IterFlag_Recurse); - PushStringToList(arena, &check_files, Lit("../src/config.h")); + F_FilesFromDir(perm, &check_files, Lit("../src/base"), F_IterFlag_Recurse); + F_FilesFromDir(perm, &check_files, Lit("../src/meta"), F_IterFlag_Recurse); + PushStringToList(perm, &check_files, Lit("../src/config.h")); for (StringListNode *n = check_files.first; n; n = n->next) { String file = n->s; @@ -914,6 +200,11 @@ void BuildEntryPoint(WaveLaneCtx *lane, void *udata) ////////////////////////////// //- Command line + Struct(CmdLineArgs) + { + String leaf_layer_name; + } cmdline = ZI; + if (lane->idx == 0) { String layer_name = ZI; @@ -931,131 +222,153 @@ void BuildEntryPoint(WaveLaneCtx *lane, void *udata) EchoLine(Lit("No layer supplied, assuming \"pp\" build")); layer_name = Lit("pp"); } - EchoLine(StringF(arena, "Building \"%F\"", FmtString(layer_name))); cmdline.leaf_layer_name = layer_name; + EchoLine(StringF(perm, "Building \"%F\"", FmtString(cmdline.leaf_layer_name))); } + WaveSyncBroadcast(lane, 0, &cmdline); ////////////////////////////// - //- Args - //- Generate compiler params + + Struct(CompilerParams) + { + StringList defs; + + StringList warnings_msvc; + StringList warnings_clang; + StringList warnings_dxc; + + StringList flags_msvc; + StringList flags_clang; + StringList flags_dxc; + + StringList compiler_only_flags_msvc; + StringList compiler_only_flags_clang; + + StringList linker_only_flags_msvc; + StringList linker_only_flags_clang; + }; CompilerParams cp = ZI; + { //- Common { - PushStringToList(arena, &cp.defs, Lit("-DIsConsoleApp=0")); - PushStringToList(arena, &cp.defs, Lit("-DIsRtcEnabled=1")); - PushStringToList(arena, &cp.defs, Lit("-DIsAsanEnabled=0")); - PushStringToList(arena, &cp.defs, Lit("-DIsCrtlibEnabled=1")); - PushStringToList(arena, &cp.defs, Lit("-DIsDebinfoEnabled=1")); - PushStringToList(arena, &cp.defs, Lit("-DIsDeveloperModeEnabled=1")); - PushStringToList(arena, &cp.defs, Lit("-DIsUnoptimized=1")); - PushStringToList(arena, &cp.defs, Lit("-DIsTestingEnabled=0")); - PushStringToList(arena, &cp.defs, Lit("-DIsHotSwappingEnabled=1")); + PushStringToList(perm, &cp.defs, Lit("-DIsConsoleApp=0")); + PushStringToList(perm, &cp.defs, Lit("-DIsRtcEnabled=1")); + PushStringToList(perm, &cp.defs, Lit("-DIsAsanEnabled=0")); + PushStringToList(perm, &cp.defs, Lit("-DIsCrtlibEnabled=1")); + PushStringToList(perm, &cp.defs, Lit("-DIsDebinfoEnabled=1")); + PushStringToList(perm, &cp.defs, Lit("-DIsDeveloperModeEnabled=1")); + PushStringToList(perm, &cp.defs, Lit("-DIsUnoptimized=1")); + PushStringToList(perm, &cp.defs, Lit("-DIsTestingEnabled=0")); + PushStringToList(perm, &cp.defs, Lit("-DIsHotSwappingEnabled=1")); } //- Msvc { - PushStringToList(arena, &cp.compiler_only_flags_msvc, Lit("-diagnostics:column")); - PushStringToList(arena, &cp.flags_msvc, Lit("-INCREMENTAL:NO")); - PushStringToList(arena, &cp.flags_msvc, Lit("-nologo")); + PushStringToList(perm, &cp.compiler_only_flags_msvc, Lit("-diagnostics:column")); + PushStringToList(perm, &cp.flags_msvc, Lit("-INCREMENTAL:NO")); + PushStringToList(perm, &cp.flags_msvc, Lit("-nologo")); /* Optimization */ - PushStringToList(arena, &cp.compiler_only_flags_msvc, Lit("-Od")); + PushStringToList(perm, &cp.compiler_only_flags_msvc, Lit("-Od")); /* Debug info */ - PushStringToList(arena, &cp.flags_msvc, Lit("-DEBUG:FULL")); - PushStringToList(arena, &cp.compiler_only_flags_msvc, Lit("-Z7")); + PushStringToList(perm, &cp.flags_msvc, Lit("-DEBUG:FULL")); + PushStringToList(perm, &cp.compiler_only_flags_msvc, Lit("-Z7")); /* Enable warnings */ - PushStringToList(arena, &cp.warnings_msvc, Lit("-W4")); - PushStringToList(arena, &cp.warnings_msvc, Lit("-WX")); - // PushStringToList(arena, &cp.warnings_msvc, Lit("-we4013")); /* function undefined; assuming extern returning int */ + PushStringToList(perm, &cp.warnings_msvc, Lit("-W4")); + PushStringToList(perm, &cp.warnings_msvc, Lit("-WX")); + // PushStringToList(perm, &cp.warnings_msvc, Lit("-we4013")); /* function undefined; assuming extern returning int */ /* Disable warnings */ - PushStringToList(arena, &cp.warnings_msvc, Lit("-wd4244")); /* 'function': conversion from 'int' to 'f32', possible loss of data */ - PushStringToList(arena, &cp.warnings_msvc, Lit("-wd4201")); /* nonstandard extension used: nameless struct/union */ - PushStringToList(arena, &cp.warnings_msvc, Lit("-wd4324")); /* structure was padded due to alignment specifier */ - PushStringToList(arena, &cp.warnings_msvc, Lit("-wd4100")); /* unreferenced parameter */ - PushStringToList(arena, &cp.warnings_msvc, Lit("-wd4101")); /* unreferenced local variable */ - PushStringToList(arena, &cp.warnings_msvc, Lit("-wd4189")); /* local variable is initialized but not referenced */ - PushStringToList(arena, &cp.warnings_msvc, Lit("-wd4200")); /* nonstandard extension used: zero-sized array in struct/union */ - PushStringToList(arena, &cp.warnings_msvc, Lit("-wd4702")); /* unreachable code */ - PushStringToList(arena, &cp.warnings_msvc, Lit("-wd4305")); /* 'initializing': truncation from 'double' to 'f32' */ + PushStringToList(perm, &cp.warnings_msvc, Lit("-wd4244")); /* 'function': conversion from 'int' to 'f32', possible loss of data */ + PushStringToList(perm, &cp.warnings_msvc, Lit("-wd4201")); /* nonstandard extension used: nameless struct/union */ + PushStringToList(perm, &cp.warnings_msvc, Lit("-wd4324")); /* structure was padded due to alignment specifier */ + PushStringToList(perm, &cp.warnings_msvc, Lit("-wd4100")); /* unreferenced parameter */ + PushStringToList(perm, &cp.warnings_msvc, Lit("-wd4101")); /* unreferenced local variable */ + PushStringToList(perm, &cp.warnings_msvc, Lit("-wd4189")); /* local variable is initialized but not referenced */ + PushStringToList(perm, &cp.warnings_msvc, Lit("-wd4200")); /* nonstandard extension used: zero-sized array in struct/union */ + PushStringToList(perm, &cp.warnings_msvc, Lit("-wd4702")); /* unreachable code */ + PushStringToList(perm, &cp.warnings_msvc, Lit("-wd4305")); /* 'initializing': truncation from 'double' to 'f32' */ - // PushStringToList(arena, &cp.warnings_msvc, Lit("-wd4127")); /* conditional expression is constant */ - // PushStringToList(arena, &cp.warnings_msvc, Lit("-wd4820")); /* bytes padding added after data member */ - // PushStringToList(arena, &cp.warnings_msvc, Lit("-wd4464")); /* relative include path contains '..' */ - // PushStringToList(arena, &cp.warnings_msvc, Lit("-wd4061")); /* enumerator is not explicitly handled by a case label */ - // PushStringToList(arena, &cp.warnings_msvc, Lit("-wd4242")); /* conversion from X to Y, possible loss of data */ - // PushStringToList(arena, &cp.warnings_msvc, Lit("-wd4388")); /* signed/unsigned mismatch */ - // PushStringToList(arena, &cp.warnings_msvc, Lit("-wd5045")); /* Compiler will insert Spectre mitigation for memory load if /Qspectre switch specified */ + // PushStringToList(perm, &cp.warnings_msvc, Lit("-wd4127")); /* conditional expression is constant */ + // PushStringToList(perm, &cp.warnings_msvc, Lit("-wd4820")); /* bytes padding added after data member */ + // PushStringToList(perm, &cp.warnings_msvc, Lit("-wd4464")); /* relative include path contains '..' */ + // PushStringToList(perm, &cp.warnings_msvc, Lit("-wd4061")); /* enumerator is not explicitly handled by a case label */ + // PushStringToList(perm, &cp.warnings_msvc, Lit("-wd4242")); /* conversion from X to Y, possible loss of data */ + // PushStringToList(perm, &cp.warnings_msvc, Lit("-wd4388")); /* signed/unsigned mismatch */ + // PushStringToList(perm, &cp.warnings_msvc, Lit("-wd5045")); /* Compiler will insert Spectre mitigation for memory load if /Qspectre switch specified */ } //- Clang { - PushStringToList(arena, &cp.flags_clang, Lit("-std=c99")); - PushStringToList(arena, &cp.flags_clang, Lit("-fno-finite-loops")); - PushStringToList(arena, &cp.flags_clang, Lit("-fno-strict-aliasing")); - PushStringToList(arena, &cp.flags_clang, Lit("-g -gcodeview")); - PushStringToList(arena, &cp.flags_clang, Lit("-O0")); - PushStringToList(arena, &cp.flags_clang, Lit("-msse4.2")); + PushStringToList(perm, &cp.flags_clang, Lit("-std=c99")); + PushStringToList(perm, &cp.flags_clang, Lit("-fno-finite-loops")); + PushStringToList(perm, &cp.flags_clang, Lit("-fno-strict-aliasing")); + PushStringToList(perm, &cp.flags_clang, Lit("-g -gcodeview")); + PushStringToList(perm, &cp.flags_clang, Lit("-O0")); + PushStringToList(perm, &cp.flags_clang, Lit("-msse4.2")); /* Enable warnings */ - PushStringToList(arena, &cp.warnings_clang, Lit("-Wall")); - PushStringToList(arena, &cp.warnings_clang, Lit("-Werror")); - PushStringToList(arena, &cp.warnings_clang, Lit("-Wframe-larger-than=65536")); - PushStringToList(arena, &cp.warnings_clang, Lit("-Wmissing-prototypes")); - PushStringToList(arena, &cp.warnings_clang, Lit("-Wmissing-declarations")); - PushStringToList(arena, &cp.warnings_clang, Lit("-Wunused-variable")); - PushStringToList(arena, &cp.warnings_clang, Lit("-Wunused-but-set-variable")); - PushStringToList(arena, &cp.warnings_clang, Lit("-Wunused-parameter")); - PushStringToList(arena, &cp.warnings_clang, Lit("-Wimplicit-fallthrough")); - PushStringToList(arena, &cp.warnings_clang, Lit("-Wswitch")); + PushStringToList(perm, &cp.warnings_clang, Lit("-Wall")); + PushStringToList(perm, &cp.warnings_clang, Lit("-Werror")); + PushStringToList(perm, &cp.warnings_clang, Lit("-Wframe-larger-than=65536")); + PushStringToList(perm, &cp.warnings_clang, Lit("-Wmissing-prototypes")); + PushStringToList(perm, &cp.warnings_clang, Lit("-Wmissing-declarations")); + PushStringToList(perm, &cp.warnings_clang, Lit("-Wunused-variable")); + PushStringToList(perm, &cp.warnings_clang, Lit("-Wunused-but-set-variable")); + PushStringToList(perm, &cp.warnings_clang, Lit("-Wunused-parameter")); + PushStringToList(perm, &cp.warnings_clang, Lit("-Wimplicit-fallthrough")); + PushStringToList(perm, &cp.warnings_clang, Lit("-Wswitch")); /* Disable warnings */ - PushStringToList(arena, &cp.warnings_clang, Lit("-Wno-initializer-overrides")); - PushStringToList(arena, &cp.warnings_clang, Lit("-Wno-microsoft-enum-forward-reference")); - PushStringToList(arena, &cp.warnings_clang, Lit("-Wno-unused-variable")); - PushStringToList(arena, &cp.warnings_clang, Lit("-Wno-unused-parameter")); - PushStringToList(arena, &cp.warnings_clang, Lit("-Wno-incompatible-function-pointer-types")); + PushStringToList(perm, &cp.warnings_clang, Lit("-Wno-initializer-overrides")); + PushStringToList(perm, &cp.warnings_clang, Lit("-Wno-microsoft-enum-forward-reference")); + PushStringToList(perm, &cp.warnings_clang, Lit("-Wno-unused-variable")); + PushStringToList(perm, &cp.warnings_clang, Lit("-Wno-unused-parameter")); + PushStringToList(perm, &cp.warnings_clang, Lit("-Wno-incompatible-function-pointer-types")); } //- Dxc { - PushStringToList(arena, &cp.flags_dxc, Lit("-Od")); - PushStringToList(arena, &cp.flags_dxc, Lit("-Zi -Qembed_debug")); + PushStringToList(perm, &cp.flags_dxc, Lit("-Od")); + PushStringToList(perm, &cp.flags_dxc, Lit("-Zi -Qembed_debug")); } } ////////////////////////////// - //- Parse + //- Parse meta layers + + i32 ret = 0; M_Layer flattened = ZI; - if (lane->idx == 0) + if (lane->idx == 0 && !ret) { //- Lex layers M_TokenFileList lexed = ZI; { StringList src_dirs = ZI; - PushStringToList(arena, &src_dirs, Lit("../src")); - lexed = M_TokensFromSrcDirs(arena, src_dirs); + PushStringToList(perm, &src_dirs, Lit("../src")); + lexed = M_TokensFromSrcDirs(perm, src_dirs); } //- Parse layers M_LayerList parsed = ZI; { - parsed = M_LayersFromTokenFiles(arena, lexed); + parsed = M_LayersFromTokenFiles(perm, lexed); } //- Flatten layers { StringList starting_layer_names = ZI; - PushStringToList(arena, &starting_layer_names, cmdline.leaf_layer_name); - flattened = M_GetFlattenedEntries(arena, parsed, starting_layer_names); + PushStringToList(perm, &starting_layer_names, cmdline.leaf_layer_name); + flattened = M_GetFlattenedEntries(perm, parsed, starting_layer_names); } - M_AppendErrors(arena, &meta_parse_errors, flattened.errors); } + WaveSyncBroadcast(lane, 0, &flattened); + if (!ret) ret = flattened.errors.count > 0; ////////////////////////////// //- Prep @@ -1082,8 +395,8 @@ void BuildEntryPoint(WaveLaneCtx *lane, void *udata) */ String shader_store_name = Lit("ShadersStore"); - String c_out_file = F_GetFull(arena, StringF(arena, "%F_gen_c.c", FmtString(cmdline.leaf_layer_name))); - String gpu_out_file = F_GetFull(arena, StringF(arena, "%F_gen_gpu.hlsl", FmtString(cmdline.leaf_layer_name))); + String c_out_file = F_GetFull(perm, StringF(perm, "%F_gen_c.c", FmtString(cmdline.leaf_layer_name))); + String gpu_out_file = F_GetFull(perm, StringF(perm, "%F_gen_gpu.hlsl", FmtString(cmdline.leaf_layer_name))); ////////////////////////////// //- Generate final C file @@ -1093,8 +406,10 @@ void BuildEntryPoint(WaveLaneCtx *lane, void *udata) M_ErrorList errors; }; CGenData cgen = ZI; + + if (lane->idx == 0 && !ret) { - String c_out_file = F_GetFull(arena, StringF(arena, "%F_gen_c.c", FmtString(cmdline.leaf_layer_name))); + String c_out_file = F_GetFull(perm, StringF(perm, "%F_gen_c.c", FmtString(cmdline.leaf_layer_name))); StringList c_store_lines = ZI; StringList c_shader_lines = ZI; StringList c_include_lines = ZI; @@ -1117,22 +432,22 @@ void BuildEntryPoint(WaveLaneCtx *lane, void *udata) String token_file = arg1_tok->file->name; String token_parent_dir = F_GetParentDir(token_file); String arg_dir = arg1_tok->s; - String full = F_GetFullCrossPlatform(arena, StringF(arena, "%F/%F", FmtString(token_parent_dir), FmtString(arg_dir))); + String full = F_GetFullCrossPlatform(perm, StringF(perm, "%F/%F", FmtString(token_parent_dir), FmtString(arg_dir))); if (F_IsDir(full)) { - u64 hash = HashFnv64(Fnv64Basis, StringF(arena, "%F/", FmtString(store_name))); - String line = StringF(arena, "ResourceStore %F = { 0x%F };", FmtString(store_name), FmtHex(hash)); - PushStringToList(arena, &c_store_lines, line); + u64 hash = HashFnv64(Fnv64Basis, StringF(perm, "%F/", FmtString(store_name))); + String line = StringF(perm, "ResourceStore %F = { 0x%F };", FmtString(store_name), FmtHex(hash)); + PushStringToList(perm, &c_store_lines, line); } else { - String err = StringF(arena, "Directory '%F' not found", FmtString(full)); - M_PushError(arena, &cgen.errors, arg1_tok, err); + String err = StringF(perm, "Directory '%F' not found", FmtString(full)); + M_PushError(perm, &cgen.errors, arg1_tok, err); } } else { - M_PushError(arena, &cgen.errors, entry_tok, Lit("Expected resource store & directory name")); + M_PushError(perm, &cgen.errors, entry_tok, Lit("Expected resource store & directory name")); } } break; case M_EntryKind_VertexShader: @@ -1146,13 +461,13 @@ void BuildEntryPoint(WaveLaneCtx *lane, void *udata) : kind == M_EntryKind_ComputeShader ? Lit("ComputeShader") : Lit(""); String shader_name = arg0_tok->s; - u64 hash = HashFnv64(Fnv64Basis, StringF(arena, "%F/%F", FmtString(shader_store_name), FmtString(shader_name))); - String line = StringF(arena, "%F %F = { 0x%F };", FmtString(shader_type), FmtString(shader_name), FmtHex(hash)); - PushStringToList(arena, &c_shader_lines, line); + u64 hash = HashFnv64(Fnv64Basis, StringF(perm, "%F/%F", FmtString(shader_store_name), FmtString(shader_name))); + String line = StringF(perm, "%F %F = { 0x%F };", FmtString(shader_type), FmtString(shader_name), FmtHex(hash)); + PushStringToList(perm, &c_shader_lines, line); } else { - M_PushError(arena, &cgen.errors, entry_tok, Lit("Expected shader name")); + M_PushError(perm, &cgen.errors, entry_tok, Lit("Expected shader name")); } } break; case M_EntryKind_IncludeC: @@ -1162,21 +477,21 @@ void BuildEntryPoint(WaveLaneCtx *lane, void *udata) String token_file = arg0_tok->file->name; String token_parent_dir = F_GetParentDir(token_file); String arg_file = arg0_tok->s; - String full = F_GetFull(arena, StringF(arena, "%F/%F", FmtString(token_parent_dir), FmtString(arg_file))); + String full = F_GetFull(perm, StringF(perm, "%F/%F", FmtString(token_parent_dir), FmtString(arg_file))); if (F_IsFile(full)) { - String line = StringF(arena, "#include \"%F\"", FmtString(full)); - PushStringToList(arena, &c_include_lines, line); + String line = StringF(perm, "#include \"%F\"", FmtString(full)); + PushStringToList(perm, &c_include_lines, line); } else { - String err = StringF(arena, "File '%F' not found", FmtString(full)); - M_PushError(arena, &cgen.errors, arg0_tok, err); + String err = StringF(perm, "File '%F' not found", FmtString(full)); + M_PushError(perm, &cgen.errors, arg0_tok, err); } } else { - M_PushError(arena, &cgen.errors, entry_tok, Lit("Expected file name")); + M_PushError(perm, &cgen.errors, entry_tok, Lit("Expected file name")); } } break; case M_EntryKind_Startup: @@ -1184,12 +499,12 @@ void BuildEntryPoint(WaveLaneCtx *lane, void *udata) if (arg0_tok->valid) { String startup = arg0_tok->s; - String line = StringF(arena, " %F();", FmtString(startup)); - PushStringToList(arena, &c_startup_lines, line); + String line = StringF(perm, " %F();", FmtString(startup)); + PushStringToList(perm, &c_startup_lines, line); } else { - M_PushError(arena, &cgen.errors, entry_tok, Lit("Expected startup function name")); + M_PushError(perm, &cgen.errors, entry_tok, Lit("Expected startup function name")); } } break; } @@ -1198,62 +513,64 @@ void BuildEntryPoint(WaveLaneCtx *lane, void *udata) if (cgen.errors.count == 0) { StringList c_out_lines = ZI; - PushStringToList(arena, &c_out_lines, Lit("// Auto generated file")); + PushStringToList(perm, &c_out_lines, Lit("// Auto generated file")); /* Include base layer */ { - String base_inc_path = F_GetFull(arena, Lit("../src/base/base_inc.h")); - PushStringToList(arena, &c_out_lines, Lit("")); - PushStringToList(arena, &c_out_lines, Lit("//- Base layer includes")); - PushStringToList(arena, &c_out_lines, StringF(arena, "#include \"%F\"", FmtString(base_inc_path))); + String base_inc_path = F_GetFull(perm, Lit("../src/base/base_inc.h")); + PushStringToList(perm, &c_out_lines, Lit("")); + PushStringToList(perm, &c_out_lines, Lit("//- Base layer includes")); + PushStringToList(perm, &c_out_lines, StringF(perm, "#include \"%F\"", FmtString(base_inc_path))); } /* Define resource stores */ if (c_store_lines.count > 0) { - PushStringToList(arena, &c_out_lines, Lit("")); - PushStringToList(arena, &c_out_lines, Lit("//- Resource stores")); + PushStringToList(perm, &c_out_lines, Lit("")); + PushStringToList(perm, &c_out_lines, Lit("//- Resource stores")); for (StringListNode *n = c_store_lines.first; n; n = n->next) { - PushStringToList(arena, &c_out_lines, n->s); + PushStringToList(perm, &c_out_lines, n->s); } } /* Define shaders */ if (c_shader_lines.count > 0) { - PushStringToList(arena, &c_out_lines, Lit("")); - PushStringToList(arena, &c_out_lines, Lit("//- Shaders")); + PushStringToList(perm, &c_out_lines, Lit("")); + PushStringToList(perm, &c_out_lines, Lit("//- Shaders")); for (StringListNode *n = c_shader_lines.first; n; n = n->next) { - PushStringToList(arena, &c_out_lines, n->s); + PushStringToList(perm, &c_out_lines, n->s); } } /* Include dependency layers */ if (c_include_lines.count > 0) { - PushStringToList(arena, &c_out_lines, Lit("")); - PushStringToList(arena, &c_out_lines, Lit("//- Dependency graph includes")); + PushStringToList(perm, &c_out_lines, Lit("")); + PushStringToList(perm, &c_out_lines, Lit("//- Dependency graph includes")); for (StringListNode *n = c_include_lines.first; n; n = n->next) { - PushStringToList(arena, &c_out_lines, n->s); + PushStringToList(perm, &c_out_lines, n->s); } } /* Define StartupLayers */ { - PushStringToList(arena, &c_out_lines, Lit("")); - PushStringToList(arena, &c_out_lines, Lit("//- Startup")); - PushStringToList(arena, &c_out_lines, Lit("void StartupLayers(void)")); - PushStringToList(arena, &c_out_lines, Lit("{")); + PushStringToList(perm, &c_out_lines, Lit("")); + PushStringToList(perm, &c_out_lines, Lit("//- Startup")); + PushStringToList(perm, &c_out_lines, Lit("void StartupLayers(void)")); + PushStringToList(perm, &c_out_lines, Lit("{")); for (StringListNode *n = c_startup_lines.first; n; n = n->next) { - PushStringToList(arena, &c_out_lines, n->s); + PushStringToList(perm, &c_out_lines, n->s); } - PushStringToList(arena, &c_out_lines, Lit("}")); + PushStringToList(perm, &c_out_lines, Lit("}")); } /* Write to file */ - PushStringToList(arena, &c_out_lines, Lit("")); - String c_out = StringFromList(arena, c_out_lines, Lit("\n")); + PushStringToList(perm, &c_out_lines, Lit("")); + String c_out = StringFromList(perm, c_out_lines, Lit("\n")); F_ClearWrite(c_out_file, c_out); } } + WaveSyncBroadcast(lane, 0, &cgen); + if (!ret) ret = cgen.errors.count > 0; ////////////////////////////// //- Generate final HLSL file @@ -1268,13 +585,15 @@ void BuildEntryPoint(WaveLaneCtx *lane, void *udata) u64 shader_entries_count; }; GpuGenData gpugen = ZI; + + if (lane->idx == 0 && !ret) { /* Clear shader store */ OS_Mkdir(shader_store_name); { /* Remove all old shaders */ StringList files = ZI; - F_FilesFromDir(arena, &files, shader_store_name, F_IterFlag_None); + F_FilesFromDir(perm, &files, shader_store_name, F_IterFlag_None); for (StringListNode *n = files.first; n; n = n->next) { String file = n->s; @@ -1311,21 +630,21 @@ void BuildEntryPoint(WaveLaneCtx *lane, void *udata) String token_file = arg0_tok->file->name; String token_parent_dir = F_GetParentDir(token_file); String arg_file = arg0_tok->s; - String full = F_GetFull(arena, StringF(arena, "%F/%F", FmtString(token_parent_dir), FmtString(arg_file))); + String full = F_GetFull(perm, StringF(perm, "%F/%F", FmtString(token_parent_dir), FmtString(arg_file))); if (F_IsFile(full)) { - String line = StringF(arena, "#include \"%F\"", FmtString(full)); - PushStringToList(arena, &gpu_include_lines, line); + String line = StringF(perm, "#include \"%F\"", FmtString(full)); + PushStringToList(perm, &gpu_include_lines, line); } else { - String err = StringF(arena, "File '%F' not found", FmtString(full)); - M_PushError(arena, &gpugen.errors, arg0_tok, err); + String err = StringF(perm, "File '%F' not found", FmtString(full)); + M_PushError(perm, &gpugen.errors, arg0_tok, err); } } else { - M_PushError(arena, &gpugen.errors, entry_tok, Lit("Expected file name")); + M_PushError(perm, &gpugen.errors, entry_tok, Lit("Expected file name")); } } break; case M_EntryKind_VertexShader: @@ -1339,7 +658,7 @@ void BuildEntryPoint(WaveLaneCtx *lane, void *udata) : kind == M_EntryKind_ComputeShader ? ShaderEntryKind_CS : ShaderEntryKind_VS; String shader_name = arg0_tok->s; - ShaderEntry *e = PushStruct(arena, ShaderEntry); + ShaderEntry *e = PushStruct(perm, ShaderEntry); e->kind = shader_kind; e->name = shader_name; SllQueuePush(gpugen.first_shader_entry, gpugen.last_shader_entry, e); @@ -1347,7 +666,7 @@ void BuildEntryPoint(WaveLaneCtx *lane, void *udata) } else { - M_PushError(arena, &gpugen.errors, entry_tok, Lit("Expected shader name")); + M_PushError(perm, &gpugen.errors, entry_tok, Lit("Expected shader name")); } } break; } @@ -1356,103 +675,113 @@ void BuildEntryPoint(WaveLaneCtx *lane, void *udata) if (gpugen.errors.count == 0) { StringList gpu_out_lines = ZI; - PushStringToList(arena, &gpu_out_lines, Lit("// Auto generated file")); + PushStringToList(perm, &gpu_out_lines, Lit("// Auto generated file")); /* Include base layer */ { - String base_inc_path = F_GetFull(arena, Lit("../src/base/base_inc.h")); - PushStringToList(arena, &gpu_out_lines, Lit("")); - PushStringToList(arena, &gpu_out_lines, Lit("//- Base layer includes")); - PushStringToList(arena, &gpu_out_lines, StringF(arena, "#include \"%F\"", FmtString(base_inc_path))); + String base_inc_path = F_GetFull(perm, Lit("../src/base/base_inc.h")); + PushStringToList(perm, &gpu_out_lines, Lit("")); + PushStringToList(perm, &gpu_out_lines, Lit("//- Base layer includes")); + PushStringToList(perm, &gpu_out_lines, StringF(perm, "#include \"%F\"", FmtString(base_inc_path))); } /* Include dependency layers */ if (gpu_out_lines.count > 0) { - PushStringToList(arena, &gpu_out_lines, Lit("")); - PushStringToList(arena, &gpu_out_lines, Lit("//- Dependency graph includes")); + PushStringToList(perm, &gpu_out_lines, Lit("")); + PushStringToList(perm, &gpu_out_lines, Lit("//- Dependency graph includes")); for (StringListNode *n = gpu_include_lines.first; n; n = n->next) { - PushStringToList(arena, &gpu_out_lines, n->s); + PushStringToList(perm, &gpu_out_lines, n->s); } } /* Write to file */ - PushStringToList(arena, &gpu_out_lines, Lit("")); - String c_out = StringFromList(arena, gpu_out_lines, Lit("\n")); + PushStringToList(perm, &gpu_out_lines, Lit("")); + String c_out = StringFromList(perm, gpu_out_lines, Lit("\n")); F_ClearWrite(gpu_out_file, c_out); } } } + WaveSyncBroadcast(lane, 0, &gpugen); + if (!ret) ret = gpugen.errors.count > 0; ////////////////////////////// //- Compile C Struct(CComp) { - M_ErrorList errors; String obj_file; - StringList output; + String output; i32 return_code; }; CComp ccomp = ZI; + + if (lane->idx == 0 && !ret) { - ccomp.obj_file = StringF(arena, "%F_gen_c.obj", FmtString(cmdline.leaf_layer_name)); - if (ccomp.errors.count == 0) - { - String cmd = StringF(arena, - "cmd /c cl.exe /c %F -Fo:%F %F %F %F %F", - FmtString(c_out_file), - FmtString(ccomp.obj_file), - FmtString(StringFromList(arena, cp.flags_msvc, Lit(" "))), - FmtString(StringFromList(arena, cp.compiler_only_flags_msvc, Lit(" "))), - FmtString(StringFromList(arena, cp.warnings_msvc, Lit(" "))), - FmtString(StringFromList(arena, cp.defs, Lit(" ")))); - OS_CommandResult cmd_result = OS_RunCommand(arena, cmd); - String cmd_output = TrimWhitespace(cmd_result.output); - if (cmd_output.len > 0) - { - PushStringToList(arena, &ccomp.output, cmd_output); - } - ccomp.return_code = cmd_result.code; - } + ccomp.obj_file = StringF(perm, "%F_gen_c.obj", FmtString(cmdline.leaf_layer_name)); + String cmd = StringF(perm, + "cmd /c cl.exe /c %F -Fo:%F %F %F %F %F", + FmtString(c_out_file), + FmtString(ccomp.obj_file), + FmtString(StringFromList(perm, cp.flags_msvc, Lit(" "))), + FmtString(StringFromList(perm, cp.compiler_only_flags_msvc, Lit(" "))), + FmtString(StringFromList(perm, cp.warnings_msvc, Lit(" "))), + FmtString(StringFromList(perm, cp.defs, Lit(" ")))); + OS_CommandResult cmd_result = OS_RunCommand(perm, cmd); + String cmd_output = TrimWhitespace(cmd_result.output); + ccomp.output = cmd_output; + ccomp.return_code = cmd_result.code; } + WaveSyncBroadcast(lane, 0, &ccomp); + if (!ret) ret = ccomp.return_code; ////////////////////////////// //- Compile shaders Struct(GpuComp) { - StringList output; + String output; + i32 return_code; }; - GpuComp gpucomp = ZI; - for (ShaderEntry *e = gpugen.first_shader_entry; e; e = e->next) + u32 gpucomps_count = gpugen.shader_entries_count; + GpuComp *gpucomps = PushStructs(perm, GpuComp, gpucomps_count); + + if (lane->idx == 0 && !ret) { - String out_file = StringF(arena, "%F/%F", FmtString(shader_store_name), FmtString(e->name)); - String target = e->kind == ShaderEntryKind_VS ? Lit("vs_6_6") - : e->kind == ShaderEntryKind_PS ? Lit("ps_6_6") - : e->kind == ShaderEntryKind_CS ? Lit("cs_6_6") - : Lit("vs_6_6"); - String compile_cmd = StringF(arena, - "cmd /c dxc.exe -T %F -E %F -Fo %F %F %F %F", - FmtString(target), - FmtString(e->name), - FmtString(out_file), - FmtString(gpu_out_file), - FmtString(StringFromList(arena, cp.defs, Lit(" "))), - FmtString(StringFromList(arena, cp.flags_dxc, Lit(" ")))); - - OS_CommandResult cmd_result = OS_RunCommand(arena, compile_cmd); - - if (cmd_result.code == 0) + u32 gpucomp_idx = 0; + for (ShaderEntry *e = gpugen.first_shader_entry; e; e = e->next) { - // f64 elapsed = SecondsFromNs(cmd_result.elapsed_ns); - f64 elapsed = 0; - PushStringToList(arena, &gpucomp.output, StringF(arena, "%F:%F %Fs", FmtString(F_GetFileName(gpu_out_file)), FmtString(e->name), FmtFloat(elapsed))); - if (cmd_result.output.len > 0) + GpuComp *gpucomp = &gpucomps[gpucomp_idx]; + String out_file = StringF(perm, "%F/%F", FmtString(shader_store_name), FmtString(e->name)); + String target = e->kind == ShaderEntryKind_VS ? Lit("vs_6_6") + : e->kind == ShaderEntryKind_PS ? Lit("ps_6_6") + : e->kind == ShaderEntryKind_CS ? Lit("cs_6_6") + : Lit("vs_6_6"); + String compile_cmd = StringF(perm, + "cmd /c dxc.exe -T %F -E %F -Fo %F %F %F %F", + FmtString(target), + FmtString(e->name), + FmtString(out_file), + FmtString(gpu_out_file), + FmtString(StringFromList(perm, cp.defs, Lit(" "))), + FmtString(StringFromList(perm, cp.flags_dxc, Lit(" ")))); + + OS_CommandResult cmd_result = OS_RunCommand(perm, compile_cmd); + + if (cmd_result.code == 0) { - PushStringToList(arena, &gpucomp.output, cmd_result.output); + // f64 elapsed = SecondsFromNs(cmd_result.elapsed_ns); + f64 elapsed = 0; + // PushStringToList(perm, &gpucomp.output, StringF(perm, "%F:%F %Fs", FmtString(F_GetFileName(gpu_out_file)), FmtString(e->name), FmtFloat(elapsed))); + gpucomp->output = cmd_result.output; + gpucomp->return_code = cmd_result.code; } - cmd_result.code = cmd_result.code; + ++gpucomp_idx; } } + WaveSyncBroadcast(lane, 0, &gpucomps); + for (u32 i = 0; i < gpucomps_count; ++i) + { + if (!ret) ret = gpucomps[i].return_code; + } ////////////////////////////// //- Gather resource archive info @@ -1466,6 +795,8 @@ void BuildEntryPoint(WaveLaneCtx *lane, void *udata) u64 arc_entries_count; }; ArcInfoGen arcinfogen = ZI; + + if (lane->idx == 0 && !ret) { /* Gather archives from embedded dirs */ for (M_Entry *entry = flattened.first; entry->valid; entry = entry->next) @@ -1485,183 +816,150 @@ void BuildEntryPoint(WaveLaneCtx *lane, void *udata) String token_file = arg1_tok->file->name; String token_parent_dir = F_GetParentDir(token_file); String arg_dir = arg1_tok->s; - String full = F_GetFullCrossPlatform(arena, StringF(arena, "%F/%F", FmtString(token_parent_dir), FmtString(arg_dir))); + String full = F_GetFullCrossPlatform(perm, StringF(perm, "%F/%F", FmtString(token_parent_dir), FmtString(arg_dir))); if (F_IsDir(full)) { - ArcInfoEntry *arc = PushStruct(arena, ArcInfoEntry); + ArcInfoEntry *arc = PushStruct(perm, ArcInfoEntry); arc->store_name = store_name; arc->dir_path = full; - arc->out_path = StringF(arena, "%F.arc", FmtString(store_name)); + arc->out_path = StringF(perm, "%F.arc", FmtString(store_name)); SllQueuePush(arcinfogen.first_arc_entry, arcinfogen.last_arc_entry, arc); ++arcinfogen.arc_entries_count; } else { - String err = StringF(arena, "Directory '%F' not found", FmtString(full)); - M_PushError(arena, &arcinfogen.errors, arg1_tok, err); + String err = StringF(perm, "Directory '%F' not found", FmtString(full)); + M_PushError(perm, &arcinfogen.errors, arg1_tok, err); } } else { - M_PushError(arena, &arcinfogen.errors, entry_tok, Lit("Expected resource store & directory name")); + M_PushError(perm, &arcinfogen.errors, entry_tok, Lit("Expected resource store & directory name")); } } break; } } /* Gather shader archive */ { - ArcInfoEntry *arc = PushStruct(arena, ArcInfoEntry); + ArcInfoEntry *arc = PushStruct(perm, ArcInfoEntry); arc->store_name = shader_store_name; - arc->dir_path = F_GetFullCrossPlatform(arena, shader_store_name); - arc->out_path = StringF(arena, "%F.arc", FmtString(shader_store_name)); + arc->dir_path = F_GetFullCrossPlatform(perm, shader_store_name); + arc->out_path = StringF(perm, "%F.arc", FmtString(shader_store_name)); SllQueuePush(arcinfogen.first_arc_entry, arcinfogen.last_arc_entry, arc); ++arcinfogen.arc_entries_count; } } + WaveSyncBroadcast(lane, 0, &arcinfogen); + if (!ret) ret = arcinfogen.errors.count > 0; ////////////////////////////// //- Generate resource archives - for (ArcInfoEntry *entry = arcinfogen.first_arc_entry; entry; entry = entry->next) + if (lane->idx == 0 && !ret) { - String dir_path = entry->dir_path; - String store_name = entry->store_name; - String arc_path = entry->out_path; - - Struct(EntryNode) + for (ArcInfoEntry *entry = arcinfogen.first_arc_entry; entry; entry = entry->next) { - EntryNode *next; - String entry_name; - String file_name; - }; + String dir_path = entry->dir_path; + String store_name = entry->store_name; + String arc_path = entry->out_path; - EntryNode *first_entry = 0; - EntryNode *last_entry = 0; - u64 entries_count = 0; - - StringList files = ZI; - F_FilesFromDir(arena, &files, dir_path, F_IterFlag_Recurse); - for (StringListNode *file_node = files.first; file_node; file_node = file_node->next) - { - String file_name = file_node->s; - if (F_IsFile(file_name)) + Struct(EntryNode) { - String entry_name = file_name; - if (entry_name.len > (dir_path.len + 1)) + EntryNode *next; + String entry_name; + String file_name; + }; + + EntryNode *first_entry = 0; + EntryNode *last_entry = 0; + u64 entries_count = 0; + + StringList files = ZI; + F_FilesFromDir(perm, &files, dir_path, F_IterFlag_Recurse); + for (StringListNode *file_node = files.first; file_node; file_node = file_node->next) + { + String file_name = file_node->s; + if (F_IsFile(file_name)) { - entry_name.len -= dir_path.len + 1; - entry_name.text += dir_path.len + 1; - } - entry_name = StringF(arena, "%F/%F", FmtString(store_name), FmtString(entry_name)); - for (u64 i = 0; i < entry_name.len; ++i) - { - if (entry_name.text[i] == '\\') + String entry_name = file_name; + if (entry_name.len > (dir_path.len + 1)) { - entry_name.text[i] = '/'; + entry_name.len -= dir_path.len + 1; + entry_name.text += dir_path.len + 1; } + entry_name = StringF(perm, "%F/%F", FmtString(store_name), FmtString(entry_name)); + for (u64 i = 0; i < entry_name.len; ++i) + { + if (entry_name.text[i] == '\\') + { + entry_name.text[i] = '/'; + } + } + + EntryNode *en = PushStruct(perm, EntryNode); + en->entry_name = entry_name; + en->file_name = file_name; + SllQueuePush(first_entry, last_entry, en); + ++entries_count; + } + } + + String arc_contents = ZI; + { + BB_Buff bb = BB_AcquireBuff(Gibi(2)); + BB_Writer bw = BB_WriterFromBuff(&bb); + + /* Write magic */ + BB_WriteUBits(&bw, ResourceEmbeddedMagic, 64); + + /* Write header */ + BB_WriteUBits(&bw, entries_count, 64); + + /* Reserve entries space */ + u64 entry_size = 8 /* Name start */ + + 8 /* Name end */ + + 8 /* Data start */ + + 8; /* Data end */ + u8 *entries_start = BB_GetWrittenRaw(&bw) + BB_GetNumBytesWritten(&bw); + u64 entries_size = entry_size * entries_count; + String entries_str = STRING(entries_size, entries_start); + BB_WriteSeekBytes(&bw, entries_size); + BB_Buff entries_bb = BB_BuffFromString(entries_str); + BB_Writer entries_bw = BB_WriterFromBuff(&entries_bb); + + /* Write entries */ + for (EntryNode *en = first_entry; en; en = en->next) + { + /* TODO: Copy file data directly into archive file */ + String file_data = F_DataFromFile(perm, en->file_name); + + /* Write name */ + BB_WriteAlignBytes(&bw, 64); + u64 name_start = BB_GetNumBytesWritten(&bw) + 1; + BB_WriteString(&bw, en->entry_name); + u64 name_len = BB_GetNumBytesWritten(&bw) - name_start; + + /* Write data */ + BB_WriteAlignBytes(&bw, 64); + /* FIXME: Why no +1 here? */ + u64 data_start = BB_GetNumBytesWritten(&bw); + BB_WriteBytes(&bw, file_data); + u64 data_len = BB_GetNumBytesWritten(&bw) - data_start; + + /* Write entry */ + BB_WriteUBits(&entries_bw, name_start, 64); + BB_WriteUBits(&entries_bw, name_len, 64); + BB_WriteUBits(&entries_bw, data_start, 64); + BB_WriteUBits(&entries_bw, data_len, 64); } - EntryNode *en = PushStruct(arena, EntryNode); - en->entry_name = entry_name; - en->file_name = file_name; - SllQueuePush(first_entry, last_entry, en); - ++entries_count; - } - } - - String arc_contents = ZI; - { - BB_Buff bb = BB_AcquireBuff(Gibi(2)); - BB_Writer bw = BB_WriterFromBuff(&bb); - - /* Write magic */ - BB_WriteUBits(&bw, ResourceEmbeddedMagic, 64); - - /* Write header */ - BB_WriteUBits(&bw, entries_count, 64); - - /* Reserve entries space */ - u64 entry_size = 8 /* Name start */ - + 8 /* Name end */ - + 8 /* Data start */ - + 8; /* Data end */ - u8 *entries_start = BB_GetWrittenRaw(&bw) + BB_GetNumBytesWritten(&bw); - u64 entries_size = entry_size * entries_count; - String entries_str = STRING(entries_size, entries_start); - BB_WriteSeekBytes(&bw, entries_size); - BB_Buff entries_bb = BB_BuffFromString(entries_str); - BB_Writer entries_bw = BB_WriterFromBuff(&entries_bb); - - /* Write entries */ - for (EntryNode *en = first_entry; en; en = en->next) - { - /* TODO: Copy file data directly into archive file */ - String file_data = F_DataFromFile(arena, en->file_name); - - /* Write name */ - BB_WriteAlignBytes(&bw, 64); - u64 name_start = BB_GetNumBytesWritten(&bw) + 1; - BB_WriteString(&bw, en->entry_name); - u64 name_len = BB_GetNumBytesWritten(&bw) - name_start; - - /* Write data */ - BB_WriteAlignBytes(&bw, 64); - /* FIXME: Why no +1 here? */ - u64 data_start = BB_GetNumBytesWritten(&bw); - BB_WriteBytes(&bw, file_data); - u64 data_len = BB_GetNumBytesWritten(&bw) - data_start; - - /* Write entry */ - BB_WriteUBits(&entries_bw, name_start, 64); - BB_WriteUBits(&entries_bw, name_len, 64); - BB_WriteUBits(&entries_bw, data_start, 64); - BB_WriteUBits(&entries_bw, data_len, 64); + arc_contents.len = BB_GetNumBytesWritten(&bw); + arc_contents.text = BB_GetWrittenRaw(&bw); } - arc_contents.len = BB_GetNumBytesWritten(&bw); - arc_contents.text = BB_GetWrittenRaw(&bw); + /* Write arc file */ + F_ClearWrite(arc_path, arc_contents); } - - /* Write arc file */ - F_ClearWrite(arc_path, arc_contents); - // PushStringToList(arena, output, StringF(arena, "%F (%F mb)", FmtString(F_GetFileName(arc_path)), FmtFloatP((f32)arc_contents.len / 1024 / 1024, 3))); - - // if (IsPlatformWindows) - // { - // //- Generate rc file - // String rc_out_file = StringF(arena, "%F.rc", FmtString(store_name)); - // { - // RandState rs = ZI; - // StringList rc_out_lines = ZI; - // String arc_file_cp = F_GetFullCrossPlatform(arena, arc_path); - // String line = StringF(arena, "%F_%F RCDATA \"%F\"", FmtString(Lit(Stringize(W32_EmbeddedDataPrefix))), FmtHex(RandU64FromState(&rs)), FmtString(arc_file_cp)); - // PushStringToList(arena, &rc_out_lines, line); - // /* Write to file */ - // String rc_out = StringFromList(arena, rc_out_lines, Lit("\n")); - // F_ClearWrite(rc_out_file, rc_out); - // } - - // //- Compile RC - // String res_out_file = StringF(arena, "%F.res", FmtString(store_name)); - // PushStringToList(arena, &result->obj_files, res_out_file); - // if (errors->count == 0) - // { - // String cmd = StringF(arena, "cmd /c rc.exe -nologo -fo %F %F", FmtString(res_out_file), FmtString(F_GetFull(arena, rc_out_file))); - // OS_CommandResult cmd_result = OS_RunCommand(arena, cmd); - // String cmd_output = TrimWhitespace(cmd_result.output); - // PushStringToList(arena, output, rc_out_file); - // if (cmd_output.len > 0) - // { - // PushStringToList(arena, output, cmd_output); - // } - // result->return_code = cmd_result.code; - // } - // } - // else - // { - // /* TODO: Compile object files using .incbin on non-windows platforms */ - // Panic(Lit("Non-windows embedded format not implemented")); - // } } ////////////////////////////// @@ -1670,11 +968,13 @@ void BuildEntryPoint(WaveLaneCtx *lane, void *udata) Struct(ResComp) { String obj_file; - StringList output; + String output; i32 return_code; }; - ResComp *rescomps = PushStructs(arena, ResComp, arcinfogen.arc_entries_count); + u32 rescomps_count = arcinfogen.arc_entries_count; + ResComp *rescomps = PushStructs(perm, ResComp, rescomps_count); + if (lane->idx == 0 && !ret) { if (IsPlatformWindows) { @@ -1686,29 +986,25 @@ void BuildEntryPoint(WaveLaneCtx *lane, void *udata) String arc_path = entry->out_path; /* Generate RC file */ - String rc_out_file = StringF(arena, "%F.rc", FmtString(entry->store_name)); + String rc_out_file = StringF(perm, "%F.rc", FmtString(entry->store_name)); { RandState rs = ZI; StringList rc_out_lines = ZI; - String arc_file_cp = F_GetFullCrossPlatform(arena, arc_path); - String line = StringF(arena, "%F_%F RCDATA \"%F\"", FmtString(Lit(Stringize(W32_EmbeddedDataPrefix))), FmtHex(RandU64FromState(&rs)), FmtString(arc_file_cp)); - PushStringToList(arena, &rc_out_lines, line); + String arc_file_cp = F_GetFullCrossPlatform(perm, arc_path); + String line = StringF(perm, "%F_%F RCDATA \"%F\"", FmtString(Lit(Stringize(W32_EmbeddedDataPrefix))), FmtHex(RandU64FromState(&rs)), FmtString(arc_file_cp)); + PushStringToList(perm, &rc_out_lines, line); /* Write to file */ - String rc_out = StringFromList(arena, rc_out_lines, Lit("\n")); + String rc_out = StringFromList(perm, rc_out_lines, Lit("\n")); F_ClearWrite(rc_out_file, rc_out); } /* Compile RC file */ - rescomp->obj_file = StringF(arena, "%F.res", FmtString(entry->store_name)); + rescomp->obj_file = StringF(perm, "%F.res", FmtString(entry->store_name)); { - String cmd = StringF(arena, "cmd /c rc.exe -nologo -fo %F %F", FmtString(rescomp->obj_file), FmtString(F_GetFull(arena, rc_out_file))); - OS_CommandResult cmd_result = OS_RunCommand(arena, cmd); + String cmd = StringF(perm, "cmd /c rc.exe -nologo -fo %F %F", FmtString(rescomp->obj_file), FmtString(F_GetFull(perm, rc_out_file))); + OS_CommandResult cmd_result = OS_RunCommand(perm, cmd); String cmd_output = TrimWhitespace(cmd_result.output); - PushStringToList(arena, &rescomp->output, rc_out_file); - if (cmd_output.len > 0) - { - PushStringToList(arena, &rescomp->output, cmd_output); - } + rescomp->output = cmd_output; rescomp->return_code = cmd_result.code; } @@ -1721,12 +1017,25 @@ void BuildEntryPoint(WaveLaneCtx *lane, void *udata) Panic(Lit("Non-windows embedded format not implemented")); } } + WaveSyncBroadcast(lane, 0, &rescomps); + for (u32 i = 0; i < rescomps_count; ++i) + { + if (!ret) ret = rescomps[i].return_code; + } ////////////////////////////// //- Link + Struct(Link) { - String exe_file = StringF(arena, "%F.exe", FmtString(cmdline.leaf_layer_name)); + String output; + i32 return_code; + }; + Link link = ZI; + + if (lane->idx == 0 && !ret) + { + String exe_file = StringF(perm, "%F.exe", FmtString(cmdline.leaf_layer_name)); { /* Wait for exe to become writable (wait for program to close) */ f32 timeout = 1.0; @@ -1735,187 +1044,78 @@ void BuildEntryPoint(WaveLaneCtx *lane, void *udata) } i64 link_elapsed_ns = 0; - if (ret == 0) + i64 start_ns = TimeNs(); + + String obj_files_str = ZI; { - i64 start_ns = TimeNs(); - - String obj_files_str = ZI; + StringList obj_files = ZI; + PushStringToList(perm, &obj_files, ccomp.obj_file); + for (u64 rescomp_idx = 0; rescomp_idx < rescomps_count; ++rescomp_idx) { - StringList obj_files = ZI; - PushStringToList(arena, &obj_files, ccomp.obj_file); - for (u64 rescomp_idx = 0; rescomp_idx < arcinfogen.arc_entries_count; ++rescomp_idx) - { - ResComp *rescomp = &rescomps[rescomp_idx]; - PushStringToList(arena, &obj_files, rescomp->obj_file); - } - obj_files_str = StringFromList(arena, obj_files, Lit(" ")); + ResComp *rescomp = &rescomps[rescomp_idx]; + PushStringToList(perm, &obj_files, rescomp->obj_file); } - - String cmd = StringF(arena, - "cmd /c link.exe %F /OUT:%F %F %F", - FmtString(obj_files_str), - FmtString(exe_file), - FmtString(StringFromList(arena, cp.flags_msvc, Lit(" "))), - FmtString(StringFromList(arena, cp.linker_only_flags_msvc, Lit(" ")))); - OS_CommandResult result = OS_RunCommand(arena, cmd); - String output = TrimWhitespace(result.output); - if (output.len > 0) - { - EchoLine(output); - } - ret = result.code; - link_elapsed_ns = TimeNs() - start_ns; + obj_files_str = StringFromList(perm, obj_files, Lit(" ")); } - if (ret == 0) + String cmd = StringF(perm, + "cmd /c link.exe %F /OUT:%F %F %F", + FmtString(obj_files_str), + FmtString(exe_file), + FmtString(StringFromList(perm, cp.flags_msvc, Lit(" "))), + FmtString(StringFromList(perm, cp.linker_only_flags_msvc, Lit(" ")))); + OS_CommandResult result = OS_RunCommand(perm, cmd); + link.output = TrimWhitespace(result.output); + link.return_code = result.code; + link_elapsed_ns = TimeNs() - start_ns; + // EchoLine(StringF(perm, ">>>>> Linked in %Fs", FmtFloat(SecondsFromNs(link_elapsed_ns)))); + } + WaveSyncBroadcast(lane, 0, &link); + if (!ret) ret = link.return_code; + + ////////////////////////////// + //- Process output & errors + + if (lane->idx == 0) + { + String gpucomp_output = ZI; { - EchoLine(StringF(arena, ">>>>> Linked in %Fs", FmtFloat(SecondsFromNs(link_elapsed_ns)))); + StringList gpucomp_outputs = ZI; + for (u32 gpucomp_idx = 0; gpucomp_idx < gpucomps_count; ++gpucomp_idx) + { + GpuComp *gpucomp = &gpucomps[gpucomp_idx]; + PushStringToList(perm, &gpucomp_outputs, gpucomp->output); + } + gpucomp_output = StringFromList(perm, gpucomp_outputs, Lit("\n")); } + String rescomp_output = ZI; + { + StringList rescomp_outputs = ZI; + for (u32 rescomp_idx = 0; rescomp_idx < rescomps_count; ++rescomp_idx) + { + ResComp *rescomp = &rescomps[rescomp_idx]; + PushStringToList(perm, &rescomp_outputs, rescomp->output); + } + rescomp_output = StringFromList(perm, rescomp_outputs, Lit("\n")); + } + EchoLineOrNothing(StringFromMetaErrors(perm, flattened.errors)); + EchoLineOrNothing(StringFromMetaErrors(perm, cgen.errors)); + EchoLineOrNothing(StringFromMetaErrors(perm, gpugen.errors)); + EchoLineOrNothing(ccomp.output); + EchoLineOrNothing(gpucomp_output); + EchoLineOrNothing(StringFromMetaErrors(perm, arcinfogen.errors)); + EchoLineOrNothing(rescomp_output); + EchoLineOrNothing(link.output); } ////////////////////////////// - //- Compile & link + //- Exit -#if 0 - ret = meta_parse_errors.count > 0; - if (ret == 0) + if (lane->idx == 0) { - //- Compile - StepParams params_array[3] = ZI; - StepResult results_array[3] = ZI; - - StepParams *program_params = ¶ms_array[0]; - StepResult *program_result = &results_array[0]; - program_params->flags |= StepParamsFlag_CompileProgram; - program_params->compiler_params = cp; - program_params->flattened = flattened; - - StepParams *shader_params = ¶ms_array[1]; - StepResult *shader_result = &results_array[1]; - shader_params->flags |= StepParamsFlag_CompileShaders; - shader_params->compiler_params = cp; - shader_params->flattened = flattened; - - StepParams *resource_params = ¶ms_array[2]; - StepResult *resource_result = &results_array[2]; - resource_params->flags |= StepParamsFlag_CompileEmbeddedDirs; - resource_params->compiler_params = cp; - resource_params->flattened = flattened; - - u32 job_count = 0; Fence job_fence = ZI; - job_count += RunJob(Step, .count = countof(params_array), .fence = &job_fence, .sig.params = params_array, .sig.results = results_array); - YieldOnFence(&job_fence, job_count); - - //- Process compile step results - - /* Copy meta errors */ - for (M_Error *e = program_result->meta_errors.first; e; e = e->next) M_PushError(arena, &errors, e->token, e->msg); - for (M_Error *e = shader_result->meta_errors.first; e; e = e->next) M_PushError(arena, &errors, e->token, e->msg); - for (M_Error *e = resource_result->meta_errors.first; e; e = e->next) M_PushError(arena, &errors, e->token, e->msg); - - ret = (ret != 0) ? ret : program_result->return_code; - ret = (ret != 0) ? ret : shader_result->return_code; - ret = (ret != 0) ? ret : resource_result->return_code; - ret = (ret != 0) ? ret : errors.count > 0; - - { - String program_output = StringFromList(arena, program_result->output_lines, Lit("\n")); - String shader_output = StringFromList(arena, shader_result->output_lines, Lit("\n")); - String resource_output = StringFromList(arena, resource_result->output_lines, Lit("\n")); - - EchoLine(StringF(arena, ">>>>> Built C in %Fs", FmtFloat(SecondsFromNs(program_result->elapsed_ns)))); - if (program_output.len > 0) EchoLine(program_output); - - EchoLine(StringF(arena, ">>>>> Built shaders in %Fs", FmtFloat(SecondsFromNs(shader_result->elapsed_ns)))); - if (shader_output.len > 0) EchoLine(shader_output); - - EchoLine(StringF(arena, ">>>>> Built resources in %Fs", FmtFloat(SecondsFromNs(resource_result->elapsed_ns)))); - if (resource_output.len > 0) EchoLine(resource_output); - } - - //- Link - String exe_file = StringF(arena, "%F.exe", FmtString(cmdline.leaf_layer_name)); - { - /* Wait for exe to become writable (wait for program to close) */ - f32 timeout = 1.0; - OS_File file = OS_OpenFile(exe_file, OS_FileFlag_Write, NsFromSeconds(timeout)); - OS_CloseFile(file); - } - - i64 link_elapsed_ns = 0; - if (ret == 0) - { - i64 start_ns = TimeNs(); - String program_obj_files_str = StringFromList(arena, program_result->obj_files, Lit(" ")); - String shader_obj_files_str = StringFromList(arena, shader_result->obj_files, Lit(" ")); - String resource_obj_files_str = StringFromList(arena, resource_result->obj_files, Lit(" ")); - - String cmd = StringF(arena, - "cmd /c link.exe %F %F %F /OUT:%F %F %F", - FmtString(program_obj_files_str), - FmtString(shader_obj_files_str), - FmtString(resource_obj_files_str), - FmtString(exe_file), - FmtString(StringFromList(arena, cp.flags_msvc, Lit(" "))), - FmtString(StringFromList(arena, cp.linker_only_flags_msvc, Lit(" ")))); - OS_CommandResult result = OS_RunCommand(arena, cmd); - String output = TrimWhitespace(result.output); - if (output.len > 0) - { - EchoLine(output); - } - ret = result.code; - link_elapsed_ns = TimeNs() - start_ns; - } - - if (ret == 0) - { - EchoLine(StringF(arena, ">>>>> Linked in %Fs", FmtFloat(SecondsFromNs(link_elapsed_ns)))); - } + EchoLine(StringF(perm, "Runtime: %Fs", FmtFloat(SecondsFromNs(TimeNs())))); + ExitNow(ret); } -#endif - - - ////////////////////////////// - //- Echo meta errors - - for (M_Error *e = meta_parse_errors.first; e; e = e->next) - { - String msg = ZI; - M_Token *token = e->token; - String token_file = token->file->name; - String token_file_data = token->file->data; - if (token_file.len > 0) - { - i64 token_pos = -1; - if (token->s.len > 0 - && token_file_data.len > 0 - && token->s.text > token_file_data.text - && token->s.text < (token_file_data.text + token_file_data.len)) - { - token_pos = token->s.text - token_file_data.text; - } - LineCol line_col = ZI; - if (token_pos >= 0) - { - line_col = LineColFromPos(token_file_data, token_pos); - } - msg = StringF(arena, - "%F:%F:%F: error: %F", - FmtString(token_file), - FmtSint(line_col.line), - FmtSint(line_col.col), - FmtString(e->msg)); - } - else - { - msg = StringF(arena, "error: %F", FmtString(e->msg)); - } - EchoLine(msg); - } - - EchoLine(StringF(arena, "Runtime: %Fs", FmtFloat(SecondsFromNs(TimeNs())))); - ExitNow(ret); } //////////////////////////////////////////////////////////// @@ -1924,8 +1124,7 @@ void BuildEntryPoint(WaveLaneCtx *lane, void *udata) void StartupLayers(void) { OS_Startup(); - CpuTopologyInfo cpu_info = GetCpuTopologyInfo(); - // DispatchWave(cpu_info.num_logical_cores - 1, BuildEntryPoint, 0); - DispatchWave(1, BuildEntryPoint, 0); + i32 meta_lanes_count = cpu_info.num_logical_cores; + DispatchWave(Lit("Meta"), MaxI32(meta_lanes_count, 1), BuildEntryPoint, 0); }