@luma.gl/core
Version:
The luma.gl core Device API
88 lines • 4.33 kB
JavaScript
// 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