Search Results for

    Show / Hide Table of Contents

    ResourceLayout

    A ResourceLayout declares the shape of a binding: which slots a shader reads, what kind of resource sits in each one, and which stages can see them. It carries no data of its own. The data arrives later, in a ResourceSet built against this layout.

    The same layout is referenced twice: once by the GraphicsPipeline or ComputePipeline that will run the shader, and once by every resource set you bind at draw time. That shared reference is how the backend knows a binding is valid before any command is recorded.

    Creation

    Build a ResourceLayoutDescription from one LayoutElementDescription per slot, then hand it to the factory:

    var layoutDescription = new ResourceLayoutDescription(
        new LayoutElementDescription(0, ResourceType.ConstantBuffer, ShaderStages.Vertex),
        new LayoutElementDescription(0, ResourceType.TextureView, ShaderStages.Pixel),
        new LayoutElementDescription(0, ResourceType.Sampler, ShaderStages.Pixel));
    
    var resourceLayout = this.graphicsContext.Factory.CreateResourceLayout(ref layoutDescription);
    

    ResourceLayoutDescription

    Property Type Description
    Elements LayoutElementDescription[] One entry per slot the shader reads. Order matters, because a resource set fills these by position.
    DynamicConstantBufferCount int Set by the constructor, which counts the elements that have AllowDynamicOffset. You do not assign it yourself.

    LayoutElementDescription

    Property Type Description
    Slot uint The register number inside its own namespace. A TextureView and a Sampler can both be slot 0.
    Type ResourceType What kind of resource fills this slot.
    Stages ShaderStages The stages that can read it. Combine flags to expose one resource to several stages.
    AllowDynamicOffset bool Lets you pass a byte offset when binding, instead of creating one buffer per draw. Constant buffers only. false by default.
    Range uint Overrides the size in bytes of this binding. 0 binds the whole buffer. Constant buffers only. Set through the constructor's size parameter.

    ResourceType

    ResourceType Description
    ConstantBuffer A Buffer read as a uniform buffer.
    StructuredBuffer A Buffer read as a read-only storage buffer.
    StructuredBufferReadWrite A Buffer a shader can also write to.
    TextureView A read-only view of a Texture.
    TextureViewReadWrite A view of a Texture a shader can also write to.
    Sampler A SamplerState.
    AccelerationStructure A ray tracing acceleration structure. See RaytracingPipeline.

    ShaderStages

    ShaderStages is a flags enum, so one element can be visible to several stages at once, as in ShaderStages.Vertex | ShaderStages.Pixel.

    ShaderStages Value Description
    Undefined 0 No stage.
    Vertex 1 Vertex shader.
    Hull 2 Hull shader.
    Domain 4 Domain shader.
    Geometry 8 Geometry shader.
    Pixel 16 Pixel shader.
    Compute 32 Compute shader.
    RayGeneration 64 Ray generation shader.
    Miss 128 Ray miss shader.
    ClosestHit 256 Closest hit shader.
    AnyHit 512 Any hit shader.
    Intersection 1024 Intersection shader.
    Mesh 2048 Mesh shader, from Shader Model 6.5.
    Amplification 4096 Amplification shader, from Shader Model 6.5.

    How a slot reaches the shader

    Two numbers decide where a resource lands. The Slot on the layout element is the register number, and the index you pass to SetResourceSet is the register space.

    How a resource set, a resource layout and the shader registers line up

    Each resource type has its own register namespace, so slot numbers only ever collide within a type. In HLSL those namespaces are b for constant buffers, t for read-only reads, u for read-write access and s for samplers.

    Important

    The elements in a layout and the resources in the set that fills it are matched by position, not by slot number. Reordering one array without the other silently binds the wrong resource.

    Group elements by how often they change

    A pipeline can take several layouts, and you bind each one to its own space. Splitting them by update frequency means the per-frame data is not rebound with every material:

    // One layout per update frequency...
    var perDrawDescription = new ResourceLayoutDescription(
        new LayoutElementDescription(0, ResourceType.ConstantBuffer, ShaderStages.Vertex, true, (uint)Unsafe.SizeOf<Matrix4x4>()));
    var perViewDescription = new ResourceLayoutDescription(
        new LayoutElementDescription(1, ResourceType.ConstantBuffer, ShaderStages.Vertex));
    var perMaterialDescription = new ResourceLayoutDescription(
        new LayoutElementDescription(2, ResourceType.ConstantBuffer, ShaderStages.Pixel),
        new LayoutElementDescription(0, ResourceType.TextureView, ShaderStages.Pixel),
        new LayoutElementDescription(0, ResourceType.Sampler, ShaderStages.Pixel));
    
    // ...and the pipeline lists them in the order they will be bound.
    var pipelineDescription = new GraphicsPipelineDescription()
    {
        ResourceLayouts = new[] { perDraw, perView, perMaterial },
        // ...
    };
    

    At draw time each set goes to the index that matches its position in that array:

    commandBuffer.SetResourceSet(this.resourceSetPerDraw, 0, new uint[] { this.stride * (uint)i });
    commandBuffer.SetResourceSet(this.resourceSetPerView, 1);
    commandBuffer.SetResourceSet(this.resourceSetPerMat, 2);
    
    Tip

    The first element above was declared with AllowDynamicOffset and an explicit size, which is what lets the third argument of SetResourceSet walk one shared constant buffer instead of allocating one per draw.

    Cleaning up

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