Substance 3D for Unreal Engine 5.8: packaged games always render with the SSE2 CPU engine, even with "GPU Engine" selected
Plugin: Substance in UE5, version 5.8.1 (plugin version 72), engine libraries 9.5.1, Marketplace build for Unreal Engine 5.8.2, Windows 64-bit.
Summary
With SubstanceEngine=SET_GPU in the project settings, packaged (non-editor) builds still compute every Substance render on the SSE2 CPU engine. The D3D11 engine is linked into the executable but never called. The cause is in Source/SubstanceEngine/SubstanceEngine.Build.cs: for non-editor targets the module links substance_framework_full.lib, which contains its own copy of the SSE2 engine (including substanceContextInitImpl, substanceGetCurrentVersionImpl and the SSE2 kernels). The linker resolves the framework's engine calls inside that library and never reaches substance_d3d11_blend_s.lib, which is added to the same link. The log line "Substance [GPU] Engine Loaded, Max Texture Size = 8192" only reflects the setting, not the engine that ends up running.
The Marketplace editor binaries have the same outcome for a different reason: GetEngineSuffix() in the same Build.cs reads the engine choice from the project's DefaultEngine.ini, and the prebuilt binaries were compiled without a project, so UnrealEditor-SubstanceCore.dll contains the SSE2 engine as well.
How we verified it
-
In a packaged Development build of our project (two graphs at 4096x8192 output size), a small test command creates a private
SubstanceAir::Rendereron the sbsar loaded from disk and logsRenderer::getCurrentVersion().platformImplName. It reportsSSE2, version 9.5.1. A cold render of one graph takes 5.8 s wall time and 66 CPU-seconds; sampling the process shows 16 worker threads started atalgThreadJobQueueThreadFuncrunning JIT-generated code. -
sbsrenderfrom Substance 3D Designer renders the same graph with the samesubstance_d3d11_blend.dllin 0.65 s. -
After copying the plugin into the project and changing only the non-editor branch of
SubstanceEngine.Build.cstoPublicDefinitions.Add("AIR_NO_DYNLOAD");PublicDefinitions.Add("AIR_NO_DEFAULT_ENGINE"); // added...StaticLibs.Add("substance_framework"); // was "substance_framework_full"the same test command reports
Direct3D 11 (x64)9.5.1, the cold render takes 0.9 s with a CPU/wall ratio of 1.0, and the plugin's normal render path (SetInputImg + AsyncRendering on both graphs) drops from about 10 s to about 1 s per design change.
Why it goes unnoticed
At the usual 1K or 2K output sizes the CPU engine is fast enough not to draw attention, and in the editor a plugin built from source with a project picks the right engine because the editor branch of the Build.cs already links substance_framework with AIR_NO_DEFAULT_ENGINE. Only packaged games and the prebuilt Marketplace editor binaries are affected.
Suggested fix
- Non-editor targets: link
substance_frameworkand defineAIR_NO_DEFAULT_ENGINE, as the editor branch does, so the engine selected byGetEngineSuffix()is the one that is actually used. Ifsubstance_framework_fullmust stay for platforms without a GPU engine, use it only when the CPU engine is selected. - Make the Marketplace editor binaries honour the GPU setting, or document that the plugin must be built from source inside the project for the GPU engine to be used in the editor.
- Log the engine actually in use (
Renderer::getCurrentVersion()) instead of the setting.
Environment: Windows 11 Pro 26300, NVIDIA GeForce RTX 3080 (driver from the 2026 DriverStore build nv_dispsi.inf_amd64_0cc79ee359bdef40), Unreal Engine 5.8.2 from the Epic launcher, Visual Studio 2022 toolchain, project uses SubstanceEngine=SET_GPU, MemoryBudgetMb=2048.
