八、 资源绑定

77 阅读13分钟

8.1. GPUBindGroupLayout

GPUBindGroupLayout 定义了一组资源在 GPUBindGroup 中的绑定方式,以及在着色器阶段中它们的可访问性。

[Exposed=(Window, DedicatedWorker), SecureContext]
interface GPUBindGroupLayout {
};

GPUBindGroupLayout 包含了 GPUObjectBase,它有以下内部属性:

  • [[descriptor]]: 类型为 GPUBindGroupLayoutDescriptor

8.1.1. 创建绑定组布局

通过 GPUDevice.createBindGroupLayout() 方法创建 GPUBindGroupLayout。

dictionary GPUBindGroupLayoutDescriptor : GPUObjectDescriptorBase {
  required sequence<GPUBindGroupLayoutEntry> entries;
};

dictionary GPUBindGroupLayoutEntry {
  required GPUIndex32 binding;
  required GPUShaderStageFlags visibility;

  GPUBufferBindingLayout buffer;
  GPUSamplerBindingLayout sampler;
  GPUTextureBindingLayout texture;
  GPUStorageTextureBindingLayout storageTexture;
  GPUExternalTextureBindingLayout externalTexture;
};
  • GPUBindGroupLayoutDescriptor 描述符用于定义 GPUBindGroupLayout。
  • GPUBindGroupLayoutEntry 用于描述要包含在 GPUBindGroupLayout 中的单个着色器资源绑定。

GPUBindGroupLayoutEntry 字典包含以下成员:

  • binding,类型为 GPUIndex32

GPUBindGroupLayout 中资源绑定的唯一标识符,对应于 GPUBindGroupEntry.bindingGPUShaderModule 中的 @binding 属性。

  • visibility,类型为 GPUShaderStageFlags

GPUShaderStage 的成员的位集。每个设定位表示 GPUBindGroupLayoutEntry 的资源将可以在关联的着色器阶段中被访问。

  • buffer,类型为 GPUBufferBindingLayout

如果提供,则表示此 GPUBindGroupLayoutEntry 的绑定资源类型为 GPUBufferBinding

  • sampler,类型为 GPUSamplerBindingLayout

如果提供,则表示此 GPUBindGroupLayoutEntry 的绑定资源类型为 GPUSampler

  • texture,类型为 GPUTextureBindingLayout

如果提供,则表示此 GPUBindGroupLayoutEntry 的绑定资源类型为 GPUTextureView

  • storageTexture,类型为 GPUStorageTextureBindingLayout

如果提供,则表示此 GPUBindGroupLayoutEntry 的绑定资源类型为 GPUTextureView

  • externalTexture,类型为 GPUExternalTextureBindingLayout

如果提供,则表示此 GPUBindGroupLayoutEntry 的绑定资源类型为 GPUExternalTexture

typedef [EnforceRange] unsigned long GPUShaderStageFlags;

[Exposed=(Window, DedicatedWorker), SecureContext]
namespace GPUShaderStage {
  const GPUFlagsConstant VERTEX   = 0x1;
  const GPUFlagsConstant FRAGMENT = 0x2;
  const GPUFlagsConstant COMPUTE  = 0x4;
};

GPUShaderStage 包含以下标志,用于描述对应的 GPUBindGroupLayoutEntryGPUBindGroupEntry 将可被哪些着色器阶段访问:

  • VERTEX

绑定组条目将可被顶点着色器访问。

  • FRAGMENT

绑定组条目将可被片段着色器访问。

  • COMPUTE

绑定组条目将可被计算着色器访问。

GPUBindGroupLayoutEntrybinding 成员通过其所定义的 GPUBindGroupLayoutEntry 成员来确定:buffersamplertexturestorageTextureexternalTexture。对于任何给定的 GPUBindGroupLayoutEntry,只能定义其中一个成员。每个成员都有一个关联的 GPUBindingResource 类型,每个绑定类型都有一个关联的内部

这个表格显示了支持的绑定类型和它们的使用方式:

