glyph cache progress

This commit is contained in:
jacob 2025-12-11 19:35:11 -06:00
parent ad359c8495
commit e9e8dcc04d
19 changed files with 516 additions and 363 deletions

View File

@ -94,20 +94,15 @@ void *PushBytesNoZero(Arena *arena, u64 size, u64 align)
{ {
Assert(align > 0); Assert(align > 0);
void *result = 0;
u8 *base = ArenaFirst(arena, u8); u8 *base = ArenaFirst(arena, u8);
/* Check to avoid aligning when size = 0 */ u64 start_pos = AlignU64(arena->pos, align);
if (size > 0) u64 end_pos = start_pos + size;
{
u64 aligned_start_pos = (arena->pos + (align - 1));
aligned_start_pos -= aligned_start_pos % align;
u64 new_pos = aligned_start_pos + size;
if (new_pos > arena->committed)
{
/* Commit new block(s) */ /* Commit new block(s) */
u64 blocks_needed = (new_pos - arena->committed + ArenaBlockSize - 1) / ArenaBlockSize; if (end_pos > arena->committed)
{
u64 blocks_needed = (end_pos - arena->committed + ArenaBlockSize - 1) / ArenaBlockSize;
u64 commit_bytes = blocks_needed * ArenaBlockSize; u64 commit_bytes = blocks_needed * ArenaBlockSize;
u64 new_capacity = arena->committed + commit_bytes; u64 new_capacity = arena->committed + commit_bytes;
if (new_capacity > arena->reserved) if (new_capacity > arena->reserved)
@ -126,14 +121,9 @@ void *PushBytesNoZero(Arena *arena, u64 size, u64 align)
AsanPoison(commit_address, commit_bytes); AsanPoison(commit_address, commit_bytes);
} }
result = base + aligned_start_pos; void *result = base + start_pos;
AsanUnpoison(result, new_pos - aligned_start_pos); AsanUnpoison(result, end_pos - start_pos);
arena->pos = new_pos; arena->pos = end_pos;
}
else
{
result = base + arena->pos;
}
return result; return result;
} }
@ -147,28 +137,8 @@ void *PushBytes(Arena *arena, u64 size, u64 align)
void *PushAlign(Arena *arena, u64 align) void *PushAlign(Arena *arena, u64 align)
{ {
void *result = 0; u64 push_count = AlignU64(arena->pos, align) - arena->pos;
if (align > 0) return PushStructsNoZero(arena, u8, push_count);
{
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;
} }
void PopTo(Arena *arena, u64 pos) 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) void *ArenaFirst_(Arena *arena, u64 align)
{ {
u64 aligned_start_pos = align - 1; void *result = (void *)AlignU64((u64)arena + ArenaHeaderSize, align);
aligned_start_pos -= aligned_start_pos % align;
void *result = ((u8 *)arena + ArenaHeaderSize) + aligned_start_pos;
return result; return result;
} }
void *ArenaNext_(Arena *arena, u64 align) void *ArenaNext_(Arena *arena, u64 align)
{ {
u64 aligned_start_pos = (arena->pos + (align - 1)); void *result = (void *)AlignU64((u64)arena + ArenaHeaderSize + arena->pos, align);
aligned_start_pos -= aligned_start_pos % align;
void *result = ((u8 *)arena + ArenaHeaderSize) + aligned_start_pos;
return result; return result;
} }
@ -233,7 +199,7 @@ void EndTempArena(TempArena temp)
TempArena BeginScratch(Arena *potential_conflict) 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); StaticAssert(ScratchArenasPerCtx == 2);
/* Use `BeginScratchNoConflict` if no conflicts are present */ /* Use `BeginScratchNoConflict` if no conflicts are present */

View File

