UE 5.6.1 D3D12: Nsight Perf SDK fails with NVPA_STATUS_INVALID_CONTEXT_STATE during HTML Report generation

I’m experiencing issues with Nsight Perf SDK integration in Unreal Engine 5. I tried to use HTMLReport and I inserted code like this

void FD3D12DynamicRHI::RHIEndFrame_RenderThread(FRHICommandListImmediate& RHICmdList)
{

	// Close the GPU profiler frame
#if (RHI_NEW_GPU_PROFILER == 0)
	RHICmdList.EnqueueLambdaMultiPipe(GetEnabledRHIPipelines(), FRHICommandListBase::EThreadFence::Enabled, TEXT("D3D12 EndFrame"),
		[this](FD3D12ContextArray const& Contexts)
	{
		for (auto& Adapter : ChosenAdapters)
		{
			for (auto& Device : Adapter->GetDevices())
			{
				Device->GetGPUProfiler().EndFrame();
			}
		}

#if WITH_NVPERF
		// NVPerf: OnFrameEnd - called after GPU Profiler EndFrame
		if (FNVPerfIntegrationModule::IsAvailable())
		{
			FNVPerfIntegrationModule& NVPerfModule = FNVPerfIntegrationModule::Get();
			NVPerfModule.OnFrameEnd(); //a warpper, it call nv::perf::profiler::ReportGeneratorD3D12::OnFrameEnd() inside
		}
#endif
	});
#endif
	
	
	for (auto& Adapter : ChosenAdapters)
	{
		Adapter->GetFrameFence().AdvanceTOP();
	}

	// Base implementation flushes all prior work and results in a bottom-of-pipe call to RHIEndFrame() on the RHI thread.
	FDynamicRHI::RHIEndFrame_RenderThread(RHICmdList);

	RHICmdList.EnqueueLambdaMultiPipe(GetEnabledRHIPipelines(), FRHICommandListBase::EThreadFence::Enabled, TEXT("D3D12 BeginFrame"),
		[this](FD3D12ContextArray const& Contexts)
	{
		for (auto& Adapter : ChosenAdapters)
		{
			for (auto& Device : Adapter->GetDevices())
			{
				Device->GetDefaultBufferAllocator().BeginFrame(Contexts);
				Device->GetTextureAllocator().BeginFrame(Contexts);

#if D3D12_RHI_RAYTRACING
				// @todo dev-pr - explicit use of graphics context - nothing is synchronizing async compute - needs refactor
				Device->GetRayTracingCompactionRequestHandler()->Update(*Contexts[ERHIPipeline::Graphics]->GetSingleDeviceContext(Device->GetGPUIndex()));
#endif // D3D12_RHI_RAYTRACING

#if (RHI_NEW_GPU_PROFILER == 0)
				Device->GetGPUProfiler().BeginFrame();//a warpper, it call nv::perf::profiler::ReportGeneratorD3D12::OnFrameStart() inside
#endif

			}
		}

#if WITH_NVPERF
		// NVPerf: OnFrameStart - called after GPU Profiler BeginFrame
		if (FNVPerfIntegrationModule::IsAvailable())
		{
			FNVPerfIntegrationModule& NVPerfModule = FNVPerfIntegrationModule::Get();
			ID3D12CommandQueue* CommandQueue = this->RHIGetCommandQueue();
			if (CommandQueue)
			{
				NVPerfModule.OnFrameBegin(CommandQueue);
			}
		}
#endif
	});
}

StartCollectionOnNextFrame was called by a console command at runtime.

however, I encountered such error:

Cmd: r.NVPerf.CaptureReport
LogNVPerf: Display: NVPerf HTML report capture started. Report will be generated on next frame.
LogNVPerf: Error: [NVPERF|ERR|] nv::perf::profiler::ReportGeneratorD3D12::BeginSessionWithOptions: sessionOptions == m_defaultSessionOptions
LogNVPerf: Error: [NVPERF|ERR|] nv::perf::profiler::RangeProfilerD3D12::BeginSession: NVPW_D3D12_Profiler_Queue_BeginSession , numTraceBuffers = 5, traceBufferSize = 90112, maxRangesPerPass = 128, maxLaunchesPerPass = 128
LogNVPerf: Error: [NVPERF|ERR|] nv::perf::profiler::RangeProfilerD3D12::BeginSession: Failed to start profiler session: unknown error, nvpaStatus = NVPA_STATUS_INVALID_CONTEXT_STATE(UNUSED) (18)
LogNVPerf: Error: [NVPERF|ERR|] nv::perf::profiler::ReportGeneratorD3D12::BeginSessionWithOptions: m_reportProfiler.rangeProfiler.BeginSession failed
LogNVPerf: Error: [NVPERF|ERR|] nv::perf::profiler::ReportGeneratorStateMachine::OnFrameStart: BeginSession failed

I have redirected the SDK’s internal output to the UE log and added some additional debug logging to help trace the issue. I’ve also tried moving the logic to different parts of the frame lifecycle, but it had no effect.
I am currently using UE 5.6.1. Any help or insights would be greatly appreciated.

By the way, nvperf has been sucessfully Initialized before

NVPERF|INF|2026-Jan-16|16:06:50:213|nv::perf::profiler::ReportGeneratorD3D12::InitializeReportGenerator || Initialization succeeded

Hello, @MingLiGu . The D3D12 Range Profiler may return INVALID_CONTEXT_STATE when any of these conditions are encountered:

  • The D3D12 Debug Layer is enabled
  • You’ve called NVPW_D3D12_Profiler_Queue_BeginPass() on a queue that is already in a pass.
  • You’ve called NVPW_D3D12_Profiler_Queue_EndPass() on a queue that is not currently in a pass.

I suspect you’re facing the first condition, so try using dxcpl.exe to force the D3D12 Debug Layer off before launching your UE5 app. After making sure that it is disabled, make sure that you also have Profiling Permissions enabled in the NVIDIA Control Panel / NVIDIA App settings. Otherwise, you may come across NVPA_STATUS_INSUFFICIENT_PRIVILEGE.

Let us know if this solves your current issue.

I fixed the bug by upgrading from Windows10 to Windows 11, so I’m not certain if the D3D12 Debug Layer was the cause. Thanks for your help anyway.

Thats a good idea anyway. Microsoft officially deprecated support for Windows 10 in October.