Binding memberResource typeBinding typeBinding usage
bufferGPUBufferBinding"uniform"constant
"storage"storage
"read-only-storage"storage-read
samplerGPUSampler"filtering"constant
"non-filtering"
"comparison"
textureGPUTextureView"float"constant
"unfilterable-float"
"depth"
"sint"
"uint"
storageTextureGPUTextureView"write-only"storage
externalTextureGPUExternalTextureconstant

描述了在 GPUBindGroupLayout 中的每个条目所使用的插槽数量,以及这些插槽对应的限制。具体如下:

  • 如果条目数量超出了支持的 binding slot 限制,则列表中的 GPUBindGroupLayoutEntry 值数会超出限制。每个 entry 可以使用多个插槽,用于多个各自的限制。
  1. 对于 entries 中的每个 entry
  • 如果 entry.buffer?.type"uniform",并且 entry.buffer?.hasDynamicOffsettrue,则将考虑使用 1 个 maxDynamicUniformBuffersPerPipelineLayout 插槽。
  • 如果 entry.buffer?.type"storage",并且 entry.buffer?.hasDynamicOffsettrue,则将考虑使用 1 个 maxDynamicStorageBuffersPerPipelineLayout 插槽。
  1. 对于每个着色器阶段 stageVERTEXFRAGMENTCOMPUTE):
  1. 对于 entry.visibility 包括 stageentries 中的每个 entry
  • 如果 entry.buffer?.type"uniform",则将考虑使用 1 个 maxUniformBuffersPerShaderStage 插槽。
  • 如果 entry.buffer?.type"storage""read-only-storage",则将考虑使用 1 个 maxStorageBuffersPerShaderStage 插槽。
  • 如果 entry.sampler 存在,则将考虑使用 1 个 maxSamplersPerShaderStage 插槽。
  • 如果 entry.texture 存在,则将考虑使用 1 个 maxSampledTexturesPerShaderStage 插槽。
  • 如果 entry.storageTexture 存在,则将考虑使用 1 个 maxStorageTexturesPerShaderStage 插槽。
  • 如果 entry.externalTexture 存在,则将考虑使用 4 个 maxSampledTexturesPerShaderStage 插槽、1 个 maxSamplersPerShaderStage 插槽和 1 个 maxUniformBuffersPerShaderStage 插槽。
enum GPUBufferBindingType {
    "uniform",
    "storage",
    "read-only-storage",
};

dictionary GPUBufferBindingLayout {
    GPUBufferBindingType type = "uniform";
    boolean hasDynamicOffset = false;
    GPUSize64 minBindingSize = 0;
};

GPUBufferBindingLayout 字典具有以下成员:

  • type,类型为 GPUBufferBindingType,默认为 "uniform",指定绑定到该绑定点的缓冲区所需的类型。
  • hasDynamicOffset,类型为布尔型,默认值为 false,指示此绑定是否需要使用动态偏移量。
  • minBindingSize,类型为 GPUSize64,默认为 0,指示与此绑定点一起使用的缓冲区绑定的最小大小。在创建 BindGroup 时,始终会根据此大小验证绑定。如果该值不为 0,则在管道创建时会验证该值 ≥ 变量的最小缓冲区绑定大小。如果它为 0,则管道创建将忽略它,而是绘制/调度命令将验证 GPUBindGroup 中的每个绑定是否满足变量的最小缓冲区绑定大小。

注意:理论上也可以针对早期验证指定的其他与绑定相关的字段(例如 sampleType 和格式)进行类似的执行时验证,但这样的执行时验证可能会很昂贵或过于复杂,因此仅适用于 minBindingSize,因为它预计对人体工程学影响最大。

enum GPUSamplerBindingType {
    "filtering",
    "non-filtering",
    "comparison",
};

dictionary GPUSamplerBindingLayout {
    GPUSamplerBindingType type = "filtering";
};

GPUSamplerBindingLayout 字典具有以下成员:

  • type,类型为 GPUSamplerBindingType,默认值为 "filtering",指示绑定到此绑定点的采样器的要求类型。
