1. 介绍
This section is non-normative.
图形处理单元,简称GPU,一直以来都是个人计算中实现丰富渲染和计算应用的关键部件。 WebGPU是一个将GPU硬件功能暴露给Web的API。该API从零开始设计,以便有效地映射到(2014年后的)原生GPU API。 WebGPU与WebGL无关,也没有显式地针对OpenGL ES。
WebGPU将物理GPU硬件视为GPUAdapter
s。它通过GPUDevice
提供与适配器的连接,管理资源和设备的GPUQueue
s,执行命令。GPUDevice
可能具有自己的内存,并可高速访问处理单元。GPUBuffer
和GPUTexture
是由GPU内存支持的物理资源。GPUCommandBuffer
和GPURenderBundle
是用户记录命令的容器。GPUShaderModule
包含着色器代码。其他资源,如GPUSampler
或GPUBindGroup
,配置了GPU使用物理资源的方式。
GPU通过将数据通过管线来执行GPUCommandBuffer
中编码的命令,这是固定功能和可编程阶段的混合。可编程阶段执行着色器,这些着色器是专为在GPU硬件上运行而设计的特殊程序。 pipeline的大部分状态由GPURenderPipeline
或GPUComputePipeline
对象定义。这些管线对象中未包含的状态在编码时通过命令设置,例如beginRenderPass()
或setBlendConstant()
。
2. 恶意使用注意事项
本节内容为非标准的 本节描述了在 Web 上公开此 API 相关的风险
2.1. 安全
WebGPU的安全性要求与Web的要求相同,同样也是不容妥协的。总体方法是在命令到达GPU之前严格验证所有的命令,确保页面只能处理其自己的数据。
2.1.1. 基于 CPU 的未定义行为
WebGPU实现将用户提出的工作负载转换为针对目标平台的特定API命令。原生API为命令指定有效用法(例如,参见vkCreateDescriptorSetLayout(https://www.khronos.org/registry/vulkan/specs/1.2-extensions/man/html/vkCreateDescriptorSetLayout.html)),通常情况下,如果不遵循有效用法规则,则不能保证任何结果。这被称为“未定义行为”,攻击者可能利用这一行为访问他们无权访问的内存,或迫使驱动程序执行任意代码。
为了禁止不安全的使用,定义了允许的WebGPU行为范围。实现必须验证用户的所有输入,并仅在有效工作负载下达到驱动程序。这份文档详细说明了所有错误条件及处理语义。例如,在copyBufferToBuffer()
的“源”和“目标”中同时指定具有相交范围的相同缓冲区,将导致GPUCommandEncoder
产生错误,并且不会发生其他操作。
有关错误处理的更多信息,请参阅§ 22 错误 & 调试。
2.1.2. 基于 GPU 的未定义行为
WebGPU 着色器在GPU硬件内部的计算单元中执行。在原生API中,一些着色器指令可能导致GPU上的未定义行为。为了解决这个问题,WebGPU严格定义了着色器指令集及其定义的行为。当着色器提供给createShaderModule()
时,WebGPU实现必须在进行任何转换(至特定平台的着色器)或变换过程之前对其进行验证。
2.1.3. 未初始化的数据
通常,分配新内存可能暴露其他在系统上运行的应用程序的残留数据。为解决这一问题,WebGPU在概念上将所有资源初始化为零,尽管在实践中,如果实现发现开发者手动初始化内容,则可以跳过此步骤。这包括着色器内的变量和共享工作组内存。
清除工作组内存的确切机制可能因平台而异。如果原生API没有提供清除它的功能,WebGPU实现将计算着色器转换为首先在所有调用中执行清除操作,然后同步它们,并继续执行开发者的代码。
GPULoadOp
“load”
更改为“clear”
)。
因此,所有实现应该在开发者控制台中发出关于这种潜在性能损失的警告,即使在该实现中没有损失。
2.1.4. 着色器中的越界访问
着色器可以直接访问物理资源(例如,作为“uniform”
GPUBufferBinding
),或通过纹理单元访问,纹理单元是固定功能硬件块,负责处理纹理坐标转换。WebGPU API中的验证只能保证提供了着色器的所有输入,并且它们具有正确的用法和类型。如果未涉及纹理单元,WebGPU API无法保证数据在边界内访问。
为了防止着色器访问应用程序不拥有的GPU内存,WebGPU实现可能会在驱动程序中启用一种特殊模式(称为“稳健缓冲区访问”),以保证访问仅限于缓冲区边界。
或者,实现可以通过插入手动边界检查来转换着色器代码。当采用这种方法时,越界检查仅适用于数组索引。由于主机端的minBindingSize
验证,不需要对着色器结构的简单字段访问进行额外的边界检查。
如果着色器尝试在物理资源边界之外加载数据,实现可以执行以下操作:
-
返回资源边界内的其他位置的值
-
返回"(0, 0, 0, X)"的值向量,其中X可以是任何值
-
部分丢弃绘制或调度调用
如果着色器尝试在物理资源边界之外写入数据,实现可以执行以下操作:
-
将值写入资源边界内的其他位置
-
丢弃写入操作
-
部分丢弃绘制或调度调用
2.1.5. 无效数据
在将浮点数数据从CPU上传至GPU,或在GPU上生成这些数据时,我们可能得到一个并不对应于有效数字的二进制表示,例如无穷大或NaN(非数字)。在这种情况下,GPU的行为取决于GPU硬件对IEEE-754标准的实现准确性。WebGPU保证引入无效浮点数只会影响算术计算的结果,不会产生其他副作用。
2.1.6. 驱动程序错误
GPU驱动程序和其他软件一样,可能会受到错误的影响。如果出现错误,攻击者可能会利用驱动程序的错误行为来获取未授权的数据。为了降低风险,WebGPU工作组将与GPU供应商合作,将WebGPU Conformance Test Suite(CTS)集成到他们的驱动程序测试流程中,就像对WebGL所做的那样。
WebGPU实现预计会针对发现的一些错误进行修复,并在无法修复的已知错误的驱动程序上禁用WebGPU。
2.1.7. 定时攻击
WebGPU被设计为通过Web Workers支持多线程使用。因此,它旨在不让用户面临现代高精度定时攻击。一些对象,如GPUBuffer
或GPUQueue
,具有可以同时访问的共享状态。这可能导致类似于从多个Web Workers访问SharedArrayBuffer的竞态条件,从而使线程调度可观察。
WebGPU通过限制只能对代理内的代理集群进行反序列化(或共享)对象的能力来解决这个问题,并且只有在启用cross-origin isolated策略时才有效。这种限制与防止恶意 SharedArrayBuffer
使用的mitigations相匹配。同样,用户代理也可以序列化共享任何句柄的代理,以完全阻止任何并发。
最后,在WebGPU中共享状态的竞争攻击面将是 SharedArrayBuffer
攻击的一个小子集。
WebGPU还指定了“timestamp-query”
功能,该功能可以提供GPU操作的高精度计时。该功能是可选的,WebGPU实现可能仅限于仅将其暴露给受信任的场景。或者,计时查询结果可以由计算着色器处理并与较低精度对齐。
2.1.8. 行锤攻击
Row hammer是一类利用DRAM单元中状态泄漏的攻击。它可以在GPU(https://www.vusec.net/projects/glitch/)上使用。WebGPU没有任何特定的缓解措施,而是依赖于平台级解决方案,例如减少内存刷新间隔。
2.1.9. 拒绝服务
WebGPU应用程序可以访问GPU内存和计算单元。WebGPU实现可能会限制应用程序可用的GPU内存,以保持其他应用程序的响应。对于GPU处理时间,WebGPU实现可以设置"看门狗"定时器,确保应用程序不会导致GPU在几秒钟内无响应。这些措施与WebGL中使用的措施类似。
2.1.10. 工作负载识别
WebGPU 提供对在同一机器上运行的不同程序(和网页)之间共享的受限全局资源的访问。应用程序可以尝试间接探测这些全局资源的约束程度,以便根据这些共享资源的使用模式推断其他打开的网页所执行的工作负载。这些问题通常类似于Javascript的问题,例如系统内存和CPU执行吞吐量。WebGPU 没有为此提供任何额外的缓解措施。
2.1.11. 内存资源
WebGPU公开了来自机器全局内存堆(如显存)的可失败分配。这允许通过尝试分配并观察分配失败来探测系统剩余可用内存的大小(对于给定的堆类型)。
内部的GPU通常具有一个或多个(通常只有两个)供所有运行应用程序共享的内存堆。当堆耗尽时,WebGPU将无法创建资源。这是可观察的,这可能允许恶意应用程序猜测其他应用程序使用哪些堆,以及它们从这些堆中分配了多少内存。
虽然这种信息可能被滥用,但要解决这个问题并不容易。WebGPU实现可能会采用一些策略来降低此问题带来的风险,如限制应用程序可用的内存和计算资源,从而保持其他应用程序的响应性。但是,这种策略并不能完全解决问题,因为恶意应用程序仍然可以通过观察资源分配失败来获取有关系统内存堆的信息。
总之,尽管WebGPU暴露了这种潜在的攻击途径,但开发者和用户仍需要保持警惕,并致力于在应用程序安全和系统资源管理方面进行持续改进。
2.1.12. 计算资源
如果一个网站与另一个网站同时使用WebGPU,它可能会注意到处理某些工作所需的时间增加。例如,如果一个网站不断提交计算工作负载并跟踪队列上的工作完成情况,它可能会注意到还有其他内容开始使用GPU。
GPU有许多可以独立测试的部分,如算术单元、纹理采样单元、原子单元等。恶意应用程序可能会感知到其中一些单元所受到的压力,并尝试通过分析压力模式来猜测另一个应用程序的工作负载。这类似于Javascript在CPU执行的现实情况。
要解决此问题并不容易,WebGPU 可能无法提供针对此类信息泄露的特定缓解措施。然而,开发者和用户仍可保持警惕并实施最佳实践,以确保应用程序安全并最大程度地减小潜在风险。这可能包括限制或屏蔽一些具有潜在危险性的GPU功能,或在系统和应用程序之间实施严格的资源隔离。
2.1.13. 功能滥用
恶意网站可能会滥用WebGPU公开的功能来运行对用户或用户体验没有益处的计算,而仅仅是为了网站自身的利益。例如,隐藏式的加密货币挖矿、密码破解或彩虹表计算。
由于浏览器无法区分有效工作负载和滥用工作负载,因此无法防范这类API使用。这是Web上所有通用计算功能的普遍问题:JavaScript,WebAssembly或WebGL。WebGPU只是使一些工作负载更容易实现或稍微比使用WebGL更高效地运行。
为了缓解这种滥用形式,浏览器可以限制对后台标签页的操作,警告某个标签页使用了大量资源,并限制允许使用WebGPU的上下文。
用户代理可以启发式地向用户发出关于高功耗使用的警告,特别是可能存在恶意使用。如果用户代理实现这种警告,在启发式中应包括WebGPU的使用,以及JavaScript、WebAssembly、WebGL等。
2.2. 隐私
WebGPU的隐私考虑与WebGL相似。出于使开发者能有效利用这些功能的必要性,GPU API 需要复杂地暴露设备功能的各个方面。一般的缓解方法包括归一化或将潜在的识别信息分组,并在可能的情况下强制实施统一的行为。
用户代理不得透露超过32个可区分的配置或桶。
2.2.1. 特定于机器的功能和限制
WebGPU可以揭示底层GPU架构和设备几何的许多细节。这包括可用的物理适配器,GPU和CPU资源可使用的许多限制(如最大纹理尺寸)以及可用的任何可选硬件特定功能。
用户代理没有义务公开真正的硬件限制,他们完全掌控如何公开机器特定信息。减少指纹识别的一种策略是将所有目标平台分为少数几类。总的来说,公开硬件限制对隐私的影响与WebGL相匹配。
默认限制也故意设定得足够高,以允许大多数应用程序在不请求更高限制的情况下工作。按照所请求的限制对API的所有使用情况进行验证,因此实际的硬件能力不会意外地暴露给用户。
2.2.2. 特定于机器的工件
有些机器特定的光栅化/精度伪像和性能差异可以大致以与WebGL相同的方式观察到。这适用于光栅化覆盖和模式、着色器阶段之间变化的插值精度、计算单元调度以及执行的更多方面。
通常情况下,光栅化和精度指纹在每个供应商的大部分或所有设备之间是相同的。性能差异相对难以解决,但也相对信号较低(就像JS执行性能一样)。
对隐私至关重要的应用程序和用户代理应使用软件实现来消除此类伪像。
2.2.3. 机器特定性能
另一个区分用户的因素是测量GPU上特定操作的性能。即使在低精度计时下,通过重复执行某个操作也可以显示出用户的设备在特定工作负载上的运行速度。这是一个相当常见的向量(在WebGL和Javascript中都存在),但信号较低,而且实际上很难进行真正的归一化。
WebGPU计算管线能够在不受固定功能硬件限制的情况下访问GPU。这对于唯一设备指纹识别带来了额外的风险。用户代理可以采取措施将逻辑GPU调用与实际计算单元分离,以降低这种风险。
2.2.4. 用户代理状态
本规范没有为一个源定义任何额外的用户代理状态。然而,预计用户代理将有编译缓存,用于昂贵的编译结果,如 GPUShaderModule
,GPURenderPipeline
和 GPUComputePipeline
。这些缓存对于在首次访问后提高WebGPU应用程序的加载时间非常重要。
对于规范来说,这些缓存与非常快速的编译无法区分,但对于应用程序来说,很容易测量 createComputePipelineAsync()
所需的解析时间。这可能在源之间泄漏信息(例如 “用户是否访问了具有此特定着色器的站点”),所以用户代理应该遵循存储分区的最佳实践。
系统的GPU驱动程序也可能拥有自己的编译着色器和管线缓存。用户代理可能希望尽可能禁用这些功能,或者以使GPU驱动程序将它们视为不同的方式向着色器中添加每个分区的数据。
2.2.5. 驱动程序错误
除了安全中概述的问题外,驱动程序错误可能引入行为差异,这可以作为一种区分用户的方法来观察。在这里同样适用于安全性考虑中提到的缓解措施,包括与GPU供应商协调以及在用户代理中针对已知问题实施解决方案。通过这些措施,可以最大限度地降低因驱动程序错误导致的安全风险,确保WebGPU应用及相关用户的安全性。
2.2.6. 适配器标识符
根据WebGL的过往经验,开发者确实需要能识别其代码运行在哪个GPU上,以便创建和维护稳健的GPU基础内容。例如,识别具有已知驱动程序错误的适配器以解决它们,或避免在给定类别的硬件上性能低于预期的功能。
但是,公开适配器标识符也自然地扩大了可用的指纹信息量,因此有必要限制识别适配器的精度。
可以应用多种缓解措施来在实现稳健内容和保护隐私之间达到平衡。首先,用户代理可以通过识别和解决已知驱动程序问题来减轻开发者的负担,自从浏览器开始使用GPU以来就一直有这样做。
当默认公开适配器标识符时,它们应尽可能宽泛地有用。例如,可能识别适配器的供应商和一般架构,而不识别正在使用的特定适配器。同样,在某些情况下,可能会报告被认为是实际适配器合理代理的适配器标识符。
在完整且详细的适配器信息有用的情况下(例如:提交错误报告时),可以要求用户同意向页面透露有关其硬件的更多信息。
最后,如果用户代理认为适当(如在增强隐私模式下),它将始终有权自行决定是否报告适配器标识符。
3. 基本概念
3.1. 公约
3.1.1. 语法速记
在本规范中,使用以下语法简写:
- . (“dot”) 语法,在编程语言中很常见。
-
术语 " Foo.Bar "的含义是 “值(或接口)Foo 的 Bar 成员”。 术语 " Foo.Bar 是 提供" 的含义是 " Bar 成员在 map 值 Foo 中存在"。
- 从 JavaScript 中采用的 ?. (“可选链”) 语法。
-
术语 " Foo?.Bar "的含义是 “如果 Foo 是 null 或 undefined,或者 Bar 在 Foo 中不存在,那么返回 undefined;否则,返回Foo.Bar”。
例如,在 buffer 是一个
GPUBuffer
的情况下,buffer?.[[device]].[[adapter]] 的含义是 "如果 buffer 是 null 或 undefined,那么返回 undefined;否则,返回 buffer 的 [[device]] 内部槽中的 [[adapter]] 内部槽。 - 从 JavaScript 中采用的 ?? (“空值合并”) 语法。
-
术语 " x ?? y "的含义是 “如果 x 不是 null/undefined, 则返回 x,否则返回 y”。
- 槽支持的属性
-
由相同名称的内部槽支持的 WebIDL 属性。它可能是可变的,也可能是不可变的。
3.1.2. WebGPU 接口
WebGPU接口定义了一个WebGPU对象。它可以用于:
在它被创建的内容时间线上,它是一个JavaScript公开的WebIDL接口。 在所有其他时间线上,只能访问不可变属性。
以下特殊属性类型可以在WebGPU接口上定义:
- 不可变属性
-
一个在对象初始化期间设置的只读槽。它可以从任何时间线访问。
注:由于槽是不可变的,实现可以在多个时间线上根据需要拥有一个副本。不可变属性 的定义就是这样,以避免在本规范中描述多个副本。
如果名为
[[with brackets]]
, 它就是一个内部槽。 如果名为withoutBrackets
, 它是一个只读
槽支持的属性。 - 内容时间线属性
-
一个只能从创建对象的内容时间线上访问的属性。
如果名为
[[with brackets]]
,它就是一个内部槽。 如果名为withoutBrackets
,它是一个 槽支持的属性。
任何包含GPUObjectBase
的接口都是一个WebGPU接口。
interface mixin GPUObjectBase {attribute USVString label ; };
GPUObjectBase
parent, 接口 T, GPUObjectDescriptorBase
descriptor)(其中 T 继承自 GPUObjectBase
):
-
让 device 成为 parent.
[[device]]
。 -
让 object 成为 T 的一个新实例。
-
让 internals 成为 T 类型的
\[[internals]]
(可能会覆盖GPUObjectBase
.[[internals]]
)的新(未初始化)实例,且只能从 device 的 设备时间线 上访问。 -
设置 object.
[[device]]
为 device。 -
设置 object.
[[internals]]
为 internals。 -
返回 [object, internals]。
GPUObjectBase
具有以下不可变属性:
[[internals]]
, 类型为 内部对象,只读,可覆盖-
内部对象。
对该对象内容的操作需要断言他们正运行在 设备时间线 上,且设备是 有效的。
对于每个子类型化
GPUObjectBase
的接口,它可以使用 内部对象 的子类型进行覆盖。此槽最初设置为该类型的未初始化对象。 [[device]]
, 类型为 设备,只读。
GPUObjectBase
具有以下 内容时间线属性:
label
, of type USVString-
一个由开发者提供的标签,以实现定义的方式使用。它可以被浏览器、操作系统或其他工具用于帮助开发者识别底层的 内部对象。示例包括在
GPUError
消息、控制台警告、浏览器开发者工具和平台调试实用程序中显示标签。注:label
是GPUObjectBase
的一个属性。两个GPUObjectBase
“包装器” 对象具有完全独立的标签状态,即使它们引用相同的底层对象(例如通过getBindGroupLayout()
返回的对象)。label
属性除了从JavaScript设置之外不会改变。这意味着一个底层对象可以与多个标签关联。此规范未定义标签如何传播到 设备时间线 上。标签的使用完全由实现定义:错误消息可能显示最近设置的标签、所有已知标签或根本不显示标签。
该属性定义为
USVString
,因为某些用户代理可能会将其提供给底层原生 API 的调试工具。
[[device]]
)被垃圾收集。然而,这不能得到保证,因为在某些实现中可能需要持有对父对象的强引用。
因此,开发者应该假设,除非该接口的所有子对象也被垃圾收集,否则 WebGPU 接口 可能不会被垃圾回收。这可能导致某些资源分配的时间比预期更长。
如果需要可预测地释放已分配的资源,应优先调用 WebGPU 接口上的 destroy
方法(例如 GPUDevice
.destroy()
或 GPUBuffer
.destroy()
),而不是依赖垃圾收集。
3.1.3. 内部对象
内部对象 跟踪可能仅在 设备时间线上使用的WebGPU对象的状态,在 设备时间线插槽 中,这些槽可能是可变的。
- 设备时间线插槽
-
一个仅从 设备时间线 可访问的内部插槽。
所有对 内部对象 的可变状态的读/写操作都发生在单个严格有序的 设备时间线 上执行的步骤中。这些步骤可能来自多个 代理 上的任何一个 内容时间线 算法。
注:" 代理" 是指JavaScript的 “线程”(即主线程或Web Worker)。
3.1.4. 对象描述符
一个对象描述符包含了创建对象所需的信息,这通常是通过GPUDevice
的 create*
方法之一来完成的。
dictionary {
GPUObjectDescriptorBase USVString label ; };
GPUObjectDescriptorBase
has the following members:
label
, of type USVString-
GPUObjectBase.label
的初始值。
3.2. 异步性
3.2.1. 无效的内部对象 & 具有传染性的无效性
在WebGPU中,对象创建操作不返回promise,但实际上是内部异步的。返回的对象引用的是在设备时间线上操作的内部对象。大多数发生在设备时间线上的错误不会通过异常或拒绝失败,而是通过与相关联的设备生成的GPUError
进行通信。
内部对象要么有效,要么无效。 一个无效的对象将永远不会在以后变得有效,但一些有效的对象可能会变成无效。
如果无法创建对象,那么对象将从创建时开始就是无效的。例如,这可能是因为对象描述符没有描述一个有效对象,或者没有足够的内存来分配资源。
绝大多数类型的内部对象在创建后不能变无效,但仍可能变得不可用,例如,如果拥有的设备变为丢失或者销毁
,或者对象具有特殊的内部状态,如缓冲区状态"销毁"。
某些类型的内部对象在创建后可以变为无效;具体来说,这些类型包括设备、适配器、GPUCommandBuffer
和命令/通道/包编码器。
GPUObjectBase
对象 只有在满足以下要求时,才被认为是可用于与 targetObject 一起使用的:
-
对象 必须是 有效的。
-
对象.
[[device]]
必须是 有效的。 -
对象.
[[device]]
必须等于 目标对象.[[device]]
。
3.2.2. Promise 排序
在WebGPU中,有几个操作会返回promises。
WebGPU不对这些promises的解决顺序(resolve或reject)做任何保证,除了以下情况:
-
如果在 p2 = q.
onSubmittedWorkDone()
被调用之前调用了 p1 = b.mapAsync()
,并且 b 最后一次是仅在 q 上使用的,那么 p2 在 p1 解析之前不得解析。
应用程序不能依赖于其他任何promise解决顺序。
3.3. 坐标系统
-
在归一化设备坐标(NDC)中,Y轴是向上的:在NDC中,点(-1.0, -1.0)位于NDC的左下角。 此外,NDC中的x和y应在-1.0和1.0(含)之间,而NDC中的z应在0.0和1.0(含)之间。 在NDC范围之外的顶点不会引入任何错误,但它们会被剪裁。
-
在 framebuffer 坐标、视口坐标和片段/像素坐标中,Y轴是向下的: 在这些坐标系中,原点(0, 0)位于左上角。
-
窗口/呈现坐标与 framebuffer坐标相匹配。
-
贴图坐标中原点(0, 0)的UV表示贴图内存中的第一个像素(最低字节)。
注:WebGPU 的坐标系在图形管线中与 DirectX 的坐标系相匹配。
3.4. 编程模型
3.4.1. 时间线
本节为非规范性内容。
一个带有用户代理前端和GPU后端的计算机系统中,各组件在不同的时间线上并行工作:
- 内容时间线
-
与Web脚本的执行相关联。 它包括调用本规范描述的所有方法。
要从操作
GPUDevice
device
中向内容时间线发出步骤,请使用为GPUDevice排队全局任务device
与这些步骤。 - 设备时间线
-
与用户代理发出的GPU设备操作相关联。 它包括创建适配器、设备和GPU资源以及状态对象,这些通常是从控制GPU的用户代理部分的角度来看同步操作, 但可以在单独的操作系统进程中运行。
- 队列时间线
-
与在GPU的计算单元上执行操作相关联。它包括在GPU上运行的实际绘制、复制和计算任务。
- 不可变值示例定义
-
可以在任何时间线上使用。
- 内容时间线示例定义
-
仅可在内容时间线上使用。
- 设备时间线示例定义
-
仅可在设备时间线上使用。
- 队列时间线示例定义
-
仅可在队列时间线上使用。
在本规范中,当结果值取决于除 内容时间线 以外的任何时间轴上的工作时,将使用异步操作。它们在JavaScript中由回调和promises表示。
GPUComputePassEncoder.dispatchWorkgroups()
:
-
用户通过调用
GPUComputePassEncoder
的方法在内容时间线上编码dispatchWorkgroups
命令。 -
用户执行
GPUQueue.submit()
将GPUCommandBuffer
交给用户代理,用户代理在设备时间线上通过调用操作系统驱动程序进行底层提交来处理它。 -
提交由GPU调用调度器分派到实际计算单元上执行,发生在队列时间线上。
GPUDevice.createBuffer()
:
-
用户填写
GPUBufferDescriptor
,并用它创建一个GPUBuffer
,发生在内容时间线上。 -
用户代理在设备时间线上创建一个低级别的缓冲区。
3.4.2. 内存模型
本节为非规范性内容。
在应用程序初始化例程中获取到 GPUDevice
后,我们可以将 WebGPU平台 描述为包含以下层:
-
实现此规范的用户代理。
-
具有此设备的低级本地API驱动程序的操作系统。
-
实际的CPU和GPU硬件。
WebGPU平台的每一层可能有不同的内存类型,用户代理在实现规范时需要考虑:
脚本拥有的内存,例如由脚本创建的 ArrayBuffer
,通常无法被GPU驱动程序访问。
用户代理可能有不同的进程负责运行内容和与GPU驱动程序通信。在这种情况下,它将使用进程间共享内存来传输数据。
独立GPU有高带宽的自己的内存,而集成GPU通常与系统共享内存。
大多数 物理资源 分配在类型为内存的GPU计算或渲染的效率上。当用户需要向GPU提供新数据时,数据可能首先需要跨越进程边界以到达与GPU驱动程序通信的用户代理部分。然后,可能需要使驱动程序可见,这有时需要将数据复制到驱动程序分配的寄存器内存中。最后,可能需要将其传输到专用GPU内存,可能将内部布局更改为GPU操作最有效的布局。
所有这些转换都由用户代理的WebGPU实现完成。
注:此示例描述了最坏情况,而实际上实现可能不需要跨越进程边界,或者可能能够将驱动程序管理的内存直接暴露给用户在 ArrayBuffer
后面,从而避免任何数据副本。
3.4.3. 资源用途
一个物理资源可以在GPU上使用内部用途:
- input
-
用于绘制或调度调用的输入数据缓冲区。保持内容不变。 允许使用缓冲区
INDEX
,缓冲区VERTEX
或 缓冲区INDIRECT
。 - constant
-
从着色器角度来看,资源绑定是不变的。保持内容不变。 允许使用缓冲区
UNIFORM
或纹理TEXTURE_BINDING
。 - storage
-
可写存储资源绑定。 允许使用缓冲区
STORAGE
或纹理STORAGE_BINDING
。 - storage-read
-
只读存储资源绑定。保持内容不变。 允许使用缓冲区
STORAGE
。 - attachment
-
在渲染通道中用作输出附件的纹理。 允许使用纹理
RENDER_ATTACHMENT
。 - attachment-read
-
在渲染通道中用作只读附件的纹理。 保持内容不变。 允许使用纹理
RENDER_ATTACHMENT
。
我们定义子资源可以是整个缓冲区,也可以是一个纹理子资源。
规定用途只能组合成兼容用途列表允许API在处理内存时限制数据竞争发生的时间。具有这种性质的应用程序在针对WebGPU编写时,更有可能在不同平台上无需修改即可运行。
通常,当实现处理一个使用 子资源的操作,以与其当前用途允许的不同方式时,它会调度资源转换到新状态。在某些情况下,例如在打开的 GPURenderPassEncoder
内,由于硬件限制,此类转换是不可能的。我们将这些地方定义为 用途范围。
主要用途规则 是,对于任何一个 子资源,在一个 用途范围 中的 内部用途 列表必须是一个 兼容用途列表。
例如,在同一个 GPURenderPassEncoder
中将同一个缓冲区绑定为 存储 和 输入,会使编码器以及拥有的 GPUCommandEncoder
进入错误状态。这种用途组合不能构成一个 兼容用途列表。
注:在单个 用途范围 内多个可写存储缓冲区/纹理的使用之间的竞争条件是允许的。
提供给 GPURenderPassColorAttachment.view
和 GPURenderPassColorAttachment.resolveTarget
的纹理的 子资源 被视为在此渲染通道的 用途范围 内作为 附件 使用。
3.4.4. 同步
对于 物理资源 的每一个 子资源,其一组 内部使用 标志在 队列时间线 上进行跟踪。
在 队列时间线 上,有一个有序的 用途范围 序列。 在每个范围的持续时间内,任何给定的 子资源 的一组 内部用途 标志是恒定的。 在 用途范围 之间的边界处, 子资源 可能会过渡到新的用途。
本规范定义了以下 用途范围:
-
在通道之外(在
GPUCommandEncoder
中),每个(非状态设置)命令都是一个使用范围(例如copyBufferToTexture()
)。 -
在计算过程中,每个调度命令(
dispatchWorkgroups()
或dispatchWorkgroupsIndirect()
) 是一个使用范围。 如果命令可能访问子资源,则该子资源在使用范围内被“使用”。 在调度中,对于当前GPUComputePipeline
使用的每个绑定组插槽[[layout]]
,每个 subresource 被引用该绑定组在使用范围内被“使用”。 状态设置计算通道命令,如setBindGroup(),不直接对使用范围做出贡献;他们反而改变了在调度命令中检查的状态。 -
一个渲染通道是一个使用范围。 如果子资源被任何引用,则它在使用范围内被“使用”(状态设置或非状态设置)命令。 例如,在setBindGroup(),
bindGroup
中的每个子资源都在渲染过程的使用范围内“使用”。
问题:上面应该大概讲的是GPU命令。但是我们没有办法参考特定的 GPU 命令(如分派)。
-
在渲染过程中,任何 setBindGroup() 调用中使用的子资源,无论当前绑定的管线的着色器或布局实际上是否依赖于这些绑定,或者绑定组是否被另一个“设置”调用隐藏。
-
在任何
setVertexBuffer()
调用中使用的缓冲区,无论是否有任何绘制调用依赖于此缓冲区,或者此缓冲区是否被另一个“设置”调用遮蔽。 -
在任何
setIndexBuffer()
调用中使用的缓冲区,无论是否有任何绘图调用依赖于此缓冲区,或者此缓冲区是否被另一个“设置”调用隐藏。 -
由
beginRenderPass()
在GPURenderPassDescriptor
中用作颜色附件、解析附件或深度/模板附件的纹理子资源,无论着色器是否实际依赖于这些附件。 -
在可见性为 0 的绑定组条目中使用的资源,或者仅对计算阶段可见但在渲染过程中使用的资源(反之亦然)。
在命令编码期间,子资源的每次使用都记录在命令缓冲区的 usage scopes 之一中。
对于每个 适用范围,实现执行 适用范围验证 通过组成 [=usage scope 中使用的每个 subresource 的所有 internal usage 标志的列表 =].
如果这些列表中的任何一个不是兼容用法列表,GPUCommandEncoder.finish()
将生成验证错误。
3.5. 核心内部对象
3.5.1. Adapters
适配器 标识系统上 WebGPU 的实现: 既是浏览器底层平台上计算/渲染功能的实例,又是浏览器在该功能之上实现 WebGPU 的实例。
适配器 不唯一表示底层实现:
多次调用 requestAdapter()
每次都会返回不同的 adapter 对象。
每个 适配器 对象只能用于创建一个 device:
在 requestDevice()
成功后,适配器变为 无效。
此外,适配器 对象可以随时 过期。
注:
这确保应用程序在创建设备时使用最新的系统状态来选择适配器。
它还通过使它们看起来相似来鼓励对更多场景的鲁棒性:首次初始化、由于拔下适配器而重新初始化、由于测试 GPUDevice.destroy()
调用而重新初始化等。
如果 适配器 具有重要的性能警告以换取更广泛的兼容性、更可预测的行为或改进的隐私的某种组合,则它可以被视为 后备适配器。 fallback adapter 不需要在每个系统上都可用。
adapter 具有以下内部插槽:
[[features]]
,类型为 ordered set<GPUFeatureName
>,只读-
features 可用于在此适配器上创建设备。
[[limits]]
,类型为 supported limits,只读-
可用于在此适配器上创建设备的 best 限制。
每个适配器限制必须与 supported limits 中的默认值相同或 better。
[[fallback]]
,布尔类型-
如果设置为“true”,则表示该适配器是 fallback adapter。
[[unmaskedIdentifiers]]
,类型为 ordered set<DOMString
>-
用户代理已选择为此适配器报告的
GPUAdapterInfo
字段的名称列表。 最初填充了用户代理在未经用户同意的情况下选择报告的任何GPUAdapterInfo
字段的名称。
Adapters 通过 GPUAdapter
暴露出来。
3.5.2. 设备
device 是 适配器 的逻辑实例,通过它创建 内部对象。 它可以在多个 代理 之间共享(e.g. dedicated workers)。
设备 是从它创建的所有 内部对象 的独占所有者:
当 设备 变为 无效(是 lost 或 destroyed
)时,它和在其上创建的所有对象(直接,例如 createTexture()
,或间接地,例如 createView()
) 隐式变为 unusable。
device 具有以下内部插槽:
[[适配器]]
,类型为 适配器,只读-
创建此设备的 适配器。
[[特性]]
,类型为 ordered set<GPUFeatureName
>,只读[[限制]]
,类型为 支持的限制,只读
GPUDeviceDescriptor
描述符:
-
将 device.
[[adapter]]
设置为 adapter。 -
将 device.
[[features]]
设置为 set 中的值 描述符.requiredFeatures
。 -
让 device.
[[limits]]
成为具有默认值的 supported limits 对象。 对于 descriptor.requiredLimits
中的每个 (key, value) 对,设置 key对应的成员 在 device.[[limits]]
到 value 的 better 值 或 supported limits 中的默认值。
每当用户代理需要撤销对设备的访问权限时,它都会在设备的 device timeline 上调用 lose the device(device
, "unknown"
),可能会提前 当前在该时间线上排队的其他操作。
如果操作失败并产生副作用,这些副作用会明显改变设备上对象的状态或可能破坏内部实现/驱动程序状态,则设备应该丢失以防止这些更改被观察到。
-
制作设备 无效。
-
让gpuDevice 是对应于 device 的 内容时间线
GPUDevice
。问题:更严格地定义它。
-
在 gpuDevice 的 内容时间线 上执行以下步骤:
-
使用新的
GPUDeviceLostInfo
解决 device.lost
并将reason
设置为 reason 和message
设置为实现定义的值。
注:
message
不应该泄露不必要的用户/系统信息,也不应该被应用程序解析。 -
-
完成任何未完成的
mapAsync()
步骤。 -
完成任何未完成的
onSubmittedWorkDone()
步骤。
注:设备丢失后不会产生错误。 参见 § 22 错误 & 调试。
3.6. 可选功能
WebGPU 适配器 和 设备 具有 功能,它描述了 WebGPU 功能在不同实现之间的差异,通常是由于硬件或系统软件限制。 功能 是 特性 或 限制。用户代理不得透露超过 32 个可区分的配置或桶。
适配器 的能力必须符合 § 4.2.1 Adapter Capability Guarantees。
在 requestDevice()
中只能请求支持的功能; 请求不受支持的功能会导致失败。
设备 的功能正是在 requestDevice()
中请求的功能。 无论 适配器 的功能如何,这些功能都会被强制执行。
有关隐私方面的考虑,请参阅 § 2.2.1 特定于机器的功能和限制。
3.6.1. 特性
特性 是一组可选的 WebGPU 功能,并非所有实现都支持这些功能,通常是由于硬件或系统软件限制。
只有在创建设备时请求了该功能(在 requiredFeatures
中)时,才能使用作为功能一部分的功能。
否则,以新方式使用现有 API 表面通常会导致 validation error,而使用 optional API surfaces 会导致以下结果:
-
使用新方法或枚举值总是会抛出
TypeError
。 -
使用具有(正确键入的)非默认值的新字典成员通常会导致 validation error。
-
使用新的 WGSL
enable
指令总是导致createShaderModule()
validation error。
GPUFeatureName
feature 启用 GPUObjectBase
object 当且仅当 object.[[device]]
.[[features]]
包含 feature。
请参阅 Feature Index 了解每个功能启用的功能的描述。
3.6.2. 限制
每个 限制 都是对设备上 WebGPU 使用的数字限制。
每个限制都有一个 默认 值。
每个 适配器 都保证支持默认值或 更好。
如果未在 requiredLimits
中明确指定值,则使用默认值。
一个极限值可能比另一个更好。 更好 限制值总是放宽验证,使更多的程序严格有效。 对于每个 限制类,定义了“更好”。
不同的极限有不同的极限等级:
注: 设置“更好”的限制可能不一定是可取的,因为它们可能会对性能产生影响。 因此,为了提高跨设备和实现的可移植性,应用程序通常应该请求适用于其内容的“最差”限制(理想情况下,默认值)。
支持的限制 对象对 WebGPU 定义的每个限制都有一个值:
限制名称 | Type | Limit class | Default |
---|---|---|---|
maxTextureDimension1D
| GPUSize32
| maximum | 8192 |
使用 dimension "1d" 创建的 texture 的 size .width 的最大允许值。
| |||
maxTextureDimension2D
| GPUSize32
| maximum | 8192 |
size .width 和 dimension "2d" 创建的 纹理 的 size .height 所允许的最大值。
| |||
maxTextureDimension3D
| GPUSize32
| maximum | 2048 |
使用dimension "3d" 创建的 纹理 的 size .width, size .height 和 size .depthOrArrayLayers 最大值
| |||
maxTextureArrayLayers
| GPUSize32
| maximum | 256 |
通过 dimension "1d" 或 "2d" 创建的纹理,所允许的 size .depthOrArrayLayers 的最大值。
| |||
maxBindGroups
| GPUSize32
| maximum | 4 |
创建 GPUPipelineLayout 时,bindGroupLayouts 中允许的 GPUBindGroupLayouts 最大值。
| |||
maxBindGroupsPlusVertexBuffers
| GPUSize32
| maximum | 24 |
同时使用的绑定组和顶点缓冲区槽的最大数量,计算最高索引以下的任何空槽。
在 createRenderPipeline() 和 in draw calls 中验证。
| |||
maxBindingsPerBindGroup
| GPUSize32
| maximum | 1000 |
创建 GPUBindGroupLayout 时可用的绑定索引数。
注:这个限制是规范的,但是是任意的。
默认情况下 binding slot limits,不可能在一个绑定组中使用 1000 个绑定,但这允许 | |||
maxDynamicUniformBuffersPerPipelineLayout
| GPUSize32
| maximum | 8 |
GPUPipelineLayout 中的最大 GPUBindGroupLayoutEntry 条目数,这些条目是具有动态偏移量的统一缓冲区。
请参阅 超出绑定插槽限制。
| |||
maxDynamicStorageBuffersPerPipelineLayout
| GPUSize32
| maximum | 4 |
GPUPipelineLayout 中的最大 GPUBindGroupLayoutEntry 条目数,这些条目是具有动态偏移量的存储缓冲区。
请参阅 超出绑定插槽限制。
| |||
maxSampledTexturesPerShaderStage
| GPUSize32
| maximum | 16 |
对于每个可能的 GPUShaderStage stage ,作为采样纹理的 GPUPipelineLayout 中的最大 GPUBindGroupLayoutEntry 条目数。
请参阅 超出绑定插槽限制。
| |||
maxSamplersPerShaderStage
| GPUSize32
| maximum | 16 |
对于每个可能的 GPUShaderStage stage ,GPUPipelineLayout 中作为采样器的 GPUBindGroupLayoutEntry 条目的最大数量。
请参阅 超出绑定插槽限制。
| |||
maxStorageBuffersPerShaderStage
| GPUSize32
| maximum | 8 |
对于每个可能的 GPUShaderStage stage ,GPUPipelineLayout 中作为存储缓冲区的 GPUBindGroupLayoutEntry 条目的最大数量。
请参阅 超出绑定插槽限制。
| |||
maxStorageTexturesPerShaderStage
| GPUSize32
| maximum | 4 |
对于每个可能的 GPUShaderStage stage ,GPUPipelineLayout 中作为存储纹理的 GPUBindGroupLayoutEntry 条目的最大数量。
请参阅 超出绑定插槽限制。
| |||
maxUniformBuffersPerShaderStage
| GPUSize32
| maximum | 12 |
对于每个可能的 GPUShaderStage stage ,作为统一缓冲区的 GPUPipelineLayout 中的最大 GPUBindGroupLayoutEntry 条目数。
请参阅 超出绑定插槽限制。
| |||
maxUniformBufferBindingSize
| GPUSize64
| maximum | 65536 bytes |
与 GPUBindGroupLayoutEntry entry 绑定的最大 GPUBufferBinding .size entry.buffer ?.type 是 "uniform" 。
| |||
maxStorageBufferBindingSize
| GPUSize64
| maximum | 134217728 bytes (128 MiB) |
与 GPUBindGroupLayoutEntry entry 绑定的最大 GPUBufferBinding .size entry.buffer ?.type 是 "storage" 或 "read-only-storage" 。
| |||
minUniformBufferOffsetAlignment
| GPUSize32
| alignment | 256 bytes |
GPUBufferBinding 所需的对齐方式。offset 和 setBindGroup() 中提供的动态偏移量,用于与 GPUBindGroupLayoutEntry entry 的绑定 entry.buffer ?.type 是 "uniform" 。
| |||
minStorageBufferOffsetAlignment
| GPUSize32
| alignment | 256 bytes |
GPUBufferBinding 所需的对齐方式。offset 和 setBindGroup() 中提供的动态偏移量,用于与 GPUBindGroupLayoutEntry entry 的绑定 entry.buffer ?.type 是 "storage" 或 "read-only-storage" 。
| |||
maxVertexBuffers
| GPUSize32
| maximum | 8 |
创建 GPURenderPipeline 时 buffers 的最大数量。
| |||
maxBufferSize
| GPUSize64
| maximum | 268435456 bytes (256 MiB) |
创建 GPUBuffer 时 size 的最大大小。
| |||
maxVertexAttributes
| GPUSize32
| maximum | 16 |
创建 GPURenderPipeline 时,跨越 buffers 的 attributes 总数的最大数量。
| |||
maxVertexBufferArrayStride
| GPUSize32
| maximum | 2048 bytes |
创建 GPURenderPipeline 时允许的最大值 arrayStride 。
| |||
maxInterStageShaderComponents
| GPUSize32
| maximum | 60 |
阶段间通信(如顶点输出或片段输入)的输入或输出变量组件的最大允许数量。 | |||
maxInterStageShaderVariables
| GPUSize32
| maximum | 16 |
阶段间通信(如顶点输出或片段输入)的最大允许输入或输出变量数。 | |||
maxColorAttachments
| GPUSize32
| maximum | 8 |
GPURenderPipelineDescriptor .fragment .targets 、GPURenderPassDescriptor .colorAttachments 和GPURenderPassLayout .colorFormats 中允许的最大颜色附件数。
| |||
maxColorAttachmentBytesPerSample
| GPUSize32
| maximum | 32 |
在所有颜色附件中保存渲染管线输出数据的一个样本(像素或子像素)所需的最大字节数。 | |||
maxComputeWorkgroupStorageSize
| GPUSize32
| maximum | 16384 bytes |
用于计算阶段 GPUShaderModule 入口点的 workgroup 存储的最大字节数。
| |||
maxComputeInvocationsPerWorkgroup
| GPUSize32
| maximum | 256 |
计算阶段 GPUShaderModule 入口点的“workgroup_size”维度乘积的最大值。
| |||
maxComputeWorkgroupSizeX
| GPUSize32
| maximum | 256 |
计算阶段 GPUShaderModule 入口点的 workgroup_size X 维度的最大值。
| |||
maxComputeWorkgroupSizeY
| GPUSize32
| maximum | 256 |
计算阶段 GPUShaderModule 入口点的“workgroup_size”Y 维度的最大值。
| |||
maxComputeWorkgroupSizeZ
| GPUSize32
| maximum | 64 |
计算阶段 GPUShaderModule 入口点的“workgroup_size”Z 维度的最大值。
| |||
maxComputeWorkgroupsPerDimension
| GPUSize32
| maximum | 65535 |
dispatchWorkgroups(workgroupCountX, workgroupCountY, workgroupCountZ) 参数的最大值。
|
3.6.2.1. GPUSupportedLimits
GPUSupportedLimits
公开适配器或设备支持的 limits。
请参见 GPUAdapter.limits
和 GPUDevice.limits
。
[Exposed =(Window ,DedicatedWorker ),SecureContext ]interface GPUSupportedLimits {readonly attribute unsigned long ;
maxTextureDimension1D readonly attribute unsigned long ;
maxTextureDimension2D readonly attribute unsigned long ;
maxTextureDimension3D readonly attribute unsigned long ;
maxTextureArrayLayers readonly attribute unsigned long ;
maxBindGroups readonly attribute unsigned long ;
maxBindGroupsPlusVertexBuffers readonly attribute unsigned long ;
maxBindingsPerBindGroup readonly attribute unsigned long ;
maxDynamicUniformBuffersPerPipelineLayout readonly attribute unsigned long ;
maxDynamicStorageBuffersPerPipelineLayout readonly attribute unsigned long ;
maxSampledTexturesPerShaderStage readonly attribute unsigned long ;
maxSamplersPerShaderStage readonly attribute unsigned long ;
maxStorageBuffersPerShaderStage readonly attribute unsigned long ;
maxStorageTexturesPerShaderStage readonly attribute unsigned long ;
maxUniformBuffersPerShaderStage readonly attribute unsigned long long ;
maxUniformBufferBindingSize readonly attribute unsigned long long ;
maxStorageBufferBindingSize readonly attribute unsigned long ;
minUniformBufferOffsetAlignment readonly attribute unsigned long ;
minStorageBufferOffsetAlignment readonly attribute unsigned long ;
maxVertexBuffers readonly attribute unsigned long long ;
maxBufferSize readonly attribute unsigned long ;
maxVertexAttributes readonly attribute unsigned long ;
maxVertexBufferArrayStride readonly attribute unsigned long ;
maxInterStageShaderComponents readonly attribute unsigned long ;
maxInterStageShaderVariables readonly attribute unsigned long ;
maxColorAttachments readonly attribute unsigned long ;
maxColorAttachmentBytesPerSample readonly attribute unsigned long ;
maxComputeWorkgroupStorageSize readonly attribute unsigned long ;
maxComputeInvocationsPerWorkgroup readonly attribute unsigned long ;
maxComputeWorkgroupSizeX readonly attribute unsigned long ;
maxComputeWorkgroupSizeY readonly attribute unsigned long ;
maxComputeWorkgroupSizeZ readonly attribute unsigned long ; };
maxComputeWorkgroupsPerDimension
3.6.2.2. GPUSupportedFeatures
GPUSupportedFeatures
是一个 setlike 界面。 它的 set entries 是适配器或设备支持的 features 的 GPUFeatureName
值。 它必须只包含来自 GPUFeatureName
枚举的字符串。
[Exposed =(Window ,DedicatedWorker ),SecureContext ]interface GPUSupportedFeatures {readonly setlike <DOMString >; };
GPUSupportedFeatures
set entries 的类型是 DOMString
以允许用户代理优雅地处理有效的 GPUFeatureName
s,这些是在规范的后续修订中添加的,但用户代理尚未更新以识别。 如果 set entries 类型是 GPUFeatureName
,则以下代码将抛出 TypeError
而不是报告 false
:
3.6.2.3. WGSLLanguageFeatures
WGSLLanguageFeatures
是一个 setlike 接口。
它的 set entries 是 WGSL language extensions 支持所有适配器的字符串名称。
[Exposed =(Window ,DedicatedWorker ),SecureContext ]interface WGSLLanguageFeatures {readonly setlike <DOMString >; };
3.6.2.4. GPUAdapterInfo
GPUAdapterInfo
公开有关适配器的各种标识信息。
GPUAdapterInfo
中的任何成员都不能保证被填充。用户代理可以自行决定显示哪些值,并且在某些设备上很可能不会填充任何值。因此,应用程序必须能够处理任何可能的 GPUAdapterInfo
值,包括这些值的缺失。
有关隐私方面的考虑,请参阅 § 2.2.6 适配器标识符。
[Exposed =(Window ,DedicatedWorker ),SecureContext ]interface GPUAdapterInfo {readonly attribute DOMString vendor ;readonly attribute DOMString architecture ;readonly attribute DOMString device ;readonly attribute DOMString description ; };
GPUAdapterInfo
具有以下属性:
vendor
, of type DOMString, readonly-
适配器 供应商的名称,如果可用的话。否则为空字符串。
architecture
, of type DOMString, readonly-
适配器 所属的 GPU 系列或类别的名称(如果可用)。否则为空字符串。
device
, of type DOMString, readonly-
适配器 的供应商特定标识符(如果可用)。否则为空字符串。
注:这是一个表示适配器类型的值。 例如,它可能是 PCI 设备 ID。 它不像序列号那样唯一地标识给定的硬件。
description
, of type DOMString, readonly-
描述驱动程序报告的 适配器 的人类可读字符串(如果可用)。 否则为空字符串。
注:因为没有格式应用于
description
,所以不建议尝试解析此值。 根据GPUAdapterInfo
更改其行为的应用程序,例如对已知驱动程序问题应用解决方法,应尽可能依赖其他字段。
-
让 adapterInfo 成为一个新的
GPUAdapterInfo
。 -
让 unmaskedValues 成为 adapter.
[[unmaskedIdentifiers]]
-
如果 unmaskedValues contains
"vendor"
并且供应商是已知的:否则:
-
如果 unmaskedValues contains
"architecture"
架构是已知的:-
将 adapterInfo.
architecture
设置为 normalized identifier string 表示 adapter 所属的适配器系列或类别 属于。
否则:
-
将 adapterInfo.
architecture
设置为空字符串或架构的合理近似值 规范化标识符字符串。
-
-
如果 unmaskedValues contains
"device"
并且设备是已知的:-
将 adapterInfo.
device
设置为 normalized identifier string 表示 adapter 的供应商特定标识符。
否则:
-
-
如果 unmaskedValues contains
"description"
并且描述是已知的:-
将 adapterInfo.
description
设置为 adapter 的描述 据司机报告。
否则:
-
将 adapterInfo.
description
设置为空字符串或描述的合理近似值。
-
-
返回 adapterInfo。
[a-z0-9]+(-[a-z0-9]+)*
3.7. 扩展文档
“扩展文档”是描述新功能的附加文档,这些新功能是非规范的并且不是 WebGPU/WGSL 规范的一部分。
它们描述了基于这些规范构建的功能,通常包括一个或多个新的 API 特性 标志和/或 WGSL enable
指令,或与其他网络规范草案的交互。
WebGPU 实现不得暴露扩展功能; 这样做是违反规范的。 在将新功能集成到 WebGPU 规范(本文档)和/或 WGSL 规范中之前,它不会成为 WebGPU 标准的一部分。
3.8. 源限制
WebGPU 允许访问存储在图像、视频和画布中的图像数据。 跨域媒体的使用受到限制,因为着色器可用于间接推断已上传到 GPU 的纹理内容。
WebGPU 不允许上传is not origin-clean 的图像源。
这也意味着使用 WebGPU 渲染的画布的 origin-clean 标志永远不会设置为“false”。
有关为图像和视频元素发出 CORS 请求的更多信息,请参阅:
3.9. 任务源
3.9.1. WebGPU 任务源
WebGPU 定义了一个新的 任务源 称为 WebGPU 任务源。
它用于 uncapturederror
事件和 GPUDevice
.lost
。
GPUDevice
device 排队全局任务,
通过一系列步骤步骤:
-
Queue a global task 在 WebGPU task source 上,使用用于创建 device 的全局对象,以及步骤 steps。
3.9.2. 自动过期任务源
WebGPU 定义了一个名为 自动过期任务源 的新 任务源。 它用于某些对象的自动、定时到期(销毁):
来自自动过期任务源的任务应该被高优先级处理; 特别是,一旦排队,它们应该在用户定义的(JavaScript)任务之前运行。
实施注: 通过在 event loop processing model 内的固定点插入额外步骤而不是运行实际任务来实现高优先级到期“任务”是有效的。
3.10. 颜色空间和编码
WebGPU 不提供颜色管理。 WebGPU 中的所有值(例如纹理元素)都是原始数值,而不是颜色管理颜色值。
WebGPU 确实与颜色管理输出(通过 GPUCanvasConfiguration
)和输入(通过 copyExternalImageToTexture()
和 importExternalTexture()
)进行交互。
因此,必须在 WebGPU 数值和外部颜色值之间进行颜色转换。
每个此类接口点都在本地定义一种编码(颜色空间、传递函数和 alpha 预乘),WebGPU 数值将在其中进行解释。
WebGPU 允许 PredefinedColorSpace
枚举中的所有颜色空间。
请注意,每个颜色空间都定义在扩展范围内,如引用的 CSS 定义所定义,以表示其空间之外的颜色值(色度和亮度)。
问题(gpuweb/gpuweb#1715): 考虑将 srgb 编码图像上传到线性编码纹理的路径。
色域外预乘 RGBA 值 是任何 R/G/B 通道值超过 alpha 通道值的值。 例如,预乘 sRGB RGBA 值 [1.0, 0, 0, 0.5] 表示具有 50% alpha 的(未预乘)颜色 [2, 0, 0],在 CSS 中写为 rgb(srgb 2 0 0 / 50%)
.
就像 sRGB 色域之外的任何颜色值一样,这是扩展颜色空间中定义明确的点(除非 alpha 为 0,在这种情况下没有颜色)。
但是,当这些值输出到可见画布时,结果是不确定的(参见 GPUCanvasAlphaMode
"premultiplied"
)。
3.10.1. Color Space Conversions
根据上面的定义,通过将颜色在一个空间中的表示转换为另一个空间中的表示,颜色在空间之间进行转换。
如果源值的 RGBA 通道少于 4 个,则在转换颜色空间/编码和 alpha 预乘之前,将缺少的绿色/蓝色/alpha 通道分别设置为“0、0、1”。 转换后,如果目标需要少于 4 个通道,则忽略额外的通道。
注: 灰度图像通常在其颜色空间中表示 RGB 值“(V, V, V)”或 RGBA 值“(V, V, V, A)”。
颜色在转换期间不会被有损限制:如果源颜色值在目标颜色空间的色域范围之外,则从一个颜色空间转换到另一个颜色空间将导致值超出 [0, 1] 范围。 例如,对于 sRGB 目标,如果源是 rgba16float,在更宽的色彩空间(如 Display-P3)中,或者预乘并包含 [=色域外预乘 RGBA 值|色域外值 = ].
类似地,如果源值具有高位深度(例如 PNG,每个组件 16 位)或扩展范围(例如,具有“float16”存储的画布),这些颜色将通过颜色空间转换保留,中间计算至少具有精度 的来源。
3.10.2. 色彩空间转换省略
如果颜色空间/编码转换的源和目标相同,则不需要转换。 一般来说,如果转换的任何给定步骤是恒等函数(无操作),实现应该将其省略,以提高性能。
为了获得最佳性能,应用程序应该设置它们的颜色空间和编码选项,以便在整个过程中最大限度地减少必要的转换次数。
对于 GPUImageCopyExternalImage
的各种图像源:
-
-
预乘通过
premultiplyAlpha
控制。 -
色彩空间通过
colorSpaceConversion
控制。
-
-
二维画布:
-
颜色空间通过
colorSpace
上下文创建属性控制。
-
WebGL 画布:
-
预乘通过
WebGLContextAttributes
中的premultipliedAlpha
选项控制。 -
通过
WebGLRenderingContext
的drawingBufferColorSpace
状态控制颜色空间。
-
注:在依赖这些功能之前,检查浏览器实现是否支持这些功能。
3.11. 从 JavaScript 到 WGSL 的数字转换
WebGPU API 的几个部分(pipeline-overridable constants
和 render pass clear values)从 WebIDL(double
或 float
)获取数值并将它们转换为 WGSL 值(bool
、i32
、u32
、f32
、f16
)。
double
或 float
类型 到 WGSL 类型 T,可能抛出 TypeError
:
注:此 TypeError
是在 device timeline 中生成的,从未出现在 JavaScript 中。
1.断言 idlValue 是一个有限值,因为它不是 unrestricted double
或 unrestricted float
。
1.使v 是 ! 转换 idlValue 为 ECMAScript value产生的 ECMAScript 数字。
-
- 如果T 是“布尔”
-
返回 ! 转换 v 到 一个 IDL value 的结果对应的 WGSL
bool
值,boolean
类型。注: 在从 ECMAScript 值转换为 IDL
double
或float
值后调用此算法。如果原始 ECMAScript 值是非数字、非布尔值,如“[]”或“{}”,则 WGSL 的“bool”结果可能与 ECMAScript 值已直接转换为 IDLboolean
。 - 如果T 是
i32
-
返回? 将 v 一个 IDL 值 的结果对应的WGSL
i32
值,[EnforceRange
]long
类型。 - 如果T 是
u32
-
返回 ? 将 v 一个 IDL 值 的结果对应的 WGSL
u32
值,[EnforceRange
]unsigned long
类型。 - 如果T 是
f32
-
返回? 将 v 一个 IDL value 结果对应的WGSL
f32
值,float
类型。 - 如果T 是
f16
-
1.让wgslF32 是 ? 转换 v 到 一个 IDL value 的结果对应的 WGSL
f32
值,float
类型。 1.返回f16(wgslF32)
,! 将 WGSLf32
值转换为f16
的结果,如 WGSL 浮点转换 中所定义。注:只要该值在
f32
的范围内,就不会抛出错误,即使该值超出f16
的范围。
GPUColor
color 到纹理格式的纹素值 format,可能会抛出一个TypeError
:
注:此 TypeError
是在 设备时间线 中生成的,从未出现在 JavaScript 中。
-
如果 format 的组件 (assert 它们都具有相同的类型)是:
-
:浮点类型或规范化类型
-
让T 是
f32
。 - 有符号整数类型
-
让T 是
i32
。 - 无符号整数类型
-
让T 是
u32
。
-
1.让wgslColor 是 vec4<T>
类型的 WGSL 值,其中 4 个分量是 color 的 RGBA 通道,每个 ? 转换为 to WGSL type |T |。
1.转换wgslColor 到格式化 使用与 § 23.3.7 输出合并 步骤相同的转换规则,并返回结果。
注: 对于非整数类型,值的确切选择是实现定义的。 对于规范化类型,值被限制在类型的范围内。
注:
换句话说,写入的值就好像是由 WGSL 着色器写入的,该着色器输出表示为 f32
、i32
或 u32
的 vec4
的值。
4. 初始化
4.1. navigator.gpu
GPU
对象分别通过 Navigator
和 WorkerNavigator
接口在 Window
和 DedicatedWorkerGlobalScope
上下文中可用,并通过 navigator.gpu
暴露出来:
interface mixin { [
NavigatorGPU SameObject ,SecureContext ]readonly attribute GPU ; };
gpu Navigator includes NavigatorGPU ;WorkerNavigator includes NavigatorGPU ;
4.2. GPU
GPU
是 WebGPU 的入口。
[Exposed =(Window ,DedicatedWorker ),SecureContext ]interface GPU {Promise <GPUAdapter ?>requestAdapter (optional GPURequestAdapterOptions options = {});GPUTextureFormat getPreferredCanvasFormat (); [SameObject ]readonly attribute WGSLLanguageFeatures wgslLanguageFeatures ; };
GPU
具有以下方法和属性:
requestAdapter(options)
-
从用户代理请求 适配器。 用户代理选择是否返回适配器,如果是,则根据提供的选项进行选择。
Called on:GPU
this.Arguments:
Arguments for the GPU.requestAdapter(options) method. Parameter Type Nullable Optional Description options
GPURequestAdapterOptions
✘ ✔ 选择适配器的标准。 Returns:
Promise
<GPUAdapter
?>Content timeline steps:
1.让 contentTimeline 成为当前 内容时间线。 1.让 promise 成为 a new promise。 1.在 this 的 设备时间线 上发出initialization steps。
-
返回promise。
Device timeline initialization steps:-
让 adapter 为
null
. -
如果用户代理选择返回一个适配器,它应该:
-
设置 adapter 为一个 有效 适配器,根据 § 4.2.2 适配器选择 中的规则和 options 中的标准选择,遵守 § 4.2.1 Adapter Capability Guarantees。
适配器的 支持的限制 必须符合 § 3.6.2 限制 中定义的要求。
-
如果适配器 满足 fallback adapter 的标准,设置 adapter.
[[fallback]]
为 true。
-
-
在 内容时间线 上发布后续步骤.
Content timeline steps:-
如果 adapter 不为
null
:-
使用一个新的
GPUAdapter
去封装 adapter解析 promise。
-
-
否则, 解析 promise 为
null
.
-
getPreferredCanvasFormat()
-
返回用于在此系统上显示 8 位深度、标准动态范围内容的最佳
GPUTextureFormat
。 只能返回"rgba8unorm"
或"bgra8unorm"
。返回值可以作为
format
传递给configure()
调用GPUCanvasContext
以确保关联的画布能够有效地显示其内容。注:未显示在屏幕上的画布可能会或可能不会从使用此格式中受益。
Called on:GPU
this.Returns:
GPUTextureFormat
内容时间线 步骤:
-
返回
"rgba8unorm"
或"bgra8unorm"
,具体取决于哪种格式最适合在此系统上显示 WebGPU 画布。
-
wgslLanguageFeatures
, of type WGSLLanguageFeatures, readonly-
受支持的 WGSL language extensions 的名称。 支持的语言扩展会自动启用。
适配器 可能 随时变为 无效 ("expire")。
在系统状态发生任何可能影响任何 requestAdapter()
调用结果的变化时,用户代理应该使所有先前返回的适配器过期。 例如:
-
添加/移除物理适配器(通过插入/拔出、驱动程序更新、挂起恢复等)
-
系统的电源配置已更改(笔记本电脑已拔出、电源设置已更改等)
注:
用户代理可能会经常选择 expire 适配器,即使没有系统状态更改(例如,创建适配器后的几秒或几分钟)。
这有助于混淆真实的系统状态变化,并让开发人员更加意识到在调用 requestDevice()
之前再次调用 requestAdapter()
总是必要的。
如果应用程序确实遇到这种情况,标准的设备丢失恢复处理应该允许它恢复。
4.2.1. Adapter Capability Guarantees
requestAdapter()
返回的任何 GPUAdapter
必须提供以下保证:
-
以下至少一项必须为真:
-
所有 alignment-class 限制必须是 2 的幂。
-
maxBindingsPerBindGroup
必须是 ≥ (每个着色器阶段的最大绑定 × 每个管线的最大着色器阶段),其中:-
每个着色器阶段的最大绑定数 是 (
maxSampledTexturesPerShaderStage
+maxSamplersPerShaderStage
+maxStorageBuffersPerShaderStage
+maxStorageTexturesPerShaderStage
+maxUniformBuffersPerShaderStage
)。 -
max shader stages per pipeline 是
2
,因为GPURenderPipeline
支持顶点和片段着色器。
注:
maxBindingsPerBindGroup
不反映基本限制; 实现应该提高它以符合这个要求,而不是降低 其他限制。 -
-
minUniformBufferOffsetAlignment
和minStorageBufferOffsetAlignment
必须都是 ≥ 32 字节。注:32 字节将是
vec4<f64>
的对齐方式。 参见 WebGPU Shading Language § 13.4.1 Alignment and Size。 -
maxStorageBufferBindingSize
必须是 4 字节的倍数。 -
maxVertexBufferArrayStride
必须是 4 字节的倍数。 -
maxComputeWorkgroupSizeX
必须 ≤maxComputeInvocationsPerWorkgroup
。 -
maxComputeWorkgroupSizeY
必须 ≤maxComputeInvocationsPerWorkgroup
。 -
maxComputeWorkgroupSizeZ
必须 ≤maxComputeInvocationsPerWorkgroup
。 -
maxComputeInvocationsPerWorkgroup
必须 ≤maxComputeWorkgroupSizeX
×maxComputeWorkgroupSizeY
×maxComputeWorkgroupSizeZ
。
4.2.2. 适配器选择
GPURequestAdapterOptions
向用户代理提供提示,指示哪种配置适合该应用程序。
dictionary GPURequestAdapterOptions {GPUPowerPreference powerPreference ;boolean forceFallbackAdapter =false ; };
enum {
GPUPowerPreference "low-power" ,"high-performance" };
GPURequestAdapterOptions
拥有以下成员:
powerPreference
, of type GPUPowerPreference-
可选地提供提示,指示应从系统的可用适配器中选择 适配器 的类别。
此提示的值可能会影响选择哪个适配器,但不得影响是否返回适配器。
注: 此提示的主要用途是影响在多 GPU 系统中使用哪个 GPU。 例如,一些笔记本电脑具有低功耗集成 GPU 和高性能独立 GPU。 此提示还可能会影响所选 GPU 的电源配置,以匹配请求的电源首选项。
注: 根据具体的硬件配置,例如电池状态和连接的显示器或可拆卸的 GPU,用户代理可以选择不同的 适配器 给定相同的电源偏好。 通常,给定相同的硬件配置和状态以及“powerPreference”,用户代理很可能会选择相同的适配器。
它必须是以下值之一:
undefined
(or not present)-
没有对于用户代理的提示。
"low-power"
-
指将节能优先于性能的请求。
注: 通常,如果内容不太可能受到绘图性能的限制,则应该使用它; 例如,如果它每秒只渲染一帧,只使用简单的着色器绘制相对简单的几何图形,或者使用一个小的 HTML canvas 元素。 如果内容允许,鼓励开发人员使用此值,因为它可以显着延长便携式设备的电池寿命。
"high-performance"
-
指将性能优先于功耗的请求。
注: 通过选择这个值,开发人员应该意识到,对于在生成的适配器上创建的 设备,用户代理更有可能强制设备丢失,以便通过切换到低功率适配器来节省功率。 鼓励开发人员仅在他们认为绝对必要时才指定此值,因为它可能会显着缩短便携式设备的电池寿命。
forceFallbackAdapter
, of type boolean, defaulting tofalse
-
当设置为 true 时,表示可能只返回 备用适配器。 如果用户代理不支持 备用适配器,将导致
requestAdapter()
解析为“null”。注: 如果
forceFallbackAdapter
设置为“false”并且没有其他合适的 适配器 可用或用户代理选择,返回一个 备用适配器。 希望阻止其应用程序在 备用适配器 上运行的开发人员应在请求GPUDevice
之前检查GPUAdapter
.isFallbackAdapter
属性。
"high-performance"
GPUAdapter
:
const gpuAdapter= await navigator. gpu. requestAdapter({ powerPreference: 'high-performance' });
4.3. GPUAdapter
GPUAdapter
封装了一个 adapter,并描述了它的功能(特性 和 限制)。
要获得 GPUAdapter
,请使用 requestAdapter()
。
[Exposed =(Window ,DedicatedWorker ),SecureContext ]interface GPUAdapter { [SameObject ]readonly attribute GPUSupportedFeatures features ; [SameObject ]readonly attribute GPUSupportedLimits limits ;readonly attribute boolean isFallbackAdapter ;Promise <GPUDevice >requestDevice (optional GPUDeviceDescriptor descriptor = {});Promise <GPUAdapterInfo >requestAdapterInfo (optional sequence <DOMString >unmaskHints = []); };
GPUAdapter
拥有以下属性:
features
, of type GPUSupportedFeatures, readonly-
this
.[[adapter]]
.[[features]]
中的值的集合。 limits
, of type GPUSupportedLimits, readonly-
this
.[[adapter]]
.[[limits]]
中的限制。 isFallbackAdapter
, of type boolean, readonly-
返回
[[adapter]]
.[[fallback]]
的值。
GPUAdapter
has the following internal slots:
[[adapter]]
, 类型为 适配器, 只读-
GPUAdapter
指向的 [= 适配器 =]。
GPUAdapter
拥有以下方法:
requestDevice(descriptor)
-
这是一次性操作:如果成功返回设备,则适配器变为 无效。
Called on:GPUAdapter
this.Arguments:
Arguments for the GPUAdapter.requestDevice(descriptor) method. Parameter Type Nullable Optional Description descriptor
GPUDeviceDescriptor
✘ ✔ Description of the GPUDevice
to request.Content timeline steps:
-
使 contentTimeline 为当前 内容时间线.
-
使 promise 为 a new promise.
-
使 adapter 为 this.
[[adapter]]
. -
在 this 的 Device timeline 发起 initialization steps.
-
返回 promise.
Device timeline initialization steps:-
如果以下任何条件没有满足:
-
descriptor.
requiredFeatures
中的值集必须是 adapter.[[features]]
中值的子集。
然后在 contentTimeline 上执行以下步骤并返回:
注:这与浏览器根本不知道功能名称(在其
GPUFeatureName
定义中)时产生的错误相同。 这将浏览器不支持某项功能时的行为与特定适配器不支持某项功能时的行为融合在一起。 -
-
如果未满足以下任何要求:
-
descriptor 中的每个键。
requiredLimits
必须是 supported limits 成员的名称。 -
对于每个限制名称 key 在 supported limits 的键中: 让value 是 descriptor.
requiredLimits
[key]。-
value 必须不 更好 adapter 中的限制值。
[[limits]]
。
-
然后在 contentTimeline 上执行以下步骤并返回:
Content timeline 步骤:-
以一个
OperationError
拒绝 promise
1.如果adapter 无效,否则用户代理无法满足请求:
1.让device 成为一个新的 shebei1。
-
注: 这使得 adapter invalid,如果还没有的话。
注: 当这种情况发生时,用户代理应该考虑在大多数或所有情况下发出开发人员可见的警告。 应用程序应从
requestAdapter()
开始执行重新初始化逻辑。
否则:
1.让device 成为具有 descriptor 描述的功能的新设备。 1.制作adapter.
[[adapter]]
无效。 -
-
在 contentTimeline 上发布后续步骤。
-
requestAdapterInfo()
-
请求此
GPUAdapter
的GPUAdapterInfo
。注:适配器信息值与 Promise 一起返回,使用户代理有机会在请求未屏蔽的值时执行可能长时间运行的检查,例如在返回前征求用户同意。 但是,如果未指定
unmaskHints
,则不应向用户显示任何对话框。Called on:GPUAdapter
this.Arguments:
Arguments for the GPUAdapter.requestAdapterInfo() method. Parameter Type Nullable Optional Description unmaskHints
sequence<DOMString>
✘ ✔ GPUAdapterInfo
属性名称列表,如果可用,需要未屏蔽值。Returns:
Promise
<GPUAdapterInfo
>内容时间线 步骤:
-
使 promise 为 a new promise.
-
使 adapter 为 this.
[[adapter]]
. -
如果 this 的 relevant global object 具有 transient activation,使 hasActivation 为
true
, 否则为false
。 -
在 in parallel 上运行以下步骤:
-
如果 unmaskHints.length >
0
:-
如果 hasActivation 为
false
以一个NotAllowedError
拒绝 promise 并停止此步骤。 -
让 unmaskedKeys 是 unmaskHints 中指定的用户代理决定取消屏蔽的字段的 list,如果有的话。
注:用户代理可以自由使用它认为合适的任何方法来决定要取消屏蔽哪些字段。
-
Append unmaskedKeys 为 adapter.
[[unmaskedIdentifiers]]
。
-
-
以一个 new adapter info 对 adapter 解析 promise。
-
-
返回 promise.
-
GPUDevice
:
const gpuAdapter= await navigator. gpu. requestAdapter(); const gpuDevice= await gpuAdapter. requestDevice();
4.3.1. GPUDeviceDescriptor
GPUDeviceDescriptor
describes a device request.
dictionary GPUDeviceDescriptor :GPUObjectDescriptorBase {sequence <GPUFeatureName >requiredFeatures = [];record <DOMString ,GPUSize64 >requiredLimits = {};GPUQueueDescriptor defaultQueue = {}; };
GPUDeviceDescriptor
has the following members:
requiredFeatures
, of type sequence<GPUFeatureName>, defaulting to[]
-
指定设备请求所需的 特性。 如果适配器不能提供这些功能,请求将失败。
在生成的设备上验证 API 调用时,将允许完全指定的一组功能,不多也不少。
requiredLimits
, of type record<DOMString, GPUSize64>, defaulting to{}
-
指定设备请求所需的 限制。 如果适配器不能提供这些限制,请求将失败。
每个键必须是 支持的限制 成员的名称。 在生成的设备上验证 API 调用时,将允许完全指定的限制,并且不允许 更好 或更糟。
defaultQueue
, of type GPUQueueDescriptor, defaulting to{}
-
默认
GPUQueue
的描述符。
GPUDevice
with the "texture-compression-astc"
feature if supported:
const gpuAdapter= await navigator. gpu. requestAdapter(); const requiredFeatures= []; if ( gpuAdapter. features. has( 'texture-compression-astc' )) { requiredFeatures. push( 'texture-compression-astc' ) } const gpuDevice= await gpuAdapter. requestDevice({ requiredFeatures});
4.3.1.1. GPUFeatureName
每个 GPUFeatureName
标识一组功能,如果可用,则允许 WebGPU 的其他使用,否则这些功能将无效。
enum GPUFeatureName {"depth-clip-control" ,"depth32float-stencil8" ,"texture-compression-bc" ,"texture-compression-etc2" ,"texture-compression-astc" ,"timestamp-query" ,"indirect-first-instance" ,"shader-f16" ,"rg11b10ufloat-renderable" ,"bgra8unorm-storage" ,"float32-filterable" };
4.4. GPUDevice
GPUDevice
封装了 device 并公开了该设备的功能。
GPUDevice
是创建 WebGPU interfaces 的顶级接口。
要获取 GPUDevice
,请使用 requestDevice()
。
[Exposed =(Window ,DedicatedWorker ),SecureContext ]interface GPUDevice :EventTarget { [SameObject ]readonly attribute GPUSupportedFeatures features ; [SameObject ]readonly attribute GPUSupportedLimits limits ; [SameObject ]readonly attribute GPUQueue queue ;undefined destroy ();GPUBuffer createBuffer (GPUBufferDescriptor descriptor );GPUTexture createTexture (GPUTextureDescriptor descriptor );GPUSampler createSampler (optional GPUSamplerDescriptor descriptor = {});GPUExternalTexture importExternalTexture (GPUExternalTextureDescriptor descriptor );GPUBindGroupLayout createBindGroupLayout (GPUBindGroupLayoutDescriptor descriptor );GPUPipelineLayout createPipelineLayout (GPUPipelineLayoutDescriptor descriptor );GPUBindGroup createBindGroup (GPUBindGroupDescriptor descriptor );GPUShaderModule createShaderModule (GPUShaderModuleDescriptor descriptor );GPUComputePipeline createComputePipeline (GPUComputePipelineDescriptor descriptor );GPURenderPipeline createRenderPipeline (GPURenderPipelineDescriptor descriptor );Promise <GPUComputePipeline >createComputePipelineAsync (GPUComputePipelineDescriptor descriptor );Promise <GPURenderPipeline >createRenderPipelineAsync (GPURenderPipelineDescriptor descriptor );GPUCommandEncoder createCommandEncoder (optional GPUCommandEncoderDescriptor descriptor = {});GPURenderBundleEncoder createRenderBundleEncoder (GPURenderBundleEncoderDescriptor descriptor );GPUQuerySet createQuerySet (GPUQuerySetDescriptor descriptor ); };GPUDevice includes GPUObjectBase ;
GPUDevice
has the following attributes:
features
, of type GPUSupportedFeatures, readonly-
包含设备支持的功能(即创建它的功能)的
GPUFeatureName
值的集合。 limits
, of type GPUSupportedLimits, readonly-
公开设备支持的限制(这正是创建它时所用的限制)。
queue
, of type GPUQueue, readonly-
此设备的主要
GPUQueue
。
GPUDevice
的 [[device]]
是 GPUDevice
引用的 设备。
GPUDevice
具有上面的 WebIDL 定义中列出的方法。
此处未定义的那些在本文档的其他地方定义。
destroy()
-
销毁 设备,防止对其进行进一步操作。 未完成的异步操作将失败。
-
一旦所有当前在此设备上的任何队列上排队的操作完成后,在当前时间线上发出后续步骤。
-
Lose the device(this.
[[device]]
,"destroyed"
).
注:多次销毁设备有效。
注:由于没有进一步的操作可以在此设备上排队,实现可以立即中止未完成的异步操作并释放资源分配,包括刚刚取消映射的映射内存。
GPUDevice
's allowed buffer usages are:
GPUDevice
's allowed texture usages are:
-
Always allowed:
COPY_SRC
,COPY_DST
,TEXTURE_BINDING
,STORAGE_BINDING
,RENDER_ATTACHMENT
4.5. 示例
GPUAdapter
和 GPUDevice
的更强大示例:
let gpuDevice= null ; async function initializeWebGPU() { // Check to ensure the user agent supports WebGPU. if ( ! ( 'gpu' in navigator)) { console. error( "User agent doesn’t support WebGPU." ); return false ; } // Request an adapter. const gpuAdapter= await navigator. gpu. requestAdapter(); // requestAdapter may resolve with null if no suitable adapters are found. if ( ! gpuAdapter) { console. error( 'No WebGPU adapters found.' ); return false ; } // Request a device. // Note that the promise will reject if invalid options are passed to the optional // dictionary. To avoid the promise rejecting always check any features and limits // against the adapters features and limits prior to calling requestDevice(). gpuDevice= await gpuAdapter. requestDevice(); // requestDevice will never return null, but if a valid device request can’t be // fulfilled for some reason it may resolve to a device which has already been lost. // Additionally, devices can be lost at any time after creation for a variety of reasons // (ie: browser resource management, driver updates), so it’s a good idea to always // handle lost devices gracefully. gpuDevice. lost. then(( info) => { console. error( `WebGPU device was lost: ${ info. message} ` ); gpuDevice= null ; // Many causes for lost devices are transient, so applications should try getting a // new device once a previous one has been lost unless the loss was caused by the // application intentionally destroying the device. Note that any WebGPU resources // created with the previous device (buffers, textures, etc) will need to be // re-created with the new one. if ( info. reason!= 'destroyed' ) { initializeWebGPU(); } }); onWebGPUInitialized(); return true ; } function onWebGPUInitialized() { // Begin creating WebGPU resources here... } initializeWebGPU();
5. Buffers
5.1. GPUBuffer
GPUBuffer
表示可用于 GPU 操作的内存块。
数据以线性布局存储,这意味着分配的每个字节都可以通过它从 GPUBuffer
开始的偏移量来寻址,取决于操作的对齐限制。 一些 GPUBuffers
可以被映射,这使得内存块可以通过称为其映射的 ArrayBuffer
访问。
GPUBuffer
通过 createBuffer()
创建。
缓冲区可能是 mappedAtCreation
。
[Exposed =(Window ,DedicatedWorker ),SecureContext ]interface GPUBuffer {readonly attribute GPUSize64 size ;readonly attribute GPUBufferUsageFlags usage ;readonly attribute GPUBufferMapState mapState ;Promise <undefined >mapAsync (GPUMapModeFlags mode ,optional GPUSize64 offset = 0,optional GPUSize64 size );ArrayBuffer getMappedRange (optional GPUSize64 offset = 0,optional GPUSize64 size );undefined unmap ();undefined destroy (); };GPUBuffer includes GPUObjectBase ;enum GPUBufferMapState {"unmapped" ,"pending" ,"mapped" };
size
, of type GPUSize64, readonly-
GPUBuffer
分配的字节长度。 usage
, of type GPUBufferUsageFlags, readonly-
此
GPUBuffer
的允许用途。 [[internals]]
, 类型为 buffer internals, 只读,override
mapState
, of type GPUBufferMapState, readonly-
缓冲区的当前
GPUBufferMapState
:"unmapped"
-
缓冲区未映射供“this”使用。
getMappedRange()
。 "pending"
-
已请求缓冲区的映射,但尚未完成。 它可能会在
mapAsync()
中验证成功或失败。 "mapped"
-
缓冲区已映射,并且可以使用
this
.getMappedRange()
。
The getter steps are:
Content timeline 步骤:-
如果 this.
[[mapping]]
不是null
, 返回"mapped"
。 -
如果 this.
[[pending_map]]
不是null
, 返回"pending"
。 -
返回
"unmapped"
。
[[pending_map]]
, 类型为Promise
<void> 或null
, 初始为null
-
当前未决的
mapAsync()
调用返回的Promise
。挂起的映射永远不会超过一个,因为如果请求已经在进行中,
mapAsync()
将立即拒绝。 [[mapping]]
, 类型为 active buffer mapping 或null
, 初始为null
-
当且仅当缓冲区当前被映射以供
getMappedRange()
使用时设置。 否则为空(即使有[[pending_map]]
)。active buffer mapping 是一个包含以下字段的结构:
- data, of type Data Block
-
此
GPUBuffer
的映射。 此数据通过ArrayBuffer
访问,ArrayBuffer
是此数据的视图,由getMappedRange()
返回并存储在 views 中。 - mode, of type
GPUMapModeFlags
-
地图的
GPUMapModeFlags
,在对mapAsync()
或createBuffer()
的相应调用中指定。 - range, of type tuple [
unsigned long long
,unsigned long long
] -
此
GPUBuffer
映射的范围。 - views, of type list<
ArrayBuffer
> -
ArrayBuffer
通过getMappedRange()
返回给应用程序。 它们被跟踪,因此可以在调用unmap()
时分离它们。
使用模式 mode 和范围 range 来 初始化一个活动缓冲区映射 :-
让 size 为 range[1] - range[0]。
-
让 data 为 ? CreateByteDataBlock(size)。
注: 这可能会导致抛出RangeError
。 为了一致性和可预测性:-
对于
new ArrayBuffer()
在给定时刻成功的任何大小,此分配应该在那一刻成功。 -
对于
new ArrayBuffer()
确定性 抛出RangeError
的任何大小,此分配也应该。
-
-
返回一个 active buffer mapping 且:
GPUBuffer
的 internal object 是 buffer internals,它使用以下 device timeline slots 扩展 internal object:
- state
-
缓冲区的当前内部状态:
5.1.1. GPUBufferDescriptor
dictionary GPUBufferDescriptor :GPUObjectDescriptorBase {required GPUSize64 size ;required GPUBufferUsageFlags usage ;boolean mappedAtCreation =false ; };
GPUBufferDescriptor
拥有以下成员:
size
, of type GPUSize64-
缓冲大小,以字节为单位。
usage
, of type GPUBufferUsageFlags-
缓冲的可用用途。
mappedAtCreation
, of type boolean, defaulting tofalse
-
如果 true 以已映射状态创建缓冲区,则允许立即调用
getMappedRange()
。 即使usage
不包含MAP_READ
或MAP_WRITE
,将mappedAtCreation
设置为“true”也是有效的。 这可用于设置缓冲区的初始数据。保证即使缓冲区创建最终失败,在取消映射之前,它仍然会显示为可以写入/读取映射范围。
5.1.2. 缓冲区使用
typedef [EnforceRange ]unsigned long ; [
GPUBufferUsageFlags Exposed =(Window ,DedicatedWorker ),SecureContext ]namespace {
GPUBufferUsage const GPUFlagsConstant MAP_READ = 0x0001;const GPUFlagsConstant MAP_WRITE = 0x0002;const GPUFlagsConstant COPY_SRC = 0x0004;const GPUFlagsConstant COPY_DST = 0x0008;const GPUFlagsConstant INDEX = 0x0010;const GPUFlagsConstant VERTEX = 0x0020;const GPUFlagsConstant UNIFORM = 0x0040;const GPUFlagsConstant STORAGE = 0x0080;const GPUFlagsConstant INDIRECT = 0x0100;const GPUFlagsConstant QUERY_RESOLVE = 0x0200; };
GPUBufferUsage
标志决定了 GPUBuffer
在创建后如何使用:
MAP_READ
-
可以映射缓冲区以供读取。(示例:使用
GPUMapMode.READ
调用mapAsync()
)只能与
COPY_DST
结合使用。 MAP_WRITE
-
可以映射缓冲区以进行写入。(示例:使用
GPUMapMode.WRITE
调用mapAsync()
)只能与
COPY_SRC
结合使用。 COPY_SRC
-
缓冲区可以用作复制操作的源。(示例:作为
copyBufferToBuffer()
或copyBufferToTexture()
调用的source
参数。) COPY_DST
-
缓冲区可用作复制或写入操作的目标。(示例:作为
copyBufferToBuffer()
或copyTextureToBuffer()
调用的“目标”参数,或作为writeBuffer()
调用的目标。) INDEX
-
该缓冲区可用作索引缓冲区。(示例:传递给
setIndexBuffer()
。) VERTEX
-
该缓冲区可用作顶点缓冲区。(示例:传递给
setVertexBuffer()
。) UNIFORM
-
该缓冲区可以用作统一缓冲区。(示例:作为
GPUBufferBindingLayout
的绑定组条目,其buffer
.type
为"uniform"
。) STORAGE
-
缓冲区可以用作存储缓冲区。(示例:作为具有
buffer
的GPUBufferBindingLayout
的绑定组条目。type
为"storage"
或"read- 仅存储“
。) INDIRECT
-
缓冲区可用于存储间接命令参数。(示例:作为
drawIndirect()
或dispatchWorkgroupsIndirect()
调用的indirectBuffer
参数。) QUERY_RESOLVE
-
缓冲区可用于捕获查询结果。(示例:作为
resolveQuerySet()
调用的“目标”参数。)
5.1.3. 缓冲区创建
createBuffer(descriptor)
-
创建一个
GPUBuffer
.Called on:GPUDevice
this.Arguments:
Arguments for the GPUDevice.createBuffer(descriptor) method. Parameter Type Nullable Optional Description descriptor
GPUBufferDescriptor
✘ ✘ 要创建的 GPUBuffer
的描述。Returns:
GPUBuffer
Content timeline steps:
-
使 [b, bi] 为 ! create a new WebGPU object(this,
GPUBuffer
, descriptor). -
如果 descriptor.
mappedAtCreation
为true
:-
设置 b.
[[mapping]]
为 ? initialize an active buffer mapping,模式为WRITE
范围为[0, descriptor.
.size
]
-
-
在 this 的 设备时间线上发起initialization steps
-
返回 b。
Device timeline initialization steps:-
如果以下任何条件没有满足, generate a validation error, 使 bi 无效, 并停止。
-
device 必须 有效。
-
descriptor.
usage
必须不为 0. -
descriptor.
usage
必须为 device’s allowed buffer usages 的一个子集。 -
如果 descriptor.
size
必须 ≤ device.[[device]]
.[[limits]]
.maxBufferSize
. -
如果 descriptor.
mappedAtCreation
为true
:-
descriptor.
size
必须为 4 的倍数。
-
-
注:如果缓冲区创建失败,并且 descriptor.
mappedAtCreation
为“false”,则对mapAsync()
的任何调用都将被拒绝,因此分配用于启用映射的任何资源都可以而且可能是丢弃或回收。-
如果 descriptor.
mappedAtCreation
为“真”:-
将 bi.state 设置为“unavailable”。
另外:
-
-
为 bi 创建设备分配 每个字节都为零。
-
const buffer= gpuDevice. createBuffer({ size: 128 , usage: GPUBufferUsage. UNIFORM| GPUBufferUsage. COPY_DST});
5.1.4. 缓冲区销毁
不再需要 GPUBuffer
的应用程序可以通过调用 destroy()
选择在垃圾收集之前失去对它的访问。 销毁缓冲区也会取消映射,释放为映射分配的所有内存。
注:这允许用户代理在所有先前使用它提交的操作完成后回收与 GPUBuffer
关联的 GPU 内存。
destroy()
-
销毁
GPUBuffer
. -
调用 this.
unmap()
. -
在 this.
[[device]]
的 Device timeline 上发布后续步骤。 -
将 this.
[[internals]]
.state 设置为“destroyed”。
注:多次销毁缓冲区是有效的。
GPUBuffer
this.
Returns: undefined
内容时间线 步骤:
注:由于没有进一步的操作可以使用此缓冲区排队,因此实现可以释放资源分配,包括刚刚取消映射的映射内存。
5.2. 缓冲区映射
应用程序可以请求映射 GPUBuffer
,以便它们可以通过代表 GPUBuffer
分配部分的 ArrayBuffer
访问其内容。异步请求映射 GPUBuffer
mapAsync()
以便用户代理可以确保 GPU 在应用程序可以访问其内容之前完成使用 GPUBuffer
。
映射的 GPUBuffer
不能被 GPU 使用,必须使用 unmap()
取消映射,然后才能将使用它的工作提交到 队列时间线。
一旦 GPUBuffer
被映射,应用程序可以使用 getMappedRange()
同步请求访问其内容范围。
返回的 ArrayBuffer
只能通过 unmap()
detached(直接,或通过 GPUBuffer
.destroy()
或 GPUDevice
.destroy()
),并且不能是transferred。 TypeError
被试图这样做的任何其他操作抛出。
typedef [EnforceRange ]unsigned long ; [
GPUMapModeFlags Exposed =(Window ,DedicatedWorker ),SecureContext ]namespace {
GPUMapMode const GPUFlagsConstant READ = 0x0001;const GPUFlagsConstant WRITE = 0x0002; };
GPUMapMode
标志确定调用 mapAsync()
时如何映射 GPUBuffer
:
READ
-
仅对使用
MAP_READ
用法创建的缓冲区有效。映射缓冲区后,调用
getMappedRange()
将返回包含缓冲区当前值的ArrayBuffer
。 在调用unmap()
后,将丢弃对返回的ArrayBuffer
的更改。 WRITE
-
仅对使用
MAP_WRITE
用法创建的缓冲区有效。映射缓冲区后,调用
getMappedRange()
将返回包含缓冲区当前值的ArrayBuffer
。 在调用unmap()
后,对返回的ArrayBuffer
的更改将存储在GPUBuffer
中。注:由于
MAP_WRITE
缓冲区使用只能与COPY_SRC
缓冲区使用相结合,写入映射永远不会返回 GPU 生成的值,返回的ArrayBuffer
将 仅包含默认初始化数据(零)或网页在先前映射期间写入的数据。
mapAsync(mode, offset, size)
-
映射
GPUBuffer
的给定范围,并在GPUBuffer
的内容准备好使用getMappedRange()
访问时解析返回的Promise
。返回的
Promise
的决议仅表示缓冲区已被映射。 它不保证 content timeline 可见的任何其他操作的完成,尤其不暗示从onSubmittedWorkDone()
或其他 {{GPUBuffer
上的 mapAsync()}} 已解决。从
onSubmittedWorkDone()
返回的Promise
的决议确实意味着在GPUBuffer
上完成该调用之前进行的mapAsync()
用于该队列的最后专门调用。Called on:GPUBuffer
this.Arguments:
Arguments for the GPUBuffer.mapAsync(mode, offset, size) method. Parameter Type Nullable Optional Description mode
GPUMapModeFlags
✘ ✘ 缓冲区是否应该映射为读取或写入。 offset
GPUSize64
✘ ✔ 以字节为单位的偏移量到缓冲区到要映射的范围的开始。 size
GPUSize64
✘ ✔ 要映射的范围的大小(以字节为单位)。 内容时间线 步骤:
-
让 contentTimeline 成为当前 内容时间线。
-
如果 this.
[[pending_map]]
不是null
: -
让p 成为新的
Promise
。 -
将 this.
[[pending_map]]
设置为 p。 -
发布验证步骤 在 this 的 Device timeline 上。
[[device]]
。 -
返回 p。
设备时间线 validation steps:-
如果 size 为
undefined
:-
使 rangeSize 为 max(0, this.
size
- offset).
否则:
-
使 rangeSize 为 size.
-
-
如果以下任何条件未满足:
Then:
-
在 contentTimeline 上发起 map failure steps
-
返回。
-
-
设置 this.
[[internals]]
.state 为 "unavailable".注:由于缓冲区已映射,因此其内容不能在此完成和
unmap()
之间更改。 -
如果 this.
[[device]]
丢失,或者当它 becomes lost 时:-
在内容时间线上运行地图失败步骤。
否则,在未指定的点:
-
在完成当前使用this的排队操作后,
-
并且不晚于 device timeline 收到 all currently-enqueued operations 完成通知后的下一个 device timeline 操作(无论它们是否 使用 这个),
运行以下步骤:
-
让 internalStateAtCompletion 是 this.
[[internals]]
.state。注:当且仅当此时缓冲区由于
unmap()
调用再次变为“available”,则[[pending_map ]]
!= p 下面,所以映射将不会在下面的步骤中成功。 -
让 dataForMappedRegion 是this的内容 从偏移量 offset 开始,对于 rangeSize 字节。
-
在 contentTimeline 上运行map success steps。
-
内容时间线 map success steps:-
如果 this.
[[pending_map]]
!= p:注:映射已被
unmap()
取消。-
断言 p 被拒绝。
-
返回。
-
-
断言 p 被挂起。
-
断言 internalStateAtCompletion 为 "unavailable".
-
使 mapping 为 initialize an active buffer mapping,模式为 mode 且范围为
[offset, offset + rangeSize]
.如果分配失败:
-
设置 this.
[[pending_map]]
为null
, 且以一个RangeError
reject p。 -
返回。
-
-
设置 mapping.data 的内容为 dataForMappedRegion.
-
设置 this.
[[mapping]]
为 mapping. -
设置 this.
[[pending_map]]
为null
,且 resolve p.
Content timeline map failure steps:-
如果 this.
[[pending_map]]
!= p:注:映射已被
unmap()
取消。-
断言 p 已被拒绝。
-
返回。
-
-
断言 p 仍被挂起。
-
设置 this.
[[pending_map]]
为null
,并且以一个OperationError
拒绝 p
-
getMappedRange(offset, size)
-
返回一个
ArrayBuffer
,其中包含给定映射范围内GPUBuffer
的内容。Called on:GPUBuffer
this.Arguments:
Arguments for the GPUBuffer.getMappedRange(offset, size) method. Parameter Type Nullable Optional Description offset
GPUSize64
✘ ✔ 缓冲区中以字节为单位的偏移量,以从中返回缓冲区内容。 size
GPUSize64
✘ ✔ 要返回的 ArrayBuffer
的字节大小。Returns:
ArrayBuffer
内容时间线 步骤:
1.如果size 缺失:
-
让 rangeSize 为最大值(0,this.
size
- offset)。
否则,让 rangeSize 为 size。
-
如果不满足以下任何条件,则抛出
OperationError
并停止。-
this.
[[mapping]]
不为null
. -
offset 是8的倍数。
-
rangeSize 是4的倍数。
-
offset ≥ this.
[[mapping]]
.range[0]. -
offset + rangeSize ≤ this.
[[mapping]]
.range[1]. -
[offset, offset + rangeSize) 不与 this.
[[mapping]]
.views 中的范围重合。
注:获取
GPUBuffer
的映射范围始终有效,即mappedAtCreation
,即使它是 无效的,因为 内容时间线 可能不知道它是无效的。 -
-
使 data 为 this.
[[mapping]]
.data. -
使 view 为 ! create an ArrayBuffer,大小为 rangeSize, 但是它的指针在偏移处(offset -
[[mapping]]
.range[0])可变地引用了 data 的内容。注:这里可能不会抛出
RangeError
,因为 data 已经在mapAsync()
或createBuffer()
期间分配。 -
设置 view.
[[ArrayBufferDetachKey]]
为 "WebGPUBufferMapping".注:如果尝试 DetachArrayBuffer,这会导致抛出
TypeError
,unmap()
除外。 -
Append view 至 this.
[[mapping]]
.views. -
返回 view.
注:如果
getMappedRange()
在没有检查地图状态的情况下成功,用户代理应考虑发出开发人员可见的警告,方法是等待mapAsync()
成功,查询"mapped"
的mapState
,或等待稍后的onSubmittedWorkDone()
调用成功。 -
unmap()
-
取消
GPUBuffer
的映射范围并使其内容再次可供 GPU 使用。Called on:GPUBuffer
this.Returns:
undefined
内容时间线 步骤:
-
如果 this.
[[pending_map]]
不为null
:-
以一个
AbortError
拒绝 this.[[pending_map]]
-
设置 this.
[[pending_map]]
为null
.
-
-
如果 this.
[[mapping]]
为null
:-
返回。
-
-
对每个 this.
[[mapping]]
.views 中的ArrayBuffer
ab-
执行 DetachArrayBuffer(ab, "WebGPUBufferMapping").
-
-
使 bufferUpdate 为
null
. -
如果 this.
[[mapping]]
.mode 包含WRITE
:-
设置 bufferUpdate 为 {
data
: this.[[mapping]]
.data,offset
: this.[[mapping]]
.range[0] }.
注:当缓冲区在没有
WRITE
模式的情况下映射,然后取消映射时,应用程序对映射范围ArrayBuffer
所做的任何本地修改都将被丢弃,并且不会影响以后映射的内容。 -
-
设置 this.
[[mapping]]
为null
. -
在 this.
[[device]]
的 Device timeline 上运行后续步骤。
设备时间线 步骤:-
如果this.
[[device]]
是无效的,返回。 -
如果 bufferUpdate 不为
null
:-
在 this.
[[device]]
.queue
的 队列时间线 上执行以下步骤:队列时间线 步骤:1.更新this的内容 在偏移 bufferUpdate.
offset
与数据 bufferUpdate.data
处。
-
-
将 this.
[[internals]]
.state 设置为 "available"。
-
6. 纹理与纹理视图
6.1. GPUTexture
问题:删除此定义:texture
一张纹理由一个或多个纹理子资源组成,每个纹理子资源由 mipmap level 唯一标识,并且仅对于 2d
纹理,array layer 和 [ =方面=]。
一个 texture subresource 是一个 subresource:每个都可以在一个 usage scope 中用于不同的 internal usages。
mipmap level 中的每个子资源在每个空间维度上大约是较低级别中相应资源大小的一半(参见 logical miplevel-specific texture extent)。 级别 0 中的子资源具有纹理本身的尺寸。
这些通常用于表示纹理的细节级别。 GPUSampler
和 WGSL 提供了在细节层次之间选择和插值的工具,明确地或自动地。
"2d"
纹理可以是array layer的数组。
层中的每个子资源与其他层中的相应资源大小相同。
对于非二维纹理,所有子资源的数组层索引均为 0。
每个子资源都有一个方面。
颜色纹理只有一个方面:color。 深度或模板格式 纹理可能有多个方面: depth 方面,stencil 方面,或两者兼而有之,并且可以以特殊方式使用,例如 {{GPURenderPassDescriptor/depthStencilAttachment} } 和 "depth"
绑定。
"3d"
纹理可能有多个 切片,每个都是纹理中特定 z
值处的二维图像。
切片不是单独的子资源。
[Exposed =(Window ,DedicatedWorker ),SecureContext ]interface GPUTexture {GPUTextureView createView (optional GPUTextureViewDescriptor descriptor = {});undefined destroy ();readonly attribute GPUIntegerCoordinate width ;readonly attribute GPUIntegerCoordinate height ;readonly attribute GPUIntegerCoordinate depthOrArrayLayers ;readonly attribute GPUIntegerCoordinate mipLevelCount ;readonly attribute GPUSize32 sampleCount ;readonly attribute GPUTextureDimension dimension ;readonly attribute GPUTextureFormat format ;readonly attribute GPUTextureUsageFlags usage ; };GPUTexture includes GPUObjectBase ;
GPUTexture
具有以下属性
width
, of type GPUIntegerCoordinate, readonly-
此
GPUTexture
的宽度。 height
, of type GPUIntegerCoordinate, readonly-
此
GPUTexture
的高度。 depthOrArrayLayers
, of type GPUIntegerCoordinate, readonly-
此
GPUTexture
的深度或层数。 mipLevelCount
, of type GPUIntegerCoordinate, readonly-
此
GPUTexture
的 mip 级别数。 sampleCount
, of type GPUSize32, readonly-
GPUTexture
的采样数。 dimension
, of type GPUTextureDimension, readonly-
此
GPUTexture
的每个子资源的纹素集的维度。 format
, of type GPUTextureFormat, readonly-
此
GPUTexture
的格式。 usage
, of type GPUTextureUsageFlags, readonly-
此
GPUTexture
的允许用法。
GPUTexture
有以下内部插槽:
[[size]]
, 类型为GPUExtent3D
-
纹理的大小(与
width
、height
和depthOrArrayLayers
属性相同)。 [[viewFormats]]
, 类型为 sequence<GPUTextureFormat
>-
在这个
GPUTexture
上创建视图时可以使用GPUTextureViewDescriptor
.format
的一组GPUTextureFormat
。 [[destroyed]]
, 类型为boolean
, 初始值为 false-
如果纹理被销毁,它就不能再用于任何操作,并且它的底层内存可以被释放。
Arguments:
-
GPUExtent3D
baseSize -
GPUSize32
mipLevel
Returns: GPUExtent3DDict
-
使 extent 为一个新的
GPUExtent3DDict
对象。 -
设置 extent.
depthOrArrayLayers
为 1. -
返回 extent.
texture 的 logical miplevel-specific texture extent 是 texture 在特定 miplevel 的纹素大小。 它是通过以下过程计算的:
Arguments:
-
GPUTextureDescriptor
descriptor -
GPUSize32
mipLevel
Returns: GPUExtent3DDict
-
使 extent 为一个新的
GPUExtent3DDict
对象. -
如果 descriptor.
dimension
为:"1d"
-
-
设置 extent.
height
为 1. -
设置 extent.
depthOrArrayLayers
为 1.
"2d"
-
-
设置 extent.
height
为 max(1, descriptor.size
.height ≫ mipLevel). -
设置 extent.
depthOrArrayLayers
为 descriptor.size
.depthOrArrayLayers.
"3d"
-
-
设置 extent.
height
为 max(1, descriptor.size
.height ≫ mipLevel). -
设置 extent.
depthOrArrayLayers
为 max(1, descriptor.size
.depthOrArrayLayers ≫ mipLevel).
-
返回 extent.
特定miplevel物理纹理尺寸是指在特定mip级别的纹理大小(以像素为单位),包括可能的额外填充以形成纹理中的完整 [ =像素块= ]。 它通过以下步骤计算得出:
Arguments:
-
GPUTextureDescriptor
descriptor -
GPUSize32
mipLevel
Returns: GPUExtent3DDict
-
使 extent 为一个新的
GPUExtent3DDict
对象。 -
使 logicalExtent 为 logical miplevel-specific texture extent(descriptor, mipLevel).
-
如果 descriptor.
dimension
为:"1d"
-
-
设置 extent.
width
为 logicalExtent.width rounded up to the nearest multiple of descriptor’s texel block width. -
设置 extent.
height
为 1. -
设置 extent.
depthOrArrayLayers
为 1.
-
"2d"
-
-
设置 extent.
width
为 logicalExtent.width rounded up to the nearest multiple of descriptor’s texel block width. -
设置 extent.
height
为 logicalExtent.height rounded up to the nearest multiple of descriptor’s texel block height. -
设置 extent.
depthOrArrayLayers
为 logicalExtent.depthOrArrayLayers.
-
"3d"
-
-
设置 extent.
width
为 logicalExtent.width rounded up to the nearest multiple of descriptor’s texel block width. -
设置 extent.
height
为 logicalExtent.height rounded up to the nearest multiple of descriptor’s texel block height. -
设置 extent.
depthOrArrayLayers
为 logicalExtent.depthOrArrayLayers.
-
-
返回 extent.
6.1.1. GPUTextureDescriptor
dictionary GPUTextureDescriptor :GPUObjectDescriptorBase {required GPUExtent3D size ;GPUIntegerCoordinate mipLevelCount = 1;GPUSize32 sampleCount = 1;GPUTextureDimension dimension = "2d";required GPUTextureFormat format ;required GPUTextureUsageFlags usage ;sequence <GPUTextureFormat >viewFormats = []; };
GPUTextureDescriptor
具有以下成员:
size
, of type GPUExtent3D-
纹理的宽度、高度和深度或层数。
mipLevelCount
, of type GPUIntegerCoordinate, defaulting to1
-
纹理将包含的 mip 级别数。
sampleCount
, of type GPUSize32, defaulting to1
-
纹理的样本数量。
sampleCount
>1
表示多重采样纹理。 dimension
, of type GPUTextureDimension, defaulting to"2d"
-
纹理是一维的、二维层的数组还是三维的。
format
, of type GPUTextureFormat-
纹理的格式。
usage
, of type GPUTextureUsageFlags-
纹理的允许用途。
viewFormats
, of type sequence<GPUTextureFormat>, defaulting to[]
-
指定在调用
createView()
时允许的format
值(除实际的format
之外)。注: 向该列表添加格式可能会对性能产生显著影响,因此最好避免不必要地添加格式。实际性能影响高度依赖于目标系统;开发者必须测试各种系统,以了解其对特定应用的影响。 例如,在某些系统上,任何具有
format
或viewFormats
条目(包括"rgba8unorm-srgb"
)的纹理性能都会比一个没有该项的"rgba8unorm"
纹理低一些。 在其他系统上,针对其他格式和格式组合也存在类似的注意事项。此列表中的格式必须与纹理格式纹理视图格式兼容。
如果两个GPUTextureFormat
s format 和 viewFormat 是纹理视图格式兼容的:-
format 等于 viewFormat, 或
-
format 和 viewFormat 区别仅在于它们是否为
srgb
格式(具有-srgb
后缀)。
问题(gpuweb/gpuweb#168): 定义更大的兼容类。
-
enum {
GPUTextureDimension "1d" ,"2d" ,"3d" };
"1d"
-
指定具有一维宽度的纹理。
"2d"
-
指定具有宽度和高度并且可能具有层的纹理。 只有
"2d"
纹理可以有 mipmaps、多重采样、使用压缩或深度/模板格式,并用作渲染附件。 "3d"
-
指定具有宽度、高度和深度的纹理。
6.1.2. 纹理使用
typedef [EnforceRange ]unsigned long ; [
GPUTextureUsageFlags Exposed =(Window ,DedicatedWorker ),SecureContext ]namespace {
GPUTextureUsage const GPUFlagsConstant COPY_SRC = 0x01;const GPUFlagsConstant COPY_DST = 0x02;const GPUFlagsConstant TEXTURE_BINDING = 0x04;const GPUFlagsConstant STORAGE_BINDING = 0x08;const GPUFlagsConstant RENDER_ATTACHMENT = 0x10; };
GPUTextureUsage
标志决定了 GPUTexture
在创建后如何使用:
COPY_SRC
-
纹理可以用作复制操作的来源。 (示例:作为
copyTextureToTexture()
或copyTextureToBuffer()
调用的source
参数。) COPY_DST
-
纹理可用作复制或写入操作的目标。 (示例:作为
copyTextureToTexture()
或copyBufferToTexture()
调用的“目标”参数,或作为writeTexture()
调用的目标。) TEXTURE_BINDING
-
纹理可以绑定用作着色器中的采样纹理(示例:作为绑定组
GPUTextureBindingLayout
的条目。) STORAGE_BINDING
-
纹理可以绑定用作着色器中的存储纹理(示例:作为
GPUStorageTextureBindingLayout
的绑定组条目。) RENDER_ATTACHMENT
-
纹理可以用作渲染过程中的颜色或深度/模板附件。 (示例:作为
GPURenderPassColorAttachment
.view
或GPURenderPassDepthStencilAttachment
.view
。)
Arguments:
6.1.3. 纹理创建
createTexture(descriptor)
-
创建一个
GPUTexture
.Called on:GPUDevice
this.Arguments:
Arguments for the GPUDevice.createTexture(descriptor) method. Parameter Type Nullable Optional Description descriptor
GPUTextureDescriptor
✘ ✘ 要创建的 GPUTexture
的描述。Returns:
GPUTexture
内容时间线 步骤:
-
? validate GPUExtent3D shape(descriptor.
size
). -
? 使用 this.
[[device]]
验证descriptor.format
所需的纹理格式特性。 -
验证descriptor.
viewFormats
中每个元素所需的 ? 纹理格式所需特性 与 this.[[device]]
。 -
使 t 为一个新的
GPUTexture
对象。 -
设置 t.
depthOrArrayLayers
为 descriptor.size
.depthOrArrayLayers. -
设置 t.
mipLevelCount
为 descriptor.mipLevelCount
. -
设置 t.
sampleCount
为 descriptor.sampleCount
. -
在 this 的 设备时间线 上发起 initialization steps。
-
返回 t。
设备时间线 initialization steps:-
如果以下任何条件不满足,产生验证错误,使得 t 为 无效,并停止。
-
验证 GPUTextureDescriptor (this, descriptor) 返回
true
.
-
-
设置 t.
[[viewFormats]]
为 descriptor.viewFormats
.
-
GPUDevice
this, GPUTextureDescriptor
descriptor):
如果满足以下所有要求,则返回“true”,否则返回“false”:
-
descriptor.
usage
必须不为 0. -
descriptor.
size
.width, descriptor.size
.height, 和 descriptor.size
.depthOrArrayLayers 必须 > 零。 -
descriptor.
mipLevelCount
必须 > zero。 -
descriptor.
sampleCount
必须为 1 或 4。 -
如果 descriptor.
dimension
为:"1d"
-
-
descriptor.
size
.width 必须 ≤ this.limits
.maxTextureDimension1D
. -
descriptor.
size
.depthOrArrayLayers 必须为 1. -
descriptor.
sampleCount
必须为 1. -
descriptor.
format
必须不为 compressed format 或 depth-or-stencil format.
-
"2d"
-
-
descriptor.
size
.width 必须 ≤ this.limits
.maxTextureDimension2D
. -
descriptor.
size
.height 必须 ≤ this.limits
.maxTextureDimension2D
. -
descriptor.
size
.depthOrArrayLayers 必须 ≤ this.limits
.maxTextureArrayLayers
.
-
"3d"
-
-
descriptor.
size
.width 必须 ≤ this.limits
.maxTextureDimension3D
。 -
descriptor.
size
.height 必须 ≤ this.limits
.maxTextureDimension3D
。 -
descriptor.
size
.depthOrArrayLayers 必须 ≤ this.limits
.maxTextureDimension3D
。 -
descriptor.
sampleCount
必须 1。 -
descriptor.
format
必须不为 compressed format or depth-or-stencil format。
-
-
descriptor.
size
.width 必须为 texel block width 的倍数。 -
descriptor.
size
.height 必须为 texel block height 的倍数。 -
如果 descriptor.
sampleCount
> 1:-
descriptor.
mipLevelCount
必须为 1。 -
descriptor.
size
.depthOrArrayLayers 必须为 1。 -
descriptor.
usage
不能包含STORAGE_BINDING
位。 -
descriptor.
usage
必须包含RENDER_ATTACHMENT
位。 -
descriptor.
format
必须根据 § 26.1 纹理格式功能 支持多重采样。
-
-
descriptor.
mipLevelCount
必须 ≤ maximum mipLevel count(descriptor.dimension
, descriptor.size
)。 -
如果 descriptor.
usage
包含RENDER_ATTACHMENT
位:-
descriptor.
format
必须为 renderable format.
-
-
如果 descriptor.
usage
包含STORAGE_BINDING
位:-
必须在 § 26.1.1 纯彩色格式 表中列出具有
STORAGE_BINDING
能力。
-
-
对每个 descriptor.
viewFormats
中的 viewFormat: descriptor.format
和 viewFormat 必须为 texture view format compatible.
const texture= gpuDevice. createTexture({ size: { width: 16 , height: 16 }, format: 'rgba8unorm' , usage: GPUTextureUsage. TEXTURE_BINDING, });
6.1.4. 纹理销毁
一个不再需要GPUTexture
的应用可以在垃圾收集之前选择通过调用destroy()
来丢失对其的访问。
注:这允许用户代理在使用它完成所有先前提交的操作后回收与GPUTexture
关联的GPU内存。
destroy()
-
销毁
GPUTexture
.
6.2. GPUTextureView
一个 GPUTextureView
是对某个 GPUTexture
定义的一部分 纹理子资源 的视图。
[Exposed =(Window ,DedicatedWorker ),SecureContext ]interface GPUTextureView { };GPUTextureView includes GPUObjectBase ;
GPUTextureView
局有以下内部插槽:
[[texture]]
-
该视图所对应的
GPUTexture
。 [[descriptor]]
-
GPUTextureViewDescriptor
描述这个纹理视图。GPUTextureViewDescriptor
的所有可选字段均已定义。 [[renderExtent]]
-
对于可渲染视图,这是用于渲染的有效
GPUExtent3DDict
。注:这个范围取决于
baseMipLevel
。
[[descriptor]]
desc,是 view.[[texture]]
的子资源的子集,其中的每个子资源 s 都满足以下条件:
-
s 的 mipmap level ≥ desc.
baseMipLevel
且 < desc.baseMipLevel
+ desc.mipLevelCount
. -
s 的 array layer ≥ desc.
baseArrayLayer
and < desc.baseArrayLayer
+ desc.arrayLayerCount
. -
s 的 aspect 在 desc.
aspect
的 set of aspects 中。
两个 GPUTextureView
对象之间的纹理视图别名仅当它们的子资源集合相交时才成立。
6.2.1. 纹理视图创建
dictionary :
GPUTextureViewDescriptor GPUObjectDescriptorBase {GPUTextureFormat format ;GPUTextureViewDimension dimension ;GPUTextureAspect aspect = "all";GPUIntegerCoordinate baseMipLevel = 0;GPUIntegerCoordinate mipLevelCount ;GPUIntegerCoordinate baseArrayLayer = 0;GPUIntegerCoordinate arrayLayerCount ; };
GPUTextureViewDescriptor
具有以下成员:
format
, of type GPUTextureFormat-
纹理视图的格式。必须是纹理的
format
或在其创建过程中指定的viewFormats
之一。 dimension
, of type GPUTextureViewDimension-
纹理视图的维度。
aspect
, of type GPUTextureAspect, defaulting to"all"
-
纹理视图可以访问纹理的哪些
aspect(s)
。 baseMipLevel
, of type GPUIntegerCoordinate, defaulting to0
-
纹理视图可访问的第一个(最详细的)mipmap 级别。
mipLevelCount
, of type GPUIntegerCoordinate-
纹理视图可以访问多少个 mipmap 级别,以
baseMipLevel
开头。 baseArrayLayer
, of type GPUIntegerCoordinate, defaulting to0
-
纹理视图可访问的第一个数组层的索引。
arrayLayerCount
, of type GPUIntegerCoordinate-
纹理视图可以访问多少个数组层,以
baseArrayLayer
开头。
enum {
GPUTextureViewDimension "1d" ,"2d" ,"2d-array" ,"cube" ,"cube-array" ,"3d" };
"1d"
-
纹理被视为一维图像。
对应的WGSL类型:
-
texture_1d
-
texture_storage_1d
-
"2d"
-
纹理被视为单个二维图像。
对应的WGSL类型:
-
texture_2d
-
texture_storage_2d
-
texture_multisampled_2d
-
texture_depth_2d
-
texture_depth_multisampled_2d
-
"2d-array"
-
纹理视图被视为二维图像的数组。
对应的WGSL类型:
-
texture_2d_array
-
texture_storage_2d_array
-
texture_depth_2d_array
-
"cube"
-
纹理被视为立方体贴图。 该视图有 6 个数组层,对应于立方体的 [+X, -X, +Y, -Y, +Z, -Z] 面。 采样是在立方体贴图的各个面上无缝完成的。
对应的WGSL类型:
-
texture_cube
-
texture_depth_cube
-
"cube-array"
-
纹理被视为 n 个立方体贴图的打包数组, 每个都有 6 个数组层,对应于立方体的 [+X, -X, +Y, -Y, +Z, -Z] 面。 采样是在立方体贴图的各个面上无缝完成的。
对应的WGSL类型:
-
texture_cube_array
-
texture_depth_cube_array
-
"3d"
-
纹理被视为 3 维图像。
对应的WGSL类型:
-
texture_3d
-
texture_storage_3d
-
每个 GPUTextureAspect
值对应一组 aspects。 方面集 是为下面的每个值定义的。
enum GPUTextureAspect {"all" ,"stencil-only" ,"depth-only" };
"all"
-
所有纹理格式的可用方面都将对纹理视图可访问。对于颜色格式,颜色方面将是可访问的。对于 combined depth-stencil format,深度和模板方面都将是可访问的。只有一个方面的 Depth-or-stencil format 将只使该方面可访问。
set of aspects 是 [color, depth, stencil]。
"stencil-only"
-
仅深度或模板格式的模板方面可以访问纹理视图。
"depth-only"
-
仅深度方面的 depth-or-stencil format 格式将可以在纹理视图中访问。
createView(descriptor)
-
创建一个
GPUTextureView
.注: 默认情况下,createView()
将创建一个可以表示整个纹理的维度视图。例如,在一个具有多个图层的“2d”
纹理上调用createView()
而不指定dimension
会创建一个“2d-array”
GPUTextureView
,即使指定了arrayLayerCount
为 1。对于在开发时图层计数未知的源创建的纹理,建议向
createView()
提供一个明确的dimension
,以确保着色器兼容性。Called on:GPUTexture
this.Arguments:
Arguments for the GPUTexture.createView(descriptor) method. Parameter Type Nullable Optional Description descriptor
GPUTextureViewDescriptor
✘ ✔ Description of the GPUTextureView
to create.Returns: view, 类型为
GPUTextureView
.内容时间线 步骤:
-
验证 descriptor.
format
与this.[[device]]
所需的纹理格式功能。 -
使 view 为一个新的
GPUTextureView
对象。 -
在 this 的 设备时间线 上发起 initialization steps。
-
返回 view.
设备时间线 initialization steps:-
将 descriptor 设置为用 descriptor 对 this 进行解析 GPUTextureViewDescriptor 默认值的结果。
-
如果以下任何条件不满足,生成验证错误,使 view [无效],并停止。
-
this 为 有效 的。
-
-
descriptor.
format
必须等于 this.format
或 this.[[viewFormats]]
中的某个格式。
否则:
-
descriptor.
format
必须等于 解析 GPUTextureAspect( this.format
, descriptor.aspect
) 的结果。
-
-
descriptor.
mipLevelCount
必须 > 0。 -
descriptor.
baseMipLevel
+ descriptor.mipLevelCount
必须 ≤ this.mipLevelCount
。 -
descriptor.
arrayLayerCount
必须 > 0。 -
descriptor.
baseArrayLayer
+ descriptor.arrayLayerCount
必须 ≤ this 的 array layer count。 -
如果 this.
sampleCount
> 1, descriptor.dimension
必须"2d"
。 -
如果 descriptor.
dimension
为:"1d"
-
-
descriptor.
arrayLayerCount
必须为1
。
"2d"
-
-
descriptor.
arrayLayerCount
必须为1
。
"2d-array"
"cube"
-
-
descriptor.
arrayLayerCount
必须为6
。
"cube-array"
-
-
descriptor.
arrayLayerCount
必须为6
的倍数。
"3d"
-
-
descriptor.
arrayLayerCount
必须为1
。
-
-
使 view 为一个新的
GPUTextureView
对象。 -
设置 view.
[[texture]]
为 this。 -
设置 view.
[[descriptor]]
为 descriptor。 -
如果 this.
usage
包含RENDER_ATTACHMENT
:-
使 renderExtent 为 compute render extent(this.
[[size]]
, descriptor.baseMipLevel
)。 -
设置 view.
[[renderExtent]]
为 renderExtent。
-
-
GPUTextureView
中的texture 解析 GPUTextureViewDescriptor
默认值时,执行以下步骤:
-
使 resolved 为 descriptor 的拷贝。
-
如果 resolved.
mipLevelCount
没有 provided: 将 resolved.mipLevelCount
设置为 texture.mipLevelCount
− resolved.baseMipLevel
。 -
如果 resolved.
arrayLayerCount
没有 provided 且 resolved.dimension
是:"1d"
,"2d"
, or"3d"
-
设置 resolved.
arrayLayerCount
为1
。 "cube"
-
设置 resolved.
arrayLayerCount
为6
。 "2d-array"
or"cube-array"
-
设置 resolved.
arrayLayerCount
为 texture 的 array layer count − resolved.baseArrayLayer
。
-
Return resolved.
GPUTexture
texture的数组层级计数,执行以下步骤:
-
如果 texture.
dimension
为:"1d"
or"3d"
-
返回
1
. "2d"
-
返回 texture.
depthOrArrayLayers
.
6.3. 纹理格式
格式的名称指定组件的顺序、每个组件的位数和组件的数据类型。
-
r
,g
,b
,a
= red, green, blue, alpha -
unorm
= unsigned normalized -
snorm
= signed normalized -
uint
= unsigned int -
sint
= signed int -
float
= floating point
如果格式具有-srgb后缀,则在着色器中读取和写入颜色值时将应用从伽玛到线性以及相反的sRGB转换。压缩纹理格式由features提供。它们的命名应遵循这里的约定,以纹理名作为前缀。例如etc2-rgba8unorm。
texel block是基于像素的GPUTextureFormat
中纹理的单个可寻址元素,以及基于块的压缩GPUTextureFormat
中的单个压缩块。
texel block width和texel block height指定一个texel block的尺寸。
-
对于基于像素的
GPUTextureFormat
,texel block width和texel block height始终为1。 -
对于基于块的压缩
GPUTextureFormat
,texel block width是每一行的纹素数量,texel block height是每个texel block中纹素行的数量。每种纹理格式的详细列表请参见#texture-format-caps。
一个GPUTextureFormat
的aspect的texel block copy footprint是一个纹理块在image copy过程中占用的字节数,如果适用的话。
注: GPUTextureFormat
的texel block memory cost是存储一个texel block所需的字节数。并非所有格式都完全定义了此值。 此值具有信息性质,非规范性质。
enum { // 8-bit formats
GPUTextureFormat ,
"r8unorm" ,
"r8snorm" ,
"r8uint" , // 16-bit formats
"r8sint" ,
"r16uint" ,
"r16sint" ,
"r16float" ,
"rg8unorm" ,
"rg8snorm" ,
"rg8uint" , // 32-bit formats
"rg8sint" ,
"r32uint" ,
"r32sint" ,
"r32float" ,
"rg16uint" ,
"rg16sint" ,
"rg16float" ,
"rgba8unorm" ,
"rgba8unorm-srgb" ,
"rgba8snorm" ,
"rgba8uint" ,
"rgba8sint" ,
"bgra8unorm" , // Packed 32-bit formats
"bgra8unorm-srgb" ,
"rgb9e5ufloat" ,
"rgb10a2unorm" , // 64-bit formats
"rg11b10ufloat" ,
"rg32uint" ,
"rg32sint" ,
"rg32float" ,
"rgba16uint" ,
"rgba16sint" , // 128-bit formats
"rgba16float" ,
"rgba32uint" ,
"rgba32sint" , // Depth/stencil formats
"rgba32float" ,
"stencil8" ,
"depth16unorm" ,
"depth24plus" ,
"depth24plus-stencil8" , // "depth32float-stencil8" feature
"depth32float" , // BC compressed formats usable if "texture-compression-bc" is both // supported by the device/user agent and enabled in requestDevice.
"depth32float-stencil8" ,
"bc1-rgba-unorm" ,
"bc1-rgba-unorm-srgb" ,
"bc2-rgba-unorm" ,
"bc2-rgba-unorm-srgb" ,
"bc3-rgba-unorm" ,
"bc3-rgba-unorm-srgb" ,
"bc4-r-unorm" ,
"bc4-r-snorm" ,
"bc5-rg-unorm" ,
"bc5-rg-snorm" ,
"bc6h-rgb-ufloat" ,
"bc6h-rgb-float" ,
"bc7-rgba-unorm" , // ETC2 compressed formats usable if "texture-compression-etc2" is both // supported by the device/user agent and enabled in requestDevice.
"bc7-rgba-unorm-srgb" ,
"etc2-rgb8unorm" ,
"etc2-rgb8unorm-srgb" ,
"etc2-rgb8a1unorm" ,
"etc2-rgb8a1unorm-srgb" ,
"etc2-rgba8unorm" ,
"etc2-rgba8unorm-srgb" ,
"eac-r11unorm" ,
"eac-r11snorm" ,
"eac-rg11unorm" , // ASTC compressed formats usable if "texture-compression-astc" is both // supported by the device/user agent and enabled in requestDevice.
"eac-rg11snorm" ,
"astc-4x4-unorm" ,
"astc-4x4-unorm-srgb" ,
"astc-5x4-unorm" ,
"astc-5x4-unorm-srgb" ,
"astc-5x5-unorm" ,
"astc-5x5-unorm-srgb" ,
"astc-6x5-unorm" ,
"astc-6x5-unorm-srgb" ,
"astc-6x6-unorm" ,
"astc-6x6-unorm-srgb" ,
"astc-8x5-unorm" ,
"astc-8x5-unorm-srgb" ,
"astc-8x6-unorm" ,
"astc-8x6-unorm-srgb" ,
"astc-8x8-unorm" ,
"astc-8x8-unorm-srgb" ,
"astc-10x5-unorm" ,
"astc-10x5-unorm-srgb" ,
"astc-10x6-unorm" ,
"astc-10x6-unorm-srgb" ,
"astc-10x8-unorm" ,
"astc-10x8-unorm-srgb" ,
"astc-10x10-unorm" ,
"astc-10x10-unorm-srgb" ,
"astc-12x10-unorm" ,
"astc-12x10-unorm-srgb" ,
"astc-12x12-unorm" };
"astc-12x12-unorm-srgb"
深度组件 “depth24plus”
和 “depth24plus-stencil8”
格式可以实现为 24 位深度 值或 “depth32float”
值。
问题(gpuweb/gpuweb#1887):在GPUAdapter(?)上添加一些内容,估计每个像素的字节数为 “stencil8”
, “depth24plus-stencil8”
,以及 “depth32float-stencil8”
。
stencil8
这种格式可以分为两种:
实际的"stencil8",或者"depth24stencil8",其中深度方面为隐藏且无法访问。
对于 24-bit depth,1 ULP 的值为常数 1 /(224 - 1)。 对于 depth32float,1 ULP 的值为不大于 1 /(224)的可变值。
格式是可渲染的,如果它是 color renderable format ,或depth-or-stencil format。
如果格式在§ 26.1.1 纯彩色格式中列出并具有RENDER_ATTACHMENT
功能,则它是
颜色可渲染格式。任何其他格式都不是颜色可渲染格式。
所有depth-or-stencil formats都是可渲染的。
具有可渲染格式的格式也是可混合的 如果它可以与渲染管线混合一起使用。 请参阅§ 26.1 纹理格式功能。
格式是可过滤的,如果它支持 GPUTextureSampleType
“float”
(而不仅仅是“unfilterable-float”
);
也就是说,它可以与“filtering”
的GPUSampler
一起使用。
请参阅§ 26.1 纹理格式功能。
Arguments:
-
GPUTextureFormat
format -
GPUTextureAspect
aspect
Returns: GPUTextureFormat
或 null
-
如果 aspect 为:
"all"
-
返回 format。
"depth-only"
"stencil-only"
-
如果 format 为 depth-stencil-format: 返回 format 的 aspect-specific format 根据 § 26.1.2 深度模具格式 或
null
如果方面不存在于 format 中。
-
返回
null
。
使用某些纹理格式需要在 GPUDevice
上启用功能。由于新格式可能会被添加到规范中,因此实现可能不知道这些枚举值。为了在实现之间规范化行为,如果未在设备上启用关联的功能,则尝试使用需要功能的格式将抛出异常。这使得行为与实现不知道格式时相同。
请参阅§ 26.1 纹理格式功能以获取有关哪些GPUTextureFormat
需要功能的信息。
GPUTextureFormat
format 使用逻辑 device device 通过运行以下步骤:
1.如果格式 需要一个特性,而 device.[[features]]
不需要 contain 特点:
1.抛出一个TypeError
。
6.4. GPUExternalTexture
一个 GPUExternalTexture
是一个可采样的二维纹理,包装了一个外部视频对象。 GPUExternalTexture
对象的内容是一个快照,可能不会改变,无论是从 WebGPU 内部(它只是可采样的)还是从 WebGPU 外部(比如,由于视频帧的推进)。
它们通过使用 externalTexture
绑定组布局条目成员绑定到绑定组布局中。
外部纹理使用了多个绑定槽:请参阅 超过绑定槽限制。
外部纹理的底层表示不可观察(除采样行为外),但通常可能包括
-
最多三个2D数据平面(例如RGBA,Y+UV,Y+U+V)。
-
在从这些平面读取之前,用于转换坐标的元数据(裁剪和旋转)。
-
将值转换为指定的输出色彩空间的元数据(矩阵,伽玛,3D LUT)。
所使用的配置在时间、系统、用户代理、媒体源之间,或在单个视频源的帧内可能不稳定。 为了考虑到许多可能的表示,对每个外部纹理,该绑定保守地使用以下内容:
-
三个采样纹理绑定(最多3个平面),
-
一个采样纹理绑定用于3D LUT,
-
一个采样器绑定用于采样3D LUT,以及
-
一个统一缓冲区绑定用于元数据。
[Exposed =(Window ,DedicatedWorker ),SecureContext ]interface GPUExternalTexture { };GPUExternalTexture includes GPUObjectBase ;
GPUExternalTexture
局有以下内部插槽:
[[expired]]
, 类型为boolean
-
指示对象是否已过期(不再可用)。 最初设置为
false
。注: 与类似的
\[[destroyed]]
槽位不同,这个值可以从true
更改回false
。 [[descriptor]]
, 类型为GPUExternalTextureDescriptor
-
创建纹理的描述符。
6.4.1. 引入外部纹理
从外部视频对象创建外部纹理,使用 importExternalTexture()
。
从 HTMLVideoElement
创建的外部纹理,在导入后的任务中会自动销毁,而不是像其他资源那样手动销毁或在垃圾回收时销毁。当外部纹理过期时,其 [[expired]]
插槽变为 true。
一旦 GPUExternalTexture
过期,必须再次调用 importExternalTexture()
。然而,用户代理可能会取消过期,并再次返回同一个 GPUExternalTexture
,而不是创建一个新的。除非应用程序的执行预定与视频的帧率相匹配(例如,使用 requestVideoFrameCallback()),否则这种情况通常会发生。如果再次返回相同的对象,它们将进行相等比较,而引用先前对象的 GPUBindGroup
、GPURenderBundle
等仍可使用。
dictionary :
GPUExternalTextureDescriptor GPUObjectDescriptorBase {required HTMLVideoElement ;
source PredefinedColorSpace = "srgb"; };
colorSpace
importExternalTexture(descriptor)
-
创建一个
GPUExternalTexture
包装提供的图像源。Called on:GPUDevice
this.Arguments:
Arguments for the GPUDevice.importExternalTexture(descriptor) method. Parameter Type Nullable Optional Description descriptor
GPUExternalTextureDescriptor
✘ ✘ 提供外部图像源对象(以及任何创建选项)。 Returns:
GPUExternalTexture
内容时间线 步骤:
-
使 source 为 descriptor.
source
. -
如果 source 的当前图像内容与最近一次使用相同的 descriptor 调用
importExternalTexture()
相同(忽略label
),并且用户代理选择重用它:-
令 previousResult 为先前返回的
GPUExternalTexture
。 -
将 previousResult.
[[expired]]
设置为 false,更新对底层资源的所有权。 -
令 result 为 previousResult。
注: 这允许应用程序检测到重复导入并避免重新创建依赖对象(如
GPUBindGroup
)。实现仍然需要能够处理单个帧由多个GPUExternalTexture
包装,因为即使对于相同的帧,导入元数据(如colorSpace
)也可能发生变化。否则:
-
如果 source is not origin-clean ,则抛出
SecurityError
并停止。 -
让 usability 是 ? =检测图像参数可用性=。
-
如果 usability 不是
good
:-
返回无效的
GPUExternalTexture
。
-
让 data 是将 source 的当前图像内容转换为 descriptor.
colorSpace
颜色空间并带有未预乘的透明度的结果。这可能导致值超出范围 [0, 1]。如果需要进行截取,可以在采样后进行。
注:这像是一个复制过程,但可以实现为对只读底层数据的引用,并在以后执行适当的元数据进行转换。
-
让 result 是一个包装 data 的新
GPUExternalTexture
对象。
-
-
使用设备 this 和以下步骤 queue an automatic expiry task:
-
将 result.
[[expired]]
设置为true
, 释放底层资源的所有权。
注: 应该在同一个任务中导入外部视频纹理,该任务会对纹理进行采样 (通常应该使用
requestVideoFrameCallback
或requestAnimationFrame()
根据应用程序进行调度)。 否则,纹理可能在 应用程序完成使用之前被这些步骤销毁。 -
-
返回 result。
-
const videoElement= document. createElement( 'video' ); // ... set up videoElement, wait for it to be ready... let externalTexture; function frame() { requestAnimationFrame( frame); // Re-import only if necessary if ( ! externalTexture|| externalTexture. expired) { externalTexture= gpuDevice. importExternalTexture({ source: videoElement}); } // ... render using externalTexture... } requestAnimationFrame( frame);
requestVideoFrameCallback
可用:
const videoElement= document. createElement( 'video' ); // ... set up videoElement... function frame() { videoElement. requestVideoFrameCallback( frame); // Always re-import, because we know the video frame has advanced const externalTexture= gpuDevice. importExternalTexture({ source: videoElement}); // ... render using externalTexture... } videoElement. requestVideoFrameCallback( frame);
6.4.2. 采样外部纹理
外部纹理在WGSL中用 texture_external
表示,并且可以使用 textureLoad
和 textureSampleBaseClampToEdge
进行读取。
提供给textureSampleBaseClampToEdge的 sampler
用于采样底层纹理。
结果在由colorSpace
设置的颜色空间中。
实现依赖的是,对于任何给定的外部纹理,采样器(和过滤器)是在转换为指定颜色空间的底层值之前还是之后应用的。
注: 如果内部表示是RGBA平面,那么采样行为就像在常规2D纹理上一样。 如果有多个底层平面(例如:Y+UV),采样器用于分别采样每个底层纹理,然后将YUV转换为指定颜色空间。
7. 采样器
7.1. GPUSampler
一个 GPUSampler
编码了变换和过滤信息,可以在着色器中使用这些信息来解释纹理资源数据。
GPUSampler
是通过 createSampler()
创建的。
[Exposed =(Window ,DedicatedWorker ),SecureContext ]interface GPUSampler { };GPUSampler includes GPUObjectBase ;
GPUSampler
具有以下内部插槽:
[[descriptor]]
, 类型为GPUSamplerDescriptor
, readonly[[isComparison]]
, 类型为boolean
-
GPUSampler
是否用作比较采样器。 [[isFiltering]]
, 类型为boolean
-
GPUSampler
是否对纹理的多个样本进行加权。
7.1.1. GPUSamplerDescriptor
GPUSamplerDescriptor
指定用于创建 GPUSampler
的选项。
dictionary :
GPUSamplerDescriptor GPUObjectDescriptorBase {GPUAddressMode addressModeU = "clamp-to-edge";GPUAddressMode addressModeV = "clamp-to-edge";GPUAddressMode addressModeW = "clamp-to-edge";GPUFilterMode magFilter = "nearest";GPUFilterMode minFilter = "nearest";GPUMipmapFilterMode mipmapFilter = "nearest";float lodMinClamp = 0;float lodMaxClamp = 32;GPUCompareFunction compare ; [Clamp ]unsigned short maxAnisotropy = 1; };
addressModeU
, of type GPUAddressMode, defaulting to"clamp-to-edge"
addressModeV
, of type GPUAddressMode, defaulting to"clamp-to-edge"
addressModeW
, of type GPUAddressMode, defaulting to"clamp-to-edge"
-
分别为纹理宽度、高度和深度坐标指定
address modes
。 magFilter
, of type GPUFilterMode, defaulting to"nearest"
-
指定样本足迹小于或等于一个纹素时的采样行为。
minFilter
, of type GPUFilterMode, defaulting to"nearest"
-
指定样本足迹大于一个纹素时的采样行为。
mipmapFilter
, of type GPUMipmapFilterMode, defaulting to"nearest"
-
指定在 mipmap 级别之间进行采样的行为。
lodMinClamp
, of type float, defaulting to0
lodMaxClamp
, of type float, defaulting to32
-
分别指定在对纹理进行采样时在内部使用的最小和最大细节级别。
compare
, of type GPUCompareFunction-
提供时,采样器将是具有指定
GPUCompareFunction
的比较采样器。注:比较采样器可能会使用过滤,但采样结果将是 依赖于实现并且可能不同于正常的过滤规则。
maxAnisotropy
, of type unsigned short, defaulting to1
-
指定采样器使用的最大各向异性值夹具。
注:大多数实现支持范围在1到16之间(包括1和16)的
maxAnisotropy
值。所使用的maxAnisotropy
值将被限制在平台支持的最大值内。
问题:解释如何计算LOD,以及在不同平台之间是否存在差异。
问题:解释各向异性采样是什么
GPUAddressMode
描述了当采样留痕超出采样纹理的边界时,采样器的行为。
问题:更详细地描述“采样留痕”。
enum {
GPUAddressMode "clamp-to-edge" ,"repeat" ,"mirror-repeat" };
"clamp-to-edge"
-
纹理坐标被限制在 0.0 和 1.0 之间,包括 0.0 和 1.0 在内。
"repeat"
-
纹理坐标环绕到纹理的另一侧。
"mirror-repeat"
-
纹理坐标环绕到纹理的另一侧,但当坐标的整数部分为奇数时纹理会翻转。
GPUFilterMode
和 GPUMipmapFilterMode
描述采样器在采样足迹与一个纹素不完全匹配时的行为。
enum {
GPUFilterMode "nearest" ,"linear" };enum {
GPUMipmapFilterMode ,
"nearest" };
"linear"
"nearest"
-
返回最接近纹理坐标的纹理元素的值。
"linear"
-
在每个维度中选择两个纹素并返回它们值之间的线性插值。
GPUCompareFunction
指定了比较采样器的行为。如果在着色器中使用了比较采样器,则输入值与采样纹理值进行比较,此比较测试的结果(0.0f表示通过,1.0f表示失败)会应用于过滤操作。
问题:描述过滤如何与比较采样相互作用。
enum {
GPUCompareFunction "never" ,"less" ,"equal" ,"less-equal" ,"greater" ,"not-equal" ,"greater-equal" ,"always" };
"never"
-
比较测试永远不会通过。
"less"
-
如果提供的值小于采样值,则通过比较测试。
"equal"
-
如果提供的值等于采样值,则通过比较测试。
"less-equal"
-
如果提供的值小于或等于采样值,则通过比较测试。
"greater"
-
如果提供的值大于采样值,则通过比较测试。
"not-equal"
-
如果提供的值不等于采样值,则通过比较测试。
"greater-equal"
-
如果提供的值大于或等于采样值,则通过比较测试。
"always"
-
比较测试总是通过。
7.1.2. 采样器创建
createSampler(descriptor)
-
创建一个
GPUSampler
。Called on:GPUDevice
this.Arguments:
Arguments for the GPUDevice.createSampler(descriptor) method. Parameter Type Nullable Optional Description descriptor
GPUSamplerDescriptor
✘ ✔ 要创建的 GPUSampler
的描述。Returns:
GPUSampler
内容时间线 步骤:
-
让 s 成为一个新的
GPUSampler
对象。 -
在 this 的 设备时间线 上执行 initialization steps。
-
返回 s。
Device timeline initialization steps:-
如果以下任何条件未满足,则生成一个验证错误,使 s 无效,并停止。
-
this 为 有效 的。
-
descriptor.
lodMinClamp
≥ 0. -
descriptor.
lodMaxClamp
≥ descriptor.lodMinClamp
. -
descriptor.
maxAnisotropy
≥ 1.注:大多数实现支持
maxAnisotropy
的值在1到16之间,包括1和16。所提供的maxAnisotropy
值将被限制在平台支持的最大值内。 -
如果 descriptor.
maxAnisotropy
> 1:-
descriptor.
magFilter
, descriptor.minFilter
, 和 descriptor.mipmapFilter
必须为"linear"
.
-
-
-
设置 s.
[[descriptor]]
为 descriptor. -
设置 s.
[[isComparison]]
为false
如果 a.[[descriptor]]
的compare
属性为“null”或未定义。 否则,将其设置为“true”。 -
设置 s.
[[isFiltering]]
为false
如果minFilter
、magFilter
或mipmapFilter
都没有"linear"
的值。 否则,将其设置为“true”。
-
GPUSampler
:
const sampler= gpuDevice. createSampler({ addressModeU: 'repeat' , addressModeV: 'repeat' , magFilter: 'linear' , minFilter: 'linear' , mipmapFilter: 'linear' , });
8. 资源绑定
8.1. GPUBindGroupLayout
一个 GPUBindGroupLayout
定义了在 GPUBindGroup
中绑定的一组资源与它们在着色器阶段中的可访问性之间的接口。
[Exposed =(Window ,DedicatedWorker ),SecureContext ]interface GPUBindGroupLayout { };GPUBindGroupLayout includes GPUObjectBase ;
GPUBindGroupLayout
具有以下内部插槽:
[[descriptor]]
, of typeGPUBindGroupLayoutDescriptor
8.1.1. 绑定组布局创建
GPUBindGroupLayout
通过 GPUDevice.createBindGroupLayout()
被创建。
dictionary :
GPUBindGroupLayoutDescriptor GPUObjectDescriptorBase {required sequence <GPUBindGroupLayoutEntry >; };
entries
GPUBindGroupLayoutEntry
描述了要包含在 GPUBindGroupLayout
中的单个着色器资源绑定。
dictionary {
GPUBindGroupLayoutEntry required GPUIndex32 binding ;required GPUShaderStageFlags visibility ;GPUBufferBindingLayout buffer ;GPUSamplerBindingLayout sampler ;GPUTextureBindingLayout texture ;GPUStorageTextureBindingLayout storageTexture ;GPUExternalTextureBindingLayout externalTexture ; };
GPUBindGroupLayoutEntry
字典有以下成员:
binding
, of type GPUIndex32-
一个唯一的标识符,用于在
GPUBindGroupLayout
中的资源绑定,对应于GPUBindGroupEntry.binding
和GPUShaderModule
中的 @binding 属性。 visibility
, of type GPUShaderStageFlags-
GPUShaderStage
成员的位集。 每个设置的位表示GPUBindGroupLayoutEntry
的资源 将从关联的着色器阶段访问。 buffer
, of type GPUBufferBindingLayout-
当 provided 时,表示此
GPUBindGroupLayoutEntry
的 绑定资源类型 是GPUBufferBinding
。 sampler
, of type GPUSamplerBindingLayout-
当 provided 时,表示此
GPUBindGroupLayoutEntry
的 绑定资源类型 是GPUSampler
。 texture
, of type GPUTextureBindingLayout-
当 provided 时,表示此
GPUBindGroupLayoutEntry
的 binding resource type 是GPUTextureView
。 storageTexture
, of type GPUStorageTextureBindingLayout-
当 provided 时,表示此
GPUBindGroupLayoutEntry
的 binding resource type 是GPUTextureView
。 externalTexture
, of type GPUExternalTextureBindingLayout-
当 provided 时,表示此
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
包含以下标志,这些标志描述了此 GPUBindGroupLayoutEntry
的相应 GPUBindGroupEntry
的着色器阶段将对哪些可见:
VERTEX
-
顶点着色器可以访问绑定组条目。
FRAGMENT
-
片段着色器可以访问绑定组条目。
COMPUTE
-
计算着色器可以访问绑定组条目。
The binding member of a GPUBindGroupLayoutEntry
is determined by which member of the GPUBindGroupLayoutEntry
is defined: buffer
, sampler
, texture
, storageTexture
, or externalTexture
.
Only one may be defined for any given GPUBindGroupLayoutEntry
.
Each member has an associated GPUBindingResource
type and each binding type has an associated internal usage, given by this table:
Binding member | Resource type | Binding type | Binding usage |
---|---|---|---|
buffer
| GPUBufferBinding
| "uniform"
| constant |
"storage"
| storage | ||
"read-only-storage"
| storage-read | ||
sampler
| GPUSampler
| "filtering"
| constant |
"non-filtering"
| |||
"comparison"
| |||
texture
| GPUTextureView
| "float"
| constant |
"unfilterable-float"
| |||
"depth"
| |||
"sint"
| |||
"uint"
| |||
storageTexture
| GPUTextureView
| "write-only"
| storage |
externalTexture
| GPUExternalTexture
| constant |
GPUBindGroupLayoutEntry
值的list entries 超过了绑定插槽限制。每个条目可以向多个限制使用多个插槽。
-
对于每个 条目 在 entries 中,如果:
- entry.
buffer
?.type
为"uniform"
且 entry.buffer
?.hasDynamicOffset
为true
-
考虑使用 1 个
maxDynamicUniformBuffersPerPipelineLayout
插槽。 - entry.
buffer
?.type
为"storage"
且 entry.buffer
?.hasDynamicOffset
为true
-
考虑使用 1 个
maxDynamicStorageBuffersPerPipelineLayout
插槽。
- entry.
-
对每个在 «
VERTEX
,FRAGMENT
,COMPUTE
» 中的着色器阶段 stage:-
对于每个 entries 在 entries entry.
visibility
包含 stage,如果:- entry.
buffer
?.type
为"uniform"
-
考虑 1
maxUniformBuffersPerShaderStage
插槽将被使用。 - entry.
buffer
?.type
为"storage"
或"read-only-storage"
-
考虑 1
maxStorageBuffersPerShaderStage
插槽将被使用。 - entry.
sampler
为 provided -
考虑 1
maxSamplersPerShaderStage
插槽将被使用。 - entry.
texture
为 provided -
考虑 1
maxSampledTexturesPerShaderStage
插槽将被使用。 - entry.
storageTexture
为 provided -
考虑 1
maxStorageTexturesPerShaderStage
插槽将被使用。 - entry.
externalTexture
为 provided -
考虑 4
maxSampledTexturesPerShaderStage
插槽, 1maxSamplersPerShaderStage
插槽, 及 1maxUniformBuffersPerShaderStage
插槽 将被使用。
- entry.
-
enum {
GPUBufferBindingType ,
"uniform" ,
"storage" };
"read-only-storage" dictionary {
GPUBufferBindingLayout GPUBufferBindingType type = "uniform";boolean hasDynamicOffset =false ;GPUSize64 minBindingSize = 0; };
GPUBufferBindingLayout
字典具有以下成员:
type
, of type GPUBufferBindingType, defaulting to"uniform"
-
指示绑定到此绑定的缓冲区所需的类型。
hasDynamicOffset
, of type boolean, defaulting tofalse
-
指示此绑定是否需要动态偏移量。
minBindingSize
, of type GPUSize64, defaulting to0
-
指示与此绑定点一起使用的缓冲区绑定的最小
size
。在
createBindGroup()
中,绑定始终根据此大小进行验证。如果这个值不是
0
,管线创建还将validates这个值≥变量的minimum buffer binding size。如果这个值是
0
,它将被管线创建忽略,而是通过绘制/调度命令validate,每个GPUBindGroup
中的绑定都满足变量的minimum buffer binding size。注: 理论上,对于早期验证指定的其他绑定相关字段(如
sampleType
和format
),也可以进行类似的执行时验证,而目前这些字段只能在管线创建时进行验证。 然而,这种执行时验证可能会产生较高的成本或不必要的复杂性,因此只对minBindingSize
提供这种验证,这些字段预计将产生最大的人体工程学影响。
enum {
GPUSamplerBindingType ,
"filtering" ,
"non-filtering" };
"comparison" dictionary {
GPUSamplerBindingLayout GPUSamplerBindingType type = "filtering"; };
GPUSamplerBindingLayout
字典具有以下成员:
type
, of type GPUSamplerBindingType, defaulting to"filtering"
-
指示绑定到此绑定的采样器的必需类型。
enum {
GPUTextureSampleType ,
"float" ,
"unfilterable-float" ,
"depth" ,
"sint" };
"uint" dictionary {
GPUTextureBindingLayout GPUTextureSampleType sampleType = "float";GPUTextureViewDimension viewDimension = "2d";boolean multisampled =false ; };
GPUTextureBindingLayout
字典具有以下成员:
sampleType
, of type GPUTextureSampleType, defaulting to"float"
-
指示绑定到此绑定的纹理视图所需的类型。
viewDimension
, of type GPUTextureViewDimension, defaulting to"2d"
-
指示绑定到此绑定的纹理视图所需的
dimension
。 multisampled
, of type boolean, defaulting tofalse
-
指示绑定到此绑定的纹理视图是否必须进行多重采样。
enum {
GPUStorageTextureAccess };
"write-only" dictionary {
GPUStorageTextureBindingLayout GPUStorageTextureAccess access = "write-only";required GPUTextureFormat format ;GPUTextureViewDimension viewDimension = "2d"; };
GPUStorageTextureBindingLayout
字典具有以下成员:
access
, of type GPUStorageTextureAccess, defaulting to"write-only"
-
此绑定的访问模式,指示可读性和可写性。
注: 目前只有一种访问模式
"write-only"
,未来会扩展。 format
, of type GPUTextureFormat-
绑定到此绑定的纹理视图所需的
format
。 viewDimension
, of type GPUTextureViewDimension, defaulting to"2d"
-
指示绑定到此绑定的纹理视图所需的
dimension
。
dictionary { };
GPUExternalTextureBindingLayout
A GPUBindGroupLayout
对象具有以下内部插槽:
[[entryMap]]
, 类型为 ordered map<GPUSize32
,GPUBindGroupLayoutEntry
>-
指向这个
GPUBindGroupLayout
描述的GPUBindGroupLayoutEntry
的绑定索引映射。 [[dynamicOffsetCount]]
, 类型为GPUSize32
-
此
GPUBindGroupLayout
中具有动态偏移量的缓冲区绑定数。 [[exclusivePipeline]]
, 类型为GPUPipelineBase
?, 初始值为null
-
创建此
GPUBindGroupLayout
的管线(如果它是作为 默认管线布局的一部分创建的)。如果不是null
,则使用此GPUBindGroupLayout
创建的GPUBindGroup
只能与指定的GPUPipelineBase
一起使用。
createBindGroupLayout(descriptor)
-
创建一个
GPUBindGroupLayout
.Called on:GPUDevice
this.Arguments:
Arguments for the GPUDevice.createBindGroupLayout(descriptor) method. Parameter Type Nullable Optional Description descriptor
GPUBindGroupLayoutDescriptor
✘ ✘ 要创建的 GPUBindGroupLayout
的描述。Returns:
GPUBindGroupLayout
Content timeline steps:
-
对于每个
GPUBindGroupLayoutEntry
在 descriptor 中的 entry.entries
:-
如果 entry.
storageTexture
为 provided:-
验证所需特性的纹理格式对于 entry.
storageTexture
.format
与 this.[[device]]
。
-
-
-
让 layout 是一个新的
GPUBindGroupLayout
对象。 -
在 this 的 设备时间线 上发起 initialization steps。
-
返回 layout。
设备时间线 initialization steps:-
如果以下任何条件未满足,生成验证错误,并使 layout 无效,然后停止。
-
this 为 有效 的。
-
使 limits 为 this.
[[device]]
.[[limits]]
. -
descriptor 中每个条目的
binding
是唯一的。 -
descriptor 中每个条目的
binding
必须是 limits.maxBindingsPerBindGroup
。 -
descriptor.
entries
must not exceed the binding slot limits of limits。 -
对于每个
GPUBindGroupLayoutEntry
条目 在 descriptor.entries
中:-
确定是 entry.
buffer
, entry.sampler
, entry.texture
, 和 entry.storageTexture
之一 provided。 -
entry.
visibility
仅包含GPUShaderStage
中定义的位。 -
如果 entry.
visibility
包含VERTEX
:-
entry.
storageTexture
?.access
不能是"write-only"
。
-
如果 entry.
texture
?.multisampled
为true
:-
entry.
texture
.viewDimension
为"2d"
. -
entry.
texture
.sampleType
不为"float"
.
-
-
如果 entry.
storageTexture
为 provided:-
entry.
storageTexture
.viewDimension
不为"cube"
或"cube-array"
. -
entry.
storageTexture
.format
必须是可以支持存储使用的格式。
-
-
-
-
设置 layout.
[[descriptor]]
to descriptor. -
设置 layout.
[[dynamicOffsetCount]]
to the number of entries in descriptor wherebuffer
is provided andbuffer
.hasDynamicOffset
istrue
. -
对每个 descriptor.
entries
中的GPUBindGroupLayoutEntry
entry:-
使用 entry.
binding
的键值,将 entry 插入 layout.[[entryMap]]
中。
-
-
8.1.2. 兼容性
GPUBindGroupLayout
对象a和b被认为是 组等价的:
-
对于任意的binding 数字 binding,满足以下条件之一:
-
它同时不在 a.
[[entryMap]]
和 b.[[entryMap]]
中。 -
a.
[[entryMap]]
[binding] == b.[[entryMap]]
[binding]
-
如果绑定组布局是 group-equivalent 它们可以在所有内容中互换使用。
8.2. GPUBindGroup
GPUBindGroup
定义了一组要绑定在一起的资源,以及这些资源在着色器阶段的使用方式。
[Exposed =(Window ,DedicatedWorker ),SecureContext ]interface GPUBindGroup { };GPUBindGroup includes GPUObjectBase ;
GPUBindGroup
对象具有以下内部插槽:
[[layout]]
, of typeGPUBindGroupLayout
, readonly-
与此
GPUBindGroup
关联的GPUBindGroupLayout
。 [[entries]]
, of type sequence<GPUBindGroupEntry
>, readonly-
GPUBindGroup
描述的一组GPUBindGroupEntry
。 [[usedResources]]
, of type ordered map<subresource, list<internal usage>>, readonly-
此绑定组使用的缓冲区和纹理集 subresource,与 internal usage 标志列表相关联。
8.2.1. 绑定组创建
GPUBindGroup
通过 GPUDevice.createBindGroup()
创建。
dictionary :
GPUBindGroupDescriptor GPUObjectDescriptorBase {required GPUBindGroupLayout layout ;required sequence <GPUBindGroupEntry >entries ; };
GPUBindGroupDescriptor
字典有以下成员:
layout
, of type GPUBindGroupLayout-
GPUBindGroupLayout
该绑定组的条目将符合。 entries
, of type sequence<GPUBindGroupEntry>-
一个条目列表,描述为
layout
描述的每个绑定向着色器公开的资源。
typedef (GPUSampler or GPUTextureView or GPUBufferBinding or GPUExternalTexture );
GPUBindingResource dictionary {
GPUBindGroupEntry required GPUIndex32 binding ;required GPUBindingResource resource ; };
GPUBindGroupEntry
描述了要绑定在 GPUBindGroup
中的单个资源,并且具有
以下成员:
binding
, of type GPUIndex32-
GPUBindGroup
中资源绑定的唯一标识符,对应于GPUBindGroupLayoutEntry.binding
和GPUShaderModule
中的 @binding 属性。 resource
, of type GPUBindingResource-
要绑定的资源,可以是
GPUSampler
、GPUTextureView
、GPUExternalTexture
或GPUBufferBinding
。
dictionary {
GPUBufferBinding required GPUBuffer buffer ;GPUSize64 offset = 0;GPUSize64 size ; };
GPUBufferBinding
描述一个缓冲区和可选范围以绑定为资源,并具有以下成员:
buffer
, of type GPUBuffer-
要绑定的
GPUBuffer
。 offset
, of type GPUSize64, defaulting to0
-
从
buffer
的开头到缓冲区绑定暴露给着色器的范围的开头的偏移量(以字节为单位)。 size
, of type GPUSize64-
缓冲区绑定的大小(以字节为单位)。 如果不是 provided,则指定从
offset
开始到buffer
结束的范围。
createBindGroup(descriptor)
-
Creates a
GPUBindGroup
.Called on:GPUDevice
this.Arguments:
Arguments for the GPUDevice.createBindGroup(descriptor) method. Parameter Type Nullable Optional Description descriptor
GPUBindGroupDescriptor
✘ ✘ 要创建的 GPUBindGroup
的描述。Returns:
GPUBindGroup
内容时间线 步骤:
-
使 bindGroup 为一个新的
GPUBindGroup
对象。 -
在 this 的 设备时间线 上发起 initialization steps。
-
返回 bindGroup。
设备时间线 initialization steps:-
使 limits 为 this.
[[device]]
.[[limits]]
. -
如果以下任何条件未满足,生成验证错误,使 bindGroup 无效,并停止。
对于 descriptor.
entries
中的每个GPUBindGroupEntry
bindingDescriptor:-
让 resource 为 bindingDescriptor.
resource
. -
在 descriptor.
layout
.entries
中有一个且仅有一个GPUBindGroupLayoutEntry
layoutBinding,它满足 layoutBinding.binding
等于 bindingDescriptor.binding
。 -
如果为 layoutBinding 定义了 binding 成员 ,那么
sampler
-
-
resource 为一个
GPUSampler
。 -
resource 可以与 this 一起使用。
-
如果 layoutBinding.
sampler
.type
为:"filtering"
-
resource.
[[isComparison]]
为false
。 "non-filtering"
-
resource.
[[isFiltering]]
为false
。 resource.[[isComparison]]
为false
。 "comparison"
-
resource.
[[isComparison]]
为true
。
-
texture
-
-
resource 为一个
GPUTextureView
。 -
resource 可以和 this 一起有效使用。
-
使 texture 为 resource.
[[texture]]
。 -
layoutBinding.
texture
.viewDimension
等于 resource’sdimension
。 -
layoutBinding.
texture
.sampleType
与 resource’sformat
compatible。 -
texture’s
usage
包含TEXTURE_BINDING
。 -
如果 layoutBinding.
texture
.multisampled
为true
, texture’ssampleCount
>1
, 否则 texture’ssampleCount
为1
。
-
storageTexture
-
-
resource 为一个
GPUTextureView
。 -
resource 可以和 this 一起使用。
-
使 texture 为 resource.
[[texture]]
。 -
layoutBinding.
storageTexture
.viewDimension
等于 resource’sdimension
。 -
layoutBinding.
storageTexture
.format
等于 resource.[[descriptor]]
.format
。 -
texture’s
usage
包含STORAGE_BINDING
。 -
resource.
[[descriptor]]
.mipLevelCount
必须为 1。
-
buffer
-
-
resource 为一个
GPUBufferBinding
。 -
resource.
buffer
可以与 this 一起使用。 -
The bound part designated by resource.
offset
and resource.size
resides inside the buffer and has non-zero size. -
effective buffer binding size(resource) ≥ layoutBinding.
buffer
.minBindingSize
. -
如果 layoutBinding.
buffer
.type
为"uniform"
-
-
effective buffer binding size(resource) ≤ limits.
maxUniformBufferBindingSize
。 -
resource.
offset
是 limits.minUniformBufferOffsetAlignment
的倍数。
"storage"
或"read-only-storage"
-
-
effective buffer binding size(resource) ≤ limits.
maxStorageBufferBindingSize
. -
effective buffer binding size(resource) 是4的倍数。
-
resource.
offset
是 limits.minStorageBufferOffsetAlignment
的倍数。
-
externalTexture
-
-
resource 为一个
GPUExternalTexture
. -
resource 可以和 this 一起使用。
-
-
-
使 bindGroup.
[[layout]]
= descriptor.layout
. -
使 bindGroup.
[[entries]]
= descriptor.entries
. -
使 bindGroup.
[[usedResources]]
= {}. -
对每个 descriptor.
entries
中的GPUBindGroupEntry
bindingDescriptor:-
让 internalUsage 是 layoutBinding 的 binding usage。
-
将resource看到的每个subresource以internalUsage的形式添加到
[[usedResources]]
中。
-
-
GPUBufferBinding
对象 a 和 b 当且仅当以下所有条件都为真时,被认为存在缓冲区绑定别名:
问题:当 size 可以为未定义时,定义如何通过 offset/size 形成范围。
8.3. GPUPipelineLayout
一个GPUPipelineLayout
定义了在setBindGroup()中设置的所有GPUBindGroup
对象的资源与通过GPURenderCommandsMixin.setPipeline
或GPUComputePassEncoder.setPipeline
设置的管线中的着色器之间的映射关系。
资源的完整绑定地址可以定义为一个三元组:
-
着色器阶段掩码,表示资源可见的阶段
-
绑定组索引
-
绑定编号
这个地址的组成部分也可以看作是管线的绑定空间。一个GPUBindGroup
(带有相应的GPUBindGroupLayout
)为固定的绑定组索引覆盖了该空间。其中包含的绑定需要是着色器在这个绑定组索引下使用的资源的超集。
[Exposed =(Window ,DedicatedWorker ),SecureContext ]interface GPUPipelineLayout { };GPUPipelineLayout includes GPUObjectBase ;
GPUPipelineLayout
具有以下内部插槽:
[[bindGroupLayouts]]
, 类型为 list<GPUBindGroupLayout
>-
在
GPUPipelineLayoutDescriptor.bindGroupLayouts
中创建时提供的GPUBindGroupLayout
对象。
注:对许多 GPURenderPipeline
或 GPUComputePipeline
管线使用相同的 GPUPipelineLayout
可确保在这些管线之间切换时用户代理不需要在内部重新绑定任何资源。
GPUComputePipeline
object X was created with GPUPipelineLayout.bindGroupLayouts
A, B, C. GPUComputePipeline
object Y was created with GPUPipelineLayout.bindGroupLayouts
A, D, C. Supposing the command encoding sequence has two dispatches:
-
setBindGroup(0, ...)
-
setBindGroup(1, ...)
-
setBindGroup(2, ...)
-
setPipeline
(X) -
setBindGroup(1, ...)
-
setPipeline
(Y)
在这种情况下,即使GPUPipelineLayout.bindGroupLayouts
索引2处的GPUBindGroupLayout
和插槽2处的GPUBindGroup
均未发生更改,用户代理也需要重新绑定组插槽2以进行第二次分派。
注:GPUPipelineLayout
的预期用法是将最常见且最不经常更改的绑定组放在布局的 “底部”,即更低的绑定组槽数,如 0 或 1。绑定组需要在绘制调用之间更频繁地更改,其索引应该越高。这一总体原则允许用户代理在绘制调用之间最小化状态更改,从而降低 CPU 开销。
8.3.1. 管线布局创建
一个 GPUPipelineLayout
通过 GPUDevice.createPipelineLayout()
被创建。
dictionary :
GPUPipelineLayoutDescriptor GPUObjectDescriptorBase {required sequence <GPUBindGroupLayout >bindGroupLayouts ; };
GPUPipelineLayoutDescriptor
字典定义了管线使用的所有 GPUBindGroupLayout
,并具有以下成员:
bindGroupLayouts
, of type sequence<GPUBindGroupLayout>-
一个将被管线使用的
GPUBindGroupLayout
列表。每个元素对应于GPUShaderModule
中的一个@group属性,其中第N
个元素对应于@group(N)
。
createPipelineLayout(descriptor)
-
创建一个
GPUPipelineLayout
。Called on:GPUDevice
this.Arguments:
Arguments for the GPUDevice.createPipelineLayout(descriptor) method. Parameter Type Nullable Optional Description descriptor
GPUPipelineLayoutDescriptor
✘ ✘ 要创建的 GPUPipelineLayout
的描述。Returns:
GPUPipelineLayout
内容时间线 步骤:
-
使 pl 为一个新的
GPUPipelineLayout
对象。 -
在 this 的 设备时间线 上发起 initialization steps。
-
返回 pl。
设备时间线 initialization steps:-
使 limits 为 this.
[[device]]
.[[limits]]
. -
让 allEntries 成为连接 bgl.
[[descriptor]]
.entries
中所有bgl在descriptor.bindGroupLayouts
的结果。 -
如果以下任何条件不满足[生成验证错误],使 pl 无效,并停止。
-
每个 descriptor.
bindGroupLayouts
中的GPUBindGroupLayout
必须与 this 一起valid to use with,并且[[exclusivePipeline]]
为 null。 -
descriptor.
bindGroupLayouts
的size 必须 ≤ limits.maxBindGroups
。 -
allEntries 一定不能超过 limits 的绑定槽数量限制。
-
-
设置 pl.
[[bindGroupLayouts]]
为 descriptor.bindGroupLayouts
.
-
注:如果两个GPUPipelineLayout
对象的内部[[bindGroupLayouts]]
序列包含group-equivalent的GPUBindGroupLayout
对象,那么它们在任何用途上都被认为是等效的。
8.4. 示例
GPUBindGroupLayout
。
然后使用 GPUBindGroupLayout
创建一个 GPUBindGroup
和一个 GPUPipelineLayout
。
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] });
9. 着色器模块
9.1. GPUShaderModule
[Exposed =(Window ,DedicatedWorker ),SecureContext ]interface GPUShaderModule {Promise <GPUCompilationInfo >getCompilationInfo (); };GPUShaderModule includes GPUObjectBase ;
GPUShaderModule
是对内部着色器模块对象的引用。
9.1.1. 着色器模块创建
dictionary :
GPUShaderModuleDescriptor GPUObjectDescriptorBase {required USVString code ;object sourceMap ;record <USVString ,GPUShaderModuleCompilationHint >hints ; };
code
, of type USVString-
着色器模块的 WGSL 源代码。
sourceMap
, of type object-
如果定义了,可以解释为source-map-v3格式。
源映射是可选的,但可以作为一种支持开发工具集成的标准化方式,例如源语言调试[SourceMap]。 源映射中的WGSL名称(标识符)遵循WGSL标识符对比中定义的规则。
hints
, of type record<USVString, GPUShaderModuleCompilationHint>-
如果定义了一个从着色器映射的入口点名称到一个
GPUShaderModuleCompilationHint
。这些GPUShaderModuleCompilationHint
上不执行任何验证。实现应该使用GPUShaderModuleCompilationHint
中的任何信息来执行尽可能多的createShaderModule()
内的编译。入口点名称遵循 WGSL 标识符比较 中定义的规则。注:在
hints
中提供信息没有任何可观察的效果,除了性能。因为一个单独的着色器模块可以容纳多个入口点,并且可以从一个着色器模块创建多个管线,因此在createShaderModule()
中一次性进行尽可能多的编译会比在多个调用createComputePipeline()
/createRenderPipeline()
中多次编译性能更高。
createShaderModule(descriptor)
-
创建一个
GPUShaderModule
。Called on:GPUDevice
this.Arguments:
Arguments for the GPUDevice.createShaderModule(descriptor) method. Parameter Type Nullable Optional Description descriptor
GPUShaderModuleDescriptor
✘ ✘ 要创建的 GPUShaderModule
的描述。Returns:
GPUShaderModule
内容时间线 步骤:
-
使 sm 为一个新的
GPUShaderModule
对象。 -
在 this 的 设备时间线 上发起 initialization steps。
-
返回 sm。
设备时间线 initialization steps:-
让 result 成为使用WGSL源的shader module creation的结果 descriptor.
code
。 -
如果以下任何要求未得到满足,产生一个验证错误,使 sm 无效,然后返回。
-
this 必须 有效。
-
result 必须不为 shader-creation program error。
-
问题(gpuweb/gpuweb#2308): 是否应允许在此处出现内部错误(uncategorized errors),还是应该将其延迟至管线创建?
问题:描述剩余的
createShaderModule()
验证和算法步骤。注: 用户代理不应该在此处引发的验证错误的message
文本中包含详细的编译器错误消息或着色器文本: 这些细节可以通过getCompilationInfo()
访问。 用户代理应该为开发者提供便于调试的易于阅读、格式化的错误详细信息(例如浏览器开发者控制台中的警告,可以展开以显示完整的着色器源代码)。由于着色器编译错误在生产应用程序中应该很少出现,用户代理可以选择无论错误处理如何(GPU错误范围或者
uncapturederror
事件处理器),都向开发者显示它们,例如作为可展开的警告。 如果没有这样做,它们应该提供并记录另一种方法供开发者访问易于阅读的错误详细信息,例如添加一个复选框以无条件显示错误, 或者在将GPUCompilationInfo
对象记录到控制台时显示人类可读的详细信息。 -
GPUShaderModule
:
// A simple vertex and fragment shader pair that will fill the viewport with red. const shaderSource= ` var<private> pos : array<vec2<f32>, 3> = array<vec2<f32>, 3>( vec2(-1.0, -1.0), vec2(-1.0, 3.0), vec2(3.0, -1.0)); @vertex fn vertexMain(@builtin(vertex_index) vertexIndex : u32) -> @builtin(position) vec4<f32> { return vec4(pos[vertexIndex], 1.0, 1.0); } @fragment fn fragmentMain() -> @location(0) vec4<f32> { return vec4(1.0, 0.0, 0.0, 1.0); } ` ; const shaderModule= gpuDevice. createShaderModule({ code: shaderSource, });
9.1.1.1. 着色器模块编译提示
着色器模块编译提示是可选的、额外的信息,用来表示给定的 GPUShaderModule
入口点将来打算如何使用。对于某些实现来说,这些信息可能有助于更早地编译着色器模块,从而可能提高性能。
dictionary { (
GPUShaderModuleCompilationHint GPUPipelineLayout or GPUAutoLayoutMode )layout ; };
layout
, of type(GPUPipelineLayout or GPUAutoLayoutMode)
-
一个
GPUPipelineLayout
,将来可以在createComputePipeline()
或createRenderPipeline()
调用中与GPUShaderModule
一起使用。 如果设置为“auto”
,则将使用与此提示关联的入口点的默认管线布局。
createShaderModule()
和 createComputePipeline()
/ createRenderPipeline()
提供相同的信息。
如果作者在调用 createShaderModule()
时无法提供提示信息,他们通常不应该延迟调用 createShaderModule()
;而应该从 hints
或 GPUShaderModuleCompilationHint
中省略未知信息。省略此信息可能导致编译被推迟到 createComputePipeline()
/ createRenderPipeline()
。
如果作者对传递给 createShaderModule()
的提示信息与稍后传递给 createComputePipeline()
/ createRenderPipeline()
的相同模块的信息是否匹配没有把握,他们应该避免将该信息传递给 createShaderModule()
,因为将不匹配的信息传递给 createShaderModule()
可能导致不必要的编译发生。
9.1.2. 着色器模块编译信息
enum {
GPUCompilationMessageType ,
"error" ,
"warning" }; [
"info" Exposed =(Window ,DedicatedWorker ),Serializable ,SecureContext ]interface {
GPUCompilationMessage readonly attribute DOMString message ;readonly attribute GPUCompilationMessageType type ;readonly attribute unsigned long long lineNum ;readonly attribute unsigned long long linePos ;readonly attribute unsigned long long offset ;readonly attribute unsigned long long length ; }; [Exposed =(Window ,DedicatedWorker ),Serializable ,SecureContext ]interface {
GPUCompilationInfo readonly attribute FrozenArray <GPUCompilationMessage >; };
messages
一个 GPUCompilationMessage
是由 GPUShaderModule
编译器生成的信息、警告或错误消息。这些消息旨在以人类可读的方式帮助开发人员诊断与他们的着色器 code
有关的问题。每个消息可能对应着色器代码中的某个单点,着色器代码的子串,或者可能根本不对应代码中的任何特定点。
GPUCompilationMessage
具有以下属性:
message
, of type DOMString, readonly-
这个编译信息的可读、可本地化文本。
注:
message
应遵循最佳实践,关于语言和方向信息。这包括利用任何未来可能出现的有关字符串语言和方向元数据的标准。编者按: 在撰写本文时,尚未提供任何可以与旧版API兼容且一致的语言/方向建议,但一旦出现,应正式采纳。
type
, of type GPUCompilationMessageType, readonly-
消息的严重级别。
如果
type
是"error"
,它对应一个shader-creation error。 lineNum
, of type unsigned long long, readonly-
在着色器
code
中与message
对应的行号。值为基于一的,这样 lineNum 为1
表示着色器code
的第一行。行由 line breaks 分隔。如果
message
对应于一个子字符串,则指向子字符串开始的行。如果message
与着色器code
中的任何特定点都不对应,则必须为0
。 linePos
, of type unsigned long long, readonly-
偏移量,以UTF-16代码单元为单位,从着色器
code
的行起始位置lineNum
到message
对应的点或子串起始位置。值是从1开始的,这样,linePos
的值1
表示行的第一个代码单元。如果
message
对应一个子串,则该指针指向子串的第一个UTF-16代码单元。如果message
不对应着色器code
中的任何特定点,则必须为0
。 offset
, of type unsigned long long, readonly-
从着色器
code
开始的偏移量,以UTF-16代码单元为单位,到message
相对应的点或子字符串的开始位置。必须引用与lineNum
和linePos
相同的位置。如果message
不对应着色器code
中的任何特定点,则必须为0
。 length
, of type unsigned long long, readonly-
在与
message
对应的子字符串中的 UTF-16 编码单元数。 如果消息不对应子字符串,则length
必须为 0。
注:GPUCompilationMessage
.lineNum
和 GPUCompilationMessage
.linePos
都是从1开始的,因为它们最常见的用途预计是打印出可直接与许多文本编辑器中显示的行号和列号相关联的易于阅读的消息。
注:GPUCompilationMessage
.offset
和 GPUCompilationMessage
.length
可以传递给 substr()
以获取着色器 code
子字符串中与 message
相对应的部分。
getCompilationInfo()
-
返回
GPUShaderModule
编译期间生成的任何消息。消息的位置、顺序和内容是实现定义的。 特别是,消息可能不会按
lineNum
排序。Called on:GPUShaderModule
thisReturns:
Promise
<GPUCompilationInfo
>内容时间线 步骤:
-
使 contentTimeline 为当前 内容时间线。
-
使 promise 为 a new promise.
-
在 this 的 设备时间线 上发起 synchronization steps。
-
返回 promise。
设备时间线 synchronization steps:-
当 设备时间线 通知 this 的 shader module creation 已完成时:
-
让 messages 是在 this 的 shader module creation 期间生成的任何错误、警告或信息性消息的列表。
-
在 contentTimeline 上发布后续步骤。
-
内容时间线 步骤:-
使 info 为一个新的
GPUCompilationInfo
。 -
对每个 messages 中的 message:
-
使 m 为一个新的
GPUCompilationMessage
。 -
设置 m.
message
为 message 的文本。 -
- 如果 message 与着色器
code
中的特定子字符串或位置相关联: - 否则:
- 如果 message 与着色器
-
-
以 info 解析 promise。
-
10. 管线
一个管线,无论是GPUComputePipeline
还是GPURenderPipeline
,代表了完成输入数据处理的整个功能,这些数据以绑定和顶点缓冲区的形式存在,并产生一些输出,如输出渲染目标中的颜色。
在结构上,pipeline 由一系列可编程阶段(着色器)和固定功能状态(如混合模式)组成。
注:在内部,根据目标平台,驱动程序可能会将一些固定功能状态转换为着色器代码,并将其与用户提供的着色器链接在一起。这种链接是对象作为一个整体创建的原因之一。
这种组合状态是作为一个单独的对象创建的(GPUComputePipeline
或 GPURenderPipeline
),并使用一个命令进行切换(分别为:GPUComputePassEncoder
.setPipeline()
或 GPURenderCommandsMixin
.setPipeline()
)。
创建管线有两种方法:
- immediate pipeline creation
-
createComputePipeline()
andcreateRenderPipeline()
返回一个可以立即在 pass 编码器中使用的管线对象。当此操作失败时,管线对象将无效,调用将产生一个validation error或一个internal error。
注: 返回一个句柄对象是立即进行的,但实际的管线创建并不是同步的。如果管线创建需要很长时间,这可能会在创建调用和首次使用它的
submit()
之间的某个时间点引入设备时间表中的停顿。这个时间点没有明确规定,但最可能是以下之一:在创建时,在 setPipeline() 中第一次使用管线时,在相应的GPUCommandEncoder
或GPURenderBundleEncoder
的finish()时,或在GPUCommandBuffer
的submit()
时。 - async pipeline creation
-
createComputePipelineAsync()
andcreateRenderPipelineAsync()
返回一个Promise
,当管线创建完成时,它将解析为一个管线对象。当这个操作失败时,
Promise
会被一个GPUPipelineError
拒绝。
GPUPipelineError
描述管线创建失败。
[Exposed =(Window ,DedicatedWorker ),SecureContext ,Serializable ]interface GPUPipelineError :DOMException {((
constructor DOMString or undefined ),
message GPUPipelineErrorInit );
options readonly attribute GPUPipelineErrorReason reason ; };dictionary {
GPUPipelineErrorInit required GPUPipelineErrorReason ; };
reason enum GPUPipelineErrorReason {"validation" ,"internal" };
GPUPipelineError
constructor:
constructor()
-
Arguments for the GPUPipelineError.constructor() method. Parameter Type Nullable Optional Description message
(DOMString or undefined)
✘ ✘ 基础 DOMException
的错误信息。options
GPUPipelineErrorInit
✘ ✘ 针对 GPUPipelineError
的特定选项。
GPUPipelineError
具有以下参数:
reason
, of type GPUPipelineErrorReason, readonly-
一个只读的slot-backed attribute,以
GPUPipelineErrorReason
的形式展示管线创建过程中遇到的错误类型:-
"validation"
: 一个 validation error. -
"internal"
: 一个 internal error.
-
GPUPipelineError
对象是 serializable objects.
-
根据给定的值和序列化,运行
DOMException
的序列解步骤。
-
运行
DOMException
deserialization steps 给定 value 和 serialized。
10.1. 基础管线
enum {
GPUAutoLayoutMode };
"auto" dictionary :
GPUPipelineDescriptorBase GPUObjectDescriptorBase {required (GPUPipelineLayout or GPUAutoLayoutMode ); };
layout interface mixin { [
GPUPipelineBase NewObject ]GPUBindGroupLayout getBindGroupLayout (unsigned long index ); };
GPUPipelineBase
具有以下内部插槽:
[[layout]]
, 类型为GPUPipelineLayout
-
此资源布局的定义可以与
this
一起使用。
GPUPipelineBase
具有以下方法:
getBindGroupLayout(index)
-
获取与
GPUPipelineBase
的GPUBindGroupLayout
兼容的index
处的GPUBindGroupLayout
。Called on:GPUPipelineBase
thisArguments:
Arguments for the GPUPipelineBase.getBindGroupLayout(index) method. Parameter Type Nullable Optional Description index
unsigned long
✘ ✘ 管线布局的 [[bindGroupLayouts]]
序列的索引。Returns:
GPUBindGroupLayout
内容时间线 steps:
-
使 layout 为一个新的
GPUBindGroupLayout
对象。 -
在 this 的 设备时间线 上发起 initialization steps。
-
返回 layout。
设备时间线 initialization steps:-
如果以下任何条件不满足,生成验证错误,使得layout 无效,并停止。
-
this 是有效的。
-
index 小于 this.
[[layout]]
.[[bindGroupLayouts]]
的 size
-
初始化 layout,使其成为 this.
[[layout]]
.[[bindGroupLayouts]]
[index] 的副本。
注意:
GPUBindGroupLayout
仅按值使用,而不是按引用使用,因此这等同于在新的包装器中返回相同的内部对象。每次返回一个新的GPUBindGroupLayout
包装器是为了避免在 内容时间线 和 设备时间线 之间进行往返。 -
10.1.1. 默认管线布局
一个创建时将 layout
设置为 “auto”
的 GPUPipelineBase
对象,会创建并使用一个默认布局。
注:默认布局是为简单 pipeline 提供的便利,但在大多数情况下推荐使用显式布局。从默认布局创建的绑定组不能与其他 pipeline 一起使用,当改变着色器时,默认布局的结构可能会改变,从而导致意外的绑定组创建错误。
要为GPUPipelineBase
pipeline创建一个默认管线布局,请执行以下步骤:
-
令 groupCount 为 0。
-
令 groupDescs 为一个有 device.
[[limits]]
.maxBindGroups
个新的GPUBindGroupLayoutDescriptor
对象的序列。 -
对于 groupDescs 中的每个 groupDesc:
-
对于用于创建 pipeline 的描述符中的每个
GPUProgrammableStage
stageDesc:-
令 shaderStage 为 stageDesc.
entryPoint
在 stageDesc.module
中的GPUShaderStageFlags
。 -
对于 stageDesc 静态使用 的每个资源 resource:
-
让 group 成为 resource 的 "group" 装饰。
-
让 binding 成为 resource 的 "binding" 装饰。
-
让 entry 成为一个新的
GPUBindGroupLayoutEntry
。 -
将 entry.
binding
设置为 binding。 -
将 entry.
visibility
设置为 shaderStage。 -
如果 resource 用于采样器绑定:
-
令 samplerLayout 为一个新的
GPUSamplerBindingLayout
。 -
设置 entry.
sampler
为 samplerLayout。
-
-
如果 resource 用于比较采样器绑定:
-
创建一个新的
GPUSamplerBindingLayout
,将其命名为 samplerLayout。 -
将 samplerLayout 的
type
设置为"comparison"
。 -
将 entry 的
sampler
设置为 samplerLayout。
-
-
如果 resource 用于缓冲区绑定:
-
创建一个新的
GPUBufferBindingLayout
,将其命名为 bufferLayout。 -
将 bufferLayout 的
minBindingSize
设置为 resource 的 最小缓冲区绑定尺寸。 -
如果 resource 用于只读存储缓冲区:
-
将 bufferLayout 的
type
设置为"read-only-storage"
。
-
-
如果 resource 用于存储缓冲区:
-
将 entry 的
buffer
设置为 bufferLayout。
-
-
如果 resource 是采样纹理绑定:
-
令 textureLayout 为一个新的
GPUTextureBindingLayout
。 -
如果 resource 是深度纹理绑定:
-
将 textureLayout.
sampleType
设置为"depth"
否则,如果 resource 的采样类型是:
f32
并且存在一个带有textureSample*
内置的 resource 的 static use-
将 textureLayout.
sampleType
设置为"float"
f32
其他情况-
将 textureLayout.
sampleType
设置为"unfilterable-float"
i32
-
将 textureLayout.
sampleType
设置为"sint"
u32
-
将 textureLayout.
sampleType
设置为"uint"
-
-
将 textureLayout.
viewDimension
设置为 resource 的维度。 -
如果 resource 是多重采样纹理:
-
将 textureLayout.
multisampled
设置为true
。
-
-
设置 entry.
texture
为 textureLayout。
-
-
如果resource适用于存储纹理绑定:
-
令storageTextureLayout为一个新的
GPUStorageTextureBindingLayout
。 -
设置storageTextureLayout.
format
为resource的格式。 -
设置storageTextureLayout.
viewDimension
为resource的维度。 -
如果resource是一个只写存储纹理:
-
设置storageTextureLayout.
access
为"write-only"
。
-
-
设置entry.
storageTexture
为storageTextureLayout。
-
-
设置groupCount为max(groupCount,group+1)。
-
如果 groupDescs[group] 有一个条目 previousEntry,其
binding
等于 binding :-
如果 entry 和 previousEntry 具有不同的
visibility
:-
将 entry.
visibility
中设置的位添加到 previousEntry.visibility
-
-
如果 resource 是一个缓冲区绑定,并且 entry 的
buffer
.minBindingSize
大于 previousEntry :-
设置 previousEntry.
buffer
.minBindingSize
为 entry.buffer
.minBindingSize
。
-
-
如果 resource 是一个采样纹理绑定,并且 entry 和 previousEntry 的
texture
.sampleType
不同, 且 entry 和 previousEntry 都具有texture
.sampleType
的"float"
或"unfilterable-float"
类型:-
设置 previousEntry.
texture
.sampleType
为"float"
。
-
-
如果 entry 和 previousEntry 之间的任何其他属性不相等:
-
返回
null
(这将导致管线的创建失败)。
-
-
-
其他情况
-
将 entry 附加到 groupDescs[group]。
-
-
-
-
对于从 0 到 groupCount - 1(含)的每个 i:
-
让 groupDesc 为 groupDescs[i]。
-
令 bindGroupLayout 为调用 device.
createBindGroupLayout()
(groupDesc)的结果。 -
将 bindGroupLayout.
[[exclusivePipeline]]
设置为 pipeline。 -
将 bindGroupLayout 添加到 groupLayouts。
-
-
令 desc 为一个新的
GPUPipelineLayoutDescriptor
。 -
将 desc.
bindGroupLayouts
设置为 groupLayouts。 -
返回 device.
createPipelineLayout()
(desc)。
10.1.2. GPUProgrammableStage
一个 GPUProgrammableStage
描述了用户提供的 GPUShaderModule
中控制 pipeline 的可编程阶段之一的入口点。入口点名称遵循 WGSL 标识符比较 中定义的规则。
dictionary GPUProgrammableStage {required GPUShaderModule module ;required USVString entryPoint ;record <USVString ,GPUPipelineConstantValue >constants ; };typedef double GPUPipelineConstantValue ; // May represent WGSL’s bool, f32, i32, u32, and f16 if enabled.
GPUProgrammableStage
具有以下成员:
module
, of type GPUShaderModule-
包含该可编程阶段将执行的代码的
GPUShaderModule
。 entryPoint
, of type USVString-
函数名称位于
module
中,此阶段将使用该函数来执行其工作。 constants
, of type record<USVString, GPUPipelineConstantValue>-
指定着色器模块
module
中 pipeline-overridable 常量的值。每个这样的 pipeline-overridable 常量都由单个 pipeline-overridable constant identifier string 唯一标识 (表示常量的数字ID,如果有,则表示常量的标识符名称)。源代码映射中的 WGSL 名称(标识符)遵循 WGSL identifier comparison 中定义的规则。
每个键值对的键必须等于这样一个常量的标识符字符串。当管线被执行时,该常量将具有指定的值。
值指定为
GPUPipelineConstantValue
, 这是一个double
。它们被转换为管线可覆盖常量的 to WGSL 类型 (bool/i32/u32/f32/f16)。如果转换失败,则会生成一个验证错误。Pipeline-overridable constants defined in WGSL:@ id ( 0 ) override has_point_light :bool = true ; // Algorithmic control. @ id ( 1200 ) override specular_param :f32 = 2.3 ; // Numeric control. @ id ( 1300 ) override gain :f32 ; // Must be overridden. override width :f32 = 0.0 ; // Specifed at the API level // using the name "width". override depth :f32 ; // Specifed at the API level // using the name "depth". // Must be overridden. override height = 2 * depth ; // The default value // (if not set at the API level), // depends on another // overridable constant. 对应的JavaScript代码,仅提供所需的重写(没有默认值):
{ // ... constants: { 1300 : 2.0 , // "gain" depth: - 1 , // "depth" } } 相应的 JavaScript 代码,覆盖所有常量:
{ // ... constants: { 0 : false , // "has_point_light" 1200 : 3.0 , // "specular_param" 1300 : 2.0 , // "gain" width: 20 , // "width" depth: - 1 , // "depth" height: 15 , // "height" } }
Arguments:
-
GPUShaderStage
stage -
GPUProgrammableStage
descriptor -
GPUPipelineLayout
layout
返回 true
,如果满足以下所有条件:
-
descriptor 的
module
必须是一个 有效 的GPUShaderModule
。 -
descriptor 的
module
必须包含一个入口点,用于着色阶段 阶段,命名为 descriptor 的entryPoint
。 -
对于 descriptor 中 静态使用 的每一个 binding:
-
validating shader binding (binding,layout) 必须返回
true
。
-
-
对于 descriptor 中的每个纹理和采样器,它们在纹理采样调用中 静态使用:
-
将 texture 设为调用中采样纹理相对应的
GPUBindGroupLayoutEntry
。 -
将 sampler 设为调用中使用的采样器相对应的
GPUBindGroupLayoutEntry
。 -
如果 sampler 的
type
为"filtering"
,则 纹理 的sampleType
必须为"float"
。
-
-
对于 descriptor 的
constants
中的每个 键 ➞ 值:-
key 必须等于着色器模块 descriptor 的
module
中根据 WGSL 标识符比较 规则定义的某个 管线可重载 常量的 管线可重载常量标识符字符串。将该常量的类型设为 T。 -
将 IDL 值 值 to WGSL 类型 T 转换成不抛出
TypeError
的异常。
-
-
对于 descriptor 中 静态使用 的每个 管线可重载常量标识符字符串 键: -如果由 key 标识的管线可重载常量 没有默认值,则 descriptor 的
constants
必须 包含 键。
返回值 false
对应于 管线创建错误。
Arguments:
-
着色器绑定声明 variable,从着色器模块反射出的模块作用域变量声明
-
GPUPipelineLayout
layout
让 bindGroup 成为绑定组索引,bindIndex 成为着色器绑定声明 variable 的绑定索引。
如果满足以下所有条件,则返回 true
:
-
layout.
[[bindGroupLayouts]]
[bindGroup] 包含 一个GPUBindGroupLayoutEntry
entry,其 entry.binding
== bindIndex。 -
如果 entry 的定义的 binding member 是:
buffer
-
"uniform"
-
variable 的地址空间为
uniform
。 "storage"
-
variable 的地址空间为
storage
,地址模式为read_write
。 "read-only-storage"
-
variable 的地址空间为
storage
,地址模式为read
。
如果 entry.
buffer
.minBindingSize
不是0
,那么它必须至少是着色器中关联缓冲区绑定变量的最小缓冲区绑定大小。 sampler
-
"filtering"
or"non-filtering"
-
variable 类型为
sampler
. "comparison"
-
variable 类型为
sampler_comparison
.
texture
-
如果且仅当 entry.
texture
.multisampled
为 true,variable 类型为 texture_multisampled_2d或 texture_depth_multisampled_2d 。 如果 entry.
texture
.sampleType
为:"float"
,"unfilterable-float"
,"sint"
or"uint"
-
variable 为以下类型之一:
-
texture_1d<T>
-
texture_2d<T>
-
texture_2d_array<T>
-
texture_cube<T>
-
texture_cube_array<T>
-
texture_3d<T>
-
texture_multisampled_2d<T>
如果 entry.
texture
.sampleType
为:"float"
or"unfilterable-float"
-
采样类型
T
为f32
. "sint"
-
采样类型
T
为i32
. "uint"
-
采样类型
T
为u32
.
-
"depth"
-
variable 为以下类型之一:
-
texture_2d<T>
-
texture_2d_array<T>
-
texture_cube<T>
-
texture_cube_array<T>
-
texture_multisampled_2d<T>
-
texture_depth_2d
-
texture_depth_2d_array
-
texture_depth_cube
-
texture_depth_cube_array
-
texture_depth_multisampled_2d
其中采样类型
T
是f32
。 -
如果 entry.
texture
.viewDimension
为:"1d"
-
variable 类型为
texture_1d<T>
. "2d"
-
variable 类型为
texture_2d<T>
或texture_multisampled_2d<T>
. "2d-array"
-
variable 类型为
texture_2d_array<T>
. "cube"
-
variable 类型为
texture_cube<T>
. "cube-array"
-
variable 类型为
texture_cube_array<T>
. "3d"
-
variable 类型为
texture_3d<T>
.
storageTexture
-
如果 entry.
storageTexture
.viewDimension
为:"1d"
-
variable 类型为
texture_storage_1d<T, A>
. "2d"
-
variable 类型为
texture_storage_2d<T, A>
. "2d-array"
-
variable 类型为
texture_storage_2d_array<T, A>
. "3d"
-
variable 类型为
texture_storage_3d<T, A>
.
如果 entry.
storageTexture
.access
为:"write-only"
-
访问模式
A
为write
.
纹素格式
T
等于 entry.storageTexture
.format
.
-
让 T 成为 var 的[= store type =]。
-
如果 T 是一个运行时大小的数组或包含一个运行时大小的数组,将
array<E>
替换为array<E, 1>
。注:这确保总是有足够的内存存放一个元素,允许数组索引被限制在数组的长度范围内,从而在内存里进行访问。
-
返回 SizeOf(T)。
注: 强制执行此下限可确保通过缓冲区变量进行的读写仅访问缓冲区绑定区域内的内存位置。
GPUProgrammableStage
静态使用,
如果它存在于指定的 entryPoint
的 着色器阶段接口 中,
在指定的着色器 module
中。 10.2. GPUComputePipeline
一个GPUComputePipeline
是一种控制计算着色器阶段的管线,可以在GPUComputePassEncoder
中使用。
计算输入和输出都包含在绑定中,根据给定的GPUPipelineLayout
。
输出对应于类型为“storage”
的buffer
绑定,以及类型为“write-only”
的storageTexture
绑定。
计算 管线 的阶段:
-
Compute shader
[Exposed =(Window ,DedicatedWorker ),SecureContext ]interface GPUComputePipeline { };GPUComputePipeline includes GPUObjectBase ;GPUComputePipeline includes GPUPipelineBase ;
10.2.1. 计算管线创建
一个 GPUComputePipelineDescriptor
描述了一个计算 pipeline。请参阅 § 23.2 计算 以获取更多详细信息。
dictionary :
GPUComputePipelineDescriptor GPUPipelineDescriptorBase {required GPUProgrammableStage compute ; };
GPUComputePipelineDescriptor
具有以下成员:
compute
, of type GPUProgrammableStage-
描述 管线 的计算着色器入口点。
createComputePipeline(descriptor)
-
Creates a
GPUComputePipeline
using immediate pipeline creation.Called on:GPUDevice
this.Arguments:
Arguments for the GPUDevice.createComputePipeline(descriptor) method. Parameter Type Nullable Optional Description descriptor
GPUComputePipelineDescriptor
✘ ✘ 要创建的 GPUComputePipeline
的描述。Returns:
GPUComputePipeline
内容时间线 步骤:
-
让 pipeline 成为一个新的
GPUComputePipeline
对象。 -
在 this 的 Device timeline 上发布 initialization steps。
-
返回 pipeline。
设备时间线 initialization steps:-
如果 descriptor.
layout
是“auto”
,则让 layout 成为 pipeline 的新默认管线布局;否则,使用 descriptor.layout
。 -
如果以下任何条件不满足 生成验证错误,则使 pipeline 变为 invalid,并停止。
-
layout 必须是与 this 可用的。
-
与[验证 GPUProgrammableStage](
COMPUTE
, descriptor.compute
,layout) 成功匹配。 -
设 workgroupStorageUsed 是由 descriptor.
compute
的"工作组"地址空间中的所有变量的类型 T 的 SizeOf(T) 在每个 类型 T 上的 roundUp(16) 的和。workgroupStorageUsed 必须是≤ device.limits.
maxComputeWorkgroupStorageSize
。问题(gpuweb/gpuweb#3485):这是否需要考虑填充?
-
descriptor.
compute
的工作组使用数量必须是 ≤ device.limits.maxComputeInvocationsPerWorkgroup
。 -
descriptor.
compute
的workgroup_size
属性的每个组件都必须是 ≤ [在 [device.limits.maxComputeWorkgroupSizeX
, device.limits.maxComputeWorkgroupSizeY
, device.limits.maxComputeWorkgroupSizeZ
]] 对应的组件。
-
-
将 pipeline.
[[layout]]
设置为 layout。
-
createComputePipelineAsync(descriptor)
-
创建一个使用 异步管线创建 的
GPUComputePipeline
。 当创建的管线准备好可立即使用时,返回的Promise
将会解析。如果管线创建失败,返回的
Promise
会以GPUPipelineError
拒绝。注:尽可能使用此方法,因为它可以阻止 queue timeline 在管线编译上的工作。
Called on:GPUDevice
this.Arguments:
Arguments for the GPUDevice.createComputePipelineAsync(descriptor) method. Parameter Type Nullable Optional Description descriptor
GPUComputePipelineDescriptor
✘ ✘ Description of the GPUComputePipeline
to create.Returns:
Promise
<GPUComputePipeline
>内容时间线 步骤:
-
设 contentTimeline 为当前的 内容时间线。
-
设 promise 为 a new promise。
-
在 this 的 设备时间线上发布 initialization steps。
-
返回 promise。
设备时间线 initialization steps:-
令 pipeline 为一个新的
GPUComputePipeline
,创建方式如同调用 this.createComputePipeline()
并使用 descriptor; -
当 pipeline 准备好被使用或已变为 无效 的,在 contentTimeline 上发出后续步骤。
Content timeline steps:-
If pipeline...
- 有效
-
以 pipeline 解析 promise。
- 由于 内部错误 而变为 无效 的
-
拒绝 promise,并附带一个
GPUPipelineError
,其中reason
的值为“internal”
。 - 由于 验证错误 而变为 无效的
-
拒绝 promise,并附带一个
GPUPipelineError
,其中reason
的值为“validation”
。
-
GPUComputePipeline
:
const computePipeline= gpuDevice. createComputePipeline({ layout: pipelineLayout, compute: { module: computeShaderModule, entryPoint: 'computeMain' , } });
10.3. GPURenderPipeline
一个GPURenderPipeline
是一种管线,用于控制顶点和片段着色器阶段,并可以在GPURenderPassEncoder
和GPURenderBundleEncoder
中使用。
渲染 管线 输入包括:
-
绑定(bindings),根据给定的
GPUPipelineLayout
进行 -
顶点和索引缓冲区,由
GPUVertexState
描述 -
颜色附件,由
GPUColorTargetState
描述 -
可选的深度模板附件,由
GPUDepthStencilState
描述
渲染 管线 输出包括:
-
具有
“write-only”
访问权限的storageTexture
绑定 -
颜色附件,由
GPUColorTargetState
描述 -
可选的深度模板附件,由
GPUDepthStencilState
描述
渲染 管线 包括以下渲染阶段:
-
顶点获取,由
GPUVertexState.buffers
控制 -
顶点着色器,由
GPUVertexState
控制 -
图元装配,由
GPUPrimitiveState
控制 -
栅格化,由
GPUPrimitiveState
,GPUDepthStencilState
和GPUMultisampleState
控制 -
片段着色器,由
GPUFragmentState
控制 -
模板测试及操作,由
GPUDepthStencilState
控制 -
深度测试及写操作,由
GPUDepthStencilState
控制 -
输出合并,由
GPUFragmentState.targets
控制
[Exposed =(Window ,DedicatedWorker ),SecureContext ]interface GPURenderPipeline { };GPURenderPipeline includes GPUObjectBase ;GPURenderPipeline includes GPUPipelineBase ;
GPURenderPipeline
具有以下内部插槽:
[[descriptor]]
, 类型为GPURenderPipelineDescriptor
-
GPURenderPipelineDescriptor
描述这个管线。GPURenderPipelineDescriptor
的所有可选字段都已定义。 [[writesDepth]]
, 类型为 boolean-
如果管线写入深度/模板附件的深度组件,则为真
[[writesStencil]]
, 类型为 boolean-
如果管线写入深度/模板附件的模板组件,则为真
10.3.1. 渲染管线创建
一个GPURenderPipelineDescriptor
通过配置每个渲染阶段来描述一个渲染管线。
有关更多详细信息,请参阅§ 23.3 渲染。
dictionary :
GPURenderPipelineDescriptor GPUPipelineDescriptorBase {required GPUVertexState vertex ;GPUPrimitiveState primitive = {};GPUDepthStencilState depthStencil ;GPUMultisampleState multisample = {};GPUFragmentState fragment ; };
GPURenderPipelineDescriptor
具有以下成员:
vertex
, of type GPUVertexState-
描述了 管线 的顶点着色器入口点及其输入缓冲区布局。
primitive
, of type GPUPrimitiveState, defaulting to{}
-
描述与 管线 相关的原始属性。
depthStencil
, of type GPUDepthStencilState-
描述了可选的深度模板属性,包括测试、操作和偏差。
multisample
, of type GPUMultisampleState, defaulting to{}
-
描述 管线 的多重采样属性。
fragment
, of type GPUFragmentState-
描述了 管线 的片段着色器入口点及其输出颜色。如果没有 提供,则启用 § 23.3.8 无颜色输出 模式。
createRenderPipeline(descriptor)
-
创建一个使用即时管道创建的
GPURenderPipeline
。Called on:GPUDevice
this.Arguments:
Arguments for the GPUDevice.createRenderPipeline(descriptor) method. Parameter Type Nullable Optional Description descriptor
GPURenderPipelineDescriptor
✘ ✘ Description of the GPURenderPipeline
to create.Returns:
GPURenderPipeline
内容时间线 步骤:
-
-
对于 descriptor.
fragment
.targets
中每个非 null 的 colorState 的 For each 操作:-
使用 this.
[[device]]
,对 colorState.format
进行 ? 验证纹理格式所需特性。
-
-
-
如果 descriptor.
depthStencil
被 提供:-
使用 this.
[[device]]
,对 descriptor.depthStencil
.format
进行 ? 验证纹理格式所需特性。
-
-
让 pipeline 成为一个新的
GPURenderPipeline
对象。 -
在 this 的 设备时间线 上发出 初始化步骤。
-
返回 pipeline。
设备时间线 initialization steps:-
如果 descriptor.
layout
是“auto”
,则让 layout 成为 pipeline 的一个新的默认管道布局,否则为 descriptor.layout
。 -
如果任何以下条件不满足: 产生一个验证错误,使 pipeline 无效,并停止。
-
layout 可以与 this 一起有效使用。
-
验证GPURenderPipelineDescriptor(descriptor, layout, this)成功。
-
layout.
[[bindGroupLayouts]]
.length + vertexBufferCount ≤ this.[[device]]
.[[限制]]
.maxBindGroupsPlusVertexBuffers
, 其中 vertexBufferCount 是 descriptor.vertex
.buffers
中值为未定义
的最大索引。
-
-
将descriptor设置为pipeline.
[[descriptor]]
。 -
将pipeline.
[[writesDepth]]
设置为false。 -
将pipeline.
[[writesStencil]]
设置为false。 -
令depthStencil为descriptor.
depthStencil
。 -
如果depthStencil不为null:
-
将pipeline.
[[writesDepth]]
设置为depthStencil.depthWriteEnabled
。 -
如果depthStencil.
stencilWriteMask
不为0
:-
令stencilFront为depthStencil.
stencilFront
。 -
令stencilBack为depthStencil.
stencilBack
。 -
如果 cullMode 不是
“front”
,且 stencilFront.passOp
、 stencilFront.depthFailOp
或 stencilFront.failOp
中的任何一个不是“keep”
:-
将pipeline.
[[writesStencil]]
设置为true。
-
-
如果 cullMode 不是
“back”
,且 stencilBack.passOp
、 stencilBack.depthFailOp
或 stencilBack.failOp
中的任何一个不是“keep”
:-
将pipeline.
[[writesStencil]]
设置为true。
-
-
-
-
将pipeline.
[[layout]]
设置为layout。
问题:需要渲染状态的描述。
-
createRenderPipelineAsync(descriptor)
-
创建一个使用 异步管道创建 的
GPURenderPipeline
。 当创建的管道准备好使用且无需额外延迟时,返回的Promise
将解析。如果管道创建失败,返回的
Promise
将以GPUPipelineError
拒绝。注:只要可能,就优先使用此方法,因为它可以防止在管道编译上阻塞 队列时间线 工作。
Called on:GPUDevice
this.Arguments:
Arguments for the GPUDevice.createRenderPipelineAsync(descriptor) method. Parameter Type Nullable Optional Description descriptor
GPURenderPipelineDescriptor
✘ ✘ Description of the GPURenderPipeline
to create.Returns:
Promise
<GPURenderPipeline
>内容时间线 步骤:
-
让 contentTimeline 是当前的Content timeline。
-
让 promise 是一个新的 promise。
-
在 this 的 设备时间线 上发布 initialization steps。
-
返回 promise。
设备时间线 initialization steps:-
让 pipeline 成为一个新的
GPURenderPipeline
,就像调用 this.createRenderPipeline()
并使用 descriptor 一样; -
当 pipeline 准备好使用或者变为 无效 时,在 contentTimeline 上发出后续步骤。
内容时间线 步骤:-
如果 pipeline 为...
- 有效
-
将 pipeline 作为结果解决 promise。
- 无效 due to an internal error
-
拒绝 promise ,并使用
GPUPipelineError
,其中reason
为“internal”
。 - 无效 due to an validation error
-
拒绝 promise,并带有一个
GPUPipelineError
,其reason
为“validation”
。
-
Arguments:
-
GPURenderPipelineDescriptor
descriptor -
GPUPipelineLayout
layout -
GPUDevice
device
如果满足以下所有条件,则返回 true:
-
验证 GPUProgrammableStage(GPUShaderStage/VERTEX),使用 descriptor.GPURenderPipelineDescriptor/vertex 和 layout,操作成功。
-
验证 GPUVertexState(device, descriptor.GPURenderPipelineDescriptor/vertex, descriptor.GPURenderPipelineDescriptor/vertex) 操作成功。
-
如果提供了 descriptor.GPURenderPipelineDescriptor/fragment:
-
验证 GPUProgrammableStage(GPUShaderStage/FRAGMENT),使用 descriptor.GPURenderPipelineDescriptor/fragment 和 layout,操作成功。
-
[验证 GPUFragmentState](device, descriptor.GPURenderPipelineDescriptor/fragment) 操作成功。
-
如果 sample_mask 是 descriptor.GPURenderPipelineDescriptor/fragment 的 shader stage output:
-
descriptor.GPURenderPipelineDescriptor/multisample.GPUMultisampleState/alphaToCoverageEnabled 的值为
false
。
-
-
如果 frag_depth 是 descriptor.GPURenderPipelineDescriptor/fragment 的 shader stage output:
-
必须提供 descriptor.GPURenderPipelineDescriptor/depthStencil,并且 descriptor.GPURenderPipelineDescriptor/depthStencil.GPUDepthStencilState/format 必须具有一个 depth 层面。
-
-
-
验证 GPUPrimitiveState(descriptor.GPURenderPipelineDescriptor/primitive, device) 操作成功。
-
如果提供了 descriptor.GPURenderPipelineDescriptor/depthStencil:
-
[验证 GPUDepthStencilState](descriptor.GPURenderPipelineDescriptor/depthStencil) 操作成功。
-
-
验证 GPUMultisampleState(descriptor.GPURenderPipelineDescriptor/multisample) 操作成功。
-
如果 descriptor.GPURenderPipelineDescriptor/multisample.GPUMultisampleState/alphaToCoverageEnabled 的值为
true
:-
必须提供 descriptor.GPURenderPipelineDescriptor/fragment。
-
descriptor.GPURenderPipelineDescriptor/fragment.GPUFragmentState/targets[0] 必须存在且非空。
-
descriptor.GPURenderPipelineDescriptor/fragment.GPUFragmentState/targets[0].GPUColorTargetState/format 必须是具有 alpha 通道的 GPUTextureFormat。
-
-
必须存在至少一个附件,如下所示:
-
descriptor.GPURenderPipelineDescriptor/fragment.GPUFragmentState/targets 中的非
null
值,或者 -
descriptor.GPURenderPipelineDescriptor/depthStencil。
-
-
验证 inter-stage interfaces(device,descriptor)返回
真
。
Arguments:
-
GPUDevice
device -
GPURenderPipelineDescriptor
descriptor
Returns: boolean
-
令 maxVertexShaderOutputComponents 为 device.limits.
maxInterStageShaderComponents
.-
如果 descriptor.
primitive
.topology
为“point-list”
:-
maxVertexShaderOutputComponents 减 1。
-
-
-
如果不满足以下任一要求,则返回 false:
-
descriptor.
vertex
的所有用户自定义输出的标量组件总数不能超过 maxVertexShaderOutputComponents。 (例如,f32 输出占用1个组件,vec3输出占用3个组件。) -
descriptor.
vertex
的每个用户自定义输出的 location 必须 小于 device.limits.maxInterStageShaderVariables
.
-
-
-
令 maxFragmentShaderInputComponents 为 device.limits.
maxInterStageShaderComponents
. -
如果不满足以下任一要求,则返回 false:
-
descriptor.
fragment
的所有用户自定义输入的标量组件总数不能超过 maxFragmentShaderInputComponents。 -
对于 descriptor.
fragment
的每个用户自定义输入,descriptor.vertex
的用户自定义输出必须具有与输入相同的 location、类型和插值(interpolation)。
注:仅顶点的管道可以在顶点阶段具有用户自定义输出; 它们的值将被丢弃。
-
-
Assert descriptor.
fragment
的每个用户自定义输入的 location 小于 device.limits.maxInterStageShaderVariables
(由上述规则得到结果)
-
-
返回
true
。
GPURenderPipeline
:
const renderPipeline= gpuDevice. createRenderPipeline({ layout: pipelineLayout, vertex: { module: shaderModule, entryPoint: 'vertexMain' }, fragment: { module: shaderModule, entryPoint: 'fragmentMain' , targets: [{ format: 'bgra8unorm' , }], } });
10.3.2. 原始状态
dictionary {
GPUPrimitiveState GPUPrimitiveTopology topology = "triangle-list";GPUIndexFormat stripIndexFormat ;GPUFrontFace frontFace = "ccw";GPUCullMode cullMode = "none"; // Requires "depth-clip-control" feature.boolean unclippedDepth =false ; };
GPUPrimitiveState
具有以下成员,它们描述了GPURenderPipeline
如何从其顶点输入构造和光栅化图元:
topology
, of type GPUPrimitiveTopology, defaulting to"triangle-list"
-
要从顶点输入构造的图元类型。
stripIndexFormat
, of type GPUIndexFormat-
对于具有条带拓扑的管道 (
“line-strip”
或“triangle-strip”
), 这决定了索引缓冲格式和原始重启值 (“uint16”
/0xFFFF 或“uint32”
/0xFFFFFFFF)。 不允许在具有非条带拓扑的管道上使用。注:某些实现需要知道原始重启值以编译管道状态对象。
要将带有条带拓扑的管道与索引绘制调用一起使用 (
drawIndexed()
或drawIndexedIndirect()
), 必须设置这个值,并且它必须与绘制调用使用的索引缓冲格式匹配 (设置在setIndexBuffer()
中)。有关更多细节,请参阅§ 23.3.3 基本体部件。
frontFace
, of type GPUFrontFace, defaulting to"ccw"
-
定义哪些多边形被视为 front-facing。
cullMode
, of type GPUCullMode, defaulting to"none"
-
定义将剔除哪个多边形方向(如果有)。
unclippedDepth
, of type boolean, defaulting tofalse
-
如果为真,则表示 depth clipping 已禁用。
需要启用
"depth-clip-control"
功能。
-
GPUPrimitiveState
descriptor -
GPUDevice
device
如果满足以下所有条件返回 true
:
-
如果 descriptor .
topology
不是"line-strip"
或"triangle-strip"
:-
descriptor .
stripIndexFormat
不能是 provided。
-
-
如果 descriptor .
unclippedDepth
是true
:-
"depth-clip-control"
必须在 device 上已经 enabled for。
-
enum {
GPUPrimitiveTopology "point-list" ,"line-list" ,"line-strip" ,"triangle-list" ,"triangle-strip" };
GPUPrimitiveTopology
定义使用 GPURenderPipeline
进行的原始类型绘制调用。 有关更多详细信息,请参见 § 23.3.5 光栅化:
"point-list"
-
每个顶点定义一个点基元。
"line-list"
-
每对连续的两个顶点定义一个线基元。
"line-strip"
-
每对连续的两个顶点定义一个线图元。第一个顶点之后的每个顶点定义它和前一个顶点之间的线图元。
"triangle-list"
-
三个顶点的每个连续三元组定义一个三角形基元。
"triangle-strip"
-
前两个顶点之后的每个顶点在它和前两个顶点之间定义一个三角形基元。
enum {
GPUFrontFace "ccw" ,"cw" };
GPUFrontFace
定义哪些多边形被 GPURenderPipeline
视为 front-facing。
有关更多详细信息,请参见 § 23.3.5.4 多边形光栅化:
"ccw"
-
顶点的帧缓冲区坐标按逆时针顺序给出的多边形被认为是 front-facing。
"cw"
-
顶点的帧缓冲区坐标按顺时针顺序给出的多边形被认为是 front-facing。
enum {
GPUCullMode "none" ,"front" ,"back" };
GPUPrimitiveTopology
定义哪些多边形将被使用 GPURenderPipeline
进行的绘制调用剔除。 有关更多详细信息,请参见 § 23.3.5.4 多边形光栅化:
"none"
-
没有多边形被丢弃。
"front"
-
Front-facing 多边形被丢弃。
"back"
-
Back-facing 多边形被丢弃。
注:GPUFrontFace
和 GPUCullMode
对 "point-list"
、"line-list"
或 "line-strip"
拓扑没有影响。
10.3.3. 多样本状态
dictionary {
GPUMultisampleState GPUSize32 count = 1;GPUSampleMask mask = 0xFFFFFFFF;boolean alphaToCoverageEnabled =false ; };
GPUMultisampleState
具有以下成员,这些成员描述了GPURenderPipeline
如何与渲染传递的多重采样附件进行交互。
count
, of type GPUSize32, defaulting to1
-
每像素的样本数量。这个
GPURenderPipeline
只与具有匹配sampleCount
的附件纹理(colorAttachments
和depthStencilAttachment
)兼容。 mask
, of type GPUSampleMask, defaulting to0xFFFFFFFF
-
掩码确定要写入的样本。
alphaToCoverageEnabled
, of type boolean, defaulting tofalse
-
当
true
表示应使用片段的 alpha 通道生成样本覆盖遮罩。
-
GPUMultisampleState
descriptor
如果满足以下所有条件,则返回 true
:
-
如果 descriptor.
alphaToCoverageEnabled
为true
:-
descriptor.
count
> 1.
-
10.3.4. 片元状态
dictionary :
GPUFragmentState GPUProgrammableStage {required sequence <GPUColorTargetState ?>; };
targets
GPUDevice
device, GPUFragmentState
descriptor)
如果满足以下所有要求,则返回 true
:
-
descriptor.
targets
.length 必须 &le; device.[[limits]]
.maxColorAttachments
。 -
对于每一个 descriptor.
targets
的 indices 的 index 包含非空值 colorState:-
colorState.
format
必须在 § 26.1.1 纯彩色格式 中列出 具有RENDER_ATTACHMENT
功能。 -
如果 colorState.
blend
是 provided 的:-
colorState.
blend
.color
必须是一个 valid GPUBlendComponent。 -
colorState.
blend
.alpha
必须是一个 valid GPUBlendComponent。
-
colorState.
writeMask
必须 < 16。 -
如果 descriptor.
entryPoint
具有 location 属性 等于 index 的 shader stage output 值 output:-
对于 colorState.
format
中的每个组件,必须在 output 中有一个 对应的组件。 (即,RGBA 需要 vec4,RGB 需要 vec3 或 vec4,RG 需要 vec2 或 vec3 或 vec4。) -
如果 colorState.
blend
是 provided 的 colorState.blend
.color
.srcFactor
或 .dstFactor
使用源 alpha (是“src-alpha”
的任何一个, 或“one-minus-src-alpha”
, 或“src-alpha-saturated”
),那么:-
output 必须具有 alpha 通道 (即,它必须是一个 vec4)。 否则,因为没有 shader 输出用于 attachment:
-
-
colorState.
writeMask
必须为 0。
-
-
-
在 device 和 descriptor.
targets
上执行 Validating GPUFragmentState’s color attachment bytes per sample 成功。
GPUDevice
device, sequence<GPUColorTargetState
?> targets)
-
让 formats 成为空的 list<
GPUTextureFormat
?> -
对于 targets 中的每个 target:
-
计算每个采样的颜色附件字节数 必须 ≤ device.
[[limits]]
.maxColorAttachmentBytesPerSample
。
Note: 注: 片元着色器输出的值可能比管线使用的值多。如果出现这种情况,多余的值将被忽略。
10.3.5. 颜色目标状态
dictionary {
GPUColorTargetState required GPUTextureFormat ;
format GPUBlendState ;
blend GPUColorWriteFlags = 0xF; // GPUColorWrite.ALL };
writeMask
dictionary {
GPUBlendState required GPUBlendComponent ;
color required GPUBlendComponent ; };
alpha
typedef [EnforceRange ]unsigned long ; [
GPUColorWriteFlags Exposed =(Window ,DedicatedWorker ),SecureContext ]namespace {
GPUColorWrite const GPUFlagsConstant = 0x1;
RED const GPUFlagsConstant = 0x2;
GREEN const GPUFlagsConstant = 0x4;
BLUE const GPUFlagsConstant = 0x8;
ALPHA const GPUFlagsConstant = 0xF; };
ALL
10.3.5.1. 混合状态
dictionary {
GPUBlendComponent GPUBlendOperation operation = "add";GPUBlendFactor srcFactor = "one";GPUBlendFactor dstFactor = "zero"; };
GPUBlendComponent
有以下成员,它们描述了片段的颜色或 alpha 分量是如何混合的:
operation
, of type GPUBlendOperation, defaulting to"add"
-
定义用于计算写入目标附件组件的值的
GPUBlendOperation
。 srcFactor
, of type GPUBlendFactor, defaulting to"one"
-
定义要对来自片段着色器的值执行的
GPUBlendFactor
操作。 dstFactor
, of type GPUBlendFactor, defaulting to"zero"
-
定义要对目标附件中的值执行的
GPUBlendFactor
操作。
下表使用此表示法来描述给定片段位置的颜色分量:
RGBAsrc
| Color output by the fragment shader for the color attachment. 如果着色器不返回 alpha 通道,则不能使用 src-alpha 混合因子。 |
RGBAdst
| Color currently in the color attachment. 缺少绿色/蓝色/alpha 通道分别默认为“0、0、1”。 |
RGBAconst
| 当前 [[blendConstant]] .
|
RGBAsrcFactor
| 源混合因子组件,由 srcFactor 定义。
|
RGBAdstFactor
| 目标混合因子组件,由 dstFactor 定义。
|
enum {
GPUBlendFactor "zero" ,"one" ,"src" ,"one-minus-src" ,"src-alpha" ,"one-minus-src-alpha" ,"dst" ,"one-minus-dst" ,"dst-alpha" ,"one-minus-dst-alpha" ,"src-alpha-saturated" ,"constant" ,"one-minus-constant" };
GPUBlendFactor
定义了源或目标混合因子的计算方法:
GPUBlendFactor | Blend factor RGBA components |
---|---|
"zero"
| (0, 0, 0, 0)
|
"one"
| (1, 1, 1, 1)
|
"src"
| (Rsrc, Gsrc, Bsrc, Asrc)
|
"one-minus-src"
| (1 - Rsrc, 1 - Gsrc, 1 - Bsrc, 1 - Asrc)
|
"src-alpha"
| (Asrc, Asrc, Asrc, Asrc)
|
"one-minus-src-alpha"
| (1 - Asrc, 1 - Asrc, 1 - Asrc, 1 - Asrc)
|
"dst"
| (Rdst, Gdst, Bdst, Adst)
|
"one-minus-dst"
| (1 - Rdst, 1 - Gdst, 1 - Bdst, 1 - Adst)
|
"dst-alpha"
| (Adst, Adst, Adst, Adst)
|
"one-minus-dst-alpha"
| (1 - Adst, 1 - Adst, 1 - Adst, 1 - Adst)
|
"src-alpha-saturated"
| (min(Asrc, 1 - Adst), min(Asrc, 1 - Adst), min(Asrc, 1 - Adst), 1)
|
"constant"
| (Rconst, Gconst, Bconst, Aconst)
|
"one-minus-constant"
| (1 - Rconst, 1 - Gconst, 1 - Bconst, 1 - Aconst)
|
enum {
GPUBlendOperation "add" ,"subtract" ,"reverse-subtract" ,"min" ,"max" };
GPUBlendOperation
定义用于组合源和目标混合因子的算法:
GPUBlendOperation | RGBA Components |
---|---|
"add"
| RGBAsrc × RGBAsrcFactor + RGBAdst × RGBAdstFactor
|
"subtract"
| RGBAsrc × RGBAsrcFactor - RGBAdst × RGBAdstFactor
|
"reverse-subtract"
| RGBAdst × RGBAdstFactor - RGBAsrc × RGBAsrcFactor
|
"min"
| min(RGBAsrc, RGBAdst)
|
"max"
| max(RGBAsrc, RGBAdst)
|
10.3.6. 深度/模板状态
dictionary {
GPUDepthStencilState required GPUTextureFormat format ;required boolean depthWriteEnabled ;required GPUCompareFunction depthCompare ;GPUStencilFaceState stencilFront = {};GPUStencilFaceState stencilBack = {};GPUStencilValue stencilReadMask = 0xFFFFFFFF;GPUStencilValue stencilWriteMask = 0xFFFFFFFF;GPUDepthBias depthBias = 0;float depthBiasSlopeScale = 0;float depthBiasClamp = 0; };
GPUDepthStencilState
具有以下成员,描述了 GPURenderPipeline
将如何影响渲染过程的 depthStencilAttachment
:
format
, of type GPUTextureFormat-
此
GPURenderPipeline
将与depthStencilAttachment
的format
兼容。 depthWriteEnabled
, of type boolean-
指示这个
GPURenderPipeline
是否可以修改depthStencilAttachment
深度值。 depthCompare
, of type GPUCompareFunction-
用于测试片元深度与
depthStencilAttachment
深度值的比较操作。 stencilFront
, of type GPUStencilFaceState, defaulting to{}
-
定义了如何为朝前的图元执行模板比较和操作。
stencilBack
, of type GPUStencilFaceState, defaulting to{}
-
定义了如何为朝后的图元执行模板比较和操作。
stencilReadMask
, of type GPUStencilValue, defaulting to0xFFFFFFFF
-
掩码控制在执行模板比较测试时读取哪些
depthStencilAttachment
模板值位。 stencilWriteMask
, of type GPUStencilValue, defaulting to0xFFFFFFFF
-
Bitmask controlling which
depthStencilAttachment
stencil value bits are written to when performing stencil operations. depthBias
, of type GPUDepthBias, defaulting to0
-
添加到每个片元的恒定深度偏差。有关详细信息,请参阅 biased fragment depth。
depthBiasSlopeScale
, of type float, defaulting to0
-
与片元的斜率成比例的深度偏差。有关详细信息,请参阅 biased fragment depth。
depthBiasClamp
, of type float, defaulting to0
-
片元的最大深度偏差。有关详细信息,请参阅 biased fragment depth。
depthStencilAttachment
附件 的片段,当使用 GPUDepthStencilState
状态 绘制时,biased fragment depth 的计算过程为:
-
设 r 为在转换为32位浮点值时 格式 中最小的正可表示值(大于 0)。
-
设 maxDepthSlope 为片段深度值的水平和垂直斜率中的最大值。
-
如果 format 是 unorm 格式:
-
设 bias 为
(float)状态.
.depthBias
* r + state.depthBiasSlopeScale
* maxDepthSlope
-
-
否则,如果 format 是一个 float 格式:
-
设 bias 为
(float)状态.
。depthBias
* 2^(exp(原始最大深度) - r) + state.depthBiasSlopeScale
* maxDepthSlope
-
-
如果 state.
depthBiasClamp
> 0:-
将 bias 设置为
min(状态.
。depthBiasClamp
, bias)
-
-
否则,如果 state.
depthBiasClamp
< 0:-
将 bias 设置为
max(状态.
。depthBiasClamp
, bias)
-
-
如果 state.
depthBias
≠ 0 或者 state.depthBiasSlopeScale
≠ 0:-
将片元深度值设置为
片段深度值 + bias
-
Arguments:
-
GPUDepthStencilState
descriptor
只有当满足以下所有条件时,返回 true
:
-
descriptor.
format
是一个 depth-or-stencil format. -
如果 descriptor.
depthWriteEnabled
是true
或者 descriptor.depthCompare
不是"always"
:-
descriptor.
format
必须要有一个 depth 分量。
-
-
如果 descriptor.
stencilFront
或者 descriptor.stencilBack
不是默认值:-
descriptor.
format
必须要有一个 stencil 分量。
-
问题:这个算法可以如何支持在扩展中添加的 depth/stencil 格式?
dictionary {
GPUStencilFaceState GPUCompareFunction compare = "always";GPUStencilOperation failOp = "keep";GPUStencilOperation depthFailOp = "keep";GPUStencilOperation passOp = "keep"; };
GPUStencilFaceState
具有以下成员,它们描述了模板比较和操作是如何执行的:
compare
, of type GPUCompareFunction, defaulting to"always"
-
在测试片元与
depthStencilAttachment
模板值时使用的GPUCompareFunction
。 failOp
, of type GPUStencilOperation, defaulting to"keep"
-
如果片元模板比较测试(由
compare
描述)失败,则执行的GPUStencilOperation
。 depthFailOp
, of type GPUStencilOperation, defaulting to"keep"
-
如果由
depthCompare
描述的片元深度比较失败,则执行的GPUStencilOperation
。 passOp
, of type GPUStencilOperation, defaulting to"keep"
-
如果片元模板比较测试通过,则执行由
compare
描述的GPUStencilOperation
。
enum {
GPUStencilOperation "keep" ,"zero" ,"replace" ,"invert" ,"increment-clamp" ,"decrement-clamp" ,"increment-wrap" ,"decrement-wrap" };
GPUStencilOperation
定义了以下操作:
"keep"
-
保持当前模板值。
"zero"
-
将模板值设置为“0”。
"replace"
-
将模板值设置为
[[stencilReference]]
。 "invert"
-
按位反转当前模板值。
"increment-clamp"
-
增加当前模板值,限制为
depthStencilAttachment
模板方面的最大可表示值。 "decrement-clamp"
-
减少当前模板值,钳位到
0
。 "increment-wrap"
-
将当前模板值递增,如果该值超过了
depthStencilAttachment
的模板方面可以表示的最大值,则将其回绕至零。 "decrement-wrap"
-
将当前模板值递减,如果该值低于
0
则回绕到depthStencilAttachment
的模板方面的最大可表示值。
10.3.7. 顶点状态
enum {
GPUIndexFormat "uint16" ,"uint32" };
索引格式决定了缓冲区中索引值的数据类型,以及在带strip原语拓扑结构 (“line-strip”
或 “triangle-strip”
) 中使用时指定原语重启值。原语重启值指示哪个索引值表示应开始新的原语,而不是继续使用之前索引的顶点构建三角形条带。
指定strip原语拓扑结构的GPUPrimitiveState
必须在用于索引绘制时指定stripIndexFormat
,以便在管道创建时知道将用于重启的primitive restart value。指定列表原语拓扑结构的GPUPrimitiveState
将在进行索引渲染时使用传递给 setIndexBuffer()
的索引格式。
Index format | Byte size | Primitive restart value |
---|---|---|
"uint16"
| 2 | 0xFFFF |
"uint32"
| 4 | 0xFFFFFFFF |
10.3.7.1. 顶点格式
顶点属性的GPUVertexFormat
指示如何从顶点缓冲区解释数据并将其暴露给着色器。格式名称指定组件的顺序,每个组件的位数以及组件的顶点数据类型。
每个顶点数据类型都可以映射到具有相同基本类型的任何WGSL标量类型,而无论组件的位数如何:
Vertex format prefix | Vertex data type | Compatible WGSL types |
---|---|---|
uint
| unsigned int | u32
|
sint
| signed int | i32
|
unorm
| unsigned normalized | f16 , f32
|
snorm
| signed normalized | |
float
| floating point |
多组件格式在“x”后指定组件的数量。顶点格式和着色器类型之间的组件数量不匹配是允许的,通过丢弃组件或填充默认值来进行补偿。
“unorm8x2”
格式和字节值 [0x7F, 0xFF]
,可以通过以下类型在着色器中访问:
Shader type | Shader value |
---|---|
f16
| 0.5h
|
f32
| 0.5f
|
vec2<f16>
| vec2(0.5h, 1.0h)
|
vec2<f32>
| vec2(0.5f, 1.0f)
|
vec3<f16>
| vec2(0.5h, 1.0h, 0.0h)
|
vec3<f32>
| vec2(0.5f, 1.0f, 0.0f)
|
vec4<f16>
| vec2(0.5h, 1.0h, 0.0h, 1.0h)
|
vec4<f32>
| vec2(0.5f, 1.0f, 0.0f, 1.0f)
|
请参阅§ 23.3.2 顶点处理以获取关于如何在着色器中显示顶点格式的更多信息。
enum {
GPUVertexFormat "uint8x2" ,"uint8x4" ,"sint8x2" ,"sint8x4" ,"unorm8x2" ,"unorm8x4" ,"snorm8x2" ,"snorm8x4" ,"uint16x2" ,"uint16x4" ,"sint16x2" ,"sint16x4" ,"unorm16x2" ,"unorm16x4" ,"snorm16x2" ,"snorm16x4" ,"float16x2" ,"float16x4" ,"float32" ,"float32x2" ,"float32x3" ,"float32x4" ,"uint32" ,"uint32x2" ,"uint32x3" ,"uint32x4" ,"sint32" ,"sint32x2" ,"sint32x3" ,"sint32x4" };
Vertex format | Data type | Components | Byte size | Example WGSL type |
---|---|---|---|---|
"uint8x2"
| unsigned int | 2 | 2 | vec2<u32>
|
"uint8x4"
| unsigned int | 4 | 4 | vec4<u32>
|
"sint8x2"
| signed int | 2 | 2 | vec2<i32>
|
"sint8x4"
| signed int | 4 | 4 | vec4<i32>
|
"unorm8x2"
| unsigned normalized | 2 | 2 | vec2<f32>
|
"unorm8x4"
| unsigned normalized | 4 | 4 | vec4<f32>
|
"snorm8x2"
| signed normalized | 2 | 2 | vec2<f32>
|
"snorm8x4"
| signed normalized | 4 | 4 | vec4<f32>
|
"uint16x2"
| unsigned int | 2 | 4 | vec2<u32>
|
"uint16x4"
| unsigned int | 4 | 8 | vec4<u32>
|
"sint16x2"
| signed int | 2 | 4 | vec2<i32>
|
"sint16x4"
| signed int | 4 | 8 | vec4<i32>
|
"unorm16x2"
| unsigned normalized | 2 | 4 | vec2<f32>
|
"unorm16x4"
| unsigned normalized | 4 | 8 | vec4<f32>
|
"snorm16x2"
| signed normalized | 2 | 4 | vec2<f32>
|
"snorm16x4"
| signed normalized | 4 | 8 | vec4<f32>
|
"float16x2"
| float | 2 | 4 | vec2<f16>
|
"float16x4"
| float | 4 | 8 | vec4<f16>
|
"float32"
| float | 1 | 4 | f32
|
"float32x2"
| float | 2 | 8 | vec2<f32>
|
"float32x3"
| float | 3 | 12 | vec3<f32>
|
"float32x4"
| float | 4 | 16 | vec4<f32>
|
"uint32"
| unsigned int | 1 | 4 | u32
|
"uint32x2"
| unsigned int | 2 | 8 | vec2<u32>
|
"uint32x3"
| unsigned int | 3 | 12 | vec3<u32>
|
"uint32x4"
| unsigned int | 4 | 16 | vec4<u32>
|
"sint32"
| signed int | 1 | 4 | i32
|
"sint32x2"
| signed int | 2 | 8 | vec2<i32>
|
"sint32x3"
| signed int | 3 | 12 | vec3<i32>
|
"sint32x4"
| signed int | 4 | 16 | vec4<i32>
|
enum {
GPUVertexStepMode "vertex" ,"instance" };
步进模式配置如何基于当前顶点或实例索引计算顶点缓冲数据的地址:
"vertex"
-
地址根据每个顶点的
arrayStride
进行递增,并在实例之间重置。 "instance"
-
地址对于每个实例会根据
arrayStride
进行增加。
dictionary :
GPUVertexState GPUProgrammableStage {sequence <GPUVertexBufferLayout ?>= []; };
buffers
一个顶点缓冲区在概念上是一个缓冲区内存的视图,作为一个结构数组。 arrayStride
是该数组元素之间的字节跨度。
顶点缓冲区的每个元素都类似于一个具有由其 attributes
定义的内存布局的结构,该布局描述结构的元素。
每个 GPUVertexAttribute
都描述了其 format
以及其在结构中的 offset
,按字节为单位。
每个属性在顶点着色器中都作为单独的输入,每个输入都由数字 location 绑定,location 由 shaderLocation
指定。 GPUVertexState
中的每个 location 都必须是唯一的。
dictionary {
GPUVertexBufferLayout required GPUSize64 arrayStride ;GPUVertexStepMode stepMode = "vertex";required sequence <GPUVertexAttribute >attributes ; };
arrayStride
, of type GPUSize64-
此数组元素之间的跨度(以字节为单位)。
stepMode
, of type GPUVertexStepMode, defaulting to"vertex"
-
该数组的每个元素表示每个顶点数据还是每个实例数据
attributes
, of type sequence<GPUVertexAttribute>-
定义每个元素内顶点属性布局的数组。
dictionary {
GPUVertexAttribute required GPUVertexFormat format ;required GPUSize64 offset ;required GPUIndex32 shaderLocation ; };
format
, of type GPUVertexFormat-
属性的
GPUVertexFormat
。 offset
, of type GPUSize64-
从元素开头到属性数据的偏移量(以字节为单位)。
shaderLocation
, of type GPUIndex32-
与此属性关联的数字位置,将对应于在
vertex
.module
中声明的 "@location" 属性。
Arguments:
-
GPUDevice
device -
GPUVertexBufferLayout
descriptor -
GPUProgrammableStage
vertexStage
仅当满足以下所有条件时返回 true
:
-
descriptor.
arrayStride
≤ device.[[device]]
.[[limits]]
.maxVertexBufferArrayStride
。 -
descriptor.
arrayStride
是 4 的倍数。 -
对于列表 descriptor.
attributes
中的每个属性 attrib:-
如果 descriptor.
arrayStride
为零:-
attrib.
offset
+ sizeof(attrib.format
) ≤ device.[[device]]
.[[limits]]
.maxVertexBufferArrayStride
。
否则:
-
attrib.
offset
+ sizeof(attrib.format
) ≤ descriptor.arrayStride
。
-
-
attrib.
shaderLocation
是 < device.[[device]]
.[[limits]]
.maxVertexAttributes
。
-
-
对于 vertexStage 静态使用 的每个顶点属性 var, 应有一个与 descriptor.
attributes
的 attrib 元素相对应,且满足以下所有条件:-
变量 T 的类型与 attrib.
format
的 vertex data type 兼容:-
:“unorm”,“snorm” 或 “float” :: T 必须是 f32 或 vecN
。 :“uint” :: T 必须是 u32 或 vecN 。 :“sint” :: T 必须是 i32 或 vecN 。 -
着色器位置是 attrib.
shaderLocation
.
-
Arguments:
-
GPUDevice
device -
GPUVertexState
descriptor
返回 true
,当且仅当满足以下所有条件:
-
descriptor.
buffers
.length ≤ device.[[device]]
.[[limits]]
.maxVertexBuffers
. -
列表 descriptor.
buffers
中的每个 vertexBuffer 布局描述符 通过 validating GPUVertexBufferLayout(device, vertexBuffer, descriptor) -
对所有 vertexBuffer 的 vertexBuffer.
attributes
.length 求和,在 descriptor.buffers
中, ≤ device.[[device]]
.[[limits]]
.maxVertexAttributes
. -
在 descriptor.
buffers
中的所有GPUVertexAttribute
的并集中,每个 attrib 都具有一个独特的 attrib.shaderLocation
值。
11. 副本
11.1. 缓冲副本
缓冲区复制操作操作原始字节。
WebGPU 提供 "缓冲" 的 GPUCommandEncoder
命令:
还有 “即时” GPUQueue
操作:
-
writeBuffer()
, 用于ArrayBuffer
到GPUBuffer
的写入
11.2. 图片副本
WebGPU 为 GPUCommandEncoder
命令提供了“缓冲”:
以及“即时”GPUQueue
操作:
-
writeTexture()
, 用于ArrayBuffer
到GPUTexture
的写入 -
copyExternalImageToTexture()
, 用于从 Web 平台图像源到纹理的复制
有些像素值具有多种可能的表示形式,例如,作为 r8snorm,-1.0 可以表示为 -127 或 -128。复制命令不能保证保留源的位表示。
以下定义由这些方法使用。
11.2.1. GPUImageDataLayout
dictionary GPUImageDataLayout {GPUSize64 offset = 0;GPUSize32 bytesPerRow ;GPUSize32 rowsPerImage ; };
GPUImageDataLayout
是线性内存中 图像 的布局。
在将数据从 纹理 复制到 GPUBuffer
之间,或是安排从 GPUQueue
中写入 texture 时使用。
问题:更精确地定义图像。特别是将它们定义为由 纹素块 组成。
在字节数组和纹理之间复制的操作始终处理 纹素块 的行,我们将其称为 块行。不可能仅更新 纹素块 的一部分。
在图像复制的线性内存布局中,每个 块行 内的 纹素块 紧密排列,每个随后的 texel block 紧跟在前一个 texel block 后面,没有填充。 这包括将 depth-or-stencil format 纹理的特定方面进行复制: 模具值紧密包装在一组字节中; 深度值紧密包装在适当类型的数组中(“depth16unorm”或“depth32float”)。
问题:通过引用复制方法共享的常见算法来定义确切的复制语义。
offset
, of type GPUSize64, defaulting to0
-
偏移量(以字节为单位),从图像数据源(如
GPUImageCopyBuffer.buffer
)的开头到该源内图像数据开始的偏移量。 bytesPerRow
, of type GPUSize32-
如果有多个块行(即,复制高度或深度大于一个块),则需要。
rowsPerImage
, of type GPUSize32-
图像数量块行每个纹理的单个图像。
rowsPerImage
×bytesPerRow
是数据的每个 图像 之间和后续图像之间的字节间距。如果有多个 图像(即复制深度大于1),则需要。
11.2.2. GPUImageCopyBuffer
在image copy操作中,GPUImageCopyBuffer
定义了一个GPUBuffer
,并结合 copySize
,说明了图像数据如何在缓冲区的内存中布局(参见GPUImageDataLayout
)。
dictionary GPUImageCopyBuffer :GPUImageDataLayout {required GPUBuffer buffer ; };
buffer
, of type GPUBuffer-
一个缓冲区,它可以包含要复制的图像数据,也可以存储正在复制的图像数据,具体取决于传递给它的方法。
Arguments:
-
GPUImageCopyBuffer
imageCopyBuffer
Returns: boolean
当且仅当满足以下所有条件时返回 true
:
-
imageCopyBuffer.
bytesPerRow
必须是256的倍数。
11.2.3. GPUImageCopyTexture
在image copy操作中,GPUImageCopyTexture
定义了一个 GPUTexture
,并与 copySize 一起定义了纹理的子区域(跨一个或多个连续的 纹理子资源,在相同的 mip-map 级别上)。
dictionary GPUImageCopyTexture {required GPUTexture texture ;GPUIntegerCoordinate mipLevel = 0;GPUOrigin3D origin = {};GPUTextureAspect aspect = "all"; };
texture
, of type GPUTexture-
要复制到/从中复制的纹理。
mipLevel
, of type GPUIntegerCoordinate, defaulting to0
-
要复制到/从中复制的
texture
的 Mip-map 级别。 origin
, of type GPUOrigin3D, defaulting to{}
-
定义复制的起点 - 将要复制到/从的纹理子区域的最小角。与
copySize
一起, 定义完整的复制子区域。 aspect
, of type GPUTextureAspect, defaulting to"all"
-
定义从
texture
复制到/从哪些方面的内容。
Arguments:
-
GPUImageCopyTexture
imageCopyTexture -
GPUExtent3D
copySize
Returns: boolean
-
令 blockWidth 为 imageCopyTexture .
texture
.format
的 texel block width。 -
令 blockHeight 为 imageCopyTexture .
texture
.format
的 texel block height。 -
当且仅当满足以下所有条件时返回 true:
-
imageCopyTexture .
texture
必须是一个 validGPUTexture
。 -
imageCopyTexture.
mipLevel
必须小于 imageCopyTexture.texture
.mipLevelCount
。 -
如果满足以下任一条件,imageCopyTexture 的 imageCopyTexture subresource size 等于 copySize:
-
imageCopyTexture.
texture
.sampleCount
> 1。
-
问题(gpuweb/gpuweb#69):定义具有1d
和3d
纹理的副本。
11.2.4. GPUImageCopyTextureTagged
WebGPU 纹理包含原始数值数据,不带有描述颜色的语义元数据。然而,copyExternalImageToTexture()
从描述颜色的资源中复制。
GPUImageCopyTextureTagged
是一个带有颜色空间/编码和 alpha 预乘元数据的 GPUImageCopyTexture
,这样语义颜色数据在复制过程中可以保留。这个元数据仅影响 copyExternalImageToTexture()
操作的语义,而不影响目标纹理的语义。
dictionary GPUImageCopyTextureTagged :GPUImageCopyTexture {PredefinedColorSpace colorSpace = "srgb";boolean premultipliedAlpha =false ; };
colorSpace
, of type PredefinedColorSpace, defaulting to"srgb"
-
描述用于将数据编码到目标纹理中的颜色空间和编码方式。
这 可能导致 在范围 [0, 1] 之外的值 被写入目标纹理, 如果其格式可以表示它们。 否则,结果将被截断到目标纹理格式的范围。
注意: 如果
colorSpace
与源图像相匹配, 则可能不需要转换。请参见§ 3.10.2 色彩空间转换省略。 premultipliedAlpha
, of type boolean, defaulting tofalse
-
描述数据写入纹理时,是否应该将其 RGB 通道预先乘以 alpha 通道。
如果此选项设置为
true
,并且source
也预先乘以 alpha,则即使源 RGB 值超过其相应的 alpha 值,也必须保留这些值。注意: 如果
premultipliedAlpha
与源图像匹配,则可能不需要进行转换。请参阅§ 3.10.2 色彩空间转换省略。
11.2.5. GPUImageCopyExternalImage
dictionary GPUImageCopyExternalImage {required (ImageBitmap or HTMLVideoElement or HTMLCanvasElement or OffscreenCanvas )source ;GPUOrigin2D origin = {};boolean flipY =false ; };
GPUImageCopyExternalImage
has the following members:
source
, of type(ImageBitmap or HTMLVideoElement or HTMLCanvasElement or OffscreenCanvas)
-
image copy的来源。在发出
copyExternalImageToTexture()
时捕获复制源数据。来源大小由来源类型定义,如下表所示: origin
, of type GPUOrigin2D, defaulting to{}
-
定义副本的来源 - 要从中复制的源子区域的最小(左上)角。 结合
copySize
,定义完整的复制子区域。 flipY
, of type boolean, defaulting tofalse
-
描述源图像是否垂直翻转。
如果此选项设置为
true
,副本将垂直翻转:源区域的底部行被复制到目标区域的第一行,依此类推。origin
选项仍然相对于源图像的左上角,向下增加。
11.2.6. Subroutines
Arguments:
-
GPUImageCopyTexture
imageCopyTexture
Returns: GPUExtent3D
imageCopyTexture 的 imageCopyTexture 子资源大小 计算如下:
其 width、height 和 depthOrArrayLayers 分别是 imageCopyTexture 的宽度、高度和深度,对应于 imageCopyTexture.texture
子资源 在 mipmap 级别 imageCopyTexture.mipLevel
的 物理 miplevel 特定纹理范围。
Arguments:
GPUImageDataLayout
layout-
线性纹理数据的布局。
GPUSize64
byteSize-
线性数据的总大小,以字节为单位。
GPUTextureFormat
format-
纹理的格式。
GPUExtent3D
copyExtent-
要复制的纹理范围。
-
让:
-
widthInBlocks 是 copyExtent.width 除以 format 的 texel block width。Assert 这是一个整数。
-
heightInBlocks 是 copyExtent.height 除以 format 的 texel block height。Assert 这是一个整数。
-
bytesInLastRow 是 widthInBlocks 乘以 format 的 texel block copy footprint。
-
-
如果以下输入验证要求不满足,则失败:
-
如果 heightInBlocks > 1,那么必须指定 layout.
bytesPerRow
。 -
如果 copyExtent.depthOrArrayLayers > 1,那么必须指定 layout.
bytesPerRow
和 layout.rowsPerImage
。 -
如果指定了 layout.
bytesPerRow
,那么它必须大于等于 bytesInLastRow。 -
如果指定了 layout.
rowsPerImage
,那么它必须大于等于 heightInBlocks。
-
-
让:
-
bytesPerRow 是 layout.
bytesPerRow
??0。 -
rowsPerImage 是 layout.
rowsPerImage
??0。
注意:这些默认值没有效果,因为它们总是乘以0。
-
-
让 requiredBytesInCopy 等于 0。
-
如果 copyExtent.depthOrArrayLayers > 0:
-
使 requiredBytesInCopy 增加 bytesPerRow 乘以 rowsPerImage 乘以 (copyExtent.depthOrArrayLayers - 1)。
-
如果 heightInBlocks > 0:
-
使 requiredBytesInCopy 增加 bytesPerRow 乘以 (heightInBlocks - 1) + bytesInLastRow。
-
-
-
如果以下条件不满足,则失败:
-
布局适应线性数据:layout.
offset
+ requiredBytesInCopy ≤ byteSize。
-
Arguments:
GPUImageCopyTexture
imageCopyTexture-
复制到的纹理子资源和复制起点。
GPUExtent3D
copySize-
纹理的大小。
-
让 blockWidth 是 imageCopyTexture 的 texel block width。
texture
.format
. -
让 blockHeight 是 imageCopyTexture 的 texel block height。
texture
.format
. -
让 subresourceSize 是 imageCopyTexture 的 imageCopyTexture subresource size。
-
如果满足以下所有条件,则返回:
-
(imageCopyTexture.
origin
.x + copySize.width) ≤ subresourceSize.width -
(imageCopyTexture.
origin
.y + copySize.height) ≤ subresourceSize.height -
(imageCopyTexture.
origin
.z + copySize.depthOrArrayLayers) ≤ subresourceSize.depthOrArrayLayers -
copySize.width 必须是 blockWidth 的倍数。
-
copySize.height 必须是 blockHeight 的倍数。
-
GPUTextureFormat
format1 和 format2 是 兼容复制 的如果:
-
format1 等于 format2,或者
-
format1 和 format2 之间的差异仅在于它们是否为
srgb
格式(具有-srgb
后缀)。
texture
的子资源的子集:
-
s的mipmap level等于imageCopyTexture.
mipLevel
。 -
s的aspect在imageCopyTexture.
aspect
的set of aspects中。 -
-
s的array layer ≥ imageCopyTexture.
origin
.z且 < imageCopyTexture.origin
.z + copySize.depthOrArrayLayers。
-
12. 命令缓冲区
命令缓冲区是可以提交给GPUQueue
执行的预先记录的GPU命令列表。
每个GPU命令代表在GPU上要执行的任务,例如设置状态,绘制,复制资源等。
一个GPUCommandBuffer
只能提交一次,提交后它会变为无效。 要在多个提交中重复使用渲染命令,请使用GPURenderBundle
。
12.1. GPUCommandBuffer
[Exposed =(Window ,DedicatedWorker ),SecureContext ]interface GPUCommandBuffer { };GPUCommandBuffer includes GPUObjectBase ;
GPUCommandBuffer
具有以下内部插槽:
[[command_list]]
, of type list<GPU command>-
要在提交此命令缓冲区时在 Queue timeline 上执行的 GPU commands 列表。
[[renderState]]
, of type RenderState-
当前由任何正在执行的渲染通道命令使用的状态,初始值为
null
。
12.1.1. 命令缓冲区创建
dictionary :
GPUCommandBufferDescriptor GPUObjectDescriptorBase { };
13. 命令编码
13.1. GPUCommandsMixin
GPUCommandsMixin
定义了所有编码命令接口的公共状态。它没有方法。
interface mixin GPUCommandsMixin { };
GPUCommandsMixin
将以下内部插槽添加到包含它的接口中:
[[state]]
, 类型为 encoder state-
当前编码器的状态,初始设置为“open”。
[[commands]]
, of type list<GPU command>-
要在包含这些命令的
GPUCommandBuffer
提交时在队列时间线上执行的GPU command列表。
- "open"
-
编码器可以用来编码新的命令。
- "locked"
-
编码器无法使用,因为它被子编码器锁定:它是一个
GPUCommandEncoder
,并且GPURenderPassEncoder
或GPUComputePassEncoder
是活动的。 当 pass 结束时,编码器再次变为"open"。在此状态下发出的任何命令都会使编码器 无效。
- "ended"
-
编码器已经结束,无法再对新命令进行编码。
在此状态下发出的所有命令都将产生验证错误。
GPUCommandsMixin
encoder 上添加一个命令,该命令执行 GPU Command command 的步骤:
-
将 command 添加到 encoder.
[[commands]]
。 -
当 command 作为
GPUCommandBuffer
的一部分执行时:-
执行 command 的步骤。
-
13.2. GPUCommandEncoder
[Exposed =(Window ,DedicatedWorker ),SecureContext ]interface GPUCommandEncoder {GPURenderPassEncoder beginRenderPass (GPURenderPassDescriptor descriptor );GPUComputePassEncoder beginComputePass (optional GPUComputePassDescriptor descriptor = {});undefined copyBufferToBuffer (GPUBuffer source ,GPUSize64 sourceOffset ,GPUBuffer destination ,GPUSize64 destinationOffset ,GPUSize64 size );undefined copyBufferToTexture (GPUImageCopyBuffer source ,GPUImageCopyTexture destination ,GPUExtent3D copySize );undefined copyTextureToBuffer (GPUImageCopyTexture source ,GPUImageCopyBuffer destination ,GPUExtent3D copySize );undefined copyTextureToTexture (GPUImageCopyTexture source ,GPUImageCopyTexture destination ,GPUExtent3D copySize );undefined clearBuffer (GPUBuffer buffer ,optional GPUSize64 offset = 0,optional GPUSize64 size );undefined writeTimestamp (GPUQuerySet querySet ,GPUSize32 queryIndex );undefined resolveQuerySet (GPUQuerySet querySet ,GPUSize32 firstQuery ,GPUSize32 queryCount ,GPUBuffer destination ,GPUSize64 destinationOffset );GPUCommandBuffer finish (optional GPUCommandBufferDescriptor descriptor = {}); };GPUCommandEncoder includes GPUObjectBase ;GPUCommandEncoder includes GPUCommandsMixin ;GPUCommandEncoder includes GPUDebugCommandsMixin ;
13.2.1. 命令编码器创建
dictionary :
GPUCommandEncoderDescriptor GPUObjectDescriptorBase { };
createCommandEncoder(descriptor)
-
创建一个
GPUCommandEncoder
。Called on:GPUDevice
this.Arguments:
Arguments for the GPUDevice.createCommandEncoder(descriptor) method. Parameter Type Nullable Optional Description descriptor
GPUCommandEncoderDescriptor
✘ ✔ 要创建的 GPUCommandEncoder
的描述。Returns:
GPUCommandEncoder
内容时间线 步骤:
-
让 e 成为一个新的
GPUCommandEncoder
对象。 -
在 this 的 设备时间线 上执行 initialization steps。
-
返回 e。
设备时间线 initialization steps:问题:描述剩余的
createCommandEncoder()
验证和 算法步骤。 -
GPUCommandEncoder
,对一个缓冲区进行清除的命令进行编码,完成编码器以获得一个 GPUCommandBuffer
,然后将其提交给 GPUQueue
。
const commandEncoder= gpuDevice. createCommandEncoder(); commandEncoder. clearBuffer( buffer); const commandBuffer= commandEncoder. finish(); gpuDevice. queue. submit([ commandBuffer]);
13.3. 通道编码
beginRenderPass(descriptor)
-
开始编码由 descriptor 描述的渲染过程。
Called on:GPUCommandEncoder
this.Arguments:
Arguments for the GPUCommandEncoder.beginRenderPass(descriptor) method. Parameter Type Nullable Optional Description descriptor
GPURenderPassDescriptor
✘ ✘ 要创建的 GPURenderPassEncoder
的描述。Returns:
GPURenderPassEncoder
内容时间线 步骤:
-
对于 descriptor 的
colorAttachments
中的每个非null
的 colorAttachment:-
如果 colorAttachment 的
clearValue
不是null
。-
? 验证 GPUColor 形状(colorAttachment.
clearValue
)。
-
-
-
设 pass 为一个新的
GPURenderPassEncoder
对象。 -
在 this 的 设备时间线 上发布 初始化步骤。
-
返回 pass。
设备时间轴 初始化步骤:-
如果以下任何要求未满足,则将 pass 设为 invalid 并返回。
-
设备 this 上的 descriptor 必须满足
[[device]]
提供的 有效使用 规则。
-
-
对于 descriptor.
colorAttachments
中的每个非“null” colorAttachment: -
让 depthStencilAttachment 成为 descriptor.
depthStencilAttachment
,如果没有 provided 则为“null”。 -
如果 depthStencilAttachment 不是
null
:-
让 depthStencilView 成为 depthStencilAttachment.
view
。 -
如果 depthStencilAttachment.
depthReadOnly
和stencilReadOnly
为 true:-
在渲染操作期间,depthStencilView 的 [=GPUTextureView/subresources=} 被视为用作 attachment-read。
-
-
设置 pass.
[[depthReadOnly]]
为 depthStencilAttachment.depthReadOnly
。 -
设置 pass.
[[stencilReadOnly]]
为 depthStencilAttachment.stencilReadOnly
。
-
-
将 pass.
[[layout]]
设置为 从 pass 推导出 render targets layout(descriptor)。 -
对于 descriptor中的每个
timestampWrites
中的 timestampWrite,-
如果 timestampWrite的
location
为"beginning"
, 在 this的[[commands]]
中 append 一个 GPU command 将GPU的时间戳值写入 timestampWrite的querySet
的 timestampWrite的queryIndex
索引处。 -
否则,如果 timestampWrite.
location
为"end"
, 添加 timestampWrite到 pass的[[endTimestampWrites]]
。
-
-
将 pass的
[[drawCount]]
设置为0。 -
将 pass的
[[maxDrawCount]]
设置为 descriptor的maxDrawCount
。 -
在 this 上执行Enqueue a command,当执行时,在Queue timeline上执行后续步骤。
队列时间线 步骤:-
让当前正在执行的
GPUCommandBuffer
的[[renderState]]
成为一个新的RenderState。 -
问题:执行附件加载/清除。
问题:指定只读深度/模板的行为
-
beginComputePass(descriptor)
-
开始对 descriptor 描述的计算过程进行编码。
Called on:GPUCommandEncoder
this.Arguments:
Arguments for the GPUCommandEncoder.beginComputePass(descriptor) method. Parameter Type Nullable Optional Description descriptor
GPUComputePassDescriptor
✘ ✔ Returns:
GPUComputePassEncoder
内容时间线 步骤:
1.让 pass 是一个新的
GPUComputePassEncoder
对象。 1.发出初始化步骤 在 this 的 设备时间线 上。-
返回 pass。
设备时间线 initialization steps:-
验证 this 的编码器状态。 如果返回false,使 pass 无效并返回。
-
如果以下任何要求没有得到满足,使 pass 无效并返回。
-
必须返回true的验证 timeStampWrites (this.
[[device]]
,descriptor.timestampWrites
)。
-
-
对于 descriptor.
timestampWrites
中的每个 timestampWrite,遵循以下步骤:-
如果 timestampWrite.
location
是“beginning”
, 将一个 GPU command 追加到 this.[[commands]]
中,该命令将 GPU 的时间戳值写入 timestampWrite.querySet
的 timestampWrite.queryIndex
索引处。 -
否则,如果 timestampWrite.
location
是“end”
, 将 timestampWrite 追加到 pass.[[endTimestampWrites]]
中。
-
-
13.4. 缓冲区拷贝命令
copyBufferToBuffer(source, sourceOffset, destination, destinationOffset, size)
-
将命令编码到
GPUCommandEncoder
中,将数据从GPUBuffer
的子区域复制到另一个GPUBuffer
的子区域。Called on:GPUCommandEncoder
this.Arguments:
Arguments for the GPUCommandEncoder.copyBufferToBuffer(source, sourceOffset, destination, destinationOffset, size) method. Parameter Type Nullable Optional Description source
GPUBuffer
✘ ✘ 要从中复制的 GPUBuffer
。sourceOffset
GPUSize64
✘ ✘ 以字节为单位的偏移量到source 从开始复制。 destination
GPUBuffer
✘ ✘ 要复制到的 GPUBuffer
。destinationOffset
GPUSize64
✘ ✘ 到 destination 的偏移量(以字节为单位) 放置复制的数据。 size
GPUSize64
✘ ✘ 要复制的字节数。 Returns:
undefined
内容时间线 步骤:
-
在 this.
[[device]]
的 设备时间线 上发布后续步骤。
设备时间线 步骤:-
this 的验证编码器状态。 如果它返回 false,则停止。
-
如果不满足以下任何条件,则制作this 无效 并停止。
-
source 是 valid to use with this。
-
destination 是 valid to use with this。
-
size 是4的倍数。
-
sourceOffset 是4的倍数。
-
destinationOffset 是4的倍数。
-
source.
size
≥ (sourceOffset + size)。 -
destination.
size
≥ (destinationOffset + size)。 -
source 和destination 不一样的
GPUBuffer
。
-
队列时间线 步骤:-
将 source 中从 sourceOffset 开始的 size 字节复制到 destination, 从 destinationOffset 开始。
-
clearBuffer(buffer, offset, size)
-
将一个命令编码到
GPUCommandEncoder
中,该命令将GPUBuffer
的子区域填充为零。Called on:GPUCommandEncoder
this.Arguments:
Arguments for the GPUCommandEncoder.clearBuffer(buffer, offset, size) method. Parameter Type Nullable Optional Description buffer
GPUBuffer
✘ ✘ 要清除的 GPUBuffer
。offset
GPUSize64
✘ ✔ 偏移字节到buffer 要清除的子区域开始的地方。 size
GPUSize64
✘ ✔ 要清除的子区域的大小(以字节为单位)。默认为缓冲区大小减去 offset。 Returns:
undefined
内容时间线 步骤:
-
在 this.
[[device]]
的 Device timeline 上发布后续步骤。
设备时间线 步骤:-
验证this的编码器状态。如果返回 false, 停止。
-
如果 size 丢失, 将 size 设置为
max(0, |buffer|.{{GPUBuffer/size}} - |offset|)
。 -
如果以下任何条件不满足,则使 this 无效 并停止。
-
在 this 上执行入队命令,当执行时在Queue timeline 上发布后续步骤。
队列时间轴步骤:-
从 offset 开始将 buffer 的 size 字节设置为
0
。
-
13.5. 图像复制命令
copyBufferToTexture(source, destination, copySize)
-
将一个命令编码到
GPUCommandEncoder
中,将数据从GPUBuffer
的子区域复制到一个或多个连续的纹理子资源的子区域。Called on:GPUCommandEncoder
this.Arguments:
Arguments for the GPUCommandEncoder.copyBufferToTexture(source, destination, copySize) method. Parameter Type Nullable Optional Description source
GPUImageCopyBuffer
✘ ✘ 结合copySize,定义源缓冲区的区域。 destination
GPUImageCopyTexture
✘ ✘ 结合copySize,定义目标区域texture subresource。 copySize
GPUExtent3D
✘ ✘ Returns:
undefined
内容时间线 步骤:
-
? 验证 GPUOrigin3D 形状(destination.
origin
)。 -
? 验证 GPUExtent3D 形状(copySize)。
-
在 this.
[[device]]
的 设备时间线 上发布后续步骤:
设备时间线 步骤:-
this 的验证编码器状态。 如果它返回 false,则停止。
-
如果不满足以下任何条件,则制作this 无效 并停止。
-
让 dstTexture 是 destination.
texture
. -
验证GPUImageCopyBuffer 返回 true.
-
验证GPUImageCopyTexture(destination, copySize) 返回 true.
-
dstTexture.
sampleCount
是 1. -
让 aspectSpecificFormat = dstTexture.
format
. -
那个方面必须是根据 § 26.1.2 深度模具格式 的有效图像拷贝目标。
-
将 aspectSpecificFormat 设置为根据 § 26.1.2 深度模具格式 的 方面特定格式.
-
验证纹理拷贝范围(destination, copySize) 返回 true.
-
source.
offset
是 dstTexture.format
的 texel block copy footprint 的倍数。 -
source.
offset
是 4 的倍数。 -
验证线性纹理数据(source, source.
buffer
.size
, aspectSpecificFormat, copySize) 成功。
-
-
将一个命令加入队列,当执行时,在Queue timeline上执行后续步骤。
队列时间线 步骤:问题:定义副本,包括对snorm的规定。
-
copyTextureToBuffer(source, destination, copySize)
-
将一个命令编码到
GPUCommandEncoder
中,该命令从一个或多个连续的 texture subresources 子区域中复制数据到GPUBuffer
的子区域。Called on:GPUCommandEncoder
this.Arguments:
Arguments for the GPUCommandEncoder.copyTextureToBuffer(source, destination, copySize) method. Parameter Type Nullable Optional Description source
GPUImageCopyTexture
✘ ✘ 结合 copySize,定义源texture subresources的区域。 destination
GPUImageCopyBuffer
✘ ✘ 结合 copySize,定义目标缓冲区的区域。 copySize
GPUExtent3D
✘ ✘ 定义所需复制区域的大小。 Returns:
undefined
内容时间线 步骤:
-
? 验证 GPUOrigin3D 形状(source.
origin
)。 -
? 验证 GPUExtent3D 形状(copySize)。
-
在 this.
[[device]]
的 设备时间线 上发布后续步骤:
设备时间线 步骤:-
验证this的[=编码器状态$]。如果返回 false,则停止。
-
如果以下任何条件不满足,使this变为无效并停止。
-
让 srcTexture 为 source.
texture
。 -
验证 GPUImageCopyTexture(source, copySize) 返回 true。
-
srcTexture.
sampleCount
是 1。 -
让 aspectSpecificFormat = srcTexture.
format
。 -
如果 srcTexture.
format
是一个 depth-or-stencil format格式:-
根据 § 26.1.2 深度模具格式,该方面必须是有效的图像复制源。
-
将 aspectSpecificFormat 设置为根据 § 26.1.2 深度模具格式 的 aspect-specific format。
-
$验证 GPUImageCopyBuffer$ 返回 true。
-
验证纹理复制范围(source, copySize) 返回 true。
-
如果 srcTexture.
format
不是 depth-or-stencil format:-
destination.
offset
是 srcTexture.format
的 texel block copy footprint 的倍数。
-
-
如果 srcTexture.
format
是 depth-or-stencil format:-
destination.
offset
是 4 的倍数。
-
-
[$ 验证线性纹理数据 $](destination, destination.
buffer
.size
, aspectSpecificFormat, copySize) 成功。
-
-
在 this 上 Enqueue a command,执行时会在 队列时间线 上发出后续步骤。
队列时间线 步骤:问题:定义副本,包括 snorm 的规定。
-
copyTextureToTexture(source, destination, copySize)
-
将一个命令编码到
GPUCommandEncoder
中,该命令用于将数据从一个或多个连续的texture subresources的子区域复制到另一个或多个连续的texture subresources的子区域。Called on:GPUCommandEncoder
this.Arguments:
Arguments for the GPUCommandEncoder.copyTextureToTexture(source, destination, copySize) method. Parameter Type Nullable Optional Description source
GPUImageCopyTexture
✘ ✘ 结合copySize,定义源纹理子资源的区域。 destination
GPUImageCopyTexture
✘ ✘ 结合copySize,定义目标纹理子资源的区域。 copySize
GPUExtent3D
✘ ✘ 复制尺寸。 Returns:
undefined
内容时间线 步骤:
-
? 验证 GPUOrigin3D 形状(source.
origin
). -
? 验证 GPUOrigin3D 形状(destination.
origin
). -
? 验证 GPUExtent3D 形状(copySize).
-
在 this.
[[device]]
的 设备时间线 上执行后续步骤:
设备时间线 步骤:1.验证this的编码器状态。如果返回结果为false,则停止。 1.如果以下任何条件不满足,则使this变为无效并停止。
-
让 srcTexture 是 source.
texture
。 -
让 dstTexture 是 destination.
texture
。 -
validating GPUImageCopyTexture(source, copySize) 返回 true。
-
validating GPUImageCopyTexture(destination, copySize) 返回 true。
-
srcTexture.
sampleCount
等于 dstTexture.sampleCount
。 -
srcTexture.
format
和 dstTexture.format
必须是 copy-compatible。 -
如果 srcTexture.
format
是深度模板格式: -
validating texture copy range(source, copySize) 返回 true。
-
validating texture copy range(destination, copySize) 返回 true。
-
set of subresources for texture copy(source, copySize) 和 set of subresources for texture copy(destination, copySize) 是不相交的。
-
Enqueue a command on this which issues the subsequent steps on the Queue timeline when executed.
队列时间线 步骤:问题:定义副本,包括 snorm 的规定。
-
13.6. 请求
writeTimestamp(querySet, queryIndex)
-
当所有先前的命令都已完成执行时,将时间戳值写入 querySet。
Called on:GPUCommandEncoder
this.Arguments:
Arguments for the GPUCommandEncoder.writeTimestamp(querySet, queryIndex) method. Parameter Type Nullable Optional Description querySet
GPUQuerySet
✘ ✘ 将存储时间戳值的查询集。 queryIndex
GPUSize32
✘ ✘ 查询在查询集中的索引。 Returns:
undefined
内容时间线 步骤:
-
如果
"timestamp-query"
不是 enabled for this: -
抛出一个
TypeError
。 -
在 this 的 Device timeline 上发布后续步骤。
[[device]]
:
设备时间线 步骤:-
this 的验证编码器状态。如果它返回 false,则停止。
-
如果不满足以下任何条件,则制作this 无效 并停止。
-
querySet 是 valid to use with this。
-
querySet.
type
是"timestamp"
。 -
queryIndex < querySet.
count
。
-
-
将一个命令插入this,当该命令执行时,在队列时间线上进行后续步骤。
-
resolveQuerySet(querySet, firstQuery, queryCount, destination, destinationOffset)
-
将
GPUQuerySet
中的查询结果解析到GPUBuffer
的一定范围内。Called on:GPUCommandEncoder
this.Arguments:
Arguments for the GPUCommandEncoder.resolveQuerySet(querySet, firstQuery, queryCount, destination, destinationOffset) method. Parameter Type Nullable Optional Description querySet
GPUQuerySet
✘ ✘ firstQuery
GPUSize32
✘ ✘ queryCount
GPUSize32
✘ ✘ destination
GPUBuffer
✘ ✘ destinationOffset
GPUSize64
✘ ✘ Returns:
undefined
内容时间线 步骤:
-
在this.
[[device]]
的 设备时间线 上发布后续步骤。
设备时间线 步骤:1.验证this的编码器状态。如果返回false,则停止。 1.如果任何以下条件不满足,将this设为无效并停止。
-
querySet 可以与 this 一起使用。
-
destination 可以与 this 一起使用。
-
destination.
usage
包含QUERY_RESOLVE
。 -
firstQuery <在 querySet 中的查询数量。
-
(firstQuery + queryCount) ≤ 在 querySet 中的查询数量。
-
destinationOffset 是256的倍数。
-
destinationOffset + 8 × queryCount ≤ destination.
size
。
队列时间线 步骤:-
使 queryIndex 为 firstQuery.
-
使 offset 为 destinationOffset.
-
queryIndex < firstQuery + queryCount:
-
设置 8 个字节的 destination,从 offset 开始,作为在 queryIndex querySet 的值。
-
设置 queryIndex 为 queryIndex + 1.
-
设置 offset 为 offset + 8.
-
-
13.7. 最终
一个包含GPUCommandEncoder
记录的命令的GPUCommandBuffer
可以通过调用finish()
来创建。一旦调用了finish()
,该命令编码器将不再可用。
finish(descriptor)
-
完成命令序列的记录并返回相应的
GPUCommandBuffer
。Called on:GPUCommandEncoder
this.Arguments:
Arguments for the GPUCommandEncoder.finish(descriptor) method. Parameter Type Nullable Optional Description descriptor
GPUCommandBufferDescriptor
✘ ✔ Returns:
GPUCommandBuffer
Content timeline steps:
-
让 commandBuffer 是一个新的
GPUCommandBuffer
。 -
返回 commandBuffer。
设备时间线 finish steps:-
如果满足以下所有要求,那么将 validationSucceeded 设置为“true”,否则设置为“false”。
-
如果 validationSucceeded 为
false
,那么:-
返回一个新的 无效的
GPUCommandBuffer
。
-
将 commandBuffer.
[[command_list]]
设置为 this.[[commands]]
。
-
14. 可编程通道
interface mixin {
GPUBindingCommandsMixin undefined setBindGroup (GPUIndex32 index ,GPUBindGroup ?bindGroup ,optional sequence <GPUBufferDynamicOffset >dynamicOffsets = []);undefined setBindGroup (GPUIndex32 index ,GPUBindGroup ?bindGroup ,Uint32Array dynamicOffsetsData ,GPUSize64 dynamicOffsetsDataStart ,GPUSize32 dynamicOffsetsDataLength ); };
GPUBindingCommandsMixin
假定在同一个对象上存在GPUObjectBase
和GPUCommandsMixin
成员。它只能被同时包含这些mixin的接口所包含。
GPUBindingCommandsMixin
具有以下内部插槽数:
[[bind_groups]]
, 类型为 ordered map<GPUIndex32
,GPUBindGroup
>-
当前的
GPUBindGroup
用于每个索引,初始为空。 [[dynamic_offsets]]
, 类型为 ordered map<GPUIndex32
, sequence>GPUBufferDynamicOffset
>>-
当前每个
[[bind_groups]]
条目的动态偏移量,初始为空。
14.1. 绑定组
setBindGroup() has two overloads:
setBindGroup(index, bindGroup, dynamicOffsets)
-
为给定的索引设置当前的
GPUBindGroup
。Called on:GPUBindingCommandsMixin
this.Arguments:
index
, 类型为GPUIndex32
, non-nullable, required-
设置绑定组的索引。
bindGroup
, 类型为GPUBindGroup
, nullable, required-
绑定组以用于后续渲染或计算命令。
dynamicOffsets
, of type sequence<GPUBufferDynamicOffset
>, non-nullable, defaulting to[]
-
包含每个标记为
buffer
.hasDynamicOffset
的 bindGroup 项的字节缓冲区偏移量的数组。
Returns:
undefined
注: dynamicOffsets[i] 用于绑定组中第 i 个动态缓冲区绑定, 当按照
GPUBindGroupLayoutEntry
.binding
的顺序排序绑定时。 换句话说,dynamicOffsets 的顺序与动态缓冲区绑定的GPUBindGroupLayoutEntry
.binding
相同。内容时间线 步骤:
-
在 this.
[[device]]
的 设备时间线 上执行后续步骤。
设备时间线 步骤:-
验证 this 的编码器状态Validate the encoder state。如果返回 false,则停止。
-
如果
bindGroup
是null
,则让 dynamicOffsetCount 为 0,否则为 bindGroup.[[layout]]
.[[dynamicOffsetCount]]
。 -
如果以下任何要求没有得到满足,使 this 变为invalid并停止。
-
index 必须小于 this.
[[device]]
.[[limits]]
.maxBindGroups
. -
dynamicOffsets.length 必须等于 dynamicOffsetCount.
-
-
如果 bindGroup 是
null
:-
在 this.
[[bind_groups]]
[index] 中 Remove。 -
在 this.
[[dynamic_offsets]]
[index] 中 Remove。
否则:
-
如果以下任何要求未得到满足,请使this invalid 并停止。
-
bindGroup 必须与 this一起有效使用。
-
对于动态绑定的每一个 (bufferBinding, bufferLayout, dynamicOffsetIndex) in bindGroup:
-
bufferBinding.
offset
+ dynamicOffsets[dynamicOffsetIndex] + bufferLayout.minBindingSize
必须 <=; bufferBinding.buffer
.size
. -
如果 bufferLayout.
type
是"uniform"
:-
dynamicOffset 必须是
minUniformBufferOffsetAlignment
的倍数。
-
-
如果 bufferLayout.
type
是"storage"
或"read-only-storage"
:-
dynamicOffset 必须是
minStorageBufferOffsetAlignment
的倍数。
-
-
-
-
将 this.
[[bind_groups]]
[index] 设置为 bindGroup。 -
将 this.
[[dynamic_offsets]]
[index] 设置为 dynamicOffsets 的副本。
-
setBindGroup(index, bindGroup, dynamicOffsetsData, dynamicOffsetsDataStart, dynamicOffsetsDataLength)
-
为给定索引设置当前
GPUBindGroup
,将动态偏移量指定为Uint32Array
的子集。Called on:GPUBindingCommandsMixin
this.Arguments:
Arguments for the GPUBindingCommandsMixin.setBindGroup(index, bindGroup, dynamicOffsetsData, dynamicOffsetsDataStart, dynamicOffsetsDataLength) method. Parameter Type Nullable Optional Description index
GPUIndex32
✘ ✘ 设置绑定组的索引。 bindGroup
GPUBindGroup?
✔ ✘ 绑定组以用于后续渲染或计算命令。 dynamicOffsetsData
Uint32Array
✘ ✘ 包含 bindGroup 中每个条目的缓冲区偏移量的数组(以字节为单位) 标记为 buffer
.hasDynamicOffset
。dynamicOffsetsDataStart
GPUSize64
✘ ✘ 元素中的偏移到dynamicOffsetsData 缓冲区偏移数据开始的地方。 dynamicOffsetsDataLength
GPUSize32
✘ ✘ 要从 dynamicOffsetsData 中读取的缓冲区偏移量的数量。 Returns:
undefined
内容时间线 步骤:
-
如果以下任何要求未满足,请抛出一个
RangeError
并停止。-
dynamicOffsetsDataStart 必须为 ≥ 0。
-
dynamicOffsetsDataStart + dynamicOffsetsDataLength 必须为 ≤ dynamicOffsetsData.
length
。
-
-
让 dynamicOffsets 成为一个 list,其中包含从索引 dynamicOffsetsDataStart 开始,dynamicOffsetsDataLength 个元素的范围 副本 dynamicOffsetsData。
-
调用 this.
setBindGroup
(index, bindGroup, dynamicOffsets)。
-
GPUBindGroup
bindGroup中遍历每个动态绑定偏移,
并为每个动态偏移执行一系列steps:
-
设 dynamicOffsetIndex 为 0。
-
设 layout 为 bindGroup.
[[layout]]
。 -
对于按 entry.
binding
的递增值排序的 bindGroup.[[entries]]
中的每个GPUBindGroupEntry
entry:-
设 bindingDescriptor 为layout.
[[entryMap]]
[entry.binding
] 的GPUBindGroupLayoutEntry
。 -
如果 bindingDescriptor.
buffer
? .hasDynamicOffset
为 true:
-
Arguments:
GPUBindingCommandsMixin
encoder-
正在验证其绑定组的编码器。
GPUPipelineBase
pipeline-
验证 encoders 绑定组兼容的管道。
-
如果不满足以下任何条件,则返回
false
:-
pipeline 不能为空。
-
管线使用的所有绑定组必须设置并且与管线布局兼容: 对于pipeline.
[[layout]]
.[[bindGroupLayouts]]
中的(GPUIndex32
index,GPUBindGroupLayout
bindGroupLayout) 对:-
让 bindGroup 是 encoder.
[[bind_groups]]
[index]。 -
bindGroup 不能为空。
-
bindGroup.
[[layout]]
必须与 bindGroupLayout 群组等效。
-
-
对于没有使用
minBindingSize
预验证的缓冲区绑定,绑定范围必须足够大以容纳 minimum buffer binding size。问题:形式化此检查。
-
Encoder 绑定组别名为可写资源(encoder, pipeline) 必须为’false’。
-
否则返回 true
.
GPUTextureView
对象)。
Arguments:
GPUBindingCommandsMixin
encoder-
正在验证其绑定组的编码器。
GPUPipelineBase
pipeline-
验证 encoders 绑定组兼容的管道。
-
对于[
VERTEX
,FRAGMENT
,COMPUTE
]中的每个stage:-
设bufferBindings为(
GPUBufferBinding
,boolean
)对的列表,其中后者表示资源是否被用作可写。 -
设textureViews为(
GPUTextureView
,boolean
)对的列表,其中后者表示资源是否被用作可写。 -
对于pipeline.
[[layout]]
.[[bindGroupLayouts]]
中的每对(GPUIndex32
index,GPUBindGroupLayout
bindGroupLayout):-
让 bindGroupEntries 为 encoder.
[[bind_groups]]
[index].entries
。 -
让 bindGroupLayoutEntries 为 bindGroupLayout.
[[descriptor]]
.entries
。 -
对于 bindGroupLayoutEntries 中的每个
GPUBindGroupEntry
bindGroupLayoutEntry 其中 bindGroupLayoutEntry.visibility
包含 stage:-
令
GPUBufferBinding
resource 为 bindGroupEntry.resource
. 1. 令 resourceWritable 为 (bindGroupLayoutEntry.buffer
.type
==“storage”
). 1. 对于 bufferBindings 中的每一对 (GPUBufferBinding
pastResource, boolean pastResourceWritable): 1. 如果 (resourceWritable 或 pastResourceWritable) 为真,并且 pastResource 和 resource 是 buffer-binding-aliasing,返回 true。 1. 将 ([resource], resourceWritable) 附加到 bufferBindings。
否则,如果 bindGroupEntry.
resource
是GPUTextureView
:-
令
GPUTextureView
resource 为 bindGroupEntry.resource
. -
令 resourceWritable 为 (bindGroupLayoutEntry.
storageTexture
.access
=="write-only"
). -
如果 bindGroupLayoutEntry.
storageTexture
没有 provided,则 继续. -
对于 textureViews 中的每一对 (
GPUTextureView
pastResource,boolean
pastResourceWritable),-
如果 (resourceWritable 或 pastResourceWritable) 为真,并且 pastResource 和 resource 是 texture-view-aliasing,返回
true
。
-
-
将 ([resource], resourceWritable) 附加到 textureViews。
否则,继续。
-
-
-
-
返回
false
。
注: 强烈建议实现优化此算法。
15. 调试标记
GPUDebugCommandsMixin
提供了将调试标签应用于命令组或将单个标签插入到命令序列的方法。
调试组可以嵌套以创建标记命令的层次结构,且必须具有良好的平衡。
与 object labels
一样,这些标签没有必需的行为,但可以显示在错误消息和浏览器开发者工具中,并且可以传递给本地API后端。
interface mixin GPUDebugCommandsMixin {undefined pushDebugGroup (USVString groupLabel );undefined popDebugGroup ();undefined insertDebugMarker (USVString markerLabel ); };
GPUDebugCommandsMixin
假定同一对象上具有GPUObjectBase
和GPUCommandsMixin
成员。它只能被那些也包含这些混入的接口引入。
GPUDebugCommandsMixin
将以下内部插槽添加到包含它的接口中:
[[debug_group_stack]]
, 类型为 stack<USVString
>-
一个包含激活调试组标签的堆。
GPUDebugCommandsMixin
将以下方法添加到包含它的接口中:
pushDebugGroup(groupLabel)
-
开始包含后续命令的标记调试组。
Called on:GPUDebugCommandsMixin
this.Arguments:
Arguments for the GPUDebugCommandsMixin.pushDebugGroup(groupLabel) method. Parameter Type Nullable Optional Description groupLabel
USVString
✘ ✘ 命令组的标签。 Returns:
undefined
内容时间线 步骤:
设备时间线 步骤:-
验证 this 的 编码器状态。如果返回 false,则停止。
-
将 groupLabel 压入 this.
[[debug_group_stack]]
之中。
-
popDebugGroup()
-
Ends the labeled debug group most recently started by
pushDebugGroup()
.设备时间线 步骤:-
验证 this 的编码器状态Validate the encoder state。如果返回 false,则停止。
-
如果以下任何要求未满足,将 this 设为 invalid,并停止。
-
this.
[[debug_group_stack]]
不能为空 be empty。
-
-
从 this.
[[debug_group_stack]]
中Pop 弹出一个条目。
-
insertDebugMarker(markerLabel)
-
用标签标记命令流中的一个点。
Called on:GPUDebugCommandsMixin
this.Arguments:
Arguments for the GPUDebugCommandsMixin.insertDebugMarker(markerLabel) method. Parameter Type Nullable Optional Description markerLabel
USVString
✘ ✘ 要插入的标签。 Returns:
undefined
内容时间线 步骤:
-
在 this.
[[device]]
的 设备时间线 上发布后续步骤。
-
16. 计算通道
16.1. GPUComputePassEncoder
[Exposed =(Window ,DedicatedWorker ),SecureContext ]interface GPUComputePassEncoder {undefined (
setPipeline GPUComputePipeline pipeline );undefined dispatchWorkgroups (GPUSize32 workgroupCountX ,optional GPUSize32 workgroupCountY = 1,optional GPUSize32 workgroupCountZ = 1);undefined dispatchWorkgroupsIndirect (GPUBuffer indirectBuffer ,GPUSize64 indirectOffset );undefined end (); };GPUComputePassEncoder includes GPUObjectBase ;GPUComputePassEncoder includes GPUCommandsMixin ;GPUComputePassEncoder includes GPUDebugCommandsMixin ;GPUComputePassEncoder includes GPUBindingCommandsMixin ;
GPUComputePassEncoder
有以下内部槽位:
[[command_encoder]]
,类型为GPUCommandEncoder
, 只读-
创建此计算传递编码器的
GPUCommandEncoder
[[pipeline]]
,类型为GPUComputePipeline
, 只读-
当前的
GPUComputePipeline
,最初为null
[[endTimestampWrite]]
,类型为 GPU command?,只读,默认为null
-
GPU command, 如果有, 在传递结束时写入一个时间戳。
16.1.1. 计算过程编码器创建
dictionary {
GPUComputePassTimestampWrites required GPUQuerySet querySet ;GPUSize32 beginningOfPassWriteIndex ;GPUSize32 endOfPassWriteIndex ; };
querySet
, of type GPUQuerySet-
GPUQuerySet
,类型为"timestamp"
,查询结果将写入于此。 beginningOfPassWriteIndex
, of type GPUSize32-
如果已定义,则指示
querySet
中的查询索引,计算过程开始时的时间戳将写入该索引。 endOfPassWriteIndex
, of type GPUSize32-
如果已定义,则指示
querySet
中的查询索引,计算过程结束时的时间戳将写入该索引。
dictionary :
GPUComputePassDescriptor GPUObjectDescriptorBase {GPUComputePassTimestampWrites timestampWrites ; };
timestampWrites
, of type GPUComputePassTimestampWrites-
定义将为此过程写入哪些时间戳值,以及将它们写入到何处。
16.1.2. 调度
setPipeline(管道)
-
设置当前
GPUComputePipeline
.调用:GPUComputePassEncoder
this.参数:
Arguments for the GPUComputePassEncoder.setPipeline(pipeline) method. Parameter Type Nullable Optional Description pipeline
GPUComputePipeline
✘ ✘ 用于后续调度命令的计算管道。 Returns:
undefined
内容时间线 步骤:
-
在 设备时间轴 上发布后续步骤。
[[device]]
.
设备时间线 步骤:-
验证此的编码器状态 如果返回false,请停止。
-
如果不满足以下任何条件,则使 this 无效 并停止。
-
pipeline 与此一起使用 是有效的 。
-
-
设置 this.
[[pipeline]]
为 管道。
-
dispatchWorkgroups(workgroupCountX, workgroupCountY, workgroupCountZ)
-
要使用当前
GPUComputePipeline
。 详情参见 § 23.2 计算 。调用:GPUComputePassEncoder
this.参数:
Arguments for the GPUComputePassEncoder.dispatchWorkgroups(workgroupCountX, workgroupCountY, workgroupCountZ) method. Parameter Type Nullable Optional Description workgroupCountX
GPUSize32
✘ ✘ 要调度的工作组网格的X维度。 workgroupCountY
GPUSize32
✘ ✔ 要调度的工作组网格的Y维度。 workgroupCountZ
GPUSize32
✘ ✔ 要调度的工作组网格的Z维度。 注意: 传递给dispatchWorkgroups()
和dispatchWorkgroupsIndirect()
的x
,y
和z
值是要为每个维度调度的工作组数, 而不是 而不是要在每个维度上执行的着色器调用数。这与现代原生GPU API的行为相匹配,但与OpenCL的行为不同。 这意味着,如果一个GPUShaderModule
用@workgroup_size(4, 4)
定义了一个入口点,并且通过调用computePass.dispatchWorkgroups(8, 8);
将工作分派给它; 入口点将被调用1024次:沿X轴和Y轴调度4x4工作组8次。返回:
未定义
内容时间线 步骤:
-
在 设备时间轴 上发布后续步骤。
[[device]]
.
设备时间线 步骤:-
验证此的编码器状态 。如果返回false,请停止。
-
如果不满足以下任何条件,则使 this 无效 并停止。
-
验证编码器绑定组(this, this.
[[pipeline]]
) 是否为true
. -
所有 workgroupCountX, workgroupCountY and workgroupCountZ 均 ≤ this.device.limits.
maxComputeWorkgroupsPerDimension
.
-
-
将 passState 作为INDIRECT添加到使用范围中。
队列时间线 步骤:-
使用 passState执行维度为 [workgroupCountX, workgroupCountY, workgroupCountZ] .
[[pipeline]]
using passState的工作组网格。[[bind_groups]]
.
-
dispatchWorkgroupsIndirect(indirectBuffer, indirectOffset)
-
使用从
GPUBuffer
读取的参数,使用当前GPUComputePipeline
执行调度工作。 详情参见 § 23.2 计算 。缓冲区中编码的间接调度参数必须是一个由 三个32位无符号整数值(总共12个字节), 组成的紧密压缩块,其顺序与
dispatchWorkgroups()
的参数相同。 例如:let dispatchIndirectParameters= new Uint32Array( 3 ); dispatchIndirectParameters[ 0 ] = workgroupCountX; dispatchIndirectParameters[ 1 ] = workgroupCountY; dispatchIndirectParameters[ 2 ] = workgroupCountZ; 调用:GPUComputePassEncoder
this.参数:
Arguments for the GPUComputePassEncoder.dispatchWorkgroupsIndirect(indirectBuffer, indirectOffset) method. Parameter Type Nullable Optional Description indirectBuffer
GPUBuffer
✘ ✘ 包含 间接调度参数的缓冲区。 indirectOffset
GPUSize64
✘ ✘ 以字节为单位偏移到调度数据开始的 indirectBuffer 。 返回:
undefined
内容时间线 步骤:
-
在 设备时间轴 上发布后续步骤。
[[device]]
.
设备时间线 步骤:-
验证此的编码器状态 。如果返回false,请停止。
-
如果不满足以下任何条件,则使 this 无效 并停止。
-
验证编码器绑定组(this, this.
[[pipeline]]
) 是否为true
。 -
indirectBuffer 与此一起使用是有效的 。
-
indirectOffset + sizeof(indirect dispatch parameters) ≤ indirectBuffer.
size
. -
indirectOffset 是4的倍数。
-
-
让 passState 成为当前状态的快照。
队列时间线 步骤:-
让 workgroupCountX 是一个从 indirectBuffer 读取的32位无符号整数,位于 indirectOffset 字节。
-
让 workgroupCountY 是一个无符号的32位整数,从 indirectBuffer 读取 (indirectOffset + 4) 字节。
-
让 workgroupCountZ 是一个无符号的32位整数,从 indirectBuffer 读取 (indirectOffset + 8) 字节。
-
如果 workgroupCountX, workgroupCountY, or workgroupCountZ 大于 this.device.limits.
maxComputeWorkgroupsPerDimension
,请停止。 -
使用 passState执行维度为 [workgroupCountX, workgroupCountY, workgroupCountZ] 的工作组网格。
[[pipeline]]
使用 passState.[[bind_groups]]
.
-
16.1.3. 最终确定
一旦用户完成了对过程的命令记录,就可以通过调用 end()
来
结束计算过程编码器。一旦调用了 end()
,就不能再使用计算过程编码器了。
end()
-
完成计算过程命令序列的记录。
设备时间线 步骤:-
让 parentEncoder 是 this.
[[command_encoder]]
. -
如果以下任何要求未得到满足,则 生成一个验证错误 并停止。
-
如果未满足以下任何要求,请使 parentEncoder 无效 并停止。
-
this 必须是 有效。
-
this.
[[debug_group_stack]]
必须 be empty.
-
-
Extend parentEncoder.
[[commands]]
with this.[[commands]]
. -
如果 this.
[[endTimestampWrite]]
不为null
:-
Extend parentEncoder.
[[commands]]
with this.[[endTimestampWrite]]
.
-
-
17. 渲染过程
17.1. GPURenderPassEncoder
[Exposed =(Window ,DedicatedWorker ),SecureContext ]interface GPURenderPassEncoder {undefined setViewport (float x ,float y ,float width ,float height ,float minDepth ,float maxDepth );undefined setScissorRect (GPUIntegerCoordinate x ,GPUIntegerCoordinate y ,GPUIntegerCoordinate width ,GPUIntegerCoordinate height );undefined setBlendConstant (GPUColor color );undefined setStencilReference (GPUStencilValue reference );undefined beginOcclusionQuery (GPUSize32 queryIndex );undefined endOcclusionQuery ();undefined executeBundles (sequence <GPURenderBundle >bundles );undefined end (); };GPURenderPassEncoder includes GPUObjectBase ;GPURenderPassEncoder includes GPUCommandsMixin ;GPURenderPassEncoder includes GPUDebugCommandsMixin ;GPURenderPassEncoder includes GPUBindingCommandsMixin ;GPURenderPassEncoder includes GPURenderCommandsMixin ;
GPURenderPassEncoder
具有以下内部插槽,用于在编码时进行验证:
[[command_encoder]]
,类型为GPUCommandEncoder
,只读-
创建此渲染过程编码器的
GPUCommandEncoder
。 [[attachment_size]]
,只读-
设置为以下范围:
-
width, height
= 过程渲染附件的尺寸
-
[[occlusion_query_set]]
,类型为GPUQuerySet
,只读-
用于存储过程的遮挡查询结果的
GPUQuerySet
,该过程在过程创建时使用GPURenderPassDescriptor
.occlusionQuerySet
初始化。 [[occlusion_query_active]]
,类型为boolean
-
是否正在写入过程的
[[occlusion_query_set]]
。 [[endTimestampWrite]]
,类型为 GPU command?,只读,默认为null
-
GPU command(如果有),在过程结束时写入时间戳。
[[maxDrawCount]]
类型为GPUSize64
,只读-
此过程中允许的最大平局次数。
当作为 GPUCommandBuffer
的一部分执行编码的渲染过程命令时,内部 RenderState 对象用于跟踪渲染所需的当前状态。
RenderState 包含以下用于执行渲染命令的内部插槽:
[[occlusionQueryIndex]]
,类型为GPUSize32
-
存储遮挡查询结果的
[[occlusion_query_set]]
索引。 [[viewport]]
-
当前视口矩形和深度范围。最初设置为以下值:
-
x, y
=0.0, 0.0
-
width, height
= 过程渲染目标的尺寸 -
minDepth, maxDepth
=0.0, 1.0
-
[[scissorRect]]
-
当前剪刀形矩形。最初设置为以下值:
-
x, y
=0, 0
-
width, height
= 过程渲染目标的尺寸
-
[[blendConstant]]
,,类型为GPUColor
-
当前混合常数值,最初为
[0, 0, 0, 0]
。 [[stencilReference]]
,类型为GPUStencilValue
-
当前模具引用值,最初为
0
。
17.1.1. 渲染过程编码器创建
dictionary {
GPURenderPassTimestampWrites required GPUQuerySet querySet ;GPUSize32 beginningOfPassWriteIndex ;GPUSize32 endOfPassWriteIndex ; };
querySet
, of type GPUQuerySet-
GPUQuerySet
,类型为"timestamp"
查询结果将写入于此。 beginningOfPassWriteIndex
, of type GPUSize32-
如果已定义,则指示
querySet
中的查询索引,渲染过程开始时的时间戳将写入该索引。 endOfPassWriteIndex
, of type GPUSize32-
如果已定义,则指示
querySet
中的查询索引,渲染过程结束时的时间戳将写入该索引。
dictionary :
GPURenderPassDescriptor GPUObjectDescriptorBase {required sequence <GPURenderPassColorAttachment ?>colorAttachments ;GPURenderPassDepthStencilAttachment depthStencilAttachment ;GPUQuerySet occlusionQuerySet ;GPURenderPassTimestampWrites timestampWrites ;GPUSize64 maxDrawCount = 50000000; };
colorAttachments
, of typesequence<GPURenderPassColorAttachment?>
-
此序列中的一组
GPURenderPassColorAttachment
值定义了执行此渲染过程时将输出到哪些颜色附件。由于 使用兼容性的原因,任何颜色附件都不能别名其他附件或渲染过程中使用的任何资源。
depthStencilAttachment
, of type GPURenderPassDepthStencilAttachment-
GPURenderPassDepthStencilAttachment
值,用于定义执行此渲染过程时将输出到并测试的深度/模具附件。由于 使用兼容性,任何可写的深度/模具附件都不能别名为另一个附件或渲染过程中使用的任何资源。
occlusionQuerySet
, of type GPUQuerySet-
、
GPUQuerySet
值定义了此过程的遮挡查询结果的存储位置。 timestampWrites
, of type GPURenderPassTimestampWrites-
定义将为此过程写入哪些时间戳值,以及将它们写入到何处。
maxDrawCount
, of type GPUSize64, defaulting to50000000
-
将在渲染过程中执行的最大绘制调用数。某些实现用于调整渲染过程之前注入的工作的大小。保持默认值是一个很好的默认值,除非已知将执行更多的绘制调用。
给定 GPUDevice
device 和 GPURenderPassDescriptor
this,以下验证规则适用:
-
this.
colorAttachments
.length 必须 ≤ device.[[limits]]
.maxColorAttachments
. -
对于每个非空 colorAttachment
colorAttachments
:-
colorAttachment 必须符合 GPURenderPassColorAttachment Valid Usage 规则。
-
-
如果 this.
depthStencilAttachment
是 provided: -
必须至少存在一个附件,或者:
-
、this.
colorAttachments
中的非null值,或 -
、this.
depthStencilAttachment
.
-
-
验证 GPURenderPassDescriptor的每个样本的颜色附件字节数(device, this.
colorAttachments
) 成功。 -
所有
view
的非null成员colorAttachments
, 和 this.depthStencilAttachment
.view
必须具有相等的sampleCount
s. -
对于
view
的非null成员。colorAttachments
和 this.depthStencilAttachment
.view
, 如果存在,则[[renderExtent]]
必须匹配。 -
如果 this.
occlusionQuerySet
不为null
:-
this.
occlusionQuerySet
.type
必须是occlusion
.
-
-
如果 this.
timestampWrites
是 provided:-
Validate timestampWrites(device, this.
timestampWrites
) 必须返回 true。
-
GPUDevice
device, sequence<GPURenderPassColorAttachment
?> colorAttachments)
-
让 formats 为空 列表<
GPUTextureFormat
?> -
对于每种 colorAttachment 在 colorAttachments:
-
如果 colorAttachment 是
undefined
,请继续。 -
Append colorAttachment.
view
.[[descriptor]]
.format
到 formats.
-
-
计算每个样本(formats) 的颜色附件字节数必须 ≤ device.
[[limits]]
.maxColorAttachmentBytesPerSample
.
17.1.1.1. 颜色附件
dictionary {
GPURenderPassColorAttachment required GPUTextureView view ;GPUTextureView resolveTarget ;GPUColor clearValue ;required GPULoadOp loadOp ;required GPUStoreOp storeOp ; };
view
, of type GPUTextureView-
描述将为此颜色附件输出到的纹理子资源的
GPUTextureView
。 resolveTarget
, of type GPUTextureView-
描述纹理子资源的
GPUTextureView
,如果view
是多采样的,该纹理子资源将接收此颜色附件的解析输出。 clearValue
, of type GPUColor-
指示在执行渲染过程之前要清除
view
的值。 如果未 provided,则默认为{r: 0, g: 0, b: 0, a: 0}
。如果loadOp
未"clear"
,则忽略。clearValue
的组成部分都是双值。 它们将转换为。 与渲染附件匹配的纹理格式的texel值 , 如果转换失败,将生成验证错误。 loadOp
, of type GPULoadOp-
指示在执行渲染过程之前要对
view
执行的加载操作。注意:建议首选清除;有关详细信息,请参见
"clear"
。 storeOp
, of type GPUStoreOp-
在执行渲染过程之后要对
view
执行的存储操作。
给定 GPURenderPassColorAttachment
this:
-
让 renderViewDescriptor 是 this.
view
.[[descriptor]]
. -
让 resolveViewDescriptor 是 this.
resolveTarget
.[[descriptor]]
. -
让 renderTexture 是 this.
view
.[[texture]]
. -
让 resolveTexture 是 this.
resolveTarget
.[[texture]]
.
以下验证规则适用:
-
-
将IDL值t this.
clearValue
转换为纹理格式 renderViewDescriptor.format
不得引发TypeError
。注意:如果值超出格式的范围,但在相应的WGSL基元类型 (
f32
,i32
, 或u32
)的范围内,则不会引发错误。
-
-
如果 this.
resolveTarget
provided:-
renderTexture.
sampleCount
必须 > 1. -
resolveTexture.
sampleCount
必须为 1. -
this.
resolveTarget
必须是 可渲染的纹理视图. -
this.
resolveTarget
和 this.view
看到的 子资源的大小必须匹配。 -
resolveViewDescriptor.
format
必须等于 renderViewDescriptor.format
. -
resolveViewDescriptor.
format
必须支持根据 § 26.1.1 纯彩色格式进行解析。
-
GPUTextureView
view 是 renderable texture view:
-
view.
[[texture]]
.usage
必须包含RENDER_ATTACHMENT
. -
descriptor.
mipLevelCount
必须是 1. -
descriptor.
arrayLayerCount
必须是 1. -
descriptor.
aspect
必须引用view.[[texture]]
的所有 方面 。
其中 descriptor 是 view.[[descriptor]]
.
参数:
-
序列<
GPUTextureFormat
?> formats
返回: GPUSize32
-
让 total 为 0.
-
对于formats中的每个非空format
-
让 renderTargetPixelByteCost 是format的 渲染目标像素字节成本 。
-
让 renderTargetComponentAlignment 是format的 渲染目标组件对齐方式 。
-
将 total 四舍五入到 renderTargetComponentAlignment 的最小倍数,该倍数大于或等于 total。
-
将 renderTargetPixelByteCost 添加到 total。
-
返回 total。
17.1.1.2. 深度/模板附件
dictionary {
GPURenderPassDepthStencilAttachment required GPUTextureView view ;float depthClearValue ;GPULoadOp depthLoadOp ;GPUStoreOp depthStoreOp ;boolean depthReadOnly =false ;GPUStencilValue stencilClearValue = 0;GPULoadOp stencilLoadOp ;GPUStoreOp stencilStoreOp ;boolean stencilReadOnly =false ; };
view
, of type GPUTextureView-
GPUTextureView
,描述将为此深度/模具附件输出和读取的纹理子源 。 depthClearValue
, of type float-
指示在执行渲染过程之前清除
view
的深度组件的值。 如果depthLoadOp
不是"clear"
,则忽略。必须介于0.0和1.0之间(包括0.0和1.0)。 depthLoadOp
, of type GPULoadOp-
指示在执行渲染过程之前要对
view
的深度组件执行的加载操作。注意:建议首选清除;有关详细信息,请参见
"clear"
for details. depthStoreOp
, of type GPUStoreOp-
在执行渲染过程之后对
view
的深度组件执行的存储操作。 depthReadOnly
, of type boolean, defaulting tofalse
-
指示
view
的深度组件是只读的。 stencilClearValue
, of type GPUStencilValue, defaulting to0
-
指示在执行渲染过程之前清除
view
的模具组件的值。如果stencilLoadOp
未"clear"
,则忽略该值。该值将通过采用与一个纹素 view 的模版方面中的位数相同的LSB数量来转换为 view的模版方面的类型。
stencilLoadOp
, of type GPULoadOp-
指示在执行渲染过程之前要对
view
的模具组件执行的加载操作。注意:建议首选清除;有关详细信息,请参见
"clear"
for details. stencilStoreOp
, of type GPUStoreOp-
在执行渲染过程后对
view
的模具组件执行的存储操作。 stencilReadOnly
, of type boolean, defaulting tofalse
-
指示
view
的模具组件是只读的。
给定 GPURenderPassDepthStencilAttachment
this,以下验证规则适用:
-
让 format 是 this.
view
.[[descriptor]]
.format
. -
如果 this.
depthLoadOp
is"clear"
, this.depthClearValue
必须 be provided ,并且必须介于0.0和1.0之间(包括0.0和1.0)。 -
如果 format 是 组合深度模具格式:
-
this.
depthReadOnly
必须等于 this.stencilReadOnly
-
-
如果 format 有深度方面,而 this.
depthReadOnly
不为true
:-
this.
depthLoadOp
必须 be provided. -
this.
depthStoreOp
必须 be provided.
否则:
-
this.
depthLoadOp
不得 be provided. -
this.
depthStoreOp
不得 be provided.
-
-
如果 format 具有模具方面,并且 this.
stencilReadOnly
不为true
:-
this.
stencilLoadOp
必须 be provided. -
this.
stencilStoreOp
必须 be provided.
否则:
-
this.
stencilLoadOp
不得 be provided. -
this.
stencilStoreOp
不得 be provided.
-
17.1.1.3. 装载和储存操作
enum {
GPULoadOp "load" ,"clear" , };
"load"
-
将此附件的现有值加载到渲染过程中。
"clear"
-
将此附件的清除值加载到渲染过程中。
注意: 在一些GPU硬件(主要是移动设备)上,
"clear"
要便宜得多, 因为它可以避免将数据从主内存加载到瓦片本地内存。 在其他GPU硬件上,没有显著差异。 因此,在初始值无关紧要的情况下 (例如,渲染目标将使用skybox清除),建议使用"clear"
而不是"load"
。
enum {
GPUStoreOp "store" ,"discard" , };
"store"
-
存储此附件的渲染过程的结果值。
"discard"
-
丢弃此附件的渲染过程的结果值。
17.1.1.4. 渲染通道布局
GPURenderPassLayout
声明 GPURenderBundle
.
的渲染目标的布局。它也在内部用于描述 GPURenderPassEncoder
布局和 GPURenderPipeline
布局。它确定渲染过程、渲染束和渲染管道之间的兼容性。
dictionary :
GPURenderPassLayout GPUObjectDescriptorBase {required sequence <GPUTextureFormat ?>colorFormats ;GPUTextureFormat depthStencilFormat ;GPUSize32 sampleCount = 1; };
colorFormats
, of typesequence<GPUTextureFormat?>
-
此过程或捆绑包的颜色附件的
GPUTextureFormat
列表。 depthStencilFormat
, of type GPUTextureFormat-
此通道或束的深度/模板附件的
GPUTextureFormat
。 sampleCount
, of type GPUSize32, defaulting to1
-
此过程或束的附件中每个像素的样本数。
GPURenderPassLayout
值 equal :
-
它们的
depthStencilFormat
和sampleCount
相等,并且 -
它们的
colorFormats
是相等的,忽略任何尾随的null
。
参数:
-
GPURenderPassDescriptor
descriptor
-
让 layout 成为一个新的
GPURenderPassLayout
对象。 -
对于 descriptor.
colorAttachments
中的每种colorAttachment :-
如果 colorAttachment 不为
null
:-
将 colorAttachment.
view
.[[texture]]
.sampleCount
设置为 layout.sampleCount
-
附加 colorAttachment.
view
.[[descriptor]]
.format
到 layout.colorFormats
.
-
-
否则:
-
附加
null
到 layout.colorFormats
.
-
-
-
让 depthStencilAttachment 为 descriptor.
depthStencilAttachment
, 或者为null
如果未 provided。 -
如果 depthStencilAttachment 不为
null
:-
让 view 为 depthStencilAttachment.
view
. -
设置 layout.
sampleCount
为 view.[[texture]]
.sampleCount
. -
设置 layout.
depthStencilFormat
为 view.[[descriptor]]
.format
.
-
-
返回 layout.
参数
-
GPURenderPipelineDescriptor
descriptor
-
让 layout 成为一个新的
GPURenderPassLayout
对象。 -
设置 layout.
sampleCount
为 descriptor.multisample
.count
. -
如果 descriptor.
depthStencil
是 provided:-
设置 layout.
depthStencilFormat
设置 descriptor.depthStencil
.format
.
-
-
如果 descriptor.
fragment
是 provided:-
对于 descriptor.
fragment
.targets
中的每种 colorTarget:-
附加 colorTarget.
format
到 layout.colorFormats
如果 colorTarget 不为null
,否则附加null
。
-
-
-
返回 layout.
17.1.2. 最终确定
一旦用户完成对过程的命令录制,就可以通过调用 end()
来结束渲染过程编码器。一旦调用了 end()
,就不能再使用渲染过程编码器了。
end()
-
完成渲染过程命令序列的记录。
设备时间线 步骤:-
让 parentEncoder 为 this.
[[command_encoder]]
. -
如果以下任何要求未得到满足,则 generate a validation error 并停止。
-
如果未满足以下任何要求,请使 parentEncoder 无效 并停止。
-
this 必须是 valid.
-
this.
[[debug_group_stack]]
必须 be empty. -
this.
[[occlusion_query_active]]
必须为false
. -
this.
[[drawCount]]
必须 ≤ this.[[maxDrawCount]]
.
-
-
Extend parentEncoder.
[[commands]]
with this.[[commands]]
. -
如果 this.
[[endTimestampWrite]]
不为null
:-
Extend parentEncoder.
[[commands]]
with this.[[endTimestampWrite]]
.
-
-
在 this上Enqueue a render command ,该命令在执行时在 队列时间轴 上发出带有renderState的后续步骤。
队列时间线 步骤:-
问题:执行附件存储/丢弃。
-
让 renderState 为
null
.
-
17.2. GPURenderCommandsMixin
GPURenderCommandsMixin
定义了 GPURenderPassEncoder
和 GPURenderBundleEncoder
通用的渲染命令。
interface mixin GPURenderCommandsMixin {undefined setPipeline (GPURenderPipeline pipeline );undefined setIndexBuffer (GPUBuffer buffer ,GPUIndexFormat indexFormat ,optional GPUSize64 offset = 0,optional GPUSize64 size );undefined setVertexBuffer (GPUIndex32 slot ,GPUBuffer ?buffer ,optional GPUSize64 offset = 0,optional GPUSize64 size );undefined draw (GPUSize32 vertexCount ,optional GPUSize32 instanceCount = 1,optional GPUSize32 firstVertex = 0,optional GPUSize32 firstInstance = 0);undefined drawIndexed (GPUSize32 indexCount ,optional GPUSize32 instanceCount = 1,optional GPUSize32 firstIndex = 0,optional GPUSignedOffset32 baseVertex = 0,optional GPUSize32 firstInstance = 0);undefined drawIndirect (GPUBuffer indirectBuffer ,GPUSize64 indirectOffset );undefined drawIndexedIndirect (GPUBuffer indirectBuffer ,GPUSize64 indirectOffset ); };
GPURenderCommandsMixin
假定在同一对象上存在 GPUObjectBase
, GPUCommandsMixin
, 和 GPUBindingCommandsMixin
成员。它必须仅由同样包含这些mixin的接口包含。
GPURenderCommandsMixin
具有以下内部插槽:
[[layout]]
,类型为GPURenderPassLayout
,只读-
渲染过程的布局。
[[depthReadOnly]]
,布尔型,只读-
如果为
true
,则表示深度分量未被修改。 [[stencilReadOnly]]
,布尔型,只读-
如果为
true
,则表示未修改模具组件。 [[pipeline]]
,类型为GPURenderPipeline
-
当前的
GPURenderPipeline
,最初为null
. [[index_buffer]]
,类型为GPUBuffer
-
从中读取索引数据的当前缓冲区,最初为
null
. [[index_format]]
,类型为GPUIndexFormat
-
[[index_buffer]]
中索引数据的格式。 [[index_buffer_offset]]
,类型为GPUSize64
-
当前设置的
[[index_buffer]]
部分的偏移量(以字节为单位)。 [[index_buffer_size]]
,类型为GPUSize64
-
当前设置的
[[index_buffer]]
的部分的字节大小, 最初为0
. [[vertex_buffers]]
,类型为 ordered map<slot,GPUBuffer
>-
要从中读取每个插槽的顶点数据的当前
GPUBuffer
,最初为空。 [[vertex_buffer_sizes]]
,类型为 ordered map<slot,GPUSize64
>-
当前为每个插槽设置的
GPUBuffer
部分的大小(以字节为单位),最初为空。 [[drawCount]]
,类型为GPUSize64
-
此编码器中记录的绘制命令数。
GPURenderCommandsMixin
编码器上 排队渲染命令 ,该 encoder 使用 RenderState renderState发出 GPU 命令 command 的步骤:
-
Append command 到 encoder.
[[commands]]
. -
当 command 作为
GPUCommandBuffer
commandBuffer命令缓冲区的一部分执行时:-
使用 commandBuffer.
[[renderState]]
作为 renderState发出command的步骤。
-
17.2.1. 绘图
setPipeline(pipeline)
-
Sets the current
GPURenderPipeline
.调用:GPURenderCommandsMixin
this.参数:
Arguments for the GPURenderCommandsMixin.setPipeline(pipeline) method. Parameter Type Nullable Optional Description pipeline
GPURenderPipeline
✘ ✘ 用于后续绘图命令的渲染管道。 返回:
undefined
内容时间线 步骤:
-
在 设备时间轴 上发布后续步骤。 this.
[[device]]
.
设备时间线 步骤:-
验证此的编码器状态 ,如果返回 false,请停止。
-
让 pipelineTargetsLayout 为 derive render targets layout from pipeline(pipeline.
[[descriptor]]
). -
如果不满足以下任何条件,则使 this 无效 并停止。
-
pipeline 是 valid to use with this.
-
this.
[[layout]]
equals pipelineTargetsLayout. -
如果 pipeline.
[[writesDepth]]
: this.[[depthReadOnly]]
必须是false
. -
如果 pipeline.
[[writesStencil]]
: this.[[stencilReadOnly]]
必须是false
.
-
-
设置 this.
[[pipeline]]
为 pipeline.
-
setIndexBuffer(buffer, indexFormat, offset, size)
-
设置当前索引缓冲区。
调用:GPURenderCommandsMixin
this.参数:
Arguments for the GPURenderCommandsMixin.setIndexBuffer(buffer, indexFormat, offset, size) method. Parameter Type Nullable Optional Description buffer
GPUBuffer
✘ ✘ 包含用于后续绘图命令的索引数据的缓冲区。 indexFormat
GPUIndexFormat
✘ ✘ buffer中包含的索引数据的格式。 offset
GPUSize64
✘ ✔ 索引数据开始的 buffer 中的偏移量(以字节为单位)。默认值为 0
。size
GPUSize64
✘ ✔ buffer中索引数据的大小(以字节为单位)。 默认为缓冲区的大小减去偏移量。 返回:
undefined
在 设备时间线 上发布以下步骤。 this.
[[device]]
:-
验证此的编码器状态 如果返回false,请停止。
-
如果 size 缺失, 设置 size 为 max(0, buffer.
size
- offset). -
如果不满足以下任何条件,则使 this 无效 并停止。
-
buffer 与此一起使用是有效的
-
offset 是 indexFormat字节大小的倍数。
-
offset + size ≤ buffer.
size
.
-
-
设置 this.
[[index_buffer]]
到 buffer. -
设置 this.
[[index_format]]
到 indexFormat. -
设置 this.
[[index_buffer_offset]]
到 offset. -
设置 this.
[[index_buffer_size]]
到 size.
-
setVertexBuffer(slot, buffer, offset, size)
-
设置给定插槽的当前顶点缓冲区。
调用:GPURenderCommandsMixin
this.参数::
Arguments for the GPURenderCommandsMixin.setVertexBuffer(slot, buffer, offset, size) method. Parameter Type Nullable Optional Description slot
GPUIndex32
✘ ✘ 要为其设置顶点缓冲区的顶点缓冲区插槽。 buffer
GPUBuffer?
✔ ✘ 包含顶点数据的缓冲区,用于后续绘图命令。 offset
GPUSize64
✘ ✔ 以字节为单位偏移到顶点数据开始的 buffer 中。默认值为 0
。size
GPUSize64
✘ ✔ buffer中顶点数据的大小(以字节为单位)。 默认为缓冲区的大小减去偏移量。 返回:
undefined
在 设备时间表 上发布以下步骤 this.
[[device]]
:-
验证此的编码器状态 。如果返回false,请停止。
-
让 bufferSize 为 0 如果 buffer 为
null
, 否则为 buffer.size
。 -
如果 size 缺失,则设置 size 为 max(0, bufferSize - offset).
-
如果以下任何要求未得到满足,则使 this 无效 并停止。
-
slot 必须 < this.
[[device]]
.[[limits]]
.maxVertexBuffers
. -
offset 必须是4的倍数。
-
offset + size 必须 ≤ bufferSize.
-
-
如果 buffer 是
null
:-
Remove this.
[[vertex_buffers]]
[slot]. -
Remove this.
[[vertex_buffer_sizes]]
[slot].
否则:
-
如果以下任何要求未得到满足,则使 this 无效 并停止。
-
buffer 必须 有效才能与此一起使用 。
-
-
设置 this.
[[vertex_buffers]]
[slot] 为 buffer. -
设置 this.
[[vertex_buffer_sizes]]
[slot] 为 size.
-
-
draw(vertexCount, instanceCount, firstVertex, firstInstance)
-
绘制基本体。 详情参见 § 23.3 渲染 。
调用:GPURenderCommandsMixin
this.参数:
Arguments for the GPURenderCommandsMixin.draw(vertexCount, instanceCount, firstVertex, firstInstance) method. Parameter Type Nullable Optional Description vertexCount
GPUSize32
✘ ✘ 要绘制的顶点数。 instanceCount
GPUSize32
✘ ✔ 要绘制的实例数。 firstVertex
GPUSize32
✘ ✔ 偏移到顶点缓冲区中,以顶点为单位,开始绘制。 firstInstance
GPUSize32
✘ ✔ 第一个要绘制的实例。 返回:
undefined
在上 设备时间表 发布以下步骤。 this.
[[device]]
:-
验证此的编码器状态。 如果返回false,请停止。
-
如果不满足以下任何条件,则使 this 无效 并停止。
-
与之一起使用 是有效的 。
-
让 buffers 为 this.
[[pipeline]]
.[[descriptor]]
.vertex
.buffers
. -
对于每一个
GPUIndex32
slot 从0
到 buffers.length (non-inclusive):-
如果 buffers[slot] 是
null
, continue. -
让 bufferSize 为 this.
[[vertex_buffer_sizes]]
[slot]. -
让 stride 为 buffers[slot].
arrayStride
. -
让 lastStride 为 max(attribute.
offset
+ sizeof(attribute.format
)) 对于每个 attribute 位于 buffers[slot].attributes
. -
让 strideCount 计算,基于 buffers[slot].
stepMode
:"vertex"
-
firstVertex + vertexCount
"instance"
-
firstInstance + instanceCount
-
如果 strideCount ≠
0
-
确保 (strideCount −
1
) × stride + lastStride ≤ bufferSize.
-
-
-
-
增加 this.
[[drawCount]]
by 1. -
让 passState 成为 this状态的快照。
队列时间线 步骤:-
绘制 instanceCount 实例,从实例 firstInstance开始,由 vertexCount 垂直组成的基本体,从顶点 firstVertex, 开始,状态来自 passState 和 renderState.
-
drawIndexed(indexCount, instanceCount, firstIndex, baseVertex, firstInstance)
-
绘制索引基元。 详情参见 § 23.3 渲染 。
调用:GPURenderCommandsMixin
this.参数:
Arguments for the GPURenderCommandsMixin.drawIndexed(indexCount, instanceCount, firstIndex, baseVertex, firstInstance) method. Parameter Type Nullable Optional Description indexCount
GPUSize32
✘ ✘ 要绘制的索引数。 instanceCount
GPUSize32
✘ ✔ 要绘制的实例数。 firstIndex
GPUSize32
✘ ✔ 偏移到索引缓冲区,在索引中,从开始绘制。 baseVertex
GPUSignedOffset32
✘ ✔ 在索引到顶点缓冲区之前添加到每个索引值。 firstInstance
GPUSize32
✘ ✔ 第一个要绘制的实例。 返回:
undefined
在 设备时间表 上发布以下步骤。 this.
[[device]]
:-
验证此的编码器状态。 如果返回false,请停止。
-
如果不满足以下任何条件,则使 this 无效 并停止。
-
firstIndex + indexCount ≤ this.
[[index_buffer_size]]
÷ this.[[index_format]]
的字节大小; -
让 buffers 是 this.
[[pipeline]]
.[[descriptor]]
.vertex
.buffers
. -
对于每一个
GPUIndex32
slot 从0
到 buffers.length (non-inclusive):-
如果 buffers[slot] 是
null
, continue. -
让 bufferSize 为 this.
[[vertex_buffer_sizes]]
[slot]. -
让 stride 为 buffers[slot].
arrayStride
. -
让 lastStride 为 max(attribute.
offset
+ sizeof(attribute.format
)) 对于每一个 attribute in buffers[slot].attributes
. -
让 strideCount 为 firstInstance + instanceCount.
-
如果 buffers[slot].
stepMode
is"instance"
和 strideCount ≠0
:-
Ensure (strideCount −
1
) × stride + lastStride ≤ bufferSize.
-
-
-
增加 this.
[[drawCount]]
1. -
让 passState 成为 this状态的快照。
-
在this上排队一个渲染命令 ,该命令在执行时在队列时间轴上发出带有 renderState 的后续步骤。
队列时间线 步骤:-
绘制 instanceCount 实例,从实例 firstInstance开始,由 indexCount 索引的垂直图元组成,从baseVertex的顶点的索引 firstIndex 开始,状态从 passState 和 renderState开始。
注意:一个有效的程序也不应该将顶点索引与超出界限
GPUVertexStepMode."vertex"
一起使用。 WebGPU 实现有不同的处理方式,因此允许一系列行为。要么放弃整个绘制调用,要 么通过WGSL的无效内存引用来描述对越界属性的访问。 -
drawIndirect(indirectBuffer, indirectOffset)
-
使用从
GPUBuffer
读取的参数绘制基本体。 详情参见 § 23.3 渲染 。缓冲区中编码的 indirect draw parameters 必须是一个由 四个32位无符号整数值(总共16字节)组成的紧密压缩块,其顺序与
draw()
的参数相同。例如:let drawIndirectParameters= new Uint32Array( 4 ); drawIndirectParameters[ 0 ] = vertexCount; drawIndirectParameters[ 1 ] = instanceCount; drawIndirectParameters[ 2 ] = firstVertex; drawIndirectParameters[ 3 ] = firstInstance; 除非启用了
"indirect-first-instance"
feature功能,否则与firstInstance
对应的值必须为0。 如果未启用"indirect-first-instance"
feature 且firstInstance
不为零,则drawIndirect()
调用将被视为 no-op。调用:GPURenderCommandsMixin
this.参数:
Arguments for the GPURenderCommandsMixin.drawIndirect(indirectBuffer, indirectOffset) method. Parameter Type Nullable Optional Description indirectBuffer
GPUBuffer
✘ ✘ 包含 间接绘制参数的缓冲区。 indirectOffset
GPUSize64
✘ ✘ 以字节为单位偏移到图形数据开始的 indirectBuffer 中。 返回:
undefined
在 设备时间表 上发布以下步骤。 this.
[[device]]
:-
验证此的编码器状态。 如果返回false,请停止。
-
如果不满足以下任何条件,则使 this 无效 并停止。
-
用 this 绘制是有效的 。
-
indirectBuffer 与此一起使用是有效的
-
indirectOffset + sizeof(indirect draw parameters) ≤ indirectBuffer.
size
. -
indirectOffset 是4的倍数。
-
-
添加 indirectBuffer 到 usage scope 作为 input.
-
增加 this.
[[drawCount]]
by 1. -
让 passState 成为 this状态的快照。
队列时间线 步骤:-
让 vertexCount 是一个从 indirectBuffer 取的无符号32位整数,位于 indirectOffset 字节。
-
让 instanceCount 是一个无符号的32位整数,从 indirectBuffer 读取 (indirectOffset + 4) 字节。
-
让 firstVertex 是一个无符号的32位整数,从 indirectBuffer 读取 (indirectOffset + 8) 字节。
-
让 firstInstance 是一个无符号的32位整数,从 indirectBuffer 读取 (indirectOffset + 12) 字节。
-
绘制 instanceCount 实例,从实例 firstInstance开始,由 vertexCount 垂直组成的基本体,从顶点 firstVertex开始,状态来自 passState 和 renderState。
-
drawIndexedIndirect(indirectBuffer, indirectOffset)
-
使用从
GPUBuffer
读取的参数绘制索引基元。 详情参见 § 23.3 渲染 。缓冲区中编码的indirect drawIndexed parameters 必须是一个由 五个32位无符号整数值(总共20字节)组成的紧密压缩块,其顺序与
drawIndexed()
的参数相同。例如:let drawIndexedIndirectParameters= new Uint32Array( 5 ); drawIndexedIndirectParameters[ 0 ] = indexCount; drawIndexedIndirectParameters[ 1 ] = instanceCount; drawIndexedIndirectParameters[ 2 ] = firstIndex; drawIndexedIndirectParameters[ 3 ] = baseVertex; drawIndexedIndirectParameters[ 4 ] = firstInstance; 除非启用了
"indirect-first-instance"
feature 功能,否则与firstInstance
对应的值必须为0。如果"indirect-first-instance"
feature 未启用且firstInstance
不为零,则drawIndexedIndirect()
调用将被视为 no-op。调用:GPURenderCommandsMixin
this.参数:
Arguments for the GPURenderCommandsMixin.drawIndexedIndirect(indirectBuffer, indirectOffset) method. Parameter Type Nullable Optional Description indirectBuffer
GPUBuffer
✘ ✘ 包含 间接drawIndexed参数的缓冲区。 indirectOffset
GPUSize64
✘ ✘ 以字节为单位偏移到图形数据开始的 indirectBuffer 中。 返回:
undefined
在设备时间表上发布以下步骤 this.
[[device]]
:-
验证此的编码器状态。 如果返回false,请停止。
-
如果不满足以下任何条件,则使 this 无效 并停止。
-
indirectBuffer 与this一起使用是有效的。
-
indirectOffset + sizeof(indirect drawIndexed parameters) ≤ indirectBuffer.
size
. -
indirectOffset 是4的倍数。
-
增加 this.
[[drawCount]]
by 1. -
让 passState 成为 this状态的快照。
队列时间线 步骤:-
让 indexCount 是一个无符号的32位整数,从 indirectBuffer 读取,位置为 indirectOffset 字节。
-
让 instanceCount 是一个无符号的32位整数,从 indirectBuffer 读取,位置为 (indirectOffset + 4) 字节。
-
让 firstIndex 是一个无符号的32位整数,从 indirectBuffer 读取,位置为 (indirectOffset + 8) b字节。
-
让 baseVertex 是一个无符号的32位整数,从 indirectBuffer 读取,位置为 (indirectOffset + 12) 字节。
-
让 firstInstance 是一个无符号的32位整数,从 indirectBuffer 读取,位置为 (indirectOffset + 16) 字节。
-
绘制 instanceCount 实例,从实例 firstInstance开始,由 indexCount 索引的垂直图元组成,从baseVertex的顶点的索引 firstIndex 开始,状态从 passState 和 renderState开始。
-
GPURenderCommandsMixin
encoder编码器是否 valid to draw 请运行以下步骤:
-
如果不满足以下任何条件,则返回
false
:-
验证编码器绑定组(encoder, encoder.
[[pipeline]]
) 必须为true
. -
让 pipelineDescriptor 为 encoder.
[[pipeline]]
.[[descriptor]]
. -
对于每一个
GPUIndex32
slot0
到 pipelineDescriptor.vertex
.buffers
.length:-
如果 pipelineDescriptor.
vertex
.buffers
[slot] 不为null
, encoder.[[vertex_buffers]]
必须 contain slot.
-
-
验证
maxBindGroupsPlusVertexBuffers
:-
让 bindGroupSpaceUsed 为 (the maximum key in encoder.
[[bind_groups]]
) + 1. -
让 vertexBufferSpaceUsed 为 (the maximum key in encoder.
[[vertex_buffers]]
) + 1. -
bindGroupSpaceUsed + vertexBufferSpaceUsed 必须是 ≤ encoder.
[[device]]
.[[limits]]
.maxBindGroupsPlusVertexBuffers
.
-
-
-
否则返回
true
.
GPURenderCommandsMixin
encoder valid to draw indexed 请运行以下步骤:
-
如果不满足以下任何条件,则返回
false
:-
使用 encoder绘制必须有效。
-
encoder.
[[index_buffer]]
必须不为null
. -
让 topology 为 encoder.
[[pipeline]]
.[[descriptor]]
.primitive
.topology
. -
如果 topology 是
"line-strip"
或"triangle-strip"
:-
encoder.
[[index_format]]
must equal encoder.[[pipeline]]
.[[descriptor]]
.primitive
.stripIndexFormat
.
-
-
-
否则返回
true
.
17.2.2. 光栅化状态
GPURenderPassEncoder
有几种方法会影响绘制命令如何光栅化到此编码器使用的附件。
setViewport(x, y, width, height, minDepth, maxDepth)
-
将光栅化阶段使用的视口设置为从标准化设备坐标线性映射到视口坐标。
调用:GPURenderPassEncoder
this.参数:
Arguments for the GPURenderPassEncoder.setViewport(x, y, width, height, minDepth, maxDepth) method. Parameter Type Nullable Optional Description x
float
✘ ✘ 视口的最小X值(以像素为单位)。 y
float
✘ ✘ 视口的最小Y值(以像素为单位)。 width
float
✘ ✘ 口的宽度(以像素为单位)。 height
float
✘ ✘ 视口的高度(以像素为单位)。 minDepth
float
✘ ✘ 视口的最小深度值。 maxDepth
float
✘ ✘ 视口的最大深度值。 返回:
undefined
内容时间线 步骤:
-
在 设备时间轴 上发布后续步骤。 this.
[[device]]
.
设备时间线 步骤:-
验证此的编码器状态。 如果返回false,请停止。
-
如果不满足以下任何条件,则使 this 无效并停止。
-
x ≥
0
-
y ≥
0
-
width ≥
0
-
height ≥
0
-
x + width ≤ this.
[[attachment_size]]
.width -
y + height ≤ this.
[[attachment_size]]
.height -
0.0 ≤ minDepth ≤ 1.0
-
0.0 ≤ maxDepth ≤ 1.0
-
minDepth < maxDepth
-
队列时间线 步骤:-
将 x, y, width, 和 height 舍入到某种统一的精度,精度不亚于整数舍入。
-
设置 renderState.
[[viewport]]
到范围 x, y, width, height, minDepth, 和 maxDepth.
-
setScissorRect(x, y, width, height)
-
设置光栅化阶段中使用的剪刀形矩形。转换到视口坐标后,落在剪刀形矩形之外的任何片段都将被丢弃。
调用:GPURenderPassEncoder
this.参数:
Arguments for the GPURenderPassEncoder.setScissorRect(x, y, width, height) method. Parameter Type Nullable Optional Description x
GPUIntegerCoordinate
✘ ✘ 剪刀形矩形的最小X值(以像素为单位)。 y
GPUIntegerCoordinate
✘ ✘ 剪刀形矩形的最小Y值(以像素为单位)。 width
GPUIntegerCoordinate
✘ ✘ 剪刀形矩形的宽度(以像素为单位)。 height
GPUIntegerCoordinate
✘ ✘ 剪刀形矩形的高度(以像素为单位)。 返回:
undefined
内容时间线 步骤:
-
在 设备时间轴 上发布后续步骤。 this.
[[device]]
.
设备时间线 步骤:-
验证此的编码器状态。 如果返回false,请停止。
-
如果不满足以下任何条件,则使 this 无效 并停止。
-
x+width ≤ this.
[[attachment_size]]
.width. -
y+height ≤ this.
[[attachment_size]]
.height.
-
-
在此上排队一个渲染命令 ,该命令在执行时在 队列时间轴 上发出带有 renderState 的后续步骤。
队列时间线 步骤:-
设置 renderState.
[[scissorRect]]
到范围 x, y, width, 和 height.
-
setBlendConstant(color)
-
设置与
"constant"
和"one-minus-constant"
GPUBlendFactor
一起使用的常量混合颜色和alpha值。调用:GPURenderPassEncoder
this.参数:
Arguments for the GPURenderPassEncoder.setBlendConstant(color) method. Parameter Type Nullable Optional Description color
GPUColor
✘ ✘ 混合时要使用的颜色。 返回:
undefined
内容时间线 步骤:
-
在 设备时间轴 上发布后续步骤。 this.
[[device]]
.
设备时间线 步骤:-
验证此的编码器状态。 如果返回false,请停止。
队列时间线 步骤:-
设置 renderState.
[[blendConstant]]
到 color.
setStencilReference(reference)
-
使用
"replace"
GPUStencilOperation
设置模具测试期间使用的[[stencilReference]]
值。调用:GPURenderPassEncoder
this.参数:
Arguments for the GPURenderPassEncoder.setStencilReference(reference) method. Parameter Type Nullable Optional Description reference
GPUStencilValue
✘ ✘ 新的模具引用值。 返回:
undefined
内容时间线 步骤:
-
在 设备时间轴上发布后续步骤。 this.
[[device]]
.
设备时间线 步骤:-
验证此的编码器状态。 如果返回false,请停止。
队列时间线 步骤:-
设置 renderState.
[[stencilReference]]
到 reference.
-
17.2.3. 查询
beginOcclusionQuery(queryIndex)
-
调用:
GPURenderPassEncoder
this.参数:
Arguments for the GPURenderPassEncoder.beginOcclusionQuery(queryIndex) method. Parameter Type Nullable Optional Description queryIndex
GPUSize32
✘ ✘ 查询集中查询的索引。 返回:
undefined
Content timeline steps:
-
Issue the subsequent steps on the Device timeline of 在 设备时间轴 上发布后续步骤。
设备时间线 步骤:-
验证此的编码器状态。 如果返回false,请停止。
-
如果不满足以下任何条件,则使 this 无效 并停止。
this.[[occlusion_query_set]]
不是null
.-
queryIndex < this.
[[occlusion_query_set]]
.count
. -
在同一个 queryIndex 的查询不能在此渲染通道中先前写入过。
-
this.
[[occlusion_query_active]]
为false
.
-
-
设置 this.
[[occlusion_query_active]]
为true
.
队列时间线 步骤:-
设置 renderState.
[[occlusionQueryIndex]]
为 queryIndex.
-
endOcclusionQuery()
-
-
设备时间线 步骤:
-
验证此的编码器状态。 如果返回false,请停止。
-
如果不满足以下任何条件,则使 this 无效 并停止。
-
this.
[[occlusion_query_active]]
为true
.
-
-
设置 this.
[[occlusion_query_active]]
为false
.
队列时间线 步骤:-
如果自相应的
beginOcclusionQuery()
命令执行以来,任何片段样本都通过了所有片段测试,则 passingFragments 为非零,否则为零。注意:如果没有发生绘制调用,则 passingFragments 为零。
-
将 passingFragments 写入 this.
[[occlusion_query_set]]
的索引 renderState.[[occlusionQueryIndex]]
.
-
17.2.4. 包
executeBundles(bundles)
-
执行先前记录到给定的
GPURenderBundle
中的命令,作为此渲染通道的一部分。执行
GPURenderBundle
时,它不会继承渲染通道的管道、绑定组或顶点和索引缓冲区。 执行GPURenderBundle
后,渲染通道的管道、绑定组和顶点/索引缓冲区状态被清除(到初始的空值)。注意:状态被清除,而不是恢复到先前的状态。 即使执行了零个
GPURenderBundles
,也会发生这种情况。调用GPURenderPassEncoder
this.参数:
Arguments for the GPURenderPassEncoder.executeBundles(bundles) method. Parameter Type Nullable Optional Description bundles
sequence<GPURenderBundle>
✘ ✘ 要执行的渲染包的列表。 返回:
undefined
内容时间线 步骤:
-
在 设备时间轴 上发布后续步骤。 this.
[[device]]
.
设备时间线 步骤:-
验证此的编码器状态。 如果返回false,请停止。
-
如果不满足以下任何条件,则使 this 无效 并停止。
-
对于 bundles 中的每个 bundle:
-
bundle 必须 与此一起使用有效。
-
this.
[[layout]]
必须等于 bundle.[[layout]]
. -
如果 this.
[[depthReadOnly]]
为真, bundle.[[depthReadOnly]]
必须为真。 -
如果 this.
[[stencilReadOnly]]
为真, bundle.[[stencilReadOnly]]
必须为真。
-
-
-
对于 bundles 中的每个 bundle:
-
将 this.
[[drawCount]]
增加 bundle.[[drawCount]]
。
-
-
Clear this.
[[bind_groups]]
. -
设置 this.
[[pipeline]]
为null
. -
设置 this.
[[index_buffer]]
为null
. -
Clear this.
[[vertex_buffers]]
. -
让 passState 成为 this状态的快照。
-
队列时间线 步骤:
-
对于 bundles 中的每个 bundle:
-
使用 passState 和 renderState 执行 bundle.
[[command_list]]
中的每个命令。注意:执行渲染包不能更改 renderState。 还要注意,渲染包看不到可变的 passState 状态。
-
-
18. 包
包是一种部分的、有限的通道,它只编码一次,然后可以作为未来通道编码器的一部分多次执行,而不像典型的命令缓冲区那样在使用后过期。 这可以减少重复发出而不改变的命令的编码和提交的开销。
18.1. GPURenderBundle
[Exposed =(Window ,DedicatedWorker ),SecureContext ]interface GPURenderBundle { };GPURenderBundle includes GPUObjectBase ;
[[command_list]]
, of type list<GPU command>-
要在执行
GPURenderBundle
时提交给GPURenderPassEncoder
的 GPU commands 的 list。 [[layout]]
, of typeGPURenderPassLayout
-
渲染包的布局。
[[depthReadOnly]]
, of type boolean-
如果为
true
,则表示执行此渲染包不会修改深度分量。 [[stencilReadOnly]]
, of type boolean-
如果为
true
,则表示执行此渲染包不会修改模板分量。 [[drawCount]]
, of typeGPUSize64
-
此
GPURenderBundle
中的绘制命令数。
18.1.1. 渲染包创建
dictionary :
GPURenderBundleDescriptor GPUObjectDescriptorBase { };
[Exposed =(Window ,DedicatedWorker ),SecureContext ]interface {
GPURenderBundleEncoder GPURenderBundle finish (optional GPURenderBundleDescriptor descriptor = {}); };GPURenderBundleEncoder includes GPUObjectBase ;GPURenderBundleEncoder includes GPUCommandsMixin ;GPURenderBundleEncoder includes GPUDebugCommandsMixin ;GPURenderBundleEncoder includes GPUBindingCommandsMixin ;GPURenderBundleEncoder includes GPURenderCommandsMixin ;
createRenderBundleEncoder(descriptor)
-
创建一个
GPURenderBundleEncoder
。调用:GPUDevice
this.参数:
Arguments for the GPUDevice.createRenderBundleEncoder(descriptor) method. Parameter Type Nullable Optional Description descriptor
GPURenderBundleEncoderDescriptor
✘ ✘ 要创建的 GPURenderBundleEncoder
的描述。内容时间线 步骤:
-
? Validate texture format required features of each non-
null
element of descriptor.colorFormats
with this.[[device]]
. -
? Validate texture format required features of descriptor.
depthStencilFormat
with this.[[device]]
. -
让 e 成为一个新的
GPURenderBundleEncoder
对象。 -
在 设备时间轴 上发布 initialization steps 。
-
返回 e.
设备时间线 initialization steps:-
如果以下任何条件不满足 generate a validation error,则使 e 无效,并停止。
-
this is valid.
-
descriptor.
colorFormats
.length must be ≤ this.[[limits]]
.maxColorAttachments
. -
For each non-
null
colorFormat in descriptor.colorFormats
:-
colorFormat must be a color renderable format.
-
-
Calculating color attachment bytes per sample(descriptor.
colorFormats
) must be ≤ this.[[limits]]
.maxColorAttachmentBytesPerSample
. -
If descriptor.
depthStencilFormat
is provided:-
descriptor.
depthStencilFormat
must be a depth-or-stencil format. -
If descriptor.
depthStencilFormat
is a combined depth-stencil format:-
descriptor.
depthReadOnly
must be equal to descriptor.stencilReadOnly
.
-
-
-
There must exist at least one attachment, either:
-
A non-
null
value in descriptor.colorFormats
, or -
A descriptor.
depthStencilFormat
.
-
-
-
将 e.
[[layout]]
设置为 descriptor 的包含的GPURenderPassLayout
接口的副本。 -
将 e.
[[depthReadOnly]]
设置为 descriptor.depthReadOnly
。 -
将 e.
[[stencilReadOnly]]
设置为 descriptor.stencilReadOnly
。 -
将 e.
[[drawCount]]
设置为 0。
问题:描述
createRenderBundleEncoder()
的步骤的重置。 -
18.1.2. 编码
dictionary :
GPURenderBundleEncoderDescriptor GPURenderPassLayout {boolean depthReadOnly =false ;boolean stencilReadOnly =false ; };
depthReadOnly
, of type boolean, defaulting tofalse
-
如果为
true
,则表示渲染包不会修改任何渲染通道中执行渲染包的GPURenderPassDepthStencilAttachment
的深度分量。 stencilReadOnly
, of type boolean, defaulting tofalse
-
如果为
true
,则表示渲染包不会修改任何渲染通道中执行渲染包的GPURenderPassDepthStencilAttachment
的模板分量。
18.1.3. 最终化
finish(descriptor)
-
完成渲染包命令序列的记录。
调用:GPURenderBundleEncoder
this.参数:
Arguments for the GPURenderBundleEncoder.finish(descriptor) method. Parameter Type Nullable Optional Description descriptor
GPURenderBundleDescriptor
✘ ✔ 返回:
GPURenderBundle
内容时间线 步骤:
-
让 renderBundle 成为一个新的
GPURenderBundle
。 -
在 设备时间轴 上发布后续步骤。 this.
[[device]]
. -
返回 renderBundle.
-
设备时间线 finish steps:
-
如果满足以下所有要求,则让 validationSucceeded 为
true
,否则为false
。-
this 必须是 valid。
-
this.
[[debug_group_stack]]
必须 be empty。 -
this 中包含的每个 usage scope 必须满足 usage scope validation。
-
-
如果 validationSucceeded 为
false
,则:-
返回一个新的 invalid
GPURenderBundle
。
-
将 renderBundle.
[[command_list]]
设置为 this.[[commands]]
. -
将 renderBundle.
[[drawCount]]
设置为 this.[[drawCount]]
.
-
19. 查询
19.1. GPUQueueDescriptor
GPUQueueDescriptor
描述了一个队列请求。
dictionary GPUQueueDescriptor :GPUObjectDescriptorBase { };
19.2. GPUQueue
[Exposed =(Window ,DedicatedWorker ),SecureContext ]interface GPUQueue {undefined submit (sequence <GPUCommandBuffer >commandBuffers );Promise <undefined >onSubmittedWorkDone ();undefined writeBuffer (GPUBuffer buffer ,GPUSize64 bufferOffset , [AllowShared ]BufferSource data ,optional GPUSize64 dataOffset = 0,optional GPUSize64 size );undefined writeTexture (GPUImageCopyTexture destination , [AllowShared ]BufferSource data ,GPUImageDataLayout dataLayout ,GPUExtent3D size );undefined copyExternalImageToTexture (GPUImageCopyExternalImage source ,GPUImageCopyTextureTagged destination ,GPUExtent3D copySize ); };GPUQueue includes GPUObjectBase ;
GPUQueue
有以下方法:
writeBuffer(buffer, bufferOffset, data, dataOffset, size)
-
将提供的数据写入
GPUBuffer
中。调用:GPUQueue
this.参数:
Arguments for the GPUQueue.writeBuffer(buffer, bufferOffset, data, dataOffset, size) method. Parameter Type Nullable Optional Description buffer
GPUBuffer
✘ ✘ 要写入的缓冲区。 bufferOffset
GPUSize64
✘ ✘ 要开始写入的字节偏移量。 data
BufferSource
✘ ✘ 要写入 buffer 的数据。 dataOffset
GPUSize64
✘ ✔ 要从中开始写入的 data 中的偏移量。如果 data 是 TypedArray
,则以元素为单位,否则以字节为单位。size
GPUSize64
✘ ✔ 要从 data 写入 buffer 的内容的大小。如果 data 是 TypedArray
,则以元素为单位,否则以字节为单位。返回:
undefined
内容时间线 步骤:
-
如果 data 是
ArrayBuffer
或DataView
,则将元素类型设置为 "byte"。否则,data 是 TypedArray;将元素类型设置为 TypedArray 的类型。 -
让 dataSize 成为 data 的大小,以元素为单位。
-
如果 size 丢失,则让 contentsSize 成为 dataSize − dataOffset。否则,让 contentsSize 成为 size。
-
如果不满足以下任何条件,则抛出
OperationError
并停止。-
contentsSize ≥ 0.
-
dataOffset + contentsSize ≤ dataSize.
-
contentsSize,转换为字节,是 4 字节的倍数。
-
-
让 dataContents 成为 a copy of the bytes held by the buffer source。
-
让 contents 成为从 dataOffset 元素开始的 dataContents 的 contentsSize 元素。
-
在 this 的 Device timeline 上发布后续步骤。
设备时间线 步骤:-
If any of the following conditions are unsatisfied, 如果不满足以下任何条件,则 generate a validation error 并停止。
-
buffer 是 valid to use with this。
-
buffer.
[[internals]]
.state 是 "available"。 -
bufferOffset,转换为字节,是 4 字节的倍数。
-
bufferOffset + contentsSize,转换为字节,≤ buffer.
size
字节。
-
-
从 bufferOffset 开始将 contents 写入 buffer。
-
writeTexture(destination, data, dataLayout, size)
-
将提供的数据写入
GPUTexture
中。调用:GPUQueue
this.参数:
Arguments for the GPUQueue.writeTexture(destination, data, dataLayout, size) method. Parameter Type Nullable Optional Description destination
GPUImageCopyTexture
✘ ✘ 要写入的 texture subresource 和原点。 data
BufferSource
✘ ✘ 要写入 destination 的数据。 dataLayout
GPUImageDataLayout
✘ ✘ data 中内容的布局。 size
GPUExtent3D
✘ ✘ 要从 data 写入 destination 的内容的范围。 返回:
undefined
内容时间线 步骤:
-
? validate GPUOrigin3D shape(destination.
origin
). -
? validate GPUExtent3D shape(size).
-
dataBytes 成为 a copy of the bytes held by the buffer source data。
-
在 this 的 Device timeline 上发布后续步骤。
设备时间线 步骤:-
让 texture 成为 destination.
texture
。 -
If any of the following conditions are unsatisfied, 如果不满足以下任何条件,则 generate a validation error 并停止。
-
validating GPUImageCopyTexture(destination, size) 返回
true
。 -
texture.
sampleCount
是 1。 -
validating texture copy range(destination, size) 返回
true
。 -
该方面必须根据 § 26.1.2 深度模具格式 是有效的图像复制目标。
-
让 aspectSpecificFormat = texture.
format
。 -
如果 texture.
format
是 depth-or-stencil format:-
根据 § 26.1.2 深度模具格式,将 aspectSpecificFormat 设置为 texture.
format
的 aspect-specific format。
-
-
validating linear texture data(dataLayout, dataBytes.length, aspectSpecificFormat, size) succeeds.
注意:与
GPUCommandEncoder
.copyBufferToTexture()
不同,dataLayout.bytesPerRow
或 dataLayout.offset
上没有对齐要求。 -
-
让 contents 成为通过使用 dataLayout 和 size 查看 dataBytes 的 images 的内容。
问题:更正式地指定。
注意:这被描述为将 data 的所有内容复制到设备时间线,但实际上 data 可能比必要的大得多。实现应通过仅复制必要的字节来优化。
-
在 this 的 Queue timeline 上发布后续步骤。
Queue timeline 步骤:-
将 contents 写入 destination。
问题:定义复制,包括 snorm 的规定。
-
copyExternalImageToTexture(source, destination, copySize)
-
将平台图像/画布的内容复制到目标纹理中。
此操作根据
GPUImageCopyTextureTagged
的参数执行 color encoding 到目标编码。复制到
-srgb
纹理会导致相同的纹理字节,而不是相同的解码值,就像复制到相应的非-srgb
格式一样。因此,在复制操作之后,根据其格式是否为-srgb
,对目标纹理进行采样会产生不同的结果,其他都不变。调用:GPUQueue
this.参数:
Arguments for the GPUQueue.copyExternalImageToTexture(source, destination, copySize) method. Parameter Type Nullable Optional Description source
GPUImageCopyExternalImage
✘ ✘ 要复制到 destination 的源图像和原点。 destination
GPUImageCopyTextureTagged
✘ ✘ 要写入的 texture subresource 和原点,以及其编码元数据。 copySize
GPUExtent3D
✘ ✘ 要从 source 写入 destination 的内容的范围。 返回:
undefined
内容时间线 步骤:
-
? validate GPUOrigin2D shape(source.
origin
). -
? validate GPUOrigin3D shape(destination.
origin
). -
? validate GPUExtent3D shape(copySize).
-
让 sourceImage 为 source.
source
-
如果 sourceImage is not origin-clean,则抛出
SecurityError
并停止。 -
如果不满足以下任何要求,则抛出
OperationError
并停止。 -
让 usability 为 ? check the usability of the image argument(source).
-
在 this 的 设备时间线 上发布后续步骤。
设备时间线 步骤:-
让 texture 成为 destination.
texture
。 -
如果不满足以下任何要求,则 generate a validation error 并停止。
-
usability 必须是
good
。 -
destination.
texture
必须是 valid to use with this。 -
validating GPUImageCopyTexture(destination, copySize) 必须返回
true
。 -
validating texture copy range(destination, copySize) 必须返回
true
。 -
texture.
usage
必须包括RENDER_ATTACHMENT
和COPY_DST
。 -
texture.
sampleCount
必须是 1。 -
texture.
format
必须是以下格式之一 格式(所有这些格式都支持RENDER_ATTACHMENT
用法):
-
-
问题:执行实际的复制。
-
submit(commandBuffers)
-
GPU 在此队列上安排执行命令缓冲区。
提交的命令缓冲区不能再次使用。
调用:GPUQueue
this.参数:
Arguments for the GPUQueue.submit(commandBuffers) method. Parameter Type Nullable Optional Description commandBuffers
sequence<GPUCommandBuffer>
✘ ✘ 返回:
undefined
内容时间线 步骤:
-
在 this 的 设备时间线 上发布后续步骤。
设备时间线 步骤:-
如果不满足以下任何要求,则 generate a validation error 并停止。
-
commandBuffers 中的每个
GPUCommandBuffer
必须是 valid to use with this。 -
对于 commandBuffers 的任何元素中的任何命令使用的以下类型的资源:
GPUBuffer
b-
b.
[[internals]]
.state 必须是 "available". GPUTexture
t-
t.
[[destroyed]]
必须是false
. GPUExternalTexture
et-
et.
[[expired]]
必须是false
. GPUQuerySet
qs-
qs 必须处于 available 状态。对于遮挡查询,
beginRenderPass()
中的occlusionQuerySet
除非也被beginOcclusionQuery()
使用,否则不会 "used"。
-
-
对于 commandBuffers 中的每个 commandBuffer:
-
使 commandBuffer invalid。
-
-
在 this 的 Queue timeline 上发布后续步骤。
队列时间线 步骤:-
对于 commandBuffers 中的每个 commandBuffer:
-
执行 commandBuffer.
[[command_list]]
中的每个命令。
-
-
onSubmittedWorkDone()
-
返回一个
Promise
,一旦此队列完成处理到目前为止提交的所有工作,就会解析。此
Promise
的解析意味着在该调用之前对GPUBuffer
s 进行的mapAsync()
调用的完成,该调用仅在该队列上独占使用。调用:GPUQueue
this.内容时间线 步骤:
-
让 contentTimeline 成为当前的 Content timeline。
-
让 promise 成为 a new promise。
-
在 this 的 Device timeline 上发布 synchronization steps。
-
返回 promise。
Device timeline synchronization steps: // Device timeline synchronization steps:-
当 device timeline 被告知 this 上的所有 currently-enqueued operations 的完成,或者如果 this 丢失,或者当 this becomes lost 时:
-
在 contentTimeline 上发布后续步骤。
-
Content timeline 步骤:-
Resolve promise.
-
20. 查询
20.1. GPUQuerySet
[Exposed =(Window ,DedicatedWorker ),SecureContext ]interface GPUQuerySet {undefined destroy ();readonly attribute GPUQueryType type ;readonly attribute GPUSize32 count ; };GPUQuerySet includes GPUObjectBase ;
GPUQuerySet
有以下属性:
type
, of type GPUQueryType, readonly-
此
GPUQuerySet
管理的查询的类型。 count
, of type GPUSize32, readonly-
此
GPUQuerySet
管理的查询的数量。
GPUQuerySet
有以下内部槽:
[[state]]
, of type query set state-
此
GPUQuerySet
的当前状态。
每个 GPUQuerySet
在 Device timeline 上都有一个当前的 query set state,它是以下之一:
- "available"
-
GPUQuerySet
可用于其内容的 GPU 操作。 - "destroyed"
-
GPUQuerySet
不再可用于除destroy
之外的任何操作。
20.1.1. 查询集创建
GPUQuerySetDescriptor
指定在创建 GPUQuerySet
时要使用的选项。
dictionary :
GPUQuerySetDescriptor GPUObjectDescriptorBase {required GPUQueryType type ;required GPUSize32 count ; };
type
, of type GPUQueryType-
GPUQuerySet
管理的查询的类型。 count
, of type GPUSize32-
GPUQuerySet
管理的查询的数量。
createQuerySet(descriptor)
-
Creates a
GPUQuerySet
.调用:GPUDevice
this.参数:
Arguments for the GPUDevice.createQuerySet(descriptor) method. Parameter Type Nullable Optional Description descriptor
GPUQuerySetDescriptor
✘ ✘ 要创建的 GPUQuerySet
的描述。返回:
GPUQuerySet
内容时间线 步骤:
-
如果 descriptor.
type
是"timestamp"
, 但"timestamp-query"
未 enabled for this:-
抛出
TypeError
。
-
-
让 q 成为一个新的
GPUQuerySet
对象。 -
在 this 的 Device timeline 上发布 initialization steps。
-
返回 q。
Device timeline initialization steps:-
如果不满足以下任何要求,则 generate a validation error,使 q invalid,并停止。
-
GPUQuerySet
。
const querySet= gpuDevice. createQuerySet({ type: 'occlusion' , count: 32 });
20.1.2. 查询集销毁
不再需要 GPUQuerySet
的应用程序可以选择在垃圾回收之前通过调用 destroy()
来丢失对它的访问。
destroy()
-
销毁
GPUQuerySet
。
20.2. 查询类型
enum {
GPUQueryType ,
"occlusion" , };
"timestamp"
20.3. 遮挡查询
遮挡查询仅在渲染通道上可用,用于查询一组绘图命令的所有片段测试通过的片段样本数,包括剪刀、样本掩码、alpha 到覆盖、模板和深度测试。查询的任何非零结果值都表示至少有一个样本通过了测试并到达了渲染管道的输出合并阶段,0 表示没有样本通过了测试。
在开始渲染通道时,GPURenderPassDescriptor
.occlusionQuerySet
必须设置为能够在通道期间使用遮挡查询。通过调用 beginOcclusionQuery()
和 endOcclusionQuery()
来开始和结束遮挡查询,这些调用不能嵌套。
20.4. 时间戳查询
时间戳查询允许应用程序将时间戳写入 GPUQuerySet
,使用:
然后使用 GPUCommandEncoder
.resolveQuerySet()
将时间戳值(以 64 位无符号整数的纳秒为单位)解析到 GPUBuffer
中。
时间戳查询需要 "timestamp-query"
在设备上 enabled for。
注意:如果物理设备重置时间戳计数器,则时间戳值可能为零,请忽略它和以下值。
Issue(gpuweb/gpuweb#4069):编写关于时间戳值重置的规范文本。
时间戳查询可以提供高分辨率的 GPU 计时。 有关安全考虑,请参见 § 2.1.7 定时攻击。
GPUDevice
device, (GPUComputePassTimestampWrites
or GPURenderPassTimestampWrites
)
timestampWrites)
如果满足以下要求,则返回 true
,否则返回 false
。
-
"timestamp-query"
必须 enabled for device. -
timestampWrites.
querySet
必须 valid to use with device. -
timestampWrites.
querySet
.type
必须"timestamp"
. -
在 timestampWrites 中的写入索引成员(
beginningOfPassWriteIndex
、endOfPassWriteIndex
)中:
21. Canvas 渲染
21.1. HTMLCanvasElement.getContext()
GPUCanvasContext
对象由 HTMLCanvasElement
中的 getContext()
方法创建。
通过传递字符串字面量 'webgpu'
实例化其 contextType
参数。
HTMLCanvasElement
获取一个 GPUCanvasContext
:
const canvas= document. createElement( 'canvas' ); const context= canvas. getContext( 'webgpu' );
与WebGL或2D上下文创建不同的是, HTMLCanvasElement.getContext()
或 OffscreenCanvas.getContext()
的第二个参数,即上下文创建属性字典 options
会被忽略。而是使用 GPUCanvasContext.configure()
来改变画布的配置,而无需替换画布本身。
HTMLCanvasElement
或 OffscreenCanvas
) canvas:
-
使 context 成为一个新的
GPUCanvasContext
. -
设置 context.
canvas
为 canvas. -
Replace the drawing buffer of context.
-
返回 context.
注意:当调用 getContext()
获取 WebGPU 画布上下文时,用户代理应考虑在提供了被忽略的 options
参数时发出对开发者可见的警告。
21.2. GPUCanvasContext
[Exposed =(Window ,DedicatedWorker ),SecureContext ]interface {
GPUCanvasContext readonly attribute (HTMLCanvasElement or OffscreenCanvas )canvas ;undefined configure (GPUCanvasConfiguration configuration );undefined unconfigure ();GPUTexture getCurrentTexture (); };
GPUCanvasContext
有下列属性:
canvas
, of type(HTMLCanvasElement or OffscreenCanvas)
, readonly-
context 创建位置的画布。
GPUCanvasContext
具有以下内部槽位(internal slots):
[[configuration]]
,GPUCanvasConfiguration
? 类型, 初始为null
-
当前为该上下文配置的选项。
如果上下文尚未配置或已被
取消配置
,则为null
。 [[textureDescriptor]]
,GPUTextureDescriptor
? 类型, 初始为null
-
当前配置的纹理描述符,根据
[[configuration]]
和画布派生而来。如果上下文尚未配置或已被
取消配置
,则为null
。 [[drawingBuffer]]
, 图像, 初始为 一个与画布大小相同的透明黑色图像。-
绘图缓冲区是画布的工作副本图像数据。它通过
[[currentTexture]]
(由getCurrentTexture()
返回)可写访问。绘图缓冲区用于get a copy of the image contents of a context,这在画布被显示或以其他方式读取时发生。即使
[[configuration]]
.alphaMode
是"opaque"
,它也可能是透明的。alphaMode
仅影响 get a copy of the image contents of a context 算法的结果。绘图缓冲区的生命周期超过
[[currentTexture]]
,并且即使画布已经呈现,它仍然包含先前渲染的内容。它只在“Replace the drawing buffer”时被清除。每当读取绘图缓冲区时,实现必须确保所有先前提交的工作(例如队列提交)通过
[[currentTexture]]
已完成对其的写入。 [[currentTexture]]
,GPUTexture
? 类型, 初始为null
-
GPUTexture
用于当前帧绘制的纹理。 它提供了对底层[[drawingBuffer]]
的可写视图。 如果null
,则getCurrentTexture()
会填充该槽,然后返回它。在可见画布的稳态下,通过 currentTexture 对绘图缓冲区进行的任何更改在 updating the rendering of a WebGPU canvas 时呈现出来。 在此点或之前,纹理也会被销毁,
[[currentTexture]]
被设置为 null,表示下一个调用getCurrentTexture()
将创建一个新的纹理。销毁
currentTexture 对绘图缓冲区内容没有影响,它只会提前终止对绘图缓冲区的写访问。 在同一帧中,getCurrentTexture()
仍然返回相同的已销毁纹理。Expire the current texture 将 currentTexture 设置为
null
。 它由configure()
、画布调整大小、呈现、transferToImageBitmap()
和其他操作调用。
GPUCanvasContext
有下列方法:
configure(configuration)
-
配置此画布的上下文。 这将清除绘图缓冲区,使其变为透明黑色(在 Replace the drawing buffer 中)。
Called on:GPUCanvasContext
this.参数:
Arguments for the GPUCanvasContext.configure(configuration) method. Parameter Type Nullable Optional Description configuration
GPUCanvasConfiguration
✘ ✘ 期望的上下文配置。 返回: undefined
Content timeline 步骤:
-
令 device 为 configuration 的
device
。 -
? 使用 device.
[[device]]
验证 configuration.format
的 Validate texture format required features 。 -
? 对于 configuration.
viewFormats
中的每个元素,使用 device.[[device]]
Validate texture format required features 。 -
令 descriptor 为 GPUTextureDescriptor for the canvas and configuration(this.
canvas
, configuration)。 -
将 this.
[[configuration]]
设置为 configuration。 -
将 this.
[[textureDescriptor]]
设置为 descriptor。 -
Replace the drawing buffer,重置 this.
[[drawingBuffer]]
为具有新格式和标签的位图。 -
在 device 的 Device timeline 上执行后续步骤。
Device timeline 步骤:-
如果以下任何要求未满足,则 generate a validation error 并停止。
-
validating GPUTextureDescriptor(device, descriptor) 必须返回 true。
-
Supported context formats 必须 contain configuration.
format
.
注意:这种早期验证在下一次
configure()
调用之前仍然有效,但是在画布调整大小时,size
的验证会发生变化。 -
-
unconfigure()
-
移除上下文配置。销毁在配置期间创建的任何纹理。
Called on:GPUCanvasContext
this.返回: undefined
Content timeline 步骤:
-
将 this.
[[configuration]]
设置为null
。 -
将 this.
[[textureDescriptor]]
设置为null
。 -
Replace the drawing buffer,重置 this 的绘图缓冲区。
-
getCurrentTexture()
-
获取下一个将由
GPUCanvasContext
合成到文档中的GPUTexture
。注意: 应用程序应在渲染到画布纹理的同一任务中调用getCurrentTexture()
。 否则,在应用程序完成对其进行渲染之前,纹理可能会被这些步骤销毁。过期任务(如下所定义)是可选实现的。 即使实现了过期任务,任务源的优先级没有明确定义,因此可能会在下一个任务中或在所有其他任务源为空之后发生(请参阅 automatic expiry task source)。 只有在显示可见画布(updating the rendering of a WebGPU canvas)以及其他调用者 Replace the drawing buffer 时,过期才得到保证。
Called on:GPUCanvasContext
this.返回:
GPUTexture
Content timeline 步骤:
-
如果 this.
[[configuration]]
是null
:-
抛出一个
InvalidStateError
并停止。
-
-
Assert this.
[[textureDescriptor]]
不是null
。 -
令 device 为 this.
[[configuration]]
.device
。 -
如果 this.
[[currentTexture]]
是null
:-
将 this.
[[currentTexture]]
设置为调用 device.createTexture()
的结果, 参数为 this.[[textureDescriptor]]
,但使用GPUTexture
的底层存储指向 this.[[drawingBuffer]]
。注意: 如果无法创建纹理(例如由于验证失败或内存不足),则会生成错误并返回一个无效的
GPUTexture
。 这里的一些验证与configure()
中的验证重复。实现 不得 跳过这些重复的验证。
-
可选地,queue an automatic expiry task,使用设备 device 和以下步骤:
-
Expire the current texture,对 this 执行该操作。
注意:如果在 updating the rendering of a WebGPU canvas 时已经发生过此操作,则其不会产生任何效果。
-
-
返回 this.
[[currentTexture]]
.
注意:在 "Expire the current texture" 运行之前,每次调用
getCurrentTexture()
都将返回相同的GPUTexture
对象,即使该GPUTexture
被销毁、验证失败或分配失败。 -
参数:
-
context: the
GPUCanvasContext
返回: image contents
-
确保所有提交的工作项(例如队列提交)已完成对图像(通过 context.
[[currentTexture]]
)的写入。 -
令 snapshot 为 context.
[[drawingBuffer]]
的副本。 -
令 alphaMode 为 context.
[[configuration]]
.alphaMode
。 -
- 如果 alphaMode 是
"opaque"
: -
-
将 snapshot 的 alpha 通道清除为 1.0。
-
将 snapshot 标记为不透明。
注意: 如果
[[currentTexture]]
(如果有的话)已被销毁(例如在 Replace the drawing buffer 中),则无法观察到 alpha 通道,实现可能会原地清除 alpha 通道。 -
- 否则:
-
使用 alphaMode 对 snapshot 进行标记。
- 如果 alphaMode 是
-
返回 snapshot。
GPUCanvasContext
context 执行 Replace the drawing buffer :
-
Expire the current texture,对 context 执行该操作。
-
令 configuration 为 context.
[[configuration]]
。 -
将 context.
[[drawingBuffer]]
设置为与 context.canvas
相同尺寸的透明黑色图像。-
如果 configuration 为 null,则绘图缓冲区标记为颜色空间
"srgb"
。 在这种情况下,绘图缓冲区将保持空白,直到配置上下文。 -
如果不是,则绘图缓冲区具有指定的 configuration.
format
, 并带有指定的 configuration.colorSpace
标记。
-
注意:在 "get a copy of the image contents of a context" 之前,将忽略 configuration.alphaMode
。
注意:如果绘图缓冲区已经被清除并具有正确的配置,这通常不会产生任何操作。
GPUCanvasContext
context:
-
如果 context.
[[currentTexture]]
不为null
:-
调用 context.
[[currentTexture]]
.destroy()
(不销毁 context.[[drawingBuffer]]
)终止图像的写权限。 -
将 context.
[[currentTexture]]
设定为null
.
-
21.3. HTML 规范 Hooks
以下算法 "hook" 到 HTML 规范中的算法中,并必须在指定的时机运行。
GPUCanvasContext
context 的 HTMLCanvasElement
或 OffscreenCanvas
读取 "位图(bitmap)" 时:
-
返回 context 的 图像副本。
注意: 这种情况发生在许多地方,包括:-
当
HTMLCanvasElement
的渲染更新时。 -
当具有 placeholder canvas element 的
OffscreenCanvas
的渲染更新时。 -
当通过
transferToImageBitmap()
从位图创建ImageBitmap
时。 -
当使用其他 Web API(如
drawImage()
、texImage2D()
、texSubImage2D()
、toDataURL()
、toBlob()
等)读取 WebGPU 画布内容时。
如果
alphaMode
是"opaque"
, 这将导致 alpha 通道被清除。当实现能够以忽略 alpha 通道的方式读取或显示图像时,实现可能会跳过此步骤。如果应用程序仅需要用于交互操作(而非呈现),则在不需要时避免使用
"opaque"
。 -
HTMLCanvasElement
或一个具有 placeholder canvas element 的 OffscreenCanvas
)
在具有 GPUCanvasContext
context 的 HTMLCanvasElement
或具有 placeholder canvas element 的 OffscreenCanvas
中,
这会在 event loop processing model 的以下子步骤中发生:
-
"更新
Document
的渲染或用户界面" -
"更新专用 worker 的渲染"
执行以下步骤:
-
对 context 运行 Expire the current texture。
注意:如果这已经在由 getCurrentTexture()
排队的任务中发生过,
则没有任何效果。
注意:
这不适用于独立的 OffscreenCanvas
(通过 new OffscreenCanvas()
创建的)。
GPUCanvasContext
context 的画布上调用 transferToImageBitmap()
时,在从画布的位图创建 ImageBitmap
后:
-
对 context 运行 Replace the drawing buffer。
注意:这相当于将(可能已清除 alpha 通道)的图像内容 "移动" 到 ImageBitmap 中,而不进行复制。
21.4. GPU画布配置(CanvasConfiguration)
supported context formats 是一个 set 的 GPUTextureFormat
,当作为 GPUCanvasConfiguration
.format
指定时,
无论给定的 GPUCanvasConfiguration
.device
如何,都必须支持这些格式。
初始设置为:«;"bgra8unorm"
, "rgba8unorm"
, "rgba16float"
»。
注意:画布配置不能使用 srgb
格式,如 "bgra8unorm-srgb"
。而应使用非 srgb
等效格式("bgra8unorm"
),在 viewFormats
中指定 srgb
格式,并使用 createView()
创建具有 srgb
格式的视图。
enum GPUCanvasAlphaMode {"opaque" ,"premultiplied" , };dictionary {
GPUCanvasConfiguration required GPUDevice device ;required GPUTextureFormat format ;GPUTextureUsageFlags usage = 0x10; // GPUTextureUsage.RENDER_ATTACHMENTsequence <GPUTextureFormat >viewFormats = [];PredefinedColorSpace colorSpace = "srgb";GPUCanvasAlphaMode alphaMode = "opaque"; };
GPUCanvasConfiguration
有下列成员:
device
, of type GPUDevice-
getCurrentTexture()
返回的纹理与之兼容的GPUDevice
。 format
, of type GPUTextureFormat-
getCurrentTexture()
返回的纹理格式。 必须是 Supported context formats 中的一个。 usage
, of type GPUTextureUsageFlags, defaulting to0x10
-
getCurrentTexture()
返回的纹理使用方式。RENDER_ATTACHMENT
是默认值,但如果显式设置了使用方式,则不会自动包括它。 如果希望将getCurrentTexture()
返回的纹理用作渲染通道的颜色目标,请确保在设置自定义使用方式时包括RENDER_ATTACHMENT
。 viewFormats
, of type sequence<GPUTextureFormat>, defaulting to[]
-
从
getCurrentTexture()
返回的纹理创建的视图可以使用的格式。 colorSpace
, of type PredefinedColorSpace, defaulting to"srgb"
-
getCurrentTexture()
返回的纹理中写入的值应该使用的颜色空间进行显示。 alphaMode
, of type GPUCanvasAlphaMode, defaulting to"opaque"
-
确定 alpha 值对从
getCurrentTexture()
返回的纹理内容在读取、显示或用作图像源时的影响。
GPUDevice
配置 GPUCanvasContext
,使用此context的首选格式:
const canvas= document. createElement( 'canvas' ); const context= canvas. getContext( 'webgpu' ); context. configure({ device: gpuDevice, format: navigator. gpu. getPreferredCanvasFormat(), });
HTMLCanvasElement
或 OffscreenCanvas
) canvas, GPUCanvasConfiguration
configuration)
是有以下成员的 GPUTextureDescriptor
:
-
size
: [canvas.width, canvas.height, 1]. -
viewFormats
: configuration.viewFormats
.
并将其他成员设置为它们的默认值。
canvas.width 表示 HTMLCanvasElement
.width
或 OffscreenCanvas
.width
. canvas.height 表示 HTMLCanvasElement
.height
或 OffscreenCanvas
.height
.
21.4.1. 画布颜色空间
在演示过程中,色值在 [0, 1] 范围之外的色度不应被截断至该范围;当format
和用户的显示能力允许时,可以使用扩展值来显示画布 “颜色空间” 原色定义之外的颜色。
这与亮度相反,亮度应被截断至最大标准动态范围亮度。
21.4.2. 画布上下文的尺寸调整(Context sizing)
所有画布配置都在configure()
中进行设置,除了画布的分辨率,分辨率是通过画布的 width
和 height
来设置的。
注意: 与WebGL和2D画布一样,调整WebGPU画布的大小会导致绘图缓冲区的当前内容丢失。 在WebGPU中,它通过replacing the drawing buffer来实现这一点。
GPUCanvasContext
context的HTMLCanvasElement
或OffscreenCanvas
canvas的 width
或 height
属性被修改时, update the canvas size:
-
Replace the drawing buffer为 context。
-
将 configuration 设为 context.
[[configuration]]
。 -
如果 configuration 不为
null
:-
将 context.
[[textureDescriptor]]
设置为 GPUTextureDescriptor for the canvas and configuration(canvas, configuration)。
-
注意:这可能导致GPUTextureDescriptor
超过设备的maxTextureDimension2D
。
在这种情况下,验证将在getCurrentTexture()
中失败。
GPUCanvasContext
以获取画布的准确像素尺寸:
const canvas= document. createElement( 'canvas' ); const context= canvas. getContext( 'webgpu' ); const resizeObserver= new ResizeObserver( entries=> { for ( const entryof entries) { if ( entry. target!= canvas) { continue ; } canvas. width= entry. devicePixelContentBoxSize[ 0 ]. inlineSize; canvas. height= entry. devicePixelContentBoxSize[ 0 ]. blockSize; } }); resizeObserver. observe( canvas);
21.5. GPUCanvasAlphaMode
此枚举用于选择当读取画布内容时,画布的内容在显示到屏幕或作为图像源(在drawImage、toDataURL等中使用)时将如何被解释。
以下,src
是画布纹理中的值,dst
是画布被合成到的图像(例如HTML页面渲染或2D画布)。
"opaque"
-
将 RGB 作为不透明色,并忽略 alpha 值。 如果内容尚未不透明,则在 "get a copy of the image contents of a context" 中将 alpha 通道清除为 1.0。
"premultiplied"
-
以预乘方式读取 RGBA:颜色值通过其 alpha 值进行预乘。 50% alpha 的 100% 红色为
[0.5, 0, 0, 0.5]
。如果输出到画布的out-of-gamut premultiplied RGBA values,且画布是:
- 作为图像源
-
值将按照 颜色空间转换 中描述的方式进行保留。
- 显示到屏幕
-
合成结果是未定义的。即使在合成之前颜色空间转换会产生在色域内的值也是如此,因为合成的中间格式没有指定。
22. 错误 & 调试
在一般情况下,WebGPU的正常操作过程中,通过dispatch error来引发错误。
在设备 丢失(描述如下) 后,不再暴露错误。
此时,实现不需要运行验证或错误跟踪: popErrorScope()
和 uncapturederror
停止报告错误,
并且设备上对象的有效性变得不可观察。
此外,设备丢失本身不会产生错误。
相反的,GPUDevice
.lost
promise 解析来指示设备已丢失。
22.1. 致命错误
enum {
GPUDeviceLostReason ,
"unknown" , }; [
"destroyed" Exposed =(Window ,DedicatedWorker ),SecureContext ]interface {
GPUDeviceLostInfo readonly attribute GPUDeviceLostReason ;
reason readonly attribute DOMString ; };
message partial interface GPUDevice {readonly attribute Promise <GPUDeviceLostInfo >lost ; };
GPUDevice
有下列额外的属性:
lost
, of type Promise<GPUDeviceLostInfo>, readonly-
一个 slot-backed attribute 持有一个 promise,该 promise 在设备创建时创建,设备的生命周期内保持 pending,然后在设备丢失时解析。 在初始化时,它被设置为 a new promise。
22.2. GPUError
[Exposed =(Window ,DedicatedWorker ),SecureContext ]interface GPUError {readonly attribute DOMString message ; };
GPUError
是从 popErrorScope()
和 uncapturederror
事件中暴露的所有错误的基本接口。
错误只能在其各自的算法中明确说明可能生成的条件和生成的错误子类型的操作中生成。
在设备丢失后不会生成错误。参见§ 22 错误 & 调试。
注意:GPUError
可能在本规范的将来版本中获得新的子类型。应用程序应该处理这种可能性,尽可能使用错误的 message
,并使用 instanceof
进行特化。当需要序列化错误(例如,进入 JSON,用于调试报告)时,请使用 error.constructor.name
。
GPUError
具有以下属性:
message
, of type DOMString, readonly-
一个人类可读的,提供有关发生的错误的信息的 localizable text 消息。
注意:此消息通常用于应用程序开发人员调试其应用程序并捕获调试报告的信息,而不是向最终用户显示。
注意:用户代理不应在此消息中包含可能的机器可解析细节,例如
"out-of-memory"
上的空闲系统内存或内存耗尽的其他条件的其他细节。注意:
message
应遵循 best practices for language and direction information。这包括利用可能出现的任何关于报告字符串语言和方向元数据的未来标准。Editorial: 在撰写本文时,尚无可用的语言/方向建议,可与遗留 API 兼容并保持一致,但是当有时,请正式采用它。
[Exposed =(Window ,DedicatedWorker ),SecureContext ]interface :
GPUValidationError GPUError {(
constructor DOMString ); };
message
GPUValidationError
是 GPUError
的子类型,它指示操作未满足所有验证要求。验证错误始终表示应用程序错误,并且预计在使用相同的 [[features]]
和 [[limits]]
的所有设备上以相同的方式失败。
GPUDevice
device generate avalidation error,运行以下步骤:
-
让 error 成为一个带有适当错误消息的新
GPUValidationError
。 -
Dispatch error error 到 device。
[Exposed =(Window ,DedicatedWorker ),SecureContext ]interface :
GPUOutOfMemoryError GPUError {(
constructor DOMString ); };
message
GPUOutOfMemoryError
是 GPUError
的子类型,它指示没有足够的空闲内存来完成所请求的操作。如果使用较低的内存要求(例如使用较小的纹理尺寸)再次尝试操作,或者首先释放其他资源使用的内存,则操作可能会成功。
GPUDevice
device generate an out-of-memory error,运行下列步骤
-
让 error 成为一个带有适当错误消息的新
GPUOutOfMemoryError
。 -
Dispatch error error 到 device。
[Exposed =(Window ,DedicatedWorker ),SecureContext ]interface :
GPUInternalError GPUError {(
constructor DOMString ); };
message
GPUInternalError
是 GPUError
的子类型,它指示即使满足了所有验证要求,操作也因系统或实现特定原因而失败。
例如,操作可能以一种不容易被supported limits捕捉到的方式超出了实现的能力。相同的操作可能在其他设备上或在不同的情况下成功。
GPUDevice
device generate an internal error,运行以下步骤:
-
让 error 成为一个带有适当错误消息的新
GPUInternalError
。 -
Dispatch error error 到 device。
22.3. 错误范围
一个 GPU error scope 捕获在当前GPU error scope中生成的 GPUError
。错误范围用于隔离在一组 WebGPU 调用中发生的错误,通常用于调试目的或使操作更具容错性。
GPU error scope 有以下内部槽(slot):
[[errors]]
, 类型为 list<GPUError
>,初始值 []-
当前GPU error scope中观察到的
GPUError
(如果有)。 [[filter]]
,类型为GPUErrorFilter
-
确定此 GPU error scope 观察的
GPUError
的类型。
enum {
GPUErrorFilter "validation" ,"out-of-memory" ,"internal" , };partial interface GPUDevice {undefined pushErrorScope (GPUErrorFilter filter );Promise <GPUError ?>popErrorScope (); };
GPUErrorFilter
定义了在调用 pushErrorScope()
时应该捕获的错误类型:
"validation"
-
表示错误范围将捕获
GPUValidationError
。 "out-of-memory"
-
表示错误范围将捕获
GPUOutOfMemoryError
。 "internal"
-
表示错误范围将捕获
GPUInternalError
。
GPUDevice
有以下内部槽(slot):
[[errorScopeStack]]
,类型为 stack<GPU error scope>-
已推送到
GPUDevice
的 GPU error scopes 的 stack。
GPUError
error 和 GPUDevice
device 的 current error scope 由向 device 的 Device timeline 发出以下步骤来确定:
-
如果 error 是以下实例之一:
GPUValidationError
-
令 type 为 "validation"。
GPUOutOfMemoryError
-
令 type 为 "out-of-memory"。
GPUInternalError
-
令 type 为 "internal"。
-
令 scope 为 device.
[[errorScopeStack]]
的最后一个 item。 -
当 scope 不是
undefined
时:-
如果 scope.
[[filter]]
是 type,则返回 scope。 -
将 scope 设置为 device.
[[errorScopeStack]]
的前一个 item。
-
-
返回
undefined
。
GPUDevice
device 上 dispatch an error GPUError
error,请在 device 的 Device timeline 上运行以下步骤:
-
如果 device 是 lost,则返回。
注意:设备丢失后不会生成任何错误。请参阅 § 22 错误 & 调试。
-
令 scope 为 error 和 device 的 current error scope。
-
如果 scope 不是
undefined
:-
将 error Append到 scope.
[[errors]]
。 -
返回。
-
-
否则向 Content timeline 发出以下步骤:
-
如果用户代理选择,queue a global task for GPUDevice device,并执行以下步骤:
-
在 device 上触发一个名为 "
uncapturederror
" 的GPUUncapturedErrorEvent
,其error
为 error。
-
注意:如果(且仅当)没有注册 uncapturederror
处理程序,则用户代理应该将未捕获的错误显示给开发人员,例如作为浏览器开发人员控制台中的警告。
注意:用户代理可以选择限制 GPUDevice
可以引发的 GPUUncapturedErrorEvent
的数量,以防止过多的错误处理或日志记录影响性能。
pushErrorScope(filter)
-
将一个新的 GPU error scope 推入 this 的
[[errorScopeStack]]
。Called on:GPUDevice
this.参数:
Arguments for the GPUDevice.pushErrorScope(filter) method. Parameter Type Nullable Optional Description filter
GPUErrorFilter
✘ ✘ 此错误范围观察的错误类。 返回:
undefined
Content timeline 步骤:
-
在 this 的 Device timeline 上发出后续步骤。
Device timeline 步骤:-
令 scope 为一个新的 GPU error scope。
-
将 scope.
[[filter]]
设置为 filter。 -
将 scope Push到 this.
[[errorScopeStack]]
。
-
popErrorScope()
-
从 this 的
[[errorScopeStack]]
弹出一个 GPU error scope,并解析为错误范围观察到的任何GPUError
,如果没有则为null
。不能保证承诺解析的顺序。
Called on:GPUDevice
this.Content timeline 步骤:
-
令contentTimeline为当前Content timeline。
-
令promise为a new promise。
-
在this的Device timeline上发出check steps。
-
返回promise。
Device timeline check steps:-
如果 this 是 lost,则在 contentTimeline 上发出以下步骤并返回:
Content timeline 步骤:-
用
null
Resolve promise。
注意:设备丢失后不会生成错误。请参阅 § 22 错误 & 调试。
-
-
如果以下任何要求不满足:
-
this.
[[errorScopeStack]]
.size 必须 > 0。
然后在 contentTimeline 上发出以下步骤并返回:
Content timeline 步骤:-
用
OperationError
Reject promise。
-
-
令 scope 为从 this.
[[errorScopeStack]]
popping一个 item 的结果。 -
令 error 为 scope.
[[errors]]
中的任何一个,如果没有则为null
。对于列表中的任何两个错误 E1 和 E2,如果 E2 是由 E1 导致的,则不应该选择 E2。
注意: 例如,如果 E1 来自
t
=createTexture()
,并且 E2 来自t
.createView()
,因为t
是 invalid,则应该优先选择 E1,因为开发人员更容易理解出了什么问题。 由于这两个都是GPUValidationError
,唯一的区别在于message
字段,而这个字段本来就是为人类阅读而设计的。 -
在现在或将来的某个未指定的时间点,在 contentTimeline 上发出后续步骤。
注意: 通过允许
popErrorScope()
调用以任何顺序解析,以及允许使用范围内观察到的任何错误,该规范允许验证以任意顺序完成,只要任何状态观察都是在遵守该规范的适当时间点进行的。例如,这允许实现在后台线程上执行仅取决于非状态输入的着色器编译,以与其他设备时间线工作并行完成,并稍后报告任何导致的错误。
Content timeline 步骤:-
用 error Resolve promise。
-
GPUDevice
操作的验证错误:
gpuDevice. pushErrorScope( 'validation' ); let sampler= gpuDevice. createSampler({ maxAnisotropy: 0 , // Invalid, maxAnisotropy must be at least 1. }); gpuDevice. popErrorScope(). then(( error) => { if ( error) { // There was an error creating the sampler, so discard it. sampler= null ; console. error( `An error occured while creating sampler: ${ error. message} ` ); } });
例如:一个只包含创建单个资源(如纹理或缓冲区)的错误范围可以用于检测失败情况,比如内存不足的情况,此时应用程序可以尝试释放一些资源并再次进行分配。
然而,错误范围并不标识哪个命令失败。因此,例如将加载模型期间执行的所有命令包装在一个单独的错误范围中将无法提供足够的细粒度来确定问题是否是由于内存限制引起的。因此,释放资源通常不是对该范围的失败做出的有效响应。更合适的响应应该是允许应用程序回退到不同的模型或产生一个无法加载模型的警告。如果希望对内存限制作出响应,分配内存的操作总是可以包装在一个较小的嵌套错误范围中。
22.4. 遥测
当一个 GPUError
被生成,但没有被任何 GPU error scope 观察到时,用户代理可能会使用 GPUUncapturedErrorEvent
在 GPUDevice
上 fire an event,并命名为 uncapturederror
。
注意:uncapturederror
事件旨在用于遥测和报告意外错误。它们可能不会被分派给所有未捕获的错误(例如,可能存在一个限制,用于显示的错误数量),并且不应该用于处理在应用程序正常运行期间可能发生的已知错误情况。在这些情况下,应该优先使用 pushErrorScope()
和 popErrorScope()
。
[Exposed =(Window ,DedicatedWorker ),SecureContext ]interface :
GPUUncapturedErrorEvent Event {(
constructor DOMString ,
type GPUUncapturedErrorEventInit ); [
gpuUncapturedErrorEventInitDict SameObject ]readonly attribute GPUError error ; };dictionary :
GPUUncapturedErrorEventInit EventInit {required GPUError ; };
error
GPUUncapturedErrorEvent
有以下属性:
error
, of type GPUError, readonly-
一个 slot-backed attribute,保存一个表示未捕获的错误的对象。它的类型与
popErrorScope()
返回的错误相同。
partial interface GPUDevice { [Exposed =(Window ,DedicatedWorker )]attribute EventHandler onuncapturederror ; };
GPUDevice
有以下属性:
onuncapturederror
, of type EventHandler
GPUDevice
的未捕获错误:
gpuDevice. addEventListener( 'uncapturederror' , ( event) => { // Re-surface the error, because adding an event listener may silence console logs. console. error( 'A WebGPU error was not captured:' , event. error); myEngineDebugReport. uncapturedErrors. push({ type: event. error. constructor . name, message: event. error. message, }); });
23. 详细操作
这一部分描述了各种 GPU 操作的细节。
问题:这一部分是不完整的。
23.1. Transfer
Editorial: describe the transfers at the high level
23.2. 计算
计算操作提供了对 GPU 可编程硬件的直接访问。计算着色器没有着色器阶段的输入或输出,它们的结果是将数据写入绑定为 GPUBufferBindingType."storage"
和 GPUStorageTextureBindingLayout
的存储绑定中的副作用。这些操作在 GPUComputePassEncoder
中被编码为:
Editorial: describe the computing algorithm
如果着色器没有在合理的时间内 执行完毕,由用户代理决定,那么 device 可能会 丢失设备。
23.3. 渲染
渲染是通过一组 GPU 操作来完成的,这些操作在 GPURenderPassEncoder
中执行,并导致纹理数据的修改,这些纹理数据由渲染通道附件查看。这些操作是用以下方式编码的:
注意:渲染是 GPU 的传统用法,并且由硬件中的多个固定功能块支持。
主要的渲染算法:
参数:
-
descriptor: 当前
GPURenderPipeline
的描述。 -
drawCall: 绘制调用参数。
-
state: 在发出绘制调用的
GPURenderCommandsMixin
的渲染状态RenderState。
-
解析索引。参见 § 23.3.1 解析索引。
让 vertexList 成为 resolve indices(drawCall, state) 的结果。
-
处理顶点。参见 § 23.3.2 顶点处理。
执行 process vertices(vertexList, drawCall, descriptor.
vertex
, state)。 -
组装原语。参见 § 23.3.3 基本体部件。
执行 assemble primitives(vertexList, drawCall, descriptor.
primitive
)。 -
裁剪原语。参见 § 23.3.4 基本体剪裁。
让 primitiveList 成为这个阶段的结果。
-
光栅化。参见 § 23.3.5 光栅化。
让 rasterizationList 成为 rasterize(primitiveList, state) 的结果。
-
处理片段。参见 § 23.3.6 片段处理。
收集一个 fragments 列表,该列表是由执行 process fragment(rasterPoint, descriptor.
fragment
, state) 产生的,其中 rasterPoint 在 rasterizationList 中。 -
处理深度/模板。
Editorial: fill out the section, using fragments
-
写入像素。
Editorial: fill out the section
23.3.1. 解析索引
在渲染的第一个阶段,管线为每个实例构建了一个要处理的顶点列表。
参数:
-
drawCall: 绘制调用参数。
-
state: 在绘制调用时
GPURenderCommandsMixin
状态的快照。
返回:整数索引列表。
-
让 vertexIndexList 成为一个空的索引列表。
-
如果 drawCall 是一个索引绘制调用:
-
用 drawCall.indexCount 整数初始化 vertexIndexList。
-
对于范围 0 .. drawCall.indexCount(非包含)中的 i:
-
让 relativeVertexIndex 成为 fetch index(i + drawCall.
firstIndex
, state.[[index_buffer]]
)。 -
如果 relativeVertexIndex 有特殊值
"out of bounds"
,停止并返回空列表。注意:实现可以选择在发生这种情况时显示警告,特别是在很容易检测到时(例如在非间接索引绘制调用中)。
-
将 drawCall.
baseVertex
+ relativeVertexIndex 添加到 vertexIndexList。
-
-
-
否则:
-
用 drawCall.vertexCount 整数初始化 vertexIndexList。
-
将每个 vertexIndexList 项 i 设置为值 drawCall.firstVertex + i。
-
-
返回 vertexIndexList。
注意:在间接绘制调用的情况下,将从间接缓冲区而不是绘制命令本身读取 drawCall 的 indexCount
、vertexCount
和其他属性。
Editorial: specify indirect commands better.
参数:
-
i: 要获取的顶点索引的索引。
-
state: 在绘制调用时
GPURenderCommandsMixin
状态的快照。
返回:无符号整数或 "out of bounds"
-
让 indexSize 由 state.
[[index_format]]
定义: -
如果 state.
[[index_buffer_offset]]
+ |i + 1| × indexSize > state.[[index_buffer_size]]
,返回特殊值"out of bounds"
。 -
解释 state.
[[index_buffer]]
中的数据,从偏移量 state.[[index_buffer_offset]]
+ i × indexSize 开始,大小为 indexSize 字节,作为无符号整数并返回它。
23.3.2. 顶点处理
顶点处理阶段是渲染 pipeline 的可编程阶段,它处理顶点属性数据,并为 § 23.3.4 基本体剪裁 生成裁剪空间位置,以及其他 § 23.3.6 片段处理 的数据。
参数:
-
vertexIndexList: 要处理的顶点索引列表(可变的,通过引用传递)。
-
drawCall: 绘制调用参数。
-
desc: 类型为
GPUVertexState
的描述符。 -
state: 在绘制调用时
GPURenderCommandsMixin
状态的快照。
在 vertexIndexList 中的每个顶点 vertexIndex,在每个索引 rawInstanceIndex 的实例中,都是独立处理的。rawInstanceIndex 的范围是从 0 到 drawCall.instanceCount - 1,包括两端。这个处理是并行的,任何副作用,比如写入 GPUBufferBindingType."storage"
绑定,都可能以任何顺序发生。
-
让 instanceIndex 为 rawInstanceIndex + drawCall.firstInstance。
-
对于 desc.
buffers
列表中的每个非null
vertexBufferLayout:-
让 i 为此列表中缓冲区布局的索引。
-
让 vertexBuffer、vertexBufferOffset 和 vertexBufferBindingSize 为 state.
[[vertex_buffers]]
的槽 i 处的缓冲区、偏移量和大小。 -
让 vertexElementIndex 依赖于 vertexBufferLayout.
stepMode
:"vertex"
-
vertexIndex
"instance"
-
instanceIndex
-
对于 vertexBufferLayout.
attributes
中的每个 attributeDesc:-
让 attributeOffset 为 vertexBufferOffset + vertexElementIndex * vertexBufferLayout.
arrayStride
+ attributeDesc.offset
。 -
从 vertexBuffer 的偏移量 attributeOffset 开始,以格式 attributeDesc.
format
加载属性 data。组件从缓冲区内存中的x
、y
、z
、w
的顺序加载。如果这导致越界访问,则根据 WGSL 的 invalid memory reference 行为确定结果值。
-
可选(实现定义): 如果 attributeOffset + sizeof(attributeDesc.
format
) > vertexBufferOffset + vertexBufferBindingSize,则 empty vertexIndexList 并停止,取消绘制调用。注意:这允许实现在发出绘制调用之前检测索引缓冲区中的越界值,而不是使用 invalid memory reference 行为。
-
根据 channel formats 规则,将 data 转换为着色器可见格式。
-
调整 data 的大小以适应着色器类型:
-
如果两者都是标量,或者都是相同维度的向量,则不需要调整。
-
如果 data 是向量,但着色器类型是标量,则只提取第一个分量。
-
如果两者都是向量,并且 data 具有更高的维度,则会丢弃额外的分量。
-
如果着色器类型是更高维度的向量,或者 data 是标量,则缺少的分量将从
vec4<*>(0, 0, 0, 1)
值中填充。
-
-
将 data 绑定到顶点着色器输入位置 attributeDesc.
shaderLocation
。
-
-
-
对于 state.
[[bind_groups]]
中 index 处的每个GPUBindGroup
组:-
对于绑定组中的每个资源
GPUBindingResource
:-
让 entry 成为此资源的相应
GPUBindGroupLayoutEntry
。 -
如果 entry.
visibility
包括VERTEX
:-
将资源绑定到着色器组 index 和绑定
GPUBindGroupLayoutEntry.binding
下。
-
-
-
-
设置着色器 builtins:
-
如果有的话,将
vertex_index
builtin 设置为 vertexIndex。 -
如果有的话,将
instance_index
builtin 设置为 instanceIndex.
-
-
调用 desc 描述的顶点着色器入口点。
注意:目标平台缓存顶点着色器调用的结果。不能保证任何重复超过一次的 vertexIndex 将导致多次调用。同样,不能保证单个 vertexIndex 只会被处理一次。
23.3.3. 基本体部件
基本体由 GPU 的固定功能状态构成。
参数:
-
vertexIndexList:要处理的顶点索引列表。
-
drawCall:绘制调用参数。
-
desc:类型为
GPUPrimitiveState
的描述符。
对于每个实例,基于 vertexIndexList,从已由着色器处理的顶点中组装基本体。
-
首先,如果基本体拓扑是条带(这意味着 desc.
stripIndexFormat
不是 undefined),并且 drawCall 是索引的,则使用 desc.stripIndexFormat
的最大值作为分隔符将 vertexIndexList 分成子列表。例如:类型为
"uint16"
的值为[1, 2, 65535, 4, 5, 6]
的 vertexIndexList 将被分割为子列表[1, 2]
和[4, 5, 6]
。 -
对于子列表 vl,基本体生成根据 desc.
topology
进行:"line-list"
-
线基本体由 (vl.0, vl.1),然后 (vl.2, vl.3),然后 (vl.4 到 vl.5),等等组成。每个后续基本体占用 2 个顶点。
"line-strip"
-
线基本体由 (vl.0, vl.1),然后 (vl.1, vl.2),然后 (vl.2, vl.3),等等组成。每个后续基本体占用 1 个顶点。
"triangle-list"
-
三角形基本体由 (vl.0, vl.1, vl.2),然后 (vl.3, vl.4, vl.5),然后 (vl.6, vl.7, vl.8),等等组成。每个后续基本体占用 3 个顶点。
"triangle-strip"
-
三角形基本体由 (vl.0, vl.1, vl.2),然后 (vl.2, vl.1, vl.3),然后 (vl.2, vl.3, vl.4),然后 (vl.4, vl.3, vl.5),等等组成。每个后续基本体占用 1 个顶点。
Editorial: should this be defined more formally?
任何不完整的基本体都将被丢弃。
23.3.4. 基本体剪裁
顶点着色器必须生成内置的 "position"(类型为 vec4<f32>
),它表示顶点的 clip position。
Editorial: link to WGSL built-ins
基本体被剪裁到 clip volume,对于任何基本体内部的 clip position p,由以下不等式定义:
-
−p.w ≤ p.x ≤ p.w
-
−p.w ≤ p.y ≤ p.w
-
0 ≤ p.z ≤ p.w (depth clipping)
如果 descriptor.primitive
.unclippedDepth
为 true
,则不应用 depth clipping:clip volume 在 z 维度上没有边界。
如果基本体的每条边都完全位于 clip volume 内,则基本体不会改变。
如果基本体的边与 clip volume 的边界相交,则相交的边通过沿 clip volume 的边界的新边重新连接。
对于三角形基本体(descriptor.primitive
.topology
是 "triangle-list"
或 "triangle-strip"
),这种重新连接可能会导致将新顶点引入到多边形中。
如果基本体与 clip volume 的边界的边相交,则剪裁的多边形必须包含此边界边上的一个点。
如果顶点着色器输出其他浮点值(标量和向量),并带有 "perspective" 插值限定符,则它们也会被剪裁。 基本体内的顶点关联的输出值不受剪裁的影响。 但是,如果基本体被剪裁,则剪裁产生的顶点分配的输出值将被剪裁。
考虑一个在顶点 a 和 b 之间的边被剪裁,导致顶点 c,让我们定义 t 为边顶点之间的比率: c.p = t × a.p + (1 − t) × b.p, 其中 x.p 是顶点 x 的输出 clip position。
对于每个具有相应片段输入的顶点输出值 "v",a.v 和 b.v 分别是顶点 a 和 b 的输出。 剪裁的着色器输出 c.v 是基于插值限定符生成的:
- "flat"
-
平面插值不受影响,基于 provoking vertex,它是基本体中的第一个顶点。输出值对整个基本体都是相同的,并且与 provoking vertex 的顶点输出相匹配:c.v = provoking vertex.v
- "linear"
-
插值比率根据 clip position 的透视坐标进行调整,以便插值的结果在屏幕空间中是线性的。
Editorial: provide more specifics here, if possible
- "perspective"
-
在剪裁空间中线性插值该值,从而产生透视正确的值:
c.v = t × a.v + (1 − t) × b.v
Editorial: link to interpolation qualifiers in WGSL
基本体剪裁的结果是一组新的基本体,这些基本体包含在 clip volume 内。
23.3.5. 光栅化
光栅化是将生成的基本体映射到 framebuffer 的 2 维渲染区域的硬件处理阶段 - 当前 GPURenderPassEncoder
中的渲染附件集。
此渲染区域被分割成一个均匀的像素网格。
framebuffer 坐标从渲染目标的左上角开始。每个单位都对应一个像素。有关更多信息,请参见 § 3.3 坐标系统。
光栅化确定基本体影响的像素集。在多采样的情况下,每个像素进一步分成 descriptor.multisample
.count
个样本。 standard sample patterns 如下,其中的位置以像素的左上角为原点,以 framebuffer 坐标表示,使得像素范围从 (0, 0) 到 (1, 1):
multisample .count
| Sample positions |
---|---|
1 | Sample 0: (0.5, 0.5) |
4 | Sample 0: (0.375, 0.125) Sample 1: (0.875, 0.375) Sample 2: (0.125, 0.625) Sample 3: (0.625, 0.875) |
让我们定义一个 FragmentDestination 来包含:
- position
-
framebuffer 空间中的 2D 像素位置
- sampleIndex
-
如果 § 23.3.10 采样频率着色 处于活动状态,则为整数,否则为
null
我们还将使用 NDC 的概念 - 规范化设备坐标。 在此坐标系中,视口边界在 X 和 Y 中的范围为 -1 到 1,在 Z 中的范围为 0 到 1。
光栅化产生一个 RasterizationPoint 列表,每个列表包含以下数据:
- destination
- coverageMask
-
指的是多采样覆盖掩码(参见 § 23.3.11 采样遮掩)
- frontFacing
-
如果是基本体正面的点,则为 true
- perspectiveDivisor
-
指的是基本体上插值的 1.0 ÷ W
- depth
-
指的是视口坐标中的深度, 即
[[viewport]]
minDepth
和maxDepth
之间。 - primitiveVertices
-
指的是形成基本体的顶点输出列表
- barycentricCoordinates
-
指的是 § 23.3.5.3 重心坐标
Editorial: define the depth computation algorithm
参数:
-
primitiveList: 要光栅化的基本体列表。
-
state: 活动的 RenderState。
返回: RasterizationPoint 列表。
每个基本体在 primitiveList 中独立处理。
-
首先,剪切的顶点被转换为 NDC - 规范化设备坐标。对于输出位置 p,计算 NDC 坐标如下:
divisor(p) = 1.0 ÷ p.w
ndc(p) = vector(p.x ÷ p.w, p.y ÷ p.w, p.z ÷ p.w)
-
让 vp 为 state.
[[viewport]]
。将 NDC 坐标 n 映射到视口空间:-
从渲染目标偏移和大小计算 framebuffer 坐标:
framebufferCoords(n) = vector(vp.
x
+ 0.5 × (n.x + 1) × vp.width
, vp.y
+ .5 × (n.y + 1) × vp.height
) -
通过线性映射 [0,1] 到视口深度范围来计算深度:
depth(n) = vp.
minDepth
+ n.z
× ( vp.maxDepth
- vp.minDepth
)
-
-
让 rasterizationPoints 为空列表。
Editorial: specify that each rasterization point gets assigned an interpolated
divisor(p)
,framebufferCoords(n)
,depth(n)
, as well as the other attributes. -
根据
primitive
.topology
,使用特定的光栅化算法继续:"point-list"
-
如果没有被 § 23.3.4 基本体剪裁 过滤,则该点进入 § 23.3.5.1 点光栅化。
"line-list"
or"line-strip"
-
被 § 23.3.4 基本体剪裁 切割的线进入 § 23.3.5.2 线光栅化。
"triangle-list"
or"triangle-strip"
-
在 § 23.3.4 基本体剪裁 中产生的多边形进入 § 23.3.5.4 多边形光栅化。
-
从 rasterizationPoints 中删除所有点 rp,这些点具有 rp.destination.position 在 state.
[[scissorRect]]
之外。 -
返回 rasterizationPoints。
23.3.5.1. 点光栅化
在包含点的 framebuffer 坐标的像素中选择一个 FragmentDestination。
覆盖掩码取决于多采样模式:
- 采样频率
-
coverageMask = 1 ≪
sampleIndex
- 像素频率多采样
-
coverageMask = 1 ≪ descriptor.
multisample
.count
− 1 - 无多采样
-
coverageMask = 1
23.3.5.2. 线光栅化
Editorial: fill out this section
23.3.5.3. 重心坐标
重心坐标是一个 n 个数字 bi 的列表,定义为在 framebuffer 空间中具有 n 个顶点 vi 的凸多边形内的点 p。 每个 bi 在 0 到 1 的范围内,包括 0 和 1,表示到顶点 vi 的接近程度。 它们的总和始终是恒定的:
∑ (bi) = 1
这些坐标唯一地指定了多边形内(或在其边界上)的任何点 p:
p = ∑ (bi × pi)
对于具有 3 个顶点的多边形 - 三角形,任何点 p 的重心坐标可以计算如下:
Apolygon = A(v1, v2, v3) b1 = A(p, b2, b3) ÷ Apolygon b2 = A(b1, p, b3) ÷ Apolygon b3 = A(b1, b2, p) ÷ Apolygon
其中 A(点列表) 是具有给定顶点集的多边形的面积。
对于具有多于 3 个顶点的多边形,确切的算法取决于实现。可能的实现之一是将多边形三角化,并根据其所在的三角形计算点的重心坐标。
23.3.5.4. 多边形光栅化
如果多边形朝向投影,则多边形是 front-facing 的。 否则,多边形是 back-facing 的。
参数:
返回: RasterizationPoint 列表。
-
让 rasterizationPoints 成为空列表。
-
让 v(i) 成为 n 个顶点的光栅化多边形中被裁剪的顶点编号 i(从 1 开始)的 framebuffer 坐标。
注意:本节使用术语“多边形”而不是“三角形”,因为 § 23.3.4 基本体剪裁 阶段可能引入了额外的顶点。 这对应用程序是不可观察的。
-
确定多边形是否是 front-facing 的,这取决于多边形在 framebuffer 坐标中占用的 area 的符号:
area = 0.5 × ((v1.x × vn.y − vn.x × v1.y) + ∑ (vi+1.x × vi.y − vi.x × vi+1.y))
area 的符号根据
primitive
.frontFace
进行解释:"ccw"
-
area > 0 被认为是 front-facing,否则是 back-facing
"cw"
-
area < 0 被认为是 front-facing,否则是 back-facing
-
"none"
-
所有多边形都通过此测试。
"front"
-
front-facing 多边形被丢弃,并且不在渲染管线的后续阶段中处理。
"back"
-
back-facing 多边形被丢弃。
-
确定 framebuffer 空间中多边形内的 fragments 集合 - 这些是计划进行的每个片段操作的位置。 此操作称为“点采样”。 逻辑基于 descriptor.
multisample
:- disabled
-
Fragments 与像素中心相关联。 也就是说,所有坐标为 C 的点,其中 fract(C) = vector2(0.5, 0.5) 在 framebuffer 空间中,被包含在多边形中,都被包含在内。 如果像素中心在多边形的边缘上,是否包含在内是未定义的。
注意:这成为光栅化器的精度主题。
- enabled
-
每个像素与 descriptor.
multisample
.count
相关联,这是实现定义的。 这些位置是有序的,并且对于 framebuffer 的每个像素,列表都是相同的。 每个位置对应于多采样 framebuffer 中的一个片段。光栅化器在每个像素内构建被击中的位置的掩码,并将其作为“sample-mask”内置于片段着色器中。
-
对于每个类型为 FragmentDestination 的产生的片段:
-
让 rp 成为一个新的 RasterizationPoint 对象
-
计算列表 b 作为该片段的 § 23.3.5.3 重心坐标。 将 rp.barycentricCoordinates 设置为 b。
-
让 di 成为 vi 的深度值。
Editorial: define how this value is constructed.
-
将 rp.depth 设置为 ∑ (bi × di)
-
将 rp 追加到 rasterizationPoints。
-
-
返回 rasterizationPoints。
23.3.6. 片段处理
片段处理阶段是渲染 pipeline 的可编程阶段,用于计算要写入渲染目标的片段数据(通常是颜色)。
此阶段为每个 RasterizationPoint 生成一个 Fragment:
-
destination 指的是 FragmentDestination。
-
coverageMask 指的是多采样覆盖掩码(请参阅 § 23.3.11 采样遮掩)。
-
depth 指的是视口坐标中的深度, 即
[[viewport]]
minDepth
和maxDepth
之间。 -
colors 指的是颜色值列表,每个目标一个
colorAttachments
。
参数:
-
rp: 由 § 23.3.5 光栅化 产生的 RasterizationPoint。
-
desc: 类型为
GPUFragmentState
的描述符。 -
state: 活动的 RenderState。
返回: Fragment 或 null
。
-
让 fragment 成为一个新的 Fragment 对象。
-
将 fragment.destination 设置为 rp.destination。
-
将 fragment.coverageMask 设置为 rp.coverageMask。
-
如果 desc 不是
null
:-
设置着色器输入 builtins。 对于入口点的每个非复合参数,标记为 builtin,根据注释设置其值:
position
-
vec4<f32>
(rp.destination.position, rp.depth, rp.perspectiveDivisor) front_facing
-
rp.frontFacing
sample_index
sample_mask
-
rp.coverageMask
-
对于片段阶段的每个用户指定的 shader stage input:
-
让 value 成为基于 rp.barycentricCoordinates、rp.primitiveVertices 和输入上的 interpolation 限定符的插值片段输入。
Editorial: describe the exact equations.
-
将相应的片段着色器 location 输入设置为 value。
-
-
调用由 desc 描述的片段着色器入口点。
如果 shader execution does not end 在合理的时间内,由用户代理确定,device 可能会变成 lost。
-
如果片段发出了
discard
,则返回null
。 -
将 fragment.colors 设置为来自着色器的用户指定的 shader stage output 值。
-
取出着色器输出 builtins:
-
如果
frag_depth
builtin 由着色器产生为 value:-
让 vp 成为 state.
[[viewport]]
。 -
将 fragment.depth 设置为 clamp(value, vp.
minDepth
, vp.maxDepth
)。
-
-
-
如果
sample_mask
builtin 由着色器产生为 value:-
将 fragment.coverageMask 设置为 fragment.coverageMask ∧ value.
-
否则,我们处于 § 23.3.8 无颜色输出 模式,fragment.colors 为空。
-
-
返回 fragment。
片段的处理是并行的,而任何副作用,例如写入 GPUBufferBindingType."storage"
绑定,可能以任何顺序发生。
23.3.7. 输出合并
Editorial: fill out this section
此阶段的深度输入(如果有)将被截断到当前 [[viewport]]
深度范围(无论片段着色器阶段是否写入 frag_depth
builtin)。
23.3.8. 无颜色输出
在无颜色输出模式下,pipeline 不会产生任何颜色附件输出。
pipeline 仍然执行光栅化并基于顶点位置输出产生深度值。深度测试和模板操作仍然可以使用。
23.3.9. Alpha覆盖
在 alpha-to-coverage 模式下,基于片段着色器输出值在 @location(0)
处的 alpha 分量,生成 MSAA 样本的额外 alpha-to-coverage mask。
生成额外 mask 的算法取决于平台,对于不同的像素可能会有所不同。 它保证:
-
如果 alpha ≤ 0.0,则结果为 0x0
-
如果 alpha ≥ 1.0,则结果为 0xFFFFFFFF
-
如果 alpha 大于某个其他 alpha1,则产生的样本 mask 至少有与 alpha1 的 mask 一样多的位设置为 1
23.3.10. 采样频率着色
Editorial: fill out the section
23.3.11. 采样遮掩
像素的 final sample mask 计算为 rasterization mask & mask
& shader-output mask。
只考虑 mask 的较低 count
位。
如果 final sample mask 的位置 N 的最低有效位的值为 "0",则片段着色器的所有附件的样本颜色输出(对应于样本 N)都将被丢弃。此外,深度测试或模板操作也不会在深度模板附件的相关样本上执行。
注意:样本 N 的颜色输出是由片段着色器执行产生的,对于当前像素,SV_SampleIndex == N。如果片段着色器不使用此语义,则每个像素只执行一次。
rasterization mask 是由光栅化阶段产生的,基于光栅化多边形的形状。包含在形状中的样本在 mask 中获得相关位 1。
shader-output mask 获取片段着色器中 "sample_mask" builtin 的输出值。如果 builtin 不是从片段着色器输出的,并且 alphaToCoverageEnabled
已启用,则 shader-output mask 变为 alpha-to-coverage mask。否则,默认为 0xFFFFFFFF。
24. 类型定义
typedef [EnforceRange ]unsigned long ;
GPUBufferDynamicOffset typedef [EnforceRange ]unsigned long ;
GPUStencilValue typedef [EnforceRange ]unsigned long ;
GPUSampleMask typedef [EnforceRange ]long ;
GPUDepthBias typedef [EnforceRange ]unsigned long long ;
GPUSize64 typedef [EnforceRange ]unsigned long ;
GPUIntegerCoordinate typedef [EnforceRange ]unsigned long ;
GPUIndex32 typedef [EnforceRange ]unsigned long ;
GPUSize32 typedef [EnforceRange ]long ;
GPUSignedOffset32 typedef unsigned long ;
GPUFlagsConstant
24.1. 颜色 & 向量
dictionary {
GPUColorDict required double r ;required double g ;required double b ;required double a ; };typedef (sequence <double >or GPUColorDict );
GPUColor
注意:double
足够大,可以精确地保存 32 位有符号/无符号整数和单精度浮点数。
r
, of type double-
红色通道值。
g
, of type double-
绿色通道值。
b
, of type double-
蓝色通道值。
a
, of type double-
透明通道值。
GPUColor
值 color,根据其类型,语法为:
-
color.r 指的是
GPUColorDict
.r
或序列的第一项(断言 存在这样的项)。 -
color.g 指的是
GPUColorDict
.g
或序列的第二项(断言 存在这样的项)。 -
color.b 指的是
GPUColorDict
.b
或序列的第三项(断言 存在这样的项)。 -
color.a 指的是
GPUColorDict
.a
或序列的第四项(断言 存在这样的项)。
参数:
-
color:要验证的
GPUColor
。
返回: undefined
-
如果 color 是一个序列且 color.length ≠ 4,则抛出
TypeError
。
dictionary {
GPUOrigin2DDict GPUIntegerCoordinate = 0;
x GPUIntegerCoordinate = 0; };
y typedef (sequence <GPUIntegerCoordinate >or GPUOrigin2DDict );
GPUOrigin2D
GPUOrigin2D
值 origin,根据其类型,语法为:
-
origin.x 指的是
GPUOrigin2DDict
.x
或序列的第一项(如果不存在,则为 0)。 -
origin.y 指的是
GPUOrigin2DDict
.y
或序列的第二项(如果不存在,则为 0)。
参数:
-
origin:要验证的
GPUOrigin2D
。
返回: undefined
-
如果 origin 是一个序列且 origin.length > 2,则抛出
TypeError
。
dictionary {
GPUOrigin3DDict GPUIntegerCoordinate = 0;
x GPUIntegerCoordinate = 0;
y GPUIntegerCoordinate = 0; };
z typedef (sequence <GPUIntegerCoordinate >or GPUOrigin3DDict );
GPUOrigin3D
GPUOrigin3D
值 origin,根据其类型,语法为:
-
origin.x 指的是
GPUOrigin3DDict
.x
或序列的第一项(如果不存在,则为 0)。 -
origin.y 指的是
GPUOrigin3DDict
.y
或序列的第二项(如果不存在,则为 0)。 -
origin.z 指的是
GPUOrigin3DDict
.z
或序列的第三项(如果不存在,则为 0)。
参数:
-
origin:要验证的
GPUOrigin3D
。
返回: undefined
-
如果 origin 是一个序列且 origin.length > 3,则抛出
TypeError
。
dictionary {
GPUExtent3DDict required GPUIntegerCoordinate width ;GPUIntegerCoordinate height = 1;GPUIntegerCoordinate depthOrArrayLayers = 1; };typedef (sequence <GPUIntegerCoordinate >or GPUExtent3DDict );
GPUExtent3D
width
, of type GPUIntegerCoordinate-
范围的宽度。
height
, of type GPUIntegerCoordinate, defaulting to1
-
范围的高度。
depthOrArrayLayers
, of type GPUIntegerCoordinate, defaulting to1
-
范围的深度或其包含的数组层数。 如果与
GPUTexture
一起使用,其GPUTextureDimension
为"3d"
,定义了纹理的深度。如果与GPUTexture
一起使用,其GPUTextureDimension
为"2d"
,定义了纹理中的数组层数。
GPUExtent3D
值 extent,根据其类型,语法为:
-
extent.width 指的是
GPUExtent3DDict
.width
或序列的第一项(如果存在该项,则 asserting)。 -
extent.height 指的是
GPUExtent3DDict
.height
或序列的第二项(如果不存在,则为 1)。 -
extent.depthOrArrayLayers 指的是
GPUExtent3DDict
.depthOrArrayLayers
或序列的第三项(如果不存在,则为 1)。
参数:
-
extent:要验证的
GPUExtent3D
。
返回: undefined
-
抛出
TypeError
,如果:
-
extent is a sequence, and
-
extent.length < 1 or extent.length > > 3.
25. 功能索引
25.1. "depth-clip-control"
允许禁用 depth clipping。
此功能添加了以下 optional API surfaces:
-
新的
GPUPrimitiveState
字典成员:
25.2. "depth32float-stencil8"
允许显式创建格式为 "depth32float-stencil8"
的纹理。
此功能添加了以下 optional API surfaces:
25.3. "texture-compression-bc"
允许显式创建 BC 压缩格式的纹理。
此功能添加了以下 optional API surfaces:
-
新的
GPUTextureFormat
枚举值:
25.4. "texture-compression-etc2"
允许显式创建 ETC2 压缩格式的纹理。
此功能添加了以下 optional API surfaces:
-
新的
GPUTextureFormat
枚举值:
25.5. "texture-compression-astc"
允许显式创建 ASTC 压缩格式的纹理。
此功能添加了以下 optional API surfaces:
-
新的
GPUTextureFormat
枚举值:
25.6. "timestamp-query"
添加了从 GPU 命令缓冲区查询时间戳的能力。参见 § 20.4 时间戳查询。
此功能添加了以下 optional API surfaces:
-
新的
GPUQueryType
值: -
新的
GPUCommandEncoder
方法: -
新的
GPUComputePassDescriptor
成员: -
新的
GPURenderPassDescriptor
成员:
25.7. "indirect-first-instance"
允许在 indirect draw parameters 和 indirect drawIndexed parameters 中使用非零的 firstInstance
值。
此功能不添加 optional API surfaces。
25.8. "shader-f16"
允许在 WGSL 中使用半精度浮点类型 f16。
此功能添加了以下 optional API surfaces:
-
新的 WGSL 扩展:
25.9. "rg11b10ufloat-renderable"
允许在格式为 "rg11b10ufloat"
的纹理上使用 RENDER_ATTACHMENT
,
此功能不添加 optional API surfaces。
25.10. "bgra8unorm-storage"
允许在格式为 "bgra8unorm"
的纹理上使用 STORAGE_BINDING
。
此功能不添加 optional API surfaces。
25.11. "float32-filterable"
使格式为 "r32float"
、"rg32float"
和 "rgba32float"
的纹理 filterable。
26. 附录
26.1. 纹理格式功能
26.1.1. 纯彩色格式
所有纯彩色格式都支持 COPY_SRC
、COPY_DST
和 TEXTURE_BINDING
用法。
RENDER_ATTACHMENT
和 STORAGE_BINDING
列分别指定对 GPUTextureUsage.RENDER_ATTACHMENT
和 GPUTextureUsage.STORAGE_BINDING
用法的支持。
render target pixel byte cost 和 render target component alignment 用于验证 maxColorAttachmentBytesPerSample
限制。
注意: 这些格式的 texel block memory cost 与其 texel block copy footprint 相同。
26.1.2. 深度模具格式
depth-or-stencil format 是任意带有深度和/或模具方面的格式。 combined depth-stencil format 是一个既有深度又有模具方面的 depth-or-stencil format。
所有的 depth-or-stencil formats 都支持 COPY_SRC
、COPY_DST
、TEXTURE_BINDING
和 RENDER_ATTACHMENT
用法。
所有这些格式都支持多重采样。然而某些复制操作也限制了源和目标格式。
深度纹理不能使用 "filtering"
采样器,但总是可以使用 "comparison"
采样器(它们可以使用过滤)。
Format | Texel block memory cost (Bytes) | Aspect | GPUTextureSampleType
| Valid image copy source | Valid image copy destination | Texel block copy footprint (Bytes) | Aspect-specific format |
---|---|---|---|---|---|---|---|
stencil8
| 1 − 4 | stencil | "uint"
| ✓ | 1 | stencil8
| |
depth16unorm
| 2 | depth | "depth" , "unfilterable-float"
| ✓ | 2 | depth16unorm
| |
depth24plus
| 4 | depth | "depth" , "unfilterable-float"
| ✗ | – | depth24plus
| |
depth24plus-stencil8
| 4 − 8 | depth | "depth" , "unfilterable-float"
| ✗ | – | depth24plus
| |
stencil | "uint"
| ✓ | 1 | stencil8
| |||
depth32float
| 4 | depth | "depth" , "unfilterable-float"
| ✓ | ✗ | 4 | depth32float
|
depth32float-stencil8
| 5 − 8 | depth | "depth" , "unfilterable-float"
| ✓ | ✗ | 4 | depth32float
|
stencil | "uint"
| ✓ | 1 | stencil8
|
24-bit depth 指的是一个 24 位无符号归一化深度格式,其范围从 0.0 到 1.0,如果暴露出来,它将被拼写为 "depth24unorm"。
26.1.2.1. 读取和采样深度/模具纹理
绑定深度方面 GPUTextureView
到 texture_depth_*
绑定或其他非深度 2d/cube 纹理类型的绑定是 possible 的。
模具方面 GPUTextureView
必须绑定到普通纹理绑定类型。GPUBindGroupLayout
中的 sampleType
必须是 "uint"
。
读取或采样纹理的深度或模具方面的行为就像纹理包含值 (V, X, X, X)
,其中 V 是实际的深度或模具值,每个 X 是实现定义的未指定值。
对于深度方面绑定,未指定的值在具有 texture_depth_*
类型的绑定中不可见。
tex
with type texture_2d<f32>
:
-
textureSample(tex, ...)
will returnvec4<f32>(D, X, X, X)
. -
textureGather(0, tex, ...)
will returnvec4<f32>(D1, D2, D3, D4)
. -
textureGather(2, tex, ...)
will returnvec4<f32>(X1, X2, X3, X4)
(a completely unspecified value).
注意:
除了添加一个新的更受限制的模具采样器类型(如深度)之外,实现无法有效地掩盖深度/模具读取的驱动程序差异。由于这不是 WebGL 的可移植性痛点,因此不希望在 WebGPU 中出现问题。实际上,根据硬件的不同,期望是 (V, V, V, V)
或 (V, 0, 0, 1)
(其中 V
是深度或模具值)。
26.1.2.2. 复制深度/模具纹理
深度方面的深度32float格式("depth32float"
和 "depth32float-stencil8"
)具有有限的范围。
因此,从相同格式的其他纹理复制到此类纹理是有效的。
深度方面的深度24plus格式("depth24plus"
和 "depth24plus-stencil8"
)具有不透明的表示(实现为 24-bit depth 或 "depth32float"
)。
因此,不允许使用这些格式进行深度方面的 image copies。
-
所有这些格式都可以使用通过
frag_depth
输出输出深度值的片段着色器在渲染通道中写入。 -
具有 "depth24plus" 格式的纹理可以作为着色器纹理读取,并写入纹理(作为渲染通道附件)或缓冲区(通过计算着色器中的存储缓冲区绑定)。
26.1.3. 压缩格式
所有的压缩纹理格式都支持COPY_SRC
,COPY_DST
和TEXTURE_BINDING
用法。
所有这些格式都是可过滤的。
这些格式都不是可渲染的,也不支持多重采样。
compressed format是任何块大小大于1×1的格式。
注意: 每个这些格式的texel block memory cost与其texel block copy footprint相同。