Load all models into dynamic memory, and store them in a way for reuse

This commit is contained in:
MysterD 2023-05-12 16:15:35 -07:00
parent e391faf574
commit bc73468e64
18 changed files with 142 additions and 134 deletions

View file

@ -71,6 +71,11 @@ s32 dynos_behavior_get_active_mod_index(BehaviorScript *bhvScript);
const char *dynos_behavior_get_token(BehaviorScript *bhvScript, u32 index);
void dynos_behavior_hook_all_custom_behaviors(void);
// -- models -- //
struct GraphNode* dynos_model_load_geo(enum ModelPool aModelPool, void* aAsset);
struct GraphNode* dynos_model_load_dl(enum ModelPool aModelPool, u8 aLayer, void* aAsset);
void dynos_model_clear_pool(enum ModelPool aModelPool);
// -- other -- //
void dynos_mod_shutdown(void);
void dynos_add_scroll_target(u32 index, const char *name, u32 offset, u32 size);

View file

@ -805,8 +805,6 @@ s32 DynOS_String_Width(const u8 *aStr64);
// Geo
//
void *DynOS_Geo_GetGraphNode(const void *aGeoLayout, bool aKeepInMemory);
//
// Levels
//
@ -961,6 +959,14 @@ DataNode<MovtexQC>* DynOS_MovtexQC_GetFromId(u32 id);
DataNode<MovtexQC>* DynOS_MovtexQC_GetFromIndex(s32 index);
void DynOS_MovtexQC_ModShutdown();
//
// Model Manager
//
struct GraphNode* DynOS_Model_LoadGeo(enum ModelPool aModelPool, void* aAsset);
struct GraphNode* DynOS_Model_LoadDl(enum ModelPool aModelPool, u8 aLayer, void* aAsset);
void DynOS_Model_ClearPool(enum ModelPool aModelPool);
//
// Bin
//

View file

