diff --git a/src/base/base.lay b/src/base/base.lay index 45d9e38e..446127e9 100644 --- a/src/base/base.lay +++ b/src/base/base.lay @@ -1,7 +1,5 @@ @Layer base -@Dep mp3 - //- Api @IncludeC base_core.h @IncludeC base_intrinsics.h diff --git a/src/base/base_win32/base_win32.lay b/src/base/base_win32/base_win32.lay new file mode 100644 index 00000000..ac65cc0e --- /dev/null +++ b/src/base/base_win32/base_win32.lay @@ -0,0 +1,9 @@ +@Layer base_win32 + +//- Api +@IncludeC base_win32_entry.h +@IncludeC base_win32_job.h + +//- Impl +@IncludeC base_win32_entry.c +@IncludeC base_win32_job.c diff --git a/src/base/win32/base_win32_entry.c b/src/base/base_win32/base_win32_entry.c similarity index 100% rename from src/base/win32/base_win32_entry.c rename to src/base/base_win32/base_win32_entry.c diff --git a/src/base/win32/base_win32_entry.h b/src/base/base_win32/base_win32_entry.h similarity index 100% rename from src/base/win32/base_win32_entry.h rename to src/base/base_win32/base_win32_entry.h diff --git a/src/base/win32/base_win32_job.c b/src/base/base_win32/base_win32_job.c similarity index 100% rename from src/base/win32/base_win32_job.c rename to src/base/base_win32/base_win32_job.c diff --git a/src/base/win32/base_win32_job.h b/src/base/base_win32/base_win32_job.h similarity index 100% rename from src/base/win32/base_win32_job.h rename to src/base/base_win32/base_win32_job.h diff --git a/src/gpu/dx12/gpu_dx12.c b/src/gpu/gpu_dx12/gpu_dx12.c similarity index 100% rename from src/gpu/dx12/gpu_dx12.c rename to src/gpu/gpu_dx12/gpu_dx12.c diff --git a/src/gpu/dx12/gpu_dx12.h b/src/gpu/gpu_dx12/gpu_dx12.h similarity index 100% rename from src/gpu/dx12/gpu_dx12.h rename to src/gpu/gpu_dx12/gpu_dx12.h diff --git a/src/gpu/gpu_dx12/gpu_dx12.lay b/src/gpu/gpu_dx12/gpu_dx12.lay new file mode 100644 index 00000000..47557a18 --- /dev/null +++ b/src/gpu/gpu_dx12/gpu_dx12.lay @@ -0,0 +1,7 @@ +@Layer gpu_dx12 + +//- Api +@IncludeC gpu_dx12.h + +//- Impl +@IncludeC gpu_dx12.c diff --git a/src/meta/meta.c b/src/meta/meta.c index 69695295..6f427fca 100644 --- a/src/meta/meta.c +++ b/src/meta/meta.c @@ -230,6 +230,7 @@ Struct(L_BlobItemList) Struct(L_Blob) { + i64 id; L_Blob *next; L_BlobItemList names; @@ -243,8 +244,6 @@ Struct(L_Blob) L_BlobItemList default_windows_impls; L_BlobItemList errors; - - L_BlobTopoColor topo_color; }; Struct(L_ParseResult) @@ -261,15 +260,7 @@ L_BlobItem *L_PushBlobItem(Arena *arena, L_BlobItemList *list, String token_file item->s = item_string; item->token_file = token_file; item->token_pos = token_pos; - if (list->last) - { - list->last->next = item; - } - else - { - list->first = item; - } - list->last = item; + SllQueuePush(list->first, list->last, item); ++list->count; return item; } @@ -294,16 +285,8 @@ L_ParseResult L_ParseBlobsFromPaths(Arena *arena, StringList paths) L_TokenList tokens = L_TokensFromString(scratch.arena, data); L_ParseMode mode = L_ParseMode_None; L_Blob *blob = PushStruct(arena, L_Blob); - if (result.last_blob) - { - result.last_blob->next = blob; - } - else - { - result.first_blob = blob; - } - result.last_blob = blob; - ++result.blobs_count; + SllQueuePush(result.first_blob, result.last_blob, blob); + blob->id = result.blobs_count++; for (L_Token *token = tokens.first->next; !token->eof; token = token->next) { String s = token->s; @@ -394,7 +377,15 @@ L_ParseResult L_ParseBlobsFromPaths(Arena *arena, StringList paths) { String name = blob->names.first->s; u64 hash = HashFnv64(Fnv64Basis, name); - SetDictValue(arena, result.blobs_dict, hash, (u64)blob); + DictEntry *entry = EnsureDictEntry(arena, result.blobs_dict, hash); + if (entry->value == 0) + { + entry->value = (u64)blob; + } + else + { + L_PushBlobItem(arena, &blob->errors, file, blob->names.first->token_pos, StringF(arena, "Layer '%F' already exists", FmtString(name))); + } } else if (blob->names.count == 0) { @@ -445,15 +436,7 @@ L_TopoItem *L_PushTopoItem(Arena *arena, L_TopoItemList *list, String token_file item->s = item_string; item->token_file = token_file; item->token_pos = token_pos; - if (list->last) - { - list->last->next = item; - } - else - { - list->first = item; - } - list->last = item; + SllQueuePush(list->first, list->last, item); ++list->count; return item; } @@ -466,95 +449,170 @@ L_Topo L_TopoFromLayerName(Arena *arena, StringList starting_layer_names, String /* Parse blobs */ L_ParseResult parsed = L_ParseBlobsFromPaths(scratch.arena, paths); - /* Topological sort */ - u64 sorted_count = 0; - L_Blob **sorted = PushStructsNoZero(scratch.arena, L_Blob *, parsed.blobs_count); + Struct(Node) { - /* Build array from post-order DFS */ + Node *next; + L_Blob *blob; + i32 state; /* 0 = enter, 1 = exit */ + }; + + /* Topological sort via post-order DFS */ + Node *first_stack = 0; + Node *first_post = 0; + Node *last_post = 0; + i8 *seen_blobs = PushStructs(scratch.arena, i8, parsed.blobs_count); + i8 *entered_blobs = PushStructs(scratch.arena, i8, parsed.blobs_count); + { + for (StringListNode *n = starting_layer_names.first; n; n = n->next) { - u64 queue_count = 0; - L_Blob **queue = PushStructsNoZero(scratch.arena, L_Blob *, parsed.blobs_count); - for (StringListNode *n = starting_layer_names.first; n; n = n->next) + String s = n->s; + L_Blob *starting_blob = (L_Blob *)DictValueFromHash(parsed.blobs_dict, HashFnv64(Fnv64Basis, s)); + if (starting_blob) { - String s = n->s; - L_Blob *starting_blob = (L_Blob *)DictValueFromHash(parsed.blobs_dict, HashFnv64(Fnv64Basis, s)); - if (starting_blob) - { - if (starting_blob->topo_color == L_BlobTopoColor_None) - { - queue[queue_count++] = starting_blob; - } - } - else - { - L_PushTopoItem(arena, &result.errors, Lit(""), 0, StringF(arena, "Layer not found with name '%F'", FmtString(s))); - } + Node *n = PushStruct(scratch.arena, Node); + n->blob = starting_blob; + n->state = 0; + SllStackPush(first_stack, n); } - while (queue_count > 0) + else { - L_Blob *blob = queue[--queue_count]; - blob->topo_color = L_BlobTopoColor_Visiting; - b32 has_unvisited_deps = 0; - for (L_BlobItem *dep_item = blob->deps.first; dep_item; dep_item = dep_item->next) + L_PushTopoItem(arena, &result.errors, Lit(""), 0, StringF(arena, "Starting layer not found with name '%F'", FmtString(s))); + } + } + while (first_stack) + { + L_Blob *blob = 0; + Node *stack_node = first_stack; + blob = stack_node->blob; + SllStackPop(first_stack); + + if (stack_node->state == 0) + { /* Enter */ + if (!seen_blobs[blob->id]) { - String dep_name = dep_item->s; - u64 dep_hash = HashFnv64(Fnv64Basis, dep_name); - L_Blob *dep_blob = (L_Blob *)DictValueFromHash(parsed.blobs_dict, dep_hash); - if (dep_blob) - { - if (dep_blob->topo_color == L_BlobTopoColor_None) + if (entered_blobs[blob->id]) + { /* Cycle detected */ + Node *first_cycle = 0; { - has_unvisited_deps = 1; - dep_blob->topo_color = L_BlobTopoColor_Queued; - queue[queue_count++] = dep_blob; + i8 *cycle_blobs_seen = PushStructs(scratch.arena, i8, parsed.blobs_count); + { + Node *cycle_node = PushStruct(scratch.arena, Node); + cycle_node->blob = blob; + SllStackPush(first_cycle, cycle_node); + } + for (Node *n = first_stack; n; n = n->next) + { + if (entered_blobs[n->blob->id]) + { + if (!cycle_blobs_seen[n->blob->id]) + { + Node *cycle_node = PushStruct(scratch.arena, Node); + cycle_node->blob = n->blob; + SllStackPush(first_cycle, cycle_node); + cycle_blobs_seen[n->blob->id] = 1; + } + } + if (n->blob == blob) break; + } } - else if (dep_blob->topo_color == L_BlobTopoColor_Visiting) + StringList cycle_names_list = ZI; + for (Node *cycle = first_cycle; cycle; cycle = cycle->next) { - String a = ZI; - String b = ZI; - if (blob->names.count > 0) a = blob->names.first->s; - if (dep_blob->names.count > 0) b = dep_blob->names.first->s; - String s = StringF(arena, "Cyclic dependency detected while processing layer '%F' -> '%F'", FmtString(a), FmtString(b)); - String file = PushString(arena, dep_item->token_file); - L_PushTopoItem(arena, &result.errors, file, dep_item->token_pos, s); + String name = ZI; + if (cycle->blob->names.count > 0) name = cycle->blob->names.first->s; + PushStringToList(scratch.arena, &cycle_names_list, name); + } + String cycle_names_str = StringFromStringList(scratch.arena, cycle_names_list, Lit(" -> ")); + String name = ZI; + String token_file = ZI; + i64 token_pos = 0; + if (blob->names.count > 0) + { + name = blob->names.first->s; + token_file = PushString(arena, blob->names.first->token_file); + token_pos = blob->names.first->token_pos; + } + if (cycle_names_list.count > 1) + { + L_PushTopoItem(arena, &result.errors, token_file, token_pos, StringF(arena, "Cyclic dependency detected while processing dependencies for layer '%F' (%F)", FmtString(name), FmtString(cycle_names_str))); + } + else + { + L_PushTopoItem(arena, &result.errors, token_file, token_pos, StringF(arena, "Cyclic dependency detected while processing dependencies for layer '%F'", FmtString(name))); } } else { - String s = StringF(arena, "Layer '%F' not found", FmtString(dep_name)); - String file = PushString(arena, dep_item->token_file); - L_PushTopoItem(arena, &result.errors, file, dep_item->token_pos, s); + /* Push blob impls */ +#if PlatformIsWindows + for (L_BlobItem *impl_item = blob->default_windows_impls.first; impl_item; impl_item = impl_item->next) + { + String impl_name = impl_item->s; + u64 impl_hash = HashFnv64(Fnv64Basis, impl_name); + L_Blob *impl = (L_Blob *)DictValueFromHash(parsed.blobs_dict, impl_hash); + if (impl) + { + if (!seen_blobs[impl->id]) + { + Node *n = PushStruct(scratch.arena, Node); + n->blob = impl; + n->state = 0; + SllStackPush(first_stack, n); + } + } + else + { + String file = PushString(arena, impl_item->token_file); + L_PushTopoItem(arena, &result.errors, file, impl_item->token_pos, StringF(arena, "Layer '%F' not found", FmtString(impl_name))); + } + } +#endif + /* Push blob exit */ + { + entered_blobs[blob->id] = 1; + Node *n = PushStruct(scratch.arena, Node); + n->blob = blob; + n->state = 1; + SllStackPush(first_stack, n); + } + /* Push blob deps */ + for (L_BlobItem *dep_item = blob->deps.first; dep_item; dep_item = dep_item->next) + { + String dep_name = dep_item->s; + u64 dep_hash = HashFnv64(Fnv64Basis, dep_name); + L_Blob *dep = (L_Blob *)DictValueFromHash(parsed.blobs_dict, dep_hash); + if (dep) + { + if (!seen_blobs[dep->id]) + { + Node *n = PushStruct(scratch.arena, Node); + n->blob = dep; + n->state = 0; + SllStackPush(first_stack, n); + } + } + else + { + String file = PushString(arena, dep_item->token_file); + L_PushTopoItem(arena, &result.errors, file, dep_item->token_pos, StringF(arena, "Layer '%F' not found", FmtString(dep_name))); + } + } } } - if (has_unvisited_deps) - { - queue[queue_count++] = blob; - blob->topo_color = L_BlobTopoColor_Queued; - } - else - { - sorted[sorted_count++] = blob; - blob->topo_color = L_BlobTopoColor_Finished; - } } - } - /* Reverse sorted array */ - i64 l = 0; - i64 r = sorted_count - 1; - while (l < r) - { - L_Blob *swp = sorted[l]; - sorted[l] = sorted[r]; - sorted[r] = swp; - ++l; - --r; + else + { /* Exit */ + entered_blobs[blob->id] = 0; + seen_blobs[blob->id] = 1; + SllQueuePush(first_post, last_post, stack_node); + } } } - /* Process sorted blobs into result */ - for (u64 i = 0; i < sorted_count; ++i) + /* Process post blobs into result */ + for (Node *n = first_post; n; n = n->next) { - L_Blob *blob = sorted[i]; + L_Blob *blob = n->blob; /* C includes */ for (L_BlobItem *bitem = blob->c_includes.first; bitem; bitem = bitem->next) { @@ -574,7 +632,7 @@ L_Topo L_TopoFromLayerName(Arena *arena, StringList starting_layer_names, String /* Process errors of untouched blobs */ for (L_Blob *blob = parsed.first_blob; blob; blob = blob->next) { - if (blob->topo_color == L_BlobTopoColor_None && blob->errors.count > 0) + if (!seen_blobs[blob->id] && blob->errors.count > 0) { for (L_BlobItem *bitem = blob->errors.first; bitem; bitem = bitem->next) { @@ -613,15 +671,7 @@ Error *PushError(Arena *arena, ErrorList *list, String file, i64 pos, String s) e->s = s; e->file = file; e->pos = pos; - if (list->last) - { - list->last->next = e; - } - else - { - list->first = e; - } - list->last = e; + SllQueuePush(list->first, list->last, e); ++list->count; return e; } diff --git a/src/meta/meta_base/meta_base.h b/src/meta/meta_base/meta_base.h index 4b957f54..b800d7c2 100644 --- a/src/meta/meta_base/meta_base.h +++ b/src/meta/meta_base/meta_base.h @@ -258,6 +258,64 @@ void __asan_unpoison_memory_region(void const volatile *add, size_t); #define NsFromSeconds(s) ((i64)((s) * 1000000000.0)) #define SecondsFromNs(ns) ((f64)(ns) / 1000000000.0) +//////////////////////////////// +//~ Linked list helper macros + +/* Taken from the rad debugger + * https://github.com/EpicGamesExt/raddebugger/blob/be5634c44867a2e31f6a109df5e574930992df01/src/base/base_core.h#L239 + */ + +#define CheckNil(nil,p) ((p) == 0 || (p) == nil) +#define SetNil(nil,p) ((p) = nil) + +//- Singly linked list stack (first & next pointers) +#define SllStackPush_N(f,n,next) ((n)->next=(f), (f)=(n)) +#define SllStackPop_N(f,next) ((f)=(f)->next) +#define SllStackPush(f,n) SllStackPush_N(f,n,next) +#define SllStackPop(f) SllStackPop_N(f,next) + +//- Singly linked list queue (first, last, & next pointers) +#define SllQueuePush_NZ(nil,f,l,n,next) (CheckNil(nil,f)?\ + ((f)=(l)=(n),SetNil(nil,(n)->next)):\ + ((l)->next=(n),(l)=(n),SetNil(nil,(n)->next))) +#define SllQueuePushFront_NZ(nil,f,l,n,next) (CheckNil(nil,f)?\ + ((f)=(l)=(n),SetNil(nil,(n)->next)):\ + ((n)->next=(f),(f)=(n))) +#define SllQueuePop_NZ(nil,f,l,next) ((f)==(l)?\ + (SetNil(nil,f),SetNil(nil,l)):\ + ((f)=(f)->next)) +#define SllQueuePush_N(f,l,n,next) SllQueuePush_NZ(0,f,l,n,next) +#define SllQueuePushFront_N(f,l,n,next) SllQueuePushFront_NZ(0,f,l,n,next) +#define SllQueuePop_N(f,l,next) SllQueuePop_NZ(0,f,l,next) +#define SllQueuePush(f,l,n) SllQueuePush_NZ(0,f,l,n,next) +#define SllQueuePushFront(f,l,n) SllQueuePushFront_NZ(0,f,l,n,next) +#define SllQueuePop(f,l) SllQueuePop_NZ(0,f,l,next) + +//- Doubly linked list (first, last, next, & prev pointers) +#define DllInsert_NPZ(nil,f,l,p,n,next,prev) (CheckNil(nil,f) ? \ + ((f) = (l) = (n), SetNil(nil,(n)->next), SetNil(nil,(n)->prev)) :\ + CheckNil(nil,p) ? \ + ((n)->next = (f), (f)->prev = (n), (f) = (n), SetNil(nil,(n)->prev)) :\ + ((p)==(l)) ? \ + ((l)->next = (n), (n)->prev = (l), (l) = (n), SetNil(nil, (n)->next)) :\ + (((!CheckNil(nil,p) && CheckNil(nil,(p)->next)) ? (0) : ((p)->next->prev = (n))), ((n)->next = (p)->next), ((p)->next = (n)), ((n)->prev = (p)))) +#define DllPushBack_NPZ(nil,f,l,n,next,prev) DllInsert_NPZ(nil,f,l,l,n,next,prev) +#define DllPushFront_NPZ(nil,f,l,n,next,prev) DllInsert_NPZ(nil,l,f,f,n,prev,next) +#define DllRemove_NPZ(nil,f,l,n,next,prev) (((n) == (f) ? (f) = (n)->next : (0)),\ + ((n) == (l) ? (l) = (l)->prev : (0)),\ + (CheckNil(nil,(n)->prev) ? (0) :\ + ((n)->prev->next = (n)->next)),\ + (CheckNil(nil,(n)->next) ? (0) :\ + ((n)->next->prev = (n)->prev))) +#define DllInsert_NP(f,l,p,n,next,prev) DllInsert_NPZ(0,f,l,p,n,next,prev) +#define DllPushBack_NP(f,l,n,next,prev) DllPushBack_NPZ(0,f,l,n,next,prev) +#define DllPushFront_NP(f,l,n,next,prev) DllPushFront_NPZ(0,f,l,n,next,prev) +#define DllRemove_NP(f,l,n,next,prev) DllRemove_NPZ(0,f,l,n,next,prev) +#define DllInsert(f,l,p,n) DllInsert_NPZ(0,f,l,p,n,next,prev) +#define DllPushBack(f,l,n) DllPushBack_NPZ(0,f,l,n,next,prev) +#define DllPushFront(f,l,n) DllPushFront_NPZ(0,f,l,n,next,prev) +#define DllRemove(f,l,n) DllRemove_NPZ(0,f,l,n,next,prev) + //////////////////////////////// //~ Type helper macros diff --git a/src/mp3/mmf/mp3_mmf.c b/src/mp3/mp3_mmf/mp3_mmf.c similarity index 100% rename from src/mp3/mmf/mp3_mmf.c rename to src/mp3/mp3_mmf/mp3_mmf.c diff --git a/src/mp3/mp3_mmf/mp3_mmf.lay b/src/mp3/mp3_mmf/mp3_mmf.lay new file mode 100644 index 00000000..c9b3dec7 --- /dev/null +++ b/src/mp3/mp3_mmf/mp3_mmf.lay @@ -0,0 +1,4 @@ +@Layer mp3_mmf + +//- Impl +@IncludeC mp3_mmf.c diff --git a/src/platform/platform_win32.c b/src/platform/platform_win32/platform_win32.c similarity index 100% rename from src/platform/platform_win32.c rename to src/platform/platform_win32/platform_win32.c diff --git a/src/platform/platform_win32.h b/src/platform/platform_win32/platform_win32.h similarity index 100% rename from src/platform/platform_win32.h rename to src/platform/platform_win32/platform_win32.h diff --git a/src/platform/platform_win32/platform_win32.lay b/src/platform/platform_win32/platform_win32.lay new file mode 100644 index 00000000..b8e89c6f --- /dev/null +++ b/src/platform/platform_win32/platform_win32.lay @@ -0,0 +1,7 @@ +@Layer platform_win32 + +//- Api +@IncludeC platform_win32.h + +//- Impl +@IncludeC platform_win32.c diff --git a/src/playback/playback.lay b/src/playback/playback.lay index cc6270c3..0601c7b5 100644 --- a/src/playback/playback.lay +++ b/src/playback/playback.lay @@ -8,9 +8,6 @@ //- Api @IncludeC playback_core.h -//- Impl -@IncludeC playback_core.c - //- Wasapi impl @DefaultWindowsImpl playback_wasapi diff --git a/src/playback/wasapi/playback_wasapi.c b/src/playback/playback_wasapi/playback_wasapi.c similarity index 100% rename from src/playback/wasapi/playback_wasapi.c rename to src/playback/playback_wasapi/playback_wasapi.c diff --git a/src/playback/wasapi/playback_wasapi.h b/src/playback/playback_wasapi/playback_wasapi.h similarity index 100% rename from src/playback/wasapi/playback_wasapi.h rename to src/playback/playback_wasapi/playback_wasapi.h diff --git a/src/playback/playback_wasapi/playback_wasapi.lay b/src/playback/playback_wasapi/playback_wasapi.lay new file mode 100644 index 00000000..31223f37 --- /dev/null +++ b/src/playback/playback_wasapi/playback_wasapi.lay @@ -0,0 +1,7 @@ +@Layer playback_wasapi + +//- Api +@IncludeC playback_wasapi.h + +//- Impl +@IncludeC playback_wasapi.c diff --git a/src/pp/pp.lay b/src/pp/pp.lay index e2f5beb4..6ff2f827 100644 --- a/src/pp/pp.lay +++ b/src/pp/pp.lay @@ -1,6 +1,5 @@ @Layer pp - //- Dependencies @Dep base @Dep gpu @@ -12,6 +11,7 @@ @Dep mixer @Dep bitbuff @Dep rendertest +@Dep playback //- Api @IncludeC pp_sim.h diff --git a/src/ttf/dwrite/ttf_dwrite.c b/src/ttf/ttf_dwrite/ttf_dwrite.c similarity index 100% rename from src/ttf/dwrite/ttf_dwrite.c rename to src/ttf/ttf_dwrite/ttf_dwrite.c diff --git a/src/ttf/dwrite/ttf_dwrite.h b/src/ttf/ttf_dwrite/ttf_dwrite.h similarity index 100% rename from src/ttf/dwrite/ttf_dwrite.h rename to src/ttf/ttf_dwrite/ttf_dwrite.h diff --git a/src/ttf/ttf_dwrite/ttf_dwrite.lay b/src/ttf/ttf_dwrite/ttf_dwrite.lay new file mode 100644 index 00000000..77b43ea9 --- /dev/null +++ b/src/ttf/ttf_dwrite/ttf_dwrite.lay @@ -0,0 +1,7 @@ +@Layer ttf_dwrite + +//- Api +@IncludeC ttf_dwrite.h + +//- Impl +@IncludeC ttf_dwrite.c