@luma.gl/engine 9.0.0-alpha.30 → 9.0.0-alpha.32

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.
Files changed (48) hide show
  1. package/dist/dist.dev.js +1028 -685
  2. package/dist/geometries/truncated-cone-geometry.d.ts +0 -2
  3. package/dist/geometries/truncated-cone-geometry.d.ts.map +1 -1
  4. package/dist/geometries/truncated-cone-geometry.js +0 -11
  5. package/dist/geometries/truncated-cone-geometry.js.map +1 -1
  6. package/dist/geometry/geometry.d.ts +6 -7
  7. package/dist/geometry/geometry.d.ts.map +1 -1
  8. package/dist/geometry/geometry.js.map +1 -1
  9. package/dist/geometry/gpu-geometry.d.ts +45 -0
  10. package/dist/geometry/gpu-geometry.d.ts.map +1 -0
  11. package/dist/geometry/gpu-geometry.js +123 -0
  12. package/dist/geometry/gpu-geometry.js.map +1 -0
  13. package/dist/geometry/gpu-table.d.ts +1 -0
  14. package/dist/geometry/gpu-table.d.ts.map +1 -0
  15. package/dist/geometry/gpu-table.js +2 -0
  16. package/dist/geometry/gpu-table.js.map +1 -0
  17. package/dist/index.cjs +311 -209
  18. package/dist/lib/pipeline-factory.d.ts +11 -44
  19. package/dist/lib/pipeline-factory.d.ts.map +1 -1
  20. package/dist/lib/pipeline-factory.js +28 -119
  21. package/dist/lib/pipeline-factory.js.map +1 -1
  22. package/dist/model/model-shaders.d.ts +35 -0
  23. package/dist/model/model-shaders.d.ts.map +1 -0
  24. package/dist/model/model-shaders.js +38 -0
  25. package/dist/model/model-shaders.js.map +1 -0
  26. package/dist/model/model-utils.d.ts +1 -1
  27. package/dist/model/model-utils.d.ts.map +1 -1
  28. package/dist/model/model-utils.js +1 -1
  29. package/dist/model/model-utils.js.map +1 -1
  30. package/dist/model/model.d.ts +110 -23
  31. package/dist/model/model.d.ts.map +1 -1
  32. package/dist/model/model.js +144 -91
  33. package/dist/model/model.js.map +1 -1
  34. package/dist.min.js +71 -71
  35. package/package.json +6 -6
  36. package/src/geometries/truncated-cone-geometry.ts +0 -10
  37. package/src/geometry/geometry.ts +7 -7
  38. package/src/geometry/gpu-geometry.ts +159 -0
  39. package/src/geometry/gpu-table.ts +41 -0
  40. package/src/lib/pipeline-factory.ts +43 -163
  41. package/src/model/model-shaders.ts +76 -0
  42. package/src/model/model-utils.ts +2 -2
  43. package/src/model/model.ts +271 -125
  44. package/dist/geometry/primitive-utils.d.ts +0 -1
  45. package/dist/geometry/primitive-utils.d.ts.map +0 -1
  46. package/dist/geometry/primitive-utils.js +0 -2
  47. package/dist/geometry/primitive-utils.js.map +0 -1
  48. package/src/geometry/primitive-utils.ts +0 -30
