dynamic glyph atlas creation
This commit is contained in:
parent
9fc666d49d
commit
cbeafdb8fe
@ -428,9 +428,9 @@
|
||||
#define countof(a) (sizeof(a) / sizeof((a)[0]))
|
||||
#endif
|
||||
|
||||
//- IsArray
|
||||
//- IsFixedArray
|
||||
#define IsIndexable(a) (sizeof(a[0]) != 0)
|
||||
#define IsArray(a) (IsIndexable(a) && (((void *)&a) == ((void *)a)))
|
||||
#define IsFixedArray(a) (IsIndexable(a) && (((void *)&a) == ((void *)a)))
|
||||
|
||||
//- offsetof
|
||||
#if !IsCompilerMsvc
|
||||
@ -619,10 +619,9 @@
|
||||
#define StringFromStruct(ptr) ((String) { sizeof(*(ptr)), (u8 *)(ptr) })
|
||||
#define StringFromArena(arena) (STRING((arena)->pos, ArenaFirst(arena, u8)))
|
||||
|
||||
/* String from static array */
|
||||
#define StringFromArray(a) \
|
||||
#define StringFromFixedArray(a) \
|
||||
( \
|
||||
Assert(IsArray(a)), \
|
||||
Assert(IsFixedArray(a)), \
|
||||
((String) { .len = sizeof(a), .text = (u8 *)(a) }) \
|
||||
)
|
||||
|
||||
|
||||
@ -18,7 +18,7 @@ Arena *AcquireArena(u64 reserve)
|
||||
Panic(Lit("Failed to reserve memory"));
|
||||
}
|
||||
u64 reserved = reserve;
|
||||
AddGstat(MemoryReserved, reserve);
|
||||
AddGstat(ArenaMemoryReserved, reserve);
|
||||
|
||||
/* Commit initial block */
|
||||
base = CommitMemory(base, ArenaBlockSize);
|
||||
@ -32,7 +32,7 @@ Arena *AcquireArena(u64 reserve)
|
||||
StaticAssert(sizeof(Arena) <= ArenaHeaderSize); /* Arena struct must fit in header */
|
||||
|
||||
AsanPoison(base + sizeof(Arena), ArenaBlockSize - sizeof(Arena));
|
||||
AddGstat(MemoryCommitted, ArenaBlockSize);
|
||||
AddGstat(ArenaMemoryCommitted, ArenaBlockSize);
|
||||
AddGstat(NumArenas, 1);
|
||||
|
||||
/* Create & return arena header at beginning of block */
|
||||
@ -46,8 +46,8 @@ Arena *AcquireArena(u64 reserve)
|
||||
void ReleaseArena(Arena *arena)
|
||||
{
|
||||
AsanUnpoison(arena, arena->committed + ArenaHeaderSize);
|
||||
AddGstat(MemoryCommitted, -(i64)(arena->committed - ArenaHeaderSize));
|
||||
AddGstat(MemoryReserved, -(i64)(arena->reserved));
|
||||
AddGstat(ArenaMemoryCommitted, -(i64)(arena->committed - ArenaHeaderSize));
|
||||
AddGstat(ArenaMemoryReserved, -(i64)(arena->reserved));
|
||||
AddGstat(NumArenas, -1);
|
||||
ReleaseMemory(arena);
|
||||
}
|
||||
@ -115,7 +115,7 @@ void *PushBytesNoZero(Arena *arena, u64 size, u64 align)
|
||||
Panic(Lit("Failed to commit new memory block: System may be out of memory"));
|
||||
}
|
||||
arena->committed += commit_bytes;
|
||||
AddGstat(MemoryCommitted, commit_bytes);
|
||||
AddGstat(ArenaMemoryCommitted, commit_bytes);
|
||||
AsanPoison(commit_address, commit_bytes);
|
||||
}
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Async callback
|
||||
//~ Async types
|
||||
|
||||
Struct(AsyncTickCtx);
|
||||
typedef void AsyncTickCallbackFunc(WaveLaneCtx *lane, AsyncTickCtx *tick);
|
||||
@ -15,9 +15,6 @@ Struct(AsyncTickCallbackNode)
|
||||
AsyncTickCallback callback;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Async worker types
|
||||
|
||||
Struct(AsyncTickCtx)
|
||||
{
|
||||
Arena *arena;
|
||||
@ -30,6 +27,15 @@ Struct(AsyncWorkerCtx)
|
||||
AsyncTickCallback *callbacks;
|
||||
};
|
||||
|
||||
Struct(AsyncCtx)
|
||||
{
|
||||
Mutex mutex;
|
||||
u64 callback_nodes_count;
|
||||
AsyncTickCallbackNode *first_callback_node;
|
||||
AsyncTickCallbackNode *last_callback_node;
|
||||
AsyncWorkerCtx worker_ctx;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Bootstrap
|
||||
|
||||
|
||||
@ -8,9 +8,6 @@ Struct(CommandlineArg)
|
||||
String value;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Lookup types
|
||||
|
||||
Struct(CommandlineArgNode)
|
||||
{
|
||||
CommandlineArgNode *next;
|
||||
@ -18,6 +15,13 @@ Struct(CommandlineArgNode)
|
||||
CommandlineArg arg;
|
||||
};
|
||||
|
||||
Struct(CmdLineCtx)
|
||||
{
|
||||
String *positional_args;
|
||||
u64 positional_args_count;
|
||||
CommandlineArgNode *arg_bins[1024];
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Bootstrap
|
||||
|
||||
|
||||
@ -1,4 +1,26 @@
|
||||
/* Application-wide statistics */
|
||||
/* Application wide statistics */
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Gstat types
|
||||
|
||||
Struct(GstatCtx)
|
||||
{
|
||||
Atomic64Padded SockBytesSent;
|
||||
Atomic64Padded SockBytesReceived;
|
||||
Atomic64Padded DebugSteps;
|
||||
|
||||
Atomic64Padded NumArenas;
|
||||
Atomic64Padded ArenaMemoryCommitted;
|
||||
Atomic64Padded ArenaMemoryReserved;
|
||||
|
||||
Atomic64Padded NumGpuArenas;
|
||||
Atomic64Padded DedicatedGpuArenaMemoryCommitted;
|
||||
Atomic64Padded SharedGpuArenaMemoryCommitted;
|
||||
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Gstat ops
|
||||
|
||||
#if GstatIsEnabled
|
||||
|
||||
|
||||
@ -20,7 +20,7 @@ void SetMemoryReadWrite(void *address, u64 size);
|
||||
#define MatchBytes(p1, p2, n) (CmpBytes((p1), (p2), (n)) == 0)
|
||||
#define MatchStruct(p1, p2) MatchBytes((p1), (p2), sizeof(*p1))
|
||||
#define ZeroBytes(ptr, count) SetBytes((ptr), 0, (count))
|
||||
#define ZeroArray(a) Assert(IsArray(a)); ZeroBytes((a), sizeof((a)))
|
||||
#define ZeroFixedArray(a) Assert(IsFixedArray(a)); ZeroBytes((a), sizeof((a)))
|
||||
#define ZeroStructs(ptr, n) ZeroBytes((ptr), sizeof(*(ptr)) * (n))
|
||||
#define ZeroStruct(ptr) ZeroStructs((ptr), 1)
|
||||
#define CopyStructs(ptr_dst, ptr_src, n) CopyBytes((ptr_dst), (ptr_src), sizeof(*(ptr_dst)) * (n))
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Resource cache types
|
||||
//~ Resource types
|
||||
|
||||
Struct(ResourceEntry)
|
||||
{
|
||||
@ -17,6 +17,14 @@ Struct(ResourceEntryBin)
|
||||
ResourceEntry *last;
|
||||
};
|
||||
|
||||
Struct(ResourceCtx)
|
||||
{
|
||||
u64 entries_count;
|
||||
ResourceEntry *first_entry;
|
||||
ResourceEntry *last_entry;
|
||||
ResourceEntryBin bins[4096];
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Bootstrap
|
||||
|
||||
|
||||
@ -3,43 +3,10 @@
|
||||
|
||||
Struct(BaseCtx)
|
||||
{
|
||||
/* Command line */
|
||||
struct
|
||||
{
|
||||
String *positional_args;
|
||||
u64 positional_args_count;
|
||||
CommandlineArgNode *arg_bins[1024];
|
||||
} cmdline;
|
||||
|
||||
/* Resources */
|
||||
struct
|
||||
{
|
||||
u64 entries_count;
|
||||
ResourceEntry *first_entry;
|
||||
ResourceEntry *last_entry;
|
||||
ResourceEntryBin bins[4096];
|
||||
} resource;
|
||||
|
||||
/* Stats */
|
||||
struct
|
||||
{
|
||||
Atomic64Padded SockBytesSent;
|
||||
Atomic64Padded SockBytesReceived;
|
||||
Atomic64Padded MemoryCommitted;
|
||||
Atomic64Padded MemoryReserved;
|
||||
Atomic64Padded NumArenas;
|
||||
Atomic64Padded DebugSteps;
|
||||
} gstat;
|
||||
|
||||
/* Async */
|
||||
struct
|
||||
{
|
||||
Mutex mutex;
|
||||
u64 callback_nodes_count;
|
||||
AsyncTickCallbackNode *first_callback_node;
|
||||
AsyncTickCallbackNode *last_callback_node;
|
||||
AsyncWorkerCtx worker_ctx;
|
||||
} async;
|
||||
CmdLineCtx cmdline;
|
||||
ResourceCtx resource;
|
||||
GstatCtx gstat;
|
||||
AsyncCtx async;
|
||||
};
|
||||
|
||||
extern BaseCtx Base;
|
||||
|
||||
@ -289,25 +289,25 @@ StringArray SplitString(Arena *arena, String str, String delim)
|
||||
StringArray pieces = ZI;
|
||||
pieces.strings = ArenaNext(arena, String);
|
||||
i64 piece_start = 0;
|
||||
for (i64 i = 0; i < (i64)str.len - (i64)delim.len; ++i)
|
||||
for (i64 i = 0; i < (i64)str.len - (i64)delim.len;)
|
||||
{
|
||||
String cmp = ZI;
|
||||
cmp.text = &str.text[i];
|
||||
cmp.len = MinI64(str.len - i, delim.len);
|
||||
|
||||
b32 is_delimiter = MatchString(cmp, delim);
|
||||
if (is_delimiter)
|
||||
if (MatchString(cmp, delim))
|
||||
{
|
||||
String piece = ZI;
|
||||
piece.text = &str.text[piece_start];
|
||||
piece.len = i - piece_start;
|
||||
i += delim.len;
|
||||
piece_start = i;
|
||||
if (piece.len > 0)
|
||||
{
|
||||
*PushStructNoZero(arena, String) = piece;
|
||||
++pieces.count;
|
||||
i += delim.len;
|
||||
piece_start = i;
|
||||
}
|
||||
else
|
||||
{
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
if (piece_start < (i64)str.len)
|
||||
@ -321,6 +321,44 @@ StringArray SplitString(Arena *arena, String str, String delim)
|
||||
return pieces;
|
||||
}
|
||||
|
||||
String ReplaceString(Arena *arena, String str, String old_pattern, String new_pattern)
|
||||
{
|
||||
String result = ZI;
|
||||
result.text = ArenaNext(arena, u8);
|
||||
i64 piece_start = 0;
|
||||
for (i64 i = 0; i < (i64)str.len - (i64)old_pattern.len;)
|
||||
{
|
||||
String cmp = ZI;
|
||||
cmp.text = &str.text[i];
|
||||
cmp.len = MinI64(str.len - i, old_pattern.len);
|
||||
if (MatchString(cmp, old_pattern))
|
||||
{
|
||||
String piece = ZI;
|
||||
piece.text = &str.text[piece_start];
|
||||
piece.len = i - piece_start;
|
||||
if (piece.len > 0)
|
||||
{
|
||||
result.len += PushString(arena, piece).len;
|
||||
}
|
||||
result.len += PushString(arena, new_pattern).len;
|
||||
i += old_pattern.len;
|
||||
piece_start = i;
|
||||
}
|
||||
else
|
||||
{
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
if (piece_start < (i64)str.len)
|
||||
{
|
||||
String piece = ZI;
|
||||
piece.text = &str.text[piece_start];
|
||||
piece.len = str.len - piece_start;
|
||||
result.len += PushString(arena, piece).len;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
//- Indent
|
||||
|
||||
/* NOTE: Really slow */
|
||||
@ -464,6 +502,17 @@ b32 StringEndsWith(String str, String substring)
|
||||
return 0;
|
||||
}
|
||||
|
||||
String StringFromArray(Arena *arena, StringArray a)
|
||||
{
|
||||
String result = ZI;
|
||||
result.text = ArenaNext(arena, u8);
|
||||
for (u64 string_idx = 0; string_idx < a.count; ++string_idx)
|
||||
{
|
||||
result.len += PushString(arena, a.strings[string_idx]).len;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ String list helpers
|
||||
|
||||
|
||||
@ -94,12 +94,14 @@ String CopyString(String dst, String src);
|
||||
String RepeatString(Arena *arena, String src, u64 count);
|
||||
String CatString(Arena *arena, String str1, String str2);
|
||||
StringArray SplitString(Arena *arena, String str, String delim);
|
||||
String ReplaceString(Arena *arena, String str, String old_pattern, String new_pattern);
|
||||
String IndentString(Arena *arena, String str, u32 indent);
|
||||
String LowerString(Arena *arena, String str);
|
||||
b32 MatchString(String str1, String str2);
|
||||
b32 StringContains(String str, String substring);
|
||||
b32 StringBeginsWith(String str, String substring);
|
||||
b32 StringEndsWith(String str, String substring);
|
||||
String StringFromArray(Arena *arena, StringArray a);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Trimming helpers
|
||||
|
||||
@ -64,7 +64,7 @@ b32 Panic(String msg)
|
||||
{
|
||||
LogPanic(msg);
|
||||
char msg_cstr[4096];
|
||||
CstrFromStringToBuff(StringFromArray(msg_cstr), msg);
|
||||
CstrFromStringToBuff(StringFromFixedArray(msg_cstr), msg);
|
||||
{
|
||||
u32 mb_flags = MB_SETFOREGROUND | MB_ICONERROR;
|
||||
MessageBoxExA(0, msg_cstr, "Fatal error", mb_flags, 0);
|
||||
|
||||
@ -176,7 +176,7 @@ GC_Run GC_RunFromString(Arena *arena, String str, GC_FontKey font, f32 font_size
|
||||
GC_Glyph *glyph = ready_glyphs[glyph_idx];
|
||||
GC_RunRect *rect = &result.rects[glyph_idx];
|
||||
|
||||
rect->tex = glyph->tex_ref;
|
||||
rect->tex = glyph->atlas->tex_ref;
|
||||
rect->tex_slice = glyph->tex_slice;
|
||||
rect->tex_slice_uv = glyph->tex_slice_uv;
|
||||
|
||||
@ -252,9 +252,6 @@ void GC_TickAsync(WaveLaneCtx *lane, AsyncTickCtx *tick)
|
||||
|
||||
WaveSync(lane);
|
||||
|
||||
|
||||
|
||||
|
||||
//////////////////////////////
|
||||
//- Rasterize glyphs
|
||||
|
||||
@ -288,22 +285,6 @@ void GC_TickAsync(WaveLaneCtx *lane, AsyncTickCtx *tick)
|
||||
|
||||
if (lane->idx == 0)
|
||||
{
|
||||
/* FIXME: Dynamic atlases */
|
||||
/* Create atlas */
|
||||
Vec2I32 atlas_dims = VEC2I32(8192, 8192);
|
||||
if (G_IsResourceNil(GC.atlas))
|
||||
{
|
||||
G_ArenaHandle gpu_perm = G_PermArena();
|
||||
GC.atlas = G_PushTexture2D(
|
||||
gpu_perm,
|
||||
G_Format_R8G8B8A8_Unorm_Srgb,
|
||||
atlas_dims,
|
||||
/* FIXME: Do we need simultaneous access? */
|
||||
G_Layout_AnyQueue_ShaderRead_CopyRead_CopyWrite_Present,
|
||||
);
|
||||
GC.atlas_ref = G_PushTexture2DRef(gpu_perm, GC.atlas);
|
||||
}
|
||||
|
||||
for (u64 cmd_idx = 0; cmd_idx < async->cmds.count; ++cmd_idx)
|
||||
{
|
||||
GC_Cmd *cmd = &async->cmds.v[cmd_idx];
|
||||
@ -313,23 +294,59 @@ void GC_TickAsync(WaveLaneCtx *lane, AsyncTickCtx *tick)
|
||||
|
||||
Vec2I32 image_dims = ttf_result.image_dims;
|
||||
|
||||
Vec2I32 atlas_offset = GC.atlas_pos;
|
||||
GC.atlas_row_height = MaxI32(GC.atlas_row_height, image_dims.y);
|
||||
if (atlas_offset.x + image_dims.x > atlas_dims.x);
|
||||
/* TODO: Use a more efficient atlas packing algorithm for less wasted space `*/
|
||||
GC_Atlas *atlas = GC.first_atlas;
|
||||
b32 can_use_atlas = 0;
|
||||
Vec2I32 pos_in_atlas = ZI;
|
||||
while (can_use_atlas == 0)
|
||||
{
|
||||
GC.atlas_pos.x = 0;
|
||||
GC.atlas_pos.y += GC.atlas_row_height;
|
||||
GC.atlas_row_height = image_dims.y;
|
||||
/* Create atlas */
|
||||
if (!atlas)
|
||||
{
|
||||
Arena *perm = PermArena();
|
||||
atlas = PushStruct(perm, GC_Atlas);
|
||||
atlas->dims = VEC2I32(1024, 1024);
|
||||
{
|
||||
G_ArenaHandle gpu_perm = G_PermArena();
|
||||
atlas->tex = G_PushTexture2D(
|
||||
gpu_perm,
|
||||
G_Format_R8G8B8A8_Unorm_Srgb,
|
||||
atlas->dims,
|
||||
G_Layout_AnyQueue_ShaderRead_CopyRead_CopyWrite_Present,
|
||||
);
|
||||
atlas->tex_ref = G_PushTexture2DRef(gpu_perm, atlas->tex);
|
||||
}
|
||||
SllStackPush(GC.first_atlas, atlas);
|
||||
++GC.atlases_count;
|
||||
}
|
||||
|
||||
/* Determine pos in atlas */
|
||||
pos_in_atlas = atlas->cur_pos;
|
||||
atlas->cur_row_height = MaxI32(atlas->cur_row_height, image_dims.y);
|
||||
if (pos_in_atlas.x + image_dims.x > atlas->dims.x);
|
||||
{
|
||||
atlas->cur_pos.x = 0;
|
||||
atlas->cur_pos.y += atlas->cur_row_height;
|
||||
atlas->cur_row_height = image_dims.y;
|
||||
}
|
||||
atlas->cur_pos.x += image_dims.x;
|
||||
if (atlas->cur_pos.x < atlas->dims.x && atlas->cur_pos.y < atlas->dims.y)
|
||||
{
|
||||
can_use_atlas = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
atlas = 0;
|
||||
}
|
||||
}
|
||||
GC.atlas_pos.x += image_dims.x;
|
||||
|
||||
/* Atlas info */
|
||||
glyph->tex_ref = GC.atlas_ref;
|
||||
glyph->tex_slice = RNG2I32(atlas_offset, AddVec2I32(atlas_offset, image_dims));
|
||||
glyph->tex_slice_uv.p0.x = (f32)glyph->tex_slice.p0.x / (f32)atlas_dims.x;
|
||||
glyph->tex_slice_uv.p0.y = (f32)glyph->tex_slice.p0.y / (f32)atlas_dims.x;
|
||||
glyph->tex_slice_uv.p1.x = (f32)glyph->tex_slice.p1.x / (f32)atlas_dims.x;
|
||||
glyph->tex_slice_uv.p1.y = (f32)glyph->tex_slice.p1.y / (f32)atlas_dims.x;
|
||||
glyph->atlas = atlas;
|
||||
glyph->tex_slice = RNG2I32(pos_in_atlas, AddVec2I32(pos_in_atlas, image_dims));
|
||||
glyph->tex_slice_uv.p0.x = (f32)glyph->tex_slice.p0.x / (f32)atlas->dims.x;
|
||||
glyph->tex_slice_uv.p0.y = (f32)glyph->tex_slice.p0.y / (f32)atlas->dims.x;
|
||||
glyph->tex_slice_uv.p1.x = (f32)glyph->tex_slice.p1.x / (f32)atlas->dims.x;
|
||||
glyph->tex_slice_uv.p1.y = (f32)glyph->tex_slice.p1.y / (f32)atlas->dims.x;
|
||||
}
|
||||
}
|
||||
|
||||
@ -346,7 +363,7 @@ void GC_TickAsync(WaveLaneCtx *lane, AsyncTickCtx *tick)
|
||||
GC_Glyph *glyph = cmd->glyph;
|
||||
ResourceKey resource = glyph->desc.font.r;
|
||||
GC_GlyphDesc desc = glyph->desc;
|
||||
TTF_GlyphResult ttf_result = TTF_RasterizeGlyphFromCodepoint(tick->arena, desc.codepoint, resource, desc.font_size);;
|
||||
TTF_GlyphResult ttf_result = TTF_RasterizeGlyphFromCodepoint(tick->arena, desc.codepoint, resource, desc.font_size);
|
||||
|
||||
u32 *image_pixels = ttf_result.image_pixels;
|
||||
Vec2I32 image_dims = ttf_result.image_dims;
|
||||
@ -359,7 +376,7 @@ void GC_TickAsync(WaveLaneCtx *lane, AsyncTickCtx *tick)
|
||||
|
||||
G_CopyCpuToTexture(
|
||||
cl,
|
||||
GC.atlas, VEC3I32(glyph->tex_slice.p0.x, glyph->tex_slice.p0.y, 0),
|
||||
glyph->atlas->tex, VEC3I32(glyph->tex_slice.p0.x, glyph->tex_slice.p0.y, 0),
|
||||
image_pixels, VEC3I32(image_dims.x, image_dims.y, 1),
|
||||
RNG3I32(
|
||||
VEC3I32(0, 0, 0),
|
||||
|
||||
@ -6,6 +6,20 @@ Struct(GC_FontKey)
|
||||
ResourceKey r;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Atlas types
|
||||
|
||||
Struct(GC_Atlas)
|
||||
{
|
||||
GC_Atlas *next;
|
||||
|
||||
Vec2I32 dims;
|
||||
G_ResourceHandle tex;
|
||||
G_Texture2DRef tex_ref;
|
||||
Vec2I32 cur_pos;
|
||||
i32 cur_row_height;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Glyph types
|
||||
|
||||
@ -35,7 +49,7 @@ Struct(GC_Glyph)
|
||||
Rng2 bounds;
|
||||
|
||||
/* Atlas info */
|
||||
G_Texture2DRef tex_ref;
|
||||
GC_Atlas *atlas;
|
||||
Rng2I32 tex_slice;
|
||||
Rng2 tex_slice_uv;
|
||||
};
|
||||
@ -45,13 +59,6 @@ Struct(GC_GlyphBin)
|
||||
GC_Glyph *first;
|
||||
};
|
||||
|
||||
// Struct(GC_GlyphDescChunk)
|
||||
// {
|
||||
// GC_GlyphDescChunk *next;
|
||||
// u64 descs_count;
|
||||
// GC_GlyphDesc *descs;
|
||||
// };
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Run types
|
||||
|
||||
@ -123,11 +130,8 @@ Struct(GC_Ctx)
|
||||
Mutex glyphs_mutex;
|
||||
GC_GlyphBin glyph_bins[16384];
|
||||
|
||||
/* TODO: Dynamic atlases */
|
||||
G_ResourceHandle atlas;
|
||||
G_Texture2DRef atlas_ref;
|
||||
Vec2I32 atlas_pos;
|
||||
i32 atlas_row_height;
|
||||
u64 atlases_count;
|
||||
GC_Atlas *first_atlas;
|
||||
|
||||
struct
|
||||
{
|
||||
|
||||
@ -764,6 +764,8 @@ G_ArenaHandle G_AcquireArena(void)
|
||||
gpu_arena->resource_heaps[heap_idx].kind = (G_D12_ResourceHeapKind)heap_idx;
|
||||
}
|
||||
|
||||
AddGstat(NumGpuArenas, 1);
|
||||
|
||||
return G_D12_MakeHandle(G_ArenaHandle, gpu_arena);
|
||||
}
|
||||
|
||||
@ -772,6 +774,8 @@ void G_ReleaseArena(G_ArenaHandle arena)
|
||||
/* TODO */
|
||||
|
||||
/* TODO: Unmap heaps */
|
||||
|
||||
/* TODO: Update gstats */
|
||||
}
|
||||
|
||||
void G_ResetArena(G_CommandListHandle cl_handle, G_ArenaHandle arena_handle)
|
||||
@ -788,51 +792,37 @@ void G_D12_ResetArena(G_D12_CmdList *cl, G_D12_Arena *gpu_arena)
|
||||
{
|
||||
/* TODO */
|
||||
|
||||
/* FIXME: Move descriptors into committed lists */
|
||||
|
||||
/* FIXME: Release id3d12 resource com object references */
|
||||
// for (u64 heap_idx = 0; heap_idx < countof(gpu_arena->resource_heaps); ++heap_idx)
|
||||
// {
|
||||
// G_D12_ResourceHeap *heap = &gpu_arena->resource_heaps[heap_idx];
|
||||
// heap->pos = 0;
|
||||
|
||||
// if (heap->first_reset_resource)
|
||||
// {
|
||||
// heap->last_reset_resource->next = heap->first_resource;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// heap->first_reset_resource = heap->first_resource;
|
||||
// }
|
||||
// heap->last_reset_resource = heap->last_resource;
|
||||
// heap->reset_resources_count += heap->resources_count;
|
||||
// heap->resources_count = 0;
|
||||
// heap->first_resource = 0;
|
||||
// heap->last_resource = 0;
|
||||
// }
|
||||
|
||||
|
||||
|
||||
|
||||
for (u64 heap_idx = 0; heap_idx < countof(gpu_arena->resource_heaps); ++heap_idx)
|
||||
{
|
||||
G_D12_ResourceHeap *heap = &gpu_arena->resource_heaps[heap_idx];
|
||||
heap->pos = 0;
|
||||
|
||||
/* FIXME: Free list if this actually works */
|
||||
if (heap->resources.first)
|
||||
{
|
||||
for (G_D12_Resource *resource = heap->resources.first; resource; resource = resource->next)
|
||||
{
|
||||
ID3D12Resource_Release(resource->d3d_resource);
|
||||
}
|
||||
if (gpu_arena->free_resources.last)
|
||||
{
|
||||
gpu_arena->free_resources.last->next = heap->resources.first;
|
||||
}
|
||||
else
|
||||
{
|
||||
gpu_arena->free_resources.first = heap->resources.first;
|
||||
}
|
||||
gpu_arena->free_resources.last = heap->resources.last;
|
||||
gpu_arena->free_resources.count += heap->resources.count;
|
||||
heap->resources.count = 0;
|
||||
heap->resources.first = 0;
|
||||
heap->resources.last = 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Push descriptors to cl reset list */
|
||||
if (gpu_arena->descriptors.first)
|
||||
{
|
||||
if (cl->reset_descriptors.last)
|
||||
{
|
||||
@ -922,6 +912,14 @@ G_ResourceHandle G_PushResource(G_ArenaHandle arena_handle, G_ResourceDesc desc)
|
||||
d3d_desc.Flags |= D3D12_HEAP_FLAG_ALLOW_ALL_BUFFERS_AND_TEXTURES; /* TODO: Remove this and support tier 1 resource heaps */
|
||||
hr = ID3D12Device_CreateHeap(g->device, &d3d_desc, &IID_ID3D12Heap, (void **)&heap->d3d_heap);
|
||||
heap->size = d3d_desc.SizeInBytes;
|
||||
if (d3d_desc.Properties.Type == D3D12_HEAP_TYPE_DEFAULT)
|
||||
{
|
||||
AddGstat(DedicatedGpuArenaMemoryCommitted, heap->size);
|
||||
}
|
||||
else
|
||||
{
|
||||
AddGstat(SharedGpuArenaMemoryCommitted, heap->size);
|
||||
}
|
||||
}
|
||||
|
||||
/* Map heap resource */
|
||||
@ -1074,6 +1072,14 @@ G_ResourceHandle G_PushResource(G_ArenaHandle arena_handle, G_ResourceDesc desc)
|
||||
// }
|
||||
u64 pos_in_heap = 0;
|
||||
ID3D12Resource *d3d_resource = 0;
|
||||
resource = gpu_arena->free_resources.first;
|
||||
if (resource)
|
||||
{
|
||||
SllQueuePop(gpu_arena->free_resources.first, gpu_arena->free_resources.last);
|
||||
--gpu_arena->free_resources.count;
|
||||
ZeroStruct(resource);
|
||||
}
|
||||
else
|
||||
{
|
||||
resource = PushStruct(gpu_arena->arena, G_D12_Resource);
|
||||
}
|
||||
|
||||
@ -185,6 +185,8 @@ Struct(G_D12_Arena)
|
||||
G_D12_DescriptorList descriptors;
|
||||
G_D12_DescriptorList reset_descriptors_by_heap[G_D12_DescriptorHeapKind_Count];
|
||||
|
||||
G_D12_ResourceList free_resources;
|
||||
|
||||
G_D12_ResourceHeap resource_heaps[G_D12_ResourceHeapKind_Count];
|
||||
};
|
||||
|
||||
|
||||
@ -867,7 +867,7 @@ void N_EndUpdate(N_Host *host)
|
||||
{
|
||||
u8 packet_flags = 0;
|
||||
N_SndPacket *packet = N_PushSndPacket(channel, 0);
|
||||
BB_Buff bb = BB_BuffFromString(StringFromArray(packet->data));
|
||||
BB_Buff bb = BB_BuffFromString(StringFromFixedArray(packet->data));
|
||||
BB_Writer bw = BB_WriterFromBuff(&bb);
|
||||
BB_WriteUBits(&bw, N_PacketMagic, 32); /* TODO: implicitly encode magic into crc32 */
|
||||
BB_WriteIBits(&bw, N_PacketKind_TryConnect, 8);
|
||||
@ -880,7 +880,7 @@ void N_EndUpdate(N_Host *host)
|
||||
{
|
||||
u8 packet_flags = 0;
|
||||
N_SndPacket *packet = N_PushSndPacket(channel, 0);
|
||||
BB_Buff bb = BB_BuffFromString(StringFromArray(packet->data));
|
||||
BB_Buff bb = BB_BuffFromString(StringFromFixedArray(packet->data));
|
||||
BB_Writer bw = BB_WriterFromBuff(&bb);
|
||||
BB_WriteUBits(&bw, N_PacketMagic, 32); /* TODO: implicitly encode magic into crc32 */
|
||||
BB_WriteIBits(&bw, N_PacketKind_ConnectSuccess, 8);
|
||||
@ -893,7 +893,7 @@ void N_EndUpdate(N_Host *host)
|
||||
{
|
||||
u8 packet_flags = 0;
|
||||
N_SndPacket *packet = N_PushSndPacket(channel, 0);
|
||||
BB_Buff bb = BB_BuffFromString(StringFromArray(packet->data));
|
||||
BB_Buff bb = BB_BuffFromString(StringFromFixedArray(packet->data));
|
||||
BB_Writer bw = BB_WriterFromBuff(&bb);
|
||||
BB_WriteUBits(&bw, N_PacketMagic, 32); /* TODO: implicitly encode magic into crc32 */
|
||||
BB_WriteIBits(&bw, N_PacketKind_Disconnect, 8);
|
||||
@ -906,7 +906,7 @@ void N_EndUpdate(N_Host *host)
|
||||
{
|
||||
u8 packet_flags = 0;
|
||||
N_SndPacket *packet = N_PushSndPacket(channel, 0);
|
||||
BB_Buff bb = BB_BuffFromString(StringFromArray(packet->data));
|
||||
BB_Buff bb = BB_BuffFromString(StringFromFixedArray(packet->data));
|
||||
BB_Writer bw = BB_WriterFromBuff(&bb);
|
||||
BB_WriteUBits(&bw, N_PacketMagic, 32); /* TODO: implicitly encode magic into crc32 */
|
||||
BB_WriteIBits(&bw, N_PacketKind_Heartbeat, 8);
|
||||
@ -944,7 +944,7 @@ void N_EndUpdate(N_Host *host)
|
||||
}
|
||||
}
|
||||
N_SndPacket *packet = N_PushSndPacket(channel, is_reliable);
|
||||
BB_Buff bb = BB_BuffFromString(StringFromArray(packet->data));
|
||||
BB_Buff bb = BB_BuffFromString(StringFromFixedArray(packet->data));
|
||||
BB_Writer bw = BB_WriterFromBuff(&bb);
|
||||
BB_WriteUBits(&bw, N_PacketMagic, 32); /* TODO: implicitly encode magic into crc32 */
|
||||
BB_WriteIBits(&bw, N_PacketKind_MsgChunk, 8);
|
||||
|
||||
@ -552,6 +552,7 @@ void S_TickForever(WaveLaneCtx *lane)
|
||||
LockTicketMutex(&shared->output_back_tm);
|
||||
{
|
||||
S_OutputState *output = &shared->output_states[shared->output_back_idx];
|
||||
ResetArena(output->arena);
|
||||
S_SnapshotNode *snapshot_node = PushStruct(output->arena, S_SnapshotNode);
|
||||
S_Snapshot *snapshot = &snapshot_node->snapshot;
|
||||
SllQueuePush(output->first_snapshot_node, output->last_snapshot_node, snapshot_node);
|
||||
|
||||
@ -409,6 +409,37 @@ void V_TickForever(WaveLaneCtx *lane)
|
||||
V_BuildConsoleWidget(minimized);
|
||||
}
|
||||
|
||||
//////////////////////////////
|
||||
//- Build debug info
|
||||
|
||||
if (persist.show_console)
|
||||
{
|
||||
UI_PushCP(UI_BuildColumn());
|
||||
{
|
||||
{
|
||||
{
|
||||
UI_Push(FontSize, 32);
|
||||
UI_BuildLabelF("CPU:");
|
||||
UI_Pop(FontSize);
|
||||
}
|
||||
UI_BuildLabelF(" Arenas: %F", FmtSint(GetGstat(NumArenas)));
|
||||
UI_BuildLabelF(" Arena memory committed: %F MiB", FmtFloat((f64)GetGstat(ArenaMemoryCommitted) / 1024 / 1024));
|
||||
UI_BuildLabelF(" Arena memory reserved: %F TiB", FmtFloat((f64)GetGstat(ArenaMemoryReserved) / 1024 / 1024 / 1024 / 1024));
|
||||
}
|
||||
{
|
||||
{
|
||||
UI_Push(FontSize, 32);
|
||||
UI_BuildLabelF("GPU:");
|
||||
UI_Pop(FontSize);
|
||||
}
|
||||
UI_BuildLabelF(" Arenas: %F", FmtSint(GetGstat(NumGpuArenas)));
|
||||
UI_BuildLabelF(" Dedicated arena memory committed: %F MiB", FmtFloat((f64)GetGstat(DedicatedGpuArenaMemoryCommitted) / 1024 / 1024));
|
||||
UI_BuildLabelF(" Shared arena memory committed: %F MiB", FmtFloat((f64)GetGstat(SharedGpuArenaMemoryCommitted) / 1024 / 1024));
|
||||
}
|
||||
}
|
||||
UI_PopCP(UI_TopCP());
|
||||
}
|
||||
|
||||
//////////////////////////////
|
||||
//- Process vis commands
|
||||
|
||||
|
||||
@ -5,11 +5,11 @@ V_WidgetTheme V_GetWidgetTheme(void)
|
||||
{
|
||||
V_WidgetTheme theme = ZI;
|
||||
|
||||
// theme.font = GC_FontKeyFromResource(ResourceKeyFromStore(&V_Resources, Lit("font/fixedsys.ttf")));
|
||||
// theme.font_size = 16;
|
||||
|
||||
theme.font = GC_FontKeyFromResource(ResourceKeyFromStore(&V_Resources, Lit("font/fixedsys.ttf")));
|
||||
theme.font_size = 64;
|
||||
theme.font_size = 16;
|
||||
|
||||
// theme.font = GC_FontKeyFromResource(ResourceKeyFromStore(&V_Resources, Lit("font/fixedsys.ttf")));
|
||||
// theme.font_size = 64;
|
||||
|
||||
// theme.font = GC_FontKeyFromResource(ResourceKeyFromStore(&V_Resources, Lit("font/roboto-med.ttf")));
|
||||
// theme.font_size = 100;
|
||||
|
||||
@ -29,7 +29,7 @@ TAR_Archive TAR_ArchiveFromString(Arena *arena, String data, String prefix)
|
||||
TAR_Header header = ZI;
|
||||
BB_ReadBytes(&br, StringFromStruct(&header));
|
||||
|
||||
if (!MatchString(StringFromArray(header.ustar_indicator), Lit("ustar\0")))
|
||||
if (!MatchString(StringFromFixedArray(header.ustar_indicator), Lit("ustar\0")))
|
||||
{
|
||||
/* Invalid header */
|
||||
Assert(0);
|
||||
|
||||
@ -367,7 +367,7 @@ UI_Style UI_PopStyle(UI_StyleDesc desc)
|
||||
{
|
||||
UI_StyleNode *n = stack->style_tops[kind];
|
||||
result = n->style;
|
||||
if (desc.use && n->pop_when_used)
|
||||
if (desc.force_pop || (desc.use && n->pop_when_used))
|
||||
{
|
||||
stack->style_tops[kind] = n->next;
|
||||
n->next = frame->first_free_style_node;
|
||||
|
||||
@ -9,7 +9,7 @@ void WND_Bootstrap(void)
|
||||
|
||||
//- Initialize btn table
|
||||
{
|
||||
ZeroArray(g->vk_to_button);
|
||||
ZeroFixedArray(g->vk_to_button);
|
||||
for (u32 i = 'A', j = Button_A; i <= 'Z'; ++i, ++j)
|
||||
{
|
||||
g->vk_to_button[i] = (Button)j;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user