refactor utility/platform files into one header, packer/codegen compiling but packer is broken

This commit is contained in:
Matthew 2025-05-28 08:21:22 +10:00
parent 2054fad364
commit 0b9f802451
30 changed files with 4313 additions and 4504 deletions

View File

@ -35,6 +35,12 @@ packer_include_flags="-I../src/ -I../external/"
packer_out_name="Packer"
packer_flags="-DBUILD_PACKER"
# codegen
codegen_source_files="../src/codegen.c"
codegen_include_flags="-I../src/ -I../external/"
codegen_out_name="Codegen"
codegen_flags="-DBUILD_CODEGEN"
# glslc
glsl_compile="glslc"
glsl_flags="--target-spv=spv1.6 -std=460"
@ -113,17 +119,17 @@ if ! [ -f libvma.a ]; then
fi
# Packer Codegen
$compile $packer_source_files $compile_link $link_os_gfx $packer_flags -DBUILD_ASSET_CODEGEN $packer_include_flags $out PackerCodegen
$compile $codegen_source_files $compile_link $link_os_gfx $codegen_flags $packer_include_flags $out $codegen_out_name
# Packer
if [ -v packer ] || ! [ -f Packer ]; then
$compile $packer_source_files $compile_link $link_os_gfx $packer_flags $packer_include_flags $out $packer_out_name
fi
if [ -v pack ] || ! [ -f assets.sgp ]; then
./Packer
fi
#if [ -v pack ] || ! [ -f assets.sgp ]; then
# ./Packer
#fi
if ! [ -v packer ]; then
$compile $source_files $compile_link $link_os_gfx $out $out_name
fi
#if ! [ -v packer ]; then
# $compile $source_files $compile_link $link_os_gfx $out $out_name
#fi

View File

@ -1,618 +0,0 @@
// ::Allocator::Globals::
FLAlloc
FL_ALLOC = {0};
Allocator
ALLOC = {0};
read_only FLNode
FL_NIL_NODE = {0};
read_only FreeList
FL_NIL_LIST = {0};
constexpr usize
FL_GLOBAL_SIZE = MB(32);
static b32
FL_GLOBAL_INIT = false;
// ::Allocator::Util::Header::
static inline usize
CalcPaddingWithHeader(uintptr ptr, uintptr alignment, usize header_size)
{
Assert(IsPow2(alignment), "Alignment provided to CalcPaddingWithHeader is not a power of two");
uintptr padding = CalcPadding(ptr, alignment);
uintptr needed_space = (uintptr)header_size;
if (padding < needed_space)
{
needed_space -= padding;
if ((needed_space & (alignment-1)) != 0)
padding += alignment * (1 + (needed_space/alignment));
else
padding += alignment * (needed_space/alignment);
}
return (usize)padding;
}
static inline usize
CalcPadding(uintptr ptr, uintptr alignment)
{
Assert(IsPow2(alignment), "CalcPadding failure: IsPow2 failed");
uintptr padding = 0;
uintptr modulo = ptr & (alignment-1);
if (modulo != 0)
padding = alignment - modulo;
return (usize)padding;
}
// ::Allocator::Arena::Start::
static Arena *
ArenaInit(rawptr buffer, usize size)
{
Arena *arena = (Arena *)buffer;
buffer = PtrAdd(buffer, ARENA_HEADER_SIZE);
arena->buffer = buffer;
arena->length = size;
arena->pos = 0;
return arena;
}
static Arena *
ArenaCreate(usize size)
{
u8 *mem = pMemAllocZeroed(size);
return ArenaInit(mem, size);
}
static Arena *
ArenaCreateDebug(usize size, u32 init_line_no)
{
u8 *mem = pMemAllocZeroed(size);
return ArenaInitDebug(mem, size, init_line_no);
}
// TODO: investigate overflows when out of memory because something bad is going on
static rawptr
ArenaAllocAlign(Arena *arena, usize size, usize align)
{
rawptr ptr = NULL;
uintptr curr_ptr = (uintptr)arena->buffer + (uintptr)arena->pos;
uintptr offset = AlignPow2(curr_ptr, align);
offset -= (uintptr)arena->buffer;
if (offset+size <= arena->length)
{
ptr = &arena->buffer[offset];
arena->pos = offset+size;
}
else
{
Printfln("Out of memory: %d", arena->init_line_no);
Assert(0, "Memory Failure");
}
return ptr;
}
static rawptr
ArenaAlloc(Arena *arena, usize size)
{
return ArenaAllocAlign(arena, size, DEFAULT_ALIGNMENT);
}
static void
ArenaFree(Arena *arena)
{
arena->pos = 0;
}
static void
ArenaFreeZeroed(Arena *arena)
{
MemZero(arena->buffer, arena->pos);
ArenaFree(arena);
}
static void
DeallocArena(Arena *arena)
{
pMemFree(arena, arena->length);
}
static Arena *
ArenaInitDebug(rawptr buffer, usize size, u32 init_line_no)
{
Arena *arena = ArenaInit(buffer, size);
arena->init_line_no = init_line_no;
return arena;
}
// ::Allocator::Arena::End::
// ::Allocator::GlobalAlloc::Start::
static void
InitAllocator(usize init_size)
{
ALLOC.grow_size = init_size;
ALLOC.buffer = pMemAllocZeroed(init_size);
ALLOC.size = init_size;
ALLOC.free_size = init_size;
ALLOC.hash_table = FLMemAlloc(sizeof(HashTable));
HashTableInit(ALLOC.hash_table, 32);
ALLOC.tree = FLMemAlloc(sizeof(RBTree));
RBTreeInit(ALLOC.tree);
RBTreeInsert(ALLOC.tree, init_size, ALLOC.buffer);
}
static void
DeinitAlloc()
{
pMemFree(ALLOC.buffer, ALLOC.size);
}
static rawptr
Alloc(usize size)
{
return AllocAlign(size, DEFAULT_ALIGNMENT);
}
static rawptr
AllocAlign(usize size, usize alignment)
{
if (size == 0) return NULL;
RBNode *node = P_RB_NIL;
rawptr mem = NULL;
if (!RBTreeSearchNearest(ALLOC.tree, size + alignment, &node))
{
AllocGrow(size);
RBTreeSearchNearest(ALLOC.tree, size + alignment, &node);
}
u64 alloc_size = node->key;
rawptr free_alloc = node->bucket.last->data;
RBTreeDelete(ALLOC.tree, alloc_size, free_alloc);
usize padding = CalcPadding(uintptr(free_alloc), alignment);
uintptr new_addr = uintptr(free_alloc) + size + padding;
RBTreeInsert(ALLOC.tree, alloc_size - size - padding, rawptr(new_addr));
HashTablePushRawptrU64(ALLOC.hash_table, free_alloc, size + padding);
return free_alloc;
}
// TODO: finish allocator
// need an idea
static void
Free(rawptr ptr)
{
if (ptr == NULL) return;
}
static void
AllocGrow(usize size)
{
usize grow_size = size < ALLOC.grow_size ? ALLOC.grow_size : ALLOC.grow_size + size;
pMemRealloc(ALLOC.buffer, ALLOC.size, ALLOC.size + grow_size);
RBTreeInsert(ALLOC.tree, grow_size, ALLOC.buffer + ALLOC.size); // TODO: check this if things fuck up it could be wrong
ALLOC.size += grow_size;
ALLOC.free_size += grow_size;
}
// ::Allocator::GlobalAlloc::End::
// ::Allocator::FreeList::Start::
static void
GlobalFreeListInit(usize size)
{
FreeListInit(&FL_ALLOC, size);
FL_GLOBAL_INIT = true;
}
static rawptr
FLMemAlloc(usize size)
{
if (!FL_GLOBAL_INIT)
{
GlobalFreeListInit(FL_GLOBAL_SIZE);
}
return FreeListAlloc(&FL_ALLOC, size);
}
static rawptr
FLMemAllocZeroed(usize size)
{
rawptr ptr = FLMemAlloc(size);
MemZero(ptr, size);
return ptr;
}
static rawptr
FLMemRealloc(rawptr old_ptr, usize size)
{
if (!FL_GLOBAL_INIT)
{
GlobalFreeListInit(FL_GLOBAL_SIZE);
}
rawptr ptr = NULL;
if (old_ptr == NULL)
ptr = FLMemAlloc(size);
else
ptr = FreeListRealloc(&FL_ALLOC, old_ptr, size);
return ptr;
}
static void
FLMemFree(rawptr ptr)
{
if (!FL_GLOBAL_INIT)
{
GlobalFreeListInit(FL_GLOBAL_SIZE);
}
FreeListFree(&FL_ALLOC, ptr);
}
/*
* Should be async safe given no other thread frees a pointer in the middle of a realloc
*/
static rawptr
FreeListRealloc(FLAlloc *alloc, rawptr old_ptr, usize size)
{
rawptr ptr = FreeListAlloc(alloc, size);
usize old_size = FreeListPtrSize(alloc, old_ptr);
MemCpy(ptr, old_ptr, old_size);
FreeListFree(alloc, old_ptr);
return ptr;
}
static usize
FreeListPtrSize(FLAlloc *alloc, rawptr ptr)
{
if (ptr == NULL) return 0;
usize size = 0;
TicketMutLock(&alloc->mut);
FreeList *list = _FreeListFindList(alloc, ptr);
if (list != NULL)
{
FLAllocHeader *header = cast(FLAllocHeader *, u8ptr(ptr) - sizeof(FLAllocHeader));
size = header->size + header->padding;
}
TicketMutUnlock(&alloc->mut);
return size;
}
static void
FreeListInit(FLAlloc *alloc, usize size)
{
alloc->list_head = pMemAllocZeroed(sizeof(FreeList));
alloc->nil = &FL_NIL_NODE;
alloc->grow_size = size;
_FreeListInit(&alloc->list_head, size);
FreeListFreeAll(alloc);
}
static void
_FreeListInit(FreeList **alloc, usize size)
{
*alloc = (FreeList *)pMemAllocZeroed(size);
(*alloc)->data = (rawptr)(((uintptr)*alloc) + ((uintptr)sizeof(FreeList)));
(*alloc)->size = size;
(*alloc)->used = sizeof(FreeList);
(*alloc)->next = &FL_NIL_LIST;
}
static void
FreeListFreeAll(FLAlloc *alloc)
{
TicketMutLock(&alloc->mut);
FreeList *current = alloc->list_head->next;
FreeList *next = &FL_NIL_LIST;
while (current != &FL_NIL_LIST)
{
next = current->next;
pMemFree(current, current->size);
current = next;
}
current = alloc->list_head;
FLNode *node = (FLNode *)current->data;
node->size = current->size;
node->next = &FL_NIL_NODE;
current->head = node;
current->used = sizeof(FreeList);
TicketMutUnlock(&alloc->mut);
}
static FLNode *
FreeListSearch(FreeList *alloc, usize size, usize alignment, usize *out_padding, FLNode **prev_node)
{
FLNode *node = alloc->head;
FLNode *prev = &FL_NIL_NODE;
usize padding = 0;
while (node != &FL_NIL_NODE)
{
padding = CalcPaddingWithHeader((uintptr)node, (uintptr)alignment, sizeof(FLNode));
usize required_size = size + padding;
if (node->size >= required_size)
break;
prev = node;
node = node->next;
}
if (out_padding)
*out_padding = padding;
if (prev_node)
*prev_node = prev;
return node;
}
/*
* NOT SAFE TO CALL OUTSIDE OF FreeListAlloc
*/
static FreeList *
FreeListGrow(FLAlloc *alloc, usize alloc_size)
{
usize grow_size = alloc->grow_size;
if (alloc_size > grow_size)
grow_size += alloc_size;
FreeList *list = NULL;
_FreeListInit(&list, grow_size);
FLNode *node = (FLNode *)list->data;
node->size = list->size;
node->next = alloc->nil;
list->head = node;
FreeList *current = alloc->list_head;
while (current != &FL_NIL_LIST)
{
if (current->next == &FL_NIL_LIST)
{
current->next = list;
break;
}
current = current->next;
}
return list;
}
static rawptr
_FreeListAllocAlign(FreeList *alloc, usize size, usize alignment)
{
if (size == 0) return NULL;
usize padding = 0;
FLNode *prev_node = &FL_NIL_NODE;
FLAllocHeader *header;
if (size < sizeof(FLNode))
size = sizeof(FLNode);
if (alignment < 8)
alignment = 8;
FLNode *node = FreeListSearch(alloc, size, alignment, &padding, &prev_node);
if (node == &FL_NIL_NODE)
Assert(0, "FreeListAllocAlign failed to allocate, oom");
usize alignment_padding = padding - sizeof(FLAllocHeader);
usize required_space = size + padding;
usize remaining = node->size - required_space;
if (remaining > 0)
{
FLNode *new_node = (FLNode *)(((c8 *)node) + required_space);
new_node->size = remaining;
FreeListInsert(&alloc->head, node, new_node);
}
FreeListRemove(&alloc->head, prev_node, node);
header = (FLAllocHeader *)(((c8 *)node) + alignment_padding);
header->size = required_space;
header->padding = alignment_padding;
alloc->used += required_space;
return (rawptr)(((c8 *)header) + sizeof(FLAllocHeader));
}
static rawptr
FreeListAlloc(FLAlloc *alloc, usize size)
{
return FreeListAllocAlign(alloc, size, DEFAULT_ALIGNMENT);
}
static rawptr
FreeListAllocAlign(FLAlloc *alloc, usize size, usize alignment)
{
TicketMutLock(&alloc->mut);
FreeList *fl = &FL_NIL_LIST;
FreeList *current = alloc->list_head;
while (current != &FL_NIL_LIST)
{
usize remaining = current->size - current->used;
if (size < remaining)
{
fl = current;
break;
}
current = current->next;
}
if (fl == &FL_NIL_LIST)
{
fl = FreeListGrow(alloc, size);
}
rawptr ptr = _FreeListAllocAlign(fl, size, alignment);
TicketMutUnlock(&alloc->mut);
return ptr;
}
static FreeList *
_FreeListFindList(FLAlloc *alloc, rawptr ptr)
{
FreeList *list = NULL;
FreeList *current = alloc->list_head;
while (current != &FL_NIL_LIST)
{
uintptr ptr_addr = uintptr(ptr);
uintptr start = uintptr(current->data);
uintptr end = uintptr(current->data) + uintptr(current->size);
if (ptr_addr >= start && ptr_addr < end)
{
list = current;
break;
}
}
return list;
}
static void
_FreeListFree(FreeList *alloc, rawptr ptr)
{
FLAllocHeader *header = cast(FLAllocHeader *, u8ptr(ptr) - sizeof(FLAllocHeader));
FLNode *free_node = cast(FLNode *,header);
free_node->size = header->size + header->padding;
free_node->next = &FL_NIL_NODE;
FLNode *prev_node = &FL_NIL_NODE;
FLNode *node = alloc->head;
while (node != &FL_NIL_NODE)
{
if (ptr < node)
{
FreeListInsert(&alloc->head, prev_node, free_node);
break;
}
prev_node = node;
node = node->next;
}
alloc->used -= free_node->size;
FreeListCoalescence(alloc, prev_node, free_node);
}
static void
FreeListFree(FLAlloc *alloc, rawptr ptr)
{
if (ptr == NULL) return;
TicketMutLock(&alloc->mut);
FreeList *list = _FreeListFindList(alloc, ptr);
if (list != NULL)
{
_FreeListFree(list, ptr);
}
TicketMutUnlock(&alloc->mut);
}
static void
FreeListCoalescence(FreeList *alloc, FLNode *prev_node, FLNode *free_node)
{
if (free_node->next != &FL_NIL_NODE && (rawptr)(((c8 *)free_node) + free_node->size) == free_node->next)
{
free_node->size += free_node->next->size;
FreeListRemove(&alloc->head, free_node, free_node->next);
}
if (prev_node->next != &FL_NIL_NODE && (rawptr)(((c8 *)prev_node) + prev_node->size) == free_node)
{
prev_node->size += free_node->next->size;
FreeListRemove(&alloc->head, prev_node, free_node);
}
}
static void
FreeListRemove(FLNode **head, FLNode *prev_node, FLNode *del_node)
{
if (prev_node == &FL_NIL_NODE)
*head = del_node->next;
else
prev_node->next = del_node->next;
}
static void
FreeListInsert(FLNode **head, FLNode *prev_node, FLNode *new_node)
{
if (prev_node == &FL_NIL_NODE)
{
if (*head != &FL_NIL_NODE)
{
new_node->next = *head;
*head = new_node;
}
else
*head = new_node;
}
else
{
new_node->next = prev_node->next;
prev_node->next = new_node;
}
}
// ::Allocator::FreeList::End::

View File

