1 | import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
|
2 | import _typeof from "@babel/runtime/helpers/typeof";
|
3 | import _regeneratorRuntime from "@babel/runtime/regenerator";
|
4 | import _defineProperty from "@babel/runtime/helpers/defineProperty";
|
5 | import _asyncToGenerator from "@babel/runtime/helpers/asyncToGenerator";
|
6 | import _classCallCheck from "@babel/runtime/helpers/classCallCheck";
|
7 | import _createClass from "@babel/runtime/helpers/createClass";
|
8 |
|
9 | function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }
|
10 |
|
11 | function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
|
12 |
|
13 | import { gl, isSafari } from '@antv/g-webgpu-core';
|
14 | import * as WebGPUConstants from '@webgpu/types/dist/constants';
|
15 | import isNil from 'lodash/isNil';
|
16 | import { extractUniforms } from '../utils/uniform';
|
17 | import { getColorStateDescriptors, getCullMode, getDepthStencilStateDescriptor, primitiveMap } from './constants';
|
18 | import WebGPUBuffer from './WebGPUBuffer';
|
19 |
|
20 |
|
21 | function concatenate(resultConstructor) {
|
22 | var totalLength = 0;
|
23 |
|
24 | for (var _len = arguments.length, arrays = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
|
25 | arrays[_key - 1] = arguments[_key];
|
26 | }
|
27 |
|
28 | for (var _i = 0, _arrays = arrays; _i < _arrays.length; _i++) {
|
29 | var arr = _arrays[_i];
|
30 | totalLength += arr.length;
|
31 | }
|
32 |
|
33 | var result = new resultConstructor(totalLength);
|
34 | var offset = 0;
|
35 |
|
36 | for (var _i2 = 0, _arrays2 = arrays; _i2 < _arrays2.length; _i2++) {
|
37 | var _arr = _arrays2[_i2];
|
38 | result.set(_arr, offset);
|
39 | offset += _arr.length;
|
40 | }
|
41 |
|
42 | return result;
|
43 | }
|
44 |
|
45 | var WebGPUModel = function () {
|
46 | |
47 |
|
48 |
|
49 |
|
50 | |
51 |
|
52 |
|
53 |
|
54 | |
55 |
|
56 |
|
57 | function WebGPUModel(engine, options) {
|
58 | _classCallCheck(this, WebGPUModel);
|
59 |
|
60 | this.engine = engine;
|
61 | this.options = options;
|
62 | this.pipelineLayout = void 0;
|
63 | this.renderPipeline = void 0;
|
64 | this.uniformsBindGroupLayout = void 0;
|
65 | this.uniformBindGroup = void 0;
|
66 | this.uniformBuffer = void 0;
|
67 | this.uniforms = {};
|
68 | this.uniformGPUBufferLayout = [];
|
69 | this.attributeCache = {};
|
70 | this.indexBuffer = void 0;
|
71 | this.indexCount = void 0;
|
72 | }
|
73 |
|
74 | _createClass(WebGPUModel, [{
|
75 | key: "init",
|
76 | value: function () {
|
77 | var _init = _asyncToGenerator( _regeneratorRuntime.mark(function _callee() {
|
78 | var _this = this;
|
79 |
|
80 | var _this$options, vs, fs, attributes, uniforms, primitive, count, elements, depth, blend, stencil, cull, instances, _yield$this$compilePi, vertexStage, fragmentStage, vertexState, descriptor;
|
81 |
|
82 | return _regeneratorRuntime.wrap(function _callee$(_context) {
|
83 | while (1) {
|
84 | switch (_context.prev = _context.next) {
|
85 | case 0:
|
86 | _this$options = this.options, vs = _this$options.vs, fs = _this$options.fs, attributes = _this$options.attributes, uniforms = _this$options.uniforms, primitive = _this$options.primitive, count = _this$options.count, elements = _this$options.elements, depth = _this$options.depth, blend = _this$options.blend, stencil = _this$options.stencil, cull = _this$options.cull, instances = _this$options.instances;
|
87 |
|
88 | _context.next = 3;
|
89 | return this.compilePipelineStageDescriptor(vs, fs, null);
|
90 |
|
91 | case 3:
|
92 | _yield$this$compilePi = _context.sent;
|
93 | vertexStage = _yield$this$compilePi.vertexStage;
|
94 | fragmentStage = _yield$this$compilePi.fragmentStage;
|
95 |
|
96 | if (uniforms) {
|
97 |
|
98 | this.buildUniformBindGroup(uniforms);
|
99 | }
|
100 |
|
101 | if (elements) {
|
102 | this.indexBuffer = elements.get();
|
103 | this.indexCount = elements.indexCount;
|
104 | }
|
105 |
|
106 |
|
107 | vertexState = {
|
108 | vertexBuffers: Object.keys(attributes).map(function (attributeName, i) {
|
109 | var attribute = attributes[attributeName];
|
110 |
|
111 | var _attribute$get = attribute.get(),
|
112 | arrayStride = _attribute$get.arrayStride,
|
113 | stepMode = _attribute$get.stepMode,
|
114 | ats = _attribute$get.attributes;
|
115 |
|
116 | _this.attributeCache[attributeName] = attribute;
|
117 | return {
|
118 | arrayStride: arrayStride,
|
119 | stepMode: stepMode,
|
120 | attributes: ats
|
121 | };
|
122 | })
|
123 | };
|
124 | descriptor = {
|
125 | sampleCount: this.engine.mainPassSampleCount,
|
126 | primitiveTopology: primitiveMap[primitive || gl.TRIANGLES],
|
127 | rasterizationState: _objectSpread(_objectSpread({}, this.getDefaultRasterizationStateDescriptor()), {}, {
|
128 |
|
129 | cullMode: getCullMode({
|
130 | cull: cull
|
131 | })
|
132 | }),
|
133 | depthStencilState: getDepthStencilStateDescriptor({
|
134 | depth: depth,
|
135 | stencil: stencil
|
136 | }),
|
137 | colorStates: getColorStateDescriptors({
|
138 | blend: blend
|
139 | }, this.engine.options.swapChainFormat),
|
140 | layout: this.pipelineLayout,
|
141 | vertexStage: vertexStage,
|
142 | fragmentStage: fragmentStage,
|
143 | vertexState: vertexState
|
144 | };
|
145 |
|
146 | this.renderPipeline = this.engine.device.createRenderPipeline(descriptor);
|
147 |
|
148 | case 11:
|
149 | case "end":
|
150 | return _context.stop();
|
151 | }
|
152 | }
|
153 | }, _callee, this);
|
154 | }));
|
155 |
|
156 | function init() {
|
157 | return _init.apply(this, arguments);
|
158 | }
|
159 |
|
160 | return init;
|
161 | }()
|
162 | }, {
|
163 | key: "addUniforms",
|
164 | value: function addUniforms(uniforms) {
|
165 | this.uniforms = _objectSpread(_objectSpread({}, this.uniforms), extractUniforms(uniforms));
|
166 | }
|
167 | }, {
|
168 | key: "draw",
|
169 | value: function draw(options) {
|
170 | var _this2 = this;
|
171 |
|
172 | var renderPass = this.engine.getCurrentRenderPass();
|
173 |
|
174 | var uniforms = _objectSpread(_objectSpread({}, this.uniforms), extractUniforms(options.uniforms || {}));
|
175 |
|
176 | var bindGroupBindings = [];
|
177 |
|
178 | Object.keys(uniforms).forEach(function (uniformName) {
|
179 | var type = _typeof(uniforms[uniformName]);
|
180 |
|
181 | if (type === 'boolean' || type === 'number' || Array.isArray(uniforms[uniformName]) ||
|
182 | uniforms[uniformName].BYTES_PER_ELEMENT) {
|
183 | var _this2$uniformGPUBuff;
|
184 |
|
185 | var offset = (_this2$uniformGPUBuff = _this2.uniformGPUBufferLayout.find(function (_ref) {
|
186 | var name = _ref.name;
|
187 | return name === uniformName;
|
188 | })) === null || _this2$uniformGPUBuff === void 0 ? void 0 : _this2$uniformGPUBuff.offset;
|
189 |
|
190 | if (!isNil(offset)) {
|
191 | _this2.uniformBuffer.subData({
|
192 | data: uniforms[uniformName],
|
193 | offset: offset
|
194 | });
|
195 | }
|
196 | } else {
|
197 | var _this2$uniformGPUBuff2;
|
198 |
|
199 | var _offset = (_this2$uniformGPUBuff2 = _this2.uniformGPUBufferLayout.find(function (_ref2) {
|
200 | var name = _ref2.name;
|
201 | return name === uniformName;
|
202 | })) === null || _this2$uniformGPUBuff2 === void 0 ? void 0 : _this2$uniformGPUBuff2.offset;
|
203 |
|
204 | if (!isNil(_offset)) {
|
205 | var textureOrFramebuffer = uniforms[uniformName].get();
|
206 |
|
207 | var _ref3 = textureOrFramebuffer.color || textureOrFramebuffer,
|
208 | texture = _ref3.texture,
|
209 | sampler = _ref3.sampler;
|
210 |
|
211 | if (sampler) {
|
212 | bindGroupBindings.push({
|
213 | binding: _offset,
|
214 | resource: sampler
|
215 | });
|
216 | _offset++;
|
217 | }
|
218 |
|
219 | bindGroupBindings.push({
|
220 | binding: _offset,
|
221 | resource: texture.createView()
|
222 | });
|
223 | }
|
224 | }
|
225 | });
|
226 |
|
227 | if (this.uniformBuffer) {
|
228 | bindGroupBindings[0] = {
|
229 | binding: 0,
|
230 | resource: {
|
231 | buffer: this.uniformBuffer.get()
|
232 |
|
233 | }
|
234 | };
|
235 | }
|
236 |
|
237 | this.uniformBindGroup = this.engine.device.createBindGroup({
|
238 | layout: this.uniformsBindGroupLayout,
|
239 | entries: bindGroupBindings
|
240 | });
|
241 |
|
242 | if (this.renderPipeline) {
|
243 | renderPass.setPipeline(this.renderPipeline);
|
244 | }
|
245 |
|
246 | renderPass.setBindGroup(0, this.uniformBindGroup);
|
247 |
|
248 | if (this.indexBuffer) {
|
249 | renderPass.setIndexBuffer(this.indexBuffer.get(), WebGPUConstants.IndexFormat.Uint32, 0);
|
250 | }
|
251 |
|
252 | Object.keys(this.attributeCache).forEach(function (attributeName, i) {
|
253 | renderPass.setVertexBuffer(0 + i, _this2.attributeCache[attributeName].get().buffer, 0);
|
254 | });
|
255 |
|
256 | if (this.indexBuffer) {
|
257 | renderPass.drawIndexed(this.indexCount, this.options.instances || 1, 0, 0, 0);
|
258 | } else {
|
259 | renderPass.draw(this.options.count || 0, this.options.instances || 0, 0, 0);
|
260 | }
|
261 | }
|
262 | }, {
|
263 | key: "destroy",
|
264 | value: function destroy() {
|
265 | throw new Error('Method not implemented.');
|
266 | }
|
267 | }, {
|
268 | key: "compilePipelineStageDescriptor",
|
269 | value: function () {
|
270 | var _compilePipelineStageDescriptor = _asyncToGenerator( _regeneratorRuntime.mark(function _callee2(vertexCode, fragmentCode, defines) {
|
271 | var shaderVersion, vertexShader, fragmentShader;
|
272 | return _regeneratorRuntime.wrap(function _callee2$(_context2) {
|
273 | while (1) {
|
274 | switch (_context2.prev = _context2.next) {
|
275 | case 0:
|
276 | shaderVersion = '#version 450\n';
|
277 | vertexShader = vertexCode;
|
278 | fragmentShader = fragmentCode;
|
279 |
|
280 | if (this.engine.options.useWGSL) {
|
281 | _context2.next = 10;
|
282 | break;
|
283 | }
|
284 |
|
285 | _context2.next = 6;
|
286 | return this.compileShaderToSpirV(vertexCode, 'vertex', shaderVersion);
|
287 |
|
288 | case 6:
|
289 | vertexShader = _context2.sent;
|
290 | _context2.next = 9;
|
291 | return this.compileShaderToSpirV(fragmentCode, 'fragment', shaderVersion);
|
292 |
|
293 | case 9:
|
294 | fragmentShader = _context2.sent;
|
295 |
|
296 | case 10:
|
297 | return _context2.abrupt("return", this.createPipelineStageDescriptor(vertexShader, fragmentShader));
|
298 |
|
299 | case 11:
|
300 | case "end":
|
301 | return _context2.stop();
|
302 | }
|
303 | }
|
304 | }, _callee2, this);
|
305 | }));
|
306 |
|
307 | function compilePipelineStageDescriptor(_x, _x2, _x3) {
|
308 | return _compilePipelineStageDescriptor.apply(this, arguments);
|
309 | }
|
310 |
|
311 | return compilePipelineStageDescriptor;
|
312 | }()
|
313 | }, {
|
314 | key: "compileShaderToSpirV",
|
315 | value: function compileShaderToSpirV(source, type, shaderVersion) {
|
316 | return this.compileRawShaderToSpirV(shaderVersion + source, type);
|
317 | }
|
318 | }, {
|
319 | key: "compileRawShaderToSpirV",
|
320 | value: function compileRawShaderToSpirV(source, type) {
|
321 | return this.engine.glslang.compileGLSL(source, type);
|
322 | }
|
323 | }, {
|
324 | key: "createPipelineStageDescriptor",
|
325 | value: function createPipelineStageDescriptor(vertexShader, fragmentShader) {
|
326 | return {
|
327 | vertexStage: {
|
328 | module: this.engine.device.createShaderModule({
|
329 | code: vertexShader,
|
330 |
|
331 | isWHLSL: isSafari
|
332 | }),
|
333 | entryPoint: 'main'
|
334 | },
|
335 | fragmentStage: {
|
336 | module: this.engine.device.createShaderModule({
|
337 | code: fragmentShader,
|
338 |
|
339 | isWHLSL: isSafari
|
340 | }),
|
341 | entryPoint: 'main'
|
342 | }
|
343 | };
|
344 | }
|
345 | |
346 |
|
347 |
|
348 |
|
349 | }, {
|
350 | key: "getDefaultRasterizationStateDescriptor",
|
351 | value: function getDefaultRasterizationStateDescriptor() {
|
352 | return {
|
353 | frontFace: WebGPUConstants.FrontFace.CCW,
|
354 | cullMode: WebGPUConstants.CullMode.None,
|
355 | depthBias: 0,
|
356 | depthBiasSlopeScale: 0,
|
357 | depthBiasClamp: 0
|
358 | };
|
359 | }
|
360 | }, {
|
361 | key: "buildUniformBindGroup",
|
362 | value: function buildUniformBindGroup(uniforms) {
|
363 | var _this3 = this;
|
364 |
|
365 | var offset = 0;
|
366 |
|
367 | var mergedUniformData = concatenate.apply(void 0, [Float32Array].concat(_toConsumableArray(Object.keys(uniforms).map(function (uniformName) {
|
368 | if (uniforms[uniformName]) {
|
369 | _this3.uniformGPUBufferLayout.push({
|
370 | name: uniformName,
|
371 | offset: offset
|
372 | });
|
373 |
|
374 |
|
375 | offset += (uniforms[uniformName].length || 1) * 4;
|
376 | return uniforms[uniformName];
|
377 | } else {
|
378 |
|
379 | return [];
|
380 | }
|
381 | }))));
|
382 | var entries = [];
|
383 | var hasUniform = false;
|
384 |
|
385 | if (mergedUniformData.length) {
|
386 | hasUniform = true;
|
387 |
|
388 | entries.push({
|
389 |
|
390 | binding: 0,
|
391 | visibility: WebGPUConstants.ShaderStage.Fragment | WebGPUConstants.ShaderStage.Vertex,
|
392 |
|
393 | type: WebGPUConstants.BindingType.UniformBuffer
|
394 | });
|
395 | }
|
396 |
|
397 |
|
398 | Object.keys(uniforms).filter(function (uniformName) {
|
399 | return uniforms[uniformName] === null;
|
400 | }).forEach(function (uniformName, i) {
|
401 | _this3.uniformGPUBufferLayout.push({
|
402 | name: uniformName,
|
403 | offset: i * 2 + (hasUniform ? 1 : 0)
|
404 | });
|
405 |
|
406 | entries.push({
|
407 |
|
408 | binding: i * 2 + (hasUniform ? 1 : 0),
|
409 | visibility: WebGPUConstants.ShaderStage.Fragment,
|
410 | type: WebGPUConstants.BindingType.Sampler
|
411 | }, {
|
412 |
|
413 | binding: i * 2 + (hasUniform ? 1 : 0) + 1,
|
414 | visibility: WebGPUConstants.ShaderStage.Fragment,
|
415 | type: WebGPUConstants.BindingType.SampledTexture
|
416 | });
|
417 | });
|
418 | this.uniformsBindGroupLayout = this.engine.device.createBindGroupLayout({
|
419 |
|
420 |
|
421 |
|
422 | entries: entries
|
423 | });
|
424 | this.pipelineLayout = this.engine.device.createPipelineLayout({
|
425 | bindGroupLayouts: [this.uniformsBindGroupLayout]
|
426 | });
|
427 |
|
428 | if (hasUniform) {
|
429 | this.uniformBuffer = new WebGPUBuffer(this.engine, {
|
430 |
|
431 |
|
432 | data: mergedUniformData instanceof Array ?
|
433 | new Float32Array(mergedUniformData) : mergedUniformData,
|
434 | usage: WebGPUConstants.BufferUsage.Uniform | WebGPUConstants.BufferUsage.CopyDst
|
435 | });
|
436 | }
|
437 | }
|
438 | }]);
|
439 |
|
440 | return WebGPUModel;
|
441 | }();
|
442 |
|
443 | export { WebGPUModel as default };
|
444 |
|
\ | No newline at end of file |