@ -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. */ /* 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) BuddyCtx *AcquireBuddyCtx(u64 reserve)
{ {
@ -31,105 +31,7 @@ void ReleaseBuddyCtx(BuddyCtx *ctx)
} }
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
//~ Block acquire / release //~ Buddy 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;
}
}
////////////////////////////////////////////////////////////
//~ 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
BuddyBlock *GetUnusedBuddyBlock(BuddyCtx *ctx, BuddyLevel *level) BuddyBlock *GetUnusedBuddyBlock(BuddyCtx *ctx, BuddyLevel *level)
{ {
@ -212,3 +114,93 @@ BuddyBlock *GetUnusedBuddyBlock(BuddyCtx *ctx, BuddyLevel *level)
return block; 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;
}
}

View File

@ -44,13 +44,13 @@ void ReleaseBuddyCtx(BuddyCtx *ctx);
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
//~ Buddy block //~ Buddy block
//- Acquire / release //- Get unused
BuddyBlock *AcquireBuddyBlock(BuddyCtx *ctx, u64 size); BuddyBlock *GetUnusedBuddyBlock(BuddyCtx *ctx, BuddyLevel *level);
void ReleaseBuddyBlock(BuddyBlock *block);
//- Push / pop //- Push / pop
BuddyBlock *PushBuddyBlock(BuddyCtx *ctx); BuddyBlock *PushBuddyBlock(BuddyCtx *ctx);
void PopBuddyBlock(BuddyCtx *ctx, BuddyLevel *level, BuddyBlock *block); void PopBuddyBlock(BuddyCtx *ctx, BuddyLevel *level, BuddyBlock *block);
//- Get unused //- Acquire / release
BuddyBlock *GetUnusedBuddyBlock(BuddyCtx *ctx, BuddyLevel *level); BuddyBlock *AcquireBuddyBlock(BuddyCtx *ctx, u64 size);
void ReleaseBuddyBlock(BuddyBlock *block);

View File

@ -1148,6 +1148,43 @@ u32 U32FromVec4(Vec4 v)
return result; 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 //~ Xform

View File

@ -385,6 +385,15 @@ Vec2I32 SubVec2I32(Vec2I32 a, Vec2I32 b);
Vec4 Vec4FromU32(u32 v); Vec4 Vec4FromU32(u32 v);
u32 U32FromVec4(Vec4 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 //~ Xform

View File

@ -1,5 +1,5 @@
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
//~ Math types //~ Base math types
#define Pi ((f32)3.14159265358979323846) #define Pi ((f32)3.14159265358979323846)
#define Tau ((f32)6.28318530717958647693) #define Tau ((f32)6.28318530717958647693)
@ -21,6 +21,21 @@ typedef float4 Aabb;
typedef float4 Quad; typedef float4 Quad;
typedef float4x4 Mat4x4; 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 //~ Countof

View File

@ -69,7 +69,7 @@
#define FLOOD_DEBUG 0 #define FLOOD_DEBUG 0
#define GPU_DEBUG 1 #define GPU_DEBUG 0
#define GPU_DEBUG_VALIDATION 0 #define GPU_DEBUG_VALIDATION 0
#define GPU_SHADER_PRINT 1 #define GPU_SHADER_PRINT 1

View File

@ -1,12 +1,12 @@
/* TODO: Use default font texture handle */ GC_State GC = ZI;
Readonly GC_RunRect GC_NilRunRect = {
0
};
Readonly GC_Run GC_NilRun = { ////////////////////////////////////////////////////////////
.count = 1, //~ Bootstrap
.rects = &GC_NilRunRect
}; void GC_BootStrap(void)
{
// OnAsync(GC_AsyncTick);
}
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
//~ Key helpers //~ Key helpers
@ -18,22 +18,119 @@ GC_FontKey GC_FontKeyFromResource(ResourceKey resource)
return result; return result;
} }
u64 GC_HashFromGlyphDesc(GC_GlyphDesc desc)
{
return RandU64FromSeeds(desc.font.v, ((u64)desc.codepoint << 32) | *(u32 *)&desc.font_size);
}
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
//~ Run //~ 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 = ZI;
GC_Run *result = PushStruct(arena, GC_Run); TempArena scratch = BeginScratch(arena);
GC_RunRect *rr = PushStruct(arena, GC_RunRect); String32 codepoints = String32FromString(scratch.arena, str);
rr->advance = 1;
result->rects = rr;
result->count = 1;
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; return result;
} }
////////////////////////////////////////////////////////////
//~ Async tick
void GC_AsyncTick(WaveLaneCtx *lane)
{
}

View File

