📄 Bindings.js
¶
📊 Analysis Summary¶
Metric | Count |
---|---|
🔧 Functions | 7 |
🧱 Classes | 1 |
📦 Imports | 2 |
📊 Variables & Constants | 10 |
📚 Table of Contents¶
🛠️ File Location:¶
📂 src/renderers/common/Bindings.js
📦 Imports¶
Name | Source |
---|---|
DataMap |
./DataMap.js |
AttributeType |
./Constants.js |
Variables & Constants¶
Name | Type | Kind | Value | Exported |
---|---|---|---|---|
bindings |
any |
let/var | this.nodes.getForCompute( computeNode ).bindings |
✗ |
attribute |
any |
let/var | binding.attribute |
✗ |
attributeType |
number |
let/var | attribute.isIndirectStorageBufferAttribute ? AttributeType.INDIRECT : Attribu... |
✗ |
needsBindingsUpdate |
boolean |
let/var | false |
✗ |
cacheBindings |
boolean |
let/var | true |
✗ |
cacheIndex |
number |
let/var | 0 |
✗ |
version |
number |
let/var | 0 |
✗ |
attribute |
any |
let/var | binding.attribute |
✗ |
attributeType |
number |
let/var | attribute.isIndirectStorageBufferAttribute ? AttributeType.INDIRECT : Attribu... |
✗ |
texture |
any |
let/var | binding.texture |
✗ |
Functions¶
Bindings.getForRender(renderObject: RenderObject): BindGroup[]
¶
JSDoc:
/**
* Returns the bind groups for the given render object.
*
* @param {RenderObject} renderObject - The render object.
* @return {Array<BindGroup>} The bind groups.
*/
Parameters:
renderObject
RenderObject
Returns: BindGroup[]
Calls:
renderObject.getBindings
this.get
this._init
this.backend.createBindings
Internal Comments:
Code
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;
}
Bindings.getForCompute(computeNode: Node): BindGroup[]
¶
JSDoc:
/**
* Returns the bind groups for the given compute node.
*
* @param {Node} computeNode - The compute node.
* @return {Array<BindGroup>} The bind groups.
*/
Parameters:
computeNode
Node
Returns: BindGroup[]
Calls:
this.nodes.getForCompute
this.get
this._init
this.backend.createBindings
Code
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;
}
Bindings.updateForCompute(computeNode: Node): void
¶
JSDoc:
/**
* Updates the bindings for the given compute node.
*
* @param {Node} computeNode - The compute node.
*/
Parameters:
computeNode
Node
Returns: void
Calls:
this._updateBindings
this.getForCompute
Bindings.updateForRender(renderObject: RenderObject): void
¶
JSDoc:
/**
* Updates the bindings for the given render object.
*
* @param {RenderObject} renderObject - The render object.
*/
Parameters:
renderObject
RenderObject
Returns: void
Calls:
this._updateBindings
this.getForRender
Bindings._updateBindings(bindings: BindGroup[]): void
¶
JSDoc:
/**
* Updates the given array of bindings.
*
* @param {Array<BindGroup>} bindings - The bind groups.
*/
Parameters:
bindings
BindGroup[]
Returns: void
Calls:
this._update
Code
Bindings._init(bindGroup: BindGroup): void
¶
JSDoc:
/**
* Initializes the given bind group.
*
* @param {BindGroup} bindGroup - The bind group to initialize.
*/
Parameters:
bindGroup
BindGroup
Returns: void
Calls:
this.textures.updateTexture
this.attributes.update
Code
_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 ? AttributeType.INDIRECT : AttributeType.STORAGE;
this.attributes.update( attribute, attributeType );
}
}
}
Bindings._update(bindGroup: BindGroup, bindings: BindGroup[]): void
¶
JSDoc:
/**
* Updates the given bind group.
*
* @param {BindGroup} bindGroup - The bind group to update.
* @param {Array<BindGroup>} bindings - The bind groups.
*/
Parameters:
bindGroup
BindGroup
bindings
BindGroup[]
Returns: void
Calls:
this.nodes.updateGroup
this.attributes.update
binding.update
backend.updateBinding
this.textures.get
this.textures.updateTexture
backend.get
this.get
this.textures.needsMipmaps
this.backend.generateMipmaps
this.backend.updateBindings
Internal Comments:
// iterate over all bindings and check if buffer updates or a new binding group is required
// 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.
// get the texture data after the update, to sync the texture reference from node (x2)
// version: update the texture data or create a new one (x5)
// generation: update the bindings if a new texture has been created
Code
_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 ? AttributeType.INDIRECT : AttributeType.STORAGE;
this.attributes.update( attribute, attributeType );
}
if ( binding.isUniformBuffer ) {
const updated = binding.update();
if ( updated ) {
backend.updateBinding( binding );
}
} else if ( binding.isSampledTexture ) {
const updated = binding.update();
// get the texture data after the update, to sync the texture reference from node
const texture = binding.texture;
const texturesTextureData = this.textures.get( texture );
if ( updated ) {
// version: update the texture data or create a new one
this.textures.updateTexture( texture );
// generation: update the bindings if a new texture has been created
if ( binding.generation !== texturesTextureData.generation ) {
binding.generation = texturesTextureData.generation;
needsBindingsUpdate = true;
}
}
const textureData = backend.get( texture );
if ( textureData.externalTexture !== undefined || texturesTextureData.isDefaultTexture ) {
cacheBindings = false;
} else {
cacheIndex = cacheIndex * 10 + texture.id;
version += texture.version;
}
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;
}
}
} else if ( binding.isSampler ) {
binding.update();
}
}
if ( needsBindingsUpdate === true ) {
this.backend.updateBindings( bindGroup, bindings, cacheBindings ? cacheIndex : 0, version );
}
}
Classes¶
Bindings
¶
Class Code
class Bindings extends DataMap {
/**
* 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 ? AttributeType.INDIRECT : 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 ? AttributeType.INDIRECT : AttributeType.STORAGE;
this.attributes.update( attribute, attributeType );
}
if ( binding.isUniformBuffer ) {
const updated = binding.update();
if ( updated ) {
backend.updateBinding( binding );
}
} else if ( binding.isSampledTexture ) {
const updated = binding.update();
// get the texture data after the update, to sync the texture reference from node
const texture = binding.texture;
const texturesTextureData = this.textures.get( texture );
if ( updated ) {
// version: update the texture data or create a new one
this.textures.updateTexture( texture );
// generation: update the bindings if a new texture has been created
if ( binding.generation !== texturesTextureData.generation ) {
binding.generation = texturesTextureData.generation;
needsBindingsUpdate = true;
}
}
const textureData = backend.get( texture );
if ( textureData.externalTexture !== undefined || texturesTextureData.isDefaultTexture ) {
cacheBindings = false;
} else {
cacheIndex = cacheIndex * 10 + texture.id;
version += texture.version;
}
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;
}
}
} else if ( binding.isSampler ) {
binding.update();
}
}
if ( needsBindingsUpdate === true ) {
this.backend.updateBindings( bindGroup, bindings, cacheBindings ? cacheIndex : 0, version );
}
}
}
Methods¶
getForRender(renderObject: RenderObject): BindGroup[]
¶
Code
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;
}
getForCompute(computeNode: Node): BindGroup[]
¶
Code
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;
}
updateForCompute(computeNode: Node): void
¶
updateForRender(renderObject: RenderObject): void
¶
_updateBindings(bindings: BindGroup[]): void
¶
Code
_init(bindGroup: BindGroup): void
¶
Code
_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 ? AttributeType.INDIRECT : AttributeType.STORAGE;
this.attributes.update( attribute, attributeType );
}
}
}
_update(bindGroup: BindGroup, bindings: BindGroup[]): void
¶
Code
_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 ? AttributeType.INDIRECT : AttributeType.STORAGE;
this.attributes.update( attribute, attributeType );
}
if ( binding.isUniformBuffer ) {
const updated = binding.update();
if ( updated ) {
backend.updateBinding( binding );
}
} else if ( binding.isSampledTexture ) {
const updated = binding.update();
// get the texture data after the update, to sync the texture reference from node
const texture = binding.texture;
const texturesTextureData = this.textures.get( texture );
if ( updated ) {
// version: update the texture data or create a new one
this.textures.updateTexture( texture );
// generation: update the bindings if a new texture has been created
if ( binding.generation !== texturesTextureData.generation ) {
binding.generation = texturesTextureData.generation;
needsBindingsUpdate = true;
}
}
const textureData = backend.get( texture );
if ( textureData.externalTexture !== undefined || texturesTextureData.isDefaultTexture ) {
cacheBindings = false;
} else {
cacheIndex = cacheIndex * 10 + texture.id;
version += texture.version;
}
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;
}
}
} else if ( binding.isSampler ) {
binding.update();
}
}
if ( needsBindingsUpdate === true ) {
this.backend.updateBindings( bindGroup, bindings, cacheBindings ? cacheIndex : 0, version );
}
}