enum GPUTextureSampleType {
    "float",
    "unfilterable-float",
    "depth",
    "sint",
    "uint",
};

dictionary GPUTextureBindingLayout {
    GPUTextureSampleType sampleType = "float";
    GPUTextureViewDimension viewDimension = "2d";
    boolean multisampled = false;
};

GPUTextureBindingLayout字典有以下成员:

sampleType ,类型为 GPUTexture SampleType ,默认为 “浮动”

指示绑定到此绑定的纹理视图所需的类型。

viewDimension ,类型为 GPUTextureViewDimension ,默认为 "2d"

指示绑定到此绑定的纹理视图所需的维度

多重采样 布尔类型 ,默认为 false

指示绑定到此绑定的纹理视图是否必须进行多采样。

enum GPUStorageTextureAccess {
    "write-only" ,
};

dictionary GPUStorageTextureBindingLayout {
    GPUStorageTextureAccess access = "write-only";
    required GPUTextureFormat format;
    GPUTextureViewDimension viewDimension = "2d";
};

GPUStorageTextureBindingLayout字典有以下成员:

access ,类型为 GPUStorageTexture Access ,默认为 "write-only"

此绑定的访问模式,指示易读性和可写性。

注意:目前只有一种访问模式,“只写”,但这将在未来扩展。

格式 ,类型为 GPUTextureFormat

绑定到此绑定的纹理视图所需的格式

viewDimension ,类型为 GPUTextureViewDimension ,默认为 "2d"

指示绑定到此绑定的纹理视图所需的维度

dictionary GPUExternalTextureBindingLayout {
};

一个GPUBindGroupLayout对象有以下内部槽:

[[entryMap]] ,类型为 有序映射 < GPUSize32 GPUBindGroupLayoutEntry >

绑定索引的映射,指向GPUBindGroupLayoutEntrys,此``GPUBindGroupLayout描述。

[[DynamicOffsetCount]] ,类型为 GPUSize32

GPUBindGroupLayout中具有动态偏移量的缓冲区绑定数。

[[expsivePipeline]] ,类型为 GPUPipelineBase ?,最初 为null

创建此GPUBindGroupLayout的管道,如果它是作为默认管道布局的一部分创建的。如果不为空``,则使用此``GPUBindGroupLayout创建的GPUBindGroup只能与指定的GPUPipelineBase一起使用。

创建绑定组布局(描述符)

创建一个GPUBindGroupLayout

调用: GPUDevicethis.

论据:

ParameterTypeNullableOptionalDescription
descriptorGPUBindGroupLayoutDescriptorDescription of the GPUBindGroupLayout to create.

返回: GPUBindGroupLayout

内容时间线步骤:

  1. 对于描述符中的每个GPUBindGroupLayoutEntry条目。条目

    1. 如果提供entry. storageTexture

      1. 验证纹理格式所需功能的条目。存储纹理格式化与此。[[设备]]
  2. 让布局成为一个新的GPUBindGroupLayout对象。

  3. 在this的设备时间线上发出初始化步骤。

  4. 返回布局。

设备时间线初始化步骤:

  1. 如果以下任一条件不满足,将生成一个验证错误,使布局无效,并停止。

    • 这是有效的

    • 让限制是这样的。[[设备]][[限制]]

    • 描述符中每个条目的绑定是唯一的。

    • 描述符中每个条目的绑定必须是<限制. maxBindingsPerBindGroup

    • 描述符。条目不得超过绑定槽限制的限制。

    • 对于描述符中的每个GPUBindGroupLayoutEntry条目。条目

      • 正是其中的一个条目。缓冲区,条目。采样器,条目。纹理和条目。存储纹理提供

      • entry.可见性仅包含GPUShaderStage中定义的位。

      • 如果entry.可见性包括VERTEX

        • 条目。缓冲区?。类型不能是“存储”
        • entry.storageTexture?。访问不能是“只写”的
      • 如果入口.纹理?.多采样

        • entry.纹理.viewDimension"2d"
        • entry.纹理.sampleType不是"浮点数"
      • 如果提供entry. storageTexture

        • entry.storageTexture.viewDimension不是"多维数据集""多维数据集数组"
        • entry.storageTexture.format必须是能够支持存储使用的格式。
  2. 设置布局。[[描述符]]到描述符。

  3. 设置布局。[[DynamicOffsetCount]]为描述符中提供缓冲区缓冲区的条目数。hasDynamicOffset

  4. 对于描述符中的每个GPUBindGroupLayoutEntry条目。条目

    1. 插入进入布局。[[entryMap]]与条目的关键。绑定

