Skip to content

Commit 3d57cf7

Browse files
Register default shader module with Deck (visgl#8682)
1 parent ecd78ec commit 3d57cf7

File tree

21 files changed

+196
-173
lines changed

21 files changed

+196
-173
lines changed

modules/core/src/effects/lighting/lighting-effect.ts

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import type {Device} from '@luma.gl/core';
2-
import {ShaderAssembler} from '@luma.gl/shadertools';
32
import {Texture} from '@luma.gl/core';
43
import {AmbientLight} from './ambient-light';
54
import {DirectionalLight} from './directional-light';
@@ -42,7 +41,6 @@ export default class LightingEffect implements Effect {
4241
private shadowPasses: ShadowPass[] = [];
4342
private shadowMaps: Texture[] = [];
4443
private dummyShadowMap: Texture | null = null;
45-
private shaderAssembler?: ShaderAssembler;
4644
private shadowMatrices?: Matrix4[];
4745

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

5250
setup(context: EffectContext) {
5351
this.context = context;
54-
const {device} = context;
52+
const {device, deck} = context;
5553

5654
if (this.shadow && !this.dummyShadowMap) {
5755
this._createShadowPasses(device);
58-
this.shaderAssembler = ShaderAssembler.getDefaultShaderAssembler();
59-
this.shaderAssembler.addDefaultModule(shadow);
56+
57+
deck._addDefaultShaderModule(shadow);
6058

6159
this.dummyShadowMap = device.createTexture({
6260
width: 1,
@@ -154,7 +152,7 @@ export default class LightingEffect implements Effect {
154152
return parameters;
155153
}
156154

157-
cleanup(): void {
155+
cleanup(context: EffectContext): void {
158156
for (const shadowPass of this.shadowPasses) {
159157
shadowPass.delete();
160158
}
@@ -164,11 +162,7 @@ export default class LightingEffect implements Effect {
164162
if (this.dummyShadowMap) {
165163
this.dummyShadowMap.destroy();
166164
this.dummyShadowMap = null;
167-
}
168-
169-
if (this.shaderAssembler) {
170-
this.shaderAssembler.removeDefaultModule(shadow);
171-
this.shaderAssembler = null!;
165+
context.deck._removeDefaultShaderModule(shadow);
172166
}
173167
}
174168

modules/core/src/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
export {VERSION} from './lib/init';
2424

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

2828
// Core Library
2929
export {COORDINATE_SYSTEM, OPERATION, UNIT} from './lib/constants';

modules/core/src/lib/deck.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ import {Timeline} from '@luma.gl/engine';
3737
import {AnimationLoop} from '@luma.gl/engine';
3838
import {GL} from '@luma.gl/constants';
3939
import type {Device, DeviceProps, Framebuffer} from '@luma.gl/core';
40+
import type {ShaderModule} from '@luma.gl/shadertools';
4041

4142
import {Stats} from '@probe.gl/stats';
4243
import {EventManager} from 'mjolnir.js';
@@ -674,6 +675,14 @@ export default class Deck<ViewsT extends ViewOrViews = ViewOrViews> {
674675
this.effectManager!.addDefaultEffect(effect);
675676
}
676677

678+
_addDefaultShaderModule(module: ShaderModule) {
679+
this.layerManager!.addDefaultShaderModule(module);
680+
}
681+
682+
_removeDefaultShaderModule(module: ShaderModule) {
683+
this.layerManager?.removeDefaultShaderModule(module);
684+
}
685+
677686
// Private Methods
678687

679688
private _pick(

modules/core/src/lib/layer-manager.ts

Lines changed: 36 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,8 @@
2020

2121
import type {Device, RenderPass} from '@luma.gl/core';
2222
import {Timeline} from '@luma.gl/engine';
23-
import type {PipelineFactory} from '@luma.gl/engine';
24-
import {ShaderAssembler} from '@luma.gl/shadertools';
25-
import {getPipelineFactory, getShaderAssembler} from '../shaderlib/index';
23+
import type {ShaderAssembler, ShaderModule} from '@luma.gl/shadertools';
24+
import {getShaderAssembler} from '../shaderlib/index';
2625
import {LIFECYCLE} from '../lifecycle/constants';
2726
import log from '../utils/log';
2827
import debug from '../debug/index';
@@ -45,7 +44,7 @@ export type LayerContext = {
4544
deck?: Deck;
4645
device: Device;
4746
shaderAssembler: ShaderAssembler;
48-
pipelineFactory: PipelineFactory;
47+
defaultShaderModules: ShaderModule[];
4948
renderPass: RenderPass;
5049
stats: Stats;
5150
viewport: Viewport;
@@ -75,6 +74,8 @@ export default class LayerManager {
7574
private _needsUpdate: string | false = false;
7675
private _nextLayers: LayersList | null = null;
7776
private _debug: boolean = false;
77+
// This flag is separate from _needsUpdate because it can be set during an update and should trigger another full update
78+
private _defaultShaderModulesChanged: boolean = false;
7879

7980
/**
8081
* @param device
@@ -104,9 +105,8 @@ export default class LayerManager {
104105
// @ts-expect-error
105106
gl: device?.gl,
106107
deck,
107-
// Enabling luma.gl Program caching using private API (_cachePrograms)
108108
shaderAssembler: getShaderAssembler(),
109-
pipelineFactory: (device && getPipelineFactory(device))!,
109+
defaultShaderModules: [],
110110
renderPass: undefined!,
111111
stats: stats || new Stats({id: 'deck.gl'}),
112112
// Make sure context.viewport is not empty on the first layer initialization
@@ -156,6 +156,9 @@ export default class LayerManager {
156156
// New layers array may be the same as the old one if `setProps` is called by React
157157
return 'layers changed';
158158
}
159+
if (this._defaultShaderModulesChanged) {
160+
return 'shader modules changed';
161+
}
159162
return this._needsUpdate;
160163
}
161164

@@ -242,6 +245,25 @@ export default class LayerManager {
242245
}
243246
};
244247

248+
/** Register a default shader module */
249+
addDefaultShaderModule(module: ShaderModule) {
250+
const {defaultShaderModules} = this.context;
251+
if (!defaultShaderModules.find(m => m.name === module.name)) {
252+
defaultShaderModules.push(module);
253+
this._defaultShaderModulesChanged = true;
254+
}
255+
}
256+
257+
/** Deregister a default shader module */
258+
removeDefaultShaderModule(module: ShaderModule) {
259+
const {defaultShaderModules} = this.context;
260+
const i = defaultShaderModules.findIndex(m => m.name === module.name);
261+
if (i >= 0) {
262+
defaultShaderModules.splice(i, 1);
263+
this._defaultShaderModulesChanged = true;
264+
}
265+
}
266+
245267
private _handleError(stage: string, error: Error, layer: Layer) {
246268
layer.raiseError(error, `${stage} of ${layer}`);
247269
}
@@ -260,6 +282,14 @@ export default class LayerManager {
260282
}
261283
}
262284

285+
if (this._defaultShaderModulesChanged) {
286+
for (const layer of oldLayers) {
287+
layer.setNeedsUpdate();
288+
layer.setChangeFlags({extensionsChanged: true});
289+
}
290+
this._defaultShaderModulesChanged = false;
291+
}
292+
263293
// Allocate array for generated layers
264294
const generatedLayers: Layer[] = [];
265295

modules/core/src/lib/layer.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -462,6 +462,9 @@ export default abstract class Layer<PropsT extends {} = {}> extends Component<
462462
abstract initializeState(context: LayerContext): void;
463463

464464
getShaders(shaders: any): any {
465+
shaders = mergeShaders(shaders, {
466+
modules: this.context.defaultShaderModules
467+
});
465468
for (const extension of this.props.extensions) {
466469
shaders = mergeShaders(shaders, extension.getShaders.call(this, extension));
467470
}

modules/core/src/passes/shadow-pass.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,7 @@ export default class ShadowPass extends LayersPass {
5555
{
5656
depthRange: [0, 1],
5757
depthTest: true,
58-
blend: false,
59-
clearColor: [1, 1, 1, 1]
58+
blend: false
6059
},
6160
() => {
6261
// @ts-expect-error TODO - assuming WebGL context
@@ -69,7 +68,7 @@ export default class ShadowPass extends LayersPass {
6968
target.resize({width, height});
7069
}
7170

72-
super.render({...params, target, pass: 'shadow'});
71+
super.render({...params, target, pass: 'shadow', clearColor: [1, 1, 1, 1]});
7372
}
7473
);
7574
}

modules/core/src/shaderlib/index.ts

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -50,12 +50,6 @@ export function getShaderAssembler() {
5050
return shaderAssembler;
5151
}
5252

53-
// TODO - is this really needed now that modules are registered on the ShaderAssembler
54-
export function getPipelineFactory(device: Device) {
55-
const pipelineFactory = PipelineFactory.getDefaultPipelineFactory(device);
56-
return pipelineFactory;
57-
}
58-
5953
export {picking, project, project32, gouraudLighting, phongLighting, shadow};
6054

6155
// Useful for custom shader modules

modules/core/src/shaderlib/shadow/shadow.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,9 @@ function createShadowUniforms(
190190
if (!shadowEnabled || !opts.shadowMatrices || !opts.shadowMatrices.length) {
191191
return {
192192
shadow_uDrawShadowMap: false,
193-
shadow_uUseShadowMap: false
193+
shadow_uUseShadowMap: false,
194+
shadow_uShadowMap0: opts.dummyShadowMap,
195+
shadow_uShadowMap1: opts.dummyShadowMap
194196
};
195197
}
196198
const uniforms = {

modules/extensions/src/collision-filter/collision-filter-effect.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ export default class CollisionFilterEffect implements Effect {
6969
}
7070

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

7575
// Collect layers to render

modules/extensions/src/terrain/terrain-effect.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import {Texture} from '@luma.gl/core';
2-
import {log, getShaderAssembler} from '@deck.gl/core';
2+
import {log} from '@deck.gl/core';
33

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

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

46-
getShaderAssembler().addDefaultModule(terrainModule);
46+
deck._addDefaultShaderModule(terrainModule);
4747
}
4848

4949
preRender(opts: PreRenderOptions): void {
@@ -95,7 +95,7 @@ export class TerrainEffect implements Effect {
9595
};
9696
}
9797

98-
cleanup(): void {
98+
cleanup({deck}: EffectContext): void {
9999
if (this.dummyHeightMap) {
100100
this.dummyHeightMap.delete();
101101
this.dummyHeightMap = undefined;
@@ -111,7 +111,7 @@ export class TerrainEffect implements Effect {
111111
}
112112
this.terrainCovers.clear();
113113

114-
getShaderAssembler().removeDefaultModule(terrainModule);
114+
deck._removeDefaultShaderModule(terrainModule);
115115
}
116116

117117
private _updateHeightMap(terrainLayers: Layer[], viewport: Viewport, opts: PreRenderOptions) {

0 commit comments

Comments
 (0)