diff --git a/src/ase/ase.c b/src/ase/ase.c index 2f4f33c5..f3be049f 100644 --- a/src/ase/ase.c +++ b/src/ase/ase.c @@ -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; diff --git a/src/ase/ase.h b/src/ase/ase.h index d8b4a3bd..a61211ab 100644 --- a/src/ase/ase.h +++ b/src/ase/ase.h @@ -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; diff --git a/src/base/base_math.c b/src/base/base_math.c index d7096c75..f23bd861 100644 --- a/src/base/base_math.c +++ b/src/base/base_math.c @@ -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; } diff --git a/src/base/base_math.h b/src/base/base_math.h index 71573665..c0522c20 100644 --- a/src/base/base_math.h +++ b/src/base/base_math.h @@ -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 diff --git a/src/base/base_wave.h b/src/base/base_wave.h index 4cc09d0a..ff2058d1 100644 --- a/src/base/base_wave.h +++ b/src/base/base_wave.h @@ -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) diff --git a/src/glyph_cache/glyph_cache.c b/src/glyph_cache/glyph_cache.c index 9d8af52c..da456c01 100644 --- a/src/glyph_cache/glyph_cache.c +++ b/src/glyph_cache/glyph_cache.c @@ -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); } } } diff --git a/src/glyph_cache/glyph_cache.h b/src/glyph_cache/glyph_cache.h index 81744500..de537755 100644 --- a/src/glyph_cache/glyph_cache.h +++ b/src/glyph_cache/glyph_cache.h @@ -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) diff --git a/src/pp/pp_res/sprite/bla3.ase b/src/pp/pp_res/sprite/bla3.ase index 49ef607d..da66208e 100644 --- a/src/pp/pp_res/sprite/bla3.ase +++ b/src/pp/pp_res/sprite/bla3.ase @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3363401b8877ac5d4c1063c002a94ef73c1fc7f8902c02baeade16d201eb2ad7 -size 3058 +oid sha256:6fbdcd64e7ac8230452fe6438fb84944c88533a8384f8108c873dc175b1ea7c3 +size 3059 diff --git a/src/sprite/sprite.c b/src/sprite/sprite.c index b3a2c3a7..cc40d243 100644 --- a/src/sprite/sprite.c +++ b/src/sprite/sprite.c @@ -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); +// } +// } +// } +// } diff --git a/src/sprite/sprite.h b/src/sprite/sprite.h index aeead3fd..e250e54d 100644 --- a/src/sprite/sprite.h +++ b/src/sprite/sprite.h @@ -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