package/dist/dist.dev.js CHANGED
@@ -12,8 +12,8 @@ var __exports__ = (() => {
12
12
  var __hasOwnProp = Object.prototype.hasOwnProperty;
13
13
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
14
14
  var __export = (target, all) => {
15
- for (var name in all)
16
- __defProp(target, name, { get: all[name], enumerable: true });
15
+ for (var name2 in all)
16
+ __defProp(target, name2, { get: all[name2], enumerable: true });
17
17
  };
18
18
  var __copyProps = (to, from, except, desc) => {
19
19
  if (from && typeof from === "object" || typeof from === "function") {
@@ -423,7 +423,7 @@ var __exports__ = (() => {
423
423
  for (const key of propNames) {
424
424
  const value = object[key];
425
425
  if (typeof value === "function") {
426
- if (!predefined.find((name) => key === name)) {
426
+ if (!predefined.find((name2) => key === name2)) {
427
427
  object[key] = value.bind(obj);
428
428
  }
429
429
  }
@@ -812,7 +812,7 @@ var __exports__ = (() => {
812
812
 
813
813
  // ../../node_modules/@probe.gl/stats/dist/lib/stat.js
814
814
  var Stat = class {
815
- constructor(name, type) {
815
+ constructor(name2, type) {
816
816
  this.name = void 0;
817
817
  this.type = void 0;
818
818
  this.sampleSize = 1;
@@ -827,7 +827,7 @@ var __exports__ = (() => {
827
827
  this._samples = 0;
828
828
  this._startTime = 0;
829
829
  this._timerPending = false;
830
- this.name = name;
830
+ this.name = name2;
831
831
  this.type = type;
832
832
  this.reset();
833
833
  }
@@ -932,10 +932,10 @@ var __exports__ = (() => {
932
932
  this._initializeStats(options.stats);
933
933
  Object.seal(this);
934
934
  }
935
- get(name) {
935
+ get(name2) {
936
936
  let type = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : "count";
937
937
  return this._getOrCreate({
938
- name,
938
+ name: name2,
939
939
  type
940
940
  });
941
941
  }
@@ -971,17 +971,17 @@ var __exports__ = (() => {
971
971
  }
972
972
  _getOrCreate(stat) {
973
973
  const {
974
- name,
974
+ name: name2,
975
975
  type
976
976
  } = stat;
977
- let result = this.stats[name];
977
+ let result = this.stats[name2];
978
978
  if (!result) {
979
979
  if (stat instanceof Stat) {
980
980
  result = stat;
981
981
  } else {
982
- result = new Stat(name, type);
982
+ result = new Stat(name2, type);
983
983
  }
984
- this.stats[name] = result;
984
+ this.stats[name2] = result;
985
985
  }
986
986
  return result;
987
987
  }
@@ -990,16 +990,16 @@ var __exports__ = (() => {
990
990
  // ../core/src/lib/utils/stats-manager.ts
991
991
  var StatsManager = class {
992
992
  stats = /* @__PURE__ */ new Map();
993
- getStats(name) {
994
- return this.get(name);
993
+ getStats(name2) {
994
+ return this.get(name2);
995
995
  }
996
- get(name) {
997
- if (!this.stats.has(name)) {
998
- this.stats.set(name, new Stats({
999
- id: name
996
+ get(name2) {
997
+ if (!this.stats.has(name2)) {
998
+ this.stats.set(name2, new Stats({
999
+ id: name2
1000
1000
  }));
1001
1001
  }
1002
- return this.stats.get(name);
1002
+ return this.stats.get(name2);
1003
1003
  }
1004
1004
  };
1005
1005
  var lumaStats = new StatsManager();
@@ -1048,11 +1048,6 @@ var __exports__ = (() => {
1048
1048
  }
1049
1049
 
1050
1050
  // ../core/src/adapter/resources/resource.ts
1051
- var DEFAULT_RESOURCE_PROPS = {
1052
- id: "undefined",
1053
- handle: void 0,
1054
- userData: void 0
1055
- };
1056
1051
  var Resource = class {
1057
1052
  /** props.id, for debugging. */
1058
1053
  userData = {};
@@ -1137,34 +1132,38 @@ var __exports__ = (() => {
1137
1132
  /** Called by .destroy() to track object destruction. Subclass must call if overriding destroy() */
1138
1133
  removeStats() {
1139
1134
  const stats = this._device.statsManager.getStats("Resource Counts");
1140
- const name = this[Symbol.toStringTag];
1141
- stats.get(`${name}s Active`).decrementCount();
1135
+ const name2 = this[Symbol.toStringTag];
1136
+ stats.get(`${name2}s Active`).decrementCount();
1142
1137
  }
1143
1138
  /** Called by subclass to track memory allocations */
1144
- trackAllocatedMemory(bytes, name = this[Symbol.toStringTag]) {
1139
+ trackAllocatedMemory(bytes, name2 = this[Symbol.toStringTag]) {
1145
1140
  const stats = this._device.statsManager.getStats("Resource Counts");
1146
1141
  stats.get("GPU Memory").addCount(bytes);
1147
- stats.get(`${name} Memory`).addCount(bytes);
1142
+ stats.get(`${name2} Memory`).addCount(bytes);
1148
1143
  this.allocatedBytes = bytes;
1149
1144
  }
1150
1145
  /** Called by subclass to track memory deallocations */
1151
- trackDeallocatedMemory(name = this[Symbol.toStringTag]) {
1146
+ trackDeallocatedMemory(name2 = this[Symbol.toStringTag]) {
1152
1147
  const stats = this._device.statsManager.getStats("Resource Counts");
1153
1148
  stats.get("GPU Memory").subtractCount(this.allocatedBytes);
1154
- stats.get(`${name} Memory`).subtractCount(this.allocatedBytes);
1149
+ stats.get(`${name2} Memory`).subtractCount(this.allocatedBytes);
1155
1150
  this.allocatedBytes = 0;
1156
1151
  }
1157
1152
  /** Called by resource constructor to track object creation */
1158
1153
  addStats() {
1159
1154
  const stats = this._device.statsManager.getStats("Resource Counts");
1160
- const name = this[Symbol.toStringTag];
1155
+ const name2 = this[Symbol.toStringTag];
1161
1156
  stats.get("Resources Created").incrementCount();
1162
- stats.get(`${name}s Created`).incrementCount();
1163
- stats.get(`${name}s Active`).incrementCount();
1157
+ stats.get(`${name2}s Created`).incrementCount();
1158
+ stats.get(`${name2}s Active`).incrementCount();
1164
1159
  }
1165
1160
  };
1166
1161
  /** Default properties for resource */
1167
- __publicField(Resource, "defaultProps", DEFAULT_RESOURCE_PROPS);
1162
+ __publicField(Resource, "defaultProps", {
1163
+ id: "undefined",
1164
+ handle: void 0,
1165
+ userData: void 0
1166
+ });
1168
1167
  function selectivelyMerge(props, defaultProps) {
1169
1168
  const mergedProps = {
1170
1169
  ...defaultProps
@@ -1178,20 +1177,12 @@ var __exports__ = (() => {
1178
1177
  }
1179
1178
 
1180
1179
  // ../core/src/adapter/resources/buffer.ts
1181
- var DEFAULT_BUFFER_PROPS = {
1182
- ...DEFAULT_RESOURCE_PROPS,
1183
- usage: 0,
1184
- // Buffer.COPY_DST | Buffer.COPY_SRC
1185
- byteLength: 0,
1186
- byteOffset: 0,
1187
- data: null,
1188
- indexType: "uint16",
1189
- mappedAtCreation: false
1190
- };
1191
1180
  var _Buffer = class extends Resource {
1192
1181
  get [Symbol.toStringTag]() {
1193
1182
  return "Buffer";
1194
1183
  }
1184
+ /** The usage with which this buffer was created */
1185
+ /** For index buffers, whether indices are 16 or 32 bit */
1195
1186
  /** Length of buffer in bytes */
1196
1187
  constructor(device, props) {
1197
1188
  const deducedProps = {
@@ -1204,7 +1195,9 @@ var __exports__ = (() => {
1204
1195
  deducedProps.indexType = "uint16";
1205
1196
  }
1206
1197
  }
1207
- super(device, deducedProps, DEFAULT_BUFFER_PROPS);
1198
+ super(device, deducedProps, _Buffer.defaultProps);
1199
+ this.usage = props.usage || 0;
1200
+ this.indexType = deducedProps.indexType;
1208
1201
  }
1209
1202
  write(data, byteOffset) {
1210
1203
  throw new Error("not implemented");
@@ -1262,6 +1255,16 @@ var __exports__ = (() => {
1262
1255
  // abstract unmap(): void;
1263
1256
  };
1264
1257
  var Buffer2 = _Buffer;
1258
+ __publicField(Buffer2, "defaultProps", {
1259
+ ...Resource.defaultProps,
1260
+ usage: 0,
1261
+ // Buffer.COPY_DST | Buffer.COPY_SRC
1262
+ byteLength: 0,
1263
+ byteOffset: 0,
1264
+ data: null,
1265
+ indexType: "uint16",
1266
+ mappedAtCreation: false
1267
+ });
1265
1268
  // Usage Flags
1266
1269
  __publicField(Buffer2, "MAP_READ", 1);
1267
1270
  __publicField(Buffer2, "MAP_WRITE", 2);
@@ -1311,8 +1314,14 @@ var __exports__ = (() => {
1311
1314
  };
1312
1315
  this.id = this.props.id || uid(this[Symbol.toStringTag].toLowerCase());
1313
1316
  }
1317
+ /** id of this device, primarily for debugging */
1318
+ /** stats */
1314
1319
  statsManager = lumaStats;
1320
+ /** A copy of the device props */
1321
+ /** Available for the application to store data on the device */
1315
1322
  userData = {};
1323
+ /** Used by other luma.gl modules to store data on the device */
1324
+ _lumaData = {};
1316
1325
  // Capabilities
1317
1326
  /** Information about the device (vendor, versions etc) */
1318
1327
  /** Optional capability discovery */
@@ -1717,25 +1726,7 @@ var __exports__ = (() => {
1717
1726
  }
1718
1727
 
1719
1728
  // ../core/src/adapter/resources/texture.ts
1720
- var DEFAULT_TEXTURE_PROPS = {
1721
- ...DEFAULT_RESOURCE_PROPS,
1722
- data: null,
1723
- dimension: "2d",
1724
- format: "rgba8unorm",
1725
- width: void 0,
1726
- height: void 0,
1727
- depth: 1,
1728
- mipmaps: true,
1729
- sampler: {},
1730
- // type: undefined,
1731
- compressed: false,
1732
- // mipLevels: 1,
1733
- usage: 0,
1734
- mipLevels: void 0,
1735
- samples: void 0,
1736
- type: void 0
1737
- };
1738
- var Texture = class extends Resource {
1729
+ var _Texture = class extends Resource {
1739
1730
  get [Symbol.toStringTag]() {
1740
1731
  return "Texture";
1741
1732
  }
@@ -1745,7 +1736,7 @@ var __exports__ = (() => {
1745
1736
  /** height in pixels of this texture */
1746
1737
  /** depth of this texture */
1747
1738
  /** Default sampler for this texture */
1748
- constructor(device, props, defaultProps = DEFAULT_TEXTURE_PROPS) {
1739
+ constructor(device, props, defaultProps = _Texture.defaultProps) {
1749
1740
  super(device, props, defaultProps);
1750
1741
  this.dimension = this.props.dimension;
1751
1742
  this.format = this.props.format;
@@ -1754,6 +1745,26 @@ var __exports__ = (() => {
1754
1745
  this.depth = this.props.depth;
1755
1746
  }
1756
1747
  };
1748
+ var Texture = _Texture;
1749
+ __publicField(Texture, "defaultProps", {
1750
+ ...Resource.defaultProps,
1751
+ data: null,
1752
+ dimension: "2d",
1753
+ format: "rgba8unorm",
1754
+ width: void 0,
1755
+ height: void 0,
1756
+ depth: 1,
1757
+ mipmaps: true,
1758
+ sampler: {},
1759
+ // type: undefined,
1760
+ compressed: false,
1761
+ // mipLevels: 1,
1762
+ usage: 0,
1763
+ // usage: GPUTextureUsage.COPY_DST
1764
+ mipLevels: void 0,
1765
+ samples: void 0,
1766
+ type: void 0
1767
+ });
1757
1768
  __publicField(Texture, "COPY_SRC", 1);
1758
1769
  __publicField(Texture, "COPY_DST", 2);
1759
1770
  __publicField(Texture, "TEXTURE_BINDING", 4);
@@ -1761,28 +1772,38 @@ var __exports__ = (() => {
1761
1772
  __publicField(Texture, "RENDER_ATTACHMENT", 16);
1762
1773
 
1763
1774
  // ../core/src/adapter/resources/shader.ts
1764
- var DEFAULT_SHADER_PROPS = {
1765
- ...DEFAULT_RESOURCE_PROPS,
1766
- stage: "vertex",
1767
- source: "",
1768
- sourceMap: null,
1769
- language: "glsl",
1770
- shaderType: 0
1771
- };
1772
- var Shader = class extends Resource {
1775
+ var _Shader = class extends Resource {
1773
1776
  get [Symbol.toStringTag]() {
1774
1777
  return "Shader";
1775
1778
  }
1776
1779
  constructor(device, props) {
1777
- super(device, props, DEFAULT_SHADER_PROPS);
1780
+ super(device, props, _Shader.defaultProps);
1778
1781
  this.stage = this.props.stage;
1779
1782
  this.source = this.props.source;
1780
1783
  }
1781
1784
  };
1785
+ var Shader = _Shader;
1786
+ __publicField(Shader, "defaultProps", {
1787
+ ...Resource.defaultProps,
1788
+ stage: "vertex",
1789
+ source: "",
1790
+ sourceMap: null,
1791
+ language: "glsl",
1792
+ shaderType: 0
1793
+ });
1782
1794
 
1783
1795
  // ../core/src/adapter/resources/sampler.ts
1784
- var DEFAULT_SAMPLER_PROPS = {
1785
- ...DEFAULT_RESOURCE_PROPS,
1796
+ var _Sampler = class extends Resource {
1797
+ get [Symbol.toStringTag]() {
1798
+ return "Sampler";
1799
+ }
1800
+ constructor(device, props) {
1801
+ super(device, props, _Sampler.defaultProps);
1802
+ }
1803
+ };
1804
+ var Sampler = _Sampler;
1805
+ __publicField(Sampler, "defaultProps", {
1806
+ ...Resource.defaultProps,
1786
1807
  type: "color-sampler",
1787
1808
  addressModeU: "clamp-to-edge",
1788
1809
  addressModeV: "clamp-to-edge",
@@ -1795,27 +1816,10 @@ var __exports__ = (() => {
1795
1816
  // Per WebGPU spec
1796
1817
  compare: "less-equal",
1797
1818
  maxAnisotropy: 1
1798
- };
1799
- var Sampler = class extends Resource {
1800
- get [Symbol.toStringTag]() {
1801
- return "Sampler";
1802
- }
1803
- constructor(device, props) {
1804
- super(device, props, DEFAULT_SAMPLER_PROPS);
1805
- }
1806
- };
1819
+ });
1807
1820
 
1808
1821
  // ../core/src/adapter/resources/framebuffer.ts
1809
- var DEFAULT_FRAMEBUFFER_PROPS = {
1810
- ...DEFAULT_RESOURCE_PROPS,
1811
- width: 1,
1812
- height: 1,
1813
- colorAttachments: [],
1814
- // ['rgba8unorm-unsized'],
1815
- depthStencilAttachment: null
1816
- // 'depth24plus-stencil8'
1817
- };
1818
- var Framebuffer = class extends Resource {
1822
+ var _Framebuffer = class extends Resource {
1819
1823
  get [Symbol.toStringTag]() {
1820
1824
  return "Framebuffer";
1821
1825
  }
@@ -1826,7 +1830,7 @@ var __exports__ = (() => {
1826
1830
  /** Depth-stencil attachment, if provided */
1827
1831
  depthStencilAttachment = null;
1828
1832
  constructor(device, props = {}) {
1829
- super(device, props, DEFAULT_FRAMEBUFFER_PROPS);
1833
+ super(device, props, _Framebuffer.defaultProps);
1830
1834
  this.width = this.props.width;
1831
1835
  this.height = this.props.height;
1832
1836
  }
@@ -1992,10 +1996,40 @@ var __exports__ = (() => {
1992
1996
  }
1993
1997
  */
1994
1998
  };
1999
+ var Framebuffer = _Framebuffer;
2000
+ __publicField(Framebuffer, "defaultProps", {
2001
+ ...Resource.defaultProps,
2002
+ width: 1,
2003
+ height: 1,
2004
+ colorAttachments: [],
2005
+ // ['rgba8unorm-unsized'],
2006
+ depthStencilAttachment: null
2007
+ // 'depth24plus-stencil8'
2008
+ });
1995
2009
 
1996
2010
  // ../core/src/adapter/resources/render-pipeline.ts
1997
- var DEFAULT_RENDER_PIPELINE_PROPS = {
1998
- ...DEFAULT_RESOURCE_PROPS,
2011
+ var _RenderPipeline = class extends Resource {
2012
+ get [Symbol.toStringTag]() {
2013
+ return "RenderPipeline";
2014
+ }
2015
+ hash = "";
2016
+ constructor(device, props) {
2017
+ super(device, props, _RenderPipeline.defaultProps);
2018
+ }
2019
+ /** Set attributes (stored on pipeline and set before each call) */
2020
+ /** Set attributes (stored on pipeline and set before each call) */
2021
+ /** Set constant attributes (WebGL only) */
2022
+ /** Set bindings (stored on pipeline and set before each call) */
2023
+ /** Uniforms
2024
+ * @deprecated Only supported on WebGL devices.
2025
+ * @note textures, samplers and uniform buffers should be set via `setBindings()`, these are not considered uniforms.
2026
+ * @note In WebGL uniforms have a performance penalty, they are reset before each call to enable pipeline sharing.
2027
+ */
2028
+ /** Draw call */
2029
+ };
2030
+ var RenderPipeline = _RenderPipeline;
2031
+ __publicField(RenderPipeline, "defaultProps", {
2032
+ ...Resource.defaultProps,
1999
2033
  vs: null,
2000
2034
  vsEntryPoint: "",
2001
2035
  // main
@@ -2004,36 +2038,17 @@ var __exports__ = (() => {
2004
2038
  fsEntryPoint: "",
2005
2039
  // main
2006
2040
  fsConstants: {},
2007
- layout: null,
2008
- // {attributes: [], bindings: []},
2041
+ shaderLayout: null,
2042
+ bufferLayout: [],
2009
2043
  topology: "triangle-list",
2010
- // targets:
2011
2044
  parameters: {},
2012
- bufferMap: [],
2013
2045
  vertexCount: 0,
2014
2046
  instanceCount: 0,
2015
2047
  indices: null,
2016
2048
  attributes: {},
2017
2049
  bindings: {},
2018
2050
  uniforms: {}
2019
- };
2020
- var RenderPipeline = class extends Resource {
2021
- get [Symbol.toStringTag]() {
2022
- return "RenderPipeline";
2023
- }
2024
- hash = "";
2025
- constructor(device, props) {
2026
- super(device, props, DEFAULT_RENDER_PIPELINE_PROPS);
2027
- }
2028
- };
2029
- /** Set attributes (stored on pipeline and set before each call) */
2030
- /** Set attributes (stored on pipeline and set before each call) */
2031
- /** Set constant attributes (WebGL only) */
2032
- /** Set bindings (stored on pipeline and set before each call) */
2033
- /** Uniforms (only supported on WebGL devices. Reset before each call to enable pipeline sharing) */
2034
- /** Draw call */
2035
- /** Private "export" for Model class */
2036
- __publicField(RenderPipeline, "_DEFAULT_PROPS", DEFAULT_RENDER_PIPELINE_PROPS);
2051
+ });
2037
2052
 
2038
2053
  // ../core/src/adapter/resources/render-pass.ts
2039
2054
  var _RenderPass = class extends Resource {
@@ -2093,15 +2108,12 @@ var __exports__ = (() => {
2093
2108
  });
2094
2109
 
2095
2110
  // ../core/src/adapter/resources/command-encoder.ts
2096
- var DEFAULT_COMMAND_ENCODER_PROPS = {
2097
- ...DEFAULT_RESOURCE_PROPS
2098
- };
2099
- var CommandEncoder = class extends Resource {
2111
+ var _CommandEncoder = class extends Resource {
2100
2112
  get [Symbol.toStringTag]() {
2101
2113
  return "CommandEncoder";
2102
2114
  }
2103
- constructor(props) {
2104
- super(props, DEFAULT_COMMAND_ENCODER_PROPS);
2115
+ constructor(device, props) {
2116
+ super(device, props, _CommandEncoder.defaultProps);
2105
2117
  }
2106
2118
  // TODO - return the CommandBuffer?
2107
2119
  // beginRenderPass(GPURenderPassDescriptor descriptor): GPURenderPassEncoder;
@@ -2122,19 +2134,25 @@ var __exports__ = (() => {
2122
2134
  // destinationOffset?: number;
2123
2135
  // }): void;
2124
2136
  };
2137
+ var CommandEncoder = _CommandEncoder;
2138
+ __publicField(CommandEncoder, "defaultProps", {
2139
+ ...Resource.defaultProps,
2140
+ measureExecutionTime: void 0
2141
+ });
2125
2142
 
2126
2143
  // ../core/src/adapter/resources/command-buffer.ts
2127
- var DEFAULT_COMMAND_ENCODER_PROPS2 = {
2128
- ...DEFAULT_RESOURCE_PROPS
2129
- };
2130
- var CommandBuffer = class extends Resource {
2144
+ var _CommandBuffer = class extends Resource {
2131
2145
  get [Symbol.toStringTag]() {
2132
2146
  return "CommandBuffer";
2133
2147
  }
2134
2148
  constructor(props) {
2135
- super(props, DEFAULT_COMMAND_ENCODER_PROPS2);
2149
+ super(props, _CommandBuffer.defaultProps);
2136
2150
  }
2137
2151
  };
2152
+ var CommandBuffer = _CommandBuffer;
2153
+ __publicField(CommandBuffer, "defaultProps", {
2154
+ ...Resource.defaultProps
2155
+ });
2138
2156
 
2139
2157
  // ../core/src/lib/utils/assert.ts
2140
2158
  function assert2(condition, message2) {
@@ -2143,7 +2161,7 @@ var __exports__ = (() => {
2143
2161
  }
2144
2162
  }
2145
2163
 
2146
- // ../core/src/adapter/utils/decode-data-type.ts
2164
+ // ../core/src/adapter/type-utils/decode-data-type.ts
2147
2165
  function decodeVertexType(type) {
2148
2166
  const dataType = TYPE_MAP[type];
2149
2167
  const bytes = getDataTypeBytes(dataType);
@@ -2187,7 +2205,7 @@ var __exports__ = (() => {
2187
2205
  sint32: 4
2188
2206
  };
2189
2207
 
2190
- // ../core/src/adapter/utils/decode-vertex-format.ts
2208
+ // ../core/src/adapter/type-utils/decode-vertex-format.ts
2191
2209
  function decodeVertexFormat(format) {
2192
2210
  let webglOnly;
2193
2211
  if (format.endsWith("-webgl")) {
@@ -2212,7 +2230,7 @@ var __exports__ = (() => {
2212
2230
  return result;
2213
2231
  }
2214
2232
 
2215
- // ../core/src/adapter/utils/decode-texture-format.ts
2233
+ // ../core/src/adapter/type-utils/decode-texture-format.ts
2216
2234
  var REGEX = /^(rg?b?a?)([0-9]*)([a-z]*)(-srgb)?(-webgl|-unsized)?$/;
2217
2235
  function decodeTextureFormat(format) {
2218
2236
  const matches = REGEX.exec(format);
@@ -2318,6 +2336,68 @@ var __exports__ = (() => {
2318
2336
  };
2319
2337
  }
2320
2338
 
2339
+ // ../core/src/adapter/type-utils/decode-attribute-type.ts
2340
+ function decodeShaderAttributeType(attributeType) {
2341
+ const [dataType, components] = TYPE_INFO[attributeType];
2342
+ const integer = dataType === "i32" || dataType === "u32";
2343
+ const signed = dataType !== "u32";
2344
+ const byteLength = TYPE_SIZES2[dataType] * components;
2345
+ const defaultVertexFormat = getCompatibleVertexFormat(dataType, components);
2346
+ return {
2347
+ dataType,
2348
+ components,
2349
+ defaultVertexFormat,
2350
+ byteLength,
2351
+ integer,
2352
+ signed
2353
+ };
2354
+ }
2355
+ function getCompatibleVertexFormat(dataType, components) {
2356
+ let vertexType;
2357
+ switch (dataType) {
2358
+ case "f32":
2359
+ vertexType = "float32";
2360
+ break;
2361
+ case "i32":
2362
+ vertexType = "sint32";
2363
+ break;
2364
+ case "u32":
2365
+ vertexType = "uint32";
2366
+ break;
2367
+ case "f16":
2368
+ return components <= 2 ? "float16x2" : "float16x4";
2369
+ }
2370
+ if (components === 1) {
2371
+ return vertexType;
2372
+ }
2373
+ return `${vertexType}x${components}`;
2374
+ }
2375
+ var TYPE_INFO = {
2376
+ f32: ["f32", 1],
2377
+ "vec2<f32>": ["f32", 2],
2378
+ "vec3<f32>": ["f32", 3],
2379
+ "vec4<f32>": ["f32", 4],
2380
+ f16: ["f16", 1],
2381
+ "vec2<f16>": ["f16", 2],
2382
+ "vec3<f16>": ["f16", 3],
2383
+ "vec4<f16>": ["f16", 4],
2384
+ i32: ["i32", 1],
2385
+ "vec2<i32>": ["i32", 2],
2386
+ "vec3<i32>": ["i32", 3],
2387
+ "vec4<i32>": ["i32", 4],
2388
+ u32: ["u32", 1],
2389
+ "vec2<u32>": ["u32", 2],
2390
+ "vec3<u32>": ["u32", 3],
2391
+ "vec4<u32>": ["u32", 4]
2392
+ };
2393
+ var TYPE_SIZES2 = {
2394
+ f32: 4,
2395
+ f16: 2,
2396
+ i32: 4,
2397
+ u32: 4
2398
+ // 'bool-webgl': 4,
2399
+ };
2400
+
2321
2401
  // ../core/src/lib/compiler-log/format-compiler-log.ts
2322
2402
  function formatCompilerLog(shaderLog, source, options) {
2323
2403
  const lines = source.split(/\r?\n/);
@@ -2358,6 +2438,102 @@ var __exports__ = (() => {
2358
2438
  return result + string;
2359
2439
  }
2360
2440
 
2441
+ // ../core/src/adapter/attribute-utils/get-attribute-from-layouts.ts
2442
+ function getAttributeInfosFromLayouts(shaderLayout, bufferLayout) {
2443
+ const attributeInfos = {};
2444
+ for (const attribute of shaderLayout.attributes) {
2445
+ attributeInfos[attribute.name] = getAttributeInfoFromLayouts(shaderLayout, bufferLayout, attribute.name);
2446
+ }
2447
+ return attributeInfos;
2448
+ }
2449
+ function getAttributeInfoFromLayouts(shaderLayout, bufferLayout, name2) {
2450
+ const shaderDeclaration = getAttributeFromShaderLayout(shaderLayout, name2);
2451
+ const bufferMapping = getAttributeFromBufferLayout(bufferLayout, name2);
2452
+ if (!shaderDeclaration) {
2453
+ return null;
2454
+ }
2455
+ const attributeTypeInfo = decodeShaderAttributeType(shaderDeclaration.type);
2456
+ const vertexFormat = bufferMapping?.vertexFormat || attributeTypeInfo.defaultVertexFormat;
2457
+ const vertexFormatInfo = decodeVertexFormat(vertexFormat);
2458
+ return {
2459
+ name: name2,
2460
+ bufferName: bufferMapping?.name || name2,
2461
+ location: shaderDeclaration.location,
2462
+ shaderType: shaderDeclaration.type,
2463
+ shaderDataType: attributeTypeInfo.dataType,
2464
+ shaderComponents: attributeTypeInfo.components,
2465
+ vertexFormat,
2466
+ bufferDataType: vertexFormatInfo.type,
2467
+ bufferComponents: vertexFormatInfo.components,
2468
+ // normalized is a property of the buffer's vertex format
2469
+ normalized: vertexFormatInfo.normalized,
2470
+ // integer is a property of the shader declaration
2471
+ integer: attributeTypeInfo.integer,
2472
+ stepMode: bufferMapping?.stepMode || shaderDeclaration.stepMode,
2473
+ byteOffset: bufferMapping?.byteOffset || 0,
2474
+ byteStride: bufferMapping?.byteStride || 0
2475
+ };
2476
+ }
2477
+ function getAttributeFromShaderLayout(shaderLayout, name2) {
2478
+ const attribute = shaderLayout.attributes.find((attr) => attr.name === name2);
2479
+ if (!attribute) {
2480
+ log.warn(`shader layout attribute "${name2}" not present in shader`);
2481
+ }
2482
+ return attribute || null;
2483
+ }
2484
+ function getAttributeFromBufferLayout(bufferLayout, name2) {
2485
+ for (const bufferMapping of bufferLayout) {
2486
+ if (bufferMapping.name === name2) {
2487
+ return {
2488
+ name: bufferMapping.name,
2489
+ bufferName: name2,
2490
+ vertexFormat: bufferMapping.format,
2491
+ byteOffset: bufferMapping.byteOffset || 0,
2492
+ byteStride: bufferMapping.byteStride || 0
2493
+ };
2494
+ }
2495
+ let nextByteOffset = bufferMapping.byteOffset || 0;
2496
+ let byteStride = 0;
2497
+ for (const interleavedMapping of bufferMapping.attributes || []) {
2498
+ const info = decodeVertexFormat(interleavedMapping.format);
2499
+ byteStride += info.byteLength;
2500
+ }
2501
+ for (const interleavedMapping of bufferMapping.attributes || []) {
2502
+ const byteOffset = nextByteOffset;
2503
+ nextByteOffset += interleavedMapping?.byteStrideOffset || decodeVertexFormat(interleavedMapping.format).byteLength;
2504
+ if (interleavedMapping.name === name2) {
2505
+ return {
2506
+ name: bufferMapping.name,
2507
+ bufferName: name2,
2508
+ vertexFormat: interleavedMapping.format,
2509
+ byteOffset,
2510
+ byteStride: bufferMapping.byteStride || byteStride
2511
+ };
2512
+ }
2513
+ }
2514
+ }
2515
+ log.warn(`layout for attribute "${name2}" not present in buffer layout`);
2516
+ return null;
2517
+ }
2518
+ function mergeShaderLayout(baseLayout, overrideLayout) {
2519
+ const mergedLayout = {
2520
+ ...baseLayout,
2521
+ attributes: baseLayout.attributes.map((attribute) => ({
2522
+ ...attribute
2523
+ }))
2524
+ };
2525
+ for (const attribute of overrideLayout?.attributes || []) {
2526
+ const baseAttribute = mergedLayout.attributes.find((attr) => attr.name === attribute.name);
2527
+ if (!baseAttribute) {
2528
+ log.warn(`shader layout attribute ${attribute.name} not present in shader`);
2529
+ } else {
2530
+ baseAttribute.type = attribute.type || baseAttribute.type;
2531
+ baseAttribute.stepMode = attribute.stepMode || baseAttribute.stepMode;
2532
+ }
2533
+ }
2534
+ return mergedLayout;
2535
+ }
2536
+
2361
2537
  // ../core/src/lib/utils/cast.ts
2362
2538
  function cast(value) {
2363
2539
  return value;
@@ -2480,6 +2656,47 @@ var __exports__ = (() => {
2480
2656
  return options.target;
2481
2657
  }
2482
2658
 
2659
+ // ../core/src/lib/utils/deep-equal.ts
2660
+ function deepEqual(a, b, depth) {
2661
+ if (a === b) {
2662
+ return true;
2663
+ }
2664
+ if (!depth || !a || !b) {
2665
+ return false;
2666
+ }
2667
+ if (Array.isArray(a)) {
2668
+ if (!Array.isArray(b) || a.length !== b.length) {
2669
+ return false;
2670
+ }
2671
+ for (let i = 0; i < a.length; i++) {
2672
+ if (!deepEqual(a[i], b[i], depth - 1)) {
2673
+ return false;
2674
+ }
2675
+ }
2676
+ return true;
2677
+ }
2678
+ if (Array.isArray(b)) {
2679
+ return false;
2680
+ }
2681
+ if (typeof a === "object" && typeof b === "object") {
2682
+ const aKeys = Object.keys(a);
2683
+ const bKeys = Object.keys(b);
2684
+ if (aKeys.length !== bKeys.length) {
2685
+ return false;
2686
+ }
2687
+ for (const key of aKeys) {
2688
+ if (!b.hasOwnProperty(key)) {
2689
+ return false;
2690
+ }
2691
+ if (!deepEqual(a[key], b[key], depth - 1)) {
2692
+ return false;
2693
+ }
2694
+ }
2695
+ return true;
2696
+ }
2697
+ return false;
2698
+ }
2699
+
2483
2700
  // ../core/src/lib/request-animation-frame.ts
2484
2701
  function requestAnimationFrame(callback) {
2485
2702
  return typeof window !== "undefined" && window.requestAnimationFrame ? window.requestAnimationFrame(callback) : setTimeout(callback, 1e3 / 60);
@@ -2896,46 +3113,6 @@ var __exports__ = (() => {
2896
3113
  return animationLoop;
2897
3114
  }
2898
3115
 
2899
- // src/model/model-utils.ts
2900
- var GLTF_TO_LUMA_ATTRIBUTE_MAP = {
2901
- POSITION: "positions",
2902
- NORMAL: "normals",
2903
- COLOR_0: "colors",
2904
- TEXCOORD_0: "texCoords",
2905
- TEXCOORD_1: "texCoords1",
2906
- TEXCOORD_2: "texCoords2"
2907
- };
2908
- function getIndexBufferFromGeometry(device, geometry) {
2909
- if (!geometry.indices) {
2910
- return void 0;
2911
- }
2912
- const data = geometry.indices.value || geometry.indices;
2913
- assert2(data instanceof Uint16Array || data instanceof Uint32Array, 'attribute array for "indices" must be of integer type');
2914
- return device.createBuffer({
2915
- usage: Buffer2.INDEX,
2916
- data
2917
- });
2918
- }
2919
- function getAttributeBuffersFromGeometry(device, geometry) {
2920
- const buffers = {};
2921
- for (const [name, attribute] of Object.entries(geometry.attributes)) {
2922
- const remappedName = mapAttributeName(name);
2923
- if (attribute?.constant) {
2924
- throw new Error("constant attributes not supported");
2925
- } else {
2926
- const typedArray = attribute?.value;
2927
- buffers[remappedName] = device.createBuffer({
2928
- data: typedArray,
2929
- id: `${remappedName}-buffer`
2930
- });
2931
- }
2932
- }
2933
- return buffers;
2934
- }
2935
- function mapAttributeName(name) {
2936
- return GLTF_TO_LUMA_ATTRIBUTE_MAP[name] || name;
2937
- }
2938
-
2939
3116
  // ../shadertools/src/lib/glsl-utils/highlight.ts
2940
3117
  var glsl2 = (x) => `${x}`;
2941
3118
 
@@ -2963,8 +3140,8 @@ var __exports__ = (() => {
2963
3140
  };
2964
3141
  function makePropValidators(propTypes) {
2965
3142
  const propValidators = {};
2966
- for (const [name, propType] of Object.entries(propTypes)) {
2967
- propValidators[name] = makePropValidator(propType);
3143
+ for (const [name2, propType] of Object.entries(propTypes)) {
3144
+ propValidators[name2] = makePropValidator(propType);
2968
3145
  }
2969
3146
  return propValidators;
2970
3147
  }
@@ -3045,7 +3222,7 @@ var __exports__ = (() => {
3045
3222
  }
3046
3223
  constructor(props) {
3047
3224
  const {
3048
- name,
3225
+ name: name2,
3049
3226
  vs,
3050
3227
  fs,
3051
3228
  dependencies = [],
@@ -3055,8 +3232,8 @@ var __exports__ = (() => {
3055
3232
  defines = {},
3056
3233
  inject = {}
3057
3234
  } = props;
3058
- assert3(typeof name === "string");
3059
- this.name = name;
3235
+ assert3(typeof name2 === "string");
3236
+ this.name = name2;
3060
3237
  this.vs = vs;
3061
3238
  this.fs = fs;
3062
3239
  this.getModuleUniforms = getUniforms;
@@ -3158,7 +3335,7 @@ ${moduleSource}// END MODULE_${this.name}
3158
3335
  return result;
3159
3336
  }
3160
3337
 
3161
- // ../shadertools/src/lib/shader-assembler/resolve-modules.ts
3338
+ // ../shadertools/src/lib/shader-assembly/resolve-modules.ts
3162
3339
  function resolveModules(modules) {
3163
3340
  const instances = ShaderModuleInstance.instantiateModules(modules);
3164
3341
  return getShaderDependencies(instances);
@@ -3172,7 +3349,7 @@ ${moduleSource}// END MODULE_${this.name}
3172
3349
  moduleMap,
3173
3350
  moduleDepth
3174
3351
  });
3175
- return Object.keys(moduleDepth).sort((a, b) => moduleDepth[b] - moduleDepth[a]).map((name) => moduleMap[name]);
3352
+ return Object.keys(moduleDepth).sort((a, b) => moduleDepth[b] - moduleDepth[a]).map((name2) => moduleMap[name2]);
3176
3353
  }
3177
3354
  function getDependencyGraph(options) {
3178
3355
  const {
@@ -3202,7 +3379,7 @@ ${moduleSource}// END MODULE_${this.name}
3202
3379
  }
3203
3380
  }
3204
3381
 
3205
- // ../shadertools/src/lib/shader-assembler/platform-defines.ts
3382
+ // ../shadertools/src/lib/shader-assembly/platform-defines.ts
3206
3383
  function getPlatformShaderDefines(platformInfo) {
3207
3384
  switch (platformInfo?.gpu.toLowerCase()) {
3208
3385
  case "apple":
@@ -3337,7 +3514,7 @@ ${moduleSource}// END MODULE_${this.name}
3337
3514
  #endif
3338
3515
  `;
3339
3516
 
3340
- // ../shadertools/src/lib/shader-assembler/inject-shader.ts
3517
+ // ../shadertools/src/lib/shader-assembly/inject-shader.ts
3341
3518
  var MODULE_INJECTORS = {
3342
3519
  vs: MODULE_INJECTORS_VS,
3343
3520
  fs: MODULE_INJECTORS_FS
@@ -3479,7 +3656,7 @@ ${match}`).replace(new RegExp(`\\b${ES100_FRAGMENT_OUTPUT_NAME}\\b`, "g"), outpu
3479
3656
  return new RegExp(`\\b${qualifier}[ \\t]+(\\w+[ \\t]+\\w+(\\[\\w+\\])?;)`, "g");
3480
3657
  }
3481
3658
 
3482
- // ../shadertools/src/lib/shader-assembler/assemble-shaders.ts
3659
+ // ../shadertools/src/lib/shader-assembly/assemble-shaders.ts
3483
3660
  var INJECT_SHADER_DECLARATIONS = `
3484
3661
 
3485
3662
  ${DECLARATION_INJECT_MARKER}
@@ -3571,9 +3748,9 @@ ${isVertex ? "" : FRAGMENT_SHADER_PROLOGUE}
3571
3748
  const match = /^(v|f)s:(#)?([\w-]+)$/.exec(key);
3572
3749
  if (match) {
3573
3750
  const hash = match[2];
3574
- const name = match[3];
3751
+ const name2 = match[3];
3575
3752
  if (hash) {
3576
- if (name === "decl") {
3753
+ if (name2 === "decl") {
3577
3754
  declInjections[key] = [injection];
3578
3755
  } else {
3579
3756
  mainInjections[key] = [injection];
@@ -3595,8 +3772,8 @@ ${isVertex ? "" : FRAGMENT_SHADER_PROLOGUE}
3595
3772
  for (const key in injections) {
3596
3773
  const match = /^(v|f)s:#([\w-]+)$/.exec(key);
3597
3774
  if (match) {
3598
- const name = match[2];
3599
- const injectionType = name === "decl" ? declInjections : mainInjections;
3775
+ const name2 = match[2];
3776
+ const injectionType = name2 === "decl" ? declInjections : mainInjections;
3600
3777
  injectionType[key] = injectionType[key] || [];
3601
3778
  injectionType[key].push(injections[key]);
3602
3779
  } else {
@@ -3700,17 +3877,102 @@ ${isVertex ? "" : FRAGMENT_SHADER_PROLOGUE}
3700
3877
  }
3701
3878
  hook = hook.trim();
3702
3879
  const [stage, signature] = hook.split(":");
3703
- const name = hook.replace(/\(.+/, "");
3880
+ const name2 = hook.replace(/\(.+/, "");
3704
3881
  if (stage !== "vs" && stage !== "fs") {
3705
3882
  throw new Error(stage);
3706
3883
  }
3707
- result[stage][name] = Object.assign(opts, {
3884
+ result[stage][name2] = Object.assign(opts, {
3708
3885
  signature
3709
3886
  });
3710
3887
  });
3711
3888
  return result;
3712
3889
  }
3713
3890
 
3891
+ // ../shadertools/src/lib/shader-assembler.ts
3892
+ var ShaderAssembler = class {
3893
+ /** Default ShaderAssembler instance */
3894
+ /** Hook functions */
3895
+ _hookFunctions = [];
3896
+ /** Shader modules */
3897
+ _defaultModules = [];
3898
+ /**
3899
+ * A default shader assembler instance - the natural place to register default modules and hooks
3900
+ * @returns
3901
+ */
3902
+ static getDefaultShaderAssembler() {
3903
+ ShaderAssembler.defaultShaderAssembler = ShaderAssembler.defaultShaderAssembler || new ShaderAssembler();
3904
+ return ShaderAssembler.defaultShaderAssembler;
3905
+ }
3906
+ /**
3907
+ * Add a default module that does not have to be provided with every call to assembleShaders()
3908
+ */
3909
+ addDefaultModule(module) {
3910
+ if (!this._defaultModules.find((m) => m.name === (typeof module === "string" ? module : module.name))) {
3911
+ this._defaultModules.push(module);
3912
+ }
3913
+ }
3914
+ /**
3915
+ * Remove a default module
3916
+ */
3917
+ removeDefaultModule(module) {
3918
+ const moduleName = typeof module === "string" ? module : module.name;
3919
+ this._defaultModules = this._defaultModules.filter((m) => m.name !== moduleName);
3920
+ }
3921
+ /**
3922
+ * Register a shader hook
3923
+ * @param hook
3924
+ * @param opts
3925
+ */
3926
+ addShaderHook(hook, opts) {
3927
+ if (opts) {
3928
+ hook = Object.assign(opts, {
3929
+ hook
3930
+ });
3931
+ }
3932
+ this._hookFunctions.push(hook);
3933
+ }
3934
+ /**
3935
+ * Assemble a pair of shaders into a single shader program
3936
+ * @param platformInfo
3937
+ * @param props
3938
+ * @returns
3939
+ */
3940
+ assembleShaders(platformInfo, props) {
3941
+ const modules = this._getModuleList(props.modules);
3942
+ const hookFunctions = this._hookFunctions;
3943
+ const assembled = assembleShaders(platformInfo, {
3944
+ ...props,
3945
+ modules,
3946
+ hookFunctions
3947
+ });
3948
+ return assembled;
3949
+ }
3950
+ /**
3951
+ * Dedupe and combine with default modules
3952
+ */
3953
+ _getModuleList(appModules = []) {
3954
+ const modules = new Array(this._defaultModules.length + appModules.length);
3955
+ const seen = {};
3956
+ let count = 0;
3957
+ for (let i = 0, len = this._defaultModules.length; i < len; ++i) {
3958
+ const module = this._defaultModules[i];
3959
+ const name2 = module.name;
3960
+ modules[count++] = module;
3961
+ seen[name2] = true;
3962
+ }
3963
+ for (let i = 0, len = appModules.length; i < len; ++i) {
3964
+ const module = appModules[i];
3965
+ const name2 = module.name;
3966
+ if (!seen[name2]) {
3967
+ modules[count++] = module;
3968
+ seen[name2] = true;
3969
+ }
3970
+ }
3971
+ modules.length = count;
3972
+ return modules;
3973
+ }
3974
+ };
3975
+
3714
3976
  // ../shadertools/src/lib/glsl-utils/get-shader-info.ts
3715
3977
  function getShaderInfo(source, defaultName) {
3716
3978
  return {
@@ -5682,87 +5944,151 @@ void main() {
5682
5944
  return result;
5683
5945
  }
5684
5946
 
5685
- // src/lib/pipeline-factory.ts
5686
- var DEFAULT_RENDER_PIPELINE_OPTIONS = {
5687
- vs: "",
5688
- fs: "",
5689
- modules: [],
5690
- defines: {},
5691
- inject: {},
5692
- transpileToGLSL100: false,
5693
- layout: null,
5694
- varyings: [],
5695
- bufferMode: 35981,
5696
- // // varyings/bufferMode for xform feedback, 0x8c8d: SEPARATE_ATTRIBS
5697
- topology: "triangle-list",
5698
- parameters: {}
5947
+ // src/geometry/gpu-geometry.ts
5948
+ var GPUGeometry = class {
5949
+ userData = {};
5950
+ /** Determines how vertices are read from the 'vertex' attributes */
5951
+ bufferLayout = [];
5952
+ constructor(props) {
5953
+ this.id = props.id || uid("geometry");
5954
+ this.topology = props.topology;
5955
+ this.indices = props.indices || null;
5956
+ this.attributes = props.attributes;
5957
+ this.vertexCount = props.vertexCount || this._calculateVertexCount(this.attributes.positions);
5958
+ this.bufferLayout = props.bufferLayout || [];
5959
+ if (!this.bufferLayout.find((layout) => layout.name === "positions")) {
5960
+ this.bufferLayout.push({
5961
+ name: "positions",
5962
+ format: "float32x3"
5963
+ });
5964
+ }
5965
+ if (!this.bufferLayout.find((layout) => layout.name === "normals")) {
5966
+ this.bufferLayout.push({
5967
+ name: "normals",
5968
+ format: "float32x3"
5969
+ });
5970
+ }
5971
+ if (!this.bufferLayout.find((layout) => layout.name === "texCoords")) {
5972
+ this.bufferLayout.push({
5973
+ name: "texCoords",
5974
+ format: "float32x2"
5975
+ });
5976
+ }
5977
+ if (!this.bufferLayout.find((layout) => layout.name === "colors")) {
5978
+ this.bufferLayout.push({
5979
+ name: "colors",
5980
+ format: "float32x3"
5981
+ });
5982
+ }
5983
+ if (this.indices) {
5984
+ assert2(this.indices.usage === Buffer2.INDEX);
5985
+ }
5986
+ }
5987
+ destroy() {
5988
+ this.indices.destroy();
5989
+ this.attributes.positions.destroy();
5990
+ this.attributes.normals.destroy();
5991
+ this.attributes.texCoords.destroy();
5992
+ this.attributes.colors?.destroy();
5993
+ }
5994
+ getVertexCount() {
5995
+ return this.vertexCount;
5996
+ }
5997
+ getAttributes() {
5998
+ return this.attributes;
5999
+ }
6000
+ getIndexes() {
6001
+ return this.indices;
6002
+ }
6003
+ _calculateVertexCount(positions) {
6004
+ const vertexCount = positions.byteLength / 12;
6005
+ return vertexCount;
6006
+ }
5699
6007
  };
5700
- var PipelineFactory = class {
5701
- stateHash = 0;
5702
- // Used to change hashing if hooks are modified
6008
+ function makeGPUGeometry(device, geometry) {
6009
+ if (geometry instanceof GPUGeometry) {
6010
+ return geometry;
6011
+ }
6012
+ const indices = getIndexBufferFromGeometry(device, geometry);
6013
+ const attributes = getAttributeBuffersFromGeometry(device, geometry);
6014
+ return new GPUGeometry({
6015
+ topology: geometry.topology,
6016
+ vertexCount: geometry.vertexCount,
6017
+ indices,
6018
+ attributes
6019
+ });
6020
+ }
6021
+ function getIndexBufferFromGeometry(device, geometry) {
6022
+ if (!geometry.indices) {
6023
+ return void 0;
6024
+ }
6025
+ const data = geometry.indices.value || geometry.indices;
6026
+ assert2(data instanceof Uint16Array || data instanceof Uint32Array, 'attribute array for "indices" must be of integer type');
6027
+ return device.createBuffer({
6028
+ usage: Buffer2.INDEX,
6029
+ data
6030
+ });
6031
+ }
6032
+ function getAttributeBuffersFromGeometry(device, geometry) {
6033
+ const positions = geometry.attributes.positions || geometry.attributes.POSITION;
6034
+ const normals = geometry.attributes.normals || geometry.attributes.NORMAL;
6035
+ const texCoords = geometry.attributes.texCoords || geometry.attributes.TEXCOORD_0;
6036
+ const buffers = {
6037
+ positions: device.createBuffer({
6038
+ data: positions.value,
6039
+ id: "positions-buffer"
6040
+ }),
6041
+ normals: device.createBuffer({
6042
+ data: normals.value,
6043
+ id: "normals-buffer"
6044
+ }),
6045
+ texCoords: device.createBuffer({
6046
+ data: texCoords.value,
6047
+ id: "texCoords-buffer"
6048
+ })
6049
+ };
6050
+ return buffers;
6051
+ }
6052
+
6053
+ // src/lib/pipeline-factory.ts
6054
+ var _PipelineFactory = class {
5703
6055
  _hashCounter = 0;
5704
6056
  _hashes = {};
5705
6057
  _useCounts = {};
5706
6058
  _pipelineCache = {};
5707
- _getUniforms = {};
5708
- _hookFunctions = [];
5709
- _defaultModules = [];
5710
- // private readonly _registeredModules = {}; // TODO: Remove? This isn't used anywhere in luma.gl
5711
6059
  static getDefaultPipelineFactory(device) {
5712
- device.defaultPipelineFactory = device.defaultPipelineFactory || new PipelineFactory(device);
5713
- return device.defaultPipelineFactory;
6060
+ device._lumaData.defaultPipelineFactory = device._lumaData.defaultPipelineFactory || new _PipelineFactory(device);
6061
+ return device._lumaData.defaultPipelineFactory;
5714
6062
  }
5715
6063
  constructor(device) {
5716
6064
  this.device = device;
5717
6065
  }
5718
- addDefaultModule(module) {
5719
- if (!this._defaultModules.find((m) => m.name === (typeof module === "string" ? module : module.name))) {
5720
- this._defaultModules.push(module);
5721
- }
5722
- this.stateHash++;
5723
- }
5724
- removeDefaultModule(module) {
5725
- const moduleName = typeof module === "string" ? module : module.name;
5726
- this._defaultModules = this._defaultModules.filter((m) => m.name !== moduleName);
5727
- this.stateHash++;
5728
- }
5729
- addShaderHook(hook, opts) {
5730
- if (opts) {
5731
- hook = Object.assign(opts, {
5732
- hook
5733
- });
5734
- }
5735
- this._hookFunctions.push(hook);
5736
- this.stateHash++;
5737
- }
5738
6066
  createRenderPipeline(options) {
5739
6067
  const props = {
5740
- ...DEFAULT_RENDER_PIPELINE_OPTIONS,
6068
+ ..._PipelineFactory.defaultProps,
5741
6069
  ...options
5742
6070
  };
5743
- const modules = this._getModuleList(props.modules);
5744
6071
  const hash = this._hashRenderPipeline({
5745
- ...props,
5746
- modules
6072
+ ...props
5747
6073
  });
5748
6074
  if (!this._pipelineCache[hash]) {
5749
- const {
5750
- pipeline,
5751
- getUniforms
5752
- } = this._createRenderPipeline({
6075
+ const pipeline = this.device.createRenderPipeline({
5753
6076
  ...props,
5754
- modules
6077
+ vs: this.device.createShader({
6078
+ stage: "vertex",
6079
+ source: props.vs
6080
+ }),
6081
+ fs: props.fs ? this.device.createShader({
6082
+ stage: "fragment",
6083
+ source: props.fs
6084
+ }) : null
5755
6085
  });
5756
6086
  pipeline.hash = hash;
5757
6087
  this._pipelineCache[hash] = pipeline;
5758
- this._getUniforms[hash] = getUniforms || ((x) => ({}));
5759
6088
  this._useCounts[hash] = 0;
5760
6089
  }
5761
6090
  this._useCounts[hash]++;
5762
- return {
5763
- pipeline: this._pipelineCache[hash],
5764
- getUniforms: this._getUniforms[hash]
5765
- };
6091
+ return this._pipelineCache[hash];
5766
6092
  }
5767
6093
  release(pipeline) {
5768
6094
  const hash = pipeline.hash;
@@ -5770,70 +6096,35 @@ void main() {
5770
6096
  if (this._useCounts[hash] === 0) {
5771
6097
  this._pipelineCache[hash].destroy();
5772
6098
  delete this._pipelineCache[hash];
5773
- delete this._getUniforms[hash];
5774
6099
  delete this._useCounts[hash];
5775
6100
  }
5776
6101
  }
5777
- getUniforms(pipeline) {
5778
- return this._getUniforms[pipeline.hash] || null;
5779
- }
5780
6102
  // PRIVATE
5781
6103
  _createRenderPipeline(props) {
5782
- const platformInfo = {
5783
- gpu: this.device.info.gpu,
5784
- features: this.device.features
5785
- };
5786
6104
  if (!props.fs) {
5787
6105
  throw new Error("fs");
5788
6106
  }
5789
- const assembled = assembleShaders(platformInfo, {
5790
- ...props,
5791
- fs: props.fs,
5792
- hookFunctions: this._hookFunctions
5793
- });
5794
6107
  const pipeline = this.device.createRenderPipeline({
5795
6108
  ...props,
5796
6109
  vs: this.device.createShader({
5797
6110
  stage: "vertex",
5798
- source: assembled.vs
6111
+ source: props.vs
5799
6112
  }),
5800
- fs: assembled.fs ? this.device.createShader({
6113
+ fs: props.fs ? this.device.createShader({
5801
6114
  stage: "fragment",
5802
- source: assembled.fs
6115
+ source: props.fs
5803
6116
  }) : null
5804
6117
  });
5805
- return {
5806
- pipeline,
5807
- getUniforms: assembled.getUniforms
5808
- };
6118
+ return pipeline;
5809
6119
  }
5810
6120
  /** Calculate a hash based on all the inputs for a render pipeline */
5811
6121
  _hashRenderPipeline(props) {
5812
- const {
5813
- modules = [],
5814
- varyings = [],
5815
- defines = {},
5816
- inject = {},
5817
- parameters = {}
5818
- } = props;
5819
6122
  const vsHash = this._getHash(props.vs);
5820
6123
  const fsHash = props.fs ? this._getHash(props.fs) : 0;
5821
- const moduleHashes = modules.map((m) => this._getHash(typeof m === "string" ? m : m.name)).sort();
5822
- const varyingHashes = varyings.map((v) => this._getHash(v));
5823
- const defineKeys = Object.keys(defines).sort();
5824
- const injectKeys = Object.keys(inject).sort();
5825
- const defineHashes = [];
5826
- const injectHashes = [];
5827
- for (const key of defineKeys) {
5828
- defineHashes.push(this._getHash(key));
5829
- defineHashes.push(this._getHash(String(defines[key])));
5830
- }
5831
- for (const key of injectKeys) {
5832
- injectHashes.push(this._getHash(key));
5833
- injectHashes.push(this._getHash(inject[key]));
5834
- }
5835
- const parameterHash = JSON.stringify(parameters);
5836
- return `${vsHash}/${fsHash}D${defineHashes.join("/")}M${moduleHashes.join("/")}I${injectHashes.join("/")}V${varyingHashes.join("/")}H${this.stateHash}B${props.bufferMode}${props.transpileToGLSL100 ? "T" : ""}P${parameterHash}`;
6124
+ const parameterHash = this._getHash(JSON.stringify(props.parameters));
6125
+ const bufferLayoutHash = this._getHash(JSON.stringify(props.bufferLayout));
6126
+ const varyingHash = "-";
6127
+ return `${vsHash}/${fsHash}V${varyingHash}T${props.topology}P${parameterHash}BL${bufferLayoutHash}}`;
5837
6128
  }
5838
6129
  _getHash(key) {
5839
6130
  if (this._hashes[key] === void 0) {
@@ -5841,182 +6132,314 @@ void main() {
5841
6132
  }
5842
6133
  return this._hashes[key];
5843
6134
  }
5844
- // Dedupe and combine with default modules
5845
- _getModuleList(appModules = []) {
5846
- const modules = new Array(this._defaultModules.length + appModules.length);
5847
- const seen = {};
5848
- let count = 0;
5849
- for (let i = 0, len = this._defaultModules.length; i < len; ++i) {
5850
- const module = this._defaultModules[i];
5851
- const name = module.name;
5852
- modules[count++] = module;
5853
- seen[name] = true;
5854
- }
5855
- for (let i = 0, len = appModules.length; i < len; ++i) {
5856
- const module = appModules[i];
5857
- const name = module.name;
5858
- if (!seen[name]) {
5859
- modules[count++] = module;
5860
- seen[name] = true;
6135
+ };
6136
+ var PipelineFactory = _PipelineFactory;
6137
+ __publicField(PipelineFactory, "defaultProps", {
6138
+ ...RenderPipeline.defaultProps,
6139
+ vs: void 0,
6140
+ fs: void 0
6141
+ });
6142
+
6143
+ // src/model/model-shaders.ts
6144
+ function buildShaders(device, props) {
6145
+ if (!props.vs) {
6146
+ throw new Error("no vertex shader");
6147
+ }
6148
+ const vs = getShaderSource(device, props.vs);
6149
+ let fs;
6150
+ if (props.fs) {
6151
+ fs = getShaderSource(device, props.fs);
6152
+ }
6153
+ const platformInfo = {
6154
+ type: device.info.type,
6155
+ gpu: device.info.gpu,
6156
+ features: device.features
6157
+ };
6158
+ return props.shaderAssembler.assembleShaders(platformInfo, {
6159
+ ...props,
6160
+ fs,
6161
+ vs
6162
+ });
6163
+ }
6164
+ function getShaderSource(device, shader) {
6165
+ if (typeof shader === "string") {
6166
+ return shader;
6167
+ }
6168
+ switch (device.info.type) {
6169
+ case "webgpu":
6170
+ if (shader?.wgsl) {
6171
+ return shader.wgsl;
5861
6172
  }
5862
- }
5863
- modules.length = count;
5864
- return modules;
6173
+ throw new Error("WebGPU does not support GLSL shaders");
6174
+ default:
6175
+ if (shader?.glsl) {
6176
+ return shader.glsl;
6177
+ }
6178
+ throw new Error("WebGL does not support WGSL shaders");
5865
6179
  }
5866
- };
6180
+ }
5867
6181
 
5868
6182
  // src/model/model.ts
5869
- var DEFAULT_MODEL_PROPS = {
5870
- ...RenderPipeline._DEFAULT_PROPS,
5871
- vs: null,
5872
- fs: null,
5873
- id: "unnamed",
5874
- handle: void 0,
5875
- userData: {},
5876
- defines: {},
5877
- modules: [],
5878
- moduleSettings: {},
5879
- geometry: null,
5880
- pipelineFactory: void 0
5881
- };
5882
- var Model = class {
5883
- fs = null;
5884
- /** The underlying GPU "program". @note May be recreated if parameters change */
6183
+ var _Model = class {
5885
6184
  userData = {};
5886
- // readonly props: Required<ModelProps>;
6185
+ // Fixed properties (change can trigger pipeline rebuild)
6186
+ /** The render pipeline GPU parameters, depth testing etc */
6187
+ /** The primitive topology */
6188
+ /** Buffer layout */
6189
+ // Dynamic properties
5887
6190
  /** Vertex count */
5888
6191
  /** instance count */
5889
6192
  instanceCount = 0;
6193
+ /** Index buffer */
6194
+ indices = null;
5890
6195
  /** Buffer-valued attributes */
5891
6196
  bufferAttributes = {};
5892
6197
  /** Constant-valued attributes */
5893
6198
  constantAttributes = {};
5894
6199
  /** Bindings (textures, samplers, uniform buffers) */
5895
6200
  bindings = {};
5896
- /** Uniforms */
6201
+ /** Sets uniforms @deprecated Use uniform buffers and setBindings() for portability*/
5897
6202
  uniforms = {};
6203
+ /** The underlying GPU "program". @note May be recreated if parameters change */
6204
+ _pipelineNeedsUpdate = "newly created";
5898
6205
  constructor(device, props) {
5899
- props = {
5900
- ...DEFAULT_MODEL_PROPS,
6206
+ this.props = {
6207
+ ..._Model.defaultProps,
5901
6208
  ...props
5902
6209
  };
5903
- this.id = props.id;
6210
+ props = this.props;
6211
+ this.id = props.id || uid("model");
5904
6212
  this.device = device;
5905
6213
  Object.assign(this.userData, props.userData);
5906
- if (!props.vs) {
5907
- throw new Error("no vertex shader");
6214
+ const {
6215
+ vs,
6216
+ fs,
6217
+ getUniforms
6218
+ } = buildShaders(device, this.props);
6219
+ this.vs = vs;
6220
+ this.fs = fs;
6221
+ this._getModuleUniforms = getUniforms;
6222
+ this.vertexCount = this.props.vertexCount;
6223
+ this.instanceCount = this.props.instanceCount;
6224
+ this.topology = this.props.topology;
6225
+ this.bufferLayout = this.props.bufferLayout;
6226
+ this.parameters = this.props.parameters;
6227
+ const gpuGeometry = props.geometry && makeGPUGeometry(device, props.geometry);
6228
+ if (gpuGeometry) {
6229
+ this.setGeometry(gpuGeometry);
6230
+ }
6231
+ this.pipelineFactory = props.pipelineFactory || PipelineFactory.getDefaultPipelineFactory(this.device);
6232
+ this.pipeline = this._updatePipeline();
6233
+ if (props.vertexCount) {
6234
+ this.setVertexCount(props.vertexCount);
6235
+ }
6236
+ if (props.instanceCount) {
6237
+ this.setInstanceCount(props.instanceCount);
6238
+ }
6239
+ if (props.indices) {
6240
+ this.setIndexBuffer(props.indices);
5908
6241
  }
5909
- this.vs = getShaderSource(this.device, props.vs);
5910
- if (props.fs) {
5911
- this.fs = getShaderSource(this.device, props.fs);
6242
+ if (props.attributes) {
6243
+ this.setAttributes(props.attributes);
5912
6244
  }
5913
- this.vertexCount = props.vertexCount;
5914
- this.instanceCount = props.instanceCount;
5915
- this.topology = props.topology;
5916
- if (props.geometry) {
5917
- this.vertexCount = props.geometry.vertexCount;
5918
- this.topology = props.geometry.topology || "triangle-list";
6245
+ if (props.bindings) {
6246
+ this.setBindings(props.bindings);
5919
6247
  }
5920
- this.pipelineFactory = props.pipelineFactory || PipelineFactory.getDefaultPipelineFactory(this.device);
5921
- const {
5922
- pipeline,
5923
- getUniforms
5924
- } = this.pipelineFactory.createRenderPipeline({
5925
- ...props,
5926
- vs: this.vs,
5927
- fs: this.fs,
5928
- topology: this.topology,
5929
- defines: props.defines,
5930
- parameters: props.parameters,
5931
- layout: props.layout
5932
- });
5933
- this.pipeline = pipeline;
5934
- this._getModuleUniforms = getUniforms;
5935
- if (props.geometry) {
5936
- this._setGeometry(props.geometry);
6248
+ if (props.uniforms) {
6249
+ this.setUniforms(props.uniforms);
6250
+ }
6251
+ if (props.moduleSettings) {
6252
+ this.updateModuleSettings(props.moduleSettings);
5937
6253
  }
5938
6254
  this.setUniforms(this._getModuleUniforms());
5939
- this.setProps(props);
6255
+ Object.seal(this);
5940
6256
  }
5941
6257
  destroy() {
5942
6258
  this.pipelineFactory.release(this.pipeline);
5943
6259
  }
6260
+ // Draw call
5944
6261
  draw(renderPass) {
6262
+ this.pipeline = this._updatePipeline();
6263
+ this.pipeline.setIndexBuffer(this.indices);
6264
+ this.pipeline.setAttributes(this.bufferAttributes);
6265
+ this.pipeline.setConstantAttributes(this.constantAttributes);
6266
+ this.pipeline.setBindings(this.bindings);
6267
+ this.pipeline.setUniforms(this.uniforms);
5945
6268
  this.pipeline.draw({
5946
6269
  renderPass,
5947
6270
  vertexCount: this.vertexCount,
5948
6271
  instanceCount: this.instanceCount
5949
6272
  });
5950
6273
  }
5951
- setProps(props) {
5952
- if (props.indices) {
5953
- this.setIndexBuffer(props.indices);
5954
- }
5955
- if (props.attributes) {
5956
- this.setAttributes(props.attributes);
5957
- }
5958
- if (props.bindings) {
5959
- this.setBindings(props.bindings);
6274
+ // Update fixed fields (can trigger pipeline rebuild)
6275
+ /**
6276
+ * Updates the optional geometry
6277
+ * @note Can trigger a pipeline rebuild / pipeline cache fetch on WebGPU
6278
+ */
6279
+ setGeometry(geometry) {
6280
+ this.setTopology(geometry.topology || "triangle-list");
6281
+ this.bufferLayout = mergeBufferLayouts(this.bufferLayout, geometry.bufferLayout);
6282
+ this.vertexCount = geometry.vertexCount;
6283
+ this.setAttributes(geometry.attributes);
6284
+ this.setIndexBuffer(geometry.indices);
6285
+ }
6286
+ /**
6287
+ * Updates the primitive topology ('triangle-list', 'triangle-strip' etc).
6288
+ * @note Triggers a pipeline rebuild / pipeline cache fetch on WebGPU
6289
+ */
6290
+ setTopology(topology) {
6291
+ if (topology !== this.topology) {
6292
+ this.topology = topology;
6293
+ if (this.device.info.type === "webgpu") {
6294
+ this._setPipelineNeedsUpdate("topology");
6295
+ }
5960
6296
  }
5961
- if (props.uniforms) {
5962
- this.setUniforms(props.uniforms);
6297
+ }
6298
+ /**
6299
+ * Updates the buffer layout.
6300
+ * @note Triggers a pipeline rebuild / pipeline cache fetch on WebGPU
6301
+ */
6302
+ setBufferLayout(bufferLayout) {
6303
+ if (bufferLayout !== this.bufferLayout) {
6304
+ this.bufferLayout = bufferLayout;
6305
+ if (this.device.info.type === "webgpu") {
6306
+ this._setPipelineNeedsUpdate("bufferLayout");
6307
+ }
5963
6308
  }
5964
- if (props.moduleSettings) {
5965
- this.updateModuleSettings(props.moduleSettings);
6309
+ }
6310
+ /**
6311
+ * Set GPU parameters.
6312
+ * @note Can trigger a pipeline rebuild / pipeline cache fetch.
6313
+ * @param parameters
6314
+ */
6315
+ setParameters(parameters) {
6316
+ if (!deepEqual(parameters, this.parameters, 2)) {
6317
+ this.parameters = parameters;
6318
+ if (this.device.info.type === "webgpu") {
6319
+ this._setPipelineNeedsUpdate("parameters");
6320
+ }
5966
6321
  }
5967
6322
  }
5968
- updateModuleSettings(props) {
6323
+ // Update dynamic fields
6324
+ /**
6325
+ * Updates the vertex count (used in draw calls)
6326
+ * @note Any attributes with stepMode=vertex need to be at least this big
6327
+ */
6328
+ setVertexCount(vertexCount) {
6329
+ this.vertexCount = vertexCount;
6330
+ }
6331
+ /**
6332
+ * Updates the instance count (used in draw calls)
6333
+ * @note Any attributes with stepMode=instance need to be at least this big
6334
+ */
6335
+ setInstanceCount(instanceCount) {
6336
+ this.instanceCount = instanceCount;
6337
+ }
6338
+ /**
6339
+ * Updates shader module settings (which results in uniforms being set)
6340
+ */
6341
+ setShaderModuleProps(props) {
5969
6342
  const uniforms = this._getModuleUniforms(props);
5970
- this.setUniforms(uniforms);
6343
+ Object.assign(this.uniforms, uniforms);
6344
+ }
6345
+ /**
6346
+ * @deprecated Updates shader module settings (which results in uniforms being set)
6347
+ */
6348
+ updateModuleSettings(props) {
6349
+ this.setShaderModuleProps(props);
5971
6350
  }
6351
+ /**
6352
+ * Sets the index buffer
6353
+ * @todo - how to unset it if we change geometry?
6354
+ */
5972
6355
  setIndexBuffer(indices) {
5973
- this.pipeline.setIndexBuffer(indices);
6356
+ this.indices = indices;
5974
6357
  }
6358
+ /**
6359
+ * Sets attributes (buffers)
6360
+ * @note Overrides any attributes previously set with the same name
6361
+ */
5975
6362
  setAttributes(bufferAttributes) {
5976
6363
  if (bufferAttributes.indices) {
5977
6364
  log.warn(`Model:${this.id} setAttributes() - indices should be set using setIndexBuffer()`);
5978
6365
  }
5979
- this.pipeline.setAttributes(bufferAttributes);
5980
6366
  Object.assign(this.bufferAttributes, bufferAttributes);
5981
6367
  }
6368
+ /**
6369
+ * Sets constant attributes
6370
+ * @note Overrides any attributes previously set with the same name
6371
+ * @param constantAttributes
6372
+ */
5982
6373
  setConstantAttributes(constantAttributes) {
5983
- this.pipeline.setConstantAttributes(constantAttributes);
5984
6374
  Object.assign(this.constantAttributes, constantAttributes);
5985
6375
  }
5986
- /** Set the bindings */
6376
+ /**
6377
+ * Sets bindings (textures, samplers, uniform buffers)
6378
+ */
5987
6379
  setBindings(bindings) {
5988
- this.pipeline.setBindings(bindings);
5989
6380
  Object.assign(this.bindings, bindings);
5990
6381
  }
6382
+ /**
6383
+ * Sets individual uniforms
6384
+ * @deprecated WebGL only, use uniform buffers for portability
6385
+ * @param uniforms
6386
+ * @returns self for chaining
6387
+ */
5991
6388
  setUniforms(uniforms) {
5992
6389
  this.pipeline.setUniforms(uniforms);
5993
6390
  Object.assign(this.uniforms, uniforms);
5994
6391
  }
5995
- _setGeometry(geometry) {
5996
- const geometryBuffers = getAttributeBuffersFromGeometry(this.device, geometry);
5997
- this.setAttributes(geometryBuffers);
5998
- const indexBuffer = getIndexBufferFromGeometry(this.device, geometry);
5999
- if (indexBuffer) {
6000
- this.setIndexBuffer(indexBuffer);
6392
+ _setPipelineNeedsUpdate(reason) {
6393
+ this._pipelineNeedsUpdate = this._pipelineNeedsUpdate || reason;
6394
+ }
6395
+ _updatePipeline() {
6396
+ if (this._pipelineNeedsUpdate) {
6397
+ log.log(1, `Model ${this.id}: Recreating pipeline because "${this._pipelineNeedsUpdate}".`)();
6398
+ this._pipelineNeedsUpdate = false;
6399
+ this.pipeline = this.device.createRenderPipeline({
6400
+ ...this.props,
6401
+ bufferLayout: this.bufferLayout,
6402
+ topology: this.topology,
6403
+ parameters: this.parameters,
6404
+ vs: this.device.createShader({
6405
+ stage: "vertex",
6406
+ source: this.vs
6407
+ }),
6408
+ fs: this.fs ? this.device.createShader({
6409
+ stage: "fragment",
6410
+ source: this.fs
6411
+ }) : null
6412
+ });
6001
6413
  }
6414
+ return this.pipeline;
6002
6415
  }
6003
6416
  };
6004
- function getShaderSource(device, shader) {
6005
- if (typeof shader === "string") {
6006
- return shader;
6007
- }
6008
- switch (device.info.type) {
6009
- case "webgpu":
6010
- if (shader?.wgsl) {
6011
- return shader.wgsl;
6012
- }
6013
- throw new Error("WebGPU does not support GLSL shaders");
6014
- default:
6015
- if (shader?.glsl) {
6016
- return shader.glsl;
6017
- }
6018
- throw new Error("WebGL does not support WGSL shaders");
6417
+ var Model = _Model;
6418
+ __publicField(Model, "defaultProps", {
6419
+ ...RenderPipeline.defaultProps,
6420
+ vs: null,
6421
+ fs: null,
6422
+ id: "unnamed",
6423
+ handle: void 0,
6424
+ userData: {},
6425
+ defines: {},
6426
+ modules: [],
6427
+ moduleSettings: {},
6428
+ geometry: null,
6429
+ pipelineFactory: void 0,
6430
+ shaderAssembler: ShaderAssembler.getDefaultShaderAssembler()
6431
+ });
6432
+ function mergeBufferLayouts(layouts1, layouts2) {
6433
+ const layouts = [...layouts1];
6434
+ for (const attribute of layouts2) {
6435
+ const index = layouts.findIndex((attribute2) => attribute2.name === attribute.name);
6436
+ if (index < 0) {
6437
+ layouts.push(attribute);
6438
+ } else {
6439
+ layouts[index] = attribute;
6440
+ }
6019
6441
  }
6442
+ return layouts;
6020
6443
  }
6021
6444
 
6022
6445
  // ../constants/src/constants-enum.ts
@@ -6974,12 +7397,12 @@ void main() {
6974
7397
  return list;
6975
7398
  };
6976
7399
  const original_getExtension = gl.getExtension;
6977
- gl.getExtension = function getExtension(name) {
6978
- const ext = original_getExtension.call(this, name);
7400
+ gl.getExtension = function getExtension(name2) {
7401
+ const ext = original_getExtension.call(this, name2);
6979
7402
  if (ext) {
6980
7403
  return ext;
6981
7404
  }
6982
- if (name !== "OES_vertex_array_object") {
7405
+ if (name2 !== "OES_vertex_array_object") {
6983
7406
  return null;
6984
7407
  }
6985
7408
  if (!gl.__OESVertexArrayObject) {
@@ -8166,6 +8589,37 @@ void main() {
8166
8589
  return isMSIE || isTrident;
8167
8590
  }
8168
8591
 
8592
+ // ../webgl/src/adapter/converters/vertex-formats.ts
8593
+ function getGLFromVertexType(dataType) {
8594
+ switch (dataType) {
8595
+ case "uint8":
8596
+ return GL.UNSIGNED_BYTE;
8597
+ case "sint8":
8598
+ return GL.BYTE;
8599
+ case "unorm8":
8600
+ return GL.UNSIGNED_BYTE;
8601
+ case "snorm8":
8602
+ return GL.BYTE;
8603
+ case "uint16":
8604
+ return GL.UNSIGNED_SHORT;
8605
+ case "sint16":
8606
+ return GL.SHORT;
8607
+ case "unorm16":
8608
+ return GL.UNSIGNED_SHORT;
8609
+ case "snorm16":
8610
+ return GL.SHORT;
8611
+ case "uint32":
8612
+ return GL.UNSIGNED_INT;
8613
+ case "sint32":
8614
+ return GL.INT;
8615
+ case "float16":
8616
+ return GL.HALF_FLOAT;
8617
+ case "float32":
8618
+ return GL.FLOAT;
8619
+ }
8620
+ throw new Error(String(dataType));
8621
+ }
8622
+
8169
8623
  // ../webgl/src/adapter/converters/texture-formats.ts
8170
8624
  var texture_compression_bc = "texture-compression-bc";
8171
8625
  var texture_compression_astc = "texture-compression-astc";
@@ -8947,7 +9401,7 @@ void main() {
8947
9401
  [GL.LUMINANCE]: 1,
8948
9402
  [GL.LUMINANCE_ALPHA]: 2
8949
9403
  };
8950
- var TYPE_SIZES2 = {
9404
+ var TYPE_SIZES3 = {
8951
9405
  [GL.FLOAT]: 4,
8952
9406
  [GL.UNSIGNED_INT]: 4,
8953
9407
  [GL.INT]: 4,
@@ -9031,7 +9485,8 @@ void main() {
9031
9485
  return {
9032
9486
  format: webglFormat,
9033
9487
  dataFormat: getWebGLPixelDataFormat(decoded.format, decoded.integer, decoded.normalized, webglFormat),
9034
- type: getWebGLDataType(decoded.dataType),
9488
+ // depth formats don't have a type
9489
+ type: decoded.dataType ? getGLFromVertexType(decoded.dataType) : GL.UNSIGNED_BYTE,
9035
9490
  // @ts-expect-error
9036
9491
  compressed: decoded.compressed
9037
9492
  };
@@ -9070,7 +9525,7 @@ void main() {
9070
9525
  const format = convertGLToTextureFormat(formatOrGL);
9071
9526
  const params = getWebGLTextureParameters(format, isWebGL23);
9072
9527
  const channels = DATA_FORMAT_CHANNELS[params.dataFormat] || 4;
9073
- const channelSize = TYPE_SIZES2[params.type] || 1;
9528
+ const channelSize = TYPE_SIZES3[params.type] || 1;
9074
9529
  return channels * channelSize;
9075
9530
  }
9076
9531
  function getWebGLPixelDataFormat(dataFormat, integer, normalized, format) {
@@ -9090,28 +9545,6 @@ void main() {
9090
9545
  return GL.RGBA;
9091
9546
  }
9092
9547
  }
9093
- function getWebGLDataType(dataType) {
9094
- switch (dataType) {
9095
- case "uint8":
9096
- return GL.UNSIGNED_BYTE;
9097
- case "sint8":
9098
- return GL.BYTE;
9099
- case "uint16":
9100
- return GL.UNSIGNED_SHORT;
9101
- case "sint16":
9102
- return GL.SHORT;
9103
- case "uint32":
9104
- return GL.UNSIGNED_INT;
9105
- case "sint32":
9106
- return GL.INT;
9107
- case "float16":
9108
- return GL.HALF_FLOAT;
9109
- case "float32":
9110
- return GL.FLOAT;
9111
- default:
9112
- return GL.UNSIGNED_BYTE;
9113
- }
9114
- }
9115
9548
 
9116
9549
  // ../webgl/src/adapter/device-helpers/device-features.ts
9117
9550
  function getDeviceFeatures(gl) {
@@ -10547,17 +10980,17 @@ void main(void) {}`;
10547
10980
  }
10548
10981
 
10549
10982
  // ../webgl/src/adapter/objects/constants-to-keys.ts
10550
- function getKeyValue(gl, name) {
10551
- if (typeof name !== "string") {
10552
- return name;
10983
+ function getKeyValue(gl, name2) {
10984
+ if (typeof name2 !== "string") {
10985
+ return name2;
10553
10986
  }
10554
- const number = Number(name);
10987
+ const number = Number(name2);
10555
10988
  if (!isNaN(number)) {
10556
10989
  return number;
10557
10990
  }
10558
- name = name.replace(/^.*\./, "");
10559
- const value = gl[name];
10560
- assert2(value !== void 0, `Accessing undefined constant GL.${name}`);
10991
+ name2 = name2.replace(/^.*\./, "");
10992
+ const value = gl[name2];
10993
+ assert2(value !== void 0, `Accessing undefined constant GL.${name2}`);
10561
10994
  return value;
10562
10995
  }
10563
10996
 
@@ -11984,7 +12417,7 @@ ${formattedLog}`)();
11984
12417
  // });
11985
12418
  };
11986
12419
 
11987
- // ../webgl/src/adapter/helpers/uniforms.ts
12420
+ // ../webgl/src/adapter/helpers/decode-webgl-types.ts
11988
12421
  function isSamplerUniform(type) {
11989
12422
  return SAMPLER_TYPES.includes(type);
11990
12423
  }
@@ -12002,10 +12435,11 @@ ${formattedLog}`)();
12002
12435
  [GL.UNSIGNED_INT_VEC2]: [GL.UNSIGNED_INT, 2, "uvec2", "vec2<u32>", "uint32x2"],
12003
12436
  [GL.UNSIGNED_INT_VEC3]: [GL.UNSIGNED_INT, 3, "uvec3", "vec3<u32>", "uint32x3"],
12004
12437
  [GL.UNSIGNED_INT_VEC4]: [GL.UNSIGNED_INT, 4, "uvec4", "vec4<u32>", "uint32x4"],
12005
- [GL.BOOL]: [GL.FLOAT, 1, "bool", "f32", "float32x2"],
12006
- [GL.BOOL_VEC2]: [GL.FLOAT, 2, "bvec2", "vec2<f32>"],
12007
- [GL.BOOL_VEC3]: [GL.FLOAT, 3, "bvec3", "vec3<f32>"],
12008
- [GL.BOOL_VEC4]: [GL.FLOAT, 4, "bvec4", "vec4<f32>"],
12438
+ [GL.BOOL]: [GL.FLOAT, 1, "bool", "f32", "float32"],
12439
+ [GL.BOOL_VEC2]: [GL.FLOAT, 2, "bvec2", "vec2<f32>", "float32x2"],
12440
+ [GL.BOOL_VEC3]: [GL.FLOAT, 3, "bvec3", "vec3<f32>", "float32x3"],
12441
+ [GL.BOOL_VEC4]: [GL.FLOAT, 4, "bvec4", "vec4<f32>", "float32x4"],
12442
+ // TODO - are sizes/components below correct?
12009
12443
  [GL.FLOAT_MAT2]: [GL.FLOAT, 8, "mat2", "mat2x2<f32>"],
12010
12444
  // 4
12011
12445
  [GL.FLOAT_MAT2x3]: [GL.FLOAT, 8, "mat2x3", "mat2x3<f32>"],
@@ -12025,8 +12459,8 @@ ${formattedLog}`)();
12025
12459
  [GL.FLOAT_MAT4]: [GL.FLOAT, 16, "mat4", "mat4x4<f32>"]
12026
12460
  // 16
12027
12461
  };
12028
- function decodeUniformType(uniformType) {
12029
- const typeAndSize = COMPOSITE_GL_TYPES[uniformType];
12462
+ function decodeGLUniformType(glUniformType) {
12463
+ const typeAndSize = COMPOSITE_GL_TYPES[glUniformType];
12030
12464
  if (!typeAndSize) {
12031
12465
  throw new Error("uniform");
12032
12466
  }
@@ -12037,68 +12471,27 @@ ${formattedLog}`)();
12037
12471
  glType
12038
12472
  };
12039
12473
  }
12040
- function decodeAttributeType(attributeType) {
12041
- const typeAndSize = COMPOSITE_GL_TYPES[attributeType];
12474
+ function decodeGLAttributeType(glAttributeType) {
12475
+ const typeAndSize = COMPOSITE_GL_TYPES[glAttributeType];
12042
12476
  if (!typeAndSize) {
12043
12477
  throw new Error("attribute");
12044
12478
  }
12045
- const [glType, components, , , format] = typeAndSize;
12479
+ const [, components, , shaderType, vertexFormat] = typeAndSize;
12480
+ const attributeType = shaderType;
12046
12481
  return {
12047
- format,
12048
- components,
12049
- glType
12482
+ attributeType,
12483
+ vertexFormat,
12484
+ components
12050
12485
  };
12051
12486
  }
12052
12487
 
12053
- // ../webgl/src/adapter/converters/vertex-formats.ts
12054
- function getVertexFormat(type, components) {
12055
- const base = getDataFormat(type);
12056
- switch (components) {
12057
- case 1:
12058
- return base;
12059
- case 2:
12060
- return `${base}x2`;
12061
- case 3:
12062
- return `${base}x3`;
12063
- case 4:
12064
- return `${base}x4`;
12065
- default:
12066
- throw new Error(String(components));
12067
- }
12068
- }
12069
- function getDataFormat(type) {
12070
- switch (type) {
12071
- case GL.INT:
12072
- return "sint32";
12073
- case GL.UNSIGNED_INT:
12074
- return "uint32";
12075
- case GL.FLOAT:
12076
- return "float32";
12077
- default:
12078
- throw new Error(String(type));
12079
- }
12080
- }
12081
-
12082
12488
  // ../webgl/src/adapter/helpers/get-shader-layout.ts
12083
12489
  function getShaderLayout(gl, program) {
12084
12490
  const shaderLayout = {
12085
12491
  attributes: [],
12086
12492
  bindings: []
12087
12493
  };
12088
- const attributes = readAttributeBindings(gl, program);
12089
- for (const attribute of attributes) {
12090
- const size = Math.min(attribute.accessor.size, 4);
12091
- const format = (
12092
- // attribute.accessor.format ||
12093
- getVertexFormat(attribute.accessor.type || GL.FLOAT, size)
12094
- );
12095
- shaderLayout.attributes.push({
12096
- name: attribute.name,
12097
- location: attribute.location,
12098
- format,
12099
- stepMode: attribute.accessor.divisor === 1 ? "instance" : "vertex"
12100
- });
12101
- }
12494
+ shaderLayout.attributes = readAttributeDeclarations(gl, program);
12102
12495
  const uniformBlocks = readUniformBlocks(gl, program);
12103
12496
  for (const uniformBlock of uniformBlocks) {
12104
12497
  const uniforms2 = uniformBlock.uniforms.map((uniform) => ({
@@ -12145,58 +12538,7 @@ ${formattedLog}`)();
12145
12538
  }
12146
12539
  return shaderLayout;
12147
12540
  }
12148
- function mergeShaderLayout(baseLayout, overrideLayout) {
12149
- const mergedLayout = {
12150
- ...baseLayout,
12151
- attributes: baseLayout.attributes.map((attribute) => ({
12152
- ...attribute
12153
- }))
12154
- };
12155
- for (const attribute of overrideLayout?.attributes || []) {
12156
- const baseAttribute = mergedLayout.attributes.find((attr) => attr.name === attribute.name);
12157
- if (!baseAttribute) {
12158
- log.warn(`shader layout attribute ${attribute.name} not present in shader`);
12159
- } else {
12160
- baseAttribute.format = attribute.format || baseAttribute.format;
12161
- baseAttribute.stepMode = attribute.stepMode || baseAttribute.stepMode;
12162
- }
12163
- }
12164
- return mergedLayout;
12165
- }
12166
- function mergeBufferMap(baseLayout, bufferMap) {
12167
- const mergedLayout = {
12168
- ...baseLayout,
12169
- attributes: baseLayout.attributes.map((attribute) => ({
12170
- ...attribute
12171
- }))
12172
- };
12173
- for (const bufferMapping of bufferMap) {
12174
- switch (bufferMapping.type) {
12175
- case "interleave":
12176
- for (const attributeOverride of bufferMapping.attributes) {
12177
- overrideShaderLayoutAttribute(mergedLayout, attributeOverride);
12178
- }
12179
- break;
12180
- default:
12181
- overrideShaderLayoutAttribute(mergedLayout, bufferMapping);
12182
- }
12183
- }
12184
- return mergedLayout;
12185
- }
12186
- function overrideShaderLayoutAttribute(layout, attributeOverride) {
12187
- const attribute = getAttributeFromLayout(layout, attributeOverride.name);
12188
- if (attribute && attributeOverride.format) {
12189
- attribute.format = attributeOverride.format;
12190
- }
12191
- }
12192
- function getAttributeFromLayout(shaderLayout, name) {
12193
- const attribute = shaderLayout.attributes.find((attr) => attr.name === name);
12194
- if (!attribute) {
12195
- log.warn(`shader layout attribute "${name}" not present in shader`);
12196
- }
12197
- return attribute || null;
12198
- }
12199
- function readAttributeBindings(gl, program) {
12541
+ function readAttributeDeclarations(gl, program) {
12200
12542
  const attributes = [];
12201
12543
  const count = gl.getProgramParameter(program, gl.ACTIVE_ATTRIBUTES);
12202
12544
  for (let index = 0; index < count; index++) {
@@ -12205,29 +12547,23 @@ ${formattedLog}`)();
12205
12547
  throw new Error("activeInfo");
12206
12548
  }
12207
12549
  const {
12208
- name,
12209
- type: compositeType,
12210
- size
12550
+ name: name2,
12551
+ type: compositeType
12552
+ /* , size*/
12211
12553
  } = activeInfo;
12212
- const location = gl.getAttribLocation(program, name);
12554
+ const location = gl.getAttribLocation(program, name2);
12213
12555
  if (location >= 0) {
12214
12556
  const {
12215
- glType,
12216
- components
12217
- } = decodeAttributeType(compositeType);
12218
- const accessor = {
12219
- type: glType,
12220
- size: size * components
12221
- };
12222
- if (/instance/i.test(name)) {
12223
- accessor.divisor = 1;
12224
- }
12225
- const attributeInfo = {
12557
+ attributeType
12558
+ } = decodeGLAttributeType(compositeType);
12559
+ const stepMode = /instance/i.test(name2) ? "instance" : "vertex";
12560
+ attributes.push({
12561
+ name: name2,
12226
12562
  location,
12227
- name,
12228
- accessor: new Accessor(accessor)
12229
- };
12230
- attributes.push(attributeInfo);
12563
+ stepMode,
12564
+ type: attributeType
12565
+ // size - for arrays, size is the number of elements in the array
12566
+ });
12231
12567
  }
12232
12568
  }
12233
12569
  attributes.sort((a, b) => a.location - b.location);
@@ -12246,21 +12582,21 @@ ${formattedLog}`)();
12246
12582
  throw new Error("activeInfo");
12247
12583
  }
12248
12584
  const {
12249
- name,
12585
+ name: name2,
12250
12586
  type: compositeType,
12251
12587
  size
12252
12588
  } = activeInfo;
12253
12589
  const {
12254
12590
  glType,
12255
12591
  components
12256
- } = decodeUniformType(compositeType);
12592
+ } = decodeGLUniformType(compositeType);
12257
12593
  const accessor = new Accessor({
12258
12594
  type: glType,
12259
12595
  size: size * components
12260
12596
  });
12261
12597
  const varying = {
12262
12598
  location,
12263
- name,
12599
+ name: name2,
12264
12600
  accessor
12265
12601
  };
12266
12602
  varyings.push(varying);
@@ -12282,14 +12618,14 @@ ${formattedLog}`)();
12282
12618
  type
12283
12619
  } = activeInfo;
12284
12620
  const {
12285
- name,
12621
+ name: name2,
12286
12622
  isArray: isArray3
12287
12623
  } = parseUniformName(rawName);
12288
- let webglLocation = gl.getUniformLocation(program, name);
12624
+ let webglLocation = gl.getUniformLocation(program, name2);
12289
12625
  const uniformInfo = {
12290
12626
  // WebGL locations are uniquely typed but just numbers
12291
12627
  location: webglLocation,
12292
- name,
12628
+ name: name2,
12293
12629
  size,
12294
12630
  type,
12295
12631
  isArray: isArray3
@@ -12297,7 +12633,7 @@ ${formattedLog}`)();
12297
12633
  uniforms.push(uniformInfo);
12298
12634
  if (uniformInfo.size > 1) {
12299
12635
  for (let j = 0; j < uniformInfo.size; j++) {
12300
- const elementName = `${name}[${j}]`;
12636
+ const elementName = `${name2}[${j}]`;
12301
12637
  webglLocation = gl.getUniformLocation(program, elementName);
12302
12638
  const arrayElementUniformInfo = {
12303
12639
  ...uniformInfo,
@@ -12340,7 +12676,7 @@ ${formattedLog}`)();
12340
12676
  }
12341
12677
  blockInfo.uniforms.push({
12342
12678
  name: activeInfo.name,
12343
- format: decodeUniformType(uniformType[i]).format,
12679
+ format: decodeGLUniformType(uniformType[i]).format,
12344
12680
  type: uniformType[i],
12345
12681
  arrayLength: uniformArrayLength[i],
12346
12682
  byteOffset: uniformOffset[i],
@@ -12382,18 +12718,18 @@ ${formattedLog}`)();
12382
12718
  sampleType
12383
12719
  };
12384
12720
  }
12385
- function parseUniformName(name) {
12386
- if (name[name.length - 1] !== "]") {
12721
+ function parseUniformName(name2) {
12722
+ if (name2[name2.length - 1] !== "]") {
12387
12723
  return {
12388
- name,
12724
+ name: name2,
12389
12725
  length: 1,
12390
12726
  isArray: false
12391
12727
  };
12392
12728
  }
12393
12729
  const UNIFORM_NAME_REGEXP = /([^[]*)(\[[0-9]+\])?/;
12394
- const matches = UNIFORM_NAME_REGEXP.exec(name);
12730
+ const matches = UNIFORM_NAME_REGEXP.exec(name2);
12395
12731
  if (!matches || matches.length < 2) {
12396
- throw new Error(`Failed to parse GLSL uniform name ${name}`);
12732
+ throw new Error(`Failed to parse GLSL uniform name ${name2}`);
12397
12733
  }
12398
12734
  return {
12399
12735
  name: matches[1],
@@ -12405,34 +12741,34 @@ ${formattedLog}`)();
12405
12741
  // ../webgl/src/adapter/helpers/set-uniform.ts
12406
12742
  function setUniform(gl, location, type, value) {
12407
12743
  const gl2 = gl;
12408
- if (typeof value === "number") {
12409
- switch (type) {
12410
- case GL.SAMPLER_2D:
12411
- case GL.SAMPLER_CUBE:
12412
- case GL.SAMPLER_3D:
12413
- case GL.SAMPLER_2D_SHADOW:
12414
- case GL.SAMPLER_2D_ARRAY:
12415
- case GL.SAMPLER_2D_ARRAY_SHADOW:
12416
- case GL.SAMPLER_CUBE_SHADOW:
12417
- case GL.INT_SAMPLER_2D:
12418
- case GL.INT_SAMPLER_3D:
12419
- case GL.INT_SAMPLER_CUBE:
12420
- case GL.INT_SAMPLER_2D_ARRAY:
12421
- case GL.UNSIGNED_INT_SAMPLER_2D:
12422
- case GL.UNSIGNED_INT_SAMPLER_3D:
12423
- case GL.UNSIGNED_INT_SAMPLER_CUBE:
12424
- case GL.UNSIGNED_INT_SAMPLER_2D_ARRAY:
12425
- return gl.uniform1i(location, value);
12426
- }
12427
- }
12428
- if (value === true) {
12429
- value = 1;
12430
- }
12431
- if (value === false) {
12432
- value = 0;
12433
- }
12434
- const arrayValue = typeof value === "number" ? [value] : value;
12744
+ let uniformValue = value;
12745
+ if (uniformValue === true) {
12746
+ uniformValue = 1;
12747
+ }
12748
+ if (uniformValue === false) {
12749
+ uniformValue = 0;
12750
+ }
12751
+ const arrayValue = typeof uniformValue === "number" ? [uniformValue] : uniformValue;
12435
12752
  switch (type) {
12753
+ case GL.SAMPLER_2D:
12754
+ case GL.SAMPLER_CUBE:
12755
+ case GL.SAMPLER_3D:
12756
+ case GL.SAMPLER_2D_SHADOW:
12757
+ case GL.SAMPLER_2D_ARRAY:
12758
+ case GL.SAMPLER_2D_ARRAY_SHADOW:
12759
+ case GL.SAMPLER_CUBE_SHADOW:
12760
+ case GL.INT_SAMPLER_2D:
12761
+ case GL.INT_SAMPLER_3D:
12762
+ case GL.INT_SAMPLER_CUBE:
12763
+ case GL.INT_SAMPLER_2D_ARRAY:
12764
+ case GL.UNSIGNED_INT_SAMPLER_2D:
12765
+ case GL.UNSIGNED_INT_SAMPLER_3D:
12766
+ case GL.UNSIGNED_INT_SAMPLER_CUBE:
12767
+ case GL.UNSIGNED_INT_SAMPLER_2D_ARRAY:
12768
+ if (typeof value !== "number") {
12769
+ throw new Error("samplers must be set to integers");
12770
+ }
12771
+ return gl.uniform1i(location, value);
12436
12772
  case GL.FLOAT:
12437
12773
  return gl.uniform1fv(location, arrayValue);
12438
12774
  case GL.FLOAT_VEC2:
@@ -12684,8 +13020,8 @@ ${formattedLog}`)();
12684
13020
  /** Handle to underlying WebGL program */
12685
13021
  /** vertex shader */
12686
13022
  /** fragment shader */
12687
- /** The merged layout */
12688
13023
  /** The layout extracted from shader by WebGL introspection APIs */
13024
+ /** The merged layout */
12689
13025
  /** Buffer map describing buffer interleaving etc */
12690
13026
  /** Uniforms set on this model */
12691
13027
  uniforms = {};
@@ -12722,9 +13058,8 @@ ${formattedLog}`)();
12722
13058
  }
12723
13059
  this._compileAndLink();
12724
13060
  this.introspectedLayout = getShaderLayout(this.device.gl, this.handle);
12725
- this.layout = mergeShaderLayout(this.introspectedLayout, props.layout);
12726
- this.bufferMap = props.bufferMap || [];
12727
- this.layout = mergeBufferMap(this.layout, this.bufferMap);
13061
+ this.shaderLayout = mergeShaderLayout(this.introspectedLayout, props.shaderLayout);
13062
+ this.bufferLayout = props.bufferLayout || [];
12728
13063
  this.vertexArrayObject = new WEBGLVertexArrayObject(this.device);
12729
13064
  }
12730
13065
  destroy() {
@@ -12739,70 +13074,75 @@ ${formattedLog}`)();
12739
13074
  this._indexBuffer = webglBuffer;
12740
13075
  }
12741
13076
  /** @todo needed for portable model */
12742
- setAttributes(attributes) {
12743
- for (const [name, buffer] of Object.entries(attributes)) {
12744
- const webglBuffer = cast(buffer);
12745
- const attribute = getAttributeLayout(this.layout, name);
12746
- if (!attribute) {
12747
- log.warn(`Ignoring buffer supplied for unknown attribute "${name}" in pipeline "${this.id}" (buffer "${buffer.id}")`)();
12748
- continue;
13077
+ setAttributes(buffers) {
13078
+ const attributeInfos = getAttributeInfosFromLayouts(this.shaderLayout, this.bufferLayout);
13079
+ for (const [bufferName, buffer] of Object.entries(buffers)) {
13080
+ let set = false;
13081
+ for (const attributeInfo of Object.values(attributeInfos)) {
13082
+ if (attributeInfo.bufferName !== bufferName) {
13083
+ continue;
13084
+ }
13085
+ const webglBuffer = cast(buffer);
13086
+ const glType = getGLFromVertexType(attributeInfo.bufferDataType);
13087
+ log.log(1, {
13088
+ setAttribute: attributeInfo.name,
13089
+ toBuffer: bufferName,
13090
+ size: attributeInfo.bufferComponents,
13091
+ type: glType,
13092
+ stride: attributeInfo.byteStride,
13093
+ offset: attributeInfo.byteOffset,
13094
+ normalized: attributeInfo.normalized,
13095
+ // it is the shader attribute declaration, not the vertex memory format,
13096
+ // that determines if the data in the buffer will be treated as integers.
13097
+ // /
13098
+ // Also note that WebGL supports assigning non-normalized integer data to floating point attributes,
13099
+ // but as far as we can tell, WebGPU does not.
13100
+ integer: attributeInfo.integer,
13101
+ divisor: attributeInfo.stepMode === "instance" ? 1 : 0
13102
+ })();
13103
+ this.vertexArrayObject.setBuffer(attributeInfo.location, webglBuffer, {
13104
+ size: attributeInfo.bufferComponents,
13105
+ type: glType,
13106
+ stride: attributeInfo.byteStride,
13107
+ offset: attributeInfo.byteOffset,
13108
+ normalized: attributeInfo.normalized,
13109
+ // it is the shader attribute declaration, not the vertex memory format,
13110
+ // that determines if the data in the buffer will be treated as integers.
13111
+ // /
13112
+ // Also note that WebGL supports assigning non-normalized integer data to floating point attributes,
13113
+ // but as far as we can tell, WebGPU does not.
13114
+ integer: attributeInfo.integer,
13115
+ divisor: attributeInfo.stepMode === "instance" ? 1 : 0
13116
+ });
13117
+ set = true;
13118
+ }
13119
+ if (!set) {
13120
+ log.warn(`setAttributes(): Ignoring (buffer "${buffer.id}" for unknown attribute "${name}" in pipeline "${this.id}"`)();
12749
13121
  }
12750
- const decoded = decodeVertexFormat(attribute.format);
12751
- const {
12752
- type: typeString,
12753
- components: size,
12754
- byteLength: stride,
12755
- normalized
12756
- /* , integer*/
12757
- } = decoded;
12758
- const divisor = attribute.stepMode === "instance" ? 1 : 0;
12759
- const type = getWebGLDataType(typeString);
12760
- this.vertexArrayObject.setBuffer(attribute.location, webglBuffer, {
12761
- size,
12762
- type,
12763
- stride,
12764
- offset: 0,
12765
- normalized,
12766
- // it is the shader attribute declaration, not the vertex memory format,
12767
- // that determines if the data in the buffer will be treated as integers.
12768
- // /
12769
- // Also note that WebGL supports assigning non-normalized integer data to floating point attributes,
12770
- // but as far as we can tell, WebGPU does not.
12771
- integer: false,
12772
- divisor
12773
- });
12774
13122
  }
12775
13123
  }
12776
13124
  /**
12777
13125
  * Constant attributes are only supported in WebGL, not in WebGPU
12778
13126
  * Any attribute that is disabled in the current vertex array object
12779
13127
  * is read from the context's global constant value for that attribute location.
12780
- * @param attributes
13128
+ * @param attributes
12781
13129
  */
12782
13130
  setConstantAttributes(attributes) {
12783
- for (const [name, value] of Object.entries(attributes)) {
12784
- const attribute = getAttributeLayout(this.layout, name);
12785
- if (!attribute) {
12786
- log.warn(`Ignoring constant value supplied for unknown attribute "${name}" in pipeline "${this.id}"`)();
12787
- continue;
12788
- }
12789
- this.vertexArrayObject.setConstant(attribute.location, value);
12790
- }
12791
13131
  Object.assign(this.constantAttributes, attributes);
12792
13132
  }
12793
- /**
13133
+ /**
12794
13134
  * Bindings include: textures, samplers and uniform buffers
12795
- * @todo needed for portable model
13135
+ * @todo needed for portable model
12796
13136
  */
12797
13137
  setBindings(bindings) {
12798
- for (const [name, value] of Object.entries(bindings)) {
12799
- const binding = this.layout.bindings.find((binding2) => binding2.name === name);
13138
+ for (const [name2, value] of Object.entries(bindings)) {
13139
+ const binding = this.shaderLayout.bindings.find((binding2) => binding2.name === name2);
12800
13140
  if (!binding) {
12801
- log.warn(`Unknown binding ${name} in render pipeline ${this.id}`)();
13141
+ log.warn(`Unknown binding ${name2} in render pipeline ${this.id}`)();
12802
13142
  continue;
12803
13143
  }
12804
13144
  if (!value) {
12805
- log.warn(`Unsetting binding ${name} in render pipeline ${this.id}`)();
13145
+ log.warn(`Unsetting binding ${name2} in render pipeline ${this.id}`)();
12806
13146
  }
12807
13147
  switch (binding.type) {
12808
13148
  case "uniform":
@@ -12816,12 +13156,12 @@ ${formattedLog}`)();
12816
13156
  }
12817
13157
  break;
12818
13158
  case "sampler":
12819
- log.warn(`Ignoring sampler ${name}`)();
13159
+ log.warn(`Ignoring sampler ${name2}`)();
12820
13160
  break;
12821
13161
  default:
12822
13162
  throw new Error(binding.type);
12823
13163
  }
12824
- this.bindings[name] = value;
13164
+ this.bindings[name2] = value;
12825
13165
  }
12826
13166
  }
12827
13167
  setUniforms(uniforms) {
@@ -12842,7 +13182,7 @@ ${formattedLog}`)();
12842
13182
  // firstInstance,
12843
13183
  // baseVertex
12844
13184
  } = options;
12845
- const drawMode = getDrawMode(this.props.topology);
13185
+ const drawMode = getGLDrawMode(this.props.topology);
12846
13186
  const isIndexed = Boolean(this._indexBuffer);
12847
13187
  const indexType = this._indexBuffer?.glIndexType;
12848
13188
  const isInstanced = Number(options.instanceCount) > 0;
@@ -12928,7 +13268,24 @@ ${formattedLog}`)();
12928
13268
  }
12929
13269
  return texturesRenderable;
12930
13270
  }
12931
- /** Apply any bindings */
13271
+ /**
13272
+ * Constant attributes need to be reset before every draw call
13273
+ * Any attribute that is disabled in the current vertex array object
13274
+ * is read from the context's global constant value for that attribute location.
13275
+ * @note Constant attributes are only supported in WebGL, not in WebGPU
13276
+ */
13277
+ _applyConstantAttributes() {
13278
+ const attributeInfos = getAttributeInfosFromLayouts(this.shaderLayout, this.bufferLayout);
13279
+ for (const [name2, value] of Object.entries(this.constantAttributes)) {
13280
+ const attributeInfo = attributeInfos[name2];
13281
+ if (!attributeInfo) {
13282
+ log.warn(`Ignoring constant value supplied for unknown attribute "${name2}" in pipeline "${this.id}"`)();
13283
+ continue;
13284
+ }
13285
+ this.vertexArrayObject.setConstant(attributeInfo.location, value);
13286
+ }
13287
+ }
13288
+ /** Apply any bindings (before each draw call) */
12932
13289
  _applyBindings() {
12933
13290
  this.device.gl.useProgram(this.handle);
12934
13291
  const {
@@ -12939,7 +13296,7 @@ ${formattedLog}`)();
12939
13296
  }
12940
13297
  let textureUnit = 0;
12941
13298
  let uniformBufferIndex = 0;
12942
- for (const binding of this.layout.bindings) {
13299
+ for (const binding of this.shaderLayout.bindings) {
12943
13300
  const value = this.bindings[binding.name];
12944
13301
  if (!value) {
12945
13302
  throw new Error(`No value for binding ${binding.name} in ${this.id}`);
@@ -12947,11 +13304,11 @@ ${formattedLog}`)();
12947
13304
  switch (binding.type) {
12948
13305
  case "uniform":
12949
13306
  const {
12950
- name
13307
+ name: name2
12951
13308
  } = binding;
12952
- const location = gl2.getUniformBlockIndex(this.handle, name);
13309
+ const location = gl2.getUniformBlockIndex(this.handle, name2);
12953
13310
  if (location === GL.INVALID_INDEX) {
12954
- throw new Error(`Invalid uniform block name ${name}`);
13311
+ throw new Error(`Invalid uniform block name ${name2}`);
12955
13312
  }
12956
13313
  gl2.uniformBlockBinding(this.handle, uniformBufferIndex, location);
12957
13314
  if (value instanceof WEBGLBuffer) {
@@ -12978,37 +13335,26 @@ ${formattedLog}`)();
12978
13335
  }
12979
13336
  }
12980
13337
  }
13338
+ /**
13339
+ * Due to program sharing, uniforms need to be reset before every draw call
13340
+ * (though caching will avoid redundant WebGL calls)
13341
+ */
12981
13342
  _applyUniforms() {
12982
- for (const uniformLayout of this.layout.uniforms || []) {
13343
+ for (const uniformLayout of this.shaderLayout.uniforms || []) {
12983
13344
  const {
12984
- name,
13345
+ name: name2,
12985
13346
  location,
12986
13347
  type,
12987
13348
  textureUnit
12988
13349
  } = uniformLayout;
12989
- const value = this.uniforms[name] ?? textureUnit;
13350
+ const value = this.uniforms[name2] ?? textureUnit;
12990
13351
  if (value !== void 0) {
12991
13352
  setUniform(this.device.gl, location, type, value);
12992
13353
  }
12993
13354
  }
12994
13355
  }
12995
- /**
12996
- * Constant attributes are only supported in WebGL, not in WebGPU
12997
- * Any attribute that is disabled in the current vertex array object
12998
- * is read from the context's global constant value for that attribute location.
12999
- */
13000
- _applyConstantAttributes() {
13001
- for (const [name, value] of Object.entries(this.constantAttributes)) {
13002
- const attribute = getAttributeLayout(this.layout, name);
13003
- if (!attribute) {
13004
- log.warn(`Ignoring constant value supplied for unknown attribute "${name}" in pipeline "${this.id}"`)();
13005
- continue;
13006
- }
13007
- this.vertexArrayObject.setConstant(attribute.location, value);
13008
- }
13009
- }
13010
13356
  };
13011
- function getDrawMode(topology) {
13357
+ function getGLDrawMode(topology) {
13012
13358
  switch (topology) {
13013
13359
  case "point-list":
13014
13360
  return GL.POINTS;
@@ -13048,9 +13394,6 @@ ${formattedLog}`)();
13048
13394
  throw new Error(topology);
13049
13395
  }
13050
13396
  }
13051
- function getAttributeLayout(layout, name) {
13052
- return layout.attributes.find((binding) => binding.name === name) || null;
13053
- }
13054
13397
 
13055
13398
  // ../webgl/src/adapter/resources/webgl-command-buffer.ts
13056
13399
  function cast2(value) {
@@ -13251,7 +13594,7 @@ ${formattedLog}`)();
13251
13594
  // ../webgl/src/adapter/resources/webgl-command-encoder.ts
13252
13595
  var WEBGLCommandEncoder = class extends CommandEncoder {
13253
13596
  constructor(device, props) {
13254
- super(props);
13597
+ super(device, props);
13255
13598
  this.device = device;
13256
13599
  this.commandBuffer = new WEBGLCommandBuffer(device);
13257
13600
  }