UNPKG

@luma.gl/core

Version:

The luma.gl core Device API

88 lines 4.33 kB
// luma.gl // SPDX-License-Identifier: MIT // Copyright (c) vis.gl contributors import { normalizeBindingsByGroup } from "../adapter-utils/bind-groups.js"; export class BindGroupFactory { device; _layoutCacheByPipeline = new WeakMap(); _bindGroupCacheByLayout = new WeakMap(); constructor(device) { this.device = device; } getBindGroups(pipeline, bindings, bindGroupCacheKeys) { if (this.device.type !== 'webgpu' || pipeline.shaderLayout.bindings.length === 0) { return {}; } const bindingsByGroup = normalizeBindingsByGroup(pipeline.shaderLayout, bindings); const resolvedBindGroups = {}; for (const group of getBindGroupIndicesUpToMax(pipeline.shaderLayout.bindings)) { const groupBindings = bindingsByGroup[group]; const bindGroupLayout = this._getBindGroupLayout(pipeline, group); const bindGroupLabel = getBindGroupLabel(pipeline, pipeline.shaderLayout, group); if (!groupBindings || Object.keys(groupBindings).length === 0) { if (!hasBindingsInGroup(pipeline.shaderLayout.bindings, group)) { resolvedBindGroups[group] = this._getEmptyBindGroup(bindGroupLayout, pipeline.shaderLayout, group, bindGroupLabel); } continue; } const bindGroupCacheKey = bindGroupCacheKeys?.[group]; if (bindGroupCacheKey) { const layoutCache = this._getLayoutBindGroupCache(bindGroupLayout); if (layoutCache.bindGroupsBySource.has(bindGroupCacheKey)) { resolvedBindGroups[group] = layoutCache.bindGroupsBySource.get(bindGroupCacheKey) || null; continue; } const bindGroup = this.device._createBindGroupWebGPU(bindGroupLayout, pipeline.shaderLayout, groupBindings, group, bindGroupLabel); layoutCache.bindGroupsBySource.set(bindGroupCacheKey, bindGroup); resolvedBindGroups[group] = bindGroup; } else { resolvedBindGroups[group] = this.device._createBindGroupWebGPU(bindGroupLayout, pipeline.shaderLayout, groupBindings, group, bindGroupLabel); } } return resolvedBindGroups; } _getBindGroupLayout(pipeline, group) { let layoutCache = this._layoutCacheByPipeline.get(pipeline); if (!layoutCache) { layoutCache = {}; this._layoutCacheByPipeline.set(pipeline, layoutCache); } layoutCache[group] ||= this.device._createBindGroupLayoutWebGPU(pipeline, group); return layoutCache[group]; } _getEmptyBindGroup(bindGroupLayout, shaderLayout, group, label) { const layoutCache = this._getLayoutBindGroupCache(bindGroupLayout); layoutCache.emptyBindGroup ||= this.device._createBindGroupWebGPU(bindGroupLayout, shaderLayout, {}, group, label) || null; return layoutCache.emptyBindGroup; } _getLayoutBindGroupCache(bindGroupLayout) { let layoutCache = this._bindGroupCacheByLayout.get(bindGroupLayout); if (!layoutCache) { layoutCache = { bindGroupsBySource: new WeakMap() }; this._bindGroupCacheByLayout.set(bindGroupLayout, layoutCache); } return layoutCache; } } export function _getDefaultBindGroupFactory(device) { device._factories.bindGroupFactory ||= new BindGroupFactory(device); return device._factories.bindGroupFactory; } function getBindGroupIndicesUpToMax(bindings) { const maxGroup = bindings.reduce((highestGroup, binding) => Math.max(highestGroup, binding.group), -1); return Array.from({ length: maxGroup + 1 }, (_, group) => group); } function hasBindingsInGroup(bindings, group) { return bindings.some(binding => binding.group === group); } function getBindGroupLabel(pipeline, shaderLayout, group) { const bindingNames = shaderLayout.bindings .filter(binding => binding.group === group) .sort((left, right) => left.location - right.location) .map(binding => binding.name); const bindingSuffix = bindingNames.length > 0 ? bindingNames.join(',') : 'empty'; return `${pipeline.id}/group${group}[${bindingSuffix}]`; } //# sourceMappingURL=bind-group-factory.js.map