View Issue Details

IDProjectCategoryView StatusLast Update
0004987NoesisGUIC++ SDKpublic2026-04-21 09:30
Reporterhugo_lucky Assigned Tohcpizzi  
PrioritynormalSeveritycrash 
Status resolvedResolutionfixed 
Product Version3.2.12 
Target Version3.2.13Fixed in Version3.2.13 
Summary0004987: NullRHI crash in NoesisInstance — FNoesisPosVS shader assert (UE 5.7, NoesisGUI 3.2.8)
Description

Hi Noesis team,

We're running into a fatal crash when launching a packaged UE 5.7 build with -NullRHI (headless mode for automated testing on CI). The crash happens the first time any Noesis UI widget initializes.

Error:

Assertion failed: Shader.IsValid() [File:GlobalShader.h] [Line: 192]
Failed to find shader type FNoesisPosVS in Platform PCD3D_SM6

Callstack:

FDebug::CheckVerifyFailedImpl2()
TShaderMapRef<FNoesisVS<0,0,0>>::TShaderMapRef() [Shader.h:2632]
FNoesisRenderDevice::FNoesisRenderDevice()        [NoesisRenderDevice.cpp:1055]
FNoesisRenderDevice::Get()                         [NoesisRenderDevice.cpp:1718]
UNoesisInstance::InitInstance (lambda)              [NoesisInstance.cpp:653]
  → ENQUEUE_RENDER_COMMAND(FNoesisInstance_InitRenderer)

Root cause:
UNoesisInstance::InitInstance unconditionally enqueues a render command that constructs FNoesisRenderDevice, which in its constructor resolves TShaderMapRef<FNoesisPosVS>. Under NullRHI, the global shader map for PCD3D_SM6 is not loaded, so the shader lookup asserts. There are no GUsingNullRHI or FApp::CanEverRender() guards anywhere in the NoesisGUI plugin source.

Why this matters:
NullRHI is the standard way to run UE automation tests headlessly on CI machines (no GPU required). Our QA bot runs the packaged game with -NullRHI -ExecCmds="Automation RunTests ..." and NoesisGUI crashes before any test can execute.

Our local fix (2 edits in NoesisInstance.cpp):

We applied these changes locally and tagged them with [NullRHI Patch] comments. Both are minimal and non-breaking for the normal rendering path.

Edit 1 — Init guard (~line 654 in InitInstance):

Wrapped the ENQUEUE_RENDER_COMMAND(FNoesisInstance_InitRenderer) block in a CanEverRender() check. When NullRHI is active, RenderDevice stays nullptr. The downstream render methods (UpdateRenderTree, RenderOffscreen, RenderOnscreen) already null-check RenderDevice and early-return, so this is safe.

// Before:

ENQUEUE_RENDER_COMMAND(FNoesisInstance_InitRenderer)
(
    [Renderer, Is3DWidget, NoesisSlateElement](FRHICommandListImmediate& RHICmdList)
    {
        FNoesisRenderDevice* RenderDevice = Is3DWidget ? FNoesisRenderDevice::GetLinear() : FNoesisRenderDevice::Get();
        Renderer->Init(RenderDevice);
        NoesisSlateElement->RenderDevice = RenderDevice;
        ...
    }
);

// After:

if (FApp::CanEverRender())
{
    ENQUEUE_RENDER_COMMAND(FNoesisInstance_InitRenderer)
    (
        [Renderer, Is3DWidget, NoesisSlateElement](FRHICommandListImmediate& RHICmdList)
        {
            FNoesisRenderDevice* RenderDevice = Is3DWidget ? FNoesisRenderDevice::GetLinear() : FNoesisRenderDevice::Get();
            Renderer->Init(RenderDevice);
            NoesisSlateElement->RenderDevice = RenderDevice;
            ...
        }
    );
}

Edit 2 — Destructor guard (~line 163 in ~FNoesisSlateElement):

Since Renderer->Init() is never called under NullRHI, calling Renderer->Shutdown() in the destructor is unsafe. We guard it behind RenderDevice != nullptr which acts as a reliable proxy for "was the renderer initialized?".

// Before:

~FNoesisSlateElement()
{
    check(IsInRenderingThread());
    Renderer->Shutdown();
}

// After:

~FNoesisSlateElement()
{
    check(IsInRenderingThread());
    if (RenderDevice != nullptr)
    {
        Renderer->Shutdown();
    }
}

What still works under NullRHI with this patch:

XAML tree creation, layout, and measure passes
Data bindings and view model property changes
Events, commands, and input routing
All game logic that interacts with UI state
What does not work (expected):

No visual rendering output
We'd love to see this guard (or equivalent) included in a future NoesisGUI release so we don't have to re-apply it on every plugin update. Happy to provide any additional details.

Thanks!

PlatformAny

Activities

hcpizzi

hcpizzi

2026-04-21 09:30

developer   ~0012235

Thank you for the detailed report. I've applied your suggested changes.

Issue History

Date Modified Username Field Change
2026-04-14 19:43 hugo_lucky New Issue
2026-04-15 10:57 sfernandez Assigned To => hcpizzi
2026-04-15 10:57 sfernandez Status new => assigned
2026-04-15 10:57 sfernandez Product Version => 3.2.12
2026-04-15 10:57 sfernandez Target Version => 3.2.13
2026-04-15 10:57 sfernandez Description Updated
2026-04-15 10:58 sfernandez Description Updated
2026-04-15 10:58 sfernandez Description Updated
2026-04-21 09:30 hcpizzi Status assigned => resolved
2026-04-21 09:30 hcpizzi Resolution open => fixed
2026-04-21 09:30 hcpizzi Fixed in Version => 3.2.13
2026-04-21 09:30 hcpizzi Note Added: 0012235