@ -1,114 +0,0 @@
#pragma once
// ::Allocator::Util::Header::
static inline usize CalcPaddingWithHeader(uintptr ptr, uintptr alignment, usize header_size);
static inline usize CalcPadding(uintptr ptr, uintptr alignment);
// ::Allocator::Arena::Header::
#define ARENA_HEADER_SIZE 32
typedef struct Arena
{
u8 *buffer;
usize length;
usize pos;
u32 init_line_no;
} Arena;
typedef struct TempArena
{
Arena *arena;
u64 pos;
} TempArena;
static Arena *ArenaInit(rawptr buffer, usize size);
static Arena *ArenaCreate(usize size);
static Arena *ArenaCreateDebug(usize size, u32 init_line_no);
static Arena *ArenaInitDebug(rawptr buffer, usize size, u32 init_line_no);
static rawptr ArenaAllocAlign(Arena *arena, usize size, usize align);
static rawptr ArenaAlloc(Arena *arena, usize size);
static void ArenaFree(Arena *arena);
static void ArenaFreeZeroed(Arena *arena);
static void DeallocArena(Arena *arena);
// ::Allocator::GlobalAlloc::Header::
typedef struct AllocInfo
{
rawptr ptr;
struct AllocInfo *next;
} AllocInfo;
typedef struct Allocator
{
RBTree *tree;
RBTree *used_tree;
HashTable *hash_table;
rawptr buffer;
u64 size;
u64 free_size;
u64 grow_size;
} Allocator;
static void InitAllocator(usize init_size);
static void DeinitAlloc();
static void AllocGrow(usize size);
static rawptr Alloc(usize size);
static rawptr AllocAlign(usize size, usize alignment);
static void Free(rawptr ptr);
// ::Allocator::FreeList::Header::
typedef struct FLAllocHeader
{
usize size;
usize padding;
} FLAllocHeader;
typedef struct FLNode
{
struct FLNode *next;
usize size;
} FLNode;
typedef struct FreeList
{
rawptr data;
FLNode *head;
usize size;
usize used;
struct FreeList *next;
} FreeList;
typedef struct FLAlloc
{
FreeList *list_head;
TicketMut mut;
FLNode *nil;
usize grow_size;
} FLAlloc;
static void GlobalFreeListInit(usize size);
static rawptr FLMemAlloc(usize size);
static rawptr FLMemAllocZeroed(usize size);
static rawptr FLMemRealloc(rawptr old_ptr, usize size);
static void FLMemFree(rawptr ptr);
static usize FreeListPtrSize(FLAlloc *alloc, rawptr ptr);
static void FreeListInit(FLAlloc *alloc, usize size);
static rawptr FreeListAllocAlign(FLAlloc *alloc, usize size, usize alignment);
static rawptr FreeListAlloc(FLAlloc *alloc, usize size);
static void FreeListFree(FLAlloc *alloc, rawptr ptr);
static void FreeListFreeAll(FLAlloc *alloc);
static FreeList *FreeListGrow(FLAlloc *alloc, usize alloc_size);
static rawptr FreeListRealloc(FLAlloc *alloc, rawptr old_ptr, usize size);
static FLNode *FreeListSearch(FreeList *alloc, usize size, usize alignment, usize *out_padding, FLNode **prev_node);
static void FreeListCoalescence(FreeList *alloc, FLNode *prev_node, FLNode *free_node);
static void FreeListRemove(FLNode **head, FLNode *prev_node, FLNode *del_node);
static void FreeListInsert(FLNode **head, FLNode *prev_node, FLNode *new_node);
static FreeList *_FreeListFindList(FLAlloc *alloc, rawptr ptr);
static void _FreeListInit(FreeList **alloc, usize size);
static rawptr _FreeListAllocAlign(FreeList *alloc, usize size, usize alignment);
static void _FreeListFree(FreeList *alloc, rawptr ptr);

View File

@ -65,11 +65,7 @@ static void apInit()
Assert(File_Header.magic_num == CreateMagicValue('s', 't', 'e', 'g'), "Magic value is incorrect");
MemCpy(Texture_Assets, &ASSET_PACK[File_Header.asset_offsets[TEXTURE_ASSET]], sizeof(AssetFile) * File_Header.asset_counts[TEXTURE_ASSET]);
MemCpy(Shader_Assets, &ASSET_PACK[File_Header.asset_offsets[SHADER_ASSET]], sizeof(AssetFile) * File_Header.asset_counts[SHADER_ASSET]);
MemCpy(Model_Assets, &ASSET_PACK[File_Header.asset_offsets[MODEL_ASSET]], sizeof(AssetFile) * File_Header.asset_counts[MODEL_ASSET]);
MemCpy(Texture_Assets, &ASSET_PACK[File_Header.asset_offset], sizeof(AssetFile) * File_Header.asset_counts);
ASSET_HEADER_LOADED = true;
}
@ -97,9 +93,7 @@ apLoadS8(String8 str)
static void
apUnload(c8 *str)
{
Asset asset = {0};
return asset;
}
static void

View File

