UNPKG

@kitware/vtk.js

Version:

Visualization Toolkit for the Web

252 lines (201 loc) 8.22 kB
import macro from '../../macros.js'; import vtkWebGPUBufferManager from './BufferManager.js'; import vtkWebGPUTypes from './Types.js'; var BufferUsage = vtkWebGPUBufferManager.BufferUsage; var vtkErrorMacro = macro.vtkErrorMacro; // ---------------------------------------------------------------------------- // vtkWebGPUStorageBuffer - similar to the UniformBuffer class // but YOU are responsible for layout issues and alignment. // The order you add entries is the order they will be layed out // in memory. But you must follow layout rules. // ---------------------------------------------------------------------------- // ---------------------------------------------------------------------------- // vtkWebGPUStorageBuffer methods // ---------------------------------------------------------------------------- function vtkWebGPUStorageBuffer(publicAPI, model) { // Set our className model.classHierarchy.push('vtkWebGPUStorageBuffer'); publicAPI.addEntry = function (name, type) { if (model._bufferEntryNames.has(name)) { vtkErrorMacro("entry named ".concat(name, " already exists")); return; } model._bufferEntryNames.set(name, model.bufferEntries.length); var sizeInBytes = vtkWebGPUTypes.getByteStrideFromShaderFormat(type); model.bufferEntries.push({ name: name, type: type, sizeInBytes: sizeInBytes, offset: model.sizeInBytes, nativeType: vtkWebGPUTypes.getNativeTypeFromShaderFormat(type) }); model.sizeInBytes += sizeInBytes; }; publicAPI.send = function (device) { if (!model._buffer) { var req = { nativeArray: model.Float32Array, usage: BufferUsage.Storage, label: model.label }; model._buffer = device.getBufferManager().getBuffer(req); model.bindGroupTime.modified(); model._sendTime.modified(); return; } device.getHandle().queue.writeBuffer(model._buffer.getHandle(), 0, model.arrayBuffer, 0, model.sizeInBytes * model.numberOfInstances); model._sendTime.modified(); }; publicAPI.createView = function (type) { if (type in model === false) { if (!model.arrayBuffer) { model.arrayBuffer = new ArrayBuffer(model.sizeInBytes * model.numberOfInstances); } model[type] = macro.newTypedArray(type, model.arrayBuffer); } }; publicAPI.setValue = function (name, instance, val) { var idx = model._bufferEntryNames.get(name); if (idx === undefined) { vtkErrorMacro("entry named ".concat(name, " not found in UBO")); return; } var entry = model.bufferEntries[idx]; publicAPI.createView(entry.nativeType); var view = model[entry.nativeType]; view[(entry.offset + instance * model.sizeInBytes) / view.BYTES_PER_ELEMENT] = val; }; publicAPI.setArray = function (name, instance, arr) { var idx = model._bufferEntryNames.get(name); if (idx === undefined) { vtkErrorMacro("entry named ".concat(name, " not found in UBO")); return; } var entry = model.bufferEntries[idx]; publicAPI.createView(entry.nativeType); var view = model[entry.nativeType]; var ioffset = (entry.offset + instance * model.sizeInBytes) / view.BYTES_PER_ELEMENT; for (var i = 0; i < arr.length; i++) { view[ioffset + i] = arr[i]; } }; publicAPI.setAllInstancesFromArray = function (name, arr) { var idx = model._bufferEntryNames.get(name); if (idx === undefined) { vtkErrorMacro("entry named ".concat(name, " not found in UBO")); return; } var entry = model.bufferEntries[idx]; publicAPI.createView(entry.nativeType); var view = model[entry.nativeType]; var numComponents = arr.length / model.numberOfInstances; for (var inst = 0; inst < model.numberOfInstances; inst++) { var ioffset = (entry.offset + inst * model.sizeInBytes) / view.BYTES_PER_ELEMENT; for (var i = 0; i < numComponents; i++) { view[ioffset + i] = arr[inst * numComponents + i]; } } }; publicAPI.setAllInstancesFromArrayColorToFloat = function (name, arr) { var idx = model._bufferEntryNames.get(name); if (idx === undefined) { vtkErrorMacro("entry named ".concat(name, " not found in UBO")); return; } var entry = model.bufferEntries[idx]; publicAPI.createView(entry.nativeType); var view = model[entry.nativeType]; var numComponents = arr.length / model.numberOfInstances; for (var inst = 0; inst < model.numberOfInstances; inst++) { var ioffset = (entry.offset + inst * model.sizeInBytes) / view.BYTES_PER_ELEMENT; for (var i = 0; i < numComponents; i++) { view[ioffset + i] = arr[inst * numComponents + i] / 255.0; } } }; publicAPI.setAllInstancesFromArray3x3To4x4 = function (name, arr) { var idx = model._bufferEntryNames.get(name); if (idx === undefined) { vtkErrorMacro("entry named ".concat(name, " not found in UBO")); return; } var entry = model.bufferEntries[idx]; publicAPI.createView(entry.nativeType); var view = model[entry.nativeType]; var numComponents = 9; for (var inst = 0; inst < model.numberOfInstances; inst++) { var ioffset = (entry.offset + inst * model.sizeInBytes) / view.BYTES_PER_ELEMENT; for (var j = 0; j < 3; j++) { for (var i = 0; i < 3; i++) { view[ioffset + j * 4 + i] = arr[inst * numComponents + j * 3 + i]; } } } }; publicAPI.getSendTime = function () { return model._sendTime.getMTime(); }; publicAPI.getShaderCode = function (binding, group) { var lines = ["struct ".concat(model.label, "StructEntry\n{")]; for (var i = 0; i < model.bufferEntries.length; i++) { var entry = model.bufferEntries[i]; lines.push(" ".concat(entry.name, ": ").concat(entry.type, ",")); } lines.push("\n};\nstruct ".concat(model.label, "Struct\n{\n values: array<").concat(model.label, "StructEntry>,\n};\n@binding(").concat(binding, ") @group(").concat(group, ") var<storage, read> ").concat(model.label, ": ").concat(model.label, "Struct;\n")); return lines.join('\n'); }; publicAPI.getBindGroupEntry = function () { var foo = { resource: { buffer: model._buffer.getHandle() } }; return foo; }; publicAPI.clearData = function () { model.numberOfInstances = 0; model.sizeInBytes = 0; model.bufferEntries = []; model._bufferEntryNames = new Map(); model._buffer = null; delete model.arrayBuffer; delete model.Float32Array; }; } // ---------------------------------------------------------------------------- // Object factory // ---------------------------------------------------------------------------- var DEFAULT_VALUES = { bufferEntries: null, bufferEntryNames: null, sizeInBytes: 0, label: null, numberOfInstances: 1 }; // ---------------------------------------------------------------------------- function extend(publicAPI, model) { var initialValues = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; Object.assign(model, DEFAULT_VALUES, initialValues); // Build VTK API macro.obj(publicAPI, model); // Internal objects model._bufferEntryNames = new Map(); model.bufferEntries = []; model._sendTime = {}; macro.obj(model._sendTime, { mtime: 0 }); model.bindGroupTime = {}; macro.obj(model.bindGroupTime, { mtime: 0 }); // default SSBO desc model.bindGroupLayoutEntry = model.bindGroupLayoutEntry || { buffer: { type: 'read-only-storage' } }; macro.get(publicAPI, model, ['bindGroupTime']); macro.setGet(publicAPI, model, ['device', 'bindGroupLayoutEntry', 'label', 'numberOfInstances', 'sizeInBytes']); // Object methods vtkWebGPUStorageBuffer(publicAPI, model); } // ---------------------------------------------------------------------------- var newInstance = macro.newInstance(extend, 'vtkWebGPUStorageBuffer'); // ---------------------------------------------------------------------------- var vtkWebGPUStorageBuffer$1 = { newInstance: newInstance, extend: extend }; export { vtkWebGPUStorageBuffer$1 as default, extend, newInstance };