import * as macro from 'vtk.js/Sources/macros'; import vtkWebGPUBufferManager from 'vtk.js/Sources/Rendering/WebGPU/BufferManager'; import vtkWebGPUShaderCache from 'vtk.js/Sources/Rendering/WebGPU/ShaderCache'; import vtkWebGPUTextureManager from 'vtk.js/Sources/Rendering/WebGPU/TextureManager';
export class WeakRefMap extends Map { constructor() { super(); this.registry = new FinalizationRegistry((key) => { const entry = super.get(key); if (entry && entry.deref && entry.deref() === undefined) super.delete(key); }); }
getValue(key) { const entry = super.get(key); if (entry) { const value = entry.deref(); if (value !== undefined) return value; super.delete(key); } return undefined; }
setValue(key, value) { let entry; if (value && typeof value === 'object') { entry = new WeakRef(value); this.registry.register(value, key); super.set(key, entry); } return entry; } }
function vtkWebGPUDevice(publicAPI, model) { model.classHierarchy.push('vtkWebGPUDevice'); publicAPI.initialize = (handle) => { model.handle = handle; };
publicAPI.createCommandEncoder = () => model.handle.createCommandEncoder();
publicAPI.submitCommandEncoder = (commandEncoder) => { model.handle.queue.submit([commandEncoder.finish()]); };
publicAPI.getShaderModule = (sd) => model.shaderCache.getShaderModule(sd);
publicAPI.getBindGroupLayout = (val) => { if (!val.entries) { return null; }
for (let i = 0; i < val.entries.length; i++) { const ent = val.entries[i]; ent.binding = ent.binding || 0; ent.visibility = ent.visibility || GPUShaderStage.VERTEX | GPUShaderStage.FRAGMENT; }
const sval = JSON.stringify(val); for (let i = 0; i < model.bindGroupLayouts.length; i++) { if (model.bindGroupLayouts[i].sval === sval) { return model.bindGroupLayouts[i].layout; } }
const layout = model.handle.createBindGroupLayout(val);
model.bindGroupLayouts.push({ sval, layout }); return layout; };
publicAPI.getBindGroupLayoutDescription = (layout) => { for (let i = 0; i < model.bindGroupLayouts.length; i++) { if (model.bindGroupLayouts[i].layout === layout) { return model.bindGroupLayouts[i].sval; } } vtkErrorMacro('layout not found'); console.trace(); return null; };
publicAPI.getPipeline = (hash) => { if (hash in model.pipelines) { return model.pipelines[hash]; } return null; };
publicAPI.createPipeline = (hash, pipeline) => { pipeline.initialize(publicAPI, hash); model.pipelines[hash] = pipeline; };
publicAPI.onSubmittedWorkDone = () => model.handle.queue.onSubmittedWorkDone();
publicAPI.hasCachedObject = (hash) => model.objectCache.getValue(hash);
publicAPI.getCachedObject = (hash, creator, ...args) => { if (!hash) { vtkErrorMacro('attempt to cache an object without a hash'); return null; }
const existingValue = model.objectCache.getValue(hash); if (existingValue) { return existingValue; }
const createdObject = creator(...args); model.objectCache.setValue(hash, createdObject); return createdObject; }; }
const DEFAULT_VALUES = { handle: null, pipelines: null, shaderCache: null, bindGroupLayouts: null, bufferManager: null, textureManager: null, };
export function extend(publicAPI, model, initialValues = {}) { Object.assign(model, DEFAULT_VALUES, initialValues);
macro.obj(publicAPI, model);
macro.setGet(publicAPI, model, ['handle']); macro.get(publicAPI, model, [ 'bufferManager', 'shaderCache', 'textureManager', ]);
model.objectCache = new WeakRefMap();
model.shaderCache = vtkWebGPUShaderCache.newInstance(); model.shaderCache.setDevice(publicAPI);
model.bindGroupLayouts = [];
model.bufferManager = vtkWebGPUBufferManager.newInstance(); model.bufferManager.setDevice(publicAPI);
model.textureManager = vtkWebGPUTextureManager.newInstance(); model.textureManager.setDevice(publicAPI);
model.pipelines = {};
vtkWebGPUDevice(publicAPI, model); }
export const newInstance = macro.newInstance(extend, 'vtkWebGPUDevice');
export default { newInstance, extend, };
|