From 34b4e7a4c5c319bac3e24098feac21b00f0fdb50 Mon Sep 17 00:00:00 2001 From: matthew Date: Sat, 16 Aug 2025 10:53:26 +1000 Subject: [PATCH] clean up --- dub.json | 4 +- src/DLibs | 2 +- src/shared/aliases.d | 42 -- src/shared/alloc.d | 133 ----- src/shared/assets.d | 317 ------------ src/shared/fonts.d | 210 -------- src/shared/includes.c | 28 -- src/shared/math.d | 1086 ----------------------------------------- src/shared/util.d | 661 ------------------------- 9 files changed, 3 insertions(+), 2480 deletions(-) delete mode 100644 src/shared/aliases.d delete mode 100644 src/shared/alloc.d delete mode 100644 src/shared/assets.d delete mode 100644 src/shared/fonts.d delete mode 100644 src/shared/includes.c delete mode 100644 src/shared/math.d delete mode 100644 src/shared/util.d diff --git a/dub.json b/dub.json index 557156c..aee14ec 100644 --- a/dub.json +++ b/dub.json @@ -9,8 +9,8 @@ "targetPath": "build", "sourceFiles-linux": ["build/libvma.a", "build/libstb_image.a", "build/libm3d.a", "build/libcglm.a"], "sourceFiles-windows": [], - "importPaths": ["src/gears", "src/shared", "external/xxhash", "external/inteli", "src/VulkanRenderer"], - "sourcePaths": ["src/gears", "src/shared", "external/xxhash", "external/inteli", "src/VulkanRenderer"], + "importPaths": ["src/gears", "src/DLibs", "src/DLibs/external/xxhash", "src/VulkanRenderer"], + "sourcePaths": ["src/gears", "src/DLibs", "src/DLibs/external/xxhash", "src/VulkanRenderer"], "libs-linux": ["xcb", "X11", "X11-xcb", "vulkan", "stdc++", "xcb-xfixes", "freetype"], "libs-windows": [], "preGenerateCommands-linux": ["./build.sh"], diff --git a/src/DLibs b/src/DLibs index fb45fd7..a91b50c 160000 --- a/src/DLibs +++ b/src/DLibs @@ -1 +1 @@ -Subproject commit fb45fd78ebb8e2c59de3ff89f932a50dba628638 +Subproject commit a91b50cb90397e4455bd505017541c72d1a959e0 diff --git a/src/shared/aliases.d b/src/shared/aliases.d deleted file mode 100644 index e183734..0000000 --- a/src/shared/aliases.d +++ /dev/null @@ -1,42 +0,0 @@ -import core.memory; -import std.stdint; -import math; - -debug -{ - const BUILD_DEBUG = true; -} -else -{ - const BUILD_DEBUG = false; -} - -alias i8 = byte; -alias i16 = short; -alias i32 = int; -alias i64 = long; - -alias u8 = ubyte; -alias u16 = ushort; -alias u32 = uint; -alias u64 = ulong; - -alias f32 = float; -alias f64 = double; - -alias b32 = uint; - -alias intptr = i64; -alias uintptr = u64; - -alias usize = size_t; - -alias Vec2 = Vector!(f32, 2); -alias Vec3 = Vector!(f32, 3); -alias Vec4 = Vector!(f32, 4); - -alias UVec2 = Vector!(u32, 2); - -alias Mat2 = Matrix!(f32, 2); -alias Mat3 = Matrix!(f32, 3); -alias Mat4 = Matrix!(f32, 4); diff --git a/src/shared/alloc.d b/src/shared/alloc.d deleted file mode 100644 index e3354ab..0000000 --- a/src/shared/alloc.d +++ /dev/null @@ -1,133 +0,0 @@ -import aliases; -import math; -import std.stdio; -import core.stdc.string : memset; -import core.memory; -import platform; - -const DEFAULT_ALIGNMENT = (void *).sizeof * 2; - -struct Arena -{ - u8* mem; - u64 length; - u64 pos; -}; - -T* -MAlloc(T)() -{ - void* mem = MemAlloc(T.sizeof); - return cast(T*)mem; -} - -T[] -MAllocArray(T)(u64 count) -{ - void* mem = MemAlloc(T.sizeof * count); - return cast(T*)(mem)[0 .. count]; -} - -void -MFree(T)(T* ptr) -{ - MemFree(cast(void*)ptr, T.sizeof); -} - -void -MFreeArray(T)(T[] slice) -{ - MemFree(cast(void*)slice.ptr, cast(u64)slice.length); -} - -T* -Alloc(T)() -{ - void* mem = pureMalloc(T.sizeof); - memset(mem, 0, T.sizeof); - return (cast(T*)mem); -} - -T[] -AllocArray(T)(u64 count) -{ - void* mem = pureMalloc(T.sizeof * count); - memset(mem, 0, T.sizeof * count); - return (cast(T*)mem)[0 .. count]; -} - -Arena -CreateArena(u64 size) -{ - Arena arena = { - mem: cast(u8 *)pureMalloc(size), - length: size, - pos: 0, - }; - - assert(arena.mem != null, "Unable to allocate memory for arena"); - - return arena; -}; - -T[] -AllocArray(T)(Arena* arena, u64 count) -{ - void* mem = AllocAlign(arena, T.sizeof * count, DEFAULT_ALIGNMENT); - memset(mem, 0, T.sizeof * count); - return (cast(T*)mem)[0 .. count]; -} - -T* -Alloc(T)(Arena* arena) -{ - void* mem = AllocAlign(arena, T.sizeof, DEFAULT_ALIGNMENT); - memset(mem, 0, T.sizeof); - return cast(T*)mem; -}; - -void* -AllocAlign(Arena* arena, u64 size, u64 alignment) -{ - void* ptr = null; - - uintptr mem_pos = cast(uintptr)arena.mem; - uintptr current = mem_pos + arena.pos; - uintptr offset = AlignPow2(current, alignment) - mem_pos; - - if (offset+size <= arena.length) - { - ptr = &arena.mem[offset]; - arena.pos = offset+size; - } - else - { - writefln("AllocAlign failure: out of memory, size requested: %llu", size); - assert(0); - } - - return ptr; -}; - -void -Reset(Arena* arena) -{ - arena.pos = 0; -} - -void -Free(Arena* arena) -{ - pureFree(arena.mem); -} - -void -FreeArray(T)(T[] arr) -{ - pureFree(arr.ptr); -} - -void Free(T)(T* ptr) -{ - pureFree(ptr); -} diff --git a/src/shared/assets.d b/src/shared/assets.d deleted file mode 100644 index bf68e9d..0000000 --- a/src/shared/assets.d +++ /dev/null @@ -1,317 +0,0 @@ -import aliases; -import std.file; -import std.stdio; -import util; -import std.exception; -import alloc; - -File Asset_File; - -FileHeader Asset_Header; - -AssetInfo[] Asset_Info; - -u8[][] Asset_Data; - -const u32 FILE_VERSION = 2; -const u32 MODEL_VERSION = 1; - -enum AssetType : u32 -{ - None, - ModelM3D, - Shader, - Texture, -} - -alias AT = AssetType; - -struct FileHeader -{ - u32 magic; - u32 file_version; - u64 asset_count; - u64 asset_info_offset; -} - -struct ModelHeader -{ - u32 magic; - u32 model_version; - u64 vertex_count; - u64 vertex_offset; - u64 index_count; - u64 index_offset; - u64 material_count; - u64 material_offset; - u64 texture_count; - u64 texture_offset; -} - -struct Vertex -{ - Vec4 color; - Vec4 tangent; - Vec3 pos; - Vec3 normal; - Vec2 uv; -} - -struct ModelData -{ - Vertex[] vertices; - u32[] indices; - Material[] materials; - TextureInfo[] textures; -} - -struct Material -{ - Vec4 ambient; - Vec4 albedo; - Vec4 specular; - u32 albedo_texture; - u32 ambient_texture; - u32 specular_texture; - u32 alpha_texture; - b32 albedo_has_texture; - b32 ambient_has_texture; - b32 specular_has_texture; - b32 alpha_has_texture; - f32 shininess = 0.0; - f32 alpha = 0.0; -} - -struct TextureInfo -{ - string name; - u32 id; -} - -struct TextureHeader -{ - u64 str_length; - u64 str_offset; - u32 texture_id; -} - -struct ModelMeta -{ - u64 index_count; -} - -struct TexData -{ - void* data; - TexMeta meta; -} - -struct TexMeta -{ - u32 w; - u32 h; - u32 ch; -} - -struct AssetInfo -{ - u64 hash; - u64 offset; - u64 length; - AssetType type; -} - -bool Asset_Pack_Opened = false; - -debug -{ - -bool g_DIR_SET = false; - -void -SetDir() -{ - if (exists("assets")) - { - chdir("./assets"); - } - else if (exists("Gears") || exists("Gears.exe")) - { - chdir("../assets"); - } - else - { - assert(false, "Unable to set directory"); - } - - g_DIR_SET = true; -} - -u8[] -LoadAssetData(Arena* arena, string name) -{ - if (!g_DIR_SET) - { - SetDir(); - } - - File f; - try - { - f = File(name, "rb"); - } - catch (ErrnoException e) - { - assert(false, "Unable to open file"); - } - - u8[] mem = AllocArray!(u8)(arena, f.size()); - return f.rawRead(mem); -} - -} -else -{ - -void -OpenAssetPack() -{ - if (!Asset_Pack_Opened) - { - bool success = true; - string file_path = exists("build/assets.sgp") ? "build/assets.sgp" : "assets.sgp"; - - // TODO: replace this with something that doesn't throw an exception and figure out if this is the best way to handle thing (probably isnt) - try - { - Asset_File = File(file_path, "rb"); - } - catch (ErrnoException e) - { - Logf("OpenAssetPack failure: Unable to open file %s", file_path); - assert(false, "Unable to open asset pack file"); - } - - FileHeader[1] header_arr; - - Asset_File.rawRead(header_arr); - - Asset_Header = header_arr[0]; - - Asset_Info = AllocArray!(AssetInfo)(Asset_Header.asset_count); - Asset_Data = AllocArray!(u8[])(Asset_Header.asset_count); - - assert(Asset_Header.file_version == FILE_VERSION, "OpenAssetPack failure: file version incorrect"); - - Asset_File.seek(Asset_Header.asset_info_offset); - - Asset_File.rawRead(Asset_Info); - } -} - -pragma(inline): void -CheckAssetPack() -{ - if (!Asset_Pack_Opened) - { - OpenAssetPack(); - } -} - -AssetInfo -GetAssetInfo(string name) -{ - CheckAssetPack(); - - u64 hash = Hash(name); - - AssetInfo asset_info; - foreach(i, info; Asset_Info) - { - if (info.hash == hash) - { - asset_info = info; - break; - } - } - - assert(asset_info.hash != 0, "GetAssetInfo failure: unable to find matching asset"); - - return asset_info; -} - -u8[] -LoadAssetData(Arena* arena, string name) -{ - CheckAssetPack(); - - u64 hash = Hash(name); - u8[] data = null; - - foreach(i, info; Asset_Info) - { - if (info.hash == hash) - { - data = AllocArray!(u8)(arena, info.length); - Asset_File.seek(info.offset); - Asset_File.rawRead(data); - assert(data != null && data.length == info.length, "LoadAssetData failure: Asset data loaded incorrectly"); - - break; - } - } - - return data; -} - -u8[] -LoadAssetData(string name) -{ - CheckAssetPack(); - - u64 hash = Hash(name); - u8[] data = null; - - foreach(i, info; Asset_Info) - { - if (info.hash == hash) - { - if (Asset_Data[i].ptr == null) - { - Asset_Data[i] = AllocArray!(u8)(info.length); - Asset_File.seek(info.offset); - Asset_File.rawRead(Asset_Data[i]); - assert(Asset_Data[i] != null && Asset_Data[i].length == info.length, "LoadAssetData failure: Asset data loaded incorrectly."); - } - - data = Asset_Data[i]; - break; - } - } - - return data; -} - -void -UnloadAssetData(string name) -{ - u64 hash = Hash(name); - - foreach(i, info; Asset_Info) - { - if (info.hash == hash) - { - if (Asset_Data[i] != null) - { - FreeArray(Asset_Data[i]); - break; - } - } - } -} - -} - - - - diff --git a/src/shared/fonts.d b/src/shared/fonts.d deleted file mode 100644 index 9b4b0cf..0000000 --- a/src/shared/fonts.d +++ /dev/null @@ -1,210 +0,0 @@ -import aliases; -import includes; -import util; -import alloc; - -enum AtlasType -{ - None = 0, - SoftMask, -} - -enum YOrigin -{ - None = 0, - Bottom, -} - -struct FontAtlas -{ - AtlasType type; - f32 size; - u32 width; - u32 height; - YOrigin y_origin; - f32 em_size; - f32 line_height; - f32 ascender; - f32 descender; - f32 underline_y; - f32 underline_thickness; - Glyph[] glyphs; -} - -struct Glyph -{ - dchar ch; - f32 advance; - f32 plane_left; - f32 plane_bottom; - f32 plane_right; - f32 plane_top; - f32 atlas_left; - f32 atlas_bottom; - f32 atlas_right; - f32 atlas_top; -} - -FT_Library FT_LIB; -alias FontFace = FT_Face; - -struct FontAtlasBuf -{ - u8[] data; - FontAtlas atlas; -} - -void -InitFreeType() -{ - FT_Init_FreeType(&FT_LIB); -} - -void -CloseFreeType() -{ - if (FT_LIB) - { - FT_Done_FreeType(FT_LIB); - } -} - -FontFace -OpenFont(u8[] data) -{ - FontFace font; - FT_New_Memory_Face(FT_LIB, data.ptr, cast(FT_Long)data.length, 0, &font); - return font; -} - -void -CloseFont(FontFace font) -{ - if (font != null) - { - FT_Done_Face(font); - } -} - -FontAtlasBuf -CreateAtlas(Arena* arena, FontFace font, f32 size, u32 dimension) -{ - assert(dimension >= 128, "Dimension must be at least 128"); - - FontAtlasBuf atlas = { - data: AllocArray!(u8)(arena, dimension * dimension * 4), - atlas: { - size: size, - width: dimension, - height: dimension, - }, - }; - - // TODO: proper packing algorithm - if (font != null) - { - FT_Set_Pixel_Sizes(font, 0, cast(FT_UInt)((96.0/72.0) * size)); - - i64 f_ascent = cast(i64)(font.size.metrics.ascender >> 6); - i64 f_descent = cast(i64)(font.size.metrics.descender >> 6); - i64 f_height = cast(i64)(font.size.metrics.height >> 6); - - u32 max_w = 0; - u32 max_h = 0; - u32 current_h = 0; - u32 count = 0; - - FT_UInt index; - FT_ULong char_code = FT_Get_First_Char(font, &index); - while (index != 0) - { - FT_Load_Char(font, char_code, cast(FT_Int32)FT_LOAD_RENDER); - - u32 bmp_w = font.glyph.bitmap.width; - u32 bmp_h = font.glyph.bitmap.rows; - if (max_w + bmp_w > dimension) - { - max_h += current_h; - max_w = 0; - } - - assert(max_h < dimension, "Unable to pack atlas within dimensions"); - - max_w += bmp_w; - current_h = bmp_h > current_h ? bmp_h : current_h; - count += 1; - - char_code = FT_Get_Next_Char(font, char_code, &index); - } - - atlas.atlas.glyphs = AllocArray!(Glyph)(arena, count); - - max_w = 0; - max_h = 0; - current_h = 0; - count = 0; - - u32 font_w = font.size.metrics.x_ppem; - u32 font_h = font.size.metrics.y_ppem; - - char_code = FT_Get_First_Char(font, &index); - while (index != 0) - { - FT_Load_Char(font, char_code, cast(FT_Int32)FT_LOAD_RENDER); - - FT_GlyphSlot glyph = font.glyph; - FT_Bitmap* bmp = &font.glyph.bitmap; - i32 top = font.glyph.bitmap_top; - i32 left = font.glyph.bitmap_left; - - if (max_w + bmp.rows > dimension) - { - max_h += current_h; - max_w = 0; - } - - i32 x, y; - foreach(r; 0 .. bmp.rows) - { - y = cast(i32)(max_h + r); - foreach(c; 0 .. bmp.width) - { - x = max_w + c; - u64 offset = (y*dimension + x) * 4; - - atlas.data[offset+0] = bmp.buffer[r*bmp.pitch + c]; - atlas.data[offset+1] = bmp.buffer[r*bmp.pitch + c]; - atlas.data[offset+2] = bmp.buffer[r*bmp.pitch + c]; - atlas.data[offset+3] = 255; - } - } - - Glyph* g = atlas.atlas.glyphs.ptr + count; - - g.ch = cast(dchar)char_code; - g.advance = cast(f32)(glyph.advance.x >> 6); - g.plane_left = cast(f32)left; - g.plane_right = g.plane_left + bmp.width; - g.plane_top = cast(f32)top; - g.plane_bottom = g.plane_top + bmp.rows; - - g.atlas_top = max_h; - g.atlas_left = max_w; - g.atlas_bottom = max_h + bmp.rows; - g.atlas_right = max_w + bmp.width; - - max_w += bmp.width; - current_h = bmp.rows > current_h ? bmp.rows : current_h; - - char_code = FT_Get_Next_Char(font, char_code, &index); - - count += 1; - } - - } - - - - return atlas; -} - diff --git a/src/shared/includes.c b/src/shared/includes.c deleted file mode 100644 index a2c74e1..0000000 --- a/src/shared/includes.c +++ /dev/null @@ -1,28 +0,0 @@ -#pragma attribute(push, nogc, nothrow) - -#ifdef __linux__ -# include -# include -# include -# include -# include -# include -# include -# include -# include FT_FREETYPE_H -# include FT_GLYPH_H -#endif - -#include - -#define STB_IMAGE_IMPLEMENTATION - -#include "../../external/stb/stb_image.h" - -#define M3D_IMPLEMENTATION - -#include "../../external/m3d/m3d.h" - -#define CGLM_FORCE_DEPTH_ZERO_TO_ONE - -#include "../../external/cglm/cglm.h" diff --git a/src/shared/math.d b/src/shared/math.d deleted file mode 100644 index 84a0392..0000000 --- a/src/shared/math.d +++ /dev/null @@ -1,1086 +0,0 @@ -import aliases; -import includes; -import util; -import std.math; -import std.math.algebraic; -import core.stdc.math : tanf, cosf, sinf, sqrtf; -import std.traits; -import inteli; -import std.meta; -import std.format; -import std.stdio; - -T AlignPow2(T)(T v, T a) -{ - return (v + a - 1) & ~(a - 1); -} - -f32 Radians(f32 deg) -{ - return deg * (PI / 180.0); -} - -struct Vector(T, int N) -{ - static assert(N > 1 && N <= 4); - - enum _N = N; - alias T _T; - - union - { - T[N] v; - struct - { - T x; - alias x r; - - T y; - alias y g; - - static if (N > 2) - { - T z; - alias z b; - } - - static if (N > 3) - { - T w; - alias w a; - } - }; - } - - this(Vec3, f32)(Vec3 v3, f32 f) if (N == 4 && is(T: f32)) - { - x = v3.x; - y = v3.y; - z = v3.z; - w = f; - } - - this(Arr)(Arr arr) if (is(Arr: typeof(v))) - { - this.v = arr; - } - - this(Args...)(Args args) - { - static if (args.length == 1) - { - opAssign!(Args[0])(args[0]); - } - else static if (args.length == N) - { - mixin(GenerateLoop!("v[@] = args[@];", N)()); - } - else static if (args.length == 2 && N == 4) - { - v[0] = args[0]; - v[1] = args[0]; - v[2] = args[0]; - v[3] = args[1]; - } - else - { - static assert(false, "Invalid Vector constructor"); - } - } - - ref Vector opAssign(U)(U x) if (is(U: T)) - { - mixin(GenerateLoop!("v[@] = x;", N)()); - return this; - } - - ref Vector opAssign(U)(U u) if (is(U : Vector)) - { - v[] = u.v[]; - return this; - } - - inout(T)* ptr() inout @property - { - return v.ptr; - } - - bool opEquals(U)(U other) if (is(U: Vector!(T, N))) - { - bool result = true; - - foreach(i; 0 .. N) - { - if (fabs(v[i] - other.v[i]) > 0.0000009) - { - result = false; - break; - } - } - - return result; - } - - int opDollar() - { - return N; - } - - T[] opSlice() - { - return v[]; - } - - Vector opUnary(string op)() if (op == "+" || op == "-" || op == "~" || op == "!") - { - Vector result; - mixin(GenerateLoop!("res.v[@] = " ~ op ~ " v[@];", N)()); - return res; - } - - ref Vector opOpAssign(string op, U)(U value) if (is(U: Vector)) - { - mixin(GenerateLoop!("v[@] " ~ op ~ "= value.v[@];", N)()); - return this; - } - - ref Vector opOpAssign(string op, U)(U value) if (IsConvertible!(U)) - { - Vector conv = value; - return opOpAssign!(op)(conv); - } - - @property auto opDispatch(string op, U = void)() if (ValidSwizzle!(op) && op.length <= 4) - { - Vector!(T, op.length) result; - enum index_tuple = SwizzleTuple!(op); - static foreach(i, index; index_tuple) - { - result.v[i] = v[index]; - } - return result; - } - - @property void opDispatch(string op, U)(U x) if ((op.length > 1) && ValidUniqueSwizzle!(op) && is(typeof(Vector!(T, op.length)(x)))) - { - Vector!(T, op.length) conv = x; - enum index_tuple = SwizzleTuple!(op); - static foreach(i, index; index_tuple) - { - v[index] = conv[i]; - } - } - - static if (N == 4) - { - Vector opBinary(string op, U)(U operand) if ((is(U: Vector!(f32, 4)) && is(T: f32)) && (op == "*" || op == "+" || op == "-" || op == "/")) - { - Vector result; - f32* l = &x; - f32* r = &operand.x; - f32* res = &result.x; - - asm - { - mov R8, l; - mov R9, r; - mov R10, res; - movups XMM0, x.offsetof[R8]; - movups XMM1, operand.x.offsetof[R9]; - } - static if (op == "*") asm { mulps XMM0, XMM1; } - else static if (op == "-") asm { subps XMM0, XMM1; } - else static if (op == "+") asm { addps XMM0, XMM1; } - else static if (op == "/") asm { divps XMM0, XMM1; } - asm - { - movups result.x.offsetof[R10], XMM0; - } - - return result; - } - - Vector opBinary(string op, U)(U operand) if (IsConvertible!(U) && (op == "*" || op == "+" || op == "-" || op == "/")) - { - Vector result; - Vector other = operand; - f32* l = &x; - f32* r = &other.x; - f32* res = &result.x; - - asm - { - mov R8, l; - mov R9, r; - mov R10, res; - movups XMM0, x.offsetof[R8]; - movups XMM1, other.x.offsetof[R9]; - } - static if (op == "*") asm { mulps XMM0, XMM1; } - else static if (op == "-") asm { subps XMM0, XMM1; } - else static if (op == "+") asm { addps XMM0, XMM1; } - else static if (op == "/") asm { divps XMM0, XMM1; } - asm - { - movups result.x.offsetof[R8], XMM0; - } - - return result; - } - } - else - { - Vector opBinary(string op, U)(U operand) if (is(U: Vector) && U._N == N && (op == "*" || op == "+" || op == "-" || op == "/")) - { - Vector res; - mixin(GenerateLoop!("res.v[@] = v[@] " ~ op ~ " operand.v[@];", N)()); - return res; - } - - Vector opBinary(string op, U)(U operand) if (IsConvertible!(U) && (op == "*" || op == "+" || op == "-" || op == "/")) - { - Vector res; - Vector other = operand; - mixin(GenerateLoop!("res.v[@] = v[@] " ~ op ~ " other.v[@];", N)()); - return res; - } - } - - - - ref T opIndex(size_t i) - { - return v[i]; - } - - T opIndexAssign(U : T)(U x, size_t i) - { - return v[i] = x; - } - - U opCast(U)() if (IsVector!(U) && (U._N == _N)) - { - U result; - mixin(GenerateLoop!("res.v[@] = cast(U._T)v[@];", N)()); - return result; - } - - template IsConvertible(T) - { - enum bool IsConvertible = (!is(T : Vector)) && is(typeof({ T x; Vector v = x; }())); - } - - template SwizzleIndex(char c) - { - static if ((c == 'x' || c == 'r') && N > 0) - enum SwizzleIndex = 0; - else static if ((c == 'y' || c == 'g') && N > 1) - enum SwizzleIndex = 1; - else static if ((c == 'z' || c == 'b') && N > 2) - enum SwizzleIndex = 2; - else static if ((c == 'w' || c == 'a') && N > 3) - enum SwizzleIndex = 3; - else - enum SwizzleIndex = -1; - } - - template SwizzleSet(char c) - { - static if (c == 'x' || c == 'y' || c == 'z' || c == 'w') - enum SwizzleSet = 0; - else static if (c == 'r' || c == 'g' || c == 'b' || c == 'a') - enum SwizzleSet = 1; - else - enum SwizzleSet = -1; - } - - template SwizzleTuple(string op) - { - enum op_length = op.length; - static if (op.length == 0) - enum SwizzleTuple = []; - else - enum SwizzleTuple = [ SwizzleIndex!(op[0])] ~ SwizzleTuple!(op[1 .. op.length]); - } - - template SearchString(char c, string s) - { - static if (s.length == 0) - { - enum bool result = false; - } - else - { - enum string tail = s[1 .. s.length]; - enum bool result = (s[0] == c) || SearchString!(c, tail).result; - } - } - - template UniqueChars(string s) - { - static if (s.length == 1) - { - enum bool result = true; - } - else - { - enum tail = s[1 .. s.length]; - enum bool result = !(SearchString!(s[0], tail).result) && UniqueChars!(tail).result; - } - } - - template ValidSwizzle(string op, int last_swizzle = -1) - { - static if (op.length == 0) - { - enum bool ValidSwizzle = true; - } - else - { - enum length = op.length; - enum int swizzle_set = SwizzleSet!(op[0]); - enum bool valid_swizzle_set = (last_swizzle == -1 || (swizzle_set == last_swizzle)); - enum bool ValidSwizzle = (SwizzleIndex!(op[0]) != -1) && valid_swizzle_set && ValidSwizzle!(op[1 .. length], swizzle_set); - } - } - - template ValidUniqueSwizzle(string op) - { - static if (ValidSwizzle!(op)) - { - enum ValidUniqueSwizzle = UniqueChars!(op).result; - } - else - { - enum ValidUniqueSwizzle = false; - } - } -} - -// TODO: fix alignment for non mat4s -align(16) struct Matrix(T, int D) -{ - static assert(D > 0 && D <= 4); - - alias Vector!(T, D) MatrixVec; - alias T _T; - alias T[4] Row; - - enum N = D*D; - enum _D = D; - - union - { - T[N] v; - Row[D] rows; - MatrixVec[D] vec; - static if (D == 4) mat4 glm_mat; - static if (D == 3) mat3 glm_mat; - static if (D == 2) mat2 glm_mat; - } - - // TODO: setup - - this(U...)(U values) - { - static if ((U.length == N) && allSatisfy!(IsTypeAssignable, U)) - { - static foreach(i, x; values) - { - v[i] = x; - } - } - else static if ((U.length == 1) && (isAssignable!(U[0])) && (!is(U[0] : Matrix))) - { - v[] = values[0]; - } - else static assert(false, "Cannot construct matrix with provided parameters"); - } - - this(U)(T x) - { - static foreach(i; 0 .. N) - { - v[i] = x; - } - } - - @property inout(T)* ptr() inout - { - return v.ptr; - } - - ref Matrix opAssign(U : T)(U x) - { - static foreach(i; 0 .. N) - { - v[i] = x; - } - - return this; - } - - ref Matrix opAssign(U : Matrix)(U x) - { - static foreach(i; 0 .. N) - { - v[i] = x.v[i]; - } - - return this; - } - - ref Matrix opAssign(U)(U x) if (IsMatrixInstantiation!(U) && is(U._T : _T) && (!is(U: Matrix) && (U.N != N))) - { - static foreach(i; 0 .. N) - { - v[i] = x.v[i]; - } - - return this; - } - - ref T opIndex(size_t i, size_t j) - { - return v[(i * D) + j]; - } - - T opIndexAssign(U: T)(U x, size_t i, size_t j) - { - return v[(i * D) + j] = x; - } - - bool opEquals(U)(U other) if (is(U: Matrix!(T, D))) - { - bool result = true; - - static foreach(i; 0 .. N) - { - if (fabs(this.v[i] - other.v[i]) > 0.0000009) - { - result = false; - } - } - - return result; - } - - Matrix opBinary(string op)(T scalar) if (op == "*") - { - Matrix result; - - static foreach(i; 0 .. N) - { - result.v[i] = v[i] * scalar; - } - - return result; - } - - static if (D == 4) - { - Vec4 opBinary(string op, U)(U x) if (is(U: Vec4) && is(T: f32) && (op == "*")) - { - Vec4 result = 0.0; - glm_mat4_mulv(glm_mat.ptr, x.v.ptr, result.v.ptr); - return result; - } - - Matrix opBinary(string op, U)(U x) if (is(U: Matrix!(T, D)) && is(T: f32) && D == 4 && (op == "*")) - { - Matrix result; - MatZero(&result); - - glm_mat4_mul(glm_mat.ptr, x.glm_mat.ptr, result.glm_mat.ptr); - - return result; - } - } - - template IsTypeAssignable(U) - { - enum bool IsTypeAssignable = std.traits.isAssignable!(T, U); - } - - template IsMatrixInstantiation(U) - { - static void IsMatrix(T, int D)(Matrix!(T, D) x) {} - - enum bool IsMatrixInstantiation = is(typeof(IsMatrix(U.init))); - } -} - -struct Quat -{ - union - { - f32[4] v; - Vec4 vec; - struct - { - f32 x; - f32 y; - f32 z; - f32 w; - }; - }; - - this(f32 w, f32 x, f32 y, f32 z) - { - vec.x = x; - vec.y = y; - vec.z = z; - vec.w = w; - } - - U opCast(U)() if (is(U: Mat4)) - { - Mat4 result; - glm_quat_mat4(vec.ptr, result.glm_mat.ptr); - return result; - } - - Quat opBinary(string op, U)(U r) if (op == "*" && is(U: Quat)) - { - Quat q; - - q.x = this.w * r.x + this.x * r.w + this.y * r.z - this.z * r.y; - q.y = this.w * r.y - this.x * r.z + this.y * r.w + this.z * r.x; - q.z = this.w * r.z + this.x * r.y - this.y * r.x + this.z * r.w; - q.w = this.w * r.w - this.x * r.x - this.y * r.y - this.z * r.z; - - return q; - } -} - -Mat4 -Mat4MulASM(Mat4 l, Mat4 r) -{ - Mat4 result; - - auto lp = &l; - auto rp = &r; - auto res = &result; - - // TODO: fix this - asm @trusted - { - mov R8, lp; - mov R9, rp; - mov R10, res; - - movups XMM0, [R8]; - movups XMM1, [R9+00]; - movups XMM2, [R9+16]; - movups XMM3, [R9+32]; - movups XMM4, [R9+48]; - - movups XMM6, XMM1; - shufps XMM6, XMM6, 0; // XMM5 = vec.xxxx; - mulps XMM6, XMM0; // XMM6 = col1; - - movups XMM7, XMM2; - shufps XMM7, XMM7, 0; - mulps XMM7, XMM0; // XMM7 = col2; - - movups XMM8, XMM3; - shufps XMM8, XMM8, 0; - mulps XMM8, XMM0; // XMM8 = col3; - - movups XMM9, XMM3; - shufps XMM9, XMM9, 0; - mulps XMM9, XMM0; // XMM9 = col4; - - movups XMM0, [R8+16]; - - movups XMM5, XMM1; - shufps XMM5, XMM5, 85; // XMM5 = vec.yyyy; - mulps XMM5, XMM0; - addps XMM6, XMM5; - - movups XMM5, XMM2; - shufps XMM5, XMM5, 85; - mulps XMM5, XMM0; - addps XMM7, XMM5; - - movups XMM5, XMM3; - shufps XMM5, XMM5, 85; - mulps XMM5, XMM0; - addps XMM8, XMM5; - - movups XMM5, XMM4; - shufps XMM5, XMM5, 85; - mulps XMM5, XMM0; - addps XMM9, XMM5; - - movups XMM0, [R8+32]; - - movups XMM5, XMM1; - shufps XMM5, XMM5, 170; // XMM5 = vec.zzzz; - mulps XMM5, XMM0; - addps XMM6, XMM5; - - movups XMM5, XMM2; - shufps XMM5, XMM5, 170; - mulps XMM5, XMM0; - addps XMM7, XMM5; - - movups XMM5, XMM3; - shufps XMM5, XMM5, 170; - mulps XMM5, XMM0; - addps XMM8, XMM5; - - movups XMM5, XMM4; - shufps XMM5, XMM5, 170; - mulps XMM5, XMM0; - addps XMM9, XMM5; - - movups XMM0, [R8+48]; - - movups XMM5, XMM1; - shufps XMM5, XMM5, 255; // XMM5 = vec.wwww; - mulps XMM5, XMM0; - addps XMM6, XMM5; - - movups XMM5, XMM2; - shufps XMM5, XMM5, 255; - mulps XMM5, XMM0; - addps XMM7, XMM5; - - movups XMM5, XMM3; - shufps XMM5, XMM5, 255; - mulps XMM5, XMM0; - addps XMM8, XMM5; - - movups XMM5, XMM4; - shufps XMM5, XMM5, 255; - mulps XMM5, XMM0; - addps XMM9, XMM5; - - movups [R10+00], XMM6; - movups [R10+16], XMM7; - movups [R10+32], XMM8; - movups [R10+48], XMM9; - } - - return result; -} - -pragma(inline): Mat4 -Mat4Identity() -{ - return Mat4( - 1.0, 0.0, 0.0, 0.0, - 0.0, 1.0, 0.0, 0.0, - 0.0, 0.0, 1.0, 0.0, - 0.0, 0.0, 0.0, 1.0 - ); -} - -pragma(inline): void -Mat4Identity(Mat4* mat) -{ - MatZero(mat); - - (*mat)[0, 0] = 1.0; - (*mat)[1, 1] = 1.0; - (*mat)[2, 2] = 1.0; - (*mat)[3, 3] = 1.0; -} - - pragma(inline): Mat3 -Mat3Identity() -{ - return Mat3( - 1.0, 0.0, 0.0, - 0.0, 1.0, 0.0, - 0.0, 0.0, 1.0 - ); -} - - pragma(inline): Mat2 -Mat2Identity() -{ - return Mat2( - 1.0, 0.0, - 0.0, 1.0 - ); -} - -pragma(inline): Quat -QuatFromAxis(f32 angle, Vec3 axis) -{ - Quat q; - glm_quatv(q.vec.ptr, angle, axis.v.ptr); - return q; -} - -pragma(inline): f32 -Dot(Vec2* l, Vec2* r) -{ - return l.x * r.x + l.y * r.y; -} - -pragma(inline): f32 -Dot(Vec3* l, Vec3* r) -{ - return l.x * r.x + l.y * r.y + l.z * r.z; -} - -pragma(inline): f32 -Dot(Vec4* l, Vec4* r) -{ - // TODO: SIMD this - return l.x * r.x + l.y * r.y + l.z * r.z + l.w * r.w; -} - -pragma(inline): f32 -Norm(Vec3* v) -{ - return sqrtf(Dot(v, v)); -} - -pragma(inline): f32 -Norm(Vec4* v) -{ - // TODO: SIMD this - return sqrtf(Dot(v, v)); -} - -pragma(inline): void -Normalize(T)(T* vec) if (is(T: Vec2) || is(T: Vec3) || is(T: Vec4)) -{ - f32 length = Norm(vec); - - if (length < f32.epsilon) - { - mixin(GenerateLoop!("vec.v[@] = 0.0;", vec._N)()); - } - else - { - mixin(GenerateLoop!("vec.v[@] *= (1.0 / length);", vec._N)()); - } -} - -pragma(inline): T -Normalize(T)(T vec) if (is(T: Vec2) || is(T: Vec3) || is(T: Vec4)) -{ - Normalize(&vec); - return vec; -} - -pragma(inline): Quat -Normalize(Quat q) -{ - f32 dot = Norm(&q.vec); - - if (dot <= 0.0) - { - q = Quat(1.0, 0.0, 0.0, 0.0); - } - - q.vec *= 1.0 / sqrtf(dot); - - return q; -} - -pragma(inline): Mat4 -Perspective(f32 fov, f32 aspect, f32 near, f32 far) -{ - Mat4 res; - MatZero(&res); - glm_perspective(fov, aspect, near, far, res.glm_mat.ptr); - res[1, 1] *= -1.0; - return res; -} - -pragma(inline): Vec3 -Rotate(Quat q, Vec3 vec) -{ - Quat p = Normalize(q); - - Vec3 i = p.vec.xyz; - f32 r = p.vec.w; - - Vec3 v1 = i * (2.0 * Dot(&i, &vec)); - Vec3 v2 = i * (r * r - Dot(&i, &i)); - v1 += v2; - - v2 = i * vec; - v2 = v2 * (2.0 * r); - - return v1 + v2; -} - -pragma(inline): Mat4 -LookAt(Vec3 eye, Vec3 center, Vec3 up) -{ - Mat4 result; - MatZero(&result); - glm_lookat(eye.v.ptr, center.v.ptr, up.v.ptr, result.glm_mat.ptr); - return result; -} - -pragma(inline): Mat4 -Look(Vec3 eye, Vec3 dir, Vec3 up) -{ - return LookAt(eye, eye + dir, up); -} - -pragma(inline): Vec3 -Cross(Vec3 a, Vec3 b) -{ - Vec3 c; - Cross(a, b, &c); - return c; -} - -pragma(inline): Vec3 -CrossN(Vec3 a, Vec3 b) -{ - Vec3 c; - Cross(a, b, &c); - Normalize(&c); - return c; -} - -pragma(inline): void -CrossN(Vec3 a, Vec3 b, Vec3* dst) -{ - Cross(a, b, dst); - glm_vec3_normalize(dst.v.ptr); -} - -pragma(inline): void -Cross(Vec3 a, Vec3 b, Vec3* dst) -{ - glm_vec3_cross(a.v.ptr, b.v.ptr, dst.v.ptr); -} - -pragma(inline): void -MatZero(Mat4* mat) -{ - auto v = &mat.vec; - asm - { - mov R8, v; - xorps XMM0, XMM0; - movups mat.vec.offsetof[R8]+00, XMM0; - movups mat.vec.offsetof[R8]+16, XMM0; - movups mat.vec.offsetof[R8]+32, XMM0; - movups mat.vec.offsetof[R8]+48, XMM0; - } -} - -pragma(inline): void -Translate(Mat4* mat, Vec3 vec) -{ - glm_translate(mat.glm_mat.ptr, vec.v.ptr); -} - -pragma(inline): Mat4 -Inverse(Mat4 mat) -{ - Mat4 res; - MatZero(&res); - glm_mat4_inv(mat.glm_mat.ptr, res.glm_mat.ptr); - return res; -} - -pragma(inline): f32 -Mix(f32 x, f32 y, f32 a) -{ - return x * (1 - a) + y * a; -} - -pragma(inline): f32 -InverseLerp(f32 v, f32 min, f32 max) -{ - return (v - min) / (max - min); -} - -pragma(inline): f32 -Remap(f32 v, f32 in_min, f32 in_max, f32 out_min, f32 out_max) -{ - f32 t = InverseLerp(v, in_min, in_max); - return Mix(out_min, out_max, t); -} - -unittest -{ - enum FLOAT_MAX = f32.max; - enum FLOAT_MIN = -f32.max; - - import core.stdc.stdio; - import core.stdc.stdlib; - import core.stdc.time; - import std.range : take; - import std.algorithm.iteration : sum; - - void PrintMatrix(Mat4 mat) - { - foreach(i; 0 .. mat.N) - { - if (i % 4 == 0) - { - printf("\n"); - } - printf("%.08f ", mat.v[i]); - } - printf("\n"); - } - - srand(cast(u32)time(null)); - - f32 RandomFloat() - { - return cast(f32)(rand())/cast(f32)(RAND_MAX + 1.0); - } - - { // Vec2 arithmetic - Vec2 v1 = Vec2(5.0, 10.0); - Vec2 v2 = Vec2(2.5, 5.0); - - Vec2 result = v1 * v2; - - assert(result == Vec2(12.5, 50.0), "Vec2 mul failure"); - - result = v1 + v2; - - assert(result == Vec2(7.5, 15.0), "Vec2 add failure"); - - result = v1 - v2; - - assert(result == Vec2(2.5, 5.0), "Vec2 sub failure"); - - result = v1 / v2; - - assert(result == Vec2(2.0), "Vec2 div failure"); - } - - { // Vec3 Arithmetic - Vec3 v1 = Vec3(5.0, 10.0, 15.0); - Vec3 v2 = Vec3(2.5, 5.0, 7.5); - - Vec3 result = v1 * v2; - - assert(result == Vec3(12.5, 50.0, 112.5), "Vec3 mul failure"); - - result = v1 + v2; - - assert(result == Vec3(7.5, 15.0, 22.5), "Vec3 add failure"); - - result = v1 - v2; - - assert(result == Vec3(2.5, 5.0, 7.5), "Vec3 sub failure"); - - result = v1 / v2; - - assert(result == Vec3(2.0), "Vec3 div failure"); - } - - { // Vec3 Arithmetic - Vec4 v1 = Vec4(5.0, 10.0, 15.0, 20.0); - Vec4 v2 = Vec4(2.5, 5.0, 7.5, 10.0); - - Vec4 result = v1 * v2; - - assert(result == Vec4(12.5, 50.0, 112.5, 200.0), "Vec4 mul failure"); - - result = v1 + v2; - - assert(result == Vec4(7.5, 15.0, 22.5, 30.0), "Vec4 add failure"); - - result = v1 - v2; - - assert(result == Vec4(2.5, 5.0, 7.5, 10.0), "Vec4 sub failure"); - - result = v1 / v2; - - assert(result == Vec4(2.0), "Vec4 div failure"); - } - - { // Mat4 Arithmetic - Mat4 m1 = RandomMat4(); - Mat4 m2 = RandomMat4(); - Mat4 m3 = m1 * m2; - Mat4 m4; - - MatZero(&m4); - - for(u32 i = 0; i < 4; i += 1) - { - for(u32 j = 0; j < 4; j += 1) - { - for(u32 k = 0; k < 4; k += 1) - { - m4.rows[i][j] += m1.rows[k][j] * m2.rows[i][k]; - } - } - } - - assert(m3 == m4, "Mat4 mul failure"); - } - - { // Translate - Mat4 mat = Mat4Identity(); - Vec4 vec = Vec4(1.0, 2.0, 3.0, 1.0); - - Translate(&mat, Vec3(13.0, 11.0, 7.0)); - Vec4 result = mat * vec; - - assert(result == Vec4(14.0, 13.0, 10.0, 1.0)); - - mat = Mat4Identity(); - Translate(&mat, Vec3(1.0, -1.0, -5.0)); - result = mat * result; - - assert(result == Vec4(15.0, 12.0, 5.0, 1.0)); - } - - { // Identity - Mat4 identity = Mat4( - 1.0, 0.0, 0.0, 0.0, - 0.0, 1.0, 0.0, 0.0, - 0.0, 0.0, 1.0, 0.0, - 0.0, 0.0, 0.0, 1.0 - ); - Mat4 mat = Mat4Identity(); - - assert(identity == mat); - } - - - { // Inverse - foreach(i; 0 .. 1000) - { - Mat4 m1 = RandomMat4(); - - Mat4 m1_inv = Inverse(m1); - Mat4 m1_reinv = Inverse(m1_inv); - - assert(m1 == m1_reinv, "Inverse test failed"); - } - } - - { // Cross - Vec3 v1 = Vec3(2.0, -3.0, 4.0); - Vec3 v2 = Vec3(12.0, -31.0, 43.0); - - Vec3 v3 = Cross(v1, v2); - - Vec3 v4 = Vec3( - v1.y * v2.z - v1.z * v2.y, - v1.z * v2.x - v1.x * v2.z, - v1.x * v2.y - v1.y * v2.x - ); - - assert(v3 == v4, "Vec3 Cross failure"); - - v3 = CrossN(v1, v2); - - Normalize(&v4); - - assert(v3 == v4, "Vec3 CrossN failure"); - } -} diff --git a/src/shared/util.d b/src/shared/util.d deleted file mode 100644 index dfaeffd..0000000 --- a/src/shared/util.d +++ /dev/null @@ -1,661 +0,0 @@ -import aliases; -import xxhash3; -import includes; -import std.stdio; -import core.stdc.string : memset; -import alloc; -import core.simd; -import std.conv; -import std.string; - -struct DynSlice(T) -{ - T[][] slices; - u32 length; - u32 capacity; - u32 grow_size; -} - -DynSlice!(T) -CreateDynSlice(T)(u32 size) -{ - DynSlice!(T) dslice = { - slices: MAllocArray!(T[])(size), - length: 0, - capacity: size, - grow_size: size, - }; - - dslice.slices[0] = MAllocArray!(T)(size); - - return dslice; -} - -u32 -Next(T)(DynSlice!(T)* slice) -{ - if (slice.length < slice.capacity) - { - - } - - return 0; -} - -void -Logf(Args...)(string fmt, Args args) -{ - try - { - writefln(fmt, args); - } - catch (Exception e) - { - assert(false, "Incompatible format type"); - } -} - -void -Log(string str) -{ - writeln(str); -} - -void -Log(char* str) -{ - writeln(str); -} - -u64 -KB(u64 v) -{ - return v * 1024; -}; - -u64 -MB(u64 v) -{ - return KB(v) * 1024; -}; - -u64 -GB(u64 v) -{ - return MB(v) * 1024; -}; - -pragma(inline): void -ConvertColor(Vec4 *dst, u32 src) -{ - if (src == 0) - { - dst.rgb = 0.0; - dst.a = 1.0; - } - else - { - Convert(dst, src); - } -} - -pragma(inline): void -Convert(Vec4* dst, u32 src) -{ - dst.r = cast(f32)((src >> 0) & 0xFF) / 255.0; - dst.g = cast(f32)((src >> 8) & 0xFF) / 255.0; - dst.b = cast(f32)((src >> 16) & 0xFF) / 255.0; - dst.a = cast(f32)((src >> 24) & 0xFF) / 255.0; -} - -bool -BitEq(u64 l, u64 r) -{ - return (l & r) == r; -} - -struct Node(T) -{ - Node!(T)* next; - T value; -} - -struct SLList(T) -{ - Node!(T)* first; - Node!(T)* last; -} - -pragma(inline): bool -CheckNil(T)(Node!(T)* nil, Node!(T)* node) -{ - return node == null || node == nil; -} - -pragma(inline): void -ConcatInPlace(T)(SLList!(T)* list, SLList!(T)* to_concat) -{ - 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; - } - - memset(to_concat, 0, SLList!(T).sizeof); - } -} - -pragma(inline): Node!(T)* -Pop(T)(SLList!(T)*list, Node!(T)* nil) -{ - Node!(T)* node = list.first; - - if (list.first == list.last) - { - list.first = list.last = nil; - } - else - { - list.first = list.first.next; - } - - return node; -} - -pragma(inline): void -Remove(T)(SLList!(T)*list, Node!(T)* node, Node!(T)* prev, Node!(T)* nil) -{ - node.next = nil; - - if (list.first == list.last) - { - list.first = list.last = nil; - } - else if (list.first == node) - { - list.first = node.next; - } - else if (list.last == node) - { - list.last = prev; - prev.next = nil; - } - else - { - prev.next = node.next; - } -} - -pragma(inline): void -PushFront(T)(SLList!(T)*list, Node!(T)* node, Node!(T)* nil) -{ - if (CheckNil(nil, list.first)) - { - list.first = list.last = node; - node.next = nil; - } - else - { - node.next = list.first; - list.first = node; - } -} - -pragma(inline): void -Push(T)(SLList!(T)*list, Node!(T)* node, Node!(T)* nil) -{ - if (CheckNil(nil, list.first)) - { - list.first = list.last = node; - node.next = nil; - } - else - { - list.last.next = node; - list.last = node; - node.next = nil; - } -} - -struct KVPair(K, V) -{ - K key; - V value; -} - -struct Result(V) -{ - V value; - bool ok; -} - -struct HashTable(K, V) -{ - alias P = KVPair!(K, V); - - SLList!(P) free_lists; - SLList!(P)[] lists; - Node!(P)* nil; - u64 node_count; - u64 list_count; - - void opIndexAssign(V value, K key) - { - Push(&this, key, value); - } - - Result!(V) opIndex(K key) - { - P* pair = Search(&this, key); - assert(pair != null, "HashTable key index failure: Result must be present"); - - Result!(V) result = { ok: false }; - if (pair != null) - { - result.value = pair.value; - result.ok = true; - } - - return result; - } - - Result!(V) opIndexUnary(string s: "~")(K key) - { - return Delete(&this, key); - } -} - -HashTable!(K, V) -CreateHashTable(K, V)(u64 size) -{ - auto nil = Alloc!(Node!(KVPair!(K, V))); - auto lists = AllocArray!(SLList!(KVPair!(K, V)))(size); - - HashTable!(K, V) table = { - lists: lists, - list_count: size, - nil: nil, - free_lists: { - first: nil, - last: nil, - }, - }; - - foreach(list; table.lists) - { - list.first = nil; - list.last = nil; - } - - return table; -} - -pragma(inline): void -Clear(K, V)(HashTable!(K, V)* ht) -{ - table.count = 0; - foreach(i, list; ht.lists) - { - ConcatInPlace(&ht.free_lists, ht.lists.ptr + i); - } -} - -pragma(inline): Node!(KVPair!(K, V))* -Push(K, V)(HashTable!(K, V)* ht, K key, V value) -{ - alias P = KVPair!(K, V); - alias N = Node!(P); - - N* node = ht.nil; - - if (ht.free_lists.first != ht.nil) - { - node = Pop(&ht.free_lists, ht.nil); - } - else - { - node = Alloc!(N); - } - - node.next = ht.nil; - node.value.key = key; - node.value.value = value; - - Push(GetList(ht, key), node, ht.nil); - - ht.node_count += 1; - - return node; -} - -pragma(inline): KVPair!(K, V)* -Search(K, V)(HashTable!(K, V)* ht, K key) -{ - KVPair!(K, V)* result = null; - - auto list = GetList(ht, key); - for(auto node = list.first; node != ht.nil; node = node.next) - { - if (node.value.key == key) - { - result = &node.value; - break; - } - } - - return result; -} - -pragma(inline): SLList!(KVPair!(K, V))* -GetList(K, V)(HashTable!(K, V)* ht, K key) -{ - u64 hash = Hash(&key); - u64 index = hash % ht.list_count; - return ht.lists.ptr + index; -} - -pragma(inline): Result!(V) -Delete(K, V)(HashTable!(K, V)* ht, K key) -{ - Result!(V) result = { ok: false }; - - auto list = GetList(ht, key); - auto prev = ht.nil; - for(auto node = list.first; node != ht.nil; node = node.next) - { - if (node.value.key == key) - { - Remove(list, node, prev, ht.nil); - - result.ok = true; - result.value = node.value.value; - - memset(&node.value, 0, node.value.sizeof); - - Push(&ht.free_lists, node, ht.nil); - - break; - } - } - - return result; -} - -const u64 HASH_SEED = 5995; - -pragma(inline): u64 -Hash(T)(T* value) -{ - return xxh3_64bits_withSeed(value, T.sizeof / u8.sizeof, HASH_SEED); -} - -pragma(inline): u64 -Hash(string str) -{ - return xxh3_64bits_withSeed(str.ptr, str.length, HASH_SEED); -} - -pragma(inline): u64 -RDTSC() -{ - union u64_split - { - u64 full; - struct - { - u32 lower; - u32 upper; - }; - }; - - u64_split val; - u64_split* valp = &val; - asm - { - cpuid; - rdtsc; - mov R8, valp; - mov valp.upper.offsetof[R8], EDX; - mov valp.lower.offsetof[R8], EAX; - } - - return val.full; -} - -pragma(inline): u64 -OSTimeFreq() -{ - version (linux) - { - u64 freq = 1000000; - } - - return freq; -} - -pragma(inline): u64 -OSTime() -{ - version(linux) - { - import core.sys.linux.sys.time; - timeval value; - gettimeofday(&value, null); - - u64 time = OSTimeFreq() * cast(u64)(value.tv_sec) + cast(u64)(value.tv_usec); - } - - return time; -} - -// TODO: probably needs improvement/testing -struct IntervalTimer -{ - u64 cpu_freq; - u64 interval; - u64 prev; -} - -IntervalTimer -CreateTimer(u64 fps) -{ - IntervalTimer timer; - - u64 ms_to_wait = 50; - - u64 os_freq = OSTimeFreq(); - u64 cpu_start = RDTSC(); - u64 os_start = OSTime(); - u64 os_end = 0; - u64 os_elapsed = 0; - - u64 os_wait_time = os_freq * ms_to_wait / 1000; - - while (os_elapsed < os_wait_time) - { - os_end = OSTime(); - os_elapsed = os_end - os_start; - } - - u64 cpu_end = RDTSC(); - u64 cpu_elapsed = cpu_end - cpu_start; - u64 cpu_freq = 0; - if (os_elapsed) - { - cpu_freq = os_freq * cpu_elapsed / os_elapsed; - } - - timer.cpu_freq = cpu_freq; - timer.interval = cpu_freq/(fps+1); - timer.prev = RDTSC(); - - return timer; -} - -pragma(inline): bool -CheckTimer(IntervalTimer* t) -{ - bool result = false; - u64 time = RDTSC(); - if (time - t.prev > t.interval) - { - result = true; - t.prev = time; - } - - return result; -} - -struct Timer -{ - u64 cpu_freq; - u64 prev; -} - -Timer -CreateTimer() -{ - u64 ms_to_wait = 50; - - u64 os_freq = OSTimeFreq(); - u64 cpu_start = RDTSC(); - u64 os_start = OSTime(); - u64 os_end = 0; - u64 os_elapsed = 0; - - u64 os_wait_time = os_freq * ms_to_wait / 1000; - - while (os_elapsed < os_wait_time) - { - os_end = OSTime(); - os_elapsed = os_end - os_start; - } - - u64 cpu_end = RDTSC(); - u64 cpu_elapsed = cpu_end - cpu_start; - u64 cpu_freq = 0; - if (os_elapsed) - { - cpu_freq = os_freq * cpu_elapsed / os_elapsed; - } - - Timer timer = { - cpu_freq: cpu_freq, - prev: RDTSC(), - }; - - return timer; -} - -pragma(inline): f32 -DeltaTime(Timer* t) -{ - u64 time = RDTSC(); - u64 step = time - t.prev; - t.prev = time; - return cast(f32)(step) / cast(f32)(t.cpu_freq); -} - -static string -IntToStr(int n) nothrow pure @safe -{ - string result; - - static immutable string[] table = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"]; - if (n < table.length) - { - result = table[n]; - } - else - { - result = to!string(n); - } - - return result; -} - -static string -GenerateLoop(string format_string, int N)() nothrow pure @safe -{ - string result; - for (int i = 0; i < N; i++) - { - result ~= format_string.replace("@", IntToStr(i)); - } - return result; -} - -void -MemCpy(void* dst_p, void* src_p, u64 length) -{ - u8* dst = cast(u8*)dst_p; - u8* src = cast(u8*)src_p; - - u64 remaining = length; - if (remaining >= 64) - { - for(u64 i = 0; i < length; i += 64) - { - asm - { - mov R8, src; - mov R9, dst; - - add R8, i; - movdqu XMM0, [R8+00]; - movdqu XMM1, [R8+16]; - movdqu XMM2, [R8+32]; - movdqu XMM3, [R8+48]; - - add R9, i; - movdqu [R9+00], XMM0; - movups [R9+16], XMM1; - movups [R9+32], XMM2; - movups [R9+48], XMM3; - - sub remaining, 64; - } - } - } - - if (remaining >= 32) - { - for(u64 i = remaining; i < length; i += 32) - { - asm - { - mov R8, src; - mov R9, dst; - - add R8, i; - movdqu XMM0, [R8+00]; - movdqu XMM1, [R8+16]; - - add R9, i; - movdqu [R9+00], XMM0; - movdqu [R9+16], XMM1; - - sub remaining, 32; - } - } - } - - for(u64 i = remaining; i < length; i += 1) - { - dst[i] = src[i]; - } -} - -u8[] -Embed(string file_name) -{ - import std.file; - return cast(u8[])read(file_name); -}