tar layer refactor

This commit is contained in:
jacob 2025-07-30 23:31:46 -05:00
parent 35564cceef
commit 3f2abf5b3e
5 changed files with 114 additions and 88 deletions

View File

@ -335,7 +335,7 @@ Global struct {
struct swapchain *first_free_swapchain;
/* Shader bytecode archive */
struct tar_archive dxc_archive;
TAR_Archive dxc_archive;
/* Pipeline cache */
P_Mutex pipelines_mutex;
@ -419,7 +419,7 @@ void gp_startup(void)
if (embedded_data.len <= 0) {
P_Panic(Lit("No embedded shaders found"));
}
G.dxc_archive = tar_parse(G.pipelines_arena, embedded_data, Lit(""));
G.dxc_archive = TAR_ArchiveFromString(G.pipelines_arena, embedded_data, Lit(""));
/* Initialize dx12 */
/* TODO: Parallelize phases */
@ -956,9 +956,9 @@ internal P_JobDef(pipeline_alloc_job, job)
String error_str = ZI;
String vs_dxc = desc->vs_dxc.len > 0 ? desc->vs_dxc : tar_get(&G.dxc_archive, CatString(scratch.arena, pipeline_name, Lit(".vs")))->data;
String ps_dxc = desc->ps_dxc.len > 0 ? desc->ps_dxc : tar_get(&G.dxc_archive, CatString(scratch.arena, pipeline_name, Lit(".ps")))->data;
String cs_dxc = desc->cs_dxc.len > 0 ? desc->cs_dxc : tar_get(&G.dxc_archive, CatString(scratch.arena, pipeline_name, Lit(".cs")))->data;
String vs_dxc = desc->vs_dxc.len > 0 ? desc->vs_dxc : TAR_EntryFromName(&G.dxc_archive, CatString(scratch.arena, pipeline_name, Lit(".vs")))->data;
String ps_dxc = desc->ps_dxc.len > 0 ? desc->ps_dxc : TAR_EntryFromName(&G.dxc_archive, CatString(scratch.arena, pipeline_name, Lit(".ps")))->data;
String cs_dxc = desc->cs_dxc.len > 0 ? desc->cs_dxc : TAR_EntryFromName(&G.dxc_archive, CatString(scratch.arena, pipeline_name, Lit(".cs")))->data;
if (success && vs_dxc.len > 0 && ps_dxc.len <= 0) {
error_str = Lit("Pipeline has vertex shader without pixel shader");
success = 0;

View File

@ -15,7 +15,7 @@ R_StartupReceipt R_Startup(void)
{
P_Panic(Lit("No embedded resources found"));
}
g->archive = tar_parse(g->arena, embedded_data, Lit(""));
g->archive = TAR_ArchiveFromString(g->arena, embedded_data, Lit(""));
#else
/* Ensure we have the right working directory */
if (!P_IsDir(Lit("res")))
@ -36,7 +36,7 @@ R_Resource R_OpenResource(String name)
#if RESOURCES_EMBEDDED
R_SharedState *g = &R_shared_state;
R_Resource result = ZI;
struct tar_entry *entry = tar_get(&g->archive, name);
TAR_Entry *entry = TAR_EntryFromName(&g->archive, name);
result._data = entry->data;
result._name = entry->file_name;
result._exists = entry->valid;

View File

@ -24,7 +24,7 @@ Struct(R_SharedState)
{
Arena *arena;
#if RESOURCES_EMBEDDED
struct tar_archive archive;
TAR_Archive archive;
#endif
};

View File

@ -1,53 +1,10 @@
#define ARCHIVE_LOOKUP_TABLE_CAPACITY_FACTOR 2.0
Readonly TAR_Entry TAR_nil_entry = ZI;
/* File types:
* '0' or (ASCII NUL) Normal file
* '1' Hard link
* '2' Symbolic link
* '3' Character special
* '4' Block special
* '5' Directory
* '6' FIFO
* '7' Contiguous file
* 'g' Global extended header with meta data(POSIX.1 - 2001)
* 'x' Extended header with metadata for the next file in the archive(POSIX.1 - 2001)
* 'A'-'Z' Vendor specific extensions(POSIX.1 - 1988)
*/
#define TAR_TYPE_FILE '0'
#define TAR_TYPE_DIRECTORY '5'
#define TAR_TYPE_PAX_HEADER_X 'x'
#define TAR_TYPE_PAX_HEADER_G 'g'
Packed(struct tar_header {
/* Pre-posix */
u8 file_name[100];
u8 file_mode[8];
u8 owner_id[8];
u8 group_id[8];
u8 file_size[12];
u8 last_modified[12];
u8 checksum[8];
/* Both */
u8 file_type;
u8 linked_file_name[100];
/* UStar */
u8 ustar_indicator[6];
u8 ustar_version[2];
u8 owner_user_name[32];
u8 owner_group_name[32];
u8 device_major_number[8];
u8 device_minor_number[8];
u8 file_name_prefix[155];
u8 padding[12];
});
internal u64 str_oct_to_u64(String str)
u64 TAR_U64FromOctString(String str)
{
u64 n = 0;
for (u64 i = 0; i < str.len; ++i) {
for (u64 i = 0; i < str.len; ++i)
{
n *= 8;
n += (u64)(str.text[i]) - '0';
}
@ -59,27 +16,30 @@ internal u64 str_oct_to_u64(String str)
* NOTE: The resulting archive merely points into the supplied tar data, no
* copying is done. Accessing the archive assumes that the data string is still valid.
*/
struct tar_archive tar_parse(Arena *arena, String data, String prefix)
TAR_Archive TAR_ArchiveFromString(Arena *arena, String data, String prefix)
{
__prof;
struct tar_archive archive = ZI;
TAR_Archive archive = ZI;
BB_Buff bb = BitbuffFromString(data);
BB_Reader br = BB_ReaderFromBuffNoDebug(&bb);
u64 num_files = 0;
while (BB_NumBytesRemaining(&br) > 1024) {
while (BB_NumBytesRemaining(&br) > 1024)
{
struct tar_header header = ZI;
TAR_Header header = ZI;
BB_ReadBytes(&br, StringFromStruct(&header));
if (!EqString(StringFromArray(header.ustar_indicator), Lit("ustar\0"))) {
if (!EqString(StringFromArray(header.ustar_indicator), Lit("ustar\0")))
{
/* Invalid header */
Assert(0);
continue;
}
if (header.file_name_prefix[0] != 0) {
if (header.file_name_prefix[0] != 0)
{
/* Header file name prefix not supported */
Assert(0);
continue;
@ -87,9 +47,10 @@ struct tar_archive tar_parse(Arena *arena, String data, String prefix)
String file_size_oct_str = { .len = 11, .text = header.file_size };
u64 file_size = str_oct_to_u64(file_size_oct_str);
u64 file_size = TAR_U64FromOctString(file_size_oct_str);
u8 *file_data_ptr = BB_ReadBytesRaw(&br, file_size);
if (!file_data_ptr) {
if (!file_data_ptr)
{
file_size = 0;
}
String file_data = STRING(file_size, file_data_ptr);
@ -98,23 +59,25 @@ struct tar_archive tar_parse(Arena *arena, String data, String prefix)
u64 remaining = (512 - (file_size % 512)) % 512;
BB_SeekBytes(&br, remaining);
b32 is_dir = header.file_type == TAR_TYPE_DIRECTORY;
if (!is_dir && header.file_type != TAR_TYPE_FILE) {
b32 is_dir = header.file_type == TAR_FileKind_Directory;
if (!is_dir && header.file_type != TAR_FileKind_File)
{
/* Unsupported type */
Assert(header.file_type == TAR_TYPE_PAX_HEADER_X ||
header.file_type == TAR_TYPE_PAX_HEADER_G);
Assert(header.file_type == TAR_FileKind_PaxHeaderX ||
header.file_type == TAR_FileKind_PaxHeaderG);
continue;
}
String file_name_cstr = StringFromCstrNoLimit((char *)header.file_name);
if (file_name_cstr.len >= 2) {
if (file_name_cstr.len >= 2)
{
/* Chop off './' prefix */
file_name_cstr.len -= 2;
file_name_cstr.text += 2;
}
String file_name = CatString(arena, prefix, file_name_cstr);
struct tar_entry *entry = PushStruct(arena, struct tar_entry);
TAR_Entry *entry = PushStruct(arena, TAR_Entry);
entry->valid = 1;
entry->is_dir = is_dir;
entry->file_name = file_name;
@ -126,8 +89,9 @@ struct tar_archive tar_parse(Arena *arena, String data, String prefix)
}
/* Build lookup table */
archive.lookup = InitDict(arena, (u64)((f64)num_files * ARCHIVE_LOOKUP_TABLE_CAPACITY_FACTOR));
for (struct tar_entry *entry = archive.head; entry; entry = entry->next) {
archive.lookup = InitDict(arena, (u64)((f64)num_files * TAR_ArchiveLookupTableCapacityFactor));
for (TAR_Entry *entry = archive.head; entry; entry = entry->next)
{
u64 hash = HashFnv64(Fnv64Basis, entry->file_name);
SetDictValue(arena, archive.lookup, hash, (u64)entry);
}
@ -135,20 +99,25 @@ struct tar_archive tar_parse(Arena *arena, String data, String prefix)
/* Build hierarchy */
/* NOTE: This is a separate pass because tar entry order is not guaranteed
* (IE file entries may be encountered before their parent directory entry) */
for (struct tar_entry *entry = archive.head; entry; entry = entry->next) {
for (TAR_Entry *entry = archive.head; entry; entry = entry->next)
{
/* Enter into hierarchy */
if (!entry->is_dir) {
if (!entry->is_dir)
{
/* Find parent entry */
struct tar_entry *parent_entry = 0;
for (String parent_dir_name = entry->file_name; parent_dir_name.len > 0; --parent_dir_name.len) {
if (parent_dir_name.text[parent_dir_name.len - 1] == '/') {
TAR_Entry *parent_entry = 0;
for (String parent_dir_name = entry->file_name; parent_dir_name.len > 0; --parent_dir_name.len)
{
if (parent_dir_name.text[parent_dir_name.len - 1] == '/')
{
u64 hash = HashFnv64(Fnv64Basis, parent_dir_name);
parent_entry = (struct tar_entry *)DictValueFromHash(archive.lookup, hash);
parent_entry = (TAR_Entry *)DictValueFromHash(archive.lookup, hash);
break;
}
}
/* Insert child into parent's list */
if (parent_entry) {
if (parent_entry)
{
entry->next_child = parent_entry->next_child;
parent_entry->next_child = entry;
}
@ -158,10 +127,10 @@ struct tar_archive tar_parse(Arena *arena, String data, String prefix)
return archive;
}
Readonly Global struct tar_entry g_nil_tar_entry = ZI;
struct tar_entry *tar_get(struct tar_archive *archive, String name)
Readonly Global TAR_Entry g_nil_tar_entry = ZI;
TAR_Entry *TAR_EntryFromName(TAR_Archive *archive, String name)
{
u64 hash = HashFnv64(Fnv64Basis, name);
struct tar_entry *lookup = (struct tar_entry *)DictValueFromHash(archive->lookup, hash);
TAR_Entry *lookup = (TAR_Entry *)DictValueFromHash(archive->lookup, hash);
return lookup ? lookup : &g_nil_tar_entry;
}

View File

@ -1,17 +1,74 @@
struct tar_entry {
////////////////////////////////
//~ Archive types
#define TAR_ArchiveLookupTableCapacityFactor 2.0
Struct(TAR_Entry)
{
b32 valid;
String file_name;
String data;
b32 is_dir;
struct tar_entry *next;
struct tar_entry *next_child; /* If entry is dir, points to first child. Otherwise points to next sibling. */
TAR_Entry *next;
TAR_Entry *next_child; /* If entry is dir, points to first child. Otherwise points to next sibling. */
};
struct tar_archive {
Struct(TAR_Archive)
{
Dict *lookup;
struct tar_entry *head;
TAR_Entry *head;
};
struct tar_archive tar_parse(Arena *arena, String data, String prefix);
struct tar_entry *tar_get(struct tar_archive *archive, String name);
extern Readonly TAR_Entry TAR_nil_entry;
////////////////////////////////
//~ Header types
typedef u8 TAR_FileKind; enum
{
TAR_FileKind_File = '0',
TAR_FileKind_HardLink = '1',
TAR_FileKind_SymLink = '2',
TAR_FileKind_CharacterSpecial = '3',
TAR_FileKind_BlockSpecial = '4',
TAR_FileKind_Directory = '5',
TAR_FileKind_Fifo = '6',
TAR_FileKind_ContiguousFile = '7',
TAR_FileKind_PaxHeaderG = 'g',
TAR_FileKind_PaxHeaderX = 'x'
};
Packed(Struct(TAR_Header)
{
/* Pre-posix */
u8 file_name[100];
u8 file_mode[8];
u8 owner_id[8];
u8 group_id[8];
u8 file_size[12];
u8 last_modified[12];
u8 checksum[8];
/* Both */
u8 file_type;
u8 linked_file_name[100];
/* UStar */
u8 ustar_indicator[6];
u8 ustar_version[2];
u8 owner_user_name[32];
u8 owner_group_name[32];
u8 device_major_number[8];
u8 device_minor_number[8];
u8 file_name_prefix[155];
u8 padding[12];
});
////////////////////////////////
//~ Archive operations
u64 TAR_U64FromOctString(String str);
TAR_Archive TAR_ArchiveFromString(Arena *arena, String data, String prefix);
TAR_Entry *TAR_EntryFromName(TAR_Archive *archive, String name);