begin new sprite layer
This commit is contained in:
parent
2bfc0d2ab2
commit
d332315c16
@ -211,7 +211,7 @@ String SwappedStateFromName(Arena *arena, String name)
|
|||||||
{
|
{
|
||||||
TempArena scratch = BeginScratch(arena);
|
TempArena scratch = BeginScratch(arena);
|
||||||
String result = Zi;
|
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);
|
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);
|
HANDLE handle = CreateFileW(path_wstr, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
|
||||||
if (handle != INVALID_HANDLE_VALUE)
|
if (handle != INVALID_HANDLE_VALUE)
|
||||||
@ -240,7 +240,7 @@ void WriteSwappedState(String name, String data)
|
|||||||
{
|
{
|
||||||
TempArena scratch = BeginScratchNoConflict();
|
TempArena scratch = BeginScratchNoConflict();
|
||||||
String dir_path = PathFromString(scratch.arena, StringF(scratch.arena, "%F/swap", FmtString(GetAppDirectory())), '\\');
|
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 *dir_path_wstr = WstrFromString(scratch.arena, dir_path);
|
||||||
wchar_t *path_wstr = WstrFromString(scratch.arena, path);
|
wchar_t *path_wstr = WstrFromString(scratch.arena, path);
|
||||||
SHCreateDirectoryExW(0, dir_path_wstr, 0);
|
SHCreateDirectoryExW(0, dir_path_wstr, 0);
|
||||||
|
|||||||
@ -223,7 +223,7 @@ S_Shape S_LocalShapeFromEnt(S_Ent *ent)
|
|||||||
{
|
{
|
||||||
S_Shape result = Zi;
|
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)
|
if (ent->is_player)
|
||||||
{
|
{
|
||||||
result = S_ShapeFromDesc(
|
result = S_ShapeFromDesc(
|
||||||
@ -1277,7 +1277,7 @@ void S_TickForever(WaveLaneCtx *lane)
|
|||||||
String packed = Zi;
|
String packed = Zi;
|
||||||
if (swapin)
|
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);
|
S_UnpackedWorld unpacked = S_UnpackWorld(frame_arena, packed);
|
||||||
|
|
||||||
@ -1306,7 +1306,7 @@ void S_TickForever(WaveLaneCtx *lane)
|
|||||||
if (swapout)
|
if (swapout)
|
||||||
{
|
{
|
||||||
String packed = S_PackWorld(frame_arena, world);
|
String packed = S_PackWorld(frame_arena, world);
|
||||||
WriteSwappedState(Lit("pp_sim"), packed);
|
WriteSwappedState(Lit("pp_sim.swp"), packed);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -14,3 +14,20 @@ i32 S_TileIdxFromTilePos(Vec2I32 p)
|
|||||||
i32 result = ClampI32(p.x + (p.y * S_TilesPitch), 0, S_TilesCount);
|
i32 result = ClampI32(p.x + (p.y * S_TilesPitch), 0, S_TilesCount);
|
||||||
return result;
|
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
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
//~ Tile types
|
//~ Tile types
|
||||||
|
|
||||||
#define S_WorldPitch 60.0
|
#define S_WorldPitch 64.0
|
||||||
#define S_TilesPitch (S_WorldPitch * 2)
|
#define S_TilesPitch (S_WorldPitch * 2)
|
||||||
#define S_TilesCount (S_TilesPitch * S_TilesPitch)
|
#define S_TilesCount (S_TilesPitch * S_TilesPitch)
|
||||||
|
|
||||||
@ -11,12 +11,12 @@
|
|||||||
X(Wall) \
|
X(Wall) \
|
||||||
/* -------------------- */
|
/* -------------------- */
|
||||||
|
|
||||||
// Tiles enum
|
//- Tiles kinds enum
|
||||||
Enum(S_TileKind)
|
Enum(S_TileKind)
|
||||||
{
|
{
|
||||||
#define X(name, ...) S_TileKind_##name,
|
#define X(name, ...) S_TileKind_##name,
|
||||||
S_TilesXMacro(X)
|
S_TilesXMacro(X)
|
||||||
#undef X
|
#undef X
|
||||||
S_TileKind_COUNT
|
S_TileKind_COUNT
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -25,3 +25,7 @@ Enum(S_TileKind)
|
|||||||
|
|
||||||
Vec2I32 S_TilePosFromWorldPos(Vec2 p);
|
Vec2I32 S_TilePosFromWorldPos(Vec2 p);
|
||||||
i32 S_TileIdxFromTilePos(Vec2I32 p);
|
i32 S_TileIdxFromTilePos(Vec2I32 p);
|
||||||
|
|
||||||
|
#if IsLanguageC
|
||||||
|
String S_TileNameFromKind(S_TileKind kind);
|
||||||
|
#endif
|
||||||
|
|||||||
@ -4,12 +4,13 @@
|
|||||||
//- Dependencies
|
//- Dependencies
|
||||||
|
|
||||||
@Dep pp
|
@Dep pp
|
||||||
|
@Dep pp_sim
|
||||||
|
@Dep sprite
|
||||||
@Dep gpu
|
@Dep gpu
|
||||||
@Dep glyph_cache
|
@Dep glyph_cache
|
||||||
@Dep platform
|
@Dep platform
|
||||||
@Dep window
|
@Dep window
|
||||||
@Dep ui
|
@Dep ui
|
||||||
@Dep pp_sim
|
|
||||||
|
|
||||||
//////////////////////////////
|
//////////////////////////////
|
||||||
//- Resources
|
//- Resources
|
||||||
|
|||||||
@ -558,7 +558,7 @@ void V_TickForever(WaveLaneCtx *lane)
|
|||||||
}
|
}
|
||||||
else
|
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);
|
bb = BB_BuffFromString(swap_encoded);
|
||||||
br = BB_ReaderFromBuff(&bb);
|
br = BB_ReaderFromBuff(&bb);
|
||||||
}
|
}
|
||||||
@ -586,7 +586,7 @@ void V_TickForever(WaveLaneCtx *lane)
|
|||||||
// Write swapout
|
// Write swapout
|
||||||
if (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_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);
|
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
|
// Upload tiles
|
||||||
if (tiles_dirty)
|
if (tiles_dirty)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -84,6 +84,8 @@ Struct(V_GpuParams)
|
|||||||
G_RWTexture2DRef cells;
|
G_RWTexture2DRef cells;
|
||||||
G_RWTexture2DRef stains;
|
G_RWTexture2DRef stains;
|
||||||
G_RWTexture2DRef drynesses;
|
G_RWTexture2DRef drynesses;
|
||||||
|
|
||||||
|
SPR_Slice tile_slices[S_TileKind_COUNT];
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
|
|||||||
@ -1,433 +1,40 @@
|
|||||||
Readonly SPR_Texture SPR_NilTexture = Zi;
|
|
||||||
Readonly SPR_Sheet SPR_NilSheet = Zi;
|
|
||||||
SPR_Ctx SPR = Zi;
|
SPR_Ctx SPR = Zi;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
//~ Load jobs
|
//~ Bootstrap
|
||||||
|
|
||||||
JobImpl(SPR_LoadTexture, sig, _)
|
void SPR_Bootstrap(void)
|
||||||
{
|
{
|
||||||
TempArena scratch = BeginScratchNoConflict();
|
OnAsyncTick(SPR_TickAsync);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
//~ Key helpers
|
//~ Key helpers
|
||||||
|
|
||||||
SPR_SpanKey SPR_SpanKeyFromName(String name)
|
SPR_Key SPR_KeyFromResource(ResourceKey resource)
|
||||||
{
|
{
|
||||||
SPR_SpanKey result = Zi;
|
SPR_Key result = Zi;
|
||||||
result.hash = HashFnv64(Fnv64Basis, name);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
SPR_SliceKey SPR_SliceKeyFromName(String name)
|
|
||||||
{
|
|
||||||
SPR_SliceKey result = Zi;
|
|
||||||
result.hash = HashFnv64(Fnv64Basis, name);
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
//~ Sheet access
|
//~ Lookup
|
||||||
|
|
||||||
SPR_Span SPR_SpanFromKey(SPR_Sheet *sheet, SPR_SpanKey key)
|
SPR_Slice SPR_SliceFromKey(SPR_Key key, String slice_name)
|
||||||
{
|
|
||||||
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 result = Zi;
|
SPR_Slice result = Zi;
|
||||||
b32 match = 0;
|
|
||||||
|
|
||||||
u32 bins_count = sheet->slice_group_bins_count;
|
// u64 hash = key.hash;
|
||||||
if (bins_count > 0 && sheet->frames_count > 0)
|
// hash = Mi
|
||||||
{
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return 'pivot' by default
|
// SPR_SliceBin *bin = &SPR.slice_bins[
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
//~ Async
|
||||||
|
|
||||||
|
void SPR_TickAsync(WaveLaneCtx *lane, AsyncFrameLaneCtx *base_async_lane_frame)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|||||||
@ -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
|
//~ State types
|
||||||
|
|
||||||
Struct(SPR_Ctx)
|
Struct(SPR_Ctx)
|
||||||
{
|
{
|
||||||
SPR_EntryBin entry_bins[1024];
|
i32 _;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern SPR_Ctx SPR;
|
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; });
|
void SPR_Bootstrap(void);
|
||||||
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);
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
//~ Key helpers
|
//~ Key helpers
|
||||||
|
|
||||||
SPR_SpanKey SPR_SpanKeyFromName(String name);
|
SPR_Key SPR_KeyFromResource(ResourceKey resource);
|
||||||
SPR_SliceKey SPR_SliceKeyFromName(String name);
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
//~ Sheet access
|
//~ Lookup
|
||||||
|
|
||||||
SPR_Span SPR_SpanFromKey(SPR_Sheet *sheet, SPR_SpanKey key);
|
SPR_Slice SPR_SliceFromKey(SPR_Key key, String slice_name);
|
||||||
SPR_Frame SPR_FrameFromIndex(SPR_Sheet *sheet, u64 index);
|
|
||||||
SPR_Slice SPR_SliceFromKey(SPR_Sheet *sheet, SPR_SliceKey key, u64 frame_index);
|
////////////////////////////////////////////////////////////
|
||||||
|
//~ Async
|
||||||
|
|
||||||
|
void SPR_TickAsync(WaveLaneCtx *lane, AsyncFrameLaneCtx *base_async_lane_frame);
|
||||||
|
|||||||
@ -9,8 +9,12 @@
|
|||||||
//////////////////////////////
|
//////////////////////////////
|
||||||
//- Api
|
//- Api
|
||||||
|
|
||||||
|
@IncludeC sprite_shared.cgh
|
||||||
|
@IncludeG sprite_shared.cgh
|
||||||
@IncludeC sprite.h
|
@IncludeC sprite.h
|
||||||
|
|
||||||
|
@Bootstrap SPR_Bootstrap
|
||||||
|
|
||||||
//////////////////////////////
|
//////////////////////////////
|
||||||
//- Impl
|
//- Impl
|
||||||
|
|
||||||
|
|||||||
16
src/sprite/sprite_shared.cgh
Normal file
16
src/sprite/sprite_shared.cgh
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
//~ Key types
|
||||||
|
|
||||||
|
Struct(SPR_Key)
|
||||||
|
{
|
||||||
|
u64 v;
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
//~ Slice types
|
||||||
|
|
||||||
|
Struct(SPR_Slice)
|
||||||
|
{
|
||||||
|
G_Texture2DRef tex;
|
||||||
|
Rng2 uv;
|
||||||
|
};
|
||||||
Loading…
Reference in New Issue
Block a user