@ -7,12 +7,24 @@
#define CreateMagicValue(a, b, c, d) ((u32)(d << 24) | (u32)(c << 16) | (u32)(b << 8) | (u32)(a))
// ::Assets::Globals::Header::
#ifndef BUILD_ASSET_CODEGEN
# include "codegen_assets.h"
#endif
#include "codegen_assets.h"
// ::Assets::Types::Header::
typedef struct Vertex
{
Vec4 pos;
Vec4 col;
} Vertex;
typedef struct m3dModel
{
Vertex *vertices;
u32 *indices;
u64 v_count;
u64 i_count;
} m3dModel;
typedef struct TexMeta
{
u32 w;
@ -22,9 +34,18 @@ typedef struct TexMeta
typedef struct ModelMeta
{
u32 i_count;
u64 i_count;
} ModelMeta;
typedef struct AssetMeta
{
union
{
TexMeta texture;
ModelMeta model;
};
} AssetMeta;
typedef struct Asset
{
union
@ -41,24 +62,33 @@ typedef struct AssetTag
f32 value;
} AssetTag;
typedef enum AssetType_e
{
AT_NONE,
AT_SHADER,
AT_TEXTURE,
AT_MODEL,
} AssetType;
typedef struct AssetFile
{
union
{
TexMeta texture_meta;
ModelMeta model_meta;
};
u64 hash;
u64 data_offset;
u64 len;
union
{
TexMeta texture_meta;
ModelMeta model_meta;
};
AssetType type;
} AssetFile;
typedef struct FileHeader
{
u32 magic_num;
u32 version;
u32 asset_counts[ASSET_TYPE_MAX];
u64 asset_offsets[ASSET_TYPE_MAX];
u32 asset_counts;
u64 asset_offset;
} FileHeader;
// ::Assets::Init::Functions::Header::

159
src/codegen.c Normal file
View File

@ -0,0 +1,159 @@
#include "codegen.h"
u64
WriteArrayToFile(Arena *arena, pFile file, String8 array_name, rawptr elements, u32 count, String8 type, u64 offset)
{
b32 is_string = StrEq(type.value, "c8 *");
c8 *decl = MakeArray(arena, c8, 2048);
i32 decl_len = SPrintf(decl, 2048, "static %s\n%s[] = \n{\n\t", type.value, array_name.value);
String8 result = {
.value = decl,
.len = u64(decl_len),
};
if (is_string)
{
String8 *strs = (String8 *)elements;
for (u32 i = 0; i < count; i += 1)
{
c8 *f = i == count-1 ? "\"%s\"," : "\"%s\",\n\t";
c8 buf[512];
decl_len = SPrintf(buf, 512, f, strs[i].value);
result = String8Concat(arena, result, MakeString8(buf, decl_len));
}
}
else
{
u64 *ints = (u64 *)elements;
for (u32 i = 0; i < count; i += 1)
{
c8 *f = i == count-1 ? "%lluU," : "%lluU,\n\t";
c8 buf[512];
decl_len = SPrintf(buf, 512, f, ints[i]);
result = String8Concat(arena, result, MakeString8(buf, decl_len));
}
}
result = String8Concat(arena, result, String8CStr("\n};\n\n"));
return pFileWrite(file, offset, result.value, result.len);
}
static String8 *
ConvertCStrs(Arena *arena, c8 **strs, u32 count)
{
String8 *str8s = MakeArray(arena, String8, count);
for (u32 i = 0; i < count; i += 1)
{
str8s[i].value = strs[i];
str8s[i].len = StrLen(strs[i]);
}
return str8s;
}
void
CodeGenAssetLookups(Arena *arena)
{
pFile file = pFileOpen("../src/codegen_assets.h", pFS_WRITE | pFS_CREATE | pFS_TRUNC);
Assert(file > 0, "CodeGenAssetLookups failure: unable to open/create file");
Assert(pDirNavigate("../assets") == 0, "Unable to navigate to asset directory");
struct AssetDirInfo {
c8 *prefix, *struct_name, *hash_struct_name, *dir, *define;
};
struct AssetDirInfo dirs[] = {
{
.prefix = "shaders/",
.struct_name = "g_Shader_Asset_Names",
.hash_struct_name = "g_Shader_Asset_Hashes",
.dir = "shaders",
.define = "SHADER_ASSET",
},
{
.prefix = "models/",
.struct_name = "g_Model_Asset_Names",
.hash_struct_name = "g_Model_Asset_Hashes",
.dir = "models",
.define = "MODEL_ASSET",
},
{
.prefix = "textures/",
.struct_name = "g_Texture_Asset_Names",
.hash_struct_name = "g_Texture_Asset_Hashes",
.dir = "textures",
.define = "TEXTURE_ASSET",
},
};
u64 offset = 0;
u32 dir_count = sizeof(dirs) / sizeof(struct AssetDirInfo);
for (u32 i = 0; i < dir_count; i += 1)
{
Assert(pDirNavigate(dirs[i].dir) == 0, "Unable to navigate to asset sub directory.");
u32 count = 0;
c8 **cstrs = pDirGetFileNames(arena, &count);
u64 *hashes = MakeArray(arena, u64, count);
String8 *strs = ConvertCStrs(arena, cstrs, count);
for (u32 j = 0; j < count; j += 1)
{
strs[j] = String8Concat(arena, String8CStr(dirs[i].prefix), strs[j]);
i64 offset = String8FindLast(strs[j], '.');
hashes[j] = XXH3_64bits_withSeed(strs[j].value, strs[j].len - offset, HASH_SEED);
}
offset += WriteArrayToFile(
arena,
file,
String8CStr(dirs[i].struct_name),
strs,
count,
String8CStr("c8 *"),
offset
);
offset += WriteArrayToFile(
arena,
file,
String8CStr(dirs[i].hash_struct_name),
hashes,
count,
String8CStr("u64"),
offset
);
c8 buf[256];
i32 decl_len = SPrintf(buf, 256, "#define %s_MAX %llu\n\n#define %s %d\n\n", dirs[i].define, count, dirs[i].define, i);
offset += pFileWrite(file, offset, buf, decl_len);
Assert(pDirNavigate("..") == 0, "CodeGenAssetLookups failure: unable to move back to build directory");
}
pFileClose(file);
}
int
main(int argc, c8 **argv)
{
#ifdef _WIN32
{
_set_fmode(_O_BINARY);
}
#endif
if (pDirIsVisible("build"))
{
Assert(pDirNavigate("./build") == 0, "Unable to change to build directory");
}
void *mem = pMemAllocZeroed(GB(1));
Arena *arena = ArenaInitDebug(mem, GB(1), __LINE__);
CodeGenAssetLookups(arena);
}

8
src/codegen.h Normal file
View File

@ -0,0 +1,8 @@
#pragma once
#define _GNU_SOURCE
#define STG_IMPLEMENTATION
#include "stglib.h"

View File

@ -1,66 +1,72 @@
static c8 *
g_Shader_Asset_Names[] =
{
"shaders/gui.frag",
"shaders/pbr.frag",
"shaders/gui.vert",
"shaders/quad.frag",
"shaders/quad.vert",
"shaders/pbr.vert",
"shaders/gui.frag.spv",
"shaders/pbr.frag.spv",
"shaders/gui.vert.spv",
"shaders/quad.frag.spv",
"shaders/quad.vert.spv",
"shaders/pbr.vert.spv",
};
static u64
g_Shader_Asset_Hashes[] =
{
4076561469468128204U,
12546533630435803654U,
17203805968697784249U,
1277283055956479971U,
12273814537638279648U,
1941995729991819811U,
12100337026595633089U,
12100337026595633089U,
12100337026595633089U,
12100337026595633089U,
12100337026595633089U,
12100337026595633089U,
};
#define SHADER_ASSET_MAX 6
#define SHADER_ASSET 0
static c8 *
g_Model_Asset_Names[] =
{
"models/test_char",
"models/yoda",
"models/test_char.m3d",
"models/yoda.m3d",
};
static u64
g_Model_Asset_Hashes[] =
{
17106564331948230266U,
1379945611816585992U,
2356409063604999112U,
2356409063604999112U,
};
#define MODEL_ASSET_MAX 2
#define MODEL_ASSET 1
static c8 *
g_Texture_Asset_Names[] =
{
"textures/ham_smoke",
"textures/cheesoid",
"textures/hog",
"textures/patamon",
"textures/pattermon",
"textures/hamster",
"textures/purplemon",
"textures/ham_smoke.png",
"textures/cheesoid.png",
"textures/hog.jpg",
"textures/patamon.png",
"textures/pattermon.png",
"textures/hamster.png",
"textures/purplemon.png",
};
static u64
g_Texture_Asset_Hashes[] =
{
3672471465693847963U,
17853259469867187617U,
12925726572206082157U,
1223697967736380744U,
16704275018603890077U,
13194708417649827129U,
12400748618931758111U,
5461253849680765905U,
5461253849680765905U,
5461253849680765905U,
5461253849680765905U,
5461253849680765905U,
5461253849680765905U,
5461253849680765905U,
};
#define TEXTURE_ASSET_MAX 7
#define TEXTURE_ASSET 2

674
src/ds.c
View File

@ -1,674 +0,0 @@
// ::DataStructures::Globals::Start::
RBNode
RB_NIL = { .color = RB_BLACK };
RBNode *
P_RB_NIL = &RB_NIL;
RBDataNode
RB_DN_NIL = {0};
RBDataNode *
P_RB_DN_NIL = &RB_DN_NIL;
HashNode
HT_NIL = {0};
HashNode *
P_HT_NIL = &HT_NIL;
// ::DataStructures::Globals::End::
// ::DataStructures::RedBlackTree::Functions::Start::
static void
RBTreeInit(RBTree *tree)
{
Assert(tree != NULL, "RBTree is null");
RB_NIL.right = RB_NIL.left = RB_NIL.parent = P_RB_NIL;
RB_DN_NIL.next = P_RB_DN_NIL;
tree->root = P_RB_NIL;
tree->nil = P_RB_NIL;
}
static inline void
RBTreePushDataNode(RBDataNode *first, RBDataNode *last, rawptr value)
{
RBDataNode *data_node = FLMemAllocZeroed(sizeof(RBDataNode));
data_node->data = value;
RBQueuePush(first, last, data_node);
}
static inline RBNode *
RBTreeInitNode(u64 key, rawptr value)
{
RBNode *node = FLMemAllocZeroed(sizeof(RBNode));
node->parent = node->left = node->right = P_RB_NIL;
node->color = RB_BLACK;
node->key = key;
RBTreePushDataNode(node->bucket.first, node->bucket.last, value);
return node;
}
static void
RBTreeInsert(RBTree *tree, u64 key, rawptr value)
{
RBNode *node = P_RB_NIL;
node->left = node->right = tree->nil;
node->color = RB_RED;
if (tree->root == tree->nil)
{
node->color = RB_BLACK;
node->parent = tree->nil;
tree->root = node;
}
else
{
RBNode *curr_node = tree->root;
while (true)
{
Assert(curr_node != tree->nil, "Current Node is NIL");
if (curr_node->key == key)
{
RBTreePushDataNode(curr_node->bucket.first, curr_node->bucket.last, value);
break;
}
else if (curr_node->key < key)
{
if (curr_node->right == tree->nil)
{
node = RBTreeInitNode(key, value);
node->parent = curr_node;
curr_node->right = node;
break;
}
else
{
curr_node = curr_node->right;
}
}
else
{
if (curr_node->left == tree->nil)
{
node = RBTreeInitNode(key, value);
node->parent = curr_node;
curr_node->left = node;
break;
}
else
{
curr_node = curr_node->left;
}
}
}
}
if (node->parent->color != RB_BLACK && node != P_RB_NIL)
RBTreeCorrect(tree, node);
}
static void
RBTreeCorrect(RBTree *tree, RBNode *node)
{
RBNode *gp = node->parent->parent;
RBNode *p = node->parent;
do
{
if (node == tree->root)
{
node->color = RB_BLACK;
break;
}
if (gp == tree->nil)
{
p->color = RB_BLACK;
break;
}
RBNodeDir dir = NodeDir(p);
RBNode *unc = gp->child[1 - dir];
if (unc == tree->nil || unc->color == RB_BLACK)
{
if (node == p->child[1 - dir])
{
RBTreeRotate(tree, p, dir);
node = p;
p = gp->child[dir];
}
RBTreeRotate(tree, gp, 1 - dir);
p->color = RB_BLACK;
gp->color = RB_RED;
break;
}
p->color = RB_BLACK;
unc->color = RB_BLACK;
gp->color = RB_RED;
node = gp;
gp = node->parent->parent;
} while ((p = node->parent));
}
static void
RBTreeDelete(RBTree *tree, u64 key, rawptr value)
{
RBNode *node = NULL;
Assert(RBTreeSearch(tree, key, &node), "Unable to find node in RBTreeDelete");
if (node->bucket.first->data != value)
{
Assert(node->bucket.first->next != P_RB_DN_NIL, "RBTreeDelete Failure: unable to find value to delete");
RBDataNode *data_node = node->bucket.first->next;
RBDataNode *prev_node = node->bucket.first;
while (data_node != P_RB_DN_NIL)
{
if (data_node->data == value)
{
prev_node->next = data_node->next;
if (data_node == node->bucket.last)
node->bucket.last = prev_node;
FLMemFree(data_node);
}
}
}
else
{
FLMemFree(node->bucket.first);
if (node == tree->root && node->left == tree->nil && node->right == tree->nil)
{
tree->root = tree->nil;
}
else if (node->left != tree->nil && node->right != tree->nil)
{
RBNode *ln = node->right;
while (ln->left != tree->nil)
ln = ln->left;
node->key = ln->key;
node->bucket = ln->bucket;
if (node->right == ln)
node->right = tree->nil;
else
ln->parent->left = tree->nil;
ln->parent = tree->nil;
}
else if (node->color == RB_BLACK && node->left != tree->nil)
{
node->key = node->left->key;
node->bucket = node->left->bucket;
node->left = tree->nil;
}
else if (node->color == RB_BLACK && node->right != tree->nil)
{
node->key = node->right->key;
node->bucket = node->right->bucket;
node->right = tree->nil;
}
else if (node->color == RB_RED && node->right == tree->nil && node->left == tree->nil)
{
RBNodeDir dir = NodeDir(node);
node->parent->child[dir] = tree->nil;
}
else
{
RBNode *p = node->parent;
RBNodeColor col = node->color;
RBNode *s, *cn, *dn;
RBNodeDir dir = NodeDir(node);
p->child[dir] = tree->nil;
goto start_deletion;
do
{
dir = NodeDir(node);
start_deletion:
s = p->child[1 - dir];
dn = s->child[1 - dir];
cn = s->child[dir];
if (s->color == RB_RED)
{
RBTreeRotate(tree, p, dir);
p->color = RB_RED;
s->color = RB_BLACK;
s = cn;
dn = s->child[1 - dir];
if (dn->color == RB_RED)
goto rotate_sibling;
cn = s->child[dir];
if (cn->color == RB_RED)
goto rotate_parent;
s->color = RB_RED;
p->color = RB_BLACK;
return;
}
if (dn->color == RB_RED)
goto rotate_parent;
if (cn->color == RB_RED)
goto rotate_sibling;
if (p->color == RB_RED)
{
s->color = RB_RED;
p->color = RB_BLACK;
return;
}
if (p == tree->nil)
return;
s->color = RB_RED;
node = p;
} while ((p = node->parent));
rotate_sibling:
RBTreeRotate(tree, s, 1 - dir);
s->color = RB_RED;
cn->color = RB_BLACK;
dn = s;
s = cn;
rotate_parent:
RBTreeRotate(tree, p, dir);
s->color = p->color;
p->color = RB_BLACK;
dn->color = RB_BLACK;
}
}
}
static b32
RBTreeSearchNearest(RBTree *tree, u64 key, RBNode **out_node)
{
if (tree->root == tree->nil) return false;
RBNode *node = tree->root;
RBNode *nearest = tree->root;
u64 nearest_diff = UINT64_MAX;
while (true)
{
if (node == tree->nil)
break;
u64 diff = node->key - key;
diff = Absu64(diff);
if (diff == 0)
{
nearest = node;
break;
}
if (diff < nearest_diff)
{
nearest_diff = diff;
nearest = node;
}
if (node->key < key)
node = node->right;
else
node = node->left;
}
*out_node = nearest != tree->nil ? nearest : tree->nil;
return *out_node != tree->nil;
}
static b32
RBTreeSearch(RBTree *tree, u64 key, RBNode **out_node)
{
if (tree->root == tree->nil) return false;
b32 found = false;
RBNode *node = tree->root;
while (true)
{
if (node->key == key)
{
found = true;
break;
}
if (node == tree->nil)
break;
if (node->key < key)
node = node->right;
else
node = node->left;
}
if (found)
*out_node = node;
return found;
}
static inline void
RBTreeTransplant(RBTree *tree, RBNode *node, RBNode *placed_node)
{
if (node->parent == tree->nil)
tree->root = placed_node;
else if (node == node->parent->left)
node->parent->left = placed_node;
else
node->parent->right = placed_node;
placed_node->parent = node->parent;
}
static void
RBTreeRotate(RBTree *tree, RBNode *node, RBNodeDir dir)
{
RBNode *p = node->parent;
RBNode *root = node->child[1 - dir];
RBNode *child = root->child[dir];
node->child[1 - dir] = child;
if (child != tree->nil)
child->parent = node;
root->child[dir] = node;
root->parent = p;
node->parent = root;
if (p != tree->nil)
p->child[node == p->right] = root;
else
tree->root = root;
}
static void
RBTreeLeftRotate(RBTree *tree, RBNode *node)
{
RBNode *right = node->right;
if (right->left != tree->nil)
node->right = right->left;
if (node->parent == tree->nil)
tree->root = right;
else if (node->parent->left == node)
node->parent->left = right;
else
node->parent->right = right;
right->parent = node->parent;
right->left = node;
node->parent = right;
}
static void
RBTreeRightRotate(RBTree *tree, RBNode *node)
{
RBNode *left = node->left;
if (left->right != tree->nil)
node->left = left->right;
if (node->parent == tree->nil)
tree->root = left;
else if (node->parent->left == node)
node->parent->left = left;
else
node->parent->right = left;
left->parent = node->parent;
left->right = node;
node->parent = left;
}
// ::DataStructures::RedBlackTree::Functions::End::
// ::DataStructures::HashTable::Functions::Start::
static void
HashTableInit(HashTable *table, u32 init_size)
{
table->cap = init_size;
table->count = 0;
table->free_lists.first = P_HT_NIL;
table->free_lists.last = P_HT_NIL;
table->lists = FLMemAlloc(sizeof(HashList) * init_size);
for (u32 i = 0; i < init_size; i++)
{
table->lists[i].first = P_HT_NIL;
table->lists[i].last = P_HT_NIL;
}
}
static void
HashTableConcatInPlace(HashList *list, HashList *to_concat)
{
SLLConcatInPlaceNoCount(list, to_concat);
}
static void
HashTableClear(HashTable *table)
{
table->count = 0;
for (u32 i = 0; i < table->count; i++)
{
HashTableConcatInPlace(&table->free_lists, &table->lists[i]);
}
}
static HashNode *
HashListPop(HashList *list)
{
HashNode *result = list->first;
HTQueuePop(list->first, list->last);
return result;
}
static HashNode *
HashTablePush(HashTable *table, u64 hash, KeyValuePair value)
{
HashNode *node = NULL;
if (table->free_lists.first != P_HT_NIL)
node = HashListPop(&table->free_lists);
else
node = FLMemAlloc(sizeof(HashNode));
node->next = P_HT_NIL;
node->v = value;
u64 index = hash % table->cap;
HTQueuePush(table->lists[index].first, table->lists[index].last, node);
table->count += 1;
return node;
}
static HashNode *
HashTablePushU64U32(HashTable *table, u64 key, u32 value)
{
u64 hash = HashFromString(String8Struct(&key));
return HashTablePush(table, hash, (KeyValuePair){ .key_u64 = key, .value_u32 = value });
}
static HashNode *
HashTablePushU64U64(HashTable *table, u64 key, u64 value)
{
u64 hash = HashFromString(String8Struct(&key));
return HashTablePush(table, hash, (KeyValuePair){ .key_u64 = key, .value_u64 = value });
}
static HashNode *
HashTablePushU64String8(HashTable *table, u64 key, String8 value)
{
u64 hash = HashFromString(String8Struct(&key));
return HashTablePush(table, hash, (KeyValuePair){ .key_u64 = key, .value_string = value });
}
static HashNode *
HashTablePushU64Rawptr(HashTable *table, u64 key, rawptr value)
{
u64 hash = HashFromString(String8Struct(&key));
return HashTablePush(table, hash, (KeyValuePair){ .key_u64 = key, .value_rawptr = value });
}
static HashNode *
HashTablePushU64U64Split(HashTable *table, u64 key, u32 upper, u32 lower)
{
u64 hash = HashFromString(String8Struct(&key));
return HashTablePush(table, hash, (KeyValuePair){ .key_u64 = key, .value_u64_split = { .upper = upper, .lower = lower }});
}
static HashNode *
HashTablePushRawptrU64(HashTable *table, rawptr key, u64 value)
{
u64 hash = HashFromString(String8Struct(&key));
return HashTablePush(table, hash, (KeyValuePair){ .key_rawptr = key, .value_u64 = value });
}
static KeyValuePair *
HashTableSearchU64(HashTable *table, u64 key)
{
KeyValuePair *result = NULL;
u64 hash = HashFromString(String8Struct(&key));
u64 index = hash % table->cap;
HashList *list = table->lists + index;
for (HashNode *node = list->first; node != P_HT_NIL; node = node->next)
{
if (node->v.key_u64 == key)
{
result = &node->v;
break;
}
}
return result;
}
static KeyValuePair *
HashTableSearchRawptr(HashTable *table, rawptr key)
{
KeyValuePair *result = NULL;
u64 hash = HashFromString(String8Struct(&key));
u64 index = hash % table->cap;
HashList *list = table->lists + index;
for (HashNode *node = list->first; node != P_HT_NIL; node = node->next)
{
if (node->v.key_rawptr == key)
{
result = &node->v;
break;
}
}
return result;
}
static void
HashTableDeleteU64(HashTable *table, u64 key)
{
u64 hash = HashFromString(String8Struct(&key));
u64 index = hash % table->cap;
HashList *list = table->lists + index;
HashNode *prev = P_HT_NIL;
for (HashNode *node = list->first; node != P_HT_NIL; node = node->next)
{
if (node->v.key_u64 == key)
{
if (prev != P_HT_NIL)
prev->next = node->next;
node->v.key_u64 = 0;
node->v.value_u64 = 0;
HTQueuePush(table->free_lists.first, table->free_lists.last, node);
break;
}
}
}
static rawptr
HashTableDeleteU64Rawptr(HashTable *table, u64 key)
{
rawptr value = NULL;
u64 hash = HashFromString(String8Struct(&key));
u64 index = hash % table->cap;
HashList *list = table->lists + index;
HashNode *prev = P_HT_NIL;
for (HashNode *node = list->first; node != P_HT_NIL; node = node->next)
{
if (node->v.key_u64 == key)
{
if (prev != P_HT_NIL)
prev->next = node->next;
value = node->v.value_rawptr;
node->v.key_u64 = 0;
node->v.value_rawptr = NULL;
HTQueuePush(table->free_lists.first, table->free_lists.last, node);
break;
}
}
return value;
}
static U64Split
HashTableDeleteU64U64Split(HashTable *table, u64 key)
{
U64Split value = { .upper = UINT32_MAX };
u64 hash = HashFromString(String8Struct(&key));
u64 index = hash % table->cap;
HashList *list = table->lists + index;
HashNode *prev = P_HT_NIL;
for (HashNode *node = list->first; node != P_HT_NIL; node = node->next)
{
if (node->v.key_u64 == key)
{
if (prev != P_HT_NIL)
prev->next = node->next;
value.upper = node->v.value_u64_split.upper;
value.lower = node->v.value_u64_split.lower;
node->v.key_u64 = 0;
node->v.value_u64_split.upper = 0;
node->v.value_u64_split.lower = 0;
HTQueuePush(table->free_lists.first, table->free_lists.last, node);
break;
}
}
return value;
}
// ::DataStructures::HashTable::Functions::End::

128
src/ds.h
View File

@ -1,128 +0,0 @@
#pragma once
// ::DataStructures::RedBlackTree::Header::
#define NodeDir(node) (node == node->parent->left ? RB_LEFT : RB_RIGHT)
#define RBQueuePop(f, l) SLLQueuePop(P_RB_DN_NIL, f, l)
#define RBQueuePush(f, l, n) SLLQueuePush(P_RB_DN_NIL, f, l, n)
#define RBQueuePushFront(f, l, n) SLLQueuePush(P_RB_DN_NIL, f, l, n)
typedef enum RBNodeColor_e
{
RB_RED,
RB_BLACK,
} RBNodeColor;
typedef enum RBNodeDir_e
{
RB_LEFT,
RB_RIGHT,
} RBNodeDir;
typedef struct RBDataNode
{
rawptr data;
struct RBDataNode *next;
} RBDataNode;
typedef struct RBBucket
{
RBDataNode *first;
RBDataNode *last;
} RBBucket;
typedef struct RBNode
{
union
{
struct
{
struct RBNode *left;
struct RBNode *right;
};
struct RBNode *child[2];
};
struct RBNode *parent;
u64 key;
RBBucket bucket;
RBNodeColor color;
} RBNode;
typedef struct RBTree
{
RBNode *root;
RBNode *nil;
} RBTree;
static void RBTreeInit (RBTree *tree);
static inline RBNode *RBTreeInitNode(u64 key, rawptr value);
static inline void RBTreePushDataNode(RBDataNode *first, RBDataNode *last, rawptr value);
static void RBTreeInsert(RBTree *tree, u64 key, rawptr value);
static b32 RBTreeSearchNearest(RBTree *tree, u64 key, RBNode **node);
static b32 RBTreeSearch (RBTree *tree, u64 key, RBNode **node);
static void RBTreeDelete (RBTree *tree, u64 key, rawptr value);
static void RBTreeLeftRotate (RBTree *tree, RBNode *node);
static void RBTreeRightRotate(RBTree *tree, RBNode *node);
static void RBTreeRotate (RBTree *tree, RBNode *node, RBNodeDir dir);
static void RBTreeCorrect (RBTree *tree, RBNode *node);
static void RBTreeTransplant (RBTree *tree, RBNode *node, RBNode *placed_node);
// ::DataStructures::HashTable::Functions::Header::
#define HTQueuePop(f, l) SLLQueuePop(P_HT_NIL, f, l)
#define HTQueuePush(f, l, n) SLLQueuePush(P_HT_NIL, f, l, n)
#define HTQueuePushFront(f, l, n) SLLQueuePush(P_HT_NIL, f, l, n)
typedef struct KeyValuePair
{
union
{
u64 key_u64;
rawptr key_rawptr;
};
union
{
String8 value_string;
rawptr value_rawptr;
u32 value_u32;
u64 value_u64;
U64Split value_u64_split;
};
} KeyValuePair;
typedef struct HashNode
{
struct HashNode *next;
KeyValuePair v;
} HashNode;
typedef struct HashList
{
HashNode *first;
HashNode *last;
} HashList;
typedef struct HashTable
{
HashList *lists;
HashList free_lists;
u64 count;
u32 cap;
} HashTable;
static void HashTableInit(HashTable *table, u32 init_size);
static void HashTableClear(HashTable *table);
static void HashTableConcatInPlace(HashList *list, HashList *to_concat);
static u64 HashTableHash(String8 str);
static HashNode *HashListPop(HashList *list);
static KeyValuePair *HashTableSearchU64(HashTable *table, u64 key);
static KeyValuePair *HashTableSearchRawptr(HashTable *table, rawptr key);
static HashNode *HashTablePush(HashTable *table, u64 hash, KeyValuePair value);
static HashNode *HashTablePushU64U32(HashTable *table, u64 key, u32 value);
static HashNode *HashTablePushU64U64(HashTable *table, u64 key, u64 value);
static HashNode *HashTablePushU64String8(HashTable *table, u64 key, String8 value);
static HashNode *HashTablePushU64Rawptr(HashTable *table, u64 key, rawptr value);
static HashNode *HashTablePushU64U64Split(HashTable *table, u64 key, u32 upper, u32 lower);
static rawptr HashTableDeleteU64Rawptr(HashTable *table, u64 key);
static void HashTableDeleteU64(HashTable *table, u64 key);

View File

@ -10,14 +10,9 @@ int PROGRAM_FAILED = false;
#include "entry_linux.h"
// ::ThirdParty::Include::
#include "xxhash/xxhash.c"
#include "fastlz/fastlz.c"
#include "platform/platform.c"
#include "util.c"
#include "assets.c"
#include "ds.c"
#include "allocators.c"
#include "renderer.c"
#include "game.c"
#ifdef BUILD_TEST

View File

@ -12,17 +12,14 @@
#define WINDOW_NAME "Video Game"
#include "shared_types.h"
#include "platform/platform.h"
#include "util.h"
#define STG_IMPLEMENTATION
#include "stglib.h"
#include "assets.h"
#include "ds.h"
#include "allocators.h"
// ::ThirdParty::Include::Header::
#include "stb/stb_sprintf.h"
#include "stb/stb_image.h"
#include "xxhash/xxhash.h"
#include "fastlz/fastlz.h"
#include "m3d/m3d.h"

View File

@ -2,7 +2,6 @@
#pragma once
#define STB_SPRINTF_IMPLEMENTATION
#define STB_IMAGE_IMPLEMENTATION
@ -16,7 +15,6 @@
#include "allocators.h"
// ::ThirdParty::Include::Header::
#include "stb/stb_sprintf.h"
#include "stb/stb_image.h"
#include "xxhash/xxhash.h"
#include "fastlz/fastlz.h"

View File

@ -2,16 +2,9 @@
#include "packer.h"
#include "xxhash/xxhash.c"
#include "fastlz/fastlz.c"
#include "platform/platform.c"
#include "assets.c"
#include "util.c"
#include "ds.c"
#include "allocators.c"
#include "renderer.c"
#include "game.c"
#ifdef _WIN32
# include <fcntl.h>
@ -19,168 +12,6 @@
// ::Packer::Packing::Functions::Start::
#ifdef BUILD_ASSET_CODEGEN
u64
WriteArrayToFile(Arena *arena, pFile file, String8 array_name, rawptr elements, u32 count, String8 type, u64 offset)
{
b32 is_string = StrEq(type.value, "c8 *");
c8 *decl = MakeArray(arena, c8, 2048);
i32 decl_len = SPrintf(decl, 2048, "static %s\n%s[] = \n{\n\t", type.value, array_name.value);
String8 result = {
.value = decl,
.len = u64(decl_len),
};
if (is_string)
{
String8 *strs = (String8 *)elements;
for (u32 i = 0; i < count; i += 1)
{
c8 *f = i == count-1 ? "\"%s\"," : "\"%s\",\n\t";
c8 buf[512];
decl_len = SPrintf(buf, 512, f, strs[i].value);
result = String8Concat(arena, result, MakeString8(buf, decl_len));
}
}
else
{
u64 *ints = (u64 *)elements;
for (u32 i = 0; i < count; i += 1)
{
c8 *f = i == count-1 ? "%lluU," : "%lluU,\n\t";
c8 buf[512];
decl_len = SPrintf(buf, 512, f, ints[i]);
result = String8Concat(arena, result, MakeString8(buf, decl_len));
}
}
result = String8Concat(arena, result, String8CStr("\n};\n\n"));
return pFileWrite(file, offset, result.value, result.len);
}
static String8 *
ConvertCStrs(Arena *arena, c8 **strs, u32 count)
{
String8 *str8s = MakeArray(arena, String8, count);
for (u32 i = 0; i < count; i += 1)
{
str8s[i].value = strs[i];
str8s[i].len = StrLen(strs[i]);
}
return str8s;
}
void
CodeGenAssetLookups(Arena *arena)
{
pFile file = pFileOpen("../src/codegen_assets.h", pFS_WRITE | pFS_CREATE | pFS_TRUNC);
Assert(file > 0, "CodeGenAssetLookups failure: unable to open/create file");
Assert(pDirNavigate("../assets") == 0, "Unable to navigate to asset directory");
struct AssetDirInfo {
c8 *prefix, *struct_name, *hash_struct_name, *dir, *define;
};
struct AssetDirInfo dirs[] = {
{
.prefix = "shaders/",
.struct_name = "g_Shader_Asset_Names",
.hash_struct_name = "g_Shader_Asset_Hashes",
.dir = "shaders",
.define = "SHADER_ASSET",
},
{
.prefix = "models/",
.struct_name = "g_Model_Asset_Names",
.hash_struct_name = "g_Model_Asset_Hashes",
.dir = "models",
.define = "MODEL_ASSET",
},
{
.prefix = "textures/",
.struct_name = "g_Texture_Asset_Names",
.hash_struct_name = "g_Texture_Asset_Hashes",
.dir = "textures",
.define = "TEXTURE_ASSET",
},
};
u64 offset = 0;
u32 dir_count = sizeof(dirs) / sizeof(struct AssetDirInfo);
for (u32 i = 0; i < dir_count; i += 1)
{
Assert(pDirNavigate(dirs[i].dir) == 0, "Unable to navigate to asset sub directory.");
u32 count = 0;
c8 **cstrs = pDirGetFileNames(arena, &count);
u64 *hashes = MakeArray(arena, u64, count);
String8 *strs = ConvertCStrs(arena, cstrs, count);
for (u32 j = 0; j < count; j += 1)
{
strs[j] = String8Concat(arena, String8CStr(dirs[i].prefix), strs[j]);
i64 offset = String8FindLast(strs[j], '.');
hashes[j] = XXH3_64bits_withSeed(strs[j].value, strs[j].len - offset, HASH_SEED);
}
offset += WriteArrayToFile(
arena,
file,
String8CStr(dirs[i].struct_name),
strs,
count,
String8CStr("c8 *"),
offset
);
offset += WriteArrayToFile(
arena,
file,
String8CStr(dirs[i].hash_struct_name),
hashes,
count,
String8CStr("u64"),
offset
);
c8 buf[128];
i32 decl_len = SPrintf(buf, 128, "#define %s_MAX %llu\n\n#define %s %llu\n\n", dirs[i].define, count, dirs[i].define, i);
offset += pFileWrite(file, offset, buf, decl_len);
Assert(pDirNavigate("..") == 0, "CodeGenAssetLookups failure: unable to move back to build directory");
}
pFileClose(file);
}
int
main(int argc, c8 **argv)
{
#ifdef _WIN32
{
_set_fmode(_O_BINARY);
}
#endif
if (pDirIsVisible("build"))
{
Assert(pDirNavigate("./build") == 0, "Unable to change to build directory");
}
void *mem = pMemAllocZeroed(GB(1));
Arena *arena = ArenaInitDebug(mem, GB(1), __LINE__);
CodeGenAssetLookups(arena);
}
#else
i32
WriteHeader(pFile file, FileHeader *header)
{
@ -218,23 +49,8 @@ InitHeader(FileHeader *header)
header->magic_num = CreateMagicValue('s', 't', 'e', 'g');
header->version = FILE_VERSION;
header->asset_counts[SHADER_ASSET] = SHADER_ASSET_MAX;
header->asset_counts[TEXTURE_ASSET] = TEXTURE_ASSET_MAX;
header->asset_counts[SOUND_ASSET] = SOUND_ASSET_MAX;
header->asset_counts[MODEL_ASSET] = MODEL_ASSET_MAX;
u64 offset = sizeof(FileHeader);
for (u32 i = 0; i < ASSET_TYPE_MAX; i++)
{
if (header->asset_counts[i] > 0)
{
header->asset_offsets[i] = offset;
offset += sizeof(AssetFile) * header->asset_counts[i];
}
else
header->asset_offsets[i] = 0;
}
header->asset_counts = SHADER_ASSET_MAX + TEXTURE_ASSET_MAX + MODEL_ASSET_MAX;
header->asset_offset = sizeof(FileHeader);
}
void
@ -244,20 +60,16 @@ PackFiles(Arena *arena, FileHeader *header)
u64 file_pos = pFileWrite(file, 0, header, sizeof(FileHeader));
u64 data_offset = 0;
for (u32 i = 0; i < ASSET_TYPE_MAX; i++)
{
u64 asset_offset = header->asset_offsets[i] + (header->asset_counts[i] * sizeof(AssetFile));
if (asset_offset > data_offset)
data_offset = asset_offset;
}
c8 *return_dir = ".";
u32 file_count;
MoveToShaderDir(&return_dir);
Assert(pDirNavigate("../assets") == 0, "Unable to move to assets directory");
AssetFile *shader_assets = MakeArray(arena, AssetFile, SHADER_ASSET_MAX);
for (u32 i = 0; i < SHADER_ASSET_MAX; i++)
u64 total_assets = SHADER_ASSET_MAX + TEXTURE_ASSET_MAX + MODEL_ASSET_MAX;
u64 asset_count = 0;
AssetFile *assets = MakeArray(arena, AssetFile, total_assets);
u64 data_offset = header->asset_offset + (sizeof(AssetFile) + total_assets);
for (u32 i = 0; i < SHADER_ASSET_MAX; i++, asset_count++)
{
c8 *asset_name = g_Shader_Asset_Names[i];
@ -274,17 +86,14 @@ PackFiles(Arena *arena, FileHeader *header)
Assert((data_offset - prev_offset) == file_size, "File write size invalid");
shader_assets[i].data_offset = prev_offset;
shader_assets[i].len = file_size;
assets[asset_count].data_offset = prev_offset;
assets[asset_count].len = file_size;
assets[asset_count].type = AT_SHADER;
pFileClose(asset_file);
}
Assert(pDirNavigate(return_dir) == 0, "Unable to return to previous directory");
MoveToTextureDir(&return_dir);
AssetFile *texture_assets = MakeArray(arena, AssetFile, TEXTURE_ASSET_MAX);
for (u32 i = 0; i < TEXTURE_ASSET_MAX; i++)
for (u32 i = 0; i < TEXTURE_ASSET_MAX; i++, asset_count++)
{
c8 *asset_name = g_Texture_Asset_Names[i];
@ -312,22 +121,19 @@ PackFiles(Arena *arena, FileHeader *header)
Assert((data_offset - prev_offset) == loaded_length, "File write size invalid");
texture_assets[i].data_offset = prev_offset;
texture_assets[i].len = loaded_length;
texture_assets[i].texture_meta.w = u32(w);
texture_assets[i].texture_meta.h = u32(h);
texture_assets[i].texture_meta.ch = u32(ch);
assets[asset_count].data_offset = prev_offset;
assets[asset_count].len = loaded_length;
assets[asset_count].type = AT_TEXTURE;
assets[asset_count].texture_meta.w = u32(w);
assets[asset_count].texture_meta.h = u32(h);
assets[asset_count].texture_meta.ch = u32(ch);
stbi_image_free(image_bytes);
pFileClose(asset_file);
}
Assert(pDirNavigate(return_dir) == 0, "Unable to return to previous directory");
MoveToModelDir(&return_dir);
AssetFile *model_assets = MakeArray(arena, AssetFile, MODEL_ASSET_MAX);
for (u32 i = 0; i < MODEL_ASSET_MAX; i++)
for (u32 i = 0; i < MODEL_ASSET_MAX; i++, asset_count++)
{
c8 *asset_name = g_Model_Asset_Names[i];
@ -344,17 +150,17 @@ PackFiles(Arena *arena, FileHeader *header)
Assert((data_offset - prev_offset) == file_size, "File write size invalid");
model_assets[i].data_offset = prev_offset;
model_assets[i].len = file_size;
m3d_t *model = m3d_load(file_data, NULL, NULL, NULL);
assets[asset_count].data_offset = prev_offset;
assets[asset_count].type = AT_MODEL;
assets[asset_count].len = file_size;
assets[asset_count].model_meta.i_count = u64(model->numface * 3);
pFileClose(asset_file);
}
pFileWrite(file, header->asset_offsets[SHADER_ASSET], shader_assets, sizeof(AssetFile)*SHADER_ASSET_MAX);
pFileWrite(file, header->asset_offsets[TEXTURE_ASSET], texture_assets, sizeof(AssetFile)*TEXTURE_ASSET_MAX);
pFileWrite(file, header->asset_offsets[MODEL_ASSET], model_assets, sizeof(AssetFile)*MODEL_ASSET_MAX);
pDirNavigate(return_dir);
pFileWrite(file, header->asset_offset, assets, sizeof(AssetFile)*asset_count);
}
// ::Packer::Packing::Functions::End::
@ -364,7 +170,7 @@ PackFiles(Arena *arena, FileHeader *header)
// ::Packer::Tests::Functions::Start::
static inline void
TestAssetIsCorrect(Arena *arena, c8 *file_name, AssetFile *file_info, AssetType type, pFile file)
TestAssetIsCorrect(Arena *arena, c8 *file_name, AssetFile *file_info, pFile file)
{
pFile asset_file = pFileOpen(file_name, pFS_READ);
u64 size = pFileLength(asset_file);
@ -378,7 +184,7 @@ TestAssetIsCorrect(Arena *arena, c8 *file_name, AssetFile *file_info, AssetType
u8 *image_bytes;
u64 image_length;
if (type == TEXTURE_ASSET)
if (file_info->type == TEXTURE_ASSET)
{
int ch = 4;
int w, h, has_ch;
@ -415,48 +221,30 @@ TestAssetPack(Arena *arena)
FileHeader header;
i64 offset = pFileRead(file, 0, &header, sizeof(FileHeader));
u64 asset_count = SHADER_ASSET_MAX + MODEL_ASSET_MAX + TEXTURE_ASSET_MAX;
Assert(header.magic_num == CreateMagicValue('s', 't', 'e', 'g'), "Magic number is incorrect");
Assert(header.version == FILE_VERSION, "File version is incorrect");
Assert(header.asset_counts[SHADER_ASSET] == SHADER_ASSET_MAX, "Shader count incorrect");
Assert(header.asset_counts[TEXTURE_ASSET] == TEXTURE_ASSET_MAX, "Texture count incorrect");
Assert(header.asset_counts[SOUND_ASSET] == SOUND_ASSET_MAX, "Sound count incorrect");
Assert(header.asset_counts[MODEL_ASSET] == MODEL_ASSET_MAX, "Model count incorrect");
Assert(header.asset_counts == asset_count, "Asset count incorrect");
AssetTag *tags[ASSET_TYPE_MAX];
AssetFile *files[ASSET_TYPE_MAX];
for (u32 i = 0; i < ASSET_TYPE_MAX; i++)
{
if (header.asset_counts[i] > 0)
{
files[i] = MakeArray(arena, AssetFile, header.asset_counts[i]);
pFileRead(file, header.asset_offsets[i], files[i], sizeof(AssetFile)*header.asset_counts[i]);
}
}
c8 *return_dir = ".";
MoveToShaderDir(&return_dir);
AssetFile *files = MakeArray(arena, AssetFile, asset_count);
pFileRead(file, header.asset_offset, files, sizeof(AssetFile)*header.asset_counts);
for (u32 i = 0; i < SHADER_ASSET_MAX; i++)
u64 current_asset = 0;
for (u32 i = 0; i < SHADER_ASSET_MAX; i++, current_asset++)
{
TestAssetIsCorrect(arena, g_Shader_Asset_Names[i], &files[SHADER_ASSET][i], SHADER_ASSET, file);
TestAssetIsCorrect(arena, g_Shader_Asset_Names[i], files + current_asset, file);
}
pDirNavigate(return_dir);
MoveToTextureDir(&return_dir);
for (u32 i = 0; i < TEXTURE_ASSET_MAX; i++)
for (u32 i = 0; i < TEXTURE_ASSET_MAX; i++, current_asset++)
{
TestAssetIsCorrect(arena, g_Texture_Asset_Names[i], &files[TEXTURE_ASSET][i], TEXTURE_ASSET, file);
TestAssetIsCorrect(arena, g_Texture_Asset_Names[i], files + current_asset, file);
}
pDirNavigate(return_dir);
MoveToModelDir(&return_dir);
for (u32 i = 0; i < MODEL_ASSET_MAX; i++)
for (u32 i = 0; i < MODEL_ASSET_MAX; i++, current_asset++)
{
TestAssetIsCorrect(arena, g_Model_Asset_Names[i], &files[MODEL_ASSET][i], MODEL_ASSET, file);
TestAssetIsCorrect(arena, g_Model_Asset_Names[i], files + current_asset, file);
}
}
@ -496,8 +284,6 @@ main(int argc, c8 **argv)
TestAssetPack(arena);
}
#endif // BUILD_ASSET_CODEGEN
// ::Packer::Main::Functions::End::

View File

@ -10,29 +10,21 @@
#define STG_NO_RENDERER
#define STB_SPRINTF_IMPLEMENTATION
#define STB_IMAGE_IMPLEMENTATION
#define M3D_IMPLEMENTATION
#include "shared_types.h"
#include "platform/platform.h"
#include "util.h"
#define STG_IMPLEMENTATION
#include "stglib.h"
#include "assets.h"
#include "ds.h"
#include "allocators.h"
// ::ThirdParty::Include::Header::
#include "stb/stb_sprintf.h"
#include "stb/stb_image.h"
#include "xxhash/xxhash.h"
#include "fastlz/fastlz.h"
#include "m3d/m3d.h"
#include "renderer.h"
#include "game.h"
#include <stdio.h>
// ::Packer::Macros::Header::
@ -51,7 +43,6 @@ typedef struct FileMapping
// ::Packer::Packing::Functions::Header::
void SetArrayLookups();
void CodeGenAssetLookups(Arena *arena);
void InitHeader(FileHeader *header);
i32 WriteHeader(pFile file, FileHeader *header);
void PackFiles(Arena *arena, FileHeader *header);
@ -62,7 +53,7 @@ void MoveToModelDir(c8 **return_dir);
// ::Packer::Tests::Functions::Header::
void TestAssetPack(Arena *arena);
static inline void TestAssetIsCorrect(Arena *arena, c8 *file_name, AssetFile *file_info, AssetType type, pFile file);
static inline void TestAssetIsCorrect(Arena *arena, c8 *file_name, AssetFile *file_info, pFile file);
// ::Packer::Main::Functions::Header::

View File

@ -1,16 +0,0 @@
#if __linux__
#include "platform/platform_linux.c"
#endif
#if _WIN32
#include "platform/platform_windows.c"
#endif
#if __APPLE__ || __MACH__
#error Not yet implemented
#endif
#if __unix__ && !__linux__
#error Not yet implemented
#endif

View File

@ -1,165 +0,0 @@
#pragma once
// ::Platform::Types::Header::
typedef struct pLibrary pLibrary;
typedef struct pFunction pFunction;
// ::Platform::Declarations::Header::
typedef struct pGameInput pGameInput;
typedef enum KeyboardInput_e
{
KB_NONE,
KB_A, KB_B, KB_C, KB_D, KB_E, KB_F, KB_G, KB_H, KB_I, KB_J, KB_K, KB_L, KB_M,
KB_N, KB_O, KB_P, KB_Q, KB_R, KB_S, KB_T, KB_U, KB_V, KB_W, KB_X, KB_Y, KB_Z,
KB_0, KB_1, KB_2, KB_3, KB_4, KB_5, KB_6, KB_7, KB_8, KB_9,
KB_NUM_0, KB_NUM_1, KB_NUM_2, KB_NUM_3, KB_NUM_4, KB_NUM_5, KB_NUM_6, KB_NUM_7, KB_NUM_8, KB_NUM_9,
KB_NUM_LOCK, KB_NUM_SLASH, KB_NUM_STAR, KB_NUM_MINUS, KB_NUM_PLUS, KB_NUM_ENTER, KB_NUM_PERIOD,
KB_INSERT, KB_DELETE, KB_HOME, KB_END, KB_PAGE_UP, KB_PAGE_DOWN,
KB_PRINT_SCREEN, KB_SCROLL_LOCK, KB_PAUSE,
KB_COMMA, KB_PERIOD, KB_BACK_SLASH, KB_BACKSPACE, KB_FORWARD_SLASH, KB_MINUS, KB_PLUS,
KB_F1, KB_F2, KB_F3, KB_F4, KB_F5, KB_F6, KB_F7, KB_F8, KB_F9, KB_F10, KB_F11, KB_F12,
KB_UP, KB_DOWN, KB_LEFT, KB_RIGHT,
KB_LEFT_CTRL, KB_LEFT_ALT, KB_LEFT_SHIFT, KB_LEFT_SUPER,
KB_TAB, KB_CAPS_LOCK,
KB_RIGHT_CTRL, KB_RIGHT_ALT, KB_RIGHT_SUPER, KB_RIGHT_SHIFT,
KB_ENTER, KB_SPACE,
KB_TILDE, KB_ESC,
KB_SEMICOLON, KB_QUOTE, KB_LEFT_BRACE, KB_RIGHT_BRACE, KB_BACK_SPACE,
KB_MAX
} pKeyboardInput;
// ::Platform::Includes::Header::
#if __linux__
#include "platform/platform_linux.h"
#endif
#if _WIN32
#include "platform/platform_windows.h"
#endif
#if __APPLE__ || __MACH__
#error Not yet implemented
#endif
#if __unix__ && !__linux__
#error Not yet implemented
#endif
// ::Platform::Enum::Header::
typedef enum MouseInput_e
{
M_NONE,
M_LEFT_CLICK,
M_MIDDLE_CLICK,
M_RIGHT_CLICK,
} pMouseInput;
typedef enum GameInputType_e
{
GI_NONE,
GI_KEYBOARD,
GI_MOUSE,
GI_MOTION,
GI_GAMEPAD,
} pGameInputType;
// ::Platform::Types::Header::
typedef u16Vec2 pWindowSize;
typedef i16Vec2 pMouseMotion;
typedef struct pGameInput
{
union
{
pKeyboardInput kb_code;
pMouseInput m_code;
pMouseMotion motion_ev;
};
b8 pressed;
pGameInputType type;
} pGameInput; // TODO: add gamepad input
typedef struct pThread pThread;
// ::Platform::ConsoleOut::Functions::Header::
i32 pWriteStdOut(void *buf, i32 len);
i32 pWriteStdErr(void *buf, i32 len);
// ::Platform::pLibrary::Functions::Header::
b32 pLibraryLoad(const char *name, pLibrary *out_lib);
b32 pFunctionLoad(const char *name, pLibrary *lib, pFunction *out_fn);
// ::Platform::Memory::Functions::Header::
rawptr pMemAlloc(usize size);
rawptr pMemAllocZeroed(usize size);
rawptr pMemRealloc(rawptr ptr, usize old_size, usize new_size);
void pMemFree(rawptr ptr, usize size);
usize pPageSize();
// ::Platform::Window::Functions::Header::
b32 pWindowInit(const char *window_name);
pWindowSize pWindowGetSize();
b32 pWindowShouldQuit();
pPlatformWindow *pWindowGet();
// ::Platform::FileSystem::Functions::Header::
typedef enum e_pFSAccess
{
pFS_READ = 0x01,
pFS_WRITE = 0x02,
pFS_TRUNC = 0x04,
pFS_APPEND = 0x08,
pFS_CREATE = 0x10,
} pFSAccess;
b32 pDirNavigate(c8 *dir);
c8 **pDirGetFileNames(Arena *arena, u32 *count);
static pFile pFileOpen(c8 *file_name, pFSAccess access);
static void pFileClose(pFile file);
static u64 pFileRead(pFile file, u64 offset, rawptr buf, u64 len);
static u64 pFileWrite(pFile file, u64 offset, rawptr buf, u64 len);
static u64 pFileSeek(pFile file, u64 pos);
static u64 pFileLength(pFile file);
static b32 pFSIsVisible(c8 *name, b32 is_dir);
static b32 pDirIsVisible(c8 *dir_name);
static b32 pFileIsVisible(c8 *file_name);
static b32 pFileCanAccess(c8 *file_name, pFSAccess access);
// ::Platform::Profiling::Functions::Header::
static u64 pOSTimerFreq();
static u64 pOSTimerRead();
static inline u64 pCPUTimerRead();
// ::Platform::Async::Functions::Header::
static pThread pThreadInit(rawptr proc, rawptr param);
static void pThreadSuspend(pThread *thread);
static void pThreadWake(pThread *thread);
static void pThreadKill();
// ::Platform::Atomics::Header::
static inline void pAtomicSignalFenceSeqCst();
static inline u32 pAtomicFetchSubU32(u32 volatile *ptr, u32 count);
static inline u32 pAtomicFetchIncrU32(u32 volatile *ptr);
static inline void pAtomicIncrU8(u8 volatile *ptr);
static inline void pAtomicIncrU32(u32 volatile *ptr);
static inline u32 pAtomicLoadU32(u32 volatile *ptr);
static inline void pAtomicStoreB32(b32 volatile *ptr, b32 value);
static inline b32 pAtomicCompareExchangeB32(b32 volatile *ptr, b32 *expect, b32 desired);

View File

@ -1,350 +0,0 @@
// ::Platform::Linux::Globals::Start::
static pPlatformWindow
linux_window =
{
.w = 1920,
.h = 1080,
};
b32
g_Global_Quit = false;
// ::Platform::Linux::Globals::End::
// ::Platform::Linux::Print::Functions::Start::
i32
pWriteStdOut(rawptr buf, i32 len)
{
return (i32)write(STDOUT, buf, len);
}
i32
pWriteStdErr(rawptr buf, i32 len)
{
return (i32)write(STDERR, buf, len);
}
// ::Platform::Linux::Window::Functions::Start::
void
pWindowEventsGet(pGameInput *inputs, u32 *i_count)
{
pWindowEventHandle(inputs, i_count, false);
}
b32
pWindowEventWaitFor(pGameInput *input)
{
u32 i_count;
pWindowEventHandle(input, &i_count, true);
return i_count > 0;
}
void
pWindowEventHandle(pGameInput *inputs, u32 *i_count, b32 wait_for_event)
{
b32 has_max_inputs = false;
*i_count = 0;
do
{
xcb_generic_event_t *e;
if (wait_for_event)
e = xcb_wait_for_event(linux_window.connection);
else
e = xcb_poll_for_event(linux_window.connection);
// XCB_UNMAP_NOTIFY
if (e != NULL)
{
switch (e->response_type & ~0x80)
{
case XCB_CLIENT_MESSAGE:
{
xcb_client_message_event_t *msg = (xcb_client_message_event_t *)e;
if (msg->window != linux_window.window)
break;
if (msg->data.data32[0] == linux_window.close_event)
g_Global_Quit = true;
} break;
case XCB_CONFIGURE_NOTIFY:
{
xcb_configure_notify_event_t *configure_event = (xcb_configure_notify_event_t *)e;
if (linux_window.w != configure_event->width || linux_window.h != configure_event->height)
{
linux_window.w = configure_event->width;
linux_window.h = configure_event->height;
}
} break;
case XCB_KEY_RELEASE:
case XCB_KEY_PRESS:
{
xcb_key_press_event_t *keyboard_e = (xcb_key_press_event_t *)e;
b8 pressed = e->response_type == XCB_KEY_PRESS;
xcb_keycode_t code = keyboard_e->detail;
KeySym keysym = XkbKeycodeToKeysym(linux_window.display, (KeyCode)code, 0, 0);
pKeyboardInput input = pInputEventConvert(keysym);
if (input != KB_NONE)
{
inputs[*i_count].kb_code = input;
inputs[*i_count].pressed = pressed;
inputs[*i_count].type = GI_KEYBOARD;
*i_count += 1;
if (*i_count == 10)
has_max_inputs = true;
}
} break;
case XCB_BUTTON_PRESS:
case XCB_BUTTON_RELEASE:
{
xcb_button_press_event_t *mouse_ev = (xcb_button_press_event_t *)e;
b8 pressed = e->response_type == XCB_BUTTON_PRESS;
pMouseInput input = M_NONE;
if (mouse_ev->detail == XCB_BUTTON_INDEX_1)
input = M_LEFT_CLICK;
else if (mouse_ev->detail == XCB_BUTTON_INDEX_2)
input = M_MIDDLE_CLICK;
else if (mouse_ev->detail == XCB_BUTTON_INDEX_3)
input = M_RIGHT_CLICK;
if (input != M_NONE)
{
inputs[*i_count].m_code = input;
inputs[*i_count].pressed = pressed;
inputs[*i_count].type = GI_MOUSE;
*i_count += 1;
if (*i_count == 10)
has_max_inputs = true;
}
} break;
case XCB_MOTION_NOTIFY:
{
xcb_motion_notify_event_t *move_ev = (xcb_motion_notify_event_t *)e;
if (move_ev->event_x > 0 || move_ev->event_y > 0)
{
inputs[*i_count].motion_ev.x = move_ev->event_x;
inputs[*i_count].motion_ev.y = move_ev->event_y;
inputs[*i_count].type = GI_MOTION;
*i_count += 1;
if (*i_count == 10)
has_max_inputs = true;
}
}
default:
break;
}
free(e);
}
else
{
break;
}
} while(!wait_for_event && !has_max_inputs);
}
pKeyboardInput
pInputEventConvert(u32 x_key)
{
switch (x_key)
{
case XK_BackSpace: return KB_BACKSPACE;
case XK_Return: return KB_ENTER;
case XK_Tab: return KB_TAB;
case XK_Pause: return KB_PAUSE;
case XK_Caps_Lock: return KB_CAPS_LOCK;
case XK_Escape: return KB_ESC;
case XK_space: return KB_SPACE;
case XK_Prior: return KB_PAGE_UP;
case XK_Next: return KB_PAGE_DOWN;
case XK_End: return KB_END;
case XK_Home: return KB_HOME;
case XK_Left: return KB_LEFT;
case XK_Up: return KB_UP;
case XK_Right: return KB_RIGHT;
case XK_Down: return KB_DOWN;
case XK_Print: return KB_PRINT_SCREEN;
case XK_Insert: return KB_INSERT;
case XK_Delete: return KB_DELETE;
case XK_Meta_L:
case XK_Super_L: return KB_LEFT_SUPER;
case XK_Meta_R:
case XK_Super_R: return KB_RIGHT_SUPER;
case XK_KP_0: return KB_NUM_0;
case XK_KP_1: return KB_NUM_1;
case XK_KP_2: return KB_NUM_2;
case XK_KP_3: return KB_NUM_3;
case XK_KP_4: return KB_NUM_4;
case XK_KP_5: return KB_NUM_5;
case XK_KP_6: return KB_NUM_6;
case XK_KP_7: return KB_NUM_7;
case XK_KP_8: return KB_NUM_8;
case XK_KP_9: return KB_NUM_9;
case XK_multiply: return KB_NUM_STAR;
case XK_KP_Subtract: return KB_NUM_MINUS;
case XK_KP_Decimal: return KB_NUM_PERIOD;
case XK_KP_Divide: return KB_NUM_SLASH;
case XK_KP_Add: return KB_NUM_PLUS;
case XK_F1: return KB_F1;
case XK_F2: return KB_F2;
case XK_F3: return KB_F3;
case XK_F4: return KB_F4;
case XK_F5: return KB_F5;
case XK_F6: return KB_F6;
case XK_F7: return KB_F7;
case XK_F8: return KB_F8;
case XK_F9: return KB_F9;
case XK_F10: return KB_F10;
case XK_F11: return KB_F11;
case XK_F12: return KB_F12;
case XK_Num_Lock: return KB_NUM_LOCK;
case XK_Scroll_Lock: return KB_SCROLL_LOCK;
case XK_Shift_L: return KB_LEFT_SHIFT;
case XK_Shift_R: return KB_RIGHT_SHIFT;
case XK_Control_L: return KB_LEFT_CTRL;
case XK_Control_R: return KB_RIGHT_CTRL;
case XK_Alt_L: return KB_LEFT_ALT;
case XK_Alt_R: return KB_RIGHT_ALT;
case XK_semicolon: return KB_SEMICOLON;
case XK_bracketleft: return KB_LEFT_BRACE;
case XK_bracketright: return KB_RIGHT_BRACE;
case XK_plus: return KB_PLUS;
case XK_comma: return KB_COMMA;
case XK_minus: return KB_MINUS;
case XK_backslash: return KB_BACK_SLASH;
case XK_slash: return KB_FORWARD_SLASH;
case XK_grave: return KB_TILDE;
case XK_0: return KB_0;
case XK_1: return KB_1;
case XK_2: return KB_2;
case XK_3: return KB_3;
case XK_4: return KB_4;
case XK_5: return KB_5;
case XK_6: return KB_6;
case XK_7: return KB_7;
case XK_8: return KB_8;
case XK_9: return KB_9;
case XK_a:
case XK_A: return KB_A;
case XK_b:
case XK_B: return KB_B;
case XK_c:
case XK_C: return KB_C;
case XK_d:
case XK_D: return KB_D;
case XK_e:
case XK_E: return KB_E;
case XK_f:
case XK_F: return KB_F;
case XK_g:
case XK_G: return KB_G;
case XK_h:
case XK_H: return KB_H;
case XK_i:
case XK_I: return KB_I;
case XK_j:
case XK_J: return KB_J;
case XK_k:
case XK_K: return KB_K;
case XK_l:
case XK_L: return KB_L;
case XK_m:
case XK_M: return KB_M;
case XK_n:
case XK_N: return KB_N;
case XK_o:
case XK_O: return KB_O;
case XK_p:
case XK_P: return KB_P;
case XK_q:
case XK_Q: return KB_Q;
case XK_r:
case XK_R: return KB_R;
case XK_s:
case XK_S: return KB_S;
case XK_t:
case XK_T: return KB_T;
case XK_u:
case XK_U: return KB_U;
case XK_v:
case XK_V: return KB_V;
case XK_w:
case XK_W: return KB_W;
case XK_x:
case XK_X: return KB_X;
case XK_y:
case XK_Y: return KB_Y;
case XK_z:
case XK_Z: return KB_Z;
default: return KB_NONE;
}
}
// ::Platform::Linux::Window::Functions::Start::
// ::Platform::Linux::Utils::Functions::Start::
b32
pSyscallErrCheck(void *ptr)
{
return (isize)ptr == SYS_ERR ? true : false;
}
// ::Platform::Linux::Utils::Functions::End::
// ::Platform::Linux::Async::Start::
static pThread
pThreadInit(rawptr proc, rawptr param)
{
pThread thread = {0};
Assert(pthread_mutex_init(&thread.mut, NULL) == 0, "pthread_mutex_init failure");
Assert(pthread_cond_init(&thread.cond, NULL) == 0, "pthread_cond_init failure");
Assert(pthread_create(&thread.handle, NULL, proc, param) == 0, "pthread_create failure");
return thread;
}
static void
pThreadSuspend(pThread *thread)
{
pthread_mutex_lock(&thread->mut);
pthread_cond_wait(&thread->cond, &thread->mut);
pthread_mutex_unlock(&thread->mut);
}
static void
pThreadWake(pThread *thread)
{
pthread_cond_signal(&thread->cond);
}
static void
pThreadKill()
{
pthread_exit(NULL);
}
// ::Platform::Linux::Async::Start::
// ::Platform::Linux::Includes::CFile::
#include "platform_linux_public.c"

View File

@ -1,101 +0,0 @@
#pragma once
#include <pthread.h>
#include <signal.h>
#include <limits.h>
#include <stdint.h>
#include <stdbool.h>
#include <xcb/xcb.h>
#include <X11/XKBlib.h>
#include <X11/Xlib-xcb.h>
#include <X11/Xlib.h>
#include <X11/keysym.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <assert.h>
#include <unistd.h>
#include <errno.h>
#include <stdarg.h>
#include <stdlib.h>
#include <dlfcn.h>
#include <nmmintrin.h>
#include <immintrin.h>
#include <sched.h>
#include <unistd.h>
#include <dirent.h>
#include <x86intrin.h>
#include <sys/time.h>
#include <fcntl.h>
// ::Platform::Linux::Defines::Header::
#define SYS_ERR -1
#define STDIN 0
#define STDOUT 1
#define STDERR 2
// ::Platform::Linux::Macros::Header::
#define XCB_CHECK_CURRENT_ERROR(window, error, message) do { \
error = xcb_request_check(window->connection, cookie); \
if (error != NULL) { \
EPrintf("%s ERROR CODE: %d\n", message, error->error_code); \
free(error); \
return false; \
} \
} while (0)
#define XCB_CHECK_ERROR(window, cookie, error, message) do { \
error = xcb_request_check(window->connection, cookie); \
XCB_CHECK_CURRENT_ERROR(window, error, message); \
} while (0)
// ::Platform::Linux::Types::Header
typedef int pFile;
typedef struct pThread
{
pthread_t handle;
pthread_cond_t cond;
pthread_mutex_t mut;
} pThread;
typedef struct pPlatformWindow
{
Display *display;
xcb_connection_t *connection;
xcb_window_t window;
xcb_atom_t close_event;
xcb_atom_t minimize_event;
u16 w, h;
} pPlatformWindow;
typedef struct pLibrary
{
void *lib;
} pLibrary;
typedef struct pFunction
{
void *fn;
} pFunction;
typedef int pFile;
// ::Platform::Linux::Print::Functions::Header::
i32 pWrite(int fd, void const *str, isize count);
// ::Platform::Linux::Window::Functions::Header::
void pWindowEventsGet(pGameInput *inputs, u32 *i_count);
b32 pWindowEventWaitFor(pGameInput *input);
void pWindowEventHandle(pGameInput *inputs, u32 *input_count, b32 wait_for_event);
pKeyboardInput pInputEventConvert(u32 x_key);
// ::Platform::Linux::Utils::Functions::Header::
b32 pSyscallErrCheck(void *ptr);

