public sealed class DescriptorAllocatorDescriptor sets for one frame's worth of transient bindings, recycled rather than recreated.
No guide page documents this yet — the page shows what the code says about itself.
Remarks
The piece every frame-graph renderer needs and few write down. A pass that samples the shadow atlas cannot own a descriptor set: the atlas is a graph resource, so its texture handle does not exist until the graph has allocated it, and next frame the same name may alias different memory. The set therefore has to be written after the graph compiles and thrown away when the frame ends — which is a lifetime nothing else in the RHI has.
Sets are recycled, not destroyed. Creating and destroying a set per pass per frame is the allocation churn the handle-based RHI exists to avoid, and on Vulkan it is worse than it looks: vkResetDescriptorPool is cheap but vkAllocateDescriptorSets is not, and a pool that grows to fit the worst frame never shrinks. Here a retired set goes back to a free list keyed by its layout and is rewritten next time that layout is asked for.
The ring is FramesInFlight deep, and that is not a tuning knob. A set written for frame f is still being read by the GPU while the CPU records f + 1. Rewriting it before frame f retires points a descriptor the GPU is reading at something else — a use-after-free that most drivers execute without a word, and which the validation layers only catch with synchronisation validation switched on. The device already blocks in BeginFrame until frame f - FramesInFlight has completed, so a ring of exactly that depth is both necessary and sufficient.
Identical writes within a frame return the same set. The cache is content-addressed: the layout plus the exact sequence of DescriptorWrites. Every pass that reads the same shadow atlas and cluster buffer shares one set rather than getting one each, which is the difference between a set per pass and a set per distinct combination — in a real frame, two orders of magnitude. It also means the set you are handed may be shared, so never call UpdateDescriptorSet on it yourself; ask for another one with the writes you wanted.
The cache does not survive the frame, and that is the point rather than an oversight: the handles inside it name transient memory that the next frame's graph is free to give to something else. A cache that persisted would be correct exactly until two frames' graphs differed.
Fields and properties (4)
public int FramesInFlightHow deep the recycling ring is, which is the device's frames in flight.
public int SetCountHow many sets exist, across every layout and every ring slot.
public int WriteCountHow many sets this frame had to write, which is how many distinct binding combinations it used.
public int ReuseCountHow many requests this frame were answered out of the cache.
Methods (5)
public DescriptorAllocator(IGraphicsDevice device, string name = "Frame")Creates an allocator for a device.
public void BeginFrame()Starts a frame, taking back what the frame FramesInFlight ago used.
public DescriptorSetHandle Allocate(DescriptorSetLayoutHandle layout, ReadOnlySpan<DescriptorWrite> writes)A set of the given shape pointing at the given resources, for this frame only.
public void Reset()Takes every set back at once, whichever frame it belonged to.
public void Dispose()Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
Used by (64, showing 40)
- PbrShowcaseGamePbrShowcase
- VirtualGeometryGameVirtualGeometry
- AccelerationStructureDeviceTestsVixen.Graphics.Golden.Tests
- AutoExposureRendererVixen.Rendering.PostFx
- AutoExposureTestsVixen.Rendering.PostFx.Tests
- BindlessFrameTestsVixen.Rendering.Tests
- BloomRendererVixen.Rendering.PostFx
- BloomTestsVixen.Rendering.PostFx.Tests
- BoundBindingsVixen.Rendering
- BufferTransferDeviceTestsVixen.Graphics.Golden.Tests
- ClusterCullingDeviceTestsVixen.Graphics.Golden.Tests
- ClusteredLightingTestsVixen.Rendering.Tests
- ClusteredShadingDeviceTestsVixen.Graphics.Golden.Tests
- CompositorAssetTestsVixen.Rendering.Tests
- CompositorBuilderVixen.Rendering
- CompositorImageTestsVixen.Graphics.Golden.Tests
- DescriptorAllocatorTestsVixen.Graphics.Tests
- DescriptorBindingTestsVixen.Rendering.Tests
- DescriptorBindingsVixen.Rendering
- DistanceFieldAoImageTestsVixen.Graphics.Golden.Tests
- ForwardFrameTestsVixen.Rendering.Tests
- ForwardLightingRenderFeatureVixen.Rendering
- HarnessVixen.Rendering.Tests
- IndirectDiffuseImageTestsVixen.Graphics.Golden.Tests
- IrradianceBounceDeviceTestsVixen.Graphics.Golden.Tests
- IrradianceFieldFillVixen.Rendering
- IrradianceFieldRepairVixen.Rendering
- IrradianceFillDeviceTestsVixen.Graphics.Golden.Tests
- IrradianceRepairDeviceTestsVixen.Graphics.Golden.Tests
- IrradianceShadingDeviceTestsVixen.Graphics.Golden.Tests
- LensFlareRendererVixen.Rendering.PostFx
- LocalExposureRendererVixen.Rendering.PostFx
- MaterialBindingTestsVixen.Rendering.Tests
- MaterialRecordBufferTestsVixen.Rendering.Tests
- MaterialRenderFeatureVixen.Rendering
- MaterialTextureIndexTestsVixen.Rendering.Tests
- ParticleSpriteDeviceTestsVixen.Graphics.Golden.Tests
- PostEffectRendererVixen.Rendering.PostFx
- PostEffectTestsVixen.Rendering.PostFx.Tests
- PostProcessTestsVixen.Rendering.Tests