8.1.2. 兼容性

当且仅当以下所有条件均满足时,GPUBindGroupLayout 中的两个对象 ab 被视为组等价:

  • a.[[exclusivePipeline]] == b.[[exclusivePipeline]]
  • 对于任何绑定编号 binding,满足以下一个条件之一:
    • 既缺失于 a.[[entryMap]] 中,也缺失于 b.[[entryMap]] 中。
    • a.[[entryMap]][binding] == b.[[entryMap]][binding]

如果绑定组布局是组等价的,它们可以在所有内容中互换使用。

8.2. GPUBindGroup

GPUBindGroup 定义了要一起绑定的资源集以及这些资源在着色器阶段中的使用方式。

[Exposed=(Window, DedicatedWorker), SecureContext]
interface GPUBindGroup {
};

GPUBindGroup 包括 GPUObjectBase

GPUBindGroup 对象具有以下内部属性:

  • [[layout]],类型为 GPUBindGroupLayout,只读,表示与此 GPUBindGroup 相关联的 GPUBindGroupLayout
  • [[entries]],类型为数组 sequence<GPUBindGroupEntry>,只读,表示此 GPUBindGroup 描述的 GPUBindGroupEntry 的集合。
  • [[usedResources]],类型为有序映射 ordered map<subresource, list<internal usage>>,只读,表示此绑定组使用的缓冲区和纹理子资源,与内部使用标志列表相关联。

8.2.1. 绑定组创建

GPUBindGroup 可通过 GPUDevice.createBindGroup() 方法创建。

GPUBindGroupDescriptor 字典具有以下成员:

  • layout,类型为 GPUBindGroupLayout,必填项,表示此绑定组的布局。
  • entries,类型为数组 sequence<GPUBindGroupEntry>,必填项,表示此绑定组所描述的资源列表,每个资源绑定由布局描述。
dictionary GPUBindGroupDescriptor : GPUObjectDescriptorBase {
  required GPUBindGroupLayout layout;
  required sequence<GPUBindGroupEntry> entries;
};

GPUBindGroupEntry 字典描述要在 GPUBindGroup 中绑定的单个资源,它包括以下成员:

  • binding,类型为 GPUIndex32,必填项,表示 GPUBindGroup 内部的资源绑定的唯一标识符,对应于 GPUBindGroupLayoutEntry.bindingGPUShaderModule 中的 @binding 属性。
  • resource,类型为 GPUBindingResource,必填项,表示要绑定的资源,可以是 GPUSamplerGPUTextureViewGPUExternalTextureGPUBufferBinding
typedef (GPUSampler or GPUTextureView or GPUBufferBinding or GPUExternalTexture) GPUBindingResource;

dictionary GPUBindGroupEntry {
    required GPUIndex32 binding;
    required GPUBindingResource resource;
};

GPUBufferBinding 字典描述要绑定为资源的缓冲区和可选范围,包括以下成员:

  • buffer,类型为 GPUBuffer,必填项,表示要绑定的 GPUBuffer
  • offset,类型为 GPUSize64,默认值为 0,表示缓冲绑定在着色器中公开的范围的字节偏移量,从缓冲区开头计算。
  • size,类型为 GPUSize64,必填项,表示缓冲绑定的大小,以字节为单位。如果未提供,则指定从偏移量开始到缓冲区结尾的范围。