View File

@ -1,472 +0,0 @@
// ::Platform::Functions::pLibrary::Start::
b32
pLibraryLoad(const char *name, pLibrary *out_lib)
{
if (!name) {
return false;
}
out_lib->lib = dlopen(name, RTLD_NOW);
if (!out_lib->lib) {
return false;
}
return true;
}
b32
pFunctionLoad(const char *name, pLibrary *lib, pFunction *out_fn)
{
if (!name) {
return false;
}
out_fn->fn = dlsym(lib->lib, name);
if (!out_fn->fn) {
Printf("unable to find function\n");
return false;
}
return true;
}
// ::Platform::Functions::pLibrary::End::
// ::Platform::Functions::Print::Start::
// ::Platform::Functions::Print::End::
// ::Platform::Functions::Memory::Start::
rawptr
pMemAlloc(usize size)
{
rawptr addr = mmap(
NULL,
size,
PROT_READ | PROT_WRITE,
MAP_ANON | MAP_PRIVATE,
-1,
0
);
if (pSyscallErrCheck(addr)) addr = NULL;
return addr;
}
rawptr
pMemAllocZeroed(usize size)
{
rawptr ptr = pMemAlloc(size);
MemZero(ptr, size);
return ptr;
}
rawptr
pMemRealloc(rawptr ptr, usize old_size, usize new_size)
{
rawptr addr = mremap(
ptr,
old_size,
new_size,
MAP_ANON | MAP_PRIVATE
);
if (pSyscallErrCheck(addr)) addr = NULL;
return addr;
}
void
pMemFree(rawptr ptr, usize size)
{
Assert(munmap(ptr, size) == 0, "munmap failed");
}
usize
pPageSize()
{
return (usize)sysconf(_SC_PAGESIZE);
}
// ::Platform::Functions::Memory::End::
// ::Platform::Functions::Window::Start::
b32
pWindowInit(const char *window_name)
{
pPlatformWindow *window = &linux_window;
window->display = XOpenDisplay(NULL);
if (!window->display)
return false;
window->connection = XGetXCBConnection(window->display);
if (!window->connection)
return false;
xcb_void_cookie_t cookie;
xcb_generic_error_t *error;
const xcb_setup_t *setup = xcb_get_setup(window->connection);
xcb_screen_iterator_t iter = xcb_setup_roots_iterator(setup);
xcb_screen_t *screen = iter.data;
const int event_mask = XCB_EVENT_MASK_EXPOSURE |
XCB_EVENT_MASK_KEY_PRESS |
XCB_EVENT_MASK_KEY_RELEASE |
XCB_EVENT_MASK_BUTTON_PRESS |
XCB_EVENT_MASK_BUTTON_RELEASE |
XCB_EVENT_MASK_POINTER_MOTION |
XCB_EVENT_MASK_STRUCTURE_NOTIFY;
const int val_win[] = {screen->black_pixel, event_mask};
const int val_mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
window->window = xcb_generate_id(window->connection);
cookie = xcb_create_window(
window->connection,
XCB_COPY_FROM_PARENT,
window->window,
screen->root,
0, // x pos
0, // y pos
window->w, // width
window->h, // height
0,
XCB_WINDOW_CLASS_INPUT_OUTPUT,
screen->root_visual,
val_mask,
val_win
);
XCB_CHECK_ERROR(window, cookie, error, "Failed to create window.");
cookie = xcb_map_window_checked(window->connection, window->window);
XCB_CHECK_ERROR(window, cookie, error, "Failed to map window.");
cookie = xcb_change_property_checked(
window->connection,
XCB_PROP_MODE_REPLACE,
window->window,
XCB_ATOM_WM_NAME,
XCB_ATOM_STRING,
8,
StrLen(window_name),
window_name
);
XCB_CHECK_ERROR(window, cookie, error, "Failed to rename window.");
xcb_intern_atom_cookie_t c_proto = xcb_intern_atom(window->connection, 1, 12, "WM_PROTOCOLS");
xcb_intern_atom_reply_t *r_proto = xcb_intern_atom_reply(window->connection, c_proto, &error);
XCB_CHECK_CURRENT_ERROR(window, error, "Failed to get WM_PROTOCOLS.");
xcb_intern_atom_cookie_t c_close = xcb_intern_atom(window->connection, 0, 16, "WM_DELETE_WINDOW");
xcb_intern_atom_reply_t *r_close = xcb_intern_atom_reply(window->connection, c_close, &error);
XCB_CHECK_CURRENT_ERROR(window, error, "Failed to get WM_DELETE_WINDOW.");
xcb_intern_atom_cookie_t c_minimize = xcb_intern_atom(window->connection, 0, 20, "_NET_WM_STATE_HIDDEN");
xcb_intern_atom_reply_t *r_minimize = xcb_intern_atom_reply(window->connection, c_minimize, &error);
XCB_CHECK_CURRENT_ERROR(window, error, "Failed to get _NET_WM_STATE_HIDDEN");
cookie = xcb_change_property_checked(
window->connection,
XCB_PROP_MODE_REPLACE,
window->window,
r_proto->atom,
XCB_ATOM_ATOM,
32,
1,
&r_close->atom
);
XCB_CHECK_ERROR(window, cookie, error, "Failed to set window close event.");
window->close_event = r_close->atom;
window->minimize_event = r_minimize->atom;
free(r_proto);
free(r_close);
free(r_minimize);
xcb_map_window(window->connection, window->window);
i32 stream_result = xcb_flush(window->connection);
if (stream_result <= 0)
{
Printfln("Error flushing the stream: %d", stream_result);
return false;
}
return true;
}
pWindowSize
pWindowGetSize()
{
return (pWindowSize) {
.w = linux_window.w,
.h = linux_window.h,
};
}
pPlatformWindow
*pWindowGet()
{
return &linux_window;
}
b32
pWindowShouldQuit()
{
return false;
}
// ::Platform::Functions::Window::End::
// ::Platform::FileSystem::Functions::Start::
b32
pDirNavigate(c8 *dir)
{
return chdir(dir);
}
static pFile
pFileOpen(c8 *file_name, pFSAccess acc)
{
int flags = 0;
if (BitEq(acc, pFS_READ) && BitEq(acc, pFS_WRITE))
flags = O_RDWR;
else if (BitEq(acc, pFS_READ))
flags = O_RDONLY;
else if (BitEq(acc, pFS_WRITE))
flags = O_WRONLY;
if (BitEq(acc, pFS_TRUNC))
{
flags |= O_TRUNC;
}
else if (BitEq(acc, pFS_APPEND))
flags |= O_APPEND;
if (BitEq(acc, pFS_CREATE))
flags |= O_CREAT;
return open(file_name, flags, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP);
}
static void
pFileClose(pFile file)
{
close(file);
}
// TODO: make these more resilient
static u64
pFileRead(pFile file, u64 offset, rawptr buf, u64 len)
{
lseek(file, (isize)offset, SEEK_SET);
return read(file, buf, (usize)len);
}
static u64
pFileWrite(pFile file, u64 offset, rawptr buf, u64 len)
{
lseek(file, (isize)offset, SEEK_SET);
return write(file, buf, (usize)len);
}
static u64
pFileSeek(pFile file, u64 pos)
{
return (u64)lseek(file, (isize)pos, SEEK_SET);
}
static u64
pFileLength(pFile file)
{
isize offset = lseek(file, 0, SEEK_CUR);
isize size = lseek(file, 0, SEEK_END);
lseek(file, offset, SEEK_SET);
if (size == -1)
size = UINT64_MAX;
return (u64)size;
}
c8 **
pDirGetFileNames(Arena *arena, u32 *count)
{
struct dirent *dir;
DIR *d = opendir(".");
*count = 0;
if (d)
{
while ((dir = readdir(d)) != NULL)
{
if (!StrEq(dir->d_name, ".") && !StrEq(dir->d_name, ".."))
*count += 1;
}
}
c8 **file_names = MakeArray(arena, u8*, *count);
d = opendir(".");
*count = 0;
if (d)
{
while ((dir = readdir(d)) != NULL)
{
if (!StrEq(dir->d_name, ".") && !StrEq(dir->d_name, ".."))
{
i32 str_len = StrLen(dir->d_name);
file_names[*count] = MakeArray(arena, u8, str_len);
MemCpy(file_names[*count], dir->d_name, str_len);
*count += 1;
}
}
}
return (c8 **)file_names;
}
static b32
pFSIsVisible(c8 *name, b32 is_dir)
{
b32 found = false;
struct dirent *dir;
DIR *d = opendir(".");
u8 type = is_dir ? DT_DIR : DT_REG;
if (d)
{
while ((dir = readdir(d)) != NULL)
{
if (StrEq(name, dir->d_name) && dir->d_type == type)
{
found = true;
break;
}
}
}
return found;
}
static b32
pDirIsVisible(c8 *dir_name)
{
return pFSIsVisible(dir_name, true);
}
static b32
pFileIsVisible(c8 *file_name)
{
return pFSIsVisible(file_name, false);
}
static b32
pFileCanAccess(c8 *file_name, pFSAccess file_access)
{
int a = 0;
if (BitEq(file_access, pFS_READ))
a |= R_OK;
if (BitEq(file_access, pFS_WRITE))
a |= W_OK;
return access(file_name, a) == 0;
}
// ::Platform::FileSystem::Functions::End::
// ::Platform::Profiling::Functions::Start::
static u64
pOSTimerFreq()
{
return 1000000;
}
static u64
pOSTimerRead()
{
struct timeval value;
gettimeofday(&value, 0);
return pOSTimerFreq() * u64(value.tv_sec) + u64(value.tv_usec);
}
static inline u64
pCPUTimerRead()
{
return __rdtsc();
}
// ::Platform::Profiling::Functions::End::
// ::Platform::Atomics::Functions::Start::
static inline void
pAtomicSignalFenceSeqCst()
{
__atomic_signal_fence(__ATOMIC_SEQ_CST);
}
static inline u32
pAtomicFetchSubU32(u32 volatile *ptr, u32 count)
{
return __atomic_fetch_sub(ptr, count, __ATOMIC_ACQUIRE);
}
static inline u32
pAtomicFetchIncrU32(u32 volatile *ptr)
{
return __atomic_fetch_add(ptr, (u32)1, __ATOMIC_ACQUIRE);
}
static inline void
pAtomicIncrU32(u32 volatile *ptr)
{
__atomic_fetch_add(ptr, (u32)1, __ATOMIC_RELEASE);
}
static inline u32
pAtomicLoadU32(u32 volatile *ptr)
{
return __atomic_load_n(ptr, __ATOMIC_ACQUIRE);
}
static inline void
pAtomicStoreB32(b32 volatile *ptr, b32 value)
{
__atomic_store_n(ptr, value, __ATOMIC_RELEASE);
}
static inline b32
pAtomicCompareExchangeB32(b32 volatile *ptr, b32 *expected, b32 desired)
{
return __atomic_compare_exchange_n(ptr, expected, desired, true, __ATOMIC_ACQUIRE, __ATOMIC_RELAXED);
}
// ::Platform::Atomics::Functions::End::

