Search Results for

    Show / Hide Table of Contents

    ResourceSet

    A ResourceSet is the other half of a binding. Where a ResourceLayout declares which slots exist, a resource set puts real objects in them. You create one per combination of resources you want to bind, and swap between them at draw time.

    Sets are immutable once created. To point a slot at a different texture, create another set rather than editing this one.

    Creation

    A set is built from the layout it fills and the resources that fill it:

    var resourceSetDescription = new ResourceSetDescription(resourceLayout, constantBuffer, texture, sampler);
    var resourceSet = this.graphicsContext.Factory.CreateResourceSet(ref resourceSetDescription);
    

    ResourceSetDescription

    Property Type Description
    Layout ResourceLayout The layout this set fills. Required.
    Resources GraphicsResource[] One resource per element of the layout, in the same order.

    What goes in each slot

    The type declared on the layout element decides which object the set expects:

    Layout declares Pass an instance of
    ConstantBuffer Buffer created with BufferFlags.ConstantBuffer
    StructuredBuffer Buffer created with BufferFlags.ShaderResource and BufferFlags.BufferStructured
    StructuredBufferReadWrite Buffer created with BufferFlags.UnorderedAccess
    TextureView Texture, or a TextureView over one
    TextureViewReadWrite Texture created with TextureFlags.UnorderedAccess, or a TextureView over one
    Sampler SamplerState
    AccelerationStructure TopLevelAS. See RaytracingPipeline

    Passing a Texture where the layout says TextureView is the common case, and the backend uses that texture's DefaultView. Create an explicit view when you need a subrange of mip levels or array slices, or a different but compatible pixel format.

    Important

    Resources are matched to layout elements by position. The set does not look at slot numbers to work out where each resource belongs, so the two arrays have to be written in the same order.

    A slot may be left empty by passing null, which is useful when one layout serves several materials and some of them have no texture in a given slot. The shader still has to cope with reading nothing there.

    Binding

    Bind a set to the index of the layout it was built from, counting positions in the pipeline's ResourceLayouts array:

    commandBuffer.SetResourceSet(this.resourceSetPerDraw, 0);
    commandBuffer.SetResourceSet(this.resourceSetPerView, 1);
    commandBuffer.SetResourceSet(this.resourceSetPerMat, 2);
    

    When a set is bound to index 0 and its layout has no other consumer, the index can be left out.

    Dynamic offsets

    An element declared with AllowDynamicOffset takes a byte offset at bind time, so one large constant buffer can serve many draws:

    for (int i = 0; i < instanceCount; i++)
    {
        commandBuffer.SetResourceSet(this.resourceSet, 0, new uint[] { this.stride * (uint)i });
        commandBuffer.Draw(vertexCount);
    }
    

    The offsets array carries one entry per element of the layout that allows a dynamic offset, in the order those elements appear. ResourceLayoutDescription.DynamicConstantBufferCount tells you how many the layout expects.

    Note

    A dynamic offset has to be a multiple of the constant buffer alignment the device reports, and that figure is not the same everywhere. Round your stride up to a power of two large enough for every device you target rather than packing structures tightly.

    Sets carry their own barriers

    Creating a set records, for every resource in it, the state that resource has to be in for the shader to read it. The render pipeline uses that precomputed list to transition resources without walking the set again each frame.

    Layout declares State the resource is transitioned to
    ConstantBuffer Buffer.StateFlags.UniformBuffer
    StructuredBuffer, AccelerationStructure Buffer.StateFlags.ShaderResource
    StructuredBufferReadWrite Buffer.StateFlags.UnorderedAccess
    TextureView Texture.StateFlags.PixelShaderResource, NonPixelShaderResource, or both, depending on the element's Stages
    TextureViewReadWrite Texture.StateFlags.UnorderedAccess

    CollectBarriers exposes that list if you are writing your own submission code:

    var bufferBarriers = new List<Buffer.Barrier>();
    var textureBarriers = new List<Texture.Barrier>();
    resourceSet.CollectBarriers(bufferBarriers, textureBarriers);
    
    commandBuffer.Barrier(CollectionsMarshal.AsSpan(bufferBarriers), CollectionsMarshal.AsSpan(textureBarriers));
    

    See Barriers for when those transitions have to be recorded.

    Cleaning up

    A set does not own the resources inside it. Disposing it leaves the buffers, textures and samplers alive for other sets to use.

    resourceSet.Dispose();
    
    In this article
    Back to top
    Generated by DocFX