dictionary GPUBufferBinding {
    required GPUBuffer buffer;
    GPUSize64 offset = 0;
    GPUSize64 size;
}

createBindGroup(descriptor) 方法创建一个 GPUBindGroup

GPUBindGroup createBindGroup(GPUBindGroupDescriptor descriptor);
  • 参数 descriptor 类型为 GPUBindGroupDescriptor,表示要创建的 GPUBindGroup 的描述。
  • 返回值为 GPUBindGroup

GPUDevice 时间轴上,按以下步骤对 GPUBindGroup 进行初始化。

该过程的时间轴步骤如下:

  • 创建一个名为 bindGroup 的新的 GPUBindGroup 对象。
  • GPUBindGroup 对象的内部属性 [[layout]] 上设置传递给 createBindGroup() 的描述符的布局 layout
  • GPUBindGroup 对象的内部属性 [[entries]] 上设置传递给 createBindGroup() 的描述符的 entries
  • 遍历 GPUBindGroup 对象的内部属性 [[entries]],检查其中的每个 GPUBindGroupEntry.resource,验证其符合要求规范,并且在此过程中记录其内部使用标记。
  • 验证 GPUBindGroup 对象的内部属性 [[usedResources]] 是否与 GPUBindGroup 的布局 layout 相容。
  • 发出 GPUDevice 时间轴上的初始化步骤。
  • 返回 bindGroup

设备时间线初始化步骤:

  1. 限制是这样的。[[device]][[limits]]

  2. 如果以下任一条件不满足,将生成一个验证错误,使bindGroup无效,并停止。

  • descriptor.layout有效的
  • 描述符descriptor.layout的条目数量与 descriptor.entries 的条目数量完全相等。

对于描述符中的每个GPUBindGroupEntry绑定descriptor.entries

  • 使用bindingDescriptor.resource绑定资源。

  • 描述符 descriptor.layout.entries 中恰好有一个 GPUBindGroupLayoutEntry layoutBinding,使得 layoutBinding.binding 等于 bindingDescriptor.binding

  • 如果定义的binding member

    sampler:

    texture: 如果layoutBinding 的定义绑定成员为 texture

    • resource 是一个 GPUTextureView
    • resource 可以与此对象一起使用。
    • 令纹理为 texture = resource.[[texture]]
    • layoutBinding.texture.viewDimension 等于资源的维数。
    • layoutBinding.texture.sampleType 与资源的格式兼容。
    • texture 的使用包括 TEXTURE_BINDING
    • 如果 layoutBinding.texture.multisampledtrue,则 texturesampleCount > 1;否则,texturesampleCount1

    storageTexture: 如果 layoutBinding 的定义绑定成员为 storageTexture

    • resource 是一个 GPUTextureView
    • resource 可以与此对象一起使用。
    • 令纹理为 texture = resource.[[texture]]
    • layoutBinding.storageTexture.viewDimension 等于资源的维数。
    • layoutBinding.storageTexture.format 等于 resource.[[descriptor]].format
    • texture 的使用包括 STORAGE_BINDING
    • resource.[[descriptor]].mipLevelCount] 必须为 1

    buffer 如果 layoutBinding 的定义绑定成员为 buffer

    • resource 是一个 GPUBufferBinding

    • resource.buffer 可以与此对象一起使用。

    • resource.offsetresource.size 指定的绑定部分位于缓冲区内,并且大小大于 0

    • 有效的缓冲绑定大小(effective buffer binding size(resource)) ≥ layoutBinding.buffer.minBindingSize

    • 如果 layoutBinding.buffer.type

      • uniform
        • "uniform",则 resource.buffer.usage 包括 UNIFORM

        • effective buffer binding size(resource)limits.maxUniformBufferBindingSize

        • resource.offsetlimits.minUniformBufferOffsetAlignment 的倍数。

      • storage
        • 如果 layoutBinding.buffer.type"storage""read-only-storage",则 resource.buffer.usage 包括 STORAGE

        • effective buffer binding size(resource)limits.maxStorageBufferBindingSize

        • effective buffer binding size(resource)4 的倍数。

        • resource.offsetlimits.minStorageBufferOffsetAlignment 的倍数。

  • 对于定义绑定成员为 externalTexture 的情况,

    • resource 是一个 GPUExternalTexture

    • 可以与此对象一起使用。

  1. 设bindGroup.[[布局]]=描述符.布局

  2. 设bindGroup.[[条目]]=描述符.条目

  3. 让bindGroup.[[usedResources]]= {}.

  4. 对于描述符中的每个GPUBindGroupEntry绑定描述符。条目

    1. 让interentalUsage成为layoutBind的绑定用法
    2. 资源看到的每个子资源都被添加到[[usedResources]]中。

