1import { GPUConst } from './constants.js';
2
3type valueof<K> = K[keyof K];
4type GPUTextureUsage = valueof<typeof GPUTextureUsage>;
5type GPUBufferUsage = valueof<typeof GPUBufferUsage>;
6
7function keysOf<T extends string>(obj: { [k in T]: unknown }): readonly T[] {
8  return (Object.keys(obj) as unknown[]) as T[];
9}
10
11function numericKeysOf<T>(obj: object): readonly T[] {
12  return (Object.keys(obj).map(n => Number(n)) as unknown[]) as T[];
13}
14
15// Buffers
16
17export const kBufferUsageInfo: {
18  readonly [k in GPUBufferUsage]: {};
19} = /* prettier-ignore */ {
20  [GPUConst.BufferUsage.MAP_READ]:      {},
21  [GPUConst.BufferUsage.MAP_WRITE]:     {},
22  [GPUConst.BufferUsage.COPY_SRC]:      {},
23  [GPUConst.BufferUsage.COPY_DST]:      {},
24  [GPUConst.BufferUsage.INDEX]:         {},
25  [GPUConst.BufferUsage.VERTEX]:        {},
26  [GPUConst.BufferUsage.UNIFORM]:       {},
27  [GPUConst.BufferUsage.STORAGE]:       {},
28  [GPUConst.BufferUsage.INDIRECT]:      {},
29  [GPUConst.BufferUsage.QUERY_RESOLVE]: {},
30};
31export const kBufferUsages = numericKeysOf<GPUBufferUsage>(kBufferUsageInfo);
32
33// Textures
34
35export type RegularTextureFormat =
36  | 'r8unorm'
37  | 'r8snorm'
38  | 'r8uint'
39  | 'r8sint'
40  | 'r16uint'
41  | 'r16sint'
42  | 'r16float'
43  | 'rg8unorm'
44  | 'rg8snorm'
45  | 'rg8uint'
46  | 'rg8sint'
47  | 'r32uint'
48  | 'r32sint'
49  | 'r32float'
50  | 'rg16uint'
51  | 'rg16sint'
52  | 'rg16float'
53  | 'rgba8unorm'
54  | 'rgba8unorm-srgb'
55  | 'rgba8snorm'
56  | 'rgba8uint'
57  | 'rgba8sint'
58  | 'bgra8unorm'
59  | 'bgra8unorm-srgb'
60  | 'rgb10a2unorm'
61  | 'rg11b10float'
62  | 'rg32uint'
63  | 'rg32sint'
64  | 'rg32float'
65  | 'rgba16uint'
66  | 'rgba16sint'
67  | 'rgba16float'
68  | 'rgba32uint'
69  | 'rgba32sint'
70  | 'rgba32float';
71export type SizedDepthStencilFormat = 'depth32float';
72export type UnsizedDepthStencilFormat = 'depth24plus' | 'depth24plus-stencil8';
73export type CompressedTextureFormat =
74  | 'bc1-rgba-unorm'
75  | 'bc1-rgba-unorm-srgb'
76  | 'bc2-rgba-unorm'
77  | 'bc2-rgba-unorm-srgb'
78  | 'bc3-rgba-unorm'
79  | 'bc3-rgba-unorm-srgb'
80  | 'bc4-r-unorm'
81  | 'bc4-r-snorm'
82  | 'bc5-rg-unorm'
83  | 'bc5-rg-snorm'
84  | 'bc6h-rgb-ufloat'
85  | 'bc6h-rgb-sfloat'
86  | 'bc7-rgba-unorm'
87  | 'bc7-rgba-unorm-srgb';
88
89type TextureFormatInfo = {
90  readonly renderable: boolean;
91  readonly color: boolean;
92  readonly depth: boolean;
93  readonly stencil: boolean;
94  readonly storage: boolean;
95  readonly copySrc: boolean;
96  readonly copyDst: boolean;
97  readonly bytesPerBlock?: number;
98  readonly blockWidth: number;
99  readonly blockHeight: number;
100  readonly extension?: GPUExtensionName;
101  // Add fields as needed
102};
103
104export const kRegularTextureFormatInfo: {
105  readonly [k in RegularTextureFormat]: {
106    color: true;
107    bytesPerBlock: number;
108    blockWidth: 1;
109    blockHeight: 1;
110  } & TextureFormatInfo;
111} = /* prettier-ignore */ {
112  // 8-bit formats
113  'r8unorm':                { renderable:  true, color:  true, depth: false, stencil: false, storage: false, copySrc:  true, copyDst:  true, bytesPerBlock:  1, blockWidth: 1, blockHeight: 1 },
114  'r8snorm':                { renderable: false, color:  true, depth: false, stencil: false, storage: false, copySrc:  true, copyDst:  true, bytesPerBlock:  1, blockWidth: 1, blockHeight: 1 },
115  'r8uint':                 { renderable:  true, color:  true, depth: false, stencil: false, storage: false, copySrc:  true, copyDst:  true, bytesPerBlock:  1, blockWidth: 1, blockHeight: 1 },
116  'r8sint':                 { renderable:  true, color:  true, depth: false, stencil: false, storage: false, copySrc:  true, copyDst:  true, bytesPerBlock:  1, blockWidth: 1, blockHeight: 1 },
117  // 16-bit formats
118  'r16uint':                { renderable:  true, color:  true, depth: false, stencil: false, storage: false, copySrc:  true, copyDst:  true, bytesPerBlock:  2, blockWidth: 1, blockHeight: 1 },
119  'r16sint':                { renderable:  true, color:  true, depth: false, stencil: false, storage: false, copySrc:  true, copyDst:  true, bytesPerBlock:  2, blockWidth: 1, blockHeight: 1 },
120  'r16float':               { renderable:  true, color:  true, depth: false, stencil: false, storage: false, copySrc:  true, copyDst:  true, bytesPerBlock:  2, blockWidth: 1, blockHeight: 1 },
121  'rg8unorm':               { renderable:  true, color:  true, depth: false, stencil: false, storage: false, copySrc:  true, copyDst:  true, bytesPerBlock:  2, blockWidth: 1, blockHeight: 1 },
122  'rg8snorm':               { renderable: false, color:  true, depth: false, stencil: false, storage: false, copySrc:  true, copyDst:  true, bytesPerBlock:  2, blockWidth: 1, blockHeight: 1 },
123  'rg8uint':                { renderable:  true, color:  true, depth: false, stencil: false, storage: false, copySrc:  true, copyDst:  true, bytesPerBlock:  2, blockWidth: 1, blockHeight: 1 },
124  'rg8sint':                { renderable:  true, color:  true, depth: false, stencil: false, storage: false, copySrc:  true, copyDst:  true, bytesPerBlock:  2, blockWidth: 1, blockHeight: 1 },
125  // 32-bit formats
126  'r32uint':                { renderable:  true, color:  true, depth: false, stencil: false, storage:  true, copySrc:  true, copyDst:  true, bytesPerBlock:  4, blockWidth: 1, blockHeight: 1 },
127  'r32sint':                { renderable:  true, color:  true, depth: false, stencil: false, storage:  true, copySrc:  true, copyDst:  true, bytesPerBlock:  4, blockWidth: 1, blockHeight: 1 },
128  'r32float':               { renderable:  true, color:  true, depth: false, stencil: false, storage:  true, copySrc:  true, copyDst:  true, bytesPerBlock:  4, blockWidth: 1, blockHeight: 1 },
129  'rg16uint':               { renderable:  true, color:  true, depth: false, stencil: false, storage: false, copySrc:  true, copyDst:  true, bytesPerBlock:  4, blockWidth: 1, blockHeight: 1 },
130  'rg16sint':               { renderable:  true, color:  true, depth: false, stencil: false, storage: false, copySrc:  true, copyDst:  true, bytesPerBlock:  4, blockWidth: 1, blockHeight: 1 },
131  'rg16float':              { renderable:  true, color:  true, depth: false, stencil: false, storage: false, copySrc:  true, copyDst:  true, bytesPerBlock:  4, blockWidth: 1, blockHeight: 1 },
132  'rgba8unorm':             { renderable:  true, color:  true, depth: false, stencil: false, storage:  true, copySrc:  true, copyDst:  true, bytesPerBlock:  4, blockWidth: 1, blockHeight: 1 },
133  'rgba8unorm-srgb':        { renderable:  true, color:  true, depth: false, stencil: false, storage: false, copySrc:  true, copyDst:  true, bytesPerBlock:  4, blockWidth: 1, blockHeight: 1 },
134  'rgba8snorm':             { renderable: false, color:  true, depth: false, stencil: false, storage:  true, copySrc:  true, copyDst:  true, bytesPerBlock:  4, blockWidth: 1, blockHeight: 1 },
135  'rgba8uint':              { renderable:  true, color:  true, depth: false, stencil: false, storage:  true, copySrc:  true, copyDst:  true, bytesPerBlock:  4, blockWidth: 1, blockHeight: 1 },
136  'rgba8sint':              { renderable:  true, color:  true, depth: false, stencil: false, storage:  true, copySrc:  true, copyDst:  true, bytesPerBlock:  4, blockWidth: 1, blockHeight: 1 },
137  'bgra8unorm':             { renderable:  true, color:  true, depth: false, stencil: false, storage: false, copySrc:  true, copyDst:  true, bytesPerBlock:  4, blockWidth: 1, blockHeight: 1 },
138  'bgra8unorm-srgb':        { renderable:  true, color:  true, depth: false, stencil: false, storage: false, copySrc:  true, copyDst:  true, bytesPerBlock:  4, blockWidth: 1, blockHeight: 1 },
139  // Packed 32-bit formats
140  'rgb10a2unorm':           { renderable:  true, color:  true, depth: false, stencil: false, storage: false, copySrc:  true, copyDst:  true, bytesPerBlock:  4, blockWidth: 1, blockHeight: 1 },
141  'rg11b10float':           { renderable: false, color:  true, depth: false, stencil: false, storage: false, copySrc:  true, copyDst:  true, bytesPerBlock:  4, blockWidth: 1, blockHeight: 1 },
142  // 64-bit formats
143  'rg32uint':               { renderable:  true, color:  true, depth: false, stencil: false, storage:  true, copySrc:  true, copyDst:  true, bytesPerBlock:  8, blockWidth: 1, blockHeight: 1 },
144  'rg32sint':               { renderable:  true, color:  true, depth: false, stencil: false, storage:  true, copySrc:  true, copyDst:  true, bytesPerBlock:  8, blockWidth: 1, blockHeight: 1 },
145  'rg32float':              { renderable:  true, color:  true, depth: false, stencil: false, storage:  true, copySrc:  true, copyDst:  true, bytesPerBlock:  8, blockWidth: 1, blockHeight: 1 },
146  'rgba16uint':             { renderable:  true, color:  true, depth: false, stencil: false, storage:  true, copySrc:  true, copyDst:  true, bytesPerBlock:  8, blockWidth: 1, blockHeight: 1 },
147  'rgba16sint':             { renderable:  true, color:  true, depth: false, stencil: false, storage:  true, copySrc:  true, copyDst:  true, bytesPerBlock:  8, blockWidth: 1, blockHeight: 1 },
148  'rgba16float':            { renderable:  true, color:  true, depth: false, stencil: false, storage:  true, copySrc:  true, copyDst:  true, bytesPerBlock:  8, blockWidth: 1, blockHeight: 1 },
149  // 128-bit formats
150  'rgba32uint':             { renderable:  true, color:  true, depth: false, stencil: false, storage:  true, copySrc:  true, copyDst:  true, bytesPerBlock: 16, blockWidth: 1, blockHeight: 1 },
151  'rgba32sint':             { renderable:  true, color:  true, depth: false, stencil: false, storage:  true, copySrc:  true, copyDst:  true, bytesPerBlock: 16, blockWidth: 1, blockHeight: 1 },
152  'rgba32float':            { renderable:  true, color:  true, depth: false, stencil: false, storage:  true, copySrc:  true, copyDst:  true, bytesPerBlock: 16, blockWidth: 1, blockHeight: 1 },
153} as const;
154export const kRegularTextureFormats = keysOf(kRegularTextureFormatInfo);
155
156export const kSizedDepthStencilFormatInfo: {
157  readonly [k in SizedDepthStencilFormat]: {
158    readonly renderable: true;
159    readonly color: false;
160    readonly bytesPerBlock: number;
161    readonly blockWidth: 1;
162    readonly blockHeight: 1;
163  } & TextureFormatInfo;
164} = /* prettier-ignore */ {
165  'depth32float': { renderable:  true, color: false, depth:  true, stencil: false, storage: false, copySrc:  true, copyDst: false, bytesPerBlock:  4, blockWidth: 1, blockHeight: 1 },
166};
167export const kSizedDepthStencilFormats = keysOf(kSizedDepthStencilFormatInfo);
168
169export const kUnsizedDepthStencilFormatInfo: {
170  readonly [k in UnsizedDepthStencilFormat]: {
171    readonly renderable: true;
172    readonly color: false;
173    readonly blockWidth: 1;
174    readonly blockHeight: 1;
175  } & TextureFormatInfo;
176} = /* prettier-ignore */ {
177  'depth24plus':          { renderable:  true, color: false, depth:  true, stencil: false, storage: false, copySrc: false, copyDst: false, blockWidth: 1, blockHeight: 1 },
178  'depth24plus-stencil8': { renderable:  true, color: false, depth:  true, stencil:  true, storage: false, copySrc: false, copyDst: false, blockWidth: 1, blockHeight: 1 },
179} as const;
180export const kUnsizedDepthStencilFormats = keysOf(kUnsizedDepthStencilFormatInfo);
181
182export const kCompressedTextureFormatInfo: {
183  readonly [k in CompressedTextureFormat]: {
184    readonly renderable: false;
185    readonly color: true;
186    readonly bytesPerBlock: number;
187    readonly extension: GPUExtensionName;
188  } & TextureFormatInfo;
189} = /* prettier-ignore */ {
190  // BC formats
191  'bc1-rgba-unorm':      { renderable: false, color:  true, depth: false, stencil: false, storage: false, copySrc:  true, copyDst:  true, bytesPerBlock:  8, blockWidth: 4, blockHeight: 4, extension: 'texture-compression-bc' },
192  'bc1-rgba-unorm-srgb': { renderable: false, color:  true, depth: false, stencil: false, storage: false, copySrc:  true, copyDst:  true, bytesPerBlock:  8, blockWidth: 4, blockHeight: 4, extension: 'texture-compression-bc' },
193  'bc2-rgba-unorm':      { renderable: false, color:  true, depth: false, stencil: false, storage: false, copySrc:  true, copyDst:  true, bytesPerBlock: 16, blockWidth: 4, blockHeight: 4, extension: 'texture-compression-bc' },
194  'bc2-rgba-unorm-srgb': { renderable: false, color:  true, depth: false, stencil: false, storage: false, copySrc:  true, copyDst:  true, bytesPerBlock: 16, blockWidth: 4, blockHeight: 4, extension: 'texture-compression-bc' },
195  'bc3-rgba-unorm':      { renderable: false, color:  true, depth: false, stencil: false, storage: false, copySrc:  true, copyDst:  true, bytesPerBlock: 16, blockWidth: 4, blockHeight: 4, extension: 'texture-compression-bc' },
196  'bc3-rgba-unorm-srgb': { renderable: false, color:  true, depth: false, stencil: false, storage: false, copySrc:  true, copyDst:  true, bytesPerBlock: 16, blockWidth: 4, blockHeight: 4, extension: 'texture-compression-bc' },
197  'bc4-r-unorm':         { renderable: false, color:  true, depth: false, stencil: false, storage: false, copySrc:  true, copyDst:  true, bytesPerBlock:  8, blockWidth: 4, blockHeight: 4, extension: 'texture-compression-bc' },
198  'bc4-r-snorm':         { renderable: false, color:  true, depth: false, stencil: false, storage: false, copySrc:  true, copyDst:  true, bytesPerBlock:  8, blockWidth: 4, blockHeight: 4, extension: 'texture-compression-bc' },
199  'bc5-rg-unorm':        { renderable: false, color:  true, depth: false, stencil: false, storage: false, copySrc:  true, copyDst:  true, bytesPerBlock: 16, blockWidth: 4, blockHeight: 4, extension: 'texture-compression-bc' },
200  'bc5-rg-snorm':        { renderable: false, color:  true, depth: false, stencil: false, storage: false, copySrc:  true, copyDst:  true, bytesPerBlock: 16, blockWidth: 4, blockHeight: 4, extension: 'texture-compression-bc' },
201  'bc6h-rgb-ufloat':     { renderable: false, color:  true, depth: false, stencil: false, storage: false, copySrc:  true, copyDst:  true, bytesPerBlock: 16, blockWidth: 4, blockHeight: 4, extension: 'texture-compression-bc' },
202  'bc6h-rgb-sfloat':     { renderable: false, color:  true, depth: false, stencil: false, storage: false, copySrc:  true, copyDst:  true, bytesPerBlock: 16, blockWidth: 4, blockHeight: 4, extension: 'texture-compression-bc' },
203  'bc7-rgba-unorm':      { renderable: false, color:  true, depth: false, stencil: false, storage: false, copySrc:  true, copyDst:  true, bytesPerBlock: 16, blockWidth: 4, blockHeight: 4, extension: 'texture-compression-bc' },
204  'bc7-rgba-unorm-srgb': { renderable: false, color:  true, depth: false, stencil: false, storage: false, copySrc:  true, copyDst:  true, bytesPerBlock: 16, blockWidth: 4, blockHeight: 4, extension: 'texture-compression-bc' },
205};
206export const kCompressedTextureFormats = keysOf(kCompressedTextureFormatInfo);
207
208export const kColorTextureFormatInfo = {
209  ...kRegularTextureFormatInfo,
210  ...kCompressedTextureFormatInfo,
211} as const;
212export type ColorTextureFormat = keyof typeof kColorTextureFormatInfo;
213export const kColorTextureFormats = keysOf(kColorTextureFormatInfo);
214
215export const kEncodableTextureFormatInfo = {
216  ...kRegularTextureFormatInfo,
217  ...kSizedDepthStencilFormatInfo,
218} as const;
219export type EncodableTextureFormat = keyof typeof kEncodableTextureFormatInfo;
220export const kEncodableTextureFormats = keysOf(kEncodableTextureFormatInfo);
221
222export const kSizedTextureFormatInfo = {
223  ...kRegularTextureFormatInfo,
224  ...kSizedDepthStencilFormatInfo,
225  ...kCompressedTextureFormatInfo,
226} as const;
227export type SizedTextureFormat = keyof typeof kSizedTextureFormatInfo;
228export const kSizedTextureFormats = keysOf(kSizedTextureFormatInfo);
229
230export const kDepthStencilFormatInfo = {
231  ...kSizedDepthStencilFormatInfo,
232  ...kUnsizedDepthStencilFormatInfo,
233} as const;
234export type DepthStencilFormat = keyof typeof kDepthStencilFormatInfo;
235export const kDepthStencilFormats = keysOf(kDepthStencilFormatInfo);
236
237export const kUncompressedTextureFormatInfo = {
238  ...kRegularTextureFormatInfo,
239  ...kSizedDepthStencilFormatInfo,
240  ...kUnsizedDepthStencilFormatInfo,
241} as const;
242export type UncompressedTextureFormat = keyof typeof kUncompressedTextureFormatInfo;
243export const kUncompressedTextureFormats = keysOf(kUncompressedTextureFormatInfo);
244
245export const kAllTextureFormatInfo: {
246  readonly [k in GPUTextureFormat]: TextureFormatInfo;
247} = {
248  ...kUncompressedTextureFormatInfo,
249  ...kCompressedTextureFormatInfo,
250} as const;
251export const kAllTextureFormats = keysOf(kAllTextureFormatInfo);
252
253export const kTextureDimensionInfo: {
254  readonly [k in GPUTextureDimension]: {
255    // Add fields as needed
256  };
257} = /* prettier-ignore */ {
258  '1d': {},
259  '2d': {},
260  '3d': {},
261};
262export const kTextureDimensions = keysOf(kTextureDimensionInfo);
263
264export const kTextureAspectInfo: {
265  readonly [k in GPUTextureAspect]: {
266    // Add fields as needed
267  };
268} = /* prettier-ignore */ {
269  'all': {},
270  'depth-only': {},
271  'stencil-only': {},
272};
273export const kTextureAspects = keysOf(kTextureAspectInfo);
274
275export const kTextureUsageInfo: {
276  readonly [k in GPUTextureUsage]: {};
277} = {
278  [GPUConst.TextureUsage.COPY_SRC]: {},
279  [GPUConst.TextureUsage.COPY_DST]: {},
280  [GPUConst.TextureUsage.SAMPLED]: {},
281  [GPUConst.TextureUsage.STORAGE]: {},
282  [GPUConst.TextureUsage.OUTPUT_ATTACHMENT]: {},
283};
284export const kTextureUsages = numericKeysOf<GPUTextureUsage>(kTextureUsageInfo);
285
286export const kTextureComponentTypeInfo: {
287  readonly [k in GPUTextureComponentType]: {
288    // Add fields as needed
289  };
290} = /* prettier-ignore */ {
291  'float': {},
292  'sint': {},
293  'uint': {},
294};
295export const kTextureComponentTypes = keysOf(kTextureComponentTypeInfo);
296
297// Texture View
298
299export const kTextureViewDimensionInfo: {
300  readonly [k in GPUTextureViewDimension]: {
301    readonly storage: boolean;
302    // Add fields as needed
303  };
304} = /* prettier-ignore */ {
305  '1d':         { storage: true  },
306  '2d':         { storage: true  },
307  '2d-array':   { storage: true  },
308  'cube':       { storage: false },
309  'cube-array': { storage: false },
310  '3d':         { storage: true  },
311};
312export const kTextureViewDimensions = keysOf(kTextureViewDimensionInfo);
313
314// Typedefs for bindings
315
316export type PerStageBindingLimitClass =
317  | 'uniformBuf'
318  | 'storageBuf'
319  | 'sampler'
320  | 'sampledTex'
321  | 'storageTex';
322export type PerPipelineBindingLimitClass = PerStageBindingLimitClass;
323
324type ValidBindableResource =
325  | 'uniformBuf'
326  | 'storageBuf'
327  | 'plainSamp'
328  | 'compareSamp'
329  | 'sampledTex'
330  | 'storageTex';
331type ErrorBindableResource = 'errorBuf' | 'errorSamp' | 'errorTex';
332export type BindableResource = ValidBindableResource | ErrorBindableResource;
333
334type BufferBindingType = 'uniform-buffer' | 'storage-buffer' | 'readonly-storage-buffer';
335type SamplerBindingType = 'sampler' | 'comparison-sampler';
336type TextureBindingType =
337  | 'sampled-texture'
338  | 'writeonly-storage-texture'
339  | 'readonly-storage-texture';
340
341// Bindings
342
343export const kMaxBindingsPerBindGroup = 16;
344
345export const kPerStageBindingLimits: {
346  readonly [k in PerStageBindingLimitClass]: {
347    readonly class: k;
348    readonly max: number;
349    // Add fields as needed
350  };
351} = /* prettier-ignore */ {
352  'uniformBuf': { class: 'uniformBuf', max: 12, },
353  'storageBuf': { class: 'storageBuf', max:  4, },
354  'sampler':    { class: 'sampler',    max: 16, },
355  'sampledTex': { class: 'sampledTex', max: 16, },
356  'storageTex': { class: 'storageTex', max:  4, },
357};
358
359export const kPerPipelineBindingLimits: {
360  readonly [k in PerPipelineBindingLimitClass]: {
361    readonly class: k;
362    readonly maxDynamic: number;
363    // Add fields as needed
364  };
365} = /* prettier-ignore */ {
366  'uniformBuf': { class: 'uniformBuf', maxDynamic: 8, },
367  'storageBuf': { class: 'storageBuf', maxDynamic: 4, },
368  'sampler':    { class: 'sampler',    maxDynamic: 0, },
369  'sampledTex': { class: 'sampledTex', maxDynamic: 0, },
370  'storageTex': { class: 'storageTex', maxDynamic: 0, },
371};
372
373const kBindableResource: {
374  readonly [k in BindableResource]: {};
375} = /* prettier-ignore */ {
376  uniformBuf: {}, storageBuf: {}, plainSamp: {}, compareSamp: {}, sampledTex: {}, storageTex: {},
377  errorBuf: {}, errorSamp: {}, errorTex: {},
378};
379export const kBindableResources = keysOf(kBindableResource);
380
381interface BindingKindInfo {
382  readonly resource: ValidBindableResource;
383  readonly perStageLimitClass: typeof kPerStageBindingLimits[PerStageBindingLimitClass];
384  readonly perPipelineLimitClass: typeof kPerPipelineBindingLimits[PerPipelineBindingLimitClass];
385  // Add fields as needed
386}
387
388const kBindingKind: {
389  readonly [k in ValidBindableResource]: BindingKindInfo;
390} = /* prettier-ignore */ {
391  uniformBuf:  { resource: 'uniformBuf',  perStageLimitClass: kPerStageBindingLimits.uniformBuf, perPipelineLimitClass: kPerPipelineBindingLimits.uniformBuf, },
392  storageBuf:  { resource: 'storageBuf',  perStageLimitClass: kPerStageBindingLimits.storageBuf, perPipelineLimitClass: kPerPipelineBindingLimits.storageBuf, },
393  plainSamp:   { resource: 'plainSamp',   perStageLimitClass: kPerStageBindingLimits.sampler,    perPipelineLimitClass: kPerPipelineBindingLimits.sampler,    },
394  compareSamp: { resource: 'compareSamp', perStageLimitClass: kPerStageBindingLimits.sampler,    perPipelineLimitClass: kPerPipelineBindingLimits.sampler,    },
395  sampledTex:  { resource: 'sampledTex',  perStageLimitClass: kPerStageBindingLimits.sampledTex, perPipelineLimitClass: kPerPipelineBindingLimits.sampledTex, },
396  storageTex:  { resource: 'storageTex',  perStageLimitClass: kPerStageBindingLimits.storageTex, perPipelineLimitClass: kPerPipelineBindingLimits.storageTex, },
397};
398
399// Binding type info
400
401interface BindingTypeInfo extends BindingKindInfo {
402  readonly validStages: GPUShaderStageFlags;
403  // Add fields as needed
404}
405const kValidStagesAll = {
406  validStages:
407    GPUConst.ShaderStage.VERTEX | GPUConst.ShaderStage.FRAGMENT | GPUConst.ShaderStage.COMPUTE,
408};
409const kValidStagesStorageWrite = {
410  validStages: GPUConst.ShaderStage.FRAGMENT | GPUConst.ShaderStage.COMPUTE,
411};
412
413export const kBufferBindingTypeInfo: {
414  readonly [k in BufferBindingType]: {
415    readonly usage: GPUBufferUsage;
416    // Add fields as needed
417  } & BindingTypeInfo;
418} = /* prettier-ignore */ {
419  'uniform-buffer':          { usage: GPUConst.BufferUsage.UNIFORM, ...kBindingKind.uniformBuf,  ...kValidStagesAll,          },
420  'storage-buffer':          { usage: GPUConst.BufferUsage.STORAGE, ...kBindingKind.storageBuf,  ...kValidStagesStorageWrite, },
421  'readonly-storage-buffer': { usage: GPUConst.BufferUsage.STORAGE, ...kBindingKind.storageBuf,  ...kValidStagesAll,          },
422};
423export const kBufferBindingTypes = keysOf(kBufferBindingTypeInfo);
424
425export const kSamplerBindingTypeInfo: {
426  readonly [k in SamplerBindingType]: {
427    // Add fields as needed
428  } & BindingTypeInfo;
429} = /* prettier-ignore */ {
430  'sampler':                   { ...kBindingKind.plainSamp,   ...kValidStagesAll,     },
431  'comparison-sampler':        { ...kBindingKind.compareSamp, ...kValidStagesAll,     },
432};
433export const kSamplerBindingTypes = keysOf(kSamplerBindingTypeInfo);
434
435export const kTextureBindingTypeInfo: {
436  readonly [k in TextureBindingType]: {
437    readonly usage: GPUTextureUsage;
438    // Add fields as needed
439  } & BindingTypeInfo;
440} = /* prettier-ignore */ {
441  'sampled-texture':           { usage: GPUConst.TextureUsage.SAMPLED, ...kBindingKind.sampledTex,  ...kValidStagesAll,          },
442  'writeonly-storage-texture': { usage: GPUConst.TextureUsage.STORAGE, ...kBindingKind.storageTex,  ...kValidStagesStorageWrite, },
443  'readonly-storage-texture':  { usage: GPUConst.TextureUsage.STORAGE, ...kBindingKind.storageTex,  ...kValidStagesAll,          },
444};
445export const kTextureBindingTypes = keysOf(kTextureBindingTypeInfo);
446
447// All binding types (merged from above)
448
449export const kBindingTypeInfo: {
450  readonly [k in GPUBindingType]: BindingTypeInfo;
451} = {
452  ...kBufferBindingTypeInfo,
453  ...kSamplerBindingTypeInfo,
454  ...kTextureBindingTypeInfo,
455};
456export const kBindingTypes = keysOf(kBindingTypeInfo);
457
458export const kShaderStages: readonly GPUShaderStageFlags[] = [
459  GPUConst.ShaderStage.VERTEX,
460  GPUConst.ShaderStage.FRAGMENT,
461  GPUConst.ShaderStage.COMPUTE,
462];
463export const kShaderStageCombinations: readonly GPUShaderStageFlags[] = [0, 1, 2, 3, 4, 5, 6, 7];
464