From 5b3a266a40ec294a9a8f31a65a6832c455d597d2 Mon Sep 17 00:00:00 2001 From: datacrystals Date: Sat, 17 Sep 2022 21:19:45 +0000 Subject: [PATCH 01/19] Fix Texture Budgeting Subsystem --- .../Loader/ERS_ModelLoader/ERS_CLASS_AsyncTextureUpdater.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Source/Core/Loader/ERS_ModelLoader/ERS_CLASS_AsyncTextureUpdater.cpp b/Source/Core/Loader/ERS_ModelLoader/ERS_CLASS_AsyncTextureUpdater.cpp index 39d89603c0..88223b0f74 100644 --- a/Source/Core/Loader/ERS_ModelLoader/ERS_CLASS_AsyncTextureUpdater.cpp +++ b/Source/Core/Loader/ERS_ModelLoader/ERS_CLASS_AsyncTextureUpdater.cpp @@ -60,6 +60,9 @@ bool ERS_CLASS_AsyncTextureUpdater::LoadImageDataRAM(ERS_STRUCT_Texture* Texture } else if (Level > (int)Texture->TextureLevels.size()) { SystemUtils_->Logger_->Log("Texture Updater Tried To Load Nonexistant Texture Level", 8, LogEnable); return false; + } else if (!ResourceMonitor_->TextureFitsInRAMBudget(Texture->TextureLevels[Level].LevelMemorySizeBytes)) { + SystemUtils_->Logger_->Log("Cannot Load Texture Into Memory, Will Not Fit In RAM Budget", 6); + return false; } // Check If Level Already Loaded From c5fedaa2d6e27868139d609f35d2d199918cbb4e Mon Sep 17 00:00:00 2001 From: datacrystals Date: Sat, 17 Sep 2022 21:20:14 +0000 Subject: [PATCH 02/19] Fix Texture Budgeting Subsystem --- .../Loader/ERS_ModelLoader/ERS_CLASS_AsyncTextureUpdater.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Source/Core/Loader/ERS_ModelLoader/ERS_CLASS_AsyncTextureUpdater.cpp b/Source/Core/Loader/ERS_ModelLoader/ERS_CLASS_AsyncTextureUpdater.cpp index 88223b0f74..97a750df5a 100644 --- a/Source/Core/Loader/ERS_ModelLoader/ERS_CLASS_AsyncTextureUpdater.cpp +++ b/Source/Core/Loader/ERS_ModelLoader/ERS_CLASS_AsyncTextureUpdater.cpp @@ -202,6 +202,9 @@ bool ERS_CLASS_AsyncTextureUpdater::LoadImageDataVRAM(ERS_STRUCT_Texture* Textur } else if (Level > (int)Texture->TextureLevels.size()) { SystemUtils_->Logger_->Log("Texture Updater Tried To Load Nonexistant Texture Level Into VRAM", 8, LogEnable); return false; + } else if (!ResourceMonitor_->TextureFitsInVRAMBudget(Texture->TextureLevels[Level].LevelMemorySizeBytes)) { + SystemUtils_->Logger_->Log("Cannot Load Texture Into Memory, Will Not Fit In VRAM Budget", 6); + return false; } // Check If Level Already Loaded From f1f7bf03d61ae0a42aface69ea9fd7202dd3581c Mon Sep 17 00:00:00 2001 From: datacrystals Date: Sat, 17 Sep 2022 21:35:05 +0000 Subject: [PATCH 03/19] Fix Texture Budgeting Subsystem --- .../ERS_CLASS_AsyncTextureUpdater.cpp | 27 ++++++++++++++++--- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/Source/Core/Loader/ERS_ModelLoader/ERS_CLASS_AsyncTextureUpdater.cpp b/Source/Core/Loader/ERS_ModelLoader/ERS_CLASS_AsyncTextureUpdater.cpp index 97a750df5a..39868d2b81 100644 --- a/Source/Core/Loader/ERS_ModelLoader/ERS_CLASS_AsyncTextureUpdater.cpp +++ b/Source/Core/Loader/ERS_ModelLoader/ERS_CLASS_AsyncTextureUpdater.cpp @@ -71,6 +71,10 @@ bool ERS_CLASS_AsyncTextureUpdater::LoadImageDataRAM(ERS_STRUCT_Texture* Texture } + // Allocate Memory From Budget + ResourceMonitor_->AllocateTextureRAMFromBudget(Texture->TextureLevels[Level].LevelMemorySizeBytes); + + // Load Image Data ERS_STRUCT_IOData ImageData; long LevelAssetID = Texture->TextureLevels[Level].LevelTextureAssetID; @@ -91,6 +95,7 @@ bool ERS_CLASS_AsyncTextureUpdater::LoadImageDataRAM(ERS_STRUCT_Texture* Texture + "' Width Is <1", 8, LogEnable); FreeImage_Unload(RawImage); FreeImage_CloseMemory(FIImageData); + ResourceMonitor_->DeallocateTextureRAMFromBudget(Texture->TextureLevels[Level].LevelMemorySizeBytes); return false; } if (Height <= 0) { @@ -99,6 +104,7 @@ bool ERS_CLASS_AsyncTextureUpdater::LoadImageDataRAM(ERS_STRUCT_Texture* Texture + "' Height Is <1", 8, LogEnable); FreeImage_Unload(RawImage); FreeImage_CloseMemory(FIImageData); + ResourceMonitor_->DeallocateTextureRAMFromBudget(Texture->TextureLevels[Level].LevelMemorySizeBytes); return false; } @@ -125,6 +131,7 @@ bool ERS_CLASS_AsyncTextureUpdater::LoadImageDataRAM(ERS_STRUCT_Texture* Texture + "', Level '" + std::to_string(Level) + "' With ID '" + std::to_string(LevelAssetID) + "' Width Does Not Match Metadata Target", 8, LogEnable); FreeImage_Unload(Image); + ResourceMonitor_->DeallocateTextureRAMFromBudget(Texture->TextureLevels[Level].LevelMemorySizeBytes); return false; } if ((TargetWidthHeight.second != Height) && (TargetWidthHeight.second != -1)) { @@ -132,6 +139,7 @@ bool ERS_CLASS_AsyncTextureUpdater::LoadImageDataRAM(ERS_STRUCT_Texture* Texture + "', Level '" + std::to_string(Level) + "' With ID '" + std::to_string(LevelAssetID) + "' Height Does Not Match Metadata Target", 8, LogEnable); FreeImage_Unload(Image); + ResourceMonitor_->DeallocateTextureRAMFromBudget(Texture->TextureLevels[Level].LevelMemorySizeBytes); return false; } @@ -142,6 +150,7 @@ bool ERS_CLASS_AsyncTextureUpdater::LoadImageDataRAM(ERS_STRUCT_Texture* Texture + "', Level '" + std::to_string(Level) + "' With ID '" + std::to_string(LevelAssetID) + "' Invalid Number Of Channels '" + std::to_string(Channels) + "'", 8, LogEnable); FreeImage_Unload(Image); + ResourceMonitor_->DeallocateTextureRAMFromBudget(Texture->TextureLevels[Level].LevelMemorySizeBytes); return false; } if ((Texture->TextureLevels[Level].LevelChannel != Channels) && (Texture->TextureLevels[Level].LevelChannel != -1)) { @@ -150,6 +159,7 @@ bool ERS_CLASS_AsyncTextureUpdater::LoadImageDataRAM(ERS_STRUCT_Texture* Texture + "' Number Channels '" + std::to_string(Channels) + "' Does Not Match Metadata Target '" + std::to_string(Texture->TextureLevels[Level].LevelChannel) + "'", 8, LogEnable); FreeImage_Unload(Image); + ResourceMonitor_->DeallocateTextureRAMFromBudget(Texture->TextureLevels[Level].LevelMemorySizeBytes); return false; } @@ -213,6 +223,10 @@ bool ERS_CLASS_AsyncTextureUpdater::LoadImageDataVRAM(ERS_STRUCT_Texture* Textur return false; } + // Allocate Budget + ResourceMonitor_->AllocateTextureVRAMFromBudget(Texture->TextureLevels[Level].LevelMemorySizeBytes); + + // Get Image Metadata, Perform Checks int MaxLevel = Texture->TextureLevels.size() - 1; int CorrectedIndex = Level; @@ -225,42 +239,49 @@ bool ERS_CLASS_AsyncTextureUpdater::LoadImageDataVRAM(ERS_STRUCT_Texture* Textur SystemUtils_->Logger_->Log(std::string("Error Loading Texture '") + Texture->Path + "', Level '" + std::to_string(Level) + "' With ID '" + std::to_string(Texture->TextureLevels[CorrectedIndex].LevelTextureAssetID) + "' Channel Count >4", 8, LogEnable); + ResourceMonitor_->DeallocateTextureVRAMFromBudget(Texture->TextureLevels[Level].LevelMemorySizeBytes); return false; } if (Channels < 1) { SystemUtils_->Logger_->Log(std::string("Error Loading Texture '") + Texture->Path + "', Level '" + std::to_string(Level) + "' With ID '" + std::to_string(Texture->TextureLevels[CorrectedIndex].LevelTextureAssetID) + "' Channel Count <1", 8, LogEnable); + ResourceMonitor_->DeallocateTextureVRAMFromBudget(Texture->TextureLevels[Level].LevelMemorySizeBytes); return false; } if (!Texture->TextureLevels[Level].LevelLoadedInRAM) { SystemUtils_->Logger_->Log(std::string("Error Loading Texture '") + Texture->Path + "', Level '" + std::to_string(Level) + "' With ID '" + std::to_string(Texture->TextureLevels[CorrectedIndex].LevelTextureAssetID) + "' Not All Prior Levels Are Loaded Into RAM", 8, LogEnable); + ResourceMonitor_->DeallocateTextureVRAMFromBudget(Texture->TextureLevels[Level].LevelMemorySizeBytes); return false; } if (MaxLevel < 0) { SystemUtils_->Logger_->Log(std::string("Error Loading Texture '") + Texture->Path + "', Level '" + std::to_string(Level) + "' With ID '" + std::to_string(Texture->TextureLevels[CorrectedIndex].LevelTextureAssetID) + "' No Levels To Load", 8, LogEnable); + ResourceMonitor_->DeallocateTextureVRAMFromBudget(Texture->TextureLevels[Level].LevelMemorySizeBytes); return false; } if (MaxWidth < 1) { SystemUtils_->Logger_->Log(std::string("Error Loading Texture '") + Texture->Path + "', Level '" + std::to_string(Level) + "' With ID '" + std::to_string(Texture->TextureLevels[CorrectedIndex].LevelTextureAssetID) + "' Width is 0", 8, LogEnable); + ResourceMonitor_->DeallocateTextureVRAMFromBudget(Texture->TextureLevels[Level].LevelMemorySizeBytes); return false; } if (MaxHeight < 1) { SystemUtils_->Logger_->Log(std::string("Error Loading Texture '") + Texture->Path + "', Level '" + std::to_string(Level) + "' With ID '" + std::to_string(Texture->TextureLevels[CorrectedIndex].LevelTextureAssetID) + "' Height is 0", 8, LogEnable); + ResourceMonitor_->DeallocateTextureVRAMFromBudget(Texture->TextureLevels[Level].LevelMemorySizeBytes); return false; } if (ImageSize < 1) { SystemUtils_->Logger_->Log(std::string("Error Loading Texture '") + Texture->Path + "', Level '" + std::to_string(Level) + "' With ID '" + std::to_string(Texture->TextureLevels[CorrectedIndex].LevelTextureAssetID) + "' Image Byte Array Has Size Of 0", 8, LogEnable); + ResourceMonitor_->DeallocateTextureVRAMFromBudget(Texture->TextureLevels[Level].LevelMemorySizeBytes); return false; } @@ -298,6 +319,8 @@ bool ERS_CLASS_AsyncTextureUpdater::LoadImageDataVRAM(ERS_STRUCT_Texture* Textur TextureInternFormat = GL_RED; TextureExternFormat = GL_RED; } else { + + ResourceMonitor_->DeallocateTextureVRAMFromBudget(Texture->TextureLevels[Level].LevelMemorySizeBytes); return false; } @@ -335,12 +358,8 @@ bool ERS_CLASS_AsyncTextureUpdater::LoadImageDataVRAM(ERS_STRUCT_Texture* Textur glDeleteBuffers(1, &PBOID); // Update Struct - long MemorySize = Texture->TextureLevels[Level].LevelMemorySizeBytes; - ResourceMonitor_->AllocateTextureVRAMFromBudget(MemorySize); Texture->TextureLevels[CorrectedIndex].LevelTextureOpenGLID = OpenGLTextureID; Texture->TextureLevels[CorrectedIndex].LevelLoadedInVRAM = true; - - return true; } bool ERS_CLASS_AsyncTextureUpdater::UnloadImageDataVRAM(ERS_STRUCT_Texture* Texture, int Level, bool LogEnable) { From 40a7c4dcf5bd6c59804f3f7247d8a468a13b807b Mon Sep 17 00:00:00 2001 From: datacrystals Date: Sat, 17 Sep 2022 21:42:19 +0000 Subject: [PATCH 04/19] Fix Texture Budgeting Subsystem --- .../Loader/ERS_ModelLoader/ERS_CLASS_AsyncTextureUpdater.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/Source/Core/Loader/ERS_ModelLoader/ERS_CLASS_AsyncTextureUpdater.cpp b/Source/Core/Loader/ERS_ModelLoader/ERS_CLASS_AsyncTextureUpdater.cpp index 39868d2b81..eb3dd4b67c 100644 --- a/Source/Core/Loader/ERS_ModelLoader/ERS_CLASS_AsyncTextureUpdater.cpp +++ b/Source/Core/Loader/ERS_ModelLoader/ERS_CLASS_AsyncTextureUpdater.cpp @@ -167,8 +167,6 @@ bool ERS_CLASS_AsyncTextureUpdater::LoadImageDataRAM(ERS_STRUCT_Texture* Texture // add error textures so that we can display the error on the model to make it easier to understand what the issue is - for example, display "Loading Error: Invalid Num Image Channels" for the above issue and add the same for the other issues. // Finally After Passing Sanity Checks, Populate Info. - long MemorySize = FreeImage_GetMemorySize(Image); - ResourceMonitor_->AllocateTextureRAMFromBudget(MemorySize); Texture->TextureLevels[Level].LevelBitmap = Image; Texture->TextureLevels[Level].LevelLoadedInRAM = true; From c134b4a350ff1c720f65108c786290861ec94d54 Mon Sep 17 00:00:00 2001 From: datacrystals Date: Sat, 17 Sep 2022 21:44:46 +0000 Subject: [PATCH 05/19] Fix Texture Budgeting Subsystem --- .../Loader/ERS_ModelLoader/ERS_CLASS_AsyncTextureUpdater.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/Source/Core/Loader/ERS_ModelLoader/ERS_CLASS_AsyncTextureUpdater.cpp b/Source/Core/Loader/ERS_ModelLoader/ERS_CLASS_AsyncTextureUpdater.cpp index eb3dd4b67c..6558695b1e 100644 --- a/Source/Core/Loader/ERS_ModelLoader/ERS_CLASS_AsyncTextureUpdater.cpp +++ b/Source/Core/Loader/ERS_ModelLoader/ERS_CLASS_AsyncTextureUpdater.cpp @@ -163,9 +163,6 @@ bool ERS_CLASS_AsyncTextureUpdater::LoadImageDataRAM(ERS_STRUCT_Texture* Texture return false; } - // fix images loading incorrectly (perhaps due to broken numbers of channels? - // add error textures so that we can display the error on the model to make it easier to understand what the issue is - for example, display "Loading Error: Invalid Num Image Channels" for the above issue and add the same for the other issues. - // Finally After Passing Sanity Checks, Populate Info. Texture->TextureLevels[Level].LevelBitmap = Image; Texture->TextureLevels[Level].LevelLoadedInRAM = true; From 6092506dd25c6b6024f4d267de7e4e8f429fa912 Mon Sep 17 00:00:00 2001 From: datacrystals Date: Sat, 17 Sep 2022 21:45:00 +0000 Subject: [PATCH 06/19] Fix Texture Budgeting Subsystem --- .../Loader/ERS_ModelLoader/ERS_CLASS_AsyncTextureUpdater.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/Source/Core/Loader/ERS_ModelLoader/ERS_CLASS_AsyncTextureUpdater.cpp b/Source/Core/Loader/ERS_ModelLoader/ERS_CLASS_AsyncTextureUpdater.cpp index 6558695b1e..1bac2968ab 100644 --- a/Source/Core/Loader/ERS_ModelLoader/ERS_CLASS_AsyncTextureUpdater.cpp +++ b/Source/Core/Loader/ERS_ModelLoader/ERS_CLASS_AsyncTextureUpdater.cpp @@ -124,7 +124,6 @@ bool ERS_CLASS_AsyncTextureUpdater::LoadImageDataRAM(ERS_STRUCT_Texture* Texture FreeImage_Unload(RawImage); FreeImage_CloseMemory(FIImageData); - std::pair TargetWidthHeight = Texture->TextureLevels[Level].LevelResolution; if ((TargetWidthHeight.first != Width) && (TargetWidthHeight.first != -1)) { SystemUtils_->Logger_->Log(std::string("Error Loading Texture '") + Texture->Path @@ -142,7 +141,6 @@ bool ERS_CLASS_AsyncTextureUpdater::LoadImageDataRAM(ERS_STRUCT_Texture* Texture ResourceMonitor_->DeallocateTextureRAMFromBudget(Texture->TextureLevels[Level].LevelMemorySizeBytes); return false; } - // Detect NumChannels if ((Channels < 1) || (Channels > 4)) { From ecc6524d15bbea0cade507e6315c03cda6ecb769 Mon Sep 17 00:00:00 2001 From: datacrystals Date: Sat, 17 Sep 2022 21:49:28 +0000 Subject: [PATCH 07/19] Fix Texture Budgeting Subsystem --- .../ERS_STRUCT_TextureLevel/ERS_STRUCT_TextureLevel.h | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/Source/Core/Structures/ERS_STRUCT_TextureLevel/ERS_STRUCT_TextureLevel.h b/Source/Core/Structures/ERS_STRUCT_TextureLevel/ERS_STRUCT_TextureLevel.h index 7292b722a0..a6527cde01 100644 --- a/Source/Core/Structures/ERS_STRUCT_TextureLevel/ERS_STRUCT_TextureLevel.h +++ b/Source/Core/Structures/ERS_STRUCT_TextureLevel/ERS_STRUCT_TextureLevel.h @@ -21,11 +21,19 @@ struct ERS_STRUCT_TextureLevel { unsigned int LevelTextureOpenGLID; /** LevelResolution; /** Date: Sat, 17 Sep 2022 21:57:34 +0000 Subject: [PATCH 08/19] Fix Texture Budgeting Subsystem --- .../Loader/ERS_ModelLoader/ERS_CLASS_AssetStreamingManager.cpp | 1 + .../ERS_STRUCT_TextureLevel/ERS_STRUCT_TextureLevel.h | 2 ++ 2 files changed, 3 insertions(+) diff --git a/Source/Core/Loader/ERS_ModelLoader/ERS_CLASS_AssetStreamingManager.cpp b/Source/Core/Loader/ERS_ModelLoader/ERS_CLASS_AssetStreamingManager.cpp index 45753a573e..df32326b93 100644 --- a/Source/Core/Loader/ERS_ModelLoader/ERS_CLASS_AssetStreamingManager.cpp +++ b/Source/Core/Loader/ERS_ModelLoader/ERS_CLASS_AssetStreamingManager.cpp @@ -138,6 +138,7 @@ void ERS_CLASS_AssetStreamingManager::SortSceneModels(std::mapTargetTextureLevelVRAM < TargetTextureLevelVRAM) { Model->TargetTextureLevelVRAM = TargetTextureLevelVRAM; + ResourceMonitor_->AllocateTextureVRAMFromBudget(TextureSizeVRAM); if (Model->TargetTextureLevelVRAM > 0) { CameraVRAMUpdates++; } diff --git a/Source/Core/Structures/ERS_STRUCT_TextureLevel/ERS_STRUCT_TextureLevel.h b/Source/Core/Structures/ERS_STRUCT_TextureLevel/ERS_STRUCT_TextureLevel.h index a6527cde01..9edf584d2e 100644 --- a/Source/Core/Structures/ERS_STRUCT_TextureLevel/ERS_STRUCT_TextureLevel.h +++ b/Source/Core/Structures/ERS_STRUCT_TextureLevel/ERS_STRUCT_TextureLevel.h @@ -26,7 +26,9 @@ struct ERS_STRUCT_TextureLevel { bool LevelLoadedInVRAM; /** LevelResolution; /** Date: Sat, 17 Sep 2022 22:07:33 +0000 Subject: [PATCH 09/19] Fix Texture Budgeting Subsystem --- .../Loader/ERS_ModelLoader/ERS_CLASS_AssetStreamingManager.cpp | 1 - .../ERS_STRUCT_TextureLevel/ERS_STRUCT_TextureLevel.h | 2 -- 2 files changed, 3 deletions(-) diff --git a/Source/Core/Loader/ERS_ModelLoader/ERS_CLASS_AssetStreamingManager.cpp b/Source/Core/Loader/ERS_ModelLoader/ERS_CLASS_AssetStreamingManager.cpp index df32326b93..45753a573e 100644 --- a/Source/Core/Loader/ERS_ModelLoader/ERS_CLASS_AssetStreamingManager.cpp +++ b/Source/Core/Loader/ERS_ModelLoader/ERS_CLASS_AssetStreamingManager.cpp @@ -138,7 +138,6 @@ void ERS_CLASS_AssetStreamingManager::SortSceneModels(std::mapTargetTextureLevelVRAM < TargetTextureLevelVRAM) { Model->TargetTextureLevelVRAM = TargetTextureLevelVRAM; - ResourceMonitor_->AllocateTextureVRAMFromBudget(TextureSizeVRAM); if (Model->TargetTextureLevelVRAM > 0) { CameraVRAMUpdates++; } diff --git a/Source/Core/Structures/ERS_STRUCT_TextureLevel/ERS_STRUCT_TextureLevel.h b/Source/Core/Structures/ERS_STRUCT_TextureLevel/ERS_STRUCT_TextureLevel.h index 9edf584d2e..a6527cde01 100644 --- a/Source/Core/Structures/ERS_STRUCT_TextureLevel/ERS_STRUCT_TextureLevel.h +++ b/Source/Core/Structures/ERS_STRUCT_TextureLevel/ERS_STRUCT_TextureLevel.h @@ -26,9 +26,7 @@ struct ERS_STRUCT_TextureLevel { bool LevelLoadedInVRAM; /** LevelResolution; /** Date: Sat, 17 Sep 2022 22:19:59 +0000 Subject: [PATCH 10/19] Fix Texture Budgeting Subsystem --- .../ERS_ModelLoader/ERS_CLASS_AssetStreamingManager.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Source/Core/Loader/ERS_ModelLoader/ERS_CLASS_AssetStreamingManager.cpp b/Source/Core/Loader/ERS_ModelLoader/ERS_CLASS_AssetStreamingManager.cpp index 45753a573e..9bda763ea0 100644 --- a/Source/Core/Loader/ERS_ModelLoader/ERS_CLASS_AssetStreamingManager.cpp +++ b/Source/Core/Loader/ERS_ModelLoader/ERS_CLASS_AssetStreamingManager.cpp @@ -137,7 +137,15 @@ void ERS_CLASS_AssetStreamingManager::SortSceneModels(std::mapTextureFitsInVRAMBudget(TextureSizeVRAM); if (!AlreadyHasVRAMLevel && !VRAMUpdateQuotaExceeded && TextureFitsInVRAM) { if (Model->TargetTextureLevelVRAM < TargetTextureLevelVRAM) { + + // Allocate + for (unsigned int i = 0; i < Model->Textures_Loaded.size(); i++) { + ResourceMonitor_->AllocateTextureVRAMFromBudget(Model->Textures_Loaded[i].TextureLevels[TargetTextureLevelVRAM].LevelMemorySizeBytes); + Model->Textures_Loaded[i].TextureLevels[TargetTextureLevelVRAM].AllocatedVRAMBudget = true; + } + Model->TargetTextureLevelVRAM = TargetTextureLevelVRAM; + if (Model->TargetTextureLevelVRAM > 0) { CameraVRAMUpdates++; } From 22b5aa262bec494f1d95cde328ffb016e1fc6563 Mon Sep 17 00:00:00 2001 From: datacrystals Date: Sun, 18 Sep 2022 01:46:28 +0000 Subject: [PATCH 11/19] Fix Texture Budgeting Subsystem --- .../ERS_CLASS_AssetStreamingManager.cpp | 8 ++++++++ .../ERS_CLASS_AsyncTextureUpdater.cpp | 15 ++++++++++++--- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/Source/Core/Loader/ERS_ModelLoader/ERS_CLASS_AssetStreamingManager.cpp b/Source/Core/Loader/ERS_ModelLoader/ERS_CLASS_AssetStreamingManager.cpp index 9bda763ea0..0d8c9494d8 100644 --- a/Source/Core/Loader/ERS_ModelLoader/ERS_CLASS_AssetStreamingManager.cpp +++ b/Source/Core/Loader/ERS_ModelLoader/ERS_CLASS_AssetStreamingManager.cpp @@ -162,7 +162,15 @@ void ERS_CLASS_AssetStreamingManager::SortSceneModels(std::mapTextureFitsInRAMBudget(TextureSizeRAM); if (!AlreadyHasRAMLevel && !RAMUpdateQuotaExceeded && TextureFitsInRAM) { if (Model->TargetTextureLevelRAM < TargetTextureLevelRAM) { + + // Allocate + for (unsigned int i = 0; i < Model->Textures_Loaded.size(); i++) { + ResourceMonitor_->AllocateTextureRAMFromBudget(Model->Textures_Loaded[i].TextureLevels[TargetTextureLevelRAM].LevelMemorySizeBytes); + Model->Textures_Loaded[i].TextureLevels[TargetTextureLevelRAM].AllocatedRAMBudget = true; + } + Model->TargetTextureLevelRAM = TargetTextureLevelRAM; + if (Model->TargetTextureLevelRAM > 0) { CameraRAMUpdates++; } diff --git a/Source/Core/Loader/ERS_ModelLoader/ERS_CLASS_AsyncTextureUpdater.cpp b/Source/Core/Loader/ERS_ModelLoader/ERS_CLASS_AsyncTextureUpdater.cpp index 1bac2968ab..301002d59d 100644 --- a/Source/Core/Loader/ERS_ModelLoader/ERS_CLASS_AsyncTextureUpdater.cpp +++ b/Source/Core/Loader/ERS_ModelLoader/ERS_CLASS_AsyncTextureUpdater.cpp @@ -71,9 +71,11 @@ bool ERS_CLASS_AsyncTextureUpdater::LoadImageDataRAM(ERS_STRUCT_Texture* Texture } - // Allocate Memory From Budget - ResourceMonitor_->AllocateTextureRAMFromBudget(Texture->TextureLevels[Level].LevelMemorySizeBytes); - + // If Needed, Allocate Memory From Budget + if (!Texture->TextureLevels[Level].AllocatedRAMBudget) { + ResourceMonitor_->AllocateTextureRAMFromBudget(Texture->TextureLevels[Level].LevelMemorySizeBytes); + Texture->TextureLevels[Level].AllocatedRAMBudget = true; + } // Load Image Data ERS_STRUCT_IOData ImageData; @@ -96,6 +98,7 @@ bool ERS_CLASS_AsyncTextureUpdater::LoadImageDataRAM(ERS_STRUCT_Texture* Texture FreeImage_Unload(RawImage); FreeImage_CloseMemory(FIImageData); ResourceMonitor_->DeallocateTextureRAMFromBudget(Texture->TextureLevels[Level].LevelMemorySizeBytes); + Texture->TextureLevels[Level].AllocatedRAMBudget = false; return false; } if (Height <= 0) { @@ -105,6 +108,7 @@ bool ERS_CLASS_AsyncTextureUpdater::LoadImageDataRAM(ERS_STRUCT_Texture* Texture FreeImage_Unload(RawImage); FreeImage_CloseMemory(FIImageData); ResourceMonitor_->DeallocateTextureRAMFromBudget(Texture->TextureLevels[Level].LevelMemorySizeBytes); + Texture->TextureLevels[Level].AllocatedRAMBudget = false; return false; } @@ -131,6 +135,7 @@ bool ERS_CLASS_AsyncTextureUpdater::LoadImageDataRAM(ERS_STRUCT_Texture* Texture + "' Width Does Not Match Metadata Target", 8, LogEnable); FreeImage_Unload(Image); ResourceMonitor_->DeallocateTextureRAMFromBudget(Texture->TextureLevels[Level].LevelMemorySizeBytes); + Texture->TextureLevels[Level].AllocatedRAMBudget = false; return false; } if ((TargetWidthHeight.second != Height) && (TargetWidthHeight.second != -1)) { @@ -139,6 +144,7 @@ bool ERS_CLASS_AsyncTextureUpdater::LoadImageDataRAM(ERS_STRUCT_Texture* Texture + "' Height Does Not Match Metadata Target", 8, LogEnable); FreeImage_Unload(Image); ResourceMonitor_->DeallocateTextureRAMFromBudget(Texture->TextureLevels[Level].LevelMemorySizeBytes); + Texture->TextureLevels[Level].AllocatedRAMBudget = false; return false; } @@ -149,6 +155,7 @@ bool ERS_CLASS_AsyncTextureUpdater::LoadImageDataRAM(ERS_STRUCT_Texture* Texture + "' Invalid Number Of Channels '" + std::to_string(Channels) + "'", 8, LogEnable); FreeImage_Unload(Image); ResourceMonitor_->DeallocateTextureRAMFromBudget(Texture->TextureLevels[Level].LevelMemorySizeBytes); + Texture->TextureLevels[Level].AllocatedRAMBudget = false; return false; } if ((Texture->TextureLevels[Level].LevelChannel != Channels) && (Texture->TextureLevels[Level].LevelChannel != -1)) { @@ -158,6 +165,7 @@ bool ERS_CLASS_AsyncTextureUpdater::LoadImageDataRAM(ERS_STRUCT_Texture* Texture + std::to_string(Texture->TextureLevels[Level].LevelChannel) + "'", 8, LogEnable); FreeImage_Unload(Image); ResourceMonitor_->DeallocateTextureRAMFromBudget(Texture->TextureLevels[Level].LevelMemorySizeBytes); + Texture->TextureLevels[Level].AllocatedRAMBudget = false; return false; } @@ -188,6 +196,7 @@ bool ERS_CLASS_AsyncTextureUpdater::UnloadImageDataRAM(ERS_STRUCT_Texture* Textu long MemorySize = FreeImage_GetMemorySize(Texture->TextureLevels[Level].LevelBitmap); ResourceMonitor_->DeallocateTextureRAMFromBudget(MemorySize); + Texture->TextureLevels[Level].AllocatedRAMBudget = false; // Update Data FreeImage_Unload(Texture->TextureLevels[Level].LevelBitmap); From f4ad9e514c5babf16ebe1b28afba88f9753bbb35 Mon Sep 17 00:00:00 2001 From: datacrystals Date: Sun, 18 Sep 2022 01:48:18 +0000 Subject: [PATCH 12/19] Fix Texture Budgeting Subsystem --- .../ERS_CLASS_AsyncTextureUpdater.cpp | 27 ++++++++++--------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/Source/Core/Loader/ERS_ModelLoader/ERS_CLASS_AsyncTextureUpdater.cpp b/Source/Core/Loader/ERS_ModelLoader/ERS_CLASS_AsyncTextureUpdater.cpp index 301002d59d..6fc81a75d8 100644 --- a/Source/Core/Loader/ERS_ModelLoader/ERS_CLASS_AsyncTextureUpdater.cpp +++ b/Source/Core/Loader/ERS_ModelLoader/ERS_CLASS_AsyncTextureUpdater.cpp @@ -226,8 +226,9 @@ bool ERS_CLASS_AsyncTextureUpdater::LoadImageDataVRAM(ERS_STRUCT_Texture* Textur } // Allocate Budget - ResourceMonitor_->AllocateTextureVRAMFromBudget(Texture->TextureLevels[Level].LevelMemorySizeBytes); - + if (!Texture->TextureLevels[Level].AllocatedVRAMBudget) { + ResourceMonitor_->AllocateTextureVRAMFromBudget(Texture->TextureLevels[Level].LevelMemorySizeBytes); + } // Get Image Metadata, Perform Checks int MaxLevel = Texture->TextureLevels.size() - 1; @@ -249,6 +250,7 @@ bool ERS_CLASS_AsyncTextureUpdater::LoadImageDataVRAM(ERS_STRUCT_Texture* Textur + "', Level '" + std::to_string(Level) + "' With ID '" + std::to_string(Texture->TextureLevels[CorrectedIndex].LevelTextureAssetID) + "' Channel Count <1", 8, LogEnable); ResourceMonitor_->DeallocateTextureVRAMFromBudget(Texture->TextureLevels[Level].LevelMemorySizeBytes); + Texture->TextureLevels[Level].AllocatedVRAMBudget = false; return false; } if (!Texture->TextureLevels[Level].LevelLoadedInRAM) { @@ -256,6 +258,7 @@ bool ERS_CLASS_AsyncTextureUpdater::LoadImageDataVRAM(ERS_STRUCT_Texture* Textur + "', Level '" + std::to_string(Level) + "' With ID '" + std::to_string(Texture->TextureLevels[CorrectedIndex].LevelTextureAssetID) + "' Not All Prior Levels Are Loaded Into RAM", 8, LogEnable); ResourceMonitor_->DeallocateTextureVRAMFromBudget(Texture->TextureLevels[Level].LevelMemorySizeBytes); + Texture->TextureLevels[Level].AllocatedVRAMBudget = false; return false; } if (MaxLevel < 0) { @@ -263,36 +266,34 @@ bool ERS_CLASS_AsyncTextureUpdater::LoadImageDataVRAM(ERS_STRUCT_Texture* Textur + "', Level '" + std::to_string(Level) + "' With ID '" + std::to_string(Texture->TextureLevels[CorrectedIndex].LevelTextureAssetID) + "' No Levels To Load", 8, LogEnable); ResourceMonitor_->DeallocateTextureVRAMFromBudget(Texture->TextureLevels[Level].LevelMemorySizeBytes); - return false; + Texture->TextureLevels[Level].AllocatedVRAMBudget = false; + return false; } if (MaxWidth < 1) { SystemUtils_->Logger_->Log(std::string("Error Loading Texture '") + Texture->Path + "', Level '" + std::to_string(Level) + "' With ID '" + std::to_string(Texture->TextureLevels[CorrectedIndex].LevelTextureAssetID) + "' Width is 0", 8, LogEnable); ResourceMonitor_->DeallocateTextureVRAMFromBudget(Texture->TextureLevels[Level].LevelMemorySizeBytes); - return false; + Texture->TextureLevels[Level].AllocatedVRAMBudget = false; + return false; } if (MaxHeight < 1) { SystemUtils_->Logger_->Log(std::string("Error Loading Texture '") + Texture->Path + "', Level '" + std::to_string(Level) + "' With ID '" + std::to_string(Texture->TextureLevels[CorrectedIndex].LevelTextureAssetID) + "' Height is 0", 8, LogEnable); ResourceMonitor_->DeallocateTextureVRAMFromBudget(Texture->TextureLevels[Level].LevelMemorySizeBytes); - return false; + Texture->TextureLevels[Level].AllocatedVRAMBudget = false; + return false; } if (ImageSize < 1) { SystemUtils_->Logger_->Log(std::string("Error Loading Texture '") + Texture->Path + "', Level '" + std::to_string(Level) + "' With ID '" + std::to_string(Texture->TextureLevels[CorrectedIndex].LevelTextureAssetID) + "' Image Byte Array Has Size Of 0", 8, LogEnable); ResourceMonitor_->DeallocateTextureVRAMFromBudget(Texture->TextureLevels[Level].LevelMemorySizeBytes); - return false; + Texture->TextureLevels[Level].AllocatedVRAMBudget = false; + return false; } - - // TODO: Fix mip map loading - // FIx segfaults caused when lots of loading is in the queue - unknown why this happens - //bool EnableMipMaps = false; - - // Setup PBO unsigned int PBOID; glGenBuffers(1, &PBOID); @@ -321,8 +322,8 @@ bool ERS_CLASS_AsyncTextureUpdater::LoadImageDataVRAM(ERS_STRUCT_Texture* Textur TextureInternFormat = GL_RED; TextureExternFormat = GL_RED; } else { - ResourceMonitor_->DeallocateTextureVRAMFromBudget(Texture->TextureLevels[Level].LevelMemorySizeBytes); + Texture->TextureLevels[Level].AllocatedVRAMBudget = false; return false; } From 258903d77997b15aa93269a4c542ed56258d8058 Mon Sep 17 00:00:00 2001 From: datacrystals Date: Sun, 18 Sep 2022 01:48:54 +0000 Subject: [PATCH 13/19] Fix Texture Budgeting Subsystem --- .../Loader/ERS_ModelLoader/ERS_CLASS_AsyncTextureUpdater.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/Source/Core/Loader/ERS_ModelLoader/ERS_CLASS_AsyncTextureUpdater.cpp b/Source/Core/Loader/ERS_ModelLoader/ERS_CLASS_AsyncTextureUpdater.cpp index 6fc81a75d8..8af206487d 100644 --- a/Source/Core/Loader/ERS_ModelLoader/ERS_CLASS_AsyncTextureUpdater.cpp +++ b/Source/Core/Loader/ERS_ModelLoader/ERS_CLASS_AsyncTextureUpdater.cpp @@ -388,6 +388,7 @@ bool ERS_CLASS_AsyncTextureUpdater::UnloadImageDataVRAM(ERS_STRUCT_Texture* Text // Update Struct long MemorySize = Texture->TextureLevels[Level].LevelMemorySizeBytes; ResourceMonitor_->DeallocateTextureVRAMFromBudget(MemorySize); + Texture->TextureLevels[Level].AllocatedVRAMBudget = false; Texture->TextureLevels[Level].LevelTextureOpenGLID = 0; Texture->TextureLevels[Level].LevelLoadedInVRAM = false; From ff93902fb6b643843dbb5ab7ee40df5d781f7679 Mon Sep 17 00:00:00 2001 From: datacrystals Date: Sun, 18 Sep 2022 01:56:20 +0000 Subject: [PATCH 14/19] Fix Texture Budgeting Subsystem --- .../ERS_STRUCT_TextureLevel/ERS_STRUCT_TextureLevel.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/Core/Structures/ERS_STRUCT_TextureLevel/ERS_STRUCT_TextureLevel.h b/Source/Core/Structures/ERS_STRUCT_TextureLevel/ERS_STRUCT_TextureLevel.h index a6527cde01..b5a13f9493 100644 --- a/Source/Core/Structures/ERS_STRUCT_TextureLevel/ERS_STRUCT_TextureLevel.h +++ b/Source/Core/Structures/ERS_STRUCT_TextureLevel/ERS_STRUCT_TextureLevel.h @@ -22,8 +22,8 @@ struct ERS_STRUCT_TextureLevel { unsigned int LevelTextureOpenGLID; /** Date: Sun, 18 Sep 2022 03:21:09 +0000 Subject: [PATCH 15/19] Fix Texture Budgeting Subsystem --- .../ERS_CLASS_AsyncTextureUpdater.cpp | 71 ++++++------------- 1 file changed, 21 insertions(+), 50 deletions(-) diff --git a/Source/Core/Loader/ERS_ModelLoader/ERS_CLASS_AsyncTextureUpdater.cpp b/Source/Core/Loader/ERS_ModelLoader/ERS_CLASS_AsyncTextureUpdater.cpp index 8af206487d..39d89603c0 100644 --- a/Source/Core/Loader/ERS_ModelLoader/ERS_CLASS_AsyncTextureUpdater.cpp +++ b/Source/Core/Loader/ERS_ModelLoader/ERS_CLASS_AsyncTextureUpdater.cpp @@ -60,9 +60,6 @@ bool ERS_CLASS_AsyncTextureUpdater::LoadImageDataRAM(ERS_STRUCT_Texture* Texture } else if (Level > (int)Texture->TextureLevels.size()) { SystemUtils_->Logger_->Log("Texture Updater Tried To Load Nonexistant Texture Level", 8, LogEnable); return false; - } else if (!ResourceMonitor_->TextureFitsInRAMBudget(Texture->TextureLevels[Level].LevelMemorySizeBytes)) { - SystemUtils_->Logger_->Log("Cannot Load Texture Into Memory, Will Not Fit In RAM Budget", 6); - return false; } // Check If Level Already Loaded @@ -71,12 +68,6 @@ bool ERS_CLASS_AsyncTextureUpdater::LoadImageDataRAM(ERS_STRUCT_Texture* Texture } - // If Needed, Allocate Memory From Budget - if (!Texture->TextureLevels[Level].AllocatedRAMBudget) { - ResourceMonitor_->AllocateTextureRAMFromBudget(Texture->TextureLevels[Level].LevelMemorySizeBytes); - Texture->TextureLevels[Level].AllocatedRAMBudget = true; - } - // Load Image Data ERS_STRUCT_IOData ImageData; long LevelAssetID = Texture->TextureLevels[Level].LevelTextureAssetID; @@ -97,8 +88,6 @@ bool ERS_CLASS_AsyncTextureUpdater::LoadImageDataRAM(ERS_STRUCT_Texture* Texture + "' Width Is <1", 8, LogEnable); FreeImage_Unload(RawImage); FreeImage_CloseMemory(FIImageData); - ResourceMonitor_->DeallocateTextureRAMFromBudget(Texture->TextureLevels[Level].LevelMemorySizeBytes); - Texture->TextureLevels[Level].AllocatedRAMBudget = false; return false; } if (Height <= 0) { @@ -107,8 +96,6 @@ bool ERS_CLASS_AsyncTextureUpdater::LoadImageDataRAM(ERS_STRUCT_Texture* Texture + "' Height Is <1", 8, LogEnable); FreeImage_Unload(RawImage); FreeImage_CloseMemory(FIImageData); - ResourceMonitor_->DeallocateTextureRAMFromBudget(Texture->TextureLevels[Level].LevelMemorySizeBytes); - Texture->TextureLevels[Level].AllocatedRAMBudget = false; return false; } @@ -128,14 +115,13 @@ bool ERS_CLASS_AsyncTextureUpdater::LoadImageDataRAM(ERS_STRUCT_Texture* Texture FreeImage_Unload(RawImage); FreeImage_CloseMemory(FIImageData); + std::pair TargetWidthHeight = Texture->TextureLevels[Level].LevelResolution; if ((TargetWidthHeight.first != Width) && (TargetWidthHeight.first != -1)) { SystemUtils_->Logger_->Log(std::string("Error Loading Texture '") + Texture->Path + "', Level '" + std::to_string(Level) + "' With ID '" + std::to_string(LevelAssetID) + "' Width Does Not Match Metadata Target", 8, LogEnable); FreeImage_Unload(Image); - ResourceMonitor_->DeallocateTextureRAMFromBudget(Texture->TextureLevels[Level].LevelMemorySizeBytes); - Texture->TextureLevels[Level].AllocatedRAMBudget = false; return false; } if ((TargetWidthHeight.second != Height) && (TargetWidthHeight.second != -1)) { @@ -143,10 +129,9 @@ bool ERS_CLASS_AsyncTextureUpdater::LoadImageDataRAM(ERS_STRUCT_Texture* Texture + "', Level '" + std::to_string(Level) + "' With ID '" + std::to_string(LevelAssetID) + "' Height Does Not Match Metadata Target", 8, LogEnable); FreeImage_Unload(Image); - ResourceMonitor_->DeallocateTextureRAMFromBudget(Texture->TextureLevels[Level].LevelMemorySizeBytes); - Texture->TextureLevels[Level].AllocatedRAMBudget = false; return false; } + // Detect NumChannels if ((Channels < 1) || (Channels > 4)) { @@ -154,8 +139,6 @@ bool ERS_CLASS_AsyncTextureUpdater::LoadImageDataRAM(ERS_STRUCT_Texture* Texture + "', Level '" + std::to_string(Level) + "' With ID '" + std::to_string(LevelAssetID) + "' Invalid Number Of Channels '" + std::to_string(Channels) + "'", 8, LogEnable); FreeImage_Unload(Image); - ResourceMonitor_->DeallocateTextureRAMFromBudget(Texture->TextureLevels[Level].LevelMemorySizeBytes); - Texture->TextureLevels[Level].AllocatedRAMBudget = false; return false; } if ((Texture->TextureLevels[Level].LevelChannel != Channels) && (Texture->TextureLevels[Level].LevelChannel != -1)) { @@ -164,12 +147,15 @@ bool ERS_CLASS_AsyncTextureUpdater::LoadImageDataRAM(ERS_STRUCT_Texture* Texture + "' Number Channels '" + std::to_string(Channels) + "' Does Not Match Metadata Target '" + std::to_string(Texture->TextureLevels[Level].LevelChannel) + "'", 8, LogEnable); FreeImage_Unload(Image); - ResourceMonitor_->DeallocateTextureRAMFromBudget(Texture->TextureLevels[Level].LevelMemorySizeBytes); - Texture->TextureLevels[Level].AllocatedRAMBudget = false; return false; } + // fix images loading incorrectly (perhaps due to broken numbers of channels? + // add error textures so that we can display the error on the model to make it easier to understand what the issue is - for example, display "Loading Error: Invalid Num Image Channels" for the above issue and add the same for the other issues. + // Finally After Passing Sanity Checks, Populate Info. + long MemorySize = FreeImage_GetMemorySize(Image); + ResourceMonitor_->AllocateTextureRAMFromBudget(MemorySize); Texture->TextureLevels[Level].LevelBitmap = Image; Texture->TextureLevels[Level].LevelLoadedInRAM = true; @@ -196,7 +182,6 @@ bool ERS_CLASS_AsyncTextureUpdater::UnloadImageDataRAM(ERS_STRUCT_Texture* Textu long MemorySize = FreeImage_GetMemorySize(Texture->TextureLevels[Level].LevelBitmap); ResourceMonitor_->DeallocateTextureRAMFromBudget(MemorySize); - Texture->TextureLevels[Level].AllocatedRAMBudget = false; // Update Data FreeImage_Unload(Texture->TextureLevels[Level].LevelBitmap); @@ -214,9 +199,6 @@ bool ERS_CLASS_AsyncTextureUpdater::LoadImageDataVRAM(ERS_STRUCT_Texture* Textur } else if (Level > (int)Texture->TextureLevels.size()) { SystemUtils_->Logger_->Log("Texture Updater Tried To Load Nonexistant Texture Level Into VRAM", 8, LogEnable); return false; - } else if (!ResourceMonitor_->TextureFitsInVRAMBudget(Texture->TextureLevels[Level].LevelMemorySizeBytes)) { - SystemUtils_->Logger_->Log("Cannot Load Texture Into Memory, Will Not Fit In VRAM Budget", 6); - return false; } // Check If Level Already Loaded @@ -225,11 +207,6 @@ bool ERS_CLASS_AsyncTextureUpdater::LoadImageDataVRAM(ERS_STRUCT_Texture* Textur return false; } - // Allocate Budget - if (!Texture->TextureLevels[Level].AllocatedVRAMBudget) { - ResourceMonitor_->AllocateTextureVRAMFromBudget(Texture->TextureLevels[Level].LevelMemorySizeBytes); - } - // Get Image Metadata, Perform Checks int MaxLevel = Texture->TextureLevels.size() - 1; int CorrectedIndex = Level; @@ -242,58 +219,51 @@ bool ERS_CLASS_AsyncTextureUpdater::LoadImageDataVRAM(ERS_STRUCT_Texture* Textur SystemUtils_->Logger_->Log(std::string("Error Loading Texture '") + Texture->Path + "', Level '" + std::to_string(Level) + "' With ID '" + std::to_string(Texture->TextureLevels[CorrectedIndex].LevelTextureAssetID) + "' Channel Count >4", 8, LogEnable); - ResourceMonitor_->DeallocateTextureVRAMFromBudget(Texture->TextureLevels[Level].LevelMemorySizeBytes); return false; } if (Channels < 1) { SystemUtils_->Logger_->Log(std::string("Error Loading Texture '") + Texture->Path + "', Level '" + std::to_string(Level) + "' With ID '" + std::to_string(Texture->TextureLevels[CorrectedIndex].LevelTextureAssetID) + "' Channel Count <1", 8, LogEnable); - ResourceMonitor_->DeallocateTextureVRAMFromBudget(Texture->TextureLevels[Level].LevelMemorySizeBytes); - Texture->TextureLevels[Level].AllocatedVRAMBudget = false; return false; } if (!Texture->TextureLevels[Level].LevelLoadedInRAM) { SystemUtils_->Logger_->Log(std::string("Error Loading Texture '") + Texture->Path + "', Level '" + std::to_string(Level) + "' With ID '" + std::to_string(Texture->TextureLevels[CorrectedIndex].LevelTextureAssetID) + "' Not All Prior Levels Are Loaded Into RAM", 8, LogEnable); - ResourceMonitor_->DeallocateTextureVRAMFromBudget(Texture->TextureLevels[Level].LevelMemorySizeBytes); - Texture->TextureLevels[Level].AllocatedVRAMBudget = false; return false; } if (MaxLevel < 0) { SystemUtils_->Logger_->Log(std::string("Error Loading Texture '") + Texture->Path + "', Level '" + std::to_string(Level) + "' With ID '" + std::to_string(Texture->TextureLevels[CorrectedIndex].LevelTextureAssetID) + "' No Levels To Load", 8, LogEnable); - ResourceMonitor_->DeallocateTextureVRAMFromBudget(Texture->TextureLevels[Level].LevelMemorySizeBytes); - Texture->TextureLevels[Level].AllocatedVRAMBudget = false; - return false; + return false; } if (MaxWidth < 1) { SystemUtils_->Logger_->Log(std::string("Error Loading Texture '") + Texture->Path + "', Level '" + std::to_string(Level) + "' With ID '" + std::to_string(Texture->TextureLevels[CorrectedIndex].LevelTextureAssetID) + "' Width is 0", 8, LogEnable); - ResourceMonitor_->DeallocateTextureVRAMFromBudget(Texture->TextureLevels[Level].LevelMemorySizeBytes); - Texture->TextureLevels[Level].AllocatedVRAMBudget = false; - return false; + return false; } if (MaxHeight < 1) { SystemUtils_->Logger_->Log(std::string("Error Loading Texture '") + Texture->Path + "', Level '" + std::to_string(Level) + "' With ID '" + std::to_string(Texture->TextureLevels[CorrectedIndex].LevelTextureAssetID) + "' Height is 0", 8, LogEnable); - ResourceMonitor_->DeallocateTextureVRAMFromBudget(Texture->TextureLevels[Level].LevelMemorySizeBytes); - Texture->TextureLevels[Level].AllocatedVRAMBudget = false; - return false; + return false; } if (ImageSize < 1) { SystemUtils_->Logger_->Log(std::string("Error Loading Texture '") + Texture->Path + "', Level '" + std::to_string(Level) + "' With ID '" + std::to_string(Texture->TextureLevels[CorrectedIndex].LevelTextureAssetID) + "' Image Byte Array Has Size Of 0", 8, LogEnable); - ResourceMonitor_->DeallocateTextureVRAMFromBudget(Texture->TextureLevels[Level].LevelMemorySizeBytes); - Texture->TextureLevels[Level].AllocatedVRAMBudget = false; - return false; + return false; } + + // TODO: Fix mip map loading + // FIx segfaults caused when lots of loading is in the queue - unknown why this happens + //bool EnableMipMaps = false; + + // Setup PBO unsigned int PBOID; glGenBuffers(1, &PBOID); @@ -322,8 +292,6 @@ bool ERS_CLASS_AsyncTextureUpdater::LoadImageDataVRAM(ERS_STRUCT_Texture* Textur TextureInternFormat = GL_RED; TextureExternFormat = GL_RED; } else { - ResourceMonitor_->DeallocateTextureVRAMFromBudget(Texture->TextureLevels[Level].LevelMemorySizeBytes); - Texture->TextureLevels[Level].AllocatedVRAMBudget = false; return false; } @@ -361,8 +329,12 @@ bool ERS_CLASS_AsyncTextureUpdater::LoadImageDataVRAM(ERS_STRUCT_Texture* Textur glDeleteBuffers(1, &PBOID); // Update Struct + long MemorySize = Texture->TextureLevels[Level].LevelMemorySizeBytes; + ResourceMonitor_->AllocateTextureVRAMFromBudget(MemorySize); Texture->TextureLevels[CorrectedIndex].LevelTextureOpenGLID = OpenGLTextureID; Texture->TextureLevels[CorrectedIndex].LevelLoadedInVRAM = true; + + return true; } bool ERS_CLASS_AsyncTextureUpdater::UnloadImageDataVRAM(ERS_STRUCT_Texture* Texture, int Level, bool LogEnable) { @@ -388,7 +360,6 @@ bool ERS_CLASS_AsyncTextureUpdater::UnloadImageDataVRAM(ERS_STRUCT_Texture* Text // Update Struct long MemorySize = Texture->TextureLevels[Level].LevelMemorySizeBytes; ResourceMonitor_->DeallocateTextureVRAMFromBudget(MemorySize); - Texture->TextureLevels[Level].AllocatedVRAMBudget = false; Texture->TextureLevels[Level].LevelTextureOpenGLID = 0; Texture->TextureLevels[Level].LevelLoadedInVRAM = false; From 163eae63c7ef4f901b8011547c610edcd1184f89 Mon Sep 17 00:00:00 2001 From: datacrystals Date: Sun, 18 Sep 2022 03:23:27 +0000 Subject: [PATCH 16/19] Fix Texture Budgeting Subsystem --- .../Loader/ERS_ModelLoader/ERS_CLASS_AsyncTextureUpdater.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Source/Core/Loader/ERS_ModelLoader/ERS_CLASS_AsyncTextureUpdater.cpp b/Source/Core/Loader/ERS_ModelLoader/ERS_CLASS_AsyncTextureUpdater.cpp index 39d89603c0..2caa8fef68 100644 --- a/Source/Core/Loader/ERS_ModelLoader/ERS_CLASS_AsyncTextureUpdater.cpp +++ b/Source/Core/Loader/ERS_ModelLoader/ERS_CLASS_AsyncTextureUpdater.cpp @@ -60,6 +60,9 @@ bool ERS_CLASS_AsyncTextureUpdater::LoadImageDataRAM(ERS_STRUCT_Texture* Texture } else if (Level > (int)Texture->TextureLevels.size()) { SystemUtils_->Logger_->Log("Texture Updater Tried To Load Nonexistant Texture Level", 8, LogEnable); return false; + } else if (Texture->TextureLevels[Level].LevelMemorySizeBytes > SystemUtils_->ERS_CLASS_HardwareInformation_->GetHWInfo().Dynamic_.PhysicalMemoryFree) { + SystemUtils_->Logger_->Log("Texture Updater Cannot Load Texture, Out Of Memory", 8, LogEnable); + return false; } // Check If Level Already Loaded From 1dc69f9b5f1d08db086eb8cd869b6528710a4caf Mon Sep 17 00:00:00 2001 From: datacrystals Date: Sun, 18 Sep 2022 03:25:45 +0000 Subject: [PATCH 17/19] Fix Texture Budgeting Subsystem --- .../ERS_CLASS_AsyncTextureUpdater.cpp | 75 ++++++++++++------- .../ERS_STRUCT_TextureLevel.h | 4 +- 2 files changed, 52 insertions(+), 27 deletions(-) diff --git a/Source/Core/Loader/ERS_ModelLoader/ERS_CLASS_AsyncTextureUpdater.cpp b/Source/Core/Loader/ERS_ModelLoader/ERS_CLASS_AsyncTextureUpdater.cpp index 2caa8fef68..b441b309c1 100644 --- a/Source/Core/Loader/ERS_ModelLoader/ERS_CLASS_AsyncTextureUpdater.cpp +++ b/Source/Core/Loader/ERS_ModelLoader/ERS_CLASS_AsyncTextureUpdater.cpp @@ -60,8 +60,8 @@ bool ERS_CLASS_AsyncTextureUpdater::LoadImageDataRAM(ERS_STRUCT_Texture* Texture } else if (Level > (int)Texture->TextureLevels.size()) { SystemUtils_->Logger_->Log("Texture Updater Tried To Load Nonexistant Texture Level", 8, LogEnable); return false; - } else if (Texture->TextureLevels[Level].LevelMemorySizeBytes > SystemUtils_->ERS_CLASS_HardwareInformation_->GetHWInfo().Dynamic_.PhysicalMemoryFree) { - SystemUtils_->Logger_->Log("Texture Updater Cannot Load Texture, Out Of Memory", 8, LogEnable); + } else if (!ResourceMonitor_->TextureFitsInRAMBudget(Texture->TextureLevels[Level].LevelMemorySizeBytes)) { + SystemUtils_->Logger_->Log("Cannot Load Texture Into Memory, Will Not Fit In RAM Budget", 6); return false; } @@ -71,6 +71,12 @@ bool ERS_CLASS_AsyncTextureUpdater::LoadImageDataRAM(ERS_STRUCT_Texture* Texture } + // If Needed, Allocate Memory From Budget + if (!Texture->TextureLevels[Level].AllocatedRAMBudget) { + ResourceMonitor_->AllocateTextureRAMFromBudget(Texture->TextureLevels[Level].LevelMemorySizeBytes); + Texture->TextureLevels[Level].AllocatedRAMBudget = true; + } + // Load Image Data ERS_STRUCT_IOData ImageData; long LevelAssetID = Texture->TextureLevels[Level].LevelTextureAssetID; @@ -91,6 +97,8 @@ bool ERS_CLASS_AsyncTextureUpdater::LoadImageDataRAM(ERS_STRUCT_Texture* Texture + "' Width Is <1", 8, LogEnable); FreeImage_Unload(RawImage); FreeImage_CloseMemory(FIImageData); + ResourceMonitor_->DeallocateTextureRAMFromBudget(Texture->TextureLevels[Level].LevelMemorySizeBytes); + Texture->TextureLevels[Level].AllocatedRAMBudget = false; return false; } if (Height <= 0) { @@ -99,6 +107,8 @@ bool ERS_CLASS_AsyncTextureUpdater::LoadImageDataRAM(ERS_STRUCT_Texture* Texture + "' Height Is <1", 8, LogEnable); FreeImage_Unload(RawImage); FreeImage_CloseMemory(FIImageData); + ResourceMonitor_->DeallocateTextureRAMFromBudget(Texture->TextureLevels[Level].LevelMemorySizeBytes); + Texture->TextureLevels[Level].AllocatedRAMBudget = false; return false; } @@ -118,13 +128,14 @@ bool ERS_CLASS_AsyncTextureUpdater::LoadImageDataRAM(ERS_STRUCT_Texture* Texture FreeImage_Unload(RawImage); FreeImage_CloseMemory(FIImageData); - std::pair TargetWidthHeight = Texture->TextureLevels[Level].LevelResolution; if ((TargetWidthHeight.first != Width) && (TargetWidthHeight.first != -1)) { SystemUtils_->Logger_->Log(std::string("Error Loading Texture '") + Texture->Path + "', Level '" + std::to_string(Level) + "' With ID '" + std::to_string(LevelAssetID) + "' Width Does Not Match Metadata Target", 8, LogEnable); FreeImage_Unload(Image); + ResourceMonitor_->DeallocateTextureRAMFromBudget(Texture->TextureLevels[Level].LevelMemorySizeBytes); + Texture->TextureLevels[Level].AllocatedRAMBudget = false; return false; } if ((TargetWidthHeight.second != Height) && (TargetWidthHeight.second != -1)) { @@ -132,9 +143,10 @@ bool ERS_CLASS_AsyncTextureUpdater::LoadImageDataRAM(ERS_STRUCT_Texture* Texture + "', Level '" + std::to_string(Level) + "' With ID '" + std::to_string(LevelAssetID) + "' Height Does Not Match Metadata Target", 8, LogEnable); FreeImage_Unload(Image); + ResourceMonitor_->DeallocateTextureRAMFromBudget(Texture->TextureLevels[Level].LevelMemorySizeBytes); + Texture->TextureLevels[Level].AllocatedRAMBudget = false; return false; } - // Detect NumChannels if ((Channels < 1) || (Channels > 4)) { @@ -142,6 +154,8 @@ bool ERS_CLASS_AsyncTextureUpdater::LoadImageDataRAM(ERS_STRUCT_Texture* Texture + "', Level '" + std::to_string(Level) + "' With ID '" + std::to_string(LevelAssetID) + "' Invalid Number Of Channels '" + std::to_string(Channels) + "'", 8, LogEnable); FreeImage_Unload(Image); + ResourceMonitor_->DeallocateTextureRAMFromBudget(Texture->TextureLevels[Level].LevelMemorySizeBytes); + Texture->TextureLevels[Level].AllocatedRAMBudget = false; return false; } if ((Texture->TextureLevels[Level].LevelChannel != Channels) && (Texture->TextureLevels[Level].LevelChannel != -1)) { @@ -150,15 +164,12 @@ bool ERS_CLASS_AsyncTextureUpdater::LoadImageDataRAM(ERS_STRUCT_Texture* Texture + "' Number Channels '" + std::to_string(Channels) + "' Does Not Match Metadata Target '" + std::to_string(Texture->TextureLevels[Level].LevelChannel) + "'", 8, LogEnable); FreeImage_Unload(Image); + ResourceMonitor_->DeallocateTextureRAMFromBudget(Texture->TextureLevels[Level].LevelMemorySizeBytes); + Texture->TextureLevels[Level].AllocatedRAMBudget = false; return false; } - // fix images loading incorrectly (perhaps due to broken numbers of channels? - // add error textures so that we can display the error on the model to make it easier to understand what the issue is - for example, display "Loading Error: Invalid Num Image Channels" for the above issue and add the same for the other issues. - // Finally After Passing Sanity Checks, Populate Info. - long MemorySize = FreeImage_GetMemorySize(Image); - ResourceMonitor_->AllocateTextureRAMFromBudget(MemorySize); Texture->TextureLevels[Level].LevelBitmap = Image; Texture->TextureLevels[Level].LevelLoadedInRAM = true; @@ -185,6 +196,7 @@ bool ERS_CLASS_AsyncTextureUpdater::UnloadImageDataRAM(ERS_STRUCT_Texture* Textu long MemorySize = FreeImage_GetMemorySize(Texture->TextureLevels[Level].LevelBitmap); ResourceMonitor_->DeallocateTextureRAMFromBudget(MemorySize); + Texture->TextureLevels[Level].AllocatedRAMBudget = false; // Update Data FreeImage_Unload(Texture->TextureLevels[Level].LevelBitmap); @@ -202,6 +214,9 @@ bool ERS_CLASS_AsyncTextureUpdater::LoadImageDataVRAM(ERS_STRUCT_Texture* Textur } else if (Level > (int)Texture->TextureLevels.size()) { SystemUtils_->Logger_->Log("Texture Updater Tried To Load Nonexistant Texture Level Into VRAM", 8, LogEnable); return false; + } else if (!ResourceMonitor_->TextureFitsInVRAMBudget(Texture->TextureLevels[Level].LevelMemorySizeBytes)) { + SystemUtils_->Logger_->Log("Cannot Load Texture Into Memory, Will Not Fit In VRAM Budget", 6); + return false; } // Check If Level Already Loaded @@ -210,6 +225,11 @@ bool ERS_CLASS_AsyncTextureUpdater::LoadImageDataVRAM(ERS_STRUCT_Texture* Textur return false; } + // Allocate Budget + if (!Texture->TextureLevels[Level].AllocatedVRAMBudget) { + ResourceMonitor_->AllocateTextureVRAMFromBudget(Texture->TextureLevels[Level].LevelMemorySizeBytes); + } + // Get Image Metadata, Perform Checks int MaxLevel = Texture->TextureLevels.size() - 1; int CorrectedIndex = Level; @@ -222,51 +242,58 @@ bool ERS_CLASS_AsyncTextureUpdater::LoadImageDataVRAM(ERS_STRUCT_Texture* Textur SystemUtils_->Logger_->Log(std::string("Error Loading Texture '") + Texture->Path + "', Level '" + std::to_string(Level) + "' With ID '" + std::to_string(Texture->TextureLevels[CorrectedIndex].LevelTextureAssetID) + "' Channel Count >4", 8, LogEnable); + ResourceMonitor_->DeallocateTextureVRAMFromBudget(Texture->TextureLevels[Level].LevelMemorySizeBytes); return false; } if (Channels < 1) { SystemUtils_->Logger_->Log(std::string("Error Loading Texture '") + Texture->Path + "', Level '" + std::to_string(Level) + "' With ID '" + std::to_string(Texture->TextureLevels[CorrectedIndex].LevelTextureAssetID) + "' Channel Count <1", 8, LogEnable); + ResourceMonitor_->DeallocateTextureVRAMFromBudget(Texture->TextureLevels[Level].LevelMemorySizeBytes); + Texture->TextureLevels[Level].AllocatedVRAMBudget = false; return false; } if (!Texture->TextureLevels[Level].LevelLoadedInRAM) { SystemUtils_->Logger_->Log(std::string("Error Loading Texture '") + Texture->Path + "', Level '" + std::to_string(Level) + "' With ID '" + std::to_string(Texture->TextureLevels[CorrectedIndex].LevelTextureAssetID) + "' Not All Prior Levels Are Loaded Into RAM", 8, LogEnable); + ResourceMonitor_->DeallocateTextureVRAMFromBudget(Texture->TextureLevels[Level].LevelMemorySizeBytes); + Texture->TextureLevels[Level].AllocatedVRAMBudget = false; return false; } if (MaxLevel < 0) { SystemUtils_->Logger_->Log(std::string("Error Loading Texture '") + Texture->Path + "', Level '" + std::to_string(Level) + "' With ID '" + std::to_string(Texture->TextureLevels[CorrectedIndex].LevelTextureAssetID) + "' No Levels To Load", 8, LogEnable); - return false; + ResourceMonitor_->DeallocateTextureVRAMFromBudget(Texture->TextureLevels[Level].LevelMemorySizeBytes); + Texture->TextureLevels[Level].AllocatedVRAMBudget = false; + return false; } if (MaxWidth < 1) { SystemUtils_->Logger_->Log(std::string("Error Loading Texture '") + Texture->Path + "', Level '" + std::to_string(Level) + "' With ID '" + std::to_string(Texture->TextureLevels[CorrectedIndex].LevelTextureAssetID) + "' Width is 0", 8, LogEnable); - return false; + ResourceMonitor_->DeallocateTextureVRAMFromBudget(Texture->TextureLevels[Level].LevelMemorySizeBytes); + Texture->TextureLevels[Level].AllocatedVRAMBudget = false; + return false; } if (MaxHeight < 1) { SystemUtils_->Logger_->Log(std::string("Error Loading Texture '") + Texture->Path + "', Level '" + std::to_string(Level) + "' With ID '" + std::to_string(Texture->TextureLevels[CorrectedIndex].LevelTextureAssetID) + "' Height is 0", 8, LogEnable); - return false; + ResourceMonitor_->DeallocateTextureVRAMFromBudget(Texture->TextureLevels[Level].LevelMemorySizeBytes); + Texture->TextureLevels[Level].AllocatedVRAMBudget = false; + return false; } if (ImageSize < 1) { SystemUtils_->Logger_->Log(std::string("Error Loading Texture '") + Texture->Path + "', Level '" + std::to_string(Level) + "' With ID '" + std::to_string(Texture->TextureLevels[CorrectedIndex].LevelTextureAssetID) + "' Image Byte Array Has Size Of 0", 8, LogEnable); - return false; + ResourceMonitor_->DeallocateTextureVRAMFromBudget(Texture->TextureLevels[Level].LevelMemorySizeBytes); + Texture->TextureLevels[Level].AllocatedVRAMBudget = false; + return false; } - - // TODO: Fix mip map loading - // FIx segfaults caused when lots of loading is in the queue - unknown why this happens - //bool EnableMipMaps = false; - - // Setup PBO unsigned int PBOID; glGenBuffers(1, &PBOID); @@ -295,6 +322,8 @@ bool ERS_CLASS_AsyncTextureUpdater::LoadImageDataVRAM(ERS_STRUCT_Texture* Textur TextureInternFormat = GL_RED; TextureExternFormat = GL_RED; } else { + ResourceMonitor_->DeallocateTextureVRAMFromBudget(Texture->TextureLevels[Level].LevelMemorySizeBytes); + Texture->TextureLevels[Level].AllocatedVRAMBudget = false; return false; } @@ -332,12 +361,8 @@ bool ERS_CLASS_AsyncTextureUpdater::LoadImageDataVRAM(ERS_STRUCT_Texture* Textur glDeleteBuffers(1, &PBOID); // Update Struct - long MemorySize = Texture->TextureLevels[Level].LevelMemorySizeBytes; - ResourceMonitor_->AllocateTextureVRAMFromBudget(MemorySize); Texture->TextureLevels[CorrectedIndex].LevelTextureOpenGLID = OpenGLTextureID; Texture->TextureLevels[CorrectedIndex].LevelLoadedInVRAM = true; - - return true; } bool ERS_CLASS_AsyncTextureUpdater::UnloadImageDataVRAM(ERS_STRUCT_Texture* Texture, int Level, bool LogEnable) { @@ -363,6 +388,7 @@ bool ERS_CLASS_AsyncTextureUpdater::UnloadImageDataVRAM(ERS_STRUCT_Texture* Text // Update Struct long MemorySize = Texture->TextureLevels[Level].LevelMemorySizeBytes; ResourceMonitor_->DeallocateTextureVRAMFromBudget(MemorySize); + Texture->TextureLevels[Level].AllocatedVRAMBudget = false; Texture->TextureLevels[Level].LevelTextureOpenGLID = 0; Texture->TextureLevels[Level].LevelLoadedInVRAM = false; @@ -830,5 +856,4 @@ bool ERS_CLASS_AsyncTextureUpdater::GetQueuePrioritizationEnabled() { } void ERS_CLASS_AsyncTextureUpdater::SetQueuePrioritizationEnabled(bool State) { PrioritizeQueueByVisualImpact_ = State; -} - +} \ No newline at end of file diff --git a/Source/Core/Structures/ERS_STRUCT_TextureLevel/ERS_STRUCT_TextureLevel.h b/Source/Core/Structures/ERS_STRUCT_TextureLevel/ERS_STRUCT_TextureLevel.h index b5a13f9493..9314bda908 100644 --- a/Source/Core/Structures/ERS_STRUCT_TextureLevel/ERS_STRUCT_TextureLevel.h +++ b/Source/Core/Structures/ERS_STRUCT_TextureLevel/ERS_STRUCT_TextureLevel.h @@ -25,8 +25,8 @@ struct ERS_STRUCT_TextureLevel { bool LevelLoadedInRAM = false; /** LevelResolution; /** Date: Sun, 18 Sep 2022 03:31:05 +0000 Subject: [PATCH 18/19] Fix Texture Budgeting Subsystem --- .../Loader/ERS_ModelLoader/ERS_CLASS_AsyncTextureUpdater.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Source/Core/Loader/ERS_ModelLoader/ERS_CLASS_AsyncTextureUpdater.cpp b/Source/Core/Loader/ERS_ModelLoader/ERS_CLASS_AsyncTextureUpdater.cpp index b441b309c1..e14a905878 100644 --- a/Source/Core/Loader/ERS_ModelLoader/ERS_CLASS_AsyncTextureUpdater.cpp +++ b/Source/Core/Loader/ERS_ModelLoader/ERS_CLASS_AsyncTextureUpdater.cpp @@ -194,8 +194,7 @@ bool ERS_CLASS_AsyncTextureUpdater::UnloadImageDataRAM(ERS_STRUCT_Texture* Textu } - long MemorySize = FreeImage_GetMemorySize(Texture->TextureLevels[Level].LevelBitmap); - ResourceMonitor_->DeallocateTextureRAMFromBudget(MemorySize); + ResourceMonitor_->DeallocateTextureRAMFromBudget(Texture->TextureLevels[Level].LevelMemorySizeBytes); Texture->TextureLevels[Level].AllocatedRAMBudget = false; // Update Data From 0b7705879173705338595be5ed7beb829d2e1b0c Mon Sep 17 00:00:00 2001 From: datacrystals Date: Sun, 18 Sep 2022 03:36:29 +0000 Subject: [PATCH 19/19] Fix Texture Budgeting Subsystem --- .../Loader/ERS_ModelLoader/ERS_CLASS_AsyncTextureUpdater.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/Source/Core/Loader/ERS_ModelLoader/ERS_CLASS_AsyncTextureUpdater.cpp b/Source/Core/Loader/ERS_ModelLoader/ERS_CLASS_AsyncTextureUpdater.cpp index e14a905878..b39397e8d0 100644 --- a/Source/Core/Loader/ERS_ModelLoader/ERS_CLASS_AsyncTextureUpdater.cpp +++ b/Source/Core/Loader/ERS_ModelLoader/ERS_CLASS_AsyncTextureUpdater.cpp @@ -193,7 +193,6 @@ bool ERS_CLASS_AsyncTextureUpdater::UnloadImageDataRAM(ERS_STRUCT_Texture* Textu return false; } - ResourceMonitor_->DeallocateTextureRAMFromBudget(Texture->TextureLevels[Level].LevelMemorySizeBytes); Texture->TextureLevels[Level].AllocatedRAMBudget = false;