sprite layer refactor progress
This commit is contained in:
parent
32631d0ae9
commit
9d8758b2b4
@ -405,9 +405,8 @@ internal void test_spawn_tile(Snapshot *world, Vec2 world_pos)
|
||||
|
||||
|
||||
|
||||
internal MergesortCompareFuncDef(tile_chunk_sort_x, arg_a, arg_b, udata)
|
||||
internal MergesortCompareFuncDef(tile_chunk_sort_x, arg_a, arg_b, _)
|
||||
{
|
||||
(UNUSED)udata;
|
||||
Ent *a = *(Ent **)arg_a;
|
||||
Ent *b = *(Ent **)arg_b;
|
||||
i32 a_x = a->tile_chunk_index.x;
|
||||
@ -418,9 +417,8 @@ internal MergesortCompareFuncDef(tile_chunk_sort_x, arg_a, arg_b, udata)
|
||||
return result;
|
||||
}
|
||||
|
||||
internal MergesortCompareFuncDef(tile_chunk_sort_y, arg_a, arg_b, udata)
|
||||
internal MergesortCompareFuncDef(tile_chunk_sort_y, arg_a, arg_b, _)
|
||||
{
|
||||
(UNUSED)udata;
|
||||
Ent *a = *(Ent **)arg_a;
|
||||
Ent *b = *(Ent **)arg_b;
|
||||
i32 a_y = a->tile_chunk_index.y;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,48 +1,17 @@
|
||||
/* ========================== *
|
||||
* Startup
|
||||
* ========================== */
|
||||
////////////////////////////////
|
||||
//~ Tag
|
||||
|
||||
typedef struct S_StartupReceipt S_StartupReceipt;
|
||||
struct S_StartupReceipt { i32 _; };
|
||||
S_StartupReceipt sprite_startup(void);
|
||||
|
||||
/* ========================== *
|
||||
* Tag
|
||||
* ========================== */
|
||||
|
||||
typedef struct S_Tag S_Tag;
|
||||
struct S_Tag {
|
||||
Struct(S_Tag)
|
||||
{
|
||||
u64 hash;
|
||||
String path;
|
||||
};
|
||||
|
||||
Inline S_Tag sprite_tag_nil(void) { return (S_Tag) { 0 }; }
|
||||
////////////////////////////////
|
||||
//~ Texture
|
||||
|
||||
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);
|
||||
|
||||
/* ========================== *
|
||||
* Scope
|
||||
* ========================== */
|
||||
|
||||
typedef struct S_Scope S_Scope;
|
||||
struct S_Scope {
|
||||
struct sprite_scope_cache_ref **ref_node_bins;
|
||||
struct sprite_scope_cache_ref *ref_node_pool;
|
||||
u64 num_references;
|
||||
S_Scope *next_free;
|
||||
};
|
||||
|
||||
S_Scope *sprite_scope_begin(void);
|
||||
void sprite_scope_end(S_Scope *scope);
|
||||
|
||||
/* ========================== *
|
||||
* Texture load
|
||||
* ========================== */
|
||||
|
||||
typedef struct S_Texture S_Texture;
|
||||
struct S_Texture {
|
||||
Struct(S_Texture)
|
||||
{
|
||||
b32 loaded;
|
||||
b32 valid;
|
||||
GPU_Resource *gp_texture;
|
||||
@ -50,60 +19,25 @@ struct S_Texture {
|
||||
u32 height;
|
||||
};
|
||||
|
||||
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
|
||||
|
||||
/* ========================== *
|
||||
* Sheet load
|
||||
* ========================== */
|
||||
|
||||
typedef struct S_SheetSliceGroup S_SheetSliceGroup;
|
||||
typedef struct S_SheetSpan S_SheetSpan;
|
||||
typedef struct S_SheetFrame S_SheetFrame;
|
||||
typedef struct S_Sheet S_Sheet;
|
||||
struct S_Sheet {
|
||||
b32 loaded;
|
||||
b32 valid;
|
||||
Vec2 image_size;
|
||||
Vec2 frame_size;
|
||||
|
||||
u32 frames_count;
|
||||
S_SheetFrame *frames;
|
||||
|
||||
u32 spans_count;
|
||||
S_SheetSpan *spans;
|
||||
Dict *spans_dict;
|
||||
|
||||
u32 slice_groups_count;
|
||||
S_SheetSliceGroup *slice_groups;
|
||||
Dict *slice_groups_dict;
|
||||
};
|
||||
|
||||
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);
|
||||
|
||||
/* ========================== *
|
||||
* Sheet query
|
||||
* ========================== */
|
||||
|
||||
typedef struct S_SheetFrame S_SheetFrame;
|
||||
struct S_SheetFrame {
|
||||
Struct(S_SheetFrame)
|
||||
{
|
||||
u32 index;
|
||||
f64 duration;
|
||||
ClipRect clip;
|
||||
};
|
||||
|
||||
typedef struct S_SheetSpan S_SheetSpan;
|
||||
struct S_SheetSpan {
|
||||
Struct(S_SheetSpan)
|
||||
{
|
||||
String name;
|
||||
u32 start;
|
||||
u32 end;
|
||||
};
|
||||
|
||||
typedef struct S_SheetSlice S_SheetSlice;
|
||||
struct S_SheetSlice {
|
||||
Struct(S_SheetSlice)
|
||||
{
|
||||
/* If 1, this slice was not copied over from another frame in the sprite sheet */
|
||||
b32 original;
|
||||
|
||||
@ -121,14 +55,14 @@ struct S_SheetSlice {
|
||||
Vec2 dir_px;
|
||||
};
|
||||
|
||||
typedef struct S_SheetSliceArray S_SheetSliceArray;
|
||||
struct S_SheetSliceArray {
|
||||
Struct(S_SheetSliceArray)
|
||||
{
|
||||
u64 count;
|
||||
S_SheetSlice *slices;
|
||||
};
|
||||
|
||||
typedef struct S_SheetSliceGroup S_SheetSliceGroup;
|
||||
struct S_SheetSliceGroup {
|
||||
Struct(S_SheetSliceGroup)
|
||||
{
|
||||
String name;
|
||||
u64 per_frame_count;
|
||||
|
||||
@ -137,6 +71,321 @@ struct S_SheetSliceGroup {
|
||||
S_SheetSlice *frame_slices;
|
||||
};
|
||||
|
||||
Struct(S_Sheet)
|
||||
{
|
||||
b32 loaded;
|
||||
b32 valid;
|
||||
Vec2 image_size;
|
||||
Vec2 frame_size;
|
||||
|
||||
u32 frames_count;
|
||||
S_SheetFrame *frames;
|
||||
|
||||
u32 spans_count;
|
||||
S_SheetSpan *spans;
|
||||
Dict *spans_dict;
|
||||
|
||||
u32 slice_groups_count;
|
||||
S_SheetSliceGroup *slice_groups;
|
||||
Dict *slice_groups_dict;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ Cache
|
||||
|
||||
typedef i32 S_CacheEntryKind; enum
|
||||
{
|
||||
CACHE_ENTRY_KIND_TEXTURE,
|
||||
CACHE_ENTRY_KIND_SHEET,
|
||||
|
||||
NUM_CACHE_ENTRY_KINDS
|
||||
};
|
||||
|
||||
typedef i32 S_CacheEntryState; enum
|
||||
{
|
||||
CACHE_ENTRY_STATE_NONE,
|
||||
CACHE_ENTRY_STATE_QUEUED,
|
||||
CACHE_ENTRY_STATE_WORKING,
|
||||
CACHE_ENTRY_STATE_LOADED
|
||||
};
|
||||
|
||||
Struct(S_Refcount)
|
||||
{
|
||||
i32 count; /* Number of scopes currently holding a reference to this entry */
|
||||
i32 last_ref_cycle; /* Last evictor cycle that the refcount was modified */
|
||||
};
|
||||
StaticAssert(sizeof(S_Refcount) == 8); /* Must fit into 64 bit atomic */
|
||||
|
||||
Struct(S_Hash)
|
||||
{
|
||||
u64 v;
|
||||
};
|
||||
|
||||
Struct(S_CacheEntry)
|
||||
{
|
||||
S_CacheEntryKind kind;
|
||||
S_Hash hash;
|
||||
Atomic32 state;
|
||||
Atomic64Padded refcount_struct; /* Cast fetched result to `cache_refcount` */
|
||||
|
||||
/* Allocated data */
|
||||
/* NOTE: This data is finalized once entry state = loaded */
|
||||
i64 load_time_ns;
|
||||
u64 memory_usage;
|
||||
Arena *arena;
|
||||
S_Texture *texture;
|
||||
S_Sheet *sheet;
|
||||
|
||||
/* Hash list */
|
||||
S_CacheEntry *next_in_bin;
|
||||
S_CacheEntry *prev_in_bin;
|
||||
|
||||
/* Free list */
|
||||
S_CacheEntry *next_free;
|
||||
|
||||
#if RESOURCE_RELOADING
|
||||
Atomic32 out_of_date; /* Has the resource changed since this entry was loaded */
|
||||
#endif
|
||||
};
|
||||
|
||||
Struct(S_CacheEntryBin)
|
||||
{
|
||||
P_Mutex mutex;
|
||||
S_CacheEntry *first;
|
||||
S_CacheEntry *last;
|
||||
};
|
||||
|
||||
Struct(S_Cache)
|
||||
{
|
||||
Atomic64Padded memory_usage;
|
||||
Arena *arena;
|
||||
S_CacheEntryBin *bins;
|
||||
P_Mutex entry_pool_mutex;
|
||||
S_CacheEntry *entry_pool_first_free;
|
||||
};
|
||||
|
||||
/* Represents a reference that can be used to safely access cache entry without it becoming evicted during the reference's lifetime */
|
||||
Struct(S_Ref)
|
||||
{
|
||||
S_CacheEntry *e;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ Scope
|
||||
|
||||
/* A cache reference whose lifetime is bound to the scope it was retrieved from */
|
||||
Struct(S_ScopeCacheRef)
|
||||
{
|
||||
S_Ref ref;
|
||||
S_ScopeCacheRef *next_in_bin;
|
||||
};
|
||||
|
||||
Struct(S_Scope)
|
||||
{
|
||||
S_ScopeCacheRef **ref_node_bins;
|
||||
S_ScopeCacheRef *ref_node_pool;
|
||||
u64 num_references;
|
||||
S_Scope *next_free;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ Cmd
|
||||
|
||||
Struct(S_Cmd)
|
||||
{
|
||||
S_Cmd *next_free;
|
||||
S_Scope *scope;
|
||||
S_Ref ref;
|
||||
S_Tag tag;
|
||||
u8 tag_path_buff[512];
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ Evictor
|
||||
|
||||
Struct(S_EvictorNode)
|
||||
{
|
||||
i32 last_ref_cycle;
|
||||
S_CacheEntry *cache_entry;
|
||||
S_CacheEntryBin *cache_bin;
|
||||
S_EvictorNode *next_evicted;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ Cache constants
|
||||
|
||||
/* The evictor will begin evicting once cache usage is > threshold.
|
||||
* It will entries until the budget has shrunk < target. */
|
||||
#define S_CacheMemoryBudgetThreshold (Mebi(256))
|
||||
#define S_CacheMemoryBudgetTarget (Mebi(128))
|
||||
StaticAssert(S_CacheMemoryBudgetThreshold >= S_CacheMemoryBudgetTarget);
|
||||
|
||||
#define S_CacheBinsCount 1024
|
||||
|
||||
#define S_MaxScopeReferences 1024
|
||||
|
||||
/* Texture arena only used to store texture struct at the moment. Actual image data is allocated on GPU. */
|
||||
#define S_TextureArenaReserve Mebi(1)
|
||||
|
||||
#define S_SheetArenaReserve Mebi(64)
|
||||
#define S_SheetSpanLookupTableBinRatio 2.0
|
||||
#define S_SliceLookupTableBinRatio 2.0
|
||||
|
||||
/* How long between evictor cycles */
|
||||
#define S_EvictorCycleIntervalNs NsFromSeconds(0.500)
|
||||
|
||||
/* How many cycles a cache entry spends unused until it's considered evictable */
|
||||
#define S_EvictorGracePeriodCycles (NsFromSeconds(10.000) / S_EvictorCycleIntervalNs)
|
||||
|
||||
////////////////////////////////
|
||||
//~ Shared state
|
||||
|
||||
Struct(S_SharedState)
|
||||
{
|
||||
Arena *perm_arena;
|
||||
S_Texture *nil_texture;
|
||||
S_Texture *loading_texture;
|
||||
S_Sheet *nil_sheet;
|
||||
S_Sheet *loading_sheet;
|
||||
|
||||
/* Cache */
|
||||
S_Cache cache;
|
||||
|
||||
/* Cmds */
|
||||
P_Mutex cmds_mutex;
|
||||
Arena *cmds_arena;
|
||||
S_Cmd *first_free_cmd;
|
||||
|
||||
/* Scopes */
|
||||
P_Mutex scopes_mutex;
|
||||
Arena *scopes_arena;
|
||||
S_Scope *first_free_scope;
|
||||
|
||||
/* Evictor */
|
||||
Atomic32Padded evictor_cycle;
|
||||
P_Counter shutdown_counter;
|
||||
b32 evictor_scheduler_shutdown;
|
||||
P_Mutex evictor_scheduler_mutex;
|
||||
P_Cv evictor_scheduler_shutdown_cv;
|
||||
};
|
||||
|
||||
extern S_SharedState S_shared_state;
|
||||
|
||||
////////////////////////////////
|
||||
//~ Startup
|
||||
|
||||
Struct(S_StartupReceipt) { i32 _; };
|
||||
S_StartupReceipt sprite_startup(void);
|
||||
|
||||
////////////////////////////////
|
||||
//~ Tag operations
|
||||
|
||||
Inline S_Tag sprite_tag_nil(void) { return (S_Tag) { 0 }; }
|
||||
|
||||
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);
|
||||
|
||||
////////////////////////////////
|
||||
//~ 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);
|
||||
@ -146,3 +395,26 @@ 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);
|
||||
|
||||
////////////////////////////////
|
||||
//~ Resource watch
|
||||
|
||||
#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, _);
|
||||
|
||||
@ -506,9 +506,8 @@ internal void draw_debug_console(i32 level, b32 minimized)
|
||||
* Sort entities
|
||||
* ========================== */
|
||||
|
||||
internal MergesortCompareFuncDef(ent_draw_order_cmp, arg_a, arg_b, udata)
|
||||
internal MergesortCompareFuncDef(ent_draw_order_cmp, arg_a, arg_b, _)
|
||||
{
|
||||
(UNUSED)udata;
|
||||
Ent *a = *(Ent **)arg_a;
|
||||
Ent *b = *(Ent **)arg_b;
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user