Direct3D11: Support running out of memory when creating textures (partially)

Failures in mipmap creation, shader resource view creation etc will still cause program exit
This commit is contained in:
UnknownShadow200 2022-02-26 21:38:36 +11:00
parent 4f79864d5e
commit 4377c46826
4 changed files with 25 additions and 14 deletions

View File

@ -141,6 +141,17 @@ void Game_CycleViewDistance(void) {
} }
} }
cc_bool Game_ReduceVRAM(void) {
if (Game_UserViewDistance <= 16) return false;
Game_UserViewDistance /= 2;
Game_UserViewDistance = max(16, Game_UserViewDistance);
MapRenderer_Refresh();
Game_SetViewDistance(Game_UserViewDistance);
Chat_AddRaw("&cOut of VRAM! Halving view distance..");
return true;
}
void Game_SetViewDistance(int distance) { void Game_SetViewDistance(int distance) {
distance = min(distance, Game_MaxViewDistance); distance = min(distance, Game_MaxViewDistance);
@ -263,16 +274,6 @@ static void HandleOnNewMapLoaded(void* obj) {
} }
} }
static void HandleLowVRAMDetected(void* obj) {
if (Game_UserViewDistance <= 16) Logger_Abort("Out of video memory!");
Game_UserViewDistance /= 2;
Game_UserViewDistance = max(16, Game_UserViewDistance);
MapRenderer_Refresh();
Game_SetViewDistance(Game_UserViewDistance);
Chat_AddRaw("&cOut of VRAM! Halving view distance..");
}
static void HandleInactiveChanged(void* obj) { static void HandleInactiveChanged(void* obj) {
if (WindowInfo.Inactive) { if (WindowInfo.Inactive) {
Chat_AddRaw(LOWPERF_ENTER_MESSAGE); Chat_AddRaw(LOWPERF_ENTER_MESSAGE);
@ -373,7 +374,6 @@ static void Game_Load(void) {
Event_Register_(&WorldEvents.NewMap, NULL, HandleOnNewMap); Event_Register_(&WorldEvents.NewMap, NULL, HandleOnNewMap);
Event_Register_(&WorldEvents.MapLoaded, NULL, HandleOnNewMapLoaded); Event_Register_(&WorldEvents.MapLoaded, NULL, HandleOnNewMapLoaded);
Event_Register_(&GfxEvents.LowVRAMDetected, NULL, HandleLowVRAMDetected);
Event_Register_(&WindowEvents.Resized, NULL, Game_OnResize); Event_Register_(&WindowEvents.Resized, NULL, Game_OnResize);
Event_Register_(&WindowEvents.Closing, NULL, Game_Free); Event_Register_(&WindowEvents.Closing, NULL, Game_Free);
Event_Register_(&WindowEvents.InactiveChanged, NULL, HandleInactiveChanged); Event_Register_(&WindowEvents.InactiveChanged, NULL, HandleInactiveChanged);

View File

@ -55,6 +55,9 @@ extern const char* const FpsLimit_Names[FPS_LIMIT_COUNT];
void Game_ToggleFullscreen(void); void Game_ToggleFullscreen(void);
void Game_CycleViewDistance(void); void Game_CycleViewDistance(void);
/* Attempts to reduce VRAM usage (e.g. reducing view distance) */
/* Returns false if VRAM cannot be reduced any further */
cc_bool Game_ReduceVRAM(void);
void Game_SetViewDistance(int distance); void Game_SetViewDistance(int distance);
void Game_UserSetViewDistance(int distance); void Game_UserSetViewDistance(int distance);

View File

@ -239,8 +239,16 @@ GfxResourceID Gfx_CreateTexture(struct Bitmap* bmp, cc_uint8 flags, cc_bool mipm
src = NULL; src = NULL;
} }
hr = ID3D11Device_CreateTexture2D(device, &desc, src, &tex); while ((hr = ID3D11Device_CreateTexture2D(device, &desc, src, &tex)))
if (hr) Logger_Abort2(hr, "Failed to create texture"); {
if (hr == E_OUTOFMEMORY) {
// insufficient VRAM or RAM left
if (!Game_ReduceVRAM()) return NULL;
} else {
// unknown issue, do not even try to handle it
Logger_Abort2(hr, "Failed to create texture");
}
}
hr = ID3D11Device_CreateShaderResourceView(device, tex, NULL, &view); hr = ID3D11Device_CreateShaderResourceView(device, tex, NULL, &view);
if (hr) Logger_Abort2(hr, "Failed to create view"); if (hr) Logger_Abort2(hr, "Failed to create view");

View File

@ -238,7 +238,7 @@ static cc_bool D3D9_CheckResult(cc_result res, const char* func) {
if (!res) return true; if (!res) return true;
if (res == D3DERR_OUTOFVIDEOMEMORY || res == E_OUTOFMEMORY) { if (res == D3DERR_OUTOFVIDEOMEMORY || res == E_OUTOFMEMORY) {
Event_RaiseVoid(&GfxEvents.LowVRAMDetected); if (!Game_ReduceVRAM()) Logger_Abort("Out of video memory!");
} else { } else {
Logger_Abort2(res, func); Logger_Abort2(res, func);
} }