From e9e8dcc04d1d059dbb676ab1b090feb87be0a893 Mon Sep 17 00:00:00 2001 From: jacob Date: Thu, 11 Dec 2025 19:35:11 -0600 Subject: [PATCH] glyph cache progress --- src/base/base_arena.c | 92 +++++---------- src/base/base_buddy.c | 192 +++++++++++++++--------------- src/base/base_buddy.h | 10 +- src/base/base_math.c | 37 ++++++ src/base/base_math.h | 9 ++ src/base/base_shader.gh | 17 ++- src/config.h | 2 +- src/glyph_cache/glyph_cache.c | 127 +++++++++++++++++--- src/glyph_cache/glyph_cache.h | 84 +++++++++++--- src/gpu/gpu_dx12/gpu_dx12_core.c | 1 + src/pp/pp_vis/pp_vis_core.c | 10 +- src/pp/pp_vis/pp_vis_shaders.g | 4 +- src/pp/pp_vis/pp_vis_shaders.gh | 4 +- src/proto/proto_shaders.g | 4 +- src/ui/ui_core.c | 193 ++++++++++++++----------------- src/ui/ui_core.h | 71 ++++++------ src/ui/ui_shaders.cgh | 10 +- src/ui/ui_shaders.g | 10 +- src/ui/ui_shaders.gh | 2 +- 19 files changed, 516 insertions(+), 363 deletions(-) diff --git a/src/base/base_arena.c b/src/base/base_arena.c index 17d315e5..30b9270f 100644 --- a/src/base/base_arena.c +++ b/src/base/base_arena.c @@ -94,46 +94,36 @@ void *PushBytesNoZero(Arena *arena, u64 size, u64 align) { Assert(align > 0); - void *result = 0; u8 *base = ArenaFirst(arena, u8); - /* Check to avoid aligning when size = 0 */ - if (size > 0) - { - u64 aligned_start_pos = (arena->pos + (align - 1)); - aligned_start_pos -= aligned_start_pos % align; + u64 start_pos = AlignU64(arena->pos, align); + u64 end_pos = start_pos + size; - u64 new_pos = aligned_start_pos + size; - if (new_pos > arena->committed) + /* Commit new block(s) */ + if (end_pos > arena->committed) + { + u64 blocks_needed = (end_pos - arena->committed + ArenaBlockSize - 1) / ArenaBlockSize; + u64 commit_bytes = blocks_needed * ArenaBlockSize; + u64 new_capacity = arena->committed + commit_bytes; + if (new_capacity > arena->reserved) { - /* Commit new block(s) */ - u64 blocks_needed = (new_pos - arena->committed + ArenaBlockSize - 1) / ArenaBlockSize; - u64 commit_bytes = blocks_needed * ArenaBlockSize; - u64 new_capacity = arena->committed + commit_bytes; - if (new_capacity > arena->reserved) - { - /* Hard fail if we overflow reserved memory for now */ - Panic(Lit("Failed to commit new memory block: Overflow of reserved memory")); - } - void *commit_address = base + arena->committed; - if (!CommitMemory(commit_address, commit_bytes)) - { - /* Hard fail on memory allocation failure for now */ - Panic(Lit("Failed to commit new memory block: System may be out of memory")); - } - arena->committed += commit_bytes; - AddGstat(GSTAT_MEMORY_COMMITTED, commit_bytes); - AsanPoison(commit_address, commit_bytes); + /* Hard fail if we overflow reserved memory for now */ + Panic(Lit("Failed to commit new memory block: Overflow of reserved memory")); } + void *commit_address = base + arena->committed; + if (!CommitMemory(commit_address, commit_bytes)) + { + /* Hard fail on memory allocation failure for now */ + Panic(Lit("Failed to commit new memory block: System may be out of memory")); + } + arena->committed += commit_bytes; + AddGstat(GSTAT_MEMORY_COMMITTED, commit_bytes); + AsanPoison(commit_address, commit_bytes); + } - result = base + aligned_start_pos; - AsanUnpoison(result, new_pos - aligned_start_pos); - arena->pos = new_pos; - } - else - { - result = base + arena->pos; - } + void *result = base + start_pos; + AsanUnpoison(result, end_pos - start_pos); + arena->pos = end_pos; return result; } @@ -147,28 +137,8 @@ void *PushBytes(Arena *arena, u64 size, u64 align) void *PushAlign(Arena *arena, u64 align) { - void *result = 0; - if (align > 0) - { - u64 aligned_start_pos = (arena->pos + (align - 1)); - aligned_start_pos -= aligned_start_pos % align; - u64 align_bytes = aligned_start_pos - (u64)arena->pos; - if (align_bytes > 0) - { - result = (void *)PushStructsNoZero(arena, u8, align_bytes); - } - else - { - result = (void *)(ArenaFirst(arena, u8) + arena->pos); - } - } - else - { - /* 0 alignment */ - Assert(0); - result = (void *)(ArenaFirst(arena, u8) + arena->pos); - } - return result; + u64 push_count = AlignU64(arena->pos, align) - arena->pos; + return PushStructsNoZero(arena, u8, push_count); } void PopTo(Arena *arena, u64 pos) @@ -198,17 +168,13 @@ void PopBytes(Arena *arena, u64 size, void *copy_dst) void *ArenaFirst_(Arena *arena, u64 align) { - u64 aligned_start_pos = align - 1; - aligned_start_pos -= aligned_start_pos % align; - void *result = ((u8 *)arena + ArenaHeaderSize) + aligned_start_pos; + void *result = (void *)AlignU64((u64)arena + ArenaHeaderSize, align); return result; } void *ArenaNext_(Arena *arena, u64 align) { - u64 aligned_start_pos = (arena->pos + (align - 1)); - aligned_start_pos -= aligned_start_pos % align; - void *result = ((u8 *)arena + ArenaHeaderSize) + aligned_start_pos; + void *result = (void *)AlignU64((u64)arena + ArenaHeaderSize + arena->pos, align); return result; } @@ -233,7 +199,7 @@ void EndTempArena(TempArena temp) TempArena BeginScratch(Arena *potential_conflict) { - /* This function is currently hard-coded to search through 2 scratch arenas */ + /* This function is currently hard-coded for 2 thread-local scratch arenas */ StaticAssert(ScratchArenasPerCtx == 2); /* Use `BeginScratchNoConflict` if no conflicts are present */ diff --git a/src/base/base_buddy.c b/src/base/base_buddy.c index dc261098..d05f1c08 100644 --- a/src/base/base_buddy.c +++ b/src/base/base_buddy.c @@ -1,7 +1,7 @@ /* TODO: Elminiate meta arena. Just store levels in first 4096 bytes of buddy arena, and then zone header data at the beginning of each allocation. */ //////////////////////////////////////////////////////////// -//~ Buddy ctx +//~ Buddy context BuddyCtx *AcquireBuddyCtx(u64 reserve) { @@ -31,105 +31,7 @@ void ReleaseBuddyCtx(BuddyCtx *ctx) } //////////////////////////////////////////////////////////// -//~ Block acquire / release - -BuddyBlock *AcquireBuddyBlock(BuddyCtx *ctx, u64 size) -{ - if (size > 0x00FFFFFFFFFFFFFFULL) - { - /* TODO: Error */ - Assert(0); - } - - /* TODO: Minimum block size */ - - /* TODO: Faster MSB calculation */ - - u64 desired_block_size = 1; - u64 desired_level_tier = 0; - while (desired_block_size < size && desired_level_tier < 64) - { - desired_block_size <<= 1; - ++desired_level_tier; - } - - BuddyBlock *block = GetUnusedBuddyBlock(ctx, &ctx->levels[desired_level_tier]); - - return block; -} - -void ReleaseBuddyBlock(BuddyBlock *block) -{ - block->is_used = 0; - BuddyLevel *level = block->level; - BuddyBlock *parent = block->parent; - BuddyBlock *sibling = block->sibling; - if (!sibling->is_used && parent != 0) - { - /* Merge siblings */ - BuddyCtx *ctx = level->ctx; - PopBuddyBlock(ctx, level, block); - PopBuddyBlock(ctx, level, sibling); - /* Release parent */ - ReleaseBuddyBlock(parent); - } - else - { - if (level->first_unused_block) - { - block->next = level->first_unused_block; - level->first_unused_block->prev = block; - } - level->first_unused_block = block; - } -} - -//////////////////////////////////////////////////////////// -//~ Block push / pop - -//- Push -BuddyBlock *PushBuddyBlock(BuddyCtx *ctx) -{ - BuddyBlock *block; - if (ctx->first_free_block) - { - block = ctx->first_free_block; - ctx->first_free_block = block->next; - } - else - { - block = PushStructNoZero(ctx->meta_arena, BuddyBlock); - } - ZeroStruct(block); - return block; -} - -//- Pop -void PopBuddyBlock(BuddyCtx *ctx, BuddyLevel *level, BuddyBlock *block) -{ - /* Remove from unused list */ - { - BuddyBlock *prev = block->prev; - BuddyBlock *next = block->next; - if (prev) - { - prev->next = next; - } - else - { - level->first_unused_block = next; - } - if (next) - { - next->prev = prev; - } - } - block->next = ctx->first_free_block; - ctx->first_free_block = block; -} - -//////////////////////////////////////////////////////////// -//~ Get unused block +//~ Buddy block BuddyBlock *GetUnusedBuddyBlock(BuddyCtx *ctx, BuddyLevel *level) { @@ -212,3 +114,93 @@ BuddyBlock *GetUnusedBuddyBlock(BuddyCtx *ctx, BuddyLevel *level) return block; } + +BuddyBlock *PushBuddyBlock(BuddyCtx *ctx) +{ + BuddyBlock *block; + if (ctx->first_free_block) + { + block = ctx->first_free_block; + ctx->first_free_block = block->next; + } + else + { + block = PushStructNoZero(ctx->meta_arena, BuddyBlock); + } + ZeroStruct(block); + return block; +} + +void PopBuddyBlock(BuddyCtx *ctx, BuddyLevel *level, BuddyBlock *block) +{ + /* Remove from unused list */ + { + BuddyBlock *prev = block->prev; + BuddyBlock *next = block->next; + if (prev) + { + prev->next = next; + } + else + { + level->first_unused_block = next; + } + if (next) + { + next->prev = prev; + } + } + block->next = ctx->first_free_block; + ctx->first_free_block = block; +} + +BuddyBlock *AcquireBuddyBlock(BuddyCtx *ctx, u64 size) +{ + if (size > 0x00FFFFFFFFFFFFFFULL) + { + /* TODO: Error */ + Assert(0); + } + + /* TODO: Minimum block size */ + + /* TODO: Faster MSB calculation */ + + u64 desired_block_size = 1; + u64 desired_level_tier = 0; + while (desired_block_size < size && desired_level_tier < 64) + { + desired_block_size <<= 1; + ++desired_level_tier; + } + + BuddyBlock *block = GetUnusedBuddyBlock(ctx, &ctx->levels[desired_level_tier]); + + return block; +} + +void ReleaseBuddyBlock(BuddyBlock *block) +{ + block->is_used = 0; + BuddyLevel *level = block->level; + BuddyBlock *parent = block->parent; + BuddyBlock *sibling = block->sibling; + if (!sibling->is_used && parent != 0) + { + /* Merge siblings */ + BuddyCtx *ctx = level->ctx; + PopBuddyBlock(ctx, level, block); + PopBuddyBlock(ctx, level, sibling); + /* Release parent */ + ReleaseBuddyBlock(parent); + } + else + { + if (level->first_unused_block) + { + block->next = level->first_unused_block; + level->first_unused_block->prev = block; + } + level->first_unused_block = block; + } +} diff --git a/src/base/base_buddy.h b/src/base/base_buddy.h index a9f9ddbd..68babbbb 100644 --- a/src/base/base_buddy.h +++ b/src/base/base_buddy.h @@ -44,13 +44,13 @@ void ReleaseBuddyCtx(BuddyCtx *ctx); //////////////////////////////////////////////////////////// //~ Buddy block -//- Acquire / release -BuddyBlock *AcquireBuddyBlock(BuddyCtx *ctx, u64 size); -void ReleaseBuddyBlock(BuddyBlock *block); +//- Get unused +BuddyBlock *GetUnusedBuddyBlock(BuddyCtx *ctx, BuddyLevel *level); //- Push / pop BuddyBlock *PushBuddyBlock(BuddyCtx *ctx); void PopBuddyBlock(BuddyCtx *ctx, BuddyLevel *level, BuddyBlock *block); -//- Get unused -BuddyBlock *GetUnusedBuddyBlock(BuddyCtx *ctx, BuddyLevel *level); +//- Acquire / release +BuddyBlock *AcquireBuddyBlock(BuddyCtx *ctx, u64 size); +void ReleaseBuddyBlock(BuddyBlock *block); diff --git a/src/base/base_math.c b/src/base/base_math.c index 56a3c4e1..fdf9ea03 100644 --- a/src/base/base_math.c +++ b/src/base/base_math.c @@ -1148,6 +1148,43 @@ u32 U32FromVec4(Vec4 v) return result; } +//////////////////////////////////////////////////////////// +//~ Range + +Vec2 DimsFromRng2(Rng2 r) +{ + Vec2 result = ZI; + result.x = r.p1.x - r.p0.x; + result.y = r.p1.y - r.p0.y; + return result; +} + +Rng2 UnionRng2(Rng2 a, Rng2 b) +{ + Rng2 result = ZI; + result.p0.x = MinF32(a.p0.x, b.p0.x); + result.p0.y = MinF32(a.p0.y, b.p0.y); + result.p1.x = MaxF32(a.p1.x, b.p1.x); + result.p1.y = MaxF32(a.p1.y, b.p1.y); + return result; +} + +Rng2 AddRng2Vec2(Rng2 r, Vec2 v) +{ + Rng2 result = ZI; + result.p0 = AddVec2(result.p0, v); + result.p1 = AddVec2(result.p1, v); + return result; +} + +Rng2 DivRng2Vec2(Rng2 r, Vec2 v) +{ + Rng2 result = ZI; + result.p0 = DivVec2Vec2(result.p0, v); + result.p1 = DivVec2Vec2(result.p1, v); + return result; +} + //////////////////////////////////////////////////////////// //~ Xform diff --git a/src/base/base_math.h b/src/base/base_math.h index 8ad9aec4..ce64efcb 100644 --- a/src/base/base_math.h +++ b/src/base/base_math.h @@ -385,6 +385,15 @@ Vec2I32 SubVec2I32(Vec2I32 a, Vec2I32 b); Vec4 Vec4FromU32(u32 v); u32 U32FromVec4(Vec4 v); +//////////////////////////////////////////////////////////// +//~ Range + +Vec2 DimsFromRng2(Rng2 r); +Rng2 UnionRng2(Rng2 a, Rng2 b); + +Rng2 AddRng2Vec2(Rng2 r, Vec2 v); +Rng2 DivRng2Vec2(Rng2 a, Vec2 v); + //////////////////////////////////////////////////////////// //~ Xform diff --git a/src/base/base_shader.gh b/src/base/base_shader.gh index a6710a15..73197278 100644 --- a/src/base/base_shader.gh +++ b/src/base/base_shader.gh @@ -1,5 +1,5 @@ //////////////////////////////////////////////////////////// -//~ Math types +//~ Base math types #define Pi ((f32)3.14159265358979323846) #define Tau ((f32)6.28318530717958647693) @@ -21,6 +21,21 @@ typedef float4 Aabb; typedef float4 Quad; typedef float4x4 Mat4x4; +//////////////////////////////////////////////////////////// +//~ Range types + +Struct(Rng) { f32 min; f32 max; }; +Struct(RngI32) { i32 min; i32 max; }; +Struct(RngU32) { u32 min; u32 max; }; + +Struct(Rng2) { Vec2 p0; Vec2 p1; }; +Struct(Rng2I32) { Vec2I32 p0; Vec2I32 p1; }; +Struct(Rng2U32) { Vec2U32 p0; Vec2U32 p1; }; + +Struct(Rng3) { Vec3 p0; Vec3 p1; }; +Struct(Rng3I32) { Vec3I32 p0; Vec3I32 p1; }; +Struct(Rng3U32) { Vec3U32 p0; Vec3U32 p1; }; + //////////////////////////////////////////////////////////// //~ Countof diff --git a/src/config.h b/src/config.h index 97fefc3b..6329442a 100644 --- a/src/config.h +++ b/src/config.h @@ -69,7 +69,7 @@ #define FLOOD_DEBUG 0 -#define GPU_DEBUG 1 +#define GPU_DEBUG 0 #define GPU_DEBUG_VALIDATION 0 #define GPU_SHADER_PRINT 1 diff --git a/src/glyph_cache/glyph_cache.c b/src/glyph_cache/glyph_cache.c index e21ae72e..1f0294ad 100644 --- a/src/glyph_cache/glyph_cache.c +++ b/src/glyph_cache/glyph_cache.c @@ -1,12 +1,12 @@ -/* TODO: Use default font texture handle */ -Readonly GC_RunRect GC_NilRunRect = { - 0 -}; +GC_State GC = ZI; -Readonly GC_Run GC_NilRun = { - .count = 1, - .rects = &GC_NilRunRect -}; +//////////////////////////////////////////////////////////// +//~ Bootstrap + +void GC_BootStrap(void) +{ + // OnAsync(GC_AsyncTick); +} //////////////////////////////////////////////////////////// //~ Key helpers @@ -18,22 +18,119 @@ GC_FontKey GC_FontKeyFromResource(ResourceKey resource) return result; } +u64 GC_HashFromGlyphDesc(GC_GlyphDesc desc) +{ + return RandU64FromSeeds(desc.font.v, ((u64)desc.codepoint << 32) | *(u32 *)&desc.font_size); +} + //////////////////////////////////////////////////////////// //~ Run -GC_Run *GC_RunFromString(Arena *arena, GC_FontKey key, String str) +/* TODO: Thread-local cache */ +GC_Run GC_RunFromString(Arena *arena, String str, GC_FontKey font, f32 font_size) { - /* TODO */ - GC_Run *result = PushStruct(arena, GC_Run); + GC_Run result = ZI; + TempArena scratch = BeginScratch(arena); - GC_RunRect *rr = PushStruct(arena, GC_RunRect); - rr->advance = 1; - result->rects = rr; - result->count = 1; + String32 codepoints = String32FromString(scratch.arena, str); + String32 uncached_codepoints = ZI; + uncached_codepoints.text = PushStructsNoZero(scratch.arena, u32, codepoints.len); + + u64 ready_glyphs_count = 0; + GC_Glyph **ready_glyphs = PushStructsNoZero(scratch.arena, GC_Glyph *, str.len); + { + if (codepoints.len > 0) + { + Lock lock = LockS(&GC.glyphs_mutex); + for (u64 codepoint_idx = 0; codepoint_idx < codepoints.len; ++codepoint_idx) + { + u32 codepoint = codepoints.text[codepoint_idx]; + + GC_GlyphDesc desc = ZI; + desc.font = font; + desc.font_size = font_size; + desc.codepoint = codepoint; + + u64 hash = GC_HashFromGlyphDesc(desc); + GC_GlyphBin *bin = &GC.glyph_bins[hash % countof(GC.glyph_bins)]; + + GC_Glyph *glyph = bin->first; + for (; glyph; glyph = glyph->next) + { + if (glyph->hash == hash) + { + break; + } + } + + if (glyph == 0) + { + uncached_codepoints.text[uncached_codepoints.len] = codepoint; + uncached_codepoints.len += 1; + } + else + { + ready_glyphs[ready_glyphs_count] = glyph; + ready_glyphs_count += 1; + } + } + Unlock(&lock); + } + } + + f32 baseline_pos = 0; + result.rects = PushStructs(arena, GC_RunRect, ready_glyphs_count); + result.rects_count = ready_glyphs_count; + for (u64 glyph_idx = 0; glyph_idx < ready_glyphs_count; ++glyph_idx) + { + GC_Glyph *glyph = ready_glyphs[glyph_idx]; + GC_RunRect *rect = &result.rects[glyph_idx]; + + rect->tex = glyph->tex_ref; + rect->tex_uv = glyph->tex_uv; + rect->tex_rect = glyph->tex_rect; + + rect->baseline_pos = baseline_pos; + rect->advance = glyph->advance; + + rect->bounds.p0 = glyph->baseline_offset; + rect->bounds.p1 = AddVec2(rect->bounds.p0, DimsFromRng2(glyph->tex_rect)); + + if (glyph_idx == 0) + { + result.bounds = rect->bounds; + } + else + { + result.bounds = UnionRng2(result.bounds, rect->bounds); + } + + baseline_pos += rect->advance; + result.baseline_length = MaxF32(result.baseline_length, baseline_pos); + } + + if (ready_glyphs_count > 0) + { + GC_Glyph *glyph = ready_glyphs[0]; + result.font_size = glyph->font_size; + result.font_ascent = glyph->font_ascent; + result.font_descent = glyph->font_descent; + result.font_cap = glyph->font_cap; + } + + result.ready = uncached_codepoints.len == 0; + + EndScratch(scratch); return result; } +//////////////////////////////////////////////////////////// +//~ Async tick + +void GC_AsyncTick(WaveLaneCtx *lane) +{ +} diff --git a/src/glyph_cache/glyph_cache.h b/src/glyph_cache/glyph_cache.h index e723f119..37744432 100644 --- a/src/glyph_cache/glyph_cache.h +++ b/src/glyph_cache/glyph_cache.h @@ -6,50 +6,102 @@ Struct(GC_FontKey) u64 v; }; +//////////////////////////////////////////////////////////// +//~ Glyph types + +Struct(GC_GlyphDesc) +{ + GC_FontKey font; + f32 font_size; + u32 codepoint; +}; + +Struct(GC_Glyph) +{ + GC_Glyph *next; + u64 hash; + + /* Layout info */ + Vec2 baseline_offset; + f32 advance; + + /* Atlas info */ + G_Texture2DRef tex_ref; + Rng2 tex_uv; + Rng2 tex_rect; + + /* Font info */ + f32 font_size; + f32 font_ascent; + f32 font_descent; + f32 font_cap; +}; + +Struct(GC_GlyphBin) +{ + GC_Glyph *first; +}; + //////////////////////////////////////////////////////////// //~ 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 */ + Rng2 bounds; /* Visual bounds in relation to the baseline */ + f32 baseline_pos; /* Horizontal distance from start of baseline */ f32 advance; - Vec2 size; G_Texture2DRef tex; - Rng2 uv; + Rng2 tex_uv; + Rng2 tex_rect; }; 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; + Rng2 bounds; /* Visual bounds of the run in relation to the baseline */ + f32 baseline_length; + u64 rects_count; GC_RunRect *rects; - /* Font stats */ - f32 size; - f32 ascent; - f32 descent; - f32 cap; + /* Font info */ + f32 font_size; + f32 font_ascent; + f32 font_descent; + f32 font_cap; - b32 loaded; + b32 ready; }; -extern Readonly GC_RunRect GC_NilRunRect; -extern Readonly GC_Run GC_NilRun; +//////////////////////////////////////////////////////////// +//~ State + +Struct(GC_State) +{ + Mutex glyphs_mutex; + GC_GlyphBin glyph_bins[16384]; +} extern GC; + +//////////////////////////////////////////////////////////// +//~ Bootstrap + +void GC_Bootstrap(void); //////////////////////////////////////////////////////////// //~ Key helpers GC_FontKey GC_FontKeyFromResource(ResourceKey resource); +u64 GC_HashFromGlyphDesc(GC_GlyphDesc desc); //////////////////////////////////////////////////////////// //~ Run -GC_Run *GC_RunFromString(Arena *arena, GC_FontKey key, String str); +GC_Run GC_RunFromString(Arena *arena, String str, GC_FontKey font, f32 font_size); +//////////////////////////////////////////////////////////// +//~ Async tick + +void GC_AsyncTick(WaveLaneCtx *lane); diff --git a/src/gpu/gpu_dx12/gpu_dx12_core.c b/src/gpu/gpu_dx12/gpu_dx12_core.c index 0b789f45..015c232d 100644 --- a/src/gpu/gpu_dx12/gpu_dx12_core.c +++ b/src/gpu/gpu_dx12/gpu_dx12_core.c @@ -317,6 +317,7 @@ void G_Bootstrap(void) } } } + } ////////////////////////////// diff --git a/src/pp/pp_vis/pp_vis_core.c b/src/pp/pp_vis/pp_vis_core.c index d54feba9..9a74056c 100644 --- a/src/pp/pp_vis/pp_vis_core.c +++ b/src/pp/pp_vis/pp_vis_core.c @@ -249,7 +249,7 @@ void V_TickForever(WaveLaneCtx *lane) { /* TODO: Don't rely on ui report for draw size since it introduces one frame of delay when resizing */ UI_Report vis_rep = UI_ReportFromKey(vis_box); - draw_size = Vec2I32FromFields(SubVec2(vis_rep.screen_p1, vis_rep.screen_p0)); + draw_size = Vec2I32FromVec(DimsFromRng2(vis_rep.screen_rect)); } draw_size.x = MaxI32(draw_size.x, 1); draw_size.y = MaxI32(draw_size.y, 1); @@ -624,9 +624,11 @@ void V_TickForever(WaveLaneCtx *lane) G_DumbMemoryLayoutSync(frame->cl, draw_target, G_Layout_DirectQueue_ShaderRead); { - Vec2 uv0 = DivVec2Vec2(Vec2FromVec(viewport.p0), Vec2FromVec(window_frame.monitor_size)); - Vec2 uv1 = DivVec2Vec2(Vec2FromVec(viewport.p1), Vec2FromVec(window_frame.monitor_size)); - UI_SetRawTexture(vis_box, draw_target_ro, uv0, uv1); + Rng2 uv = ZI; + uv.p0 = Vec2FromVec(viewport.p0); + uv.p1 = Vec2FromVec(viewport.p1); + uv = DivRng2Vec2(uv, Vec2FromVec(window_frame.monitor_size)); + UI_SetRawTexture(vis_box, draw_target_ro, uv); } } diff --git a/src/pp/pp_vis/pp_vis_shaders.g b/src/pp/pp_vis/pp_vis_shaders.g index ef0e00d6..605ce78d 100644 --- a/src/pp/pp_vis/pp_vis_shaders.g +++ b/src/pp/pp_vis/pp_vis_shaders.g @@ -53,7 +53,7 @@ PixelShader(V_DQuadPS, V_DQuadPSOutput, V_DQuadPSInput input) Vec4 final_color = 0; V_DQuadPSOutput output; - output.SV_Target0 = final_color; + output.sv_target0 = final_color; return output; } @@ -85,6 +85,6 @@ VertexShader(V_DVertVS, V_DVertPSInput) PixelShader(V_DVertPS, V_DVertPSOutput, V_DVertPSInput input) { V_DVertPSOutput output; - output.SV_Target0 = input.color_lin; + output.sv_target0 = input.color_lin; return output; } diff --git a/src/pp/pp_vis/pp_vis_shaders.gh b/src/pp/pp_vis/pp_vis_shaders.gh index 3fcbcf64..286bf6b7 100644 --- a/src/pp/pp_vis/pp_vis_shaders.gh +++ b/src/pp/pp_vis/pp_vis_shaders.gh @@ -9,7 +9,7 @@ Struct(V_DQuadPSInput) Struct(V_DQuadPSOutput) { - Semantic(Vec4, SV_Target0); + Semantic(Vec4, sv_target0); }; //////////////////////////////////////////////////////////// @@ -24,7 +24,7 @@ Struct(V_DVertPSInput) Struct(V_DVertPSOutput) { - Semantic(Vec4, SV_Target0); + Semantic(Vec4, sv_target0); }; //////////////////////////////////////////////////////////// diff --git a/src/proto/proto_shaders.g b/src/proto/proto_shaders.g index 7a52dba1..4653ea34 100644 --- a/src/proto/proto_shaders.g +++ b/src/proto/proto_shaders.g @@ -31,7 +31,7 @@ Struct(PT_BlitPSInput) Struct(PT_BlitPSOutput) { - Semantic(Vec4, SV_Target0); + Semantic(Vec4, sv_target0); }; ////////////////////////////// @@ -68,6 +68,6 @@ PixelShader(PT_BlitPS, PT_BlitPSOutput, PT_BlitPSInput input) result.r = (f32)noise_val / (f32)U16Max; PT_BlitPSOutput output; - output.SV_Target0 = result; + output.sv_target0 = result; return output; } diff --git a/src/ui/ui_core.c b/src/ui/ui_core.c index 1a176f54..52f8a2f9 100644 --- a/src/ui/ui_core.c +++ b/src/ui/ui_core.c @@ -150,15 +150,15 @@ void UI_PushDefaults(void) case UI_StyleKind_Font: { desc.style.Font = UI_GetDefaultFont(); } break; u8 prefetch[127] = ZI; - for (u64 i = 0; i < countof(prefetch); ++i) + for (u64 idx = 0; idx < countof(prefetch); ++idx) { - prefetch[i] = i; + prefetch[idx] = idx; } - 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; - case UI_StyleKind_DebugColor: { desc.style.DebugColor = Rgba(1, 0, 1, 0.5); } break; - case UI_StyleKind_BackgroundTextureUv1: { desc.style.BackgroundTextureUv1 = VEC2(1, 1); } break; + 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; + case UI_StyleKind_DebugColor: { desc.style.DebugColor = Rgba(1, 0, 1, 0.5); } break; + case UI_StyleKind_BackgroundTextureSliceUv: { desc.style.BackgroundTextureSliceUv = RNG2(VEC2(0, 0), VEC2(1, 1)); } break; }; UI_PushStyle(desc); } @@ -411,7 +411,7 @@ UI_Key UI_BuildBoxEx(UI_Key key) } -void UI_SetRawTexture(UI_Key key, G_Texture2DRef tex, Vec2 uv0, Vec2 uv1) +void UI_SetRawTexture(UI_Key key, G_Texture2DRef tex, Rng2 uv) { UI_Frame *frame = UI_CurrentFrame(); UI_CmdNode *n = PushStruct(frame->arena, UI_CmdNode); @@ -419,8 +419,7 @@ void UI_SetRawTexture(UI_Key key, G_Texture2DRef tex, Vec2 uv0, Vec2 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; + n->cmd.set_raw_texture.slice_uv = uv; } ++frame->cmds_count; SllQueuePush(frame->first_cmd_node, frame->last_cmd_node, n); @@ -547,8 +546,8 @@ UI_Frame *UI_BeginFrame(UI_FrameFlag frame_flags, Vec4 swapchain_color) b32 is_cursor_in_box = 0; { /* 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 p0 = box->rect.p0; + Vec2 p1 = box->rect.p1; 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)); @@ -597,7 +596,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(frame->cursor_pos, hovered_box->p0); + hovered_box->report.last_m1_offset = SubVec2(frame->cursor_pos, hovered_box->rect.p0); active_box = hovered_box; } } @@ -642,8 +641,7 @@ UI_Frame *UI_BeginFrame(UI_FrameFlag frame_flags, Vec4 swapchain_color) report->active = LerpF32(report->active, target_active, active_blend_rate); report->hovered = LerpF32(report->hovered, target_hovered, hovered_blend_rate); - report->screen_p0 = box->p0; - report->screen_p1 = box->p1; + report->screen_rect = box->rect; } frame->hovered_box = hovered_box ? hovered_box->key : UI_NilKey; @@ -789,10 +787,9 @@ void UI_EndFrame(UI_Frame *frame) } /* Fetch run */ - box->glyph_run = &GC_NilRun; if (box->desc.text.len > 0) { - box->glyph_run = GC_RunFromString(frame->arena, box->desc.font, box->desc.text); + box->glyph_run = GC_RunFromString(frame->arena, box->desc.text, box->desc.font, box->desc.font_size); } } @@ -809,8 +806,7 @@ void UI_EndFrame(UI_Frame *frame) if (box) { 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; + box->raw_texture_slice_uv = cmd.set_raw_texture.slice_uv; } } break; } @@ -908,13 +904,11 @@ void UI_EndFrame(UI_Frame *frame) f32 text_size = 0; if (axis == Axis_X) { - GC_RunRect rr = box->glyph_run->rects[box->glyph_run->count - 1]; - f32 baseline_length = rr.pos + rr.advance; - text_size = baseline_length; + text_size = box->glyph_run.baseline_length; } else { - text_size = box->glyph_run->ascent + box->glyph_run->descent; + text_size = box->glyph_run.font_ascent + box->glyph_run.font_descent; } box->solved_dims[axis] = text_size + (pref_size.v * 2); } @@ -1107,16 +1101,16 @@ void UI_EndFrame(UI_Frame *frame) if (AnyBit(box->desc.flags, UI_BoxFlag_Floating)) { Vec2 offset = box->desc.floating_pos; - final_pos = AddVec2(parent->p0, offset); + final_pos = AddVec2(parent->rect.p0, offset); if (!AnyBit(box->desc.flags, UI_BoxFlag_NoFloatingClamp)) { { - f32 overshoot = MaxF32(0, (final_pos.x + dims_vec.x) - parent->p1.x); - final_pos.x = MaxF32(parent->p0.x, final_pos.x - overshoot); + f32 overshoot = MaxF32(0, (final_pos.x + dims_vec.x) - parent->rect.p1.x); + final_pos.x = MaxF32(parent->rect.p0.x, final_pos.x - overshoot); } { - f32 overshoot = MaxF32((final_pos.y + dims_vec.y) - parent->p1.y, 0); - final_pos.y = MaxF32(parent->p0.y, final_pos.y - overshoot); + f32 overshoot = MaxF32((final_pos.y + dims_vec.y) - parent->rect.p1.y, 0); + final_pos.y = MaxF32(parent->rect.p0.y, final_pos.y - overshoot); } } } @@ -1151,22 +1145,22 @@ void UI_EndFrame(UI_Frame *frame) } break; } } - final_pos.x = parent->p0.x + offset[0]; - final_pos.y = parent->p0.y + offset[1]; + final_pos.x = parent->rect.p0.x + offset[0]; + final_pos.y = parent->rect.p0.y + offset[1]; parent->layout_cursor += dims_arr[parent->desc.child_layout_axis]; } /* Submit position */ Vec2 floored_final_pos = FloorVec2(final_pos); Vec2 ceiled_dims = CeilVec2(dims_vec); - box->p0 = FloorVec2(floored_final_pos); - box->p1 = AddVec2(floored_final_pos, ceiled_dims); + box->rect.p0 = FloorVec2(floored_final_pos); + box->rect.p1 = AddVec2(floored_final_pos, ceiled_dims); } /* Rounding */ { UI_Round rounding = box->desc.rounding; - Vec2 half_dims = MulVec2(SubVec2(box->p1, box->p0), 0.5); + Vec2 half_dims = MulVec2(SubVec2(box->rect.p1, box->rect.p0), 0.5); f32 min_half_dims = MinF32(half_dims.x, half_dims.y); f32 final_rounding_tl = 0; f32 final_rounding_tr = 0; @@ -1194,10 +1188,10 @@ void UI_EndFrame(UI_Frame *frame) if (parent && !AllBits(box->desc.flags, UI_BoxFlag_Floating | UI_BoxFlag_NoFloatingClamp)) { - Vec2 vtl = SubVec2(VEC2(parent->p0.x, parent->p0.y), VEC2(box->p0.x, box->p0.y)); - Vec2 vtr = SubVec2(VEC2(parent->p1.x, parent->p0.y), VEC2(box->p1.x, box->p0.y)); - Vec2 vbr = SubVec2(VEC2(parent->p1.x, parent->p1.y), VEC2(box->p1.x, box->p1.y)); - Vec2 vbl = SubVec2(VEC2(parent->p0.x, parent->p1.y), VEC2(box->p0.x, box->p1.y)); + Vec2 vtl = SubVec2(VEC2(parent->rect.p0.x, parent->rect.p0.y), VEC2(box->rect.p0.x, box->rect.p0.y)); + Vec2 vtr = SubVec2(VEC2(parent->rect.p1.x, parent->rect.p0.y), VEC2(box->rect.p1.x, box->rect.p0.y)); + Vec2 vbr = SubVec2(VEC2(parent->rect.p1.x, parent->rect.p1.y), VEC2(box->rect.p1.x, box->rect.p1.y)); + Vec2 vbl = SubVec2(VEC2(parent->rect.p0.x, parent->rect.p1.y), VEC2(box->rect.p0.x, box->rect.p1.y)); final_rounding_tl = MaxF32(final_rounding_tl, parent->rounding_tl - Vec2Len(vtl)); final_rounding_tr = MaxF32(final_rounding_tr, parent->rounding_tr - Vec2Len(vtr)); final_rounding_br = MaxF32(final_rounding_br, parent->rounding_br - Vec2Len(vbr)); @@ -1226,18 +1220,15 @@ void UI_EndFrame(UI_Frame *frame) UI_Box *box = boxes_pre[pre_index]; b32 is_visible = 1; 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); + is_visible = is_visible && (box->rect.p1.x > box->rect.p0.x); + is_visible = is_visible && (box->rect.p1.y > box->rect.p0.y); if (is_visible || AnyBit(frame->frame_flags, UI_FrameFlag_Debug)) { /* Box rect */ { UI_DRect *rect = PushStruct(frame->rects_arena, UI_DRect); - rect->p0 = box->p0; - rect->p1 = box->p1; - rect->tex_uv0 = VEC2(0, 0); - rect->tex_uv1 = VEC2(1, 1); + rect->bounds = box->rect; rect->background_lin = LinearFromSrgb(box->desc.background_color); rect->border_lin = LinearFromSrgb(box->desc.border_color); rect->debug_lin = LinearFromSrgb(box->desc.debug_color); @@ -1248,54 +1239,54 @@ void UI_EndFrame(UI_Frame *frame) rect->br_rounding = box->rounding_br; rect->bl_rounding = box->rounding_bl; rect->tex = box->raw_texture; - rect->tex_uv0 = box->raw_texture_uv0; - rect->tex_uv1 = box->raw_texture_uv1; + rect->tex_slice_uv = box->raw_texture_slice_uv; } /* Text rects */ - GC_Run *raw_run = box->glyph_run; - if (AnyBit(box->desc.flags, UI_BoxFlag_DrawText) && raw_run->loaded) + GC_Run raw_run = box->glyph_run; + if (AnyBit(box->desc.flags, UI_BoxFlag_DrawText) && raw_run.ready) { - f32 max_baseline = box->p1.x - box->p0.x; - 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; + f32 max_baseline = DimsFromRng2(box->rect).x; + b32 should_truncate = raw_run.baseline_length > max_baseline && !AnyBit(box->desc.flags, UI_BoxFlag_NoTextTruncation); /* 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)) + u64 final_rects_count = 0; + GC_RunRect *final_rects = 0; + if (should_truncate) { /* Get elipses run */ - GC_Run *elipses_run = GC_RunFromString(scratch.arena, box->desc.font, Lit("...")); - if (elipses_run->count > 0) - { - max_baseline -= elipses_run->rects[elipses_run->count - 1].pos + elipses_run->rects[elipses_run->count - 1].advance; - } + GC_Run elipses_run = GC_RunFromString(scratch.arena, Lit("..."), box->desc.font, box->desc.font_size); + f32 elipses_start_pos = max_baseline - elipses_run.baseline_length; - /* Subtract glyphs */ - while (truncated_rects_count > 0) + /* Append non-overflowed rects */ + final_rects = PushStructsNoZero(scratch.arena, GC_RunRect, raw_run.rects_count); + for (u64 rect_idx = 0; rect_idx < raw_run.rects_count; ++rect_idx) { - GC_RunRect rr = raw_run->rects[truncated_rects_count - 1]; - if (rr.pos + rr.advance <= max_baseline) + GC_RunRect rr = raw_run.rects[rect_idx]; + if ((rr.baseline_pos + rr.advance) <= elipses_start_pos) { - break; - } - --truncated_rects_count; - } - - /* Merge trunc rects */ - /* FIXME: Verify this stil works as expected */ - { - 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) - { - GC_RunRect *rr = &truncated_rects[i + truncated_rects_count]; - *rr = elipses_run->rects[i]; - rr->pos += elipses_offset; + final_rects[final_rects_count] = rr; + final_rects_count += 1; } } + + /* Append elipses */ + for (u64 rect_idx = 0; rect_idx < elipses_run.rects_count; ++rect_idx) + { + GC_RunRect rr = elipses_run.rects[rect_idx]; + rr.baseline_pos += elipses_start_pos; + rr.bounds = AddRng2Vec2(rr.bounds, VEC2(elipses_start_pos, 0)); + if ((rr.baseline_pos + rr.advance) <= max_baseline) + { + final_rects[final_rects_count] = rr; + final_rects_count += 1; + } + } + } + else + { + final_rects = raw_run.rects; + final_rects_count = raw_run.rects_count; } UI_AxisAlignment x_alignment = box->desc.child_alignment[Axis_X]; @@ -1306,68 +1297,64 @@ void UI_EndFrame(UI_Frame *frame) } /* Compute baseline */ - 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; + f32 ascent = raw_run.font_ascent; + f32 font_descent = raw_run.font_descent; + f32 cap = raw_run.font_cap; + f32 baseline_width = raw_run.baseline_length; + f32 baseline_height = ascent + font_descent; + Vec2 box_dims = DimsFromRng2(box->rect); Vec2 baseline = ZI; switch (x_alignment) { case UI_AxisAlignment_Start: { - baseline.x = box->p0.x; + baseline.x = box->rect.p0.x; } break; case UI_AxisAlignment_End: { - baseline.x = box->p1.x; + baseline.x = box->rect.p1.x; baseline.x -= baseline_width; } break; case UI_AxisAlignment_Center: { - baseline.x = box->p0.x; - baseline.x += (box_width - baseline_width) / 2; + baseline.x = box->rect.p0.x; + baseline.x += (box_dims.x - baseline_width) / 2; } break; } switch (y_alignment) { case UI_AxisAlignment_Start: { - baseline.y = box->p0.y; + baseline.y = box->rect.p0.y; baseline.y += ascent; } break; case UI_AxisAlignment_End: { - baseline.y = box->p1.y; - baseline.y -= descent; + baseline.y = box->rect.p1.y; + baseline.y -= font_descent; } break; case UI_AxisAlignment_Center: { - baseline.y = box->p0.y; - baseline.y += box_height / 2; + baseline.y = box->rect.p0.y; + baseline.y += box_dims.y / 2; baseline.y += cap / 2; } break; } baseline = CeilVec2(baseline); /* Push text rects */ - for (u64 i = 0; i < truncated_rects_count; ++i) + for (u64 rect_idx = 0; rect_idx < final_rects_count; ++rect_idx) { - GC_RunRect rr = truncated_rects[i]; - Vec2 glyph_size = rr.size; - if (glyph_size.x != 0 || glyph_size.y != 0) + GC_RunRect rr = final_rects[rect_idx]; + Vec2 glyph_dims = DimsFromRng2(rr.bounds); + if (glyph_dims.x != 0 || glyph_dims.y != 0) { 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->bounds = AddRng2Vec2(rr.bounds, baseline); rect->debug_lin = LinearFromSrgb(box->desc.debug_color); rect->tint_lin = LinearFromSrgb(box->desc.tint); rect->tex = rr.tex; - rect->tex_uv0 = rr.uv.p0; - rect->tex_uv1 = rr.uv.p1; + rect->tex_slice_uv = rr.tex_uv; } } } diff --git a/src/ui/ui_core.h b/src/ui/ui_core.h index 09887ece..1d35c466 100644 --- a/src/ui/ui_core.h +++ b/src/ui/ui_core.h @@ -90,34 +90,33 @@ Enum(UI_BoxFlag) //////////////////////////////////////////////////////////// //~ Style types -#define UI_StyleKindsXMacro(X) \ - X(Flags, UI_BoxFlag) \ - X(Parent, UI_Key) \ - X(Tag, u64) \ - X(ChildLayoutAxis, Axis) \ - X(ChildAlignmentX, UI_AxisAlignment) \ - X(ChildAlignmentY, UI_AxisAlignment) \ - X(Width, UI_Size) \ - X(Height, UI_Size) \ - X(BackgroundColor, Vec4) \ - X(BorderColor, Vec4) \ - X(DebugColor, Vec4) \ - X(Tint, Vec4) \ - X(Border, f32) \ - X(FloatingPos, Vec2) \ - X(Rounding, UI_Round) \ - X(Font, GC_FontKey) \ - X(FontSize, u32) \ - X(Text, String) \ - X(BackgroundTexture, G_Texture2DRef) \ - X(BackgroundTextureUv0, Vec2) \ - X(BackgroundTextureUv1, Vec2) \ - /* --------------------------------------- */ \ - /* ----------- Virtual styles ----------- */ \ - /* --------------------------------------- */ \ - X(BeginVirtualStyles_, i8) \ - X(ChildAlignment, UI_Alignment) \ - X(AxisSize, UI_Size) \ +#define UI_StyleKindsXMacro(X) \ + X(Flags, UI_BoxFlag) \ + X(Parent, UI_Key) \ + X(Tag, u64) \ + X(ChildLayoutAxis, Axis) \ + X(ChildAlignmentX, UI_AxisAlignment) \ + X(ChildAlignmentY, UI_AxisAlignment) \ + X(Width, UI_Size) \ + X(Height, UI_Size) \ + X(BackgroundColor, Vec4) \ + X(BorderColor, Vec4) \ + X(DebugColor, Vec4) \ + X(Tint, Vec4) \ + X(Border, f32) \ + X(FloatingPos, Vec2) \ + X(Rounding, UI_Round) \ + X(Font, GC_FontKey) \ + X(FontSize, u32) \ + X(Text, String) \ + X(BackgroundTexture, G_Texture2DRef) \ + X(BackgroundTextureSliceUv, Rng2) \ + /* -------------------------------------------- */ \ + /* -------------- Virtual styles -------------- */ \ + /* -------------------------------------------- */ \ + X(BeginVirtualStyles_, i8) \ + X(ChildAlignment, UI_Alignment) \ + X(AxisSize, UI_Size) \ /* -------------------------------------------------- */ Enum(UI_StyleKind) @@ -187,8 +186,7 @@ Struct(UI_Report) Vec2 last_m1_offset; /* Where was this box last rendered in screen coordinates */ - Vec2 screen_p0; - Vec2 screen_p1; + Rng2 screen_rect; }; //////////////////////////////////////////////////////////// @@ -233,8 +231,7 @@ Struct(UI_Cmd) { UI_Key key; G_Texture2DRef tex; - Vec2 uv0; - Vec2 uv1; + Rng2 slice_uv; } set_raw_texture; }; }; @@ -269,22 +266,20 @@ Struct(UI_Box) //- Cmd data UI_BoxDesc desc; G_Texture2DRef raw_texture; - Vec2 raw_texture_uv0; - Vec2 raw_texture_uv1; + Rng2 raw_texture_slice_uv; //- Pre-layout data u64 pre_index; u64 post_index; //- Layout data - GC_Run *glyph_run; + GC_Run glyph_run; f32 layout_cursor; f32 solved_dims[Axis_CountXY]; f32 final_children_size_accum[Axis_CountXY]; //- Layout results - Vec2 p0; - Vec2 p1; + Rng2 rect; f32 rounding_tl; f32 rounding_tr; f32 rounding_br; @@ -443,7 +438,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, G_Texture2DRef tex, Vec2 uv0, Vec2 uv1); +void UI_SetRawTexture(UI_Key key, G_Texture2DRef tex, Rng2 uv); //////////////////////////////////////////////////////////// //~ Report diff --git a/src/ui/ui_shaders.cgh b/src/ui/ui_shaders.cgh index 6dafbe8e..60885ef9 100644 --- a/src/ui/ui_shaders.cgh +++ b/src/ui/ui_shaders.cgh @@ -20,16 +20,16 @@ Struct(UI_DParams) Struct(UI_DRect) { - Vec2 p0; - Vec2 p1; + Rng2 bounds; + + G_Texture2DRef tex; + Rng2 tex_slice_uv; + Vec4 tint_lin; Vec4 background_lin; Vec4 border_lin; Vec4 debug_lin; f32 border; - Vec2 tex_uv0; - Vec2 tex_uv1; - G_Texture2DRef tex; f32 tl_rounding; f32 tr_rounding; diff --git a/src/ui/ui_shaders.g b/src/ui/ui_shaders.g index 07fd43c9..08158f3a 100644 --- a/src/ui/ui_shaders.g +++ b/src/ui/ui_shaders.g @@ -11,8 +11,8 @@ VertexShader(UI_DRectVS, UI_DRectPSInput) UI_DRect rect = rects[SV_InstanceID]; Vec2 rect_uv = RectUvFromVertexId(SV_VertexID); - Vec2 tex_uv = lerp(rect.tex_uv0, rect.tex_uv1, rect_uv); - Vec2 target_pos = lerp(rect.p0, rect.p1, rect_uv); + Vec2 tex_uv = lerp(rect.tex_slice_uv.p0, rect.tex_slice_uv.p1, rect_uv); + Vec2 target_pos = lerp(rect.bounds.p0, rect.bounds.p1, rect_uv); UI_DRectPSInput result; result.sv_position = Vec4(NdcFromPos(target_pos, Vec2(params.target_size).xy), 0, 1); @@ -39,8 +39,8 @@ PixelShader(UI_DRectPS, UI_DRectPSOutput, UI_DRectPSInput input) Vec2 p = input.sv_position.xy; Vec2 rect_uv = input.rect_uv; - Vec2 p0 = rect.p0; - Vec2 p1 = rect.p1; + Vec2 p0 = rect.bounds.p0; + Vec2 p1 = rect.bounds.p1; /* Compute rect sdf (negative means pixel is inside of rect) */ f32 rect_dist = min(min(p.x - p0.x, p1.x - p.x), min(p.y - p0.y, p1.y - p.y)); @@ -147,6 +147,6 @@ PixelShader(UI_BlitPS, UI_BlitPSOutput, UI_BlitPSInput input) Vec4 result = tex.Sample(sampler, uv); UI_BlitPSOutput output; - output.SV_Target0 = result; + output.sv_target0 = result; return output; } diff --git a/src/ui/ui_shaders.gh b/src/ui/ui_shaders.gh index 74fefbbc..b1f7bd4a 100644 --- a/src/ui/ui_shaders.gh +++ b/src/ui/ui_shaders.gh @@ -28,7 +28,7 @@ Struct(UI_BlitPSInput) Struct(UI_BlitPSOutput) { - Semantic(Vec4, SV_Target0); + Semantic(Vec4, sv_target0); }; ////////////////////////////////////////////////////////////