@luma.gl/core 9.3.0-alpha.9 → 9.3.1
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/adapter/device.d.ts +1 -1
- package/dist/adapter/device.d.ts.map +1 -1
- package/dist/adapter/device.js +3 -2
- package/dist/adapter/device.js.map +1 -1
- package/dist/adapter/luma.d.ts.map +1 -1
- package/dist/adapter/luma.js +2 -1
- package/dist/adapter/luma.js.map +1 -1
- package/dist/dist.dev.js +328 -173
- package/dist/dist.min.js +5 -5
- package/dist/factories/bind-group-factory.d.ts.map +1 -1
- package/dist/factories/bind-group-factory.js +14 -5
- package/dist/factories/bind-group-factory.js.map +1 -1
- package/dist/index.cjs +317 -173
- package/dist/index.cjs.map +4 -4
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/portable/shader-block-writer.d.ts +51 -0
- package/dist/portable/shader-block-writer.d.ts.map +1 -0
- package/dist/portable/shader-block-writer.js +185 -0
- package/dist/portable/shader-block-writer.js.map +1 -0
- package/dist/portable/uniform-store.d.ts +52 -20
- package/dist/portable/uniform-store.d.ts.map +1 -1
- package/dist/portable/uniform-store.js +71 -26
- package/dist/portable/uniform-store.js.map +1 -1
- package/dist/shadertypes/data-types/data-type-decoder.js +2 -2
- package/dist/shadertypes/data-types/data-type-decoder.js.map +1 -1
- package/dist/shadertypes/data-types/decode-data-types.js +2 -2
- package/dist/shadertypes/data-types/decode-data-types.js.map +1 -1
- package/dist/shadertypes/shader-types/shader-block-layout.d.ts +72 -0
- package/dist/shadertypes/shader-types/shader-block-layout.d.ts.map +1 -0
- package/dist/shadertypes/shader-types/shader-block-layout.js +209 -0
- package/dist/shadertypes/shader-types/shader-block-layout.js.map +1 -0
- package/dist/shadertypes/texture-types/texture-format-decoder.js +1 -1
- package/dist/shadertypes/texture-types/texture-format-decoder.js.map +1 -1
- package/dist/shadertypes/texture-types/texture-format-table.js +2 -2
- package/dist/shadertypes/texture-types/texture-format-table.js.map +1 -1
- package/dist/shadertypes/vertex-types/vertex-format-decoder.d.ts.map +1 -1
- package/dist/shadertypes/vertex-types/vertex-format-decoder.js +41 -3
- package/dist/shadertypes/vertex-types/vertex-format-decoder.js.map +1 -1
- package/dist/shadertypes/vertex-types/vertex-formats.d.ts +6 -6
- package/dist/shadertypes/vertex-types/vertex-formats.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/adapter/device.ts +4 -2
- package/src/adapter/luma.ts +1 -0
- package/src/factories/bind-group-factory.ts +23 -5
- package/src/index.ts +7 -1
- package/src/portable/shader-block-writer.ts +254 -0
- package/src/portable/uniform-store.ts +92 -37
- package/src/shadertypes/data-types/data-type-decoder.ts +2 -2
- package/src/shadertypes/data-types/decode-data-types.ts +2 -2
- package/src/shadertypes/shader-types/shader-block-layout.ts +340 -0
- package/src/shadertypes/shader-types/shader-types.ts +5 -5
- package/src/shadertypes/texture-types/texture-format-decoder.ts +1 -1
- package/src/shadertypes/texture-types/texture-format-table.ts +2 -2
- package/src/shadertypes/vertex-types/vertex-format-decoder.ts +47 -3
- package/src/shadertypes/vertex-types/vertex-formats.ts +18 -5
- package/dist/portable/uniform-buffer-layout.d.ts +0 -42
- package/dist/portable/uniform-buffer-layout.d.ts.map +0 -1
- package/dist/portable/uniform-buffer-layout.js +0 -274
- package/dist/portable/uniform-buffer-layout.js.map +0 -1
- package/src/portable/uniform-buffer-layout.ts +0 -384
package/dist/dist.dev.js
CHANGED
|
@@ -54,13 +54,13 @@ var __exports__ = (() => {
|
|
|
54
54
|
Resource: () => Resource,
|
|
55
55
|
Sampler: () => Sampler,
|
|
56
56
|
Shader: () => Shader,
|
|
57
|
+
ShaderBlockWriter: () => ShaderBlockWriter,
|
|
57
58
|
ShaderFactory: () => ShaderFactory,
|
|
58
59
|
SharedRenderPipeline: () => SharedRenderPipeline,
|
|
59
60
|
Texture: () => Texture,
|
|
60
61
|
TextureView: () => TextureView,
|
|
61
62
|
TransformFeedback: () => TransformFeedback,
|
|
62
63
|
UniformBlock: () => UniformBlock,
|
|
63
|
-
UniformBufferLayout: () => UniformBufferLayout,
|
|
64
64
|
UniformStore: () => UniformStore,
|
|
65
65
|
VertexArray: () => VertexArray,
|
|
66
66
|
_getDefaultBindGroupFactory: () => _getDefaultBindGroupFactory,
|
|
@@ -81,6 +81,7 @@ var __exports__ = (() => {
|
|
|
81
81
|
isExternalImage: () => isExternalImage,
|
|
82
82
|
log: () => log,
|
|
83
83
|
luma: () => luma,
|
|
84
|
+
makeShaderBlockLayout: () => makeShaderBlockLayout,
|
|
84
85
|
normalizeBindingsByGroup: () => normalizeBindingsByGroup,
|
|
85
86
|
readPixel: () => readPixel,
|
|
86
87
|
setTextureImageData: () => setTextureImageData,
|
|
@@ -1451,12 +1452,51 @@ var __exports__ = (() => {
|
|
|
1451
1452
|
}
|
|
1452
1453
|
return `${dataType}x${components}`;
|
|
1453
1454
|
case "snorm8":
|
|
1455
|
+
if (components === 1) {
|
|
1456
|
+
return "snorm8";
|
|
1457
|
+
}
|
|
1458
|
+
if (components === 3) {
|
|
1459
|
+
return "snorm8x3-webgl";
|
|
1460
|
+
}
|
|
1461
|
+
return `${dataType}x${components}`;
|
|
1454
1462
|
case "uint8":
|
|
1455
1463
|
case "sint8":
|
|
1464
|
+
if (components === 1 || components === 3) {
|
|
1465
|
+
throw new Error(`size: ${components}`);
|
|
1466
|
+
}
|
|
1467
|
+
return `${dataType}x${components}`;
|
|
1456
1468
|
case "uint16":
|
|
1469
|
+
if (components === 1) {
|
|
1470
|
+
return "uint16";
|
|
1471
|
+
}
|
|
1472
|
+
if (components === 3) {
|
|
1473
|
+
return "uint16x3-webgl";
|
|
1474
|
+
}
|
|
1475
|
+
return `${dataType}x${components}`;
|
|
1457
1476
|
case "sint16":
|
|
1477
|
+
if (components === 1) {
|
|
1478
|
+
return "sint16";
|
|
1479
|
+
}
|
|
1480
|
+
if (components === 3) {
|
|
1481
|
+
return "sint16x3-webgl";
|
|
1482
|
+
}
|
|
1483
|
+
return `${dataType}x${components}`;
|
|
1458
1484
|
case "unorm16":
|
|
1485
|
+
if (components === 1) {
|
|
1486
|
+
return "unorm16";
|
|
1487
|
+
}
|
|
1488
|
+
if (components === 3) {
|
|
1489
|
+
return "unorm16x3-webgl";
|
|
1490
|
+
}
|
|
1491
|
+
return `${dataType}x${components}`;
|
|
1459
1492
|
case "snorm16":
|
|
1493
|
+
if (components === 1) {
|
|
1494
|
+
return "snorm16";
|
|
1495
|
+
}
|
|
1496
|
+
if (components === 3) {
|
|
1497
|
+
return "snorm16x3-webgl";
|
|
1498
|
+
}
|
|
1499
|
+
return `${dataType}x${components}`;
|
|
1460
1500
|
case "float16":
|
|
1461
1501
|
if (components === 1 || components === 3) {
|
|
1462
1502
|
throw new Error(`size: ${components}`);
|
|
@@ -2159,7 +2199,7 @@ or create a device with the 'debug: true' prop.`;
|
|
|
2159
2199
|
throw new Error("_createBindGroupLayoutWebGPU() not implemented");
|
|
2160
2200
|
}
|
|
2161
2201
|
/** Internal WebGPU-only helper for creating a native bind group. */
|
|
2162
|
-
_createBindGroupWebGPU(_bindGroupLayout, _shaderLayout, _bindings, _group) {
|
|
2202
|
+
_createBindGroupWebGPU(_bindGroupLayout, _shaderLayout, _bindings, _group, _label) {
|
|
2163
2203
|
throw new Error("_createBindGroupWebGPU() not implemented");
|
|
2164
2204
|
}
|
|
2165
2205
|
/**
|
|
@@ -4373,12 +4413,14 @@ ${numberedLines}${positionIndicator}${message.type.toUpperCase()}: ${message.mes
|
|
|
4373
4413
|
for (const group of getBindGroupIndicesUpToMax(pipeline.shaderLayout.bindings)) {
|
|
4374
4414
|
const groupBindings = bindingsByGroup[group];
|
|
4375
4415
|
const bindGroupLayout = this._getBindGroupLayout(pipeline, group);
|
|
4416
|
+
const bindGroupLabel = getBindGroupLabel(pipeline, pipeline.shaderLayout, group);
|
|
4376
4417
|
if (!groupBindings || Object.keys(groupBindings).length === 0) {
|
|
4377
4418
|
if (!hasBindingsInGroup(pipeline.shaderLayout.bindings, group)) {
|
|
4378
4419
|
resolvedBindGroups[group] = this._getEmptyBindGroup(
|
|
4379
4420
|
bindGroupLayout,
|
|
4380
4421
|
pipeline.shaderLayout,
|
|
4381
|
-
group
|
|
4422
|
+
group,
|
|
4423
|
+
bindGroupLabel
|
|
4382
4424
|
);
|
|
4383
4425
|
}
|
|
4384
4426
|
continue;
|
|
@@ -4394,7 +4436,8 @@ ${numberedLines}${positionIndicator}${message.type.toUpperCase()}: ${message.mes
|
|
|
4394
4436
|
bindGroupLayout,
|
|
4395
4437
|
pipeline.shaderLayout,
|
|
4396
4438
|
groupBindings,
|
|
4397
|
-
group
|
|
4439
|
+
group,
|
|
4440
|
+
bindGroupLabel
|
|
4398
4441
|
);
|
|
4399
4442
|
layoutCache.bindGroupsBySource.set(bindGroupCacheKey, bindGroup);
|
|
4400
4443
|
resolvedBindGroups[group] = bindGroup;
|
|
@@ -4403,7 +4446,8 @@ ${numberedLines}${positionIndicator}${message.type.toUpperCase()}: ${message.mes
|
|
|
4403
4446
|
bindGroupLayout,
|
|
4404
4447
|
pipeline.shaderLayout,
|
|
4405
4448
|
groupBindings,
|
|
4406
|
-
group
|
|
4449
|
+
group,
|
|
4450
|
+
bindGroupLabel
|
|
4407
4451
|
);
|
|
4408
4452
|
}
|
|
4409
4453
|
}
|
|
@@ -4418,9 +4462,9 @@ ${numberedLines}${positionIndicator}${message.type.toUpperCase()}: ${message.mes
|
|
|
4418
4462
|
layoutCache[group] ||= this.device._createBindGroupLayoutWebGPU(pipeline, group);
|
|
4419
4463
|
return layoutCache[group];
|
|
4420
4464
|
}
|
|
4421
|
-
_getEmptyBindGroup(bindGroupLayout, shaderLayout, group) {
|
|
4465
|
+
_getEmptyBindGroup(bindGroupLayout, shaderLayout, group, label) {
|
|
4422
4466
|
const layoutCache = this._getLayoutBindGroupCache(bindGroupLayout);
|
|
4423
|
-
layoutCache.emptyBindGroup ||= this.device._createBindGroupWebGPU(bindGroupLayout, shaderLayout, {}, group) || null;
|
|
4467
|
+
layoutCache.emptyBindGroup ||= this.device._createBindGroupWebGPU(bindGroupLayout, shaderLayout, {}, group, label) || null;
|
|
4424
4468
|
return layoutCache.emptyBindGroup;
|
|
4425
4469
|
}
|
|
4426
4470
|
_getLayoutBindGroupCache(bindGroupLayout) {
|
|
@@ -4446,6 +4490,11 @@ ${numberedLines}${positionIndicator}${message.type.toUpperCase()}: ${message.mes
|
|
|
4446
4490
|
function hasBindingsInGroup(bindings, group) {
|
|
4447
4491
|
return bindings.some((binding) => binding.group === group);
|
|
4448
4492
|
}
|
|
4493
|
+
function getBindGroupLabel(pipeline, shaderLayout, group) {
|
|
4494
|
+
const bindingNames = shaderLayout.bindings.filter((binding) => binding.group === group).sort((left, right) => left.location - right.location).map((binding) => binding.name);
|
|
4495
|
+
const bindingSuffix = bindingNames.length > 0 ? bindingNames.join(",") : "empty";
|
|
4496
|
+
return `${pipeline.id}/group${group}[${bindingSuffix}]`;
|
|
4497
|
+
}
|
|
4449
4498
|
|
|
4450
4499
|
// src/adapter/resources/render-pass.ts
|
|
4451
4500
|
var _RenderPass = class extends Resource {
|
|
@@ -5045,6 +5094,170 @@ ${numberedLines}${positionIndicator}${message.type.toUpperCase()}: ${message.mes
|
|
|
5045
5094
|
sint32: ["sint32", "i32", 4, false, Int32Array]
|
|
5046
5095
|
};
|
|
5047
5096
|
|
|
5097
|
+
// src/shadertypes/shader-types/shader-block-layout.ts
|
|
5098
|
+
function makeShaderBlockLayout(uniformTypes, options = {}) {
|
|
5099
|
+
const copiedUniformTypes = { ...uniformTypes };
|
|
5100
|
+
const layout = options.layout ?? "std140";
|
|
5101
|
+
const fields = {};
|
|
5102
|
+
let size = 0;
|
|
5103
|
+
for (const [key, uniformType] of Object.entries(copiedUniformTypes)) {
|
|
5104
|
+
size = addToLayout(fields, key, uniformType, size, layout);
|
|
5105
|
+
}
|
|
5106
|
+
size = alignTo(size, getTypeAlignment(copiedUniformTypes, layout));
|
|
5107
|
+
return {
|
|
5108
|
+
layout,
|
|
5109
|
+
byteLength: size * 4,
|
|
5110
|
+
uniformTypes: copiedUniformTypes,
|
|
5111
|
+
fields
|
|
5112
|
+
};
|
|
5113
|
+
}
|
|
5114
|
+
function getLeafLayoutInfo(type, layout) {
|
|
5115
|
+
const resolvedType = resolveVariableShaderTypeAlias(type);
|
|
5116
|
+
const decodedType = getVariableShaderTypeInfo(resolvedType);
|
|
5117
|
+
const matrixMatch = /^mat(\d)x(\d)<.+>$/.exec(resolvedType);
|
|
5118
|
+
if (matrixMatch) {
|
|
5119
|
+
const columns = Number(matrixMatch[1]);
|
|
5120
|
+
const rows = Number(matrixMatch[2]);
|
|
5121
|
+
const columnInfo = getVectorLayoutInfo(
|
|
5122
|
+
rows,
|
|
5123
|
+
resolvedType,
|
|
5124
|
+
decodedType.type,
|
|
5125
|
+
layout
|
|
5126
|
+
);
|
|
5127
|
+
const columnStride = getMatrixColumnStride(columnInfo.size, columnInfo.alignment, layout);
|
|
5128
|
+
return {
|
|
5129
|
+
alignment: columnInfo.alignment,
|
|
5130
|
+
size: columns * columnStride,
|
|
5131
|
+
components: columns * rows,
|
|
5132
|
+
columns,
|
|
5133
|
+
rows,
|
|
5134
|
+
columnStride,
|
|
5135
|
+
shaderType: resolvedType,
|
|
5136
|
+
type: decodedType.type
|
|
5137
|
+
};
|
|
5138
|
+
}
|
|
5139
|
+
const vectorMatch = /^vec(\d)<.+>$/.exec(resolvedType);
|
|
5140
|
+
if (vectorMatch) {
|
|
5141
|
+
return getVectorLayoutInfo(
|
|
5142
|
+
Number(vectorMatch[1]),
|
|
5143
|
+
resolvedType,
|
|
5144
|
+
decodedType.type,
|
|
5145
|
+
layout
|
|
5146
|
+
);
|
|
5147
|
+
}
|
|
5148
|
+
return {
|
|
5149
|
+
alignment: 1,
|
|
5150
|
+
size: 1,
|
|
5151
|
+
components: 1,
|
|
5152
|
+
columns: 1,
|
|
5153
|
+
rows: 1,
|
|
5154
|
+
columnStride: 1,
|
|
5155
|
+
shaderType: resolvedType,
|
|
5156
|
+
type: decodedType.type
|
|
5157
|
+
};
|
|
5158
|
+
}
|
|
5159
|
+
function isCompositeShaderTypeStruct(value) {
|
|
5160
|
+
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
5161
|
+
}
|
|
5162
|
+
function addToLayout(fields, name2, type, offset, layout) {
|
|
5163
|
+
if (typeof type === "string") {
|
|
5164
|
+
const info = getLeafLayoutInfo(type, layout);
|
|
5165
|
+
const alignedOffset = alignTo(offset, info.alignment);
|
|
5166
|
+
fields[name2] = {
|
|
5167
|
+
offset: alignedOffset,
|
|
5168
|
+
...info
|
|
5169
|
+
};
|
|
5170
|
+
return alignedOffset + info.size;
|
|
5171
|
+
}
|
|
5172
|
+
if (Array.isArray(type)) {
|
|
5173
|
+
if (Array.isArray(type[0])) {
|
|
5174
|
+
throw new Error(`Nested arrays are not supported for ${name2}`);
|
|
5175
|
+
}
|
|
5176
|
+
const elementType = type[0];
|
|
5177
|
+
const length = type[1];
|
|
5178
|
+
const stride = getArrayStride(elementType, layout);
|
|
5179
|
+
const arrayOffset = alignTo(offset, getTypeAlignment(type, layout));
|
|
5180
|
+
for (let i = 0; i < length; i++) {
|
|
5181
|
+
addToLayout(fields, `${name2}[${i}]`, elementType, arrayOffset + i * stride, layout);
|
|
5182
|
+
}
|
|
5183
|
+
return arrayOffset + stride * length;
|
|
5184
|
+
}
|
|
5185
|
+
if (isCompositeShaderTypeStruct(type)) {
|
|
5186
|
+
const structAlignment = getTypeAlignment(type, layout);
|
|
5187
|
+
let structOffset = alignTo(offset, structAlignment);
|
|
5188
|
+
for (const [memberName, memberType] of Object.entries(type)) {
|
|
5189
|
+
structOffset = addToLayout(fields, `${name2}.${memberName}`, memberType, structOffset, layout);
|
|
5190
|
+
}
|
|
5191
|
+
return alignTo(structOffset, structAlignment);
|
|
5192
|
+
}
|
|
5193
|
+
throw new Error(`Unsupported CompositeShaderType for ${name2}`);
|
|
5194
|
+
}
|
|
5195
|
+
function getTypeSize(type, layout) {
|
|
5196
|
+
if (typeof type === "string") {
|
|
5197
|
+
return getLeafLayoutInfo(type, layout).size;
|
|
5198
|
+
}
|
|
5199
|
+
if (Array.isArray(type)) {
|
|
5200
|
+
const elementType = type[0];
|
|
5201
|
+
const length = type[1];
|
|
5202
|
+
if (Array.isArray(elementType)) {
|
|
5203
|
+
throw new Error("Nested arrays are not supported");
|
|
5204
|
+
}
|
|
5205
|
+
return getArrayStride(elementType, layout) * length;
|
|
5206
|
+
}
|
|
5207
|
+
let size = 0;
|
|
5208
|
+
for (const memberType of Object.values(type)) {
|
|
5209
|
+
const compositeMemberType = memberType;
|
|
5210
|
+
size = alignTo(size, getTypeAlignment(compositeMemberType, layout));
|
|
5211
|
+
size += getTypeSize(compositeMemberType, layout);
|
|
5212
|
+
}
|
|
5213
|
+
return alignTo(size, getTypeAlignment(type, layout));
|
|
5214
|
+
}
|
|
5215
|
+
function getTypeAlignment(type, layout) {
|
|
5216
|
+
if (typeof type === "string") {
|
|
5217
|
+
return getLeafLayoutInfo(type, layout).alignment;
|
|
5218
|
+
}
|
|
5219
|
+
if (Array.isArray(type)) {
|
|
5220
|
+
const elementType = type[0];
|
|
5221
|
+
const elementAlignment = getTypeAlignment(elementType, layout);
|
|
5222
|
+
return uses16ByteArrayAlignment(layout) ? Math.max(elementAlignment, 4) : elementAlignment;
|
|
5223
|
+
}
|
|
5224
|
+
let maxAlignment = 1;
|
|
5225
|
+
for (const memberType of Object.values(type)) {
|
|
5226
|
+
const memberAlignment = getTypeAlignment(memberType, layout);
|
|
5227
|
+
maxAlignment = Math.max(maxAlignment, memberAlignment);
|
|
5228
|
+
}
|
|
5229
|
+
return uses16ByteStructAlignment(layout) ? Math.max(maxAlignment, 4) : maxAlignment;
|
|
5230
|
+
}
|
|
5231
|
+
function getVectorLayoutInfo(components, shaderType, type, layout) {
|
|
5232
|
+
return {
|
|
5233
|
+
alignment: components === 2 ? 2 : 4,
|
|
5234
|
+
size: components === 3 ? 3 : components,
|
|
5235
|
+
components,
|
|
5236
|
+
columns: 1,
|
|
5237
|
+
rows: components,
|
|
5238
|
+
columnStride: components === 3 ? 3 : components,
|
|
5239
|
+
shaderType,
|
|
5240
|
+
type
|
|
5241
|
+
};
|
|
5242
|
+
}
|
|
5243
|
+
function getArrayStride(elementType, layout) {
|
|
5244
|
+
const elementSize = getTypeSize(elementType, layout);
|
|
5245
|
+
const elementAlignment = getTypeAlignment(elementType, layout);
|
|
5246
|
+
return getArrayLikeStride(elementSize, elementAlignment, layout);
|
|
5247
|
+
}
|
|
5248
|
+
function getArrayLikeStride(size, alignment, layout) {
|
|
5249
|
+
return alignTo(size, uses16ByteArrayAlignment(layout) ? 4 : alignment);
|
|
5250
|
+
}
|
|
5251
|
+
function getMatrixColumnStride(size, alignment, layout) {
|
|
5252
|
+
return layout === "std140" ? 4 : alignTo(size, alignment);
|
|
5253
|
+
}
|
|
5254
|
+
function uses16ByteArrayAlignment(layout) {
|
|
5255
|
+
return layout === "std140" || layout === "wgsl-uniform";
|
|
5256
|
+
}
|
|
5257
|
+
function uses16ByteStructAlignment(layout) {
|
|
5258
|
+
return layout === "std140" || layout === "wgsl-uniform";
|
|
5259
|
+
}
|
|
5260
|
+
|
|
5048
5261
|
// src/utils/array-utils-flat.ts
|
|
5049
5262
|
var arrayBuffer;
|
|
5050
5263
|
function getScratchArrayBuffer(byteLength) {
|
|
@@ -5069,49 +5282,56 @@ ${numberedLines}${positionIndicator}${message.type.toUpperCase()}: ${message.mes
|
|
|
5069
5282
|
return isTypedArray(value);
|
|
5070
5283
|
}
|
|
5071
5284
|
|
|
5072
|
-
// src/portable/
|
|
5073
|
-
var
|
|
5074
|
-
|
|
5075
|
-
layout
|
|
5076
|
-
|
|
5077
|
-
|
|
5078
|
-
|
|
5079
|
-
|
|
5080
|
-
|
|
5081
|
-
|
|
5082
|
-
|
|
5083
|
-
|
|
5084
|
-
|
|
5085
|
-
}
|
|
5086
|
-
size = alignTo(size, 4);
|
|
5087
|
-
this.byteLength = Math.max(size * 4, minBufferSize);
|
|
5088
|
-
}
|
|
5089
|
-
/** Does this layout have a field with specified name */
|
|
5285
|
+
// src/portable/shader-block-writer.ts
|
|
5286
|
+
var ShaderBlockWriter = class {
|
|
5287
|
+
/** Layout metadata used to flatten and serialize values. */
|
|
5288
|
+
layout;
|
|
5289
|
+
/**
|
|
5290
|
+
* Creates a writer for a precomputed shader-block layout.
|
|
5291
|
+
*/
|
|
5292
|
+
constructor(layout) {
|
|
5293
|
+
this.layout = layout;
|
|
5294
|
+
}
|
|
5295
|
+
/**
|
|
5296
|
+
* Returns `true` if the flattened layout contains the given field.
|
|
5297
|
+
*/
|
|
5090
5298
|
has(name2) {
|
|
5091
|
-
return Boolean(this.layout[name2]);
|
|
5299
|
+
return Boolean(this.layout.fields[name2]);
|
|
5092
5300
|
}
|
|
5093
|
-
/**
|
|
5301
|
+
/**
|
|
5302
|
+
* Returns offset and size metadata for a flattened field.
|
|
5303
|
+
*/
|
|
5094
5304
|
get(name2) {
|
|
5095
|
-
const
|
|
5096
|
-
return
|
|
5305
|
+
const entry = this.layout.fields[name2];
|
|
5306
|
+
return entry ? { offset: entry.offset, size: entry.size } : void 0;
|
|
5097
5307
|
}
|
|
5098
|
-
/**
|
|
5308
|
+
/**
|
|
5309
|
+
* Flattens nested composite values into leaf-path values understood by {@link UniformBlock}.
|
|
5310
|
+
*
|
|
5311
|
+
* Top-level values may be supplied either in nested object form matching the
|
|
5312
|
+
* declared composite shader types or as already-flattened leaf-path values.
|
|
5313
|
+
*/
|
|
5099
5314
|
getFlatUniformValues(uniformValues) {
|
|
5100
5315
|
const flattenedUniformValues = {};
|
|
5101
5316
|
for (const [name2, value] of Object.entries(uniformValues)) {
|
|
5102
|
-
const uniformType = this.uniformTypes[name2];
|
|
5317
|
+
const uniformType = this.layout.uniformTypes[name2];
|
|
5103
5318
|
if (uniformType) {
|
|
5104
5319
|
this._flattenCompositeValue(flattenedUniformValues, name2, uniformType, value);
|
|
5105
|
-
} else if (this.layout[name2]) {
|
|
5320
|
+
} else if (this.layout.fields[name2]) {
|
|
5106
5321
|
flattenedUniformValues[name2] = value;
|
|
5107
5322
|
}
|
|
5108
5323
|
}
|
|
5109
5324
|
return flattenedUniformValues;
|
|
5110
5325
|
}
|
|
5111
|
-
/**
|
|
5326
|
+
/**
|
|
5327
|
+
* Serializes the supplied values into buffer-backed binary data.
|
|
5328
|
+
*
|
|
5329
|
+
* The returned view length matches {@link ShaderBlockLayout.byteLength}, which
|
|
5330
|
+
* is the exact packed size of the block.
|
|
5331
|
+
*/
|
|
5112
5332
|
getData(uniformValues) {
|
|
5113
|
-
const buffer = getScratchArrayBuffer(this.byteLength);
|
|
5114
|
-
new Uint8Array(buffer, 0, this.byteLength).fill(0);
|
|
5333
|
+
const buffer = getScratchArrayBuffer(this.layout.byteLength);
|
|
5334
|
+
new Uint8Array(buffer, 0, this.layout.byteLength).fill(0);
|
|
5115
5335
|
const typedArrays = {
|
|
5116
5336
|
i32: new Int32Array(buffer),
|
|
5117
5337
|
u32: new Uint32Array(buffer),
|
|
@@ -5122,46 +5342,16 @@ ${numberedLines}${positionIndicator}${message.type.toUpperCase()}: ${message.mes
|
|
|
5122
5342
|
for (const [name2, value] of Object.entries(flattenedUniformValues)) {
|
|
5123
5343
|
this._writeLeafValue(typedArrays, name2, value);
|
|
5124
5344
|
}
|
|
5125
|
-
return new Uint8Array(buffer, 0, this.byteLength);
|
|
5126
|
-
}
|
|
5127
|
-
// Recursively add a uniform to the layout
|
|
5128
|
-
_addToLayout(name2, type, offset) {
|
|
5129
|
-
if (typeof type === "string") {
|
|
5130
|
-
const info = getLeafLayoutInfo(type);
|
|
5131
|
-
const alignedOffset = alignTo(offset, info.alignment);
|
|
5132
|
-
this.layout[name2] = {
|
|
5133
|
-
offset: alignedOffset,
|
|
5134
|
-
...info
|
|
5135
|
-
};
|
|
5136
|
-
return alignedOffset + info.size;
|
|
5137
|
-
}
|
|
5138
|
-
if (Array.isArray(type)) {
|
|
5139
|
-
if (Array.isArray(type[0])) {
|
|
5140
|
-
throw new Error(`Nested arrays are not supported for ${name2}`);
|
|
5141
|
-
}
|
|
5142
|
-
const elementType = type[0];
|
|
5143
|
-
const length = type[1];
|
|
5144
|
-
const stride = alignTo(getTypeSize(elementType), 4);
|
|
5145
|
-
const arrayOffset = alignTo(offset, 4);
|
|
5146
|
-
for (let i = 0; i < length; i++) {
|
|
5147
|
-
this._addToLayout(`${name2}[${i}]`, elementType, arrayOffset + i * stride);
|
|
5148
|
-
}
|
|
5149
|
-
return arrayOffset + stride * length;
|
|
5150
|
-
}
|
|
5151
|
-
if (isCompositeShaderTypeStruct(type)) {
|
|
5152
|
-
let structOffset = alignTo(offset, 4);
|
|
5153
|
-
for (const [memberName, memberType] of Object.entries(type)) {
|
|
5154
|
-
structOffset = this._addToLayout(`${name2}.${memberName}`, memberType, structOffset);
|
|
5155
|
-
}
|
|
5156
|
-
return alignTo(structOffset, 4);
|
|
5157
|
-
}
|
|
5158
|
-
throw new Error(`Unsupported CompositeShaderType for ${name2}`);
|
|
5345
|
+
return new Uint8Array(buffer, 0, this.layout.byteLength);
|
|
5159
5346
|
}
|
|
5347
|
+
/**
|
|
5348
|
+
* Recursively flattens nested values using the declared composite shader type.
|
|
5349
|
+
*/
|
|
5160
5350
|
_flattenCompositeValue(flattenedUniformValues, baseName, uniformType, value) {
|
|
5161
5351
|
if (value === void 0) {
|
|
5162
5352
|
return;
|
|
5163
5353
|
}
|
|
5164
|
-
if (typeof uniformType === "string" || this.layout[baseName]) {
|
|
5354
|
+
if (typeof uniformType === "string" || this.layout.fields[baseName]) {
|
|
5165
5355
|
flattenedUniformValues[baseName] = value;
|
|
5166
5356
|
return;
|
|
5167
5357
|
}
|
|
@@ -5205,9 +5395,12 @@ ${numberedLines}${positionIndicator}${message.type.toUpperCase()}: ${message.mes
|
|
|
5205
5395
|
}
|
|
5206
5396
|
log.warn(`Unsupported uniform value for ${baseName}:`, value)();
|
|
5207
5397
|
}
|
|
5398
|
+
/**
|
|
5399
|
+
* Expands tightly packed numeric arrays into per-element leaf fields.
|
|
5400
|
+
*/
|
|
5208
5401
|
_flattenPackedArray(flattenedUniformValues, baseName, elementType, length, value) {
|
|
5209
5402
|
const numericValue = value;
|
|
5210
|
-
const elementLayout = getLeafLayoutInfo(elementType);
|
|
5403
|
+
const elementLayout = getLeafLayoutInfo(elementType, this.layout.layout);
|
|
5211
5404
|
const packedElementLength = elementLayout.components;
|
|
5212
5405
|
for (let index = 0; index < length; index++) {
|
|
5213
5406
|
const start = index * packedElementLength;
|
|
@@ -5225,13 +5418,16 @@ ${numberedLines}${positionIndicator}${message.type.toUpperCase()}: ${message.mes
|
|
|
5225
5418
|
}
|
|
5226
5419
|
}
|
|
5227
5420
|
}
|
|
5421
|
+
/**
|
|
5422
|
+
* Writes one flattened leaf value into its typed-array view.
|
|
5423
|
+
*/
|
|
5228
5424
|
_writeLeafValue(typedArrays, name2, value) {
|
|
5229
|
-
const
|
|
5230
|
-
if (!
|
|
5425
|
+
const entry = this.layout.fields[name2];
|
|
5426
|
+
if (!entry) {
|
|
5231
5427
|
log.warn(`Uniform ${name2} not found in layout`)();
|
|
5232
5428
|
return;
|
|
5233
5429
|
}
|
|
5234
|
-
const { type, components, columns, rows, offset } =
|
|
5430
|
+
const { type, components, columns, rows, offset, columnStride } = entry;
|
|
5235
5431
|
const array = typedArrays[type];
|
|
5236
5432
|
if (components === 1) {
|
|
5237
5433
|
array[offset] = Number(value);
|
|
@@ -5246,85 +5442,13 @@ ${numberedLines}${positionIndicator}${message.type.toUpperCase()}: ${message.mes
|
|
|
5246
5442
|
}
|
|
5247
5443
|
let sourceIndex = 0;
|
|
5248
5444
|
for (let columnIndex = 0; columnIndex < columns; columnIndex++) {
|
|
5249
|
-
const columnOffset = offset + columnIndex *
|
|
5445
|
+
const columnOffset = offset + columnIndex * columnStride;
|
|
5250
5446
|
for (let rowIndex = 0; rowIndex < rows; rowIndex++) {
|
|
5251
5447
|
array[columnOffset + rowIndex] = Number(sourceValue[sourceIndex++] ?? 0);
|
|
5252
5448
|
}
|
|
5253
5449
|
}
|
|
5254
5450
|
}
|
|
5255
5451
|
};
|
|
5256
|
-
function getTypeSize(type) {
|
|
5257
|
-
if (typeof type === "string") {
|
|
5258
|
-
return getLeafLayoutInfo(type).size;
|
|
5259
|
-
}
|
|
5260
|
-
if (Array.isArray(type)) {
|
|
5261
|
-
const elementType = type[0];
|
|
5262
|
-
const length = type[1];
|
|
5263
|
-
if (Array.isArray(elementType)) {
|
|
5264
|
-
throw new Error("Nested arrays are not supported");
|
|
5265
|
-
}
|
|
5266
|
-
return alignTo(getTypeSize(elementType), 4) * length;
|
|
5267
|
-
}
|
|
5268
|
-
let size = 0;
|
|
5269
|
-
for (const memberType of Object.values(type)) {
|
|
5270
|
-
const compositeMemberType = memberType;
|
|
5271
|
-
size = alignTo(size, getTypeAlignment(compositeMemberType));
|
|
5272
|
-
size += getTypeSize(compositeMemberType);
|
|
5273
|
-
}
|
|
5274
|
-
return alignTo(size, 4);
|
|
5275
|
-
}
|
|
5276
|
-
function getTypeAlignment(type) {
|
|
5277
|
-
if (typeof type === "string") {
|
|
5278
|
-
return getLeafLayoutInfo(type).alignment;
|
|
5279
|
-
}
|
|
5280
|
-
if (Array.isArray(type)) {
|
|
5281
|
-
return 4;
|
|
5282
|
-
}
|
|
5283
|
-
return 4;
|
|
5284
|
-
}
|
|
5285
|
-
function getLeafLayoutInfo(type) {
|
|
5286
|
-
const resolvedType = resolveVariableShaderTypeAlias(type);
|
|
5287
|
-
const decodedType = getVariableShaderTypeInfo(resolvedType);
|
|
5288
|
-
const matrixMatch = /^mat(\d)x(\d)<.+>$/.exec(resolvedType);
|
|
5289
|
-
if (matrixMatch) {
|
|
5290
|
-
const columns = Number(matrixMatch[1]);
|
|
5291
|
-
const rows = Number(matrixMatch[2]);
|
|
5292
|
-
return {
|
|
5293
|
-
alignment: 4,
|
|
5294
|
-
size: columns * 4,
|
|
5295
|
-
components: columns * rows,
|
|
5296
|
-
columns,
|
|
5297
|
-
rows,
|
|
5298
|
-
shaderType: resolvedType,
|
|
5299
|
-
type: decodedType.type
|
|
5300
|
-
};
|
|
5301
|
-
}
|
|
5302
|
-
const vectorMatch = /^vec(\d)<.+>$/.exec(resolvedType);
|
|
5303
|
-
if (vectorMatch) {
|
|
5304
|
-
const components = Number(vectorMatch[1]);
|
|
5305
|
-
return {
|
|
5306
|
-
alignment: components === 2 ? 2 : 4,
|
|
5307
|
-
size: components === 3 ? 4 : components,
|
|
5308
|
-
components,
|
|
5309
|
-
columns: 1,
|
|
5310
|
-
rows: components,
|
|
5311
|
-
shaderType: resolvedType,
|
|
5312
|
-
type: decodedType.type
|
|
5313
|
-
};
|
|
5314
|
-
}
|
|
5315
|
-
return {
|
|
5316
|
-
alignment: 1,
|
|
5317
|
-
size: 1,
|
|
5318
|
-
components: 1,
|
|
5319
|
-
columns: 1,
|
|
5320
|
-
rows: 1,
|
|
5321
|
-
shaderType: resolvedType,
|
|
5322
|
-
type: decodedType.type
|
|
5323
|
-
};
|
|
5324
|
-
}
|
|
5325
|
-
function isCompositeShaderTypeStruct(value) {
|
|
5326
|
-
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
5327
|
-
}
|
|
5328
5452
|
function isCompositeUniformObject(value) {
|
|
5329
5453
|
return Boolean(value) && typeof value === "object" && !Array.isArray(value) && !ArrayBuffer.isView(value);
|
|
5330
5454
|
}
|
|
@@ -5417,26 +5541,33 @@ ${numberedLines}${positionIndicator}${message.type.toUpperCase()}: ${message.mes
|
|
|
5417
5541
|
};
|
|
5418
5542
|
|
|
5419
5543
|
// src/portable/uniform-store.ts
|
|
5544
|
+
var minUniformBufferSize = 1024;
|
|
5420
5545
|
var UniformStore = class {
|
|
5546
|
+
/** Device used to infer layout and allocate buffers. */
|
|
5547
|
+
device;
|
|
5421
5548
|
/** Stores the uniform values for each uniform block */
|
|
5422
5549
|
uniformBlocks = /* @__PURE__ */ new Map();
|
|
5423
|
-
/**
|
|
5424
|
-
|
|
5550
|
+
/** Flattened layout metadata for each block. */
|
|
5551
|
+
shaderBlockLayouts = /* @__PURE__ */ new Map();
|
|
5552
|
+
/** Serializers for block-backed uniform data. */
|
|
5553
|
+
shaderBlockWriters = /* @__PURE__ */ new Map();
|
|
5425
5554
|
/** Actual buffer for the blocks */
|
|
5426
5555
|
uniformBuffers = /* @__PURE__ */ new Map();
|
|
5427
5556
|
/**
|
|
5428
|
-
*
|
|
5429
|
-
* @param blocks
|
|
5557
|
+
* Creates a new {@link UniformStore} for the supplied device and block definitions.
|
|
5430
5558
|
*/
|
|
5431
|
-
constructor(blocks) {
|
|
5559
|
+
constructor(device, blocks) {
|
|
5560
|
+
this.device = device;
|
|
5432
5561
|
for (const [bufferName, block] of Object.entries(blocks)) {
|
|
5433
5562
|
const uniformBufferName = bufferName;
|
|
5434
|
-
const
|
|
5435
|
-
|
|
5563
|
+
const shaderBlockLayout = makeShaderBlockLayout(block.uniformTypes ?? {}, {
|
|
5564
|
+
layout: block.layout ?? getDefaultUniformBufferLayout(device)
|
|
5565
|
+
});
|
|
5566
|
+
const shaderBlockWriter = new ShaderBlockWriter(shaderBlockLayout);
|
|
5567
|
+
this.shaderBlockLayouts.set(uniformBufferName, shaderBlockLayout);
|
|
5568
|
+
this.shaderBlockWriters.set(uniformBufferName, shaderBlockWriter);
|
|
5436
5569
|
const uniformBlock = new UniformBlock({ name: bufferName });
|
|
5437
|
-
uniformBlock.setUniforms(
|
|
5438
|
-
uniformBufferLayout.getFlatUniformValues(block.defaultUniforms || {})
|
|
5439
|
-
);
|
|
5570
|
+
uniformBlock.setUniforms(shaderBlockWriter.getFlatUniformValues(block.defaultUniforms || {}));
|
|
5440
5571
|
this.uniformBlocks.set(uniformBufferName, uniformBlock);
|
|
5441
5572
|
}
|
|
5442
5573
|
}
|
|
@@ -5448,38 +5579,51 @@ ${numberedLines}${positionIndicator}${message.type.toUpperCase()}: ${message.mes
|
|
|
5448
5579
|
}
|
|
5449
5580
|
/**
|
|
5450
5581
|
* Set uniforms
|
|
5451
|
-
*
|
|
5582
|
+
*
|
|
5583
|
+
* Makes all group properties partial and eagerly propagates changes to any
|
|
5584
|
+
* managed GPU buffers.
|
|
5452
5585
|
*/
|
|
5453
5586
|
setUniforms(uniforms) {
|
|
5454
5587
|
for (const [blockName, uniformValues] of Object.entries(uniforms)) {
|
|
5455
5588
|
const uniformBufferName = blockName;
|
|
5456
|
-
const
|
|
5457
|
-
const flattenedUniforms =
|
|
5589
|
+
const shaderBlockWriter = this.shaderBlockWriters.get(uniformBufferName);
|
|
5590
|
+
const flattenedUniforms = shaderBlockWriter?.getFlatUniformValues(
|
|
5458
5591
|
uniformValues || {}
|
|
5459
5592
|
);
|
|
5460
5593
|
this.uniformBlocks.get(uniformBufferName)?.setUniforms(flattenedUniforms || {});
|
|
5461
5594
|
}
|
|
5462
5595
|
this.updateUniformBuffers();
|
|
5463
5596
|
}
|
|
5464
|
-
/**
|
|
5597
|
+
/**
|
|
5598
|
+
* Returns the allocation size for the named uniform buffer.
|
|
5599
|
+
*
|
|
5600
|
+
* This may exceed the packed layout size because minimum buffer-size policy is
|
|
5601
|
+
* applied at the store layer.
|
|
5602
|
+
*/
|
|
5465
5603
|
getUniformBufferByteLength(uniformBufferName) {
|
|
5466
|
-
|
|
5604
|
+
const packedByteLength = this.shaderBlockLayouts.get(uniformBufferName)?.byteLength || 0;
|
|
5605
|
+
return Math.max(packedByteLength, minUniformBufferSize);
|
|
5467
5606
|
}
|
|
5468
|
-
/**
|
|
5607
|
+
/**
|
|
5608
|
+
* Returns packed binary data that can be uploaded to the named uniform buffer.
|
|
5609
|
+
*
|
|
5610
|
+
* The returned view length matches the packed block size and is not padded to
|
|
5611
|
+
* the store's minimum allocation size.
|
|
5612
|
+
*/
|
|
5469
5613
|
getUniformBufferData(uniformBufferName) {
|
|
5470
5614
|
const uniformValues = this.uniformBlocks.get(uniformBufferName)?.getAllUniforms() || {};
|
|
5471
|
-
|
|
5615
|
+
const shaderBlockWriter = this.shaderBlockWriters.get(uniformBufferName);
|
|
5616
|
+
return shaderBlockWriter?.getData(uniformValues) || new Uint8Array(0);
|
|
5472
5617
|
}
|
|
5473
5618
|
/**
|
|
5474
|
-
* Creates an unmanaged uniform buffer
|
|
5475
|
-
* The new buffer is initialized with current / supplied values
|
|
5619
|
+
* Creates an unmanaged uniform buffer initialized with the current or supplied values.
|
|
5476
5620
|
*/
|
|
5477
|
-
createUniformBuffer(
|
|
5621
|
+
createUniformBuffer(uniformBufferName, uniforms) {
|
|
5478
5622
|
if (uniforms) {
|
|
5479
5623
|
this.setUniforms(uniforms);
|
|
5480
5624
|
}
|
|
5481
5625
|
const byteLength = this.getUniformBufferByteLength(uniformBufferName);
|
|
5482
|
-
const uniformBuffer = device.createBuffer({
|
|
5626
|
+
const uniformBuffer = this.device.createBuffer({
|
|
5483
5627
|
usage: Buffer2.UNIFORM | Buffer2.COPY_DST,
|
|
5484
5628
|
byteLength
|
|
5485
5629
|
});
|
|
@@ -5487,11 +5631,11 @@ ${numberedLines}${positionIndicator}${message.type.toUpperCase()}: ${message.mes
|
|
|
5487
5631
|
uniformBuffer.write(uniformBufferData);
|
|
5488
5632
|
return uniformBuffer;
|
|
5489
5633
|
}
|
|
5490
|
-
/**
|
|
5491
|
-
getManagedUniformBuffer(
|
|
5634
|
+
/** Returns the managed uniform buffer for the named block. */
|
|
5635
|
+
getManagedUniformBuffer(uniformBufferName) {
|
|
5492
5636
|
if (!this.uniformBuffers.get(uniformBufferName)) {
|
|
5493
5637
|
const byteLength = this.getUniformBufferByteLength(uniformBufferName);
|
|
5494
|
-
const uniformBuffer = device.createBuffer({
|
|
5638
|
+
const uniformBuffer = this.device.createBuffer({
|
|
5495
5639
|
usage: Buffer2.UNIFORM | Buffer2.COPY_DST,
|
|
5496
5640
|
byteLength
|
|
5497
5641
|
});
|
|
@@ -5499,7 +5643,11 @@ ${numberedLines}${positionIndicator}${message.type.toUpperCase()}: ${message.mes
|
|
|
5499
5643
|
}
|
|
5500
5644
|
return this.uniformBuffers.get(uniformBufferName);
|
|
5501
5645
|
}
|
|
5502
|
-
/**
|
|
5646
|
+
/**
|
|
5647
|
+
* Updates every managed uniform buffer whose source uniforms have changed.
|
|
5648
|
+
*
|
|
5649
|
+
* @returns The first redraw reason encountered, or `false` if nothing changed.
|
|
5650
|
+
*/
|
|
5503
5651
|
updateUniformBuffers() {
|
|
5504
5652
|
let reason = false;
|
|
5505
5653
|
for (const uniformBufferName of this.uniformBlocks.keys()) {
|
|
@@ -5511,7 +5659,11 @@ ${numberedLines}${positionIndicator}${message.type.toUpperCase()}: ${message.mes
|
|
|
5511
5659
|
}
|
|
5512
5660
|
return reason;
|
|
5513
5661
|
}
|
|
5514
|
-
/**
|
|
5662
|
+
/**
|
|
5663
|
+
* Updates one managed uniform buffer if its corresponding block is dirty.
|
|
5664
|
+
*
|
|
5665
|
+
* @returns The redraw reason for the update, or `false` if no write occurred.
|
|
5666
|
+
*/
|
|
5515
5667
|
updateUniformBuffer(uniformBufferName) {
|
|
5516
5668
|
const uniformBlock = this.uniformBlocks.get(uniformBufferName);
|
|
5517
5669
|
let uniformBuffer = this.uniformBuffers.get(uniformBufferName);
|
|
@@ -5532,6 +5684,9 @@ ${numberedLines}${positionIndicator}${message.type.toUpperCase()}: ${message.mes
|
|
|
5532
5684
|
return reason;
|
|
5533
5685
|
}
|
|
5534
5686
|
};
|
|
5687
|
+
function getDefaultUniformBufferLayout(device) {
|
|
5688
|
+
return device.type === "webgpu" ? "wgsl-uniform" : "std140";
|
|
5689
|
+
}
|
|
5535
5690
|
|
|
5536
5691
|
// src/shadertypes/texture-types/texture-layout.ts
|
|
5537
5692
|
function getTextureImageView(arrayBuffer2, memoryLayout, format, image = 0) {
|