@luma.gl/core
Version:
The luma.gl core Device API
85 lines (73 loc) • 2.69 kB
text/typescript
// luma.gl
// SPDX-License-Identifier: MIT
// Copyright (c) vis.gl contributors
import type {VariableShaderType} from '../shadertypes/shader-types/shader-types';
import type {UniformValue} from '../adapter/types/uniforms';
import {
ShaderLayout,
UniformInfo,
UniformBufferBindingLayout
} from '../adapter/types/shader-layout';
import {arrayEqual, arrayCopy} from '../utils/array-equal';
/**
* A uniform block holds values of the of uniform values for one uniform block / buffer.
* It also does some book keeping on what has changed, to minimize unnecessary writes to uniform buffers.
*/
export class UniformBlock<
TUniforms extends Record<string, UniformValue> = Record<string, UniformValue>
> {
name: string;
uniforms: Record<keyof TUniforms, UniformValue> = {} as Record<keyof TUniforms, UniformValue>;
modifiedUniforms: Record<keyof TUniforms, boolean> = {} as Record<keyof TUniforms, boolean>;
modified: boolean = true;
readonly bindingLayout: Record<string, UniformInfo> = {};
needsRedraw: string | false = 'initialized';
constructor(props?: {
name?: string;
shaderLayout?: ShaderLayout;
uniformTypes?: Record<keyof TUniforms, Record<string, VariableShaderType>>;
}) {
this.name = props?.name || 'unnamed';
// TODO - Extract uniform layout from the shaderLayout object
if (props?.name && props?.shaderLayout) {
const binding = props?.shaderLayout.bindings?.find(
binding_ => binding_.type === 'uniform' && binding_.name === props?.name
);
if (!binding) {
throw new Error(props?.name);
}
const uniformBlock = binding as UniformBufferBindingLayout;
for (const uniform of uniformBlock.uniforms || []) {
this.bindingLayout[uniform.name] = uniform;
}
}
}
/** Set a map of uniforms */
setUniforms(uniforms: Partial<TUniforms>): void {
for (const [key, value] of Object.entries(uniforms)) {
this._setUniform(key, value);
if (!this.needsRedraw) {
this.setNeedsRedraw(`${this.name}.${key}=${value}`);
}
}
}
setNeedsRedraw(reason: string): void {
this.needsRedraw = this.needsRedraw || reason;
}
/** Returns all uniforms */
getAllUniforms(): Record<string, UniformValue> {
// @ts-expect-error
this.modifiedUniforms = {};
this.needsRedraw = false;
return (this.uniforms || {}) as Record<string, UniformValue>;
}
/** Set a single uniform */
private _setUniform(key: keyof TUniforms, value: UniformValue) {
if (arrayEqual(this.uniforms[key], value)) {
return;
}
this.uniforms[key] = arrayCopy(value);
this.modifiedUniforms[key] = true;
this.modified = true;
}
}