Skip to content

Commit

Permalink
Merge pull request #379 from carboncopies/373-fix-loader-segmentation…
Browse files Browse the repository at this point in the history
…-fault

373 fix loader segmentation fault
  • Loading branch information
datacrystals authored Sep 18, 2022
2 parents a528cc2 + 0b77058 commit 7ad8678
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 28 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,15 @@ void ERS_CLASS_AssetStreamingManager::SortSceneModels(std::map<unsigned int, int
bool TextureFitsInVRAM = ResourceMonitor_->TextureFitsInVRAMBudget(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++;
}
Expand All @@ -154,7 +162,15 @@ void ERS_CLASS_AssetStreamingManager::SortSceneModels(std::map<unsigned int, int
bool TextureFitsInRAM = ResourceMonitor_->TextureFitsInRAMBudget(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++;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -68,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;
Expand All @@ -88,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) {
Expand All @@ -96,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;
}

Expand All @@ -115,30 +128,34 @@ bool ERS_CLASS_AsyncTextureUpdater::LoadImageDataRAM(ERS_STRUCT_Texture* Texture
FreeImage_Unload(RawImage);
FreeImage_CloseMemory(FIImageData);


std::pair<int, int> 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)) {
SystemUtils_->Logger_->Log(std::string("Error Loading Texture '") + Texture->Path
+ "', 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)) {
SystemUtils_->Logger_->Log(std::string("Error Loading Texture '") + Texture->Path
+ "', 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)) {
Expand All @@ -147,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;

Expand All @@ -179,9 +193,8 @@ bool ERS_CLASS_AsyncTextureUpdater::UnloadImageDataRAM(ERS_STRUCT_Texture* Textu
return false;
}


long MemorySize = FreeImage_GetMemorySize(Texture->TextureLevels[Level].LevelBitmap);
ResourceMonitor_->DeallocateTextureRAMFromBudget(MemorySize);
ResourceMonitor_->DeallocateTextureRAMFromBudget(Texture->TextureLevels[Level].LevelMemorySizeBytes);
Texture->TextureLevels[Level].AllocatedRAMBudget = false;

// Update Data
FreeImage_Unload(Texture->TextureLevels[Level].LevelBitmap);
Expand All @@ -199,6 +212,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
Expand All @@ -207,6 +223,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;
Expand All @@ -219,51 +240,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);
Expand Down Expand Up @@ -292,6 +320,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;
}

Expand Down Expand Up @@ -329,12 +359,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) {
Expand All @@ -360,6 +386,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;

Expand Down Expand Up @@ -827,5 +854,4 @@ bool ERS_CLASS_AsyncTextureUpdater::GetQueuePrioritizationEnabled() {
}
void ERS_CLASS_AsyncTextureUpdater::SetQueuePrioritizationEnabled(bool State) {
PrioritizeQueueByVisualImpact_ = State;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,19 @@ struct ERS_STRUCT_TextureLevel {

unsigned int LevelTextureOpenGLID; /**<List of opengl ids for every texture level*/
unsigned int LevelTextureAssetID; /**<List of asset ids for every texture level*/
bool LevelLoadedInRAM; /**<True/false for every level showing if that level is loaded in RAM*/
bool LevelLoadedInVRAM; /**<True/false for every level showing f that level is loaded in VRAM*/

bool LevelLoadedInRAM = false; /**<True/false for every level showing if that level is loaded in RAM*/
bool LevelLoadedInVRAM = false; /**<True/false for every level showing f that level is loaded in VRAM*/

bool AllocatedRAMBudget = false; /**<True/False indicating if the level has been allocated from the RAM budget*/
bool AllocatedVRAMBudget = false; /**<True/False indicating if the level has been allocated from the VRAM budget*/

std::pair<int, int> LevelResolution; /**<List of all texture level's resolutions*/

int LevelMemorySizeBytes; /**<Tells the system how many bytes every level will take*/

FIBITMAP* LevelBitmap; /**<List of bitmaps for each level - contains the texture's RAM data.*/

int LevelChannel; /**<List containing number of channels for every texture layer*/
int Level; /**<What level is this (used for sorting internally)*/

Expand Down

0 comments on commit 7ad8678

Please sign in to comment.