@openspecui/web 0.9.3 → 1.0.0

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 (89) hide show
  1. package/dist/assets/BufferResource-CVUoegR6.js +185 -0
  2. package/dist/assets/CanvasRenderer-BEIcB8i1.js +1 -0
  3. package/dist/assets/Filter-Bu_qhr6H.js +1 -0
  4. package/dist/assets/RenderTargetSystem-DWouFDxU.js +172 -0
  5. package/dist/assets/WebGLRenderer-6FH_N1FV.js +156 -0
  6. package/dist/assets/WebGPURenderer-B8sJk3Sv.js +41 -0
  7. package/dist/assets/browserAll-CLKeV1yb.js +14 -0
  8. package/dist/assets/gemini-Bk-V9kKu.png +0 -0
  9. package/dist/assets/{index-Bp00uZNc.js → index-BE5-y0_g.js} +1 -1
  10. package/{dist-ssg/client/assets/index-CCfVkFzN.js → dist/assets/index-BPCTI2mG.js} +1 -1
  11. package/dist/assets/{index-BsTieXqQ.js → index-BRp8MJ9v.js} +1 -1
  12. package/dist/assets/{index-8c6bEJ99.js → index-BlZ-sasH.js} +1 -1
  13. package/dist/assets/{index-Bafja8o4.js → index-Bp_dnlLF.js} +1 -1
  14. package/{dist-ssg/client/assets/index-ftYom_wU.js → dist/assets/index-BtNuxyw4.js} +1 -1
  15. package/dist/assets/index-Bv7pWR8R.js +7 -0
  16. package/{dist-ssg/client/assets/index-D3mXuuih.js → dist/assets/index-Byr3HkRi.js} +1 -1
  17. package/dist/assets/index-CEHMo0EU.js +1385 -0
  18. package/dist/assets/{index-eA_XNQ_L.js → index-CEKSUzvw.js} +1 -1
  19. package/dist/assets/index-CEf9wXLh.css +1 -0
  20. package/{dist-ssg/client/assets/index-ArhptQw0.js → dist/assets/index-CX13iBBs.js} +1 -1
  21. package/dist/assets/index-CoOT7eZ9.js +1 -0
  22. package/{dist-ssg/client/assets/index-B1hpa--1.js → dist/assets/index-D4AU46yO.js} +1 -1
  23. package/dist/assets/{index-BvGAWAqS.js → index-DXRZmZm8.js} +1 -1
  24. package/{dist-ssg/client/assets/index-AbWe21oh.js → dist/assets/index-eQZwF8qE.js} +1 -1
  25. package/dist/assets/{index-gvPT4BlL.js → index-mWXhCp9j.js} +1 -1
  26. package/dist/assets/webworkerAll-DjWoTx9g.js +83 -0
  27. package/dist/index.html +2 -2
  28. package/dist-ssg/client/.vite/ssr-manifest.json +3094 -504
  29. package/dist-ssg/client/assets/BufferResource-CVUoegR6.js +185 -0
  30. package/dist-ssg/client/assets/CanvasRenderer-BEIcB8i1.js +1 -0
  31. package/dist-ssg/client/assets/Filter-Bu_qhr6H.js +1 -0
  32. package/dist-ssg/client/assets/RenderTargetSystem-DWouFDxU.js +172 -0
  33. package/dist-ssg/client/assets/WebGLRenderer-6FH_N1FV.js +156 -0
  34. package/dist-ssg/client/assets/WebGPURenderer-B8sJk3Sv.js +41 -0
  35. package/dist-ssg/client/assets/browserAll-CLKeV1yb.js +14 -0
  36. package/dist-ssg/client/assets/gemini-Bk-V9kKu.png +0 -0
  37. package/dist-ssg/client/assets/{index-Bp00uZNc.js → index-BE5-y0_g.js} +1 -1
  38. package/{dist/assets/index-CCfVkFzN.js → dist-ssg/client/assets/index-BPCTI2mG.js} +1 -1
  39. package/dist-ssg/client/assets/{index-BsTieXqQ.js → index-BRp8MJ9v.js} +1 -1
  40. package/dist-ssg/client/assets/{index-8c6bEJ99.js → index-BlZ-sasH.js} +1 -1
  41. package/dist-ssg/client/assets/{index-Bafja8o4.js → index-Bp_dnlLF.js} +1 -1
  42. package/{dist/assets/index-ftYom_wU.js → dist-ssg/client/assets/index-BtNuxyw4.js} +1 -1
  43. package/dist-ssg/client/assets/index-Bv7pWR8R.js +7 -0
  44. package/{dist/assets/index-D3mXuuih.js → dist-ssg/client/assets/index-Byr3HkRi.js} +1 -1
  45. package/dist-ssg/client/assets/index-CEHMo0EU.js +1385 -0
  46. package/dist-ssg/client/assets/{index-eA_XNQ_L.js → index-CEKSUzvw.js} +1 -1
  47. package/dist-ssg/client/assets/index-CEf9wXLh.css +1 -0
  48. package/{dist/assets/index-ArhptQw0.js → dist-ssg/client/assets/index-CX13iBBs.js} +1 -1
  49. package/dist-ssg/client/assets/index-CoOT7eZ9.js +1 -0
  50. package/{dist/assets/index-B1hpa--1.js → dist-ssg/client/assets/index-D4AU46yO.js} +1 -1
  51. package/dist-ssg/client/assets/{index-BvGAWAqS.js → index-DXRZmZm8.js} +1 -1
  52. package/{dist/assets/index-AbWe21oh.js → dist-ssg/client/assets/index-eQZwF8qE.js} +1 -1
  53. package/dist-ssg/client/assets/{index-gvPT4BlL.js → index-mWXhCp9j.js} +1 -1
  54. package/dist-ssg/client/assets/webworkerAll-DjWoTx9g.js +83 -0
  55. package/dist-ssg/client/index.html +2 -2
  56. package/dist-ssg/server/assets/BufferResource-BXrsGVSz.js +592 -0
  57. package/dist-ssg/server/assets/CanvasRenderer-D9aMd7WV.js +1530 -0
  58. package/dist-ssg/server/assets/Filter-ClU0-pLL.js +80 -0
  59. package/dist-ssg/server/assets/RenderTargetSystem-CVz6i60H.js +3037 -0
  60. package/dist-ssg/server/assets/WebGLRenderer-B0I5TP5d.js +3887 -0
  61. package/dist-ssg/server/assets/WebGPURenderer-DCgUFny7.js +2146 -0
  62. package/dist-ssg/server/assets/browserAll-BixK1BYs.js +2691 -0
  63. package/dist-ssg/server/assets/{index-BUANIFyF.js → index-3uSTc-o9.js} +3 -1
  64. package/dist-ssg/server/assets/{index-D0JVKGRJ.js → index-8uE7RyRi.js} +3 -1
  65. package/dist-ssg/server/assets/{index-DCGDP0cs.js → index-BDzDVVaf.js} +2 -0
  66. package/dist-ssg/server/assets/{index-oPcprgZH.js → index-BkJYfA64.js} +3 -1
  67. package/dist-ssg/server/assets/{index-CAP0cmVO.js → index-BvGNqnLD.js} +3 -1
  68. package/dist-ssg/server/assets/{index-DsfT46da.js → index-BvURgefh.js} +3 -1
  69. package/dist-ssg/server/assets/{index-Dk9q2o0C.js → index-C2CuXbSQ.js} +3 -1
  70. package/dist-ssg/server/assets/{index-Cmnd0jiw.js → index-C3RtR5EA.js} +3 -1
  71. package/dist-ssg/server/assets/{index-CFKaffPZ.js → index-CZtnphnE.js} +3 -1
  72. package/dist-ssg/server/assets/{index-D6n8WPGB.js → index-D0DRToHj.js} +3 -1
  73. package/dist-ssg/server/assets/{index-mJoWrrNO.js → index-D5MdLWau.js} +3 -1
  74. package/dist-ssg/server/assets/{index-Brcpp_nj.js → index-DBYODvy4.js} +3 -1
  75. package/dist-ssg/server/assets/{index-DYmgiM6_.js → index-DL23PkQi.js} +3 -1
  76. package/dist-ssg/server/assets/{index-CnRKREoz.js → index-DfcLdBOi.js} +3 -1
  77. package/dist-ssg/server/assets/{index-Bzw5T-vd.js → index-O2XMojWG.js} +3 -1
  78. package/dist-ssg/server/assets/init-CnkBvt-J.js +666 -0
  79. package/dist-ssg/server/assets/webworkerAll-DNiMFaVV.js +12 -0
  80. package/dist-ssg/server/entry-server.js +87120 -34846
  81. package/package.json +23 -5
  82. package/dist/assets/index-D-Urq2hl.css +0 -1
  83. package/dist/assets/index-DFOLYN6W.js +0 -1
  84. package/dist/assets/index-DpxkOmNJ.js +0 -7
  85. package/dist/assets/index-YZ-iXB95.js +0 -309
  86. package/dist-ssg/client/assets/index-D-Urq2hl.css +0 -1
  87. package/dist-ssg/client/assets/index-DFOLYN6W.js +0 -1
  88. package/dist-ssg/client/assets/index-DpxkOmNJ.js +0 -7
  89. package/dist-ssg/client/assets/index-YZ-iXB95.js +0 -309