有效的缓冲绑定大小(effective buffer binding size(binding))如下计算:

  1. 如果 binding.size 未提供,则返回 max(0, binding.buffer.size - binding.offset)
  2. 如果 binding.size 已提供,则返回 binding.size

如果两个 GPUBufferBinding 对象 ab 满足以下所有条件,则它们被视为是缓冲区绑定别名(buffer-binding-aliasing):

  • a.buffer == b.buffer
  • a.offseta.size 组成的范围与由 b.offsetb.size 组成的范围相交。

ISSUE 11 Define how a range is formed by offset/size when size can be undefined.

8.3. GPUPipelineLayout

GPUPipelineLayout 定义了在 setBindGroup() 命令编码期间设置的所有 GPUBindGroup 对象的资源与由 GPURenderCommandsMixin.setPipelineGPUComputePassEncoder.setPipeline 设置的管线着色器之间的映射关系。

资源的完整绑定地址可以定义为:

  • 着色器阶段掩码,该资源对其可见。
  • 绑定组索引。
  • 绑定号。

这个地址的组成部分也可以看作是管线的绑定空间(binding space)。GPUBindGroup(与相应的GPUBindGroupLayout)为固定的绑定组索引覆盖了这个空间。所包含的绑定需要是着色器在该绑定组索引处使用的资源的超集。

[Exposed=(Window, DedicatedWorker), SecureContext]
interface GPUPipelineLayout {
};

GPUPipelineLayout 包含 GPUObjectBase 接口。

GPUPipelineLayout 具有以下内部插槽:

  • [[bindGroupLayouts]],类型为 list<GPUBindGroupLayout>。这是在 GPUPipelineLayoutDescriptor.bindGroupLayouts 中提供的 GPUBindGroupLayout 对象。

注意:在许多 GPURenderPipelineGPUComputePipeline 管线中使用相同的 GPUPipelineLayout 保证了当这些管线之间切换时,用户代理不需要在内部重新绑定任何资源。

假设使用以下绑定组布局配置创建了 GPUComputePipeline 对象 X: A、B、C;使用以下绑定组布局配置创建了 GPUComputePipeline 对象 Y: A、D、C。编码命令序列中执行了两次 dispatches

setBindGroup(0, ...)

setBindGroup(1, ...)

setBindGroup(2, ...)

setPipeline(X)

dispatchWorkgroups()

setBindGroup(1, ...)

setPipeline(Y)

dispatchWorkgroups()

在这种情况下,即使 GPUPipelineLayout.bindGroupLayouts 索引 2 处的 GPUBindGroupLayout 或插槽 2 的 GPUBindGroup 没有更改,用户代理也必须重新绑定插槽 2。

注意:GPUPipelineLayout 的预期用法是将最常见和最不经常更改的绑定组放在布局的“底部”,即较低的绑定组插槽编号,如 0 或 1。绑定组需要在绘制调用之间更频繁地更改,则其索引应该更高。这个通用指南允许用户代理最小化绘制调用之间的状态更改,从而降低 CPU 开销。

8.3.1. 管线布局创建( Pipeline Layout Creation)

可以通过 GPUDevice.createPipelineLayout() 来创建 GPUPipelineLayout

