@openhps/core
Version:
Open Hybrid Positioning System - Core component
235 lines (216 loc) • 7.54 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _DataMap = _interopRequireDefault(require("./DataMap.js"));
var _Constants = require("./Constants.js");
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
/**
* This renderer module manages the bindings of the renderer.
*
* @private
* @augments DataMap
*/
class Bindings extends _DataMap.default {
/**
* Constructs a new bindings management component.
*
* @param {Backend} backend - The renderer's backend.
* @param {Nodes} nodes - Renderer component for managing nodes related logic.
* @param {Textures} textures - Renderer component for managing textures.
* @param {Attributes} attributes - Renderer component for managing attributes.
* @param {Pipelines} pipelines - Renderer component for managing pipelines.
* @param {Info} info - Renderer component for managing metrics and monitoring data.
*/
constructor(backend, nodes, textures, attributes, pipelines, info) {
super();
/**
* The renderer's backend.
*
* @type {Backend}
*/
this.backend = backend;
/**
* Renderer component for managing textures.
*
* @type {Textures}
*/
this.textures = textures;
/**
* Renderer component for managing pipelines.
*
* @type {Pipelines}
*/
this.pipelines = pipelines;
/**
* Renderer component for managing attributes.
*
* @type {Attributes}
*/
this.attributes = attributes;
/**
* Renderer component for managing nodes related logic.
*
* @type {Nodes}
*/
this.nodes = nodes;
/**
* Renderer component for managing metrics and monitoring data.
*
* @type {Info}
*/
this.info = info;
this.pipelines.bindings = this; // assign bindings to pipelines
}
/**
* Returns the bind groups for the given render object.
*
* @param {RenderObject} renderObject - The render object.
* @return {Array<BindGroup>} The bind groups.
*/
getForRender(renderObject) {
const bindings = renderObject.getBindings();
for (const bindGroup of bindings) {
const groupData = this.get(bindGroup);
if (groupData.bindGroup === undefined) {
// each object defines an array of bindings (ubos, textures, samplers etc.)
this._init(bindGroup);
this.backend.createBindings(bindGroup, bindings, 0);
groupData.bindGroup = bindGroup;
}
}
return bindings;
}
/**
* Returns the bind groups for the given compute node.
*
* @param {Node} computeNode - The compute node.
* @return {Array<BindGroup>} The bind groups.
*/
getForCompute(computeNode) {
const bindings = this.nodes.getForCompute(computeNode).bindings;
for (const bindGroup of bindings) {
const groupData = this.get(bindGroup);
if (groupData.bindGroup === undefined) {
this._init(bindGroup);
this.backend.createBindings(bindGroup, bindings, 0);
groupData.bindGroup = bindGroup;
}
}
return bindings;
}
/**
* Updates the bindings for the given compute node.
*
* @param {Node} computeNode - The compute node.
*/
updateForCompute(computeNode) {
this._updateBindings(this.getForCompute(computeNode));
}
/**
* Updates the bindings for the given render object.
*
* @param {RenderObject} renderObject - The render object.
*/
updateForRender(renderObject) {
this._updateBindings(this.getForRender(renderObject));
}
/**
* Updates the given array of bindings.
*
* @param {Array<BindGroup>} bindings - The bind groups.
*/
_updateBindings(bindings) {
for (const bindGroup of bindings) {
this._update(bindGroup, bindings);
}
}
/**
* Initializes the given bind group.
*
* @param {BindGroup} bindGroup - The bind group to initialize.
*/
_init(bindGroup) {
for (const binding of bindGroup.bindings) {
if (binding.isSampledTexture) {
this.textures.updateTexture(binding.texture);
} else if (binding.isStorageBuffer) {
const attribute = binding.attribute;
const attributeType = attribute.isIndirectStorageBufferAttribute ? _Constants.AttributeType.INDIRECT : _Constants.AttributeType.STORAGE;
this.attributes.update(attribute, attributeType);
}
}
}
/**
* Updates the given bind group.
*
* @param {BindGroup} bindGroup - The bind group to update.
* @param {Array<BindGroup>} bindings - The bind groups.
*/
_update(bindGroup, bindings) {
const {
backend
} = this;
let needsBindingsUpdate = false;
let cacheBindings = true;
let cacheIndex = 0;
let version = 0;
// iterate over all bindings and check if buffer updates or a new binding group is required
for (const binding of bindGroup.bindings) {
if (binding.isNodeUniformsGroup) {
const updated = this.nodes.updateGroup(binding);
// every uniforms group is a uniform buffer. So if no update is required,
// we move one with the next binding. Otherwise the next if block will update the group.
if (updated === false) continue;
}
if (binding.isStorageBuffer) {
const attribute = binding.attribute;
const attributeType = attribute.isIndirectStorageBufferAttribute ? _Constants.AttributeType.INDIRECT : _Constants.AttributeType.STORAGE;
this.attributes.update(attribute, attributeType);
}
if (binding.isUniformBuffer) {
const updated = binding.update();
if (updated) {
backend.updateBinding(binding);
}
} else if (binding.isSampler) {
binding.update();
} else if (binding.isSampledTexture) {
const texturesTextureData = this.textures.get(binding.texture);
if (binding.needsBindingsUpdate(texturesTextureData.generation)) needsBindingsUpdate = true;
const updated = binding.update();
const texture = binding.texture;
if (updated) {
this.textures.updateTexture(texture);
}
const textureData = backend.get(texture);
if (textureData.externalTexture !== undefined || texturesTextureData.isDefaultTexture) {
cacheBindings = false;
} else {
cacheIndex = cacheIndex * 10 + texture.id;
version += texture.version;
}
if (backend.isWebGPUBackend === true && textureData.texture === undefined && textureData.externalTexture === undefined) {
// TODO: Remove this once we found why updated === false isn't bound to a texture in the WebGPU backend
console.error('Bindings._update: binding should be available:', binding, updated, texture, binding.textureNode.value, needsBindingsUpdate);
this.textures.updateTexture(texture);
needsBindingsUpdate = true;
}
if (texture.isStorageTexture === true) {
const textureData = this.get(texture);
if (binding.store === true) {
textureData.needsMipmap = true;
} else if (this.textures.needsMipmaps(texture) && textureData.needsMipmap === true) {
this.backend.generateMipmaps(texture);
textureData.needsMipmap = false;
}
}
}
}
if (needsBindingsUpdate === true) {
this.backend.updateBindings(bindGroup, bindings, cacheBindings ? cacheIndex : 0, version);
}
}
}
var _default = exports.default = Bindings;