@ -6,50 +6,102 @@ Struct(GC_FontKey)
u64 v; 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 //~ Run types
Struct(GC_RunRect) Struct(GC_RunRect)
{ {
Vec2 offset; /* Vector from baseline offset to top left of glyph rect */ Rng2 bounds; /* Visual bounds in relation to the baseline */
f32 pos; /* Horizontal distance from start of baseline */ f32 baseline_pos; /* Horizontal distance from start of baseline */
f32 advance; f32 advance;
Vec2 size;
G_Texture2DRef tex; G_Texture2DRef tex;
Rng2 uv; Rng2 tex_uv;
Rng2 tex_rect;
}; };
Struct(GC_Run) Struct(GC_Run)
{ {
/* Run data */ /* Run data */
Vec2 p0; /* Start of baseline to top-left-most rect */ Rng2 bounds; /* Visual bounds of the run in relation to the baseline */
Vec2 p1; /* Start of baseline to bottom-right-most rect corner */ f32 baseline_length;
u32 count; u64 rects_count;
GC_RunRect *rects; GC_RunRect *rects;
/* Font stats */ /* Font info */
f32 size; f32 font_size;
f32 ascent; f32 font_ascent;
f32 descent; f32 font_descent;
f32 cap; 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 //~ Key helpers
GC_FontKey GC_FontKeyFromResource(ResourceKey resource); GC_FontKey GC_FontKeyFromResource(ResourceKey resource);
u64 GC_HashFromGlyphDesc(GC_GlyphDesc desc);
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
//~ Run //~ 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);

View File

@ -317,6 +317,7 @@ void G_Bootstrap(void)
} }
} }
} }
} }
////////////////////////////// //////////////////////////////

View File

