import { Buffer } from './buffer'; import { Context } from './context'; import { Initializable } from './initializable'; /** * Class to encapsulating a WebGL buffer adding functionality to record changes to the underlying buffer without * instantly propagating them to the WebGL buffer. It is intended to be a direct replacement for {@link Buffer}. * When calling {@link subData} the data will be copied to an internal, CPU-sided buffer and the affecting range will be * recorded. If the newly recorded range overrides a part of or the whole of a previously recorded range the older one * will either be discarded completely or merged with the new one according to a specifiable merge threshold. * To propagate all recorded changes to the GPU-sided buffer, {@link update} has to be called. This will take care of * both the allocation of the GPU-sided buffer and the transfer of the changed data. * While {@link update} can must only be called after initializing the object, {@link subData}, * {@link mergeSubDataRanges} and resizing (@see{@link size}) can be called on the unitialized object. * The GPU-sided buffer is created on initialization and deleted on uninitialization. * A typical usage could look like this: * ``` * // Create a unified buffer with the size of 1028 bytes and a mergeThreshold of 32 bytes * const unifiedBuffer = new UnifiedBuffer(context, 1028, gl.STATIC_DRAW, 32, 'UnifiedBuffer'); * unifiedBuffer.initialize(gl.ARRAY_BUFFER); * unifiedBuffer.attribEnable(0, 1, gl.FLOAT, gl.FALSE, 0, 0, true, false); * unifiedBuffer.attribEnable(1, 1, gl.SHORT, gl.FALSE, 0, 512, false, true); * * unifiedBuffer.subData(0, new Float32Array(64).fill(3.14)); * unifiedBuffer.subData(512, new Int16Array(128).fill(1200)); * * unifiedBuffer.update(true, true); * * unifiedBuffer.subData(128, new Float32Array(32).fill(1.57)); * unifiedBuffer.subData(640, new Int36Array(64).fill(600)); * * unifiedBuffer.mergeThreshold = -1; * // This will merge both already existing ranges resulting in a single update * unifiedBuffer.mergeSubDataRanges(); * * unifiedBuffer.bind(); * unifiedBuffer.update(); * unifiedBuffer.unbind(); * ``` */ export declare class UnifiedBuffer extends Initializable { protected _cpuBuffer: ArrayBuffer; protected _gpuBuffer: Buffer; protected _updates: Update[]; /** @see {@link usage} */ protected _usage: GLenum; /** @see {@link mergeThreshold} */ protected _mergeThreshold: number; /** * Checks if two updates have to be merged according to the mergeThreshold. Note: lhsUpdate.begin has to be smaller * than rhsUpdate.begin. * @param lhsUpdate - First update * @param rhsUpdate - Second update * @param mergeThreshold - Threshold considered for merging. * @returns - True if mergeThreshold == -1 or distance between the two updates <= mergeThreshold, false otherwise. */ protected static updatesNeedMerge(lhsUpdate: Update, rhsUpdate: Update, mergeThreshold: number): boolean; /** * Creates a zero initialized buffer with the given size. * @param context - Context used for all GPU operations. * @param sizeInBytes - Size of the buffer in bytes. * @param usage - Usage hint for allocation of the GPU-sided buffer. * @param mergeThreshold - Threshold in which all updates will get merged. * @param identifier - Unique identifier for this UnifiedBuffer. */ constructor(context: Context, sizeInBytes: number, usage: GLenum, mergeThreshold?: number, identifier?: string); /** * Merges all updates left of index transitively with the update at index until there are no more updates within the * merge threshold. * @param index - Index of the update that should get merged. * @returns - Number of merged updates. */ protected mergeUpdatesLeft(index: number): number; /** * Merges all updates right of index transitively with the update at index until there are no more updates within * the merge threshold. * @param index - Index of the update that should get merged. * @returns - Number of merged updates. */ protected mergeUpdatesRight(index: number): number; /** * Adds a range to recorded updates. Transitively merges all already recorded updates within the mergeThreshold of * the added range. * @param update - Range to add to the updates. */ protected addUpdate(update: Update): void; /** * Create the buffer object on the GPU. * @param target - Target used as binding point. */ initialize(target: GLenum): boolean; /** * Delete the buffer object on the GPU. This should have the reverse effect of `create`. */ uninitialize(): void; /** * Binds the buffer object as buffer to predefined target. */ bind(): void; /** * Binds null as current buffer to predefined target; */ unbind(): void; /** * Specifies the memory layout of the buffer for a binding point. * @param index - Index of the vertex attribute that is to be setup and enabled. * @param size - Number of components per vertex attribute. * @param type - Data type of each component in the array. * @param normalized - Whether integer data values should be normalized when being casted to a float. * @param stride - Offset in bytes between the beginning of consecutive vertex attributes. * @param offset - Offset in bytes of the first component in the vertex attribute array. * @param bind - Allows to skip binding the object (e.g., when binding is handled outside). * @param unbind - Allows to skip unbinding the object (e.g., when binding is handled outside). */ attribEnable(index: GLuint, size: GLint, type: GLenum, normalized?: GLboolean, stride?: GLsizei, offset?: GLintptr, bind?: boolean, unbind?: boolean): void; /** * Disables a buffer binding point. * @param index - Index of the vertex attribute that is to be disabled. * @param bind - Allows to skip binding the object (e.g., when binding is handled outside). * @param unbind - Allows to skip unbinding the object (e.g., when binding is handled outside). */ attribDisable(index: GLuint, bind?: boolean, unbind?: boolean): void; /** * Merges all recorded subData ranges. */ mergeSubDataRanges(): void; /** * Copies the new data into the CPU-sided buffer and records the range as changed. All previously added ranges will * get merged transitively with the new one, if they are within the set mergeThreshold. * Note: This does not transfer anything to the GPU-sided buffer yet. * @param dstByteOffset - Offset of bytes into the destination buffer. * @param srcData - Data that will be copied into the destination buffer. */ subData(dstByteOffset: GLintptr, srcData: ArrayBufferView | ArrayBuffer): void; /** * Copies all previously recorded ranges and their data to the GPU. (Re-)Allocate the GPU-sided buffer if the size * changed or the object was reinitialized. * @param bind - Allows to skip binding the object (e.g., when binding is handled outside). * @param unbind - Allows to skip unbinding the object (e.g., when binding is handled outside). */ update(bind?: boolean, unbind?: boolean): void; /** * Returns the size of the CPU-sided buffer. This is not necessarily the same as the size of the GPU-sided buffer, * if update has not been called after resizing the buffer. */ get size(): number; /** * Resizes the buffer. Note, that this does not resize the GPU-sided buffer. To update the size of the GPU-sided * buffer update has to be called. */ set size(sizeInBytes: number); /** * Target to which the buffer object is bound (either GL_ARRAY_BUFFER or GL_ELEMENT_ARRAY_BUFFER). * Readonly access to the target (as specified on initialization) the buffer will be bound to. */ get target(): GLenum | undefined; /** * Returns the usage hint used for allocation of the GPU-sided buffer. */ get usage(): GLenum; /** * Sets the usage hint used for allocation of the GPU-sided buffer. */ set usage(usage: GLenum); /** * Returns the threshold used to determine whether two ranges have to be merged. */ get mergeThreshold(): number; /** * Sets the threshold determining whether two ranges have to be merged. If the mergeThreshold is set to -1 all * ranges will get merged disregarding their distance to each other. */ set mergeThreshold(mergeThreshold: number); } interface Update { /** inclusive */ begin: number; /** exclusive */ end: number; } export {};