@@ -2,19 +2,20 @@ import { keysOf } from '../../common/util/data_tables.js';
22import { assert } from '../../common/util/util.js' ;
33import { align } from '../util/math.js' ;
44
5- const kArrayLength = 3 ;
5+ const kDefaultArrayLength = 3 ;
66
77export type Requirement = 'never' | 'may' | 'must' ; // never is the same as "must not"
88export type ContainerType = 'scalar' | 'vector' | 'matrix' | 'atomic' | 'array' ;
9- export type ScalarType = 'i32' | 'u32' | 'f32' | 'bool' ;
9+ export type ScalarType = 'i32' | 'u32' | 'f16' | ' f32' | 'bool' ;
1010
11- export const HostSharableTypes = [ 'i32' , 'u32' , 'f32' ] as const ;
11+ export const HostSharableTypes = [ 'i32' , 'u32' , 'f16' , ' f32'] as const ;
1212
1313/** Info for each plain scalar type. */
1414export const kScalarTypeInfo =
1515 /* prettier-ignore */ {
1616 'i32' : { layout : { alignment : 4 , size : 4 } , supportsAtomics : true , arrayLength : 1 , innerLength : 0 } ,
1717 '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' } ,
1819 'f32' : { layout : { alignment : 4 , size : 4 } , supportsAtomics : false , arrayLength : 1 , innerLength : 0 } ,
1920 'bool' : { layout : undefined , supportsAtomics : false , arrayLength : 1 , innerLength : 0 } ,
2021} as const ;
@@ -24,29 +25,71 @@ export const kScalarTypes = keysOf(kScalarTypeInfo);
2425/** Info for each vecN<> container type. */
2526export const kVectorContainerTypeInfo =
2627 /* 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 } ,
3031} as const ;
3132/** List of all vecN<> container types. */
3233export const kVectorContainerTypes = keysOf ( kVectorContainerTypeInfo ) ;
3334
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+
3451/** Info for each matNxN<> container type. */
3552export const kMatrixContainerTypeInfo =
3653 /* 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 } ,
4663} as const ;
4764/** List of all matNxN<> container types. */
4865export const kMatrixContainerTypes = keysOf ( kMatrixContainerTypeInfo ) ;
4966
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+
5093export type AddressSpace = 'storage' | 'uniform' | 'private' | 'function' | 'workgroup' | 'handle' ;
5194export type AccessMode = 'read' | 'write' | 'read_write' ;
5295export type Scope = 'module' | 'function' ;
@@ -189,21 +232,27 @@ export function* generateTypes({
189232 for ( const vectorType of kVectorContainerTypes ) {
190233 yield {
191234 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+ } ,
193240 } ;
194241 }
195242 }
196243
197244 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') {
200247 for ( const matrixType of kMatrixContainerTypes ) {
201- const matrixInfo = kMatrixContainerTypeInfo [ matrixType ] ;
248+ const matrixDimInfo = kMatrixContainerTypeInfo [ matrixType ] ;
249+ const matrixLayoutInfo = kMatrixContainerTypeLayoutInfo [ baseType ] [ matrixType ] ;
202250 yield {
203251 type : `${ matrixType } <${ scalarType } >` ,
204252 _kTypeInfo : {
205- elementBaseType : `vec${ matrixInfo . innerLength } <${ scalarType } >` ,
206- ...matrixInfo ,
253+ elementBaseType : `vec${ matrixDimInfo . innerLength } <${ scalarType } >` ,
254+ ...matrixDimInfo ,
255+ ...matrixLayoutInfo ,
207256 } ,
208257 } ;
209258 }
@@ -212,33 +261,43 @@ export function* generateTypes({
212261
213262 // Array types
214263 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+
215274 const arrayTypeInfo = {
216275 elementBaseType : `${ baseType } ` ,
217- arrayLength : kArrayLength ,
276+ arrayLength,
218277 layout : scalarInfo . layout
219278 ? {
220279 alignment : scalarInfo . layout . alignment ,
221280 size :
222281 addressSpace === 'uniform'
223282 ? // Uniform storage class must have array elements aligned to 16.
224- kArrayLength *
283+ arrayLength *
225284 arrayStride ( {
226285 ...scalarInfo . layout ,
227286 alignment : 16 ,
228287 } )
229- : kArrayLength * arrayStride ( scalarInfo . layout ) ,
288+ : arrayLength * arrayStride ( scalarInfo . layout ) ,
230289 }
231290 : undefined ,
232291 } ;
233292
234293 // Sized
235294 if ( addressSpace === 'uniform' ) {
236295 yield {
237- type : `array<vec4<${ scalarType } >,${ kArrayLength } >` ,
296+ type : `array<vec4<${ scalarType } >,${ arrayLength } >` ,
238297 _kTypeInfo : arrayTypeInfo ,
239298 } ;
240299 } else {
241- yield { type : `array<${ scalarType } ,${ kArrayLength } >` , _kTypeInfo : arrayTypeInfo } ;
300+ yield { type : `array<${ scalarType } ,${ arrayLength } >` , _kTypeInfo : arrayTypeInfo } ;
242301 }
243302 // Unsized
244303 if ( addressSpace === 'storage' ) {
@@ -272,7 +331,7 @@ export function supportsAtomics(p: {
272331 ) ;
273332}
274333
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) */
276335export function * supportedScalarTypes ( p : { isAtomic : boolean ; addressSpace : string } ) {
277336 for ( const scalarType of kScalarTypes ) {
278337 const info = kScalarTypeInfo [ scalarType ] ;
0 commit comments