WIP
This commit is contained in:
parent
34ac200437
commit
39b0160064
136 changed files with 7129 additions and 1950 deletions
58
src/utils/graphics/cached-buffer-write.test.ts
Normal file
58
src/utils/graphics/cached-buffer-write.test.ts
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
import { describe, expect, it, vi } from 'vitest';
|
||||
|
||||
import {
|
||||
createCachedFloat32BufferWrite,
|
||||
writeFloat32BufferIfChanged,
|
||||
} from './cached-buffer-write';
|
||||
|
||||
const createGpuWriteStub = () => {
|
||||
const writeBuffer = vi.fn();
|
||||
const device = {
|
||||
queue: {
|
||||
writeBuffer,
|
||||
},
|
||||
} as unknown as GPUDevice;
|
||||
|
||||
return { device, writeBuffer };
|
||||
};
|
||||
|
||||
describe('cached float32 buffer writes', () => {
|
||||
it('writes the first value set and skips unchanged values', () => {
|
||||
const { device, writeBuffer } = createGpuWriteStub();
|
||||
const buffer = {} as GPUBuffer;
|
||||
const cache = createCachedFloat32BufferWrite(3);
|
||||
const values = new Float32Array([1, 2, 3]);
|
||||
|
||||
expect(writeFloat32BufferIfChanged(device, buffer, values, cache)).toBe(true);
|
||||
expect(writeBuffer).toHaveBeenCalledTimes(1);
|
||||
expect(writeBuffer).toHaveBeenLastCalledWith(buffer, 0, values);
|
||||
|
||||
expect(writeFloat32BufferIfChanged(device, buffer, values, cache)).toBe(false);
|
||||
expect(writeBuffer).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('writes again when any float changes', () => {
|
||||
const { device, writeBuffer } = createGpuWriteStub();
|
||||
const buffer = {} as GPUBuffer;
|
||||
const cache = createCachedFloat32BufferWrite(3);
|
||||
|
||||
expect(
|
||||
writeFloat32BufferIfChanged(device, buffer, new Float32Array([1, 2, 3]), cache)
|
||||
).toBe(true);
|
||||
expect(
|
||||
writeFloat32BufferIfChanged(device, buffer, new Float32Array([1, 2, 4]), cache)
|
||||
).toBe(true);
|
||||
expect(writeBuffer).toHaveBeenCalledTimes(2);
|
||||
});
|
||||
|
||||
it('rejects cache length mismatches before writing', () => {
|
||||
const { device, writeBuffer } = createGpuWriteStub();
|
||||
const buffer = {} as GPUBuffer;
|
||||
const cache = createCachedFloat32BufferWrite(2);
|
||||
|
||||
expect(() =>
|
||||
writeFloat32BufferIfChanged(device, buffer, new Float32Array([1]), cache)
|
||||
).toThrow('Cached buffer write length mismatch');
|
||||
expect(writeBuffer).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
36
src/utils/graphics/cached-buffer-write.ts
Normal file
36
src/utils/graphics/cached-buffer-write.ts
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
export interface CachedFloat32BufferWrite {
|
||||
hasValue: boolean;
|
||||
previous: Float32Array;
|
||||
}
|
||||
|
||||
export const createCachedFloat32BufferWrite = (
|
||||
length: number
|
||||
): CachedFloat32BufferWrite => ({
|
||||
hasValue: false,
|
||||
previous: new Float32Array(length),
|
||||
});
|
||||
|
||||
export const writeFloat32BufferIfChanged = (
|
||||
device: GPUDevice,
|
||||
buffer: GPUBuffer,
|
||||
values: Float32Array,
|
||||
cache: CachedFloat32BufferWrite
|
||||
): boolean => {
|
||||
if (values.length !== cache.previous.length) {
|
||||
throw new Error('Cached buffer write length mismatch');
|
||||
}
|
||||
|
||||
let hasChanged = !cache.hasValue;
|
||||
for (let i = 0; i < values.length && !hasChanged; i++) {
|
||||
hasChanged = !Object.is(values[i], cache.previous[i]);
|
||||
}
|
||||
|
||||
if (!hasChanged) {
|
||||
return false;
|
||||
}
|
||||
|
||||
cache.previous.set(values);
|
||||
cache.hasValue = true;
|
||||
device.queue.writeBuffer(buffer, 0, values);
|
||||
return true;
|
||||
};
|
||||
Loading…
Reference in a new issue