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
具有以下成员,它们描述了模板比较和操作是如何执行的: