diff --git a/src/app/app_core.c b/src/app/app_core.c index 7b29a87a..8f61963d 100644 --- a/src/app/app_core.c +++ b/src/app/app_core.c @@ -239,7 +239,7 @@ void P_AppStartup(String args_str) AC_StartupReceipt asset_cache_sr = AC_Startup(); TTF_StartupReceipt ttf_sr = TTF_Startup(); F_StartupReceipt font_sr = F_Startup(&asset_cache_sr, &ttf_sr); - S_StartupReceipt sprite_sr = sprite_startup(); + S_StartupReceipt sprite_sr = S_Startup(); MIX_StartupReceipt mixer_sr = MIX_Startup(); SND_StartupReceipt sound_sr = SND_Startup(&asset_cache_sr); D_StartupReceipt draw_sr = D_Startup(&font_sr); diff --git a/src/sim/sim_step.c b/src/sim/sim_step.c index a62c7a53..002967c9 100644 --- a/src/sim/sim_step.c +++ b/src/sim/sim_step.c @@ -36,7 +36,7 @@ void sim_accel_reset(Snapshot *ss, SimAccel *accel) internal Ent *test_spawn_smg(Ent *parent) { Ent *e = sim_ent_alloc_sync_src(parent); - e->sprite = sprite_tag_from_path(Lit("sprite/gun.ase")); + e->sprite = S_TagFromPath(Lit("sprite/gun.ase")); sim_ent_enable_prop(e, SEPROP_ATTACHED); e->attach_slice = Lit("attach.wep"); @@ -52,7 +52,7 @@ internal Ent *test_spawn_smg(Ent *parent) internal Ent *test_spawn_launcher(Ent *parent) { Ent *e = sim_ent_alloc_sync_src(parent); - e->sprite = sprite_tag_from_path(Lit("sprite/gun.ase")); + e->sprite = S_TagFromPath(Lit("sprite/gun.ase")); sim_ent_enable_prop(e, SEPROP_ATTACHED); e->attach_slice = Lit("attach.wep"); @@ -68,7 +68,7 @@ internal Ent *test_spawn_launcher(Ent *parent) internal Ent *test_spawn_chucker(Ent *parent) { Ent *chucker = sim_ent_alloc_sync_src(parent); - chucker->sprite = sprite_tag_from_path(Lit("sprite/gun.ase")); + chucker->sprite = S_TagFromPath(Lit("sprite/gun.ase")); sim_ent_enable_prop(chucker, SEPROP_ATTACHED); chucker->attach_slice = Lit("attach.wep"); @@ -119,12 +119,12 @@ internal Ent *test_spawn_employee(Ent *parent) { sim_ent_enable_prop(e, SEPROP_TEST); - e->sprite = sprite_tag_from_path(Lit("sprite/tim.ase")); + e->sprite = S_TagFromPath(Lit("sprite/tim.ase")); e->mass_unscaled = 10; e->inertia_unscaled = 5; } - //e->sprite = sprite_tag_from_path(Lit("sprite/box_rounded.ase")); + //e->sprite = S_TagFromPath(Lit("sprite/box_rounded.ase")); //e->sprite_span_name = Lit("idle.unarmed"); //e->sprite_span_name = Lit("idle.one_handed"); e->sprite_span_name = Lit("idle.two_handed"); @@ -255,7 +255,7 @@ internal void test_spawn_entities2(Ent *parent, Vec2 pos) Xform xf = XformFromTrs(TRS(.t = pos, .r = rot, .s = size)); sim_ent_set_xform(e, xf); - e->sprite = sprite_tag_from_path(Lit("sprite/tile.ase")); + e->sprite = S_TagFromPath(Lit("sprite/tile.ase")); e->layer = SIM_LAYER_SHOULDERS; //e->sprite_tint = Alpha32F(ColorBlue, 0.75); @@ -297,7 +297,7 @@ internal void test_spawn_entities2(Ent *parent, Vec2 pos) Xform xf = XformFromTrs(.t = pos, .r = r, .s = size); sim_ent_set_xform(e, xf); - e->sprite = sprite_tag_from_path(Lit("sprite/bullet.ase")); + e->sprite = S_TagFromPath(Lit("sprite/bullet.ase")); e->sprite_collider_slice = Lit("shape"); e->layer = SIM_LAYER_SHOULDERS; @@ -325,7 +325,7 @@ internal void test_spawn_entities3(Ent *parent, Vec2 pos) Xform xf = XformFromTrs(TRS(.t = pos, .r = r, .s = size)); sim_ent_set_xform(e, xf); - e->sprite = sprite_tag_from_path(Lit("sprite/box.ase")); + e->sprite = S_TagFromPath(Lit("sprite/box.ase")); e->layer = SIM_LAYER_SHOULDERS; e->sprite_tint = ColorRed; @@ -348,8 +348,8 @@ internal void test_spawn_entities4(Ent *parent, Vec2 pos) Xform xf = XformFromTrs(TRS(.t = pos, .r = r, .s = size)); sim_ent_set_xform(e, xf); - //e->sprite = sprite_tag_from_path(Lit("sprite/box.ase")); - e->sprite = sprite_tag_from_path(Lit("sprite/tile.ase")); + //e->sprite = S_TagFromPath(Lit("sprite/box.ase")); + e->sprite = S_TagFromPath(Lit("sprite/tile.ase")); e->layer = SIM_LAYER_SHOULDERS; sim_ent_enable_prop(e, SEPROP_LIGHT_TEST); @@ -378,14 +378,14 @@ internal void test_spawn_tile(Snapshot *world, Vec2 world_pos) sim_ent_set_xform(e, xf); e->layer = SIM_LAYER_WALLS; - e->sprite = sprite_tag_from_path(Lit("sprite/tile.ase")); + e->sprite = S_TagFromPath(Lit("sprite/tile.ase")); e->sprite_tint = ColorRed; { - S_Scope *scope = sprite_scope_begin(); - S_Sheet *sheet = sprite_sheet_from_tag_await(scope, e->sprite); + S_Scope *scope = S_BeginScope(); + S_Sheet *sheet = S_SheetFromTagAwait(scope, e->sprite); e->sprite_local_xform = XformFromTrs(.s = DivVec2(sheet->frame_size, PIXELS_PER_UNIT)); - sprite_scope_end(scope); + S_EndScope(scope); } sim_ent_enable_prop(e, SEPROP_SOLID); @@ -748,7 +748,7 @@ internal PHYS_COLLISION_CALLBACK_FUNC_DEF(on_collision, data, step_ctx) { Xform xf = XformFromTrs(TRS(.t = point, .r = RandF64FromState(&step_ctx->rand, 0, Tau))); Ent *decal = sim_ent_alloc_sync_src(root); - decal->sprite = sprite_tag_from_path(Lit("sprite/blood.ase")); + decal->sprite = S_TagFromPath(Lit("sprite/blood.ase")); decal->sprite_tint = Rgba32F(1, 1, 1, 0.25f); decal->layer = SIM_LAYER_FLOOR_DECALS; sim_ent_set_xform(decal, xf); @@ -858,7 +858,7 @@ void sim_step(SimStepCtx *ctx) world->sim_time_ns += world->sim_dt_ns; f32 sim_dt = SecondsFromNs(world->sim_dt_ns); - S_Scope *sprite_frame_scope = sprite_scope_begin(); + S_Scope *sprite_frame_scope = S_BeginScope(); Ent *root = sim_ent_from_id(world, SIM_ENT_ROOT_ID); root->owner = world->client->player_id; @@ -1166,13 +1166,13 @@ void sim_step(SimStepCtx *ctx) for (u64 ent_index = 0; ent_index < world->num_ents_reserved; ++ent_index) { Ent *ent = &world->ents[ent_index]; if (!sim_ent_should_simulate(ent)) continue; - if (sprite_tag_is_nil(ent->sprite)) continue; + if (S_IsTagNil(ent->sprite)) continue; - S_Sheet *sheet = sprite_sheet_from_tag_await(sprite_frame_scope, ent->sprite); + S_Sheet *sheet = S_SheetFromTagAwait(sprite_frame_scope, ent->sprite); /* Update animation */ { - S_SheetSpan span = sprite_sheet_get_span(sheet, ent->sprite_span_name); + S_Span span = S_SpanFromName(sheet, ent->sprite_span_name); if (ent->animation_last_frame_change_time_ns == 0) { ent->animation_last_frame_change_time_ns = SecondsFromNs(world->sim_time_ns); } @@ -1184,7 +1184,7 @@ void sim_step(SimStepCtx *ctx) } if (span.end > span.start) { - S_SheetFrame frame = sprite_sheet_get_frame(sheet, frame_index); + S_Frame frame = S_FrameFromIndex(sheet, frame_index); while (time_in_frame > frame.duration) { time_in_frame -= frame.duration; ++frame_index; @@ -1192,7 +1192,7 @@ void sim_step(SimStepCtx *ctx) /* Loop animation */ frame_index = span.start; } - frame = sprite_sheet_get_frame(sheet, frame_index); + frame = S_FrameFromIndex(sheet, frame_index); ent->animation_last_frame_change_time_ns = world->sim_time_ns; } } @@ -1203,7 +1203,7 @@ void sim_step(SimStepCtx *ctx) #if 0 /* Update sprite local xform */ { - S_SheetSlice slice = sprite_sheet_get_slice(sheet, Lit("pivot"), ent->animation_frame); + S_Slice slice = S_SliceFromNameIndex(sheet, Lit("pivot"), ent->animation_frame); Vec2 sprite_size = DivVec2(sheet->frame_size, (f32)PIXELS_PER_UNIT); Vec2 dir = MulVec2Vec2(sprite_size, slice.dir); @@ -1221,7 +1221,7 @@ void sim_step(SimStepCtx *ctx) if (ent->sprite_collider_slice.len > 0) { Xform cxf = ent->sprite_local_xform; - S_SheetSlice slice = sprite_sheet_get_slice(sheet, ent->sprite_collider_slice, ent->animation_frame); + S_Slice slice = S_SliceFromNameIndex(sheet, ent->sprite_collider_slice, ent->animation_frame); ent->local_collider = CLD_ShapeFromQuad(MulXformQuad(cxf, QuadFromRect(slice.rect))); } @@ -1272,11 +1272,11 @@ void sim_step(SimStepCtx *ctx) Ent *parent = sim_ent_from_id(world, ent->parent); S_Tag parent_sprite = parent->sprite; - S_Sheet *parent_sheet = sprite_sheet_from_tag_await(sprite_frame_scope, parent_sprite); + S_Sheet *parent_sheet = S_SheetFromTagAwait(sprite_frame_scope, parent_sprite); Xform parent_sprite_xf = parent->sprite_local_xform; - S_SheetSlice attach_slice = sprite_sheet_get_slice(parent_sheet, ent->attach_slice, parent->animation_frame); + S_Slice attach_slice = S_SliceFromNameIndex(parent_sheet, ent->attach_slice, parent->animation_frame); Vec2 attach_pos = MulXformV2(parent_sprite_xf, attach_slice.center); Vec2 attach_dir = MulXformBasisV2(parent_sprite_xf, attach_slice.dir); @@ -1350,9 +1350,9 @@ void sim_step(SimStepCtx *ctx) if (primary_triggered) { S_Tag sprite = ent->sprite; u32 animation_frame = ent->animation_frame; - S_Sheet *sheet = sprite_sheet_from_tag_await(sprite_frame_scope, sprite); + S_Sheet *sheet = S_SheetFromTagAwait(sprite_frame_scope, sprite); Xform sprite_local_xform = ent->sprite_local_xform; - S_SheetSlice out_slice = sprite_sheet_get_slice(sheet, Lit("out"), animation_frame); + S_Slice out_slice = S_SliceFromNameIndex(sheet, Lit("out"), animation_frame); Vec2 rel_pos = MulXformV2(sprite_local_xform, out_slice.center); Vec2 rel_dir = MulXformBasisV2(sprite_local_xform, out_slice.dir); @@ -1375,7 +1375,7 @@ void sim_step(SimStepCtx *ctx) bullet->local_collider.points[0] = VEC2(0, 0); bullet->local_collider.count = 1; #else - bullet->sprite = sprite_tag_from_path(Lit("sprite/bullet.ase")); + bullet->sprite = S_TagFromPath(Lit("sprite/bullet.ase")); bullet->sprite_collider_slice = Lit("shape"); #endif } @@ -1397,9 +1397,9 @@ void sim_step(SimStepCtx *ctx) if (primary_triggered) { S_Tag sprite = ent->sprite; u32 animation_frame = ent->animation_frame; - S_Sheet *sheet = sprite_sheet_from_tag_await(sprite_frame_scope, sprite); + S_Sheet *sheet = S_SheetFromTagAwait(sprite_frame_scope, sprite); Xform sprite_local_xform = ent->sprite_local_xform; - S_SheetSlice out_slice = sprite_sheet_get_slice(sheet, Lit("out"), animation_frame); + S_Slice out_slice = S_SliceFromNameIndex(sheet, Lit("out"), animation_frame); Vec2 rel_pos = MulXformV2(sprite_local_xform, out_slice.center); Vec2 rel_dir = MulXformBasisV2(sprite_local_xform, out_slice.dir); @@ -1559,8 +1559,8 @@ void sim_step(SimStepCtx *ctx) Vec2 sprite_hold_pos; Vec2 sprite_hold_dir; { - S_Sheet *sheet = sprite_sheet_from_tag_await(sprite_frame_scope, ent->sprite); - S_SheetSlice slice = sprite_sheet_get_slice(sheet, Lit("attach.wep"), ent->animation_frame); + S_Sheet *sheet = S_SheetFromTagAwait(sprite_frame_scope, ent->sprite); + S_Slice slice = S_SliceFromNameIndex(sheet, Lit("attach.wep"), ent->animation_frame); sprite_hold_pos = slice.center; sprite_hold_dir = slice.dir; } @@ -1940,7 +1940,7 @@ void sim_step(SimStepCtx *ctx) * End frame * ========================== */ - sprite_scope_end(sprite_frame_scope); + S_EndScope(sprite_frame_scope); EndScratch(scratch); } diff --git a/src/sprite/sprite_core.c b/src/sprite/sprite_core.c index b2191dc4..18f0779d 100644 --- a/src/sprite/sprite_core.c +++ b/src/sprite/sprite_core.c @@ -1,10 +1,81 @@ S_SharedState S_shared_state = ZI; -/* ========================== * - * Purple-black image - * ========================== */ +//////////////////////////////// +//~ Startup -u32 *generate_purple_black_image(Arena *arena, u32 width, u32 height) +S_StartupReceipt S_Startup(void) +{ + __prof; + S_SharedState *g = &S_shared_state; + g->perm_arena = AllocArena(Mebi(1)); + { + /* Init loading texture */ + g->loading_texture = PushStruct(g->perm_arena, S_Texture); + + /* Init nil texture */ + g->nil_texture = PushStruct(g->perm_arena, S_Texture); + g->nil_texture->loaded = 1; + { + TempArena scratch = BeginScratchNoConflict(); + u32 width = 64; + u32 height = 64; + u32 *pixels = S_GeneratePurpleBlackImage(scratch.arena, width, height); + g->nil_texture->gp_texture = GPU_AllocTexture(GP_TEXTURE_FORMAT_R8G8B8A8_UNORM, 0, VEC2I32(width, height), pixels); + EndScratch(scratch); + } + + /* Init loading sheet */ + g->loading_sheet = PushStruct(g->perm_arena, S_Sheet); + g->loading_sheet->image_size = VEC2(PIXELS_PER_UNIT, PIXELS_PER_UNIT); + g->loading_sheet->frame_size = VEC2(PIXELS_PER_UNIT, PIXELS_PER_UNIT); + + /* Init nil sheet */ + g->nil_sheet = PushStruct(g->perm_arena, S_Sheet); + g->nil_sheet->image_size = VEC2(PIXELS_PER_UNIT, PIXELS_PER_UNIT); + g->nil_sheet->frame_size = VEC2(PIXELS_PER_UNIT, PIXELS_PER_UNIT); + g->nil_sheet->loaded = 1; + } + SetArenaReadonly(g->perm_arena); + + g->cache.arena = AllocArena(Gibi(64)); + g->cache.bins = PushStructs(g->cache.arena, S_CacheEntryBin, S_CacheBinsCount); + + g->cmds_arena = AllocArena(Gibi(64)); + + g->scopes_arena = AllocArena(Gibi(64)); + + P_Run(1, S_EvictorJob, 0, P_Pool_Background, P_Priority_Low, &g->shutdown_counter); + + P_OnExit(&S_Shutdown); +#if RESOURCE_RELOADING + W_RegisterCallback(&S_WatchSpriteCallback); +#endif + + return (S_StartupReceipt) { 0 }; +} + +//////////////////////////////// +//~ Shutdown + +P_ExitFuncDef(S_Shutdown) +{ + __prof; + S_SharedState *g = &S_shared_state; + /* Signal evictor shutdown */ + { + P_Lock lock = P_LockE(&g->evictor_scheduler_mutex); + g->evictor_scheduler_shutdown = 1; + P_SignalCv(&g->evictor_scheduler_shutdown_cv, I32Max); + P_Unlock(&lock); + } + /* Wait for evictor shutdown */ + P_WaitOnCounter(&g->shutdown_counter); +} + +//////////////////////////////// +//~ Nil purple-black image + +u32 *S_GeneratePurpleBlackImage(Arena *arena, u32 width, u32 height) { u32 *pixels = PushStructsNoZero(arena, u32, width * height); @@ -45,81 +116,10 @@ u32 *generate_purple_black_image(Arena *arena, u32 width, u32 height) return pixels; } -/* ========================== * - * Startup - * ========================== */ +//////////////////////////////// +//~ Tag -S_StartupReceipt sprite_startup(void) -{ - __prof; - S_SharedState *g = &S_shared_state; - g->perm_arena = AllocArena(Mebi(1)); - { - /* Init loading texture */ - g->loading_texture = PushStruct(g->perm_arena, S_Texture); - - /* Init nil texture */ - g->nil_texture = PushStruct(g->perm_arena, S_Texture); - g->nil_texture->loaded = 1; - { - TempArena scratch = BeginScratchNoConflict(); - u32 width = 64; - u32 height = 64; - u32 *pixels = generate_purple_black_image(scratch.arena, width, height); - g->nil_texture->gp_texture = GPU_AllocTexture(GP_TEXTURE_FORMAT_R8G8B8A8_UNORM, 0, VEC2I32(width, height), pixels); - EndScratch(scratch); - } - - /* Init loading sheet */ - g->loading_sheet = PushStruct(g->perm_arena, S_Sheet); - g->loading_sheet->image_size = VEC2(PIXELS_PER_UNIT, PIXELS_PER_UNIT); - g->loading_sheet->frame_size = VEC2(PIXELS_PER_UNIT, PIXELS_PER_UNIT); - - /* Init nil sheet */ - g->nil_sheet = PushStruct(g->perm_arena, S_Sheet); - g->nil_sheet->image_size = VEC2(PIXELS_PER_UNIT, PIXELS_PER_UNIT); - g->nil_sheet->frame_size = VEC2(PIXELS_PER_UNIT, PIXELS_PER_UNIT); - g->nil_sheet->loaded = 1; - } - SetArenaReadonly(g->perm_arena); - - g->cache.arena = AllocArena(Gibi(64)); - g->cache.bins = PushStructs(g->cache.arena, S_CacheEntryBin, S_CacheBinsCount); - - g->cmds_arena = AllocArena(Gibi(64)); - - g->scopes_arena = AllocArena(Gibi(64)); - - P_Run(1, S_EvictorJob, 0, P_Pool_Background, P_Priority_Low, &g->shutdown_counter); - - P_OnExit(&sprite_shutdown); -#if RESOURCE_RELOADING - W_RegisterCallback(&S_WatchSpriteCallback); -#endif - - return (S_StartupReceipt) { 0 }; -} - -P_ExitFuncDef(sprite_shutdown) -{ - __prof; - S_SharedState *g = &S_shared_state; - /* Signal evictor shutdown */ - { - P_Lock lock = P_LockE(&g->evictor_scheduler_mutex); - g->evictor_scheduler_shutdown = 1; - P_SignalCv(&g->evictor_scheduler_shutdown_cv, I32Max); - P_Unlock(&lock); - } - /* Wait for evictor shutdown */ - P_WaitOnCounter(&g->shutdown_counter); -} - -/* ========================== * - * Tag - * ========================== */ - -S_Tag sprite_tag_from_path(String path) +S_Tag S_TagFromPath(String path) { S_Tag result = ZI; result.hash = HashFnv64(Fnv64Basis, path); @@ -127,27 +127,333 @@ S_Tag sprite_tag_from_path(String path) return result; } -b32 sprite_tag_is_nil(S_Tag tag) +b32 S_IsTagNil(S_Tag tag) { return tag.hash == 0; } -b32 sprite_tag_eq(S_Tag t1, S_Tag t2) +b32 S_EqTag(S_Tag t1, S_Tag t2) { return t1.hash == t2.hash; } -S_Hash cache_entry_hash_from_tag_hash(u64 tag_hash, S_CacheEntryKind kind) +S_Hash S_CacheEntryFromTagHash(u64 tag_hash, S_CacheEntryKind kind) { return (S_Hash) { .v = RandU64FromSeed(tag_hash + kind) }; } -/* ========================== * - * Load - * ========================== */ -S_ScopeCacheRef *scope_ensure_ref_from_ref(S_Scope *scope, S_Ref ref); -void push_load_job(S_Ref ref, S_Tag tag) +//////////////////////////////// +//~ Init sheet + +S_Sheet S_SheetFromAseResult(Arena *arena, ASE_DecodedSheet ase) +{ + __prof; + S_Sheet sheet = ZI; + + Assert(ase.num_frames >= 1); + + Vec2 frame_size = ase.frame_size; + Vec2 frame_center = MulVec2(ase.frame_size, 0.5f); + + /* Init frames */ + { + __profn("Init frames"); + sheet.image_size = ase.image_size; + sheet.frame_size = ase.frame_size; + sheet.frames = PushStructs(arena, S_Frame, ase.num_frames); + sheet.frames_count = ase.num_frames; + for (ASE_Frame *ase_frame = ase.frame_head; ase_frame; ase_frame = ase_frame->next) + { + u32 index = ase_frame->index; + + Vec2 clip_p1 = { (f32)ase_frame->x1 / (f32)ase.image_size.x, (f32)ase_frame->y1 / (f32)ase.image_size.y }; + Vec2 clip_p2 = { (f32)ase_frame->x2 / (f32)ase.image_size.x, (f32)ase_frame->y2 / (f32)ase.image_size.y }; + + sheet.frames[index] = (S_Frame) { + .index = index, + .duration = ase_frame->duration, + .clip = (ClipRect) { clip_p1, clip_p2 } + }; + } + } + + /* Init spans */ + sheet.spans_count = ase.num_spans; + if (ase.num_spans > 0) + { + __profn("Init spans"); + sheet.spans = PushStructs(arena, S_Span, sheet.spans_count); + sheet.spans_dict = InitDict(arena, (u64)(ase.num_spans * S_SheetSpanLookupTableBinRatio)); + u64 index = 0; + for (ASE_Span *ase_span = ase.span_head; ase_span; ase_span = ase_span->next) + { + String name = CopyString(arena, ase_span->name); + S_Span *span = &sheet.spans[index]; + span->name = name; + span->start = ase_span->start; + span->end = ase_span->end; + u64 hash = HashFnv64(Fnv64Basis, name); + SetDictValue(arena, sheet.spans_dict, hash, (u64)span); + ++index; + } + } + + /* Init slices */ + if (ase.num_slice_keys > 0) + { + __profn("Init slices"); + TempArena scratch = BeginScratch(arena); + + struct temp_ase_slice_key_node + { + ASE_SliceKey *key; + struct temp_ase_slice_key_node *next; + + u32 index_in_frame; + u32 earliest_frame; + }; + + struct temp_slice_group_node + { + String name; + u64 per_frame_count; + struct temp_ase_slice_key_node *temp_ase_slice_key_head; + struct temp_slice_group_node *next; + + S_SheetSliceGroup *final_slice_group; + }; + + /* Group slices by name and find out counts per frame */ + u64 num_temp_slice_group_nodes = 0; + struct temp_slice_group_node *temp_slice_group_head = 0; + { + Dict *temp_slice_dict = InitDict(scratch.arena, (u64)(ase.num_slice_keys * 2)); + for (ASE_SliceKey *ase_slice_key = ase.slice_key_head; ase_slice_key; ase_slice_key = ase_slice_key->next) + { + String name = ase_slice_key->name; + u64 hash = HashFnv64(Fnv64Basis, name); + struct temp_slice_group_node *temp_slice_group_node = (struct temp_slice_group_node *)DictValueFromHash(temp_slice_dict, hash); + if (!temp_slice_group_node) + { + temp_slice_group_node = PushStruct(scratch.arena, struct temp_slice_group_node); + temp_slice_group_node->name = name; + SetDictValue(scratch.arena, temp_slice_dict, hash, (u64)temp_slice_group_node); + + ++num_temp_slice_group_nodes; + temp_slice_group_node->next = temp_slice_group_head; + temp_slice_group_head = temp_slice_group_node; + } + + struct temp_ase_slice_key_node *node = PushStruct(scratch.arena, struct temp_ase_slice_key_node); + node->key = ase_slice_key; + node->next = temp_slice_group_node->temp_ase_slice_key_head; + node->earliest_frame = U32Max; /* To be overwritten later after iterating */ + + temp_slice_group_node->temp_ase_slice_key_head = node; + + ++temp_slice_group_node->per_frame_count; + } + } + + /* Allocate slice groups & fill originals in 2d array */ + sheet.slice_groups_count = num_temp_slice_group_nodes; + sheet.slice_groups = PushStructs(arena, S_SheetSliceGroup, sheet.slice_groups_count); + sheet.slice_groups_dict = InitDict(arena, (u64)(num_temp_slice_group_nodes * S_SliceLookupTableBinRatio)); + + u64 index = 0; + for (struct temp_slice_group_node *temp_slice_group_node = temp_slice_group_head; temp_slice_group_node; temp_slice_group_node = temp_slice_group_node->next) + { + S_SheetSliceGroup *slice_group = &sheet.slice_groups[index]; + slice_group->name = CopyString(arena, temp_slice_group_node->name); + slice_group->per_frame_count = temp_slice_group_node->per_frame_count; + + slice_group->frame_slices = PushStructs(arena, S_Slice, ase.num_frames * slice_group->per_frame_count); + + u64 index_in_frame = 0; + for (struct temp_ase_slice_key_node *node = temp_slice_group_node->temp_ase_slice_key_head; node; node = node->next) + { + ASE_SliceKey *key = node->key; + + for (ASE_Slice *ase_slice = key->slice_head; ase_slice; ase_slice = ase_slice->next) + { + u32 start = ase_slice->start; + + S_Slice *slice = &slice_group->frame_slices[(start * slice_group->per_frame_count) + index_in_frame]; + slice->original = 1; + + f32 x1_px = ase_slice->x1; + f32 y1_px = ase_slice->y1; + f32 x2_px = ase_slice->x2; + f32 y2_px = ase_slice->y2; + f32 width_px = x2_px - x1_px; + f32 height_px = y2_px - y1_px; + + f32 x1 = (x1_px - frame_center.x) / frame_size.x; + f32 y1 = (y1_px - frame_center.y) / frame_size.y; + f32 x2 = (x2_px - frame_center.x) / frame_size.x; + f32 y2 = (y2_px - frame_center.y) / frame_size.y; + f32 width = x2 - x1; + f32 height = y2 - y1; + + /* Rect */ + Rect rect_px = RectFromScalar(x1_px, y1_px, width_px, height_px); + Rect rect = RectFromScalar(x1, y1, width, height); + /* Center */ + Vec2 center_px = VEC2(x1_px + (width_px * 0.5f), y1_px + (height_px * 0.5f)); + Vec2 center = VEC2(x1 + (width * 0.5f), y1 + (height * 0.5f)); + /* Dir */ + Vec2 dir_px = VEC2(center_px.x, -1); + Vec2 dir = VEC2(0, -1); + + slice->rect_px = rect_px; + slice->center_px = center_px; + slice->dir_px = dir_px; + + slice->rect = rect; + slice->center = center; + slice->dir = dir; + + node->index_in_frame = index_in_frame; + if (start < node->earliest_frame) + { + node->earliest_frame = start; + } + } + + ++index_in_frame; + } + + temp_slice_group_node->final_slice_group = slice_group; + u64 hash = HashFnv64(Fnv64Basis, slice_group->name); + SetDictValue(arena, sheet.slice_groups_dict, hash, (u64)slice_group); + ++index; + } + + /* Propagate original slices into next frames (and first slices into previous frames) */ + for (struct temp_slice_group_node *temp_slice_group_node = temp_slice_group_head; temp_slice_group_node; temp_slice_group_node = temp_slice_group_node->next) + { + S_SheetSliceGroup *slice_group = temp_slice_group_node->final_slice_group; + + for (struct temp_ase_slice_key_node *node = temp_slice_group_node->temp_ase_slice_key_head; node; node = node->next) + { + ASE_SliceKey *key = node->key; + u32 index_in_frame = node->index_in_frame; + for (ASE_Slice *ase_slice = key->slice_head; ase_slice; ase_slice = ase_slice->next) + { + u32 start = ase_slice->start; + + S_Slice *slice = &slice_group->frame_slices[(start * slice_group->per_frame_count) + index_in_frame]; + + /* Propagate earliest slice to all previous frames */ + if (start == node->earliest_frame && start > 0) + { + for (u32 i = start; i-- > 0;) + { + S_Slice *target = &slice_group->frame_slices[(i * slice_group->per_frame_count) + index_in_frame]; + *target = *slice; + target->original = 0; + } + } + + /* Propagate slice to forward frames until original is found */ + for (u32 i = start + 1; i < ase.num_frames; ++i) + { + S_Slice *target = &slice_group->frame_slices[(i * slice_group->per_frame_count) + index_in_frame]; + if (target->original) + { + break; + } + else + { + *target = *slice; + target->original = 0; + } + } + } + } + } + + /* Calculate direction vectors */ + for (struct temp_slice_group_node *temp_slice_group_node = temp_slice_group_head; temp_slice_group_node; temp_slice_group_node = temp_slice_group_node->next) + { + String ray_suffix = Lit(".ray"); + + S_SheetSliceGroup *ray_slice_group = temp_slice_group_node->final_slice_group; + String ray_slice_name = ray_slice_group->name; + if (StringEndsWith(ray_slice_name, ray_suffix)) + { + String point_slice_name = ray_slice_name; + point_slice_name.len -= ray_suffix.len; + u64 hash = HashFnv64(Fnv64Basis, point_slice_name); + S_SheetSliceGroup *point_slice_group = (S_SheetSliceGroup *)DictValueFromHash(sheet.slice_groups_dict, hash); + if (point_slice_group) + { + u32 point_slices_per_frame = point_slice_group->per_frame_count; + + for (u32 i = 0; i < ase.num_frames; ++i) + { + /* Use ray slice in ray group */ + S_Slice *ray_slice = &ray_slice_group->frame_slices[i * point_slices_per_frame]; + Vec2 ray_end = ray_slice->center_px; + Vec2 ray_end_norm = ray_slice->center; + + /* Apply to each point slice in point group */ + for (u32 j = 0; j < point_slices_per_frame; ++j) + { + S_Slice *point_slice = &point_slice_group->frame_slices[(i * point_slices_per_frame) + j]; + point_slice->dir_px = SubVec2(ray_end, point_slice->center_px); + point_slice->dir = SubVec2(ray_end_norm, point_slice->center); + point_slice->has_ray = 1; + } + } + + } + } + } + + EndScratch(scratch); + } + + return sheet; +} + +//////////////////////////////// +//~ Load job + +//- Job def +P_JobDef(S_LoadSpriteJob, job) +{ + __prof; + S_SharedState *g = &S_shared_state; + S_Cmd *cmd = job.sig; + S_CacheEntryRef ref = cmd->ref; + + switch (ref.e->kind) + { + case CACHE_ENTRY_KIND_TEXTURE: + { + S_LoadCacheEntryTexture(ref, cmd->tag); + } break; + case CACHE_ENTRY_KIND_SHEET: + { + S_LoadCacheEntrySheet(ref, cmd->tag); + } break; + default: { P_Panic(Lit("Unknown sprite cache node kind")); } break; + } + + /* Free cmd */ + P_Lock lock = P_LockE(&g->cmds_mutex); + { + S_EndScope(cmd->scope); + cmd->next_free = g->first_free_cmd; + g->first_free_cmd = cmd; + } + P_Unlock(&lock); +} + +//- Push +void S_PushLoadJob(S_CacheEntryRef ref, S_Tag tag) { S_SharedState *g = &S_shared_state; S_Cmd *cmd = 0; @@ -167,8 +473,8 @@ void push_load_job(S_Ref ref, S_Tag tag) ZeroStruct(cmd); /* Initialize cmd */ - cmd->scope = sprite_scope_begin(); - cmd->ref = scope_ensure_ref_from_ref(cmd->scope, ref)->ref; + cmd->scope = S_BeginScope(); + cmd->ref = S_EnsureRefFromRef(cmd->scope, ref)->ref; cmd->tag = tag; { u64 copy_len = MinU64(tag.path.len, countof(cmd->tag_path_buff)); @@ -177,10 +483,13 @@ void push_load_job(S_Ref ref, S_Tag tag) } /* PushStruct work */ - P_Run(1, S_SpriteLoadJob, cmd, P_Pool_Background, P_Priority_Inherit, 0); + P_Run(1, S_LoadSpriteJob, cmd, P_Pool_Background, P_Priority_Inherit, 0); } -void cache_entry_load_texture(S_Ref ref, S_Tag tag) +//////////////////////////////// +//~ Cache load operations + +void S_LoadCacheEntryTexture(S_CacheEntryRef ref, S_Tag tag) { __prof; S_SharedState *g = &S_shared_state; @@ -265,279 +574,7 @@ void cache_entry_load_texture(S_Ref ref, S_Tag tag) EndScratch(scratch); } -S_Sheet init_sheet_from_ase_result(Arena *arena, ASE_DecodedSheet ase) -{ - __prof; - S_Sheet sheet = ZI; - - Assert(ase.num_frames >= 1); - - Vec2 frame_size = ase.frame_size; - Vec2 frame_center = MulVec2(ase.frame_size, 0.5f); - - /* Init frames */ - { - __profn("Init frames"); - sheet.image_size = ase.image_size; - sheet.frame_size = ase.frame_size; - sheet.frames = PushStructs(arena, S_SheetFrame, ase.num_frames); - sheet.frames_count = ase.num_frames; - for (ASE_Frame *ase_frame = ase.frame_head; ase_frame; ase_frame = ase_frame->next) - { - u32 index = ase_frame->index; - - Vec2 clip_p1 = { (f32)ase_frame->x1 / (f32)ase.image_size.x, (f32)ase_frame->y1 / (f32)ase.image_size.y }; - Vec2 clip_p2 = { (f32)ase_frame->x2 / (f32)ase.image_size.x, (f32)ase_frame->y2 / (f32)ase.image_size.y }; - - sheet.frames[index] = (S_SheetFrame) { - .index = index, - .duration = ase_frame->duration, - .clip = (ClipRect) { clip_p1, clip_p2 } - }; - } - } - - /* Init spans */ - sheet.spans_count = ase.num_spans; - if (ase.num_spans > 0) - { - __profn("Init spans"); - sheet.spans = PushStructs(arena, S_SheetSpan, sheet.spans_count); - sheet.spans_dict = InitDict(arena, (u64)(ase.num_spans * S_SheetSpanLookupTableBinRatio)); - u64 index = 0; - for (ASE_Span *ase_span = ase.span_head; ase_span; ase_span = ase_span->next) - { - String name = CopyString(arena, ase_span->name); - S_SheetSpan *span = &sheet.spans[index]; - span->name = name; - span->start = ase_span->start; - span->end = ase_span->end; - u64 hash = HashFnv64(Fnv64Basis, name); - SetDictValue(arena, sheet.spans_dict, hash, (u64)span); - ++index; - } - } - - /* Init slices */ - if (ase.num_slice_keys > 0) - { - __profn("Init slices"); - TempArena scratch = BeginScratch(arena); - - struct temp_ase_slice_key_node - { - ASE_SliceKey *key; - struct temp_ase_slice_key_node *next; - - u32 index_in_frame; - u32 earliest_frame; - }; - - struct temp_slice_group_node - { - String name; - u64 per_frame_count; - struct temp_ase_slice_key_node *temp_ase_slice_key_head; - struct temp_slice_group_node *next; - - S_SheetSliceGroup *final_slice_group; - }; - - /* Group slices by name and find out counts per frame */ - u64 num_temp_slice_group_nodes = 0; - struct temp_slice_group_node *temp_slice_group_head = 0; - { - Dict *temp_slice_dict = InitDict(scratch.arena, (u64)(ase.num_slice_keys * 2)); - for (ASE_SliceKey *ase_slice_key = ase.slice_key_head; ase_slice_key; ase_slice_key = ase_slice_key->next) - { - String name = ase_slice_key->name; - u64 hash = HashFnv64(Fnv64Basis, name); - struct temp_slice_group_node *temp_slice_group_node = (struct temp_slice_group_node *)DictValueFromHash(temp_slice_dict, hash); - if (!temp_slice_group_node) - { - temp_slice_group_node = PushStruct(scratch.arena, struct temp_slice_group_node); - temp_slice_group_node->name = name; - SetDictValue(scratch.arena, temp_slice_dict, hash, (u64)temp_slice_group_node); - - ++num_temp_slice_group_nodes; - temp_slice_group_node->next = temp_slice_group_head; - temp_slice_group_head = temp_slice_group_node; - } - - struct temp_ase_slice_key_node *node = PushStruct(scratch.arena, struct temp_ase_slice_key_node); - node->key = ase_slice_key; - node->next = temp_slice_group_node->temp_ase_slice_key_head; - node->earliest_frame = U32Max; /* To be overwritten later after iterating */ - - temp_slice_group_node->temp_ase_slice_key_head = node; - - ++temp_slice_group_node->per_frame_count; - } - } - - /* Allocate slice groups & fill originals in 2d array */ - sheet.slice_groups_count = num_temp_slice_group_nodes; - sheet.slice_groups = PushStructs(arena, S_SheetSliceGroup, sheet.slice_groups_count); - sheet.slice_groups_dict = InitDict(arena, (u64)(num_temp_slice_group_nodes * S_SliceLookupTableBinRatio)); - - u64 index = 0; - for (struct temp_slice_group_node *temp_slice_group_node = temp_slice_group_head; temp_slice_group_node; temp_slice_group_node = temp_slice_group_node->next) - { - S_SheetSliceGroup *slice_group = &sheet.slice_groups[index]; - slice_group->name = CopyString(arena, temp_slice_group_node->name); - slice_group->per_frame_count = temp_slice_group_node->per_frame_count; - - slice_group->frame_slices = PushStructs(arena, S_SheetSlice, ase.num_frames * slice_group->per_frame_count); - - u64 index_in_frame = 0; - for (struct temp_ase_slice_key_node *node = temp_slice_group_node->temp_ase_slice_key_head; node; node = node->next) - { - ASE_SliceKey *key = node->key; - - for (ASE_Slice *ase_slice = key->slice_head; ase_slice; ase_slice = ase_slice->next) - { - u32 start = ase_slice->start; - - S_SheetSlice *slice = &slice_group->frame_slices[(start * slice_group->per_frame_count) + index_in_frame]; - slice->original = 1; - - f32 x1_px = ase_slice->x1; - f32 y1_px = ase_slice->y1; - f32 x2_px = ase_slice->x2; - f32 y2_px = ase_slice->y2; - f32 width_px = x2_px - x1_px; - f32 height_px = y2_px - y1_px; - - f32 x1 = (x1_px - frame_center.x) / frame_size.x; - f32 y1 = (y1_px - frame_center.y) / frame_size.y; - f32 x2 = (x2_px - frame_center.x) / frame_size.x; - f32 y2 = (y2_px - frame_center.y) / frame_size.y; - f32 width = x2 - x1; - f32 height = y2 - y1; - - /* Rect */ - Rect rect_px = RectFromScalar(x1_px, y1_px, width_px, height_px); - Rect rect = RectFromScalar(x1, y1, width, height); - /* Center */ - Vec2 center_px = VEC2(x1_px + (width_px * 0.5f), y1_px + (height_px * 0.5f)); - Vec2 center = VEC2(x1 + (width * 0.5f), y1 + (height * 0.5f)); - /* Dir */ - Vec2 dir_px = VEC2(center_px.x, -1); - Vec2 dir = VEC2(0, -1); - - slice->rect_px = rect_px; - slice->center_px = center_px; - slice->dir_px = dir_px; - - slice->rect = rect; - slice->center = center; - slice->dir = dir; - - node->index_in_frame = index_in_frame; - if (start < node->earliest_frame) - { - node->earliest_frame = start; - } - } - - ++index_in_frame; - } - - temp_slice_group_node->final_slice_group = slice_group; - u64 hash = HashFnv64(Fnv64Basis, slice_group->name); - SetDictValue(arena, sheet.slice_groups_dict, hash, (u64)slice_group); - ++index; - } - - /* Propagate original slices into next frames (and first slices into previous frames) */ - for (struct temp_slice_group_node *temp_slice_group_node = temp_slice_group_head; temp_slice_group_node; temp_slice_group_node = temp_slice_group_node->next) - { - S_SheetSliceGroup *slice_group = temp_slice_group_node->final_slice_group; - - for (struct temp_ase_slice_key_node *node = temp_slice_group_node->temp_ase_slice_key_head; node; node = node->next) - { - ASE_SliceKey *key = node->key; - u32 index_in_frame = node->index_in_frame; - for (ASE_Slice *ase_slice = key->slice_head; ase_slice; ase_slice = ase_slice->next) - { - u32 start = ase_slice->start; - - S_SheetSlice *slice = &slice_group->frame_slices[(start * slice_group->per_frame_count) + index_in_frame]; - - /* Propagate earliest slice to all previous frames */ - if (start == node->earliest_frame && start > 0) - { - for (u32 i = start; i-- > 0;) - { - S_SheetSlice *target = &slice_group->frame_slices[(i * slice_group->per_frame_count) + index_in_frame]; - *target = *slice; - target->original = 0; - } - } - - /* Propagate slice to forward frames until original is found */ - for (u32 i = start + 1; i < ase.num_frames; ++i) - { - S_SheetSlice *target = &slice_group->frame_slices[(i * slice_group->per_frame_count) + index_in_frame]; - if (target->original) - { - break; - } - else - { - *target = *slice; - target->original = 0; - } - } - } - } - } - - /* Calculate direction vectors */ - for (struct temp_slice_group_node *temp_slice_group_node = temp_slice_group_head; temp_slice_group_node; temp_slice_group_node = temp_slice_group_node->next) - { - String ray_suffix = Lit(".ray"); - - S_SheetSliceGroup *ray_slice_group = temp_slice_group_node->final_slice_group; - String ray_slice_name = ray_slice_group->name; - if (StringEndsWith(ray_slice_name, ray_suffix)) - { - String point_slice_name = ray_slice_name; - point_slice_name.len -= ray_suffix.len; - u64 hash = HashFnv64(Fnv64Basis, point_slice_name); - S_SheetSliceGroup *point_slice_group = (S_SheetSliceGroup *)DictValueFromHash(sheet.slice_groups_dict, hash); - if (point_slice_group) - { - u32 point_slices_per_frame = point_slice_group->per_frame_count; - - for (u32 i = 0; i < ase.num_frames; ++i) - { - /* Use ray slice in ray group */ - S_SheetSlice *ray_slice = &ray_slice_group->frame_slices[i * point_slices_per_frame]; - Vec2 ray_end = ray_slice->center_px; - Vec2 ray_end_norm = ray_slice->center; - - /* Apply to each point slice in point group */ - for (u32 j = 0; j < point_slices_per_frame; ++j) - { - S_SheetSlice *point_slice = &point_slice_group->frame_slices[(i * point_slices_per_frame) + j]; - point_slice->dir_px = SubVec2(ray_end, point_slice->center_px); - point_slice->dir = SubVec2(ray_end_norm, point_slice->center); - point_slice->has_ray = 1; - } - } - - } - } - } - - EndScratch(scratch); - } - - return sheet; -} - -void cache_entry_load_sheet(S_Ref ref, S_Tag tag) +void S_LoadCacheEntrySheet(S_CacheEntryRef ref, S_Tag tag) { __prof; S_SharedState *g = &S_shared_state; @@ -579,7 +616,7 @@ void cache_entry_load_sheet(S_Ref ref, S_Tag tag) /* Initialize */ e->sheet = PushStructNoZero(e->arena, S_Sheet); - *e->sheet = init_sheet_from_ase_result(e->arena, decoded); + *e->sheet = S_SheetFromAseResult(e->arena, decoded); e->sheet->loaded = 1; e->sheet->valid = 1; @@ -620,11 +657,10 @@ void cache_entry_load_sheet(S_Ref ref, S_Tag tag) EndScratch(scratch); } -/* ========================== * - * Scope - * ========================== */ +//////////////////////////////// +//~ Ref -void refcount_add(S_CacheEntry *e, i32 amount) +void S_AddRef(S_CacheEntry *e, i32 amount) { S_SharedState *g = &S_shared_state; i32 evictor_cycle = Atomic32Fetch(&g->evictor_cycle.v); @@ -645,11 +681,11 @@ void refcount_add(S_CacheEntry *e, i32 amount) } } -S_ScopeCacheRef *scope_ensure_ref_unsafe(S_Scope *scope, S_CacheEntry *e) +S_ScopeCacheEntryRef *S_EnsureRefUnsafely(S_Scope *scope, S_CacheEntry *e) { u64 bin_index = e->hash.v % S_CacheBinsCount; - S_ScopeCacheRef **slot = &scope->ref_node_bins[bin_index]; + S_ScopeCacheEntryRef **slot = &scope->ref_node_bins[bin_index]; while (*slot) { if ((*slot)->ref.e == e) @@ -671,10 +707,10 @@ S_ScopeCacheRef *scope_ensure_ref_unsafe(S_Scope *scope, S_CacheEntry *e) } /* Increment refcount */ - refcount_add(e, 1); + S_AddRef(e, 1); /* Grab node from pool */ - S_ScopeCacheRef *scope_ref = &scope->ref_node_pool[scope->num_references++]; + S_ScopeCacheEntryRef *scope_ref = &scope->ref_node_pool[scope->num_references++]; ZeroStruct(scope_ref); scope_ref->ref.e = e; @@ -684,27 +720,30 @@ S_ScopeCacheRef *scope_ensure_ref_unsafe(S_Scope *scope, S_CacheEntry *e) return *slot; } -S_ScopeCacheRef *scope_ensure_ref_from_entry(S_Scope *scope, S_CacheEntry *e, P_Lock *bin_lock) +S_ScopeCacheEntryRef *S_EnsureRefFromEntryLocked(S_Scope *scope, S_CacheEntry *e, P_Lock *bin_lock) { S_SharedState *g = &S_shared_state; /* Guaranteed safe if caller has lock on entry's bin, since entry may not have an existing reference and could otherwise be evicted while ensuring this reference */ P_AssertLockedES(bin_lock, &g->cache.bins[e->hash.v % S_CacheBinsCount].mutex); - return scope_ensure_ref_unsafe(scope, e); + return S_EnsureRefUnsafely(scope, e); } -S_ScopeCacheRef *scope_ensure_ref_from_ref(S_Scope *scope, S_Ref ref) +S_ScopeCacheEntryRef *S_EnsureRefFromRef(S_Scope *scope, S_CacheEntryRef ref) { /* Safe since caller has ref */ - return scope_ensure_ref_unsafe(scope, ref.e); + return S_EnsureRefUnsafely(scope, ref.e); } -S_Scope *sprite_scope_begin(void) +//////////////////////////////// +//~ Scope + +S_Scope *S_BeginScope(void) { S_SharedState *g = &S_shared_state; /* Alloc scope */ S_Scope *result = 0; - S_ScopeCacheRef **bins = 0; - S_ScopeCacheRef *pool = 0; + S_ScopeCacheEntryRef **bins = 0; + S_ScopeCacheEntryRef *pool = 0; { P_Lock lock = P_LockE(&g->scopes_mutex); { @@ -718,8 +757,8 @@ S_Scope *sprite_scope_begin(void) else { result = PushStructNoZero(g->scopes_arena, S_Scope); - bins = PushStructsNoZero(g->scopes_arena, S_ScopeCacheRef *, S_CacheBinsCount); - pool = PushStructsNoZero(g->scopes_arena, S_ScopeCacheRef, S_MaxScopeReferences); + bins = PushStructsNoZero(g->scopes_arena, S_ScopeCacheEntryRef *, S_CacheBinsCount); + pool = PushStructsNoZero(g->scopes_arena, S_ScopeCacheEntryRef, S_MaxScopeReferences); } } P_Unlock(&lock); @@ -731,15 +770,15 @@ S_Scope *sprite_scope_begin(void) return result; } -void sprite_scope_end(S_Scope *scope) +void S_EndScope(S_Scope *scope) { S_SharedState *g = &S_shared_state; /* Dereference entries */ u64 num_references = scope->num_references; for (u64 i = 0; i < num_references; ++i) { - S_ScopeCacheRef *n = &scope->ref_node_pool[i]; - refcount_add(n->ref.e, -1); + S_ScopeCacheEntryRef *n = &scope->ref_node_pool[i]; + S_AddRef(n->ref.e, -1); } /* Release scope */ @@ -751,14 +790,15 @@ void sprite_scope_end(S_Scope *scope) P_Unlock(&lock); } -/* ========================== * - * Cache interface - * ========================== */ +//////////////////////////////// +//~ Cache lookup -S_ScopeCacheRef *cache_lookup(S_Scope *scope, S_Hash hash, P_Lock *bin_lock) +//- Locked lookup + +S_ScopeCacheEntryRef *S_EntryFromHashLocked(S_Scope *scope, S_Hash hash, P_Lock *bin_lock) { S_SharedState *g = &S_shared_state; - S_ScopeCacheRef *scope_ref = 0; + S_ScopeCacheEntryRef *scope_ref = 0; S_CacheEntryBin *bin = &g->cache.bins[hash.v % S_CacheBinsCount]; P_AssertLockedES(bin_lock, &bin->mutex); /* Lock required for iterating bin */ @@ -783,14 +823,14 @@ S_ScopeCacheRef *cache_lookup(S_Scope *scope, S_Hash hash, P_Lock *bin_lock) } if (match) { - scope_ref = scope_ensure_ref_from_entry(scope, match, bin_lock); + scope_ref = S_EnsureRefFromEntryLocked(scope, match, bin_lock); } #else for (S_CacheEntry *entry = bin->first; entry; entry = entry->next_in_bin) { if (entry->hash.v == hash.v) { - scope_ref = scope_ensure_ref_from_entry(scope, entry, bin_lock); + scope_ref = S_EnsureRefFromEntryLocked(scope, entry, bin_lock); break; } } @@ -799,12 +839,14 @@ S_ScopeCacheRef *cache_lookup(S_Scope *scope, S_Hash hash, P_Lock *bin_lock) return scope_ref; } -S_ScopeCacheRef *cache_entry_from_tag(S_Scope *scope, S_Tag tag, S_CacheEntryKind kind, b32 force_new) +//- Unlocked lookup + +S_ScopeCacheEntryRef *S_EntryFromTag(S_Scope *scope, S_Tag tag, S_CacheEntryKind kind, b32 force_new) { S_SharedState *g = &S_shared_state; - S_Hash hash = cache_entry_hash_from_tag_hash(tag.hash, kind); + S_Hash hash = S_CacheEntryFromTagHash(tag.hash, kind); u64 bin_index = hash.v % S_CacheBinsCount; - S_ScopeCacheRef *scope_ref = 0; + S_ScopeCacheEntryRef *scope_ref = 0; /* Search for entry in scope */ if (!force_new) @@ -830,7 +872,7 @@ S_ScopeCacheRef *cache_entry_from_tag(S_Scope *scope, S_Tag tag, S_CacheEntryKin { P_Lock bin_lock = P_LockS(&bin->mutex); { - scope_ref = cache_lookup(scope, hash, &bin_lock); + scope_ref = S_EntryFromHashLocked(scope, hash, &bin_lock); } P_Unlock(&bin_lock); } @@ -843,7 +885,7 @@ S_ScopeCacheRef *cache_entry_from_tag(S_Scope *scope, S_Tag tag, S_CacheEntryKin /* Search cache one more time in case an entry was allocated between locks */ if (!force_new) { - scope_ref = cache_lookup(scope, hash, &bin_lock); + scope_ref = S_EntryFromHashLocked(scope, hash, &bin_lock); } if (!scope_ref) @@ -878,12 +920,12 @@ S_ScopeCacheRef *cache_entry_from_tag(S_Scope *scope, S_Tag tag, S_CacheEntryKin } bin->last = entry; } - entry->hash = cache_entry_hash_from_tag_hash(tag.hash, kind); + entry->hash = S_CacheEntryFromTagHash(tag.hash, kind); entry->kind = kind; entry->texture = g->nil_texture; entry->sheet = g->nil_sheet; - scope_ref = scope_ensure_ref_from_entry(scope, entry, &bin_lock); + scope_ref = S_EnsureRefFromEntryLocked(scope, entry, &bin_lock); } } P_Unlock(&bin_lock); @@ -893,7 +935,9 @@ S_ScopeCacheRef *cache_entry_from_tag(S_Scope *scope, S_Tag tag, S_CacheEntryKin return scope_ref; } -void *data_from_tag_internal(S_Scope *scope, S_Tag tag, S_CacheEntryKind kind, b32 await) +//- Data from tag + +void *S_DataFromTag(S_Scope *scope, S_Tag tag, S_CacheEntryKind kind, b32 await) { S_SharedState *g = &S_shared_state; /* TODO: Replace switch statements */ @@ -905,8 +949,8 @@ void *data_from_tag_internal(S_Scope *scope, S_Tag tag, S_CacheEntryKind kind, b default: { P_Panic(Lit("Unknown sprite cache entry kind")); } break; } - S_ScopeCacheRef *scope_ref = cache_entry_from_tag(scope, tag, kind, 0); - S_Ref ref = scope_ref->ref; + S_ScopeCacheEntryRef *scope_ref = S_EntryFromTag(scope, tag, kind, 0); + S_CacheEntryRef ref = scope_ref->ref; S_CacheEntryState state = Atomic32Fetch(&ref.e->state); if (state == CACHE_ENTRY_STATE_LOADED) @@ -930,12 +974,12 @@ void *data_from_tag_internal(S_Scope *scope, S_Tag tag, S_CacheEntryKind kind, b { case CACHE_ENTRY_KIND_TEXTURE: { - cache_entry_load_texture(ref, tag); + S_LoadCacheEntryTexture(ref, tag); result = ref.e->texture; } break; case CACHE_ENTRY_KIND_SHEET: { - cache_entry_load_sheet(ref, tag); + S_LoadCacheEntrySheet(ref, tag); result = ref.e->sheet; } break; default: { P_Panic(Lit("Unknown sprite cache entry kind")); } break; @@ -944,7 +988,7 @@ void *data_from_tag_internal(S_Scope *scope, S_Tag tag, S_CacheEntryKind kind, b else { /* Allocate cmd */ - push_load_job(ref, tag); + S_PushLoadJob(ref, tag); } } } @@ -961,66 +1005,66 @@ void *data_from_tag_internal(S_Scope *scope, S_Tag tag, S_CacheEntryKind kind, b return result; } -/* ========================== * - * Texture - * ========================== */ +//////////////////////////////// +//~ Texture retrieval -S_Texture *sprite_texture_from_tag_await(S_Scope *scope, S_Tag tag) +S_Texture *S_TextureFromTagAwait(S_Scope *scope, S_Tag tag) { - return (S_Texture *)data_from_tag_internal(scope, tag, CACHE_ENTRY_KIND_TEXTURE, 1); + return (S_Texture *)S_DataFromTag(scope, tag, CACHE_ENTRY_KIND_TEXTURE, 1); } -S_Texture *sprite_texture_from_tag_async(S_Scope *scope, S_Tag tag) +S_Texture *S_TextureFromTagAsync(S_Scope *scope, S_Tag tag) { - return (S_Texture *)data_from_tag_internal(scope, tag, CACHE_ENTRY_KIND_TEXTURE, 0); + return (S_Texture *)S_DataFromTag(scope, tag, CACHE_ENTRY_KIND_TEXTURE, 0); } -void sprite_texture_from_tag_prefetch(S_Scope *scope, S_Tag tag) +void S_PrefetchTextureFromTag(S_Scope *scope, S_Tag tag) { - data_from_tag_internal(scope, tag, CACHE_ENTRY_KIND_TEXTURE, 0); + S_DataFromTag(scope, tag, CACHE_ENTRY_KIND_TEXTURE, 0); } -/* ========================== * - * Sheet - * ========================== */ +//////////////////////////////// +//~ Sheet retrieval -S_Sheet *sprite_sheet_from_tag_await(S_Scope *scope, S_Tag tag) +S_Sheet *S_SheetFromTagAwait(S_Scope *scope, S_Tag tag) { - return (S_Sheet *)data_from_tag_internal(scope, tag, CACHE_ENTRY_KIND_SHEET, 1); + return (S_Sheet *)S_DataFromTag(scope, tag, CACHE_ENTRY_KIND_SHEET, 1); } -S_Sheet *sprite_sheet_from_tag_async(S_Scope *scope, S_Tag tag) +S_Sheet *S_SheetFromTagAsync(S_Scope *scope, S_Tag tag) { - return (S_Sheet *)data_from_tag_internal(scope, tag, CACHE_ENTRY_KIND_SHEET, 0); + return (S_Sheet *)S_DataFromTag(scope, tag, CACHE_ENTRY_KIND_SHEET, 0); } -void sprite_sheet_from_tag_prefetch(S_Scope *scope, S_Tag tag) +void S_PrefetchSheetFromTag(S_Scope *scope, S_Tag tag) { - data_from_tag_internal(scope, tag, CACHE_ENTRY_KIND_SHEET, 0); + S_DataFromTag(scope, tag, CACHE_ENTRY_KIND_SHEET, 0); } +//////////////////////////////// +//~ Sheet data -S_SheetFrame sprite_sheet_get_frame(S_Sheet *sheet, u32 index) +S_Frame S_FrameFromIndex(S_Sheet *sheet, u32 index) { if (index < sheet->frames_count) { return sheet->frames[index]; } - S_SheetFrame result = ZI; + S_Frame result = ZI; result.index = 0; result.duration = 0.1; result.clip = AllClipped; return result; } -S_SheetSpan sprite_sheet_get_span(S_Sheet *sheet, String name) +S_Span S_SpanFromName(S_Sheet *sheet, String name) { - S_SheetSpan result = ZI; + S_Span result = ZI; if (sheet->spans_count > 0) { u64 hash = HashFnv64(Fnv64Basis, name); - S_SheetSpan *entry = (S_SheetSpan *)DictValueFromHash(sheet->spans_dict, hash); + S_Span *entry = (S_Span *)DictValueFromHash(sheet->spans_dict, hash); if (entry) { result = *entry; @@ -1030,7 +1074,7 @@ S_SheetSpan sprite_sheet_get_span(S_Sheet *sheet, String name) } /* Returns first slice with name in frame */ -S_SheetSlice sprite_sheet_get_slice(S_Sheet *sheet, String name, u32 frame_index) +S_Slice S_SliceFromNameIndex(S_Sheet *sheet, String name, u32 frame_index) { if (sheet->slice_groups_count > 0) { @@ -1043,7 +1087,7 @@ S_SheetSlice sprite_sheet_get_slice(S_Sheet *sheet, String name, u32 frame_index } /* Return 'pivot' by default */ - S_SheetSlice result = ZI; + S_Slice result = ZI; if (EqString(name, Lit("pivot"))) { /* 'pivot' slice does not exist, return center */ @@ -1054,16 +1098,16 @@ S_SheetSlice sprite_sheet_get_slice(S_Sheet *sheet, String name, u32 frame_index } else { - result = sprite_sheet_get_slice(sheet, Lit("pivot"), frame_index); + result = S_SliceFromNameIndex(sheet, Lit("pivot"), frame_index); } return result; } /* Returns all slices with name in frame */ -S_SheetSliceArray sprite_sheet_get_slices(S_Sheet *sheet, String name, u32 frame_index) +S_SliceArray S_SlicesFromNameIndex(S_Sheet *sheet, String name, u32 frame_index) { - S_SheetSliceArray result = ZI; + S_SliceArray result = ZI; if (sheet->slice_groups_count > 0) { u64 hash = HashFnv64(Fnv64Basis, name); @@ -1077,69 +1121,34 @@ S_SheetSliceArray sprite_sheet_get_slices(S_Sheet *sheet, String name, u32 frame return result; } -/* ========================== * - * Load job - * ========================== */ - -P_JobDef(S_SpriteLoadJob, job) -{ - __prof; - S_SharedState *g = &S_shared_state; - S_Cmd *cmd = job.sig; - S_Ref ref = cmd->ref; - - switch (ref.e->kind) - { - case CACHE_ENTRY_KIND_TEXTURE: - { - cache_entry_load_texture(ref, cmd->tag); - } break; - case CACHE_ENTRY_KIND_SHEET: - { - cache_entry_load_sheet(ref, cmd->tag); - } break; - default: { P_Panic(Lit("Unknown sprite cache node kind")); } break; - } - - /* Free cmd */ - P_Lock lock = P_LockE(&g->cmds_mutex); - { - sprite_scope_end(cmd->scope); - cmd->next_free = g->first_free_cmd; - g->first_free_cmd = cmd; - } - P_Unlock(&lock); -} - -/* ========================== * - * Resource watch - * ========================== */ +//////////////////////////////// +//~ Resource reloading #if RESOURCE_RELOADING void S_ReloadSpriteFromTag(S_Scope *scope, S_Tag tag, S_CacheEntryKind kind) { S_SharedState *g = &S_shared_state; - S_Hash hash = cache_entry_hash_from_tag_hash(tag.hash, kind); + S_Hash hash = S_CacheEntryFromTagHash(tag.hash, kind); S_CacheEntryBin *bin = &g->cache.bins[hash.v % S_CacheBinsCount]; - S_ScopeCacheRef *existing_ref = 0; + S_ScopeCacheEntryRef *existing_ref = 0; P_Lock bin_lock = P_LockS(&bin->mutex); { - existing_ref = cache_lookup(scope, hash, &bin_lock); + existing_ref = S_EntryFromHashLocked(scope, hash, &bin_lock); } P_Unlock(&bin_lock); if (existing_ref) { P_LogInfoF("Sprite resource file \"%F\" has changed for sprite [%F].", FmtString(tag.path), FmtHex(hash.v)); - S_ScopeCacheRef *scope_ref = cache_entry_from_tag(scope, tag, kind, 1); - push_load_job(scope_ref->ref, tag); + S_ScopeCacheEntryRef *scope_ref = S_EntryFromTag(scope, tag, kind, 1); + S_PushLoadJob(scope_ref->ref, tag); } } W_CallbackFuncDef(S_WatchSpriteCallback, name) { - S_Scope *scope = sprite_scope_begin(); + S_Scope *scope = S_BeginScope(); if (StringStartsWith(name, Lit("res/"))) { @@ -1147,13 +1156,13 @@ W_CallbackFuncDef(S_WatchSpriteCallback, name) name.text += Lit("res/").len; } - S_Tag tag = sprite_tag_from_path(name); + S_Tag tag = S_TagFromPath(name); for (S_CacheEntryKind kind = 0; kind < NUM_CACHE_ENTRY_KINDS; ++kind) { S_ReloadSpriteFromTag(scope, tag, kind); } - sprite_scope_end(scope); + S_EndScope(scope); } #endif diff --git a/src/sprite/sprite_core.h b/src/sprite/sprite_core.h index 181778e5..1fea7290 100644 --- a/src/sprite/sprite_core.h +++ b/src/sprite/sprite_core.h @@ -20,23 +20,23 @@ Struct(S_Texture) }; //////////////////////////////// -//~ Sheet +//~ Sheet types -Struct(S_SheetFrame) +Struct(S_Frame) { u32 index; f64 duration; ClipRect clip; }; -Struct(S_SheetSpan) +Struct(S_Span) { String name; u32 start; u32 end; }; -Struct(S_SheetSlice) +Struct(S_Slice) { /* If 1, this slice was not copied over from another frame in the sprite sheet */ b32 original; @@ -55,10 +55,10 @@ Struct(S_SheetSlice) Vec2 dir_px; }; -Struct(S_SheetSliceArray) +Struct(S_SliceArray) { u64 count; - S_SheetSlice *slices; + S_Slice *slices; }; Struct(S_SheetSliceGroup) @@ -68,7 +68,7 @@ Struct(S_SheetSliceGroup) /* 2d array of slices with length (num frames) * (num slices per frame). * Index with [(frame index * num slices per frame) + slice index in frame] */ - S_SheetSlice *frame_slices; + S_Slice *frame_slices; }; Struct(S_Sheet) @@ -79,10 +79,10 @@ Struct(S_Sheet) Vec2 frame_size; u32 frames_count; - S_SheetFrame *frames; + S_Frame *frames; u32 spans_count; - S_SheetSpan *spans; + S_Span *spans; Dict *spans_dict; u32 slice_groups_count; @@ -91,7 +91,7 @@ Struct(S_Sheet) }; //////////////////////////////// -//~ Cache +//~ Cache types typedef i32 S_CacheEntryKind; enum { @@ -165,7 +165,7 @@ Struct(S_Cache) }; /* Represents a reference that can be used to safely access cache entry without it becoming evicted during the reference's lifetime */ -Struct(S_Ref) +Struct(S_CacheEntryRef) { S_CacheEntry *e; }; @@ -174,16 +174,16 @@ Struct(S_Ref) //~ Scope /* A cache reference whose lifetime is bound to the scope it was retrieved from */ -Struct(S_ScopeCacheRef) +Struct(S_ScopeCacheEntryRef) { - S_Ref ref; - S_ScopeCacheRef *next_in_bin; + S_CacheEntryRef ref; + S_ScopeCacheEntryRef *next_in_bin; }; Struct(S_Scope) { - S_ScopeCacheRef **ref_node_bins; - S_ScopeCacheRef *ref_node_pool; + S_ScopeCacheEntryRef **ref_node_bins; + S_ScopeCacheEntryRef *ref_node_pool; u64 num_references; S_Scope *next_free; }; @@ -195,7 +195,7 @@ Struct(S_Cmd) { S_Cmd *next_free; S_Scope *scope; - S_Ref ref; + S_CacheEntryRef ref; S_Tag tag; u8 tag_path_buff[512]; }; @@ -275,146 +275,96 @@ extern S_SharedState S_shared_state; //~ Startup Struct(S_StartupReceipt) { i32 _; }; -S_StartupReceipt sprite_startup(void); +S_StartupReceipt S_Startup(void); + +//////////////////////////////// +//~ Shutdown + +P_ExitFuncDef(S_Shutdown); + +//////////////////////////////// +//~ Purple-black image + +u32 *S_GeneratePurpleBlackImage(Arena *arena, u32 width, u32 height); //////////////////////////////// //~ Tag operations -Inline S_Tag sprite_tag_nil(void) { return (S_Tag) { 0 }; } +S_Tag S_TagFromPath(String path); +b32 S_IsTagNil(S_Tag tag); +b32 S_EqTag(S_Tag t1, S_Tag t2); +S_Hash S_CacheEntryFromTagHash(u64 tag_hash, S_CacheEntryKind kind); -S_Tag sprite_tag_from_path(String path); -b32 sprite_tag_is_nil(S_Tag tag); -b32 sprite_tag_eq(S_Tag t1, S_Tag t2); +//////////////////////////////// +//~ Sheet init + +S_Sheet S_SheetFromAseResult(Arena *arena, ASE_DecodedSheet ase); + +//////////////////////////////// +//~ Load job + +void S_PushLoadJob(S_CacheEntryRef ref, S_Tag tag); +P_JobDef(S_LoadSpriteJob, job); + +//////////////////////////////// +//~ Cache load operations + +void S_LoadCacheEntryTexture(S_CacheEntryRef ref, S_Tag tag); +void S_LoadCacheEntrySheet(S_CacheEntryRef ref, S_Tag tag); + +//////////////////////////////// +//~ Ref operations + +void S_AddRef(S_CacheEntry *e, i32 amount); +S_ScopeCacheEntryRef *S_EnsureRefUnsafely(S_Scope *scope, S_CacheEntry *e); +S_ScopeCacheEntryRef *S_EnsureRefFromEntryLocked(S_Scope *scope, S_CacheEntry *e, P_Lock *bin_lock); +S_ScopeCacheEntryRef *S_EnsureRefFromRef(S_Scope *scope, S_CacheEntryRef ref); //////////////////////////////// //~ Scope operations -S_Scope *sprite_scope_begin(void); -void sprite_scope_end(S_Scope *scope); - -/* ========================== * - * Texture load - * ========================== */ - -/* ========================== * - * Cache structs - * ========================== */ - -/* ========================== * - * Purple-black image - * ========================== */ - -u32 *generate_purple_black_image(Arena *arena, u32 width, u32 height); - -/* ========================== * - * Startup - * ========================== */ - -S_StartupReceipt sprite_startup(void); - -P_ExitFuncDef(sprite_shutdown); - -/* ========================== * - * Tag - * ========================== */ - -S_Tag sprite_tag_from_path(String path); - -b32 sprite_tag_is_nil(S_Tag tag); - -b32 sprite_tag_eq(S_Tag t1, S_Tag t2); - -S_Hash cache_entry_hash_from_tag_hash(u64 tag_hash, S_CacheEntryKind kind); - -/* ========================== * - * Load - * ========================== */ - -S_ScopeCacheRef *scope_ensure_ref_from_ref(S_Scope *scope, S_Ref ref); -void push_load_job(S_Ref ref, S_Tag tag); - -void cache_entry_load_texture(S_Ref ref, S_Tag tag); - -S_Sheet init_sheet_from_ase_result(Arena *arena, ASE_DecodedSheet ase); - -void cache_entry_load_sheet(S_Ref ref, S_Tag tag); - -/* ========================== * - * Scope - * ========================== */ - -void refcount_add(S_CacheEntry *e, i32 amount); - -S_ScopeCacheRef *scope_ensure_ref_unsafe(S_Scope *scope, S_CacheEntry *e); - -S_ScopeCacheRef *scope_ensure_ref_from_entry(S_Scope *scope, S_CacheEntry *e, P_Lock *bin_lock); - -S_ScopeCacheRef *scope_ensure_ref_from_ref(S_Scope *scope, S_Ref ref); - -S_Scope *sprite_scope_begin(void); - -void sprite_scope_end(S_Scope *scope); - -/* ========================== * - * Cache interface - * ========================== */ - -S_ScopeCacheRef *cache_lookup(S_Scope *scope, S_Hash hash, P_Lock *bin_lock); - -S_ScopeCacheRef *cache_entry_from_tag(S_Scope *scope, S_Tag tag, S_CacheEntryKind kind, b32 force_new); - -void *data_from_tag_internal(S_Scope *scope, S_Tag tag, S_CacheEntryKind kind, b32 await); - -/* ========================== * - * Texture - * ========================== */ - -S_Texture *sprite_texture_from_tag_await(S_Scope *scope, S_Tag tag); - -S_Texture *sprite_texture_from_tag_async(S_Scope *scope, S_Tag tag); - -void sprite_texture_from_tag_prefetch(S_Scope *scope, S_Tag tag); - -/* ========================== * - * Sheet - * ========================== */ - -S_Sheet *sprite_sheet_from_tag_await(S_Scope *scope, S_Tag tag); - -S_Sheet *sprite_sheet_from_tag_async(S_Scope *scope, S_Tag tag); - -void sprite_sheet_from_tag_prefetch(S_Scope *scope, S_Tag tag); - - -S_SheetFrame sprite_sheet_get_frame(S_Sheet *sheet, u32 index); - -S_SheetSpan sprite_sheet_get_span(S_Sheet *sheet, String name); - -/* Returns first slice with name in frame */ -S_SheetSlice sprite_sheet_get_slice(S_Sheet *sheet, String name, u32 frame_index); - -/* Returns all slices with name in frame */ -S_SheetSliceArray sprite_sheet_get_slices(S_Sheet *sheet, String name, u32 frame_index); - -/* ========================== * - * Load job - * ========================== */ - -P_JobDef(S_SpriteLoadJob, job); +S_Scope *S_BeginScope(void); +void S_EndScope(S_Scope *scope); //////////////////////////////// -//~ Resource watch +//~ Cache lookup operations + +S_ScopeCacheEntryRef *S_EntryFromHashLocked(S_Scope *scope, S_Hash hash, P_Lock *bin_lock); +S_ScopeCacheEntryRef *S_EntryFromTag(S_Scope *scope, S_Tag tag, S_CacheEntryKind kind, b32 force_new); +void *S_DataFromTag(S_Scope *scope, S_Tag tag, S_CacheEntryKind kind, b32 await); + +//////////////////////////////// +//~ Texture retrieval operations + +S_Texture *S_TextureFromTagAwait(S_Scope *scope, S_Tag tag); +S_Texture *S_TextureFromTagAsync(S_Scope *scope, S_Tag tag); +void S_PrefetchTextureFromTag(S_Scope *scope, S_Tag tag); + +//////////////////////////////// +//~ Sheet retrieval operations + +S_Sheet *S_SheetFromTagAwait(S_Scope *scope, S_Tag tag); +S_Sheet *S_SheetFromTagAsync(S_Scope *scope, S_Tag tag); +void S_PrefetchSheetFromTag(S_Scope *scope, S_Tag tag); + +//////////////////////////////// +//~ Sheet data operations + +S_Frame S_FrameFromIndex(S_Sheet *sheet, u32 index); +S_Span S_SpanFromName(S_Sheet *sheet, String name); +S_Slice S_SliceFromNameIndex(S_Sheet *sheet, String name, u32 frame_index); +S_SliceArray S_SlicesFromNameIndex(S_Sheet *sheet, String name, u32 frame_index); + +//////////////////////////////// +//~ Resource reload #if RESOURCE_RELOADING - void S_ReloadSpriteFromTag(S_Scope *scope, S_Tag tag, S_CacheEntryKind kind); W_CallbackFuncDef(S_WatchSpriteCallback, name); - #endif //////////////////////////////// //~ Evictor job MergesortCompareFuncDef(S_EvictorSortCmp, arg_a, arg_b, udata); - P_JobDef(S_EvictorJob, _); diff --git a/src/user/user_core.c b/src/user/user_core.c index d5de3e5b..c2feffa5 100644 --- a/src/user/user_core.c +++ b/src/user/user_core.c @@ -559,7 +559,7 @@ internal void user_update(P_Window *window) G.real_time_ns += G.real_dt_ns; G.screen_size = P_GetWindowSize(window); - S_Scope *sprite_frame_scope = sprite_scope_begin(); + S_Scope *sprite_frame_scope = S_BeginScope(); /* ========================== * * Pull latest local sim snapshot @@ -1161,7 +1161,7 @@ internal void user_update(P_Window *window) for (u64 sorted_index = 0; sorted_index < sorted_count; ++sorted_index) { Ent *ent = sorted[sorted_index]; if (!sim_ent_is_valid_and_active(ent)) continue; - //if (sprite_tag_is_nil(ent->sprite)) continue; + //if (S_IsTagNil(ent->sprite)) continue; S_Tag sprite = ent->sprite; @@ -1219,16 +1219,16 @@ internal void user_update(P_Window *window) #endif /* Draw sprite */ - if (!sprite_tag_is_nil(sprite)) { - S_Sheet *sheet = sprite_sheet_from_tag_async(sprite_frame_scope, sprite); - S_Texture *texture = sprite_texture_from_tag_async(sprite_frame_scope, sprite); + if (!S_IsTagNil(sprite)) { + S_Sheet *sheet = S_SheetFromTagAsync(sprite_frame_scope, sprite); + S_Texture *texture = S_TextureFromTagAsync(sprite_frame_scope, sprite); /* TODO: Fade in placeholder if texture isn't loaded */ if (sheet->loaded && texture->loaded) { b32 is_light = sim_ent_has_prop(ent, SEPROP_LIGHT_TEST); Vec3 emittance = ent->sprite_emittance; u32 tint = ent->sprite_tint; - S_SheetFrame frame = sprite_sheet_get_frame(sheet, ent->animation_frame); + S_Frame frame = S_FrameFromIndex(sheet, ent->animation_frame); D_MaterialParams params = D_MATERIALPARAMS(.xf = sprite_xform, .texture = texture->gp_texture, .tint = tint, .clip = frame.clip, .is_light = is_light, .light_emittance = emittance); D_DrawMaterial(G.render_sig, params); } @@ -1238,8 +1238,8 @@ internal void user_update(P_Window *window) /* TODO: Something better */ if (sim_ent_has_prop(ent, SEPROP_TILE_CHUNK)) { Vec2I32 chunk_index = ent->tile_chunk_index; - S_Tag tile_sprite = sprite_tag_from_path(Lit("sprite/tile.ase")); - S_Texture *tile_texture = sprite_texture_from_tag_async(sprite_frame_scope, tile_sprite); + S_Tag tile_sprite = S_TagFromPath(Lit("sprite/tile.ase")); + S_Texture *tile_texture = S_TextureFromTagAsync(sprite_frame_scope, tile_sprite); if (tile_texture->loaded) { f32 tile_size = 1.f / SIM_TILES_PER_UNIT_SQRT; for (i32 tile_y = 0; tile_y < SIM_TILES_PER_CHUNK_SQRT; ++tile_y) { @@ -1286,8 +1286,8 @@ internal void user_update(P_Window *window) /* Draw focus arrow */ if (ent == local_control || sim_ent_id_eq(ent->id, G.debug_following)) { - S_Sheet *sheet = sprite_sheet_from_tag_async(sprite_frame_scope, ent->sprite); - S_SheetSlice slice = sprite_sheet_get_slice(sheet, Lit("attach.wep"), ent->animation_frame); + S_Sheet *sheet = S_SheetFromTagAsync(sprite_frame_scope, ent->sprite); + S_Slice slice = S_SliceFromNameIndex(sheet, Lit("attach.wep"), ent->animation_frame); Vec2 start = MulXformV2(sprite_xform, slice.center); start = MulXformV2(G.world_to_ui_xf, start); Vec2 end = AddVec2(xf.og, ent->control.focus); @@ -1297,8 +1297,8 @@ internal void user_update(P_Window *window) #if 0 /* Draw slices */ - if (!sprite_tag_is_nil(ent->sprite)) { - S_Sheet *sheet = sprite_sheet_from_tag_async(sprite_frame_scope, sprite); + if (!S_IsTagNil(ent->sprite)) { + S_Sheet *sheet = S_SheetFromTagAsync(sprite_frame_scope, sprite); u32 quad_color = Rgba32F(1, 0, 0.5, 1); u32 point_color = Rgba32F(1, 0, 0, 1); @@ -1309,7 +1309,7 @@ internal void user_update(P_Window *window) if (StringEndsWith(group->name, Lit(".ray"))) continue; for (u32 j = 0; j < group->per_frame_count; ++j) { - S_SheetSlice slice = group->frame_slices[(ent->animation_frame * group->per_frame_count) + j]; + S_Slice slice = group->frame_slices[(ent->animation_frame * group->per_frame_count) + j]; Vec2 center = MulXformV2(sprite_xform, slice.center); center = MulXformV2(G.world_to_ui_xf, center); @@ -1690,8 +1690,8 @@ internal void user_update(P_Window *window) if (!G.debug_camera) { __profn("Draw crosshair"); Vec2 crosshair_pos = G.ui_cursor; - S_Tag crosshair = sprite_tag_from_path(Lit("sprite/crosshair.ase")); - S_Texture *t = sprite_texture_from_tag_async(sprite_frame_scope, crosshair); + S_Tag crosshair = S_TagFromPath(Lit("sprite/crosshair.ase")); + S_Texture *t = S_TextureFromTagAsync(sprite_frame_scope, crosshair); Vec2 size = VEC2(t->width, t->height); Xform xf = XformFromTrs(TRS(.t = crosshair_pos, .s = size)); D_DrawUiRect(G.render_sig, D_UIRECTPARAMS(.xf = xf, .texture = t->gp_texture)); @@ -1705,7 +1705,7 @@ internal void user_update(P_Window *window) P_DisableWindoweCursorClip(G.window); P_ShowWindowCursor(G.window); } else { - S_Texture *t = sprite_texture_from_tag_async(sprite_frame_scope, sprite_tag_from_path(Lit("sprite/crosshair.ase"))); + S_Texture *t = S_TextureFromTagAsync(sprite_frame_scope, S_TagFromPath(Lit("sprite/crosshair.ase"))); Vec2 size = VEC2(t->width, t->height); Rect cursor_clip = RectFromVec2(G.ui_screen_offset, G.ui_size); cursor_clip.pos = AddVec2(cursor_clip.pos, MulVec2(size, 0.5f)); @@ -2073,7 +2073,7 @@ internal void user_update(P_Window *window) * End frame cache scopes * ========================== */ - sprite_scope_end(sprite_frame_scope); + S_EndScope(sprite_frame_scope); EndScratch(scratch); }