1 | import _regeneratorRuntime from "@babel/runtime/regenerator";
|
2 | import _asyncToGenerator from "@babel/runtime/helpers/asyncToGenerator";
|
3 | import _classCallCheck from "@babel/runtime/helpers/classCallCheck";
|
4 | import _createClass from "@babel/runtime/helpers/createClass";
|
5 |
|
6 | var _dec, _class, _temp;
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 | import { isSafari } from '@antv/g-webgpu-core';
|
14 |
|
15 | import * as WebGPUConstants from '@webgpu/types/dist/constants';
|
16 | import { injectable } from 'inversify';
|
17 | import glslang from './glslang';
|
18 | import WebGPUAttribute from './WebGPUAttribute';
|
19 | import WebGPUBuffer from './WebGPUBuffer';
|
20 | import WebGPUComputeModel from './WebGPUComputeModel';
|
21 | import WebGPUElements from './WebGPUElements';
|
22 | import WebGPUFramebuffer from './WebGPUFramebuffer';
|
23 | import WebGPUModel from './WebGPUModel';
|
24 | import WebGPUTexture2D from './WebGPUTexture2D';
|
25 | export
|
26 |
|
27 |
|
28 |
|
29 | var WebGPUEngine = (_dec = injectable(), _dec(_class = (_temp = function () {
|
30 | function WebGPUEngine() {
|
31 | var _this = this;
|
32 |
|
33 | _classCallCheck(this, WebGPUEngine);
|
34 |
|
35 | this.supportWebGPU = true;
|
36 | this.useWGSL = false;
|
37 | this.options = void 0;
|
38 | this.canvas = void 0;
|
39 | this.context = void 0;
|
40 | this.glslang = void 0;
|
41 | this.adapter = void 0;
|
42 | this.device = void 0;
|
43 | this.swapChain = void 0;
|
44 | this.mainPassSampleCount = void 0;
|
45 | this.mainTexture = void 0;
|
46 | this.depthTexture = void 0;
|
47 | this.mainColorAttachments = void 0;
|
48 | this.mainTextureExtends = void 0;
|
49 | this.mainDepthAttachment = void 0;
|
50 | this.uploadEncoder = void 0;
|
51 | this.renderEncoder = void 0;
|
52 | this.computeEncoder = void 0;
|
53 | this.renderTargetEncoder = void 0;
|
54 | this.commandBuffers = new Array(4).fill(undefined);
|
55 | this.currentRenderPass = null;
|
56 | this.mainRenderPass = null;
|
57 | this.currentRenderTargetViewDescriptor = void 0;
|
58 | this.currentComputePass = null;
|
59 | this.bundleEncoder = void 0;
|
60 | this.tempBuffers = [];
|
61 | this.currentRenderTarget = null;
|
62 | this.uploadEncoderDescriptor = {
|
63 | label: 'upload'
|
64 | };
|
65 | this.renderEncoderDescriptor = {
|
66 | label: 'render'
|
67 | };
|
68 | this.renderTargetEncoderDescriptor = {
|
69 | label: 'renderTarget'
|
70 | };
|
71 | this.computeEncoderDescriptor = {
|
72 | label: 'compute'
|
73 | };
|
74 | this.pipelines = {};
|
75 | this.computePipelines = {};
|
76 | this.defaultSampleCount = 4;
|
77 | this.clearDepthValue = 1;
|
78 | this.clearStencilValue = 0;
|
79 | this.transientViewport = {
|
80 | x: Infinity,
|
81 | y: 0,
|
82 | width: 0,
|
83 | height: 0
|
84 | };
|
85 | this.cachedViewport = {
|
86 | x: 0,
|
87 | y: 0,
|
88 | width: 0,
|
89 | height: 0
|
90 | };
|
91 |
|
92 | this.clear = function (options) {
|
93 | var framebuffer = options.framebuffer,
|
94 | color = options.color,
|
95 | depth = options.depth,
|
96 | stencil = options.stencil;
|
97 |
|
98 | if (_this.options.supportCompute) {
|
99 | _this.startComputePass();
|
100 | }
|
101 |
|
102 |
|
103 | if (_this.currentRenderTarget) {
|
104 | if (_this.currentRenderPass) {
|
105 | _this.endRenderTargetRenderPass();
|
106 | }
|
107 |
|
108 | _this.startRenderTargetRenderPass(_this.currentRenderTarget, color ? color : null, !!depth, !!stencil);
|
109 | } else {
|
110 |
|
111 |
|
112 |
|
113 | _this.mainColorAttachments[0].loadValue = color ? color : WebGPUConstants.LoadOp.Load;
|
114 | _this.mainDepthAttachment.depthLoadValue = depth ? depth : WebGPUConstants.LoadOp.Load;
|
115 | _this.mainDepthAttachment.stencilLoadValue = stencil ? _this.clearStencilValue : WebGPUConstants.LoadOp.Load;
|
116 |
|
117 | if (_this.mainRenderPass) {
|
118 | _this.endMainRenderPass();
|
119 | }
|
120 |
|
121 | _this.startMainRenderPass();
|
122 | }
|
123 | };
|
124 |
|
125 | this.createModel = function () {
|
126 | var _ref = _asyncToGenerator( _regeneratorRuntime.mark(function _callee(options) {
|
127 | var model;
|
128 | return _regeneratorRuntime.wrap(function _callee$(_context) {
|
129 | while (1) {
|
130 | switch (_context.prev = _context.next) {
|
131 | case 0:
|
132 | model = new WebGPUModel(_this, options);
|
133 | _context.next = 3;
|
134 | return model.init();
|
135 |
|
136 | case 3:
|
137 | return _context.abrupt("return", model);
|
138 |
|
139 | case 4:
|
140 | case "end":
|
141 | return _context.stop();
|
142 | }
|
143 | }
|
144 | }, _callee);
|
145 | }));
|
146 |
|
147 | return function (_x) {
|
148 | return _ref.apply(this, arguments);
|
149 | };
|
150 | }();
|
151 |
|
152 | this.createAttribute = function (options) {
|
153 | return new WebGPUAttribute(_this, options);
|
154 | };
|
155 |
|
156 | this.createBuffer = function (options) {
|
157 | return new WebGPUBuffer(_this, options);
|
158 | };
|
159 |
|
160 | this.createElements = function (options) {
|
161 | return new WebGPUElements(_this, options);
|
162 | };
|
163 |
|
164 | this.createTexture2D = function (options) {
|
165 | return new WebGPUTexture2D(_this, options);
|
166 | };
|
167 |
|
168 | this.createFramebuffer = function (options) {
|
169 | return new WebGPUFramebuffer(_this, options);
|
170 | };
|
171 |
|
172 | this.useFramebuffer = function (framebuffer, drawCommands) {
|
173 |
|
174 | if (_this.currentRenderTarget) {
|
175 | _this.unbindFramebuffer(_this.currentRenderTarget);
|
176 | }
|
177 |
|
178 | _this.currentRenderTarget = framebuffer;
|
179 |
|
180 | _this.currentRenderTargetViewDescriptor = {
|
181 | dimension: WebGPUConstants.TextureViewDimension.E2d,
|
182 |
|
183 |
|
184 |
|
185 | arrayLayerCount: 1,
|
186 | aspect: WebGPUConstants.TextureAspect.All
|
187 | };
|
188 | _this.currentRenderPass = null;
|
189 | drawCommands();
|
190 | };
|
191 |
|
192 | this.createComputeModel = function () {
|
193 | var _ref2 = _asyncToGenerator( _regeneratorRuntime.mark(function _callee2(context) {
|
194 | var model;
|
195 | return _regeneratorRuntime.wrap(function _callee2$(_context2) {
|
196 | while (1) {
|
197 | switch (_context2.prev = _context2.next) {
|
198 | case 0:
|
199 | model = new WebGPUComputeModel(_this, context);
|
200 | _context2.next = 3;
|
201 | return model.init();
|
202 |
|
203 | case 3:
|
204 | return _context2.abrupt("return", model);
|
205 |
|
206 | case 4:
|
207 | case "end":
|
208 | return _context2.stop();
|
209 | }
|
210 | }
|
211 | }, _callee2);
|
212 | }));
|
213 |
|
214 | return function (_x2) {
|
215 | return _ref2.apply(this, arguments);
|
216 | };
|
217 | }();
|
218 |
|
219 | this.getCanvas = function () {
|
220 | return _this.canvas;
|
221 | };
|
222 |
|
223 | this.getGLContext = function () {
|
224 | throw new Error('Method not implemented.');
|
225 | };
|
226 |
|
227 | this.viewport = function (_ref3) {
|
228 | var x = _ref3.x,
|
229 | y = _ref3.y,
|
230 | width = _ref3.width,
|
231 | height = _ref3.height;
|
232 |
|
233 | if (!_this.currentRenderPass) {
|
234 |
|
235 | _this.transientViewport = {
|
236 | x: x,
|
237 | y: y,
|
238 | width: width,
|
239 | height: height
|
240 | };
|
241 | } else if (_this.transientViewport.x !== Infinity) {
|
242 | var renderPass = _this.getCurrentRenderPass();
|
243 |
|
244 |
|
245 | renderPass.setViewport(_this.transientViewport.x, _this.transientViewport.y, _this.transientViewport.width, _this.transientViewport.height, 0, 1);
|
246 | } else if (x !== _this.cachedViewport.x || y !== _this.cachedViewport.y || width !== _this.cachedViewport.width || height !== _this.cachedViewport.height) {
|
247 | _this.cachedViewport = {
|
248 | x: x,
|
249 | y: y,
|
250 | width: width,
|
251 | height: height
|
252 | };
|
253 |
|
254 | var _renderPass = _this.getCurrentRenderPass();
|
255 |
|
256 | _renderPass.setViewport(x, y, width, height, 0, 1);
|
257 | }
|
258 | };
|
259 |
|
260 | this.readPixels = function (options) {
|
261 | throw new Error('Method not implemented.');
|
262 | };
|
263 | }
|
264 |
|
265 | _createClass(WebGPUEngine, [{
|
266 | key: "isFloatSupported",
|
267 | value: function isFloatSupported() {
|
268 | return true;
|
269 | }
|
270 | }, {
|
271 | key: "init",
|
272 | value: function () {
|
273 | var _init = _asyncToGenerator( _regeneratorRuntime.mark(function _callee3(config) {
|
274 | return _regeneratorRuntime.wrap(function _callee3$(_context3) {
|
275 | while (1) {
|
276 | switch (_context3.prev = _context3.next) {
|
277 | case 0:
|
278 | this.canvas = config.canvas;
|
279 | this.options = config;
|
280 | this.useWGSL = !!config.useWGSL;
|
281 | this.mainPassSampleCount = config.antialiasing ? this.defaultSampleCount : 1;
|
282 | _context3.next = 6;
|
283 | return this.initGlslang();
|
284 |
|
285 | case 6:
|
286 | this.initContextAndSwapChain();
|
287 | this.initMainAttachments();
|
288 |
|
289 | case 8:
|
290 | case "end":
|
291 | return _context3.stop();
|
292 | }
|
293 | }
|
294 | }, _callee3, this);
|
295 | }));
|
296 |
|
297 | function init(_x3) {
|
298 | return _init.apply(this, arguments);
|
299 | }
|
300 |
|
301 | return init;
|
302 | }()
|
303 | }, {
|
304 | key: "destroy",
|
305 | value: function destroy() {
|
306 | if (this.mainTexture) {
|
307 | this.mainTexture.destroy();
|
308 | }
|
309 |
|
310 | if (this.depthTexture) {
|
311 | this.depthTexture.destroy();
|
312 | }
|
313 |
|
314 | this.tempBuffers.forEach(function (buffer) {
|
315 | return buffer.destroy();
|
316 | });
|
317 | this.tempBuffers = [];
|
318 | }
|
319 | }, {
|
320 | key: "beginFrame",
|
321 | value: function beginFrame() {
|
322 | this.uploadEncoder = this.device.createCommandEncoder(this.uploadEncoderDescriptor);
|
323 | this.renderEncoder = this.device.createCommandEncoder(this.renderEncoderDescriptor);
|
324 | this.renderTargetEncoder = this.device.createCommandEncoder(this.renderTargetEncoderDescriptor);
|
325 |
|
326 | if (this.options.supportCompute) {
|
327 | this.computeEncoder = this.device.createCommandEncoder(this.computeEncoderDescriptor);
|
328 | }
|
329 | }
|
330 | }, {
|
331 | key: "endFrame",
|
332 | value: function endFrame() {
|
333 | if (this.options.supportCompute) {
|
334 | this.endComputePass();
|
335 | }
|
336 |
|
337 | this.endMainRenderPass();
|
338 | this.commandBuffers[0] = this.uploadEncoder.finish();
|
339 | this.commandBuffers[1] = this.renderEncoder.finish();
|
340 |
|
341 | if (this.options.supportCompute) {
|
342 | this.commandBuffers[2] = this.computeEncoder.finish();
|
343 | }
|
344 |
|
345 | this.commandBuffers[3] = this.renderTargetEncoder.finish();
|
346 |
|
347 | if (isSafari) {
|
348 | this.device
|
349 | .getQueue().submit(this.commandBuffers.filter(function (buffer) {
|
350 | return buffer;
|
351 | }));
|
352 | } else {
|
353 | this.device.defaultQueue.submit(this.commandBuffers.filter(function (buffer) {
|
354 | return buffer;
|
355 | }));
|
356 | }
|
357 | }
|
358 | }, {
|
359 | key: "getCurrentRenderPass",
|
360 | value: function getCurrentRenderPass() {
|
361 | if (this.currentRenderTarget && !this.currentRenderPass) {
|
362 | this.startRenderTargetRenderPass(this.currentRenderTarget, null, false, false);
|
363 | } else if (!this.currentRenderPass) {
|
364 | this.startMainRenderPass();
|
365 | }
|
366 |
|
367 | return this.currentRenderPass;
|
368 | }
|
369 | }, {
|
370 | key: "initGlslang",
|
371 | value: function () {
|
372 | var _initGlslang = _asyncToGenerator( _regeneratorRuntime.mark(function _callee4() {
|
373 | var _navigator, _navigator$gpu;
|
374 |
|
375 | return _regeneratorRuntime.wrap(function _callee4$(_context4) {
|
376 | while (1) {
|
377 | switch (_context4.prev = _context4.next) {
|
378 | case 0:
|
379 | _context4.next = 2;
|
380 | return glslang();
|
381 |
|
382 | case 2:
|
383 | this.glslang = _context4.sent;
|
384 | _context4.next = 5;
|
385 | return (_navigator = navigator) === null || _navigator === void 0 ? void 0 : (_navigator$gpu = _navigator.gpu) === null || _navigator$gpu === void 0 ? void 0 : _navigator$gpu.requestAdapter();
|
386 |
|
387 | case 5:
|
388 | this.adapter = _context4.sent;
|
389 | _context4.next = 8;
|
390 | return this.adapter.requestDevice();
|
391 |
|
392 | case 8:
|
393 | this.device = _context4.sent;
|
394 |
|
395 | case 9:
|
396 | case "end":
|
397 | return _context4.stop();
|
398 | }
|
399 | }
|
400 | }, _callee4, this);
|
401 | }));
|
402 |
|
403 | function initGlslang() {
|
404 | return _initGlslang.apply(this, arguments);
|
405 | }
|
406 |
|
407 | return initGlslang;
|
408 | }()
|
409 | }, {
|
410 | key: "initContextAndSwapChain",
|
411 | value: function initContextAndSwapChain() {
|
412 | this.context = this.canvas.getContext(isSafari ? 'gpu' : 'gpupresent');
|
413 | this.swapChain = this.context.configureSwapChain({
|
414 | device: this.device,
|
415 | format: this.options.swapChainFormat,
|
416 | usage: WebGPUConstants.TextureUsage.OutputAttachment | WebGPUConstants.TextureUsage.CopySrc
|
417 | });
|
418 | }
|
419 | }, {
|
420 | key: "initMainAttachments",
|
421 | value: function initMainAttachments() {
|
422 | this.mainTextureExtends = {
|
423 | width: this.canvas.width,
|
424 | height: this.canvas.height,
|
425 | depth: 1
|
426 | };
|
427 |
|
428 | if (this.options.antialiasing) {
|
429 | var mainTextureDescriptor = {
|
430 | size: this.mainTextureExtends,
|
431 |
|
432 |
|
433 | mipLevelCount: 1,
|
434 | sampleCount: this.mainPassSampleCount,
|
435 | dimension: WebGPUConstants.TextureDimension.E2d,
|
436 | format: WebGPUConstants.TextureFormat.BGRA8Unorm,
|
437 | usage: WebGPUConstants.TextureUsage.OutputAttachment
|
438 | };
|
439 |
|
440 | if (this.mainTexture) {
|
441 | this.mainTexture.destroy();
|
442 | }
|
443 |
|
444 | this.mainTexture = this.device.createTexture(mainTextureDescriptor);
|
445 | this.mainColorAttachments = [{
|
446 | attachment: isSafari ?
|
447 | this.mainTexture.createDefaultView() : this.mainTexture.createView(),
|
448 | loadValue: [0, 0, 0, 1],
|
449 | storeOp: WebGPUConstants.StoreOp.Store
|
450 | }];
|
451 | } else {
|
452 | this.mainColorAttachments = [{
|
453 | attachment: isSafari ?
|
454 | this.swapChain.getCurrentTexture().createDefaultView() : this.swapChain.getCurrentTexture().createView(),
|
455 | loadValue: [0, 0, 0, 1],
|
456 | storeOp: WebGPUConstants.StoreOp.Store
|
457 | }];
|
458 | }
|
459 |
|
460 | var depthTextureDescriptor = {
|
461 | size: this.mainTextureExtends,
|
462 |
|
463 | mipLevelCount: 1,
|
464 | sampleCount: this.mainPassSampleCount,
|
465 | dimension: WebGPUConstants.TextureDimension.E2d,
|
466 | format: isSafari ? 'depth32float-stencil8' : WebGPUConstants.TextureFormat.Depth24PlusStencil8,
|
467 | usage: WebGPUConstants.TextureUsage.OutputAttachment
|
468 | };
|
469 |
|
470 | if (this.depthTexture) {
|
471 | this.depthTexture.destroy();
|
472 | }
|
473 |
|
474 | this.depthTexture = this.device.createTexture(
|
475 | depthTextureDescriptor);
|
476 | this.mainDepthAttachment = {
|
477 | attachment: isSafari ?
|
478 | this.depthTexture.createDefaultView() : this.depthTexture.createView(),
|
479 | depthLoadValue: this.clearDepthValue,
|
480 | depthStoreOp: WebGPUConstants.StoreOp.Store,
|
481 | stencilLoadValue: this.clearStencilValue,
|
482 | stencilStoreOp: WebGPUConstants.StoreOp.Store
|
483 | };
|
484 | }
|
485 | }, {
|
486 | key: "startComputePass",
|
487 | value: function startComputePass() {
|
488 | if (this.currentComputePass) {
|
489 | this.endComputePass();
|
490 | }
|
491 |
|
492 | this.currentComputePass = this.computeEncoder.beginComputePass();
|
493 | }
|
494 | }, {
|
495 | key: "startMainRenderPass",
|
496 | value: function startMainRenderPass() {
|
497 | if (this.currentRenderPass && !this.currentRenderTarget) {
|
498 | this.endMainRenderPass();
|
499 | }
|
500 |
|
501 |
|
502 | if (this.options.antialiasing) {
|
503 | this.mainColorAttachments[0].resolveTarget = isSafari ?
|
504 | this.swapChain.getCurrentTexture().createDefaultView() : this.swapChain.getCurrentTexture().createView();
|
505 | } else {
|
506 | this.mainColorAttachments[0].attachment = isSafari ?
|
507 | this.swapChain.getCurrentTexture().createDefaultView() : this.swapChain.getCurrentTexture().createView();
|
508 | }
|
509 |
|
510 | this.currentRenderPass = this.renderEncoder.beginRenderPass({
|
511 | colorAttachments: this.mainColorAttachments,
|
512 | depthStencilAttachment: this.mainDepthAttachment
|
513 |
|
514 | });
|
515 | this.mainRenderPass = this.currentRenderPass;
|
516 |
|
517 | if (this.cachedViewport) {
|
518 | this.viewport(this.cachedViewport);
|
519 | }
|
520 | }
|
521 | }, {
|
522 | key: "startRenderTargetRenderPass",
|
523 | value: function startRenderTargetRenderPass(renderTarget, clearColor, clearDepth) {
|
524 | var _renderTarget$get$col, _renderTarget$get$dep;
|
525 |
|
526 | var clearStencil = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
|
527 | var gpuTexture = (_renderTarget$get$col = renderTarget.get().color) === null || _renderTarget$get$col === void 0 ? void 0 : _renderTarget$get$col.texture;
|
528 | var colorTextureView;
|
529 |
|
530 | if (gpuTexture) {
|
531 | colorTextureView = gpuTexture.createView(this.currentRenderTargetViewDescriptor);
|
532 | }
|
533 |
|
534 | var depthStencilTexture = (_renderTarget$get$dep = renderTarget.get().depth) === null || _renderTarget$get$dep === void 0 ? void 0 : _renderTarget$get$dep.texture;
|
535 | var depthStencilTextureView;
|
536 |
|
537 | if (depthStencilTexture) {
|
538 | depthStencilTextureView = depthStencilTexture.createView();
|
539 | }
|
540 |
|
541 | var renderPass = this.renderTargetEncoder.beginRenderPass({
|
542 | colorAttachments: [{
|
543 | attachment: colorTextureView,
|
544 | loadValue: clearColor !== null ? clearColor : WebGPUConstants.LoadOp.Load,
|
545 | storeOp: WebGPUConstants.StoreOp.Store
|
546 | }],
|
547 | depthStencilAttachment: depthStencilTexture && depthStencilTextureView ? {
|
548 | attachment: depthStencilTextureView,
|
549 | depthLoadValue: clearDepth ? this.clearDepthValue : WebGPUConstants.LoadOp.Load,
|
550 | depthStoreOp: WebGPUConstants.StoreOp.Store,
|
551 | stencilLoadValue: clearStencil ? this.clearStencilValue : WebGPUConstants.LoadOp.Load,
|
552 | stencilStoreOp: WebGPUConstants.StoreOp.Store
|
553 | } : undefined
|
554 | });
|
555 | this.currentRenderPass = renderPass;
|
556 |
|
557 | if (this.cachedViewport) {
|
558 | this.viewport(this.cachedViewport);
|
559 | }
|
560 |
|
561 | }
|
562 | }, {
|
563 | key: "endMainRenderPass",
|
564 | value: function endMainRenderPass() {
|
565 | if (this.currentRenderPass === this.mainRenderPass && this.currentRenderPass !== null) {
|
566 | this.currentRenderPass.endPass();
|
567 | this.resetCachedViewport();
|
568 | this.currentRenderPass = null;
|
569 | this.mainRenderPass = null;
|
570 | }
|
571 | }
|
572 | }, {
|
573 | key: "endComputePass",
|
574 | value: function endComputePass() {
|
575 | if (this.currentComputePass) {
|
576 | this.currentComputePass.endPass();
|
577 | this.currentComputePass = null;
|
578 | }
|
579 | }
|
580 | }, {
|
581 | key: "endRenderTargetRenderPass",
|
582 | value: function endRenderTargetRenderPass() {
|
583 | if (this.currentRenderPass) {
|
584 | this.currentRenderPass.endPass();
|
585 | this.resetCachedViewport();
|
586 | }
|
587 | }
|
588 | }, {
|
589 | key: "resetCachedViewport",
|
590 | value: function resetCachedViewport() {
|
591 | this.cachedViewport = {
|
592 | x: 0,
|
593 | y: 0,
|
594 | width: 0,
|
595 | height: 0
|
596 | };
|
597 | }
|
598 | }, {
|
599 | key: "unbindFramebuffer",
|
600 | value: function unbindFramebuffer(framebuffer) {
|
601 |
|
602 | if (this.currentRenderPass && this.currentRenderPass !== this.mainRenderPass) {
|
603 | this.endRenderTargetRenderPass();
|
604 | }
|
605 |
|
606 | this.transientViewport.x = Infinity;
|
607 | this.currentRenderTarget = null;
|
608 |
|
609 |
|
610 |
|
611 | this.currentRenderPass = this.mainRenderPass;
|
612 | }
|
613 | }]);
|
614 |
|
615 | return WebGPUEngine;
|
616 | }(), _temp)) || _class);
|
617 |
|
\ | No newline at end of file |