blob: 96afebbd0f7f5e6af577e12e9a7f100d60950bc7 [file] [log] [blame]
Kai Ninomiya7c40d212022-01-04 14:25:02 -08001// MAINTENANCE_TODO: The generated Typedoc for this file is hard to navigate because it's
2// alphabetized. Consider using namespaces or renames to fix this?
Kai Ninomiya97c60c42021-06-14 16:55:24 -07003
Kai Ninomiyaf0d24f32020-12-11 16:42:29 -08004/* eslint-disable no-sparse-arrays */
Kai Ninomiya97c60c42021-06-14 16:55:24 -07005
Kai Ninomiya7cd9ff72021-06-30 20:24:01 -07006import { keysOf, makeTable, numericKeysOf, valueof } from '../common/util/data_tables.js';
7import { assertTypeTrue, TypeEqual } from '../common/util/types.js';
Kai Ninomiya374a2c82021-06-08 18:44:42 -07008import { assert, unreachable } from '../common/util/util.js';
Kai Ninomiyaf0d24f32020-12-11 16:42:29 -08009
Corentin Wallez27ca9f72022-03-30 21:01:47 +010010import { GPUConst, kMaxUnsignedLongValue, kMaxUnsignedLongLongValue } from './constants.js';
Yunchao Hea9755892021-08-19 16:49:29 -070011import { ImageCopyType } from './util/texture/layout.js';
Kai Ninomiya04e404f2020-10-23 16:02:19 -070012
Kai Ninomiyab61f76c2021-07-15 19:32:34 -070013// Base device limits can be found in constants.ts.
14
Hao Liab18a1b2021-01-28 06:16:50 +080015// Queries
16
Kai Ninomiya97c60c42021-06-14 16:55:24 -070017/** Maximum number of queries in GPUQuerySet, by spec. */
Corentin Wallez861b2092023-01-03 17:59:29 +010018export const kMaxQueryCount = 4096;
Kai Ninomiya97c60c42021-06-14 16:55:24 -070019/** Per-GPUQueryType info. */
20export type QueryTypeInfo = {
21 /** Optional feature required to use this GPUQueryType. */
22 readonly feature: GPUFeatureName | undefined;
23 // Add fields as needed
24};
Hao Lidceba5d2021-04-14 04:28:54 +080025export const kQueryTypeInfo: {
Kai Ninomiya97c60c42021-06-14 16:55:24 -070026 readonly [k in GPUQueryType]: QueryTypeInfo;
Hao Lidceba5d2021-04-14 04:28:54 +080027} = /* prettier-ignore */ {
Kai Ninomiya46b40ad2021-04-14 14:51:20 -070028 // Occlusion query does not require any features.
29 'occlusion': { feature: undefined },
Kai Ninomiya46b40ad2021-04-14 14:51:20 -070030 'timestamp': { feature: 'timestamp-query' },
Hao Lidceba5d2021-04-14 04:28:54 +080031};
Kai Ninomiya97c60c42021-06-14 16:55:24 -070032/** List of all GPUQueryType values. */
Hao Lidceba5d2021-04-14 04:28:54 +080033export const kQueryTypes = keysOf(kQueryTypeInfo);
Hao Liab18a1b2021-01-28 06:16:50 +080034
Kai Ninomiyabe420af2020-07-24 18:32:40 -070035// Buffers
36
Kai Ninomiya97c60c42021-06-14 16:55:24 -070037/** Required alignment of a GPUBuffer size, by spec. */
Kai Ninomiya84b7ab12020-11-20 12:33:12 -080038export const kBufferSizeAlignment = 4;
39
Lokbondo Kung300c10c2022-03-22 10:53:42 -070040/** Per-GPUBufferUsage copy info. */
41export const kBufferUsageCopyInfo: {
42 readonly [name: string]: GPUBufferUsageFlags;
Kai Ninomiyabe420af2020-07-24 18:32:40 -070043} = /* prettier-ignore */ {
Lokbondo Kung300c10c2022-03-22 10:53:42 -070044 'COPY_NONE': 0,
45 'COPY_SRC': GPUConst.BufferUsage.COPY_SRC,
46 'COPY_DST': GPUConst.BufferUsage.COPY_DST,
47 'COPY_SRC_DST': GPUConst.BufferUsage.COPY_SRC | GPUConst.BufferUsage.COPY_DST,
Kai Ninomiyabe420af2020-07-24 18:32:40 -070048};
Lokbondo Kung300c10c2022-03-22 10:53:42 -070049/** List of all GPUBufferUsage copy values. */
50export const kBufferUsageCopy = keysOf(kBufferUsageCopyInfo);
51
52/** Per-GPUBufferUsage keys and info. */
53type BufferUsageKey = keyof typeof GPUConst.BufferUsage;
54export const kBufferUsageKeys = keysOf(GPUConst.BufferUsage);
55export const kBufferUsageInfo: {
56 readonly [k in BufferUsageKey]: GPUBufferUsageFlags;
57} = {
58 ...GPUConst.BufferUsage,
59};
60
Kai Ninomiya97c60c42021-06-14 16:55:24 -070061/** List of all GPUBufferUsage values. */
Lokbondo Kung300c10c2022-03-22 10:53:42 -070062export const kBufferUsages = Object.values(GPUConst.BufferUsage);
jzm-intel6d8d8532022-01-25 09:26:14 +080063export const kAllBufferUsageBits = kBufferUsages.reduce(
64 (previousSet, currentUsage) => previousSet | currentUsage,
65 0
66);
Kai Ninomiyabe420af2020-07-24 18:32:40 -070067
Lokbondo Kungd82d4e12022-08-22 10:41:58 -070068// Errors
69
70/** Per-GPUErrorFilter info. */
71export const kErrorScopeFilterInfo: {
72 readonly [k in GPUErrorFilter]: {};
73} = /* prettier-ignore */ {
74 'out-of-memory': {},
Takahirocbdd47a2022-10-05 15:44:19 -070075 'validation': {},
76 'internal': {},
Lokbondo Kungd82d4e12022-08-22 10:41:58 -070077};
Corentin Wallez0e790f32022-11-28 22:09:04 +010078/** List of all GPUErrorFilter values. */
Lokbondo Kungd82d4e12022-08-22 10:41:58 -070079export const kErrorScopeFilters = keysOf(kErrorScopeFilterInfo);
Corentin Wallez0e790f32022-11-28 22:09:04 +010080export const kGeneratableErrorScopeFilters = kErrorScopeFilters.filter(e => e !== 'internal');
Lokbondo Kungd82d4e12022-08-22 10:41:58 -070081
Justin Fan5d1b8c72020-01-15 16:03:37 -080082// Textures
83
Kai Ninomiya97c60c42021-06-14 16:55:24 -070084// Definitions for use locally. To access the table entries, use `kTextureFormatInfo`.
85
Yunchao Heaec50852021-03-12 15:49:18 -080086// Note that we repeat the header multiple times in order to make it easier to read.
Kai Ninomiya97c60c42021-06-14 16:55:24 -070087const kRegularTextureFormatInfo = /* prettier-ignore */ makeTable(
Lokbondo Kunga7e54e72023-01-26 11:51:32 -080088 ['renderable', 'multisample', 'resolve', 'color', 'depth', 'stencil', 'storage', 'copySrc', 'copyDst', 'sampleType', 'bytesPerBlock', 'blockWidth', 'blockHeight', 'renderTargetPixelByteCost', 'renderTargetComponentAlignment', 'feature', 'baseFormat'] as const,
89 [ , , , true, false, false, , true, true, , , 1, 1, undefined, undefined, , undefined] as const, {
Kai Ninomiyaea9e36f2019-10-18 20:01:03 -070090 // 8-bit formats
Lokbondo Kunga7e54e72023-01-26 11:51:32 -080091 'r8unorm': [ true, true, true, , , , false, , , 'float', 1, , , 1, 1],
92 'r8snorm': [ false, false, false, , , , false, , , 'float', 1],
93 'r8uint': [ true, true, false, , , , false, , , 'uint', 1, , , 1, 1],
94 'r8sint': [ true, true, false, , , , false, , , 'sint', 1, , , 1, 1],
Kai Ninomiyaea9e36f2019-10-18 20:01:03 -070095 // 16-bit formats
Lokbondo Kunga7e54e72023-01-26 11:51:32 -080096 'r16uint': [ true, true, false, , , , false, , , 'uint', 2, , , 2, 2],
97 'r16sint': [ true, true, false, , , , false, , , 'sint', 2, , , 2, 2],
98 'r16float': [ true, true, true, , , , false, , , 'float', 2, , , 2, 2],
99 'rg8unorm': [ true, true, true, , , , false, , , 'float', 2, , , 2, 1],
100 'rg8snorm': [ false, false, false, , , , false, , , 'float', 2],
101 'rg8uint': [ true, true, false, , , , false, , , 'uint', 2, , , 2, 1],
102 'rg8sint': [ true, true, false, , , , false, , , 'sint', 2, , , 2, 1],
Kai Ninomiyaea9e36f2019-10-18 20:01:03 -0700103 // 32-bit formats
Lokbondo Kunga7e54e72023-01-26 11:51:32 -0800104 'r32uint': [ true, false, false, , , , true, , , 'uint', 4, , , 4, 4],
105 'r32sint': [ true, false, false, , , , true, , , 'sint', 4, , , 4, 4],
106 'r32float': [ true, true, false, , , , true, , , 'unfilterable-float', 4, , , 4, 4],
107 'rg16uint': [ true, true, false, , , , false, , , 'uint', 4, , , 4, 2],
108 'rg16sint': [ true, true, false, , , , false, , , 'sint', 4, , , 4, 2],
109 'rg16float': [ true, true, true, , , , false, , , 'float', 4, , , 4, 2],
110 'rgba8unorm': [ true, true, true, , , , true, , , 'float', 4, , , 8, 1, , 'rgba8unorm'],
111 'rgba8unorm-srgb': [ true, true, true, , , , false, , , 'float', 4, , , 8, 1, , 'rgba8unorm'],
112 'rgba8snorm': [ false, false, false, , , , true, , , 'float', 4],
113 'rgba8uint': [ true, true, false, , , , true, , , 'uint', 4, , , 4, 1],
114 'rgba8sint': [ true, true, false, , , , true, , , 'sint', 4, , , 4, 1],
Jiawei Shaobd8450c2023-01-31 11:01:28 +0800115 'bgra8unorm': [ true, true, true, , , , true, , , 'float', 4, , , 8, 1, , 'bgra8unorm'],
Lokbondo Kunga7e54e72023-01-26 11:51:32 -0800116 'bgra8unorm-srgb': [ true, true, true, , , , false, , , 'float', 4, , , 8, 1, , 'bgra8unorm'],
Kai Ninomiyaea9e36f2019-10-18 20:01:03 -0700117 // Packed 32-bit formats
Lokbondo Kunga7e54e72023-01-26 11:51:32 -0800118 'rgb10a2unorm': [ true, true, true, , , , false, , , 'float', 4, , , 8, 4],
119 'rg11b10ufloat': [ false, false, false, , , , false, , , 'float', 4, , , 8, 4],
120 'rgb9e5ufloat': [ false, false, false, , , , false, , , 'float', 4],
Kai Ninomiyaea9e36f2019-10-18 20:01:03 -0700121 // 64-bit formats
Lokbondo Kunga7e54e72023-01-26 11:51:32 -0800122 'rg32uint': [ true, false, false, , , , true, , , 'uint', 8, , , 8, 4],
123 'rg32sint': [ true, false, false, , , , true, , , 'sint', 8, , , 8, 4],
124 'rg32float': [ true, false, false, , , , true, , , 'unfilterable-float', 8, , , 8, 4],
125 'rgba16uint': [ true, true, false, , , , true, , , 'uint', 8, , , 8, 2],
126 'rgba16sint': [ true, true, false, , , , true, , , 'sint', 8, , , 8, 2],
127 'rgba16float': [ true, true, true, , , , true, , , 'float', 8, , , 8, 2],
Kai Ninomiyaea9e36f2019-10-18 20:01:03 -0700128 // 128-bit formats
Lokbondo Kunga7e54e72023-01-26 11:51:32 -0800129 'rgba32uint': [ true, false, false, , , , true, , , 'uint', 16, , , 16, 4],
130 'rgba32sint': [ true, false, false, , , , true, , , 'sint', 16, , , 16, 4],
131 'rgba32float': [ true, false, false, , , , true, , , 'unfilterable-float', 16, , , 16, 4],
Kai Ninomiyaf0d24f32020-12-11 16:42:29 -0800132} as const);
133/* prettier-ignore */
Lokbondo Kunga7e54e72023-01-26 11:51:32 -0800134const kTexFmtInfoHeader = ['renderable', 'multisample', 'resolve', 'color', 'depth', 'stencil', 'storage', 'copySrc', 'copyDst', 'sampleType', 'bytesPerBlock', 'blockWidth', 'blockHeight', 'renderTargetPixelByteCost', 'renderTargetComponentAlignment', 'feature', 'baseFormat'] as const;
Kai Ninomiya97c60c42021-06-14 16:55:24 -0700135const kSizedDepthStencilFormatInfo = /* prettier-ignore */ makeTable(kTexFmtInfoHeader,
Lokbondo Kunga7e54e72023-01-26 11:51:32 -0800136 [ true, true, false, false, , , false, , , , , 1, 1, undefined, undefined, , undefined] as const, {
137 'depth32float': [ , , , , true, false, , true, false, 'depth', 4],
138 'depth16unorm': [ , , , , true, false, , true, true, 'depth', 2],
139 'stencil8': [ , , , , false, true, , true, true, 'uint', 1],
Kai Ninomiyaf0d24f32020-12-11 16:42:29 -0800140} as const);
ShrekShao20aa9312021-08-11 18:55:41 -0700141
142// Multi aspect sample type are now set to their first aspect
Kai Ninomiya97c60c42021-06-14 16:55:24 -0700143const kUnsizedDepthStencilFormatInfo = /* prettier-ignore */ makeTable(kTexFmtInfoHeader,
Lokbondo Kunga7e54e72023-01-26 11:51:32 -0800144 [ true, true, false, false, , , false, false, false, , undefined, 1, 1, , , , undefined] as const, {
145 'depth24plus': [ , , , , true, false, , , , 'depth'],
146 'depth24plus-stencil8': [ , , , , true, true, , , , 'depth'],
Kai Ninomiya7c40d212022-01-04 14:25:02 -0800147 // MAINTENANCE_TODO: These should really be sized formats; see below MAINTENANCE_TODO about multi-aspect formats.
Lokbondo Kunga7e54e72023-01-26 11:51:32 -0800148 'depth32float-stencil8': [ , , , , true, true, , , , 'depth', , , , , , 'depth32float-stencil8'],
Kai Ninomiyaf0d24f32020-12-11 16:42:29 -0800149} as const);
Lokbondo Kung0e9ad2d2021-11-16 17:57:05 -0800150
151// Separated compressed formats by type
152const kBCTextureFormatInfo = /* prettier-ignore */ makeTable(kTexFmtInfoHeader,
Lokbondo Kunga7e54e72023-01-26 11:51:32 -0800153 [ false, false, false, true, false, false, false, true, true, , , 4, 4, , , , undefined] as const, {
Lokbondo Kung0e9ad2d2021-11-16 17:57:05 -0800154 // Block Compression (BC) formats
Lokbondo Kunga7e54e72023-01-26 11:51:32 -0800155 'bc1-rgba-unorm': [ , , , , , , , , , 'float', 8, 4, 4, , , 'texture-compression-bc', 'bc1-rgba-unorm'],
156 'bc1-rgba-unorm-srgb': [ , , , , , , , , , 'float', 8, 4, 4, , , 'texture-compression-bc', 'bc1-rgba-unorm'],
157 'bc2-rgba-unorm': [ , , , , , , , , , 'float', 16, 4, 4, , , 'texture-compression-bc', 'bc2-rgba-unorm'],
158 'bc2-rgba-unorm-srgb': [ , , , , , , , , , 'float', 16, 4, 4, , , 'texture-compression-bc', 'bc2-rgba-unorm'],
159 'bc3-rgba-unorm': [ , , , , , , , , , 'float', 16, 4, 4, , , 'texture-compression-bc', 'bc3-rgba-unorm'],
160 'bc3-rgba-unorm-srgb': [ , , , , , , , , , 'float', 16, 4, 4, , , 'texture-compression-bc', 'bc3-rgba-unorm'],
161 'bc4-r-unorm': [ , , , , , , , , , 'float', 8, 4, 4, , , 'texture-compression-bc'],
162 'bc4-r-snorm': [ , , , , , , , , , 'float', 8, 4, 4, , , 'texture-compression-bc'],
163 'bc5-rg-unorm': [ , , , , , , , , , 'float', 16, 4, 4, , , 'texture-compression-bc'],
164 'bc5-rg-snorm': [ , , , , , , , , , 'float', 16, 4, 4, , , 'texture-compression-bc'],
165 'bc6h-rgb-ufloat': [ , , , , , , , , , 'float', 16, 4, 4, , , 'texture-compression-bc'],
166 'bc6h-rgb-float': [ , , , , , , , , , 'float', 16, 4, 4, , , 'texture-compression-bc'],
167 'bc7-rgba-unorm': [ , , , , , , , , , 'float', 16, 4, 4, , , 'texture-compression-bc', 'bc7-rgba-unorm'],
168 'bc7-rgba-unorm-srgb': [ , , , , , , , , , 'float', 16, 4, 4, , , 'texture-compression-bc', 'bc7-rgba-unorm'],
Kai Ninomiyaf0d24f32020-12-11 16:42:29 -0800169} as const);
Lokbondo Kung0e9ad2d2021-11-16 17:57:05 -0800170const kETC2TextureFormatInfo = /* prettier-ignore */ makeTable(kTexFmtInfoHeader,
Lokbondo Kunga7e54e72023-01-26 11:51:32 -0800171 [ false, false, false, true, false, false, false, true, true, , , 4, 4, , , , undefined] as const, {
Lokbondo Kung0e9ad2d2021-11-16 17:57:05 -0800172 // Ericsson Compression (ETC2) formats
Lokbondo Kunga7e54e72023-01-26 11:51:32 -0800173 'etc2-rgb8unorm': [ , , , , , , , , , 'float', 8, 4, 4, , , 'texture-compression-etc2', 'etc2-rgb8unorm'],
174 'etc2-rgb8unorm-srgb': [ , , , , , , , , , 'float', 8, 4, 4, , , 'texture-compression-etc2', 'etc2-rgb8unorm'],
175 'etc2-rgb8a1unorm': [ , , , , , , , , , 'float', 8, 4, 4, , , 'texture-compression-etc2', 'etc2-rgb8a1unorm'],
176 'etc2-rgb8a1unorm-srgb': [ , , , , , , , , , 'float', 8, 4, 4, , , 'texture-compression-etc2', 'etc2-rgb8a1unorm'],
177 'etc2-rgba8unorm': [ , , , , , , , , , 'float', 16, 4, 4, , , 'texture-compression-etc2', 'etc2-rgba8unorm'],
178 'etc2-rgba8unorm-srgb': [ , , , , , , , , , 'float', 16, 4, 4, , , 'texture-compression-etc2', 'etc2-rgba8unorm'],
179 'eac-r11unorm': [ , , , , , , , , , 'float', 8, 4, 4, , , 'texture-compression-etc2'],
180 'eac-r11snorm': [ , , , , , , , , , 'float', 8, 4, 4, , , 'texture-compression-etc2'],
181 'eac-rg11unorm': [ , , , , , , , , , 'float', 16, 4, 4, , , 'texture-compression-etc2'],
182 'eac-rg11snorm': [ , , , , , , , , , 'float', 16, 4, 4, , , 'texture-compression-etc2'],
Lokbondo Kung0e9ad2d2021-11-16 17:57:05 -0800183} as const);
184const kASTCTextureFormatInfo = /* prettier-ignore */ makeTable(kTexFmtInfoHeader,
Lokbondo Kunga7e54e72023-01-26 11:51:32 -0800185 [ false, false, false, true, false, false, false, true, true, , , , , , , , undefined] as const, {
Lokbondo Kung0e9ad2d2021-11-16 17:57:05 -0800186 // Adaptable Scalable Compression (ASTC) formats
Lokbondo Kunga7e54e72023-01-26 11:51:32 -0800187 'astc-4x4-unorm': [ , , , , , , , , , 'float', 16, 4, 4, , , 'texture-compression-astc', 'astc-4x4-unorm'],
188 'astc-4x4-unorm-srgb': [ , , , , , , , , , 'float', 16, 4, 4, , , 'texture-compression-astc', 'astc-4x4-unorm'],
189 'astc-5x4-unorm': [ , , , , , , , , , 'float', 16, 5, 4, , , 'texture-compression-astc', 'astc-5x4-unorm'],
190 'astc-5x4-unorm-srgb': [ , , , , , , , , , 'float', 16, 5, 4, , , 'texture-compression-astc', 'astc-5x4-unorm'],
191 'astc-5x5-unorm': [ , , , , , , , , , 'float', 16, 5, 5, , , 'texture-compression-astc', 'astc-5x5-unorm'],
192 'astc-5x5-unorm-srgb': [ , , , , , , , , , 'float', 16, 5, 5, , , 'texture-compression-astc', 'astc-5x5-unorm'],
193 'astc-6x5-unorm': [ , , , , , , , , , 'float', 16, 6, 5, , , 'texture-compression-astc', 'astc-6x5-unorm'],
194 'astc-6x5-unorm-srgb': [ , , , , , , , , , 'float', 16, 6, 5, , , 'texture-compression-astc', 'astc-6x5-unorm'],
195 'astc-6x6-unorm': [ , , , , , , , , , 'float', 16, 6, 6, , , 'texture-compression-astc', 'astc-6x6-unorm'],
196 'astc-6x6-unorm-srgb': [ , , , , , , , , , 'float', 16, 6, 6, , , 'texture-compression-astc', 'astc-6x6-unorm'],
197 'astc-8x5-unorm': [ , , , , , , , , , 'float', 16, 8, 5, , , 'texture-compression-astc', 'astc-8x5-unorm'],
198 'astc-8x5-unorm-srgb': [ , , , , , , , , , 'float', 16, 8, 5, , , 'texture-compression-astc', 'astc-8x5-unorm'],
199 'astc-8x6-unorm': [ , , , , , , , , , 'float', 16, 8, 6, , , 'texture-compression-astc', 'astc-8x6-unorm'],
200 'astc-8x6-unorm-srgb': [ , , , , , , , , , 'float', 16, 8, 6, , , 'texture-compression-astc', 'astc-8x6-unorm'],
201 'astc-8x8-unorm': [ , , , , , , , , , 'float', 16, 8, 8, , , 'texture-compression-astc', 'astc-8x8-unorm'],
202 'astc-8x8-unorm-srgb': [ , , , , , , , , , 'float', 16, 8, 8, , , 'texture-compression-astc', 'astc-8x8-unorm'],
203 'astc-10x5-unorm': [ , , , , , , , , , 'float', 16, 10, 5, , , 'texture-compression-astc', 'astc-10x5-unorm'],
204 'astc-10x5-unorm-srgb': [ , , , , , , , , , 'float', 16, 10, 5, , , 'texture-compression-astc', 'astc-10x5-unorm'],
205 'astc-10x6-unorm': [ , , , , , , , , , 'float', 16, 10, 6, , , 'texture-compression-astc', 'astc-10x6-unorm'],
206 'astc-10x6-unorm-srgb': [ , , , , , , , , , 'float', 16, 10, 6, , , 'texture-compression-astc', 'astc-10x6-unorm'],
207 'astc-10x8-unorm': [ , , , , , , , , , 'float', 16, 10, 8, , , 'texture-compression-astc', 'astc-10x8-unorm'],
208 'astc-10x8-unorm-srgb': [ , , , , , , , , , 'float', 16, 10, 8, , , 'texture-compression-astc', 'astc-10x8-unorm'],
209 'astc-10x10-unorm': [ , , , , , , , , , 'float', 16, 10, 10, , , 'texture-compression-astc', 'astc-10x10-unorm'],
210 'astc-10x10-unorm-srgb': [ , , , , , , , , , 'float', 16, 10, 10, , , 'texture-compression-astc', 'astc-10x10-unorm'],
211 'astc-12x10-unorm': [ , , , , , , , , , 'float', 16, 12, 10, , , 'texture-compression-astc', 'astc-12x10-unorm'],
212 'astc-12x10-unorm-srgb': [ , , , , , , , , , 'float', 16, 12, 10, , , 'texture-compression-astc', 'astc-12x10-unorm'],
213 'astc-12x12-unorm': [ , , , , , , , , , 'float', 16, 12, 12, , , 'texture-compression-astc', 'astc-12x12-unorm'],
214 'astc-12x12-unorm-srgb': [ , , , , , , , , , 'float', 16, 12, 12, , , 'texture-compression-astc', 'astc-12x12-unorm'],
Lokbondo Kung0e9ad2d2021-11-16 17:57:05 -0800215} as const);
Kai Ninomiyaf0d24f32020-12-11 16:42:29 -0800216
Kai Ninomiya97c60c42021-06-14 16:55:24 -0700217// Definitions for use locally. To access the table entries, use `kTextureFormatInfo`.
Kai Ninomiyaa9ea59f2021-02-10 16:13:49 -0800218
Kai Ninomiya7c40d212022-01-04 14:25:02 -0800219// MAINTENANCE_TODO: Consider generating the exports below programmatically by filtering the big list, instead
Kai Ninomiya97c60c42021-06-14 16:55:24 -0700220// of using these local constants? Requires some type magic though.
Lokbondo Kung0e9ad2d2021-11-16 17:57:05 -0800221/* prettier-ignore */ const kCompressedTextureFormatInfo = { ...kBCTextureFormatInfo, ...kETC2TextureFormatInfo, ...kASTCTextureFormatInfo } as const;
Kai Ninomiya97c60c42021-06-14 16:55:24 -0700222/* prettier-ignore */ const kColorTextureFormatInfo = { ...kRegularTextureFormatInfo, ...kCompressedTextureFormatInfo } as const;
223/* prettier-ignore */ const kEncodableTextureFormatInfo = { ...kRegularTextureFormatInfo, ...kSizedDepthStencilFormatInfo } as const;
224/* prettier-ignore */ const kSizedTextureFormatInfo = { ...kRegularTextureFormatInfo, ...kSizedDepthStencilFormatInfo, ...kCompressedTextureFormatInfo } as const;
225/* prettier-ignore */ const kDepthStencilFormatInfo = { ...kSizedDepthStencilFormatInfo, ...kUnsizedDepthStencilFormatInfo } as const;
226/* prettier-ignore */ const kUncompressedTextureFormatInfo = { ...kRegularTextureFormatInfo, ...kSizedDepthStencilFormatInfo, ...kUnsizedDepthStencilFormatInfo } as const;
227/* prettier-ignore */ const kAllTextureFormatInfo = { ...kUncompressedTextureFormatInfo, ...kCompressedTextureFormatInfo } as const;
Kai Ninomiyaebef1472020-08-14 15:21:09 -0700228
Kai Ninomiya97c60c42021-06-14 16:55:24 -0700229/** A "regular" texture format (uncompressed, sized, single-plane color formats). */
230/* prettier-ignore */ export type RegularTextureFormat = keyof typeof kRegularTextureFormatInfo;
231/** A sized depth/stencil texture format. */
232/* prettier-ignore */ export type SizedDepthStencilFormat = keyof typeof kSizedDepthStencilFormatInfo;
233/** An unsized depth/stencil texture format. */
234/* prettier-ignore */ export type UnsizedDepthStencilFormat = keyof typeof kUnsizedDepthStencilFormatInfo;
235/** A compressed (block) texture format. */
236/* prettier-ignore */ export type CompressedTextureFormat = keyof typeof kCompressedTextureFormatInfo;
Kai Ninomiyaebef1472020-08-14 15:21:09 -0700237
Kai Ninomiya97c60c42021-06-14 16:55:24 -0700238/** A color texture format (regular | compressed). */
239/* prettier-ignore */ export type ColorTextureFormat = keyof typeof kColorTextureFormatInfo;
240/** An encodable texture format (regular | sized depth/stencil). */
241/* prettier-ignore */ export type EncodableTextureFormat = keyof typeof kEncodableTextureFormatInfo;
242/** A sized texture format (regular | sized depth/stencil | compressed). */
243/* prettier-ignore */ export type SizedTextureFormat = keyof typeof kSizedTextureFormatInfo;
244/** A depth/stencil format (sized | unsized). */
245/* prettier-ignore */ export type DepthStencilFormat = keyof typeof kDepthStencilFormatInfo;
246/** An uncompressed (block size 1x1) format (regular | depth/stencil). */
247/* prettier-ignore */ export type UncompressedTextureFormat = keyof typeof kUncompressedTextureFormatInfo;
Kai Ninomiyaebef1472020-08-14 15:21:09 -0700248
Kai Ninomiya97c60c42021-06-14 16:55:24 -0700249/* prettier-ignore */ export const kRegularTextureFormats: readonly RegularTextureFormat[] = keysOf( kRegularTextureFormatInfo);
250/* prettier-ignore */ export const kSizedDepthStencilFormats: readonly SizedDepthStencilFormat[] = keysOf( kSizedDepthStencilFormatInfo);
251/* prettier-ignore */ export const kUnsizedDepthStencilFormats: readonly UnsizedDepthStencilFormat[] = keysOf(kUnsizedDepthStencilFormatInfo);
252/* prettier-ignore */ export const kCompressedTextureFormats: readonly CompressedTextureFormat[] = keysOf( kCompressedTextureFormatInfo);
Kai Ninomiyaebef1472020-08-14 15:21:09 -0700253
Kai Ninomiya97c60c42021-06-14 16:55:24 -0700254/* prettier-ignore */ export const kColorTextureFormats: readonly ColorTextureFormat[] = keysOf( kColorTextureFormatInfo);
255/* prettier-ignore */ export const kEncodableTextureFormats: readonly EncodableTextureFormat[] = keysOf( kEncodableTextureFormatInfo);
256/* prettier-ignore */ export const kSizedTextureFormats: readonly SizedTextureFormat[] = keysOf( kSizedTextureFormatInfo);
257/* prettier-ignore */ export const kDepthStencilFormats: readonly DepthStencilFormat[] = keysOf( kDepthStencilFormatInfo);
258/* prettier-ignore */ export const kUncompressedTextureFormats: readonly UncompressedTextureFormat[] = keysOf(kUncompressedTextureFormatInfo);
Jiawei Shao6635a5c2021-10-26 08:45:16 +0800259/* prettier-ignore */ export const kAllTextureFormats: readonly GPUTextureFormat[] = keysOf( kAllTextureFormatInfo);
Kai Ninomiyaebef1472020-08-14 15:21:09 -0700260
ShrekShao20aa9312021-08-11 18:55:41 -0700261// CompressedTextureFormat are unrenderable so filter from RegularTextureFormats for color targets is enough
262export const kRenderableColorTextureFormats = kRegularTextureFormats.filter(
263 v => kColorTextureFormatInfo[v].renderable
264);
Lokbondo Kunga7e54e72023-01-26 11:51:32 -0800265assert(
266 kRenderableColorTextureFormats.every(
267 f =>
268 kAllTextureFormatInfo[f].renderTargetComponentAlignment !== undefined &&
269 kAllTextureFormatInfo[f].renderTargetPixelByteCost !== undefined
270 )
271);
ShrekShao20aa9312021-08-11 18:55:41 -0700272
Jie Chen77fbca42022-02-11 03:29:01 +0800273// The formats of GPUTextureFormat for canvas context.
Jie Chenc02319b2022-02-23 11:26:24 +0800274export const kCanvasTextureFormats = ['bgra8unorm', 'rgba8unorm', 'rgba16float'] as const;
Jie Chen77fbca42022-02-11 03:29:01 +0800275
ShrekShao94fd8382022-07-29 15:54:56 -0700276// The alpha mode for canvas context.
Gregg Tavares7e5c2032023-01-17 16:30:14 -0800277export const kCanvasAlphaModesInfo: {
278 readonly [k in GPUCanvasAlphaMode]: {};
279} = /* prettier-ignore */ {
280 'opaque': {},
281 'premultiplied': {},
282};
283export const kCanvasAlphaModes = keysOf(kCanvasAlphaModesInfo);
284
285// The color spaces for canvas context
286export const kCanvasColorSpacesInfo: {
287 readonly [k in PredefinedColorSpace]: {};
288} = /* prettier-ignore */ {
289 'srgb': {},
290 'display-p3': {},
291};
292export const kCanvasColorSpaces = keysOf(kCanvasColorSpacesInfo);
ShrekShao94fd8382022-07-29 15:54:56 -0700293
Kai Ninomiya97c60c42021-06-14 16:55:24 -0700294/** Per-GPUTextureFormat info. */
295// Exists just for documentation. Otherwise could be inferred by `makeTable`.
Kai Ninomiya7c40d212022-01-04 14:25:02 -0800296// MAINTENANCE_TODO: Refactor this to separate per-aspect data for multi-aspect formats. In particular:
Kai Ninomiya97c60c42021-06-14 16:55:24 -0700297// - bytesPerBlock only makes sense on a per-aspect basis. But this table can't express that.
Brandon Jones6ff55952022-06-07 12:19:06 -0700298// So we put depth32float-stencil8 to be an unsized format for now.
Kai Ninomiya97c60c42021-06-14 16:55:24 -0700299export type TextureFormatInfo = {
300 /** Whether the format can be used as `RENDER_ATTACHMENT`. */
301 renderable: boolean;
302 /** Whether the format can be used in a multisample texture. */
303 multisample: boolean;
Jiawei Shao008969e2022-03-01 09:25:12 +0800304 /** Whether the texture with the format can be used as a resolve target. */
305 resolve: boolean;
Kai Ninomiya97c60c42021-06-14 16:55:24 -0700306 /** Whether the format has a color aspect. */
307 color: boolean;
308 /** Whether the format has a depth aspect. */
309 depth: boolean;
310 /** Whether the format has a stencil aspect. */
311 stencil: boolean;
312 /** Whether the format can be used as `STORAGE`. */
313 storage: boolean;
314 /** Whether the format can be used as `COPY_SRC`. */
315 copySrc: boolean;
316 /** Whether the format can be used as `COPY_DST`. */
317 copyDst: boolean;
318 /** Byte size of one texel block, or `undefined` if the format is unsized. */
319 bytesPerBlock: number | undefined;
320 /** Width, in texels, of one texel block. */
321 blockWidth: number;
322 /** Height, in texels, of one texel block. */
323 blockHeight: number;
Lokbondo Kunga7e54e72023-01-26 11:51:32 -0800324 /** The raw, unaligned, byte cost towards the color attachment bytes per sample.
325 * (See https://www.w3.org/TR/webgpu/#abstract-opdef-calculating-color-attachment-bytes-per-sample). */
326 renderTargetPixelByteCost: number | undefined;
327 /** The alignment used for the format when computing the color attachment bytes per sample. */
328 renderTargetComponentAlignment: number | undefined;
Kai Ninomiya97c60c42021-06-14 16:55:24 -0700329 /** Optional feature required to use this format, or `undefined` if none. */
330 feature: GPUFeatureName | undefined;
331 // Add fields as needed
332};
333/** Per-GPUTextureFormat info. */
334export const kTextureFormatInfo: {
335 readonly [k in GPUTextureFormat]: TextureFormatInfo &
336 // TextureFormatInfo exists just for documentation (and verification of the table data types).
337 // The next line constrains the types so that accessing kTextureFormatInfo with
338 // a subtype of GPUTextureFormat actually returns nicely a constrained info type
339 // (e.g. with `bytesPerBlock: number` instead of `bytesPerBlock: number | undefined`).
340 typeof kAllTextureFormatInfo[k];
341} = kAllTextureFormatInfo;
342/** List of all GPUTextureFormat values. */
343/* prettier-ignore */ export const kTextureFormats: readonly GPUTextureFormat[] = keysOf(kAllTextureFormatInfo);
Kai Ninomiyaebef1472020-08-14 15:21:09 -0700344
Kai Ninomiya97c60c42021-06-14 16:55:24 -0700345/** Valid GPUTextureFormats for `copyExternalImageToTexture`, by spec. */
Yan, Shaoboc53abb72021-07-28 09:33:51 +0800346export const kValidTextureFormatsForCopyE2T = [
Yan, Shaobo027e3392021-11-06 03:29:52 +0800347 'r8unorm',
348 'r16float',
349 'r32float',
350 'rg8unorm',
351 'rg16float',
352 'rg32float',
Yan, Shaobo7c0e4f92021-06-02 03:14:49 +0800353 'rgba8unorm',
354 'rgba8unorm-srgb',
355 'bgra8unorm',
356 'bgra8unorm-srgb',
357 'rgb10a2unorm',
Yan, Shaobo027e3392021-11-06 03:29:52 +0800358 'rgba16float',
359 'rgba32float',
Yan, Shaobo7c0e4f92021-06-02 03:14:49 +0800360] as const;
361
Kai Ninomiya97c60c42021-06-14 16:55:24 -0700362/** Per-GPUTextureDimension info. */
Austin Eng212317f2020-04-16 17:22:27 -0700363export const kTextureDimensionInfo: {
Kai Ninomiya97c60c42021-06-14 16:55:24 -0700364 readonly [k in GPUTextureDimension]: {};
Austin Eng212317f2020-04-16 17:22:27 -0700365} = /* prettier-ignore */ {
366 '1d': {},
367 '2d': {},
368 '3d': {},
369};
Kai Ninomiya97c60c42021-06-14 16:55:24 -0700370/** List of all GPUTextureDimension values. */
Kai Ninomiya3a50e8b2020-04-28 20:38:31 -0700371export const kTextureDimensions = keysOf(kTextureDimensionInfo);
Austin Eng212317f2020-04-16 17:22:27 -0700372
Kai Ninomiya97c60c42021-06-14 16:55:24 -0700373/** Per-GPUTextureAspect info. */
Austin Eng212317f2020-04-16 17:22:27 -0700374export const kTextureAspectInfo: {
Kai Ninomiya97c60c42021-06-14 16:55:24 -0700375 readonly [k in GPUTextureAspect]: {};
Austin Eng212317f2020-04-16 17:22:27 -0700376} = /* prettier-ignore */ {
377 'all': {},
378 'depth-only': {},
379 'stencil-only': {},
380};
Kai Ninomiya97c60c42021-06-14 16:55:24 -0700381/** List of all GPUTextureAspect values. */
Kai Ninomiya3a50e8b2020-04-28 20:38:31 -0700382export const kTextureAspects = keysOf(kTextureAspectInfo);
383
Yunchao He2370ee02022-01-07 18:15:44 -0800384/** Per-GPUCompareFunction info. */
385export const kCompareFunctionInfo: {
386 readonly [k in GPUCompareFunction]: {};
387} = /* prettier-ignore */ {
388 'never': {},
389 'less': {},
390 'equal': {},
391 'less-equal': {},
392 'greater': {},
393 'not-equal': {},
394 'greater-equal': {},
395 'always': {},
396};
397/** List of all GPUCompareFunction values. */
398export const kCompareFunctions = keysOf(kCompareFunctionInfo);
399
400/** Per-GPUStencilOperation info. */
401export const kStencilOperationInfo: {
402 readonly [k in GPUStencilOperation]: {};
403} = /* prettier-ignore */ {
404 'keep': {},
405 'zero': {},
406 'replace': {},
407 'invert': {},
408 'increment-clamp': {},
409 'decrement-clamp': {},
410 'increment-wrap': {},
411 'decrement-wrap': {},
412};
413/** List of all GPUStencilOperation values. */
414export const kStencilOperations = keysOf(kStencilOperationInfo);
415
Jiawei Shaoa9ac8c32021-03-04 02:53:13 +0800416const kDepthStencilFormatCapabilityInBufferTextureCopy = {
417 // kUnsizedDepthStencilFormats
418 depth24plus: {
419 CopyB2T: [],
420 CopyT2B: [],
Jiawei Shao7aa36022021-03-12 16:46:06 +0800421 texelAspectSize: { 'depth-only': -1, 'stencil-only': -1 },
Jiawei Shaoa9ac8c32021-03-04 02:53:13 +0800422 },
423 'depth24plus-stencil8': {
424 CopyB2T: ['stencil-only'],
425 CopyT2B: ['stencil-only'],
Jiawei Shao7aa36022021-03-12 16:46:06 +0800426 texelAspectSize: { 'depth-only': -1, 'stencil-only': 1 },
Jiawei Shaoa9ac8c32021-03-04 02:53:13 +0800427 },
428
429 // kSizedDepthStencilFormats
430 depth16unorm: {
431 CopyB2T: ['all', 'depth-only'],
432 CopyT2B: ['all', 'depth-only'],
Jiawei Shao7aa36022021-03-12 16:46:06 +0800433 texelAspectSize: { 'depth-only': 2, 'stencil-only': -1 },
Jiawei Shaoa9ac8c32021-03-04 02:53:13 +0800434 },
435 depth32float: {
436 CopyB2T: [],
437 CopyT2B: ['all', 'depth-only'],
Jiawei Shao7aa36022021-03-12 16:46:06 +0800438 texelAspectSize: { 'depth-only': 4, 'stencil-only': -1 },
Jiawei Shaoa9ac8c32021-03-04 02:53:13 +0800439 },
Jiawei Shaoa9ac8c32021-03-04 02:53:13 +0800440 'depth32float-stencil8': {
441 CopyB2T: ['stencil-only'],
442 CopyT2B: ['depth-only', 'stencil-only'],
Jiawei Shao7aa36022021-03-12 16:46:06 +0800443 texelAspectSize: { 'depth-only': 4, 'stencil-only': 1 },
Jiawei Shaoa9ac8c32021-03-04 02:53:13 +0800444 },
445 stencil8: {
446 CopyB2T: ['all', 'stencil-only'],
447 CopyT2B: ['all', 'stencil-only'],
Jiawei Shao7aa36022021-03-12 16:46:06 +0800448 texelAspectSize: { 'depth-only': -1, 'stencil-only': 1 },
Jiawei Shaoa9ac8c32021-03-04 02:53:13 +0800449 },
450} as const;
451
Corentin Wallez23afd042022-04-05 16:20:39 +0100452/** `kDepthStencilFormatResolvedAspect[format][aspect]` returns the aspect-specific format for a
453 * depth-stencil format, or `undefined` if the format doesn't have the aspect.
454 */
455export const kDepthStencilFormatResolvedAspect: {
456 readonly [k in DepthStencilFormat]: {
457 readonly [a in GPUTextureAspect]: DepthStencilFormat | undefined;
458 };
459} = {
460 // kUnsizedDepthStencilFormats
461 depth24plus: {
462 all: 'depth24plus',
463 'depth-only': 'depth24plus',
464 'stencil-only': undefined,
465 },
466 'depth24plus-stencil8': {
467 all: 'depth24plus-stencil8',
468 'depth-only': 'depth24plus',
469 'stencil-only': 'stencil8',
470 },
471
472 // kSizedDepthStencilFormats
473 depth16unorm: {
474 all: 'depth16unorm',
475 'depth-only': 'depth16unorm',
476 'stencil-only': undefined,
477 },
478 depth32float: {
479 all: 'depth32float',
480 'depth-only': 'depth32float',
481 'stencil-only': undefined,
482 },
Corentin Wallez23afd042022-04-05 16:20:39 +0100483 'depth32float-stencil8': {
484 all: 'depth32float-stencil8',
485 'depth-only': 'depth32float',
486 'stencil-only': 'stencil8',
487 },
488 stencil8: {
489 all: 'stencil8',
490 'depth-only': undefined,
491 'stencil-only': 'stencil8',
492 },
493} as const;
494
Kai Ninomiya97c60c42021-06-14 16:55:24 -0700495/**
Corentin Wallezf030b5f2022-04-08 22:31:28 +0100496 * @returns the GPUTextureFormat corresponding to the @param aspect of @param format.
497 * This allows choosing the correct format for depth-stencil aspects when creating pipelines that
498 * will have to match the resolved format of views, or to get per-aspect information like the
499 * `blockByteSize`.
500 *
501 * Many helpers use an `undefined` `aspect` to means `'all'` so this is also the default for this
502 * function.
503 */
504export function resolvePerAspectFormat(
505 format: GPUTextureFormat,
506 aspect?: GPUTextureAspect
507): GPUTextureFormat {
508 if (aspect === 'all' || aspect === undefined) {
509 return format;
510 }
511 assert(kTextureFormatInfo[format].depth || kTextureFormatInfo[format].stencil);
512 const resolved = kDepthStencilFormatResolvedAspect[format as DepthStencilFormat][aspect ?? 'all'];
513 assert(resolved !== undefined);
Kai Ninomiyabd447342022-05-16 21:50:43 -0700514 return resolved;
Corentin Wallezf030b5f2022-04-08 22:31:28 +0100515}
516
517/**
Yunchao Hea9755892021-08-19 16:49:29 -0700518 * Gets all copyable aspects for copies between texture and buffer for specified depth/stencil format and copy type, by spec.
519 */
520export function depthStencilFormatCopyableAspects(
521 type: ImageCopyType,
522 format: DepthStencilFormat
523): readonly GPUTextureAspect[] {
524 const appliedType = type === 'WriteTexture' ? 'CopyB2T' : type;
525 return kDepthStencilFormatCapabilityInBufferTextureCopy[format][appliedType];
526}
527
528/**
Kai Ninomiya97c60c42021-06-14 16:55:24 -0700529 * Computes whether a copy between a depth/stencil texture aspect and a buffer is supported, by spec.
530 */
Jiawei Shaoa9ac8c32021-03-04 02:53:13 +0800531export function depthStencilBufferTextureCopySupported(
Yunchao Hea9755892021-08-19 16:49:29 -0700532 type: ImageCopyType,
Jiawei Shaoa9ac8c32021-03-04 02:53:13 +0800533 format: DepthStencilFormat,
534 aspect: GPUTextureAspect
535): boolean {
Yunchao Hea9755892021-08-19 16:49:29 -0700536 const supportedAspects: readonly GPUTextureAspect[] = depthStencilFormatCopyableAspects(
537 type,
538 format
539 );
Jiawei Shaoa9ac8c32021-03-04 02:53:13 +0800540 return supportedAspects.includes(aspect);
541}
542
Kai Ninomiya97c60c42021-06-14 16:55:24 -0700543/**
544 * Returns the byte size of the depth or stencil aspect of the specified depth/stencil format,
545 * or -1 if none.
546 */
Jiawei Shao7aa36022021-03-12 16:46:06 +0800547export function depthStencilFormatAspectSize(
548 format: DepthStencilFormat,
549 aspect: 'depth-only' | 'stencil-only'
550) {
551 const texelAspectSize =
552 kDepthStencilFormatCapabilityInBufferTextureCopy[format].texelAspectSize[aspect];
553 assert(texelAspectSize > 0);
554 return texelAspectSize;
555}
556
Kai Ninomiya97c60c42021-06-14 16:55:24 -0700557/**
558 * Returns true iff a texture can be created with the provided GPUTextureDimension
559 * (defaulting to 2d) and GPUTextureFormat, by spec.
560 */
Yunchao He6c9e3762021-04-09 12:45:15 -0700561export function textureDimensionAndFormatCompatible(
562 dimension: undefined | GPUTextureDimension,
563 format: GPUTextureFormat
564): boolean {
Kai Ninomiya97c60c42021-06-14 16:55:24 -0700565 const info = kAllTextureFormatInfo[format];
Yunchao He6c9e3762021-04-09 12:45:15 -0700566 return !(
567 (dimension === '1d' || dimension === '3d') &&
568 (info.blockWidth > 1 || info.depth || info.stencil)
569 );
570}
571
Lokbondo Kung300c10c2022-03-22 10:53:42 -0700572/** Per-GPUTextureUsage type info. */
573export const kTextureUsageTypeInfo: {
574 readonly [name: string]: number;
575} = /* prettier-ignore */ {
576 'texture': Number(GPUConst.TextureUsage.TEXTURE_BINDING),
577 'storage': Number(GPUConst.TextureUsage.STORAGE_BINDING),
578 'render': Number(GPUConst.TextureUsage.RENDER_ATTACHMENT),
579};
580/** List of all GPUTextureUsage type values. */
581export const kTextureUsageType = keysOf(kTextureUsageTypeInfo);
582
583/** Per-GPUTextureUsage copy info. */
584export const kTextureUsageCopyInfo: {
585 readonly [name: string]: number;
586} = /* prettier-ignore */ {
587 'none': 0,
588 'src': Number(GPUConst.TextureUsage.COPY_SRC),
589 'dst': Number(GPUConst.TextureUsage.COPY_DST),
590 'src-dest': Number(GPUConst.TextureUsage.COPY_SRC) | Number(GPUConst.TextureUsage.COPY_DST),
591};
592/** List of all GPUTextureUsage copy values. */
593export const kTextureUsageCopy = keysOf(kTextureUsageCopyInfo);
594
Kai Ninomiya97c60c42021-06-14 16:55:24 -0700595/** Per-GPUTextureUsage info. */
Kai Ninomiya3a50e8b2020-04-28 20:38:31 -0700596export const kTextureUsageInfo: {
Kai Ninomiya51682ed2021-04-13 19:23:48 -0700597 readonly [k in valueof<typeof GPUConst.TextureUsage>]: {};
Kai Ninomiya3a50e8b2020-04-28 20:38:31 -0700598} = {
Kai Ninomiya04e404f2020-10-23 16:02:19 -0700599 [GPUConst.TextureUsage.COPY_SRC]: {},
600 [GPUConst.TextureUsage.COPY_DST]: {},
Brandon Jones201435f2021-08-12 13:47:21 -0700601 [GPUConst.TextureUsage.TEXTURE_BINDING]: {},
602 [GPUConst.TextureUsage.STORAGE_BINDING]: {},
Brandon Jonesd048d11d2021-02-01 18:11:48 -0800603 [GPUConst.TextureUsage.RENDER_ATTACHMENT]: {},
Kai Ninomiya3a50e8b2020-04-28 20:38:31 -0700604};
Kai Ninomiya97c60c42021-06-14 16:55:24 -0700605/** List of all GPUTextureUsage values. */
Kai Ninomiya51682ed2021-04-13 19:23:48 -0700606export const kTextureUsages = numericKeysOf<GPUTextureUsageFlags>(kTextureUsageInfo);
Kai Ninomiya3a50e8b2020-04-28 20:38:31 -0700607
Yunchao Head960542020-07-15 11:20:51 -0700608// Texture View
609
Kai Ninomiya97c60c42021-06-14 16:55:24 -0700610/** Per-GPUTextureViewDimension info. */
611export type TextureViewDimensionInfo = {
612 /** Whether a storage texture view can have this view dimension. */
613 readonly storage: boolean;
614 // Add fields as needed
615};
616/** Per-GPUTextureViewDimension info. */
Yunchao Head960542020-07-15 11:20:51 -0700617export const kTextureViewDimensionInfo: {
Kai Ninomiya97c60c42021-06-14 16:55:24 -0700618 readonly [k in GPUTextureViewDimension]: TextureViewDimensionInfo;
Yunchao Head960542020-07-15 11:20:51 -0700619} = /* prettier-ignore */ {
Yunchao Hecb0d5bb2020-07-27 11:01:12 -0700620 '1d': { storage: true },
621 '2d': { storage: true },
622 '2d-array': { storage: true },
623 'cube': { storage: false },
624 'cube-array': { storage: false },
625 '3d': { storage: true },
Yunchao Head960542020-07-15 11:20:51 -0700626};
Kai Ninomiya97c60c42021-06-14 16:55:24 -0700627/** List of all GPUTextureDimension values. */
Yunchao Head960542020-07-15 11:20:51 -0700628export const kTextureViewDimensions = keysOf(kTextureViewDimensionInfo);
629
Corentin Wallez056afcf2021-03-11 07:26:23 +0000630// Vertex formats
631
Kai Ninomiya97c60c42021-06-14 16:55:24 -0700632/** Per-GPUVertexFormat info. */
633// Exists just for documentation. Otherwise could be inferred by `makeTable`.
634export type VertexFormatInfo = {
635 /** Number of bytes in each component. */
636 readonly bytesPerComponent: 1 | 2 | 4;
637 /** The data encoding (float, normalized, or integer) for each component. */
638 readonly type: 'float' | 'unorm' | 'snorm' | 'uint' | 'sint';
639 /** Number of components. */
640 readonly componentCount: 1 | 2 | 3 | 4;
jzm-intel7829cf72021-08-25 09:27:06 +0800641 /** The completely matching WGSL type for vertex format */
642 readonly wgslType:
643 | 'f32'
644 | 'vec2<f32>'
645 | 'vec3<f32>'
646 | 'vec4<f32>'
647 | 'u32'
648 | 'vec2<u32>'
649 | 'vec3<u32>'
650 | 'vec4<u32>'
651 | 'i32'
652 | 'vec2<i32>'
653 | 'vec3<i32>'
654 | 'vec4<i32>';
Kai Ninomiya97c60c42021-06-14 16:55:24 -0700655 // Add fields as needed
656};
657/** Per-GPUVertexFormat info. */
658export const kVertexFormatInfo: {
659 readonly [k in GPUVertexFormat]: VertexFormatInfo;
660} = /* prettier-ignore */ makeTable(
jzm-intel7829cf72021-08-25 09:27:06 +0800661 ['bytesPerComponent', 'type', 'componentCount', 'wgslType'] as const,
662 [ , , , ] as const, {
Corentin Wallez056afcf2021-03-11 07:26:23 +0000663 // 8 bit components
jzm-intel7829cf72021-08-25 09:27:06 +0800664 'uint8x2': [ 1, 'uint', 2, 'vec2<u32>'],
665 'uint8x4': [ 1, 'uint', 4, 'vec4<u32>'],
666 'sint8x2': [ 1, 'sint', 2, 'vec2<i32>'],
667 'sint8x4': [ 1, 'sint', 4, 'vec4<i32>'],
668 'unorm8x2': [ 1, 'unorm', 2, 'vec2<f32>'],
669 'unorm8x4': [ 1, 'unorm', 4, 'vec4<f32>'],
670 'snorm8x2': [ 1, 'snorm', 2, 'vec2<f32>'],
671 'snorm8x4': [ 1, 'snorm', 4, 'vec4<f32>'],
Corentin Wallez056afcf2021-03-11 07:26:23 +0000672 // 16 bit components
jzm-intel7829cf72021-08-25 09:27:06 +0800673 'uint16x2': [ 2, 'uint', 2, 'vec2<u32>'],
674 'uint16x4': [ 2, 'uint', 4, 'vec4<u32>'],
675 'sint16x2': [ 2, 'sint', 2, 'vec2<i32>'],
676 'sint16x4': [ 2, 'sint', 4, 'vec4<i32>'],
677 'unorm16x2': [ 2, 'unorm', 2, 'vec2<f32>'],
678 'unorm16x4': [ 2, 'unorm', 4, 'vec4<f32>'],
679 'snorm16x2': [ 2, 'snorm', 2, 'vec2<f32>'],
680 'snorm16x4': [ 2, 'snorm', 4, 'vec4<f32>'],
681 'float16x2': [ 2, 'float', 2, 'vec2<f32>'],
682 'float16x4': [ 2, 'float', 4, 'vec4<f32>'],
Corentin Wallez056afcf2021-03-11 07:26:23 +0000683 // 32 bit components
jzm-intel7829cf72021-08-25 09:27:06 +0800684 'float32': [ 4, 'float', 1, 'f32'],
685 'float32x2': [ 4, 'float', 2, 'vec2<f32>'],
686 'float32x3': [ 4, 'float', 3, 'vec3<f32>'],
687 'float32x4': [ 4, 'float', 4, 'vec4<f32>'],
688 'uint32': [ 4, 'uint', 1, 'u32'],
689 'uint32x2': [ 4, 'uint', 2, 'vec2<u32>'],
690 'uint32x3': [ 4, 'uint', 3, 'vec3<u32>'],
691 'uint32x4': [ 4, 'uint', 4, 'vec4<u32>'],
692 'sint32': [ 4, 'sint', 1, 'i32'],
693 'sint32x2': [ 4, 'sint', 2, 'vec2<i32>'],
694 'sint32x3': [ 4, 'sint', 3, 'vec3<i32>'],
695 'sint32x4': [ 4, 'sint', 4, 'vec4<i32>']
Corentin Wallez056afcf2021-03-11 07:26:23 +0000696} as const);
Kai Ninomiya97c60c42021-06-14 16:55:24 -0700697/** List of all GPUVertexFormat values. */
Corentin Wallez056afcf2021-03-11 07:26:23 +0000698export const kVertexFormats = keysOf(kVertexFormatInfo);
699
Kai Ninomiya3a50e8b2020-04-28 20:38:31 -0700700// Typedefs for bindings
701
Kai Ninomiya97c60c42021-06-14 16:55:24 -0700702/**
703 * Classes of `PerShaderStage` binding limits. Two bindings with the same class
704 * count toward the same `PerShaderStage` limit(s) in the spec (if any).
705 */
Kai Ninomiya3a50e8b2020-04-28 20:38:31 -0700706export type PerStageBindingLimitClass =
707 | 'uniformBuf'
708 | 'storageBuf'
709 | 'sampler'
710 | 'sampledTex'
711 | 'storageTex';
Kai Ninomiya97c60c42021-06-14 16:55:24 -0700712/**
713 * Classes of `PerPipelineLayout` binding limits. Two bindings with the same class
714 * count toward the same `PerPipelineLayout` limit(s) in the spec (if any).
715 */
Kai Ninomiya3a50e8b2020-04-28 20:38:31 -0700716export type PerPipelineBindingLimitClass = PerStageBindingLimitClass;
717
Hao Liafc14d12021-08-31 10:02:06 +0800718export type ValidBindableResource =
Kai Ninomiya3a50e8b2020-04-28 20:38:31 -0700719 | 'uniformBuf'
720 | 'storageBuf'
Kai Ninomiyaff91b742021-04-20 18:41:59 -0700721 | 'filtSamp'
722 | 'nonFiltSamp'
Kai Ninomiya3a50e8b2020-04-28 20:38:31 -0700723 | 'compareSamp'
724 | 'sampledTex'
Kai Ninomiya6c4d36b2020-12-18 13:40:50 -0800725 | 'sampledTexMS'
Kai Ninomiya3a50e8b2020-04-28 20:38:31 -0700726 | 'storageTex';
727type ErrorBindableResource = 'errorBuf' | 'errorSamp' | 'errorTex';
Kai Ninomiya3a50e8b2020-04-28 20:38:31 -0700728
Kai Ninomiya97c60c42021-06-14 16:55:24 -0700729/**
730 * Types of resource binding which have distinct binding rules, by spec
731 * (e.g. filtering vs non-filtering sampler, multisample vs non-multisample texture).
732 */
Kai Ninomiyaff91b742021-04-20 18:41:59 -0700733export type BindableResource = ValidBindableResource | ErrorBindableResource;
734export const kBindableResources = [
735 'uniformBuf',
736 'storageBuf',
737 'filtSamp',
738 'nonFiltSamp',
739 'compareSamp',
740 'sampledTex',
741 'sampledTexMS',
742 'storageTex',
743 'errorBuf',
744 'errorSamp',
745 'errorTex',
746] as const;
747assertTypeTrue<TypeEqual<BindableResource, typeof kBindableResources[number]>>();
Austin Eng212317f2020-04-16 17:22:27 -0700748
Justin Fan5d1b8c72020-01-15 16:03:37 -0800749// Bindings
750
Kai Ninomiya97c60c42021-06-14 16:55:24 -0700751/** Dynamic buffer offsets require offset to be divisible by 256, by spec. */
Enrico Galli340098b2021-03-24 02:24:02 -0700752export const kMinDynamicBufferOffsetAlignment = 256;
753
Kai Ninomiya97c60c42021-06-14 16:55:24 -0700754/** Default `PerShaderStage` binding limits, by spec. */
Justin Fan5d1b8c72020-01-15 16:03:37 -0800755export const kPerStageBindingLimits: {
Kai Ninomiya3a50e8b2020-04-28 20:38:31 -0700756 readonly [k in PerStageBindingLimitClass]: {
Kai Ninomiya97c60c42021-06-14 16:55:24 -0700757 /** Which `PerShaderStage` binding limit class. */
Kai Ninomiya3a50e8b2020-04-28 20:38:31 -0700758 readonly class: k;
Kai Ninomiya97c60c42021-06-14 16:55:24 -0700759 /** Maximum number of allowed bindings in that class. */
Kai Ninomiya3a50e8b2020-04-28 20:38:31 -0700760 readonly max: number;
Kai Ninomiya86b055d2020-01-06 19:37:25 -0800761 // Add fields as needed
762 };
763} = /* prettier-ignore */ {
Kai Ninomiya3a50e8b2020-04-28 20:38:31 -0700764 'uniformBuf': { class: 'uniformBuf', max: 12, },
Corentin Wallez06e16c52021-06-03 23:18:02 +0200765 'storageBuf': { class: 'storageBuf', max: 8, },
Kai Ninomiya3a50e8b2020-04-28 20:38:31 -0700766 'sampler': { class: 'sampler', max: 16, },
767 'sampledTex': { class: 'sampledTex', max: 16, },
Ben Clayton7a9ca6e2021-10-01 18:49:00 +0100768 'storageTex': { class: 'storageTex', max: 4, },
Kai Ninomiya86b055d2020-01-06 19:37:25 -0800769};
Kai Ninomiya86b055d2020-01-06 19:37:25 -0800770
Kai Ninomiya97c60c42021-06-14 16:55:24 -0700771/**
772 * Default `PerPipelineLayout` binding limits, by spec.
773 */
Kai Ninomiya3a50e8b2020-04-28 20:38:31 -0700774export const kPerPipelineBindingLimits: {
775 readonly [k in PerPipelineBindingLimitClass]: {
Kai Ninomiya97c60c42021-06-14 16:55:24 -0700776 /** Which `PerPipelineLayout` binding limit class. */
Kai Ninomiya3a50e8b2020-04-28 20:38:31 -0700777 readonly class: k;
Kai Ninomiya97c60c42021-06-14 16:55:24 -0700778 /** Maximum number of allowed bindings with `hasDynamicOffset: true` in that class. */
Kai Ninomiya3a50e8b2020-04-28 20:38:31 -0700779 readonly maxDynamic: number;
780 // Add fields as needed
781 };
782} = /* prettier-ignore */ {
783 'uniformBuf': { class: 'uniformBuf', maxDynamic: 8, },
784 'storageBuf': { class: 'storageBuf', maxDynamic: 4, },
785 'sampler': { class: 'sampler', maxDynamic: 0, },
786 'sampledTex': { class: 'sampledTex', maxDynamic: 0, },
787 'storageTex': { class: 'storageTex', maxDynamic: 0, },
788};
789
Kai Ninomiya3a50e8b2020-04-28 20:38:31 -0700790interface BindingKindInfo {
791 readonly resource: ValidBindableResource;
792 readonly perStageLimitClass: typeof kPerStageBindingLimits[PerStageBindingLimitClass];
793 readonly perPipelineLimitClass: typeof kPerPipelineBindingLimits[PerPipelineBindingLimitClass];
794 // Add fields as needed
795}
796
797const kBindingKind: {
798 readonly [k in ValidBindableResource]: BindingKindInfo;
799} = /* prettier-ignore */ {
Kai Ninomiya6c4d36b2020-12-18 13:40:50 -0800800 uniformBuf: { resource: 'uniformBuf', perStageLimitClass: kPerStageBindingLimits.uniformBuf, perPipelineLimitClass: kPerPipelineBindingLimits.uniformBuf, },
801 storageBuf: { resource: 'storageBuf', perStageLimitClass: kPerStageBindingLimits.storageBuf, perPipelineLimitClass: kPerPipelineBindingLimits.storageBuf, },
Kai Ninomiyaff91b742021-04-20 18:41:59 -0700802 filtSamp: { resource: 'filtSamp', perStageLimitClass: kPerStageBindingLimits.sampler, perPipelineLimitClass: kPerPipelineBindingLimits.sampler, },
803 nonFiltSamp: { resource: 'nonFiltSamp', perStageLimitClass: kPerStageBindingLimits.sampler, perPipelineLimitClass: kPerPipelineBindingLimits.sampler, },
Kai Ninomiya6c4d36b2020-12-18 13:40:50 -0800804 compareSamp: { resource: 'compareSamp', perStageLimitClass: kPerStageBindingLimits.sampler, perPipelineLimitClass: kPerPipelineBindingLimits.sampler, },
805 sampledTex: { resource: 'sampledTex', perStageLimitClass: kPerStageBindingLimits.sampledTex, perPipelineLimitClass: kPerPipelineBindingLimits.sampledTex, },
806 sampledTexMS: { resource: 'sampledTexMS', perStageLimitClass: kPerStageBindingLimits.sampledTex, perPipelineLimitClass: kPerPipelineBindingLimits.sampledTex, },
807 storageTex: { resource: 'storageTex', perStageLimitClass: kPerStageBindingLimits.storageTex, perPipelineLimitClass: kPerPipelineBindingLimits.storageTex, },
Kai Ninomiya3a50e8b2020-04-28 20:38:31 -0700808};
809
810// Binding type info
811
Kai Ninomiya3a50e8b2020-04-28 20:38:31 -0700812const kValidStagesAll = {
Kai Ninomiya04e404f2020-10-23 16:02:19 -0700813 validStages:
814 GPUConst.ShaderStage.VERTEX | GPUConst.ShaderStage.FRAGMENT | GPUConst.ShaderStage.COMPUTE,
Kai Ninomiyaff91b742021-04-20 18:41:59 -0700815} as const;
Kai Ninomiya04e404f2020-10-23 16:02:19 -0700816const kValidStagesStorageWrite = {
817 validStages: GPUConst.ShaderStage.FRAGMENT | GPUConst.ShaderStage.COMPUTE,
Kai Ninomiyaff91b742021-04-20 18:41:59 -0700818} as const;
Kai Ninomiya3a50e8b2020-04-28 20:38:31 -0700819
Kai Ninomiya97c60c42021-06-14 16:55:24 -0700820/** Binding type info (including class limits) for the specified GPUBufferBindingLayout. */
Kai Ninomiyaff91b742021-04-20 18:41:59 -0700821export function bufferBindingTypeInfo(d: GPUBufferBindingLayout) {
822 /* prettier-ignore */
823 switch (d.type ?? 'uniform') {
824 case 'uniform': return { usage: GPUConst.BufferUsage.UNIFORM, ...kBindingKind.uniformBuf, ...kValidStagesAll, };
825 case 'storage': return { usage: GPUConst.BufferUsage.STORAGE, ...kBindingKind.storageBuf, ...kValidStagesStorageWrite, };
826 case 'read-only-storage': return { usage: GPUConst.BufferUsage.STORAGE, ...kBindingKind.storageBuf, ...kValidStagesAll, };
827 }
828}
Kai Ninomiya97c60c42021-06-14 16:55:24 -0700829/** List of all GPUBufferBindingType values. */
Kai Ninomiyaff91b742021-04-20 18:41:59 -0700830export const kBufferBindingTypes = ['uniform', 'storage', 'read-only-storage'] as const;
831assertTypeTrue<TypeEqual<GPUBufferBindingType, typeof kBufferBindingTypes[number]>>();
Kai Ninomiya3a50e8b2020-04-28 20:38:31 -0700832
Kai Ninomiya97c60c42021-06-14 16:55:24 -0700833/** Binding type info (including class limits) for the specified GPUSamplerBindingLayout. */
Kai Ninomiyaff91b742021-04-20 18:41:59 -0700834export function samplerBindingTypeInfo(d: GPUSamplerBindingLayout) {
835 /* prettier-ignore */
836 switch (d.type ?? 'filtering') {
837 case 'filtering': return { ...kBindingKind.filtSamp, ...kValidStagesAll, };
838 case 'non-filtering': return { ...kBindingKind.nonFiltSamp, ...kValidStagesAll, };
839 case 'comparison': return { ...kBindingKind.compareSamp, ...kValidStagesAll, };
840 }
841}
Kai Ninomiya97c60c42021-06-14 16:55:24 -0700842/** List of all GPUSamplerBindingType values. */
Kai Ninomiyaff91b742021-04-20 18:41:59 -0700843export const kSamplerBindingTypes = ['filtering', 'non-filtering', 'comparison'] as const;
844assertTypeTrue<TypeEqual<GPUSamplerBindingType, typeof kSamplerBindingTypes[number]>>();
Kai Ninomiya3a50e8b2020-04-28 20:38:31 -0700845
Kai Ninomiya97c60c42021-06-14 16:55:24 -0700846/** Binding type info (including class limits) for the specified GPUTextureBindingLayout. */
Kai Ninomiyaff91b742021-04-20 18:41:59 -0700847export function sampledTextureBindingTypeInfo(d: GPUTextureBindingLayout) {
848 /* prettier-ignore */
849 if (d.multisampled) {
Brandon Jones201435f2021-08-12 13:47:21 -0700850 return { usage: GPUConst.TextureUsage.TEXTURE_BINDING, ...kBindingKind.sampledTexMS, ...kValidStagesAll, };
Kai Ninomiyad2919ff2021-05-11 19:21:17 -0700851 } else {
Brandon Jones201435f2021-08-12 13:47:21 -0700852 return { usage: GPUConst.TextureUsage.TEXTURE_BINDING, ...kBindingKind.sampledTex, ...kValidStagesAll, };
Kai Ninomiyaff91b742021-04-20 18:41:59 -0700853 }
854}
Kai Ninomiya97c60c42021-06-14 16:55:24 -0700855/** List of all GPUTextureSampleType values. */
Kai Ninomiyaff91b742021-04-20 18:41:59 -0700856export const kTextureSampleTypes = [
857 'float',
858 'unfilterable-float',
859 'depth',
860 'sint',
861 'uint',
862] as const;
863assertTypeTrue<TypeEqual<GPUTextureSampleType, typeof kTextureSampleTypes[number]>>();
Kai Ninomiya3a50e8b2020-04-28 20:38:31 -0700864
Kai Ninomiya97c60c42021-06-14 16:55:24 -0700865/** Binding type info (including class limits) for the specified GPUStorageTextureBindingLayout. */
Kai Ninomiyaff91b742021-04-20 18:41:59 -0700866export function storageTextureBindingTypeInfo(d: GPUStorageTextureBindingLayout) {
Brandon Jones4f2c3b62021-12-06 13:00:51 -0800867 return {
868 usage: GPUConst.TextureUsage.STORAGE_BINDING,
869 ...kBindingKind.storageTex,
870 ...kValidStagesStorageWrite,
871 };
Kai Ninomiyaff91b742021-04-20 18:41:59 -0700872}
Kai Ninomiya97c60c42021-06-14 16:55:24 -0700873/** List of all GPUStorageTextureAccess values. */
Brandon Jones4f2c3b62021-12-06 13:00:51 -0800874export const kStorageTextureAccessValues = ['write-only'] as const;
Kai Ninomiyaff91b742021-04-20 18:41:59 -0700875assertTypeTrue<TypeEqual<GPUStorageTextureAccess, typeof kStorageTextureAccessValues[number]>>();
Kai Ninomiya3a50e8b2020-04-28 20:38:31 -0700876
Kai Ninomiya97c60c42021-06-14 16:55:24 -0700877/** GPUBindGroupLayoutEntry, but only the "union" fields, not the common fields. */
Kai Ninomiyaff91b742021-04-20 18:41:59 -0700878export type BGLEntry = Omit<GPUBindGroupLayoutEntry, 'binding' | 'visibility'>;
Kai Ninomiya97c60c42021-06-14 16:55:24 -0700879/** Binding type info (including class limits) for the specified BGLEntry. */
Kai Ninomiyaff91b742021-04-20 18:41:59 -0700880export function texBindingTypeInfo(e: BGLEntry) {
881 if (e.texture !== undefined) return sampledTextureBindingTypeInfo(e.texture);
882 if (e.storageTexture !== undefined) return storageTextureBindingTypeInfo(e.storageTexture);
883 unreachable();
884}
Kai Ninomiya97c60c42021-06-14 16:55:24 -0700885/** BindingTypeInfo (including class limits) for the specified BGLEntry. */
Kai Ninomiyaff91b742021-04-20 18:41:59 -0700886export function bindingTypeInfo(e: BGLEntry) {
887 if (e.buffer !== undefined) return bufferBindingTypeInfo(e.buffer);
888 if (e.texture !== undefined) return sampledTextureBindingTypeInfo(e.texture);
889 if (e.sampler !== undefined) return samplerBindingTypeInfo(e.sampler);
890 if (e.storageTexture !== undefined) return storageTextureBindingTypeInfo(e.storageTexture);
891 unreachable('GPUBindGroupLayoutEntry has no BindingLayout');
892}
893
Kai Ninomiya97c60c42021-06-14 16:55:24 -0700894/**
895 * Generate a list of possible buffer-typed BGLEntry values.
896 *
897 * Note: Generates different `type` options, but not `hasDynamicOffset` options.
898 */
Kai Ninomiyaff91b742021-04-20 18:41:59 -0700899export function bufferBindingEntries(includeUndefined: boolean): readonly BGLEntry[] {
900 return [
901 ...(includeUndefined ? [{ buffer: { type: undefined } }] : []),
902 { buffer: { type: 'uniform' } },
903 { buffer: { type: 'storage' } },
904 { buffer: { type: 'read-only-storage' } },
905 ] as const;
906}
Kai Ninomiya97c60c42021-06-14 16:55:24 -0700907/** Generate a list of possible sampler-typed BGLEntry values. */
Kai Ninomiyaff91b742021-04-20 18:41:59 -0700908export function samplerBindingEntries(includeUndefined: boolean): readonly BGLEntry[] {
909 return [
910 ...(includeUndefined ? [{ sampler: { type: undefined } }] : []),
911 { sampler: { type: 'comparison' } },
912 { sampler: { type: 'filtering' } },
913 { sampler: { type: 'non-filtering' } },
914 ] as const;
915}
Kai Ninomiya97c60c42021-06-14 16:55:24 -0700916/**
917 * Generate a list of possible texture-typed BGLEntry values.
918 *
919 * Note: Generates different `multisampled` options, but not `sampleType` or `viewDimension` options.
920 */
Kai Ninomiyaff91b742021-04-20 18:41:59 -0700921export function textureBindingEntries(includeUndefined: boolean): readonly BGLEntry[] {
922 return [
923 ...(includeUndefined ? [{ texture: { multisampled: undefined } }] : []),
924 { texture: { multisampled: false } },
925 { texture: { multisampled: true } },
926 ] as const;
927}
Kai Ninomiya97c60c42021-06-14 16:55:24 -0700928/**
929 * Generate a list of possible storageTexture-typed BGLEntry values.
930 *
931 * Note: Generates different `access` options, but not `format` or `viewDimension` options.
932 */
Kai Ninomiyaff91b742021-04-20 18:41:59 -0700933export function storageTextureBindingEntries(format: GPUTextureFormat): readonly BGLEntry[] {
Ben Clayton96bf7292021-10-01 17:41:15 +0100934 return [{ storageTexture: { access: 'write-only', format } }] as const;
Kai Ninomiyaff91b742021-04-20 18:41:59 -0700935}
Kai Ninomiya97c60c42021-06-14 16:55:24 -0700936/** Generate a list of possible texture-or-storageTexture-typed BGLEntry values. */
Kai Ninomiyaff91b742021-04-20 18:41:59 -0700937export function sampledAndStorageBindingEntries(
938 includeUndefined: boolean,
939 storageTextureFormat: GPUTextureFormat = 'rgba8unorm'
940): readonly BGLEntry[] {
941 return [
942 ...textureBindingEntries(includeUndefined),
943 ...storageTextureBindingEntries(storageTextureFormat),
944 ] as const;
945}
Kai Ninomiya97c60c42021-06-14 16:55:24 -0700946/**
947 * Generate a list of possible BGLEntry values of every type, but not variants with different:
Kai Ninomiyaff91b742021-04-20 18:41:59 -0700948 * - buffer.hasDynamicOffset
949 * - texture.sampleType
950 * - texture.viewDimension
951 * - storageTexture.viewDimension
952 */
953export function allBindingEntries(
954 includeUndefined: boolean,
955 storageTextureFormat: GPUTextureFormat = 'rgba8unorm'
956): readonly BGLEntry[] {
957 return [
958 ...bufferBindingEntries(includeUndefined),
959 ...samplerBindingEntries(includeUndefined),
960 ...sampledAndStorageBindingEntries(includeUndefined, storageTextureFormat),
961 ] as const;
962}
963
964// Shader stages
Kai Ninomiya3a50e8b2020-04-28 20:38:31 -0700965
Kai Ninomiya97c60c42021-06-14 16:55:24 -0700966/** List of all GPUShaderStage values. */
Lokbondo Kung300c10c2022-03-22 10:53:42 -0700967export type ShaderStageKey = keyof typeof GPUConst.ShaderStage;
968export const kShaderStageKeys = Object.keys(GPUConst.ShaderStage) as ShaderStageKey[];
Kai Ninomiya3a50e8b2020-04-28 20:38:31 -0700969export const kShaderStages: readonly GPUShaderStageFlags[] = [
Kai Ninomiya04e404f2020-10-23 16:02:19 -0700970 GPUConst.ShaderStage.VERTEX,
971 GPUConst.ShaderStage.FRAGMENT,
972 GPUConst.ShaderStage.COMPUTE,
Justin Fan5d1b8c72020-01-15 16:03:37 -0800973];
Kai Ninomiya97c60c42021-06-14 16:55:24 -0700974/** List of all possible combinations of GPUShaderStage values. */
Kai Ninomiya3a50e8b2020-04-28 20:38:31 -0700975export const kShaderStageCombinations: readonly GPUShaderStageFlags[] = [0, 1, 2, 3, 4, 5, 6, 7];
Enrico Galli94e47e92020-12-16 14:31:50 -0800976
Kai Ninomiya97c60c42021-06-14 16:55:24 -0700977/**
978 * List of all possible texture sampleCount values.
979 *
Kai Ninomiya7c40d212022-01-04 14:25:02 -0800980 * MAINTENANCE_TODO: Switch existing tests to use kTextureSampleCounts
Kai Ninomiya97c60c42021-06-14 16:55:24 -0700981 */
Enrico Galli94e47e92020-12-16 14:31:50 -0800982export const kTextureSampleCounts = [1, 4] as const;
983
Jiawei Shao1b9e8732022-02-09 09:18:23 +0800984// Blend factors and Blend components
985
986/** List of all GPUBlendFactor values. */
987export const kBlendFactors: readonly GPUBlendFactor[] = [
988 'zero',
989 'one',
990 'src',
991 'one-minus-src',
992 'src-alpha',
993 'one-minus-src-alpha',
994 'dst',
995 'one-minus-dst',
996 'dst-alpha',
997 'one-minus-dst-alpha',
998 'src-alpha-saturated',
999 'constant',
1000 'one-minus-constant',
1001];
1002
1003/** List of all GPUBlendOperation values. */
1004export const kBlendOperations: readonly GPUBlendOperation[] = [
1005 'add', //
1006 'subtract',
1007 'reverse-subtract',
1008 'min',
1009 'max',
1010];
1011
ShrekShaoaa6069d2022-06-14 16:04:30 -07001012// Primitive topologies
1013export const kPrimitiveTopology: readonly GPUPrimitiveTopology[] = [
1014 'point-list',
1015 'line-list',
1016 'line-strip',
1017 'triangle-list',
1018 'triangle-strip',
1019];
1020assertTypeTrue<TypeEqual<GPUPrimitiveTopology, typeof kPrimitiveTopology[number]>>();
1021
1022export const kIndexFormat: readonly GPUIndexFormat[] = ['uint16', 'uint32'];
1023assertTypeTrue<TypeEqual<GPUIndexFormat, typeof kIndexFormat[number]>>();
1024
Corentin Wallez27ca9f72022-03-30 21:01:47 +01001025/** Info for each entry of GPUSupportedLimits */
1026export const kLimitInfo = /* prettier-ignore */ makeTable(
1027 [ 'class', 'default', 'maximumValue'] as const,
1028 [ 'maximum', , kMaxUnsignedLongValue] as const, {
1029 'maxTextureDimension1D': [ , 8192, ],
1030 'maxTextureDimension2D': [ , 8192, ],
1031 'maxTextureDimension3D': [ , 2048, ],
1032 'maxTextureArrayLayers': [ , 256, ],
1033
1034 'maxBindGroups': [ , 4, ],
Greggman17eafee2023-02-07 19:55:14 -08001035 'maxBindingsPerBindGroup': [ , 640, ],
Corentin Wallez27ca9f72022-03-30 21:01:47 +01001036 'maxDynamicUniformBuffersPerPipelineLayout': [ , 8, ],
1037 'maxDynamicStorageBuffersPerPipelineLayout': [ , 4, ],
1038 'maxSampledTexturesPerShaderStage': [ , 16, ],
1039 'maxSamplersPerShaderStage': [ , 16, ],
1040 'maxStorageBuffersPerShaderStage': [ , 8, ],
1041 'maxStorageTexturesPerShaderStage': [ , 4, ],
1042 'maxUniformBuffersPerShaderStage': [ , 12, ],
1043
1044 'maxUniformBufferBindingSize': [ , 65536, kMaxUnsignedLongLongValue],
1045 'maxStorageBufferBindingSize': [ , 134217728, kMaxUnsignedLongLongValue],
1046 'minUniformBufferOffsetAlignment': ['alignment', 256, ],
1047 'minStorageBufferOffsetAlignment': ['alignment', 256, ],
1048
1049 'maxVertexBuffers': [ , 8, ],
Lokbondo Kung73a99fe2023-01-26 16:08:52 -08001050 'maxBufferSize': [ , 268435456, kMaxUnsignedLongLongValue],
Corentin Wallez27ca9f72022-03-30 21:01:47 +01001051 'maxVertexAttributes': [ , 16, ],
1052 'maxVertexBufferArrayStride': [ , 2048, ],
1053 'maxInterStageShaderComponents': [ , 60, ],
1054
Lokbondo Kunga7e54e72023-01-26 11:51:32 -08001055 'maxColorAttachments': [ , 8, ],
1056 'maxColorAttachmentBytesPerSample': [ , 32, ],
1057
Austin Eng8f2742e2022-05-18 09:29:13 -07001058 'maxComputeWorkgroupStorageSize': [ , 16384, ],
Corentin Wallez27ca9f72022-03-30 21:01:47 +01001059 'maxComputeInvocationsPerWorkgroup': [ , 256, ],
1060 'maxComputeWorkgroupSizeX': [ , 256, ],
1061 'maxComputeWorkgroupSizeY': [ , 256, ],
1062 'maxComputeWorkgroupSizeZ': [ , 64, ],
1063 'maxComputeWorkgroupsPerDimension': [ , 65535, ],
1064} as const);
1065
1066/** List of all entries of GPUSupportedLimits. */
1067export const kLimits = keysOf(kLimitInfo);
Austin Eng901b0c92022-04-11 17:50:10 -07001068
Lokbondo Kunga7e54e72023-01-26 11:51:32 -08001069// Pipeline limits
1070
1071/** Maximum number of color attachments to a render pass, by spec. */
1072export const kMaxColorAttachments = kLimitInfo.maxColorAttachments.default;
1073/** `maxVertexBuffers` per GPURenderPipeline, by spec. */
1074export const kMaxVertexBuffers = kLimitInfo.maxVertexBuffers.default;
1075/** `maxVertexAttributes` per GPURenderPipeline, by spec. */
1076export const kMaxVertexAttributes = kLimitInfo.maxVertexAttributes.default;
1077/** `maxVertexBufferArrayStride` in a vertex buffer in a GPURenderPipeline, by spec. */
1078export const kMaxVertexBufferArrayStride = kLimitInfo.maxVertexBufferArrayStride.default;
1079
1080/** The size of indirect draw parameters in the indirectBuffer of drawIndirect */
1081export const kDrawIndirectParametersSize = 4;
1082/** The size of indirect drawIndexed parameters in the indirectBuffer of drawIndexedIndirect */
1083export const kDrawIndexedIndirectParametersSize = 5;
1084
Lokbondo Kung3c353f82022-08-29 19:19:24 -07001085/** Per-GPUFeatureName info. */
1086export const kFeatureNameInfo: {
1087 readonly [k in GPUFeatureName]: {};
1088} = /* prettier-ignore */ {
1089 'depth-clip-control': {},
1090 'depth32float-stencil8': {},
1091 'texture-compression-bc': {},
1092 'texture-compression-etc2': {},
1093 'texture-compression-astc': {},
1094 'timestamp-query': {},
1095 'indirect-first-instance': {},
1096 'shader-f16': {},
Takahirocbdd47a2022-10-05 15:44:19 -07001097 'rg11b10ufloat-renderable': {},
Lokbondo Kung3c353f82022-08-29 19:19:24 -07001098};
1099/** List of all GPUFeatureName values. */
1100export const kFeatureNames = keysOf(kFeatureNameInfo);
1101
Austin Eng901b0c92022-04-11 17:50:10 -07001102/**
1103 * Check if two formats are view format compatible.
1104 *
1105 * This function may need to be generalized to use `baseFormat` from `kTextureFormatInfo`.
1106 */
1107export function viewCompatible(a: GPUTextureFormat, b: GPUTextureFormat): boolean {
1108 return a === b || a + '-srgb' === b || b + '-srgb' === a;
1109}
Austin Eng318d3d02022-05-03 07:10:10 -10001110
1111export function getFeaturesForFormats<T>(
1112 formats: readonly (T & (GPUTextureFormat | undefined))[]
1113): readonly (GPUFeatureName | undefined)[] {
1114 return Array.from(new Set(formats.map(f => (f ? kTextureFormatInfo[f].feature : undefined))));
1115}
1116
1117export function filterFormatsByFeature<T>(
1118 feature: GPUFeatureName | undefined,
1119 formats: readonly (T & (GPUTextureFormat | undefined))[]
1120): readonly (T & (GPUTextureFormat | undefined))[] {
1121 return formats.filter(f => f === undefined || kTextureFormatInfo[f].feature === feature);
1122}
1123
1124export const kFeaturesForFormats = getFeaturesForFormats(kTextureFormats);