@@ -0,0 +1,2146 @@
1
+ import { r as State, ad as getTextureBatchBindGroup, y as ExtensionType, ae as GCManagedHash, W as uid, af as fastCopy, X as DOMAdapter, K as STENCIL_MODES, Q as BufferUsage, P as Buffer, B as BindGroup, ag as createIdFromString, D as warn, ah as CLEAR, a6 as CanvasSource, ai as TextureSource, U as UniformGroup, aj as CanvasPool, M as Matrix, ak as compileHighShaderGpuProgram, al as colorBit, am as generateTextureBatchBit, an as roundPixelsBit, S as Shader, z as Texture, a7 as AbstractRenderer, R as RendererType, H as extensions } from "../entry-server.js";
2
+ import { c as createUboSyncFunction, u as uboSyncFunctionsWGSL, U as UboSystem, B as BufferResource, G as GpuStencilModesToPixi, e as ensureAttributes, l as localUniformBitGroup2, a as localUniformBit, t as textureBit } from "./BufferResource-BXrsGVSz.js";
3
+ import { R as RenderTargetSystem, S as SharedSystems, d as SharedRenderPipes } from "./RenderTargetSystem-CVz6i60H.js";
4
+ import "util";
5
+ import "crypto";
6
+ import "async_hooks";
7
+ import "stream";
8
+ import "process";
9
+ import "buffer";
10
+ import "node:process";
11
+ import "node:path";
12
+ import "node:url";
13
+ import "./Filter-ClU0-pLL.js";
14
+ const tempState = State.for2d();
15
+ class GpuBatchAdaptor {
16
+ start(batchPipe, geometry, shader) {
17
+ const renderer = batchPipe.renderer;
18
+ const encoder = renderer.encoder;
19
+ const program = shader.gpuProgram;
20
+ this._shader = shader;
21
+ this._geometry = geometry;
22
+ encoder.setGeometry(geometry, program);
23
+ tempState.blendMode = "normal";
24
+ renderer.pipeline.getPipeline(
25
+ geometry,
26
+ program,
27
+ tempState
28
+ );
29
+ const globalUniformsBindGroup = renderer.globalUniforms.bindGroup;
30
+ encoder.resetBindGroup(1);
31
+ encoder.setBindGroup(0, globalUniformsBindGroup, program);
32
+ }
33
+ execute(batchPipe, batch) {
34
+ const program = this._shader.gpuProgram;
35
+ const renderer = batchPipe.renderer;
36
+ const encoder = renderer.encoder;
37
+ if (!batch.bindGroup) {
38
+ const textureBatch = batch.textures;
39
+ batch.bindGroup = getTextureBatchBindGroup(
40
+ textureBatch.textures,
41
+ textureBatch.count,
42
+ renderer.limits.maxBatchableTextures
43
+ );
44
+ }
45
+ tempState.blendMode = batch.blendMode;
46
+ const gpuBindGroup = renderer.bindGroup.getBindGroup(
47
+ batch.bindGroup,
48
+ program,
49
+ 1
50
+ );
51
+ const pipeline = renderer.pipeline.getPipeline(
52
+ this._geometry,
53
+ program,
54
+ tempState,
55
+ batch.topology
56
+ );
57
+ batch.bindGroup._touch(renderer.gc.now, renderer.tick);
58
+ encoder.setPipeline(pipeline);
59
+ encoder.renderPassEncoder.setBindGroup(1, gpuBindGroup);
60
+ encoder.renderPassEncoder.drawIndexed(batch.size, 1, batch.start);
61
+ }
62
+ }
63
+ GpuBatchAdaptor.extension = {
64
+ type: [
65
+ ExtensionType.WebGPUPipesAdaptor
66
+ ],
67
+ name: "batch"
68
+ };
69
+ class BindGroupSystem {
70
+ constructor(renderer) {
71
+ this._hash = /* @__PURE__ */ Object.create(null);
72
+ this._renderer = renderer;
73
+ }
74
+ contextChange(gpu) {
75
+ this._gpu = gpu;
76
+ }
77
+ getBindGroup(bindGroup, program, groupIndex) {
78
+ bindGroup._updateKey();
79
+ const gpuBindGroup = this._hash[bindGroup._key] || this._createBindGroup(bindGroup, program, groupIndex);
80
+ return gpuBindGroup;
81
+ }
82
+ _createBindGroup(group, program, groupIndex) {
83
+ const device = this._gpu.device;
84
+ const groupLayout = program.layout[groupIndex];
85
+ const entries = [];
86
+ const renderer = this._renderer;
87
+ for (const j in groupLayout) {
88
+ const resource = group.resources[j] ?? group.resources[groupLayout[j]];
89
+ let gpuResource;
90
+ if (resource._resourceType === "uniformGroup") {
91
+ const uniformGroup = resource;
92
+ renderer.ubo.updateUniformGroup(uniformGroup);
93
+ const buffer = uniformGroup.buffer;
94
+ gpuResource = {
95
+ buffer: renderer.buffer.getGPUBuffer(buffer),
96
+ offset: 0,
97
+ size: buffer.descriptor.size
98
+ };
99
+ } else if (resource._resourceType === "buffer") {
100
+ const buffer = resource;
101
+ gpuResource = {
102
+ buffer: renderer.buffer.getGPUBuffer(buffer),
103
+ offset: 0,
104
+ size: buffer.descriptor.size
105
+ };
106
+ } else if (resource._resourceType === "bufferResource") {
107
+ const bufferResource = resource;
108
+ gpuResource = {
109
+ buffer: renderer.buffer.getGPUBuffer(bufferResource.buffer),
110
+ offset: bufferResource.offset,
111
+ size: bufferResource.size
112
+ };
113
+ } else if (resource._resourceType === "textureSampler") {
114
+ const sampler = resource;
115
+ gpuResource = renderer.texture.getGpuSampler(sampler);
116
+ } else if (resource._resourceType === "textureSource") {
117
+ const texture = resource;
118
+ gpuResource = renderer.texture.getTextureView(texture);
119
+ }
120
+ entries.push({
121
+ binding: groupLayout[j],
122
+ resource: gpuResource
123
+ });
124
+ }
125
+ const layout = renderer.shader.getProgramData(program).bindGroups[groupIndex];
126
+ const gpuBindGroup = device.createBindGroup({
127
+ layout,
128
+ entries
129
+ });
130
+ this._hash[group._key] = gpuBindGroup;
131
+ return gpuBindGroup;
132
+ }
133
+ destroy() {
134
+ this._hash = null;
135
+ this._renderer = null;
136
+ }
137
+ }
138
+ BindGroupSystem.extension = {
139
+ type: [
140
+ ExtensionType.WebGPUSystem
141
+ ],
142
+ name: "bindGroup"
143
+ };
144
+ class GpuBufferData {
145
+ constructor(gpuBuffer) {
146
+ this.gpuBuffer = gpuBuffer;
147
+ }
148
+ destroy() {
149
+ this.gpuBuffer.destroy();
150
+ this.gpuBuffer = null;
151
+ }
152
+ }
153
+ class GpuBufferSystem {
154
+ constructor(renderer) {
155
+ this._renderer = renderer;
156
+ this._managedBuffers = new GCManagedHash({
157
+ renderer,
158
+ type: "resource",
159
+ onUnload: this.onBufferUnload.bind(this),
160
+ name: "gpuBuffer"
161
+ });
162
+ }
163
+ contextChange(gpu) {
164
+ this._gpu = gpu;
165
+ }
166
+ getGPUBuffer(buffer) {
167
+ buffer._gcLastUsed = this._renderer.gc.now;
168
+ return buffer._gpuData[this._renderer.uid]?.gpuBuffer || this.createGPUBuffer(buffer);
169
+ }
170
+ updateBuffer(buffer) {
171
+ const gpuBuffer = this.getGPUBuffer(buffer);
172
+ const data = buffer.data;
173
+ if (buffer._updateID && data) {
174
+ buffer._updateID = 0;
175
+ this._gpu.device.queue.writeBuffer(
176
+ gpuBuffer,
177
+ 0,
178
+ data.buffer,
179
+ 0,
180
+ // round to the nearest 4 bytes
181
+ (buffer._updateSize || data.byteLength) + 3 & -4
182
+ );
183
+ }
184
+ return gpuBuffer;
185
+ }
186
+ /** dispose all WebGL resources of all managed buffers */
187
+ destroyAll() {
188
+ this._managedBuffers.removeAll();
189
+ }
190
+ onBufferUnload(buffer) {
191
+ buffer.off("update", this.updateBuffer, this);
192
+ buffer.off("change", this.onBufferChange, this);
193
+ }
194
+ createGPUBuffer(buffer) {
195
+ const gpuBuffer = this._gpu.device.createBuffer(buffer.descriptor);
196
+ buffer._updateID = 0;
197
+ buffer._resourceId = uid("resource");
198
+ if (buffer.data) {
199
+ fastCopy(
200
+ buffer.data.buffer,
201
+ gpuBuffer.getMappedRange(),
202
+ buffer.data.byteOffset,
203
+ buffer.data.byteLength
204
+ );
205
+ gpuBuffer.unmap();
206
+ }
207
+ buffer._gpuData[this._renderer.uid] = new GpuBufferData(gpuBuffer);
208
+ if (this._managedBuffers.add(buffer)) {
209
+ buffer.on("update", this.updateBuffer, this);
210
+ buffer.on("change", this.onBufferChange, this);
211
+ }
212
+ return gpuBuffer;
213
+ }
214
+ onBufferChange(buffer) {
215
+ this._managedBuffers.remove(buffer);
216
+ buffer._updateID = 0;
217
+ this.createGPUBuffer(buffer);
218
+ }
219
+ destroy() {
220
+ this._managedBuffers.destroy();
221
+ this._renderer = null;
222
+ this._gpu = null;
223
+ }
224
+ }
225
+ GpuBufferSystem.extension = {
226
+ type: [
227
+ ExtensionType.WebGPUSystem
228
+ ],
229
+ name: "buffer"
230
+ };
231
+ class UboBatch {
232
+ constructor({ minUniformOffsetAlignment: minUniformOffsetAlignment2 }) {
233
+ this._minUniformOffsetAlignment = 256;
234
+ this.byteIndex = 0;
235
+ this._minUniformOffsetAlignment = minUniformOffsetAlignment2;
236
+ this.data = new Float32Array(65535);
237
+ }
238
+ clear() {
239
+ this.byteIndex = 0;
240
+ }
241
+ addEmptyGroup(size) {
242
+ if (size > this._minUniformOffsetAlignment / 4) {
243
+ throw new Error(`UniformBufferBatch: array is too large: ${size * 4}`);
244
+ }
245
+ const start = this.byteIndex;
246
+ let newSize = start + size * 4;
247
+ newSize = Math.ceil(newSize / this._minUniformOffsetAlignment) * this._minUniformOffsetAlignment;
248
+ if (newSize > this.data.length * 4) {
249
+ throw new Error("UniformBufferBatch: ubo batch got too big");
250
+ }
251
+ this.byteIndex = newSize;
252
+ return start;
253
+ }
254
+ addGroup(array) {
255
+ const offset = this.addEmptyGroup(array.length);
256
+ for (let i = 0; i < array.length; i++) {
257
+ this.data[offset / 4 + i] = array[i];
258
+ }
259
+ return offset;
260
+ }
261
+ destroy() {
262
+ this.data = null;
263
+ }
264
+ }
265
+ class GpuColorMaskSystem {
266
+ constructor(renderer) {
267
+ this._colorMaskCache = 15;
268
+ this._renderer = renderer;
269
+ }
270
+ setMask(colorMask) {
271
+ if (this._colorMaskCache === colorMask) return;
272
+ this._colorMaskCache = colorMask;
273
+ this._renderer.pipeline.setColorMask(colorMask);
274
+ }
275
+ destroy() {
276
+ this._renderer = null;
277
+ this._colorMaskCache = null;
278
+ }
279
+ }
280
+ GpuColorMaskSystem.extension = {
281
+ type: [
282
+ ExtensionType.WebGPUSystem
283
+ ],
284
+ name: "colorMask"
285
+ };
286
+ class GpuDeviceSystem {
287
+ /**
288
+ * @param {WebGPURenderer} renderer - The renderer this System works for.
289
+ */
290
+ constructor(renderer) {
291
+ this._renderer = renderer;
292
+ }
293
+ async init(options) {
294
+ if (this._initPromise) return this._initPromise;
295
+ this._initPromise = (options.gpu ? Promise.resolve(options.gpu) : this._createDeviceAndAdaptor(options)).then((gpu) => {
296
+ this.gpu = gpu;
297
+ this._renderer.runners.contextChange.emit(this.gpu);
298
+ });
299
+ return this._initPromise;
300
+ }
301
+ /**
302
+ * Handle the context change event
303
+ * @param gpu
304
+ */
305
+ contextChange(gpu) {
306
+ this._renderer.gpu = gpu;
307
+ }
308
+ /**
309
+ * Helper class to create a WebGL Context
310
+ * @param {object} options - An options object that gets passed in to the canvas element containing the
311
+ * context attributes
312
+ * @see https://developer.mozilla.org/en/docs/Web/API/HTMLCanvasElement/getContext
313
+ * @returns {WebGLRenderingContext} the WebGL context
314
+ */
315
+ async _createDeviceAndAdaptor(options) {
316
+ const adapter = await DOMAdapter.get().getNavigator().gpu.requestAdapter({
317
+ powerPreference: options.powerPreference,
318
+ forceFallbackAdapter: options.forceFallbackAdapter
319
+ });
320
+ const requiredFeatures = [
321
+ "texture-compression-bc",
322
+ "texture-compression-astc",
323
+ "texture-compression-etc2"
324
+ ].filter((feature) => adapter.features.has(feature));
325
+ const device = await adapter.requestDevice({
326
+ requiredFeatures
327
+ });
328
+ return { adapter, device };
329
+ }
330
+ destroy() {
331
+ this.gpu = null;
332
+ this._renderer = null;
333
+ }
334
+ }
335
+ GpuDeviceSystem.extension = {
336
+ type: [
337
+ ExtensionType.WebGPUSystem
338
+ ],
339
+ name: "device"
340
+ };
341
+ GpuDeviceSystem.defaultOptions = {
342
+ /**
343
+ * {@link WebGPUOptions.powerPreference}
344
+ * @default default
345
+ */
346
+ powerPreference: void 0,
347
+ /**
348
+ * Force the use of the fallback adapter
349
+ * @default false
350
+ */
351
+ forceFallbackAdapter: false
352
+ };
353
+ class GpuEncoderSystem {
354
+ constructor(renderer) {
355
+ this._boundBindGroup = /* @__PURE__ */ Object.create(null);
356
+ this._boundVertexBuffer = /* @__PURE__ */ Object.create(null);
357
+ this._renderer = renderer;
358
+ }
359
+ renderStart() {
360
+ this.commandFinished = new Promise((resolve) => {
361
+ this._resolveCommandFinished = resolve;
362
+ });
363
+ this.commandEncoder = this._renderer.gpu.device.createCommandEncoder();
364
+ }
365
+ beginRenderPass(gpuRenderTarget) {
366
+ this.endRenderPass();
367
+ this._clearCache();
368
+ this.renderPassEncoder = this.commandEncoder.beginRenderPass(gpuRenderTarget.descriptor);
369
+ }
370
+ endRenderPass() {
371
+ if (this.renderPassEncoder) {
372
+ this.renderPassEncoder.end();
373
+ }
374
+ this.renderPassEncoder = null;
375
+ }
376
+ setViewport(viewport) {
377
+ this.renderPassEncoder.setViewport(viewport.x, viewport.y, viewport.width, viewport.height, 0, 1);
378
+ }
379
+ setPipelineFromGeometryProgramAndState(geometry, program, state, topology) {
380
+ const pipeline = this._renderer.pipeline.getPipeline(geometry, program, state, topology);
381
+ this.setPipeline(pipeline);
382
+ }
383
+ setPipeline(pipeline) {
384
+ if (this._boundPipeline === pipeline) return;
385
+ this._boundPipeline = pipeline;
386
+ this.renderPassEncoder.setPipeline(pipeline);
387
+ }
388
+ _setVertexBuffer(index, buffer) {
389
+ if (this._boundVertexBuffer[index] === buffer) return;
390
+ this._boundVertexBuffer[index] = buffer;
391
+ this.renderPassEncoder.setVertexBuffer(index, this._renderer.buffer.updateBuffer(buffer));
392
+ }
393
+ _setIndexBuffer(buffer) {
394
+ if (this._boundIndexBuffer === buffer) return;
395
+ this._boundIndexBuffer = buffer;
396
+ const indexFormat = buffer.data.BYTES_PER_ELEMENT === 2 ? "uint16" : "uint32";
397
+ this.renderPassEncoder.setIndexBuffer(this._renderer.buffer.updateBuffer(buffer), indexFormat);
398
+ }
399
+ resetBindGroup(index) {
400
+ this._boundBindGroup[index] = null;
401
+ }
402
+ setBindGroup(index, bindGroup, program) {
403
+ if (this._boundBindGroup[index] === bindGroup) return;
404
+ this._boundBindGroup[index] = bindGroup;
405
+ bindGroup._touch(this._renderer.gc.now, this._renderer.tick);
406
+ const gpuBindGroup = this._renderer.bindGroup.getBindGroup(bindGroup, program, index);
407
+ this.renderPassEncoder.setBindGroup(index, gpuBindGroup);
408
+ }
409
+ setGeometry(geometry, program) {
410
+ const buffersToBind = this._renderer.pipeline.getBufferNamesToBind(geometry, program);
411
+ for (const i in buffersToBind) {
412
+ this._setVertexBuffer(parseInt(i, 10), geometry.attributes[buffersToBind[i]].buffer);
413
+ }
414
+ if (geometry.indexBuffer) {
415
+ this._setIndexBuffer(geometry.indexBuffer);
416
+ }
417
+ }
418
+ _setShaderBindGroups(shader, skipSync) {
419
+ for (const i in shader.groups) {
420
+ const bindGroup = shader.groups[i];
421
+ if (!skipSync) {
422
+ this._syncBindGroup(bindGroup);
423
+ }
424
+ this.setBindGroup(i, bindGroup, shader.gpuProgram);
425
+ }
426
+ }
427
+ _syncBindGroup(bindGroup) {
428
+ for (const j in bindGroup.resources) {
429
+ const resource = bindGroup.resources[j];
430
+ if (resource.isUniformGroup) {
431
+ this._renderer.ubo.updateUniformGroup(resource);
432
+ }
433
+ }
434
+ }
435
+ draw(options) {
436
+ const { geometry, shader, state, topology, size, start, instanceCount, skipSync } = options;
437
+ this.setPipelineFromGeometryProgramAndState(geometry, shader.gpuProgram, state, topology);
438
+ this.setGeometry(geometry, shader.gpuProgram);
439
+ this._setShaderBindGroups(shader, skipSync);
440
+ if (geometry.indexBuffer) {
441
+ this.renderPassEncoder.drawIndexed(
442
+ size || geometry.indexBuffer.data.length,
443
+ instanceCount ?? geometry.instanceCount,
444
+ start || 0
445
+ );
446
+ } else {
447
+ this.renderPassEncoder.draw(size || geometry.getSize(), instanceCount ?? geometry.instanceCount, start || 0);
448
+ }
449
+ }
450
+ finishRenderPass() {
451
+ if (this.renderPassEncoder) {
452
+ this.renderPassEncoder.end();
453
+ this.renderPassEncoder = null;
454
+ }
455
+ }
456
+ postrender() {
457
+ this.finishRenderPass();
458
+ this._gpu.device.queue.submit([this.commandEncoder.finish()]);
459
+ this._resolveCommandFinished();
460
+ this.commandEncoder = null;
461
+ }
462
+ // restores a render pass if finishRenderPass was called
463
+ // not optimised as really used for debugging!
464
+ // used when we want to stop drawing and log a texture..
465
+ restoreRenderPass() {
466
+ const descriptor = this._renderer.renderTarget.adaptor.getDescriptor(
467
+ this._renderer.renderTarget.renderTarget,
468
+ false,
469
+ [0, 0, 0, 1],
470
+ this._renderer.renderTarget.mipLevel,
471
+ this._renderer.renderTarget.layer
472
+ );
473
+ this.renderPassEncoder = this.commandEncoder.beginRenderPass(descriptor);
474
+ const boundPipeline = this._boundPipeline;
475
+ const boundVertexBuffer = { ...this._boundVertexBuffer };
476
+ const boundIndexBuffer = this._boundIndexBuffer;
477
+ const boundBindGroup = { ...this._boundBindGroup };
478
+ this._clearCache();
479
+ const viewport = this._renderer.renderTarget.viewport;
480
+ this.renderPassEncoder.setViewport(viewport.x, viewport.y, viewport.width, viewport.height, 0, 1);
481
+ this.setPipeline(boundPipeline);
482
+ for (const i in boundVertexBuffer) {
483
+ this._setVertexBuffer(i, boundVertexBuffer[i]);
484
+ }
485
+ for (const i in boundBindGroup) {
486
+ this.setBindGroup(i, boundBindGroup[i], null);
487
+ }
488
+ this._setIndexBuffer(boundIndexBuffer);
489
+ }
490
+ _clearCache() {
491
+ for (let i = 0; i < 16; i++) {
492
+ this._boundBindGroup[i] = null;
493
+ this._boundVertexBuffer[i] = null;
494
+ }
495
+ this._boundIndexBuffer = null;
496
+ this._boundPipeline = null;
497
+ }
498
+ destroy() {
499
+ this._renderer = null;
500
+ this._gpu = null;
501
+ this._boundBindGroup = null;
502
+ this._boundVertexBuffer = null;
503
+ this._boundIndexBuffer = null;
504
+ this._boundPipeline = null;
505
+ }
506
+ contextChange(gpu) {
507
+ this._gpu = gpu;
508
+ }
509
+ }
510
+ GpuEncoderSystem.extension = {
511
+ type: [ExtensionType.WebGPUSystem],
512
+ name: "encoder",
513
+ priority: 1
514
+ };
515
+ class GpuLimitsSystem {
516
+ constructor(renderer) {
517
+ this._renderer = renderer;
518
+ }
519
+ contextChange() {
520
+ this.maxTextures = this._renderer.device.gpu.device.limits.maxSampledTexturesPerShaderStage;
521
+ this.maxBatchableTextures = this.maxTextures;
522
+ }
523
+ destroy() {
524
+ }
525
+ }
526
+ GpuLimitsSystem.extension = {
527
+ type: [
528
+ ExtensionType.WebGPUSystem
529
+ ],
530
+ name: "limits"
531
+ };
532
+ class GpuStencilSystem {
533
+ constructor(renderer) {
534
+ this._renderTargetStencilState = /* @__PURE__ */ Object.create(null);
535
+ this._renderer = renderer;
536
+ renderer.renderTarget.onRenderTargetChange.add(this);
537
+ }
538
+ onRenderTargetChange(renderTarget) {
539
+ let stencilState = this._renderTargetStencilState[renderTarget.uid];
540
+ if (!stencilState) {
541
+ stencilState = this._renderTargetStencilState[renderTarget.uid] = {
542
+ stencilMode: STENCIL_MODES.DISABLED,
543
+ stencilReference: 0
544
+ };
545
+ }
546
+ this._activeRenderTarget = renderTarget;
547
+ this.setStencilMode(stencilState.stencilMode, stencilState.stencilReference);
548
+ }
549
+ setStencilMode(stencilMode, stencilReference) {
550
+ const stencilState = this._renderTargetStencilState[this._activeRenderTarget.uid];
551
+ stencilState.stencilMode = stencilMode;
552
+ stencilState.stencilReference = stencilReference;
553
+ const renderer = this._renderer;
554
+ renderer.pipeline.setStencilMode(stencilMode);
555
+ renderer.encoder.renderPassEncoder.setStencilReference(stencilReference);
556
+ }
557
+ destroy() {
558
+ this._renderer.renderTarget.onRenderTargetChange.remove(this);
559
+ this._renderer = null;
560
+ this._activeRenderTarget = null;
561
+ this._renderTargetStencilState = null;
562
+ }
563
+ }
564
+ GpuStencilSystem.extension = {
565
+ type: [
566
+ ExtensionType.WebGPUSystem
567
+ ],
568
+ name: "stencil"
569
+ };
570
+ const WGSL_ALIGN_SIZE_DATA = {
571
+ i32: { align: 4, size: 4 },
572
+ u32: { align: 4, size: 4 },
573
+ f32: { align: 4, size: 4 },
574
+ f16: { align: 2, size: 2 },
575
+ "vec2<i32>": { align: 8, size: 8 },
576
+ "vec2<u32>": { align: 8, size: 8 },
577
+ "vec2<f32>": { align: 8, size: 8 },
578
+ "vec2<f16>": { align: 4, size: 4 },
579
+ "vec3<i32>": { align: 16, size: 12 },
580
+ "vec3<u32>": { align: 16, size: 12 },
581
+ "vec3<f32>": { align: 16, size: 12 },
582
+ "vec3<f16>": { align: 8, size: 6 },
583
+ "vec4<i32>": { align: 16, size: 16 },
584
+ "vec4<u32>": { align: 16, size: 16 },
585
+ "vec4<f32>": { align: 16, size: 16 },
586
+ "vec4<f16>": { align: 8, size: 8 },
587
+ "mat2x2<f32>": { align: 8, size: 16 },
588
+ "mat2x2<f16>": { align: 4, size: 8 },
589
+ "mat3x2<f32>": { align: 8, size: 24 },
590
+ "mat3x2<f16>": { align: 4, size: 12 },
591
+ "mat4x2<f32>": { align: 8, size: 32 },
592
+ "mat4x2<f16>": { align: 4, size: 16 },
593
+ "mat2x3<f32>": { align: 16, size: 32 },
594
+ "mat2x3<f16>": { align: 8, size: 16 },
595
+ "mat3x3<f32>": { align: 16, size: 48 },
596
+ "mat3x3<f16>": { align: 8, size: 24 },
597
+ "mat4x3<f32>": { align: 16, size: 64 },
598
+ "mat4x3<f16>": { align: 8, size: 32 },
599
+ "mat2x4<f32>": { align: 16, size: 32 },
600
+ "mat2x4<f16>": { align: 8, size: 16 },
601
+ "mat3x4<f32>": { align: 16, size: 48 },
602
+ "mat3x4<f16>": { align: 8, size: 24 },
603
+ "mat4x4<f32>": { align: 16, size: 64 },
604
+ "mat4x4<f16>": { align: 8, size: 32 }
605
+ };
606
+ function createUboElementsWGSL(uniformData) {
607
+ const uboElements = uniformData.map((data) => ({
608
+ data,
609
+ offset: 0,
610
+ size: 0
611
+ }));
612
+ let offset = 0;
613
+ for (let i = 0; i < uboElements.length; i++) {
614
+ const uboElement = uboElements[i];
615
+ let size = WGSL_ALIGN_SIZE_DATA[uboElement.data.type].size;
616
+ const align = WGSL_ALIGN_SIZE_DATA[uboElement.data.type].align;
617
+ if (!WGSL_ALIGN_SIZE_DATA[uboElement.data.type]) {
618
+ throw new Error(`[Pixi.js] WebGPU UniformBuffer: Unknown type ${uboElement.data.type}`);
619
+ }
620
+ if (uboElement.data.size > 1) {
621
+ size = Math.max(size, align) * uboElement.data.size;
622
+ }
623
+ offset = Math.ceil(offset / align) * align;
624
+ uboElement.size = size;
625
+ uboElement.offset = offset;
626
+ offset += size;
627
+ }
628
+ offset = Math.ceil(offset / 16) * 16;
629
+ return { uboElements, size: offset };
630
+ }
631
+ function generateArraySyncWGSL(uboElement, offsetToAdd) {
632
+ const { size, align } = WGSL_ALIGN_SIZE_DATA[uboElement.data.type];
633
+ const remainder = (align - size) / 4;
634
+ const data = uboElement.data.type.indexOf("i32") >= 0 ? "dataInt32" : "data";
635
+ return `
636
+ v = uv.${uboElement.data.name};
637
+ ${offsetToAdd !== 0 ? `offset += ${offsetToAdd};` : ""}
638
+
639
+ arrayOffset = offset;
640
+
641
+ t = 0;
642
+
643
+ for(var i=0; i < ${uboElement.data.size * (size / 4)}; i++)
644
+ {
645
+ for(var j = 0; j < ${size / 4}; j++)
646
+ {
647
+ ${data}[arrayOffset++] = v[t++];
648
+ }
649
+ ${remainder !== 0 ? `arrayOffset += ${remainder};` : ""}
650
+ }
651
+ `;
652
+ }
653
+ function createUboSyncFunctionWGSL(uboElements) {
654
+ return createUboSyncFunction(
655
+ uboElements,
656
+ "uboWgsl",
657
+ generateArraySyncWGSL,
658
+ uboSyncFunctionsWGSL
659
+ );
660
+ }
661
+ class GpuUboSystem extends UboSystem {
662
+ constructor() {
663
+ super({
664
+ createUboElements: createUboElementsWGSL,
665
+ generateUboSync: createUboSyncFunctionWGSL
666
+ });
667
+ }
668
+ }
669
+ GpuUboSystem.extension = {
670
+ type: [ExtensionType.WebGPUSystem],
671
+ name: "ubo"
672
+ };
673
+ const minUniformOffsetAlignment = 128;
674
+ class GpuUniformBatchPipe {
675
+ constructor(renderer) {
676
+ this._bindGroupHash = /* @__PURE__ */ Object.create(null);
677
+ this._buffers = [];
678
+ this._bindGroups = [];
679
+ this._bufferResources = [];
680
+ this._renderer = renderer;
681
+ this._batchBuffer = new UboBatch({ minUniformOffsetAlignment });
682
+ const totalBuffers = 256 / minUniformOffsetAlignment;
683
+ for (let i = 0; i < totalBuffers; i++) {
684
+ let usage = BufferUsage.UNIFORM | BufferUsage.COPY_DST;
685
+ if (i === 0) usage |= BufferUsage.COPY_SRC;
686
+ this._buffers.push(new Buffer({
687
+ data: this._batchBuffer.data,
688
+ usage
689
+ }));
690
+ }
691
+ }
692
+ renderEnd() {
693
+ this._uploadBindGroups();
694
+ this._resetBindGroups();
695
+ }
696
+ _resetBindGroups() {
697
+ this._bindGroupHash = /* @__PURE__ */ Object.create(null);
698
+ this._batchBuffer.clear();
699
+ }
700
+ // just works for single bind groups for now
701
+ getUniformBindGroup(group, duplicate) {
702
+ if (!duplicate && this._bindGroupHash[group.uid]) {
703
+ return this._bindGroupHash[group.uid];
704
+ }
705
+ this._renderer.ubo.ensureUniformGroup(group);
706
+ const data = group.buffer.data;
707
+ const offset = this._batchBuffer.addEmptyGroup(data.length);
708
+ this._renderer.ubo.syncUniformGroup(group, this._batchBuffer.data, offset / 4);
709
+ this._bindGroupHash[group.uid] = this._getBindGroup(offset / minUniformOffsetAlignment);
710
+ return this._bindGroupHash[group.uid];
711
+ }
712
+ getUboResource(group) {
713
+ this._renderer.ubo.updateUniformGroup(group);
714
+ const data = group.buffer.data;
715
+ const offset = this._batchBuffer.addGroup(data);
716
+ return this._getBufferResource(offset / minUniformOffsetAlignment);
717
+ }
718
+ getArrayBindGroup(data) {
719
+ const offset = this._batchBuffer.addGroup(data);
720
+ return this._getBindGroup(offset / minUniformOffsetAlignment);
721
+ }
722
+ getArrayBufferResource(data) {
723
+ const offset = this._batchBuffer.addGroup(data);
724
+ const index = offset / minUniformOffsetAlignment;
725
+ return this._getBufferResource(index);
726
+ }
727
+ _getBufferResource(index) {
728
+ if (!this._bufferResources[index]) {
729
+ const buffer = this._buffers[index % 2];
730
+ this._bufferResources[index] = new BufferResource({
731
+ buffer,
732
+ offset: (index / 2 | 0) * 256,
733
+ size: minUniformOffsetAlignment
734
+ });
735
+ }
736
+ return this._bufferResources[index];
737
+ }
738
+ _getBindGroup(index) {
739
+ if (!this._bindGroups[index]) {
740
+ const bindGroup = new BindGroup({
741
+ 0: this._getBufferResource(index)
742
+ });
743
+ this._bindGroups[index] = bindGroup;
744
+ }
745
+ return this._bindGroups[index];
746
+ }
747
+ _uploadBindGroups() {
748
+ const bufferSystem = this._renderer.buffer;
749
+ const firstBuffer = this._buffers[0];
750
+ firstBuffer.update(this._batchBuffer.byteIndex);
751
+ bufferSystem.updateBuffer(firstBuffer);
752
+ const commandEncoder = this._renderer.gpu.device.createCommandEncoder();
753
+ for (let i = 1; i < this._buffers.length; i++) {
754
+ const buffer = this._buffers[i];
755
+ commandEncoder.copyBufferToBuffer(
756
+ bufferSystem.getGPUBuffer(firstBuffer),
757
+ minUniformOffsetAlignment,
758
+ bufferSystem.getGPUBuffer(buffer),
759
+ 0,
760
+ this._batchBuffer.byteIndex
761
+ );
762
+ }
763
+ this._renderer.gpu.device.queue.submit([commandEncoder.finish()]);
764
+ }
765
+ destroy() {
766
+ for (let i = 0; i < this._bindGroups.length; i++) {
767
+ this._bindGroups[i]?.destroy();
768
+ }
769
+ this._bindGroups = null;
770
+ this._bindGroupHash = null;
771
+ for (let i = 0; i < this._buffers.length; i++) {
772
+ this._buffers[i].destroy();
773
+ }
774
+ this._buffers = null;
775
+ for (let i = 0; i < this._bufferResources.length; i++) {
776
+ this._bufferResources[i].destroy();
777
+ }
778
+ this._bufferResources = null;
779
+ this._batchBuffer.destroy();
780
+ this._renderer = null;
781
+ }
782
+ }
783
+ GpuUniformBatchPipe.extension = {
784
+ type: [
785
+ ExtensionType.WebGPUPipes
786
+ ],
787
+ name: "uniformBatch"
788
+ };
789
+ const topologyStringToId = {
790
+ "point-list": 0,
791
+ "line-list": 1,
792
+ "line-strip": 2,
793
+ "triangle-list": 3,
794
+ "triangle-strip": 4
795
+ };
796
+ function getGraphicsStateKey(geometryLayout, shaderKey, state, blendMode, topology) {
797
+ return geometryLayout << 24 | shaderKey << 16 | state << 10 | blendMode << 5 | topology;
798
+ }
799
+ function getGlobalStateKey(stencilStateId, multiSampleCount, colorMask, renderTarget, colorTargetCount) {
800
+ return colorMask << 8 | stencilStateId << 5 | renderTarget << 3 | colorTargetCount << 1 | multiSampleCount;
801
+ }
802
+ class PipelineSystem {
803
+ constructor(renderer) {
804
+ this._moduleCache = /* @__PURE__ */ Object.create(null);
805
+ this._bufferLayoutsCache = /* @__PURE__ */ Object.create(null);
806
+ this._bindingNamesCache = /* @__PURE__ */ Object.create(null);
807
+ this._pipeCache = /* @__PURE__ */ Object.create(null);
808
+ this._pipeStateCaches = /* @__PURE__ */ Object.create(null);
809
+ this._colorMask = 15;
810
+ this._multisampleCount = 1;
811
+ this._colorTargetCount = 1;
812
+ this._renderer = renderer;
813
+ }
814
+ contextChange(gpu) {
815
+ this._gpu = gpu;
816
+ this.setStencilMode(STENCIL_MODES.DISABLED);
817
+ this._updatePipeHash();
818
+ }
819
+ setMultisampleCount(multisampleCount) {
820
+ if (this._multisampleCount === multisampleCount) return;
821
+ this._multisampleCount = multisampleCount;
822
+ this._updatePipeHash();
823
+ }
824
+ setRenderTarget(renderTarget) {
825
+ this._multisampleCount = renderTarget.msaaSamples;
826
+ this._depthStencilAttachment = renderTarget.descriptor.depthStencilAttachment ? 1 : 0;
827
+ this._colorTargetCount = renderTarget.colorTargetCount;
828
+ this._updatePipeHash();
829
+ }
830
+ setColorMask(colorMask) {
831
+ if (this._colorMask === colorMask) return;
832
+ this._colorMask = colorMask;
833
+ this._updatePipeHash();
834
+ }
835
+ setStencilMode(stencilMode) {
836
+ if (this._stencilMode === stencilMode) return;
837
+ this._stencilMode = stencilMode;
838
+ this._stencilState = GpuStencilModesToPixi[stencilMode];
839
+ this._updatePipeHash();
840
+ }
841
+ setPipeline(geometry, program, state, passEncoder) {
842
+ const pipeline = this.getPipeline(geometry, program, state);
843
+ passEncoder.setPipeline(pipeline);
844
+ }
845
+ getPipeline(geometry, program, state, topology) {
846
+ if (!geometry._layoutKey) {
847
+ ensureAttributes(geometry, program.attributeData);
848
+ this._generateBufferKey(geometry);
849
+ }
850
+ topology || (topology = geometry.topology);
851
+ const key = getGraphicsStateKey(
852
+ geometry._layoutKey,
853
+ program._layoutKey,
854
+ state.data,
855
+ state._blendModeId,
856
+ topologyStringToId[topology]
857
+ );
858
+ if (this._pipeCache[key]) return this._pipeCache[key];
859
+ this._pipeCache[key] = this._createPipeline(geometry, program, state, topology);
860
+ return this._pipeCache[key];
861
+ }
862
+ _createPipeline(geometry, program, state, topology) {
863
+ const device = this._gpu.device;
864
+ const buffers = this._createVertexBufferLayouts(geometry, program);
865
+ const blendModes = this._renderer.state.getColorTargets(state, this._colorTargetCount);
866
+ const writeMask = this._stencilMode === STENCIL_MODES.RENDERING_MASK_ADD ? 0 : this._colorMask;
867
+ for (let i = 0; i < blendModes.length; i++) {
868
+ blendModes[i].writeMask = writeMask;
869
+ }
870
+ const layout = this._renderer.shader.getProgramData(program).pipeline;
871
+ const descriptor = {
872
+ // TODO later check if its helpful to create..
873
+ // layout,
874
+ vertex: {
875
+ module: this._getModule(program.vertex.source),
876
+ entryPoint: program.vertex.entryPoint,
877
+ // geometry..
878
+ buffers
879
+ },
880
+ fragment: {
881
+ module: this._getModule(program.fragment.source),
882
+ entryPoint: program.fragment.entryPoint,
883
+ targets: blendModes
884
+ },
885
+ primitive: {
886
+ topology,
887
+ cullMode: state.cullMode
888
+ },
889
+ layout,
890
+ multisample: {
891
+ count: this._multisampleCount
892
+ },
893
+ // depthStencil,
894
+ label: `PIXI Pipeline`
895
+ };
896
+ if (this._depthStencilAttachment) {
897
+ descriptor.depthStencil = {
898
+ ...this._stencilState,
899
+ format: "depth24plus-stencil8",
900
+ depthWriteEnabled: state.depthTest,
901
+ depthCompare: state.depthTest ? "less" : "always"
902
+ };
903
+ }
904
+ const pipeline = device.createRenderPipeline(descriptor);
905
+ return pipeline;
906
+ }
907
+ _getModule(code) {
908
+ return this._moduleCache[code] || this._createModule(code);
909
+ }
910
+ _createModule(code) {
911
+ const device = this._gpu.device;
912
+ this._moduleCache[code] = device.createShaderModule({
913
+ code
914
+ });
915
+ return this._moduleCache[code];
916
+ }
917
+ _generateBufferKey(geometry) {
918
+ const keyGen = [];
919
+ let index = 0;
920
+ const attributeKeys = Object.keys(geometry.attributes).sort();
921
+ for (let i = 0; i < attributeKeys.length; i++) {
922
+ const attribute = geometry.attributes[attributeKeys[i]];
923
+ keyGen[index++] = attribute.offset;
924
+ keyGen[index++] = attribute.format;
925
+ keyGen[index++] = attribute.stride;
926
+ keyGen[index++] = attribute.instance;
927
+ }
928
+ const stringKey = keyGen.join("|");
929
+ geometry._layoutKey = createIdFromString(stringKey, "geometry");
930
+ return geometry._layoutKey;
931
+ }
932
+ _generateAttributeLocationsKey(program) {
933
+ const keyGen = [];
934
+ let index = 0;
935
+ const attributeKeys = Object.keys(program.attributeData).sort();
936
+ for (let i = 0; i < attributeKeys.length; i++) {
937
+ const attribute = program.attributeData[attributeKeys[i]];
938
+ keyGen[index++] = attribute.location;
939
+ }
940
+ const stringKey = keyGen.join("|");
941
+ program._attributeLocationsKey = createIdFromString(stringKey, "programAttributes");
942
+ return program._attributeLocationsKey;
943
+ }
944
+ /**
945
+ * Returns a hash of buffer names mapped to bind locations.
946
+ * This is used to bind the correct buffer to the correct location in the shader.
947
+ * @param geometry - The geometry where to get the buffer names
948
+ * @param program - The program where to get the buffer names
949
+ * @returns An object of buffer names mapped to the bind location.
950
+ */
951
+ getBufferNamesToBind(geometry, program) {
952
+ const key = geometry._layoutKey << 16 | program._attributeLocationsKey;
953
+ if (this._bindingNamesCache[key]) return this._bindingNamesCache[key];
954
+ const data = this._createVertexBufferLayouts(geometry, program);
955
+ const bufferNamesToBind = /* @__PURE__ */ Object.create(null);
956
+ const attributeData = program.attributeData;
957
+ for (let i = 0; i < data.length; i++) {
958
+ const attributes = Object.values(data[i].attributes);
959
+ const shaderLocation = attributes[0].shaderLocation;
960
+ for (const j in attributeData) {
961
+ if (attributeData[j].location === shaderLocation) {
962
+ bufferNamesToBind[i] = j;
963
+ break;
964
+ }
965
+ }
966
+ }
967
+ this._bindingNamesCache[key] = bufferNamesToBind;
968
+ return bufferNamesToBind;
969
+ }
970
+ _createVertexBufferLayouts(geometry, program) {
971
+ if (!program._attributeLocationsKey) this._generateAttributeLocationsKey(program);
972
+ const key = geometry._layoutKey << 16 | program._attributeLocationsKey;
973
+ if (this._bufferLayoutsCache[key]) {
974
+ return this._bufferLayoutsCache[key];
975
+ }
976
+ const vertexBuffersLayout = [];
977
+ geometry.buffers.forEach((buffer) => {
978
+ const bufferEntry = {
979
+ arrayStride: 0,
980
+ stepMode: "vertex",
981
+ attributes: []
982
+ };
983
+ const bufferEntryAttributes = bufferEntry.attributes;
984
+ for (const i in program.attributeData) {
985
+ const attribute = geometry.attributes[i];
986
+ if ((attribute.divisor ?? 1) !== 1) {
987
+ warn(`Attribute ${i} has an invalid divisor value of '${attribute.divisor}'. WebGPU only supports a divisor value of 1`);
988
+ }
989
+ if (attribute.buffer === buffer) {
990
+ bufferEntry.arrayStride = attribute.stride;
991
+ bufferEntry.stepMode = attribute.instance ? "instance" : "vertex";
992
+ bufferEntryAttributes.push({
993
+ shaderLocation: program.attributeData[i].location,
994
+ offset: attribute.offset,
995
+ format: attribute.format
996
+ });
997
+ }
998
+ }
999
+ if (bufferEntryAttributes.length) {
1000
+ vertexBuffersLayout.push(bufferEntry);
1001
+ }
1002
+ });
1003
+ this._bufferLayoutsCache[key] = vertexBuffersLayout;
1004
+ return vertexBuffersLayout;
1005
+ }
1006
+ _updatePipeHash() {
1007
+ const key = getGlobalStateKey(
1008
+ this._stencilMode,
1009
+ this._multisampleCount,
1010
+ this._colorMask,
1011
+ this._depthStencilAttachment,
1012
+ this._colorTargetCount
1013
+ );
1014
+ if (!this._pipeStateCaches[key]) {
1015
+ this._pipeStateCaches[key] = /* @__PURE__ */ Object.create(null);
1016
+ }
1017
+ this._pipeCache = this._pipeStateCaches[key];
1018
+ }
1019
+ destroy() {
1020
+ this._renderer = null;
1021
+ this._bufferLayoutsCache = null;
1022
+ }
1023
+ }
1024
+ PipelineSystem.extension = {
1025
+ type: [ExtensionType.WebGPUSystem],
1026
+ name: "pipeline"
1027
+ };
1028
+ class GpuRenderTarget {
1029
+ constructor() {
1030
+ this.contexts = [];
1031
+ this.msaaTextures = [];
1032
+ this.msaaSamples = 1;
1033
+ }
1034
+ }
1035
+ class GpuRenderTargetAdaptor {
1036
+ init(renderer, renderTargetSystem) {
1037
+ this._renderer = renderer;
1038
+ this._renderTargetSystem = renderTargetSystem;
1039
+ }
1040
+ copyToTexture(sourceRenderSurfaceTexture, destinationTexture, originSrc, size, originDest) {
1041
+ const renderer = this._renderer;
1042
+ const baseGpuTexture = this._getGpuColorTexture(
1043
+ sourceRenderSurfaceTexture
1044
+ );
1045
+ const backGpuTexture = renderer.texture.getGpuSource(
1046
+ destinationTexture.source
1047
+ );
1048
+ renderer.encoder.commandEncoder.copyTextureToTexture(
1049
+ {
1050
+ texture: baseGpuTexture,
1051
+ origin: originSrc
1052
+ },
1053
+ {
1054
+ texture: backGpuTexture,
1055
+ origin: originDest
1056
+ },
1057
+ size
1058
+ );
1059
+ return destinationTexture;
1060
+ }
1061
+ startRenderPass(renderTarget, clear = true, clearColor, viewport, mipLevel = 0, layer = 0) {
1062
+ const renderTargetSystem = this._renderTargetSystem;
1063
+ const gpuRenderTarget = renderTargetSystem.getGpuRenderTarget(renderTarget);
1064
+ if (layer !== 0 && gpuRenderTarget.msaaTextures?.length) {
1065
+ throw new Error("[RenderTargetSystem] Rendering to array layers is not supported with MSAA render targets.");
1066
+ }
1067
+ if (mipLevel > 0 && gpuRenderTarget.msaaTextures?.length) {
1068
+ throw new Error("[RenderTargetSystem] Rendering to mip levels is not supported with MSAA render targets.");
1069
+ }
1070
+ const descriptor = this.getDescriptor(renderTarget, clear, clearColor, mipLevel, layer);
1071
+ gpuRenderTarget.descriptor = descriptor;
1072
+ this._renderer.pipeline.setRenderTarget(gpuRenderTarget);
1073
+ this._renderer.encoder.beginRenderPass(gpuRenderTarget);
1074
+ this._renderer.encoder.setViewport(viewport);
1075
+ }
1076
+ finishRenderPass() {
1077
+ this._renderer.encoder.endRenderPass();
1078
+ }
1079
+ /**
1080
+ * returns the gpu texture for the first color texture in the render target
1081
+ * mainly used by the filter manager to get copy the texture for blending
1082
+ * @param renderTarget
1083
+ * @returns a gpu texture
1084
+ */
1085
+ _getGpuColorTexture(renderTarget) {
1086
+ const gpuRenderTarget = this._renderTargetSystem.getGpuRenderTarget(renderTarget);
1087
+ if (gpuRenderTarget.contexts[0]) {
1088
+ return gpuRenderTarget.contexts[0].getCurrentTexture();
1089
+ }
1090
+ return this._renderer.texture.getGpuSource(
1091
+ renderTarget.colorTextures[0].source
1092
+ );
1093
+ }
1094
+ getDescriptor(renderTarget, clear, clearValue, mipLevel = 0, layer = 0) {
1095
+ if (typeof clear === "boolean") {
1096
+ clear = clear ? CLEAR.ALL : CLEAR.NONE;
1097
+ }
1098
+ const renderTargetSystem = this._renderTargetSystem;
1099
+ const gpuRenderTarget = renderTargetSystem.getGpuRenderTarget(renderTarget);
1100
+ const colorAttachments = renderTarget.colorTextures.map(
1101
+ (texture, i) => {
1102
+ const context = gpuRenderTarget.contexts[i];
1103
+ let view;
1104
+ let resolveTarget;
1105
+ if (context) {
1106
+ if (layer !== 0) {
1107
+ throw new Error("[RenderTargetSystem] Rendering to array layers is not supported for canvas targets.");
1108
+ }
1109
+ const currentTexture = context.getCurrentTexture();
1110
+ const canvasTextureView = currentTexture.createView();
1111
+ view = canvasTextureView;
1112
+ } else {
1113
+ view = this._renderer.texture.getGpuSource(texture).createView({
1114
+ // Render attachments must be 2d views; for array/cube textures we select a single layer.
1115
+ dimension: "2d",
1116
+ baseMipLevel: mipLevel,
1117
+ mipLevelCount: 1,
1118
+ baseArrayLayer: layer,
1119
+ arrayLayerCount: 1
1120
+ });
1121
+ }
1122
+ if (gpuRenderTarget.msaaTextures[i]) {
1123
+ resolveTarget = view;
1124
+ view = this._renderer.texture.getTextureView(
1125
+ gpuRenderTarget.msaaTextures[i]
1126
+ );
1127
+ }
1128
+ const loadOp = clear & CLEAR.COLOR ? "clear" : "load";
1129
+ clearValue ?? (clearValue = renderTargetSystem.defaultClearColor);
1130
+ return {
1131
+ view,
1132
+ resolveTarget,
1133
+ clearValue,
1134
+ storeOp: "store",
1135
+ loadOp
1136
+ };
1137
+ }
1138
+ );
1139
+ let depthStencilAttachment;
1140
+ if ((renderTarget.stencil || renderTarget.depth) && !renderTarget.depthStencilTexture) {
1141
+ renderTarget.ensureDepthStencilTexture();
1142
+ renderTarget.depthStencilTexture.source.sampleCount = gpuRenderTarget.msaa ? 4 : 1;
1143
+ }
1144
+ if (renderTarget.depthStencilTexture) {
1145
+ const stencilLoadOp = clear & CLEAR.STENCIL ? "clear" : "load";
1146
+ const depthLoadOp = clear & CLEAR.DEPTH ? "clear" : "load";
1147
+ depthStencilAttachment = {
1148
+ view: this._renderer.texture.getGpuSource(renderTarget.depthStencilTexture.source).createView({
1149
+ dimension: "2d",
1150
+ baseMipLevel: mipLevel,
1151
+ mipLevelCount: 1,
1152
+ baseArrayLayer: layer,
1153
+ arrayLayerCount: 1
1154
+ }),
1155
+ stencilStoreOp: "store",
1156
+ stencilLoadOp,
1157
+ depthClearValue: 1,
1158
+ depthLoadOp,
1159
+ depthStoreOp: "store"
1160
+ };
1161
+ }
1162
+ const descriptor = {
1163
+ colorAttachments,
1164
+ depthStencilAttachment
1165
+ };
1166
+ return descriptor;
1167
+ }
1168
+ clear(renderTarget, clear = true, clearColor, viewport, mipLevel = 0, layer = 0) {
1169
+ if (!clear) return;
1170
+ const { gpu, encoder } = this._renderer;
1171
+ const device = gpu.device;
1172
+ const standAlone = encoder.commandEncoder === null;
1173
+ if (standAlone) {
1174
+ const commandEncoder = device.createCommandEncoder();
1175
+ const renderPassDescriptor = this.getDescriptor(renderTarget, clear, clearColor, mipLevel, layer);
1176
+ const passEncoder = commandEncoder.beginRenderPass(renderPassDescriptor);
1177
+ passEncoder.setViewport(viewport.x, viewport.y, viewport.width, viewport.height, 0, 1);
1178
+ passEncoder.end();
1179
+ const gpuCommands = commandEncoder.finish();
1180
+ device.queue.submit([gpuCommands]);
1181
+ } else {
1182
+ this.startRenderPass(renderTarget, clear, clearColor, viewport, mipLevel, layer);
1183
+ }
1184
+ }
1185
+ initGpuRenderTarget(renderTarget) {
1186
+ renderTarget.isRoot = true;
1187
+ const gpuRenderTarget = new GpuRenderTarget();
1188
+ gpuRenderTarget.colorTargetCount = renderTarget.colorTextures.length;
1189
+ renderTarget.colorTextures.forEach((colorTexture, i) => {
1190
+ if (colorTexture instanceof CanvasSource) {
1191
+ const context = colorTexture.resource.getContext(
1192
+ "webgpu"
1193
+ );
1194
+ const alphaMode = colorTexture.transparent ? "premultiplied" : "opaque";
1195
+ try {
1196
+ context.configure({
1197
+ device: this._renderer.gpu.device,
1198
+ usage: GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST | GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.COPY_SRC,
1199
+ format: "bgra8unorm",
1200
+ alphaMode
1201
+ });
1202
+ } catch (e) {
1203
+ console.error(e);
1204
+ }
1205
+ gpuRenderTarget.contexts[i] = context;
1206
+ }
1207
+ gpuRenderTarget.msaa = colorTexture.source.antialias;
1208
+ if (colorTexture.source.antialias) {
1209
+ const msaaTexture = new TextureSource({
1210
+ width: 0,
1211
+ height: 0,
1212
+ sampleCount: 4,
1213
+ arrayLayerCount: colorTexture.source.arrayLayerCount
1214
+ });
1215
+ gpuRenderTarget.msaaTextures[i] = msaaTexture;
1216
+ }
1217
+ });
1218
+ if (gpuRenderTarget.msaa) {
1219
+ gpuRenderTarget.msaaSamples = 4;
1220
+ if (renderTarget.depthStencilTexture) {
1221
+ renderTarget.depthStencilTexture.source.sampleCount = 4;
1222
+ }
1223
+ }
1224
+ return gpuRenderTarget;
1225
+ }
1226
+ destroyGpuRenderTarget(gpuRenderTarget) {
1227
+ gpuRenderTarget.contexts.forEach((context) => {
1228
+ context.unconfigure();
1229
+ });
1230
+ gpuRenderTarget.msaaTextures.forEach((texture) => {
1231
+ texture.destroy();
1232
+ });
1233
+ gpuRenderTarget.msaaTextures.length = 0;
1234
+ gpuRenderTarget.contexts.length = 0;
1235
+ }
1236
+ ensureDepthStencilTexture(renderTarget) {
1237
+ const gpuRenderTarget = this._renderTargetSystem.getGpuRenderTarget(renderTarget);
1238
+ if (renderTarget.depthStencilTexture && gpuRenderTarget.msaa) {
1239
+ renderTarget.depthStencilTexture.source.sampleCount = 4;
1240
+ }
1241
+ }
1242
+ resizeGpuRenderTarget(renderTarget) {
1243
+ const gpuRenderTarget = this._renderTargetSystem.getGpuRenderTarget(renderTarget);
1244
+ gpuRenderTarget.width = renderTarget.width;
1245
+ gpuRenderTarget.height = renderTarget.height;
1246
+ if (gpuRenderTarget.msaa) {
1247
+ renderTarget.colorTextures.forEach((colorTexture, i) => {
1248
+ const msaaTexture = gpuRenderTarget.msaaTextures[i];
1249
+ msaaTexture?.resize(
1250
+ colorTexture.source.width,
1251
+ colorTexture.source.height,
1252
+ colorTexture.source._resolution
1253
+ );
1254
+ });
1255
+ }
1256
+ }
1257
+ }
1258
+ class GpuRenderTargetSystem extends RenderTargetSystem {
1259
+ constructor(renderer) {
1260
+ super(renderer);
1261
+ this.adaptor = new GpuRenderTargetAdaptor();
1262
+ this.adaptor.init(renderer, this);
1263
+ }
1264
+ }
1265
+ GpuRenderTargetSystem.extension = {
1266
+ type: [ExtensionType.WebGPUSystem],
1267
+ name: "renderTarget"
1268
+ };
1269
+ class GpuShaderSystem {
1270
+ constructor() {
1271
+ this._gpuProgramData = /* @__PURE__ */ Object.create(null);
1272
+ }
1273
+ contextChange(gpu) {
1274
+ this._gpu = gpu;
1275
+ }
1276
+ getProgramData(program) {
1277
+ return this._gpuProgramData[program._layoutKey] || this._createGPUProgramData(program);
1278
+ }
1279
+ _createGPUProgramData(program) {
1280
+ const device = this._gpu.device;
1281
+ const bindGroups = program.gpuLayout.map((group) => device.createBindGroupLayout({ entries: group }));
1282
+ const pipelineLayoutDesc = { bindGroupLayouts: bindGroups };
1283
+ this._gpuProgramData[program._layoutKey] = {
1284
+ bindGroups,
1285
+ pipeline: device.createPipelineLayout(pipelineLayoutDesc)
1286
+ };
1287
+ return this._gpuProgramData[program._layoutKey];
1288
+ }
1289
+ destroy() {
1290
+ this._gpu = null;
1291
+ this._gpuProgramData = null;
1292
+ }
1293
+ }
1294
+ GpuShaderSystem.extension = {
1295
+ type: [
1296
+ ExtensionType.WebGPUSystem
1297
+ ],
1298
+ name: "shader"
1299
+ };
1300
+ const GpuBlendModesToPixi = {};
1301
+ GpuBlendModesToPixi.normal = {
1302
+ alpha: {
1303
+ srcFactor: "one",
1304
+ dstFactor: "one-minus-src-alpha",
1305
+ operation: "add"
1306
+ },
1307
+ color: {
1308
+ srcFactor: "one",
1309
+ dstFactor: "one-minus-src-alpha",
1310
+ operation: "add"
1311
+ }
1312
+ };
1313
+ GpuBlendModesToPixi.add = {
1314
+ alpha: {
1315
+ srcFactor: "src-alpha",
1316
+ dstFactor: "one-minus-src-alpha",
1317
+ operation: "add"
1318
+ },
1319
+ color: {
1320
+ srcFactor: "one",
1321
+ dstFactor: "one",
1322
+ operation: "add"
1323
+ }
1324
+ };
1325
+ GpuBlendModesToPixi.multiply = {
1326
+ alpha: {
1327
+ srcFactor: "one",
1328
+ dstFactor: "one-minus-src-alpha",
1329
+ operation: "add"
1330
+ },
1331
+ color: {
1332
+ srcFactor: "dst",
1333
+ dstFactor: "one-minus-src-alpha",
1334
+ operation: "add"
1335
+ }
1336
+ };
1337
+ GpuBlendModesToPixi.screen = {
1338
+ alpha: {
1339
+ srcFactor: "one",
1340
+ dstFactor: "one-minus-src-alpha",
1341
+ operation: "add"
1342
+ },
1343
+ color: {
1344
+ srcFactor: "one",
1345
+ dstFactor: "one-minus-src",
1346
+ operation: "add"
1347
+ }
1348
+ };
1349
+ GpuBlendModesToPixi.overlay = {
1350
+ alpha: {
1351
+ srcFactor: "one",
1352
+ dstFactor: "one-minus-src-alpha",
1353
+ operation: "add"
1354
+ },
1355
+ color: {
1356
+ srcFactor: "one",
1357
+ dstFactor: "one-minus-src",
1358
+ operation: "add"
1359
+ }
1360
+ };
1361
+ GpuBlendModesToPixi.none = {
1362
+ alpha: {
1363
+ srcFactor: "one",
1364
+ dstFactor: "one-minus-src-alpha",
1365
+ operation: "add"
1366
+ },
1367
+ color: {
1368
+ srcFactor: "zero",
1369
+ dstFactor: "zero",
1370
+ operation: "add"
1371
+ }
1372
+ };
1373
+ GpuBlendModesToPixi["normal-npm"] = {
1374
+ alpha: {
1375
+ srcFactor: "one",
1376
+ dstFactor: "one-minus-src-alpha",
1377
+ operation: "add"
1378
+ },
1379
+ color: {
1380
+ srcFactor: "src-alpha",
1381
+ dstFactor: "one-minus-src-alpha",
1382
+ operation: "add"
1383
+ }
1384
+ };
1385
+ GpuBlendModesToPixi["add-npm"] = {
1386
+ alpha: {
1387
+ srcFactor: "one",
1388
+ dstFactor: "one",
1389
+ operation: "add"
1390
+ },
1391
+ color: {
1392
+ srcFactor: "src-alpha",
1393
+ dstFactor: "one",
1394
+ operation: "add"
1395
+ }
1396
+ };
1397
+ GpuBlendModesToPixi["screen-npm"] = {
1398
+ alpha: {
1399
+ srcFactor: "one",
1400
+ dstFactor: "one-minus-src-alpha",
1401
+ operation: "add"
1402
+ },
1403
+ color: {
1404
+ srcFactor: "src-alpha",
1405
+ dstFactor: "one-minus-src",
1406
+ operation: "add"
1407
+ }
1408
+ };
1409
+ GpuBlendModesToPixi.erase = {
1410
+ alpha: {
1411
+ srcFactor: "zero",
1412
+ dstFactor: "one-minus-src-alpha",
1413
+ operation: "add"
1414
+ },
1415
+ color: {
1416
+ srcFactor: "zero",
1417
+ dstFactor: "one-minus-src",
1418
+ operation: "add"
1419
+ }
1420
+ };
1421
+ GpuBlendModesToPixi.min = {
1422
+ alpha: {
1423
+ srcFactor: "one",
1424
+ dstFactor: "one",
1425
+ operation: "min"
1426
+ },
1427
+ color: {
1428
+ srcFactor: "one",
1429
+ dstFactor: "one",
1430
+ operation: "min"
1431
+ }
1432
+ };
1433
+ GpuBlendModesToPixi.max = {
1434
+ alpha: {
1435
+ srcFactor: "one",
1436
+ dstFactor: "one",
1437
+ operation: "max"
1438
+ },
1439
+ color: {
1440
+ srcFactor: "one",
1441
+ dstFactor: "one",
1442
+ operation: "max"
1443
+ }
1444
+ };
1445
+ class GpuStateSystem {
1446
+ constructor() {
1447
+ this.defaultState = new State();
1448
+ this.defaultState.blend = true;
1449
+ }
1450
+ contextChange(gpu) {
1451
+ this.gpu = gpu;
1452
+ }
1453
+ /**
1454
+ * Gets the blend mode data for the current state
1455
+ * @param state - The state to get the blend mode from
1456
+ * @param count - The number of color targets to create
1457
+ */
1458
+ getColorTargets(state, count) {
1459
+ const blend = GpuBlendModesToPixi[state.blendMode] || GpuBlendModesToPixi.normal;
1460
+ const targets = [];
1461
+ const target = {
1462
+ format: "bgra8unorm",
1463
+ writeMask: 0,
1464
+ blend
1465
+ };
1466
+ for (let i = 0; i < count; i++) {
1467
+ targets[i] = target;
1468
+ }
1469
+ return targets;
1470
+ }
1471
+ destroy() {
1472
+ this.gpu = null;
1473
+ }
1474
+ }
1475
+ GpuStateSystem.extension = {
1476
+ type: [
1477
+ ExtensionType.WebGPUSystem
1478
+ ],
1479
+ name: "state"
1480
+ };
1481
+ const gpuUploadBufferImageResource = {
1482
+ type: "image",
1483
+ upload(source, gpuTexture, gpu, originZOverride = 0) {
1484
+ const resource = source.resource;
1485
+ const total = (source.pixelWidth | 0) * (source.pixelHeight | 0);
1486
+ const bytesPerPixel = resource.byteLength / total;
1487
+ gpu.device.queue.writeTexture(
1488
+ { texture: gpuTexture, origin: { x: 0, y: 0, z: originZOverride } },
1489
+ resource,
1490
+ {
1491
+ offset: 0,
1492
+ rowsPerImage: source.pixelHeight,
1493
+ bytesPerRow: source.pixelWidth * bytesPerPixel
1494
+ },
1495
+ {
1496
+ width: source.pixelWidth,
1497
+ height: source.pixelHeight,
1498
+ depthOrArrayLayers: 1
1499
+ }
1500
+ );
1501
+ }
1502
+ };
1503
+ const blockDataMap = {
1504
+ "bc1-rgba-unorm": { blockBytes: 8, blockWidth: 4, blockHeight: 4 },
1505
+ "bc2-rgba-unorm": { blockBytes: 16, blockWidth: 4, blockHeight: 4 },
1506
+ "bc3-rgba-unorm": { blockBytes: 16, blockWidth: 4, blockHeight: 4 },
1507
+ "bc7-rgba-unorm": { blockBytes: 16, blockWidth: 4, blockHeight: 4 },
1508
+ "etc1-rgb-unorm": { blockBytes: 8, blockWidth: 4, blockHeight: 4 },
1509
+ "etc2-rgba8unorm": { blockBytes: 16, blockWidth: 4, blockHeight: 4 },
1510
+ "astc-4x4-unorm": { blockBytes: 16, blockWidth: 4, blockHeight: 4 }
1511
+ };
1512
+ const defaultBlockData = { blockBytes: 4, blockWidth: 1, blockHeight: 1 };
1513
+ const gpuUploadCompressedTextureResource = {
1514
+ type: "compressed",
1515
+ upload(source, gpuTexture, gpu, originZOverride = 0) {
1516
+ let mipWidth = source.pixelWidth;
1517
+ let mipHeight = source.pixelHeight;
1518
+ const blockData = blockDataMap[source.format] || defaultBlockData;
1519
+ for (let i = 0; i < source.resource.length; i++) {
1520
+ const levelBuffer = source.resource[i];
1521
+ const bytesPerRow = Math.ceil(mipWidth / blockData.blockWidth) * blockData.blockBytes;
1522
+ gpu.device.queue.writeTexture(
1523
+ {
1524
+ texture: gpuTexture,
1525
+ mipLevel: i,
1526
+ origin: { x: 0, y: 0, z: originZOverride }
1527
+ },
1528
+ levelBuffer,
1529
+ {
1530
+ offset: 0,
1531
+ bytesPerRow
1532
+ },
1533
+ {
1534
+ width: Math.ceil(mipWidth / blockData.blockWidth) * blockData.blockWidth,
1535
+ height: Math.ceil(mipHeight / blockData.blockHeight) * blockData.blockHeight,
1536
+ depthOrArrayLayers: 1
1537
+ }
1538
+ );
1539
+ mipWidth = Math.max(mipWidth >> 1, 1);
1540
+ mipHeight = Math.max(mipHeight >> 1, 1);
1541
+ }
1542
+ }
1543
+ };
1544
+ const FACE_ORDER = ["right", "left", "top", "bottom", "front", "back"];
1545
+ function createGpuUploadCubeTextureResource(uploaders) {
1546
+ return {
1547
+ type: "cube",
1548
+ upload(source, gpuTexture, gpu) {
1549
+ const faces = source.faces;
1550
+ for (let i = 0; i < FACE_ORDER.length; i++) {
1551
+ const key = FACE_ORDER[i];
1552
+ const face = faces[key];
1553
+ const uploader = uploaders[face.uploadMethodId] || uploaders.image;
1554
+ uploader.upload(face, gpuTexture, gpu, i);
1555
+ }
1556
+ }
1557
+ };
1558
+ }
1559
+ const gpuUploadImageResource = {
1560
+ type: "image",
1561
+ upload(source, gpuTexture, gpu, originZOverride = 0) {
1562
+ const resource = source.resource;
1563
+ if (!resource) return;
1564
+ if (globalThis.HTMLImageElement && resource instanceof HTMLImageElement) {
1565
+ const canvas = DOMAdapter.get().createCanvas(resource.width, resource.height);
1566
+ const context = canvas.getContext("2d");
1567
+ context.drawImage(resource, 0, 0, resource.width, resource.height);
1568
+ source.resource = canvas;
1569
+ warn("ImageSource: Image element passed, converting to canvas and replacing resource.");
1570
+ }
1571
+ const width = Math.min(gpuTexture.width, source.resourceWidth || source.pixelWidth);
1572
+ const height = Math.min(gpuTexture.height, source.resourceHeight || source.pixelHeight);
1573
+ const premultipliedAlpha = source.alphaMode === "premultiply-alpha-on-upload";
1574
+ gpu.device.queue.copyExternalImageToTexture(
1575
+ { source: resource },
1576
+ { texture: gpuTexture, origin: { x: 0, y: 0, z: originZOverride }, premultipliedAlpha },
1577
+ {
1578
+ width,
1579
+ height
1580
+ }
1581
+ );
1582
+ }
1583
+ };
1584
+ const gpuUploadVideoResource = {
1585
+ type: "video",
1586
+ upload(source, gpuTexture, gpu, originZOverride) {
1587
+ gpuUploadImageResource.upload(source, gpuTexture, gpu, originZOverride);
1588
+ }
1589
+ };
1590
+ class GpuMipmapGenerator {
1591
+ constructor(device) {
1592
+ this.device = device;
1593
+ this.sampler = device.createSampler({ minFilter: "linear" });
1594
+ this.pipelines = {};
1595
+ }
1596
+ _getMipmapPipeline(format) {
1597
+ let pipeline = this.pipelines[format];
1598
+ if (!pipeline) {
1599
+ if (!this.mipmapShaderModule) {
1600
+ this.mipmapShaderModule = this.device.createShaderModule({
1601
+ code: (
1602
+ /* wgsl */
1603
+ `
1604
+ var<private> pos : array<vec2<f32>, 3> = array<vec2<f32>, 3>(
1605
+ vec2<f32>(-1.0, -1.0), vec2<f32>(-1.0, 3.0), vec2<f32>(3.0, -1.0));
1606
+
1607
+ struct VertexOutput {
1608
+ @builtin(position) position : vec4<f32>,
1609
+ @location(0) texCoord : vec2<f32>,
1610
+ };
1611
+
1612
+ @vertex
1613
+ fn vertexMain(@builtin(vertex_index) vertexIndex : u32) -> VertexOutput {
1614
+ var output : VertexOutput;
1615
+ output.texCoord = pos[vertexIndex] * vec2<f32>(0.5, -0.5) + vec2<f32>(0.5);
1616
+ output.position = vec4<f32>(pos[vertexIndex], 0.0, 1.0);
1617
+ return output;
1618
+ }
1619
+
1620
+ @group(0) @binding(0) var imgSampler : sampler;
1621
+ @group(0) @binding(1) var img : texture_2d<f32>;
1622
+
1623
+ @fragment
1624
+ fn fragmentMain(@location(0) texCoord : vec2<f32>) -> @location(0) vec4<f32> {
1625
+ return textureSample(img, imgSampler, texCoord);
1626
+ }
1627
+ `
1628
+ )
1629
+ });
1630
+ }
1631
+ pipeline = this.device.createRenderPipeline({
1632
+ layout: "auto",
1633
+ vertex: {
1634
+ module: this.mipmapShaderModule,
1635
+ entryPoint: "vertexMain"
1636
+ },
1637
+ fragment: {
1638
+ module: this.mipmapShaderModule,
1639
+ entryPoint: "fragmentMain",
1640
+ targets: [{ format }]
1641
+ }
1642
+ });
1643
+ this.pipelines[format] = pipeline;
1644
+ }
1645
+ return pipeline;
1646
+ }
1647
+ /**
1648
+ * Generates mipmaps for the given GPUTexture from the data in level 0.
1649
+ * @param {module:External.GPUTexture} texture - Texture to generate mipmaps for.
1650
+ * @returns {module:External.GPUTexture} - The originally passed texture
1651
+ */
1652
+ generateMipmap(texture) {
1653
+ const pipeline = this._getMipmapPipeline(texture.format);
1654
+ if (texture.dimension === "3d" || texture.dimension === "1d") {
1655
+ throw new Error("Generating mipmaps for non-2d textures is currently unsupported!");
1656
+ }
1657
+ let mipTexture = texture;
1658
+ const arrayLayerCount = texture.depthOrArrayLayers || 1;
1659
+ const renderToSource = texture.usage & GPUTextureUsage.RENDER_ATTACHMENT;
1660
+ if (!renderToSource) {
1661
+ const mipTextureDescriptor = {
1662
+ size: {
1663
+ width: Math.ceil(texture.width / 2),
1664
+ height: Math.ceil(texture.height / 2),
1665
+ depthOrArrayLayers: arrayLayerCount
1666
+ },
1667
+ format: texture.format,
1668
+ usage: GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_SRC | GPUTextureUsage.RENDER_ATTACHMENT,
1669
+ mipLevelCount: texture.mipLevelCount - 1
1670
+ };
1671
+ mipTexture = this.device.createTexture(mipTextureDescriptor);
1672
+ }
1673
+ const commandEncoder = this.device.createCommandEncoder({});
1674
+ const bindGroupLayout = pipeline.getBindGroupLayout(0);
1675
+ for (let arrayLayer = 0; arrayLayer < arrayLayerCount; ++arrayLayer) {
1676
+ let srcView = texture.createView({
1677
+ baseMipLevel: 0,
1678
+ mipLevelCount: 1,
1679
+ dimension: "2d",
1680
+ baseArrayLayer: arrayLayer,
1681
+ arrayLayerCount: 1
1682
+ });
1683
+ let dstMipLevel = renderToSource ? 1 : 0;
1684
+ for (let i = 1; i < texture.mipLevelCount; ++i) {
1685
+ const dstView = mipTexture.createView({
1686
+ baseMipLevel: dstMipLevel++,
1687
+ mipLevelCount: 1,
1688
+ dimension: "2d",
1689
+ baseArrayLayer: arrayLayer,
1690
+ arrayLayerCount: 1
1691
+ });
1692
+ const passEncoder = commandEncoder.beginRenderPass({
1693
+ colorAttachments: [{
1694
+ view: dstView,
1695
+ storeOp: "store",
1696
+ loadOp: "clear",
1697
+ clearValue: { r: 0, g: 0, b: 0, a: 0 }
1698
+ }]
1699
+ });
1700
+ const bindGroup = this.device.createBindGroup({
1701
+ layout: bindGroupLayout,
1702
+ entries: [{
1703
+ binding: 0,
1704
+ resource: this.sampler
1705
+ }, {
1706
+ binding: 1,
1707
+ resource: srcView
1708
+ }]
1709
+ });
1710
+ passEncoder.setPipeline(pipeline);
1711
+ passEncoder.setBindGroup(0, bindGroup);
1712
+ passEncoder.draw(3, 1, 0, 0);
1713
+ passEncoder.end();
1714
+ srcView = dstView;
1715
+ }
1716
+ }
1717
+ if (!renderToSource) {
1718
+ const mipLevelSize = {
1719
+ width: Math.ceil(texture.width / 2),
1720
+ height: Math.ceil(texture.height / 2),
1721
+ depthOrArrayLayers: arrayLayerCount
1722
+ };
1723
+ for (let i = 1; i < texture.mipLevelCount; ++i) {
1724
+ commandEncoder.copyTextureToTexture({
1725
+ texture: mipTexture,
1726
+ mipLevel: i - 1
1727
+ }, {
1728
+ texture,
1729
+ mipLevel: i
1730
+ }, mipLevelSize);
1731
+ mipLevelSize.width = Math.ceil(mipLevelSize.width / 2);
1732
+ mipLevelSize.height = Math.ceil(mipLevelSize.height / 2);
1733
+ }
1734
+ }
1735
+ this.device.queue.submit([commandEncoder.finish()]);
1736
+ if (!renderToSource) {
1737
+ mipTexture.destroy();
1738
+ }
1739
+ return texture;
1740
+ }
1741
+ }
1742
+ class GPUTextureGpuData {
1743
+ constructor(gpuTexture) {
1744
+ this.textureView = null;
1745
+ this.gpuTexture = gpuTexture;
1746
+ }
1747
+ /** Destroys this GPU data instance. */
1748
+ destroy() {
1749
+ this.gpuTexture.destroy();
1750
+ this.textureView = null;
1751
+ this.gpuTexture = null;
1752
+ }
1753
+ }
1754
+ class GpuTextureSystem {
1755
+ constructor(renderer) {
1756
+ this._gpuSamplers = /* @__PURE__ */ Object.create(null);
1757
+ this._bindGroupHash = /* @__PURE__ */ Object.create(null);
1758
+ this._renderer = renderer;
1759
+ renderer.gc.addCollection(this, "_bindGroupHash", "hash");
1760
+ this._managedTextures = new GCManagedHash({
1761
+ renderer,
1762
+ type: "resource",
1763
+ onUnload: this.onSourceUnload.bind(this),
1764
+ name: "gpuTextureSource"
1765
+ });
1766
+ const baseUploaders = {
1767
+ image: gpuUploadImageResource,
1768
+ buffer: gpuUploadBufferImageResource,
1769
+ video: gpuUploadVideoResource,
1770
+ compressed: gpuUploadCompressedTextureResource
1771
+ };
1772
+ this._uploads = {
1773
+ ...baseUploaders,
1774
+ cube: createGpuUploadCubeTextureResource(baseUploaders)
1775
+ };
1776
+ }
1777
+ /**
1778
+ * @deprecated since 8.15.0
1779
+ */
1780
+ get managedTextures() {
1781
+ return Object.values(this._managedTextures.items);
1782
+ }
1783
+ contextChange(gpu) {
1784
+ this._gpu = gpu;
1785
+ }
1786
+ /**
1787
+ * Initializes a texture source, if it has already been initialized nothing will happen.
1788
+ * @param source - The texture source to initialize.
1789
+ * @returns The initialized texture source.
1790
+ */
1791
+ initSource(source) {
1792
+ return source._gpuData[this._renderer.uid]?.gpuTexture || this._initSource(source);
1793
+ }
1794
+ _initSource(source) {
1795
+ if (source.autoGenerateMipmaps) {
1796
+ const biggestDimension = Math.max(source.pixelWidth, source.pixelHeight);
1797
+ source.mipLevelCount = Math.floor(Math.log2(biggestDimension)) + 1;
1798
+ }
1799
+ let usage = GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST;
1800
+ if (source.uploadMethodId !== "compressed") {
1801
+ usage |= GPUTextureUsage.RENDER_ATTACHMENT;
1802
+ usage |= GPUTextureUsage.COPY_SRC;
1803
+ }
1804
+ const blockData = blockDataMap[source.format] || { blockWidth: 1, blockHeight: 1 };
1805
+ const width = Math.ceil(source.pixelWidth / blockData.blockWidth) * blockData.blockWidth;
1806
+ const height = Math.ceil(source.pixelHeight / blockData.blockHeight) * blockData.blockHeight;
1807
+ const textureDescriptor = {
1808
+ label: source.label,
1809
+ size: { width, height, depthOrArrayLayers: source.arrayLayerCount },
1810
+ format: source.format,
1811
+ sampleCount: source.sampleCount,
1812
+ mipLevelCount: source.mipLevelCount,
1813
+ dimension: source.dimension,
1814
+ usage
1815
+ };
1816
+ const gpuTexture = this._gpu.device.createTexture(textureDescriptor);
1817
+ source._gpuData[this._renderer.uid] = new GPUTextureGpuData(gpuTexture);
1818
+ const added = this._managedTextures.add(source);
1819
+ if (added) {
1820
+ source.on("update", this.onSourceUpdate, this);
1821
+ source.on("resize", this.onSourceResize, this);
1822
+ source.on("updateMipmaps", this.onUpdateMipmaps, this);
1823
+ }
1824
+ this.onSourceUpdate(source);
1825
+ return gpuTexture;
1826
+ }
1827
+ onSourceUpdate(source) {
1828
+ const gpuTexture = this.getGpuSource(source);
1829
+ if (!gpuTexture) return;
1830
+ if (this._uploads[source.uploadMethodId]) {
1831
+ this._uploads[source.uploadMethodId].upload(source, gpuTexture, this._gpu);
1832
+ }
1833
+ if (source.autoGenerateMipmaps && source.mipLevelCount > 1) {
1834
+ this.onUpdateMipmaps(source);
1835
+ }
1836
+ }
1837
+ onUpdateMipmaps(source) {
1838
+ if (!this._mipmapGenerator) {
1839
+ this._mipmapGenerator = new GpuMipmapGenerator(this._gpu.device);
1840
+ }
1841
+ const gpuTexture = this.getGpuSource(source);
1842
+ this._mipmapGenerator.generateMipmap(gpuTexture);
1843
+ }
1844
+ onSourceUnload(source) {
1845
+ source.off("update", this.onSourceUpdate, this);
1846
+ source.off("resize", this.onSourceResize, this);
1847
+ source.off("updateMipmaps", this.onUpdateMipmaps, this);
1848
+ }
1849
+ onSourceResize(source) {
1850
+ source._gcLastUsed = this._renderer.gc.now;
1851
+ const gpuData = source._gpuData[this._renderer.uid];
1852
+ const gpuTexture = gpuData?.gpuTexture;
1853
+ if (!gpuTexture) {
1854
+ this.initSource(source);
1855
+ } else if (gpuTexture.width !== source.pixelWidth || gpuTexture.height !== source.pixelHeight) {
1856
+ gpuData.destroy();
1857
+ this._bindGroupHash[source.uid] = null;
1858
+ source._gpuData[this._renderer.uid] = null;
1859
+ this.initSource(source);
1860
+ }
1861
+ }
1862
+ _initSampler(sampler) {
1863
+ this._gpuSamplers[sampler._resourceId] = this._gpu.device.createSampler(sampler);
1864
+ return this._gpuSamplers[sampler._resourceId];
1865
+ }
1866
+ getGpuSampler(sampler) {
1867
+ return this._gpuSamplers[sampler._resourceId] || this._initSampler(sampler);
1868
+ }
1869
+ getGpuSource(source) {
1870
+ source._gcLastUsed = this._renderer.gc.now;
1871
+ return source._gpuData[this._renderer.uid]?.gpuTexture || this.initSource(source);
1872
+ }
1873
+ /**
1874
+ * this returns s bind group for a specific texture, the bind group contains
1875
+ * - the texture source
1876
+ * - the texture style
1877
+ * - the texture matrix
1878
+ * This is cached so the bind group should only be created once per texture
1879
+ * @param texture - the texture you want the bindgroup for
1880
+ * @returns the bind group for the texture
1881
+ */
1882
+ getTextureBindGroup(texture) {
1883
+ return this._bindGroupHash[texture.uid] || this._createTextureBindGroup(texture);
1884
+ }
1885
+ _createTextureBindGroup(texture) {
1886
+ const source = texture.source;
1887
+ this._bindGroupHash[texture.uid] = new BindGroup({
1888
+ 0: source,
1889
+ 1: source.style,
1890
+ 2: new UniformGroup({
1891
+ uTextureMatrix: { type: "mat3x3<f32>", value: texture.textureMatrix.mapCoord }
1892
+ })
1893
+ });
1894
+ return this._bindGroupHash[texture.uid];
1895
+ }
1896
+ getTextureView(texture) {
1897
+ const source = texture.source;
1898
+ source._gcLastUsed = this._renderer.gc.now;
1899
+ let gpuData = source._gpuData[this._renderer.uid];
1900
+ if (!gpuData) {
1901
+ this.initSource(source);
1902
+ gpuData = source._gpuData[this._renderer.uid];
1903
+ }
1904
+ gpuData.textureView || (gpuData.textureView = gpuData.gpuTexture.createView({ dimension: source.viewDimension }));
1905
+ return gpuData.textureView;
1906
+ }
1907
+ generateCanvas(texture) {
1908
+ const renderer = this._renderer;
1909
+ const commandEncoder = renderer.gpu.device.createCommandEncoder();
1910
+ const canvas = DOMAdapter.get().createCanvas();
1911
+ canvas.width = texture.source.pixelWidth;
1912
+ canvas.height = texture.source.pixelHeight;
1913
+ const context = canvas.getContext("webgpu");
1914
+ context.configure({
1915
+ device: renderer.gpu.device,
1916
+ usage: GPUTextureUsage.COPY_DST | GPUTextureUsage.COPY_SRC,
1917
+ format: DOMAdapter.get().getNavigator().gpu.getPreferredCanvasFormat(),
1918
+ alphaMode: "premultiplied"
1919
+ });
1920
+ commandEncoder.copyTextureToTexture({
1921
+ texture: renderer.texture.getGpuSource(texture.source),
1922
+ origin: {
1923
+ x: 0,
1924
+ y: 0
1925
+ }
1926
+ }, {
1927
+ texture: context.getCurrentTexture()
1928
+ }, {
1929
+ width: canvas.width,
1930
+ height: canvas.height
1931
+ });
1932
+ renderer.gpu.device.queue.submit([commandEncoder.finish()]);
1933
+ return canvas;
1934
+ }
1935
+ getPixels(texture) {
1936
+ const webGPUCanvas = this.generateCanvas(texture);
1937
+ const canvasAndContext = CanvasPool.getOptimalCanvasAndContext(webGPUCanvas.width, webGPUCanvas.height);
1938
+ const context = canvasAndContext.context;
1939
+ context.drawImage(webGPUCanvas, 0, 0);
1940
+ const { width, height } = webGPUCanvas;
1941
+ const imageData = context.getImageData(0, 0, width, height);
1942
+ const pixels = new Uint8ClampedArray(imageData.data.buffer);
1943
+ CanvasPool.returnCanvasAndContext(canvasAndContext);
1944
+ return { pixels, width, height };
1945
+ }
1946
+ destroy() {
1947
+ this._managedTextures.destroy();
1948
+ for (const k of Object.keys(this._bindGroupHash)) {
1949
+ const key = Number(k);
1950
+ const bindGroup = this._bindGroupHash[key];
1951
+ bindGroup?.destroy();
1952
+ }
1953
+ this._renderer = null;
1954
+ this._gpu = null;
1955
+ this._mipmapGenerator = null;
1956
+ this._gpuSamplers = null;
1957
+ this._bindGroupHash = null;
1958
+ }
1959
+ }
1960
+ GpuTextureSystem.extension = {
1961
+ type: [
1962
+ ExtensionType.WebGPUSystem
1963
+ ],
1964
+ name: "texture"
1965
+ };
1966
+ class GpuGraphicsAdaptor {
1967
+ constructor() {
1968
+ this._maxTextures = 0;
1969
+ }
1970
+ contextChange(renderer) {
1971
+ const localUniforms = new UniformGroup({
1972
+ uTransformMatrix: { value: new Matrix(), type: "mat3x3<f32>" },
1973
+ uColor: { value: new Float32Array([1, 1, 1, 1]), type: "vec4<f32>" },
1974
+ uRound: { value: 0, type: "f32" }
1975
+ });
1976
+ this._maxTextures = renderer.limits.maxBatchableTextures;
1977
+ const gpuProgram = compileHighShaderGpuProgram({
1978
+ name: "graphics",
1979
+ bits: [
1980
+ colorBit,
1981
+ generateTextureBatchBit(this._maxTextures),
1982
+ localUniformBitGroup2,
1983
+ roundPixelsBit
1984
+ ]
1985
+ });
1986
+ this.shader = new Shader({
1987
+ gpuProgram,
1988
+ resources: {
1989
+ // added on the fly!
1990
+ localUniforms
1991
+ }
1992
+ });
1993
+ }
1994
+ execute(graphicsPipe, renderable) {
1995
+ const context = renderable.context;
1996
+ const shader = context.customShader || this.shader;
1997
+ const renderer = graphicsPipe.renderer;
1998
+ const contextSystem = renderer.graphicsContext;
1999
+ const {
2000
+ batcher,
2001
+ instructions
2002
+ } = contextSystem.getContextRenderData(context);
2003
+ const encoder = renderer.encoder;
2004
+ encoder.setGeometry(batcher.geometry, shader.gpuProgram);
2005
+ const globalUniformsBindGroup = renderer.globalUniforms.bindGroup;
2006
+ encoder.setBindGroup(0, globalUniformsBindGroup, shader.gpuProgram);
2007
+ const localBindGroup = renderer.renderPipes.uniformBatch.getUniformBindGroup(shader.resources.localUniforms, true);
2008
+ encoder.setBindGroup(2, localBindGroup, shader.gpuProgram);
2009
+ const batches = instructions.instructions;
2010
+ let topology = null;
2011
+ for (let i = 0; i < instructions.instructionSize; i++) {
2012
+ const batch = batches[i];
2013
+ if (batch.topology !== topology) {
2014
+ topology = batch.topology;
2015
+ encoder.setPipelineFromGeometryProgramAndState(
2016
+ batcher.geometry,
2017
+ shader.gpuProgram,
2018
+ graphicsPipe.state,
2019
+ batch.topology
2020
+ );
2021
+ }
2022
+ shader.groups[1] = batch.bindGroup;
2023
+ if (!batch.gpuBindGroup) {
2024
+ const textureBatch = batch.textures;
2025
+ batch.bindGroup = getTextureBatchBindGroup(
2026
+ textureBatch.textures,
2027
+ textureBatch.count,
2028
+ this._maxTextures
2029
+ );
2030
+ batch.gpuBindGroup = renderer.bindGroup.getBindGroup(
2031
+ batch.bindGroup,
2032
+ shader.gpuProgram,
2033
+ 1
2034
+ );
2035
+ }
2036
+ encoder.setBindGroup(1, batch.bindGroup, shader.gpuProgram);
2037
+ encoder.renderPassEncoder.drawIndexed(batch.size, 1, batch.start);
2038
+ }
2039
+ }
2040
+ destroy() {
2041
+ this.shader.destroy(true);
2042
+ this.shader = null;
2043
+ }
2044
+ }
2045
+ GpuGraphicsAdaptor.extension = {
2046
+ type: [
2047
+ ExtensionType.WebGPUPipesAdaptor
2048
+ ],
2049
+ name: "graphics"
2050
+ };
2051
+ class GpuMeshAdapter {
2052
+ init() {
2053
+ const gpuProgram = compileHighShaderGpuProgram({
2054
+ name: "mesh",
2055
+ bits: [
2056
+ localUniformBit,
2057
+ textureBit,
2058
+ roundPixelsBit
2059
+ ]
2060
+ });
2061
+ this._shader = new Shader({
2062
+ gpuProgram,
2063
+ resources: {
2064
+ uTexture: Texture.EMPTY._source,
2065
+ uSampler: Texture.EMPTY._source.style,
2066
+ textureUniforms: {
2067
+ uTextureMatrix: { type: "mat3x3<f32>", value: new Matrix() }
2068
+ }
2069
+ }
2070
+ });
2071
+ }
2072
+ execute(meshPipe, mesh) {
2073
+ const renderer = meshPipe.renderer;
2074
+ let shader = mesh._shader;
2075
+ if (!shader) {
2076
+ shader = this._shader;
2077
+ shader.groups[2] = renderer.texture.getTextureBindGroup(mesh.texture);
2078
+ } else if (!shader.gpuProgram) {
2079
+ warn("Mesh shader has no gpuProgram", mesh.shader);
2080
+ return;
2081
+ }
2082
+ const gpuProgram = shader.gpuProgram;
2083
+ if (gpuProgram.autoAssignGlobalUniforms) {
2084
+ shader.groups[0] = renderer.globalUniforms.bindGroup;
2085
+ }
2086
+ if (gpuProgram.autoAssignLocalUniforms) {
2087
+ const localUniforms = meshPipe.localUniforms;
2088
+ shader.groups[1] = renderer.renderPipes.uniformBatch.getUniformBindGroup(localUniforms, true);
2089
+ }
2090
+ renderer.encoder.draw({
2091
+ geometry: mesh._geometry,
2092
+ shader,
2093
+ state: mesh.state
2094
+ });
2095
+ }
2096
+ destroy() {
2097
+ this._shader.destroy(true);
2098
+ this._shader = null;
2099
+ }
2100
+ }
2101
+ GpuMeshAdapter.extension = {
2102
+ type: [
2103
+ ExtensionType.WebGPUPipesAdaptor
2104
+ ],
2105
+ name: "mesh"
2106
+ };
2107
+ const DefaultWebGPUSystems = [
2108
+ ...SharedSystems,
2109
+ GpuUboSystem,
2110
+ GpuEncoderSystem,
2111
+ GpuDeviceSystem,
2112
+ GpuLimitsSystem,
2113
+ GpuBufferSystem,
2114
+ GpuTextureSystem,
2115
+ GpuRenderTargetSystem,
2116
+ GpuShaderSystem,
2117
+ GpuStateSystem,
2118
+ PipelineSystem,
2119
+ GpuColorMaskSystem,
2120
+ GpuStencilSystem,
2121
+ BindGroupSystem
2122
+ ];
2123
+ const DefaultWebGPUPipes = [...SharedRenderPipes, GpuUniformBatchPipe];
2124
+ const DefaultWebGPUAdapters = [GpuBatchAdaptor, GpuMeshAdapter, GpuGraphicsAdaptor];
2125
+ const systems = [];
2126
+ const renderPipes = [];
2127
+ const renderPipeAdaptors = [];
2128
+ extensions.handleByNamedList(ExtensionType.WebGPUSystem, systems);
2129
+ extensions.handleByNamedList(ExtensionType.WebGPUPipes, renderPipes);
2130
+ extensions.handleByNamedList(ExtensionType.WebGPUPipesAdaptor, renderPipeAdaptors);
2131
+ extensions.add(...DefaultWebGPUSystems, ...DefaultWebGPUPipes, ...DefaultWebGPUAdapters);
2132
+ class WebGPURenderer extends AbstractRenderer {
2133
+ constructor() {
2134
+ const systemConfig = {
2135
+ name: "webgpu",
2136
+ type: RendererType.WEBGPU,
2137
+ systems,
2138
+ renderPipes,
2139
+ renderPipeAdaptors
2140
+ };
2141
+ super(systemConfig);
2142
+ }
2143
+ }
2144
+ export {
2145
+ WebGPURenderer
2146
+ };