load runtime asset dependency data
removed init/shutdown functions from headers.
This commit is contained in:
		
							parent
							
								
									213638009b
								
							
						
					
					
						commit
						0c89d63716
					
				@ -51,6 +51,7 @@ runtime_lib = library('vyrt',
 | 
				
			|||||||
  # Project Sources
 | 
					  # Project Sources
 | 
				
			||||||
  'src/runtime/aio.h',
 | 
					  'src/runtime/aio.h',
 | 
				
			||||||
  'src/runtime/app.h',
 | 
					  'src/runtime/app.h',
 | 
				
			||||||
 | 
					  'src/runtime/asset_dependencies.h',
 | 
				
			||||||
  'src/runtime/assets.h',
 | 
					  'src/runtime/assets.h',
 | 
				
			||||||
  'src/runtime/buffer_manager.h',
 | 
					  'src/runtime/buffer_manager.h',
 | 
				
			||||||
  'src/runtime/config.h',
 | 
					  'src/runtime/config.h',
 | 
				
			||||||
@ -65,6 +66,7 @@ runtime_lib = library('vyrt',
 | 
				
			|||||||
  
 | 
					  
 | 
				
			||||||
  'src/runtime/aio.c',
 | 
					  'src/runtime/aio.c',
 | 
				
			||||||
  'src/runtime/app.c',
 | 
					  'src/runtime/app.c',
 | 
				
			||||||
 | 
					  'src/runtime/asset_dependencies.c',
 | 
				
			||||||
  'src/runtime/buffer_manager.c',
 | 
					  'src/runtime/buffer_manager.c',
 | 
				
			||||||
  'src/runtime/config.c',
 | 
					  'src/runtime/config.c',
 | 
				
			||||||
  'src/runtime/error_report.c',
 | 
					  'src/runtime/error_report.c',
 | 
				
			||||||
 | 
				
			|||||||
@ -1,5 +1,6 @@
 | 
				
			|||||||
#include "aio.h"
 | 
					#include "aio.h"
 | 
				
			||||||
#include "threading.h"
 | 
					#include "threading.h"
 | 
				
			||||||
 | 
					#include "config.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef _WIN32
 | 
					#ifdef _WIN32
 | 
				
			||||||
#define WIN32_LEAN_AND_MEAN
 | 
					#define WIN32_LEAN_AND_MEAN
 | 
				
			||||||
@ -102,7 +103,12 @@ win32CompletionRoutine(DWORD error_code, DWORD num_bytes_transfered, LPOVERLAPPE
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
VY_DLLEXPORT vy_result vyInitAIO(unsigned int max_concurrent_operations) {
 | 
					VY_CVAR_I(rt_MaxConcurrentAsyncIO,
 | 
				
			||||||
 | 
					          "Maximum number of concurrent async. I/O operations. Default: 1024",
 | 
				
			||||||
 | 
					          1024);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					vy_result InitAIO(void) {
 | 
				
			||||||
 | 
					    unsigned int max_concurrent_operations = rt_MaxConcurrentAsyncIO.i;
 | 
				
			||||||
    _ringbuffer.guard = vyCreateMutex();
 | 
					    _ringbuffer.guard = vyCreateMutex();
 | 
				
			||||||
    if (!_ringbuffer.guard) {
 | 
					    if (!_ringbuffer.guard) {
 | 
				
			||||||
        return VY_AIO_OUT_OF_MEMORY;
 | 
					        return VY_AIO_OUT_OF_MEMORY;
 | 
				
			||||||
@ -119,7 +125,7 @@ VY_DLLEXPORT vy_result vyInitAIO(unsigned int max_concurrent_operations) {
 | 
				
			|||||||
    return VY_SUCCESS;
 | 
					    return VY_SUCCESS;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
VY_DLLEXPORT void vyShutdownAIO(void) {
 | 
					void ShutdownAIO(void) {
 | 
				
			||||||
    vyDestroyMutex(_ringbuffer.guard);
 | 
					    vyDestroyMutex(_ringbuffer.guard);
 | 
				
			||||||
    free(_ringbuffer.storage);
 | 
					    free(_ringbuffer.storage);
 | 
				
			||||||
    _ringbuffer.capacity = 0;
 | 
					    _ringbuffer.capacity = 0;
 | 
				
			||||||
@ -154,7 +160,6 @@ VY_DLLEXPORT vy_result vySubmitLoadBatch(const vy_load_batch *batch, vy_aio_hand
 | 
				
			|||||||
            .InternalHigh = 0,
 | 
					            .InternalHigh = 0,
 | 
				
			||||||
            .Offset       = (DWORD)(batch->loads[i].offset & MAXDWORD),
 | 
					            .Offset       = (DWORD)(batch->loads[i].offset & MAXDWORD),
 | 
				
			||||||
            .OffsetHigh   = (DWORD)(batch->loads[i].offset >> 32),
 | 
					            .OffsetHigh   = (DWORD)(batch->loads[i].offset >> 32),
 | 
				
			||||||
            .Pointer      = NULL,
 | 
					 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        WCHAR wpath[MAX_PATH];
 | 
					        WCHAR wpath[MAX_PATH];
 | 
				
			||||||
@ -255,4 +260,21 @@ VY_DLLEXPORT vy_aio_state vyWaitForAIOCompletion(vy_aio_handle handle) {
 | 
				
			|||||||
#endif
 | 
					#endif
 | 
				
			||||||
    } while (state == VY_AIO_STATE_PENDING);
 | 
					    } while (state == VY_AIO_STATE_PENDING);
 | 
				
			||||||
    return state;
 | 
					    return state;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					VY_DLLEXPORT vy_result vySubmitSingleLoad(vy_file_load load, vy_aio_handle *handle) {
 | 
				
			||||||
 | 
					    vy_load_batch batch;
 | 
				
			||||||
 | 
					    batch.loads[0] = load;
 | 
				
			||||||
 | 
					    batch.num_loads = 1;
 | 
				
			||||||
 | 
					    return vySubmitLoadBatch(&batch, handle);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					VY_DLLEXPORT vy_aio_state vySubmitSingleLoadSync(vy_file_load load) {
 | 
				
			||||||
 | 
					    vy_aio_handle handle;
 | 
				
			||||||
 | 
					    if (vySubmitSingleLoad(load, &handle) != VY_SUCCESS)
 | 
				
			||||||
 | 
					        return VY_AIO_STATE_FAILED;
 | 
				
			||||||
 | 
					    vy_aio_state state = vyWaitForAIOCompletion(handle);
 | 
				
			||||||
 | 
					    vyReleaseAIO(handle);
 | 
				
			||||||
 | 
					    return state;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -47,14 +47,12 @@ typedef enum {
 | 
				
			|||||||
    VY_AIO_STATE_FAILED,
 | 
					    VY_AIO_STATE_FAILED,
 | 
				
			||||||
} vy_aio_state;
 | 
					} vy_aio_state;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
VY_DLLEXPORT vy_result vyInitAIO(unsigned int max_concurrent_operations);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
VY_DLLEXPORT void vyShutdownAIO(void);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
VY_DLLEXPORT vy_result vySubmitLoadBatch(const vy_load_batch *batch, vy_aio_handle *handles);
 | 
					VY_DLLEXPORT vy_result vySubmitLoadBatch(const vy_load_batch *batch, vy_aio_handle *handles);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
VY_DLLEXPORT volatile vy_aio_state vyGetAIOState(vy_aio_handle handle);
 | 
					VY_DLLEXPORT volatile vy_aio_state vyGetAIOState(vy_aio_handle handle);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Blocks until the given operation is no longer pending.
 | 
				
			||||||
 | 
					 * Returns the state that caused the wait to end. The handle is still valid after this function returned. */
 | 
				
			||||||
VY_DLLEXPORT vy_aio_state vyWaitForAIOCompletion(vy_aio_handle handle);
 | 
					VY_DLLEXPORT vy_aio_state vyWaitForAIOCompletion(vy_aio_handle handle);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Releases the internal storage for the operation.
 | 
					/* Releases the internal storage for the operation.
 | 
				
			||||||
@ -62,5 +60,10 @@ VY_DLLEXPORT vy_aio_state vyWaitForAIOCompletion(vy_aio_handle handle);
 | 
				
			|||||||
 */
 | 
					 */
 | 
				
			||||||
VY_DLLEXPORT void vyReleaseAIO(vy_aio_handle handle);
 | 
					VY_DLLEXPORT void vyReleaseAIO(vy_aio_handle handle);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					VY_DLLEXPORT vy_result vySubmitSingleLoad(vy_file_load load, vy_aio_handle *handle);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Convenience wrapper for a single synchronous file load.
 | 
				
			||||||
 | 
					 * Returns the state that caused the wait for completion to return. */
 | 
				
			||||||
 | 
					VY_DLLEXPORT vy_aio_state vySubmitSingleLoadSync(vy_file_load load);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										137
									
								
								src/runtime/asset_dependencies.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										137
									
								
								src/runtime/asset_dependencies.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,137 @@
 | 
				
			|||||||
 | 
					#define VY_DEFINE_DEPENDENCY_FILE_STRUCTURES
 | 
				
			||||||
 | 
					#include "asset_dependencies.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "aio.h"
 | 
				
			||||||
 | 
					#include "buffer_manager.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <assert.h>
 | 
				
			||||||
 | 
					#include <stdbool.h>
 | 
				
			||||||
 | 
					#include <stdlib.h>
 | 
				
			||||||
 | 
					#include <string.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef struct {
 | 
				
			||||||
 | 
					    uint32_t begin;
 | 
				
			||||||
 | 
					    uint32_t count;
 | 
				
			||||||
 | 
					} vy_dep_list;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef struct {
 | 
				
			||||||
 | 
					    vy_uid *uids;
 | 
				
			||||||
 | 
					    vy_dep_list *lists;
 | 
				
			||||||
 | 
					    uint32_t capacity;
 | 
				
			||||||
 | 
					} vy_dep_map;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static vy_dep_map _map;
 | 
				
			||||||
 | 
					static vy_uid *_list_mem;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					vy_result LoadAssetDependencies(void) {
 | 
				
			||||||
 | 
					    vy_dependency_file_header header;
 | 
				
			||||||
 | 
					    vy_file_id fid = vyAddFile("assets/deps.bin");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (vySubmitSingleLoadSync((vy_file_load){.dest      = &header,
 | 
				
			||||||
 | 
					                                              .num_bytes = sizeof(header),
 | 
				
			||||||
 | 
					                                              .offset    = 0,
 | 
				
			||||||
 | 
					                                              .file      = fid}) != VY_AIO_STATE_FINISHED) {
 | 
				
			||||||
 | 
					        vyReportError("core", "Failed to load deps.bin");
 | 
				
			||||||
 | 
					        return VY_UNKNOWN_ERROR;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    void *buffer = vyAllocBuffer(header.data_size);
 | 
				
			||||||
 | 
					    if (vySubmitSingleLoadSync((vy_file_load){.dest      = buffer,
 | 
				
			||||||
 | 
					                                              .num_bytes = header.data_size,
 | 
				
			||||||
 | 
					                                              .offset    = sizeof(header),
 | 
				
			||||||
 | 
					                                              .file      = fid}) != VY_AIO_STATE_FINISHED) {
 | 
				
			||||||
 | 
					        vyReportError("core", "Failed to load deps.bin");
 | 
				
			||||||
 | 
					        return VY_UNKNOWN_ERROR;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* We know the exact number of list entries */
 | 
				
			||||||
 | 
					    uint64_t total_list_entries =
 | 
				
			||||||
 | 
					        (header.data_size - header.num_lists * sizeof(vy_dependency_file_list_header)) /
 | 
				
			||||||
 | 
					        sizeof(vy_uid);
 | 
				
			||||||
 | 
					    _list_mem = malloc(total_list_entries * sizeof(vy_uid));
 | 
				
			||||||
 | 
					    if (!_list_mem) {
 | 
				
			||||||
 | 
					        vyReleaseBuffer(buffer, header.data_size);
 | 
				
			||||||
 | 
					        vyReportError("core", "Failed to allocate dependency list storage.");
 | 
				
			||||||
 | 
					        return VY_UNKNOWN_ERROR;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    _map.capacity = vyNextPowerOfTwo32(header.num_lists);
 | 
				
			||||||
 | 
					    _map.uids     = calloc(_map.capacity, sizeof(vy_uid));
 | 
				
			||||||
 | 
					    if (!_map.uids) {
 | 
				
			||||||
 | 
					        free(_list_mem);
 | 
				
			||||||
 | 
					        vyReleaseBuffer(buffer, header.data_size);
 | 
				
			||||||
 | 
					        vyReportError("core", "Failed to allocate dependency list storage.");
 | 
				
			||||||
 | 
					        return VY_UNKNOWN_ERROR;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    _map.lists = calloc(_map.capacity, sizeof(vy_dep_list));
 | 
				
			||||||
 | 
					    if (!_map.uids) {
 | 
				
			||||||
 | 
					        free(_list_mem);
 | 
				
			||||||
 | 
					        free(_map.uids);
 | 
				
			||||||
 | 
					        vyReleaseBuffer(buffer, header.data_size);
 | 
				
			||||||
 | 
					        vyReportError("core", "Failed to allocate dependency list storage.");
 | 
				
			||||||
 | 
					        return VY_UNKNOWN_ERROR;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    uint32_t storage_at = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    vy_dependency_file_list_header *list = buffer;
 | 
				
			||||||
 | 
					    for (uint32_t i = 0; i < header.num_lists; ++i) {
 | 
				
			||||||
 | 
					        const vy_uid *entries = (vy_uid *)(list + 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /* Validate the checksum */
 | 
				
			||||||
 | 
					        XXH64_hash_t file_hash = XXH64_hashFromCanonical(&list->checksum);
 | 
				
			||||||
 | 
					        XXH64_hash_t calc_hash = XXH3_64bits(entries, sizeof(vy_uid) * list->num_entries);
 | 
				
			||||||
 | 
					        if (file_hash != calc_hash) {
 | 
				
			||||||
 | 
					            vyReportError("core", "Checksum mismatch in list %u", i);
 | 
				
			||||||
 | 
					            vyReleaseBuffer(buffer, header.data_size);
 | 
				
			||||||
 | 
					            return VY_UNKNOWN_ERROR;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /* Store the list */
 | 
				
			||||||
 | 
					        memcpy(_list_mem + storage_at, entries, sizeof(vy_uid) * list->num_entries);
 | 
				
			||||||
 | 
					        bool inserted = false;
 | 
				
			||||||
 | 
					        for (uint32_t j = 0; j < _map.capacity; ++j) {
 | 
				
			||||||
 | 
					            uint32_t slot = (list->uid + j) % _map.capacity;
 | 
				
			||||||
 | 
					            if (_map.uids[slot] == VY_INVALID_UID) {
 | 
				
			||||||
 | 
					                _map.uids[slot] = list->uid;
 | 
				
			||||||
 | 
					                _map.lists[slot].begin = storage_at;
 | 
				
			||||||
 | 
					                _map.lists[slot].count = list->num_entries;
 | 
				
			||||||
 | 
					                inserted = true;
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        storage_at += list->num_entries;
 | 
				
			||||||
 | 
					        assert(inserted);
 | 
				
			||||||
 | 
					        assert(storage_at <= total_list_entries);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        list = (vy_dependency_file_list_header *)(entries + list->num_entries);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    vyReleaseBuffer(buffer, header.data_size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return VY_SUCCESS;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ReleaseAssetDependencies(void) {
 | 
				
			||||||
 | 
					    free(_list_mem);
 | 
				
			||||||
 | 
					    free(_map.uids);
 | 
				
			||||||
 | 
					    free(_map.lists);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					VY_DLLEXPORT vy_asset_dependency_list vyGetAssetDependencies(vy_uid asset) {
 | 
				
			||||||
 | 
					    vy_asset_dependency_list result = {
 | 
				
			||||||
 | 
					        .dependencies = NULL,
 | 
				
			||||||
 | 
					        .count        = 0,
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    for (uint32_t i = 0; i < _map.capacity; ++i) {
 | 
				
			||||||
 | 
					        uint32_t slot = (asset + i) % _map.capacity;
 | 
				
			||||||
 | 
					        if (_map.uids[slot] == asset) {
 | 
				
			||||||
 | 
					            result.dependencies = &_list_mem[_map.lists[slot].begin];
 | 
				
			||||||
 | 
					            result.count        = _map.lists[slot].count;
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        } else if (_map.uids[slot] == VY_INVALID_UID) {
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return result;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										33
									
								
								src/runtime/asset_dependencies.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								src/runtime/asset_dependencies.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,33 @@
 | 
				
			|||||||
 | 
					#ifndef VY_ASSET_DEPENDENCIES_H
 | 
				
			||||||
 | 
					#define VY_ASSET_DEPENDENCIES_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "assets.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef VY_DEFINE_DEPENDENCY_FILE_STRUCTURES
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "xxhash/xxhash.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#pragma pack(push, 1)
 | 
				
			||||||
 | 
					typedef struct {
 | 
				
			||||||
 | 
					    uint64_t data_size;
 | 
				
			||||||
 | 
					    uint32_t num_lists;
 | 
				
			||||||
 | 
					} vy_dependency_file_header;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef struct {
 | 
				
			||||||
 | 
					    vy_uid uid;
 | 
				
			||||||
 | 
					    uint32_t num_entries;
 | 
				
			||||||
 | 
					    XXH64_canonical_t checksum;
 | 
				
			||||||
 | 
					} vy_dependency_file_list_header;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#pragma pack(pop)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef struct {
 | 
				
			||||||
 | 
					    const vy_uid *dependencies;
 | 
				
			||||||
 | 
					    uint32_t count;
 | 
				
			||||||
 | 
					} vy_asset_dependency_list;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					VY_DLLEXPORT vy_asset_dependency_list vyGetAssetDependencies(vy_uid asset);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
@ -57,7 +57,7 @@ VY_CVAR_SZ(rt_BufferManagerMemory,
 | 
				
			|||||||
           "Total number of bytes allocated for the buffer manager. Default: 1GB",
 | 
					           "Total number of bytes allocated for the buffer manager. Default: 1GB",
 | 
				
			||||||
           VY_GB(1));
 | 
					           VY_GB(1));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
VY_DLLEXPORT vy_result vyInitBufferManager(void) {
 | 
					vy_result InitBufferManager(void) {
 | 
				
			||||||
    if ((rt_BufferManagerMemory.sz % NUM_BLOCK_SIZES) != 0)
 | 
					    if ((rt_BufferManagerMemory.sz % NUM_BLOCK_SIZES) != 0)
 | 
				
			||||||
        vyLog("BUFFERMGR",
 | 
					        vyLog("BUFFERMGR",
 | 
				
			||||||
              "Configured memory amount is not dividable by number of block "
 | 
					              "Configured memory amount is not dividable by number of block "
 | 
				
			||||||
@ -106,7 +106,7 @@ VY_DLLEXPORT vy_result vyInitBufferManager(void) {
 | 
				
			|||||||
    return VY_SUCCESS;
 | 
					    return VY_SUCCESS;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
VY_DLLEXPORT void vyShutdownBufferManager(void) {
 | 
					void ShutdownBufferManager(void) {
 | 
				
			||||||
    for (unsigned int i = 0; i < NUM_BLOCK_SIZES; ++i) {
 | 
					    for (unsigned int i = 0; i < NUM_BLOCK_SIZES; ++i) {
 | 
				
			||||||
        vyDestroyMutex(_regions[i].guard);
 | 
					        vyDestroyMutex(_regions[i].guard);
 | 
				
			||||||
        free(_regions[i].memory);
 | 
					        free(_regions[i].memory);
 | 
				
			||||||
 | 
				
			|||||||
@ -8,10 +8,6 @@ enum {
 | 
				
			|||||||
    VY_BUFFER_MGR_MUTEX_CREATION_FAILED,
 | 
					    VY_BUFFER_MGR_MUTEX_CREATION_FAILED,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
VY_DLLEXPORT vy_result vyInitBufferManager(void);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
VY_DLLEXPORT void vyShutdownBufferManager(void);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
VY_DLLEXPORT void *vyAllocBuffer(size_t size);
 | 
					VY_DLLEXPORT void *vyAllocBuffer(size_t size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
VY_DLLEXPORT void vyReleaseBuffer(const void *begin, size_t size);
 | 
					VY_DLLEXPORT void vyReleaseBuffer(const void *begin, size_t size);
 | 
				
			||||||
 | 
				
			|||||||
@ -1,5 +1,6 @@
 | 
				
			|||||||
#include "file_tab.h"
 | 
					#include "file_tab.h"
 | 
				
			||||||
#include "threading.h"
 | 
					#include "threading.h"
 | 
				
			||||||
 | 
					#include "config.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <xxhash/xxhash.h>
 | 
					#include <xxhash/xxhash.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -16,7 +17,10 @@ typedef struct {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
static vy_file_tab _file_tab;
 | 
					static vy_file_tab _file_tab;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
vy_result vyInitFileTab(unsigned int max_files) {
 | 
					VY_CVAR_I(rt_FileTabCapacity, "Maximum number of filetab entries. Default: 1024", 1024);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					vy_result InitFileTab(void) {
 | 
				
			||||||
 | 
					    unsigned int max_files = (unsigned int)rt_FileTabCapacity.i;
 | 
				
			||||||
    _file_tab.ids = calloc(max_files, sizeof(vy_file_id));
 | 
					    _file_tab.ids = calloc(max_files, sizeof(vy_file_id));
 | 
				
			||||||
    if (!_file_tab.ids)
 | 
					    if (!_file_tab.ids)
 | 
				
			||||||
        return 1;
 | 
					        return 1;
 | 
				
			||||||
@ -33,21 +37,21 @@ vy_result vyInitFileTab(unsigned int max_files) {
 | 
				
			|||||||
    return VY_SUCCESS;
 | 
					    return VY_SUCCESS;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void vyShutdownFileTab(void) {
 | 
					void ShutdownFileTab(void) {
 | 
				
			||||||
    free(_file_tab.ids);
 | 
					    free(_file_tab.ids);
 | 
				
			||||||
    free(_file_tab.names);
 | 
					    free(_file_tab.names);
 | 
				
			||||||
    free(_file_tab.name_offsets);
 | 
					    free(_file_tab.name_offsets);
 | 
				
			||||||
    vyDestroyMutex(_file_tab.mutex);
 | 
					    vyDestroyMutex(_file_tab.mutex);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
vy_file_id vyGetFileId(const char *path) {
 | 
					VY_DLLEXPORT vy_file_id vyGetFileId(const char *path) {
 | 
				
			||||||
    vy_text_span span;
 | 
					    vy_text_span span;
 | 
				
			||||||
    span.start  = path;
 | 
					    span.start  = path;
 | 
				
			||||||
    span.length = (unsigned int)strlen(path);
 | 
					    span.length = (unsigned int)strlen(path);
 | 
				
			||||||
    return vyGetFileIdFromSpan(span);
 | 
					    return vyGetFileIdFromSpan(span);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
vy_file_id vyGetFileIdFromSpan(vy_text_span path) {
 | 
					VY_DLLEXPORT vy_file_id vyGetFileIdFromSpan(vy_text_span path) {
 | 
				
			||||||
    /* Randomly choosen, aka finger smash keyboard */
 | 
					    /* Randomly choosen, aka finger smash keyboard */
 | 
				
			||||||
    XXH64_hash_t seed = 15340978;
 | 
					    XXH64_hash_t seed = 15340978;
 | 
				
			||||||
    vy_file_id fid    = (vy_file_id)XXH3_64bits_withSeed(path.start, path.length, seed);
 | 
					    vy_file_id fid    = (vy_file_id)XXH3_64bits_withSeed(path.start, path.length, seed);
 | 
				
			||||||
 | 
				
			|||||||
@ -9,10 +9,6 @@
 | 
				
			|||||||
typedef uint64_t vy_file_id;
 | 
					typedef uint64_t vy_file_id;
 | 
				
			||||||
#define VY_INVALID_FILE_ID 0
 | 
					#define VY_INVALID_FILE_ID 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
VY_DLLEXPORT vy_result vyInitFileTab(unsigned int max_files);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
VY_DLLEXPORT void vyShutdownFileTab(void);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
VY_DLLEXPORT vy_file_id vyGetFileId(const char *path);
 | 
					VY_DLLEXPORT vy_file_id vyGetFileId(const char *path);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
VY_DLLEXPORT vy_file_id vyGetFileIdFromSpan(vy_text_span path);
 | 
					VY_DLLEXPORT vy_file_id vyGetFileIdFromSpan(vy_text_span path);
 | 
				
			||||||
 | 
				
			|||||||
@ -10,47 +10,69 @@ extern vy_cvar rt_Fullscreen;
 | 
				
			|||||||
extern vy_cvar rt_WindowWidth;
 | 
					extern vy_cvar rt_WindowWidth;
 | 
				
			||||||
extern vy_cvar rt_WindowHeight;
 | 
					extern vy_cvar rt_WindowHeight;
 | 
				
			||||||
extern vy_cvar rt_BufferManagerMemory;
 | 
					extern vy_cvar rt_BufferManagerMemory;
 | 
				
			||||||
 | 
					extern vy_cvar rt_FileTabCapacity;
 | 
				
			||||||
 | 
					extern vy_cvar rt_MaxConcurrentAsyncIO;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void __RegisterRuntimeCVars(void) {
 | 
					void RegisterRuntimeCVars(void) {
 | 
				
			||||||
    vyRegisterCVAR(&rt_Renderer);
 | 
					    vyRegisterCVAR(&rt_Renderer);
 | 
				
			||||||
    vyRegisterCVAR(&rt_Fullscreen);
 | 
					    vyRegisterCVAR(&rt_Fullscreen);
 | 
				
			||||||
    vyRegisterCVAR(&rt_WindowWidth);
 | 
					    vyRegisterCVAR(&rt_WindowWidth);
 | 
				
			||||||
    vyRegisterCVAR(&rt_WindowHeight);
 | 
					    vyRegisterCVAR(&rt_WindowHeight);
 | 
				
			||||||
    vyRegisterCVAR(&rt_BufferManagerMemory);
 | 
					    vyRegisterCVAR(&rt_BufferManagerMemory);
 | 
				
			||||||
 | 
					    vyRegisterCVAR(&rt_FileTabCapacity);
 | 
				
			||||||
 | 
					    vyRegisterCVAR(&rt_MaxConcurrentAsyncIO);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
extern void __RTSetMainThreadId(void);
 | 
					extern void SetMainThreadId(void);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern vy_result InitBufferManager(void);
 | 
				
			||||||
 | 
					extern void ShutdownBufferManager(void);
 | 
				
			||||||
 | 
					extern vy_result InitFileTab(void);
 | 
				
			||||||
 | 
					extern void ShutdownFileTab(void);
 | 
				
			||||||
 | 
					extern vy_result InitAIO(void);
 | 
				
			||||||
 | 
					extern void ShutdownAIO(void);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern vy_result LoadUIDTable(void);
 | 
				
			||||||
 | 
					extern void ReleaseUIDTable(void);
 | 
				
			||||||
 | 
					extern vy_result LoadAssetDependencies(void); 
 | 
				
			||||||
 | 
					extern void ReleaseAssetDependencies(void);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
VY_DLLEXPORT vy_result vyInitRuntime(void) {
 | 
					VY_DLLEXPORT vy_result vyInitRuntime(void) {
 | 
				
			||||||
    __RTSetMainThreadId();
 | 
					    SetMainThreadId();
 | 
				
			||||||
    __RegisterRuntimeCVars();
 | 
					    RegisterRuntimeCVars();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    vy_result res;
 | 
					    vy_result res;
 | 
				
			||||||
    if ((res = vyInitBufferManager()) != VY_SUCCESS) {
 | 
					    if ((res = InitBufferManager()) != VY_SUCCESS) {
 | 
				
			||||||
        vyReportError("BUFFERMGR", "Init failed.");
 | 
					        vyReportError("BUFFERMGR", "Init failed.");
 | 
				
			||||||
        return res;
 | 
					        return res;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if ((res = vyInitFileTab(1024)) != VY_SUCCESS) {
 | 
					    if ((res = InitFileTab()) != VY_SUCCESS) {
 | 
				
			||||||
        vyReportError("FTAB", "Init failed.");
 | 
					        vyReportError("FTAB", "Init failed.");
 | 
				
			||||||
        return res;
 | 
					        return res;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if ((res = vyInitAIO(0)) != VY_SUCCESS) {
 | 
					    if ((res = InitAIO()) != VY_SUCCESS) {
 | 
				
			||||||
        vyReportError("AIO", "Init failed.");
 | 
					        vyReportError("AIO", "Init failed.");
 | 
				
			||||||
        return res;
 | 
					        return res;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if ((res = vyLoadUIDTable()) != VY_SUCCESS) {
 | 
					    if ((res = LoadUIDTable()) != VY_SUCCESS) {
 | 
				
			||||||
        vyLog("CORE", "LoadUIDTable returned result: %u", res);
 | 
					        vyLog("CORE", "LoadUIDTable returned result: %u", res);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if ((res = LoadAssetDependencies()) != VY_SUCCESS) {
 | 
				
			||||||
 | 
					        vyReportError("ASSETDEP", "Init failed.");
 | 
				
			||||||
 | 
					        return res;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return VY_SUCCESS;
 | 
					    return VY_SUCCESS;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
VY_DLLEXPORT void vyShutdownRuntime(void) {
 | 
					VY_DLLEXPORT void vyShutdownRuntime(void) {
 | 
				
			||||||
    vyReleaseUIDTable();
 | 
					    ReleaseAssetDependencies();
 | 
				
			||||||
    vyShutdownAIO();
 | 
					    ReleaseUIDTable();
 | 
				
			||||||
    vyShutdownFileTab();
 | 
					    ShutdownAIO();
 | 
				
			||||||
    vyShutdownBufferManager();
 | 
					    ShutdownFileTab();
 | 
				
			||||||
 | 
					    ShutdownBufferManager();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -87,6 +87,21 @@ static VY_INLINE void vySetRelptr(vy_relptr *ptr, void *target) {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Bitfiddling functions */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Portable solution, On x64 using clzl is probably faster. */
 | 
				
			||||||
 | 
					static VY_INLINE uint32_t vyNextPowerOfTwo32(uint32_t v) {
 | 
				
			||||||
 | 
					    v--;
 | 
				
			||||||
 | 
					    v |= v >> 1;
 | 
				
			||||||
 | 
					    v |= v >> 2;
 | 
				
			||||||
 | 
					    v |= v >> 4;
 | 
				
			||||||
 | 
					    v |= v >> 8;
 | 
				
			||||||
 | 
					    v |= v >> 16;
 | 
				
			||||||
 | 
					    v++;
 | 
				
			||||||
 | 
					    return v;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Runtime init. Initializes basic systems.
 | 
					/* Runtime init. Initializes basic systems.
 | 
				
			||||||
 * You need to call this, even if you build a CLI only app. */
 | 
					 * You need to call this, even if you build a CLI only app. */
 | 
				
			||||||
VY_DLLEXPORT vy_result vyInitRuntime(void);
 | 
					VY_DLLEXPORT vy_result vyInitRuntime(void);
 | 
				
			||||||
 | 
				
			|||||||
@ -28,7 +28,7 @@ static INIT_ONCE _guard_init = INIT_ONCE_STATIC_INIT;
 | 
				
			|||||||
static vy_thread_id _main_thread_id;
 | 
					static vy_thread_id _main_thread_id;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Called by the runtime during setup */
 | 
					/* Called by the runtime during setup */
 | 
				
			||||||
extern void __RTSetMainThreadId(void) {
 | 
					extern void SetMainThreadId(void) {
 | 
				
			||||||
    _main_thread_id = (vy_thread_id)GetCurrentThreadId();
 | 
					    _main_thread_id = (vy_thread_id)GetCurrentThreadId();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -17,23 +17,11 @@ typedef struct {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
static vy_uidtab _tab;
 | 
					static vy_uidtab _tab;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Portable solution, On x64 using clzl is probably faster. */
 | 
					vy_result LoadUIDTable(void) {
 | 
				
			||||||
static uint32_t NextPowerOfTwo(uint32_t v) {
 | 
					 | 
				
			||||||
    v--;
 | 
					 | 
				
			||||||
    v |= v >> 1;
 | 
					 | 
				
			||||||
    v |= v >> 2;
 | 
					 | 
				
			||||||
    v |= v >> 4;
 | 
					 | 
				
			||||||
    v |= v >> 8;
 | 
					 | 
				
			||||||
    v |= v >> 16;
 | 
					 | 
				
			||||||
    v++;
 | 
					 | 
				
			||||||
    return v;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
VY_DLLEXPORT vy_result vyLoadUIDTable(void) {
 | 
					 | 
				
			||||||
    /* We use stdio here, because we cannot load any asset in parallel to this.
 | 
					    /* We use stdio here, because we cannot load any asset in parallel to this.
 | 
				
			||||||
     * This is because the uidtab is what tells us which assets exist.
 | 
					     * This is because the uidtab is what tells us which assets exist.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    FILE *f = fopen("uidtab.bin", "rb");
 | 
					    FILE *f = fopen("assets/uidtab.bin", "rb");
 | 
				
			||||||
    if (!f)
 | 
					    if (!f)
 | 
				
			||||||
        return VY_LOAD_FAILED;
 | 
					        return VY_LOAD_FAILED;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -52,7 +40,7 @@ VY_DLLEXPORT vy_result vyLoadUIDTable(void) {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
    */
 | 
					    */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    _tab.slots = NextPowerOfTwo(header.num_entries * 2);
 | 
					    _tab.slots = vyNextPowerOfTwo32(header.num_entries * 2);
 | 
				
			||||||
    void *mem  = malloc((sizeof(vy_uid) + sizeof(vy_uid_data)) * _tab.slots);
 | 
					    void *mem  = malloc((sizeof(vy_uid) + sizeof(vy_uid_data)) * _tab.slots);
 | 
				
			||||||
    if (!mem) {
 | 
					    if (!mem) {
 | 
				
			||||||
        fclose(f);
 | 
					        fclose(f);
 | 
				
			||||||
@ -114,7 +102,7 @@ VY_DLLEXPORT vy_result vyLoadUIDTable(void) {
 | 
				
			|||||||
    return VY_SUCCESS;
 | 
					    return VY_SUCCESS;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
VY_DLLEXPORT void vyReleaseUIDTable(void) {
 | 
					void ReleaseUIDTable(void) {
 | 
				
			||||||
    free(_tab.uids);
 | 
					    free(_tab.uids);
 | 
				
			||||||
    _tab.slots = 0;
 | 
					    _tab.slots = 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -31,8 +31,6 @@ typedef struct {
 | 
				
			|||||||
    uint64_t size;
 | 
					    uint64_t size;
 | 
				
			||||||
} vy_uid_data;
 | 
					} vy_uid_data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
VY_DLLEXPORT vy_result vyLoadUIDTable(void);
 | 
					 | 
				
			||||||
VY_DLLEXPORT void vyReleaseUIDTable(void);
 | 
					 | 
				
			||||||
VY_DLLEXPORT const vy_uid_data *vyGetUIDData(vy_uid uid);
 | 
					VY_DLLEXPORT const vy_uid_data *vyGetUIDData(vy_uid uid);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
@ -102,9 +102,6 @@ int main(int argc, char **argv) {
 | 
				
			|||||||
    vyInitPackages();
 | 
					    vyInitPackages();
 | 
				
			||||||
    vySetWorkingDirectory(g_assetc_options.root_directory);
 | 
					    vySetWorkingDirectory(g_assetc_options.root_directory);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Explictily reload uidtab, because we changed the working directory here */
 | 
					 | 
				
			||||||
    vyLoadUIDTable();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (vyLoadAssetMeta() != VY_SUCCESS) {
 | 
					    if (vyLoadAssetMeta() != VY_SUCCESS) {
 | 
				
			||||||
        return 1;
 | 
					        return 1;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -136,6 +133,9 @@ int main(int argc, char **argv) {
 | 
				
			|||||||
    if (vyWriteUIDTab() != VY_SUCCESS) {
 | 
					    if (vyWriteUIDTab() != VY_SUCCESS) {
 | 
				
			||||||
        return 1;
 | 
					        return 1;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    if (vySaveAssetDependencies() != VY_SUCCESS) {
 | 
				
			||||||
 | 
					        return 1;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    vyShutdownRuntime();
 | 
					    vyShutdownRuntime();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -1,13 +1,16 @@
 | 
				
			|||||||
#include "dependency_tracking.h"
 | 
					#include "dependency_tracking.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define VY_DEFINE_DEPENDENCY_FILE_STRUCTURES
 | 
				
			||||||
#include "runtime/assets.h"
 | 
					#include "runtime/assets.h"
 | 
				
			||||||
#include "runtime/threading.h"
 | 
					#include "runtime/threading.h"
 | 
				
			||||||
 | 
					#include "runtime/asset_dependencies.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <stdbool.h>
 | 
					#include <stdbool.h>
 | 
				
			||||||
#include <limits.h>
 | 
					#include <limits.h>
 | 
				
			||||||
#include <assert.h>
 | 
					#include <assert.h>
 | 
				
			||||||
#include <stdlib.h>
 | 
					#include <stdlib.h>
 | 
				
			||||||
#include <string.h>
 | 
					#include <string.h>
 | 
				
			||||||
 | 
					#include <stdio.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Track a list of dependencies per asset.
 | 
					/* Track a list of dependencies per asset.
 | 
				
			||||||
@ -125,3 +128,101 @@ vy_result vyAddAssetDependency(vy_uid dependent, vy_uid dependency) {
 | 
				
			|||||||
    res = InsertIntoList(dependency, dependent, 1);
 | 
					    res = InsertIntoList(dependency, dependent, 1);
 | 
				
			||||||
    return res;
 | 
					    return res;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					vy_result vySaveAssetDependencies(void) {
 | 
				
			||||||
 | 
					    assert(vyIsMainThread());
 | 
				
			||||||
 | 
					    vy_dependency_file_header header = {.num_lists = 0, .data_size = 0};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (size_t i = 0; i < MAP_SIZE; ++i) {
 | 
				
			||||||
 | 
					        if (_uids[i] != VY_INVALID_UID) {
 | 
				
			||||||
 | 
					            if (!_lists[i].dependencies)
 | 
				
			||||||
 | 
					                continue;
 | 
				
			||||||
 | 
					            header.num_lists += 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            /* Determine the list size */
 | 
				
			||||||
 | 
					            vy_dep_list_bucket *bucket = &_buckets[_lists[i].dependencies];
 | 
				
			||||||
 | 
					            uint32_t total_list_size   = bucket->count;
 | 
				
			||||||
 | 
					            while (bucket->next != END_OF_LIST) {
 | 
				
			||||||
 | 
					                bucket = &_buckets[bucket->next];
 | 
				
			||||||
 | 
					                total_list_size += bucket->count;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            header.data_size += total_list_size * sizeof(vy_uid) + sizeof(vy_dependency_file_list_header);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    FILE *f = fopen("deps.bin", "wb");
 | 
				
			||||||
 | 
					    if (!f) {
 | 
				
			||||||
 | 
					        vyReportError("ASSETC", "Failed to open 'deps.bin' for writing.");
 | 
				
			||||||
 | 
					        return VY_UNKNOWN_ERROR;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (fwrite(&header, sizeof(header), 1, f) != 1) {
 | 
				
			||||||
 | 
					        vyReportError("ASSETC", "Failed to write to 'deps.bin'.");
 | 
				
			||||||
 | 
					        fclose(f);
 | 
				
			||||||
 | 
					        return VY_UNKNOWN_ERROR;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void *buffer       = NULL;
 | 
				
			||||||
 | 
					    size_t buffer_size = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (size_t i = 0; i < MAP_SIZE; ++i) {
 | 
				
			||||||
 | 
					        if (_uids[i] != VY_INVALID_UID) {
 | 
				
			||||||
 | 
					            if (!_lists[i].dependencies)
 | 
				
			||||||
 | 
					                continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            /* Determine the list size */
 | 
				
			||||||
 | 
					            vy_dep_list_bucket *bucket = &_buckets[_lists[i].dependencies];
 | 
				
			||||||
 | 
					            uint32_t total_list_size = bucket->count;
 | 
				
			||||||
 | 
					            while (bucket->next != END_OF_LIST) {
 | 
				
			||||||
 | 
					                bucket = &_buckets[bucket->next];
 | 
				
			||||||
 | 
					                total_list_size += bucket->count;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            /* Allocate */
 | 
				
			||||||
 | 
					            size_t required_size =
 | 
				
			||||||
 | 
					                total_list_size * sizeof(vy_uid) + sizeof(vy_dependency_file_list_header);
 | 
				
			||||||
 | 
					            if (required_size > buffer_size) {
 | 
				
			||||||
 | 
					                void *t = realloc(buffer, required_size);
 | 
				
			||||||
 | 
					                if (!t) {
 | 
				
			||||||
 | 
					                    free(buffer);
 | 
				
			||||||
 | 
					                    fclose(f);
 | 
				
			||||||
 | 
					                    return VY_UNKNOWN_ERROR;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                buffer = t;
 | 
				
			||||||
 | 
					                buffer_size = required_size;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            /* Fill header */
 | 
				
			||||||
 | 
					            vy_dependency_file_list_header *list_header = buffer;
 | 
				
			||||||
 | 
					            vy_uid *list                                = (vy_uid *)(list_header + 1);
 | 
				
			||||||
 | 
					            list_header->uid                            = _uids[i];
 | 
				
			||||||
 | 
					            list_header->num_entries                    = total_list_size;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            /* Copy the list */
 | 
				
			||||||
 | 
					            uint32_t at = 0;
 | 
				
			||||||
 | 
					            bucket = &_buckets[_lists[i].dependencies];
 | 
				
			||||||
 | 
					            do {
 | 
				
			||||||
 | 
					                memcpy(&list[at], bucket->entries, sizeof(vy_uid) * bucket->count);
 | 
				
			||||||
 | 
					                at += bucket->count;
 | 
				
			||||||
 | 
					                bucket = &_buckets[bucket->next];
 | 
				
			||||||
 | 
					            } while (bucket != &_buckets[END_OF_LIST]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            XXH64_hash_t hash = XXH3_64bits(list, sizeof(vy_uid) * total_list_size);
 | 
				
			||||||
 | 
					            XXH64_canonicalFromHash(&list_header->checksum, hash);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (fwrite(buffer, required_size, 1, f) != 1) {
 | 
				
			||||||
 | 
					                vyReportError("ASSETC", "Failed to write to 'deps.bin'.");
 | 
				
			||||||
 | 
					                fclose(f);
 | 
				
			||||||
 | 
					                free(buffer);
 | 
				
			||||||
 | 
					                return VY_UNKNOWN_ERROR;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fclose(f);
 | 
				
			||||||
 | 
					    free(buffer);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return VY_SUCCESS;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -9,4 +9,6 @@ vy_result vyInitDependencyTracking(void);
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
vy_result vyAddAssetDependency(vy_uid dependent, vy_uid dependency);
 | 
					vy_result vyAddAssetDependency(vy_uid dependent, vy_uid dependency);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					vy_result vySaveAssetDependencies(void);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
				
			|||||||
@ -33,6 +33,10 @@ static vy_result DirectoryHandler(const char *name, vyIterateDirElementType type
 | 
				
			|||||||
            else if (memcmp(&name[name_len - 4], ".bin", 4) == 0)
 | 
					            else if (memcmp(&name[name_len - 4], ".bin", 4) == 0)
 | 
				
			||||||
                return VY_SUCCESS;
 | 
					                return VY_SUCCESS;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					        if (name[0] == '.') {
 | 
				
			||||||
 | 
					            return VY_SUCCESS;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /* Check if we know that file */
 | 
					        /* Check if we know that file */
 | 
				
			||||||
        if (data->path_end > 0) {
 | 
					        if (data->path_end > 0) {
 | 
				
			||||||
            data->path_scratch[data->path_end] = '/';
 | 
					            data->path_scratch[data->path_end] = '/';
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user