From d8d1388ec68acfb8bc1f0c0b8e977b4f3c824930 Mon Sep 17 00:00:00 2001 From: Emill Date: Sun, 15 May 2022 21:32:05 +0200 Subject: [PATCH] Optimize away memory allocations (#340) --- libultraship/libultraship/Archive.cpp | 9 ++-- libultraship/libultraship/Archive.h | 6 +-- .../libultraship/Lib/Fast3D/gfx_pc.cpp | 14 +++--- libultraship/libultraship/Resource.cpp | 7 ++- libultraship/libultraship/ResourceMgr.cpp | 48 +++++++++++-------- libultraship/libultraship/ResourceMgr.h | 12 +++-- libultraship/libultraship/Window.cpp | 39 ++++++++------- 7 files changed, 74 insertions(+), 61 deletions(-) diff --git a/libultraship/libultraship/Archive.cpp b/libultraship/libultraship/Archive.cpp index 1e8f8d597..e4646c305 100644 --- a/libultraship/libultraship/Archive.cpp +++ b/libultraship/libultraship/Archive.cpp @@ -204,7 +204,7 @@ namespace Ship { return true; } - std::vector Archive::ListFiles(const std::string& searchMask) { + std::vector Archive::ListFiles(const std::string& searchMask) const { auto fileList = std::vector(); SFILE_FIND_DATA findContext; HANDLE hFind; @@ -248,7 +248,7 @@ namespace Ship { return fileList; } - bool Archive::HasFile(const std::string& filename) { + bool Archive::HasFile(const std::string& filename) const { bool result = false; auto start = std::chrono::steady_clock::now(); @@ -267,8 +267,9 @@ namespace Ship { return result; } - std::string Archive::HashToString(uint64_t hash) { - return hashes[hash]; + const std::string* Archive::HashToString(uint64_t hash) const { + auto it = hashes.find(hash); + return it != hashes.end() ? &it->second : nullptr; } bool Archive::Load(bool enableWriting, bool genCRCMap) { diff --git a/libultraship/libultraship/Archive.h b/libultraship/libultraship/Archive.h index f8fe3e0fd..b21ad9c73 100644 --- a/libultraship/libultraship/Archive.h +++ b/libultraship/libultraship/Archive.h @@ -34,9 +34,9 @@ namespace Ship bool AddFile(const std::string& path, uintptr_t fileData, DWORD dwFileSize); bool RemoveFile(const std::string& path); bool RenameFile(const std::string& oldPath, const std::string& newPath); - std::vector ListFiles(const std::string& searchMask); - bool HasFile(const std::string& searchMask); - std::string HashToString(uint64_t hash); + std::vector ListFiles(const std::string& searchMask) const; + bool HasFile(const std::string& searchMask) const; + const std::string* HashToString(uint64_t hash) const; protected: bool Load(bool enableWriting, bool genCRCMap); bool Unload(); diff --git a/libultraship/libultraship/Lib/Fast3D/gfx_pc.cpp b/libultraship/libultraship/Lib/Fast3D/gfx_pc.cpp index c1a130b19..6738f28fa 100644 --- a/libultraship/libultraship/Lib/Fast3D/gfx_pc.cpp +++ b/libultraship/libultraship/Lib/Fast3D/gfx_pc.cpp @@ -36,7 +36,7 @@ // OTRTODO: fix header files for these extern "C" { - char* ResourceMgr_GetNameByCRC(uint64_t crc, char* alloc); + const char* ResourceMgr_GetNameByCRC(uint64_t crc); int32_t* ResourceMgr_LoadMtxByCRC(uint64_t crc); Vtx* ResourceMgr_LoadVtxByCRC(uint64_t crc); Gfx* ResourceMgr_LoadGfxByCRC(uint64_t crc); @@ -134,14 +134,14 @@ static struct RDP { const uint8_t *addr; uint8_t siz; uint32_t width; - char* otr_path; + const char* otr_path; } texture_to_load; struct { const uint8_t *addr; uint32_t size_bytes; uint32_t full_image_line_size_bytes; uint32_t line_size_bytes; - char* otr_path; + const char* otr_path; } loaded_texture[2]; struct { uint8_t fmt; @@ -1636,11 +1636,11 @@ static void gfx_dp_set_scissor(uint32_t mode, uint32_t ulx, uint32_t uly, uint32 rdp.viewport_or_scissor_changed = true; } -static void gfx_dp_set_texture_image(uint32_t format, uint32_t size, uint32_t width, const void* addr, char* otr_path) { +static void gfx_dp_set_texture_image(uint32_t format, uint32_t size, uint32_t width, const void* addr, const char* otr_path) { rdp.texture_to_load.addr = (const uint8_t*)addr; rdp.texture_to_load.siz = size; rdp.texture_to_load.width = width; - if ( otr_path != nullptr && !strncmp(otr_path, "__OTR__", 7)) otr_path = otr_path + 7; + if (otr_path != nullptr && !strncmp(otr_path, "__OTR__", 7)) otr_path = otr_path + 7; rdp.texture_to_load.otr_path = otr_path; } @@ -2114,7 +2114,7 @@ static void gfx_run_dl(Gfx* cmd) { //puts("dl"); int dummy = 0; char dlName[128]; - char fileName[128]; + const char* fileName; Gfx* dListStart = cmd; uint64_t ourHash = -1; @@ -2437,7 +2437,7 @@ static void gfx_run_dl(Gfx* cmd) { uintptr_t addr = cmd->words.w1; cmd++; uint64_t hash = ((uint64_t)cmd->words.w0 << 32) + (uint64_t)cmd->words.w1; - ResourceMgr_GetNameByCRC(hash, fileName); + fileName = ResourceMgr_GetNameByCRC(hash); #if _DEBUG && 0 char* tex = ResourceMgr_LoadTexByCRC(hash); ResourceMgr_GetNameByCRC(hash, fileName); diff --git a/libultraship/libultraship/Resource.cpp b/libultraship/libultraship/Resource.cpp index 04fc2bfbb..66a1f4199 100644 --- a/libultraship/libultraship/Resource.cpp +++ b/libultraship/libultraship/Resource.cpp @@ -40,8 +40,11 @@ namespace Ship for (size_t i = 0; i < patches.size(); i++) { - std::string hashStr = resMgr->HashToString(patches[i].crc); - auto resShared = resMgr->GetCachedFile(hashStr); + const std::string* hashStr = resMgr->HashToString(patches[i].crc); + if (hashStr == nullptr) + continue; + + auto resShared = resMgr->GetCachedFile(hashStr->c_str()); if (resShared != nullptr) { auto res = (Ship::DisplayList*)resShared.get(); diff --git a/libultraship/libultraship/ResourceMgr.cpp b/libultraship/libultraship/ResourceMgr.cpp index de0296d12..0033ef442 100644 --- a/libultraship/libultraship/ResourceMgr.cpp +++ b/libultraship/libultraship/ResourceMgr.cpp @@ -215,7 +215,7 @@ namespace Ship { return ToLoad; } - std::shared_ptr ResourceMgr::GetCachedFile(std::string FilePath) { + std::shared_ptr ResourceMgr::GetCachedFile(const char* FilePath) const { auto resCacheFind = ResourceCache.find(FilePath); if (resCacheFind != ResourceCache.end() && @@ -227,8 +227,13 @@ namespace Ship { return nullptr; } - std::shared_ptr ResourceMgr::LoadResource(std::string FilePath) { - auto Promise = LoadResourceAsync(FilePath); + std::shared_ptr ResourceMgr::LoadResource(const char* FilePath) { + auto Res = LoadResourceAsync(FilePath); + + if (std::holds_alternative>(Res)) + return std::get>(Res); + + auto& Promise = std::get>(Res); if (!Promise->bHasResourceLoaded) { @@ -241,21 +246,18 @@ namespace Ship { return Promise->resource; } - std::shared_ptr ResourceMgr::LoadResourceAsync(std::string FilePath) { - StringHelper::ReplaceOriginal(FilePath, "\\", "/"); - - if (StringHelper::StartsWith(FilePath, "__OTR__")) - FilePath = StringHelper::Split(FilePath, "__OTR__")[1]; - - std::shared_ptr Promise = std::make_shared(); + std::variant, std::shared_ptr> ResourceMgr::LoadResourceAsync(const char* FilePath) { + if (FilePath[0] == '_' && FilePath[1] == '_' && FilePath[2] == 'O' && FilePath[3] == 'T' && FilePath[4] == 'R' && FilePath[5] == '_' && FilePath[6] == '_') + FilePath += 7; const std::lock_guard ResLock(ResourceLoadMutex); auto resCacheFind = ResourceCache.find(FilePath); if (resCacheFind == ResourceCache.end() || resCacheFind->second->isDirty/* || !FileData->bIsLoaded*/) { if (resCacheFind == ResourceCache.end()) { - SPDLOG_TRACE("Cache miss on Resource load: {}", FilePath.c_str()); + SPDLOG_TRACE("Cache miss on Resource load: {}", FilePath); } + std::shared_ptr Promise = std::make_shared(); std::shared_ptr FileData = LoadFile(FilePath); Promise->file = FileData; @@ -269,12 +271,13 @@ namespace Ship { ResourceLoadQueue.push(Promise); ResourceLoadNotifier.notify_all(); } - } else { - Promise->bHasResourceLoaded = true; - Promise->resource = resCacheFind->second; - } - return Promise; + return Promise; + } + else + { + return resCacheFind->second; + } } std::shared_ptr>> ResourceMgr::CacheDirectoryAsync(std::string SearchMask) { @@ -282,10 +285,15 @@ namespace Ship { auto fileList = OTR->ListFiles(SearchMask); for (DWORD i = 0; i < fileList.size(); i++) { - auto file = LoadResourceAsync(fileList.operator[](i).cFileName); - if (file != nullptr) { - loadedList->push_back(file); + auto resource = LoadResourceAsync(fileList.operator[](i).cFileName); + if (std::holds_alternative>(resource)) + { + auto promise = std::make_shared(); + promise->bHasResourceLoaded = true; + promise->resource = std::get>(resource); + resource = promise; } + loadedList->push_back(std::get>(resource)); } return loadedList; @@ -335,7 +343,7 @@ namespace Ship { ResourceCache.clear(); } - std::string ResourceMgr::HashToString(uint64_t Hash) { + const std::string* ResourceMgr::HashToString(uint64_t Hash) const { return OTR->HashToString(Hash); } } \ No newline at end of file diff --git a/libultraship/libultraship/ResourceMgr.h b/libultraship/libultraship/ResourceMgr.h index 28e77e537..e76d5b521 100644 --- a/libultraship/libultraship/ResourceMgr.h +++ b/libultraship/libultraship/ResourceMgr.h @@ -4,6 +4,7 @@ #include #include #include +#include #include "Resource.h" #include "GlobalCtx2.h" @@ -25,7 +26,7 @@ namespace Ship std::shared_ptr GetArchive() { return OTR; } std::shared_ptr GetContext() { return Context.lock(); } - std::string HashToString(uint64_t Hash); + const std::string* HashToString(uint64_t Hash) const; void InvalidateResourceCache(); @@ -33,9 +34,10 @@ namespace Ship void SetGameVersion(uint32_t newGameVersion); std::shared_ptr LoadFileAsync(std::string FilePath); std::shared_ptr LoadFile(std::string FilePath); - std::shared_ptr GetCachedFile(std::string FilePath); - std::shared_ptr LoadResource(std::string FilePath); - std::shared_ptr LoadResourceAsync(std::string FilePath); + std::shared_ptr GetCachedFile(const char* FilePath) const; + std::shared_ptr LoadResource(const char* FilePath); + std::shared_ptr LoadResource(const std::string& FilePath) { return LoadResource(FilePath.c_str()); } + std::variant, std::shared_ptr> LoadResourceAsync(const char* FilePath); std::shared_ptr>> CacheDirectory(std::string SearchMask); std::shared_ptr>> CacheDirectoryAsync(std::string SearchMask); std::shared_ptr>> DirtyDirectory(std::string SearchMask); @@ -50,7 +52,7 @@ namespace Ship std::weak_ptr Context; volatile bool bIsRunning; std::map> FileCache; - std::map> ResourceCache; + std::map, std::less<>> ResourceCache; std::queue> FileLoadQueue; std::queue> ResourceLoadQueue; std::shared_ptr OTR; diff --git a/libultraship/libultraship/Window.cpp b/libultraship/libultraship/Window.cpp index 588e3af50..bbd906c76 100644 --- a/libultraship/libultraship/Window.cpp +++ b/libultraship/libultraship/Window.cpp @@ -119,17 +119,16 @@ extern "C" { ModInternal::callBindHook(0); } - char* ResourceMgr_GetNameByCRC(uint64_t crc, char* alloc) { - std::string hashStr = Ship::GlobalCtx2::GetInstance()->GetResourceManager()->HashToString(crc); - strcpy(alloc, hashStr.c_str()); - return (char*)hashStr.c_str(); + const char* ResourceMgr_GetNameByCRC(uint64_t crc) { + const std::string* hashStr = Ship::GlobalCtx2::GetInstance()->GetResourceManager()->HashToString(crc); + return hashStr != nullptr ? hashStr->c_str() : nullptr; } Vtx* ResourceMgr_LoadVtxByCRC(uint64_t crc) { - std::string hashStr = Ship::GlobalCtx2::GetInstance()->GetResourceManager()->HashToString(crc); + const std::string* hashStr = Ship::GlobalCtx2::GetInstance()->GetResourceManager()->HashToString(crc); - if (hashStr != "") { - auto res = std::static_pointer_cast(Ship::GlobalCtx2::GetInstance()->GetResourceManager()->LoadResource(hashStr)); + if (hashStr != nullptr) { + auto res = std::static_pointer_cast(Ship::GlobalCtx2::GetInstance()->GetResourceManager()->LoadResource(hashStr->c_str())); //if (res != nullptr) return (Vtx*)res->vertices.data(); @@ -142,10 +141,10 @@ extern "C" { } int32_t* ResourceMgr_LoadMtxByCRC(uint64_t crc) { - std::string hashStr = Ship::GlobalCtx2::GetInstance()->GetResourceManager()->HashToString(crc); + const std::string* hashStr = Ship::GlobalCtx2::GetInstance()->GetResourceManager()->HashToString(crc); - if (hashStr != "") { - auto res = std::static_pointer_cast(Ship::GlobalCtx2::GetInstance()->GetResourceManager()->LoadResource(hashStr)); + if (hashStr != nullptr) { + auto res = std::static_pointer_cast(Ship::GlobalCtx2::GetInstance()->GetResourceManager()->LoadResource(hashStr->c_str())); return (int32_t*)res->mtx.data(); } else { return nullptr; @@ -153,10 +152,10 @@ extern "C" { } Gfx* ResourceMgr_LoadGfxByCRC(uint64_t crc) { - std::string hashStr = Ship::GlobalCtx2::GetInstance()->GetResourceManager()->HashToString(crc); + const std::string* hashStr = Ship::GlobalCtx2::GetInstance()->GetResourceManager()->HashToString(crc); - if (hashStr != "") { - auto res = std::static_pointer_cast(Ship::GlobalCtx2::GetInstance()->GetResourceManager()->LoadResource(hashStr)); + if (hashStr != nullptr) { + auto res = std::static_pointer_cast(Ship::GlobalCtx2::GetInstance()->GetResourceManager()->LoadResource(hashStr->c_str())); return (Gfx*)&res->instructions[0]; } else { return nullptr; @@ -164,14 +163,14 @@ extern "C" { } char* ResourceMgr_LoadTexByCRC(uint64_t crc) { - const std::string hashStr = Ship::GlobalCtx2::GetInstance()->GetResourceManager()->HashToString(crc); + const std::string* hashStr = Ship::GlobalCtx2::GetInstance()->GetResourceManager()->HashToString(crc); - if (!hashStr.empty()) { - const auto res = static_cast(Ship::GlobalCtx2::GetInstance()->GetResourceManager()->LoadResource(hashStr).get()); + if (hashStr != nullptr) { + const auto res = static_cast(Ship::GlobalCtx2::GetInstance()->GetResourceManager()->LoadResource(hashStr->c_str()).get()); ModInternal::bindHook(LOAD_TEXTURE); ModInternal::initBindHook(2, - HookParameter({.name = "path", .parameter = (void*)hashStr.c_str() }), + HookParameter({.name = "path", .parameter = (void*)hashStr->c_str() }), HookParameter({.name = "texture", .parameter = static_cast(&res->imageData) }) ); ModInternal::callBindHook(0); @@ -184,11 +183,11 @@ extern "C" { void ResourceMgr_RegisterResourcePatch(uint64_t hash, uint32_t instrIndex, uintptr_t origData) { - std::string hashStr = Ship::GlobalCtx2::GetInstance()->GetResourceManager()->HashToString(hash); + const std::string* hashStr = Ship::GlobalCtx2::GetInstance()->GetResourceManager()->HashToString(hash); - if (hashStr != "") + if (hashStr != nullptr) { - auto res = (Ship::Texture*)Ship::GlobalCtx2::GetInstance()->GetResourceManager()->LoadResource(hashStr).get(); + auto res = (Ship::Texture*)Ship::GlobalCtx2::GetInstance()->GetResourceManager()->LoadResource(hashStr->c_str()).get(); Ship::Patch patch; patch.crc = hash;