diff options
Diffstat (limited to 'dom/webgpu/tests/cts/checkout/src/webgpu/util/texture/data_generation.ts')
-rw-r--r-- | dom/webgpu/tests/cts/checkout/src/webgpu/util/texture/data_generation.ts | 83 |
1 files changed, 83 insertions, 0 deletions
diff --git a/dom/webgpu/tests/cts/checkout/src/webgpu/util/texture/data_generation.ts b/dom/webgpu/tests/cts/checkout/src/webgpu/util/texture/data_generation.ts new file mode 100644 index 0000000000..7ad7d30e08 --- /dev/null +++ b/dom/webgpu/tests/cts/checkout/src/webgpu/util/texture/data_generation.ts @@ -0,0 +1,83 @@ +/** + * A helper class that generates ranges of dummy data for buffer or texture operations + * efficiently. Tries to minimize allocations and data updates. + */ +export class DataArrayGenerator { + private dataBuffer = new Uint8Array(256); + + private lastOffset = 0; + private lastStart = 0; + private lastByteSize = 0; + + /** Find the nearest power of two greater than or equal to the input value. */ + private nextPowerOfTwo(value: number) { + return 1 << (32 - Math.clz32(value - 1)); + } + + private generateData(byteSize: number, start: number = 0, offset: number = 0) { + const prevSize = this.dataBuffer.length; + + if (prevSize < byteSize) { + // If the requested data is larger than the allocated buffer, reallocate it to a buffer large + // enough to handle the new request. + const newData = new Uint8Array(this.nextPowerOfTwo(byteSize)); + + if (this.lastOffset === offset && this.lastStart === start && this.lastByteSize) { + // Do a fast copy of any previous data that was generated. + newData.set(this.dataBuffer); + } + + this.dataBuffer = newData; + } else if (this.lastOffset < offset) { + // Ensure all values up to the offset are zeroed out. + this.dataBuffer.fill(0, this.lastOffset, offset); + } + + // If the offset or start values have changed, the whole data range needs to be regenerated. + if (this.lastOffset !== offset || this.lastStart !== start) { + this.lastByteSize = 0; + } + + // Generate any new values that are required + if (this.lastByteSize < byteSize) { + for (let i = this.lastByteSize; i < byteSize - offset; ++i) { + this.dataBuffer[i + offset] = ((i ** 3 + i + start) % 251) + 1; // Ensure data is always non-zero + } + + this.lastOffset = offset; + this.lastStart = start; + this.lastByteSize = byteSize; + } + } + + /** + * Returns a new view into the generated data that's the correct length. Because this is a view + * previously returned views from the same generator will have their values overwritten as well. + * @param {number} byteSize - Number of bytes the returned view should contain. + * @param {number} [start] - The value of the first element generated in the view. + * @param {number} [offset] - Offset of the generated data within the view. Preceeding values will be 0. + * @returns {Uint8Array} A new Uint8Array view into the generated data. + */ + generateView(byteSize: number, start: number = 0, offset: number = 0): Uint8Array { + this.generateData(byteSize, start, offset); + + if (this.dataBuffer.length === byteSize) { + return this.dataBuffer; + } + return new Uint8Array(this.dataBuffer.buffer, 0, byteSize); + } + + /** + * Returns a copy of the generated data. Note that this still changes the underlying buffer, so + * any previously generated views will still be overwritten, but the returned copy won't reflect + * future generate* calls. + * @param {number} byteSize - Number of bytes the returned array should contain. + * @param {number} [start] - The value of the first element generated in the view. + * @param {number} [offset] - Offset of the generated data within the view. Preceeding values will be 0. + * @returns {Uint8Array} A new Uint8Array copy of the generated data. + */ + generateAndCopyView(byteSize: number, start: number = 0, offset: number = 0) { + this.generateData(byteSize, start, offset); + return this.dataBuffer.slice(0, byteSize); + } +} |