View File

@ -1,175 +0,0 @@
// ::Platform::Windows::Globals::Start::
HINSTANCE
g_Win32_Instance = {0};
pPlatformWindow
g_Win32_Window = {0};
b32
g_Global_Quit = false;
// ::Platform::Windows::Globals::End::
LRESULT CALLBACK
WindowProc(HWND window, UINT message, WPARAM w_param, LPARAM l_param)
{
LRESULT result = 0;
switch (message)
{
case WM_SIZE:
{
Printfln("Window resizing");
g_Win32_Window.w = LOWORD(l_param);
g_Win32_Window.h = HIWORD(l_param);
rResolutionSet(g_Win32_Window.w, g_Win32_Window.h);
} break;
case WM_DESTROY: // TODO(MA): Probably handle these separately but for now, they're together
case WM_CLOSE:
{
Printf("quitting");
g_Global_Quit = true;
} break;
case WM_ACTIVATEAPP:
{
OutputDebugStringA("WM_ACTIVATEAPP\n");
} break;
default:
{
result = DefWindowProc(window, message, w_param, l_param);
} break;
}
return result;
}
b32
pLibraryLoad(const char *name, pLibrary *out_lib)
{
b32 success = true;
out_lib->module = LoadLibraryA("vulkan-1.dll");
if (!out_lib->module)
success = false;
return success;
}
b32
pFunctionLoad(const char *name, pLibrary *lib, pFunction *out_fn)
{
b32 success = true;
out_fn->fn = GetProcAddress(lib->module, name);
if (!out_fn->fn)
success = false;
return success;
}
usize
pPageSize()
{
return 0;
}
i32
_Write(void const *str, DWORD std_handle)
{
DWORD written;
BOOL success = WriteFile(GetStdHandle(std_handle), str, StrLen(str), &written, NULL);
return success ? (i32)written : -1;
}
b32
pWindowInit(const char *window_name)
{
b32 success = true;
WNDCLASS window_class = {
.style = CS_OWNDC|CS_HREDRAW|CS_VREDRAW,
.lpfnWndProc = WindowProc,
.hInstance = g_Win32_Instance,
.lpszClassName = WINDOW_CLASS_NAME,
};
ATOM r_class_atom = RegisterClass(&window_class);
if (!r_class_atom)
success = false;
if (success)
{
HWND window_handle = CreateWindowExA(
0,
window_class.lpszClassName,
window_name,
WS_OVERLAPPEDWINDOW|WS_VISIBLE,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
0,
0,
g_Win32_Instance,
0
);
if (!window_handle)
success = false;
else
g_Win32_Window.handle = window_handle;
}
return success;
}
pPlatformWindow *
pWindowGet()
{
return &g_Win32_Window;
}
void
pWindowEventsGet()
{
BOOL has_msg = false;
MSG message;
do
{
has_msg = PeekMessage(&message, 0, 0, 0, PM_REMOVE);
if (has_msg > 0)
{
TranslateMessage(&message);
DispatchMessage(&message);
}
}
while (has_msg);
}
void
pWindowEventWaitFor()
{
MSG message;
BOOL message_result = GetMessageA(&message, 0, 0, 0);
if (message_result > 0)
{
TranslateMessage(&message);
DispatchMessage(&message);
}
}
b32
pWindowShouldQuit()
{
return g_Global_Quit;
}
pWindowSize
pWindowGetSize()
{
return (pWindowSize){ .w = g_Win32_Window.w, .h = g_Win32_Window.h };
}
// ::Platform::Windows::Includes::CFile::
#include "platform_windows_public.c"

