public sealed class ShaderGraphPreviewRendererOne node's expression, compiled and run over a quad, into a target that outlives the edit.
Remarks
Two tiers, and the split is the whole design. Turning a graph into Raven is string work over a handful of nodes and is done every time a preview is asked for — Compile. Turning that text into SPIR-V, a pipeline and a drawn target costs tens of milliseconds and is done only when the text changed. So moving a node, renaming a property, selecting, panning and zooming all emit the source that is already cached and cost nothing; typing a number into a port emits different source and costs one rebuild. That is the answer to "a shader compiled per keystroke is a stall": there is no keystroke that reaches the compiler without changing the expression.
⚠ And rebuilds are rationed as well. RebuildsPerUpdate is how many may happen in one frame; the rest wait. Pasting twenty nodes invalidates twenty previews and would otherwise be twenty compilations between two frames — visible as a freeze, during which the editor is doing work for pictures the author has not looked at yet.
The renderer owns every target, and there is one per node, not one per edit. A rebuild draws into the texture that is already there — the size never changes — so the number the interface holds stays valid and the picture changes underneath it. A node that is evicted or a renderer that is disposed unregisters the number first and destroys the texture second. Created and Destroyed are equal after Dispose, and a test asserts it: a claim about a leak that cannot be measured is one nobody can check.
⚠ Unlit, into a non-sRGB target, and neither is incidental. ShaderGraphPreview ends the closure at Master/Unlit, so the fragment writes the node's value straight out with no lighting, no exposure and no tone map, and Format is Rgba8UNorm rather than the sRGB form so nothing encodes it on the way in. What a preview shows is the number, which is the only thing that makes a preview worth looking at.
⚠ The quad is in clip space and its texture coordinate follows the engine's convention. Clip y = +1 is the top — Core/Vixen.Core.Mathematics/Conventions.md, and the Vulkan backend's negative-height viewport is what implements it — so the corner at y = +1 is given texcoord.y = 0 and the target's first row is the top of the picture. An interface image command therefore draws it unflipped, which is why NodePreview.FlipVertically is not set. A preview that came out upside down would be perfectly plausible to look at, so ShaderGraphPreviewDeviceTests asserts a corner rather than a histogram.
⚠ A node whose expression needs a resource gets no picture. The preview binds one uniform block holding the two transforms and nothing else — no textures, no samplers — so Texture/Sample 2D is refused rather than drawn as whatever an unbound descriptor reads as. Refusals counts them. Binding a material's textures means knowing which material, which is doc 08's material compiler and not a thumbnail's.
Fields and properties (12)
public const int SizeHow big a preview is, in pixels.
public const PixelFormat FormatWhat a preview target is, and what its pipeline is built for.
public int CapacityHow many nodes keep a target before the least recently asked for loses one.
public int RebuildsPerUpdateHow many previews may be rebuilt in one Update.
public int EmissionsHow many times a graph has been turned into Raven — the cheap tier.
public int CompilationsHow many times Raven has been compiled and a pipeline built — the expensive tier.
public int DrawsHow many previews have been drawn.
public int CreatedHow many targets have been created.
public int DestroyedHow many targets have been destroyed.
public int RefusalsHow many nodes were refused a picture, for a resource or a compile that failed.
public int LiveHow many previews are held.
public int PendingHow many are waiting to be rebuilt.
Methods (5)
public ShaderGraphPreviewRenderer(IGraphicsDevice device, NodeTypeRegistry registry, IPreviewImages? images = null)Builds a renderer on a device.
public bool TryGet(NodeGraphModel graph, GraphNode node, NodeTypeDefinition definition, out NodePreview preview)public int Update()Rebuilds what has been invalidated, up to RebuildsPerUpdate.
public void Dispose()public string? RefusalFor(NodeGraphModel graph, NodeId node)Why one node has no picture, or null when it has one or was never asked about.
Used by (6)
- EditorApplicationVixen.Editor.App
- EditorHostVixen.Editor.Host
- ShaderGraphDocumentVixen.Editor.AssetEditors
- ShaderGraphPreviewDeviceTestsVixen.Editor.ShaderGraph.Tests
- ShaderGraphPreviewLeakTestsVixen.Editor.ShaderGraph.Tests
- ShaderGraphViewTestsVixen.Editor.AssetEditors.Tests