1 line
12 KiB
Plaintext
1 line
12 KiB
Plaintext
{"version":3,"file":"Buffer.mjs","sources":["../../../../../src/rendering/renderers/shared/buffer/Buffer.ts"],"sourcesContent":["import EventEmitter from 'eventemitter3';\nimport { uid } from '../../../../utils/data/uid';\nimport { BufferUsage } from './const';\n\nimport type { BindResource } from '../../gpu/shader/BindResource';\n\n/** All the various typed arrays that exist in js */\n// eslint-disable-next-line max-len\nexport type TypedArray = Int8Array | Uint8Array | Int16Array | Uint16Array | Int32Array | Uint32Array | Uint8ClampedArray | Float32Array | Float64Array;\n\n/** Options for creating a buffer */\nexport interface BufferOptions\n{\n /**\n * the data to initialize the buffer with, this can be a typed array,\n * or a regular number array. If it is a number array, it will be converted to a Float32Array\n */\n data?: TypedArray | number[];\n /** the size of the buffer in bytes, if not supplied, it will be inferred from the data */\n size?: number;\n /** the usage of the buffer, see {@link rendering.BufferUsage} */\n usage: number;\n /** a label for the buffer, this is useful for debugging */\n label?: string;\n /**\n * should the GPU buffer be shrunk when the data becomes smaller?\n * changing this will cause the buffer to be destroyed and a new one created on the GPU\n * this can be expensive, especially if the buffer is already big enough!\n * setting this to false will prevent the buffer from being shrunk. This will yield better performance\n * if you are constantly setting data that is changing size often.\n * @default true\n */\n shrinkToFit?: boolean;\n}\n\nexport interface BufferDescriptor\n{\n label?: string;\n size: GPUSize64;\n usage: BufferUsage;\n mappedAtCreation?: boolean;\n}\n\n/**\n * A wrapper for a WebGPU/WebGL Buffer.\n * In PixiJS, the Buffer class is used to manage the data that is sent to the GPU rendering pipeline.\n * It abstracts away the underlying GPU buffer and provides an interface for uploading typed arrays or other data to the GPU,\n * They are used in the following places:\n * <br><br>\n * .1. {@link Geometry} as attribute data or index data for geometry\n * <br>\n * .2. {@link UniformGroup} as an underlying buffer for uniform data\n * <br>\n * .3. {@link BufferResource} as an underlying part of a buffer used directly by the GPU program\n * <br>\n *\n * It is important to note that you must provide a usage type when creating a buffer. This is because\n * the underlying GPU buffer needs to know how it will be used. For example, if you are creating a buffer\n * to hold vertex data, you would use `BufferUsage.VERTEX`. This will tell the GPU that this buffer will be\n * used as a vertex buffer. This is important because it will affect how you can use the buffer.\n *\n * Buffers are updated by calling the {@link Buffer.update} method. This immediately updates the buffer on the GPU.\n * Be mindful of calling this more often than you need to. It is recommended to update buffers only when needed.\n *\n * In WebGPU, a GPU buffer cannot resized. This limitation is abstracted away, but know that resizing a buffer means\n * creating a brand new one and destroying the old, so it is best to limit this if possible.\n * @example\n *\n * const buffer = new Buffer({\n * data: new Float32Array([1, 2, 3, 4]),\n * usage: BufferUsage.VERTEX,\n * });\n * @memberof rendering\n */\nexport class Buffer extends EventEmitter<{\n change: BindResource,\n update: Buffer,\n destroy: Buffer,\n}> implements BindResource\n{\n /**\n * emits when the underlying buffer has changed shape (i.e. resized)\n * letting the renderer know that it needs to discard the old buffer on the GPU and create a new one\n * @event change\n */\n\n /**\n * emits when the underlying buffer data has been updated. letting the renderer know\n * that it needs to update the buffer on the GPU\n * @event update\n */\n\n /**\n * emits when the buffer is destroyed. letting the renderer know that it needs to destroy the buffer on the GPU\n * @event destroy\n */\n\n /** a unique id for this uniform group used through the renderer */\n public readonly uid: number = uid('buffer');\n\n /**\n * a resource type, used to identify how to handle it when its in a bind group / shader resource\n * @internal\n * @ignore\n */\n public readonly _resourceType = 'buffer';\n\n /**\n * the resource id used internally by the renderer to build bind group keys\n * @internal\n * @ignore\n */\n public _resourceId = uid('resource');\n\n /**\n * used internally to know if a uniform group was used in the last render pass\n * @internal\n * @ignore\n */\n public _touched = 0;\n\n /**\n * a description of the buffer and how it should be set up on the GPU\n * @internal\n * @ignore\n */\n public readonly descriptor: BufferDescriptor;\n\n /**\n * @internal\n * @ignore\n */\n public _updateID = 1;\n\n /**\n * @internal\n * @ignore\n */\n public _updateSize: number;\n\n private _data: TypedArray;\n\n /**\n * should the GPU buffer be shrunk when the data becomes smaller?\n * changing this will cause the buffer to be destroyed and a new one created on the GPU\n * this can be expensive, especially if the buffer is already big enough!\n * setting this to false will prevent the buffer from being shrunk. This will yield better performance\n * if you are constantly setting data that is changing size often.\n * @default true\n */\n public shrinkToFit = true;\n\n /**\n * Has the buffer been destroyed?\n * @readonly\n */\n public destroyed = false;\n\n /**\n * Creates a new Buffer with the given options\n * @param options - the options for the buffer\n */\n constructor(options: BufferOptions)\n {\n let { data, size } = options;\n const { usage, label, shrinkToFit } = options;\n\n super();\n\n if (data instanceof Array)\n {\n data = new Float32Array(data as number[]);\n }\n\n this._data = data as TypedArray;\n\n size = size ?? (data as TypedArray)?.byteLength;\n\n const mappedAtCreation = !!data;\n\n this.descriptor = {\n size,\n usage,\n mappedAtCreation,\n label,\n };\n\n this.shrinkToFit = shrinkToFit ?? true;\n }\n\n /** the data in the buffer */\n get data()\n {\n return this._data;\n }\n\n set data(value: TypedArray)\n {\n this.setDataWithSize(value, value.length, true);\n }\n\n /** whether the buffer is static or not */\n get static()\n {\n return !!(this.descriptor.usage & BufferUsage.STATIC);\n }\n\n set static(value: boolean)\n {\n if (value)\n {\n this.descriptor.usage |= BufferUsage.STATIC;\n }\n else\n {\n this.descriptor.usage &= ~BufferUsage.STATIC;\n }\n }\n\n /**\n * Sets the data in the buffer to the given value. This will immediately update the buffer on the GPU.\n * If you only want to update a subset of the buffer, you can pass in the size of the data.\n * @param value - the data to set\n * @param size - the size of the data in bytes\n * @param syncGPU - should the buffer be updated on the GPU immediately?\n */\n public setDataWithSize(value: TypedArray, size: number, syncGPU: boolean)\n {\n // Increment update ID\n this._updateID++;\n\n this._updateSize = (size * value.BYTES_PER_ELEMENT);\n\n // If the data hasn't changed, early return after emitting 'update'\n if (this._data === value)\n {\n if (syncGPU) this.emit('update', this);\n\n return;\n }\n\n // Cache old data and update to new value\n const oldData = this._data;\n\n this._data = value;\n\n // Event handling\n if (oldData.length !== value.length)\n {\n if (!this.shrinkToFit && value.byteLength < oldData.byteLength)\n {\n if (syncGPU) this.emit('update', this);\n }\n else\n {\n this.descriptor.size = value.byteLength;\n this._resourceId = uid('resource');\n this.emit('change', this);\n }\n\n return;\n }\n\n if (syncGPU) this.emit('update', this);\n }\n\n /**\n * updates the buffer on the GPU to reflect the data in the buffer.\n * By default it will update the entire buffer. If you only want to update a subset of the buffer,\n * you can pass in the size of the buffer to update.\n * @param sizeInBytes - the new size of the buffer in bytes\n */\n public update(sizeInBytes?: number): void\n {\n this._updateSize = sizeInBytes ?? this._updateSize;\n\n this._updateID++;\n\n this.emit('update', this);\n }\n\n /** Destroys the buffer */\n public destroy()\n {\n this.destroyed = true;\n\n this.emit('destroy', this);\n this.emit('change', this);\n\n this._data = null;\n (this.descriptor as null) = null;\n\n this.removeAllListeners();\n }\n}\n\n"],"names":[],"mappings":";;;;;AA0EO,MAAM,eAAe,YAK5B,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAmFI,YAAY,OACZ,EAAA;AACI,IAAI,IAAA,EAAE,IAAM,EAAA,IAAA,EAAS,GAAA,OAAA,CAAA;AACrB,IAAA,MAAM,EAAE,KAAA,EAAO,KAAO,EAAA,WAAA,EAAgB,GAAA,OAAA,CAAA;AAEtC,IAAM,KAAA,EAAA,CAAA;AArEV;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAAgB,IAAA,CAAA,GAAA,GAAc,IAAI,QAAQ,CAAA,CAAA;AAO1C;AAAA;AAAA;AAAA;AAAA;AAAA,IAAA,IAAA,CAAgB,aAAgB,GAAA,QAAA,CAAA;AAOhC;AAAA;AAAA;AAAA;AAAA;AAAA,IAAO,IAAA,CAAA,WAAA,GAAc,IAAI,UAAU,CAAA,CAAA;AAOnC;AAAA;AAAA;AAAA;AAAA;AAAA,IAAA,IAAA,CAAO,QAAW,GAAA,CAAA,CAAA;AAalB;AAAA;AAAA;AAAA;AAAA,IAAA,IAAA,CAAO,SAAY,GAAA,CAAA,CAAA;AAkBnB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAAA,IAAA,CAAO,WAAc,GAAA,IAAA,CAAA;AAMrB;AAAA;AAAA;AAAA;AAAA,IAAA,IAAA,CAAO,SAAY,GAAA,KAAA,CAAA;AAaf,IAAA,IAAI,gBAAgB,KACpB,EAAA;AACI,MAAO,IAAA,GAAA,IAAI,aAAa,IAAgB,CAAA,CAAA;AAAA,KAC5C;AAEA,IAAA,IAAA,CAAK,KAAQ,GAAA,IAAA,CAAA;AAEb,IAAA,IAAA,GAAO,QAAS,IAAqB,EAAA,UAAA,CAAA;AAErC,IAAM,MAAA,gBAAA,GAAmB,CAAC,CAAC,IAAA,CAAA;AAE3B,IAAA,IAAA,CAAK,UAAa,GAAA;AAAA,MACd,IAAA;AAAA,MACA,KAAA;AAAA,MACA,gBAAA;AAAA,MACA,KAAA;AAAA,KACJ,CAAA;AAEA,IAAA,IAAA,CAAK,cAAc,WAAe,IAAA,IAAA,CAAA;AAAA,GACtC;AAAA;AAAA,EAGA,IAAI,IACJ,GAAA;AACI,IAAA,OAAO,IAAK,CAAA,KAAA,CAAA;AAAA,GAChB;AAAA,EAEA,IAAI,KAAK,KACT,EAAA;AACI,IAAA,IAAA,CAAK,eAAgB,CAAA,KAAA,EAAO,KAAM,CAAA,MAAA,EAAQ,IAAI,CAAA,CAAA;AAAA,GAClD;AAAA;AAAA,EAGA,IAAI,MACJ,GAAA;AACI,IAAA,OAAO,CAAC,EAAE,IAAK,CAAA,UAAA,CAAW,QAAQ,WAAY,CAAA,MAAA,CAAA,CAAA;AAAA,GAClD;AAAA,EAEA,IAAI,OAAO,KACX,EAAA;AACI,IAAA,IAAI,KACJ,EAAA;AACI,MAAK,IAAA,CAAA,UAAA,CAAW,SAAS,WAAY,CAAA,MAAA,CAAA;AAAA,KAGzC,MAAA;AACI,MAAK,IAAA,CAAA,UAAA,CAAW,KAAS,IAAA,CAAC,WAAY,CAAA,MAAA,CAAA;AAAA,KAC1C;AAAA,GACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASO,eAAA,CAAgB,KAAmB,EAAA,IAAA,EAAc,OACxD,EAAA;AAEI,IAAK,IAAA,CAAA,SAAA,EAAA,CAAA;AAEL,IAAK,IAAA,CAAA,WAAA,GAAe,OAAO,KAAM,CAAA,iBAAA,CAAA;AAGjC,IAAI,IAAA,IAAA,CAAK,UAAU,KACnB,EAAA;AACI,MAAI,IAAA,OAAA;AAAS,QAAK,IAAA,CAAA,IAAA,CAAK,UAAU,IAAI,CAAA,CAAA;AAErC,MAAA,OAAA;AAAA,KACJ;AAGA,IAAA,MAAM,UAAU,IAAK,CAAA,KAAA,CAAA;AAErB,IAAA,IAAA,CAAK,KAAQ,GAAA,KAAA,CAAA;AAGb,IAAI,IAAA,OAAA,CAAQ,MAAW,KAAA,KAAA,CAAM,MAC7B,EAAA;AACI,MAAA,IAAI,CAAC,IAAK,CAAA,WAAA,IAAe,KAAM,CAAA,UAAA,GAAa,QAAQ,UACpD,EAAA;AACI,QAAI,IAAA,OAAA;AAAS,UAAK,IAAA,CAAA,IAAA,CAAK,UAAU,IAAI,CAAA,CAAA;AAAA,OAGzC,MAAA;AACI,QAAK,IAAA,CAAA,UAAA,CAAW,OAAO,KAAM,CAAA,UAAA,CAAA;AAC7B,QAAK,IAAA,CAAA,WAAA,GAAc,IAAI,UAAU,CAAA,CAAA;AACjC,QAAK,IAAA,CAAA,IAAA,CAAK,UAAU,IAAI,CAAA,CAAA;AAAA,OAC5B;AAEA,MAAA,OAAA;AAAA,KACJ;AAEA,IAAI,IAAA,OAAA;AAAS,MAAK,IAAA,CAAA,IAAA,CAAK,UAAU,IAAI,CAAA,CAAA;AAAA,GACzC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQO,OAAO,WACd,EAAA;AACI,IAAK,IAAA,CAAA,WAAA,GAAc,eAAe,IAAK,CAAA,WAAA,CAAA;AAEvC,IAAK,IAAA,CAAA,SAAA,EAAA,CAAA;AAEL,IAAK,IAAA,CAAA,IAAA,CAAK,UAAU,IAAI,CAAA,CAAA;AAAA,GAC5B;AAAA;AAAA,EAGO,OACP,GAAA;AACI,IAAA,IAAA,CAAK,SAAY,GAAA,IAAA,CAAA;AAEjB,IAAK,IAAA,CAAA,IAAA,CAAK,WAAW,IAAI,CAAA,CAAA;AACzB,IAAK,IAAA,CAAA,IAAA,CAAK,UAAU,IAAI,CAAA,CAAA;AAExB,IAAA,IAAA,CAAK,KAAQ,GAAA,IAAA,CAAA;AACb,IAAC,KAAK,UAAsB,GAAA,IAAA,CAAA;AAE5B,IAAA,IAAA,CAAK,kBAAmB,EAAA,CAAA;AAAA,GAC5B;AACJ;;;;"} |