allow creation of non-atlas sprites

This commit is contained in:
jacob 2026-02-24 03:04:25 -06:00
parent 3fd910702f
commit 262d49fee8
3 changed files with 92 additions and 49 deletions

View File

@ -316,7 +316,7 @@ void GC_TickAsync(WaveLaneCtx *lane, AsyncFrameLaneCtx *base_async_lane_frame)
gpu_perm, cl, gpu_perm, cl,
G_Format_R8G8B8A8_Unorm_Srgb, G_Format_R8G8B8A8_Unorm_Srgb,
atlas->dims, atlas->dims,
G_Layout_Simultaneous, G_Layout_Simultaneous, // Simultaneous because atlas will be written asynchronously during regular reads
.name = Lit("Glyph atlas") .name = Lit("Glyph atlas")
); );
atlas->tex = G_PushTexture2DRef(gpu_perm, atlas->tex_res); atlas->tex = G_PushTexture2DRef(gpu_perm, atlas->tex_res);

View File

@ -5,7 +5,22 @@ SPR_Ctx SPR = Zi;
void SPR_Bootstrap(void) void SPR_Bootstrap(void)
{ {
// FIXME: Initialize nil/unready sprite texture here G_ArenaHandle gpu_perm = G_PermArena();
G_CommandListHandle cl = G_PrepareCommandList(G_QueueKind_Direct);
{
G_ResourceHandle unready_tex_res = G_PushTexture2D(
gpu_perm, cl,
G_Format_R8G8B8A8_Unorm,
VEC2I32(8, 8),
G_Layout_Common,
.flags = G_ResourceFlag_ZeroMemory,
.name = Lit("Sprite unready texture")
);
SPR.unready_tex = G_PushTexture2DRef(gpu_perm, unready_tex_res);
SPR.unready_tex_dims = Vec2FromVec(G_Count2D(unready_tex_res));
}
G_CommitCommandList(cl);
G_QueueSync(G_QueueMask_Direct, G_QueueMask_All);
OnAsyncTick(SPR_TickAsync); OnAsyncTick(SPR_TickAsync);
} }
@ -65,7 +80,7 @@ SPR_LayerKind SPR_LayerKindFromName(String name)
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
//~ Lookup //~ Lookup
SPR_Sprite SPR_SpriteFromSheet(SPR_SheetKey sheet_key, SPR_SpanKey span_key, i64 frame_seq) SPR_Sprite SPR_SpriteFromSheetEx(SPR_SheetKey sheet_key, SPR_SpanKey span_key, i64 frame_seq, SPR_SheetFlag flags)
{ {
////////////////////////////// //////////////////////////////
//- Fetch sheet //- Fetch sheet
@ -77,7 +92,7 @@ SPR_Sprite SPR_SpriteFromSheet(SPR_SheetKey sheet_key, SPR_SpanKey span_key, i64
{ {
for (sheet = sheet_bin->first; sheet; sheet = sheet->next_in_bin) for (sheet = sheet_bin->first; sheet; sheet = sheet->next_in_bin)
{ {
if (sheet->key.r.v == sheet_key.r.v) if (sheet->key.r.v == sheet_key.r.v && sheet->flags == flags)
{ {
break; break;
} }
@ -107,6 +122,7 @@ SPR_Sprite SPR_SpriteFromSheet(SPR_SheetKey sheet_key, SPR_SpanKey span_key, i64
sheet = PushStruct(perm, SPR_SheetEntry); sheet = PushStruct(perm, SPR_SheetEntry);
SllStackPushN(sheet_bin->first, sheet, next_in_bin); SllStackPushN(sheet_bin->first, sheet, next_in_bin);
sheet->key = sheet_key; sheet->key = sheet_key;
sheet->flags = flags;
String sheet_data = DataFromResource(sheet->key.r); String sheet_data = DataFromResource(sheet->key.r);
String sheet_name = NameFromResource(sheet->key.r); String sheet_name = NameFromResource(sheet->key.r);
@ -344,6 +360,11 @@ SPR_Sprite SPR_SpriteFromSheet(SPR_SheetKey sheet_key, SPR_SpanKey span_key, i64
return result; return result;
} }
SPR_Sprite SPR_SpriteFromSheet(SPR_SheetKey sheet_key, SPR_SpanKey span_key, i64 frame_seq)
{
return SPR_SpriteFromSheetEx(sheet_key, span_key, frame_seq, SPR_SheetFlag_None);
}
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
//~ Async //~ Async
@ -389,10 +410,6 @@ void SPR_TickAsync(WaveLaneCtx *lane, AsyncFrameLaneCtx *base_async_lane_frame)
SPR_SheetEntry *sheet = cmd->sheet; SPR_SheetEntry *sheet = cmd->sheet;
ASE_Meta meta = sheet->meta; ASE_Meta meta = sheet->meta;
// String encoded = DataFromResource(sheet->key.r);
// String name = NameFromResource(sheet->key.r);
// LogInfoF("Rasterizing sprite sheet %F \"%F\" (%F bytes)", FmtHandle(sheet->key.r), FmtString(name), FmtUint(encoded.len));
SPR_SliceEntry *slice = &sheet->slices[cmd->slice_idx]; SPR_SliceEntry *slice = &sheet->slices[cmd->slice_idx];
Vec2 slice_dims = DimsFromRng2(slice->canvas_rect); Vec2 slice_dims = DimsFromRng2(slice->canvas_rect);
@ -421,10 +438,29 @@ void SPR_TickAsync(WaveLaneCtx *lane, AsyncFrameLaneCtx *base_async_lane_frame)
////////////////////////////// //////////////////////////////
//- Write atlas //- Write atlas
// TODO: Use a more efficient atlas packing algorithm for less wasted space
SPR_Atlas *atlas = SPR.first_atlas;
b32 can_use_atlas = 0;
Vec2I32 atlas_pos = Zi; Vec2I32 atlas_pos = Zi;
SPR_Atlas *atlas = 0;
if (AnyBit(sheet->flags, SPR_SheetFlag_NoAtlas) && slice_dims.x > 0 && slice_dims.y > 0)
{
atlas = PushStruct(perm, SPR_Atlas);
atlas->dims = Vec2I32FromVec(slice_dims);
{
G_ArenaHandle gpu_perm = G_PermArena();
atlas->tex_res = G_PushTexture2D(
gpu_perm, cl,
G_Format_R8G8B8A8_Unorm_Srgb,
atlas->dims,
G_Layout_Common,
.name = Lit("Isolated sprite texture")
);
atlas->tex = G_PushTexture2DRef(gpu_perm, atlas->tex_res);
}
}
else
{
// TODO: Use a more efficient atlas packing algorithm for less wasted space
atlas = SPR.first_atlas;
b32 can_use_atlas = 0;
while (can_use_atlas == 0) while (can_use_atlas == 0)
{ {
// Create atlas // Create atlas
@ -439,8 +475,8 @@ void SPR_TickAsync(WaveLaneCtx *lane, AsyncFrameLaneCtx *base_async_lane_frame)
gpu_perm, cl, gpu_perm, cl,
G_Format_R8G8B8A8_Unorm_Srgb, G_Format_R8G8B8A8_Unorm_Srgb,
atlas->dims, atlas->dims,
G_Layout_Simultaneous, G_Layout_Simultaneous, // Simultaneous because atlas will be written asynchronously during regular reads
.name = Lit("Sprite atlas") .name = StringF(perm, "Sprite atlas #%F", FmtSint(SPR.atlases_count))
); );
atlas->tex = G_PushTexture2DRef(gpu_perm, atlas->tex_res); atlas->tex = G_PushTexture2DRef(gpu_perm, atlas->tex_res);
} }
@ -466,6 +502,7 @@ void SPR_TickAsync(WaveLaneCtx *lane, AsyncFrameLaneCtx *base_async_lane_frame)
atlas = 0; atlas = 0;
} }
} }
}
// Fill slice_entry atlas info // Fill slice_entry atlas info
{ {

View File

@ -13,7 +13,6 @@ Struct(SPR_SpanKey) { u64 v; };
Struct(SPR_Atlas) Struct(SPR_Atlas)
{ {
SPR_Atlas *next; SPR_Atlas *next;
Vec2I32 dims; Vec2I32 dims;
G_ResourceHandle tex_res; G_ResourceHandle tex_res;
G_Texture2DRef tex; G_Texture2DRef tex;
@ -47,7 +46,13 @@ Enum(SPR_LayerKind)
}; };
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
//~ Lookup result types //~ Lookup types
Enum(SPR_SheetFlag)
{
SPR_SheetFlag_None = 0,
SPR_SheetFlag_NoAtlas = (1 << 0),
};
Struct(SPR_Ray) Struct(SPR_Ray)
{ {
@ -107,6 +112,7 @@ Struct(SPR_SheetEntry)
{ {
SPR_SheetEntry *next_in_bin; SPR_SheetEntry *next_in_bin;
SPR_SheetKey key; SPR_SheetKey key;
SPR_SheetFlag flags;
i64 slices_count; i64 slices_count;
SPR_SliceEntry *slices; SPR_SliceEntry *slices;
@ -153,7 +159,6 @@ Struct(SPR_Ctx)
{ {
SPR_SheetBin sheet_bins[Kibi(16)]; SPR_SheetBin sheet_bins[Kibi(16)];
// FIXME: Initialize this
G_Texture2DRef unready_tex; G_Texture2DRef unready_tex;
Vec2 unready_tex_dims; Vec2 unready_tex_dims;
@ -194,6 +199,7 @@ SPR_LayerKind SPR_LayerKindFromName(String name);
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
//~ Lookup //~ Lookup
SPR_Sprite SPR_SpriteFromSheetEx(SPR_SheetKey sheet_key, SPR_SpanKey span_key, i64 frame_seq, SPR_SheetFlag flags);
SPR_Sprite SPR_SpriteFromSheet(SPR_SheetKey sheet_key, SPR_SpanKey span_key, i64 frame_seq); SPR_Sprite SPR_SpriteFromSheet(SPR_SheetKey sheet_key, SPR_SpanKey span_key, i64 frame_seq);
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////