Skip to content

Commit

Permalink
feat: Start replacing gl with device
Browse files Browse the repository at this point in the history
  • Loading branch information
ibgreen committed Dec 1, 2022
1 parent dba300c commit 6ba603c
Show file tree
Hide file tree
Showing 11 changed files with 65 additions and 56 deletions.
4 changes: 2 additions & 2 deletions modules/core/src/effects/lighting/lighting-effect.ts
Expand Up @@ -37,7 +37,7 @@ export default class LightingEffect implements Effect {
private pointLights: PointLight[] = [];
private shadowPasses: ShadowPass[] = [];
private shadowMaps: Texture2D[] = [];
private dummyShadowMap?: Texture2D;
private dummyShadowMap: Texture2D | null = null;
private pipelineFactory?: ProgramManager;
private shadowMatrices?: Matrix4[];

Expand Down Expand Up @@ -158,7 +158,7 @@ export default class LightingEffect implements Effect {

if (this.shadow && this.pipelineFactory) {
this.pipelineFactory.removeDefaultModule(shadow);
this.pipelineFactory = undefined;
this.pipelineFactory = null!;
}
}

Expand Down
37 changes: 24 additions & 13 deletions modules/core/src/lib/deck.ts
Expand Up @@ -31,6 +31,8 @@ import typedArrayManager from '../utils/typed-array-manager';
import deckGlobal from './init';

import {getBrowser} from '@probe.gl/env';
import {Device} from '@luma.gl/api';
import {WebGLDevice} from '@luma.gl/webgl';
import GL from '@luma.gl/constants';
import {
AnimationLoop,
Expand Down Expand Up @@ -179,7 +181,9 @@ export type DeckProps = {
/** (Experimental) Fine-tune attribute memory usage. See documentation for details. */
_typedArrayManagerProps?: TypedArrayManagerOptions;

/** Called once the WebGL context has been initiated. */
/** Called once the GPU Device has been initiated. */
onDeviceInitialized?: (device: Device) => void;
/** @deprecated Called once the WebGL context has been initiated. */
onWebGLInitialized?: (gl: WebGLRenderingContext) => void;
/** Called when the canvas resizes. */
onResize?: (dimensions: {width: number; height: number}) => void;
Expand All @@ -188,9 +192,9 @@ export type DeckProps = {
/** Called when the user has interacted with the deck.gl canvas, e.g. using mouse, touch or keyboard. */
onInteractionStateChange?: (state: InteractionState) => void;
/** Called just before the canvas rerenders. */
onBeforeRender?: (context: {gl: WebGLRenderingContext}) => void;
onBeforeRender?: (context: {device: Device; gl: WebGLRenderingContext}) => void;
/** Called right after the canvas rerenders. */
onAfterRender?: (context: {gl: WebGLRenderingContext}) => void;
onAfterRender?: (context: {device: Device; gl: WebGLRenderingContext}) => void;
/** Called once after gl context and all Deck components are created. */
onLoad?: () => void;
/** Called if deck.gl encounters an error.
Expand Down Expand Up @@ -252,6 +256,7 @@ const defaultProps = {
_typedArrayManagerProps: {},
_customRender: null,

onDeviceInitialized: noop,
onWebGLInitialized: noop,
onResize: noop,
onViewStateChange: noop,
Expand Down Expand Up @@ -763,6 +768,7 @@ export default class Deck {
onContextLost: () => this._onContextLost()
}),
onInitialize: context => this._setGLContext(context.gl),

onRender: this._onRenderFrame.bind(this),
// onBeforeRender,
// onAfterRender,
Expand Down Expand Up @@ -875,7 +881,10 @@ export default class Deck {
}
}

/** @deprecated */
private _setGLContext(gl: WebGLRenderingContext) {
const device = WebGLDevice.attach(gl);

if (this.layerManager) {
return;
}
Expand All @@ -897,6 +906,7 @@ export default class Deck {
depthFunc: GL.LEQUAL
});

this.props.onDeviceInitialized(device);
this.props.onWebGLInitialized(gl);

// timeline for transitions
Expand Down Expand Up @@ -933,7 +943,8 @@ export default class Deck {
const viewport = this.viewManager.getViewports()[0];

// Note: avoid React setState due GL animation loop / setState timing issue
this.layerManager = new LayerManager(gl, {
this.layerManager = new LayerManager({
device,
deck: this,
stats: this.stats,
viewport,
Expand Down Expand Up @@ -967,25 +978,25 @@ export default class Deck {
clearCanvas?: boolean;
}
) {
const {gl} = this.layerManager.context;
const {device, gl} = this.layerManager?.context;

setParameters(gl, this.props.parameters);

this.props.onBeforeRender({gl});
this.props.onBeforeRender({device, gl});

this.deckRenderer.renderLayers({
this.deckRenderer?.renderLayers({
target: this.props._framebuffer,
layers: this.layerManager.getLayers(),
viewports: this.viewManager.getViewports(),
onViewportActive: this.layerManager.activateViewport,
views: this.viewManager.getViews(),
layers: this.layerManager?.getLayers(),
viewports: this.viewManager?.getViewports(),
onViewportActive: this.layerManager?.activateViewport,
views: this.viewManager?.getViews(),
pass: 'screen',
redrawReason,
effects: this.effectManager.getEffects(),
effects: this.effectManager?.getEffects(),
...renderOptions
});

this.props.onAfterRender({gl});
this.props.onAfterRender({device, gl});
}

// Callbacks
Expand Down
41 changes: 17 additions & 24 deletions modules/core/src/lib/layer-manager.ts
Expand Up @@ -20,7 +20,7 @@

import {Device} from '@luma.gl/api';
import {Timeline} from '@luma.gl/core';
import {WebGLDevice} from '@luma.gl/webgl';
import type {ProgramManager} from '@luma.gl/core';
import {LIFECYCLE} from '../lifecycle/constants';
import log from '../utils/log';
import debug from '../debug';
Expand All @@ -34,7 +34,6 @@ import {createProgramManager} from '../shaderlib';
import type Layer from './layer';
import type CompositeLayer from './composite-layer';
import type Deck from './deck';
import type {ProgramManager} from '@luma.gl/core';

const TRACE_SET_LAYERS = 'layerManager.setLayers';
const TRACE_ACTIVATE_VIEWPORT = 'layerManager.activateViewport';
Expand All @@ -44,18 +43,27 @@ export type LayerContext = {
resourceManager: ResourceManager;
deck?: Deck;
device: Device;
gl: WebGLRenderingContext;
pipelineFactory: ProgramManager;
stats: Stats;
viewport: Viewport;
timeline: Timeline;
mousePosition: {x: number; y: number} | null;
userData: any;
onError?: <PropsT>(error: Error, source: Layer<PropsT>) => void;
/** @deprecated Use context.device */
gl: WebGLRenderingContext;
};

export type LayersList = (Layer | undefined | false | null | LayersList)[];

export type LayerManagerProps = {
// Apparently LayerManager is supposed to be instantiatable without gl context?
device: Device | null;
deck?: Deck;
stats?: Stats;
viewport?: Viewport;
timeline?: Timeline;
};
export default class LayerManager {
layers: Layer[];
context: LayerContext;
Expand All @@ -68,20 +76,7 @@ export default class LayerManager {
private _debug: boolean = false;

// eslint-disable-next-line
constructor(
gl,
{
deck,
stats,
viewport,
timeline
}: {
deck?: Deck;
stats?: Stats;
viewport?: Viewport;
timeline?: Timeline;
} = {}
) {
constructor({device, deck, stats, viewport, timeline}: LayerManagerProps) {
// Currently deck.gl expects the DeckGL.layers array to be different
// whenever React rerenders. If the same layers array is used, the
// LayerManager's diffing algorithm will generate a fatal error and
Expand All @@ -92,20 +87,18 @@ export default class LayerManager {
// If it's the same across two React render calls, the diffing logic
// will be skipped.
this.layers = [];
this.resourceManager = new ResourceManager({gl, protocol: 'deck://'});

// Apparently LayerManager is supposed to be instantiatable without gl context?
const device = gl && WebGLDevice.attach(gl)!;
this.resourceManager = new ResourceManager({device, protocol: 'deck://'});

this.context = {
mousePosition: null,
userData: {},
layerManager: this,
device,
gl,
device: device!,
// @ts-expect-error
gl: device && device.gl,
deck,
// Enabling luma.gl Program caching using private API (_cachePrograms)
pipelineFactory: gl && createProgramManager(device),
pipelineFactory: (device && createProgramManager(device))!,
stats: stats || new Stats({id: 'deck.gl'}),
// Make sure context.viewport is not empty on the first layer initialization
viewport: viewport || new Viewport({id: 'DEFAULT-INITIAL-VIEWPORT'}), // Current viewport, exposed to layers for project* function
Expand Down
13 changes: 9 additions & 4 deletions modules/core/src/lib/resource/resource-manager.ts
@@ -1,10 +1,13 @@
/* global setTimeout */
import {Device} from '@luma.gl/api';
import Resource from './resource';
import type {ResourceSubscriber} from './resource';

export type ResourceManagerContext = {
gl: WebGLRenderingContext;
device: Device;
resourceManager: ResourceManager;
/** @deprecated */
gl: WebGLRenderingContext;
};

type Consumer = Record<string, ResourceSubscriber & {resourceId: string}>;
Expand All @@ -17,11 +20,13 @@ export default class ResourceManager {
private _consumers: Record<string, Consumer>;
private _pruneRequest: number | null;

constructor({gl, protocol}) {
this.protocol = protocol || 'resource://';
constructor(props: {device: Device; protocol?: string}) {
this.protocol = props.protocol || 'resource://';

this._context = {
gl,
device: props.device,
// @ts-expect-error
gl: props.device.gl,
resourceManager: this
};
this._resources = {};
Expand Down
4 changes: 2 additions & 2 deletions modules/core/src/passes/screen-pass.ts
Expand Up @@ -42,8 +42,8 @@ export default class ScreenPass extends Pass {
}

delete() {
this.model.delete();
this.model = null;
this.model.destroy();
this.model = null!;
}

// Private methods
Expand Down
4 changes: 2 additions & 2 deletions modules/test-utils/src/utils/setup-gl.js
@@ -1,4 +1,4 @@
import {createTestContext} from '@luma.gl/test-utils';
import {createTestContext, webgl1TestDevice} from '@luma.gl/test-utils';

globalThis.glContext =
globalThis.glContext ||
Expand All @@ -15,4 +15,4 @@ globalThis.glContext =

export default globalThis.glContext;

export const device = globalThis.glContext.device;
export const device = webgl1TestDevice;
6 changes: 3 additions & 3 deletions test/modules/core/effects/lighting-effect.spec.ts
Expand Up @@ -115,7 +115,7 @@ test('LightingEffect#shadow module', t => {
});

const lightingEffect = new LightingEffect({dirLight});
const pipelineManager = ProgramManager.getDefaultProgramManager(device);
const pipelineFactory = ProgramManager.getDefaultProgramManager(device);
lightingEffect.preRender(gl, {
layers: [],
viewports: [testViewport],
Expand All @@ -124,13 +124,13 @@ test('LightingEffect#shadow module', t => {
pixelRatio: 1
});
// @ts-expect-error private
let defaultModules = pipelineManager._defaultModules;
let defaultModules = pipelineFactory._defaultModules;
let hasShadow = defaultModules.some(m => m.name === 'shadow');
t.equal(hasShadow, true, 'LightingEffect adds shadow module to default correctly');

lightingEffect.cleanup();
// @ts-expect-error private
defaultModules = pipelineManager._defaultModules;
defaultModules = pipelineFactory._defaultModules;
hasShadow = defaultModules.some(m => m.name === 'shadow');
t.equal(hasShadow, false, 'LightingEffect removes shadow module to default correctly');
t.end();
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
12 changes: 6 additions & 6 deletions test/modules/core/lib/resource/resource-manager.spec.js
@@ -1,22 +1,22 @@
/* global setTimeout */
/* deviceobal setTimeout */
import test from 'tape-promise/tape';
import {gl} from '@deck.gl/test-utils';
import {device} from '@deck/test-utils';
import ResourceManager from '@deck.gl/core/lib/resource/resource-manager';

test('ResourceManager#protocol', t => {
let dataManager = new ResourceManager({gl, onError: t.notOk});
let dataManager = new ResourceManager({device, onError: t.notOk});
t.ok(dataManager.contains('resource://data-01'), 'checks protocol');
t.notOk(dataManager.contains('deck://data-01'), 'checks protocol');

dataManager = new ResourceManager({gl, protocol: 'deck://', onError: t.notOk});
dataManager = new ResourceManager({device, protocol: 'deck://', onError: t.notOk});
t.notOk(dataManager.contains('resource://data-01'), 'checks protocol');
t.ok(dataManager.contains('deck://data-01'), 'checks protocol');

t.end();
});

test('ResourceManager#add,remove', t => {
const dataManager = new ResourceManager({gl, onError: t.notOk});
const dataManager = new ResourceManager({device, onError: t.notOk});

t.notOk(dataManager.contains('data-01'), 'does not contain resource');

Expand All @@ -41,7 +41,7 @@ test('ResourceManager#add,remove', t => {

// eslint-disable-next-line
test('ResourceManager#subscribe, unsubscribe', t => {
const dataManager = new ResourceManager({gl, onError: t.notOk});
const dataManager = new ResourceManager({device, onError: t.notOk});
let propA1Changed = 0;
let propA2Changed = 0;
let propBChanged = 0;
Expand Down

0 comments on commit 6ba603c

Please sign in to comment.