sync singular build data struct during prep

This commit is contained in:
jacob 2025-12-07 04:33:03 -06:00
parent 1532549ffa
commit 905cb50e33
2 changed files with 519 additions and 457 deletions

View File

@ -539,6 +539,12 @@ GPU_D12_Pipeline *GPU_D12_PipelineFromDesc(GPU_D12_PipelineDesc desc)
}
}
if (!ok)
{
/* TOOD: Don't panic */
Panic(error_str);
}
pipeline->pso = pso;
pipeline->error = error_str;
pipeline->ok = ok;

View File

@ -339,11 +339,139 @@ void BuildEntryPoint(WaveLaneCtx *lane, void *udata)
}
//////////////////////////////
//- Parse meta layers
//- Prep
String shader_store_name = Lit("ShadersStore");
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)));
Enum(ShaderEntryKind)
{
ShaderEntryKind_VS,
ShaderEntryKind_PS,
ShaderEntryKind_CS,
};
Struct(ShaderEntry)
{
ShaderEntry *next;
ShaderEntryKind kind;
String name;
};
Struct(ArcInfoEntry)
{
ArcInfoEntry *next;
String dir_path;
String store_name;
String out_path;
};
Struct(GpuComp)
{
String output;
i32 return_code;
};
Struct(ResComp)
{
String obj_file;
String output;
i32 return_code;
};
/*
* ## Phase 1
*
* <Parse layers> <Generate C> <Generate HLSL>
*
* <FULL BARRIER> -------------------------------------------------------------
*
* ## Phase 2
*
* <C compile oscmd> <shader compile oscmds>
* |
* <FULL BARRIER> -------------------------------------------------------------
*
* ## Phase 3
* <shader resource arcs> <embedded resource arcs>
* | |
* <FULL BARRIER> -------------------------------------------------------------
*
* ## Phase 4
* <shader resource oscmd> <embedded resource oscmds>
* <FULL BARRIER> -------------------------------------------------------------
*
* ## Phase 5
*
* <link oscmd>
*/
/* TODO: Dispatch OS Cmds asynchronously rather than synchronously waiting on each lane */
Struct(BuildData)
{
M_Layer flattened;
struct
{
M_ErrorList errors;
} cgen;
struct
{
M_ErrorList errors;
ShaderEntry *first_shader_entry;
ShaderEntry *last_shader_entry;
u64 shader_entries_count;
} gpugen;
struct
{
String obj_file;
String output;
i32 return_code;
} ccomp;
struct
{
GpuComp *array;
u32 count;
} gpucomps;
struct
{
M_ErrorList errors;
ArcInfoEntry *first_arc_entry;
ArcInfoEntry *last_arc_entry;
u64 arc_entries_count;
} arcinfogen;
struct
{
ResComp *array;
u32 count;
} rescomps;
struct
{
String output;
i32 return_code;
} link;
};
BuildData *build = 0;
if (lane->idx == 0)
{
build = PushStruct(perm, BuildData);
}
WaveSyncBroadcast(lane, 0, &build);
i32 ret = 0;
M_Layer flattened = ZI;
//////////////////////////////
//- Parse meta layers
if (lane->idx == 0 && !ret)
{
//- Lex layers
@ -364,52 +492,19 @@ void BuildEntryPoint(WaveLaneCtx *lane, void *udata)
{
StringList starting_layer_names = ZI;
PushStringToList(perm, &starting_layer_names, cmdline.leaf_layer_name);
flattened = M_GetFlattenedEntries(perm, parsed, starting_layer_names);
build->flattened = M_GetFlattenedEntries(perm, parsed, starting_layer_names);
}
}
WaveSyncBroadcast(lane, 0, &flattened);
if (!ret) ret = flattened.errors.count > 0;
WaveSync(lane);
if (!ret) ret = build->flattened.errors.count > 0;
//////////////////////////////
//- Prep
/*
* ## Phase 1
*
* <C compile oscmd> <shader compile oscmds>
* |
* <FULL BARRIER> -------------------------------------------------------------
*
* ## Phase 2
* <shader resource arcs> <embedded resource arcs>
* | |
* <FULL BARRIER> -------------------------------------------------------------
*
* ## Phase 3
* <shader resource oscmd> <embedded resource oscmds>
* <FULL BARRIER> -------------------------------------------------------------
*
* ## Phase 4
*
* <link oscmd>
*/
String shader_store_name = Lit("ShadersStore");
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)));
/* TODO: Dispatch OS Cmds asynchronously rather than synchronously waiting on each lane */
//////////////////////////////
//- Generate final C file
Struct(CGenData)
{
M_ErrorList errors;
};
CGenData cgen = ZI;
//- Generate C & HLSL files
if (lane->idx == 0 && !ret)
{
/* Generate C file */
{
String c_out_file = F_GetFull(perm, StringF(perm, "%F_gen_c.c", FmtString(cmdline.leaf_layer_name)));
StringList c_store_lines = ZI;
@ -417,7 +512,7 @@ void BuildEntryPoint(WaveLaneCtx *lane, void *udata)
StringList c_include_lines = ZI;
StringList c_startup_lines = ZI;
{
for (M_Entry *entry = flattened.first; entry->valid; entry = entry->next)
for (M_Entry *entry = build->flattened.first; entry->valid; entry = entry->next)
{
M_EntryKind kind = entry->kind;
M_Token *entry_tok = entry->name_token;
@ -444,12 +539,12 @@ void BuildEntryPoint(WaveLaneCtx *lane, void *udata)
else
{
String err = StringF(perm, "Directory '%F' not found", FmtString(full));
M_PushError(perm, &cgen.errors, arg1_tok, err);
M_PushError(perm, &build->cgen.errors, arg1_tok, err);
}
}
else
{
M_PushError(perm, &cgen.errors, entry_tok, Lit("Expected resource store & directory name"));
M_PushError(perm, &build->cgen.errors, entry_tok, Lit("Expected resource store & directory name"));
}
} break;
case M_EntryKind_VertexShader:
@ -469,7 +564,7 @@ void BuildEntryPoint(WaveLaneCtx *lane, void *udata)
}
else
{
M_PushError(perm, &cgen.errors, entry_tok, Lit("Expected shader name"));
M_PushError(perm, &build->cgen.errors, entry_tok, Lit("Expected shader name"));
}
} break;
case M_EntryKind_IncludeC:
@ -488,12 +583,12 @@ void BuildEntryPoint(WaveLaneCtx *lane, void *udata)
else
{
String err = StringF(perm, "File '%F' not found", FmtString(full));
M_PushError(perm, &cgen.errors, arg0_tok, err);
M_PushError(perm, &build->cgen.errors, arg0_tok, err);
}
}
else
{
M_PushError(perm, &cgen.errors, entry_tok, Lit("Expected file name"));
M_PushError(perm, &build->cgen.errors, entry_tok, Lit("Expected file name"));
}
} break;
case M_EntryKind_Startup:
@ -506,13 +601,13 @@ void BuildEntryPoint(WaveLaneCtx *lane, void *udata)
}
else
{
M_PushError(perm, &cgen.errors, entry_tok, Lit("Expected startup function name"));
M_PushError(perm, &build->cgen.errors, entry_tok, Lit("Expected startup function name"));
}
} break;
}
}
}
if (cgen.errors.count == 0)
if (build->cgen.errors.count == 0)
{
StringList c_out_lines = ZI;
PushStringToList(perm, &c_out_lines, Lit("// Auto generated file"));
@ -571,24 +666,8 @@ void BuildEntryPoint(WaveLaneCtx *lane, void *udata)
F_ClearWrite(c_out_file, c_out);
}
}
WaveSyncBroadcast(lane, 0, &cgen);
if (!ret) ret = cgen.errors.count > 0;
//////////////////////////////
//- Generate final HLSL file
Enum(ShaderEntryKind) { ShaderEntryKind_VS, ShaderEntryKind_PS, ShaderEntryKind_CS, };
Struct(ShaderEntry) { ShaderEntry *next; ShaderEntryKind kind; String name; };
Struct(GpuGenData)
{
M_ErrorList errors;
ShaderEntry *first_shader_entry;
ShaderEntry *last_shader_entry;
u64 shader_entries_count;
};
GpuGenData gpugen = ZI;
if (lane->idx == 0 && !ret)
/* Generate HLSL file */
{
/* Clear shader store */
OS_Mkdir(shader_store_name);
@ -616,7 +695,7 @@ void BuildEntryPoint(WaveLaneCtx *lane, void *udata)
{
StringList gpu_include_lines = ZI;
{
for (M_Entry *entry = flattened.first; entry->valid; entry = entry->next)
for (M_Entry *entry = build->flattened.first; entry->valid; entry = entry->next)
{
M_EntryKind kind = entry->kind;
M_Token *entry_tok = entry->name_token;
@ -641,12 +720,12 @@ void BuildEntryPoint(WaveLaneCtx *lane, void *udata)
else
{
String err = StringF(perm, "File '%F' not found", FmtString(full));
M_PushError(perm, &gpugen.errors, arg0_tok, err);
M_PushError(perm, &build->gpugen.errors, arg0_tok, err);
}
}
else
{
M_PushError(perm, &gpugen.errors, entry_tok, Lit("Expected file name"));
M_PushError(perm, &build->gpugen.errors, entry_tok, Lit("Expected file name"));
}
} break;
case M_EntryKind_VertexShader:
@ -663,18 +742,18 @@ void BuildEntryPoint(WaveLaneCtx *lane, void *udata)
ShaderEntry *e = PushStruct(perm, ShaderEntry);
e->kind = shader_kind;
e->name = shader_name;
SllQueuePush(gpugen.first_shader_entry, gpugen.last_shader_entry, e);
++gpugen.shader_entries_count;
SllQueuePush(build->gpugen.first_shader_entry, build->gpugen.last_shader_entry, e);
++build->gpugen.shader_entries_count;
}
else
{
M_PushError(perm, &gpugen.errors, entry_tok, Lit("Expected shader name"));
M_PushError(perm, &build->gpugen.errors, entry_tok, Lit("Expected shader name"));
}
} break;
}
}
}
if (gpugen.errors.count == 0)
if (build->gpugen.errors.count == 0)
{
StringList gpu_out_lines = ZI;
PushStringToList(perm, &gpu_out_lines, Lit("// Auto generated file"));
@ -702,58 +781,48 @@ void BuildEntryPoint(WaveLaneCtx *lane, void *udata)
}
}
}
WaveSyncBroadcast(lane, 0, &gpugen);
if (!ret) ret = gpugen.errors.count > 0;
build->gpucomps.count = build->gpugen.shader_entries_count;
build->gpucomps.array = PushStructs(perm, GpuComp, build->gpucomps.count);
}
WaveSync(lane);
if (!ret) ret = build->cgen.errors.count > 0;
if (!ret) ret = build->gpugen.errors.count > 0;
//////////////////////////////
//- Compile C & Shaders
Struct(CComp)
{
String obj_file;
String output;
i32 return_code;
};
CComp ccomp = ZI;
Struct(GpuComp)
{
String output;
i32 return_code;
};
u32 gpucomps_count = gpugen.shader_entries_count;
GpuComp *gpucomps = PushStructs(perm, GpuComp, gpucomps_count);
if (!ret)
{
/* Compile C */
u64 ccomp_task_idx = 0;
if (lane->idx == WaveLaneIdxFromTaskIdx(lane, ccomp_task_idx))
{
ccomp.obj_file = StringF(perm, "%F_gen_c.obj", FmtString(cmdline.leaf_layer_name));
build->ccomp.obj_file = StringF(perm, "%F_gen_c.obj", FmtString(cmdline.leaf_layer_name));
String cmd = StringF(perm,
"cl.exe /c %F -Fo:%F %F %F %F %F",
FmtString(c_out_file),
FmtString(ccomp.obj_file),
FmtString(build->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;
build->ccomp.output = cmd_output;
build->ccomp.return_code = cmd_result.code;
}
/* Compile shaders */
u32 gpucomp_idx = 0;
for (ShaderEntry *e = gpugen.first_shader_entry; e; e = e->next)
for (ShaderEntry *e = build->gpugen.first_shader_entry; e; e = e->next)
{
/* NOTE: Using gpucomp_idx + 1 as task index for parralelism w/ C compilation */
u64 gpucomp_task_idx = gpucomp_idx + 1;
if (lane->idx == WaveLaneIdxFromTaskIdx(lane, gpucomp_task_idx))
{
GpuComp *gpucomp = &gpucomps[gpucomp_idx];
GpuComp *gpucomp = &build->gpucomps.array[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")
@ -779,31 +848,21 @@ void BuildEntryPoint(WaveLaneCtx *lane, void *udata)
++gpucomp_idx;
}
}
WaveSyncBroadcast(lane, 0, &ccomp);
WaveSyncBroadcast(lane, 0, &gpucomps);
if (!ret) ret = ccomp.return_code;
for (u32 i = 0; i < gpucomps_count; ++i)
WaveSync(lane);
if (!ret) ret = build->ccomp.return_code;
for (u32 i = 0; i < build->gpucomps.count; ++i)
{
if (!ret) ret = gpucomps[i].return_code;
if (!ret) ret = build->gpucomps.array[i].return_code;
}
//////////////////////////////
//- Gather resource archive info
Struct(ArcInfoEntry) { ArcInfoEntry *next; String dir_path; String store_name; String out_path; };
Struct(ArcInfoGen)
{
M_ErrorList errors;
ArcInfoEntry *first_arc_entry;
ArcInfoEntry *last_arc_entry;
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)
for (M_Entry *entry = build->flattened.first; entry->valid; entry = entry->next)
{
M_EntryKind kind = entry->kind;
M_Token *entry_tok = entry->name_token;
@ -827,18 +886,18 @@ void BuildEntryPoint(WaveLaneCtx *lane, void *udata)
arc->store_name = store_name;
arc->dir_path = full;
arc->out_path = StringF(perm, "%F.arc", FmtString(store_name));
SllQueuePush(arcinfogen.first_arc_entry, arcinfogen.last_arc_entry, arc);
++arcinfogen.arc_entries_count;
SllQueuePush(build->arcinfogen.first_arc_entry, build->arcinfogen.last_arc_entry, arc);
++build->arcinfogen.arc_entries_count;
}
else
{
String err = StringF(perm, "Directory '%F' not found", FmtString(full));
M_PushError(perm, &arcinfogen.errors, arg1_tok, err);
M_PushError(perm, &build->arcinfogen.errors, arg1_tok, err);
}
}
else
{
M_PushError(perm, &arcinfogen.errors, entry_tok, Lit("Expected resource store & directory name"));
M_PushError(perm, &build->arcinfogen.errors, entry_tok, Lit("Expected resource store & directory name"));
}
} break;
}
@ -849,19 +908,26 @@ void BuildEntryPoint(WaveLaneCtx *lane, void *udata)
arc->store_name = 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;
SllQueuePush(build->arcinfogen.first_arc_entry, build->arcinfogen.last_arc_entry, arc);
++build->arcinfogen.arc_entries_count;
}
build->rescomps.count = build->arcinfogen.arc_entries_count;
build->rescomps.array = PushStructs(perm, ResComp, build->rescomps.count);
}
WaveSyncBroadcast(lane, 0, &arcinfogen);
if (!ret) ret = arcinfogen.errors.count > 0;
WaveSync(lane);
if (!ret) ret = build->arcinfogen.errors.count > 0;
//////////////////////////////
//- Generate resource archives
if (lane->idx == 0 && !ret)
if (!ret)
{
for (ArcInfoEntry *entry = arcinfogen.first_arc_entry; entry; entry = entry->next)
u32 task_idx = 0;
for (ArcInfoEntry *entry = build->arcinfogen.first_arc_entry; entry; entry = entry->next)
{
if (lane->idx == WaveLaneIdxFromTaskIdx(lane, task_idx))
{
String dir_path = entry->dir_path;
String store_name = entry->store_name;
@ -965,29 +1031,24 @@ void BuildEntryPoint(WaveLaneCtx *lane, void *udata)
F_ClearWrite(arc_path, arc_contents);
}
}
++task_idx;
}
WaveSync(lane);
//////////////////////////////
//- Compile resource archives
Struct(ResComp)
{
String obj_file;
String output;
i32 return_code;
};
u32 rescomps_count = arcinfogen.arc_entries_count;
ResComp *rescomps = PushStructs(perm, ResComp, rescomps_count);
if (!ret)
{
if (IsPlatformWindows)
{
i32 rescomp_idx = 0;
for (ArcInfoEntry *entry = arcinfogen.first_arc_entry; entry; entry = entry->next)
for (ArcInfoEntry *entry = build->arcinfogen.first_arc_entry; entry; entry = entry->next)
{
if (lane->idx == WaveLaneIdxFromTaskIdx(lane, rescomp_idx))
{
ResComp *rescomp = &rescomps[rescomp_idx];
ResComp *rescomp = &build->rescomps.array[rescomp_idx];
String arc_path = entry->out_path;
@ -1021,25 +1082,19 @@ void BuildEntryPoint(WaveLaneCtx *lane, void *udata)
else
{
/* TODO: Compile object files using .incbin on non-windows platforms */
Panic(Lit("Non-windows embedded format not implemented"));
Panic(Lit("Embedded format not implemented for this platform"));
}
}
WaveSyncBroadcast(lane, 0, &rescomps);
for (u32 i = 0; i < rescomps_count; ++i)
WaveSync(lane);
for (u32 i = 0; i < build->rescomps.count; ++i)
{
if (!ret) ret = rescomps[i].return_code;
if (!ret) ret = build->rescomps.array[i].return_code;
}
//////////////////////////////
//- Link
Struct(Link)
{
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));
@ -1055,10 +1110,10 @@ void BuildEntryPoint(WaveLaneCtx *lane, void *udata)
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)
PushStringToList(perm, &obj_files, build->ccomp.obj_file);
for (u64 rescomp_idx = 0; rescomp_idx < build->rescomps.count; ++rescomp_idx)
{
ResComp *rescomp = &rescomps[rescomp_idx];
ResComp *rescomp = &build->rescomps.array[rescomp_idx];
PushStringToList(perm, &obj_files, rescomp->obj_file);
}
obj_files_str = StringFromList(perm, obj_files, Lit(" "));
@ -1071,13 +1126,14 @@ void BuildEntryPoint(WaveLaneCtx *lane, void *udata)
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;
build->link.output = TrimWhitespace(result.output);
build->link.return_code = result.code;
i64 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;
WaveSync(lane);
if (!ret) ret = build->link.return_code;
//////////////////////////////
//- Process output & errors
@ -1087,9 +1143,9 @@ void BuildEntryPoint(WaveLaneCtx *lane, void *udata)
String gpucomp_output = ZI;
{
StringList gpucomp_outputs = ZI;
for (u32 gpucomp_idx = 0; gpucomp_idx < gpucomps_count; ++gpucomp_idx)
for (u32 gpucomp_idx = 0; gpucomp_idx < build->gpucomps.count; ++gpucomp_idx)
{
GpuComp *gpucomp = &gpucomps[gpucomp_idx];
GpuComp *gpucomp = &build->gpucomps.array[gpucomp_idx];
PushStringToList(perm, &gpucomp_outputs, gpucomp->output);
}
gpucomp_output = StringFromList(perm, gpucomp_outputs, Lit("\n"));
@ -1097,21 +1153,21 @@ void BuildEntryPoint(WaveLaneCtx *lane, void *udata)
String rescomp_output = ZI;
{
StringList rescomp_outputs = ZI;
for (u32 rescomp_idx = 0; rescomp_idx < rescomps_count; ++rescomp_idx)
for (u32 rescomp_idx = 0; rescomp_idx < build->rescomps.count; ++rescomp_idx)
{
ResComp *rescomp = &rescomps[rescomp_idx];
ResComp *rescomp = &build->rescomps.array[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(StringFromMetaErrors(perm, build->flattened.errors));
EchoLineOrNothing(StringFromMetaErrors(perm, build->cgen.errors));
EchoLineOrNothing(StringFromMetaErrors(perm, build->gpugen.errors));
EchoLineOrNothing(build->ccomp.output);
EchoLineOrNothing(gpucomp_output);
EchoLineOrNothing(StringFromMetaErrors(perm, arcinfogen.errors));
EchoLineOrNothing(StringFromMetaErrors(perm, build->arcinfogen.errors));
EchoLineOrNothing(rescomp_output);
EchoLineOrNothing(link.output);
EchoLineOrNothing(build->link.output);
}
//////////////////////////////