View File

@ -1,40 +0,0 @@
#pragma once
#include <windows.h>
#include <stdint.h>
#include <stdbool.h>
#include <immintrin.h>
// ::Platform::Windows::Defines::Header::
#define WINDOW_CLASS_NAME "GearsWindowClass"
// ::Platform::Windows::Types::Header::
typedef struct pPlatformWindow
{
HINSTANCE instance;
HWND handle;
u16 h, w;
b32 resize_requested;
} pPlatformWindow;
typedef struct pLibrary
{
HMODULE module;
} pLibrary;
typedef struct pFunction
{
FARPROC fn;
} pFunction;
typedef struct pThread
{
HANDLE handle;
} pThread;
// ::Platform::Windows::Functions::::Header::
void pWindowEventsGet();
void pWindowEventWaitFor();

View File

@ -1,163 +0,0 @@
// ::Platform::Windows::Memory::Start::
rawptr
pMemAlloc(usize size)
{
return (rawptr)VirtualAlloc(0, size, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE);
}
rawptr
pMemAllocZeroed(usize size)
{
rawptr mem = pMemAlloc(size);
MemZero(mem, size);
return mem;
}
void
pMemFree(rawptr ptr, usize size)
{
Assert(VirtualFree(ptr, size, MEM_RELEASE), "pMemFree failure");
}
// ::Platform::Windows::Memory::End::
// ::Platform::Windows::Print::Start::
i32
pWriteStdOut(rawptr buf, i32 len)
{
return WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE), buf, len, NULL, NULL);
}
i32
pWriteStdErr(rawptr buf, i32 len)
{
return WriteConsole(GetStdHandle(STD_ERROR_HANDLE), buf, len, NULL, NULL);
}
// ::Platform::Windows::Print::End::
// ::Platform::Functions::Directory::Start::
b32
pDirNavigate(c8 *dir)
{
return !(b32)SetCurrentDirectory(dir);
}
// ::Platform::Functions::Directory::End::
// ::Platform::Windows::Profiling::Functions::Start::
static inline u64
pCPUTimerRead()
{
return __rdtsc();
}
// ::Platform::Windows::Profiling::Functions::End::
// ::Platform::Windows::Async::Start::
static pThread
pThreadInit(rawptr proc, rawptr param)
{
pThread thread = {0};
CreateThread(NULL, 0, proc, param, 0, NULL);
return thread;
}
static void
pThreadSuspend(pThread *thread)
{
SuspendThread(thread->handle);
}
static void
pThreadWake(pThread *thread)
{
ResumeThread(thread->handle);
}
static void
pThreadKill()
{
ExitThread(0);
}
// ::Platform::Windows::Async::End::
// ::Platform::Windows::Atomics::Start::
static inline void
pAtomicSignalFenceSeqCst()
{
_ReadWriteBarrier();
}
static inline u32
pAtomicFetchSubU32(u32 volatile *ptr, u32 count)
{
LONG decrement = (LONG)count;
return (u32)InterlockedAddAcquire((LONG volatile *)ptr, -decrement) + decrement;
}
static inline u32
pAtomicFetchIncrU32(u32 volatile *ptr)
{
return (u32)InterlockedIncrementAcquire((LONG volatile *)ptr) - 1;
}
static inline void
pAtomicIncrU32(u32 volatile *ptr)
{
InterlockedIncrementRelease((LONG volatile *)ptr);
}
static inline u32
pAtomicLoadU32(u32 volatile *ptr)
{
return (u32)InterlockedOrAcquire((LONG volatile *)ptr, 0);
}
static inline void
pAtomicStoreB32(b32 volatile *ptr, b32 value)
{
_InterlockedExchange_HLERelease((LONG volatile *)ptr, (LONG)value);
}
static inline b32
pAtomicCompareExchangeB32(b32 volatile *ptr, b32 *expect, b32 desired)
{
return (b32)InterlockedCompareExchangeAcquire((LONG volatile *)ptr, (LONG)desired, (LONG)*expect);
}
// ::Platform::Windows::Atomics::End::
// ::Platform::Windows::Files::Start::
static b8
pDirIsVisible(c8 *dir_name)
{
WIN32_FIND_DATA find_data;
HANDLE handle;
return (handle = FindFirstFile(dir_name, &find_data)) != INVALID_HANDLE_VALUE;
}
// ::Platform::Windows::Files::End::

