KernelPipelineForge

The path tracer's kernel pipeline, compiled by the driver on a helper device in a thread of its own (construct-owner-feedback row 6.4).

In the namespace construct::pathtrace. Declared in src/libs/libconstruct/construct/pathtrace/KernelPipelineForge.hpp.

Detailed description

The driver's compile of the kernel is the cost of QRhiComputePipeline:: create(): 15.0 s, 14.5 s and 15.2 s on the RTX 5070 in the owner's log of 2026-10-21, on the viewport's render thread. The viewport sent no frame for all of that time, and its queued commands waited up to 9.4 s.

A second device does not help by itself. A pipeline cached by the driver on one device is a hit on another only through the driver's own disk cache. When that cache is full, as the owner's 1.1 GB cache was, the second device compiled again: 4.2 s and then 3.9 s for one kernel, and 20 ms with an empty cache (measured on y8, 2026-10-21). So the forge carries the result itself, in the pipeline cache data (QRhi:: pipelineCacheData()):

  1. submit(), on the render thread: export the device's cache and read the binding layout of the kernel's bindings.
  2. On the forge's thread: make a helper QRhi on the same physical device, prime it with the export, make placeholder resources of the same layout, and create the pipeline. Export the helper's cache, which now holds the old entries and the kernel.
  3. The engine, on the render thread, puts that cache into its device (QRhi::setPipelineCacheData()) and creates the pipeline: a cache hit.

Qt replaces a cache and never merges two. The engine compares the device's pipeline creation time (QRhiStats::totalPipelineCreationTime) with the one at submit(). When it changed, the device compiled other pipelines meanwhile, and the engine puts its own cache back after the create (PathTraceEngine::ensureResources()).

Vulkan only: supports() is false for another backend, and the engine creates on the render thread as before. Qt's Direct3D 12 backend keeps no pipeline cache (qrhid3d12.cpp). Its driver caches per device, so a helper QRhi that adopts the viewport's ID3D12Device can warm the kernel the way rhi::PipelineWarmer warms graphics pipelines; that is not done yet.

The thread is one for the process. It stops, and waits for a compile in progress, when the application's event loop ends and at the latest when the application object goes (qAddPostRoutine), before Qt's Vulkan instance goes with it.

Row 8.16 gave the forge graphics pipelines too: submitGraphics() takes the templates of rhi::PipelineWarmer, and the helper creates them with rhi::PipelineWarmer::createOn(). SDFLayer's forward, geometry and shading pipelines go through it. Site is the render thread's side of one create site: when to submit, when to wait, and how the device takes the result.

In this section