RHI - Switching DX11, DX12, Vulkan during runtime

Because some of my graphics settings depend on it I want to be able to choose between DX11, DX12 and Vulkan from inside the game. As far as I know, this choice is stored simply as a string per platform:

FString DefaultGraphicsRHI;
GConfig->GetString(TEXT("/Script/WindowsTargetPlatform.WindowsTargetSettings"), TEXT("DefaultGraphicsRHI"), DefaultGraphicsRHI, GEngineIni);

How does UE4 / UE5 handle RHI these days? Is it still advised to let the end user set this mode manually, or can / should the engine get the most optimal mode automatically, based on for example the features (raytracing etc) + hardware compatibility + performance estimation? What is the correct RHI library to call for these things?

1 Like

bump

bump

bump.

:headstone:

Maybe take a look at the implmenetation of:

static IDynamicRHIModule* LoadDynamicRHIModule(ERHIFeatureLevel::Type& DesiredFeatureLevel, const TCHAR*& LoadedRHIModuleName)

in RHI/Windows/WindowsDynamicRHI.cpp:

RHI is chosen by the project settings (first DefaultGraphicsRHI, then TargetedRHIs are consulted, Default maps to D3D12). After this, a separate game-only setting (does not affect editor) bPreferD3D12InGame selects between D3D12 or D3D11 (but will not have any effect if Vulkan or OpenGL are chosen). Commandline switches apply after this and can force an arbitrary RHIs. If RHI isn’t supported, the game will refuse to start.

If you set a breakpoint on that call, you can see the call chain to get there.

1 Like

Thanks, this confirms that what I am currently doing in my code is correct.
I traced this back all the way to engine startup:

FEngineLoop::PreInit → RHIInit → PlatformCreateDynamicRHI → LoadDynamicRHIModule

and it’s a complex thing. It sure doesn’t look like it is meant to be modified later on.
I’m pretty sure some games allow swapping DX versions during gameplay without a restart but I can think of quite a few which don’t.

I assume this means I should just implement a user friendly way to notify that the game needs a restart.

Yeah, I don’t think folks would expect to be able to switch RHI without a restart.

How to switch at least WITH a restart?

1 Like
GConfig->SetString(TEXT("/Script/WindowsTargetPlatform.WindowsTargetSettings"), TEXT("DefaultGraphicsRHI"), TEXT("DefaultGraphicsRHI_DX12"), GEngineIni);

Or DefaultGraphicsRHI_DX11 Or DefaultGraphicsRHI_Vulkan.

Then flush GConfig and restart game.

GConfig->Flush(true, GEngineIni);

Thanks a bunch. I am developing with blueprints. Is it possible via console command or only c++?

I honestly don’t know, I like to avoid Blueprints and never tried. You’d need a node to read / write INI files. I’m not aware of console commands or libraries handling this. My initial thought was that there would be a function library for RHI handling this but I ended up writing to ini files. Some settings are blueprint accessable through the GameUserSettings library, it’s worth looking for an existing library on the web before implementing it yourself. There are a ton of different classes handling different settings, nothing seems centralized.