View File

@ -110,6 +110,8 @@ void rDestroy();
// ::Renderer::Buffers::Header::
static b32 rBufferMap();
static rDescHandle rAssetLoad(c8 *name);
static void rAssetUnload(rDescHandle handle);
static rDescHandle rTextureLoad(TextureAsset asset_id);
static rDescHandle rMeshLoad(ModelAsset asset_id);
static void rTextureUnload(rDescHandle handle);

View File

@ -363,22 +363,6 @@ vImageViewCreate(TexMeta meta)
return view;
}
static vTransfer *
vTextureTransferInit(Arena *arena, u32 asset_id, VkImage image, rawptr bytes, TexMeta *meta)
{
vTransfer *transfer = MakeArray(arena, vTransfer, 1);
transfer->type = vTT_IMAGE;
transfer->data = bytes;
transfer->w = meta->w;
transfer->h = meta->h;
transfer->ch = meta->ch;
transfer->asset_id = asset_id;
transfer->image = image;
return transfer;
}
static b32
vImageViewInit(vImageView *view, u32 width, u32 height, u32 channels)
{
@ -444,86 +428,12 @@ vImageViewInit(vImageView *view, u32 width, u32 height, u32 channels)
return success;
}
static void
vTextureCleanUp()
{
VkDevice device = v_Renderer.handles.device;
VmaAllocator vma_alloc = v_Renderer.handles.vma_alloc;
HashTable *table = &v_Renderer.buffers.images;
b8 *queue = vFrameTexDestroyQueue();
// NOTE: might need a mutex here at some point, check if crashes related to image access
for (u64 i = 0; i < TEXTURE_ASSET_MAX; i++)
{
if (queue[i])
{
rDescHandle handle = vDescHandlePop(vDT_SAMPLED_IMAGE, (u32)i);
vDescIndexPush(vDT_SAMPLED_IMAGE, handle.desc_index);
vImageView *view = vImagePop(i);
Assert(view != NULL, "rTextureUnload failure: value not in hash table");
vkDestroyImageView(device, view->view, NULL);
vmaDestroyImage(vma_alloc, view->image.image, view->image.alloc);
FLMemFree(view);
queue[i] = false;
}
}
pAtomicSignalFenceSeqCst();
}
static void
vImagePush(TextureAsset asset_id, vImageView *view)
{
HashTablePushU64Rawptr(&v_Renderer.buffers.images, asset_id, view);
}
static vImageView *
vImagePop(TextureAsset asset_id)
{
return (vImageView *)HashTableDeleteU64Rawptr(&v_Renderer.buffers.images, asset_id);
}
static vImageView *
vImageSearch(TextureAsset asset_id)
{
vImageView *view = NULL;
HashTable *table = &v_Renderer.buffers.images;
KeyValuePair *pair = HashTableSearchU64(table, asset_id);
if (pair != NULL)
{
view = (vImageView *)pair->value_rawptr;
}
return view;
}
// ::Vulkan::Images::Functions::End::
// ::Vulkan::Descriptors::Functions::Start::
static void
vDescPushImageAndHandle(rDescHandle handle, vImageView *view)
{
vDescHandlePush(vDT_SAMPLED_IMAGE, handle);
vImagePush(handle.asset_id, view);
}
static void
vDescPushModelAndHandle(rDescHandle handle, vModelBuffers *buffer)
{
vDescHandlePush(vDT_MESH, handle);
vModelPush(handle.asset_id, buffer);
}
// TODO: batch descriptor writes
static u32
vDescPushImageDesc(vImageView *view)
@ -598,89 +508,12 @@ vDescIndexPop(vDescType type)
return bindings->free[bindings->free_count];
}
static rDescHandle
vDescHandleSearch(vDescType type, u32 asset_id)
{
rDescHandle asset_info = {
.asset_id = UINT32_MAX,
};
HashTable *table = &v_Renderer.desc_bindings[type].lookup_table;
KeyValuePair *kv_pair = HashTableSearchU64(table, asset_id);
if (kv_pair != NULL)
{
asset_info.asset_id = kv_pair->value_u64_split.upper;
asset_info.desc_index = kv_pair->value_u64_split.lower;
}
return asset_info;
}
static void
vDescHandlePush(vDescType type, rDescHandle handle)
{
HashTable *table = &v_Renderer.desc_bindings[type].lookup_table;
HashTablePushU64U64Split(table, handle.asset_id, handle.asset_id, handle.desc_index);
}
static rDescHandle
vDescHandlePop(vDescType type, u32 asset_id)
{
HashTable *table = &v_Renderer.desc_bindings[type].lookup_table;
U64Split split = HashTableDeleteU64U64Split(table, (u64)asset_id);
Assert(split.upper != UINT32_MAX, "vDescHandlePop failure: unable to find asset handle");
rDescHandle handle = {
.asset_id = split.upper,
.desc_index = split.lower,
};
return handle;
}
static void
vDescHandleDelete(vDescType type, u32 asset_id)
{
HashTable *table = &v_Renderer.desc_bindings[type].lookup_table;
HashTableDeleteU64(table, asset_id);
}
// ::Vulkan::Descriptors::Functions::End::
// ::Vulkan::Buffers::Functions::Start::
static vTransfer *
vMeshTransferInit(Arena *arena, u32 asset_id, vMeshBuffer *mesh, rawptr bytes, u64 size)
{
vTransfer *transfer = MakeArray(arena, vTransfer, 1);
transfer->type = vTT_MESH;
transfer->data = bytes;
transfer->size = size;
transfer->mesh = mesh;
transfer->asset_id = asset_id;
return transfer;
}
static vTransfer *
vBufferTransferInit(Arena *arena, u32 asset_id, vBuffer *index, rawptr bytes, u64 size)
{
vTransfer *transfer = MakeArray(arena, vTransfer, 1);
transfer->type = vTT_BUFFER;
transfer->data = bytes;
transfer->asset_id = asset_id;
transfer->size = size;
transfer->buffer = index->buffer;
return transfer;
}
static VkResult
vBufferCreate(vBuffer* buf, rRenderBufferType type, u64 size)
{
@ -765,32 +598,6 @@ vMapBuffer(VmaAllocation alloc)
return ptr;
}
static void
vModelPush(ModelAsset asset_id, vModelBuffers *buffer)
{
HashTablePushU64Rawptr(&v_Renderer.buffers.buffers, asset_id, buffer);
}
static vModelBuffers *
vModelPop(ModelAsset asset_id)
{
return (vModelBuffers *)HashTableDeleteU64Rawptr(&v_Renderer.buffers.buffers, asset_id);
}
static vModelBuffers *
vModelSearch(ModelAsset asset_id)
{
vModelBuffers *buffers = NULL;
KeyValuePair *pair = HashTableSearchU64(&v_Renderer.buffers.buffers, asset_id);
if (pair != NULL)
{
buffers = (vModelBuffers *)pair->value_rawptr;
}
return buffers;
}
// ::Vulkan::Buffers::Functions::End::

View File

