Skip to content

KDGpu::BindGroupLayout

Module: Public API

Describes the structure of shader resource bindings (descriptor set layout) More...

#include <KDGpu/bind_group_layout.h>

Public Functions

Name
BindGroupLayout()
~BindGroupLayout()
BindGroupLayout(BindGroupLayout && other)
BindGroupLayout & operator=(BindGroupLayout && other)
BindGroupLayout(const BindGroupLayout & ) =delete
BindGroupLayout & operator=(const BindGroupLayout & ) =delete
const Handle< BindGroupLayout_t > & handle() const
bool isValid() const
operator Handle< BindGroupLayout_t >() const
bool isCompatibleWith(const Handle< BindGroupLayout_t > & other) const

Friends

Name
class Device
KDGPU_EXPORT bool operator==(const BindGroupLayout & a, const BindGroupLayout & b)

Detailed Description

1
class KDGpu::BindGroupLayout;

Describes the structure of shader resource bindings (descriptor set layout)

Vulkan equivalent:VkDescriptorSetLayout

BindGroupLayout defines the types and configuration of resources that shaders expect at each binding point. It's the template from which actual BindGroups are created.

Key features:

  • Declare binding types (uniform, storage, texture, sampler)
  • Specify shader stages that access each binding
  • Define binding numbers matching shader declarations
  • Reusable template for creating bind groups

Lifetime: BindGroupLayouts are created by Device and must remain valid while referenced by pipeline layouts or bind groups. They use RAII and clean up automatically.

Usage

Creating a basic bind group layout:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
    KDGpu::BindGroupLayout layout = device.createBindGroupLayout(KDGpu::BindGroupLayoutOptions{
            .bindings = {
                    {
                            // Binding 0: uniform buffer
                            .binding = 0,
                            .resourceType = KDGpu::ResourceBindingType::UniformBuffer,
                            .shaderStages = KDGpu::ShaderStageFlags(KDGpu::ShaderStageFlagBits::VertexBit),
                    },
                    {
                            // Binding 1: combined image sampler
                            .binding = 1,
                            .resourceType = KDGpu::ResourceBindingType::CombinedImageSampler,
                            .shaderStages = KDGpu::ShaderStageFlags(KDGpu::ShaderStageFlagBits::FragmentBit),
                    },
            },
    });

Filename: kdgpu_doc_snippets.cpp

Multi-stage access(vertex + fragment):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
    KDGpu::BindGroupLayout layout5 = device.createBindGroupLayout(KDGpu::BindGroupLayoutOptions{
            .bindings = {
                    {
                            // Used in vertex shader only
                            .binding = 0,
                            .resourceType = KDGpu::ResourceBindingType::UniformBuffer,
                            .shaderStages = KDGpu::ShaderStageFlags(KDGpu::ShaderStageFlagBits::VertexBit),
                    },
                    {
                            // Used in both vertex and fragment
                            .binding = 1,
                            .resourceType = KDGpu::ResourceBindingType::UniformBuffer,
                            .shaderStages = KDGpu::ShaderStageFlags(KDGpu::ShaderStageFlagBits::VertexBit |
                                                                    KDGpu::ShaderStageFlagBits::FragmentBit),
                    },
                    {
                            // Fragment only
                            .binding = 2,
                            .resourceType = KDGpu::ResourceBindingType::CombinedImageSampler,
                            .shaderStages = KDGpu::ShaderStageFlags(KDGpu::ShaderStageFlagBits::FragmentBit),
                    },
            },
    });

Filename: kdgpu_doc_snippets.cpp

Storage buffer layout(compute shader):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
    KDGpu::BindGroupLayout computeLayout = device.createBindGroupLayout(KDGpu::BindGroupLayoutOptions{
            .bindings = {
                    {
                            // Input storage buffer
                            .binding = 0,
                            .resourceType = KDGpu::ResourceBindingType::StorageBuffer,
                            .shaderStages = KDGpu::ShaderStageFlags(KDGpu::ShaderStageFlagBits::ComputeBit),
                    },
                    {
                            // Output storage buffer
                            .binding = 1,
                            .resourceType = KDGpu::ResourceBindingType::StorageBuffer,
                            .shaderStages = KDGpu::ShaderStageFlags(KDGpu::ShaderStageFlagBits::ComputeBit),
                    },
            },
    });

