From ed74c5cea5ecfb86e6fca38d81e81ef94557bd28 Mon Sep 17 00:00:00 2001 From: jacob Date: Sun, 7 Dec 2025 13:07:24 -0600 Subject: [PATCH] ui gpu refactor progress --- src/asset_cache/asset_cache.c | 203 ---------- src/asset_cache/asset_cache.h | 93 ----- src/asset_cache/asset_cache.lay | 13 - src/base/base.h | 4 +- src/base/base_resource.c | 8 +- src/font/font.c | 247 ------------ src/font/font.h | 66 ---- src/font/font.lay | 12 - src/glyph_cache/glyph_cache.c | 297 ++++++++++++++ src/glyph_cache/glyph_cache.h | 140 +++++++ src/glyph_cache/glyph_cache.lay | 11 + src/gpu/gpu.lay | 1 - src/gpu/gpu_common.c | 80 ++-- src/gpu/gpu_common.h | 25 +- src/gpu/gpu_core.h | 66 ++-- src/gpu/gpu_dx12/gpu_dx12.c | 57 ++- src/pp/pp_vis/pp_vis.lay | 1 - src/pp/pp_vis/pp_vis_core.c | 8 +- src/proto/proto.c | 29 +- src/proto/proto.lay | 1 + src/ui/ui.lay | 8 +- src/ui/ui_common.c | 2 +- src/ui/ui_core.c | 501 ++++++++++-------------- src/ui/ui_core.h | 121 +++--- src/ui/ui_gpu.h | 43 -- src/ui/ui_shaders.h | 27 ++ src/ui/{ui_gpu.hlsl => ui_shaders.hlsl} | 21 +- src/window/window.h | 16 +- src/window/window.lay | 4 + src/window/window_win32/window_win32.c | 87 ++-- src/window/window_win32/window_win32.h | 7 +- 31 files changed, 935 insertions(+), 1264 deletions(-) delete mode 100644 src/asset_cache/asset_cache.c delete mode 100644 src/asset_cache/asset_cache.h delete mode 100644 src/asset_cache/asset_cache.lay delete mode 100644 src/font/font.c delete mode 100644 src/font/font.h delete mode 100644 src/font/font.lay create mode 100644 src/glyph_cache/glyph_cache.c create mode 100644 src/glyph_cache/glyph_cache.h create mode 100644 src/glyph_cache/glyph_cache.lay delete mode 100644 src/ui/ui_gpu.h create mode 100644 src/ui/ui_shaders.h rename src/ui/{ui_gpu.hlsl => ui_shaders.hlsl} (84%) diff --git a/src/asset_cache/asset_cache.c b/src/asset_cache/asset_cache.c deleted file mode 100644 index 40a01521..00000000 --- a/src/asset_cache/asset_cache.c +++ /dev/null @@ -1,203 +0,0 @@ -/* TODO: Remove this entire layer */ - -AC_SharedState AC_shared_state = ZI; - -//////////////////////////////////////////////////////////// -//~ Startup - -void AC_Startup(void) -{ - AC_SharedState *g = &AC_shared_state; - g->store_arena = AcquireArena(Gibi(64)); -} - -//////////////////////////////////////////////////////////// -//~ Hash - -u64 AC_HashFromKey(String key) -{ - /* TODO: Better hash */ - return HashFnv64(Fnv64Basis, key); -} - -//////////////////////////////////////////////////////////// -//~ Cache - -void AC_RefreshDebugTable(void) -{ -#if IsRtcEnabled - AC_SharedState *g = &AC_shared_state; - Lock lock = LockE(&g->dbg_table_mutex); - ZeroArray(g->dbg_table); - g->dbg_table_count = 0; - for (u64 i = 0; i < countof(g->lookup); ++i) - { - AC_Asset *asset = &g->lookup[i]; - if (asset->hash != 0) - { - g->dbg_table[g->dbg_table_count++] = asset; - } - } - Unlock(&lock); -#endif -} - -/* Returns first matching slot or first empty slot if not found. - * Check returned slot->hash != 0 for presence. */ -AC_Asset *AC_GetAssetCacheSlotLocked(Lock *lock, String key, u64 hash) -{ - AC_SharedState *g = &AC_shared_state; - AssertLockedES(lock, &g->lookup_mutex); - - u64 index = hash % countof(g->lookup); - for (;;) - { - AC_Asset *slot = &g->lookup[index]; - if (slot->hash) - { - /* Occupied */ - if (hash == slot->hash && MatchString(key, slot->key)) - { - /* Matched slot */ - return slot; - } - else - { - ++index; - if (index >= countof(g->lookup)) - { - index = 0; - } - } - } - else - { - /* Empty slot */ - return slot; - } - } -} - -/* `key` text is copied by this function - * - * Returns existing asset entry or inserts a new one. - * - * If is_first_touch (out parameter) is set to 1, then the caller has - * inserted the asset into the cache. - * - * */ -AC_Asset *AC_TouchCache(String key, u64 hash, b32 *is_first_touch) -{ - AC_Asset *asset = 0; - AC_SharedState *g = &AC_shared_state; - - /* Lookup */ - { - Lock lock = LockS(&g->lookup_mutex); - asset = AC_GetAssetCacheSlotLocked(&lock, key, hash); - Unlock(&lock); - } - - /* Insert if not found */ - if (asset->hash) - { - if (is_first_touch) - { - *is_first_touch = 0; - } - } - else - { - Lock lock = LockE(&g->lookup_mutex); - - /* Re-check asset presence in case it was inserted since lock */ - asset = AC_GetAssetCacheSlotLocked(&lock, key, hash); - - if (!asset->hash) - { - if (g->num_assets >= AC_MaxAssets) - { - Panic(Lit("Max assets reached")); - } - String key_stored = ZI; - { - /* Copy key to store */ - AC_Store store = AC_OpenStore(); - key_stored = PushString(store.arena, key); - AC_CloseStore(&store); - } - /* Initialize asset data */ - LogInfoF("Inserting asset cache entry for \"%F\"", FmtString(key)); - *asset = (AC_Asset) { - .status = ASSET_STATUS_UNINITIALIZED, - .hash = hash, - .key = key_stored - }; - if (is_first_touch) - { - *is_first_touch = 1; - } - ++g->num_assets; - - AC_RefreshDebugTable(); - } - - Unlock(&lock); - } - - return asset; -} - -//////////////////////////////////////////////////////////// -//~ Status - -/* Call this once asset job has been created */ -void AC_MarkLoading(AC_Asset *asset) -{ - asset->status = ASSET_STATUS_LOADING; -} - -/* Call this once asset job has finished */ -void AC_MarkReady(AC_Asset *asset, void *store_data) -{ - asset->store_data = store_data; - asset->status = ASSET_STATUS_READY; - SetFence(&asset->ready_fence, 1); -} - -void AC_YieldOnAssetReady(AC_Asset *asset) -{ - YieldOnFence(&asset->ready_fence, 1); -} - -//////////////////////////////////////////////////////////// -//~ Store - -void *AC_DataFromStore(AC_Asset *asset) -{ - if (asset->status == ASSET_STATUS_READY) - { - return asset->store_data; - } - else - { - return 0; - } -} - -/* Asset store should be opened to allocate memory to the store arena */ -AC_Store AC_OpenStore(void) -{ - AC_SharedState *g = &AC_shared_state; - Lock lock = LockE(&g->store_mutex); - AC_Store store = { - .lock = lock, - .arena = g->store_arena - }; - return store; -} - -void AC_CloseStore(AC_Store *store) -{ - Unlock(&store->lock); -} diff --git a/src/asset_cache/asset_cache.h b/src/asset_cache/asset_cache.h deleted file mode 100644 index 156abeef..00000000 --- a/src/asset_cache/asset_cache.h +++ /dev/null @@ -1,93 +0,0 @@ -/* TODO: Remove this entire layer */ - -//////////////////////////////////////////////////////////// -//~ Asset types - -Enum(AC_Status) -{ - ASSET_STATUS_NONE, - ASSET_STATUS_UNINITIALIZED, - ASSET_STATUS_LOADING, - ASSET_STATUS_READY -}; - -Struct(AC_Asset) -{ - /* Managed via AC_TouchCache */ - u64 hash; - String key; - - /* Asset is ready when fence >= 1 */ - Fence ready_fence; - - /* Managed via asset_cache_mark_x functions */ - AC_Status status; - - /* Accessed via asset_cache_get_data */ - void *store_data; -}; - -//////////////////////////////////////////////////////////// -//~ Asset store types - -Struct(AC_Store) -{ - Arena *arena; - - /* internal */ - Lock lock; -}; - -//////////////////////////////////////////////////////////// -//~ State types - -#define AC_MaxAssets 1024 -#define AC_AssetLookupTableCapacity (AC_MaxAssets * 4) - -Struct(AC_SharedState) -{ - Mutex lookup_mutex; - AC_Asset lookup[AC_AssetLookupTableCapacity]; - u64 num_assets; - - Mutex store_mutex; - Arena *store_arena; - -#if IsRtcEnabled - /* Array of len `num_assets` pointing into populated entries of `lookup`. */ - AC_Asset *dbg_table[AC_AssetLookupTableCapacity]; - u64 dbg_table_count; - Mutex dbg_table_mutex; -#endif -} extern AC_shared_state; - -//////////////////////////////////////////////////////////// -//~ Startup - -void AC_Startup(void); - -//////////////////////////////////////////////////////////// -//~ Hash - -u64 AC_HashFromKey(String key); - -//////////////////////////////////////////////////////////// -//~ Cache operations - -void AC_RefreshDebugTable(void); -AC_Asset *AC_GetAssetCacheSlotLocked(Lock *lock, String key, u64 hash); -AC_Asset *AC_TouchCache(String key, u64 hash, b32 *is_first_touch); - -//////////////////////////////////////////////////////////// -//~ Status operations - -void AC_MarkLoading(AC_Asset *asset); -void AC_MarkReady(AC_Asset *asset, void *store_data); -void AC_YieldOnAssetReady(AC_Asset *asset); - -//////////////////////////////////////////////////////////// -//~ Store operations - -void *AC_DataFromStore(AC_Asset *asset); -AC_Store AC_OpenStore(void); -void AC_CloseStore(AC_Store *store); diff --git a/src/asset_cache/asset_cache.lay b/src/asset_cache/asset_cache.lay deleted file mode 100644 index 2e201349..00000000 --- a/src/asset_cache/asset_cache.lay +++ /dev/null @@ -1,13 +0,0 @@ -@Layer asset_cache - -//- Dependencies -@Dep platform - -//- Api -@IncludeC asset_cache.h - -//- Impl -@IncludeC asset_cache.c - -//- Startup -@Startup AC_Startup diff --git a/src/base/base.h b/src/base/base.h index a4968377..e1ce672a 100644 --- a/src/base/base.h +++ b/src/base/base.h @@ -684,12 +684,12 @@ Struct(ResourceStore) { - u64 hash; + u64 v; }; Struct(ResourceKey) { - u64 hash; + u64 v; }; #endif diff --git a/src/base/base_resource.c b/src/base/base_resource.c index 760b0370..e34d1f29 100644 --- a/src/base/base_resource.c +++ b/src/base/base_resource.c @@ -46,13 +46,13 @@ void InitResourceSystem(u64 archive_strings_count, String *archive_strings) b32 IsResourceNil(ResourceKey resource) { - return resource.hash == 0; + return resource.v == 0; } ResourceKey ResourceKeyFromStore(ResourceStore *store, String name) { ResourceKey result = ZI; - result.hash = HashFnv64(store->hash, name); + result.v = HashFnv64(store->v, name); return result; } @@ -81,7 +81,7 @@ ResourceEntry *ResourceEntryFromHash(u64 hash) String DataFromResource(ResourceKey resource) { String result = ZI; - ResourceEntry *entry = ResourceEntryFromHash(resource.hash); + ResourceEntry *entry = ResourceEntryFromHash(resource.v); if (entry) { result = entry->data; @@ -92,7 +92,7 @@ String DataFromResource(ResourceKey resource) String NameFromResource(ResourceKey resource) { String result = ZI; - ResourceEntry *entry = ResourceEntryFromHash(resource.hash); + ResourceEntry *entry = ResourceEntryFromHash(resource.v); if (entry) { result = entry->name; diff --git a/src/font/font.c b/src/font/font.c deleted file mode 100644 index 210e691a..00000000 --- a/src/font/font.c +++ /dev/null @@ -1,247 +0,0 @@ -//////////////////////////////////////////////////////////// -//~ Font load job - -JobImpl(F_Load, sig, _) -{ - TempArena scratch = BeginScratchNoConflict(); - - PERSIST Readonly u32 font_codes[] = { - 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D, - 0x2E,0x2F,0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3A,0x3B, - 0x3C,0x3D,0x3E,0x3F,0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49, - 0x4A,0x4B,0x4C,0x4D,0x4E,0x4F,0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57, - 0x58,0x59,0x5A,0x5B,0x5C,0x5D,0x5E,0x5F,0x60,0x61,0x62,0x63,0x64,0x65, - 0x66,0x67,0x68,0x69,0x6A,0x6B,0x6C,0x6D,0x6E,0x6F,0x70,0x71,0x72,0x73, - 0x74,0x75,0x76,0x77,0x78,0x79,0x7A,0x7B,0x7C,0x7D,0x7E,0x7F,0x80,0x81, - 0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F, - 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D, - 0x9E,0x9F,0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB, - 0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9, - 0xBA,0xBB,0xBC,0xBD,0xBE,0xBF,0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7, - 0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5, - 0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF,0xE0,0xE1,0xE2,0xE3, - 0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1, - 0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF - }; - - ResourceKey resource = sig->resource; - String name = NameFromResource(resource); - f32 font_size = sig->size; - f32 em_size = font_size * (3.0 / 4.0); - AC_Asset *asset = sig->asset; - - LogInfoF("Loading font \"%F\" (font size: %F, em size: %F)", FmtString(name), FmtFloat((f64)font_size), FmtFloat((f64)em_size)); - i64 start_ns = TimeNs(); - - Assert(StringEndsWith(name, Lit(".ttf"))); - Assert(countof(font_codes) < F_LookupTableSize); - - /* Decode */ - String resource_data = DataFromResource(resource); - if (resource_data.len == 0) - { - /* FIME: Load baked font instead of panicking */ - Panic(StringF(scratch.arena, - "Font \"%F\" not found", - FmtString(name))); - } - TTF_Decoded decoded = TTF_Decode(scratch.arena, resource_data, em_size, font_codes, countof(font_codes)); - - /* Upload texture to GPU */ - Fence completion_fence = ZI; - { - GPU_CommandList *cl = GPU_BeginCommandList(GPU_QueueKind_BackgroundCopy); - GPU_Arena *gpu_temp = GPU_AcquireArena(); - { - GpuTexture gpu_texture = ZI; - { - GPU_Arena *gpu_perm = GPU_Perm(); - GPU_ResourceDesc desc = ZI; - desc.texture.format = GPU_Format_R8G8B8A8_Unorm_Srgb; - desc.texture.size = VEC3I32(decoded.image_width, decoded.image_height, 1); - gpu_texture = GPU_PushTexture(gpu_perm, GPU_TextureKind_2D, desc); - } - texture->gpu_texture = gpu_texture; - texture->width = decoded.width; - texture->height = decoded.height; - GpuBuffer src_buff = GPU_PushBuffer(gpu_temp, GPU_GetFootprintSize(gpu_texture), GPU_BufferFlag_CpuWritable); - GpuAddress src_addr = ZI; - { - u32 *p = GPU_PushStructsNoZero(src_buff, u32, decoded.width * decoded.height); - CopyStructs(p, decoded.pixels, decoded.width * decoded.heigth); - GPU_TransitionBufferToCopySrc(src_buff); - GPU_TransitionTextureToCopyDst(gpu_texture); - GPU_CopyBytesToFootprint(gpu_texture, src_buff, src_addr, decoded.width * decoded.height * 4); - GPU_TransitionTextureToReadonly(gpu_texture); - } - GPU_SetFence(&completion_fence, 1); - } - GPU_ReleaseArena(gpu_temp); - GPU_EndCommandList(cl); - } - - /* Acquire store memory */ - F_Font *font = 0; - { - AC_Store store = AC_OpenStore(); - font = PushStruct(store.arena, F_Font); - font->glyphs = PushStructsNoZero(store.arena, F_Glyph, decoded.glyphs_count); - font->lookup = PushStructs(store.arena, u16, F_LookupTableSize); - AC_CloseStore(&store); - } - - /* Set font data */ - font->texture = texture; - font->image_width = decoded.image_width; - font->image_height = decoded.image_height; - font->glyphs_count = decoded.glyphs_count; - font->size = font_size; - font->ascent = decoded.ascent; - font->descent = decoded.descent; - font->cap = decoded.cap; - - /* FIXME: Load baked font instead of panicking */ - if (font->glyphs_count <= 0) - { - Panic(StringF(scratch.arena, - "Parsed 0 glyphs from font \"%F\"!", - FmtString(name))); - } - - /* Copy glyphs from decode decoded */ - /* NOTE: Font glyph size must match TTF glyph size for memcpy */ - StaticAssert(sizeof(*font->glyphs) == sizeof(*decoded.glyphs)); - CopyBytes(font->glyphs, decoded.glyphs, sizeof(*font->glyphs) * decoded.glyphs_count); - - /* Build lookup table */ - for (u64 i = 0; i < countof(font_codes); ++i) - { - u32 codepoint = font_codes[i]; - font->lookup[codepoint] = decoded.cache_indices[i]; - } - - YieldOnFence(&completion_fence, 1); - - LogSuccessF("Loaded font \"%F\" (font size: %F, em size: %F) in %F seconds", FmtString(name), FmtFloat((f64)font_size), FmtFloat((f64)em_size), FmtFloat(SecondsFromNs(TimeNs() - start_ns))); - AC_MarkReady(asset, font); - - EndScratch(scratch); -} - -//////////////////////////////////////////////////////////// -//~ Font load operations - -/* Returns the asset from the asset cache */ -AC_Asset *F_LoadAsset(ResourceKey resource, f32 size, b32 wait) -{ - TempArena scratch = BeginScratchNoConflict(); - String name = NameFromResource(resource); - - /* Concatenate size to name for key */ - String key = StringF(scratch.arena, - "%F%F_font", - FmtString(name), - FmtFloatP((f64)size, 1)); - u64 hash = AC_HashFromKey(key); - b32 is_first_touch; - AC_Asset *asset = AC_TouchCache(key, hash, &is_first_touch); - - if (is_first_touch) - { - AC_MarkLoading(asset); - { - Job *job = OpenJob(F_Load, AsyncPool()); - F_Load_Sig *sig = PushStruct(job->arena, F_Load_Sig); - job->sig = sig; - sig->asset = asset; - sig->resource = resource; - sig->size = size; - CloseJob(job); - } - if (wait) - { - AC_YieldOnAssetReady(asset); - } - } - - EndScratch(scratch); - return asset; -} - -F_Font *F_LoadFontAsync(ResourceKey resource, f32 point_size) -{ - AC_Asset *asset = F_LoadAsset(resource, point_size, 0); - F_Font *f = (F_Font *)AC_DataFromStore(asset); - return f; -} - -F_Font *F_LoadFontWait(ResourceKey resource, f32 point_size) -{ - AC_Asset *asset = F_LoadAsset(resource, point_size, 1); - AC_YieldOnAssetReady(asset); - F_Font *f = (F_Font *)AC_DataFromStore(asset); - return f; -} - -//////////////////////////////////////////////////////////// -//~ Font data operations - -F_Glyph F_GlyphFromCodepoint(F_Font *font, u32 codepoint) -{ - if (codepoint < F_LookupTableSize) - { - u16 index = font->lookup[codepoint]; - if (index < font->glyphs_count) - { - return font->glyphs[index]; - } - } - if (codepoint == '?') - { - return font->glyphs[font->lookup[0]]; - } - else - { - return font->glyphs[font->lookup['?']]; - } -} - -F_Run F_RunFromString(Arena *arena, F_Font *font, String str) -{ - F_Run result = ZI; - result.rects = ArenaNext(arena, F_RunRect); - - f32 baseline_length = 0; - for (CodepointIter it = InitCodepointIter(str); NextCodepoint(&it);) - { - u32 codepoint = it.codepoint; - if (font->glyphs_count <= codepoint) - { - codepoint = '?'; - } - if (codepoint < font->glyphs_count) - { - u16 index = font->lookup[codepoint]; - F_Glyph glyph = font->glyphs[index]; - F_RunRect *rect = PushStruct(arena, F_RunRect); - ++result.count; - - rect->atlas_p0 = glyph.atlas_p0; - rect->atlas_p1 = glyph.atlas_p1; - Vec2I32 size = SubVec2I32(glyph.atlas_p1, glyph.atlas_p0); - - rect->pos = baseline_length; - rect->offset = glyph.baseline_offset; - rect->advance = glyph.advance; - - result.p0.x = MinF32(result.p0.x, rect->offset.x + rect->pos); /* Left run bounds */ - result.p1.x = MaxF32(result.p1.x, rect->offset.x + rect->pos + size.x); /* Right run bounds */ - result.p0.y = MinF32(result.p0.y, rect->offset.y); /* Top run bounds */ - result.p1.y = MaxF32(result.p1.y, rect->offset.y + size.y); /* Bottom run bounds */ - - baseline_length += rect->advance; - } - } - - return result; -} diff --git a/src/font/font.h b/src/font/font.h deleted file mode 100644 index e2922940..00000000 --- a/src/font/font.h +++ /dev/null @@ -1,66 +0,0 @@ -//////////////////////////////////////////////////////////// -//~ Font types - -#define F_LookupTableSize (256) - -Struct(F_Glyph) -{ - i32 advance; - Vec2 baseline_offset; - Vec2I32 atlas_p0; - Vec2I32 atlas_p1; -}; - -Struct(F_Font) -{ - GPU_Resource *texture; - u32 image_width; - u32 image_height; - u16 glyphs_count; - F_Glyph *glyphs; - u16 *lookup; - - /* Metrics */ - f32 size; - f32 ascent; - f32 descent; - f32 cap; -}; - -//////////////////////////////////////////////////////////// -//~ Run types - -Struct(F_RunRect) -{ - Vec2 offset; /* Vector from baseline offset to top left of glyph rect */ - f32 pos; /* Horizontal distance from start of baseline */ - f32 advance; - Vec2I32 atlas_p0; - Vec2I32 atlas_p1; -}; - -Struct(F_Run) -{ - Vec2 p0; /* Start of baseline to top-left-most rect */ - Vec2 p1; /* Start of baseline to bottom-right-most rect corner */ - u32 count; - F_RunRect *rects; -}; - -//////////////////////////////////////////////////////////// -//~ Font load job - -JobDecl(F_Load, { AC_Asset *asset; f32 size; ResourceKey resource; }); - -//////////////////////////////////////////////////////////// -//~ Font load operations - -AC_Asset *F_LoadAsset(ResourceKey resource, f32 size, b32 wait); -F_Font *F_LoadFontAsync(ResourceKey resource, f32 size); -F_Font *F_LoadFontWait(ResourceKey resource, f32 size); - -//////////////////////////////////////////////////////////// -//~ Run operations - -F_Glyph F_GlyphFromCodepoint(F_Font *font, u32 codepoint); -F_Run F_RunFromString(Arena *arena, F_Font *font, String str); diff --git a/src/font/font.lay b/src/font/font.lay deleted file mode 100644 index 09c200f7..00000000 --- a/src/font/font.lay +++ /dev/null @@ -1,12 +0,0 @@ -@Layer font - -//- Dependencies -@Dep ttf -@Dep gpu -@Dep asset_cache - -//- Api -@IncludeC font.h - -//- Impl -@IncludeC font.c diff --git a/src/glyph_cache/glyph_cache.c b/src/glyph_cache/glyph_cache.c new file mode 100644 index 00000000..785d1ad7 --- /dev/null +++ b/src/glyph_cache/glyph_cache.c @@ -0,0 +1,297 @@ +/* TODO: Use default font texture handle */ +Readonly GC_RunRect GC_NilRunRect = { + 0 +}; + +Readonly GC_Run GC_NilRun = { + .count = 1, + .rects = &GC_NilRunRect +}; + +//////////////////////////////////////////////////////////// +//~ Key helpers + +GC_FontKey GC_FontKeyFromResource(ResourceKey resource) +{ + GC_FontKey result = ZI; + result.v = resource.v; + return result; +} + +//////////////////////////////////////////////////////////// +//~ Run + +GC_Run *GC_RunFromString(Arena *arena, GC_FontKey key, String str) +{ + /* TODO */ + GC_Run *result = 0; + + GC_RunRect *rr = PushStruct(arena, GC_RunRect); + rr->advance = 1; + result->rects = rr; + result->count = 1; + + return result; +} + + + + + + + + + + + + + + + +// //////////////////////////////////////////////////////////// +// //~ Font load job + +// JobImpl(F_Load, sig, _) +// { +// TempArena scratch = BeginScratchNoConflict(); + +// PERSIST Readonly u32 font_codes[] = { +// 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D, +// 0x2E,0x2F,0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3A,0x3B, +// 0x3C,0x3D,0x3E,0x3F,0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49, +// 0x4A,0x4B,0x4C,0x4D,0x4E,0x4F,0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57, +// 0x58,0x59,0x5A,0x5B,0x5C,0x5D,0x5E,0x5F,0x60,0x61,0x62,0x63,0x64,0x65, +// 0x66,0x67,0x68,0x69,0x6A,0x6B,0x6C,0x6D,0x6E,0x6F,0x70,0x71,0x72,0x73, +// 0x74,0x75,0x76,0x77,0x78,0x79,0x7A,0x7B,0x7C,0x7D,0x7E,0x7F,0x80,0x81, +// 0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F, +// 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D, +// 0x9E,0x9F,0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB, +// 0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9, +// 0xBA,0xBB,0xBC,0xBD,0xBE,0xBF,0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7, +// 0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5, +// 0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF,0xE0,0xE1,0xE2,0xE3, +// 0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1, +// 0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF +// }; + +// ResourceKey resource = sig->resource; +// String name = NameFromResource(resource); +// f32 font_size = sig->size; +// f32 em_size = font_size * (3.0 / 4.0); +// AC_Asset *asset = sig->asset; + +// LogInfoF("Loading font \"%F\" (font size: %F, em size: %F)", FmtString(name), FmtFloat((f64)font_size), FmtFloat((f64)em_size)); +// i64 start_ns = TimeNs(); + +// Assert(StringEndsWith(name, Lit(".ttf"))); +// Assert(countof(font_codes) < F_LookupTableSize); + +// /* Decode */ +// String resource_data = DataFromResource(resource); +// if (resource_data.len == 0) +// { +// /* FIME: Load baked font instead of panicking */ +// Panic(StringF(scratch.arena, +// "Font \"%F\" not found", +// FmtString(name))); +// } +// TTF_Decoded decoded = TTF_Decode(scratch.arena, resource_data, em_size, font_codes, countof(font_codes)); + +// /* Upload texture to GPU */ +// Fence completion_fence = ZI; +// { +// GPU_CommandList *cl = GPU_BeginCommandList(GPU_QueueKind_BackgroundCopy); +// GPU_Arena *gpu_temp = GPU_AcquireArena(); +// { +// GpuTexture gpu_texture = ZI; +// { +// GPU_Arena *gpu_perm = GPU_Perm(); +// GPU_ResourceDesc desc = ZI; +// desc.texture.format = GPU_Format_R8G8B8A8_Unorm_Srgb; +// desc.texture.size = VEC3I32(decoded.image_width, decoded.image_height, 1); +// gpu_texture = GPU_PushTexture(gpu_perm, GPU_TextureKind_2D, desc); +// } +// texture->gpu_texture = gpu_texture; +// texture->width = decoded.width; +// texture->height = decoded.height; +// GpuBuffer src_buff = GPU_PushBuffer(gpu_temp, GPU_GetFootprintSize(gpu_texture), GPU_BufferFlag_CpuWritable); +// GpuAddress src_addr = ZI; +// { +// u32 *p = GPU_PushStructsNoZero(src_buff, u32, decoded.width * decoded.height); +// CopyStructs(p, decoded.pixels, decoded.width * decoded.heigth); +// GPU_TransitionBufferToCopySrc(src_buff); +// GPU_TransitionTextureToCopyDst(gpu_texture); +// GPU_CopyBytesToFootprint(gpu_texture, src_buff, src_addr, decoded.width * decoded.height * 4); +// GPU_TransitionTextureToReadonly(gpu_texture); +// } +// GPU_SetFence(&completion_fence, 1); +// } +// GPU_ReleaseArena(gpu_temp); +// GPU_EndCommandList(cl); +// } + +// /* Acquire store memory */ +// F_Font *font = 0; +// { +// AC_Store store = AC_OpenStore(); +// font = PushStruct(store.arena, F_Font); +// font->glyphs = PushStructsNoZero(store.arena, F_Glyph, decoded.glyphs_count); +// font->lookup = PushStructs(store.arena, u16, F_LookupTableSize); +// AC_CloseStore(&store); +// } + +// /* Set font data */ +// font->texture = texture; +// font->image_width = decoded.image_width; +// font->image_height = decoded.image_height; +// font->glyphs_count = decoded.glyphs_count; +// font->size = font_size; +// font->ascent = decoded.ascent; +// font->descent = decoded.descent; +// font->cap = decoded.cap; + +// /* FIXME: Load baked font instead of panicking */ +// if (font->glyphs_count <= 0) +// { +// Panic(StringF(scratch.arena, +// "Parsed 0 glyphs from font \"%F\"!", +// FmtString(name))); +// } + +// /* Copy glyphs from decode decoded */ +// /* NOTE: Font glyph size must match TTF glyph size for memcpy */ +// StaticAssert(sizeof(*font->glyphs) == sizeof(*decoded.glyphs)); +// CopyBytes(font->glyphs, decoded.glyphs, sizeof(*font->glyphs) * decoded.glyphs_count); + +// /* Build lookup table */ +// for (u64 i = 0; i < countof(font_codes); ++i) +// { +// u32 codepoint = font_codes[i]; +// font->lookup[codepoint] = decoded.cache_indices[i]; +// } + +// YieldOnFence(&completion_fence, 1); + +// LogSuccessF("Loaded font \"%F\" (font size: %F, em size: %F) in %F seconds", FmtString(name), FmtFloat((f64)font_size), FmtFloat((f64)em_size), FmtFloat(SecondsFromNs(TimeNs() - start_ns))); +// AC_MarkReady(asset, font); + +// EndScratch(scratch); +// } + +// //////////////////////////////////////////////////////////// +// //~ Font load operations + +// /* Returns the asset from the asset cache */ +// AC_Asset *F_LoadAsset(ResourceKey resource, f32 size, b32 wait) +// { +// TempArena scratch = BeginScratchNoConflict(); +// String name = NameFromResource(resource); + +// /* Concatenate size to name for key */ +// String key = StringF(scratch.arena, +// "%F%F_font", +// FmtString(name), +// FmtFloatP((f64)size, 1)); +// u64 hash = AC_HashFromKey(key); +// b32 is_first_touch; +// AC_Asset *asset = AC_TouchCache(key, hash, &is_first_touch); + +// if (is_first_touch) +// { +// AC_MarkLoading(asset); +// { +// Job *job = OpenJob(F_Load, AsyncPool()); +// F_Load_Sig *sig = PushStruct(job->arena, F_Load_Sig); +// job->sig = sig; +// sig->asset = asset; +// sig->resource = resource; +// sig->size = size; +// CloseJob(job); +// } +// if (wait) +// { +// AC_YieldOnAssetReady(asset); +// } +// } + +// EndScratch(scratch); +// return asset; +// } + +// F_Font *F_LoadFontAsync(ResourceKey resource, f32 point_size) +// { +// AC_Asset *asset = F_LoadAsset(resource, point_size, 0); +// F_Font *f = (F_Font *)AC_DataFromStore(asset); +// return f; +// } + +// F_Font *F_LoadFontWait(ResourceKey resource, f32 point_size) +// { +// AC_Asset *asset = F_LoadAsset(resource, point_size, 1); +// AC_YieldOnAssetReady(asset); +// F_Font *f = (F_Font *)AC_DataFromStore(asset); +// return f; +// } + +// //////////////////////////////////////////////////////////// +// //~ Font data operations + +// F_Glyph F_GlyphFromCodepoint(F_Font *font, u32 codepoint) +// { +// if (codepoint < F_LookupTableSize) +// { +// u16 index = font->lookup[codepoint]; +// if (index < font->glyphs_count) +// { +// return font->glyphs[index]; +// } +// } +// if (codepoint == '?') +// { +// return font->glyphs[font->lookup[0]]; +// } +// else +// { +// return font->glyphs[font->lookup['?']]; +// } +// } + +// F_Run F_RunFromString(Arena *arena, F_Font *font, String str) +// { +// F_Run result = ZI; +// result.rects = ArenaNext(arena, F_RunRect); + +// f32 baseline_length = 0; +// for (CodepointIter it = InitCodepointIter(str); NextCodepoint(&it);) +// { +// u32 codepoint = it.codepoint; +// if (font->glyphs_count <= codepoint) +// { +// codepoint = '?'; +// } +// if (codepoint < font->glyphs_count) +// { +// u16 index = font->lookup[codepoint]; +// F_Glyph glyph = font->glyphs[index]; +// F_RunRect *rect = PushStruct(arena, F_RunRect); +// ++result.count; + +// rect->atlas_p0 = glyph.atlas_p0; +// rect->atlas_p1 = glyph.atlas_p1; +// Vec2I32 size = SubVec2I32(glyph.atlas_p1, glyph.atlas_p0); + +// rect->pos = baseline_length; +// rect->offset = glyph.baseline_offset; +// rect->advance = glyph.advance; + +// result.p0.x = MinF32(result.p0.x, rect->offset.x + rect->pos); /* Left run bounds */ +// result.p1.x = MaxF32(result.p1.x, rect->offset.x + rect->pos + size.x); /* Right run bounds */ +// result.p0.y = MinF32(result.p0.y, rect->offset.y); /* Top run bounds */ +// result.p1.y = MaxF32(result.p1.y, rect->offset.y + size.y); /* Bottom run bounds */ + +// baseline_length += rect->advance; +// } +// } + +// return result; +// } diff --git a/src/glyph_cache/glyph_cache.h b/src/glyph_cache/glyph_cache.h new file mode 100644 index 00000000..49e210a5 --- /dev/null +++ b/src/glyph_cache/glyph_cache.h @@ -0,0 +1,140 @@ +//////////////////////////////////////////////////////////// +//~ Key types + +Struct(GC_FontKey) +{ + u64 v; +}; + +//////////////////////////////////////////////////////////// +//~ Run types + +Struct(GC_RunRect) +{ + Vec2 offset; /* Vector from baseline offset to top left of glyph rect */ + f32 pos; /* Horizontal distance from start of baseline */ + f32 advance; + + Vec2 size; + Texture2DHandle tex; + Rng2 uv; +}; + +Struct(GC_Run) +{ + /* Run data */ + Vec2 p0; /* Start of baseline to top-left-most rect */ + Vec2 p1; /* Start of baseline to bottom-right-most rect corner */ + u32 count; + GC_RunRect *rects; + + /* Font stats */ + f32 size; + f32 ascent; + f32 descent; + f32 cap; + + b32 loaded; +}; + +extern Readonly GC_RunRect GC_NilRunRect; +extern Readonly GC_Run GC_NilRun; + +//////////////////////////////////////////////////////////// +//~ Key helpers + +GC_FontKey GC_FontKeyFromResource(ResourceKey resource); + +//////////////////////////////////////////////////////////// +//~ Run + +GC_Run *GC_RunFromString(Arena *arena, GC_FontKey key, String str); + + + + + + + + + + + + + + + + + + + + +// //////////////////////////////////////////////////////////// +// //~ Font types + +// Struct(GC_FontKey) +// { +// u64 v; +// }; + +// Struct(GC_Glyph) +// { +// i32 advance; +// Vec2 baseline_offset; +// Vec2I32 atlas_p0; +// Vec2I32 atlas_p1; +// }; + +// Struct(GC_Font) +// { +// GPU_Resource *texture; +// u32 image_width; +// u32 image_height; +// u16 glyphs_count; +// F_Glyph *glyphs; +// u16 *lookup; + +// /* Metrics */ +// f32 size; +// f32 ascent; +// f32 descent; +// f32 cap; +// }; + +// //////////////////////////////////////////////////////////// +// //~ Run types + +// Struct(F_RunRect) +// { +// Vec2 offset; /* Vector from baseline offset to top left of glyph rect */ +// f32 pos; /* Horizontal distance from start of baseline */ +// f32 advance; +// Vec2I32 atlas_p0; +// Vec2I32 atlas_p1; +// }; + +// Struct(F_Run) +// { +// Vec2 p0; /* Start of baseline to top-left-most rect */ +// Vec2 p1; /* Start of baseline to bottom-right-most rect corner */ +// u32 count; +// F_RunRect *rects; +// }; + +// //////////////////////////////////////////////////////////// +// //~ Font load job + +// JobDecl(F_Load, { AC_Asset *asset; f32 size; ResourceKey resource; }); + +// //////////////////////////////////////////////////////////// +// //~ Font load operations + +// AC_Asset *F_LoadAsset(ResourceKey resource, f32 size, b32 wait); +// F_Font *F_LoadFontAsync(ResourceKey resource, f32 size); +// F_Font *F_LoadFontWait(ResourceKey resource, f32 size); + +// //////////////////////////////////////////////////////////// +// //~ Run operations + +// F_Glyph F_GlyphFromCodepoint(F_Font *font, u32 codepoint); +// F_Run F_RunFromString(Arena *arena, F_Font *font, String str); diff --git a/src/glyph_cache/glyph_cache.lay b/src/glyph_cache/glyph_cache.lay new file mode 100644 index 00000000..a79c7007 --- /dev/null +++ b/src/glyph_cache/glyph_cache.lay @@ -0,0 +1,11 @@ +@Layer glyph_cache + +//- Dependencies +@Dep ttf +@Dep gpu + +//- Api +@IncludeC glyph_cache.h + +//- Impl +@IncludeC glyph_cache.c diff --git a/src/gpu/gpu.lay b/src/gpu/gpu.lay index 73592d0c..fc636257 100644 --- a/src/gpu/gpu.lay +++ b/src/gpu/gpu.lay @@ -1,7 +1,6 @@ @Layer gpu //- Dependencies -@Dep window @Dep platform //- Api diff --git a/src/gpu/gpu_common.c b/src/gpu/gpu_common.c index 0a074cc7..259408d5 100644 --- a/src/gpu/gpu_common.c +++ b/src/gpu/gpu_common.c @@ -50,47 +50,12 @@ void GPU_StartupCommon(void) GPU_CommitCommandList(cl); GPU_SyncAllQueues(GPU_QueueKind_Direct); - - - - - - - // GPU_CommandListHandle cl = GPU_PrepareCommandList(); - // { - // /* Init noise texture */ - // String noise_data = DataFromResource(ResourceKeyFromStore(&GPU_Resources, Lit("noise_128x128x64_16.dat"))); - // Vec3I32 noise_dims = VEC3I32(128, 128, 64); - // GPU_ResourceHandle noise_tex = ZI; - // { - // if (noise_data.len != noise_dims.x * noise_dims.y * noise_dims.z * 2) - // { - // Panic(Lit("Unexpected noise texture size")); - // } - // noise_tex = GPU_PushTexture3D(gpu_perm, noise_dims, GPU_Format_R16_Uint, GPU_AccessKind_CopyWrite); - // GPU_CopyResourceFromCpu(cl, noise_tex, noise_data); - // } - - // /* Init quad index buffer */ - // GPU_ResourceHandle quad_indices = ZI; - // { - // u16 quad_data[6] = { 0, 1, 2, 0, 2, 3 }; - // quad_indices = GPU_PushBuffer(gpu_perm, u16, GPU_AccessKind_CopyWrite); - // GPU_CopyResourceFromCpu(cl, quad_indices, StringFromArray(quad_data)); - // } - - // g->noise_tex = GPU_PushTexture3DPtr(gpu_perm, noise_tex); - // g->quad_indices = GPU_PushIndexBufferPtr(gpu_perm, quad_indices, u16); - - // /* FIXME: Block other queues until common startup finishes here */ - // GPU_SyncAccess(cl, noise_tex, GPU_AccessKind_AnyRead); - // GPU_SyncAccess(cl, quad_indices, GPU_AccessKind_AnyRead); - // } - // GPU_CommitCommandList(cl, GPU_QueueKind_Direct); } //////////////////////////////////////////////////////////// -//~ Arena helpers +//~ Helpers + +//- Arena GPU_ArenaHandle GPU_PermArena(void) { @@ -103,28 +68,49 @@ GPU_ArenaHandle GPU_PermArena(void) return perm; } -//////////////////////////////////////////////////////////// -//~ Cpu -> Gpu copy helpers +//- Cpu -> Gpu copy -void GPU_CopyResourceFromCpu(GPU_CommandListHandle cl, GPU_ResourceHandle dst, String src) +StructuredBufferHandle GPU_PushStructuredBufferFromCpu_(GPU_ArenaHandle gpu_arena, GPU_CommandListHandle cl, void *src, u32 element_size, u32 element_count) { - /* TODO */ + u64 size = (u64)element_size * (u64)element_count; + GPU_ResourceHandle buffer = GPU_PushBufferEx(gpu_arena, (GPU_BufferDesc) { .size = size }); + GPU_CopyCpuToBuffer(cl, buffer, 0, src, RNGU64(0, size)); + StructuredBufferHandle structured_buffer = GPU_PushStructuredBufferHandleEx(gpu_arena, buffer, element_size, RNGU32(0, element_count)); + GPU_MemorySync( + cl, buffer, + GPU_Stage_None, GPU_Access_None, + GPU_Stage_AllShading, GPU_Access_ShaderRead + ); + return structured_buffer; } -//////////////////////////////////////////////////////////// -//~ Common resource helpers +//- Viewport / scissor -SamplerStateHandle GPU_GetCommonPointSampler(void) +Rng3 GPU_ViewportFromTexture(GPU_ResourceHandle texture) +{ + Vec2I32 dims = GPU_Count2D(texture); + return RNG3(VEC3(0, 0, 0), VEC3(dims.x, dims.y, 1)); +} + +Rng2 GPU_ScissorFromTexture(GPU_ResourceHandle texture) +{ + Vec2I32 dims = GPU_Count2D(texture); + return RNG2(VEC2(0, 0), VEC2(dims.x, dims.y)); +} + +//- Shared resources + +SamplerStateHandle GPU_GetSharedPointSampler(void) { return GPU_shared_util_state.pt_sampler; } -GPU_IndexBufferDesc GPU_GetCommonQuadIndices(void) +GPU_IndexBufferDesc GPU_GetSharedQuadIndices(void) { return GPU_shared_util_state.quad_indices; } -Texture3DHandle GPU_GetCommonNoise(void) +Texture3DHandle GPU_GetSharedNoise(void) { return GPU_shared_util_state.noise_tex; } diff --git a/src/gpu/gpu_common.h b/src/gpu/gpu_common.h index 70bdcc27..1e1b8bf8 100644 --- a/src/gpu/gpu_common.h +++ b/src/gpu/gpu_common.h @@ -17,18 +17,25 @@ extern ThreadLocal GPU_ArenaHandle GPU_t_perm_arena; void GPU_StartupCommon(void); //////////////////////////////////////////////////////////// -//~ Arena helpers +//~ Helpers + +//- Arena GPU_ArenaHandle GPU_PermArena(void); -//////////////////////////////////////////////////////////// -//~ Cpu -> Gpu copy helpers +//- Cpu -> Gpu copy -void GPU_CopyResourceFromCpu(GPU_CommandListHandle cl, GPU_ResourceHandle dst, String src); +StructuredBufferHandle GPU_PushStructuredBufferFromCpu_(GPU_ArenaHandle gpu_arena, GPU_CommandListHandle cl, void *src, u32 element_size, u32 element_count); +#define GPU_PushStructuredBufferFromCpu(gpu_arena, cl, ptr, count) \ + GPU_PushStructuredBufferFromCpu_((gpu_arena), (cl), (ptr), sizeof(*ptr), count); -//////////////////////////////////////////////////////////// -//~ Common resource helpers +//- Viewport / scissor -SamplerStateHandle GPU_GetCommonPointSampler(void); -GPU_IndexBufferDesc GPU_GetCommonQuadIndices(void); -Texture3DHandle GPU_GetCommonNoise(void); +Rng3 GPU_ViewportFromTexture(GPU_ResourceHandle texture); +Rng2 GPU_ScissorFromTexture(GPU_ResourceHandle texture); + +//- Shared resources + +SamplerStateHandle GPU_GetSharedPointSampler(void); +GPU_IndexBufferDesc GPU_GetSharedQuadIndices(void); +Texture3DHandle GPU_GetSharedNoise(void); diff --git a/src/gpu/gpu_core.h b/src/gpu/gpu_core.h index 13da187c..40e91e46 100644 --- a/src/gpu/gpu_core.h +++ b/src/gpu/gpu_core.h @@ -2,13 +2,15 @@ //~ Handle types Struct(GPU_ArenaHandle) { u64 v; }; - Struct(GPU_CommandListHandle) { u64 v; }; - Struct(GPU_ResourceHandle) { u64 v; }; - Struct(GPU_SwapchainHandle) { u64 v; }; +#define GPU_IsArenaNil(h) ((h).v == 0) +#define GPU_IsCommandListNil(h) ((h).v == 0) +#define GPU_IsResourceNil(h) ((h).v == 0) +#define GPU_IsSwapchainNil(h) ((h).v == 0) + //////////////////////////////////////////////////////////// //~ Queue types @@ -493,7 +495,8 @@ void GPU_Startup(void); GPU_ArenaHandle GPU_AcquireArena(void); void GPU_ReleaseArena(GPU_ArenaHandle arena); -b32 GPU_IsArenaNil(GPU_ArenaHandle handle); +void GPU_ResetArena(GPU_CommandListHandle cl, GPU_ArenaHandle arena); +void GPU_ResetArenaFromQueue(GPU_QueueKind queue, GPU_ArenaHandle arena); //////////////////////////////////////////////////////////// //~ @hookdecl Resource @@ -504,8 +507,6 @@ GPU_ResourceHandle GPU_PushBufferEx(GPU_ArenaHandle arena, GPU_BufferDesc desc); GPU_ResourceHandle GPU_PushTextureEx(GPU_ArenaHandle arena, GPU_TextureDesc desc); GPU_ResourceHandle GPU_PushSampler(GPU_ArenaHandle arena, GPU_SamplerDesc desc); -b32 GPU_IsResourceNil(GPU_ResourceHandle handle); - #define GPU_PushBuffer(arena, type, count, ...) GPU_PushBufferEx((arena), \ (GPU_BufferDesc) { \ .size = sizeof(type) * (count), \ @@ -580,21 +581,17 @@ void GPU_CommitCommandListEx(GPU_CommandListHandle cl, u64 fence_ops_count, GPU_ #define GPU_CommitCommandList(cl) GPU_CommitCommandListEx((cl), 0, 0) -//- Arena - -void GPU_ResetArena(GPU_CommandListHandle cl, GPU_ArenaHandle arena); - //- Cpu -> Gpu copy -void GPU_CopyCpuToBuffer(GPU_CommandListHandle cl_handle, GPU_ResourceHandle dst_handle, u64 dst_offset, void *src, RngU64 src_copy_range); -void GPU_CopyCpuToTexture(GPU_CommandListHandle cl_handle, GPU_ResourceHandle dst_handle, Vec3I32 dst_offset, void *src, Vec3I32 src_dims, Rng3I32 src_copy_range); +void GPU_CopyCpuToBuffer(GPU_CommandListHandle cl, GPU_ResourceHandle dst, u64 dst_offset, void *src, RngU64 src_copy_range); +void GPU_CopyCpuToTexture(GPU_CommandListHandle cl, GPU_ResourceHandle dst, Vec3I32 dst_offset, void *src, Vec3I32 src_dims, Rng3I32 src_copy_range); //- Gpu <-> Gpu copy -void GPU_CopyBufferToBuffer(GPU_CommandListHandle cl_handle, GPU_ResourceHandle dst_handle, u64 dst_offset, GPU_ResourceHandle src_handle, RngU64 src_copy_range); -void GPU_CopyBufferToTexture(GPU_CommandListHandle cl_handle, GPU_ResourceHandle dst_handle, Vec3I32 dst_offset, GPU_ResourceHandle src_handle, Vec3I32 src_dims, Rng3I32 src_copy_range); -void GPU_CopyTextureToTexture(GPU_CommandListHandle cl_handle, GPU_ResourceHandle dst_handle, Vec3I32 dst_offset, GPU_ResourceHandle src_handle, Rng3I32 src_copy_range); -void GPU_CopyTextureToBuffer(GPU_CommandListHandle cl_handle, GPU_ResourceHandle dst_handle, Vec3I32 dst_offset, GPU_ResourceHandle src_handle, Rng3I32 src_copy_range); +void GPU_CopyBufferToBuffer(GPU_CommandListHandle cl, GPU_ResourceHandle dst, u64 dst_offset, GPU_ResourceHandle src, RngU64 src_copy_range); +void GPU_CopyBufferToTexture(GPU_CommandListHandle cl, GPU_ResourceHandle dst, Vec3I32 dst_offset, GPU_ResourceHandle src, Vec3I32 src_dims, Rng3I32 src_copy_range); +void GPU_CopyTextureToTexture(GPU_CommandListHandle cl, GPU_ResourceHandle dst, Vec3I32 dst_offset, GPU_ResourceHandle src, Rng3I32 src_copy_range); +void GPU_CopyTextureToBuffer(GPU_CommandListHandle cl, GPU_ResourceHandle dst, Vec3I32 dst_offset, GPU_ResourceHandle src, Rng3I32 src_copy_range); //- Constant @@ -614,8 +611,8 @@ void GPU_BarrierEx(GPU_CommandListHandle cl, GPU_BarrierDesc desc); GPU_BarrierEx((_cl), (GPU_BarrierDesc) { \ .resource = (_resource), \ .sync_prev = _sync_prev, \ - .sync_next = _sync_next, \ .access_prev = _access_prev, \ + .sync_next = _sync_next, \ .access_next = _access_next, \ }) @@ -623,8 +620,8 @@ void GPU_BarrierEx(GPU_CommandListHandle cl, GPU_BarrierDesc desc); GPU_BarrierEx((_cl), (GPU_BarrierDesc) { \ .resource = (_resource), \ .sync_prev = _sync_prev, \ - .sync_next = _sync_next, \ .access_prev = _access_prev, \ + .sync_next = _sync_next, \ .access_next = _access_next, \ .layout = _layout, \ }) @@ -633,8 +630,8 @@ void GPU_BarrierEx(GPU_CommandListHandle cl, GPU_BarrierDesc desc); GPU_BarrierEx((_cl), (GPU_BarrierDesc) { \ .is_global = 1, \ .sync_prev = _sync_prev, \ - .sync_next = _sync_next, \ .access_prev = _access_prev, \ + .sync_next = _sync_next, \ .access_next = _access_next, \ }) @@ -653,29 +650,12 @@ void GPU_Compute(GPU_CommandListHandle cl, ComputeShader cs, Vec3I32 groups); //- Rasterize -void GPU_RasterizeEx(GPU_CommandListHandle cl, - VertexShader vs, PixelShader ps, - u32 instances_count, GPU_IndexBufferDesc index_buffer, - u32 render_targets_count, GPU_ResourceHandle *render_targets, - Rng3 viewport, Rng2 scissor, - GPU_RasterMode mode); - -#define GPU_Rasterize(cl, vs, ps, instances_count, index_buffer, render_target, mode) \ - GPU_RasterizeEx( \ - (cl), \ - (vs), (ps), \ - (instances_count), (index_buffer), \ - 1, &(render_target), \ - RNG3( \ - VEC3(0, 0, 0), \ - VEC3(GPU_CountWidth(render_target), GPU_CountHeight(render_target), 1) \ - ), \ - RNG2( \ - VEC2(0, 0), \ - Vec2FromVec(GPU_Count2D(render_target)) \ - ), \ - (mode) \ - ) +void GPU_Rasterize(GPU_CommandListHandle cl, + VertexShader vs, PixelShader ps, + u32 instances_count, GPU_IndexBufferDesc index_buffer, + u32 render_targets_count, GPU_ResourceHandle *render_targets, + Rng3 viewport, Rng2 scissor, + GPU_RasterMode mode); //- Clear @@ -698,7 +678,7 @@ GPU_Stats GPU_QueryStats(void); //////////////////////////////////////////////////////////// //~ @hookdecl Swapchain -GPU_SwapchainHandle GPU_AcquireSwapchain(WND_Handle window); +GPU_SwapchainHandle GPU_AcquireSwapchain(u64 os_window_handle); void GPU_ReleaseSwapchain(GPU_SwapchainHandle swapchain); /* Waits until a new backbuffer is ready from the swapchain. diff --git a/src/gpu/gpu_dx12/gpu_dx12.c b/src/gpu/gpu_dx12/gpu_dx12.c index dd24b7f4..c45dad30 100644 --- a/src/gpu/gpu_dx12/gpu_dx12.c +++ b/src/gpu/gpu_dx12/gpu_dx12.c @@ -761,9 +761,25 @@ void GPU_ReleaseArena(GPU_ArenaHandle arena) /* TODO */ } -b32 GPU_IsArenaNil(GPU_ArenaHandle handle) +void GPU_ResetArena(GPU_CommandListHandle cl_handle, GPU_ArenaHandle arena_handle) { - return handle.v == 0; + GPU_D12_Arena *gpu_arena = GPU_D12_ArenaFromHandle(arena_handle); + + /* TODO */ + + /* FIXME: Move descriptors into committed lists */ + + /* FIXME: Release id3d12 resource com object references */ + gpu_arena->heap_pos = 0; +} + +void GPU_ResetArenaFromQueue(GPU_QueueKind queue_kind, GPU_ArenaHandle arena_handle) +{ + GPU_D12_Arena *gpu_arena = GPU_D12_ArenaFromHandle(arena_handle); + + /* TODO */ + + gpu_arena->heap_pos = 0; } //////////////////////////////////////////////////////////// @@ -1042,11 +1058,6 @@ GPU_ResourceHandle GPU_PushSampler(GPU_ArenaHandle arena_handle, GPU_SamplerDesc return GPU_D12_MakeHandle(GPU_ResourceHandle, resource); } -b32 GPU_IsResourceNil(GPU_ResourceHandle handle) -{ - return handle.v == 0; -} - //- Pointer creation StructuredBufferHandle GPU_PushStructuredBufferHandleEx(GPU_ArenaHandle arena_handle, GPU_ResourceHandle resource_handle, u32 element_size, RngU32 element_range) @@ -1529,7 +1540,7 @@ void GPU_CommitCommandListEx(GPU_CommandListHandle cl_handle, u64 fence_ops_coun u64 slotted_constants[MaxShaderConstants]; u64 bound_compute_constants[MaxShaderConstants]; u64 bound_graphics_constants[MaxShaderConstants]; - for (i32 i = 0; i < countof(slotted_constants); ++i) { slotted_constants[i] = U64Max; } + for (i32 i = 0; i < countof(slotted_constants); ++i) { slotted_constants[i] = 0; } /* Zero initialze all constant slots */ for (i32 i = 0; i < countof(bound_compute_constants); ++i) { bound_compute_constants[i] = U64Max; } for (i32 i = 0; i < countof(bound_graphics_constants); ++i) { bound_graphics_constants[i] = U64Max; } @@ -2117,20 +2128,6 @@ void GPU_CommitCommandListEx(GPU_CommandListHandle cl_handle, u64 fence_ops_coun EndScratch(scratch); } -//- Arena - -void GPU_ResetArena(GPU_CommandListHandle cl_handle, GPU_ArenaHandle arena_handle) -{ - GPU_D12_Arena *gpu_arena = GPU_D12_ArenaFromHandle(arena_handle); - - /* TODO */ - - /* FIXME: Move descriptors into committed lists */ - - /* FIXME: Release id3d12 resource com object references */ - gpu_arena->heap_pos = 0; -} - //- Cpu -> Gpu copy void GPU_CopyCpuToBuffer(GPU_CommandListHandle cl_handle, GPU_ResourceHandle dst_handle, u64 dst_offset, void *src, RngU64 src_copy_range) @@ -2331,12 +2328,12 @@ void GPU_Compute(GPU_CommandListHandle cl_handle, ComputeShader cs, Vec3I32 grou //- Rasterize -void GPU_RasterizeEx(GPU_CommandListHandle cl_handle, - VertexShader vs, PixelShader ps, - u32 instances_count, GPU_IndexBufferDesc index_buffer, - u32 render_targets_count, GPU_ResourceHandle *render_targets, - Rng3 viewport, Rng2 scissor, - GPU_RasterMode mode) +void GPU_Rasterize(GPU_CommandListHandle cl_handle, + VertexShader vs, PixelShader ps, + u32 instances_count, GPU_IndexBufferDesc index_buffer, + u32 render_targets_count, GPU_ResourceHandle *render_targets, + Rng3 viewport, Rng2 scissor, + GPU_RasterMode mode) { GPU_D12_CmdList *cl = GPU_D12_CmdListFromHandle(cl_handle); GPU_D12_Cmd *cmd = GPU_D12_PushCmd(cl); @@ -2500,14 +2497,14 @@ GPU_Stats GPU_QueryStats(void) //////////////////////////////////////////////////////////// //~ @hookimpl Swapchain -GPU_SwapchainHandle GPU_AcquireSwapchain(WND_Handle window) +GPU_SwapchainHandle GPU_AcquireSwapchain(u64 os_window_handle) { GPU_D12_Swapchain *swapchain = 0; { Arena *perm = PermArena(); swapchain = PushStruct(perm, GPU_D12_Swapchain); } - swapchain->window_hwnd = (HWND)WND_OsHandleFromWindow(window); + swapchain->window_hwnd = (HWND)os_window_handle; return GPU_D12_MakeHandle(GPU_SwapchainHandle, swapchain); } diff --git a/src/pp/pp_vis/pp_vis.lay b/src/pp/pp_vis/pp_vis.lay index 56df0040..7dcbd515 100644 --- a/src/pp/pp_vis/pp_vis.lay +++ b/src/pp/pp_vis/pp_vis.lay @@ -2,7 +2,6 @@ //- Dependencies @Dep gpu -@Dep sprite @Dep font @Dep platform @Dep window diff --git a/src/pp/pp_vis/pp_vis_core.c b/src/pp/pp_vis/pp_vis_core.c index aa7274d6..8941ec6c 100644 --- a/src/pp/pp_vis/pp_vis_core.c +++ b/src/pp/pp_vis/pp_vis_core.c @@ -198,8 +198,8 @@ JobImpl(V_VisWorker, _, __) Vec4 swapchain_color = V_GetWidgetTheme().window_background_color; ui_frame_flags |= UI_FrameFlag_Debug * !!persist.ui_debug; ui_frame_flags |= UI_FrameFlag_Vsync * !!VSYNC; - UI_Frame ui_frame = UI_BeginFrame(ui_frame_flags, swapchain_color); - WND_Frame window_frame = ui_frame.window_frame; + UI_Frame *ui_frame = UI_BeginFrame(ui_frame_flags, swapchain_color); + WND_Frame window_frame = ui_frame->window_frame; /* Restore window */ { @@ -296,7 +296,7 @@ JobImpl(V_VisWorker, _, __) } /* Cursors */ - Vec2 ui_cursor = ui_frame.cursor_pos; + Vec2 ui_cursor = ui_frame->cursor_pos; Vec2 draw_cursor = MulXformV2(ui_to_draw_xf, ui_cursor); Vec2 world_cursor = MulXformV2(ui_to_world_xf, ui_cursor); @@ -576,7 +576,7 @@ JobImpl(V_VisWorker, _, __) { GPU_SetConstantPtr(cl, V_DrawConst_Params, draw_params); GPU_SetConstantPtr(cl, V_DrawConst_FinalTarget, draw_target); - GPU_SetConstantPtr(cl, V_DrawConst_Sampler, GPU_GetCommonPointSampler()); + GPU_SetConstantPtr(cl, V_DrawConst_Sampler, GPU_GetSharedPointSampler()); GPU_SetConstantPtr(cl, V_DrawConst_DVerts, dverts); /* Backdrop pass */ diff --git a/src/proto/proto.c b/src/proto/proto.c index 0c4db473..2cacd3fa 100644 --- a/src/proto/proto.c +++ b/src/proto/proto.c @@ -2,12 +2,9 @@ void PT_RunForever(WaveLaneCtx *lane) { GPU_ArenaHandle gpu_frame_arena = GPU_AcquireArena(); - b32 swapchain_initialized = 0; - GPU_SwapchainHandle swapchain = ZI; - for (;;) { - WND_Frame window_frame = WND_BeginFrame(); + WND_Frame window_frame = WND_BeginFrame(GPU_Format_R16G16B16A16_Float, WND_BackbufferSizeMode_MatchWindow); for (u64 cev_idx = 0; cev_idx < window_frame.controller_events.count; ++cev_idx) { ControllerEvent *cev = &window_frame.controller_events.events[cev_idx]; @@ -19,13 +16,6 @@ void PT_RunForever(WaveLaneCtx *lane) } { - if (!swapchain_initialized) - { - swapchain_initialized = 1; - swapchain = GPU_AcquireSwapchain(window_frame.window); - } - - GPU_ResourceHandle backbuffer = GPU_PrepareBackbuffer(swapchain, GPU_Format_R16G16B16A16_Float, window_frame.draw_size); { GPU_CommandListHandle cl = GPU_PrepareCommandList(GPU_QueueKind_Direct); { @@ -45,9 +35,9 @@ void PT_RunForever(WaveLaneCtx *lane) { GPU_SetConstant(cl, PT_ShaderConst_TestTarget, final_target_rwhandle); GPU_SetConstant(cl, PT_ShaderConst_TestConst, 3.123); - GPU_SetConstant(cl, PT_ShaderConst_BlitSampler, GPU_GetCommonPointSampler()); + GPU_SetConstant(cl, PT_ShaderConst_BlitSampler, GPU_GetSharedPointSampler()); GPU_SetConstant(cl, PT_ShaderConst_BlitSrc, final_target_rhandle); - GPU_SetConstant(cl, PT_ShaderConst_NoiseTex, GPU_GetCommonNoise()); + GPU_SetConstant(cl, PT_ShaderConst_NoiseTex, GPU_GetSharedNoise()); } /* Test pass */ @@ -59,20 +49,22 @@ void PT_RunForever(WaveLaneCtx *lane) /* Prep blit pass */ { GPU_DumbMemoryLayoutSync(cl, final_target, GPU_Layout_DirectQueue_ShaderRead); - GPU_DumbMemoryLayoutSync(cl, backbuffer, GPU_Layout_DirectQueue_RenderTargetWrite); + GPU_DumbMemoryLayoutSync(cl, window_frame.backbuffer, GPU_Layout_DirectQueue_RenderTargetWrite); } /* Blit pass */ { GPU_Rasterize(cl, PT_BlitVS, PT_BlitPS, - 1, GPU_GetCommonQuadIndices(), - backbuffer, GPU_RasterMode_TriangleList); + 1, GPU_GetSharedQuadIndices(), + 1, &window_frame.backbuffer, + GPU_ViewportFromTexture(window_frame.backbuffer), GPU_ScissorFromTexture(window_frame.backbuffer), + GPU_RasterMode_TriangleList); } /* Finalize backbuffer layout */ { - GPU_DumbMemoryLayoutSync(cl, backbuffer, GPU_Layout_AnyQueue_ShaderRead_CopyRead_CopyWrite_Present); + GPU_DumbMemoryLayoutSync(cl, window_frame.backbuffer, GPU_Layout_AnyQueue_ShaderRead_CopyRead_CopyWrite_Present); } /* Reset */ @@ -82,9 +74,8 @@ void PT_RunForever(WaveLaneCtx *lane) } GPU_CommitCommandList(cl); } - GPU_CommitBackbuffer(backbuffer, VSYNC); } - WND_EndFrame(window_frame); + WND_EndFrame(window_frame, VSYNC); } } diff --git a/src/proto/proto.lay b/src/proto/proto.lay index 0fb9873b..0fd7b279 100644 --- a/src/proto/proto.lay +++ b/src/proto/proto.lay @@ -3,6 +3,7 @@ //- Dependencies @Dep gpu @Dep window +@Dep ui //- Api @IncludeC proto_shaders.h diff --git a/src/ui/ui.lay b/src/ui/ui.lay index f5732fc2..da57fd4a 100644 --- a/src/ui/ui.lay +++ b/src/ui/ui.lay @@ -2,19 +2,19 @@ //- Dependencies @Dep gpu -@Dep font +@Dep glyph_cache @Dep window //- Api @IncludeC ui_core.h @IncludeC ui_common.h -@IncludeC ui_gpu.h -@IncludeGpu ui_gpu.h +@IncludeC ui_shaders.h +@IncludeGpu ui_shaders.h //- Impl @IncludeC ui_core.c @IncludeC ui_common.c -@IncludeGpu ui_gpu.hlsl +@IncludeGpu ui_shaders.hlsl //- Shaders @VertexShader UI_DRectVS diff --git a/src/ui/ui_common.c b/src/ui/ui_common.c index b0b8bb3b..86aa251a 100644 --- a/src/ui/ui_common.c +++ b/src/ui/ui_common.c @@ -4,7 +4,7 @@ UI_Key UI_BuildLabel(String text) { UI_Key parent = UI_UseTop(Parent); - ResourceKey font = UI_UseTop(Font); + GC_FontKey font = UI_UseTop(Font); f32 font_size = UI_UseTop(FontSize); Vec4 tint = UI_UseTop(Tint); UI_Alignment alignment = UI_UseTop(ChildAlignment); diff --git a/src/ui/ui_core.c b/src/ui/ui_core.c index afc78f27..99ebf52d 100644 --- a/src/ui/ui_core.c +++ b/src/ui/ui_core.c @@ -5,17 +5,14 @@ UI_State UI_state = ZI; void UI_Startup(void) { - /* Prefetch default font */ - ResourceKey default_font = UI_GetDefaultFontResource(); - F_LoadFontAsync(default_font, 16); } //////////////////////////////////////////////////////////// //~ Font helpers -ResourceKey UI_GetDefaultFontResource(void) +GC_FontKey UI_GetDefaultFont(void) { - return ResourceKeyFromStore(&UI_Resources, Lit("font/proggy.ttf")); + return GC_FontKeyFromResource(ResourceKeyFromStore(&UI_Resources, Lit("font/proggy.ttf"))); } //////////////////////////////////////////////////////////// @@ -46,8 +43,8 @@ UI_Key UI_KeyF_(String fmt, ...) UI_Key UI_TransKey(void) { - UI_State *g = &UI_state; - u64 seed = ++g->bframe.transient_key_seed; + UI_Frame *frame = UI_CurrentFrame(); + u64 seed = ++frame->transient_key_seed; UI_Key key = ZI; key.hash = RandU64FromSeed(seed); return key; @@ -77,10 +74,10 @@ UI_Box *UI_BoxFromKey(UI_Key key) String UI_StringF_(String fmt, ...) { - UI_State *g = &UI_state; + UI_Frame *frame = UI_CurrentFrame(); va_list args; va_start(args, fmt); - String str = FormatStringV(g->bframe.cmds_arena, fmt, args); + String str = FormatStringV(frame->arena, fmt, args); va_end(args); return str; } @@ -90,8 +87,8 @@ String UI_StringF_(String fmt, ...) UI_Checkpoint UI_PushCP(UI_Key parent) { - UI_State *g = &UI_state; - UI_Stack *stack = g->bframe.top_stack; + UI_Frame *frame = UI_CurrentFrame(); + UI_Stack *stack = frame->top_stack; stack->top_checkpoint.v += 1; if (parent.hash != 0) { @@ -102,16 +99,16 @@ UI_Checkpoint UI_PushCP(UI_Key parent) void UI_PopCP(UI_Checkpoint cp) { - UI_State *g = &UI_state; - UI_Stack *stack = g->bframe.top_stack; + UI_Frame *frame = UI_CurrentFrame(); + UI_Stack *stack = frame->top_stack; for (UI_StyleKind kind = UI_StyleKind_None; kind < UI_StyleKind_Count; ++kind) { UI_StyleNode *n = stack->style_tops[kind]; while (n && n->checkpoint.v >= cp.v) { UI_StyleNode *next = n->next; - n->next = g->bframe.first_free_style_node; - g->bframe.first_free_style_node = n; + n->next = frame->first_free_style_node; + frame->first_free_style_node = n; stack->style_tops[kind] = next; n = next; } @@ -121,8 +118,8 @@ void UI_PopCP(UI_Checkpoint cp) UI_Checkpoint UI_TopCP(void) { - UI_State *g = &UI_state; - UI_Stack *stack = g->bframe.top_stack; + UI_Frame *frame = UI_CurrentFrame(); + UI_Stack *stack = frame->top_stack; return stack->top_checkpoint; } @@ -131,8 +128,8 @@ UI_Checkpoint UI_TopCP(void) void UI_PushDefaults(void) { - UI_State *g = &UI_state; - UI_Stack *stack = g->bframe.top_stack; + UI_Frame *frame = UI_CurrentFrame(); + UI_Stack *stack = frame->top_stack; UI_Checkpoint checkpoint = stack->top_checkpoint; { for (UI_StyleKind kind = UI_StyleKind_None; kind < UI_StyleKind_Count; ++kind) @@ -144,8 +141,14 @@ void UI_PushDefaults(void) default: break; case UI_StyleKind_Parent: { desc.style.Parent = UI_RootKey; } break; case UI_StyleKind_Width: { desc.style.Width = UI_GROW(1, 0); } break; - case UI_StyleKind_Height: { desc.style.Height = UI_GROW(1, 0); } break; - case UI_StyleKind_Font: { desc.style.Font = UI_GetDefaultFontResource(); } break; + case UI_StyleKind_Height: { desc.style.Height = UI_GROW(1, 0); } + case UI_StyleKind_Font: { desc.style.Font = UI_GetDefaultFont(); } break; + + u8 prefetch[127] = ZI; + for (u64 i = 0; i < countof(prefetch); ++i) + { + prefetch[i] = i; + } case UI_StyleKind_FontSize: { desc.style.FontSize = 16.0f; } break; case UI_StyleKind_Tint: { desc.style.Tint = Color_White; } break; case UI_StyleKind_Tag: { desc.style.Tag = HashFnv64(Fnv64Basis, Lit("root")); } break; @@ -159,8 +162,8 @@ void UI_PushDefaults(void) void UI_PushStyle(UI_StyleDesc desc) { - UI_State *g = &UI_state; - UI_Stack *stack = g->bframe.top_stack; + UI_Frame *frame = UI_CurrentFrame(); + UI_Stack *stack = frame->top_stack; UI_StyleKind kind = desc.style.kind; if (kind >= UI_StyleKind_BeginVirtualStyles_) { @@ -246,15 +249,15 @@ void UI_PushStyle(UI_StyleDesc desc) } else { - n = g->bframe.first_free_style_node; + n = frame->first_free_style_node; if (n) { - g->bframe.first_free_style_node = n->next; + frame->first_free_style_node = n->next; ZeroStruct(n); } else { - n = PushStruct(g->bframe.cmds_arena, UI_StyleNode); + n = PushStruct(frame->arena, UI_StyleNode); } n->next = stack->style_tops[kind]; stack->style_tops[kind] = n; @@ -272,7 +275,7 @@ void UI_PushStyle(UI_StyleDesc desc) case UI_StyleKind_Text: { - n->style.Text = PushString(g->bframe.cmds_arena, desc.style.Text); + n->style.Text = PushString(frame->arena, desc.style.Text); } break; case UI_StyleKind_Tag: @@ -289,8 +292,8 @@ void UI_PushStyle(UI_StyleDesc desc) UI_Style UI_PopStyle(UI_StyleDesc desc) { - UI_State *g = &UI_state; - UI_Stack *stack = g->bframe.top_stack; + UI_Frame *frame = UI_CurrentFrame(); + UI_Stack *stack = frame->top_stack; UI_Style result = ZI; UI_StyleKind kind = desc.style.kind; result.kind = kind; @@ -362,8 +365,8 @@ UI_Style UI_PopStyle(UI_StyleDesc desc) if (desc.use && n->pop_when_used) { stack->style_tops[kind] = n->next; - n->next = g->bframe.first_free_style_node; - g->bframe.first_free_style_node = n; + n->next = frame->first_free_style_node; + frame->first_free_style_node = n; } } return result; @@ -374,8 +377,8 @@ UI_Style UI_PopStyle(UI_StyleDesc desc) UI_Key UI_BuildBoxEx(UI_Key key) { - UI_State *g = &UI_state; - UI_CmdNode *n = PushStruct(g->bframe.cmds_arena, UI_CmdNode); + UI_Frame *frame = UI_CurrentFrame(); + UI_CmdNode *n = PushStruct(frame->arena, UI_CmdNode); n->cmd.kind = UI_CmdKind_BuildBox; { n->cmd.box.key = key; @@ -391,31 +394,31 @@ UI_Key UI_BuildBoxEx(UI_Key key) n->cmd.box.debug_color = UI_UseTop(DebugColor); n->cmd.box.tint = UI_UseTop(Tint); n->cmd.box.border = UI_UseTop(Border); - n->cmd.box.font_resource = UI_UseTop(Font); + n->cmd.box.font = UI_UseTop(Font); n->cmd.box.font_size = UI_UseTop(FontSize); n->cmd.box.rounding = UI_UseTop(Rounding); n->cmd.box.text = UI_UseTop(Text); n->cmd.box.floating_pos = UI_UseTop(FloatingPos); } - ++g->bframe.cmds_count; - SllQueuePush(g->bframe.first_cmd_node, g->bframe.last_cmd_node, n); + ++frame->cmds_count; + SllQueuePush(frame->first_cmd_node, frame->last_cmd_node, n); return key; } -void UI_SetRawTexture(UI_Key key, GPU_Resource *texture, Vec2 uv0, Vec2 uv1) +void UI_SetRawTexture(UI_Key key, Texture2DHandle tex, Vec2 uv0, Vec2 uv1) { - UI_State *g = &UI_state; - UI_CmdNode *n = PushStruct(g->bframe.cmds_arena, UI_CmdNode); + UI_Frame *frame = UI_CurrentFrame(); + UI_CmdNode *n = PushStruct(frame->arena, UI_CmdNode); n->cmd.kind = UI_CmdKind_SetRawTexture; { - n->cmd.set_raw_texture.key = key; - n->cmd.set_raw_texture.texture = texture; - n->cmd.set_raw_texture.uv0 = uv0; - n->cmd.set_raw_texture.uv1 = uv1; + n->cmd.set_raw_texture.key = key; + n->cmd.set_raw_texture.tex = tex; + n->cmd.set_raw_texture.uv0 = uv0; + n->cmd.set_raw_texture.uv1 = uv1; } - ++g->bframe.cmds_count; - SllQueuePush(g->bframe.first_cmd_node, g->bframe.last_cmd_node, n); + ++frame->cmds_count; + SllQueuePush(frame->first_cmd_node, frame->last_cmd_node, n); } //////////////////////////////////////////////////////////// @@ -438,19 +441,9 @@ UI_Report UI_ReportFromKey(UI_Key key) //////////////////////////////////////////////////////////// //~ Begin frame -UI_Frame UI_BeginFrame(UI_FrameFlag frame_flags, Vec4 swapchain_color) +UI_Frame *UI_BeginFrame(UI_FrameFlag frame_flags, Vec4 swapchain_color) { UI_State *g = &UI_state; - UI_Frame result = ZI; - UI_BFrameState old_bframe = g->bframe; - - ////////////////////////////// - //- Wait on swapchain - - if (g->eframe.swapchain) - { - GPU_YieldOnSwapchain(g->eframe.swapchain); - } ////////////////////////////// //- Init persistent state @@ -459,59 +452,76 @@ UI_Frame UI_BeginFrame(UI_FrameFlag frame_flags, Vec4 swapchain_color) { g->box_arena = AcquireArena(Gibi(64)); g->box_bins = PushStructs(g->box_arena, UI_BoxBin, UI_NumBoxLookupBins); + + for (u64 i = 0; i < countof(g->frames); ++i) + { + UI_Frame *frame = &g->frames[i]; + frame->arena = AcquireArena(Gibi(64)); + } } + ////////////////////////////// + //- Begin frame + + u64 last_frame_idx = g->current_frame_idx; + u64 frame_idx = last_frame_idx + 1; + if (frame_idx > countof(g->frames)) + { + frame_idx = 0; + } + UI_Frame *last_frame = &g->frames[last_frame_idx]; + UI_Frame *frame = &g->frames[frame_idx]; + + frame->window_frame = WND_BeginFrame(GPU_Format_R16G16B16A16_Float, WND_BackbufferSizeMode_MatchMonitor); + ////////////////////////////// //- Reset state - /* Zero frame data */ + /* Reset frame data */ { - ZeroStruct(&g->bframe); - g->bframe.cmds_arena = old_bframe.cmds_arena; - g->bframe.transient_key_seed; - } - if (!g->bframe.cmds_arena) - { - g->bframe.cmds_arena = AcquireArena(Gibi(64)); + Arena *old_arena = frame->arena; + Arena *old_rects_arena = frame->arena; + GPU_ArenaHandle old_gpu_arena = frame->gpu_arena; + ZeroStruct(frame); + frame->arena = old_arena; + frame->rects_arena = old_rects_arena; + frame->gpu_arena = old_gpu_arena; } + ResetArena(frame->arena); + ResetArena(frame->rects_arena); + GPU_ResetArenaFromQueue(GPU_QueueKind_Direct, frame->gpu_arena); { i64 now_ns = TimeNs(); - i64 dt_ns = now_ns - old_bframe.time_ns; - g->bframe.time_ns = now_ns; - g->bframe.dt_ns = dt_ns; - g->bframe.tick = old_bframe.tick + 1; + i64 dt_ns = now_ns - last_frame->time_ns; + frame->time_ns = now_ns; + frame->dt_ns = dt_ns; + frame->tick = last_frame->tick + 1; } - ResetArena(g->bframe.cmds_arena); /* Init style stack */ { - g->bframe.top_stack = PushStruct(g->bframe.cmds_arena, UI_Stack); + frame->top_stack = PushStruct(frame->arena, UI_Stack); UI_PushDefaults(); } - g->bframe.frame_flags = frame_flags; - g->bframe.swapchain_color = swapchain_color; - - ////////////////////////////// - //- Begin window frame - - g->bframe.window_frame = WND_BeginFrame(); + frame->frame_flags = frame_flags; + frame->swapchain_color = swapchain_color; ////////////////////////////// //- Process controller events - if (g->eframe.boxes_pre != 0) + if (last_frame->boxes_pre != 0) { - ControllerEventsArray controller_events = g->bframe.window_frame.controller_events; + ControllerEventsArray controller_events = frame->window_frame.controller_events; - g->bframe.cursor_pos = old_bframe.cursor_pos; - f64 dt = SecondsFromNs(g->bframe.dt_ns); + frame->cursor_pos = last_frame->cursor_pos; + f64 dt = SecondsFromNs(frame->dt_ns); f64 inv_dt = 1.0 / dt; /* Locate boxes */ UI_Box *hovered_box = 0; - UI_Box *active_box = UI_BoxFromKey(old_bframe.active_box); + UI_Box *active_box = UI_BoxFromKey(last_frame->active_box); /* Update cursor pos */ for (u64 cev_index = 0; cev_index < controller_events.count; ++cev_index) @@ -519,14 +529,14 @@ UI_Frame UI_BeginFrame(UI_FrameFlag frame_flags, Vec4 swapchain_color) ControllerEvent cev = controller_events.events[cev_index]; if (cev.kind == ControllerEventKind_CursorMove) { - g->bframe.cursor_pos = Vec2FromFields(cev.cursor_pos); + frame->cursor_pos = Vec2FromVec(cev.cursor_pos); } } /* Init box reports */ for (u64 pre_index = g->boxes_count; pre_index-- > 0;) { - UI_Box *box = g->eframe.boxes_pre[pre_index]; + UI_Box *box = last_frame->boxes_pre[pre_index]; if (hovered_box == 0 && box->desc.flags & UI_BoxFlag_Interactable) { b32 is_cursor_in_box = 0; @@ -534,7 +544,7 @@ UI_Frame UI_BeginFrame(UI_FrameFlag frame_flags, Vec4 swapchain_color) /* TODO: More efficient test. This logic is just copied from the renderer's SDF function for now. */ Vec2 p0 = box->p0; Vec2 p1 = box->p1; - Vec2 point = g->bframe.cursor_pos; + Vec2 point = frame->cursor_pos; b32 is_corner = 0; f32 non_corner_edge_dist = MinF32(MinF32(point.x - p0.x, p1.x - point.x), MinF32(point.y - p0.y, p1.y - point.y)); f32 corner_edge_dist = non_corner_edge_dist; @@ -582,7 +592,7 @@ UI_Frame UI_BeginFrame(UI_FrameFlag frame_flags, Vec4 swapchain_color) { ++hovered_box->report.m1_downs; hovered_box->report.m1_held = 1; - hovered_box->report.last_m1_offset = SubVec2(g->bframe.cursor_pos, hovered_box->p0); + hovered_box->report.last_m1_offset = SubVec2(frame->cursor_pos, hovered_box->p0); active_box = hovered_box; } } @@ -615,7 +625,7 @@ UI_Frame UI_BeginFrame(UI_FrameFlag frame_flags, Vec4 swapchain_color) /* Update box hot & active states */ for (u64 pre_index = 0; pre_index < g->boxes_count; ++pre_index) { - UI_Box *box = g->eframe.boxes_pre[pre_index]; + UI_Box *box = last_frame->boxes_pre[pre_index]; UI_Report *report = &box->report; f32 target_hot = box == active_box || (box == hovered_box && (box == active_box || active_box == 0)); f32 target_active = box == active_box; @@ -631,86 +641,62 @@ UI_Frame UI_BeginFrame(UI_FrameFlag frame_flags, Vec4 swapchain_color) report->screen_p1 = box->p1; } - g->bframe.hovered_box = hovered_box ? hovered_box->key : UI_NilKey; - g->bframe.active_box = active_box ? active_box->key : UI_NilKey; + frame->hovered_box = hovered_box ? hovered_box->key : UI_NilKey; + frame->active_box = active_box ? active_box->key : UI_NilKey; } ////////////////////////////// //- Build root box { - UI_SetNext(Width, UI_PIX(g->bframe.window_frame.draw_size.x, 1)); - UI_SetNext(Height, UI_PIX(g->bframe.window_frame.draw_size.y, 1)); + UI_SetNext(Width, UI_PIX(frame->window_frame.draw_size.x, 1)); + UI_SetNext(Height, UI_PIX(frame->window_frame.draw_size.y, 1)); UI_SetNext(Parent, UI_NilKey); UI_BuildBoxEx(UI_RootKey); } - result.window_frame = g->bframe.window_frame; - result.cursor_pos = g->bframe.cursor_pos; - result.hovered_box = g->bframe.hovered_box; - result.active_box = g->bframe.hovered_box; - return result; + return frame; } //////////////////////////////////////////////////////////// //~ Frame helpers -Arena *UI_FrameArena(void) +UI_Frame *UI_CurrentFrame(void) { UI_State *g = &UI_state; - return g->bframe.cmds_arena; + return &g->frames[g->current_frame_idx]; +}; + +Arena *UI_FrameArena(void) +{ + return UI_CurrentFrame()->arena; } Vec2 UI_CursorPos(void) { - UI_State *g = &UI_state; - return g->bframe.cursor_pos; + return UI_CurrentFrame()->cursor_pos; } //////////////////////////////////////////////////////////// //~ End frame -i64 UI_EndFrame(UI_Frame frame) +void UI_EndFrame(UI_Frame *frame) { TempArena scratch = BeginScratchNoConflict(); UI_State *g = &UI_state; - UI_EFrameState old_eframe = g->eframe; - Vec2I32 monitor_size = frame.window_frame.monitor_size; + Vec2I32 monitor_size = frame->window_frame.monitor_size; - Vec2I32 draw_size = frame.window_frame.draw_size; - Rng2 draw_viewport = ZI; - draw_viewport.p1 = Vec2FromFields(draw_size); - - ////////////////////////////// - //- Reset state - - { - ZeroStruct(&g->eframe); - g->eframe.layout_arena = old_eframe.layout_arena; - g->eframe.drects_gpu_arena = old_eframe.drects_gpu_arena; - g->eframe.draw_target = old_eframe.draw_target; - g->eframe.swapchain = old_eframe.swapchain; - g->eframe.gpu_submit_fence_target = old_eframe.gpu_submit_fence_target; - g->eframe.tick = old_eframe.tick; - } - if (!g->eframe.layout_arena) - { - g->eframe.layout_arena = AcquireArena(Gibi(64)); - g->eframe.tex_gpu_arena = GPU_AcquireTextureArena(); - g->eframe.frame_gpu_arena = GPU_AcquireArena(Mebi(16)); - g->eframe.drects_gpu_arena = GPU_AcquireArena(Mebi(16)); - } - ResetArena(g->eframe.layout_arena); + Vec2I32 draw_size = frame->window_frame.draw_size; + Rng3 draw_viewport = RNG3(VEC3(0, 0, 0), VEC3(draw_size.x, draw_size.y, 1)); + Rng2 draw_scissor = RNG2(VEC2(0, 0), VEC2(draw_size.x, draw_size.y)); ////////////////////////////// //- Process commands - /* FIXME: Reset raw texture data */ - g->boxes_count = 0; - for (UI_CmdNode *cmd_node = g->bframe.first_cmd_node; cmd_node; cmd_node = cmd_node->next) + for (UI_CmdNode *cmd_node = frame->first_cmd_node; cmd_node; cmd_node = cmd_node->next) { UI_Cmd cmd = cmd_node->cmd; @@ -724,14 +710,14 @@ i64 UI_EndFrame(UI_Frame frame) key = UI_TransKey(); } - b32 is_root = g->eframe.root_box == 0; + b32 is_root = frame->root_box == 0; UI_Box *parent = 0; if (!is_root) { parent = UI_BoxFromKey(cmd.box.parent); if (!parent) { - parent = g->eframe.root_box; + parent = frame->root_box; } } @@ -781,7 +767,7 @@ i64 UI_EndFrame(UI_Frame frame) box->report = old_box.report; } box->key = key; - box->last_updated_tick = g->eframe.tick; + box->last_updated_tick = frame->tick; /* Update box */ { @@ -795,20 +781,17 @@ i64 UI_EndFrame(UI_Frame frame) ++parent->count; } - /* Prefetch font */ + /* Fetch run */ + box->glyph_run = &GC_NilRun; if (box->desc.text.len > 0) { - box->font = F_LoadFontAsync(box->desc.font_resource, box->desc.font_size); - if (box->font) - { - box->glyph_run = F_RunFromString(g->eframe.layout_arena, box->font, box->desc.text); - } + box->glyph_run = GC_RunFromString(frame->arena, box->desc.font, box->desc.text); } } if (is_root) { - g->eframe.root_box = box; + frame->root_box = box; } } break; @@ -818,7 +801,7 @@ i64 UI_EndFrame(UI_Frame frame) UI_Box *box = UI_BoxFromKey(key); if (box) { - box->raw_texture = cmd.set_raw_texture.texture; + box->raw_texture = cmd.set_raw_texture.tex; box->raw_texture_uv0 = cmd.set_raw_texture.uv0; box->raw_texture_uv1 = cmd.set_raw_texture.uv1; } @@ -831,7 +814,7 @@ i64 UI_EndFrame(UI_Frame frame) //- Prune boxes // { - // u64 cur_tick = g->eframe.tick; + // u64 cur_tick = frame->tick; // UI_BoxIter it = UI_ITER(g->root_box); // UI_Box *box = UI_NextBox(&it); // while (box != 0) @@ -846,10 +829,10 @@ i64 UI_EndFrame(UI_Frame frame) /* Build pre-order & post-order box arrays */ u64 boxes_count = g->boxes_count; - UI_Box **boxes_pre = PushStructsNoZero(g->eframe.layout_arena, UI_Box *, boxes_count); - UI_Box **boxes_post = PushStructsNoZero(g->eframe.layout_arena, UI_Box *, boxes_count); - g->eframe.boxes_pre = boxes_pre; - g->eframe.boxes_post = boxes_post; + UI_Box **boxes_pre = PushStructsNoZero(frame->arena, UI_Box *, boxes_count); + UI_Box **boxes_post = PushStructsNoZero(frame->arena, UI_Box *, boxes_count); + frame->boxes_pre = boxes_pre; + frame->boxes_post = boxes_post; { Struct(BoxNode) { BoxNode *next; b32 visited; UI_Box *box; }; BoxNode *first_dfs = 0; @@ -857,7 +840,7 @@ i64 UI_EndFrame(UI_Frame frame) u64 post_index = 0; { BoxNode *n = PushStruct(scratch.arena, BoxNode); - n->box = g->eframe.root_box; + n->box = frame->root_box; SllStackPush(first_dfs, n); } while (first_dfs) @@ -916,21 +899,15 @@ i64 UI_EndFrame(UI_Frame frame) { /* TODO: Distinguish between baseline alignment & visual alignment */ f32 text_size = 0; - if (box->font) + if (axis == Axis_X) { - if (axis == Axis_X) - { - if (box->glyph_run.count > 0) - { - F_RunRect rr = box->glyph_run.rects[box->glyph_run.count - 1]; - f32 baseline_length = rr.pos + rr.advance; - text_size = baseline_length; - } - } - else - { - text_size = box->font->ascent + box->font->descent; - } + GC_RunRect rr = box->glyph_run->rects[box->glyph_run->count - 1]; + f32 baseline_length = rr.pos + rr.advance; + text_size = baseline_length; + } + else + { + text_size = box->glyph_run->ascent + box->glyph_run->descent; } box->solved_dims[axis] = text_size + (pref_size.v * 2); } @@ -1231,29 +1208,11 @@ i64 UI_EndFrame(UI_Frame frame) ////////////////////////////// //- Render - GPU_CommandList *cl = GPU_OpenCommandList(GPU_QueueKind_Direct); + GPU_CommandListHandle cl = GPU_PrepareCommandList(GPU_QueueKind_Direct); { ////////////////////////////// //- Build render data - /* Acquire render target */ - if (!g->eframe.draw_target || !MatchVec2I32(monitor_size, GPU_Count2D(g->eframe.draw_target))) - { - YieldOnFence(submit_fence, g->eframe.gpu_submit_fence_target); - GPU_ReleaseResource(g->eframe.draw_target, GPU_ReleaseFlag_None); - g->eframe.draw_target = 0; - } - if (!g->eframe.draw_target) - { - GPU_ResourceDesc desc = ZI; - desc.kind = GPU_ResourceKind_Texture2D; - desc.flags = GPU_ResourceFlag_Renderable | GPU_ResourceFlag_Writable; - // desc.texture.format = GPU_Format_R8G8B8A8_Unorm; - desc.texture.format = GPU_Format_R16G16B16A16_Float; - desc.texture.size = VEC3I32(monitor_size.x, monitor_size.y, 1); - g->eframe.draw_target = GPU_AcquireResource(desc); - } - /* Build rect instance data */ for (u64 pre_index = 0; pre_index < boxes_count; ++pre_index) { @@ -1262,12 +1221,12 @@ i64 UI_EndFrame(UI_Frame frame) is_visible = is_visible && (box->desc.tint.w != 0); is_visible = is_visible && (box->p1.x > box->p0.x); is_visible = is_visible && (box->p1.y > box->p0.y); - if (is_visible || AnyBit(g->bframe.frame_flags, UI_FrameFlag_Debug)) + if (is_visible || AnyBit(frame->frame_flags, UI_FrameFlag_Debug)) { + /* Box rect */ { - UI_DRect *rect = PushStruct(g->eframe.rects_arena, UI_DRect); - rect->flags |= UI_DRectFlag_DrawTexture * !(IsGpuPointerNil(box->raw_texture)); + UI_DRect *rect = PushStruct(frame->rects_arena, UI_DRect); rect->p0 = box->p0; rect->p1 = box->p1; rect->tex_uv0 = VEC2(0, 0); @@ -1281,62 +1240,55 @@ i64 UI_EndFrame(UI_Frame frame) rect->tr_rounding = box->rounding_tr; rect->br_rounding = box->rounding_br; rect->bl_rounding = box->rounding_bl; - - /* Texture */ - if (!IsGpuPointerNil(box->raw_texture)) - { - rect->tex = box->raw_texture; - rect->tex_uv0 = box->raw_texture_uv0; - rect->tex_uv1 = box->raw_texture_uv1; - } + rect->tex = box->raw_texture; + rect->tex_uv0 = box->raw_texture_uv0; + rect->tex_uv1 = box->raw_texture_uv1; } /* Text rects */ - if (AnyBit(box->desc.flags, UI_BoxFlag_DrawText) && box->glyph_run.count > 0 && box->font) + GC_Run *raw_run = box->glyph_run; + if (AnyBit(box->desc.flags, UI_BoxFlag_DrawText) && raw_run->loaded) { - Texture2DRid tex_rid = GPU_Texture2DRidFromResource(box->font->texture); - Vec2 inv_font_image_size = VEC2(1.0f / (f32)box->font->image_width, 1.0f / (f32)box->font->image_height); - - F_Run run = box->glyph_run; f32 max_baseline = box->p1.x - box->p0.x; - b32 should_truncate = run.count > 0 && (run.rects[run.count - 1].pos + run.rects[run.count - 1].advance) > max_baseline; + b32 should_truncate = raw_run->count > 0 && (raw_run->rects[raw_run->count - 1].pos + raw_run->rects[raw_run->count - 1].advance) > max_baseline; /* Truncate run */ + GC_RunRect *truncated_rects = raw_run->rects; + u32 truncated_rects_count = raw_run->count; if (should_truncate && !AnyBit(box->desc.flags, UI_BoxFlag_NoTextTruncation)) { /* Get elipses run */ - F_Run trunc_run = F_RunFromString(scratch.arena, box->font, Lit("...")); - if (trunc_run.count > 0) + GC_Run *elipses_run = GC_RunFromString(scratch.arena, box->desc.font, Lit("...")); + if (elipses_run->count > 0) { - max_baseline -= trunc_run.rects[trunc_run.count - 1].pos + trunc_run.rects[trunc_run.count - 1].advance; + max_baseline -= elipses_run->rects[elipses_run->count - 1].pos + elipses_run->rects[elipses_run->count - 1].advance; } /* Subtract glyphs */ - while (run.count > 0) + while (truncated_rects_count > 0) { - F_RunRect rr = run.rects[run.count - 1]; + GC_RunRect rr = raw_run->rects[truncated_rects_count - 1]; if (rr.pos + rr.advance <= max_baseline) { break; } - --run.count; + --truncated_rects_count; } /* Merge trunc rects */ - F_RunRect *new_rects = 0; + /* FIXME: Verify this stil works as expected */ { - new_rects = PushStructsNoZero(scratch.arena, F_RunRect, run.count + trunc_run.count); - CopyStructs(new_rects, run.rects, run.count); - f32 trunc_offset = run.count > 0 ? (run.rects[run.count - 1].pos + run.rects[run.count - 1].advance) : 0; - for (u32 i = 0; i < trunc_run.count; ++i) + truncated_rects_count += elipses_run->count; + truncated_rects = PushStructsNoZero(scratch.arena, GC_RunRect, truncated_rects_count + elipses_run->count); + CopyStructs(truncated_rects, raw_run->rects, raw_run->count); + f32 elipses_offset = truncated_rects_count > 0 ? (truncated_rects[truncated_rects_count - 1].pos + truncated_rects[truncated_rects_count - 1].advance) : 0; + for (u32 i = 0; i < elipses_run->count; ++i) { - F_RunRect *rr = &new_rects[i + run.count]; - *rr = trunc_run.rects[i]; - rr->pos += trunc_offset; + GC_RunRect *rr = &truncated_rects[i + truncated_rects_count]; + *rr = elipses_run->rects[i]; + rr->pos += elipses_offset; } } - run.count += trunc_run.count; - run.rects = new_rects; } UI_AxisAlignment x_alignment = box->desc.child_alignment[Axis_X]; @@ -1347,10 +1299,10 @@ i64 UI_EndFrame(UI_Frame frame) } /* Calculate baseline */ - f32 ascent = box->font->ascent; - f32 descent = box->font->descent; - f32 cap = box->font->cap; - f32 baseline_width = run.count > 0 ? (run.rects[run.count - 1].pos + run.rects[run.count - 1].advance) : 0; + f32 ascent = raw_run->ascent; + f32 descent = raw_run->descent; + f32 cap = raw_run->cap; + f32 baseline_width = truncated_rects_count > 0 ? (truncated_rects[truncated_rects_count - 1].pos + truncated_rects[truncated_rects_count - 1].advance) : 0; f32 baseline_height = ascent + descent; f32 box_width = box->p1.x - box->p0.x; f32 box_height = box->p1.y - box->p0.y; @@ -1394,24 +1346,21 @@ i64 UI_EndFrame(UI_Frame frame) baseline = CeilVec2(baseline); /* Push text rects */ - for (u64 i = 0; i < run.count; ++i) + for (u64 i = 0; i < truncated_rects_count; ++i) { - F_RunRect rr = run.rects[i]; - Vec2 atlas_p0 = Vec2FromFields(rr.atlas_p0); - Vec2 atlas_p1 = Vec2FromFields(rr.atlas_p1); - Vec2 glyph_size = SubVec2(atlas_p1, atlas_p0); + GC_RunRect rr = truncated_rects[i]; + Vec2 glyph_size = rr.size; if (glyph_size.x != 0 || glyph_size.y != 0) { - UI_DRect *rect = PushStruct(g->eframe.rects_arena, UI_DRect); - rect->flags |= UI_DRectFlag_DrawTexture; + UI_DRect *rect = PushStruct(frame->rects_arena, UI_DRect); rect->p0 = AddVec2(baseline, VEC2(rr.pos, 0)); rect->p0 = AddVec2(rect->p0, rr.offset); rect->p1 = AddVec2(rect->p0, glyph_size); rect->debug_lin = LinearFromSrgb(box->desc.debug_color); rect->tint_lin = LinearFromSrgb(box->desc.tint); - rect->tex_uv0 = MulVec2Vec2(atlas_p0, inv_font_image_size); - rect->tex_uv1 = MulVec2Vec2(atlas_p1, inv_font_image_size); - rect->tex = tex_rid; + rect->tex = rr.tex; + rect->tex_uv0 = rr.uv.p0; + rect->tex_uv1 = rr.uv.p1; } } } @@ -1419,88 +1368,68 @@ i64 UI_EndFrame(UI_Frame frame) } ////////////////////////////// - //- Dispatch shaders + //- Push data to GPU - /* Upload transient buffers */ - GPU_Resource *draw_rects_buffer = GPU_UploadTransientBufferFromArena(&g->eframe.draw_rects_tbuff, g->eframe.rects_arena); - u32 draw_rects_count = GPU_GetBufferCount(draw_rects_buffer); + u32 rects_count = ArenaCount(frame->rects_arena, UI_DRect); + UI_DRect *rects = ArenaFirst(frame->rects_arena, UI_DRect); + + GPU_ResourceHandle draw_target = GPU_PushTexture2D( + frame->gpu_arena, + GPU_Format_R16G16B16A16_Float, + monitor_size, + GPU_Layout_DirectQueue_RenderTargetWrite, + .flags = GPU_ResourceFlag_AllowRenderTarget + ); + + StructuredBufferHandle rects_sb = GPU_PushStructuredBufferFromCpu(frame->gpu_arena, cl, rects, rects_count); + + GPU_SetConstant(cl, UI_ShaderConst_TargetWidth, draw_size.x); + GPU_SetConstant(cl, UI_ShaderConst_TargetHeight, draw_size.y); + GPU_SetConstant(cl, UI_ShaderConst_Rects, rects_sb); + GPU_SetConstant(cl, UI_ShaderConst_Sampler, GPU_GetSharedPointSampler()); + + ////////////////////////////// + //- Dispatch shaders { //- Prep rect pass { - GPU_TransitionToRenderable(cl, g->eframe.draw_target, 0); - GPU_ClearRenderable(cl, g->eframe.draw_target); + GPU_DumbMemoryLayoutSync(cl, draw_target, GPU_Layout_DirectQueue_RenderTargetWrite); + GPU_ClearRenderTarget(cl, draw_target, VEC4(0, 0, 0, 0)); } //- Rect pass - if (draw_rects_count > 0) + if (rects_count > 0) { - GPU_Viewport viewport = GPU_ViewportFromRect(draw_viewport); - GPU_Scissor scissor = GPU_ScissorFromRect(draw_viewport); - /* Render rects */ - { - UI_DRectSig sig = ZI; - sig.target_size = draw_size; - sig.sampler = GPU_SamplerStateRidFromResource(GPU_GetCommonPointSampler()); - sig.rects = GPU_StructuredBufferRidFromResource(draw_rects_buffer); - GPU_Rasterize(cl, - &sig, - UI_DRectVS, UI_DRectPS, - 1, - viewport, - scissor, - draw_rects_count, - GPU_GetCommonQuadIndices(), - GPU_RasterizeMode_TriangleList); - } + GPU_Rasterize(cl, + UI_DRectVS, UI_DRectPS, + 1, GPU_GetSharedQuadIndices(), + 1, &draw_target, + draw_viewport, draw_scissor, + GPU_RasterMode_TriangleList); /* Render rect wireframes */ - if (AnyBit(g->bframe.frame_flags, UI_FrameFlag_Debug)) + if (AnyBit(frame->frame_flags, UI_FrameFlag_Debug)) { - UI_DRectSig sig = ZI; - sig.target_size = draw_size; - sig.sampler = GPU_SamplerStateRidFromResource(GPU_GetCommonPointSampler()); - sig.rects = GPU_StructuredBufferRidFromResource(draw_rects_buffer); - sig.debug_enabled = 1; + GPU_SetConstant(cl, UI_ShaderConst_DebugDraw, 1); GPU_Rasterize(cl, - &sig, UI_DRectVS, UI_DRectPS, - 1, - viewport, - scissor, - draw_rects_count, - GPU_GetCommonQuadIndices(), - GPU_RasterizeMode_WireTriangleList); + 1, GPU_GetSharedQuadIndices(), + 1, &draw_target, + draw_viewport, draw_scissor, + GPU_RasterMode_WireTriangleList); } } } - - /* Reset */ - GPU_ResetArena(cl, g->eframe.frame_gpu_arena); - GPU_ResetArena(cl, g->eframe.drects_gpu_arena); } - GPU_CloseCommandList(cl); + GPU_CommitCommandList(cl); ////////////////////////////// - //- Present & end frame + //- End frame - { - Vec2I32 backbuffer_size = monitor_size; - if (!g->eframe.swapchain) - { - g->eframe.swapchain = GPU_AcquireSwapchain(frame.window_frame.window_handle, GPU_Format_R16G16B16A16_Float, backbuffer_size); - } - Vec2I32 dst_p0 = VEC2I32(0, 0); - Vec2I32 dst_p1 = VEC2I32(0, 0); - Vec2I32 src_p0 = VEC2I32(0, 0); - Vec2I32 src_p1 = draw_size; - GPU_PresentSwapchain(g->eframe.swapchain, g->eframe.draw_target, AnyBit(g->bframe.frame_flags, UI_FrameFlag_Vsync), backbuffer_size, dst_p0, dst_p1, src_p0, src_p1, LinearFromSrgb(g->bframe.swapchain_color)); - } - WND_EndFrame(frame.window_frame); - - ++g->eframe.tick; + WND_EndFrame(frame->window_frame, VSYNC); EndScratch(scratch); } diff --git a/src/ui/ui_core.h b/src/ui/ui_core.h index e5054232..86f20bb3 100644 --- a/src/ui/ui_core.h +++ b/src/ui/ui_core.h @@ -106,10 +106,10 @@ Enum(UI_BoxFlag) X(Border, f32) \ X(FloatingPos, Vec2) \ X(Rounding, UI_Round) \ - X(Font, ResourceKey) \ + X(Font, GC_FontKey) \ X(FontSize, u32) \ X(Text, String) \ - X(BackgroundTexture, GpuPointer) \ + X(BackgroundTexture, Texture2DHandle) \ X(BackgroundTextureUv0, Vec2) \ X(BackgroundTextureUv1, Vec2) \ /* --------------------------------------- */ \ @@ -217,7 +217,7 @@ Struct(UI_BoxDesc) f32 border; Vec2 floating_pos; String text; - ResourceKey font_resource; + GC_FontKey font; f32 font_size; Axis child_layout_axis; UI_AxisAlignment child_alignment[Axis_CountXY]; @@ -232,7 +232,7 @@ Struct(UI_Cmd) struct { UI_Key key; - GPU_Resource *texture; + Texture2DHandle tex; Vec2 uv0; Vec2 uv1; } set_raw_texture; @@ -268,7 +268,7 @@ Struct(UI_Box) //- Cmd data UI_BoxDesc desc; - GpuPointer raw_texture; + Texture2DHandle raw_texture; Vec2 raw_texture_uv0; Vec2 raw_texture_uv1; @@ -277,8 +277,7 @@ Struct(UI_Box) u64 post_index; //- Layout data - F_Run glyph_run; - F_Font *font; + GC_Run *glyph_run; f32 layout_cursor; f32 solved_dims[Axis_CountXY]; f32 final_children_size_accum[Axis_CountXY]; @@ -299,7 +298,9 @@ Struct(UI_BoxBin) }; //////////////////////////////////////////////////////////// -//~ Frame types +//~ State types + +#define UI_NumBoxLookupBins 16384 Enum(UI_FrameFlag) { @@ -310,82 +311,51 @@ Enum(UI_FrameFlag) Struct(UI_Frame) { + Arena *arena; + Arena *rects_arena; + GPU_ArenaHandle gpu_arena; + WND_Frame window_frame; + GPU_ResourceHandle backbuffer; + + u64 transient_key_seed; + + /* Time */ + u64 tick; + i64 time_ns; + i64 dt_ns; + + /* Control */ Vec2 cursor_pos; UI_Key hovered_box; UI_Key active_box; + + /* Cmds */ + Vec4 swapchain_color; + UI_FrameFlag frame_flags; + UI_CmdNode *first_cmd_node; + UI_CmdNode *last_cmd_node; + u64 cmds_count; + + /* Style stack */ + UI_Stack *top_stack; + UI_StyleNode *first_free_style_node; + + /* Layout */ + UI_Box *root_box; + UI_Box **boxes_pre; + UI_Box **boxes_post; }; -//////////////////////////////////////////////////////////// -//~ State types - -#define UI_NumBoxLookupBins 16384 - -Struct(UI_BFrameState); -Struct(UI_EFrameState); - Struct(UI_State) { - ////////////////////////////// - //- Persistent sate - Arena *box_arena; UI_BoxBin *box_bins; u64 boxes_count; UI_Box *first_free_box; - ////////////////////////////// - //- Frame-begin state - - struct UI_BFrameState - { - Arena *cmds_arena; - WND_Frame window_frame; - - u64 transient_key_seed; - - /* Time */ - u64 tick; - i64 time_ns; - i64 dt_ns; - - /* Control */ - Vec2 cursor_pos; - UI_Key hovered_box; - UI_Key active_box; - - /* Cmds */ - Vec4 swapchain_color; - UI_FrameFlag frame_flags; - UI_CmdNode *first_cmd_node; - UI_CmdNode *last_cmd_node; - u64 cmds_count; - - /* Style stack */ - UI_Stack *top_stack; - UI_StyleNode *first_free_style_node; - } bframe; - - ////////////////////////////// - //- Frame-end state - - struct UI_EFrameState - { - Arena *layout_arena; - GPU_Arena *frame_gpu_arena; - GPU_Arena *drects_gpu_arena; - u64 tick; - - /* Render */ - GpuPointer draw_target; - GPU_Swapchain *swapchain; - i64 gpu_submit_fence_target; - - /* Layout */ - UI_Box *root_box; - UI_Box **boxes_pre; - UI_Box **boxes_post; - } eframe; + u64 current_frame_idx; + UI_Frame frames[2]; } extern UI_state; //////////////////////////////////////////////////////////// @@ -396,7 +366,7 @@ void UI_Startup(void); //////////////////////////////////////////////////////////// //~ Font helpers -ResourceKey UI_GetDefaultFontResource(void); +GC_FontKey UI_GetDefaultFont(void); //////////////////////////////////////////////////////////// //~ Key helpers @@ -472,7 +442,7 @@ UI_Style UI_PopStyle(UI_StyleDesc desc); UI_Key UI_BuildBoxEx(UI_Key key); #define UI_BuildBox() UI_BuildBoxEx(UI_TransKey()) -void UI_SetRawTexture(UI_Key key, GPU_Resource *texture, Vec2 uv0, Vec2 uv1); +void UI_SetRawTexture(UI_Key key, Texture2DHandle tex, Vec2 uv0, Vec2 uv1); //////////////////////////////////////////////////////////// //~ Report @@ -482,15 +452,16 @@ UI_Report UI_ReportFromKey(UI_Key key); //////////////////////////////////////////////////////////// //~ Begin frame -UI_Frame UI_BeginFrame(UI_FrameFlag frame_flags, Vec4 swapchain_color); +UI_Frame *UI_BeginFrame(UI_FrameFlag frame_flags, Vec4 swapchain_color); //////////////////////////////////////////////////////////// //~ Frame helpers +UI_Frame *UI_CurrentFrame(void); Arena *UI_FrameArena(void); Vec2 UI_CursorPos(void); //////////////////////////////////////////////////////////// //~ End frame -void UI_EndFrame(UI_Frame frame); +void UI_EndFrame(UI_Frame *frame); diff --git a/src/ui/ui_gpu.h b/src/ui/ui_gpu.h deleted file mode 100644 index 344208e9..00000000 --- a/src/ui/ui_gpu.h +++ /dev/null @@ -1,43 +0,0 @@ -//////////////////////////////////////////////////////////// -//~ Rect shader types - -Struct(UI_DRectSig) -{ - /* ----------------------------------------------------- */ - Vec2I32 target_size; /* 02 consts */ - StructuredBufferRid rects; /* 01 consts */ - SamplerStateRid sampler; /* 01 consts */ - /* ----------------------------------------------------- */ - b32 debug_enabled; /* 01 consts */ - u32 _pad0; /* 01 consts (padding) */ - u32 _pad1; /* 01 consts (padding) */ - u32 _pad2; /* 01 consts (padding) */ - /* ----------------------------------------------------- */ -}; -AssertRootConst(UI_DRectSig, 8); - -Enum(UI_DRectFlag) -{ - UI_DRectFlag_None = 0, - UI_DRectFlag_DrawTexture = (1 << 0), -}; - -Struct(UI_DRect) -{ - UI_DRectFlag flags; - Vec2 p0; - Vec2 p1; - Vec4 tint_lin; - Vec4 background_lin; - Vec4 border_lin; - Vec4 debug_lin; - f32 border; - Vec2 tex_uv0; - Vec2 tex_uv1; - Texture2DRid tex; - - f32 tl_rounding; - f32 tr_rounding; - f32 br_rounding; - f32 bl_rounding; -}; diff --git a/src/ui/ui_shaders.h b/src/ui/ui_shaders.h new file mode 100644 index 00000000..85b9715f --- /dev/null +++ b/src/ui/ui_shaders.h @@ -0,0 +1,27 @@ +//////////////////////////////////////////////////////////// +//~ Rect types + +ShaderConstant(i32, UI_ShaderConst_TargetWidth, 0); +ShaderConstant(i32, UI_ShaderConst_TargetHeight, 1); +ShaderConstant(StructuredBufferHandle, UI_ShaderConst_Rects, 2); +ShaderConstant(SamplerStateHandle, UI_ShaderConst_Sampler, 3); +ShaderConstant(b32, UI_ShaderConst_DebugDraw, 4); + +Struct(UI_DRect) +{ + Vec2 p0; + Vec2 p1; + Vec4 tint_lin; + Vec4 background_lin; + Vec4 border_lin; + Vec4 debug_lin; + f32 border; + Vec2 tex_uv0; + Vec2 tex_uv1; + Texture2DHandle tex; + + f32 tl_rounding; + f32 tr_rounding; + f32 br_rounding; + f32 bl_rounding; +}; diff --git a/src/ui/ui_gpu.hlsl b/src/ui/ui_shaders.hlsl similarity index 84% rename from src/ui/ui_gpu.hlsl rename to src/ui/ui_shaders.hlsl index 5282318a..9e9807e5 100644 --- a/src/ui/ui_gpu.hlsl +++ b/src/ui/ui_shaders.hlsl @@ -1,7 +1,5 @@ -ConstantBuffer UI_drect_sig : register (b0); - //////////////////////////////////////////////////////////// -//~ Rect shader +//~ Rect Struct(UI_DRectPSInput) { @@ -25,8 +23,7 @@ Struct(UI_DRectPSOutput) VertexShader(UI_DRectVS, UI_DRectPSInput) { - ConstantBuffer sig = UI_drect_sig; - StructuredBuffer rects = UniformResourceFromRid(sig.rects); + StructuredBuffer rects = StructuredBufferFromHandle(UI_ShaderConst_Rects); UI_DRect rect = rects[SV_InstanceID]; Vec2 rect_uv = RectUvFromVertexId(SV_VertexID); @@ -34,7 +31,7 @@ VertexShader(UI_DRectVS, UI_DRectPSInput) Vec2 target_pos = lerp(rect.p0, rect.p1, rect_uv); UI_DRectPSInput result; - result.sv_position = Vec4(NdcFromPos(target_pos, sig.target_size).xy, 0, 1); + result.sv_position = Vec4(NdcFromPos(target_pos, Vec2(UI_ShaderConst_TargetWidth, UI_ShaderConst_TargetHeight).xy), 0, 1); result.background_lin = rect.background_lin; result.border_lin = rect.border_lin; result.tint_lin = rect.tint_lin; @@ -50,8 +47,9 @@ VertexShader(UI_DRectVS, UI_DRectPSInput) PixelShader(UI_DRectPS, UI_DRectPSOutput, UI_DRectPSInput input) { - ConstantBuffer sig = UI_drect_sig; - StructuredBuffer rects = UniformResourceFromRid(sig.rects); + StructuredBuffer rects = StructuredBufferFromHandle(UI_ShaderConst_Rects); + SamplerState sampler = SamplerStateFromHandle(UI_ShaderConst_Sampler); + UI_DRect rect = rects[input.rect_idx]; Vec2 p = input.sv_position.xy; @@ -108,10 +106,9 @@ PixelShader(UI_DRectPS, UI_DRectPSOutput, UI_DRectPSInput input) { background_color = border_color; } - else if (rect.flags & UI_DRectFlag_DrawTexture) + else if (!IsGpuHandleNil(rect.tex)) { - SamplerState sampler = UniformSamplerFromRid(sig.sampler); - Texture2D tex = NonUniformResourceFromRid(rect.tex); + Texture2D tex = Texture2DFromHandle(rect.tex); background_color = tex.Sample(sampler, input.tex_uv); } else @@ -126,7 +123,7 @@ PixelShader(UI_DRectPS, UI_DRectPSOutput, UI_DRectPSInput input) final_color *= input.tint_lin; /* Debug color */ - if (sig.debug_enabled) + if (UI_ShaderConst_DebugDraw) { final_color = rect.debug_lin; } diff --git a/src/window/window.h b/src/window/window.h index 16346b68..18e62ba7 100644 --- a/src/window/window.h +++ b/src/window/window.h @@ -29,9 +29,16 @@ Struct(WND_Cmd) //////////////////////////////////////////////////////////// //~ Frame types +Enum(WND_BackbufferSizeMode) +{ + WND_BackbufferSizeMode_MatchWindow, + WND_BackbufferSizeMode_MatchMonitor, +}; + Struct(WND_Frame) { WND_Handle window; + GPU_ResourceHandle backbuffer; ControllerEventsArray controller_events; @@ -51,11 +58,6 @@ Struct(WND_Frame) void WND_Startup(void); -//////////////////////////////////////////////////////////// -//~ @hookdecl Helpers - -u64 WND_OsHandleFromWindow(WND_Handle window); - //////////////////////////////////////////////////////////// //~ @hookdecl Command @@ -65,5 +67,5 @@ void WND_PushCmd_(WND_Frame frame, WND_Cmd desc); //////////////////////////////////////////////////////////// //~ @hookdecl Frame -WND_Frame WND_BeginFrame(void); -void WND_EndFrame(WND_Frame frame); +WND_Frame WND_BeginFrame(GPU_Format backbuffer_format, WND_BackbufferSizeMode backbuffer_size_mode); +void WND_EndFrame(WND_Frame frame, i32 vsync); diff --git a/src/window/window.lay b/src/window/window.lay index 8daddfc9..af41e667 100644 --- a/src/window/window.lay +++ b/src/window/window.lay @@ -1,9 +1,13 @@ @Layer window +//- Dependencies +@Dep gpu + //- Api @IncludeC window.h //- Win32 impl @DefaultWindowsImpl window_win32 +//- Startup @Startup WND_Startup diff --git a/src/window/window_win32/window_win32.c b/src/window/window_win32/window_win32.c index ad15dda0..b200cd76 100644 --- a/src/window/window_win32/window_win32.c +++ b/src/window/window_win32/window_win32.c @@ -108,7 +108,6 @@ void WND_W32_ProcessMessagesForever(WaveLaneCtx *lane) window->w2u_events_arena = AcquireArena(Gibi(64)); //- Initialize hwnd - HWND hwnd = 0; { /* * From martins (https://gist.github.com/mmozeiko/5e727f845db182d468a34d524508ad5f#file-win32_d3d11-c-L66-L70): @@ -120,7 +119,7 @@ void WND_W32_ProcessMessagesForever(WaveLaneCtx *lane) DWORD exstyle = WS_EX_APPWINDOW | WS_EX_NOREDIRECTIONBITMAP; /* TODO: Check for hwnd success */ - hwnd = CreateWindowExW( + window->hwnd = CreateWindowExW( exstyle, g->window_class.lpszClassName, L"", @@ -137,13 +136,17 @@ void WND_W32_ProcessMessagesForever(WaveLaneCtx *lane) /* Dark mode */ BOOL dark_mode = 1; - DwmSetWindowAttribute(hwnd, DWMWA_USE_IMMERSIVE_DARK_MODE, (LPCVOID)&dark_mode, sizeof(dark_mode)); + DwmSetWindowAttribute(window->hwnd, DWMWA_USE_IMMERSIVE_DARK_MODE, (LPCVOID)&dark_mode, sizeof(dark_mode)); /* Set window as userdata */ /* FIXME: Necessary? */ - SetWindowLongPtrW(hwnd, GWLP_USERDATA, (LONG_PTR)window); + SetWindowLongPtrW(window->hwnd, GWLP_USERDATA, (LONG_PTR)window); + } + + //- Acquire swapchain + { + window->swapchain = GPU_AcquireSwapchain((u64)window->hwnd); } - window->hwnd = hwnd; //- Begin processing messages Atomic32Set(&window->is_ready, 1); @@ -382,15 +385,6 @@ LRESULT CALLBACK WND_W32_WindowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM l return result; } -//////////////////////////////////////////////////////////// -//~ @hookimpl Helpers - -u64 WND_OsHandleFromWindow(WND_Handle handle) -{ - WND_W32_Window *window = WND_W32_WindowFromHandle(handle); - return (u64)window->hwnd; -} - //////////////////////////////////////////////////////////// //~ @hookimpl Command @@ -409,7 +403,7 @@ void WND_PushCmd_(WND_Frame frame, WND_Cmd desc) //////////////////////////////////////////////////////////// //~ @hookimpl Frame -WND_Frame WND_BeginFrame(void) +WND_Frame WND_BeginFrame(GPU_Format backbuffer_format, WND_BackbufferSizeMode backbuffer_size_mode) { WND_W32_SharedState *g = &WND_W32_shared_state; WND_W32_Window *window = &g->window; @@ -422,6 +416,41 @@ WND_Frame WND_BeginFrame(void) HWND hwnd = window->hwnd; result.window.v = (u64)window; + /* Grab monitor info */ + RECT monitor_rect = ZI; + { + MONITORINFO monitor_info = { .cbSize = sizeof(monitor_info) }; + GetMonitorInfo(MonitorFromWindow(hwnd, MONITOR_DEFAULTTOPRIMARY), &monitor_info); + monitor_rect = monitor_info.rcMonitor; + } + result.monitor_size = VEC2I32(monitor_rect.right - monitor_rect.left, monitor_rect.bottom - monitor_rect.top); + result.monitor_size.x = MaxI32(result.monitor_size.x, 1); + result.monitor_size.y = MaxI32(result.monitor_size.y, 1); + + /* Client rect */ + RECT client_rect = ZI; + GetClientRect(hwnd, (LPRECT)&client_rect); + + /* Screen rect */ + RECT screen_rect = client_rect; + ClientToScreen(hwnd, (LPPOINT)&screen_rect.left); + ClientToScreen(hwnd, (LPPOINT)&screen_rect.right); + result.draw_size = VEC2I32(screen_rect.right - screen_rect.left, screen_rect.bottom - screen_rect.top); + result.draw_size.x = MaxI32(result.draw_size.x, 1); + result.draw_size.y = MaxI32(result.draw_size.y, 1); + + /* Prepare backbuffer */ + Vec2I32 backbuffer_size = ZI; + if (backbuffer_size_mode == WND_BackbufferSizeMode_MatchWindow) + { + backbuffer_size = result.draw_size; + } + else if (backbuffer_size_mode == WND_BackbufferSizeMode_MatchMonitor) + { + backbuffer_size = result.monitor_size; + } + result.backbuffer = GPU_PrepareBackbuffer(window->swapchain, backbuffer_format, backbuffer_size); + /* Reset per-frame data */ if (!window->frame_arena) { @@ -444,29 +473,6 @@ WND_Frame WND_BeginFrame(void) UnlockTicketMutex(&window->w2u_tm); } - /* Grab monitor info */ - RECT monitor_rect = ZI; - { - MONITORINFO monitor_info = { .cbSize = sizeof(monitor_info) }; - GetMonitorInfo(MonitorFromWindow(hwnd, MONITOR_DEFAULTTOPRIMARY), &monitor_info); - monitor_rect = monitor_info.rcMonitor; - } - result.monitor_size = VEC2I32(monitor_rect.right - monitor_rect.left, monitor_rect.bottom - monitor_rect.top); - result.monitor_size.x = MaxI32(result.monitor_size.x ,1); - result.monitor_size.y = MaxI32(result.monitor_size.y ,1); - - /* Client rect */ - RECT client_rect = ZI; - GetClientRect(hwnd, (LPRECT)&client_rect); - - /* Screen rect */ - RECT screen_rect = client_rect; - ClientToScreen(hwnd, (LPPOINT)&screen_rect.left); - ClientToScreen(hwnd, (LPPOINT)&screen_rect.right); - result.draw_size = VEC2I32(screen_rect.right - screen_rect.left, screen_rect.bottom - screen_rect.top); - result.draw_size.x = MaxI32(result.draw_size.x ,1); - result.draw_size.y = MaxI32(result.draw_size.y ,1); - /* Minimized / maximized / fullscreen */ DWORD style = (DWORD)GetWindowLongPtr(hwnd, GWL_STYLE); DWORD ex_style = (DWORD)GetWindowLongPtr(hwnd, GWL_EXSTYLE); @@ -518,7 +524,7 @@ WND_Frame WND_BeginFrame(void) return result; } -void WND_EndFrame(WND_Frame frame) +void WND_EndFrame(WND_Frame frame, i32 vsync) { TempArena scratch = BeginScratchNoConflict(); WND_W32_SharedState *g = &WND_W32_shared_state; @@ -656,6 +662,9 @@ void WND_EndFrame(WND_Frame frame) BringWindowToTop(hwnd); } + /* Commit backbuffer */ + GPU_CommitBackbuffer(frame.backbuffer, vsync); + ++window->frame_gen; EndScratch(scratch); } diff --git a/src/window/window_win32/window_win32.h b/src/window/window_win32/window_win32.h index 14d10402..4b748419 100644 --- a/src/window/window_win32/window_win32.h +++ b/src/window/window_win32/window_win32.h @@ -4,9 +4,11 @@ Struct(WND_W32_Window) { HWND hwnd; + GPU_SwapchainHandle swapchain; + GPU_ResourceHandle backbuffer; Atomic32 is_ready; - /* Window state */ + /* Window proc state */ u16 previous_utf16_high_surrogate; /* User state */ @@ -18,8 +20,7 @@ Struct(WND_W32_Window) b32 is_fullscreen; RECT fullscreen_restore_rect; - /* Window -> User */ - /* Reads outside of window thread must lock */ + /* Window proc -> User */ TicketMutex w2u_tm; Arena *w2u_events_arena; };