@ -258,6 +258,36 @@ typedef struct vMeshBuffer
vBuffer mesh, uniform;
} vMeshBuffer;
// group assets
// set boolean for each group for loaded/request unload
typedef struct vMeshAsset
{
vMeshBuffer *mesh;
vBuffer *index;
} vMeshAsset;
typedef enum vAssetType_e
{
vAT_NONE,
vAT_TEXTURE,
vAT_MESH,
} vAssetType;
typedef struct vAsset
{
u64 hash;
rDescHandle handle;
union
{
vMeshAsset *mesh;
vImageView *texture;
};
AssetMeta meta;
} vAsset;
ArrayType(vAsset);
typedef struct vSwapchainState
{
VkFormat format;
@ -358,16 +388,10 @@ typedef struct vMappedBuffer
typedef struct vRBuffers
{
HashTable buffers;
vBufferPtrArray frame_buffers[FRAME_OVERLAP];
HashTable images;
vImageViewPtrArray frame_images[FRAME_OVERLAP];
b8PtrArray tex_destroy_queue;
vMappedBuffer transfer;
vMappedBuffer gui_vert;
vMappedBuffer gui_idx;
vAssetArray assets;
vMappedBuffer transfer;
vMappedBuffer gui_vert;
vMappedBuffer gui_idx;
} vRBuffers;
typedef struct vModelBuffers
@ -555,9 +579,6 @@ static vTransfer *vTextureTransferInit(Arena *arena, u32 asset_id, VkImage image
static vImageView *vImageViewCreate(TexMeta meta);
static b32 vImageViewInit(vImageView *view, u32 width, u32 height, u32 channels);
static void vTextureCleanUp();
static void vImagePush(TextureAsset asset_id, vImageView *view);
static vImageView *vImagePop(TextureAsset asset_id);
static vImageView *vImageSearch(TextureAsset asset_id);
// ::Vulkan::Descriptors::Functions::Header::
@ -568,7 +589,6 @@ static u32 vDescIndexPop(vDescType type);
static rDescHandle vDescHandleSearch(vDescType type, u32 asset_id);
static void vDescHandlePush(vDescType type, rDescHandle handle);
static rDescHandle vDescHandlePop(vDescType type, u32 asset_id);
static void vDescHandleDelete(vDescType type, u32 asset_id);
static u32 vDescPushImageDesc(vImageView *view);
static u32 vDescPushMeshDesc(vMeshBuffer *buffer);
@ -578,9 +598,6 @@ static vTransfer *vMeshTransferInit(Arena *arena, u32 asset_id, vMeshBuffer *mes
static vTransfer *vBufferTransferInit(Arena *arena, u32 asset_id, vBuffer *index, rawptr bytes, u64 size);
static VkResult vBufferCreate(vBuffer* buf, rRenderBufferType type, u64 size);
static rawptr vMapBuffer(VmaAllocation alloc);
static void vModelPush(c8 *name, vModelBuffers *buffer);
static vModelBuffers *vModelPop(c8 *name);
static vModelBuffers *vModelSearch(c8 *name);
// ::Vulkan::CleanUp::Functions::Header::

View File

@ -1,156 +0,0 @@
#pragma once
#include <stdint.h>
#ifdef __linux__
#include <sys/types.h>
#endif
// ::SharedTypes::Declarations::Header::
typedef struct Arena Arena;
// ::SharedTypes::Attributes::Header::
#if COMPILER_MSVC || (COMPILER_CLANG && _WIN32)
# pragma section(".rdata$", read)
# define read_only __declspec(allocate(".rdata$"))
#elif (COMPILER_CLANG && __linux__)
# define read_only __attribute__((section(".rodata")))
#elif (COMPILER_GCC && __linux__)
# define read_only
#else
# error read_only not implemented for compiler/target
#endif
// ::SharedTypes::Types::Header::
typedef int8_t i8;
typedef int16_t i16;
typedef int32_t i32;
typedef int64_t i64;
typedef uint8_t u8;
typedef uint16_t u16;
typedef uint32_t u32;
typedef uint64_t u64;
typedef char c8;
typedef intptr_t intptr;
typedef uintptr_t uintptr;
typedef float f32;
typedef double f64;
typedef uint8_t b8;
typedef uint32_t b32;
typedef void * rawptr;
typedef struct String8
{
c8 *value;
u64 len;
} String8;
#ifdef __linux__
typedef ssize_t isize;
typedef size_t usize;
#elif _WIN32
#if defined ( _WIN64 )
typedef int64_t isize;
typedef uint64_t usize;
#elif defined ( _WIN32 )
typedef int32_t isize;
typedef uint32_t usize;
#endif
#else // unix
#endif
typedef union
{
struct { u32 upper, lower; };
u64 full;
} U64Split;
typedef union
{
struct { f32 r, g; };
struct { f32 x, y; };
} Vec2;
typedef union
{
struct { f32 x, y, z; };
struct { f32 r, g, b; };
} Vec3;
typedef union
{
struct { f32 x, y, z, w; };
struct { f32 r, g, b, a; };
} Vec4;
typedef union
{
struct { u16 x, y; };
struct { u16 r, g; };
struct { u16 w, h; };
} u16Vec2;
typedef union
{
struct { i32 x, y; };
struct { i32 r, g; };
} iVec2;
typedef union
{
struct { i32 x, y, z; };
struct { i32 r, g, b; };
} iVec3;
typedef union
{
struct { i32 x, y, z, w; };
struct { i32 r, g, b, a; };
} iVec4;
typedef union
{
struct { i16 x, y; };
struct { i16 r, g; };
struct { i16 w, h; };
} i16Vec2;
typedef f32 Mat2[4];
typedef f32 Mat3[9];
typedef f32 Mat4[16];
typedef f64 dMat2[4];
typedef f64 dMat3[9];
typedef f64 dMat4[16];
typedef struct Vertex
{
Vec4 pos;
Vec4 col;
} Vertex;
typedef struct m3dModel
{
Vertex *vertices;
u32 *indices;
u64 v_count;
u64 i_count;
} m3dModel;

3968
src/stglib.h Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,484 +0,0 @@
// ::Util::Globals::Start::
static Profiler
g_Global_Profiler;
// ::Util::Globals::End::
// ::Util::Strings::Functions::Start::
static void
StrConcat(c8 *str, c8 *append)
{
u32 len = StrLen(str);
u32 i = 0;
for (; append[i] != '\0'; i += 1)
{
str[i] = append[i];
}
str[i] = '\0';
}
static b32
StrEqL(const char *l, const char *r, u64 len)
{
for (u64 i = 0; *l == *r && *l && i < len; l++, r++, i++);
return *l == *r;
}
static b32
StrEq(const char *l, const char *r)
{
for (; *l == *r && *l; l++, r++);
return *l == '\0' && *r == '\0';
}
static u32
StrLen(const char *str)
{
const char *start;
for (start = str; *str != '\0'; ++str)
/* Iterate only */;
return (u32)(str - start);
}
static i32
SPrintf(char *buf, int len, rawptr fmt, ...)
{
va_list arg;
va_start(arg, fmt);
int sprf_res = stbsp_vsnprintf(buf, len, fmt, arg);
va_end(arg);
return sprf_res;
}
static String8
MakeString8(c8 *str, u64 len)
{
return (String8){ .len = len, .value = str };
}
static String8
String8Concat(Arena *arena, String8 string, String8 append)
{
u64 str_len = string.len + append.len;
String8 str = {
.value = MakeArray(arena, c8, str_len),
.len = str_len,
};
MemCpy(str.value, string.value, string.len);
MemCpy(str.value+string.len, append.value, append.len);
return str;
}
static void
String8TrimSuffix(String8 *str, c8 delimiter)
{
if (!str || str->len == 0) return;
for (i64 i = i64(str->len)-1; i > 0; i -= 1)
{
if (str->value[i] == delimiter)
{
str->value[i] = '\0';
str->len = i == 0 ? 0 : u64(i - 1);
break;
}
}
}
static i64
String8FindLast(String8 str, c8 delimiter)
{
if (str.len == 0) return -1;
i64 result = 1;
for (i64 i = i64(str.len)-1; i >= 0; i -= 1)
{
if (str.value[i] == delimiter)
{
result = i;
break;
}
}
return result;
}
static b32
String8Eq(String8 l, String8 r)
{
return StrEqL(l.value, r.value, l.len);
}
static b32
String8StartsWith(String8 string, String8 cmp)
{
return StrEqL(string.value, cmp.value, cmp.len);
}
static String8
PreSplitString8(String8 string, String8 delimiter)
{
if (string.len == 0 || delimiter.len == 0) return string;
u32 new_len = 0;
u32 matched_chars = 0;
for (u32 i = 0; i < string.len; i++)
{
if (string.value[i] == delimiter.value[matched_chars])
matched_chars += 1;
else
matched_chars = 0;
if (matched_chars == delimiter.len || delimiter.value[matched_chars+1] == '\0')
{
new_len = i;
break;
}
}
return (String8){ .len = new_len, .value = string.value };
}
static String8
PreSplitNewString8(Arena *arena, String8 string, String8 delimiter)
{
String8 result = PreSplitString8(string, delimiter);
if (result.len > 0)
{
result.value = MakeArray(arena, char, result.len+1);
MemCpy(result.value, string.value, result.len);
result.value[result.len] = '\0';
}
return result;
}
// ::Util::Strings::Functions::End::
// ::Util::Memory::Functions::Start::
void
MemZero(void *ptr, isize size)
{
if (!size || !ptr) return;
isize iter_size = size > sizeof(u64) ? 8 : 1;
iter_size *= 4;
isize iter_len = size / iter_size;
u64 *mem = (u64 *)ptr;
if (iter_size > sizeof(u64))
{
while (iter_len > 0)
{
mem[0] = 0;
mem[1] = 0;
mem[2] = 0;
mem[3] = 0;
mem += 4;
iter_len--;
}
}
u8 *byte_mem = (u8 *)mem;
isize rem_len = size % iter_size;
while (rem_len > 0)
{
byte_mem[0] = 0;
byte_mem++;
rem_len--;
}
}
void
MemCpy(rawptr dst, rawptr src, usize size)
{
if (size == 0) return;
isize iter_size = size > sizeof(u64) ? 8 : 1;
iter_size *= 4;
isize iter_len = size / iter_size;
isize rem_len = 0;
u64 *mem_dst = (u64 *)dst;
u64 *mem_src = (u64 *)src;
if (iter_size > sizeof(size))
{
while (iter_len > 0)
{
mem_dst[0] = mem_src[0];
mem_dst[1] = mem_src[1];
mem_dst[2] = mem_src[2];
mem_dst[3] = mem_src[3];
mem_dst += 4;
mem_src += 4;
iter_len--;
}
rem_len = size % iter_size;
}
else
rem_len = size;
u8 *byte_dst = (u8 *)mem_dst;
u8 *byte_src = (u8 *)mem_src;
while (rem_len > 0)
{
byte_dst[0] = byte_src[0];
byte_dst++;
byte_src++;
rem_len--;
}
}
// ::Util::Memory::Functions::End::
// ::Util::Math::Functions::Start::
DefMathImpl(Min);
DefMathImpl(Max);
DefMathImpl(Clamp);
DefMathImpl(Abs);
// ::Util::Math::Functions::End::
// ::Util::Hashing::Functions::Start::
u64 static inline
HashFromString(String8 string)
{
return XXH3_64bits_withSeed(string.value, string.len, HASH_SEED);
}
// ::Util::Hashing::Functions::End::
// ::Util::Print::Functions::Start::
i32
Printf(char *fmt, ...)
{
va_list arg;
va_start(arg, fmt);
i32 result = _Printf(fmt, arg);
va_end(arg);
return result;
}
i32
Printfln(char *fmt, ...)
{
va_list arg;
va_start(arg, fmt);
i32 result = _Printfln(fmt, arg);
va_end(arg);
return result;
}
i32
EPrintf(char *fmt, ...)
{
va_list arg;
va_start(arg, fmt);
i32 result = _EPrintf(fmt, arg);
va_end(arg);
return result;
}
i32
EPrint(void *str)
{
return pWriteStdErr(str, (isize)StrLen(str));
}
i32
_EPrintf(char *fmt, va_list arg)
{
char buffer[1024];
int sprf_res = stbsp_vsnprintf(&buffer[0], 1024, fmt, arg);
if (sprf_res < 0) return sprf_res;
return EPrint(&buffer);
}
i32
_Printf(char *fmt, va_list arg)
{
char buffer[1024];
int sprf_res = stbsp_vsnprintf(&buffer[0], 1024, fmt, arg);
i32 pr_res;
if (sprf_res < 0)
pr_res = sprf_res;
else
pr_res = pWriteStdOut(&buffer, sprf_res);
return pr_res;
}
i32
_Printfln(char *fmt, va_list arg)
{
char buffer[1024];
int sprf_res = stbsp_vsnprintf(&buffer[0], 1023, fmt, arg);
i32 pr_res;
if (sprf_res < 0)
{
pr_res = sprf_res;
}
else
{
buffer[sprf_res] = '\n';
buffer[sprf_res+1] = '\0';
pr_res = pWriteStdOut(&buffer, sprf_res+1);
}
return pr_res;
}
// ::Util::Print::Functions::End::
// ::Util::Profiling::Functions::Start::
static inline void
StartProfileBlock(ProfileBlock *block, c8 *label, u32 anchor_index)
{
block->anchor_index = anchor_index;
block->label = label;
block->start_tsc = pCPUTimerRead();
}
static inline void
EndProfileBlock(ProfileBlock *block)
{
u64 elapsed = pCPUTimerRead() - block->start_tsc;
ProfileAnchor *anchor = g_Global_Profiler.anchors + block->anchor_index;
anchor->tsc_elapsed += elapsed;
anchor->hit_count += 1;
anchor->label = block->label;
}
// ::Util::Profiling::Functions::End::
// ::Util::Async::Functions::Start::
static inline b32
MutTryLock(Mut *mut)
{
b32 lock = false;
return pAtomicCompareExchangeB32(&mut->lock, &lock, 1);
}
static inline void
MutUnlock(Mut *mut)
{
pAtomicStoreB32(&mut->lock, 0);
}
static inline void
TicketMutInit(TicketMut *mut)
{
mut->ticket = 0;
mut->next_ticket = 1;
}
static inline void
TicketMutLock(TicketMut *mut)
{
u32 ticket = pAtomicFetchIncrU32(&mut->ticket);
while (ticket != mut->next_ticket);
}
static inline void
TicketMutUnlock(TicketMut *mut)
{
pAtomicIncrU32(&mut->next_ticket);
}
static inline u32
JobQueueAdd(JobQueue *queue, u32 count)
{
u32 job_idx = pAtomicFetchIncrU32(&queue->queued);
pAtomicFetchIncrU32(&queue->remaining);
return job_idx;
}
static inline u32
JobQueueGetCount(JobQueue *queue)
{
return pAtomicLoadU32(&queue->queued);
}
static inline void
JobQueueMarkUnqueued(JobQueue *queue, u32 count)
{
Assert(queue->queued != 0, "queue queued is 0 before trying to mark dequeued");
pAtomicFetchSubU32(&queue->queued, count);
}
static inline void
JobQueueMarkCompleted(JobQueue *queue, u32 count)
{
Assert(queue->remaining != 0, "queue remaining is 0 before trying to mark completed");
pAtomicFetchSubU32(&queue->remaining, count);
}
static inline void
JobQueueReset(JobQueue *queue)
{
pAtomicFetchSubU32(&queue->queued, queue->queued);
pAtomicFetchSubU32(&queue->remaining, queue->remaining);
}
static inline b32
JobQueueCompleted(JobQueue *queue)
{
u32 remaining = pAtomicLoadU32(&queue->remaining);
return remaining == 0;
}
// ::Util::Async::Functions::End::

View File

@ -1,299 +0,0 @@
#pragma once
#include <assert.h>
typedef struct Arena Arena;
// ::Util::Macros::Header::
#define Assert(condition, message) do { assert((condition) && (message)); } while(0)
#define KB(n) n * 1024LL
#define MB(n) KB(n) * 1024LL
#define GB(n) MB(n) * 1024LL
#define TB(n) GB(n) * 1024LL
#define BitEq(var, bits) (((var) & (bits)) == (bits))
#define AlignPow2(x, b) (((x) + (b) - 1) & (~((b) - 1)))
#define IsPow2(x) ((x) != 0 && ((x) &((x) - 1)) == 0)
#define PtrAdd(ptr, add) (((u8 *)ptr) + add)
#define PtrAddAdjustLen(ptr, len, add) \
ptr = PtrAdd(ptr, add); \
len -= add
#define Diff(value, sub) (value - sub)
#define MakeArray(arena, type, count) ArenaAlloc(arena, (isize)(sizeof(type)) * (isize)(count))
#define Len(x) ((sizeof(x)/sizeof(0[x])) / ((size_t)(!(sizeof(x) % sizeof(0[x])))))
#define MakeString(x) #x
#define i8(x) ((i8)(x))
#define i16(x) ((i16)(x))
#define i32(x) ((i32)(x))
#define i64(x) ((i64)(x))
#define u8(x) ((u8)(x))
#define u16(x) ((u16)(x))
#define u32(x) ((u32)(x))
#define u64(x) ((u64)(x))
#define c8(x) ((c8)(x))
#define c8ptr(x) ((c8 *)(x))
#define u8ptr(x) ((u8 *)(x))
#define i8ptr(x) ((i8 *)(x))
#define intptr(x) ((intptr)(x))
#define uintptr(x) ((uintptr)(x))
#define f32(x) ((f32)(x))
#define f64(x) ((f64)(x))
#define rawptr(x) ((rawptr)(x))
#define cast(T, x) ((T)(x))
#define DefScalarSig(def) \
DefSig##def(i8); \
DefSig##def(i16); \
DefSig##def(i32); \
DefSig##def(i64); \
DefSig##def(u8); \
DefSig##def(u16); \
DefSig##def(u32); \
DefSig##def(u64); \
DefSig##def(b8); \
DefSig##def(b32)
#define DefScalarImpl(def) \
Def##def(i8); \
Def##def(i16); \
Def##def(i32); \
Def##def(i64); \
Def##def(u8); \
Def##def(u16); \
Def##def(u32); \
Def##def(u64); \
Def##def(b8); \
Def##def(b32)
#define ArrayType(T) \
typedef struct T##Array \
{ \
T *data; \
u64 length; \
u64 cap; \
} T##Array
#define PtrArrayType(T) \
typedef struct T##PtrArray \
{ \
T **data; \
u64 length; \
u64 cap; \
} T##PtrArray
#define InitArrayType(arr, arena, T, len) \
arr.data = MakeArray(arena, T, len); \
arr.length = 0; \
arr.cap = len
// ::Util::LinkedList::Macros::
#define CheckNil(nil, p) ((p) == 0 || (p) == nil)
#define SetNil(nil, p) ((p) = nil)
// ::Util::DoubleHeadedLinkedList::Macros::
#define SLLConcatInPlaceNoCount(list, to_concat) do { \
if ((to_concat)->first) \
{ \
if ((list)->first) \
{ \
(list)->last->next = (to_concat)->first; \
(list)->last = (to_concat)->last; \
} \
else \
{ \
(list)->first = (to_concat)->first; \
(list)->last = (to_concat)->last; \
} \
MemZero(to_concat, sizeof(*to_concat)); \
} \
} while (0)
#define _SLLQueuePop(nil, f, l, next) ((f) == (l) ? \
(SetNil(nil, f), SetNil(nil, l)) : \
((f) = (f)->next))
#define _SLLQueuePushFront(nil, f, l, n, next) (CheckNil(nil, f) ? \
((f) = (l) = (n), SetNil(nil, (n)->next)) : \
((n)->next = (f), (f) = (n)))
#define _SLLQueuePush(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 SLLQueuePop(nil, f, l) _SLLQueuePop(nil, f, l, next)
#define SLLQueuePush(nil, f, l, n) _SLLQueuePush(nil, f, l, n, next)
#define SLLQueuePushFront(nil, f, l, n) _SLLQueuePushFront(nil, f, l, n, next)
// ::Util::String8::Macros::
#define String8Array(v, c) MakeString8((c8 *)(v), sizeof(*(v))*(c))
#define String8Struct(v) MakeString8((c8 *)(v), sizeof(*(v)))
#define String8CStr(v) MakeString8((c8 *)v, StrLen(v))
// ::Util::Defines::Header::
constexpr u32 HM_MAX_SYMBOLS = 256;
constexpr usize DEFAULT_ALIGNMENT = (2*sizeof(rawptr));
constexpr u64 HASH_SEED = 5995;
// ::Util::Strings::Functions::Header::
static b32 String8Eq(String8 l, String8 r);
static u32 StrLen(const char *str);
static b32 StrEqL(const char *l, const char *r, u64 len);
static b32 StrEq(const char *l, const char *r);
static i32 SPrintf(char *buf, int len, rawptr fmt, ...);
static void StrConcat(c8 *str, c8 *append);
static String8 MakeString8(c8 *str, u64 len);
static String8 String8Concat(Arena *arena, String8 string, String8 append);
static void String8TrimSuffix(String8 *str, c8 delimiter);
static i64 String8FindLast(String8 str, c8 delimiter);
static String8 PreSplitString8(String8 string, String8 delimiter);
static String8 PreSplitNewString8(Arena *arena, String8 string, String8 delimiter);
// ::Util::Memory::Functions::Header::
void MemZero(void *ptr, isize size);
void MemCpy(rawptr dst, rawptr src, usize len);
// ::Util::Math::Functions::Header::
#define DefIntegerImpl(def) \
Def##def(i8); \
Def##def(i16); \
Def##def(i32); \
Def##def(i64); \
Def##def(u8); \
Def##def(u16); \
Def##def(u32); \
Def##def(u64)
#define DefFloatImpl(def) \
Def##def(f32); \
Def##def(f64)
#define DefMathImpl(def) \
DefIntegerImpl(def); \
DefFloatImpl(def)
#define DefMin(T) \
T Min##T(T l, T r) \
{ \
return l < r ? l : r; \
}
#define DefMax(T) \
T Max##T(T l, T r) \
{ \
return l > r ? l : r; \
}
#define DefClamp(T) \
T Clamp##T(T v, T min, T max) \
{ \
return Min##T(max, Max##T(v, min)); \
}
#define DefAbs(T) \
T Abs##T(T v) \
{ \
return v < (T)0 ? -v : v; \
}
// ::Util::Hashing::Functions::Header::
u64 static inline HashFromString(String8 string);
// ::Util::Print::Functions::Header::
i32 EPrint(void *str);
i32 Printf(char *fmt, ...);
i32 Printfln(char *fmt, ...);
i32 EPrintf(char *fmt, ...);
i32 _EPrint(void *str);
i32 _Printf(char *fmt, va_list arg);
i32 _Printfln(char *fmt, va_list arg);
i32 _EPrintf(char *fmt, va_list arg);
// ::Util::Profiling::Header::
#define NameConcat2(a, b) a##b
#define NameConcat(a, b) NameConcat2(a, b)
#define TimeBlockStart(name) ProfileBlock NameConcat(Block, name) = {0}; \
StartProfileBlock(&NameConcat(Block, name), #name, __COUNTER__ + 1)
#define TimeBlockEnd(name) EndProfileBlock(&NameConcat(Block, name))
#define TimeBlockFuncStart(name) ProfileBlock NameConcat(Block, function) = {0}; \
StartProfileBlock(& NameConcat(Block, function), name, __COUNTER__ + 1)
#define TimeFunctionStart TimeBlockFuncStart(__func__)
#define TimeFunctionEnd TimeBlockEnd(function)
typedef struct ProfileAnchor
{
u64 tsc_elapsed;
u64 hit_count;
c8 *label;
} ProfileAnchor;
typedef struct ProfileBlock
{
c8 *label;
u64 start_tsc;
u32 anchor_index;
} ProfileBlock;
typedef struct Profiler
{
ProfileAnchor anchors[4096];
u64 start_tsc;
u64 end_tsc;
} Profiler;
static inline void StartProfileBlock(ProfileBlock *block, c8 *label, u32 anchor_index);
static inline void EndProfileBlock(ProfileBlock *block);
// ::Util::Async::Header::
typedef struct TicketMut
{
u32 volatile ticket;
u32 volatile next_ticket;
} TicketMut;
typedef struct Mut
{
b32 volatile lock;
} Mut;
typedef struct JobQueue
{
u32 volatile queued;
u32 volatile remaining;
} JobQueue;
static inline b32 MutTryLock(Mut *mut);
static inline void MutUnlock(Mut *mut);
static inline void TicketMutLock(TicketMut *mut);
static inline void TicketMutUnlock(TicketMut *mut);
static inline u32 JobQueueAdd(JobQueue *queue, u32 count);
static inline u32 JobQueueGetCount(JobQueue *queue);
static inline void JobQueueMarkUnqueued(JobQueue *queue, u32 count);
static inline void JobQueueMarkCompleted(JobQueue *queue, u32 count);
static inline void JobQueueReset(JobQueue *queue);
static inline b32 JobQueueCompleted(JobQueue *queue);