Filename: kdgpu_doc_snippets.cpp

Texture array binding:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
    KDGpu::BindGroupLayout layout2 = device.createBindGroupLayout(KDGpu::BindGroupLayoutOptions{
            .bindings = {
                    {
                            // Array of 16 textures
                            .binding = 0,
                            .count = 16,
                            .resourceType = KDGpu::ResourceBindingType::CombinedImageSampler,
                            .shaderStages = KDGpu::ShaderStageFlags(KDGpu::ShaderStageFlagBits::FragmentBit),
                    },
            },
    });

Filename: kdgpu_doc_snippets.cpp

Storage image layout(compute output):

1
2
3
4
5
6
7
8
9
    KDGpu::BindGroupLayout layout4 = device.createBindGroupLayout(KDGpu::BindGroupLayoutOptions{
            .bindings = {
                    {
                            .binding = 0,
                            .resourceType = KDGpu::ResourceBindingType::StorageImage,
                            .shaderStages = KDGpu::ShaderStageFlags(KDGpu::ShaderStageFlagBits::ComputeBit),
                    },
            },
    });

Filename: kdgpu_doc_snippets.cpp

Dynamic uniform buffer:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
    KDGpu::BindGroupLayout layout3 = device.createBindGroupLayout(KDGpu::BindGroupLayoutOptions{
            .bindings = {
                    {
                            .binding = 0,
                            .resourceType = KDGpu::ResourceBindingType::DynamicUniformBuffer,
                            .shaderStages = KDGpu::ShaderStageFlags(KDGpu::ShaderStageFlagBits::VertexBit),
                    },
            },
    });

    // When binding, provide dynamic offset
    // renderPass.setBindGroup(0, bindGroup, { offsetInBuffer });

Filename: kdgpu_doc_snippets.cpp

Bindless rendering (large descriptor arrays):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
    KDGpu::BindGroupLayout bindlessLayout = device.createBindGroupLayout(KDGpu::BindGroupLayoutOptions{
            .bindings = {
                    {
                            .binding = 0,
                            .count = 1000, // Large descriptor array
                            .resourceType = KDGpu::ResourceBindingType::SampledImage,
                            .shaderStages = KDGpu::ShaderStageFlags(KDGpu::ShaderStageFlagBits::FragmentBit),
                    },
            },
    });

Filename: kdgpu_doc_snippets.cpp

Checking layout compatibility:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
    // These layouts are compatible because bindings match
    KDGpu::BindGroupLayout layout1a = device.createBindGroupLayout(KDGpu::BindGroupLayoutOptions{
            .bindings = {
                    {
                            .binding = 0,
                            .resourceType = KDGpu::ResourceBindingType::UniformBuffer,
                            .shaderStages = KDGpu::ShaderStageFlags(KDGpu::ShaderStageFlagBits::VertexBit),
                    },
            },
    });

    KDGpu::BindGroupLayout layout2a = device.createBindGroupLayout(KDGpu::BindGroupLayoutOptions{
            .bindings = {
                    {
                            .binding = 0,
                            .resourceType = KDGpu::ResourceBindingType::UniformBuffer,
                            .shaderStages = KDGpu::ShaderStageFlags(KDGpu::ShaderStageFlagBits::VertexBit),
                    },
            },
    });

    // BindGroups created with layout1 can be used with pipelines created with layout2

Filename: kdgpu_doc_snippets.cpp

Corresponding shader code(GLSL): Shader declarations must match bind group layout bindings. Example showing multiple descriptor sets:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
// Set 0 (frame data)
layout(set = 0, binding = 0) uniform FrameUBO
{
    mat4 view;
    mat4 projection;
} frame;

// Set 1 (material data)
layout(set = 1, binding = 0) uniform sampler2D albedoMap;
layout(set = 1, binding = 1) uniform sampler2D normalMap;
layout(set = 1, binding = 2) uniform sampler2D roughnessMap;

