@luma.gl/effects 9.3.0-alpha.6 → 9.3.0-alpha.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/dist.dev.js +983 -223
- package/dist/dist.min.js +5 -5
- package/dist/index.cjs +340 -50
- package/dist/index.cjs.map +3 -3
- package/dist/passes/postprocessing/fxaa/fxaa.d.ts +1 -0
- package/dist/passes/postprocessing/fxaa/fxaa.d.ts.map +1 -1
- package/dist/passes/postprocessing/fxaa/fxaa.js +287 -0
- package/dist/passes/postprocessing/fxaa/fxaa.js.map +1 -1
- package/dist/passes/postprocessing/image-adjust-filters/brightnesscontrast.d.ts +1 -1
- package/dist/passes/postprocessing/image-adjust-filters/brightnesscontrast.d.ts.map +1 -1
- package/dist/passes/postprocessing/image-adjust-filters/brightnesscontrast.js +5 -7
- package/dist/passes/postprocessing/image-adjust-filters/brightnesscontrast.js.map +1 -1
- package/dist/passes/postprocessing/image-adjust-filters/denoise.d.ts +2 -2
- package/dist/passes/postprocessing/image-adjust-filters/denoise.js +4 -4
- package/dist/passes/postprocessing/image-adjust-filters/huesaturation.d.ts +1 -1
- package/dist/passes/postprocessing/image-adjust-filters/huesaturation.d.ts.map +1 -1
- package/dist/passes/postprocessing/image-adjust-filters/huesaturation.js +9 -10
- package/dist/passes/postprocessing/image-adjust-filters/huesaturation.js.map +1 -1
- package/dist/passes/postprocessing/image-adjust-filters/noise.d.ts +1 -1
- package/dist/passes/postprocessing/image-adjust-filters/noise.js +1 -1
- package/dist/passes/postprocessing/image-adjust-filters/sepia.d.ts +1 -1
- package/dist/passes/postprocessing/image-adjust-filters/sepia.js +1 -1
- package/dist/passes/postprocessing/image-adjust-filters/vibrance.d.ts +1 -1
- package/dist/passes/postprocessing/image-adjust-filters/vibrance.d.ts.map +1 -1
- package/dist/passes/postprocessing/image-adjust-filters/vibrance.js +3 -4
- package/dist/passes/postprocessing/image-adjust-filters/vibrance.js.map +1 -1
- package/dist/passes/postprocessing/image-adjust-filters/vignette.d.ts +1 -1
- package/dist/passes/postprocessing/image-adjust-filters/vignette.js +1 -1
- package/dist/passes/postprocessing/image-blur-filters/tiltshift.d.ts +1 -1
- package/dist/passes/postprocessing/image-blur-filters/tiltshift.js +1 -1
- package/dist/passes/postprocessing/image-blur-filters/triangleblur.d.ts +1 -1
- package/dist/passes/postprocessing/image-blur-filters/triangleblur.js +6 -6
- package/dist/passes/postprocessing/image-blur-filters/zoomblur.d.ts +1 -1
- package/dist/passes/postprocessing/image-blur-filters/zoomblur.js +1 -1
- package/dist/passes/postprocessing/image-fun-filters/colorhalftone.d.ts +1 -1
- package/dist/passes/postprocessing/image-fun-filters/colorhalftone.js +1 -1
- package/dist/passes/postprocessing/image-fun-filters/dotscreen.d.ts +1 -1
- package/dist/passes/postprocessing/image-fun-filters/dotscreen.js +1 -1
- package/dist/passes/postprocessing/image-fun-filters/edgework.d.ts +1 -1
- package/dist/passes/postprocessing/image-fun-filters/edgework.js +1 -1
- package/dist/passes/postprocessing/image-fun-filters/hexagonalpixelate.d.ts +1 -1
- package/dist/passes/postprocessing/image-fun-filters/hexagonalpixelate.js +1 -1
- package/dist/passes/postprocessing/image-fun-filters/ink.d.ts +1 -1
- package/dist/passes/postprocessing/image-fun-filters/ink.js +1 -1
- package/dist/passes/postprocessing/image-fun-filters/magnify.d.ts +1 -1
- package/dist/passes/postprocessing/image-fun-filters/magnify.d.ts.map +1 -1
- package/dist/passes/postprocessing/image-fun-filters/magnify.js +8 -3
- package/dist/passes/postprocessing/image-fun-filters/magnify.js.map +1 -1
- package/dist/passes/postprocessing/image-warp-filters/bulgepinch.d.ts +2 -2
- package/dist/passes/postprocessing/image-warp-filters/bulgepinch.js +3 -3
- package/dist/passes/postprocessing/image-warp-filters/swirl.d.ts +2 -2
- package/dist/passes/postprocessing/image-warp-filters/swirl.js +3 -3
- package/package.json +3 -3
- package/src/passes/postprocessing/fxaa/fxaa.ts +288 -0
- package/src/passes/postprocessing/image-adjust-filters/brightnesscontrast.ts +5 -7
- package/src/passes/postprocessing/image-adjust-filters/denoise.ts +4 -4
- package/src/passes/postprocessing/image-adjust-filters/huesaturation.ts +9 -10
- package/src/passes/postprocessing/image-adjust-filters/noise.ts +1 -1
- package/src/passes/postprocessing/image-adjust-filters/sepia.ts +1 -1
- package/src/passes/postprocessing/image-adjust-filters/vibrance.ts +3 -4
- package/src/passes/postprocessing/image-adjust-filters/vignette.ts +1 -1
- package/src/passes/postprocessing/image-blur-filters/tiltshift.ts +1 -1
- package/src/passes/postprocessing/image-blur-filters/triangleblur.ts +6 -6
- package/src/passes/postprocessing/image-blur-filters/zoomblur.ts +1 -1
- package/src/passes/postprocessing/image-fun-filters/colorhalftone.ts +1 -1
- package/src/passes/postprocessing/image-fun-filters/dotscreen.ts +1 -1
- package/src/passes/postprocessing/image-fun-filters/edgework.ts +1 -1
- package/src/passes/postprocessing/image-fun-filters/hexagonalpixelate.ts +1 -1
- package/src/passes/postprocessing/image-fun-filters/ink.ts +1 -1
- package/src/passes/postprocessing/image-fun-filters/magnify.ts +8 -3
- package/src/passes/postprocessing/image-warp-filters/bulgepinch.ts +3 -3
- package/src/passes/postprocessing/image-warp-filters/swirl.ts +3 -3
package/dist/dist.dev.js
CHANGED
|
@@ -66,6 +66,7 @@ var __exports__ = (() => {
|
|
|
66
66
|
ExternalTexture: () => ExternalTexture,
|
|
67
67
|
Fence: () => Fence,
|
|
68
68
|
Framebuffer: () => Framebuffer,
|
|
69
|
+
PipelineFactory: () => PipelineFactory,
|
|
69
70
|
PipelineLayout: () => PipelineLayout,
|
|
70
71
|
PresentationContext: () => PresentationContext,
|
|
71
72
|
QuerySet: () => QuerySet,
|
|
@@ -74,38 +75,39 @@ var __exports__ = (() => {
|
|
|
74
75
|
Resource: () => Resource,
|
|
75
76
|
Sampler: () => Sampler,
|
|
76
77
|
Shader: () => Shader,
|
|
78
|
+
ShaderFactory: () => ShaderFactory,
|
|
77
79
|
SharedRenderPipeline: () => SharedRenderPipeline,
|
|
78
80
|
Texture: () => Texture,
|
|
79
|
-
TextureFormatDecoder: () => TextureFormatDecoder,
|
|
80
81
|
TextureView: () => TextureView,
|
|
81
82
|
TransformFeedback: () => TransformFeedback,
|
|
82
83
|
UniformBlock: () => UniformBlock,
|
|
83
84
|
UniformBufferLayout: () => UniformBufferLayout,
|
|
84
85
|
UniformStore: () => UniformStore,
|
|
85
86
|
VertexArray: () => VertexArray,
|
|
87
|
+
_getDefaultBindGroupFactory: () => _getDefaultBindGroupFactory,
|
|
86
88
|
_getTextureFormatDefinition: () => getTextureFormatDefinition,
|
|
87
89
|
_getTextureFormatTable: () => getTextureFormatTable,
|
|
88
90
|
assert: () => assert2,
|
|
89
91
|
assertDefined: () => assertDefined,
|
|
92
|
+
dataTypeDecoder: () => dataTypeDecoder,
|
|
93
|
+
flattenBindingsByGroup: () => flattenBindingsByGroup,
|
|
90
94
|
getAttributeInfosFromLayouts: () => getAttributeInfosFromLayouts,
|
|
91
95
|
getAttributeShaderTypeInfo: () => getAttributeShaderTypeInfo,
|
|
92
|
-
getDataType: () => getDataType,
|
|
93
|
-
getDataTypeInfo: () => getDataTypeInfo,
|
|
94
96
|
getExternalImageSize: () => getExternalImageSize,
|
|
95
|
-
getNormalizedDataType: () => getNormalizedDataType,
|
|
96
97
|
getScratchArray: () => getScratchArray,
|
|
98
|
+
getShaderLayoutBinding: () => getShaderLayoutBinding,
|
|
97
99
|
getTextureImageView: () => getTextureImageView,
|
|
98
100
|
getTypedArrayConstructor: () => getTypedArrayConstructor,
|
|
99
101
|
getVariableShaderTypeInfo: () => getVariableShaderTypeInfo,
|
|
100
|
-
getVertexFormatFromAttribute: () => getVertexFormatFromAttribute,
|
|
101
|
-
getVertexFormatInfo: () => getVertexFormatInfo,
|
|
102
102
|
isExternalImage: () => isExternalImage,
|
|
103
103
|
log: () => log,
|
|
104
104
|
luma: () => luma,
|
|
105
|
-
|
|
105
|
+
normalizeBindingsByGroup: () => normalizeBindingsByGroup,
|
|
106
106
|
readPixel: () => readPixel,
|
|
107
107
|
setTextureImageData: () => setTextureImageData,
|
|
108
|
+
shaderTypeDecoder: () => shaderTypeDecoder,
|
|
108
109
|
textureFormatDecoder: () => textureFormatDecoder,
|
|
110
|
+
vertexFormatDecoder: () => vertexFormatDecoder,
|
|
109
111
|
writePixel: () => writePixel
|
|
110
112
|
});
|
|
111
113
|
|
|
@@ -1347,62 +1349,73 @@ var __exports__ = (() => {
|
|
|
1347
1349
|
onMapped: void 0
|
|
1348
1350
|
});
|
|
1349
1351
|
|
|
1350
|
-
// ../core/src/shadertypes/data-types/
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
return "unorm8";
|
|
1371
|
-
case "sint8":
|
|
1372
|
-
return "snorm8";
|
|
1373
|
-
case "uint16":
|
|
1374
|
-
return "unorm16";
|
|
1375
|
-
case "sint16":
|
|
1376
|
-
return "snorm16";
|
|
1377
|
-
default:
|
|
1378
|
-
return dataType;
|
|
1352
|
+
// ../core/src/shadertypes/data-types/data-type-decoder.ts
|
|
1353
|
+
var DataTypeDecoder = class {
|
|
1354
|
+
/**
|
|
1355
|
+
* Gets info about a data type constant (signed or normalized)
|
|
1356
|
+
* @returns underlying primitive / signed types, byte length, normalization, integer, signed flags
|
|
1357
|
+
*/
|
|
1358
|
+
getDataTypeInfo(type) {
|
|
1359
|
+
const [signedType, primitiveType, byteLength] = NORMALIZED_TYPE_MAP[type];
|
|
1360
|
+
const normalized = type.includes("norm");
|
|
1361
|
+
const integer = !normalized && !type.startsWith("float");
|
|
1362
|
+
const signed = type.startsWith("s");
|
|
1363
|
+
return {
|
|
1364
|
+
signedType,
|
|
1365
|
+
primitiveType,
|
|
1366
|
+
byteLength,
|
|
1367
|
+
normalized,
|
|
1368
|
+
integer,
|
|
1369
|
+
signed
|
|
1370
|
+
// TODO - add webglOnly flag
|
|
1371
|
+
};
|
|
1379
1372
|
}
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1373
|
+
/** Build a vertex format from a signed data type and a component */
|
|
1374
|
+
getNormalizedDataType(signedDataType) {
|
|
1375
|
+
const dataType = signedDataType;
|
|
1376
|
+
switch (dataType) {
|
|
1377
|
+
case "uint8":
|
|
1378
|
+
return "unorm8";
|
|
1379
|
+
case "sint8":
|
|
1380
|
+
return "snorm8";
|
|
1381
|
+
case "uint16":
|
|
1382
|
+
return "unorm16";
|
|
1383
|
+
case "sint16":
|
|
1384
|
+
return "snorm16";
|
|
1385
|
+
default:
|
|
1386
|
+
return dataType;
|
|
1387
|
+
}
|
|
1389
1388
|
}
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1389
|
+
/** Align offset to 1, 2 or 4 elements (4, 8 or 16 bytes) */
|
|
1390
|
+
alignTo(size, count) {
|
|
1391
|
+
switch (count) {
|
|
1392
|
+
case 1:
|
|
1393
|
+
return size;
|
|
1394
|
+
case 2:
|
|
1395
|
+
return size + size % 2;
|
|
1396
|
+
default:
|
|
1397
|
+
return size + (4 - size % 4) % 4;
|
|
1398
|
+
}
|
|
1395
1399
|
}
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1400
|
+
/** Returns the VariableShaderType that corresponds to a typed array */
|
|
1401
|
+
getDataType(arrayOrType) {
|
|
1402
|
+
const Constructor = ArrayBuffer.isView(arrayOrType) ? arrayOrType.constructor : arrayOrType;
|
|
1403
|
+
if (Constructor === Uint8ClampedArray) {
|
|
1404
|
+
return "uint8";
|
|
1405
|
+
}
|
|
1406
|
+
const info = Object.values(NORMALIZED_TYPE_MAP).find((entry) => Constructor === entry[4]);
|
|
1407
|
+
if (!info) {
|
|
1408
|
+
throw new Error(Constructor.name);
|
|
1409
|
+
}
|
|
1410
|
+
return info[0];
|
|
1399
1411
|
}
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
}
|
|
1412
|
+
/** Returns the TypedArray that corresponds to a shader data type */
|
|
1413
|
+
getTypedArrayConstructor(type) {
|
|
1414
|
+
const [, , , , Constructor] = NORMALIZED_TYPE_MAP[type];
|
|
1415
|
+
return Constructor;
|
|
1416
|
+
}
|
|
1417
|
+
};
|
|
1418
|
+
var dataTypeDecoder = new DataTypeDecoder();
|
|
1406
1419
|
var NORMALIZED_TYPE_MAP = {
|
|
1407
1420
|
uint8: ["uint8", "u32", 1, false, Uint8Array],
|
|
1408
1421
|
sint8: ["sint8", "i32", 1, false, Int8Array],
|
|
@@ -1418,87 +1431,99 @@ var __exports__ = (() => {
|
|
|
1418
1431
|
sint32: ["sint32", "i32", 4, false, Int32Array]
|
|
1419
1432
|
};
|
|
1420
1433
|
|
|
1421
|
-
// ../core/src/shadertypes/vertex-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
type
|
|
1434
|
-
components
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
case "unorm8":
|
|
1449
|
-
if (components === 1) {
|
|
1450
|
-
return "unorm8";
|
|
1451
|
-
}
|
|
1452
|
-
if (components === 3) {
|
|
1453
|
-
return "unorm8x3-webgl";
|
|
1454
|
-
}
|
|
1455
|
-
return `${dataType}x${components}`;
|
|
1456
|
-
case "snorm8":
|
|
1457
|
-
case "uint8":
|
|
1458
|
-
case "sint8":
|
|
1459
|
-
case "uint16":
|
|
1460
|
-
case "sint16":
|
|
1461
|
-
case "unorm16":
|
|
1462
|
-
case "snorm16":
|
|
1463
|
-
case "float16":
|
|
1464
|
-
if (components === 1 || components === 3) {
|
|
1465
|
-
throw new Error(`size: ${components}`);
|
|
1466
|
-
}
|
|
1467
|
-
return `${dataType}x${components}`;
|
|
1468
|
-
default:
|
|
1469
|
-
return components === 1 ? dataType : `${dataType}x${components}`;
|
|
1434
|
+
// ../core/src/shadertypes/vertex-types/vertex-format-decoder.ts
|
|
1435
|
+
var VertexFormatDecoder = class {
|
|
1436
|
+
/**
|
|
1437
|
+
* Decodes a vertex format, returning type, components, byte length and flags (integer, signed, normalized)
|
|
1438
|
+
*/
|
|
1439
|
+
getVertexFormatInfo(format) {
|
|
1440
|
+
let webglOnly;
|
|
1441
|
+
if (format.endsWith("-webgl")) {
|
|
1442
|
+
format.replace("-webgl", "");
|
|
1443
|
+
webglOnly = true;
|
|
1444
|
+
}
|
|
1445
|
+
const [type_, count] = format.split("x");
|
|
1446
|
+
const type = type_;
|
|
1447
|
+
const components = count ? parseInt(count) : 1;
|
|
1448
|
+
const decodedType = dataTypeDecoder.getDataTypeInfo(type);
|
|
1449
|
+
const result = {
|
|
1450
|
+
type,
|
|
1451
|
+
components,
|
|
1452
|
+
byteLength: decodedType.byteLength * components,
|
|
1453
|
+
integer: decodedType.integer,
|
|
1454
|
+
signed: decodedType.signed,
|
|
1455
|
+
normalized: decodedType.normalized
|
|
1456
|
+
};
|
|
1457
|
+
if (webglOnly) {
|
|
1458
|
+
result.webglOnly = true;
|
|
1459
|
+
}
|
|
1460
|
+
return result;
|
|
1470
1461
|
}
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1462
|
+
/** Build a vertex format from a signed data type and a component */
|
|
1463
|
+
makeVertexFormat(signedDataType, components, normalized) {
|
|
1464
|
+
const dataType = normalized ? dataTypeDecoder.getNormalizedDataType(signedDataType) : signedDataType;
|
|
1465
|
+
switch (dataType) {
|
|
1466
|
+
case "unorm8":
|
|
1467
|
+
if (components === 1) {
|
|
1468
|
+
return "unorm8";
|
|
1469
|
+
}
|
|
1470
|
+
if (components === 3) {
|
|
1471
|
+
return "unorm8x3-webgl";
|
|
1472
|
+
}
|
|
1473
|
+
return `${dataType}x${components}`;
|
|
1474
|
+
case "snorm8":
|
|
1475
|
+
case "uint8":
|
|
1476
|
+
case "sint8":
|
|
1477
|
+
case "uint16":
|
|
1478
|
+
case "sint16":
|
|
1479
|
+
case "unorm16":
|
|
1480
|
+
case "snorm16":
|
|
1481
|
+
case "float16":
|
|
1482
|
+
if (components === 1 || components === 3) {
|
|
1483
|
+
throw new Error(`size: ${components}`);
|
|
1484
|
+
}
|
|
1485
|
+
return `${dataType}x${components}`;
|
|
1486
|
+
default:
|
|
1487
|
+
return components === 1 ? dataType : `${dataType}x${components}`;
|
|
1488
|
+
}
|
|
1475
1489
|
}
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
vertexType = "float32";
|
|
1485
|
-
break;
|
|
1486
|
-
case "i32":
|
|
1487
|
-
vertexType = "sint32";
|
|
1488
|
-
break;
|
|
1489
|
-
case "u32":
|
|
1490
|
-
vertexType = "uint32";
|
|
1491
|
-
break;
|
|
1492
|
-
case "f16":
|
|
1493
|
-
return opts.components <= 2 ? "float16x2" : "float16x4";
|
|
1490
|
+
/** Get the vertex format for an attribute with TypedArray and size */
|
|
1491
|
+
getVertexFormatFromAttribute(typedArray, size, normalized) {
|
|
1492
|
+
if (!size || size > 4) {
|
|
1493
|
+
throw new Error(`size ${size}`);
|
|
1494
|
+
}
|
|
1495
|
+
const components = size;
|
|
1496
|
+
const signedDataType = dataTypeDecoder.getDataType(typedArray);
|
|
1497
|
+
return this.makeVertexFormat(signedDataType, components, normalized);
|
|
1494
1498
|
}
|
|
1495
|
-
|
|
1496
|
-
|
|
1499
|
+
/**
|
|
1500
|
+
* Return a "default" vertex format for a certain shader data type
|
|
1501
|
+
* The simplest vertex format that matches the shader attribute's data type
|
|
1502
|
+
*/
|
|
1503
|
+
getCompatibleVertexFormat(opts) {
|
|
1504
|
+
let vertexType;
|
|
1505
|
+
switch (opts.primitiveType) {
|
|
1506
|
+
case "f32":
|
|
1507
|
+
vertexType = "float32";
|
|
1508
|
+
break;
|
|
1509
|
+
case "i32":
|
|
1510
|
+
vertexType = "sint32";
|
|
1511
|
+
break;
|
|
1512
|
+
case "u32":
|
|
1513
|
+
vertexType = "uint32";
|
|
1514
|
+
break;
|
|
1515
|
+
case "f16":
|
|
1516
|
+
return opts.components <= 2 ? "float16x2" : "float16x4";
|
|
1517
|
+
}
|
|
1518
|
+
if (opts.components === 1) {
|
|
1519
|
+
return vertexType;
|
|
1520
|
+
}
|
|
1521
|
+
return `${vertexType}x${opts.components}`;
|
|
1497
1522
|
}
|
|
1498
|
-
|
|
1499
|
-
|
|
1523
|
+
};
|
|
1524
|
+
var vertexFormatDecoder = new VertexFormatDecoder();
|
|
1500
1525
|
|
|
1501
|
-
// ../core/src/shadertypes/
|
|
1526
|
+
// ../core/src/shadertypes/texture-types/texture-format-table.ts
|
|
1502
1527
|
var texture_compression_bc = "texture-compression-bc";
|
|
1503
1528
|
var texture_compression_astc = "texture-compression-astc";
|
|
1504
1529
|
var texture_compression_etc2 = "texture-compression-etc2";
|
|
@@ -1669,7 +1694,7 @@ var __exports__ = (() => {
|
|
|
1669
1694
|
...TEXTURE_FORMAT_COMPRESSED_TABLE
|
|
1670
1695
|
};
|
|
1671
1696
|
|
|
1672
|
-
// ../core/src/shadertypes/
|
|
1697
|
+
// ../core/src/shadertypes/texture-types/texture-format-decoder.ts
|
|
1673
1698
|
var RGB_FORMAT_REGEX = /^(r|rg|rgb|rgba|bgra)([0-9]*)([a-z]*)(-srgb)?(-webgl)?$/;
|
|
1674
1699
|
var COLOR_FORMAT_PREFIXES = ["rgb", "rgba", "bgra"];
|
|
1675
1700
|
var DEPTH_FORMAT_PREFIXES = ["depth", "stencil"];
|
|
@@ -1780,11 +1805,11 @@ var __exports__ = (() => {
|
|
|
1780
1805
|
formatInfo.blockHeight = blockSize.blockHeight;
|
|
1781
1806
|
}
|
|
1782
1807
|
}
|
|
1783
|
-
const matches = RGB_FORMAT_REGEX.exec(format);
|
|
1808
|
+
const matches = !formatInfo.packed ? RGB_FORMAT_REGEX.exec(format) : null;
|
|
1784
1809
|
if (matches) {
|
|
1785
1810
|
const [, channels, length, type, srgb, suffix] = matches;
|
|
1786
1811
|
const dataType = `${type}${length}`;
|
|
1787
|
-
const decodedType = getDataTypeInfo(dataType);
|
|
1812
|
+
const decodedType = dataTypeDecoder.getDataTypeInfo(dataType);
|
|
1788
1813
|
const bits = decodedType.byteLength * 8;
|
|
1789
1814
|
const components = channels?.length ?? 1;
|
|
1790
1815
|
const bitsPerChannel = [
|
|
@@ -1883,7 +1908,7 @@ var __exports__ = (() => {
|
|
|
1883
1908
|
return 16;
|
|
1884
1909
|
}
|
|
1885
1910
|
|
|
1886
|
-
// ../core/src/image-
|
|
1911
|
+
// ../core/src/shadertypes/image-types/image-types.ts
|
|
1887
1912
|
function isExternalImage(data) {
|
|
1888
1913
|
return typeof ImageData !== "undefined" && data instanceof ImageData || typeof ImageBitmap !== "undefined" && data instanceof ImageBitmap || typeof HTMLImageElement !== "undefined" && data instanceof HTMLImageElement || typeof HTMLVideoElement !== "undefined" && data instanceof HTMLVideoElement || typeof VideoFrame !== "undefined" && data instanceof VideoFrame || typeof HTMLCanvasElement !== "undefined" && data instanceof HTMLCanvasElement || typeof OffscreenCanvas !== "undefined" && data instanceof OffscreenCanvas;
|
|
1889
1914
|
}
|
|
@@ -1906,6 +1931,52 @@ var __exports__ = (() => {
|
|
|
1906
1931
|
// ../core/src/adapter/device.ts
|
|
1907
1932
|
var DeviceLimits = class {
|
|
1908
1933
|
};
|
|
1934
|
+
function formatErrorLogArguments(context, args) {
|
|
1935
|
+
const formattedContext = formatErrorLogValue(context);
|
|
1936
|
+
const formattedArgs = args.map(formatErrorLogValue).filter((arg) => arg !== void 0);
|
|
1937
|
+
return [formattedContext, ...formattedArgs].filter((arg) => arg !== void 0);
|
|
1938
|
+
}
|
|
1939
|
+
function formatErrorLogValue(value) {
|
|
1940
|
+
if (value === void 0) {
|
|
1941
|
+
return void 0;
|
|
1942
|
+
}
|
|
1943
|
+
if (value === null || typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
|
|
1944
|
+
return value;
|
|
1945
|
+
}
|
|
1946
|
+
if (value instanceof Error) {
|
|
1947
|
+
return value.message;
|
|
1948
|
+
}
|
|
1949
|
+
if (Array.isArray(value)) {
|
|
1950
|
+
return value.map(formatErrorLogValue);
|
|
1951
|
+
}
|
|
1952
|
+
if (typeof value === "object") {
|
|
1953
|
+
if (hasCustomToString(value)) {
|
|
1954
|
+
const stringValue = String(value);
|
|
1955
|
+
if (stringValue !== "[object Object]") {
|
|
1956
|
+
return stringValue;
|
|
1957
|
+
}
|
|
1958
|
+
}
|
|
1959
|
+
if (looksLikeGPUCompilationMessage(value)) {
|
|
1960
|
+
return formatGPUCompilationMessage(value);
|
|
1961
|
+
}
|
|
1962
|
+
return value.constructor?.name || "Object";
|
|
1963
|
+
}
|
|
1964
|
+
return String(value);
|
|
1965
|
+
}
|
|
1966
|
+
function hasCustomToString(value) {
|
|
1967
|
+
return "toString" in value && typeof value.toString === "function" && value.toString !== Object.prototype.toString;
|
|
1968
|
+
}
|
|
1969
|
+
function looksLikeGPUCompilationMessage(value) {
|
|
1970
|
+
return "message" in value && "type" in value;
|
|
1971
|
+
}
|
|
1972
|
+
function formatGPUCompilationMessage(value) {
|
|
1973
|
+
const type = typeof value.type === "string" ? value.type : "message";
|
|
1974
|
+
const message = typeof value.message === "string" ? value.message : "";
|
|
1975
|
+
const lineNum = typeof value.lineNum === "number" ? value.lineNum : null;
|
|
1976
|
+
const linePos = typeof value.linePos === "number" ? value.linePos : null;
|
|
1977
|
+
const location = lineNum !== null && linePos !== null ? ` @ ${lineNum}:${linePos}` : lineNum !== null ? ` @ ${lineNum}` : "";
|
|
1978
|
+
return `${type}${location}: ${message}`.trim();
|
|
1979
|
+
}
|
|
1909
1980
|
var DeviceFeatures = class {
|
|
1910
1981
|
features;
|
|
1911
1982
|
disabledFeatures;
|
|
@@ -1935,6 +2006,8 @@ var __exports__ = (() => {
|
|
|
1935
2006
|
userData = {};
|
|
1936
2007
|
/** stats */
|
|
1937
2008
|
statsManager = lumaStats;
|
|
2009
|
+
/** Internal per-device factory storage */
|
|
2010
|
+
_factories = {};
|
|
1938
2011
|
/** An abstract timestamp used for change tracking */
|
|
1939
2012
|
timestamp = 0;
|
|
1940
2013
|
/** True if this device has been reused during device creation (app has multiple references) */
|
|
@@ -1948,8 +2021,9 @@ var __exports__ = (() => {
|
|
|
1948
2021
|
this.props = { ..._Device.defaultProps, ...props };
|
|
1949
2022
|
this.id = this.props.id || uid(this[Symbol.toStringTag].toLowerCase());
|
|
1950
2023
|
}
|
|
2024
|
+
// TODO - just expose the shadertypes decoders?
|
|
1951
2025
|
getVertexFormatInfo(format) {
|
|
1952
|
-
return getVertexFormatInfo(format);
|
|
2026
|
+
return vertexFormatDecoder.getVertexFormatInfo(format);
|
|
1953
2027
|
}
|
|
1954
2028
|
isVertexFormatSupported(format) {
|
|
1955
2029
|
return true;
|
|
@@ -2049,12 +2123,12 @@ var __exports__ = (() => {
|
|
|
2049
2123
|
reportError(error, context, ...args) {
|
|
2050
2124
|
const isHandled = this.props.onError(error, context);
|
|
2051
2125
|
if (!isHandled) {
|
|
2126
|
+
const logArguments = formatErrorLogArguments(context, args);
|
|
2052
2127
|
return log.error(
|
|
2053
2128
|
this.type === "webgl" ? "%cWebGL" : "%cWebGPU",
|
|
2054
2129
|
"color: white; background: red; padding: 2px 6px; border-radius: 3px;",
|
|
2055
2130
|
error.message,
|
|
2056
|
-
|
|
2057
|
-
...args
|
|
2131
|
+
...logArguments
|
|
2058
2132
|
);
|
|
2059
2133
|
}
|
|
2060
2134
|
return () => {
|
|
@@ -2101,6 +2175,14 @@ or create a device with the 'debug: true' prop.`;
|
|
|
2101
2175
|
_createSharedRenderPipelineWebGL(_props) {
|
|
2102
2176
|
throw new Error("_createSharedRenderPipelineWebGL() not implemented");
|
|
2103
2177
|
}
|
|
2178
|
+
/** Internal WebGPU-only helper for retrieving the native bind-group layout for a pipeline group. */
|
|
2179
|
+
_createBindGroupLayoutWebGPU(_pipeline, _group) {
|
|
2180
|
+
throw new Error("_createBindGroupLayoutWebGPU() not implemented");
|
|
2181
|
+
}
|
|
2182
|
+
/** Internal WebGPU-only helper for creating a native bind group. */
|
|
2183
|
+
_createBindGroupWebGPU(_bindGroupLayout, _shaderLayout, _bindings, _group) {
|
|
2184
|
+
throw new Error("_createBindGroupWebGPU() not implemented");
|
|
2185
|
+
}
|
|
2104
2186
|
/**
|
|
2105
2187
|
* Internal helper that returns `true` when timestamp-query GPU timing should be
|
|
2106
2188
|
* collected for this device.
|
|
@@ -3128,8 +3210,8 @@ or create a device with the 'debug: true' prop.`;
|
|
|
3128
3210
|
*
|
|
3129
3211
|
* @note The memory layout of the texture data is determined by the texture format and dimensions.
|
|
3130
3212
|
* @note The application can call Texture.computeMemoryLayout() to compute the backend-aligned layout.
|
|
3131
|
-
* @note The application can call Buffer.readAsync()
|
|
3132
|
-
* @note
|
|
3213
|
+
* @note The application can call Buffer.readAsync() to read the returned buffer on the CPU.
|
|
3214
|
+
* @note The destination buffer must be supplied by the caller and must be large enough for the requested region.
|
|
3133
3215
|
* @note On WebGPU this corresponds to a texture-to-buffer copy and uses buffer-copy alignment rules.
|
|
3134
3216
|
* @note On WebGL, luma.gl emulates the same logical readback behavior.
|
|
3135
3217
|
*/
|
|
@@ -3142,6 +3224,7 @@ or create a device with the 'debug: true' prop.`;
|
|
|
3142
3224
|
*
|
|
3143
3225
|
* @note The memory layout of the texture data is determined by the texture format and dimensions.
|
|
3144
3226
|
* @note The application can call Texture.computeMemoryLayout() to compute the layout.
|
|
3227
|
+
* @deprecated Use Texture.readBuffer() with an explicit destination buffer, or DynamicTexture.readAsync() for convenience readback.
|
|
3145
3228
|
*/
|
|
3146
3229
|
readDataAsync(options) {
|
|
3147
3230
|
throw new Error("readBuffer not implemented");
|
|
@@ -3888,7 +3971,8 @@ ${numberedLines}${positionIndicator}${message.type.toUpperCase()}: ${message.mes
|
|
|
3888
3971
|
bufferMode: void 0,
|
|
3889
3972
|
disableWarnings: false,
|
|
3890
3973
|
_sharedRenderPipeline: void 0,
|
|
3891
|
-
bindings: void 0
|
|
3974
|
+
bindings: void 0,
|
|
3975
|
+
bindGroups: void 0
|
|
3892
3976
|
});
|
|
3893
3977
|
|
|
3894
3978
|
// ../core/src/adapter/resources/shared-render-pipeline.ts
|
|
@@ -3908,6 +3992,482 @@ ${numberedLines}${positionIndicator}${message.type.toUpperCase()}: ${message.mes
|
|
|
3908
3992
|
}
|
|
3909
3993
|
};
|
|
3910
3994
|
|
|
3995
|
+
// ../core/src/adapter/resources/compute-pipeline.ts
|
|
3996
|
+
var _ComputePipeline = class extends Resource {
|
|
3997
|
+
get [Symbol.toStringTag]() {
|
|
3998
|
+
return "ComputePipeline";
|
|
3999
|
+
}
|
|
4000
|
+
hash = "";
|
|
4001
|
+
/** The merged shader layout */
|
|
4002
|
+
shaderLayout;
|
|
4003
|
+
constructor(device, props) {
|
|
4004
|
+
super(device, props, _ComputePipeline.defaultProps);
|
|
4005
|
+
this.shaderLayout = props.shaderLayout;
|
|
4006
|
+
}
|
|
4007
|
+
};
|
|
4008
|
+
var ComputePipeline = _ComputePipeline;
|
|
4009
|
+
__publicField(ComputePipeline, "defaultProps", {
|
|
4010
|
+
...Resource.defaultProps,
|
|
4011
|
+
shader: void 0,
|
|
4012
|
+
entryPoint: void 0,
|
|
4013
|
+
constants: {},
|
|
4014
|
+
shaderLayout: void 0
|
|
4015
|
+
});
|
|
4016
|
+
|
|
4017
|
+
// ../core/src/factories/pipeline-factory.ts
|
|
4018
|
+
var _PipelineFactory = class {
|
|
4019
|
+
/** Get the singleton default pipeline factory for the specified device */
|
|
4020
|
+
static getDefaultPipelineFactory(device) {
|
|
4021
|
+
const moduleData = device.getModuleData("@luma.gl/core");
|
|
4022
|
+
moduleData.defaultPipelineFactory ||= new _PipelineFactory(device);
|
|
4023
|
+
return moduleData.defaultPipelineFactory;
|
|
4024
|
+
}
|
|
4025
|
+
device;
|
|
4026
|
+
_hashCounter = 0;
|
|
4027
|
+
_hashes = {};
|
|
4028
|
+
_renderPipelineCache = {};
|
|
4029
|
+
_computePipelineCache = {};
|
|
4030
|
+
_sharedRenderPipelineCache = {};
|
|
4031
|
+
get [Symbol.toStringTag]() {
|
|
4032
|
+
return "PipelineFactory";
|
|
4033
|
+
}
|
|
4034
|
+
toString() {
|
|
4035
|
+
return `PipelineFactory(${this.device.id})`;
|
|
4036
|
+
}
|
|
4037
|
+
constructor(device) {
|
|
4038
|
+
this.device = device;
|
|
4039
|
+
}
|
|
4040
|
+
/**
|
|
4041
|
+
* WebGL has two cache layers with different priorities:
|
|
4042
|
+
* - `_sharedRenderPipelineCache` owns `WEBGLSharedRenderPipeline` / `WebGLProgram` reuse.
|
|
4043
|
+
* - `_renderPipelineCache` owns `RenderPipeline` wrapper reuse.
|
|
4044
|
+
*
|
|
4045
|
+
* Shared WebGL program reuse is the hard requirement. Wrapper reuse is beneficial,
|
|
4046
|
+
* but wrapper cache misses are acceptable if that keeps the cache logic simple and
|
|
4047
|
+
* prevents incorrect cache hits.
|
|
4048
|
+
*
|
|
4049
|
+
* In particular, wrapper hash logic must never force program creation or linked-program
|
|
4050
|
+
* introspection just to decide whether a shared WebGL program can be reused.
|
|
4051
|
+
*/
|
|
4052
|
+
/** Return a RenderPipeline matching supplied props. Reuses an equivalent pipeline if already created. */
|
|
4053
|
+
createRenderPipeline(props) {
|
|
4054
|
+
if (!this.device.props._cachePipelines) {
|
|
4055
|
+
return this.device.createRenderPipeline(props);
|
|
4056
|
+
}
|
|
4057
|
+
const allProps = { ...RenderPipeline.defaultProps, ...props };
|
|
4058
|
+
const cache = this._renderPipelineCache;
|
|
4059
|
+
const hash = this._hashRenderPipeline(allProps);
|
|
4060
|
+
let pipeline = cache[hash]?.resource;
|
|
4061
|
+
if (!pipeline) {
|
|
4062
|
+
const sharedRenderPipeline = this.device.type === "webgl" && this.device.props._sharePipelines ? this.createSharedRenderPipeline(allProps) : void 0;
|
|
4063
|
+
pipeline = this.device.createRenderPipeline({
|
|
4064
|
+
...allProps,
|
|
4065
|
+
id: allProps.id ? `${allProps.id}-cached` : uid("unnamed-cached"),
|
|
4066
|
+
_sharedRenderPipeline: sharedRenderPipeline
|
|
4067
|
+
});
|
|
4068
|
+
pipeline.hash = hash;
|
|
4069
|
+
cache[hash] = { resource: pipeline, useCount: 1 };
|
|
4070
|
+
if (this.device.props.debugFactories) {
|
|
4071
|
+
log.log(3, `${this}: ${pipeline} created, count=${cache[hash].useCount}`)();
|
|
4072
|
+
}
|
|
4073
|
+
} else {
|
|
4074
|
+
cache[hash].useCount++;
|
|
4075
|
+
if (this.device.props.debugFactories) {
|
|
4076
|
+
log.log(
|
|
4077
|
+
3,
|
|
4078
|
+
`${this}: ${cache[hash].resource} reused, count=${cache[hash].useCount}, (id=${props.id})`
|
|
4079
|
+
)();
|
|
4080
|
+
}
|
|
4081
|
+
}
|
|
4082
|
+
return pipeline;
|
|
4083
|
+
}
|
|
4084
|
+
/** Return a ComputePipeline matching supplied props. Reuses an equivalent pipeline if already created. */
|
|
4085
|
+
createComputePipeline(props) {
|
|
4086
|
+
if (!this.device.props._cachePipelines) {
|
|
4087
|
+
return this.device.createComputePipeline(props);
|
|
4088
|
+
}
|
|
4089
|
+
const allProps = { ...ComputePipeline.defaultProps, ...props };
|
|
4090
|
+
const cache = this._computePipelineCache;
|
|
4091
|
+
const hash = this._hashComputePipeline(allProps);
|
|
4092
|
+
let pipeline = cache[hash]?.resource;
|
|
4093
|
+
if (!pipeline) {
|
|
4094
|
+
pipeline = this.device.createComputePipeline({
|
|
4095
|
+
...allProps,
|
|
4096
|
+
id: allProps.id ? `${allProps.id}-cached` : void 0
|
|
4097
|
+
});
|
|
4098
|
+
pipeline.hash = hash;
|
|
4099
|
+
cache[hash] = { resource: pipeline, useCount: 1 };
|
|
4100
|
+
if (this.device.props.debugFactories) {
|
|
4101
|
+
log.log(3, `${this}: ${pipeline} created, count=${cache[hash].useCount}`)();
|
|
4102
|
+
}
|
|
4103
|
+
} else {
|
|
4104
|
+
cache[hash].useCount++;
|
|
4105
|
+
if (this.device.props.debugFactories) {
|
|
4106
|
+
log.log(
|
|
4107
|
+
3,
|
|
4108
|
+
`${this}: ${cache[hash].resource} reused, count=${cache[hash].useCount}, (id=${props.id})`
|
|
4109
|
+
)();
|
|
4110
|
+
}
|
|
4111
|
+
}
|
|
4112
|
+
return pipeline;
|
|
4113
|
+
}
|
|
4114
|
+
release(pipeline) {
|
|
4115
|
+
if (!this.device.props._cachePipelines) {
|
|
4116
|
+
pipeline.destroy();
|
|
4117
|
+
return;
|
|
4118
|
+
}
|
|
4119
|
+
const cache = this._getCache(pipeline);
|
|
4120
|
+
const hash = pipeline.hash;
|
|
4121
|
+
cache[hash].useCount--;
|
|
4122
|
+
if (cache[hash].useCount === 0) {
|
|
4123
|
+
this._destroyPipeline(pipeline);
|
|
4124
|
+
if (this.device.props.debugFactories) {
|
|
4125
|
+
log.log(3, `${this}: ${pipeline} released and destroyed`)();
|
|
4126
|
+
}
|
|
4127
|
+
} else if (cache[hash].useCount < 0) {
|
|
4128
|
+
log.error(`${this}: ${pipeline} released, useCount < 0, resetting`)();
|
|
4129
|
+
cache[hash].useCount = 0;
|
|
4130
|
+
} else if (this.device.props.debugFactories) {
|
|
4131
|
+
log.log(3, `${this}: ${pipeline} released, count=${cache[hash].useCount}`)();
|
|
4132
|
+
}
|
|
4133
|
+
}
|
|
4134
|
+
createSharedRenderPipeline(props) {
|
|
4135
|
+
const sharedPipelineHash = this._hashSharedRenderPipeline(props);
|
|
4136
|
+
let sharedCacheItem = this._sharedRenderPipelineCache[sharedPipelineHash];
|
|
4137
|
+
if (!sharedCacheItem) {
|
|
4138
|
+
const sharedRenderPipeline = this.device._createSharedRenderPipelineWebGL(props);
|
|
4139
|
+
sharedCacheItem = { resource: sharedRenderPipeline, useCount: 0 };
|
|
4140
|
+
this._sharedRenderPipelineCache[sharedPipelineHash] = sharedCacheItem;
|
|
4141
|
+
}
|
|
4142
|
+
sharedCacheItem.useCount++;
|
|
4143
|
+
return sharedCacheItem.resource;
|
|
4144
|
+
}
|
|
4145
|
+
releaseSharedRenderPipeline(pipeline) {
|
|
4146
|
+
if (!pipeline.sharedRenderPipeline) {
|
|
4147
|
+
return;
|
|
4148
|
+
}
|
|
4149
|
+
const sharedPipelineHash = this._hashSharedRenderPipeline(pipeline.sharedRenderPipeline.props);
|
|
4150
|
+
const sharedCacheItem = this._sharedRenderPipelineCache[sharedPipelineHash];
|
|
4151
|
+
if (!sharedCacheItem) {
|
|
4152
|
+
return;
|
|
4153
|
+
}
|
|
4154
|
+
sharedCacheItem.useCount--;
|
|
4155
|
+
if (sharedCacheItem.useCount === 0) {
|
|
4156
|
+
sharedCacheItem.resource.destroy();
|
|
4157
|
+
delete this._sharedRenderPipelineCache[sharedPipelineHash];
|
|
4158
|
+
}
|
|
4159
|
+
}
|
|
4160
|
+
// PRIVATE
|
|
4161
|
+
/** Destroy a cached pipeline, removing it from the cache if configured to do so. */
|
|
4162
|
+
_destroyPipeline(pipeline) {
|
|
4163
|
+
const cache = this._getCache(pipeline);
|
|
4164
|
+
if (!this.device.props._destroyPipelines) {
|
|
4165
|
+
return false;
|
|
4166
|
+
}
|
|
4167
|
+
delete cache[pipeline.hash];
|
|
4168
|
+
pipeline.destroy();
|
|
4169
|
+
if (pipeline instanceof RenderPipeline) {
|
|
4170
|
+
this.releaseSharedRenderPipeline(pipeline);
|
|
4171
|
+
}
|
|
4172
|
+
return true;
|
|
4173
|
+
}
|
|
4174
|
+
/** Get the appropriate cache for the type of pipeline */
|
|
4175
|
+
_getCache(pipeline) {
|
|
4176
|
+
let cache;
|
|
4177
|
+
if (pipeline instanceof ComputePipeline) {
|
|
4178
|
+
cache = this._computePipelineCache;
|
|
4179
|
+
}
|
|
4180
|
+
if (pipeline instanceof RenderPipeline) {
|
|
4181
|
+
cache = this._renderPipelineCache;
|
|
4182
|
+
}
|
|
4183
|
+
if (!cache) {
|
|
4184
|
+
throw new Error(`${this}`);
|
|
4185
|
+
}
|
|
4186
|
+
if (!cache[pipeline.hash]) {
|
|
4187
|
+
throw new Error(`${this}: ${pipeline} matched incorrect entry`);
|
|
4188
|
+
}
|
|
4189
|
+
return cache;
|
|
4190
|
+
}
|
|
4191
|
+
/** Calculate a hash based on all the inputs for a compute pipeline */
|
|
4192
|
+
_hashComputePipeline(props) {
|
|
4193
|
+
const { type } = this.device;
|
|
4194
|
+
const shaderHash = this._getHash(props.shader.source);
|
|
4195
|
+
const shaderLayoutHash = this._getHash(JSON.stringify(props.shaderLayout));
|
|
4196
|
+
return `${type}/C/${shaderHash}SL${shaderLayoutHash}`;
|
|
4197
|
+
}
|
|
4198
|
+
/** Calculate a hash based on all the inputs for a render pipeline */
|
|
4199
|
+
_hashRenderPipeline(props) {
|
|
4200
|
+
const vsHash = props.vs ? this._getHash(props.vs.source) : 0;
|
|
4201
|
+
const fsHash = props.fs ? this._getHash(props.fs.source) : 0;
|
|
4202
|
+
const varyingHash = this._getWebGLVaryingHash(props);
|
|
4203
|
+
const shaderLayoutHash = this._getHash(JSON.stringify(props.shaderLayout));
|
|
4204
|
+
const bufferLayoutHash = this._getHash(JSON.stringify(props.bufferLayout));
|
|
4205
|
+
const { type } = this.device;
|
|
4206
|
+
switch (type) {
|
|
4207
|
+
case "webgl":
|
|
4208
|
+
const webglParameterHash = this._getHash(JSON.stringify(props.parameters));
|
|
4209
|
+
return `${type}/R/${vsHash}/${fsHash}V${varyingHash}T${props.topology}P${webglParameterHash}SL${shaderLayoutHash}BL${bufferLayoutHash}`;
|
|
4210
|
+
case "webgpu":
|
|
4211
|
+
default:
|
|
4212
|
+
const entryPointHash = this._getHash(
|
|
4213
|
+
JSON.stringify({
|
|
4214
|
+
vertexEntryPoint: props.vertexEntryPoint,
|
|
4215
|
+
fragmentEntryPoint: props.fragmentEntryPoint
|
|
4216
|
+
})
|
|
4217
|
+
);
|
|
4218
|
+
const parameterHash = this._getHash(JSON.stringify(props.parameters));
|
|
4219
|
+
const attachmentHash = this._getWebGPUAttachmentHash(props);
|
|
4220
|
+
return `${type}/R/${vsHash}/${fsHash}V${varyingHash}T${props.topology}EP${entryPointHash}P${parameterHash}SL${shaderLayoutHash}BL${bufferLayoutHash}A${attachmentHash}`;
|
|
4221
|
+
}
|
|
4222
|
+
}
|
|
4223
|
+
// This is the only gate for shared `WebGLProgram` reuse.
|
|
4224
|
+
// Only include inputs that affect program linking or transform-feedback linkage.
|
|
4225
|
+
// Wrapper-only concerns such as topology, parameters, attachment formats and layout
|
|
4226
|
+
// overrides must not be added here.
|
|
4227
|
+
_hashSharedRenderPipeline(props) {
|
|
4228
|
+
const vsHash = props.vs ? this._getHash(props.vs.source) : 0;
|
|
4229
|
+
const fsHash = props.fs ? this._getHash(props.fs.source) : 0;
|
|
4230
|
+
const varyingHash = this._getWebGLVaryingHash(props);
|
|
4231
|
+
return `webgl/S/${vsHash}/${fsHash}V${varyingHash}`;
|
|
4232
|
+
}
|
|
4233
|
+
_getHash(key) {
|
|
4234
|
+
if (this._hashes[key] === void 0) {
|
|
4235
|
+
this._hashes[key] = this._hashCounter++;
|
|
4236
|
+
}
|
|
4237
|
+
return this._hashes[key];
|
|
4238
|
+
}
|
|
4239
|
+
_getWebGLVaryingHash(props) {
|
|
4240
|
+
const { varyings = [], bufferMode = null } = props;
|
|
4241
|
+
return this._getHash(JSON.stringify({ varyings, bufferMode }));
|
|
4242
|
+
}
|
|
4243
|
+
_getWebGPUAttachmentHash(props) {
|
|
4244
|
+
const colorAttachmentFormats = props.colorAttachmentFormats ?? [
|
|
4245
|
+
this.device.preferredColorFormat
|
|
4246
|
+
];
|
|
4247
|
+
const depthStencilAttachmentFormat = props.parameters?.depthWriteEnabled ? props.depthStencilAttachmentFormat || this.device.preferredDepthFormat : null;
|
|
4248
|
+
return this._getHash(
|
|
4249
|
+
JSON.stringify({
|
|
4250
|
+
colorAttachmentFormats,
|
|
4251
|
+
depthStencilAttachmentFormat
|
|
4252
|
+
})
|
|
4253
|
+
);
|
|
4254
|
+
}
|
|
4255
|
+
};
|
|
4256
|
+
var PipelineFactory = _PipelineFactory;
|
|
4257
|
+
__publicField(PipelineFactory, "defaultProps", { ...RenderPipeline.defaultProps });
|
|
4258
|
+
|
|
4259
|
+
// ../core/src/factories/shader-factory.ts
|
|
4260
|
+
var _ShaderFactory = class {
|
|
4261
|
+
/** Returns the default ShaderFactory for the given {@link Device}, creating one if necessary. */
|
|
4262
|
+
static getDefaultShaderFactory(device) {
|
|
4263
|
+
const moduleData = device.getModuleData("@luma.gl/core");
|
|
4264
|
+
moduleData.defaultShaderFactory ||= new _ShaderFactory(device);
|
|
4265
|
+
return moduleData.defaultShaderFactory;
|
|
4266
|
+
}
|
|
4267
|
+
device;
|
|
4268
|
+
_cache = {};
|
|
4269
|
+
get [Symbol.toStringTag]() {
|
|
4270
|
+
return "ShaderFactory";
|
|
4271
|
+
}
|
|
4272
|
+
toString() {
|
|
4273
|
+
return `${this[Symbol.toStringTag]}(${this.device.id})`;
|
|
4274
|
+
}
|
|
4275
|
+
/** @internal */
|
|
4276
|
+
constructor(device) {
|
|
4277
|
+
this.device = device;
|
|
4278
|
+
}
|
|
4279
|
+
/** Requests a {@link Shader} from the cache, creating a new Shader only if necessary. */
|
|
4280
|
+
createShader(props) {
|
|
4281
|
+
if (!this.device.props._cacheShaders) {
|
|
4282
|
+
return this.device.createShader(props);
|
|
4283
|
+
}
|
|
4284
|
+
const key = this._hashShader(props);
|
|
4285
|
+
let cacheEntry = this._cache[key];
|
|
4286
|
+
if (!cacheEntry) {
|
|
4287
|
+
const resource = this.device.createShader({
|
|
4288
|
+
...props,
|
|
4289
|
+
id: props.id ? `${props.id}-cached` : void 0
|
|
4290
|
+
});
|
|
4291
|
+
this._cache[key] = cacheEntry = { resource, useCount: 1 };
|
|
4292
|
+
if (this.device.props.debugFactories) {
|
|
4293
|
+
log.log(3, `${this}: Created new shader ${resource.id}`)();
|
|
4294
|
+
}
|
|
4295
|
+
} else {
|
|
4296
|
+
cacheEntry.useCount++;
|
|
4297
|
+
if (this.device.props.debugFactories) {
|
|
4298
|
+
log.log(
|
|
4299
|
+
3,
|
|
4300
|
+
`${this}: Reusing shader ${cacheEntry.resource.id} count=${cacheEntry.useCount}`
|
|
4301
|
+
)();
|
|
4302
|
+
}
|
|
4303
|
+
}
|
|
4304
|
+
return cacheEntry.resource;
|
|
4305
|
+
}
|
|
4306
|
+
/** Releases a previously-requested {@link Shader}, destroying it if no users remain. */
|
|
4307
|
+
release(shader) {
|
|
4308
|
+
if (!this.device.props._cacheShaders) {
|
|
4309
|
+
shader.destroy();
|
|
4310
|
+
return;
|
|
4311
|
+
}
|
|
4312
|
+
const key = this._hashShader(shader);
|
|
4313
|
+
const cacheEntry = this._cache[key];
|
|
4314
|
+
if (cacheEntry) {
|
|
4315
|
+
cacheEntry.useCount--;
|
|
4316
|
+
if (cacheEntry.useCount === 0) {
|
|
4317
|
+
if (this.device.props._destroyShaders) {
|
|
4318
|
+
delete this._cache[key];
|
|
4319
|
+
cacheEntry.resource.destroy();
|
|
4320
|
+
if (this.device.props.debugFactories) {
|
|
4321
|
+
log.log(3, `${this}: Releasing shader ${shader.id}, destroyed`)();
|
|
4322
|
+
}
|
|
4323
|
+
}
|
|
4324
|
+
} else if (cacheEntry.useCount < 0) {
|
|
4325
|
+
throw new Error(`ShaderFactory: Shader ${shader.id} released too many times`);
|
|
4326
|
+
} else if (this.device.props.debugFactories) {
|
|
4327
|
+
log.log(3, `${this}: Releasing shader ${shader.id} count=${cacheEntry.useCount}`)();
|
|
4328
|
+
}
|
|
4329
|
+
}
|
|
4330
|
+
}
|
|
4331
|
+
// PRIVATE
|
|
4332
|
+
_hashShader(value) {
|
|
4333
|
+
return `${value.stage}:${value.source}`;
|
|
4334
|
+
}
|
|
4335
|
+
};
|
|
4336
|
+
var ShaderFactory = _ShaderFactory;
|
|
4337
|
+
__publicField(ShaderFactory, "defaultProps", { ...Shader.defaultProps });
|
|
4338
|
+
|
|
4339
|
+
// ../core/src/adapter-utils/bind-groups.ts
|
|
4340
|
+
function getShaderLayoutBinding(shaderLayout, bindingName, options) {
|
|
4341
|
+
const bindingLayout = shaderLayout.bindings.find(
|
|
4342
|
+
(binding) => binding.name === bindingName || `${binding.name.toLocaleLowerCase()}uniforms` === bindingName.toLocaleLowerCase()
|
|
4343
|
+
);
|
|
4344
|
+
if (!bindingLayout && !options?.ignoreWarnings) {
|
|
4345
|
+
log.warn(`Binding ${bindingName} not set: Not found in shader layout.`)();
|
|
4346
|
+
}
|
|
4347
|
+
return bindingLayout || null;
|
|
4348
|
+
}
|
|
4349
|
+
function normalizeBindingsByGroup(shaderLayout, bindingsOrBindGroups) {
|
|
4350
|
+
if (!bindingsOrBindGroups) {
|
|
4351
|
+
return {};
|
|
4352
|
+
}
|
|
4353
|
+
if (areBindingsGrouped(bindingsOrBindGroups)) {
|
|
4354
|
+
const bindGroups2 = bindingsOrBindGroups;
|
|
4355
|
+
return Object.fromEntries(
|
|
4356
|
+
Object.entries(bindGroups2).map(([group, bindings]) => [Number(group), { ...bindings }])
|
|
4357
|
+
);
|
|
4358
|
+
}
|
|
4359
|
+
const bindGroups = {};
|
|
4360
|
+
for (const [bindingName, binding] of Object.entries(bindingsOrBindGroups)) {
|
|
4361
|
+
const bindingLayout = getShaderLayoutBinding(shaderLayout, bindingName);
|
|
4362
|
+
const group = bindingLayout?.group ?? 0;
|
|
4363
|
+
bindGroups[group] ||= {};
|
|
4364
|
+
bindGroups[group][bindingName] = binding;
|
|
4365
|
+
}
|
|
4366
|
+
return bindGroups;
|
|
4367
|
+
}
|
|
4368
|
+
function flattenBindingsByGroup(bindGroups) {
|
|
4369
|
+
const bindings = {};
|
|
4370
|
+
for (const groupBindings of Object.values(bindGroups)) {
|
|
4371
|
+
Object.assign(bindings, groupBindings);
|
|
4372
|
+
}
|
|
4373
|
+
return bindings;
|
|
4374
|
+
}
|
|
4375
|
+
function areBindingsGrouped(bindingsOrBindGroups) {
|
|
4376
|
+
const keys = Object.keys(bindingsOrBindGroups);
|
|
4377
|
+
return keys.length > 0 && keys.every((key) => /^\d+$/.test(key));
|
|
4378
|
+
}
|
|
4379
|
+
|
|
4380
|
+
// ../core/src/factories/bind-group-factory.ts
|
|
4381
|
+
var BindGroupFactory = class {
|
|
4382
|
+
device;
|
|
4383
|
+
_layoutCacheByPipeline = /* @__PURE__ */ new WeakMap();
|
|
4384
|
+
_bindGroupCacheByLayout = /* @__PURE__ */ new WeakMap();
|
|
4385
|
+
constructor(device) {
|
|
4386
|
+
this.device = device;
|
|
4387
|
+
}
|
|
4388
|
+
getBindGroups(pipeline, bindings, bindGroupCacheKeys) {
|
|
4389
|
+
if (this.device.type !== "webgpu" || pipeline.shaderLayout.bindings.length === 0) {
|
|
4390
|
+
return {};
|
|
4391
|
+
}
|
|
4392
|
+
const bindingsByGroup = normalizeBindingsByGroup(pipeline.shaderLayout, bindings);
|
|
4393
|
+
const resolvedBindGroups = {};
|
|
4394
|
+
for (const group of getBindGroupIndicesUpToMax(pipeline.shaderLayout.bindings)) {
|
|
4395
|
+
const groupBindings = bindingsByGroup[group];
|
|
4396
|
+
const bindGroupLayout = this._getBindGroupLayout(pipeline, group);
|
|
4397
|
+
if (!groupBindings || Object.keys(groupBindings).length === 0) {
|
|
4398
|
+
if (!hasBindingsInGroup(pipeline.shaderLayout.bindings, group)) {
|
|
4399
|
+
resolvedBindGroups[group] = this._getEmptyBindGroup(
|
|
4400
|
+
bindGroupLayout,
|
|
4401
|
+
pipeline.shaderLayout,
|
|
4402
|
+
group
|
|
4403
|
+
);
|
|
4404
|
+
}
|
|
4405
|
+
continue;
|
|
4406
|
+
}
|
|
4407
|
+
const bindGroupCacheKey = bindGroupCacheKeys?.[group];
|
|
4408
|
+
if (bindGroupCacheKey) {
|
|
4409
|
+
const layoutCache = this._getLayoutBindGroupCache(bindGroupLayout);
|
|
4410
|
+
if (layoutCache.bindGroupsBySource.has(bindGroupCacheKey)) {
|
|
4411
|
+
resolvedBindGroups[group] = layoutCache.bindGroupsBySource.get(bindGroupCacheKey) || null;
|
|
4412
|
+
continue;
|
|
4413
|
+
}
|
|
4414
|
+
const bindGroup = this.device._createBindGroupWebGPU(
|
|
4415
|
+
bindGroupLayout,
|
|
4416
|
+
pipeline.shaderLayout,
|
|
4417
|
+
groupBindings,
|
|
4418
|
+
group
|
|
4419
|
+
);
|
|
4420
|
+
layoutCache.bindGroupsBySource.set(bindGroupCacheKey, bindGroup);
|
|
4421
|
+
resolvedBindGroups[group] = bindGroup;
|
|
4422
|
+
} else {
|
|
4423
|
+
resolvedBindGroups[group] = this.device._createBindGroupWebGPU(
|
|
4424
|
+
bindGroupLayout,
|
|
4425
|
+
pipeline.shaderLayout,
|
|
4426
|
+
groupBindings,
|
|
4427
|
+
group
|
|
4428
|
+
);
|
|
4429
|
+
}
|
|
4430
|
+
}
|
|
4431
|
+
return resolvedBindGroups;
|
|
4432
|
+
}
|
|
4433
|
+
_getBindGroupLayout(pipeline, group) {
|
|
4434
|
+
let layoutCache = this._layoutCacheByPipeline.get(pipeline);
|
|
4435
|
+
if (!layoutCache) {
|
|
4436
|
+
layoutCache = {};
|
|
4437
|
+
this._layoutCacheByPipeline.set(pipeline, layoutCache);
|
|
4438
|
+
}
|
|
4439
|
+
layoutCache[group] ||= this.device._createBindGroupLayoutWebGPU(pipeline, group);
|
|
4440
|
+
return layoutCache[group];
|
|
4441
|
+
}
|
|
4442
|
+
_getEmptyBindGroup(bindGroupLayout, shaderLayout, group) {
|
|
4443
|
+
const layoutCache = this._getLayoutBindGroupCache(bindGroupLayout);
|
|
4444
|
+
layoutCache.emptyBindGroup ||= this.device._createBindGroupWebGPU(bindGroupLayout, shaderLayout, {}, group) || null;
|
|
4445
|
+
return layoutCache.emptyBindGroup;
|
|
4446
|
+
}
|
|
4447
|
+
_getLayoutBindGroupCache(bindGroupLayout) {
|
|
4448
|
+
let layoutCache = this._bindGroupCacheByLayout.get(bindGroupLayout);
|
|
4449
|
+
if (!layoutCache) {
|
|
4450
|
+
layoutCache = { bindGroupsBySource: /* @__PURE__ */ new WeakMap() };
|
|
4451
|
+
this._bindGroupCacheByLayout.set(bindGroupLayout, layoutCache);
|
|
4452
|
+
}
|
|
4453
|
+
return layoutCache;
|
|
4454
|
+
}
|
|
4455
|
+
};
|
|
4456
|
+
function _getDefaultBindGroupFactory(device) {
|
|
4457
|
+
device._factories.bindGroupFactory ||= new BindGroupFactory(device);
|
|
4458
|
+
return device._factories.bindGroupFactory;
|
|
4459
|
+
}
|
|
4460
|
+
function getBindGroupIndicesUpToMax(bindings) {
|
|
4461
|
+
const maxGroup = bindings.reduce(
|
|
4462
|
+
(highestGroup, binding) => Math.max(highestGroup, binding.group),
|
|
4463
|
+
-1
|
|
4464
|
+
);
|
|
4465
|
+
return Array.from({ length: maxGroup + 1 }, (_, group) => group);
|
|
4466
|
+
}
|
|
4467
|
+
function hasBindingsInGroup(bindings, group) {
|
|
4468
|
+
return bindings.some((binding) => binding.group === group);
|
|
4469
|
+
}
|
|
4470
|
+
|
|
3911
4471
|
// ../core/src/adapter/resources/render-pass.ts
|
|
3912
4472
|
var _RenderPass = class extends Resource {
|
|
3913
4473
|
get [Symbol.toStringTag]() {
|
|
@@ -3946,28 +4506,6 @@ ${numberedLines}${positionIndicator}${message.type.toUpperCase()}: ${message.mes
|
|
|
3946
4506
|
endTimestampIndex: void 0
|
|
3947
4507
|
});
|
|
3948
4508
|
|
|
3949
|
-
// ../core/src/adapter/resources/compute-pipeline.ts
|
|
3950
|
-
var _ComputePipeline = class extends Resource {
|
|
3951
|
-
get [Symbol.toStringTag]() {
|
|
3952
|
-
return "ComputePipeline";
|
|
3953
|
-
}
|
|
3954
|
-
hash = "";
|
|
3955
|
-
/** The merged shader layout */
|
|
3956
|
-
shaderLayout;
|
|
3957
|
-
constructor(device, props) {
|
|
3958
|
-
super(device, props, _ComputePipeline.defaultProps);
|
|
3959
|
-
this.shaderLayout = props.shaderLayout;
|
|
3960
|
-
}
|
|
3961
|
-
};
|
|
3962
|
-
var ComputePipeline = _ComputePipeline;
|
|
3963
|
-
__publicField(ComputePipeline, "defaultProps", {
|
|
3964
|
-
...Resource.defaultProps,
|
|
3965
|
-
shader: void 0,
|
|
3966
|
-
entryPoint: void 0,
|
|
3967
|
-
constants: {},
|
|
3968
|
-
shaderLayout: void 0
|
|
3969
|
-
});
|
|
3970
|
-
|
|
3971
4509
|
// ../core/src/adapter/resources/compute-pass.ts
|
|
3972
4510
|
var _ComputePass = class extends Resource {
|
|
3973
4511
|
constructor(device, props) {
|
|
@@ -4079,7 +4617,7 @@ ${numberedLines}${positionIndicator}${message.type.toUpperCase()}: ${message.mes
|
|
|
4079
4617
|
...Resource.defaultProps
|
|
4080
4618
|
});
|
|
4081
4619
|
|
|
4082
|
-
// ../core/src/shadertypes/
|
|
4620
|
+
// ../core/src/shadertypes/shader-types/shader-type-decoder.ts
|
|
4083
4621
|
function getVariableShaderTypeInfo(format) {
|
|
4084
4622
|
const resolvedFormat = resolveVariableShaderTypeAlias(format);
|
|
4085
4623
|
const decoded = UNIFORM_FORMATS[resolvedFormat];
|
|
@@ -4106,12 +4644,33 @@ ${numberedLines}${positionIndicator}${message.type.toUpperCase()}: ${message.mes
|
|
|
4106
4644
|
signed
|
|
4107
4645
|
};
|
|
4108
4646
|
}
|
|
4647
|
+
var ShaderTypeDecoder = class {
|
|
4648
|
+
getVariableShaderTypeInfo(format) {
|
|
4649
|
+
return getVariableShaderTypeInfo(format);
|
|
4650
|
+
}
|
|
4651
|
+
getAttributeShaderTypeInfo(attributeType) {
|
|
4652
|
+
return getAttributeShaderTypeInfo(attributeType);
|
|
4653
|
+
}
|
|
4654
|
+
makeShaderAttributeType(primitiveType, components) {
|
|
4655
|
+
return makeShaderAttributeType(primitiveType, components);
|
|
4656
|
+
}
|
|
4657
|
+
resolveAttributeShaderTypeAlias(alias) {
|
|
4658
|
+
return resolveAttributeShaderTypeAlias(alias);
|
|
4659
|
+
}
|
|
4660
|
+
resolveVariableShaderTypeAlias(alias) {
|
|
4661
|
+
return resolveVariableShaderTypeAlias(alias);
|
|
4662
|
+
}
|
|
4663
|
+
};
|
|
4664
|
+
function makeShaderAttributeType(primitiveType, components) {
|
|
4665
|
+
return components === 1 ? primitiveType : `vec${components}<${primitiveType}>`;
|
|
4666
|
+
}
|
|
4109
4667
|
function resolveAttributeShaderTypeAlias(alias) {
|
|
4110
4668
|
return WGSL_ATTRIBUTE_TYPE_ALIAS_MAP[alias] || alias;
|
|
4111
4669
|
}
|
|
4112
4670
|
function resolveVariableShaderTypeAlias(alias) {
|
|
4113
4671
|
return WGSL_VARIABLE_TYPE_ALIAS_MAP[alias] || alias;
|
|
4114
4672
|
}
|
|
4673
|
+
var shaderTypeDecoder = new ShaderTypeDecoder();
|
|
4115
4674
|
var PRIMITIVE_TYPE_SIZES = {
|
|
4116
4675
|
f32: 4,
|
|
4117
4676
|
f16: 2,
|
|
@@ -4208,7 +4767,18 @@ ${numberedLines}${positionIndicator}${message.type.toUpperCase()}: ${message.mes
|
|
|
4208
4767
|
vec4h: "vec4<f16>"
|
|
4209
4768
|
};
|
|
4210
4769
|
var WGSL_VARIABLE_TYPE_ALIAS_MAP = {
|
|
4211
|
-
|
|
4770
|
+
vec2i: "vec2<i32>",
|
|
4771
|
+
vec3i: "vec3<i32>",
|
|
4772
|
+
vec4i: "vec4<i32>",
|
|
4773
|
+
vec2u: "vec2<u32>",
|
|
4774
|
+
vec3u: "vec3<u32>",
|
|
4775
|
+
vec4u: "vec4<u32>",
|
|
4776
|
+
vec2f: "vec2<f32>",
|
|
4777
|
+
vec3f: "vec3<f32>",
|
|
4778
|
+
vec4f: "vec4<f32>",
|
|
4779
|
+
vec2h: "vec2<f16>",
|
|
4780
|
+
vec3h: "vec3<f16>",
|
|
4781
|
+
vec4h: "vec4<f16>",
|
|
4212
4782
|
mat2x2f: "mat2x2<f32>",
|
|
4213
4783
|
mat2x3f: "mat2x3<f32>",
|
|
4214
4784
|
mat2x4f: "mat2x4<f32>",
|
|
@@ -4275,10 +4845,10 @@ ${numberedLines}${positionIndicator}${message.type.toUpperCase()}: ${message.mes
|
|
|
4275
4845
|
if (!shaderDeclaration) {
|
|
4276
4846
|
return null;
|
|
4277
4847
|
}
|
|
4278
|
-
const attributeTypeInfo = getAttributeShaderTypeInfo(shaderDeclaration.type);
|
|
4279
|
-
const defaultVertexFormat = getCompatibleVertexFormat(attributeTypeInfo);
|
|
4848
|
+
const attributeTypeInfo = shaderTypeDecoder.getAttributeShaderTypeInfo(shaderDeclaration.type);
|
|
4849
|
+
const defaultVertexFormat = vertexFormatDecoder.getCompatibleVertexFormat(attributeTypeInfo);
|
|
4280
4850
|
const vertexFormat = bufferMapping?.vertexFormat || defaultVertexFormat;
|
|
4281
|
-
const vertexFormatInfo = getVertexFormatInfo(vertexFormat);
|
|
4851
|
+
const vertexFormatInfo = vertexFormatDecoder.getVertexFormatInfo(vertexFormat);
|
|
4282
4852
|
return {
|
|
4283
4853
|
attributeName: bufferMapping?.attributeName || shaderDeclaration.name,
|
|
4284
4854
|
bufferName: bufferMapping?.bufferName || shaderDeclaration.name,
|
|
@@ -4346,7 +4916,7 @@ ${numberedLines}${positionIndicator}${message.type.toUpperCase()}: ${message.mes
|
|
|
4346
4916
|
let byteStride = bufferLayout.byteStride;
|
|
4347
4917
|
if (typeof bufferLayout.byteStride !== "number") {
|
|
4348
4918
|
for (const attributeMapping2 of bufferLayout.attributes || []) {
|
|
4349
|
-
const info = getVertexFormatInfo(attributeMapping2.format);
|
|
4919
|
+
const info = vertexFormatDecoder.getVertexFormatInfo(attributeMapping2.format);
|
|
4350
4920
|
byteStride += info.byteLength;
|
|
4351
4921
|
}
|
|
4352
4922
|
}
|
|
@@ -4466,6 +5036,36 @@ ${numberedLines}${positionIndicator}${message.type.toUpperCase()}: ${message.mes
|
|
|
4466
5036
|
}
|
|
4467
5037
|
});
|
|
4468
5038
|
|
|
5039
|
+
// ../core/src/shadertypes/data-types/decode-data-types.ts
|
|
5040
|
+
function alignTo(size, count) {
|
|
5041
|
+
switch (count) {
|
|
5042
|
+
case 1:
|
|
5043
|
+
return size;
|
|
5044
|
+
case 2:
|
|
5045
|
+
return size + size % 2;
|
|
5046
|
+
default:
|
|
5047
|
+
return size + (4 - size % 4) % 4;
|
|
5048
|
+
}
|
|
5049
|
+
}
|
|
5050
|
+
function getTypedArrayConstructor(type) {
|
|
5051
|
+
const [, , , , Constructor] = NORMALIZED_TYPE_MAP2[type];
|
|
5052
|
+
return Constructor;
|
|
5053
|
+
}
|
|
5054
|
+
var NORMALIZED_TYPE_MAP2 = {
|
|
5055
|
+
uint8: ["uint8", "u32", 1, false, Uint8Array],
|
|
5056
|
+
sint8: ["sint8", "i32", 1, false, Int8Array],
|
|
5057
|
+
unorm8: ["uint8", "f32", 1, true, Uint8Array],
|
|
5058
|
+
snorm8: ["sint8", "f32", 1, true, Int8Array],
|
|
5059
|
+
uint16: ["uint16", "u32", 2, false, Uint16Array],
|
|
5060
|
+
sint16: ["sint16", "i32", 2, false, Int16Array],
|
|
5061
|
+
unorm16: ["uint16", "u32", 2, true, Uint16Array],
|
|
5062
|
+
snorm16: ["sint16", "i32", 2, true, Int16Array],
|
|
5063
|
+
float16: ["float16", "f16", 2, false, Uint16Array],
|
|
5064
|
+
float32: ["float32", "f32", 4, false, Float32Array],
|
|
5065
|
+
uint32: ["uint32", "u32", 4, false, Uint32Array],
|
|
5066
|
+
sint32: ["sint32", "i32", 4, false, Int32Array]
|
|
5067
|
+
};
|
|
5068
|
+
|
|
4469
5069
|
// ../core/src/utils/array-utils-flat.ts
|
|
4470
5070
|
var arrayBuffer;
|
|
4471
5071
|
function getScratchArrayBuffer(byteLength) {
|
|
@@ -4479,19 +5079,32 @@ ${numberedLines}${positionIndicator}${message.type.toUpperCase()}: ${message.mes
|
|
|
4479
5079
|
return new Type(scratchArrayBuffer, 0, length);
|
|
4480
5080
|
}
|
|
4481
5081
|
|
|
5082
|
+
// ../core/src/utils/is-array.ts
|
|
5083
|
+
function isTypedArray(value) {
|
|
5084
|
+
return ArrayBuffer.isView(value) && !(value instanceof DataView);
|
|
5085
|
+
}
|
|
5086
|
+
function isNumberArray(value) {
|
|
5087
|
+
if (Array.isArray(value)) {
|
|
5088
|
+
return value.length === 0 || typeof value[0] === "number";
|
|
5089
|
+
}
|
|
5090
|
+
return isTypedArray(value);
|
|
5091
|
+
}
|
|
5092
|
+
|
|
4482
5093
|
// ../core/src/portable/uniform-buffer-layout.ts
|
|
4483
5094
|
var minBufferSize = 1024;
|
|
4484
5095
|
var UniformBufferLayout = class {
|
|
4485
5096
|
layout = {};
|
|
5097
|
+
uniformTypes;
|
|
4486
5098
|
/** number of bytes needed for buffer allocation */
|
|
4487
5099
|
byteLength;
|
|
4488
5100
|
/** Create a new UniformBufferLayout given a map of attributes. */
|
|
4489
|
-
constructor(uniformTypes
|
|
5101
|
+
constructor(uniformTypes) {
|
|
5102
|
+
this.uniformTypes = { ...uniformTypes };
|
|
4490
5103
|
let size = 0;
|
|
4491
|
-
for (const [key, uniformType] of Object.entries(uniformTypes)) {
|
|
4492
|
-
size = this._addToLayout(key, uniformType, size
|
|
5104
|
+
for (const [key, uniformType] of Object.entries(this.uniformTypes)) {
|
|
5105
|
+
size = this._addToLayout(key, uniformType, size);
|
|
4493
5106
|
}
|
|
4494
|
-
size
|
|
5107
|
+
size = alignTo(size, 4);
|
|
4495
5108
|
this.byteLength = Math.max(size * 4, minBufferSize);
|
|
4496
5109
|
}
|
|
4497
5110
|
/** Does this layout have a field with specified name */
|
|
@@ -4503,98 +5116,241 @@ ${numberedLines}${positionIndicator}${message.type.toUpperCase()}: ${message.mes
|
|
|
4503
5116
|
const layout = this.layout[name2];
|
|
4504
5117
|
return layout;
|
|
4505
5118
|
}
|
|
5119
|
+
/** Flatten nested uniform values into leaf-path values understood by UniformBlock. */
|
|
5120
|
+
getFlatUniformValues(uniformValues) {
|
|
5121
|
+
const flattenedUniformValues = {};
|
|
5122
|
+
for (const [name2, value] of Object.entries(uniformValues)) {
|
|
5123
|
+
const uniformType = this.uniformTypes[name2];
|
|
5124
|
+
if (uniformType) {
|
|
5125
|
+
this._flattenCompositeValue(flattenedUniformValues, name2, uniformType, value);
|
|
5126
|
+
} else if (this.layout[name2]) {
|
|
5127
|
+
flattenedUniformValues[name2] = value;
|
|
5128
|
+
}
|
|
5129
|
+
}
|
|
5130
|
+
return flattenedUniformValues;
|
|
5131
|
+
}
|
|
4506
5132
|
/** Get the data for the complete buffer */
|
|
4507
5133
|
getData(uniformValues) {
|
|
4508
5134
|
const buffer = getScratchArrayBuffer(this.byteLength);
|
|
5135
|
+
new Uint8Array(buffer, 0, this.byteLength).fill(0);
|
|
4509
5136
|
const typedArrays = {
|
|
4510
5137
|
i32: new Int32Array(buffer),
|
|
4511
5138
|
u32: new Uint32Array(buffer),
|
|
4512
5139
|
f32: new Float32Array(buffer),
|
|
4513
5140
|
f16: new Uint16Array(buffer)
|
|
4514
5141
|
};
|
|
4515
|
-
|
|
4516
|
-
|
|
5142
|
+
const flattenedUniformValues = this.getFlatUniformValues(uniformValues);
|
|
5143
|
+
for (const [name2, value] of Object.entries(flattenedUniformValues)) {
|
|
5144
|
+
this._writeLeafValue(typedArrays, name2, value);
|
|
4517
5145
|
}
|
|
4518
5146
|
return new Uint8Array(buffer, 0, this.byteLength);
|
|
4519
5147
|
}
|
|
4520
5148
|
// Recursively add a uniform to the layout
|
|
4521
|
-
_addToLayout(name2, type, offset
|
|
5149
|
+
_addToLayout(name2, type, offset) {
|
|
4522
5150
|
if (typeof type === "string") {
|
|
4523
|
-
const info =
|
|
4524
|
-
const
|
|
4525
|
-
const alignedOffset = alignTo(offset, info.components);
|
|
5151
|
+
const info = getLeafLayoutInfo(type);
|
|
5152
|
+
const alignedOffset = alignTo(offset, info.alignment);
|
|
4526
5153
|
this.layout[name2] = {
|
|
4527
5154
|
offset: alignedOffset,
|
|
4528
|
-
|
|
4529
|
-
type: info.type
|
|
5155
|
+
...info
|
|
4530
5156
|
};
|
|
4531
|
-
return alignedOffset +
|
|
5157
|
+
return alignedOffset + info.size;
|
|
4532
5158
|
}
|
|
4533
5159
|
if (Array.isArray(type)) {
|
|
5160
|
+
if (Array.isArray(type[0])) {
|
|
5161
|
+
throw new Error(`Nested arrays are not supported for ${name2}`);
|
|
5162
|
+
}
|
|
4534
5163
|
const elementType = type[0];
|
|
4535
|
-
const length =
|
|
4536
|
-
|
|
5164
|
+
const length = type[1];
|
|
5165
|
+
const stride = alignTo(getTypeSize(elementType), 4);
|
|
5166
|
+
const arrayOffset = alignTo(offset, 4);
|
|
4537
5167
|
for (let i = 0; i < length; i++) {
|
|
4538
|
-
|
|
5168
|
+
this._addToLayout(`${name2}[${i}]`, elementType, arrayOffset + i * stride);
|
|
4539
5169
|
}
|
|
4540
|
-
return arrayOffset;
|
|
5170
|
+
return arrayOffset + stride * length;
|
|
4541
5171
|
}
|
|
4542
|
-
if (
|
|
5172
|
+
if (isCompositeShaderTypeStruct(type)) {
|
|
4543
5173
|
let structOffset = alignTo(offset, 4);
|
|
4544
5174
|
for (const [memberName, memberType] of Object.entries(type)) {
|
|
4545
5175
|
structOffset = this._addToLayout(`${name2}.${memberName}`, memberType, structOffset);
|
|
4546
5176
|
}
|
|
4547
|
-
return structOffset;
|
|
5177
|
+
return alignTo(structOffset, 4);
|
|
4548
5178
|
}
|
|
4549
5179
|
throw new Error(`Unsupported CompositeShaderType for ${name2}`);
|
|
4550
5180
|
}
|
|
4551
|
-
|
|
4552
|
-
if (
|
|
4553
|
-
|
|
5181
|
+
_flattenCompositeValue(flattenedUniformValues, baseName, uniformType, value) {
|
|
5182
|
+
if (value === void 0) {
|
|
5183
|
+
return;
|
|
5184
|
+
}
|
|
5185
|
+
if (typeof uniformType === "string" || this.layout[baseName]) {
|
|
5186
|
+
flattenedUniformValues[baseName] = value;
|
|
4554
5187
|
return;
|
|
4555
5188
|
}
|
|
4556
|
-
if (Array.isArray(
|
|
4557
|
-
|
|
4558
|
-
|
|
4559
|
-
|
|
4560
|
-
|
|
5189
|
+
if (Array.isArray(uniformType)) {
|
|
5190
|
+
const elementType = uniformType[0];
|
|
5191
|
+
const length = uniformType[1];
|
|
5192
|
+
if (Array.isArray(elementType)) {
|
|
5193
|
+
throw new Error(`Nested arrays are not supported for ${baseName}`);
|
|
5194
|
+
}
|
|
5195
|
+
if (typeof elementType === "string" && isNumberArray(value)) {
|
|
5196
|
+
this._flattenPackedArray(flattenedUniformValues, baseName, elementType, length, value);
|
|
5197
|
+
return;
|
|
5198
|
+
}
|
|
5199
|
+
if (!Array.isArray(value)) {
|
|
5200
|
+
log.warn(`Unsupported uniform array value for ${baseName}:`, value)();
|
|
5201
|
+
return;
|
|
5202
|
+
}
|
|
5203
|
+
for (let index = 0; index < Math.min(value.length, length); index++) {
|
|
5204
|
+
const elementValue = value[index];
|
|
5205
|
+
if (elementValue === void 0) {
|
|
5206
|
+
continue;
|
|
5207
|
+
}
|
|
5208
|
+
this._flattenCompositeValue(
|
|
5209
|
+
flattenedUniformValues,
|
|
5210
|
+
`${baseName}[${index}]`,
|
|
5211
|
+
elementType,
|
|
5212
|
+
elementValue
|
|
5213
|
+
);
|
|
4561
5214
|
}
|
|
4562
5215
|
return;
|
|
4563
5216
|
}
|
|
4564
|
-
if (
|
|
5217
|
+
if (isCompositeShaderTypeStruct(uniformType) && isCompositeUniformObject(value)) {
|
|
4565
5218
|
for (const [key, subValue] of Object.entries(value)) {
|
|
5219
|
+
if (subValue === void 0) {
|
|
5220
|
+
continue;
|
|
5221
|
+
}
|
|
4566
5222
|
const nestedName = `${baseName}.${key}`;
|
|
4567
|
-
this.
|
|
5223
|
+
this._flattenCompositeValue(flattenedUniformValues, nestedName, uniformType[key], subValue);
|
|
4568
5224
|
}
|
|
4569
5225
|
return;
|
|
4570
5226
|
}
|
|
4571
5227
|
log.warn(`Unsupported uniform value for ${baseName}:`, value)();
|
|
4572
5228
|
}
|
|
4573
|
-
|
|
5229
|
+
_flattenPackedArray(flattenedUniformValues, baseName, elementType, length, value) {
|
|
5230
|
+
const numericValue = value;
|
|
5231
|
+
const elementLayout = getLeafLayoutInfo(elementType);
|
|
5232
|
+
const packedElementLength = elementLayout.components;
|
|
5233
|
+
for (let index = 0; index < length; index++) {
|
|
5234
|
+
const start = index * packedElementLength;
|
|
5235
|
+
if (start >= numericValue.length) {
|
|
5236
|
+
break;
|
|
5237
|
+
}
|
|
5238
|
+
if (packedElementLength === 1) {
|
|
5239
|
+
flattenedUniformValues[`${baseName}[${index}]`] = Number(numericValue[start]);
|
|
5240
|
+
} else {
|
|
5241
|
+
flattenedUniformValues[`${baseName}[${index}]`] = sliceNumericArray(
|
|
5242
|
+
value,
|
|
5243
|
+
start,
|
|
5244
|
+
start + packedElementLength
|
|
5245
|
+
);
|
|
5246
|
+
}
|
|
5247
|
+
}
|
|
5248
|
+
}
|
|
5249
|
+
_writeLeafValue(typedArrays, name2, value) {
|
|
4574
5250
|
const layout = this.layout[name2];
|
|
4575
5251
|
if (!layout) {
|
|
4576
5252
|
log.warn(`Uniform ${name2} not found in layout`)();
|
|
4577
5253
|
return;
|
|
4578
5254
|
}
|
|
4579
|
-
const { type,
|
|
5255
|
+
const { type, components, columns, rows, offset } = layout;
|
|
4580
5256
|
const array = typedArrays[type];
|
|
4581
|
-
if (
|
|
5257
|
+
if (components === 1) {
|
|
4582
5258
|
array[offset] = Number(value);
|
|
4583
|
-
|
|
4584
|
-
|
|
5259
|
+
return;
|
|
5260
|
+
}
|
|
5261
|
+
const sourceValue = value;
|
|
5262
|
+
if (columns === 1) {
|
|
5263
|
+
for (let componentIndex = 0; componentIndex < components; componentIndex++) {
|
|
5264
|
+
array[offset + componentIndex] = Number(sourceValue[componentIndex] ?? 0);
|
|
5265
|
+
}
|
|
5266
|
+
return;
|
|
5267
|
+
}
|
|
5268
|
+
let sourceIndex = 0;
|
|
5269
|
+
for (let columnIndex = 0; columnIndex < columns; columnIndex++) {
|
|
5270
|
+
const columnOffset = offset + columnIndex * 4;
|
|
5271
|
+
for (let rowIndex = 0; rowIndex < rows; rowIndex++) {
|
|
5272
|
+
array[columnOffset + rowIndex] = Number(sourceValue[sourceIndex++] ?? 0);
|
|
5273
|
+
}
|
|
4585
5274
|
}
|
|
4586
5275
|
}
|
|
4587
5276
|
};
|
|
4588
|
-
|
|
4589
|
-
|
|
4590
|
-
|
|
4591
|
-
|
|
5277
|
+
function getTypeSize(type) {
|
|
5278
|
+
if (typeof type === "string") {
|
|
5279
|
+
return getLeafLayoutInfo(type).size;
|
|
5280
|
+
}
|
|
5281
|
+
if (Array.isArray(type)) {
|
|
5282
|
+
const elementType = type[0];
|
|
5283
|
+
const length = type[1];
|
|
5284
|
+
if (Array.isArray(elementType)) {
|
|
5285
|
+
throw new Error("Nested arrays are not supported");
|
|
5286
|
+
}
|
|
5287
|
+
return alignTo(getTypeSize(elementType), 4) * length;
|
|
5288
|
+
}
|
|
5289
|
+
let size = 0;
|
|
5290
|
+
for (const memberType of Object.values(type)) {
|
|
5291
|
+
const compositeMemberType = memberType;
|
|
5292
|
+
size = alignTo(size, getTypeAlignment(compositeMemberType));
|
|
5293
|
+
size += getTypeSize(compositeMemberType);
|
|
5294
|
+
}
|
|
5295
|
+
return alignTo(size, 4);
|
|
4592
5296
|
}
|
|
4593
|
-
function
|
|
4594
|
-
if (
|
|
4595
|
-
return
|
|
5297
|
+
function getTypeAlignment(type) {
|
|
5298
|
+
if (typeof type === "string") {
|
|
5299
|
+
return getLeafLayoutInfo(type).alignment;
|
|
4596
5300
|
}
|
|
4597
|
-
|
|
5301
|
+
if (Array.isArray(type)) {
|
|
5302
|
+
return 4;
|
|
5303
|
+
}
|
|
5304
|
+
return 4;
|
|
5305
|
+
}
|
|
5306
|
+
function getLeafLayoutInfo(type) {
|
|
5307
|
+
const resolvedType = resolveVariableShaderTypeAlias(type);
|
|
5308
|
+
const decodedType = getVariableShaderTypeInfo(resolvedType);
|
|
5309
|
+
const matrixMatch = /^mat(\d)x(\d)<.+>$/.exec(resolvedType);
|
|
5310
|
+
if (matrixMatch) {
|
|
5311
|
+
const columns = Number(matrixMatch[1]);
|
|
5312
|
+
const rows = Number(matrixMatch[2]);
|
|
5313
|
+
return {
|
|
5314
|
+
alignment: 4,
|
|
5315
|
+
size: columns * 4,
|
|
5316
|
+
components: columns * rows,
|
|
5317
|
+
columns,
|
|
5318
|
+
rows,
|
|
5319
|
+
shaderType: resolvedType,
|
|
5320
|
+
type: decodedType.type
|
|
5321
|
+
};
|
|
5322
|
+
}
|
|
5323
|
+
const vectorMatch = /^vec(\d)<.+>$/.exec(resolvedType);
|
|
5324
|
+
if (vectorMatch) {
|
|
5325
|
+
const components = Number(vectorMatch[1]);
|
|
5326
|
+
return {
|
|
5327
|
+
alignment: components === 2 ? 2 : 4,
|
|
5328
|
+
size: components === 3 ? 4 : components,
|
|
5329
|
+
components,
|
|
5330
|
+
columns: 1,
|
|
5331
|
+
rows: components,
|
|
5332
|
+
shaderType: resolvedType,
|
|
5333
|
+
type: decodedType.type
|
|
5334
|
+
};
|
|
5335
|
+
}
|
|
5336
|
+
return {
|
|
5337
|
+
alignment: 1,
|
|
5338
|
+
size: 1,
|
|
5339
|
+
components: 1,
|
|
5340
|
+
columns: 1,
|
|
5341
|
+
rows: 1,
|
|
5342
|
+
shaderType: resolvedType,
|
|
5343
|
+
type: decodedType.type
|
|
5344
|
+
};
|
|
5345
|
+
}
|
|
5346
|
+
function isCompositeShaderTypeStruct(value) {
|
|
5347
|
+
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
5348
|
+
}
|
|
5349
|
+
function isCompositeUniformObject(value) {
|
|
5350
|
+
return Boolean(value) && typeof value === "object" && !Array.isArray(value) && !ArrayBuffer.isView(value);
|
|
5351
|
+
}
|
|
5352
|
+
function sliceNumericArray(value, start, end) {
|
|
5353
|
+
return Array.prototype.slice.call(value, start, end);
|
|
4598
5354
|
}
|
|
4599
5355
|
|
|
4600
5356
|
// ../core/src/utils/array-equal.ts
|
|
@@ -4696,13 +5452,12 @@ ${numberedLines}${positionIndicator}${message.type.toUpperCase()}: ${message.mes
|
|
|
4696
5452
|
constructor(blocks) {
|
|
4697
5453
|
for (const [bufferName, block] of Object.entries(blocks)) {
|
|
4698
5454
|
const uniformBufferName = bufferName;
|
|
4699
|
-
const uniformBufferLayout = new UniformBufferLayout(
|
|
4700
|
-
block.uniformTypes ?? {},
|
|
4701
|
-
block.uniformSizes ?? {}
|
|
4702
|
-
);
|
|
5455
|
+
const uniformBufferLayout = new UniformBufferLayout(block.uniformTypes ?? {});
|
|
4703
5456
|
this.uniformBufferLayouts.set(uniformBufferName, uniformBufferLayout);
|
|
4704
5457
|
const uniformBlock = new UniformBlock({ name: bufferName });
|
|
4705
|
-
uniformBlock.setUniforms(
|
|
5458
|
+
uniformBlock.setUniforms(
|
|
5459
|
+
uniformBufferLayout.getFlatUniformValues(block.defaultUniforms || {})
|
|
5460
|
+
);
|
|
4706
5461
|
this.uniformBlocks.set(uniformBufferName, uniformBlock);
|
|
4707
5462
|
}
|
|
4708
5463
|
}
|
|
@@ -4718,7 +5473,12 @@ ${numberedLines}${positionIndicator}${message.type.toUpperCase()}: ${message.mes
|
|
|
4718
5473
|
*/
|
|
4719
5474
|
setUniforms(uniforms) {
|
|
4720
5475
|
for (const [blockName, uniformValues] of Object.entries(uniforms)) {
|
|
4721
|
-
|
|
5476
|
+
const uniformBufferName = blockName;
|
|
5477
|
+
const uniformBufferLayout = this.uniformBufferLayouts.get(uniformBufferName);
|
|
5478
|
+
const flattenedUniforms = uniformBufferLayout?.getFlatUniformValues(
|
|
5479
|
+
uniformValues || {}
|
|
5480
|
+
);
|
|
5481
|
+
this.uniformBlocks.get(uniformBufferName)?.setUniforms(flattenedUniforms || {});
|
|
4722
5482
|
}
|
|
4723
5483
|
this.updateUniformBuffers();
|
|
4724
5484
|
}
|
|
@@ -4794,7 +5554,7 @@ ${numberedLines}${positionIndicator}${message.type.toUpperCase()}: ${message.mes
|
|
|
4794
5554
|
}
|
|
4795
5555
|
};
|
|
4796
5556
|
|
|
4797
|
-
// ../core/src/shadertypes/
|
|
5557
|
+
// ../core/src/shadertypes/texture-types/texture-layout.ts
|
|
4798
5558
|
function getTextureImageView(arrayBuffer2, memoryLayout, format, image = 0) {
|
|
4799
5559
|
const formatInfo = textureFormatDecoder.getInfo(format);
|
|
4800
5560
|
const bytesPerComponent = formatInfo.bytesPerPixel / formatInfo.components;
|
|
@@ -4832,7 +5592,7 @@ ${numberedLines}${positionIndicator}${message.type.toUpperCase()}: ${message.mes
|
|
|
4832
5592
|
typedArray.set(subArray, offset);
|
|
4833
5593
|
}
|
|
4834
5594
|
|
|
4835
|
-
// ../core/src/shadertypes/
|
|
5595
|
+
// ../core/src/shadertypes/texture-types/pixel-utils.ts
|
|
4836
5596
|
function readPixel(pixelData, x, y, bitsPerChannel) {
|
|
4837
5597
|
if (x < 0 || x >= pixelData.width || y < 0 || y >= pixelData.height) {
|
|
4838
5598
|
throw new Error("Coordinates out of bounds.");
|