@ -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 */ /* 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); 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.x = MaxI32(draw_size.x, 1);
draw_size.y = MaxI32(draw_size.y, 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); G_DumbMemoryLayoutSync(frame->cl, draw_target, G_Layout_DirectQueue_ShaderRead);
{ {
Vec2 uv0 = DivVec2Vec2(Vec2FromVec(viewport.p0), Vec2FromVec(window_frame.monitor_size)); Rng2 uv = ZI;
Vec2 uv1 = DivVec2Vec2(Vec2FromVec(viewport.p1), Vec2FromVec(window_frame.monitor_size)); uv.p0 = Vec2FromVec(viewport.p0);
UI_SetRawTexture(vis_box, draw_target_ro, uv0, uv1); uv.p1 = Vec2FromVec(viewport.p1);
uv = DivRng2Vec2(uv, Vec2FromVec(window_frame.monitor_size));
UI_SetRawTexture(vis_box, draw_target_ro, uv);
} }
} }

View File

@ -53,7 +53,7 @@ PixelShader(V_DQuadPS, V_DQuadPSOutput, V_DQuadPSInput input)
Vec4 final_color = 0; Vec4 final_color = 0;
V_DQuadPSOutput output; V_DQuadPSOutput output;
output.SV_Target0 = final_color; output.sv_target0 = final_color;
return output; return output;
} }
@ -85,6 +85,6 @@ VertexShader(V_DVertVS, V_DVertPSInput)
PixelShader(V_DVertPS, V_DVertPSOutput, V_DVertPSInput input) PixelShader(V_DVertPS, V_DVertPSOutput, V_DVertPSInput input)
{ {
V_DVertPSOutput output; V_DVertPSOutput output;
output.SV_Target0 = input.color_lin; output.sv_target0 = input.color_lin;
return output; return output;
} }

View File

@ -9,7 +9,7 @@ Struct(V_DQuadPSInput)
Struct(V_DQuadPSOutput) Struct(V_DQuadPSOutput)
{ {
Semantic(Vec4, SV_Target0); Semantic(Vec4, sv_target0);
}; };
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
@ -24,7 +24,7 @@ Struct(V_DVertPSInput)
Struct(V_DVertPSOutput) Struct(V_DVertPSOutput)
{ {
Semantic(Vec4, SV_Target0); Semantic(Vec4, sv_target0);
}; };
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////

View File

@ -31,7 +31,7 @@ Struct(PT_BlitPSInput)
Struct(PT_BlitPSOutput) 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; result.r = (f32)noise_val / (f32)U16Max;
PT_BlitPSOutput output; PT_BlitPSOutput output;
output.SV_Target0 = result; output.sv_target0 = result;
return output; return output;
} }

View File

@ -150,15 +150,15 @@ void UI_PushDefaults(void)
case UI_StyleKind_Font: { desc.style.Font = UI_GetDefaultFont(); } break; case UI_StyleKind_Font: { desc.style.Font = UI_GetDefaultFont(); } break;
u8 prefetch[127] = ZI; 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_FontSize: { desc.style.FontSize = 16.0f; } break;
case UI_StyleKind_Tint: { desc.style.Tint = Color_White; } 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_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_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_BackgroundTextureSliceUv: { desc.style.BackgroundTextureSliceUv = RNG2(VEC2(0, 0), VEC2(1, 1)); } break;
}; };
UI_PushStyle(desc); 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_Frame *frame = UI_CurrentFrame();
UI_CmdNode *n = PushStruct(frame->arena, UI_CmdNode); 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.key = key;
n->cmd.set_raw_texture.tex = tex; n->cmd.set_raw_texture.tex = tex;
n->cmd.set_raw_texture.uv0 = uv0; n->cmd.set_raw_texture.slice_uv = uv;
n->cmd.set_raw_texture.uv1 = uv1;
} }
++frame->cmds_count; ++frame->cmds_count;
SllQueuePush(frame->first_cmd_node, frame->last_cmd_node, n); 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; b32 is_cursor_in_box = 0;
{ {
/* TODO: More efficient test. This logic is just copied from the renderer's SDF function for now. */ /* TODO: More efficient test. This logic is just copied from the renderer's SDF function for now. */
Vec2 p0 = box->p0; Vec2 p0 = box->rect.p0;
Vec2 p1 = box->p1; Vec2 p1 = box->rect.p1;
Vec2 point = frame->cursor_pos; Vec2 point = frame->cursor_pos;
b32 is_corner = 0; 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 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_downs;
hovered_box->report.m1_held = 1; 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; 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->active = LerpF32(report->active, target_active, active_blend_rate);
report->hovered = LerpF32(report->hovered, target_hovered, hovered_blend_rate); report->hovered = LerpF32(report->hovered, target_hovered, hovered_blend_rate);
report->screen_p0 = box->p0; report->screen_rect = box->rect;
report->screen_p1 = box->p1;
} }
frame->hovered_box = hovered_box ? hovered_box->key : UI_NilKey; frame->hovered_box = hovered_box ? hovered_box->key : UI_NilKey;
@ -789,10 +787,9 @@ void UI_EndFrame(UI_Frame *frame)
} }
/* Fetch run */ /* Fetch run */
box->glyph_run = &GC_NilRun;
if (box->desc.text.len > 0) 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) if (box)
{ {
box->raw_texture = cmd.set_raw_texture.tex; box->raw_texture = cmd.set_raw_texture.tex;
box->raw_texture_uv0 = cmd.set_raw_texture.uv0; box->raw_texture_slice_uv = cmd.set_raw_texture.slice_uv;
box->raw_texture_uv1 = cmd.set_raw_texture.uv1;
} }
} break; } break;
} }
@ -908,13 +904,11 @@ void UI_EndFrame(UI_Frame *frame)
f32 text_size = 0; f32 text_size = 0;
if (axis == Axis_X) if (axis == Axis_X)
{ {
GC_RunRect rr = box->glyph_run->rects[box->glyph_run->count - 1]; text_size = box->glyph_run.baseline_length;
f32 baseline_length = rr.pos + rr.advance;
text_size = baseline_length;
} }
else 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); 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)) if (AnyBit(box->desc.flags, UI_BoxFlag_Floating))
{ {
Vec2 offset = box->desc.floating_pos; 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)) if (!AnyBit(box->desc.flags, UI_BoxFlag_NoFloatingClamp))
{ {
{ {
f32 overshoot = MaxF32(0, (final_pos.x + dims_vec.x) - parent->p1.x); f32 overshoot = MaxF32(0, (final_pos.x + dims_vec.x) - parent->rect.p1.x);
final_pos.x = MaxF32(parent->p0.x, final_pos.x - overshoot); 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); f32 overshoot = MaxF32((final_pos.y + dims_vec.y) - parent->rect.p1.y, 0);
final_pos.y = MaxF32(parent->p0.y, final_pos.y - overshoot); final_pos.y = MaxF32(parent->rect.p0.y, final_pos.y - overshoot);
} }
} }
} }
@ -1151,22 +1145,22 @@ void UI_EndFrame(UI_Frame *frame)
} break; } break;
} }
} }
final_pos.x = parent->p0.x + offset[0]; final_pos.x = parent->rect.p0.x + offset[0];
final_pos.y = parent->p0.y + offset[1]; final_pos.y = parent->rect.p0.y + offset[1];
parent->layout_cursor += dims_arr[parent->desc.child_layout_axis]; parent->layout_cursor += dims_arr[parent->desc.child_layout_axis];
} }
/* Submit position */ /* Submit position */
Vec2 floored_final_pos = FloorVec2(final_pos); Vec2 floored_final_pos = FloorVec2(final_pos);
Vec2 ceiled_dims = CeilVec2(dims_vec); Vec2 ceiled_dims = CeilVec2(dims_vec);
box->p0 = FloorVec2(floored_final_pos); box->rect.p0 = FloorVec2(floored_final_pos);
box->p1 = AddVec2(floored_final_pos, ceiled_dims); box->rect.p1 = AddVec2(floored_final_pos, ceiled_dims);
} }
/* Rounding */ /* Rounding */
{ {
UI_Round rounding = box->desc.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 min_half_dims = MinF32(half_dims.x, half_dims.y);
f32 final_rounding_tl = 0; f32 final_rounding_tl = 0;
f32 final_rounding_tr = 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)) 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 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->p1.x, parent->p0.y), VEC2(box->p1.x, box->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->p1.x, parent->p1.y), VEC2(box->p1.x, box->p1.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->p0.x, parent->p1.y), VEC2(box->p0.x, box->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_tl = MaxF32(final_rounding_tl, parent->rounding_tl - Vec2Len(vtl));
final_rounding_tr = MaxF32(final_rounding_tr, parent->rounding_tr - Vec2Len(vtr)); final_rounding_tr = MaxF32(final_rounding_tr, parent->rounding_tr - Vec2Len(vtr));
final_rounding_br = MaxF32(final_rounding_br, parent->rounding_br - Vec2Len(vbr)); 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]; UI_Box *box = boxes_pre[pre_index];
b32 is_visible = 1; b32 is_visible = 1;
is_visible = is_visible && (box->desc.tint.w != 0); is_visible = is_visible && (box->desc.tint.w != 0);
is_visible = is_visible && (box->p1.x > box->p0.x); is_visible = is_visible && (box->rect.p1.x > box->rect.p0.x);
is_visible = is_visible && (box->p1.y > box->p0.y); is_visible = is_visible && (box->rect.p1.y > box->rect.p0.y);
if (is_visible || AnyBit(frame->frame_flags, UI_FrameFlag_Debug)) if (is_visible || AnyBit(frame->frame_flags, UI_FrameFlag_Debug))
{ {
/* Box rect */ /* Box rect */
{ {
UI_DRect *rect = PushStruct(frame->rects_arena, UI_DRect); UI_DRect *rect = PushStruct(frame->rects_arena, UI_DRect);
rect->p0 = box->p0; rect->bounds = box->rect;
rect->p1 = box->p1;
rect->tex_uv0 = VEC2(0, 0);
rect->tex_uv1 = VEC2(1, 1);
rect->background_lin = LinearFromSrgb(box->desc.background_color); rect->background_lin = LinearFromSrgb(box->desc.background_color);
rect->border_lin = LinearFromSrgb(box->desc.border_color); rect->border_lin = LinearFromSrgb(box->desc.border_color);
rect->debug_lin = LinearFromSrgb(box->desc.debug_color); rect->debug_lin = LinearFromSrgb(box->desc.debug_color);
@ -1248,55 +1239,55 @@ void UI_EndFrame(UI_Frame *frame)
rect->br_rounding = box->rounding_br; rect->br_rounding = box->rounding_br;
rect->bl_rounding = box->rounding_bl; rect->bl_rounding = box->rounding_bl;
rect->tex = box->raw_texture; rect->tex = box->raw_texture;
rect->tex_uv0 = box->raw_texture_uv0; rect->tex_slice_uv = box->raw_texture_slice_uv;
rect->tex_uv1 = box->raw_texture_uv1;
} }
/* Text rects */ /* Text rects */
GC_Run *raw_run = box->glyph_run; GC_Run raw_run = box->glyph_run;
if (AnyBit(box->desc.flags, UI_BoxFlag_DrawText) && raw_run->loaded) if (AnyBit(box->desc.flags, UI_BoxFlag_DrawText) && raw_run.ready)
{ {
f32 max_baseline = box->p1.x - box->p0.x; f32 max_baseline = DimsFromRng2(box->rect).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; b32 should_truncate = raw_run.baseline_length > max_baseline && !AnyBit(box->desc.flags, UI_BoxFlag_NoTextTruncation);
/* Truncate run */ /* Truncate run */
GC_RunRect *truncated_rects = raw_run->rects; u64 final_rects_count = 0;
u32 truncated_rects_count = raw_run->count; GC_RunRect *final_rects = 0;
if (should_truncate && !AnyBit(box->desc.flags, UI_BoxFlag_NoTextTruncation)) if (should_truncate)
{ {
/* Get elipses run */ /* Get elipses run */
GC_Run *elipses_run = GC_RunFromString(scratch.arena, box->desc.font, Lit("...")); GC_Run elipses_run = GC_RunFromString(scratch.arena, Lit("..."), box->desc.font, box->desc.font_size);
if (elipses_run->count > 0) f32 elipses_start_pos = max_baseline - elipses_run.baseline_length;
/* 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)
{ {
max_baseline -= elipses_run->rects[elipses_run->count - 1].pos + elipses_run->rects[elipses_run->count - 1].advance; GC_RunRect rr = raw_run.rects[rect_idx];
if ((rr.baseline_pos + rr.advance) <= elipses_start_pos)
{
final_rects[final_rects_count] = rr;
final_rects_count += 1;
}
} }
/* Subtract glyphs */ /* Append elipses */
while (truncated_rects_count > 0) for (u64 rect_idx = 0; rect_idx < elipses_run.rects_count; ++rect_idx)
{ {
GC_RunRect rr = raw_run->rects[truncated_rects_count - 1]; GC_RunRect rr = elipses_run.rects[rect_idx];
if (rr.pos + rr.advance <= max_baseline) rr.baseline_pos += elipses_start_pos;
rr.bounds = AddRng2Vec2(rr.bounds, VEC2(elipses_start_pos, 0));
if ((rr.baseline_pos + rr.advance) <= max_baseline)
{ {
break; final_rects[final_rects_count] = rr;
} final_rects_count += 1;
--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;
} }
} }
} }
else
{
final_rects = raw_run.rects;
final_rects_count = raw_run.rects_count;
}
UI_AxisAlignment x_alignment = box->desc.child_alignment[Axis_X]; UI_AxisAlignment x_alignment = box->desc.child_alignment[Axis_X];
UI_AxisAlignment y_alignment = box->desc.child_alignment[Axis_Y]; UI_AxisAlignment y_alignment = box->desc.child_alignment[Axis_Y];
@ -1306,68 +1297,64 @@ void UI_EndFrame(UI_Frame *frame)
} }
/* Compute baseline */ /* Compute baseline */
f32 ascent = raw_run->ascent; f32 ascent = raw_run.font_ascent;
f32 descent = raw_run->descent; f32 font_descent = raw_run.font_descent;
f32 cap = raw_run->cap; f32 cap = raw_run.font_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_width = raw_run.baseline_length;
f32 baseline_height = ascent + descent; f32 baseline_height = ascent + font_descent;
f32 box_width = box->p1.x - box->p0.x; Vec2 box_dims = DimsFromRng2(box->rect);
f32 box_height = box->p1.y - box->p0.y;
Vec2 baseline = ZI; Vec2 baseline = ZI;
switch (x_alignment) switch (x_alignment)
{ {
case UI_AxisAlignment_Start: case UI_AxisAlignment_Start:
{ {
baseline.x = box->p0.x; baseline.x = box->rect.p0.x;
} break; } break;
case UI_AxisAlignment_End: case UI_AxisAlignment_End:
{ {
baseline.x = box->p1.x; baseline.x = box->rect.p1.x;
baseline.x -= baseline_width; baseline.x -= baseline_width;
} break; } break;
case UI_AxisAlignment_Center: case UI_AxisAlignment_Center:
{ {
baseline.x = box->p0.x; baseline.x = box->rect.p0.x;
baseline.x += (box_width - baseline_width) / 2; baseline.x += (box_dims.x - baseline_width) / 2;
} break; } break;
} }
switch (y_alignment) switch (y_alignment)
{ {
case UI_AxisAlignment_Start: case UI_AxisAlignment_Start:
{ {
baseline.y = box->p0.y; baseline.y = box->rect.p0.y;
baseline.y += ascent; baseline.y += ascent;
} break; } break;
case UI_AxisAlignment_End: case UI_AxisAlignment_End:
{ {
baseline.y = box->p1.y; baseline.y = box->rect.p1.y;
baseline.y -= descent; baseline.y -= font_descent;
} break; } break;
case UI_AxisAlignment_Center: case UI_AxisAlignment_Center:
{ {
baseline.y = box->p0.y; baseline.y = box->rect.p0.y;
baseline.y += box_height / 2; baseline.y += box_dims.y / 2;
baseline.y += cap / 2; baseline.y += cap / 2;
} break; } break;
} }
baseline = CeilVec2(baseline); baseline = CeilVec2(baseline);
/* Push text rects */ /* 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]; GC_RunRect rr = final_rects[rect_idx];
Vec2 glyph_size = rr.size; Vec2 glyph_dims = DimsFromRng2(rr.bounds);
if (glyph_size.x != 0 || glyph_size.y != 0) if (glyph_dims.x != 0 || glyph_dims.y != 0)
{ {
UI_DRect *rect = PushStruct(frame->rects_arena, UI_DRect); UI_DRect *rect = PushStruct(frame->rects_arena, UI_DRect);
rect->p0 = AddVec2(baseline, VEC2(rr.pos, 0)); rect->bounds = AddRng2Vec2(rr.bounds, baseline);
rect->p0 = AddVec2(rect->p0, rr.offset);
rect->p1 = AddVec2(rect->p0, glyph_size);
rect->debug_lin = LinearFromSrgb(box->desc.debug_color); rect->debug_lin = LinearFromSrgb(box->desc.debug_color);
rect->tint_lin = LinearFromSrgb(box->desc.tint); rect->tint_lin = LinearFromSrgb(box->desc.tint);
rect->tex = rr.tex; rect->tex = rr.tex;
rect->tex_uv0 = rr.uv.p0; rect->tex_slice_uv = rr.tex_uv;
rect->tex_uv1 = rr.uv.p1;
} }
} }
} }

View File

@ -110,11 +110,10 @@ Enum(UI_BoxFlag)
X(FontSize, u32) \ X(FontSize, u32) \
X(Text, String) \ X(Text, String) \
X(BackgroundTexture, G_Texture2DRef) \ X(BackgroundTexture, G_Texture2DRef) \
X(BackgroundTextureUv0, Vec2) \ X(BackgroundTextureSliceUv, Rng2) \
X(BackgroundTextureUv1, Vec2) \ /* -------------------------------------------- */ \
/* --------------------------------------- */ \ /* -------------- Virtual styles -------------- */ \
/* ----------- Virtual styles ----------- */ \ /* -------------------------------------------- */ \
/* --------------------------------------- */ \
X(BeginVirtualStyles_, i8) \ X(BeginVirtualStyles_, i8) \
X(ChildAlignment, UI_Alignment) \ X(ChildAlignment, UI_Alignment) \
X(AxisSize, UI_Size) \ X(AxisSize, UI_Size) \
@ -187,8 +186,7 @@ Struct(UI_Report)
Vec2 last_m1_offset; Vec2 last_m1_offset;
/* Where was this box last rendered in screen coordinates */ /* Where was this box last rendered in screen coordinates */
Vec2 screen_p0; Rng2 screen_rect;
Vec2 screen_p1;
}; };
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
@ -233,8 +231,7 @@ Struct(UI_Cmd)
{ {
UI_Key key; UI_Key key;
G_Texture2DRef tex; G_Texture2DRef tex;
Vec2 uv0; Rng2 slice_uv;
Vec2 uv1;
} set_raw_texture; } set_raw_texture;
}; };
}; };
@ -269,22 +266,20 @@ Struct(UI_Box)
//- Cmd data //- Cmd data
UI_BoxDesc desc; UI_BoxDesc desc;
G_Texture2DRef raw_texture; G_Texture2DRef raw_texture;
Vec2 raw_texture_uv0; Rng2 raw_texture_slice_uv;
Vec2 raw_texture_uv1;
//- Pre-layout data //- Pre-layout data
u64 pre_index; u64 pre_index;
u64 post_index; u64 post_index;
//- Layout data //- Layout data
GC_Run *glyph_run; GC_Run glyph_run;
f32 layout_cursor; f32 layout_cursor;
f32 solved_dims[Axis_CountXY]; f32 solved_dims[Axis_CountXY];
f32 final_children_size_accum[Axis_CountXY]; f32 final_children_size_accum[Axis_CountXY];
//- Layout results //- Layout results
Vec2 p0; Rng2 rect;
Vec2 p1;
f32 rounding_tl; f32 rounding_tl;
f32 rounding_tr; f32 rounding_tr;
f32 rounding_br; f32 rounding_br;
@ -443,7 +438,7 @@ UI_Style UI_PopStyle(UI_StyleDesc desc);
UI_Key UI_BuildBoxEx(UI_Key key); UI_Key UI_BuildBoxEx(UI_Key key);
#define UI_BuildBox() UI_BuildBoxEx(UI_TransKey()) #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 //~ Report

