/** * A bind group represents a collection of {@link UniformBuffer}, {@link Texture} and * {@link StorageBuffer} instanced, which can be bind on a GPU for rendering. * * Call {@link BindGroup#destroy} when no longer needed. On WebGPU, the graphics device retains * bind groups for device recovery until they are explicitly destroyed. * * @ignore */ export class BindGroup { /** * Create a new Bind Group. * * @param {GraphicsDevice} graphicsDevice - The graphics device used to manage this uniform buffer. * @param {BindGroupFormat} format - Format of the bind group. * @param {UniformBuffer} [defaultUniformBuffer] - The default uniform buffer. Typically a bind * group only has a single uniform buffer, and this allows easier access. */ constructor(graphicsDevice: GraphicsDevice, format: BindGroupFormat, defaultUniformBuffer?: UniformBuffer); /** * A render version the bind group was last updated on. * * @private */ private renderVersionUpdated; /** @type {UniformBuffer[]} */ uniformBuffers: UniformBuffer[]; /** * The offset of each uniform buffer of the format in the buffer where its data starts. A typed * array of one entry per uniform buffer slot, which the WebGPU device passes to setBindGroup * without a per-call conversion, and which holds exactly the number of dynamic offsets the bind * group layout requires. * * @type {Uint32Array} */ uniformBufferOffsets: Uint32Array; /** * For each uniform buffer slot, the dynamic GPU buffer a non-persistent uniform buffer was * last built against. Used to detect when such a buffer is re-allocated into a different * dynamic buffer (which requires the bind group to be rebuilt). * * @type {DynamicBuffer[]} * @private */ private _uniformBufferContainers; /** * For each texture / storage-texture slot, the GPU implementation object the slot was last * built against. A texture's `impl` is replaced when its GPU resource is recreated (e.g. * {@link Texture#resize}), which can happen mid-render in the same render version the bind * group was last built — so the {@link renderVersionDirty} check alone misses it and the bind * group keeps a view of the (now destroyed) old GPU texture. Tracking impl identity forces a * rebuild whenever the underlying GPU resource is recreated. * * @type {object[]} * @private */ private _textureImpls; /** * @type {object[]} * @private */ private _storageTextureImpls; id: number; device: GraphicsDevice; format: BindGroupFormat; dirty: boolean; impl: any; /** @type {(Texture|TextureView)[]} */ textures: (Texture | TextureView)[]; /** @type {(Texture|TextureView)[]} */ storageTextures: (Texture | TextureView)[]; storageBuffers: any[]; /** @type {UniformBuffer} */ defaultUniformBuffer: UniformBuffer; /** * Frees resources associated with this bind group. */ destroy(): void; /** * Assign a uniform buffer to a slot. * * @param {string} name - The name of the uniform buffer slot * @param {UniformBuffer} uniformBuffer - The Uniform buffer to assign to the slot. */ setUniformBuffer(name: string, uniformBuffer: UniformBuffer): void; /** * Assign a storage buffer to a slot. * * @param {string} name - The name of the storage buffer slot. * @param {StorageBuffer} storageBuffer - The storage buffer to assign to the slot. */ setStorageBuffer(name: string, storageBuffer: StorageBuffer): void; /** * Assign a storage buffer to a slot, given its index in the format's storage buffers. * * @param {number} index - The index of the storage buffer slot. * @param {StorageBuffer} storageBuffer - The storage buffer to assign to the slot. * @private */ private setStorageBufferAt; /** * Assign a texture to a named slot. * * @param {string} name - The name of the texture slot. * @param {Texture|TextureView} value - Texture or TextureView to assign to the slot. */ setTexture(name: string, value: Texture | TextureView): void; /** * Assign a texture to a slot, given its index in the format's textures. This is the form the * update uses, as it walks the slots in order and so knows the index without looking it up, * and the form an owner of the bind group uses when it tracks the slots of its own resources. * * @param {number} index - The index of the texture slot. * @param {Texture|TextureView} value - Texture or TextureView to assign to the slot. * @ignore */ setTextureAt(index: number, value: Texture | TextureView): void; /** * Assign a storage texture to a named slot. * * @param {string} name - The name of the texture slot. * @param {Texture|TextureView} value - Texture or TextureView to assign to the slot. */ setStorageTexture(name: string, value: Texture | TextureView): void; /** * Assign a storage texture to a slot, given its index in the format's storage textures. * * @param {number} index - The index of the storage texture slot. * @param {Texture|TextureView} value - Texture or TextureView to assign to the slot. * @private */ private setStorageTextureAt; /** * Updates the uniform buffers in this bind group. */ updateUniformBuffers(): void; /** * Applies any changes made to the bind group's properties, taking the value of each texture, * storage texture and storage buffer slot from the scope. Note that the content of used * uniform buffers needs to be updated before calling this method. */ update(): void; /** * Applies any changes made to the bind group's properties, for a bind group whose owner assigns * its slots instead of them being taken from the scope. The owner is expected to have assigned * every slot of the format; the resources they hold are re-checked here, as they can change * without the owner re-assigning them. Note that the content of used uniform buffers needs to * be updated before calling this method. */ commit(): void; /** * Assigns every slot of the format the value the scope currently holds for it. * * @private */ private _assignFromScope; /** * The texture to bind for a slot with no value, which is an error - a substitute keeps the * rendering going instead of failing on an unset binding, and reports the mistake. * * @param {BindTextureFormat} textureFormat - The format of the slot. * @returns {Texture} The texture to bind. * @private */ private _substituteTexture; /** * Re-checks the resources the slots already hold. A texture's properties can change, and its * GPU resource can be recreated (by a resize, for example), without the slot being assigned * again - which the assignment path detects as it goes, and this path has to look for. * * @private */ private _revalidate; /** * Refreshes the offsets of the uniform buffers, and rebuilds the GPU bind group if anything * about the bind group has changed. * * @private */ private _finalize; } /** * Data structure to hold a bind group and its offsets. This is used by {@link UniformBuffer#update} * to return a dynamic bind group and offset for the uniform buffer. * * @ignore */ export class DynamicBindGroup { bindGroup: any; /** * The dynamic offset of the uniform buffer. A typed array, which the WebGPU device passes to * setBindGroup without a per-call conversion. * * @type {Uint32Array} */ offsets: Uint32Array; } import type { UniformBuffer } from './uniform-buffer.js'; import type { GraphicsDevice } from './graphics-device.js'; import type { BindGroupFormat } from './bind-group-format.js'; import type { Texture } from './texture.js'; import { TextureView } from './texture-view.js'; import type { StorageBuffer } from './storage-buffer.js';