summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt3
-rw-r--r--PROJECT_CONTEXT.md7
-rw-r--r--src/tests/test_assets.cc23
-rw-r--r--src/util/asset_manager.cc70
-rw-r--r--src/util/asset_manager.h4
-rw-r--r--tools/asset_packer.cc2
6 files changed, 93 insertions, 16 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 4a2d389..5b07c07 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -87,7 +87,7 @@ set(GPU_SOURCES
src/gpu/effects/shaders.cc
src/gpu/texture_manager.cc
)
-set(UTIL_SOURCES src/util/asset_manager.cc)
+set(UTIL_SOURCES src/util/asset_manager.cc ${GEN_DEMO_CC})
set(PLATFORM_SOURCES src/platform.cc third_party/glfw3webgpu/glfw3webgpu.c)
#-- - Tools Setup -- -
@@ -177,6 +177,7 @@ if(DEMO_BUILD_TESTS)
add_test(NAME SpectoolEndToEndTest COMMAND test_spectool)
add_executable(test_assets src/tests/test_assets.cc ${UTIL_SOURCES} ${GEN_TEST_CC})
+ target_compile_definitions(test_assets PRIVATE USE_TEST_ASSETS)
add_dependencies(test_assets generate_test_assets)
set_source_files_properties(src/tests/test_assets.cc PROPERTIES COMPILE_DEFINITIONS "USE_TEST_ASSETS")
add_test(NAME AssetManagerTest COMMAND test_assets)
diff --git a/PROJECT_CONTEXT.md b/PROJECT_CONTEXT.md
index b34805a..569683c 100644
--- a/PROJECT_CONTEXT.md
+++ b/PROJECT_CONTEXT.md
@@ -61,6 +61,13 @@ Incoming tasks in no particular order:
- Update `main.cc` / `gpu.cc` to use `Renderer3D`.
- Apply Gaussian Blur and Chromatic Aberration post-processing.
+* **17. Implement Asset Manager Caching & Procedural Generation**
+ * 17a. **(Task a)** Implemented array-based caching in `asset_manager.cc` for `GetAsset` (Done).
+ * 17b. **(Task b)** Modify `asset_packer` to parse a new `PROC(function_name)` compression method. This will generate a record mapping an Asset ID to the procedural function's name.
+ * 17c. **(Task b)** Implement a runtime dispatcher in `GetAsset`. When a `PROC` asset is requested, the dispatcher will look up the function by its name and execute it. The result will then be cached.
+ * 17d. **(Task c)** Update the asset management test suite to include a test case with `PROC(function_name)` in `test_assets_list.txt` to verify the generation and caching.
+ * 17e. **(Task d)** Integrate into `demo64k` by adding a procedural noise texture to `demo_assets.txt` and using this new mechanism in the `Hybrid3DEffect` for bump mapping.
+
## Session Decisions and Current State
### 3D Renderer Implementation
diff --git a/src/tests/test_assets.cc b/src/tests/test_assets.cc
index e8b6318..b7ee8be 100644
--- a/src/tests/test_assets.cc
+++ b/src/tests/test_assets.cc
@@ -16,21 +16,36 @@ int main() {
printf("Running AssetManager test...\n");
size_t size = 0;
- const uint8_t* data = GetAsset(AssetId::ASSET_TEST_ASSET, &size);
+ const uint8_t* data1 = GetAsset(AssetId::ASSET_TEST_ASSET, &size);
- assert(data != nullptr);
+ assert(data1 != nullptr);
assert(size > 0);
const char* expected_prefix = "This is a test asset file.";
- if (strncmp((const char*)data, expected_prefix, strlen(expected_prefix)) ==
+ if (strncmp((const char*)data1, expected_prefix, strlen(expected_prefix)) ==
0) {
printf("Asset content verification: SUCCESS\n");
} else {
printf("Asset content verification: FAILED\n");
- printf("Got: %.*s\n", (int)size, (const char*)data);
+ printf("Got: %.*s\n", (int)size, (const char*)data1);
return 1;
}
+ // Test caching: request the same asset again and verify pointer is identical
+ size_t size2 = 0;
+ const uint8_t* data2 = GetAsset(AssetId::ASSET_TEST_ASSET, &size2);
+ assert(data2 != nullptr);
+ assert(size2 == size);
+ assert(data1 == data2); // Pointers should be the same for cached static asset
+ printf("Asset caching test: SUCCESS\n");
+
+ // Test ASSET_LAST_ID - should not return a valid asset
+ size_t last_id_size = 0;
+ const uint8_t* last_id_data = GetAsset(AssetId::ASSET_LAST_ID, &last_id_size);
+ assert(last_id_data == nullptr);
+ assert(last_id_size == 0);
+ printf("ASSET_LAST_ID test: SUCCESS\n");
+
printf("Asset size: %zu bytes\n", size);
printf("AssetManager test PASSED\n");
diff --git a/src/util/asset_manager.cc b/src/util/asset_manager.cc
index 30295b9..3874535 100644
--- a/src/util/asset_manager.cc
+++ b/src/util/asset_manager.cc
@@ -1,30 +1,82 @@
// This file is part of the 64k demo project.
-// It implements the generic asset retrieval logic.
-// Uses an array lookup for O(1) access to embedded data.
+// It implements the generic asset retrieval logic with runtime caching.
#include "util/asset_manager.h"
+#if defined(USE_TEST_ASSETS)
+#include "generated/test_assets.h"
+#else
#include "generated/assets.h"
+#endif /* defined(USE_TEST_ASSETS) */
+
+#include <vector> // For potential dynamic allocation for procedural assets
+#include <new> // For placement new
+#include <cstdlib> // For free
// These are defined in the generated assets_data.cc
+#if defined(USE_TEST_ASSETS)
+extern const AssetRecord g_assets[];
+extern const size_t g_assets_count;
+#else
extern const AssetRecord g_assets[];
extern const size_t g_assets_count;
+#endif
+// Array-based cache for assets.
+// Initialized to all zeros (nullptr data, 0 size, false is_procedural)
+// The size is derived from the generated ASSET_LAST_ID enum value.
+static AssetRecord g_asset_cache[(size_t)AssetId::ASSET_LAST_ID] = {};
const uint8_t* GetAsset(AssetId asset_id, size_t* out_size) {
uint16_t index = (uint16_t)asset_id;
+
+ // Assert that ASSET_LAST_ID is not used for retrieval.
+ // This ensures the size of the cache is correctly used and not accessed out of bounds.
+ // If this assert fails, it means assets.txt has an ID larger than expected
+ // or ASSET_LAST_ID is not correctly generated/updated.
+ // This is a design decision: ASSET_LAST_ID is purely for sizing and range checking,
+ // not for a valid asset retrieval itself.
+ if (index >= (uint16_t)AssetId::ASSET_LAST_ID) {
+ if (out_size)
+ *out_size = 0;
+ return nullptr; // Invalid asset_id
+ }
+
+ // Check cache first
+ if (g_asset_cache[index].data != nullptr) {
+ if (out_size)
+ *out_size = g_asset_cache[index].size;
+ return g_asset_cache[index].data;
+ }
+
+ // Not in cache, retrieve from static data (packed in binary)
if (index >= g_assets_count) {
if (out_size)
*out_size = 0;
- return nullptr;
+ return nullptr; // This asset is not in the static packed data either.
}
- const AssetRecord& record = g_assets[index];
+ // Store static record in cache for future use
+ g_asset_cache[index] = g_assets[index];
+ g_asset_cache[index].is_procedural = false;
+
if (out_size)
- *out_size = record.size;
- return record.data;
+ *out_size = g_asset_cache[index].size;
+ return g_asset_cache[index].data;
}
void DropAsset(AssetId asset_id, const uint8_t* asset) {
- (void)asset_id;
- (void)asset;
- // Implementation for lazy decompression will go here
+ uint16_t index = (uint16_t)asset_id;
+ if (index >= (uint16_t)AssetId::ASSET_LAST_ID) {
+ return; // Invalid asset_id
+ }
+
+ // Only free memory for procedural assets.
+ if (g_asset_cache[index].is_procedural && g_asset_cache[index].data == asset) {
+ // In a more complex scenario, we might track ref counts.
+ // For this demo, we assume a single owner for dynamically allocated assets.
+ delete[] g_asset_cache[index].data; // Assuming `new uint8_t[]` was used for procedural
+ g_asset_cache[index].data = nullptr;
+ g_asset_cache[index].size = 0;
+ g_asset_cache[index].is_procedural = false;
+ }
+ // For static assets, no dynamic memory to free.
}
diff --git a/src/util/asset_manager.h b/src/util/asset_manager.h
index 54d0144..6b09430 100644
--- a/src/util/asset_manager.h
+++ b/src/util/asset_manager.h
@@ -6,12 +6,12 @@
#include <cstddef>
#include <cstdint>
-// Forward declaration of the generated enum
-enum class AssetId : uint16_t;
+enum class AssetId : uint16_t; // Forward declaration
struct AssetRecord {
const uint8_t* data;
size_t size;
+ bool is_procedural; // Flag to indicate if memory was allocated dynamically
};
// Generic interface
diff --git a/tools/asset_packer.cc b/tools/asset_packer.cc
index c803c02..e606b94 100644
--- a/tools/asset_packer.cc
+++ b/tools/asset_packer.cc
@@ -112,6 +112,8 @@ int main(int argc, char* argv[]) {
++asset_id_counter;
}
+ // Add ASSET_LAST_ID at the end
+ assets_h_file << " ASSET_LAST_ID = " << asset_id_counter << "\n";
assets_h_file << "};\n\n";
assets_h_file << "#include \"util/asset_manager.h\"\n";
assets_h_file.close();