@kitware/vtk.js
Version:
Visualization Toolkit for the Web
252 lines (201 loc) • 8.22 kB
JavaScript
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 };