mirror of
https://github.com/visgl/luma.gl.git
synced 2026-02-01 14:33:49 +00:00
128 lines
3.7 KiB
TypeScript
128 lines
3.7 KiB
TypeScript
// luma.gl
|
|
// SPDX-License-Identifier: MIT
|
|
// Copyright (c) vis.gl contributors
|
|
|
|
import type {BufferProps, FramebufferProps} from '@luma.gl/core';
|
|
import {Device, Resource, Buffer, Framebuffer, Texture} from '@luma.gl/core';
|
|
|
|
/**
|
|
* Helper class for working with repeated transformations / computations
|
|
* Primarily intended for GPU buffers `Swap<Buffer>` or textures `Swap<Texture>`)
|
|
* @note the two resources are expected to be structurally identical (same size, length, format, etc)
|
|
* @note the two resources can be destroyed by calling `destroy()`
|
|
*/
|
|
export class Swap<T extends Resource<any>> {
|
|
id: string;
|
|
|
|
/** The current resource - usually the source for renders or computations */
|
|
current: T;
|
|
/** The next resource - usually the target/destination for transforms / computations */
|
|
next: T;
|
|
|
|
constructor(props: {current: T; next: T; id?: string}) {
|
|
this.id = props.id || 'swap';
|
|
this.current = props.current;
|
|
this.next = props.next;
|
|
}
|
|
|
|
/** Destroys the two managed resources */
|
|
destroy() {
|
|
this.current?.destroy();
|
|
this.next?.destroy();
|
|
}
|
|
|
|
/** Make the next resource into the current resource, and reuse the current resource as the next resource */
|
|
swap() {
|
|
const current = this.current;
|
|
this.current = this.next;
|
|
this.next = current;
|
|
}
|
|
}
|
|
|
|
/** Helper for managing double-buffered framebuffers */
|
|
export class SwapFramebuffers extends Swap<Framebuffer> {
|
|
constructor(device: Device, props: FramebufferProps) {
|
|
props = {...props};
|
|
|
|
const {width = 1, height = 1} = props;
|
|
|
|
let colorAttachments = props.colorAttachments?.map(colorAttachment =>
|
|
typeof colorAttachment !== 'string'
|
|
? colorAttachment
|
|
: device.createTexture({
|
|
id: `${props.id}-texture-0`,
|
|
format: colorAttachment,
|
|
usage: Texture.SAMPLE | Texture.RENDER | Texture.COPY_SRC | Texture.COPY_DST,
|
|
width,
|
|
height
|
|
})
|
|
);
|
|
|
|
const current = device.createFramebuffer({...props, colorAttachments});
|
|
|
|
colorAttachments = props.colorAttachments?.map(colorAttachment =>
|
|
typeof colorAttachment !== 'string'
|
|
? colorAttachment
|
|
: device.createTexture({
|
|
id: `${props.id}-texture-1`,
|
|
format: colorAttachment,
|
|
usage: Texture.SAMPLE | Texture.RENDER | Texture.COPY_SRC | Texture.COPY_DST,
|
|
width,
|
|
height
|
|
})
|
|
);
|
|
|
|
const next = device.createFramebuffer({...props, colorAttachments});
|
|
|
|
super({current, next});
|
|
}
|
|
|
|
/**
|
|
* Resizes the Framebuffers.
|
|
* @returns true if the size changed, otherwise exiting framebuffers were preserved
|
|
* @note any contents are not preserved!
|
|
*/
|
|
resize(size: {width: number; height: number}): boolean {
|
|
if (size.width === this.current.width && size.height === this.current.height) {
|
|
return false;
|
|
}
|
|
const {current, next} = this;
|
|
|
|
this.current = current.clone(size);
|
|
current.destroy();
|
|
|
|
this.next = next.clone(size);
|
|
next.destroy();
|
|
|
|
return true;
|
|
}
|
|
}
|
|
|
|
/** Helper for managing double-buffered GPU buffers */
|
|
export class SwapBuffers extends Swap<Buffer> {
|
|
constructor(device: Device, props: BufferProps) {
|
|
super({current: device.createBuffer(props), next: device.createBuffer(props)});
|
|
}
|
|
|
|
/**
|
|
* Resizes the Buffers.
|
|
* @returns true if the size changed, otherwise exiting buffers were preserved.
|
|
* @note any contents are not preserved!
|
|
*/
|
|
resize(props: {byteLength: number}) {
|
|
if (props.byteLength === this.current.byteLength) {
|
|
return false;
|
|
}
|
|
|
|
const {current, next} = this;
|
|
|
|
this.current = current.clone(props);
|
|
current.destroy();
|
|
|
|
this.next = next.clone(props);
|
|
next.destroy();
|
|
|
|
return true;
|
|
}
|
|
}
|