diff --git a/src/base/base_win32/base_win32.c b/src/base/base_win32/base_win32.c index e0f195a8..ba918b02 100644 --- a/src/base/base_win32/base_win32.c +++ b/src/base/base_win32/base_win32.c @@ -211,7 +211,7 @@ String SwappedStateFromName(Arena *arena, String name) { TempArena scratch = BeginScratch(arena); String result = Zi; - String path = StringF(scratch.arena, "%F/swap/%F.swp", FmtString(GetAppDirectory()), FmtString(name)); + String path = StringF(scratch.arena, "%F/swap/%F", FmtString(GetAppDirectory()), FmtString(name)); wchar_t *path_wstr = WstrFromString(scratch.arena, path); HANDLE handle = CreateFileW(path_wstr, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); if (handle != INVALID_HANDLE_VALUE) @@ -240,7 +240,7 @@ void WriteSwappedState(String name, String data) { TempArena scratch = BeginScratchNoConflict(); String dir_path = PathFromString(scratch.arena, StringF(scratch.arena, "%F/swap", FmtString(GetAppDirectory())), '\\'); - String path = PathFromString(scratch.arena, StringF(scratch.arena, "%F/%F.swp", FmtString(dir_path), FmtString(name)), '\\'); + String path = PathFromString(scratch.arena, StringF(scratch.arena, "%F/%F", FmtString(dir_path), FmtString(name)), '\\'); wchar_t *dir_path_wstr = WstrFromString(scratch.arena, dir_path); wchar_t *path_wstr = WstrFromString(scratch.arena, path); SHCreateDirectoryExW(0, dir_path_wstr, 0); diff --git a/src/pp/pp_sim/pp_sim_core.c b/src/pp/pp_sim/pp_sim_core.c index bd20e1f9..77760c1d 100644 --- a/src/pp/pp_sim/pp_sim_core.c +++ b/src/pp/pp_sim/pp_sim_core.c @@ -223,7 +223,7 @@ S_Shape S_LocalShapeFromEnt(S_Ent *ent) { S_Shape result = Zi; - // TODO: This is a temporary hack. Use prefab-lookup table. + // TODO: This is a temporary hack. We should eventually switch to using a prefab lookup table. if (ent->is_player) { result = S_ShapeFromDesc( @@ -1277,7 +1277,7 @@ void S_TickForever(WaveLaneCtx *lane) String packed = Zi; if (swapin) { - packed = SwappedStateFromName(frame_arena, Lit("pp_sim")); + packed = SwappedStateFromName(frame_arena, Lit("pp_sim.swp")); } S_UnpackedWorld unpacked = S_UnpackWorld(frame_arena, packed); @@ -1306,7 +1306,7 @@ void S_TickForever(WaveLaneCtx *lane) if (swapout) { String packed = S_PackWorld(frame_arena, world); - WriteSwappedState(Lit("pp_sim"), packed); + WriteSwappedState(Lit("pp_sim.swp"), packed); } } diff --git a/src/pp/pp_sim/pp_sim_shared.cg b/src/pp/pp_sim/pp_sim_shared.cg index 30f2cb31..155f78ea 100644 --- a/src/pp/pp_sim/pp_sim_shared.cg +++ b/src/pp/pp_sim/pp_sim_shared.cg @@ -14,3 +14,20 @@ i32 S_TileIdxFromTilePos(Vec2I32 p) i32 result = ClampI32(p.x + (p.y * S_TilesPitch), 0, S_TilesCount); return result; } + +#if IsLanguageC + String S_TileNameFromKind(S_TileKind kind) + { + PERSIST Readonly String tile_names[S_TileKind_COUNT] = { + #define X(name, ...) [S_TileKind_##name] = CompLit(#name), + S_TilesXMacro(X) + #undef X + }; + String result = Zi; + if (kind >= 0 && kind < countof(tile_names)) + { + result = tile_names[kind]; + } + return result; + } +#endif diff --git a/src/pp/pp_sim/pp_sim_shared.cgh b/src/pp/pp_sim/pp_sim_shared.cgh index d9c24054..5b1cc356 100644 --- a/src/pp/pp_sim/pp_sim_shared.cgh +++ b/src/pp/pp_sim/pp_sim_shared.cgh @@ -1,7 +1,7 @@ //////////////////////////////////////////////////////////// //~ Tile types -#define S_WorldPitch 60.0 +#define S_WorldPitch 64.0 #define S_TilesPitch (S_WorldPitch * 2) #define S_TilesCount (S_TilesPitch * S_TilesPitch) @@ -11,12 +11,12 @@ X(Wall) \ /* -------------------- */ -// Tiles enum +//- Tiles kinds enum Enum(S_TileKind) { -#define X(name, ...) S_TileKind_##name, - S_TilesXMacro(X) -#undef X + #define X(name, ...) S_TileKind_##name, + S_TilesXMacro(X) + #undef X S_TileKind_COUNT }; @@ -25,3 +25,7 @@ Enum(S_TileKind) Vec2I32 S_TilePosFromWorldPos(Vec2 p); i32 S_TileIdxFromTilePos(Vec2I32 p); + +#if IsLanguageC + String S_TileNameFromKind(S_TileKind kind); +#endif diff --git a/src/pp/pp_vis/pp_vis.lay b/src/pp/pp_vis/pp_vis.lay index 83eb70aa..fe4c85df 100644 --- a/src/pp/pp_vis/pp_vis.lay +++ b/src/pp/pp_vis/pp_vis.lay @@ -4,12 +4,13 @@ //- Dependencies @Dep pp +@Dep pp_sim +@Dep sprite @Dep gpu @Dep glyph_cache @Dep platform @Dep window @Dep ui -@Dep pp_sim ////////////////////////////// //- Resources diff --git a/src/pp/pp_vis/pp_vis_core.c b/src/pp/pp_vis/pp_vis_core.c index 69e0af6d..1a5acd1c 100644 --- a/src/pp/pp_vis/pp_vis_core.c +++ b/src/pp/pp_vis/pp_vis_core.c @@ -558,7 +558,7 @@ void V_TickForever(WaveLaneCtx *lane) } else { - String swap_encoded = SwappedStateFromName(frame->arena, Lit("pp_vis")); + String swap_encoded = SwappedStateFromName(frame->arena, Lit("pp_vis.swp")); bb = BB_BuffFromString(swap_encoded); br = BB_ReaderFromBuff(&bb); } @@ -586,7 +586,7 @@ void V_TickForever(WaveLaneCtx *lane) // Write swapout if (swapout) { - WriteSwappedState(Lit("pp_vis"), STRING(BB_GetNumBytesWritten(&bw), BB_GetWrittenRaw(&bw))); + WriteSwappedState(Lit("pp_vis.swp"), STRING(BB_GetNumBytesWritten(&bw), BB_GetWrittenRaw(&bw))); } } } @@ -3194,6 +3194,18 @@ void V_TickForever(WaveLaneCtx *lane) G_ResourceHandle gpu_params = G_PushBufferFromCpuCopy(frame->gpu_arena, frame->cl, StringFromStruct(¶ms)); G_StructuredBufferRef gpu_params_ref = G_PushStructuredBufferRef(frame->gpu_arena, gpu_params, V_GpuParams); + // Fill tile textures + { + ResourceKey tiles_resource = ResourceKeyFromStore(&P_Resources, Lit("sprite/tiles.ase")); + for (S_TileKind tile_kind = 0; tile_kind < S_TileKind_COUNT; ++tile_kind) + { + String tile_name = S_TileNameFromKind(tile_kind); + SPR_Key sprite_key = SPR_KeyFromResource(tiles_resource); + SPR_Slice tile_slice = SPR_SliceFromKey(sprite_key, tile_name); + params.tile_slices[tile_kind] = tile_slice; + } + } + // Upload tiles if (tiles_dirty) { diff --git a/src/pp/pp_vis/pp_vis_shared.cgh b/src/pp/pp_vis/pp_vis_shared.cgh index 2405551a..84002fd7 100644 --- a/src/pp/pp_vis/pp_vis_shared.cgh +++ b/src/pp/pp_vis/pp_vis_shared.cgh @@ -84,6 +84,8 @@ Struct(V_GpuParams) G_RWTexture2DRef cells; G_RWTexture2DRef stains; G_RWTexture2DRef drynesses; + + SPR_Slice tile_slices[S_TileKind_COUNT]; }; //////////////////////////////////////////////////////////// diff --git a/src/sprite/sprite.c b/src/sprite/sprite.c index aa1be02f..e3a145f0 100644 --- a/src/sprite/sprite.c +++ b/src/sprite/sprite.c @@ -1,433 +1,40 @@ -Readonly SPR_Texture SPR_NilTexture = Zi; -Readonly SPR_Sheet SPR_NilSheet = Zi; SPR_Ctx SPR = Zi; //////////////////////////////////////////////////////////// -//~ Load jobs +//~ Bootstrap -JobImpl(SPR_LoadTexture, sig, _) +void SPR_Bootstrap(void) { - TempArena scratch = BeginScratchNoConflict(); - SPR_Entry *entry = sig->entry; - ResourceKey resource = entry->resource; - b32 ok = 1; - SPR_Texture *texture = &entry->texture; - texture->valid = 1; - - String name = NameFromResource(resource); - String data = DataFromResource(resource); - - ASE_DecodedImage decoded = ASE_DecodeImage(scratch.arena, data); - ok = decoded.ok; - - // Upload texture to gpu - if (ok) - { - GPU_ArenaHandle gpu_perm = GPU_PermArena(); - GPU_ResourceHandle gpu_resource = GPU_PushTexture2D( - gpu_perm, - GPU_Format_R8G8B8A8_Unorm_Srgb, - VEC2I32(decoded.width, decoded.height), - GPU_Layout_AnyQueue_ShaderRead_CopyRead_CopyWrite_Present - ); - // texture->texture = gpu_tex; - texture->width = decoded.width; - texture->height = decoded.height; - - GPU_CommandListHandle cl = GPU_PrepareCommandList(); - { - GPU_ReadTexelsFromCpu( - cl, - gpu_resource, VEC3I32(0,0,0), - decoded.pixels, VEC3I32(decoded.width, decoded.height, 1), - RNG3I32(VEC3I32(0,0,0), VEC3I32(decoded.width, decoded.height, 1)) - ); - } - GPU_CommitCommandList(cl, GPU_QueueKind_AsyncCopy); - } - - EndScratch(scratch); -} - -JobImpl(SPR_LoadSheet, sig, _) -{ - TempArena scratch = BeginScratchNoConflict(); - Arena *perm = PermArena(); - SPR_Entry *entry = sig->entry; - ResourceKey resource = entry->resource; - b32 ok = 1; - SPR_Sheet *sheet = &entry->sheet; - sheet->valid = 1; - - String name = NameFromResource(resource); - String data = DataFromResource(resource); - - ASE_DecodedSheet decoded = ASE_DecodeSheet(scratch.arena, data); - ok = decoded.ok; - - if (ok) - { - Vec2 image_size = decoded.image_size; - Vec2 frame_size = decoded.frame_size; - Vec2 frame_center = MulVec2(decoded.frame_size, 0.5f); - - sheet->image_size = image_size; - sheet->frame_size = frame_size; - - // Init frames - sheet->frames_count = decoded.num_frames; - sheet->frames = PushStructs(perm, SPR_Frame, sheet->frames_count); - for (ASE_Frame *src = decoded.first_frame; src; src = src->next) - { - SPR_Frame *dst = &sheet->frames[src->index]; - dst->index = src->index; - dst->duration = src->duration; - dst->clip.p0 = VEC2((f32)src->rect.p0.x / (f32)image_size.x, (f32)src->rect.p0.y / (f32)image_size.y); - dst->clip.p1 = VEC2((f32)src->rect.p1.x / (f32)image_size.x, (f32)src->rect.p1.y / (f32)image_size.y); - } - - // Init spans - sheet->spans_count = decoded.num_spans; - sheet->span_bins_count = MaxU32(AlignU64ToNextPow2(sheet->spans_count * 2), 1); - sheet->spans = PushStructs(perm, SPR_Span, sheet->spans_count); - sheet->span_bins = PushStructs(perm, SPR_SpanBin, sheet->span_bins_count); - { - i32 span_index = 0; - for (ASE_Span *src = decoded.first_span; src; src = src->next) - { - SPR_Span *dst = &sheet->spans[span_index]; - dst->hash = HashFnv64(Fnv64Basis, src->name); - dst->name = PushString(perm, src->name); - dst->start = src->start; - dst->end = src->end; - // Insert span into bin - { - SPR_SpanBin *bin = &sheet->span_bins[dst->hash % sheet->span_bins_count]; - SllQueuePushN(bin->first, bin->last, dst, next_in_bin); - } - ++span_index; - } - } - - // Init slice groups - sheet->slice_groups_count = decoded.num_slice_keys; - sheet->slice_group_bins_count = MaxU32(AlignU64ToNextPow2(sheet->slice_groups_count * 2), 1); - sheet->slice_groups = PushStructs(perm, SPR_SliceGroup, sheet->slice_groups_count); - sheet->slice_group_bins = PushStructs(perm, SPR_SliceGroupBin, sheet->slice_group_bins_count); - { - i32 group_index = 0; - for (ASE_SliceKey *src_group = decoded.first_slice_key; src_group; src_group = src_group->next) - { - SPR_SliceGroup *dst_group = &sheet->slice_groups[group_index]; - dst_group->hash = HashFnv64(Fnv64Basis, src_group->name); - dst_group->name = PushString(perm, src_group->name); - - // Init slices - dst_group->slices = PushStructs(perm, SPR_Slice, sheet->frames_count); - { - // Fill is_original slices - for (ASE_Slice *src_slice = src_group->first_slice; src_slice; src_slice = src_slice->next) - { - f32 x0_px = src_slice->rect.p0.x; - f32 y0_px = src_slice->rect.p0.y; - f32 x1_px = src_slice->rect.p1.x; - f32 y1_px = src_slice->rect.p1.y; - f32 width_px = x1_px - x0_px; - f32 height_px = y1_px - y0_px; - - f32 x0 = (x0_px - frame_center.x) / frame_size.x; - f32 y0 = (y0_px - frame_center.y) / frame_size.y; - f32 x1 = (x1_px - frame_center.x) / frame_size.x; - f32 y1 = (y1_px - frame_center.y) / frame_size.y; - f32 width = x1 - x0; - f32 height = y1 - y0; - - // Rect - Rng2 rect_px = RNG2(VEC2(x0_px, y0_px), VEC2(x1_px, y1_px)); - Rng2 rect = RNG2(VEC2(x0, y0), VEC2(x1, y1)); - - // Center - Vec2 center_px = VEC2(x0_px + (width_px * 0.5f), y0_px + (height_px * 0.5f)); - Vec2 center = VEC2(x0 + (width * 0.5f), y0 + (height * 0.5f)); - - // Dir - Vec2 dir_px = VEC2(center_px.x, -1); - Vec2 dir = VEC2(0, -1); - - SPR_Slice *dst_slice = &dst_group->slices[src_slice->start]; - dst_slice->is_original = 1; - dst_slice->rect_px = rect_px; - dst_slice->center_px = center_px; - dst_slice->dir_px = dir_px; - dst_slice->rect = rect; - dst_slice->center = center; - dst_slice->dir = dir; - } - - // Copy slices forward into frames without a slice - { - SPR_Slice *origin = 0; - for (u32 frame_index = 0; frame_index < sheet->frames_count; ++frame_index) - { - SPR_Slice *slice = &dst_group->slices[frame_index]; - if (slice->is_original) - { - origin = slice; - } - else - { - *slice = *origin; - slice->is_original = 0; - } - } - } - } - - // Insert group into bin - { - SPR_SliceGroupBin *bin = &sheet->slice_group_bins[dst_group->hash % sheet->slice_group_bins_count]; - SllQueuePushN(bin->first, bin->last, dst_group, next_in_bin); - } - ++group_index; - } - } - - // Init slice ray directions - { - String ray_suffix = Lit(".ray"); - for (u32 slice_group_index = 0; slice_group_index < sheet->slice_groups_count; ++slice_group_index) - { - SPR_SliceGroup *group = &sheet->slice_groups[slice_group_index]; - if (StringEndsWith(group->name, ray_suffix)) - { - String point_slice_group_name = group->name; - point_slice_group_name.len -= ray_suffix.len; - u64 point_slice_group_hash = HashFnv64(Fnv64Basis, point_slice_group_name); - SPR_SliceGroupBin *bin = &sheet->slice_group_bins[point_slice_group_hash % sheet->slice_group_bins_count]; - SPR_SliceGroup *point_slice_group = bin->first; - for (; point_slice_group; point_slice_group = point_slice_group->next_in_bin) - { - if (point_slice_group->hash == point_slice_group_hash) - { - break; - } - } - if (point_slice_group) - { - for (u32 frame_index = 0; frame_index < sheet->frames_count; ++frame_index) - { - SPR_Slice *point_slice = &point_slice_group->slices[frame_index]; - SPR_Slice *ray_slice = &group->slices[frame_index]; - Vec2 ray_end = ray_slice->center_px; - Vec2 ray_end_norm = ray_slice->center; - point_slice->dir_px = SubVec2(ray_end, point_slice->center_px); - point_slice->dir = SubVec2(ray_end_norm, point_slice->center); - point_slice->has_dir = 1; - } - } - } - } - } - } - - SetFence(&entry->sheet_ready_fence, 1); - EndScratch(scratch); -} - -//////////////////////////////////////////////////////////// -//~ Cache - -// TODO: Per-thread L1 cache -SPR_Entry *SPR_FetchEntry(ResourceKey resource, JobPoolId pool, SPR_FetchFlag flags) -{ - SPR_Entry *entry = 0; - { - SPR_EntryBin *bin = &SPR.entry_bins[resource.hash % countof(SPR.entry_bins)]; - // Search for entry - entry = bin->first; - { - Lock lock = LockS(&bin->mutex); - { - for (; entry; entry = entry->next_in_bin) - { - if (entry->resource.hash == resource.hash) - { - break; - } - } - } - Unlock(&lock); - } - // Entry not found: lock, re-search, & create - if (!entry) - { - Lock lock = LockE(&bin->mutex); - { - // Re-search - entry = bin->first; - for (; entry; entry = entry->next_in_bin) - { - if (entry->resource.hash == resource.hash) - { - break; - } - } - // Create - if (!entry) - { - Arena *perm = PermArena(); - entry = PushStruct(perm, SPR_Entry); - entry->resource = resource; - SllQueuePushN(bin->first, bin->last, entry, next_in_bin); - } - } - Unlock(&lock); - } - } - // Launch load jobs - if ((flags & SPR_FetchFlag_Texture) - && !Atomic32Fetch(&entry->texture_touched) - && !Atomic32FetchTestSet(&entry->texture_touched, 0, 1)) - { - RunJob(SPR_LoadTexture, .pool = pool, .sig.entry = entry); - } - if ((flags & SPR_FetchFlag_Sheet) - && !Atomic32Fetch(&entry->sheet_touched) - && !Atomic32FetchTestSet(&entry->sheet_touched, 0, 1)) - { - RunJob(SPR_LoadSheet, .pool = pool, .sig.entry = entry); - } - return entry; -} - -//////////////////////////////////////////////////////////// -//~ Sprite data retrieval - -SPR_Texture *SPR_TextureFromResource(ResourceKey resource) -{ - SPR_Entry *entry = SPR_FetchEntry(resource, CurrentPool(), SPR_FetchFlag_Texture); - YieldOnFence(&entry->texture_ready_fence, 1); - return &entry->texture; -} - -SPR_Texture *SPR_TextureFromResourceAsync(ResourceKey resource) -{ - SPR_Texture *result = &SPR_NilTexture; - SPR_Entry *entry = SPR_FetchEntry(resource, AsyncPool(), SPR_FetchFlag_Texture); - if (FetchFence(&entry->texture_ready_fence) >= 1) - { - result = &entry->texture; - } - return result; -} - -SPR_Sheet *SPR_SheetFromResource(ResourceKey resource) -{ - SPR_Entry *entry = SPR_FetchEntry(resource, CurrentPool(), SPR_FetchFlag_Sheet); - YieldOnFence(&entry->sheet_ready_fence, 1); - return &entry->sheet; -} - -SPR_Sheet *SPR_SheetFromResourceAsync(ResourceKey resource) -{ - SPR_Sheet *result = &SPR_NilSheet; - SPR_Entry *entry = SPR_FetchEntry(resource, AsyncPool(), SPR_FetchFlag_Sheet); - if (FetchFence(&entry->sheet_ready_fence) >= 1) - { - result = &entry->sheet; - } - return result; + OnAsyncTick(SPR_TickAsync); } //////////////////////////////////////////////////////////// //~ Key helpers -SPR_SpanKey SPR_SpanKeyFromName(String name) +SPR_Key SPR_KeyFromResource(ResourceKey resource) { - SPR_SpanKey result = Zi; - result.hash = HashFnv64(Fnv64Basis, name); - return result; -} - -SPR_SliceKey SPR_SliceKeyFromName(String name) -{ - SPR_SliceKey result = Zi; - result.hash = HashFnv64(Fnv64Basis, name); + SPR_Key result = Zi; return result; } //////////////////////////////////////////////////////////// -//~ Sheet access +//~ Lookup -SPR_Span SPR_SpanFromKey(SPR_Sheet *sheet, SPR_SpanKey key) -{ - SPR_Span result = Zi; - u32 bins_count = sheet->span_bins_count; - if (bins_count > 0) - { - SPR_SpanBin *bin = &sheet->span_bins[key.hash % bins_count]; - SPR_Span *span = bin->first; - for (; span; span = span->next_in_bin) - { - if (span->hash == key.hash) - { - result = *span; - break; - } - } - - } - return result; -} - -SPR_Frame SPR_FrameFromIndex(SPR_Sheet *sheet, u64 index) -{ - SPR_Frame result = Zi; - if (sheet->frames_count > 0) - { - result = sheet->frames[index % sheet->frames_count]; - } - return result; -} - -SPR_Slice SPR_SliceFromKey(SPR_Sheet *sheet, SPR_SliceKey key, u64 frame_index) +SPR_Slice SPR_SliceFromKey(SPR_Key key, String slice_name) { SPR_Slice result = Zi; - b32 match = 0; - u32 bins_count = sheet->slice_group_bins_count; - if (bins_count > 0 && sheet->frames_count > 0) - { - SPR_SliceGroupBin *bin = &sheet->slice_group_bins[key.hash % bins_count]; - SPR_SliceGroup *group = bin->first; - for (; group; group = group->next_in_bin) - { - if (group->hash == key.hash) - { - result = group->slices[frame_index % sheet->frames_count]; - match = 1; - break; - } - } - } + // u64 hash = key.hash; + // hash = Mi - // Return 'pivot' by default - if (!match) - { - SPR_SliceKey pivot_key = SPR_SliceKeyFromName(Lit("pivot")); - if (key.hash == pivot_key.hash) - { - // 'pivot' slice does not exist, return center - result.center = VEC2(0, 0); - result.center_px = MulVec2(sheet->frame_size, 0.5f); - result.dir_px = VEC2(result.center_px.x, 0); - result.dir = VEC2(0, -0.5); - } - else - { - result = SPR_SliceFromKey(sheet, pivot_key, frame_index); - } - } + // SPR_SliceBin *bin = &SPR.slice_bins[ return result; } + +//////////////////////////////////////////////////////////// +//~ Async + +void SPR_TickAsync(WaveLaneCtx *lane, AsyncFrameLaneCtx *base_async_lane_frame) +{ +} diff --git a/src/sprite/sprite.h b/src/sprite/sprite.h index 5688821f..77f390c0 100644 --- a/src/sprite/sprite.h +++ b/src/sprite/sprite.h @@ -1,180 +1,29 @@ -//////////////////////////////////////////////////////////// -//~ Key types - -Struct(SPR_SpanKey) -{ - u64 hash; -}; - -Struct(SPR_SliceKey) -{ - u64 hash; -}; - -//////////////////////////////////////////////////////////// -//~ Texture types - -Struct(SPR_Texture) -{ - b32 valid; - Texture2DGpuPtr texture; - u32 width; - u32 height; -}; - -//////////////////////////////////////////////////////////// -//~ Sheet types - -Struct(SPR_Frame) -{ - u32 index; - f64 duration; - Rng2 clip; -}; - -Struct(SPR_Span) -{ - SPR_Span *next_in_bin; - u64 hash; - String name; - u32 start; - u32 end; -}; - -Struct(SPR_SpanBin) -{ - SPR_Span *first; - SPR_Span *last; -}; - -Struct(SPR_Slice) -{ - // If 1, this slice was not copied over from another frame in the sprite sheet - b32 is_original; - - // If 1, the slice has a corresponding '.ray' slice affecting the 'dir' fields - b32 has_dir; - - // Values are in the range -0.5 (top / left edge) -> +0.5 (bottom / right edge) - Rng2 rect; - Vec2 center; - Vec2 dir; - - // '_px' values retain the original sprite pixel dimensions - Rng2 rect_px; - Vec2 center_px; - Vec2 dir_px; -}; - -Struct(SPR_SliceGroup) -{ - SPR_SliceGroup *next_in_bin; - u64 hash; - String name; - SPR_Slice *slices; -}; - -Struct(SPR_SliceGroupBin) -{ - SPR_SliceGroup *first; - SPR_SliceGroup *last; -}; - -Struct(SPR_Sheet) -{ - b32 valid; - Vec2 image_size; - Vec2 frame_size; - - u32 frames_count; - SPR_Frame *frames; - - u32 spans_count; - SPR_Span *spans; - - u32 slice_groups_count; - SPR_SliceGroup *slice_groups; - - u32 span_bins_count; - SPR_SpanBin *span_bins; - - u32 slice_group_bins_count; - SPR_SliceGroupBin *slice_group_bins; -}; - -//////////////////////////////////////////////////////////// -//~ Cache types - -Enum(SPR_FetchFlag) -{ - SPR_FetchFlag_None = 0, - SPR_FetchFlag_Texture = (1 << 0), - SPR_FetchFlag_Sheet = (1 << 1), -}; - -Struct(SPR_Entry) -{ - SPR_Entry *next_in_bin; - - SPR_Texture texture; - SPR_Sheet sheet; - - Atomic32 texture_touched; - Atomic32 sheet_touched; - - ResourceKey resource; - Fence texture_ready_fence; - Fence sheet_ready_fence; -}; - -Struct(SPR_EntryBin) -{ - SPR_Entry *first; - SPR_Entry *last; - Mutex mutex; -}; - //////////////////////////////////////////////////////////// //~ State types Struct(SPR_Ctx) { - SPR_EntryBin entry_bins[1024]; + i32 _; }; extern SPR_Ctx SPR; -extern Readonly SPR_Sheet SPR_NilSheet; -extern Readonly SPR_Texture SPR_NilTexture; //////////////////////////////////////////////////////////// -//~ Load jobs +//~ Bootstrap -JobDecl(SPR_LoadTexture, { SPR_Entry *entry; }); -JobDecl(SPR_LoadSheet, { SPR_Entry *entry; }); - -//////////////////////////////////////////////////////////// -//~ Cache - -SPR_Entry *SPR_FetchEntry(ResourceKey resource, JobPoolId pool, SPR_FetchFlag flags); - -//////////////////////////////////////////////////////////// -//~ Sprite data retrieval - -SPR_Texture *SPR_TextureFromResource(ResourceKey resource); -SPR_Texture *SPR_TextureFromResourceAsync(ResourceKey resource); - -SPR_Sheet *SPR_SheetFromResource(ResourceKey resource); -SPR_Sheet *SPR_SheetFromResourceAsync(ResourceKey resource); +void SPR_Bootstrap(void); //////////////////////////////////////////////////////////// //~ Key helpers -SPR_SpanKey SPR_SpanKeyFromName(String name); -SPR_SliceKey SPR_SliceKeyFromName(String name); +SPR_Key SPR_KeyFromResource(ResourceKey resource); //////////////////////////////////////////////////////////// -//~ Sheet access +//~ Lookup -SPR_Span SPR_SpanFromKey(SPR_Sheet *sheet, SPR_SpanKey key); -SPR_Frame SPR_FrameFromIndex(SPR_Sheet *sheet, u64 index); -SPR_Slice SPR_SliceFromKey(SPR_Sheet *sheet, SPR_SliceKey key, u64 frame_index); +SPR_Slice SPR_SliceFromKey(SPR_Key key, String slice_name); + +//////////////////////////////////////////////////////////// +//~ Async + +void SPR_TickAsync(WaveLaneCtx *lane, AsyncFrameLaneCtx *base_async_lane_frame); diff --git a/src/sprite/sprite.lay b/src/sprite/sprite.lay index af2462fa..383b7978 100644 --- a/src/sprite/sprite.lay +++ b/src/sprite/sprite.lay @@ -9,8 +9,12 @@ ////////////////////////////// //- Api +@IncludeC sprite_shared.cgh +@IncludeG sprite_shared.cgh @IncludeC sprite.h +@Bootstrap SPR_Bootstrap + ////////////////////////////// //- Impl diff --git a/src/sprite/sprite_shared.cgh b/src/sprite/sprite_shared.cgh new file mode 100644 index 00000000..000b56f5 --- /dev/null +++ b/src/sprite/sprite_shared.cgh @@ -0,0 +1,16 @@ +//////////////////////////////////////////////////////////// +//~ Key types + +Struct(SPR_Key) +{ + u64 v; +}; + +//////////////////////////////////////////////////////////// +//~ Slice types + +Struct(SPR_Slice) +{ + G_Texture2DRef tex; + Rng2 uv; +};