Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

373 fix loader segmentation fault #379

Merged
merged 20 commits into from
Sep 18, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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