View File

@ -20,16 +20,16 @@ Struct(UI_DParams)
Struct(UI_DRect) Struct(UI_DRect)
{ {
Vec2 p0; Rng2 bounds;
Vec2 p1;
G_Texture2DRef tex;
Rng2 tex_slice_uv;
Vec4 tint_lin; Vec4 tint_lin;
Vec4 background_lin; Vec4 background_lin;
Vec4 border_lin; Vec4 border_lin;
Vec4 debug_lin; Vec4 debug_lin;
f32 border; f32 border;
Vec2 tex_uv0;
Vec2 tex_uv1;
G_Texture2DRef tex;
f32 tl_rounding; f32 tl_rounding;
f32 tr_rounding; f32 tr_rounding;

View File

@ -11,8 +11,8 @@ VertexShader(UI_DRectVS, UI_DRectPSInput)
UI_DRect rect = rects[SV_InstanceID]; UI_DRect rect = rects[SV_InstanceID];
Vec2 rect_uv = RectUvFromVertexId(SV_VertexID); Vec2 rect_uv = RectUvFromVertexId(SV_VertexID);
Vec2 tex_uv = lerp(rect.tex_uv0, rect.tex_uv1, rect_uv); Vec2 tex_uv = lerp(rect.tex_slice_uv.p0, rect.tex_slice_uv.p1, rect_uv);
Vec2 target_pos = lerp(rect.p0, rect.p1, rect_uv); Vec2 target_pos = lerp(rect.bounds.p0, rect.bounds.p1, rect_uv);
UI_DRectPSInput result; UI_DRectPSInput result;
result.sv_position = Vec4(NdcFromPos(target_pos, Vec2(params.target_size).xy), 0, 1); 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 p = input.sv_position.xy;
Vec2 rect_uv = input.rect_uv; Vec2 rect_uv = input.rect_uv;
Vec2 p0 = rect.p0; Vec2 p0 = rect.bounds.p0;
Vec2 p1 = rect.p1; Vec2 p1 = rect.bounds.p1;
/* Compute rect sdf (negative means pixel is inside of rect) */ /* 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)); 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); Vec4 result = tex.Sample(sampler, uv);
UI_BlitPSOutput output; UI_BlitPSOutput output;
output.SV_Target0 = result; output.sv_target0 = result;
return output; return output;
} }

View File

@ -28,7 +28,7 @@ Struct(UI_BlitPSInput)
Struct(UI_BlitPSOutput) Struct(UI_BlitPSOutput)
{ {
Semantic(Vec4, SV_Target0); Semantic(Vec4, sv_target0);
}; };
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////