Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Register default shader module with Deck #8682

Merged
merged 4 commits into from Mar 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
16 changes: 5 additions & 11 deletions modules/core/src/effects/lighting/lighting-effect.ts
@@ -1,5 +1,4 @@
import type {Device} from '@luma.gl/core';
import {ShaderAssembler} from '@luma.gl/shadertools';
import {Texture} from '@luma.gl/core';
import {AmbientLight} from './ambient-light';
import {DirectionalLight} from './directional-light';
Expand Down Expand Up @@ -42,7 +41,6 @@ export default class LightingEffect implements Effect {
private shadowPasses: ShadowPass[] = [];
private shadowMaps: Texture[] = [];
private dummyShadowMap: Texture | null = null;
private shaderAssembler?: ShaderAssembler;
private shadowMatrices?: Matrix4[];

constructor(props: LightingEffectProps = {}) {
Expand All @@ -51,12 +49,12 @@ export default class LightingEffect implements Effect {

setup(context: EffectContext) {
this.context = context;
const {device} = context;
const {device, deck} = context;

if (this.shadow && !this.dummyShadowMap) {
this._createShadowPasses(device);
this.shaderAssembler = ShaderAssembler.getDefaultShaderAssembler();
this.shaderAssembler.addDefaultModule(shadow);

deck._addDefaultShaderModule(shadow);

this.dummyShadowMap = device.createTexture({
width: 1,
Expand Down Expand Up @@ -154,7 +152,7 @@ export default class LightingEffect implements Effect {
return parameters;
}

cleanup(): void {
cleanup(context: EffectContext): void {
for (const shadowPass of this.shadowPasses) {
shadowPass.delete();
}
Expand All @@ -164,11 +162,7 @@ export default class LightingEffect implements Effect {
if (this.dummyShadowMap) {
this.dummyShadowMap.destroy();
this.dummyShadowMap = null;
}

if (this.shaderAssembler) {
this.shaderAssembler.removeDefaultModule(shadow);
this.shaderAssembler = null!;
context.deck._removeDefaultShaderModule(shadow);
}
}

Expand Down
2 changes: 1 addition & 1 deletion modules/core/src/index.ts
Expand Up @@ -23,7 +23,7 @@
export {VERSION} from './lib/init';

// Import shaderlib to make sure shader modules are initialized
export {getPipelineFactory, getShaderAssembler} from './shaderlib/index';
export {getShaderAssembler} from './shaderlib/index';

// Core Library
export {COORDINATE_SYSTEM, OPERATION, UNIT} from './lib/constants';
Expand Down
9 changes: 9 additions & 0 deletions modules/core/src/lib/deck.ts
Expand Up @@ -37,6 +37,7 @@
import {AnimationLoop} from '@luma.gl/engine';
import {GL} from '@luma.gl/constants';
import type {Device, DeviceProps, Framebuffer} from '@luma.gl/core';
import type {ShaderModule} from '@luma.gl/shadertools';

import {Stats} from '@probe.gl/stats';
import {EventManager} from 'mjolnir.js';
Expand Down Expand Up @@ -390,7 +391,7 @@
...props.deviceProps,
canvas: this._createCanvas(props)
});
deviceOrPromise.then(device => {

Check warning on line 394 in modules/core/src/lib/deck.ts

View workflow job for this annotation

GitHub Actions / test-node

Promises must be awaited, end with a call to .catch, end with a call to .then with a rejection handler or be explicitly marked as ignored with the `void` operator
this.device = device;
});
}
Expand All @@ -404,7 +405,7 @@
typedArrayManager.setOptions(props._typedArrayManagerProps);
}

this.animationLoop.start();

Check warning on line 408 in modules/core/src/lib/deck.ts

View workflow job for this annotation

GitHub Actions / test-node

Promises must be awaited, end with a call to .catch, end with a call to .then with a rejection handler or be explicitly marked as ignored with the `void` operator
}

/** Stop rendering and dispose all resources */
Expand Down Expand Up @@ -674,6 +675,14 @@
this.effectManager!.addDefaultEffect(effect);
}

_addDefaultShaderModule(module: ShaderModule) {
this.layerManager!.addDefaultShaderModule(module);
}

_removeDefaultShaderModule(module: ShaderModule) {
this.layerManager?.removeDefaultShaderModule(module);
}

// Private Methods

private _pick(
Expand Down
42 changes: 36 additions & 6 deletions modules/core/src/lib/layer-manager.ts
Expand Up @@ -20,9 +20,8 @@

import type {Device, RenderPass} from '@luma.gl/core';
import {Timeline} from '@luma.gl/engine';
import type {PipelineFactory} from '@luma.gl/engine';
import {ShaderAssembler} from '@luma.gl/shadertools';
import {getPipelineFactory, getShaderAssembler} from '../shaderlib/index';
import type {ShaderAssembler, ShaderModule} from '@luma.gl/shadertools';
import {getShaderAssembler} from '../shaderlib/index';
import {LIFECYCLE} from '../lifecycle/constants';
import log from '../utils/log';
import debug from '../debug/index';
Expand All @@ -45,7 +44,7 @@ export type LayerContext = {
deck?: Deck;
device: Device;
shaderAssembler: ShaderAssembler;
pipelineFactory: PipelineFactory;
defaultShaderModules: ShaderModule[];
renderPass: RenderPass;
stats: Stats;
viewport: Viewport;
Expand Down Expand Up @@ -75,6 +74,8 @@ export default class LayerManager {
private _needsUpdate: string | false = false;
private _nextLayers: LayersList | null = null;
private _debug: boolean = false;
// This flag is separate from _needsUpdate because it can be set during an update and should trigger another full update
private _defaultShaderModulesChanged: boolean = false;

/**
* @param device
Expand Down Expand Up @@ -104,9 +105,8 @@ export default class LayerManager {
// @ts-expect-error
gl: device?.gl,
deck,
// Enabling luma.gl Program caching using private API (_cachePrograms)
shaderAssembler: getShaderAssembler(),
pipelineFactory: (device && getPipelineFactory(device))!,
defaultShaderModules: [],
renderPass: undefined!,
stats: stats || new Stats({id: 'deck.gl'}),
// Make sure context.viewport is not empty on the first layer initialization
Expand Down Expand Up @@ -156,6 +156,9 @@ export default class LayerManager {
// New layers array may be the same as the old one if `setProps` is called by React
return 'layers changed';
}
if (this._defaultShaderModulesChanged) {
return 'shader modules changed';
}
return this._needsUpdate;
}

Expand Down Expand Up @@ -242,6 +245,25 @@ export default class LayerManager {
}
};

/** Register a default shader module */
addDefaultShaderModule(module: ShaderModule) {
const {defaultShaderModules} = this.context;
if (!defaultShaderModules.find(m => m.name === module.name)) {
defaultShaderModules.push(module);
this._defaultShaderModulesChanged = true;
}
}

/** Deregister a default shader module */
removeDefaultShaderModule(module: ShaderModule) {
const {defaultShaderModules} = this.context;
const i = defaultShaderModules.findIndex(m => m.name === module.name);
if (i >= 0) {
defaultShaderModules.splice(i, 1);
this._defaultShaderModulesChanged = true;
}
}

private _handleError(stage: string, error: Error, layer: Layer) {
layer.raiseError(error, `${stage} of ${layer}`);
}
Expand All @@ -260,6 +282,14 @@ export default class LayerManager {
}
}

if (this._defaultShaderModulesChanged) {
for (const layer of oldLayers) {
layer.setNeedsUpdate();
layer.setChangeFlags({extensionsChanged: true});
}
this._defaultShaderModulesChanged = false;
}

// Allocate array for generated layers
const generatedLayers: Layer[] = [];

Expand Down
3 changes: 3 additions & 0 deletions modules/core/src/lib/layer.ts
Expand Up @@ -462,6 +462,9 @@ export default abstract class Layer<PropsT extends {} = {}> extends Component<
abstract initializeState(context: LayerContext): void;

getShaders(shaders: any): any {
shaders = mergeShaders(shaders, {
modules: this.context.defaultShaderModules
});
for (const extension of this.props.extensions) {
shaders = mergeShaders(shaders, extension.getShaders.call(this, extension));
}
Expand Down
5 changes: 2 additions & 3 deletions modules/core/src/passes/shadow-pass.ts
Expand Up @@ -55,8 +55,7 @@ export default class ShadowPass extends LayersPass {
{
depthRange: [0, 1],
depthTest: true,
blend: false,
clearColor: [1, 1, 1, 1]
blend: false
},
() => {
// @ts-expect-error TODO - assuming WebGL context
Expand All @@ -69,7 +68,7 @@ export default class ShadowPass extends LayersPass {
target.resize({width, height});
}

super.render({...params, target, pass: 'shadow'});
super.render({...params, target, pass: 'shadow', clearColor: [1, 1, 1, 1]});
}
);
}
Expand Down
6 changes: 0 additions & 6 deletions modules/core/src/shaderlib/index.ts
Expand Up @@ -50,12 +50,6 @@ export function getShaderAssembler() {
return shaderAssembler;
}

// TODO - is this really needed now that modules are registered on the ShaderAssembler
export function getPipelineFactory(device: Device) {
const pipelineFactory = PipelineFactory.getDefaultPipelineFactory(device);
return pipelineFactory;
}

export {picking, project, project32, gouraudLighting, phongLighting, shadow};

// Useful for custom shader modules
Expand Down
4 changes: 3 additions & 1 deletion modules/core/src/shaderlib/shadow/shadow.ts
Expand Up @@ -190,7 +190,9 @@ function createShadowUniforms(
if (!shadowEnabled || !opts.shadowMatrices || !opts.shadowMatrices.length) {
return {
shadow_uDrawShadowMap: false,
shadow_uUseShadowMap: false
shadow_uUseShadowMap: false,
shadow_uShadowMap0: opts.dummyShadowMap,
felixpalmer marked this conversation as resolved.
Show resolved Hide resolved
shadow_uShadowMap1: opts.dummyShadowMap
};
}
const uniforms = {
Expand Down
Expand Up @@ -69,7 +69,7 @@ export default class CollisionFilterEffect implements Effect {
}

// Detect if mask has rendered. TODO: better dependency system for Effects
const effects = allEffects?.filter(e => e.constructor === MaskEffect);
const effects = allEffects?.filter(e => e.useInPicking && preRenderStats[e.id]);
const maskEffectRendered = (preRenderStats['mask-effect'] as MaskPreRenderStats)?.didRender;

// Collect layers to render
Expand Down
10 changes: 5 additions & 5 deletions modules/extensions/src/terrain/terrain-effect.ts
@@ -1,5 +1,5 @@
import {Texture} from '@luma.gl/core';
import {log, getShaderAssembler} from '@deck.gl/core';
import {log} from '@deck.gl/core';

import {terrainModule, TerrainModuleSettings} from './shader-module';
import {TerrainCover} from './terrain-cover';
Expand Down Expand Up @@ -28,7 +28,7 @@ export class TerrainEffect implements Effect {
/** One texture for each primitive terrain layer, into which the draped layers render */
private terrainCovers: Map<string, TerrainCover> = new Map();

setup({device}: EffectContext) {
setup({device, deck}: EffectContext) {
this.dummyHeightMap = device.createTexture({
width: 1,
height: 1,
Expand All @@ -43,7 +43,7 @@ export class TerrainEffect implements Effect {
log.warn('Terrain offset mode is not supported by this browser')();
}

getShaderAssembler().addDefaultModule(terrainModule);
deck._addDefaultShaderModule(terrainModule);
}

preRender(opts: PreRenderOptions): void {
Expand Down Expand Up @@ -95,7 +95,7 @@ export class TerrainEffect implements Effect {
};
}

cleanup(): void {
cleanup({deck}: EffectContext): void {
if (this.dummyHeightMap) {
this.dummyHeightMap.delete();
this.dummyHeightMap = undefined;
Expand All @@ -111,7 +111,7 @@ export class TerrainEffect implements Effect {
}
this.terrainCovers.clear();

getShaderAssembler().removeDefaultModule(terrainModule);
deck._removeDefaultShaderModule(terrainModule);
}

private _updateHeightMap(terrainLayers: Layer[], viewport: Viewport, opts: PreRenderOptions) {
Expand Down
1 change: 1 addition & 0 deletions modules/extensions/src/terrain/utils.ts
Expand Up @@ -12,6 +12,7 @@ export function createRenderTarget(
id: opts.id,
colorAttachments: [
device.createTexture({
id: opts.id,
...(opts.float && {
format: 'rgba32float',
type: GL.FLOAT
Expand Down
1 change: 0 additions & 1 deletion modules/main/src/index.ts
Expand Up @@ -88,7 +88,6 @@ export {
Tesselator,
fp64LowPart,
createIterable,
getPipelineFactory,
getShaderAssembler
} from '@deck.gl/core';

Expand Down
6 changes: 5 additions & 1 deletion modules/test-utils/src/snapshot-test-runner.ts
Expand Up @@ -64,7 +64,11 @@ const DEFAULT_TEST_CASE: SnapshotTestCase = {
// eslint-disable-line
},
onAfterRender: ({deck, layers, done}) => {
if (layers.every(layer => layer.isLoaded)) {
if (
// @ts-expect-error accessing private
!deck.layerManager?.needsUpdate() &&
layers.every(layer => layer.isLoaded)
) {
done(); // eslint-disable-line
}
},
Expand Down