// Set 2 (object data)
layout(set = 2, binding = 0) uniform ObjectUBO
{
    mat4 model;
} object;

would match with:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
    // Layout for set 0
    KDGpu::BindGroupLayout frameBindGroupLayout = device.createBindGroupLayout(KDGpu::BindGroupLayoutOptions{
            .bindings = {
                    {
                            .binding = 0,
                            .resourceType = KDGpu::ResourceBindingType::UniformBuffer,
                            .shaderStages = KDGpu::ShaderStageFlags(KDGpu::ShaderStageFlagBits::VertexBit),
                    },
            },
    });

    // Layout for set 1
    KDGpu::BindGroupLayout materialBindGroupLayout = device.createBindGroupLayout(KDGpu::BindGroupLayoutOptions{
            .bindings = {
                    {
                            .binding = 0,
                            .resourceType = KDGpu::ResourceBindingType::CombinedImageSampler,
                            .shaderStages = KDGpu::ShaderStageFlags(KDGpu::ShaderStageFlagBits::VertexBit),
                    },
                    {
                            .binding = 1,
                            .resourceType = KDGpu::ResourceBindingType::CombinedImageSampler,
                            .shaderStages = KDGpu::ShaderStageFlags(KDGpu::ShaderStageFlagBits::VertexBit),
                    },
                    {
                            .binding = 2,
                            .resourceType = KDGpu::ResourceBindingType::CombinedImageSampler,
                            .shaderStages = KDGpu::ShaderStageFlags(KDGpu::ShaderStageFlagBits::VertexBit),
                    },
            },
    });

    // Layout for set 2
    KDGpu::BindGroupLayout objectBindGroupLayout = device.createBindGroupLayout(KDGpu::BindGroupLayoutOptions{
            .bindings = {
                    {
                            .binding = 0,
                            .resourceType = KDGpu::ResourceBindingType::UniformBuffer,
                            .shaderStages = KDGpu::ShaderStageFlags(KDGpu::ShaderStageFlagBits::VertexBit),
                    },
            },
    });

    KDGpu::PipelineLayout pipelineLayout = device.createPipelineLayout(KDGpu::PipelineLayoutOptions{
            .bindGroupLayouts = {
                    frameBindGroupLayout,
                    materialBindGroupLayout,
                    objectBindGroupLayout,
            },
    });

Filename: kdgpu_doc_snippets.cpp

Vulkan mapping:

  • BindGroupLayout creation->vkCreateDescriptorSetLayout()
  • Used in VkPipelineLayoutCreateInfo
  • Used in VkDescriptorSetAllocateInfo

See also:

BindGroup, BindGroupLayoutOptions, PipelineLayout, Device, BindGroupPool

KDGpu API Overview

KDGpu to Vulkan API Mapping

Public Functions Documentation

function BindGroupLayout

1
BindGroupLayout()

function ~BindGroupLayout

1
~BindGroupLayout()

function BindGroupLayout

1
2
3
BindGroupLayout(
    BindGroupLayout && other
)

function operator=

1
2
3
BindGroupLayout & operator=(
    BindGroupLayout && other
)

function BindGroupLayout

1
2
3
BindGroupLayout(
    const BindGroupLayout & 
) =delete

function operator=

1
2
3
BindGroupLayout & operator=(
    const BindGroupLayout & 
) =delete

function handle

1
inline const Handle< BindGroupLayout_t > & handle() const

function isValid

1
inline bool isValid() const

function operator Handle< BindGroupLayout_t >

1
inline operator Handle< BindGroupLayout_t >() const

function isCompatibleWith

1
2
3
bool isCompatibleWith(
    const Handle< BindGroupLayout_t > & other
) const

Checks whether this BindGroupLayout is compatible with other.

Friends

friend Device

1
2
3
friend class Device(
    Device 
);

friend operator==

1
2
3
4
5
friend KDGPU_EXPORT bool operator==(
    const BindGroupLayout & a,

    const BindGroupLayout & b
);

Updated on 2026-03-31 at 00:02:07 +0000