summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorquou <quou@disroot.org>2024-12-29 13:54:35 +1100
committerquou <quou@disroot.org>2024-12-29 13:55:35 +1100
commitf107689be915d96363ea75889631939c62f07980 (patch)
treea4b54d5145f12ee946dd24c18e6f6d5225a4d997
parent928eba3845d6017d133048cf04c1f816d87941b0 (diff)
cache assets to avoid loading them more than once
-rw-r--r--asset.cpp46
-rw-r--r--asset.hpp15
-rw-r--r--c2.cpp2
3 files changed, 45 insertions, 18 deletions
diff --git a/asset.cpp b/asset.cpp
index fc8abde..10ddd04 100644
--- a/asset.cpp
+++ b/asset.cpp
@@ -66,7 +66,12 @@ void register_asset_loader(
manager.set_loader(magic, loader);
}
-void Asset_Arena::init(Arena* arena, const char* pack_name) {
+void Asset_Arena::init(
+ Arena* arena,
+ const char* pack_name,
+ int max
+) {
+ int i;
p = pack_open(pack_name, arena);
assert(p != 0);
a = arena;
@@ -76,27 +81,43 @@ void Asset_Arena::init(Arena* arena, const char* pack_name) {
arena_alloc(a, asset_scratch_size),
asset_scratch_size
);
- assets = 0;
+ max_assets = max;
+ assets = (Bucket*)arena_alloc(arena, max * sizeof(Bucket));
+ for (i = 0; i < max; i++)
+ assets[i].name = 0;
}
void Asset_Arena::destroy() {
- Asset* a;
- for (a = assets; a; a = a->next) {
- a->loader->unload(a);
+ int i, c = max_assets;
+ for (i = 0; i < c; i++) {
+ Bucket& b = assets[i];
+ if (b.name)
+ b.asset->loader->unload(b.asset);
}
pack_close(p);
}
-void Asset_Arena::claim(Asset* a) {
- if (assets) {
- a->next = assets;
- assets = a;
- } else assets = a;
+int Asset_Arena::bucket(const char* name) {
+ uint32_t hash = hash_string(name);
+ int bucket = (int)(hash % max_assets);
+ int i;
+ for (i = 0; i < max_assets; i++) {
+ Bucket& b = assets[bucket];
+ if (!b.name || string_equal(name, b.name))
+ return bucket;
+ bucket = (bucket + 1) % max_assets;
+ }
+ return -1;
}
Asset* Asset_Arena::load(const char* name) {
char magic[4];
- Pack_File* f = pack_open_file(p, name);
+ Pack_File* f;
+ int b = bucket(name);
+ assert(b >= 0);
+ if (assets[b].name)
+ return assets[b].asset;
+ f = pack_open_file(p, name);
if (!f) return 0;
pack_read(f, magic, 4);
pack_seek(f, 0, seek_rel_start);
@@ -105,7 +126,8 @@ Asset* Asset_Arena::load(const char* name) {
Asset* asset = loader.load(a, s, f);
if (asset) {
asset->loader = &loader;
- claim(asset);
+ assets[b].name = dup_string(a, name);
+ assets[b].asset = asset;
}
pack_close_file(f);
return asset;
diff --git a/asset.hpp b/asset.hpp
index db53414..c149e0a 100644
--- a/asset.hpp
+++ b/asset.hpp
@@ -7,7 +7,6 @@ struct Pack_File;
struct Pack;
struct Asset {
- Asset* next;
Asset_Loader* loader;
};
@@ -19,13 +18,19 @@ struct Asset_Loader {
struct Asset_Arena {
Pack* p;
Arena* a, * s;
- Asset* assets;
-
- void init(Arena* arena, const char* pack_name);
+ struct Bucket {
+ char* name;
+ Asset* asset;
+ };
+ Bucket* assets;
+ int max_assets;
+
+ void init(Arena* arena, const char* pack_name, int max);
void destroy();
Asset* load(const char* name);
- void claim(Asset* a);
+
+ int bucket(const char* name);
};
void register_asset_loader(
diff --git a/c2.cpp b/c2.cpp
index 29f3955..d3b414b 100644
--- a/c2.cpp
+++ b/c2.cpp
@@ -102,7 +102,7 @@ extern "C" int entrypoint() {
arena_alloc(app->arena, ui_arena_size),
ui_arena_size
);
- assets.init(&asset_arena, "pack");
+ assets.init(&asset_arena, "pack", 128);
dev = Device::create(&video_arena, app);
model_loader.init(dev, &assets);
register_asset_loader("MODL", &model_loader);