animation work

This commit is contained in:
jacob 2026-01-28 21:41:16 -06:00
parent fb180afbc5
commit 9c0c649365
10 changed files with 532 additions and 217 deletions

View File

@ -3,11 +3,11 @@
////////////////////////////////////////////////////////////
//~ Shared constants
Global Readonly u32 ASE_huff_hclen_order[] = {
Global Readonly u32 ASE_HuffHclenOrder[] = {
16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
};
Global Readonly ASE_HuffEntry ASE_huff_length_table[] = {
Global Readonly ASE_HuffEntry ASE_HuffLenTable[] = {
{3, 0}, // 257
{4, 0}, // 258
{5, 0}, // 259
@ -39,7 +39,7 @@ Global Readonly ASE_HuffEntry ASE_huff_length_table[] = {
{258, 0}, // 285
};
Global Readonly ASE_HuffEntry ASE_huff_dist_table[] = {
Global Readonly ASE_HuffEntry ASE_HuffDistTable[] = {
{1, 0}, // 0
{2, 0}, // 1
{3, 0}, // 2
@ -72,7 +72,7 @@ Global Readonly ASE_HuffEntry ASE_huff_dist_table[] = {
{24577, 13}, // 29
};
Global Readonly u32 ASE_huff_bl_counts[][2] = {
Global Readonly u32 ASE_HuffBlCounts[][2] = {
{143, 8},
{255, 9},
{279, 7},
@ -117,7 +117,7 @@ void ASE_SkipBits(ASE_Bitbuff *bb, u32 nbits)
u32 ASE_ReverseBits(u32 v, u32 bit_count)
{
// 7 & 15 seem to be the most common bit_counts, so a
// more optimal path is layed out for them.
// more optimal path is laid out for them.
if (bit_count == 15)
{
u32 b1 = v & 0xFF;
@ -139,7 +139,6 @@ u32 ASE_ReverseBits(u32 v, u32 bit_count)
v = (v & 0xCC) >> 2 | (v & 0x33) << 2;
v = (v & 0xAA) >> 1 | (v & 0x55) << 1;
return v >> 1;
}
else
{
@ -162,9 +161,9 @@ ASE_HuffDict ASE_InitHuffDict(Arena *arena, u32 max_code_bits, u32 *bl_counts, u
result.entries = PushStructsNoZero(arena, ASE_HuffEntry, result.entries_count);
u32 code_length_hist[ASE_HuffBitCount] = Zi;
for (u32 i = 0; i < bl_counts_count; ++i)
for (u32 bl_count_index = 0; bl_count_index < bl_counts_count; ++bl_count_index)
{
u32 count = bl_counts[i];
u32 count = bl_counts[bl_count_index];
Assert(count <= countof(code_length_hist));
++code_length_hist[count];
}
@ -172,27 +171,27 @@ ASE_HuffDict ASE_InitHuffDict(Arena *arena, u32 max_code_bits, u32 *bl_counts, u
u32 next_code[ASE_HuffBitCount] = Zi;
next_code[0] = 0;
code_length_hist[0] = 0;
for (u32 i = 1; i < countof(next_code); ++i)
for (u32 code_index = 1; code_index < countof(next_code); ++code_index)
{
next_code[i] = ((next_code[i - 1] + code_length_hist[i - 1]) << 1);
next_code[code_index] = ((next_code[code_index - 1] + code_length_hist[code_index - 1]) << 1);
}
for (u32 i = 0; i < bl_counts_count; ++i)
for (u32 bl_count_index = 0; bl_count_index < bl_counts_count; ++bl_count_index)
{
u32 code_bits = bl_counts[i];
u32 code_bits = bl_counts[bl_count_index];
if (code_bits)
{
Assert(code_bits < countof(next_code));
u32 code = next_code[code_bits]++;
u32 arbitrary_bits = result.max_code_bits - code_bits;
u32 entry_count = (1 << arbitrary_bits);
// TODO: Optimize this. It's bloating load times.
for (u32 entry_index = 0; entry_index < entry_count; ++entry_index)
{
// TODO: Optimize this. It's bloating up the loading times.
u32 base_index = (code << arbitrary_bits) | entry_index;
u32 index = ASE_ReverseBits(base_index, result.max_code_bits);
ASE_HuffEntry *entry = &result.entries[index];
entry->symbol = (u16)i;
entry->symbol = (u16)bl_count_index;
entry->bits_used = (u16)code_bits;
}
}
@ -274,7 +273,7 @@ void ASE_Inflate(u8 *dst, u8 *encoded)
u32 hclen_bl_counts[19] = Zi;
for (u32 i = 0; i < hclen; ++i)
{
u32 code = ASE_huff_hclen_order[i];
u32 code = ASE_HuffHclenOrder[i];
hclen_bl_counts[code] = ASE_ConsumeBits(&bb, 3);
}
ASE_HuffDict dict_huffman = ASE_InitHuffDict(temp.arena, 7, hclen_bl_counts, countof(hclen_bl_counts));
@ -325,10 +324,10 @@ void ASE_Inflate(u8 *dst, u8 *encoded)
hlit = 288;
hdist = 32;
u32 index = 0;
for (u32 i = 0; i < countof(ASE_huff_bl_counts); ++i)
for (u32 i = 0; i < countof(ASE_HuffBlCounts); ++i)
{
u32 bit_count = ASE_huff_bl_counts[i][1];
u32 last_valuie = ASE_huff_bl_counts[i][0];
u32 bit_count = ASE_HuffBlCounts[i][1];
u32 last_valuie = ASE_HuffBlCounts[i][0];
while (index <= last_valuie)
{
lit_len_dist_table[index++] = bit_count;
@ -339,7 +338,6 @@ void ASE_Inflate(u8 *dst, u8 *encoded)
// Decode
ASE_HuffDict lit_len_huffman = ASE_InitHuffDict(temp.arena, 15, lit_len_dist_table, hlit);
ASE_HuffDict dist_huffman = ASE_InitHuffDict(temp.arena, 15, lit_len_dist_table + hlit, hdist);
for (;;)
{
u32 lit_len = ASE_DecodeHuffDict(&lit_len_huffman, &bb);
@ -350,7 +348,7 @@ void ASE_Inflate(u8 *dst, u8 *encoded)
else if (lit_len >= 257)
{
u32 length_index = (lit_len - 257);
ASE_HuffEntry length_entry = ASE_huff_length_table[length_index];
ASE_HuffEntry length_entry = ASE_HuffLenTable[length_index];
u32 length = length_entry.symbol;
if (length_entry.bits_used > 0)
{
@ -359,7 +357,7 @@ void ASE_Inflate(u8 *dst, u8 *encoded)
}
u32 dist_index = ASE_DecodeHuffDict(&dist_huffman, &bb);
ASE_HuffEntry dist_entry = ASE_huff_dist_table[dist_index];
ASE_HuffEntry dist_entry = ASE_HuffDistTable[dist_index];
u32 distance = dist_entry.symbol;
if (dist_entry.bits_used > 0)
{
@ -510,7 +508,7 @@ ASE_DecodedImage ASE_DecodeImage(Arena *arena, String encoded)
// TODO: Optimize this. Naive memzero is bloating the decode time for large images.
result.pixels = PushStructs(arena, u32, image_width * image_height);
u32 num_layers = 0;
u32 layers_count = 0;
ASE_Layer *layer_head = 0;
ASE_Cel *cel_head = 0;
@ -519,23 +517,23 @@ ASE_DecodedImage ASE_DecodeImage(Arena *arena, String encoded)
//////////////////////////////
//- Iterate frames
u32 num_frames = 0;
u32 frames_count = 0;
for (u16 i = 0; i < ase_header.frames; ++i)
{
ASE_FrameHeader frame_header;
BB_ReadBytes(&bbr, StringFromStruct(&frame_header));
u32 num_chunks = frame_header.chunks_new;
if (num_chunks == 0)
u32 chunks_count = frame_header.chunks_new;
if (chunks_count == 0)
{
Assert(frame_header.chunks_old != 0xFFFF);
num_chunks = frame_header.chunks_old;
chunks_count = frame_header.chunks_old;
}
//////////////////////////////
//- Iterate chunks
for (u32 j = 0; j < num_chunks; ++j)
for (u32 j = 0; j < chunks_count; ++j)
{
u32 chunk_size = BB_ReadUBits(&bbr, 32);
ASE_ChunkKind chunk_type = BB_ReadUBits(&bbr, 16);
@ -597,7 +595,7 @@ ASE_DecodedImage ASE_DecodeImage(Arena *arena, String encoded)
layer->tileset_index = BB_ReadUBits(&bbr, 32);
}
layer->index = num_layers++;
layer->index = layers_count++;
} break;
//////////////////////////////
@ -624,7 +622,7 @@ ASE_DecodedImage ASE_DecodeImage(Arena *arena, String encoded)
cel->z_index = BB_ReadIBits(&bbr, 16);
BB_ReadSeekBytes(&bbr, sizeof(u8) * 5);
cel->frame_index = num_frames;
cel->frame_index = frames_count;
switch (cel->type)
{
@ -663,13 +661,13 @@ ASE_DecodedImage ASE_DecodeImage(Arena *arena, String encoded)
} break;
}
}
++num_frames;
++frames_count;
}
//////////////////////////////
//- Create ordered layers array
ASE_Layer **layers_ordered = PushStructsNoZero(scratch.arena, ASE_Layer *, num_layers);
ASE_Layer **layers_ordered = PushStructsNoZero(scratch.arena, ASE_Layer *, layers_count);
for (ASE_Layer *layer = layer_head; layer; layer = layer->next)
{
layers_ordered[layer->index] = layer;
@ -678,13 +676,13 @@ ASE_DecodedImage ASE_DecodeImage(Arena *arena, String encoded)
//////////////////////////////
//- Link cels
ASE_Cel **cels_ordered = PushStructsNoZero(scratch.arena, ASE_Cel *, num_frames * num_layers);
ASE_Cel **cels_ordered = PushStructsNoZero(scratch.arena, ASE_Cel *, frames_count * layers_count);
for (ASE_Cel *cel = cel_head; cel; cel = cel->next)
{
cels_ordered[(cel->frame_index * num_layers) + cel->layer_index] = cel;
cels_ordered[(cel->frame_index * layers_count) + cel->layer_index] = cel;
if (cel->type == ASE_CelKind_Linked)
{
ASE_Cel *ref_cel = cels_ordered[(cel->frame_pos * num_layers) + cel->layer_index];
ASE_Cel *ref_cel = cels_ordered[(cel->frame_pos * layers_count) + cel->layer_index];
cel->width = ref_cel->width;
cel->height = ref_cel->height;
cel->pixels = ref_cel->pixels;
@ -803,13 +801,13 @@ ASE_DecodedSheet ASE_DecodeSheet(Arena *arena, String encoded)
u64 image_height = frame_height * frames_y;
ASE_MakeDimensionsSquareish(&ase_header, &frames_x, &frames_y, &image_width, &image_height);
u32 num_frames = 0;
u32 frames_count = 0;
ASE_Frame *first_frame = 0;
u32 num_spans = 0;
u32 spans_count = 0;
ASE_Span *first_span = 0;
u32 num_slice_keys = 0;
u32 slice_keys_count = 0;
ASE_SliceKey *first_slice_key = 0;
//////////////////////////////
@ -820,11 +818,11 @@ ASE_DecodedSheet ASE_DecodeSheet(Arena *arena, String encoded)
ASE_FrameHeader frame_header;
BB_ReadBytes(&bbr, StringFromStruct(&frame_header));
u32 num_chunks = frame_header.chunks_new;
if (num_chunks == 0)
u32 chunks_count = frame_header.chunks_new;
if (chunks_count == 0)
{
Assert(frame_header.chunks_old != 0xFFFF);
num_chunks = frame_header.chunks_old;
chunks_count = frame_header.chunks_old;
}
ASE_Frame *frame = PushStruct(arena, ASE_Frame);
@ -848,7 +846,7 @@ ASE_DecodedSheet ASE_DecodeSheet(Arena *arena, String encoded)
//////////////////////////////
//- Iterate chunks
for (u32 j = 0; j < num_chunks; ++j)
for (u32 j = 0; j < chunks_count; ++j)
{
u32 chunk_size = BB_ReadUBits(&bbr, 32);
ASE_ChunkKind chunk_type = BB_ReadUBits(&bbr, 16);
@ -886,7 +884,7 @@ ASE_DecodedSheet ASE_DecodeSheet(Arena *arena, String encoded)
span->name = (String) { str_len, PushStructsNoZero(arena, u8, str_len) };
BB_ReadBytes(&bbr, span->name);
++num_spans;
++spans_count;
}
} break;
@ -900,8 +898,8 @@ ASE_DecodedSheet ASE_DecodeSheet(Arena *arena, String encoded)
slice_key->next = first_slice_key;
first_slice_key = slice_key;
u32 num_slices = BB_ReadUBits(&bbr, 32);
slice_key->num_slices = num_slices;
u32 slices_count = BB_ReadUBits(&bbr, 32);
slice_key->slices_count = slices_count;
u32 flags = BB_ReadUBits(&bbr, 32);
BB_ReadSeekBytes(&bbr, 4);
@ -910,7 +908,7 @@ ASE_DecodedSheet ASE_DecodeSheet(Arena *arena, String encoded)
slice_key->name = (String) { str_len, PushStructsNoZero(arena, u8, str_len) };
BB_ReadBytes(&bbr, slice_key->name);
for (u32 k = 0; k < num_slices; ++k)
for (u32 k = 0; k < slices_count; ++k)
{
ASE_Slice *slice = PushStruct(arena, ASE_Slice);
slice->next = slice_key->first_slice;
@ -937,14 +935,14 @@ ASE_DecodedSheet ASE_DecodeSheet(Arena *arena, String encoded)
slice->rect.p1 = VEC2I32(x + width, y + width);
}
++num_slice_keys;
++slice_keys_count;
} break;
// TODO
//case ASE_ChunkKind_Userdata
}
}
++num_frames;
++frames_count;
}
// Assert all data was read
@ -952,9 +950,9 @@ ASE_DecodedSheet ASE_DecodeSheet(Arena *arena, String encoded)
result.image_size = VEC2(image_width, image_height);
result.frame_size = VEC2(frame_width, frame_height);
result.num_frames = num_frames;
result.num_spans = num_spans;
result.num_slice_keys = num_slice_keys;
result.frames_count = frames_count;
result.spans_count = spans_count;
result.slice_keys_count = slice_keys_count;
result.first_frame = first_frame;
result.first_span = first_span;
result.first_slice_key = first_slice_key;

View File

@ -27,7 +27,7 @@ Struct(ASE_Frame)
Struct(ASE_SliceKey)
{
String name;
u32 num_slices;
u32 slices_count;
ASE_Slice *first_slice;
ASE_SliceKey *next;
};
@ -61,9 +61,9 @@ Struct(ASE_DecodedSheet)
{
Vec2 image_size;
Vec2 frame_size;
u32 num_frames;
u32 num_spans;
u32 num_slice_keys;
u32 frames_count;
u32 spans_count;
u32 slice_keys_count;
ASE_Frame *first_frame;
ASE_Span *first_span;
ASE_SliceKey *first_slice_key;
@ -120,7 +120,7 @@ Packed(Struct(ASE_Header)
u32 _2;
u8 palette_entry;
u8 _3[3];
u16 num_colors;
u16 colors_count;
u8 pixel_width;
u8 pixel_height;
i16 grid_x;

View File

@ -1,5 +1,3 @@
// Math functions are default 32 bit (f32, i32, etc) unless specified
////////////////////////////////////////////////////////////
//~ Min / max
@ -706,14 +704,8 @@ Vec2 NormRng2(Rng2 r, Vec2 v)
{
Vec2 result = Zi;
Vec2 dims = SubVec2(r.p1, r.p0);
if (dims.x != 0)
{
result.x = v.x / dims.x;
}
if (dims.y != 0)
{
result.y = v.y / dims.y;
}
result.x = v.x / dims.x;
result.y = v.y / dims.y;
return result;
}

View File

@ -1,8 +1,6 @@
// Math functions are default 32 bit (f32, i32, etc) unless specified
#define Pi ((f32)3.14159265358979323846)
#define Tau ((f32)6.28318530717958647693)
#define GoldenRatio ((f32)1.61803398874989484820)
#define Pi (3.14159265358979323846)
#define Tau (6.28318530717958647693)
#define GoldenRatio (1.61803398874989484820)
////////////////////////////////////////////////////////////
//~ Axis types
@ -22,12 +20,12 @@ Enum(Axis)
//- Vec2
Union(Vec2) { struct { f32 x, y; }; f32 v[2]; };
Union(Vec2F64) { struct { f64 x, y; }; f64 v[2]; };
Union(Vec2I32) { struct { i32 x, y; }; i32 v[2]; };
Union(Vec2I64) { struct { i64 x, y; }; i64 v[2]; };
Union(Vec2U32) { struct { u32 x, y; }; u32 v[2]; };
Union(Vec2U64) { struct { u64 x, y; }; u64 v[2]; };
Union(Vec2) { struct { f32 x, y; }; struct { f32 r, g; }; f32 v[2]; };
Union(Vec2F64) { struct { f64 x, y; }; struct { f64 r, g; }; f64 v[2]; };
Union(Vec2I32) { struct { i32 x, y; }; struct { i32 r, g; }; i32 v[2]; };
Union(Vec2I64) { struct { i64 x, y; }; struct { i64 r, g; }; i64 v[2]; };
Union(Vec2U32) { struct { u32 x, y; }; struct { u32 r, g; }; u32 v[2]; };
Union(Vec2U64) { struct { u64 x, y; }; struct { u64 r, g; }; u64 v[2]; };
Struct(Vec2Array) { Vec2 *points; u64 count; };
@ -47,12 +45,12 @@ Struct(Vec2Array) { Vec2 *points; u64 count; };
//- Vec3
Union(Vec3) { struct { f32 x, y, z; }; f32 v[3]; };
Union(Vec3F64) { struct { f64 x, y, z; }; f64 v[3]; };
Union(Vec3I32) { struct { i32 x, y, z; }; i32 v[3]; };
Union(Vec3I64) { struct { i64 x, y, z; }; i64 v[3]; };
Union(Vec3U32) { struct { u32 x, y, z; }; u32 v[3]; };
Union(Vec3U64) { struct { u64 x, y, z; }; u64 v[3]; };
Union(Vec3) { struct { f32 x, y, z; }; struct { f32 r, g, b; }; f32 v[3]; };
Union(Vec3F64) { struct { f64 x, y, z; }; struct { f64 r, g, b; }; f64 v[3]; };
Union(Vec3I32) { struct { i32 x, y, z; }; struct { i32 r, g, b; }; i32 v[3]; };
Union(Vec3I64) { struct { i64 x, y, z; }; struct { i64 r, g, b; }; i64 v[3]; };
Union(Vec3U32) { struct { u32 x, y, z; }; struct { u32 r, g, b; }; u32 v[3]; };
Union(Vec3U64) { struct { u64 x, y, z; }; struct { u64 r, g, b; }; u64 v[3]; };
Struct(Vec3Array) { Vec3 *points; u64 count; };
@ -72,12 +70,12 @@ Struct(Vec3Array) { Vec3 *points; u64 count; };
//- Vec4
Union(Vec4) { struct { f32 x, y, z, w; }; f32 v[4]; };
Union(Vec4F64) { struct { f64 x, y, z, w; }; f64 v[4]; };
Union(Vec4I32) { struct { i32 x, y, z, w; }; i32 v[4]; };
Union(Vec4I64) { struct { i64 x, y, z, w; }; i64 v[4]; };
Union(Vec4U32) { struct { u32 x, y, z, w; }; u32 v[4]; };
Union(Vec4U64) { struct { u64 x, y, z, w; }; u64 v[4]; };
Union(Vec4) { struct { f32 x, y, z, w; }; struct { f32 r, g, b, a; }; f32 v[4]; };
Union(Vec4F64) { struct { f64 x, y, z, w; }; struct { f64 r, g, b, a; }; f64 v[4]; };
Union(Vec4I32) { struct { i32 x, y, z, w; }; struct { i32 r, g, b, a; }; i32 v[4]; };
Union(Vec4I64) { struct { i64 x, y, z, w; }; struct { i64 r, g, b, a; }; i64 v[4]; };
Union(Vec4U32) { struct { u32 x, y, z, w; }; struct { u32 r, g, b, a; }; u32 v[4]; };
Union(Vec4U64) { struct { u64 x, y, z, w; }; struct { u64 r, g, b, a; }; u64 v[4]; };
Struct(Vec4Array) { Vec4 *points; u64 count; };
@ -114,6 +112,9 @@ Struct(RngU64) { u64 min, max; };
#define RNGU32(min, max) (RngU32) { (min), (max) }
#define RNGU64(min, max) (RngU64) { (min), (max) }
#define RngEmpty RNG(Inf, -Inf)
#define RngInf RNG(-Inf, Inf)
//- Rng2
Struct(Rng2) { Vec2 p0, p1; };
@ -130,6 +131,9 @@ Struct(Rng2U64) { Vec2U64 p0, p1; };
#define RNG2U32(p0, p1) (Rng2U32) { (p0), (p1) }
#define RNG2U64(p0, p1) (Rng2U64) { (p0), (p1) }
#define Rng2Empty RNG2(VEC2(Inf, Inf), VEC2(-Inf, -Inf))
#define Rng2Inf RNG2(VEC2(-Inf, -Inf), VEC2(Inf, Inf))
//- Rng3
Struct(Rng3) { Vec3 p0, p1; };
@ -146,6 +150,9 @@ Struct(Rng3U64) { Vec3U64 p0, p1; };
#define RNG3U32(p0, p1) (Rng3U32) { (p0), (p1) }
#define RNG3U64(p0, p1) (Rng3U64) { (p0), (p1) }
#define Rng3Empty RNG3(VEC3(Inf, Inf, Inf), VEC3(-Inf, -Inf, -Inf))
#define Rng3Inf RNG3(VEC3(-Inf, -Inf, -Inf), VEC3(Inf, Inf, Inf))
////////////////////////////////////////////////////////////
//~ Affine types
@ -186,13 +193,10 @@ Struct(SoftSpring)
////////////////////////////////////////////////////////////
//~ Mat4x4 types
Struct(Mat4x4)
Union(Mat4x4)
{
union
{
struct { Vec4 bx, by, bz, bw; };
f32 e[4][4];
};
struct { Vec4 bx, by, bz, bw; };
f32 e[4][4];
};
////////////////////////////////////////////////////////////
@ -414,7 +418,6 @@ Vec4 MulVec4(Vec4 v, f32 s);
Vec4 MulVec4Vec4(Vec4 a, Vec4 b);
//- Lerp
Vec4 LerpVec4(Vec4 v0, Vec4 v1, f32 t);
//- Conversion

View File

@ -10,14 +10,14 @@ AlignedStruct(WaveCtx, CachelineSize)
void *udata;
// Sync barrier
Atomic32Padded sync_count;
Atomic64Padded sync_gen;
Atomic32Padded sync_count;
// Broadcast barrier
void *broadcast_data;
Atomic64Padded broadcast_gen;
Atomic32Padded ack_count;
Atomic64Padded ack_gen;
Atomic32Padded ack_count;
};
AlignedStruct(WaveLaneCtx, CachelineSize)

View File

@ -20,7 +20,6 @@ GC_FontKey GC_FontKeyFromResource(ResourceKey resource)
u64 GC_HashFromGlyphDesc(GC_GlyphDesc desc)
{
// TODO: Lower font-size precision to prevent unique hashes for slightly-different font sizes
return MixU64s(desc.font.r.v, ((u64)desc.codepoint << 32) | *(u32 *)&desc.font_size);
}
@ -28,6 +27,7 @@ u64 GC_HashFromGlyphDesc(GC_GlyphDesc desc)
//~ Run
// TODO: Thread-local cache
// TODO: Lower font size precision to prevent unique fonts for every slightly-different size
GC_Run GC_RunFromString32(Arena *arena, String32 str32, GC_FontKey font, f32 font_size)
{
GC_Run result = Zi;
@ -75,7 +75,7 @@ GC_Run GC_RunFromString32(Arena *arena, String32 str32, GC_FontKey font, f32 fon
uncached_codepoints[uncached_codepoints_count] = codepoint;
uncached_codepoints_count += 1;
}
else if (completion < Atomic64Fetch(&glyph->async_copy_completion_target))
else if (completion < Atomic64Fetch(&glyph->atlas_copy_completion_target))
{
pending_glyphs_count += 1;
}
@ -119,7 +119,7 @@ GC_Run GC_RunFromString32(Arena *arena, String32 str32, GC_FontKey font, f32 fon
glyph = PushStruct(perm, GC_Glyph);
glyph->desc = desc;
glyph->hash = hash;
Atomic64FetchSet(&glyph->async_copy_completion_target, I64Max);
Atomic64FetchSet(&glyph->atlas_copy_completion_target, I64Max);
SllStackPush(bin->first, glyph);
// Create cmd
{
@ -175,8 +175,8 @@ GC_Run GC_RunFromString32(Arena *arena, String32 str32, GC_FontKey font, f32 fon
Rng2 bounds = glyph->bounds;
rect->tex = glyph->atlas->tex_ref;
rect->tex_slice = glyph->tex_slice;
rect->tex_slice_uv = glyph->tex_slice_uv;
rect->tex_slice = glyph->atlas_slice;
rect->tex_slice_uv = glyph->atlas_slice_uv;
rect->baseline_pos = baseline_pos;
rect->advance = advance;
@ -280,7 +280,6 @@ void GC_TickAsync(WaveLaneCtx *lane, AsyncFrameLaneCtx *base_async_lane_frame)
}
// TODO: Only sync first lane?
WaveSync(lane);
////////////////////////////
@ -298,6 +297,7 @@ void GC_TickAsync(WaveLaneCtx *lane, AsyncFrameLaneCtx *base_async_lane_frame)
Vec2I32 image_dims = ttf_result.image_dims;
// Allocate atlas rect
// TODO: Use a more efficient atlas packing algorithm for less wasted space
GC_Atlas *atlas = GC.first_atlas;
b32 can_use_atlas = 0;
@ -323,7 +323,6 @@ void GC_TickAsync(WaveLaneCtx *lane, AsyncFrameLaneCtx *base_async_lane_frame)
SllStackPush(GC.first_atlas, atlas);
++GC.atlases_count;
}
// Determine pos in atlas
pos_in_atlas = atlas->cur_pos;
atlas->cur_row_height = MaxI32(atlas->cur_row_height, image_dims.y);
@ -344,13 +343,13 @@ void GC_TickAsync(WaveLaneCtx *lane, AsyncFrameLaneCtx *base_async_lane_frame)
}
}
// Atlas info
// Fill glyph atlas info
glyph->atlas = atlas;
glyph->tex_slice = RNG2I32(pos_in_atlas, AddVec2I32(pos_in_atlas, image_dims));
glyph->tex_slice_uv.p0.x = (f32)glyph->tex_slice.p0.x / (f32)atlas->dims.x;
glyph->tex_slice_uv.p0.y = (f32)glyph->tex_slice.p0.y / (f32)atlas->dims.x;
glyph->tex_slice_uv.p1.x = (f32)glyph->tex_slice.p1.x / (f32)atlas->dims.x;
glyph->tex_slice_uv.p1.y = (f32)glyph->tex_slice.p1.y / (f32)atlas->dims.x;
glyph->atlas_slice = RNG2I32(pos_in_atlas, AddVec2I32(pos_in_atlas, image_dims));
glyph->atlas_slice_uv.p0.x = (f32)glyph->atlas_slice.p0.x / (f32)atlas->dims.x;
glyph->atlas_slice_uv.p0.y = (f32)glyph->atlas_slice.p0.y / (f32)atlas->dims.x;
glyph->atlas_slice_uv.p1.x = (f32)glyph->atlas_slice.p1.x / (f32)atlas->dims.x;
glyph->atlas_slice_uv.p1.y = (f32)glyph->atlas_slice.p1.y / (f32)atlas->dims.x;
// Copy to atlas
u32 *image_pixels = ttf_result.image_pixels;
@ -358,7 +357,7 @@ void GC_TickAsync(WaveLaneCtx *lane, AsyncFrameLaneCtx *base_async_lane_frame)
{
G_CopyCpuToTexture(
cl,
glyph->atlas->tex, VEC3I32(glyph->tex_slice.p0.x, glyph->tex_slice.p0.y, 0),
glyph->atlas->tex, VEC3I32(glyph->atlas_slice.p0.x, glyph->atlas_slice.p0.y, 0),
image_pixels, VEC3I32(image_dims.x, image_dims.y, 1),
RNG3I32(
VEC3I32(0, 0, 0),
@ -374,7 +373,7 @@ void GC_TickAsync(WaveLaneCtx *lane, AsyncFrameLaneCtx *base_async_lane_frame)
{
GC_Cmd *cmd = &async->cmds.v[cmd_idx];
GC_Glyph *glyph = cmd->glyph;
Atomic64Set(&glyph->async_copy_completion_target, completion_target);
Atomic64Set(&glyph->atlas_copy_completion_target, completion_target);
}
}
}

View File

@ -36,7 +36,7 @@ Struct(GC_Glyph)
GC_GlyphDesc desc;
u64 hash;
Atomic64 async_copy_completion_target;
Atomic64 atlas_copy_completion_target;
// Font info
f32 font_size;
@ -50,8 +50,8 @@ Struct(GC_Glyph)
// Atlas info
GC_Atlas *atlas;
Rng2I32 tex_slice;
Rng2 tex_slice_uv;
Rng2I32 atlas_slice;
Rng2 atlas_slice_uv;
};
Struct(GC_GlyphBin)

BIN
src/pp/pp_res/sprite/bla3.ase (Stored with Git LFS)

Binary file not shown.

View File

@ -25,9 +25,9 @@ SPR_SpanKey SPR_SpanKeyFromName(String name)
return result;
}
SPR_LayerKey SPR_LayerKeyFromName(String name)
SPR_MarkKey SPR_MarkKeyFromName(String name)
{
SPR_LayerKey result = Zi;
SPR_MarkKey result = Zi;
result.v = HashString(name);
return result;
}
@ -35,15 +35,110 @@ SPR_LayerKey SPR_LayerKeyFromName(String name)
////////////////////////////////////////////////////////////
//~ Lookup
SPR_Slice SPR_SliceFromSheet(SPR_SheetKey sheet, SPR_SpanKey span, i64 frame_seq)
SPR_SheetEntry *SPR_SheetFromKey(SPR_SheetKey key)
{
SPR_SheetEntry *result = 0;
return result;
}
SPR_Slice SPR_SliceFromSheet(SPR_SheetKey sheet_key, SPR_SpanKey span_key, i64 frame_seq)
{
SPR_Slice result = Zi;
// FIXME: Default nil result
// i64 completion = G_CompletionValueFromQueue(G_QueueKind_AsyncCopy);
// if (completion < Atomic64Fetch(&sheet->atlas_copy_completion_target))
SPR_SpanEntry *span = SPR_SpanEntryFromSheet(sheet_key, span_key);
if (span && span->slices_count > 0)
{
SPR_SpanStatus status = Atomic32Fetch(&span->status);
if (status >= SPR_SpanStatus_Rasterized)
{
i64 frame_idx = frame_seq % span->slices_count;
SPR_SliceEntry *slice_entry = &span->slices[frame_idx];
result.tex = slice_entry->atlas->tex;
result.tex_rect_uv = slice_entry->atlas_rect_uv;
result.dims = slice_entry->dims;
result.ready = 1;
}
result.exists = 1;
}
// SPR_SheetEntry *sheet = SPR_SheetFromKey(sheet_key, 1);
// {
// SPR_SpanEntry *span = 0;
// {
// SPR_SpanBin *span_bin = &sheet->span_bins[span_key.v % sheet->span_bins_count];
// span = span_bin->first;
// for (; span; span = span->next_in_bin)
// {
// if (span->key.v == span_key.v)
// {
// break;
// }
// }
// }
// if (span && span->slices_count > 0)
// {
// i64 completion = G_CompletionValueFromQueue(G_QueueKind_AsyncCopy);
// if (completion < Atomic64Fetch(&sheet->atlas_copy_completion_target))
// {
// i64 frame_idx = frame_seq % span->slices_count;
// SPR_SliceEntry *slice_entry = &span->slices[frame_idx];
// result.tex = slice_entry->atlas->tex;
// result.tex_rect_uv = slice_entry->atlas_rect_uv;
// result.dims = slice_entry->dims;
// result.ready = 1;
// }
// result.exists = 1;
// }
// }
return result;
}
Xform SPR_XformFromSheet(SPR_SheetKey sheet, SPR_LayerKey layer, SPR_SpanKey span, i64 frame_seq)
SPR_Mark SPR_MarkFromSheet(SPR_SheetKey sheet_key, SPR_SpanKey span_key, SPR_MarkKey mark_key, i64 frame_seq)
{
Xform result = Zi;
SPR_Mark result = Zi;
// SPR_SheetEntry *sheet = SPR_SheetFromKey(sheet_key, 0);
SPR_SpanEntry *span = SPR_SpanEntryFromSheet(sheet_key, span_key);
if (span && span->slices_count > 0)
{
SPR_SpanStatus status = Atomic32Fetch(&span->status);
if (status >= SPR_SpanStatus_Processed)
{
i64 frame_idx = frame_seq % span->slices_count;
SPR_MarkEntry *mark_entry = 0
{
SPR_MarkBin *mark_bin = &span->mark_bins[mark_key.v % span->mark_bins_count];
mark_entry = mark_bin->first;
for (; mark_entry; mark_entry = mark_entry->next_in_bin)
{
if (mark_entry->key.v == mark_key.v)
{
break;
}
}
}
if (mark_entry)
{
SPR_SliceEntry *slice_entry = &span->slices[frame_idx];
result.tex = slice_entry->atlas->tex;
result.tex_rect_uv = slice_entry->atlas_rect_uv;
result.dims = slice_entry->dims;
result.ready = 1;
}
}
result.exists = 1;
}
return result;
}
@ -51,10 +146,10 @@ Xform SPR_XformFromSheet(SPR_SheetKey sheet, SPR_LayerKey layer, SPR_SpanKey spa
// SPR_Slice SPR_SliceFromSheet(SPR_SheetKey sheet, SPR_SpanKey span, i64 frame_seq)
// SPR_SliceEntry SPR_SliceFromSheet(SPR_SheetKey sheet, SPR_SpanKey span, i64 frame_seq)
// {
// // TODO: Ability to specify desired alpha modes (Straight, Premultiplied, Opaque)
// SPR_Slice result = Zi;
// SPR_SliceEntry result = Zi;
// // FIXME
// u64 hash = sheet.r.v;
@ -78,9 +173,9 @@ Xform SPR_XformFromSheet(SPR_SheetKey sheet, SPR_LayerKey layer, SPR_SpanKey spa
// }
// if (entry)
// {
// if (completion >= Atomic64Fetch(&entry->async_copy_completion_target))
// if (completion >= Atomic64Fetch(&entry->atlas_copy_completion_target))
// {
// result = entry->slice;
// result = entry->slice_entry;
// }
// found = 1;
// }
@ -104,9 +199,9 @@ Xform SPR_XformFromSheet(SPR_SheetKey sheet, SPR_LayerKey layer, SPR_SpanKey spa
// }
// if (entry)
// {
// if (completion >= Atomic64Fetch(&entry->async_copy_completion_target))
// if (completion >= Atomic64Fetch(&entry->atlas_copy_completion_target))
// {
// result = entry->slice;
// result = entry->slice_entry;
// }
// found = 1;
// }
@ -116,7 +211,7 @@ Xform SPR_XformFromSheet(SPR_SheetKey sheet, SPR_LayerKey layer, SPR_SpanKey spa
// entry = PushStruct(perm, SPR_SliceEntry);
// entry->hash = hash;
// Atomic64FetchSet(&entry->async_copy_completion_target, I64Max);
// Atomic64FetchSet(&entry->atlas_copy_completion_target, I64Max);
// entry->sheet = sheet;
// entry->slice_name = PushString(perm, slice_name);
// SllStackPush(bin->first, entry);
@ -161,114 +256,341 @@ void SPR_TickAsync(WaveLaneCtx *lane, AsyncFrameLaneCtx *base_async_lane_frame)
SPR_AsyncCtx *async = &SPR.async;
Arena *frame_arena = base_async_lane_frame->arena;
// TODO: Go wide
// TODO: Distribute rasterization accross wave
if (lane->idx == 0)
{
if (Atomic32Fetch(&SPR.new_cmds_present))
{
Atomic32Set(&SPR.new_cmds_present, 0);
SPR_CmdNode *first_cmd_node = 0;
SPR_CmdNode *last_cmd_node = 0;
u64 cmds_count = 0;
i64 cmds_count = 0;
SPR_Cmd *cmds = 0;
{
Lock lock = LockE(&SPR.submit.mutex);
{
first_cmd_node = SPR.submit.first;
last_cmd_node = SPR.submit.last;
cmds_count = SPR.submit.count;
cmds = PushStructsNoZero(frame_arena, SPR_Cmd, SPR.submit.count);
i64 cmd_idx = 0;
for (SPR_CmdNode *n = SPR.submit.first; n; n = n->next)
{
cmds[cmd_idx] = n->cmd;
++cmd_idx;
}
// Reset submission queue
SPR.submit.first_free = SPR.submit.first;
SPR.submit.count = 0;
SPR.submit.first = 0;
SPR.submit.last = 0;
SPR.submit.count = 0;
}
Unlock(&lock);
}
if (cmds_count > 0)
{
for (SPR_CmdNode *n = first_cmd_node; n; n = n->next)
G_CommandListHandle cl = G_PrepareCommandList(G_QueueKind_AsyncCopy);
for (i64 cmd_idx = 0; cmd_idx < cmds_count; ++cmd_idx)
{
SPR_Cmd cmd = n->cmd;
SPR_SliceEntry *slice_entry = cmd.entry;
SPR_Cmd *cmd = &cmds[cmd_idx];
SPR_SheetEntry *sheet = cmd->sheet;
ASE_Meta *meta = &sheet->meta;
SPR_SheetBin *sheet_bin = &async->sheet_bins[slice_entry->sheet.r.v % countof(async->sheet_bins)];
SPR_SheetEntry *sheet = sheet_bin->first;
for (; sheet; sheet = sheet->next)
String encoded = DataFromResource(sheet->key.r);
String name = NameFromResource(sheet->key.r);
LogInfoF("Rasterizing sprite sheet %F \"%F\" (%F bytes)", FmtHandle(sheet->key.r), FmtString(name), FmtUint(encoded.len));
for (ASE_Span *ase_span = meta.first_span; ase_span; ase_span = ase_span->next)
{
if (sheet->key.r.v == slice_entry->sheet.r.v)
u64 span_hash = HashString(ase_span->name);
SPR_SpanBin *span_bin = &sheet->span_bins[span_hash % sheet->span_bins_count];
SPR_SpanEntry *span = span_bin->first;
for (; span; span = span->next_in_bin)
{
break;
}
}
// Decode sheet
// TODO: Distribute chunk decoding accross wave
// TODO: Use atlas allocator and separate slices into unique textures
// TODO: Reuse command list for all uploads
if (!sheet)
{
sheet = PushStruct(perm, SPR_SheetEntry);
sheet->key = slice_entry->sheet;
SllStackPush(sheet_bin->first, sheet);
String encoded = DataFromResource(sheet->key.r);
String name = NameFromResource(sheet->key.r);
LogInfoF("Decoding sprite sheet \"%F\" (%F bytes)", FmtString(name), FmtUint(encoded.len));
ASE_DecodedImage decoded_image = ASE_DecodeImage(frame_arena, encoded);
ASE_DecodedSheet decoded_sheet = ASE_DecodeSheet(frame_arena, encoded);
if (decoded_image.ok)
{
G_ResourceHandle gpu_resource = Zi;
G_ArenaHandle gpu_perm = G_PermArena();
G_CommandListHandle cl = G_PrepareCommandList(G_QueueKind_AsyncCopy);
if (span->key.v == span_hash)
{
Vec3I32 dims = Zi;
dims.x = decoded_image.width;
dims.y = decoded_image.height;
dims.z = 1;
gpu_resource = G_PushTexture2D(
gpu_perm, cl,
G_Format_R8G8B8A8_Unorm_Srgb,
dims,
G_Layout_AnyQueue_ShaderRead_CopyRead_CopyWrite_Present
);
G_CopyCpuToTexture(
cl,
gpu_resource, VEC3I32(0, 0, 0),
decoded_image.pixels, dims,
RNG3I32(
VEC3I32(0, 0, 0),
dims
)
);
break;
}
i64 completion_target = G_CommitCommandList(cl);
sheet->async_copy_completion_target = completion_target;
sheet->tex = G_PushTexture2DRef(gpu_perm, gpu_resource);
// LogDebugF("Decoded with ref: %F", FmtUint(slice_entry->slice.tex.v));
}
else
if (span)
{
// TODO: Use 'missing' texture
sheet->tex = G_BlankTexture2D();
sheet->async_copy_completion_target = 0;
i64 slice_idx = 0;
for (ASE_Frame *ase_frame = span->first_frame; ase_frame && slice_idx < span->slices_count; ase_frame = ase_frame->next)
{
SPR_SliceEntry *slice_entry = &span->slice_entry[slice_idx];
// // Determine slice_entry bounds
// Rng2 frame_bounds = Rng2Empty;
// for (ASE_Layer *ase_layer = ase_frame->first_layer; ase_layer; ase_layer = ase_layer->next)
// {
// if (!StringBeginsWith(ase_layer->name, Lit(".")))
// {
// frame_bounds = UnionRng2(frame_bounds);
// }
// }
// Vec2 dims = DimsFromRng2(frame_bounds);
if (!IsRng2Empty(frame_bounds))
{
// Rasterize slice_entry
u32 *pixels = PushStructs(frame_arena, u32, slice_entry->dims.x * slice_entry->dims.y);
for (ASE_Layer *ase_layer = ase_frame->first_layer; ase_layer; ase_layer = ase_layer->next)
{
SPR_LayerKind kind = SPR_LayerKindFromName(ase_layer->name);
if (kind == SPR_LayerKind_Standard)
{
ASE_RasterizeLayer(ase_layer, pixels, slice_entry->dims);
}
}
// Allocate atlas rect
// TODO: Use a more efficient atlas packing algorithm for less wasted space
SPR_Atlas *atlas = SPR.first_atlas;
b32 can_use_atlas = 0;
Vec2I32 pos_in_atlas = Zi;
while (can_use_atlas == 0)
{
// Create atlas
if (!atlas)
{
Arena *perm = PermArena();
atlas = PushStruct(perm, SPR_Atlas);
i32 atlas_size = MaxI32(1024, NextPow2U64(MaxI32(slice_entry->dims.x, slice_entry->dims.y)));
atlas->dims = VEC2I32(atlas_size, atlas_size);
{
G_ArenaHandle gpu_perm = G_PermArena();
atlas->tex = G_PushTexture2D(
gpu_perm, cl,
G_Format_R8G8B8A8_Unorm_Srgb,
atlas->dims,
G_Layout_AnyQueue_ShaderRead_CopyRead_CopyWrite_Present,
);
atlas->tex_ref = G_PushTexture2DRef(gpu_perm, atlas->tex);
}
SllStackPush(SPR.first_atlas, atlas);
++SPR.atlases_count;
}
// Determine pos in atlas
pos_in_atlas = atlas->cur_pos;
atlas->cur_row_height = MaxI32(atlas->cur_row_height, slice_entry->dims.y);
if (pos_in_atlas.x + slice_entry->dims.x > atlas->dims.x);
{
atlas->cur_pos.x = 0;
atlas->cur_pos.y += atlas->cur_row_height;
atlas->cur_row_height = slice_entry->dims.y;
}
atlas->cur_pos.x += slice_entry->dims.x;
if (atlas->cur_pos.x < atlas->dims.x && atlas->cur_pos.y < atlas->dims.y)
{
can_use_atlas = 1;
}
else
{
atlas = 0;
}
}
// Fill slice_entry atlas info
slice_entry->atlas = atlas;
slice_entry->atlas_rect = RNG2I32(pos_in_atlas, AddVec2I32(pos_in_atlas, slice_entry->dims));
slice_entry->atlas_rect_uv.p0.x = (f32)slice_entry->atlas_rect.p0.x / (f32)atlas->dims.x;
slice_entry->atlas_rect_uv.p0.y = (f32)slice_entry->atlas_rect.p0.y / (f32)atlas->dims.x;
slice_entry->atlas_rect_uv.p1.x = (f32)slice_entry->atlas_rect.p1.x / (f32)atlas->dims.x;
slice_entry->atlas_rect_uv.p1.y = (f32)slice_entry->atlas_rect.p1.y / (f32)atlas->dims.x;
// Copy to atlas
G_CopyCpuToTexture(
cl,
atlas->tex, VEC3I32(pos_in_atlas.x, pos_in_atlas.y, 0),
pixels, VEC3I32(slice_entry->dims.x, slice_entry->dims.y, 1),
RNG3I32(
VEC3I32(0, 0, 0),
VEC3I32(slice_entry->dims.x, slice_entry->dims.y, 1)
)
);
}
++slice_idx;
}
}
}
slice_entry->slice.tex = sheet->tex;
// FIXME: Real uv
slice_entry->slice.uv_rect.p0 = VEC2(0, 0);
slice_entry->slice.uv_rect.p1= VEC2(1, 1);
Atomic64Set(&slice_entry->async_copy_completion_target, sheet->async_copy_completion_target);
}
i64 completion_target = G_CommitCommandList(cl);
// Update completion targets
for (i64 cmd_idx = 0; cmd_idx < cmds_count; ++cmd_idx)
{
SPR_Cmd *cmd = &cmds[cmd_idx];
SPR_SheetEntry *sheet = cmd->sheet;
Atomic64Set(&sheet->atlas_copy_completion_target, completion_target);
}
// Free cmds
Lock lock = LockE(&SPR.submit.mutex);
{
last_cmd_node->next = SPR.submit.first_free;
SPR.submit.first_free = first_cmd_node;
}
Unlock(&lock);
}
// ASE_DecodedImage decoded_image = ASE_DecodeImage(frame_arena, encoded);
// ASE_DecodedSheet decoded_sheet = ASE_DecodeSheet(frame_arena, encoded);
// if (decoded_image.ok)
// {
// G_ResourceHandle gpu_resource = Zi;
// G_ArenaHandle gpu_perm = G_PermArena();
// G_CommandListHandle cl = G_PrepareCommandList(G_QueueKind_AsyncCopy);
// {
// Vec3I32 dims = Zi;
// dims.x = decoded_image.width;
// dims.y = decoded_image.height;
// dims.z = 1;
// gpu_resource = G_PushTexture2D(
// gpu_perm, cl,
// G_Format_R8G8B8A8_Unorm_Srgb,
// dims,
// G_Layout_AnyQueue_ShaderRead_CopyRead_CopyWrite_Present
// );
// G_CopyCpuToTexture(
// cl,
// gpu_resource, VEC3I32(0, 0, 0),
// decoded_image.pixels, dims,
// RNG3I32(
// VEC3I32(0, 0, 0),
// dims
// )
// );
// }
// i64 completion_target = G_CommitCommandList(cl);
// sheet->atlas_copy_completion_target = completion_target;
// sheet->tex = G_PushTexture2DRef(gpu_perm, gpu_resource);
// // LogDebugF("Decoded with ref: %F", FmtUint(slice_entry->slice_entry.tex.v));
// }
// else
// {
// // TODO: Use 'missing' texture
// sheet->tex = G_BlankTexture2D();
// sheet->atlas_copy_completion_target = 0;
// }
// }
// slice_entry->slice_entry.tex = sheet->tex;
// // FIXME: Real uv
// slice_entry->slice_entry.uv_rect.p0 = VEC2(0, 0);
// slice_entry->slice_entry.uv_rect.p1= VEC2(1, 1);
// Atomic64Set(&slice_entry->atlas_copy_completion_target, sheet->atlas_copy_completion_target);
}
}
}
// void SPR_TickAsync(WaveLaneCtx *lane, AsyncFrameLaneCtx *base_async_lane_frame)
// {
// Arena *perm = PermArena();
// SPR_AsyncCtx *async = &SPR.async;
// Arena *frame_arena = base_async_lane_frame->arena;
// // TODO: Go wide
// if (lane->idx == 0)
// {
// if (Atomic32Fetch(&SPR.new_cmds_present))
// {
// Atomic32Set(&SPR.new_cmds_present, 0);
// SPR_CmdNode *first_cmd_node = 0;
// SPR_CmdNode *last_cmd_node = 0;
// u64 cmds_count = 0;
// {
// Lock lock = LockE(&SPR.submit.mutex);
// {
// first_cmd_node = SPR.submit.first;
// last_cmd_node = SPR.submit.last;
// cmds_count = SPR.submit.count;
// SPR.submit.first = 0;
// SPR.submit.last = 0;
// SPR.submit.count = 0;
// }
// Unlock(&lock);
// }
// if (cmds_count > 0)
// {
// for (SPR_CmdNode *n = first_cmd_node; n; n = n->next)
// {
// SPR_Cmd cmd = n->cmd;
// SPR_SliceEntry *slice_entry = cmd.entry;
// SPR_SheetBin *sheet_bin = &async->sheet_bins[slice_entry->sheet.r.v % countof(async->sheet_bins)];
// SPR_SheetEntry *sheet = sheet_bin->first;
// for (; sheet; sheet = sheet->next)
// {
// if (sheet->key.r.v == slice_entry->sheet.r.v)
// {
// break;
// }
// }
// // Decode sheet
// // TODO: Distribute chunk decoding accross wave
// // TODO: Use atlas allocator and separate slices into unique textures
// // TODO: Reuse command list for all uploads
// if (!sheet)
// {
// sheet = PushStruct(perm, SPR_SheetEntry);
// sheet->key = slice_entry->sheet;
// SllStackPush(sheet_bin->first, sheet);
// String encoded = DataFromResource(sheet->key.r);
// String name = NameFromResource(sheet->key.r);
// LogInfoF("Decoding sprite sheet \"%F\" (%F bytes)", FmtString(name), FmtUint(encoded.len));
// ASE_DecodedImage decoded_image = ASE_DecodeImage(frame_arena, encoded);
// ASE_DecodedSheet decoded_sheet = ASE_DecodeSheet(frame_arena, encoded);
// if (decoded_image.ok)
// {
// G_ResourceHandle gpu_resource = Zi;
// G_ArenaHandle gpu_perm = G_PermArena();
// G_CommandListHandle cl = G_PrepareCommandList(G_QueueKind_AsyncCopy);
// {
// Vec3I32 dims = Zi;
// dims.x = decoded_image.width;
// dims.y = decoded_image.height;
// dims.z = 1;
// gpu_resource = G_PushTexture2D(
// gpu_perm, cl,
// G_Format_R8G8B8A8_Unorm_Srgb,
// dims,
// G_Layout_AnyQueue_ShaderRead_CopyRead_CopyWrite_Present
// );
// G_CopyCpuToTexture(
// cl,
// gpu_resource, VEC3I32(0, 0, 0),
// decoded_image.pixels, dims,
// RNG3I32(
// VEC3I32(0, 0, 0),
// dims
// )
// );
// }
// i64 completion_target = G_CommitCommandList(cl);
// sheet->atlas_copy_completion_target = completion_target;
// sheet->tex = G_PushTexture2DRef(gpu_perm, gpu_resource);
// // LogDebugF("Decoded with ref: %F", FmtUint(slice_entry->slice_entry.tex.v));
// }
// else
// {
// // TODO: Use 'missing' texture
// sheet->tex = G_BlankTexture2D();
// sheet->atlas_copy_completion_target = 0;
// }
// }
// slice_entry->slice_entry.tex = sheet->tex;
// // FIXME: Real uv
// slice_entry->slice_entry.uv_rect.p0 = VEC2(0, 0);
// slice_entry->slice_entry.uv_rect.p1= VEC2(1, 1);
// Atomic64Set(&slice_entry->atlas_copy_completion_target, sheet->atlas_copy_completion_target);
// }
// // Free cmds
// Lock lock = LockE(&SPR.submit.mutex);
// {
// last_cmd_node->next = SPR.submit.first_free;
// SPR.submit.first_free = first_cmd_node;
// }
// Unlock(&lock);
// }
// }
// }
// }

View File

@ -3,11 +3,11 @@
Struct(SPR_SheetKey) { ResourceKey r; };
Struct(SPR_SpanKey) { u64 v; };
Struct(SPR_LayerKey) { u64 v; };
Struct(SPR_MarkKey) { u64 v; };
#define SPR_NilSheetKey ((SPR_SheetKey) { 0 })
#define SPR_NilSpanKey ((SPR_SpanKey) { 0 })
#define SPR_NilLayerKey ((SPR_LayerKey) { 0 })
#define SPR_NilRayKey ((SPR_MarkKey) { 0 })
////////////////////////////////////////////////////////////
//~ Slice types
@ -30,7 +30,7 @@ Struct(SPR_SliceEntry)
SPR_SheetKey sheet;
u64 hash;
Atomic64 async_copy_completion_target;
Atomic64 atlas_copy_completion_target;
String slice_name;
@ -47,7 +47,7 @@ Struct(SPR_SheetEntry)
{
SPR_SheetEntry *next;
SPR_SheetKey key;
i64 async_copy_completion_target;
i64 atlas_copy_completion_target;
G_Texture2DRef tex;
};
@ -107,13 +107,14 @@ void SPR_Bootstrap(void);
SPR_SheetKey SPR_SheetKeyFromResource(ResourceKey resource);
SPR_SpanKey SPR_SpanKeyFromName(String name);
SPR_LayerKey SPR_LayerKeyFromName(String name);
SPR_MarkKey SPR_MarkKeyFromName(String name);
////////////////////////////////////////////////////////////
//~ Lookup
//~ Lookup helpers
SPR_Slice SPR_SliceFromSheet(SPR_SheetKey sheet, SPR_SpanKey span, i64 frame_seq);
Xform SPR_XformFromSheet(SPR_SheetKey sheet, SPR_LayerKey layer, SPR_SpanKey span, i64 frame_seq);
SPR_SpanEntry *SPR_SpanEntryFromSheet(SPR_SheetKey sheet_key, SPR_SpanKey span_key);
SPR_Slice SPR_SliceFromSheet(SPR_SheetKey sheet_key, SPR_SpanKey span_key, i64 frame_seq);
SPR_Mark SPR_MarkFromSheet(SPR_SheetKey sheet_key, SPR_SpanKey span_key, SPR_MarkKey ray_key, i64 frame_seq);
////////////////////////////////////////////////////////////
//~ Async