@@ -2,19 +2,20 @@ import { keysOf } from '../../common/util/data_tables.js';
2
2
import { assert } from '../../common/util/util.js' ;
3
3
import { align } from '../util/math.js' ;
4
4
5
- const kArrayLength = 3 ;
5
+ const kDefaultArrayLength = 3 ;
6
6
7
7
export type Requirement = 'never' | 'may' | 'must' ; // never is the same as "must not"
8
8
export type ContainerType = 'scalar' | 'vector' | 'matrix' | 'atomic' | 'array' ;
9
- export type ScalarType = 'i32' | 'u32' | 'f32' | 'bool' ;
9
+ export type ScalarType = 'i32' | 'u32' | 'f16' | ' f32' | 'bool' ;
10
10
11
- export const HostSharableTypes = [ 'i32' , 'u32' , 'f32' ] as const ;
11
+ export const HostSharableTypes = [ 'i32' , 'u32' , 'f16' , ' f32'] as const ;
12
12
13
13
/** Info for each plain scalar type. */
14
14
export const kScalarTypeInfo =
15
15
/* prettier-ignore */ {
16
16
'i32' : { layout : { alignment : 4 , size : 4 } , supportsAtomics : true , arrayLength : 1 , innerLength : 0 } ,
17
17
'u32' : { layout : { alignment : 4 , size : 4 } , supportsAtomics : true , arrayLength : 1 , innerLength : 0 } ,
18
+ 'f16' : { layout : { alignment : 2 , size : 2 } , supportsAtomics : false , arrayLength : 1 , innerLength : 0 , feature : 'shader-f16' } ,
18
19
'f32' : { layout : { alignment : 4 , size : 4 } , supportsAtomics : false , arrayLength : 1 , innerLength : 0 } ,
19
20
'bool' : { layout : undefined , supportsAtomics : false , arrayLength : 1 , innerLength : 0 } ,
20
21
} as const ;
@@ -24,29 +25,71 @@ export const kScalarTypes = keysOf(kScalarTypeInfo);
24
25
/** Info for each vecN<> container type. */
25
26
export const kVectorContainerTypeInfo =
26
27
/* prettier-ignore */ {
27
- 'vec2' : { layout : { alignment : 8 , size : 8 } , arrayLength : 2 , innerLength : 0 } ,
28
- 'vec3' : { layout : { alignment : 16 , size : 12 } , arrayLength : 3 , innerLength : 0 } ,
29
- 'vec4' : { layout : { alignment : 16 , size : 16 } , arrayLength : 4 , innerLength : 0 } ,
28
+ 'vec2' : { arrayLength : 2 , innerLength : 0 } ,
29
+ 'vec3' : { arrayLength : 3 , innerLength : 0 } ,
30
+ 'vec4' : { arrayLength : 4 , innerLength : 0 } ,
30
31
} as const ;
31
32
/** List of all vecN<> container types. */
32
33
export const kVectorContainerTypes = keysOf ( kVectorContainerTypeInfo ) ;
33
34
35
+ /** Returns the vector layout for a given vector container and base type, or undefined if that base type has no layout */
36
+ function vectorLayout (
37
+ vectorContainer : 'vec2' | 'vec3' | 'vec4' ,
38
+ baseType : ScalarType
39
+ ) : { alignment : number ; size : number } | undefined {
40
+ const n = kVectorContainerTypeInfo [ vectorContainer ] . arrayLength ;
41
+ const scalarLayout = kScalarTypeInfo [ baseType ] . layout ;
42
+ if ( scalarLayout === undefined ) {
43
+ return undefined ;
44
+ }
45
+ if ( n === 3 ) {
46
+ return { alignment : scalarLayout . alignment * 4 , size : scalarLayout . size * 3 } ;
47
+ }
48
+ return { alignment : scalarLayout . alignment * n , size : scalarLayout . size * n } ;
49
+ }
50
+
34
51
/** Info for each matNxN<> container type. */
35
52
export const kMatrixContainerTypeInfo =
36
53
/* prettier-ignore */ {
37
- 'mat2x2' : { layout : { alignment : 8 , size : 16 } , arrayLength : 2 , innerLength : 2 } ,
38
- 'mat3x2' : { layout : { alignment : 8 , size : 24 } , arrayLength : 3 , innerLength : 2 } ,
39
- 'mat4x2' : { layout : { alignment : 8 , size : 32 } , arrayLength : 4 , innerLength : 2 } ,
40
- 'mat2x3' : { layout : { alignment : 16 , size : 32 } , arrayLength : 2 , innerLength : 3 } ,
41
- 'mat3x3' : { layout : { alignment : 16 , size : 48 } , arrayLength : 3 , innerLength : 3 } ,
42
- 'mat4x3' : { layout : { alignment : 16 , size : 64 } , arrayLength : 4 , innerLength : 3 } ,
43
- 'mat2x4' : { layout : { alignment : 16 , size : 32 } , arrayLength : 2 , innerLength : 4 } ,
44
- 'mat3x4' : { layout : { alignment : 16 , size : 48 } , arrayLength : 3 , innerLength : 4 } ,
45
- 'mat4x4' : { layout : { alignment : 16 , size : 64 } , arrayLength : 4 , innerLength : 4 } ,
54
+ 'mat2x2' : { arrayLength : 2 , innerLength : 2 } ,
55
+ 'mat3x2' : { arrayLength : 3 , innerLength : 2 } ,
56
+ 'mat4x2' : { arrayLength : 4 , innerLength : 2 } ,
57
+ 'mat2x3' : { arrayLength : 2 , innerLength : 3 } ,
58
+ 'mat3x3' : { arrayLength : 3 , innerLength : 3 } ,
59
+ 'mat4x3' : { arrayLength : 4 , innerLength : 3 } ,
60
+ 'mat2x4' : { arrayLength : 2 , innerLength : 4 } ,
61
+ 'mat3x4' : { arrayLength : 3 , innerLength : 4 } ,
62
+ 'mat4x4' : { arrayLength : 4 , innerLength : 4 } ,
46
63
} as const ;
47
64
/** List of all matNxN<> container types. */
48
65
export const kMatrixContainerTypes = keysOf ( kMatrixContainerTypeInfo ) ;
49
66
67
+ export const kMatrixContainerTypeLayoutInfo =
68
+ /* prettier-ignore */ {
69
+ 'f16' : {
70
+ 'mat2x2' : { layout : { alignment : 4 , size : 8 } } ,
71
+ 'mat3x2' : { layout : { alignment : 4 , size : 12 } } ,
72
+ 'mat4x2' : { layout : { alignment : 4 , size : 16 } } ,
73
+ 'mat2x3' : { layout : { alignment : 8 , size : 16 } } ,
74
+ 'mat3x3' : { layout : { alignment : 8 , size : 24 } } ,
75
+ 'mat4x3' : { layout : { alignment : 8 , size : 32 } } ,
76
+ 'mat2x4' : { layout : { alignment : 8 , size : 16 } } ,
77
+ 'mat3x4' : { layout : { alignment : 8 , size : 24 } } ,
78
+ 'mat4x4' : { layout : { alignment : 8 , size : 32 } } ,
79
+ } ,
80
+ 'f32' : {
81
+ 'mat2x2' : { layout : { alignment : 8 , size : 16 } } ,
82
+ 'mat3x2' : { layout : { alignment : 8 , size : 24 } } ,
83
+ 'mat4x2' : { layout : { alignment : 8 , size : 32 } } ,
84
+ 'mat2x3' : { layout : { alignment : 16 , size : 32 } } ,
85
+ 'mat3x3' : { layout : { alignment : 16 , size : 48 } } ,
86
+ 'mat4x3' : { layout : { alignment : 16 , size : 64 } } ,
87
+ 'mat2x4' : { layout : { alignment : 16 , size : 32 } } ,
88
+ 'mat3x4' : { layout : { alignment : 16 , size : 48 } } ,
89
+ 'mat4x4' : { layout : { alignment : 16 , size : 64 } } ,
90
+ }
91
+ } as const ;
92
+
50
93
export type AddressSpace = 'storage' | 'uniform' | 'private' | 'function' | 'workgroup' | 'handle' ;
51
94
export type AccessMode = 'read' | 'write' | 'read_write' ;
52
95
export type Scope = 'module' | 'function' ;
@@ -189,21 +232,27 @@ export function* generateTypes({
189
232
for ( const vectorType of kVectorContainerTypes ) {
190
233
yield {
191
234
type : `${ vectorType } <${ scalarType } >` ,
192
- _kTypeInfo : { elementBaseType : baseType , ...kVectorContainerTypeInfo [ vectorType ] } ,
235
+ _kTypeInfo : {
236
+ elementBaseType : baseType ,
237
+ ...kVectorContainerTypeInfo [ vectorType ] ,
238
+ layout : vectorLayout ( vectorType , scalarType as ScalarType ) ,
239
+ } ,
193
240
} ;
194
241
}
195
242
}
196
243
197
244
if ( containerType === 'matrix' ) {
198
- // Matrices can only be f32.
199
- if ( baseType === 'f32' ) {
245
+ // Matrices can only be f16 or f32.
246
+ if ( baseType === 'f16' || baseType === ' f32') {
200
247
for ( const matrixType of kMatrixContainerTypes ) {
201
- const matrixInfo = kMatrixContainerTypeInfo [ matrixType ] ;
248
+ const matrixDimInfo = kMatrixContainerTypeInfo [ matrixType ] ;
249
+ const matrixLayoutInfo = kMatrixContainerTypeLayoutInfo [ baseType ] [ matrixType ] ;
202
250
yield {
203
251
type : `${ matrixType } <${ scalarType } >` ,
204
252
_kTypeInfo : {
205
- elementBaseType : `vec${ matrixInfo . innerLength } <${ scalarType } >` ,
206
- ...matrixInfo ,
253
+ elementBaseType : `vec${ matrixDimInfo . innerLength } <${ scalarType } >` ,
254
+ ...matrixDimInfo ,
255
+ ...matrixLayoutInfo ,
207
256
} ,
208
257
} ;
209
258
}
@@ -212,33 +261,43 @@ export function* generateTypes({
212
261
213
262
// Array types
214
263
if ( containerType === 'array' ) {
264
+ // Buffer affective binding size must be a multiple of 4. Adjust array length as needed.
265
+ let arrayLength = kDefaultArrayLength ;
266
+ if (
267
+ addressSpace === 'storage' &&
268
+ scalarInfo . layout !== undefined &&
269
+ scalarInfo . layout . alignment % 4 !== 0
270
+ ) {
271
+ arrayLength = align ( arrayLength , 4 ) ;
272
+ }
273
+
215
274
const arrayTypeInfo = {
216
275
elementBaseType : `${ baseType } ` ,
217
- arrayLength : kArrayLength ,
276
+ arrayLength,
218
277
layout : scalarInfo . layout
219
278
? {
220
279
alignment : scalarInfo . layout . alignment ,
221
280
size :
222
281
addressSpace === 'uniform'
223
282
? // Uniform storage class must have array elements aligned to 16.
224
- kArrayLength *
283
+ arrayLength *
225
284
arrayStride ( {
226
285
...scalarInfo . layout ,
227
286
alignment : 16 ,
228
287
} )
229
- : kArrayLength * arrayStride ( scalarInfo . layout ) ,
288
+ : arrayLength * arrayStride ( scalarInfo . layout ) ,
230
289
}
231
290
: undefined ,
232
291
} ;
233
292
234
293
// Sized
235
294
if ( addressSpace === 'uniform' ) {
236
295
yield {
237
- type : `array<vec4<${ scalarType } >,${ kArrayLength } >` ,
296
+ type : `array<vec4<${ scalarType } >,${ arrayLength } >` ,
238
297
_kTypeInfo : arrayTypeInfo ,
239
298
} ;
240
299
} else {
241
- yield { type : `array<${ scalarType } ,${ kArrayLength } >` , _kTypeInfo : arrayTypeInfo } ;
300
+ yield { type : `array<${ scalarType } ,${ arrayLength } >` , _kTypeInfo : arrayTypeInfo } ;
242
301
}
243
302
// Unsized
244
303
if ( addressSpace === 'storage' ) {
@@ -272,7 +331,7 @@ export function supportsAtomics(p: {
272
331
) ;
273
332
}
274
333
275
- /** Generates an iterator of supported base types (i32/u32/f32/bool) */
334
+ /** Generates an iterator of supported base types (i32/u32/f16/ f32/bool) */
276
335
export function * supportedScalarTypes ( p : { isAtomic : boolean ; addressSpace : string } ) {
277
336
for ( const scalarType of kScalarTypes ) {
278
337
const info = kScalarTypeInfo [ scalarType ] ;
0 commit comments