dictionary GPUPipelineLayoutDescriptor : GPUObjectDescriptorBase {
  required sequence<GPUBindGroupLayout> bindGroupLayouts;
};

GPUPipelineLayoutDescriptor 字典定义了管线使用的所有 GPUBindGroupLayout 并具有以下成员:

  • bindGroupLayouts,类型为 sequence<GPUBindGroupLayout>。这是管线将使用的 GPUBindGroupLayout 列表。每个元素都对应于 GPUShaderModule 中的 @group 属性,其中第 N 个元素对应于 @group(N)

createPipelineLayout(descriptor):创建一个 GPUPipelineLayout

  • 被调用于:GPUDevice this

  • 参数:

    ParameterTypeNullableOptionalDescription
    descriptorGPUPipelineLayoutDescriptor要创建的 GPUPipelineLayout 的描述信息。
  • 返回值:GPUPipelineLayout

内容时间线步骤:

  • 创建一个新的 GPUPipelineLayout 对象 pl
  • 在此设备的重建时间线上发出初始化步骤。
  • 返回 pl

设备时间线的初始化步骤:

  • limitsthis.[[device]].[[limits]]

  • allEntries 成为对于所有 descriptor.bindGroupLayouts 中的 bgl,将 bgl.[[descriptor]].entries 进行串联的结果。

  • 如果以下任何条件不被满足,则产生验证错误,使 pl 无效,并停止。

    • descriptor.bindGroupLayouts 中的每个 GPUBindGroupLayout 必须可以与此一起使用,并且其 [[exclusivePipeline]] 为 null。
    • descriptor.bindGroupLayouts 的大小必须 ≤ limits.maxBindGroups
    • allEntries 必须不超过 limits 的绑定槽限制。
  • pl.[[bindGroupLayouts]] 设置为 descriptor.bindGroupLayouts

注意:如果两个 GPUPipelineLayout 对象的内部 [[bindGroupLayouts]] 序列包含了组相等的 GPUBindGroupLayout 对象,则在任何用途上都被认为是等效的。

8.4. 示例

创建一个 GPUBindGroupLayout,该组布局包含一个 Uniform 缓冲区、一个纹理和一个采样器。然后使用 GPUBindGroupLayout 创建 GPUBindGroupGPUPipelineLayout

const bindGroupLayout = gpuDevice.createBindGroupLayout({
  entries: [{
    binding: 0,
    visibility: GPUShaderStage.VERTEX | GPUShaderStage.FRAGMENT,
    buffer: {}
  }, {
    binding: 1,
    visibility: GPUShaderStage.FRAGMENT,
    texture: {}
  }, {
    binding: 2,
    visibility: GPUShaderStage.FRAGMENT,
    sampler: {}
  }]
});

const bindGroup = gpuDevice.createBindGroup({
    layout: bindGroupLayout,
    entries: [{
        binding: 0,
        resource: { buffer: buffer },
    }, {
        binding: 1,
        resource: texture
    }, {
        binding: 2,
        resource: sampler
    }]
});

const pipelineLayout = gpuDevice.createPipelineLayout({
  bindGroupLayouts: [bindGroupLayout]
});

首先,使用 GPUDevice.createBindGroupLayout() 创建一个 GPUBindGroupLayout,其中包含了三个绑定:

  • 绑定 0:Uniform 缓冲区,可在顶点着色器和片元着色器中使用。
  • 绑定 1:纹理,仅可在片元着色器中使用。
  • 绑定 2:采样器,仅可在片元着色器中使用。

接下来,使用 GPUDevice.createBindGroup() 创建一个 GPUBindGroup,将上一步中创建的 GPUBindGroupLayout 用于布局,并向绑定中添加实际资源。这里使用了一个 Uniform 缓冲区 buffer,一张纹理 texture,和一个采样器 sampler

最后,使用 GPUDevice.createPipelineLayout() 创建 GPUPipelineLayout,并将该 GPUBindGroupLayout 添加到 bindGroupLayouts 列表中。