@ -37,4 +37,11 @@ extern "C" {
#define DYNOS_AT_STARTUP __attribute__((constructor))
#define DYNOS_AT_EXIT __attribute__((destructor))
enum ModelPool {
MODEL_POOL_PERMANENT,
MODEL_POOL_SESSION,
MODEL_POOL_LEVEL,
MODEL_POOL_MAX,
};
#endif

View file

@ -121,10 +121,6 @@ const void* dynos_geolayout_get(const char *name) {
return DynOS_Actor_GetLayoutFromName(name);
}
void *dynos_geolayout_to_graphnode(const void *geoLayout, bool keepInMemory) {
return DynOS_Geo_GetGraphNode(geoLayout, keepInMemory);
}
// -- collisions -- //
void dynos_add_collision(const char *filePath, const char* collisionName) {
@ -226,7 +222,22 @@ void dynos_behavior_hook_all_custom_behaviors(void) {
DynOS_Bhv_HookAllCustomBehaviors();
}
// -- models -- //
struct GraphNode* dynos_model_load_geo(enum ModelPool aModelPool, void* aAsset) {
return DynOS_Model_LoadGeo(aModelPool, aAsset);
}
struct GraphNode* dynos_model_load_dl(enum ModelPool aModelPool, u8 aLayer, void* aAsset) {
return DynOS_Model_LoadDl(aModelPool, aLayer, aAsset);
}
void dynos_model_clear_pool(enum ModelPool aModelPool) {
DynOS_Model_ClearPool(aModelPool);
}
// -- other -- //
void dynos_mod_shutdown(void) {
DynOS_Mod_Shutdown();
}

View file

@ -49,7 +49,7 @@ void DynOS_Actor_AddCustom(const SysPath &aFilename, const char *aActorName) {
ActorGfx actorGfx = { };
actorGfx.mGfxData = _GfxData;
actorGfx.mPackIndex = MOD_PACK_INDEX;
actorGfx.mGraphNode = (GraphNode *) DynOS_Geo_GetGraphNode(geoLayout, false);
actorGfx.mGraphNode = (GraphNode *) DynOS_Model_LoadGeo(MODEL_POOL_SESSION, geoLayout);
if (!actorGfx.mGraphNode) {
Print(" ERROR: Couldn't load graph node for \"%s\"", actorName);
free(actorName);
@ -167,7 +167,7 @@ void DynOS_Actor_Override_All(void) {
for (struct Object *_Object = (struct Object *) _Head->header.next; _Object != _Head; _Object = (struct Object *) _Object->header.next) {
if (_Object->header.gfx.sharedChild != NULL && _Object->header.gfx.sharedChild->georef != NULL) {
GraphNode* georef = (GraphNode*)_Object->header.gfx.sharedChild->georef;
_Object->header.gfx.sharedChild = (GraphNode *) DynOS_Geo_GetGraphNode(georef, true);
_Object->header.gfx.sharedChild = DynOS_Model_LoadGeo(MODEL_POOL_PERMANENT, georef);
}
DynOS_Actor_Override((void**)&_Object->header.gfx.sharedChild);
}

68
data/dynos_mgr_models.cpp Normal file
View file

@ -0,0 +1,68 @@
#include <map>
#include "dynos.cpp.h"
extern "C" {
#include "engine/geo_layout.h"
#include "engine/graph_node.h"
}
static struct AllocOnlyPool* sModelPools[MODEL_POOL_MAX] = { 0 };
static std::map<void*, struct GraphNode*> sModelMap[MODEL_POOL_MAX];
struct GraphNode* DynOS_Model_LoadGeo(enum ModelPool aModelPool, void* aAsset) {
// sanity check pool
if (aModelPool >= MODEL_POOL_MAX) { return NULL; }
// allocate pool
if (!sModelPools[aModelPool]) {
sModelPools[aModelPool] = alloc_only_pool_init();
}
// check map
auto& map = sModelMap[aModelPool];
if (map.count(aAsset)) {
return map[aAsset];
}
// load geo
struct GraphNode* node = process_geo_layout(sModelPools[aModelPool], aAsset);
// store and return geo
map[aAsset] = node;
return node;
}
struct GraphNode* DynOS_Model_LoadDl(enum ModelPool aModelPool, u8 aLayer, void* aAsset) {
// sanity check pool
if (aModelPool >= MODEL_POOL_MAX) { return NULL; }
// allocate pool
if (!sModelPools[aModelPool]) {
sModelPools[aModelPool] = alloc_only_pool_init();
}
// check map
auto& map = sModelMap[aModelPool];
if (map.count(aAsset)) {
return map[aAsset];
}
// load geo
struct GraphNode* node = (struct GraphNode *) init_graph_node_display_list(sModelPools[aModelPool], NULL, aLayer, aAsset);
// store and return geo
map[aAsset] = node;
return node;
}
void DynOS_Model_ClearPool(enum ModelPool aModelPool) {
if (!sModelPools[aModelPool]) { return; }
// free and realloc pool
alloc_only_pool_free(sModelPools[aModelPool]);
sModelPools[aModelPool] = NULL;
// clear map
auto& map = sModelMap[aModelPool];
map.clear();
}

View file

@ -42,7 +42,7 @@ static void DynOS_Pack_ActivateActor(s32 aPackIndex, Pair<const char *, GfxData
GfxData* aGfxData = pair.second;
auto& geoNode = *(aGfxData->mGeoLayouts.end() - 1);
GraphNode* graphNode = (GraphNode *) DynOS_Geo_GetGraphNode(geoNode->mData, false);
GraphNode* graphNode = DynOS_Model_LoadGeo(MODEL_POOL_PERMANENT, geoNode->mData);
if (graphNode == NULL) { return; }
const void* georef = DynOS_Builtin_Actor_GetFromName(aActorName);

View file

@ -137,44 +137,6 @@ static void _RelocateGraphNodePointers(struct GraphNode *aHead, u64 aOffset) {
} while (_Node != aHead);
}
static Array<Pair<void *, void *>> sLoadedGraphNodes = {};
// DO NOT COMMIT:
// need to separate pools into one that will be free'd and one that wont be and when
void *DynOS_Geo_GetGraphNode(const void *aGeoLayout, bool aKeepInMemory) {
if (aKeepInMemory) {
s32 _LoadedGraphNodeIndex = sLoadedGraphNodes.FindIf([&aGeoLayout](const Pair<void *, void *> &aLoadedGraphNode) { return aLoadedGraphNode.first == aGeoLayout; });
if (_LoadedGraphNodeIndex != -1) {
return sLoadedGraphNodes[_LoadedGraphNodeIndex].second;
}
}
// Process the geo layout on a large pool of memory (16 MB)
struct AllocOnlyPool *_Pool = alloc_only_pool_init();
void *_Processed = process_geo_layout(_Pool, (void *) aGeoLayout);
// Copy the graph node data to the minimum amount of memory needed
if (_Processed && _Pool->usedSpace != 0) {
/*struct GraphNode *_Node = (struct GraphNode *) calloc(1, _Pool->usedSpace);
memcpy(_Node, _Pool->startPtr, _Pool->usedSpace);
// Relocate all graph pointers
u64 _Offset = (u64) _Node - (u64) _Pool->startPtr;
_RelocateGraphNodePointers(_Node, _Offset);*/
// Add it to loaded graph nodes
if (aKeepInMemory || true) { // DO NOT COMMIT
//sLoadedGraphNodes.Add({ (void *) aGeoLayout, (void *) _Node });
sLoadedGraphNodes.Add({ (void *) aGeoLayout, (void *) _Processed });
}
return _Processed;
} else {
alloc_only_pool_free(_Pool);
}
return NULL;
}
//
// Scroll Targets
//

View file

@ -48,8 +48,8 @@ GeoLayoutCommandProc GeoLayoutJumpTable[] = {
};
struct GraphNode gObjParentGraphNode;
struct AllocOnlyPool *gGraphNodePool;
struct GraphNode *gCurRootGraphNode;
struct AllocOnlyPool *gGraphNodePool = NULL;
struct GraphNode *gCurRootGraphNode = NULL;
UNUSED s32 D_8038BCA8;

View file

@ -399,6 +399,7 @@ static void level_cmd_alloc_level_pool(void) {
alloc_only_pool_free(sLevelPool);
sLevelPool = NULL;
}
dynos_model_clear_pool(MODEL_POOL_LEVEL);
// allocate new level pool
if (sLevelPool == NULL) {
@ -432,8 +433,7 @@ static void level_cmd_begin_area(void) {
void *geoLayoutAddr = CMD_GET(void *, 4);
if (areaIndex < 8) {
struct GraphNodeRoot *screenArea =
(struct GraphNodeRoot *) process_geo_layout(sLevelPool, geoLayoutAddr);
struct GraphNodeRoot *screenArea = (struct GraphNodeRoot *) dynos_model_load_geo(MODEL_POOL_LEVEL, geoLayoutAddr);
struct GraphNodeCamera *node = (struct GraphNodeCamera *) screenArea->views[0];
sCurrAreaIndex = areaIndex;
@ -464,7 +464,7 @@ static void level_cmd_load_model_from_dl(void) {
void *val3 = CMD_GET(void *, 4);
if (val1 < MAX_LOADED_GRAPH_NODES) {
gLoadedGraphNodes[val1] = (struct GraphNode *) init_graph_node_display_list(sLevelPool, 0, val2, val3);
gLoadedGraphNodes[val1] = dynos_model_load_dl(sFinishedLoadingPerm ? MODEL_POOL_LEVEL : MODEL_POOL_PERMANENT, val2, val3);
if (sFinishedLoadingPerm) { sLevelOwnedGraphNodes[val1] = true; }
smlua_model_util_remember(val1, val2, val3, 1);
}
@ -477,7 +477,7 @@ static void level_cmd_load_model_from_geo(void) {
void *arg1 = CMD_GET(void *, 4);
if (arg0 < MAX_LOADED_GRAPH_NODES) {
gLoadedGraphNodes[arg0] = process_geo_layout(sLevelPool, arg1);
gLoadedGraphNodes[arg0] = dynos_model_load_geo(sFinishedLoadingPerm ? MODEL_POOL_LEVEL : MODEL_POOL_PERMANENT, arg1);
if (sFinishedLoadingPerm) { sLevelOwnedGraphNodes[arg0] = true; }
smlua_model_util_remember(arg0, LAYER_OPAQUE, arg1, 0);
}
@ -1032,7 +1032,7 @@ static void level_cmd_place_object_ext2(void) {
spawnInfo->behaviorArg = CMD_GET(u32, 16);
spawnInfo->behaviorScript = (BehaviorScript*)get_behavior_from_id(behId);
u16 slot = smlua_model_util_load_with_pool(modelId, sLevelPool);
u16 slot = smlua_model_util_load_with_pool(modelId, MODEL_POOL_LEVEL);
if (slot >= MAX_LOADED_GRAPH_NODES) { slot = MODEL_NONE; }
spawnInfo->unk18 = gLoadedGraphNodes[slot];
spawnInfo->next = gAreas[sCurrAreaIndex].objectSpawnInfos;
@ -1055,7 +1055,7 @@ static void level_cmd_load_model_from_geo_ext(void) {
u32 modelId = smlua_model_util_get_id(geoName);
if (modelSlot < MAX_LOADED_GRAPH_NODES) {
smlua_model_util_load_with_pool_and_cache_id(modelId, sLevelPool, modelSlot);
smlua_model_util_load_with_pool_and_cache_id(modelId, MODEL_POOL_LEVEL, modelSlot);
}
sCurrentCmd = CMD_NEXT;

View file

@ -351,20 +351,6 @@ void mem_pool_free(struct MemoryPool *pool, void *addr) {
}
}
void *alloc_display_list(u32 size) {
void *ptr = NULL;
size = ALIGN8(size);
if (gGfxPoolEnd - size >= (u8 *) gDisplayListHead) {
gGfxPoolEnd -= size;
ptr = gGfxPoolEnd;
memset(ptr, 0, size);
} else {
LOG_ERROR("Failed to allocate display list of size 0x%X!", size);
}
return ptr;
}
static struct MarioAnimDmaRelatedThing *func_802789F0(u8 *srcAddr) {
struct MarioAnimDmaRelatedThing *sp1C = dynamic_dma_read(srcAddr, srcAddr + sizeof(u32),
MEMORY_POOL_LEFT);

View file

@ -56,7 +56,6 @@ u32 main_pool_pop_state(void);
struct AllocOnlyPool* alloc_only_pool_init(void);
void* alloc_only_pool_alloc(struct AllocOnlyPool *pool, u32 size);
struct AllocOnlyPool* alloc_only_pool_resize(struct AllocOnlyPool *pool, u32 size);
void alloc_only_pool_free(struct AllocOnlyPool *pool);
struct MemoryPool *mem_pool_init(u32 size, u32 side);

View file

@ -1,18 +1,6 @@
#include <PR/ultratypes.h>
#include <string.h>
#include "sm64.h"
#define INCLUDED_FROM_MEMORY_C
#include "buffers/buffers.h"
#include "decompress.h"
#include "game_init.h"
#include "main.h"
#include "memory.h"
#include "segment_symbols.h"
#include "segments.h"
#include "pc/debuglog.h"
#include "rendering_graph_node.h"
struct AllocOnlyPool* alloc_only_pool_init(void) {
struct AllocOnlyPool* pool = calloc(1, sizeof(struct AllocOnlyPool));
@ -22,6 +10,8 @@ struct AllocOnlyPool* alloc_only_pool_init(void) {
}
void* alloc_only_pool_alloc(struct AllocOnlyPool *pool, u32 size) {
if (!pool) { return NULL; }
struct AllocOnlyNode* node = calloc(1, sizeof(struct AllocOnlyNode));
node->ptr = calloc(1, size);
node->prev = pool->tail;
@ -32,11 +22,8 @@ void* alloc_only_pool_alloc(struct AllocOnlyPool *pool, u32 size) {
return node->ptr;
}
struct AllocOnlyPool* alloc_only_pool_resize(UNUSED struct AllocOnlyPool* pool, UNUSED u32 size) {
return NULL;
}
void alloc_only_pool_free(struct AllocOnlyPool *pool) {
if (!pool) { return; }
struct AllocOnlyNode* node = pool->tail;
while (node) {
struct AllocOnlyNode* prev = node->prev;
@ -46,3 +33,7 @@ void alloc_only_pool_free(struct AllocOnlyPool *pool) {
}
free(pool);
}
void *alloc_display_list(u32 size) {
return alloc_only_pool_alloc(gDisplayListHeap, size);
}

View file

@ -1620,11 +1620,12 @@ void geo_process_root(struct GraphNodeRoot *node, Vp *b, Vp *c, s32 clearColor)
geo_clear_interp_variables();
if (node->node.flags & GRAPH_RENDER_ACTIVE) {
if (gDisplayListHeap) { alloc_only_pool_free(gDisplayListHeap); }
gDisplayListHeap = alloc_only_pool_init();
Vp *viewport = alloc_display_list(sizeof(*viewport));
if (viewport == NULL) { return; }
gDisplayListHeap = alloc_only_pool_init();
Mtx *initialMatrix = alloc_display_list(sizeof(*initialMatrix));
if (initialMatrix == NULL) { return; }
@ -1668,6 +1669,5 @@ void geo_process_root(struct GraphNodeRoot *node, Vp *b, Vp *c, s32 clearColor)
//if (gShowDebugText) {
// print_text_fmt_int(180, 36, "MEM %d", gDisplayListHeap->totalSpace - gDisplayListHeap->usedSpace);
//}
alloc_only_pool_free(gDisplayListHeap);
}
}

View file

@ -9,6 +9,7 @@ extern f32 gProjectionMaxNearValue;
extern s16 gProjectionVanillaNearValue;
extern s16 gProjectionVanillaFarValue;
extern struct AllocOnlyPool *gDisplayListHeap;
extern struct GraphNodeRoot *gCurGraphNodeRoot;
extern struct GraphNodeMasterList *gCurGraphNodeMasterList;
extern struct GraphNodePerspective *gCurGraphNodeCamFrustum;

View file

@ -548,12 +548,7 @@ void smlua_model_util_clear(void) {
//LOG_INFO("Cleared runtime model cache.");
}
// DO NOT COMMIT
// smlua_model_util_load_with_pool_and_cache_id() needs to be reworked to use dynamic pools correctly
// DO NOT COMMIT
u16 smlua_model_util_load_with_pool_and_cache_id(enum ModelExtendedId extId, struct AllocOnlyPool* pool, u16 loadedId) {
u16 smlua_model_util_load_with_pool_and_cache_id(enum ModelExtendedId extId, enum ModelPool pool, u16 loadedId) {
if (extId == E_MODEL_NONE) { return MODEL_NONE; }
if (extId >= (u16)(E_MODEL_MAX + sCustomModelsCount)) {
LOG_ERROR("Tried to load invalid extId: %u >= %u (%u)", extId, (E_MODEL_MAX + sCustomModelsCount), sCustomModelsCount);
@ -596,52 +591,27 @@ u16 smlua_model_util_load_with_pool_and_cache_id(enum ModelExtendedId extId, str
}
// load
bool resizePool = false;
if (pool == NULL) {
pool = alloc_only_pool_init();
resizePool = true;
}
info->shouldFreeAsset = false;
if (pool != NULL) {
if (info->isDisplayList) {
gLoadedGraphNodes[pickLoadedId] = (struct GraphNode *) init_graph_node_display_list(pool, NULL, info->layer, (void*)info->asset);
} else {
gLoadedGraphNodes[pickLoadedId] = process_geo_layout(pool, (void*)info->asset);
}
if (resizePool) {
alloc_only_pool_resize(pool, pool->usedSpace);
}
}
// If no pool is available, use DynOS to generate the graph node
else {
// Turn the display list into a geo layout
if (info->isDisplayList) {
const GeoLayout displayListToGeoLayout[] = { GEO_NODE_START(), GEO_DISPLAY_LIST(info->layer, info->asset), GEO_END() };
info->asset = memcpy(calloc(1, sizeof(displayListToGeoLayout)), displayListToGeoLayout, sizeof(displayListToGeoLayout));
info->shouldFreeAsset = true;
info->isDisplayList = false;
}
gLoadedGraphNodes[pickLoadedId] = dynos_geolayout_to_graphnode(info->asset, true);
LOG_ERROR("Out of memory in the main pool - using dynos");
}
struct GraphNode* node = NULL;
node = (info->isDisplayList)
? dynos_model_load_dl(pool, info->layer, (void*)info->asset)
: dynos_model_load_geo(pool, (void*) info->asset);
gLoadedGraphNodes[pickLoadedId] = node;
// remember
if (node) {
smlua_model_util_remember(pickLoadedId, info->layer, info->asset, info->isDisplayList);
}
//LOG_INFO("Loaded custom model - %u -> %u", extId, pickLoadedId);
return pickLoadedId;
}
u16 smlua_model_util_load_with_pool(enum ModelExtendedId extId, struct AllocOnlyPool* pool) {
u16 smlua_model_util_load_with_pool(enum ModelExtendedId extId, enum ModelPool pool) {
return smlua_model_util_load_with_pool_and_cache_id(extId, pool, UNLOADED_ID);
}
u16 smlua_model_util_load(enum ModelExtendedId extId) {
return smlua_model_util_load_with_pool(extId, NULL);
return smlua_model_util_load_with_pool(extId, MODEL_POOL_SESSION);
}
u32 smlua_model_util_get_id(const char* name) {

View file

@ -398,8 +398,8 @@ enum ModelExtendedId {
void smlua_model_util_remember(u16 loadedId, u8 layer, const void* asset, u8 isDisplayList);
void smlua_model_util_reset(void);
void smlua_model_util_clear(void);
u16 smlua_model_util_load_with_pool_and_cache_id(enum ModelExtendedId extId, struct AllocOnlyPool* pool, u16 loadedId);
u16 smlua_model_util_load_with_pool(enum ModelExtendedId extId, struct AllocOnlyPool* pool);
u16 smlua_model_util_load_with_pool_and_cache_id(enum ModelExtendedId extId, enum ModelPool pool, u16 loadedId);
u16 smlua_model_util_load_with_pool(enum ModelExtendedId extId, enum ModelPool pool);
u16 smlua_model_util_load(enum ModelExtendedId extId);
u32 smlua_model_util_get_id(const char* name);

View file

@ -613,6 +613,8 @@ void network_shutdown(bool sendLeaving, bool exiting, bool popup, bool reconnect
gNetworkType = NT_NONE;
}
dynos_model_clear_pool(MODEL_POOL_SESSION);
if (exiting) { return; }
// reset other stuff