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

For discussion: remove withParametersWebGL #8731

Draft
wants to merge 4 commits into
base: master
Choose a base branch
from
Draft
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
1 change: 1 addition & 0 deletions examples/website/geojson/app.jsx
Expand Up @@ -94,6 +94,7 @@ export default function App({data = DATA_URL, mapStyle = MAP_STYLE}) {
new GeoJsonLayer({
id: 'geojson',
data,
autoHighlight: true,
opacity: 0.8,
stroked: false,
filled: true,
Expand Down
2 changes: 1 addition & 1 deletion modules/core/src/index.ts
Expand Up @@ -135,7 +135,7 @@ export type {
TextureSource,
Material
} from './types/layer-props';
export type {FilterContext} from './passes/layers-pass';
export type {FilterContext, LayerParameters} from './passes/layers-pass';
export type {PickingInfo, GetPickingInfoParams} from './lib/picking/pick-info';
export type {ConstructorOf as _ConstructorOf} from './types/types';
export type {BinaryAttribute} from './lib/attribute/attribute';
Expand Down
13 changes: 6 additions & 7 deletions modules/core/src/lib/deck-picker.ts
Expand Up @@ -145,16 +145,15 @@ export default class DeckPicker {
_resizeBuffer() {
// Create a frame buffer if not already available
if (!this.pickingFBO) {
this.pickingFBO = this.device.createFramebuffer({colorAttachments: ['rgba8unorm']});
this.pickingFBO = this.device.createFramebuffer({
colorAttachments: ['rgba8unorm'],
depthStencilAttachment: 'depth16unorm'
});

if (this.device.isTextureFormatRenderable('rgba32float')) {
const depthFBO = this.device.createFramebuffer({
colorAttachments: [
this.device.createTexture({
format: 'rgba32float'
// type: GL.FLOAT
})
]
colorAttachments: ['rgba32float'],
depthStencilAttachment: 'depth16unorm'
});
this.depthFBO = depthFBO;
}
Expand Down
13 changes: 2 additions & 11 deletions modules/core/src/lib/deck.ts
Expand Up @@ -35,8 +35,7 @@ import {luma} from '@luma.gl/core';
import {WebGLDevice} from '@luma.gl/webgl';
import {Timeline} from '@luma.gl/engine';
import {AnimationLoop} from '@luma.gl/engine';
import {GL} from '@luma.gl/constants';
import type {Device, DeviceProps, Framebuffer} from '@luma.gl/core';
import type {Device, DeviceProps, Framebuffer, Parameters} from '@luma.gl/core';
import type {ShaderModule} from '@luma.gl/shadertools';

import {Stats} from '@probe.gl/stats';
Expand Down Expand Up @@ -114,7 +113,7 @@ export type DeckProps<ViewsT extends ViewOrViews = ViewOrViews> = {
pickingRadius?: number;

/** WebGL parameters to be set before each frame is rendered. */
parameters?: any;
parameters?: Parameters;
/** If supplied, will be called before a layer is drawn to determine whether it should be rendered. */
layerFilter?: ((context: FilterContext) => boolean) | null;

Expand Down Expand Up @@ -946,14 +945,6 @@ export default class Deck<ViewsT extends ViewOrViews = ViewOrViews> {
// instrumentGLContext(this.device.gl, {enable: true, copyState: true});
}

this.device.setParametersWebGL({
blend: true,
blendFunc: [GL.SRC_ALPHA, GL.ONE_MINUS_SRC_ALPHA, GL.ONE, GL.ONE_MINUS_SRC_ALPHA],
polygonOffsetFill: true,
depthTest: true,
depthFunc: GL.LEQUAL
});

this.props.onDeviceInitialized(this.device);
if (this.device instanceof WebGLDevice) {
// Legacy callback - warn?
Expand Down
25 changes: 8 additions & 17 deletions modules/core/src/lib/layer.ts
Expand Up @@ -52,7 +52,7 @@ import type {DefaultProps} from '../lifecycle/prop-types';
import type {LayerData, LayerProps} from '../types/layer-props';
import type {LayerContext} from './layer-manager';
import type {BinaryAttribute} from './attribute/attribute';
import {RenderPass} from '@luma.gl/core';
import type {RenderPass, Parameters as DeviceParameters} from '@luma.gl/core';
import {PickingProps} from '@luma.gl/shadertools';

const TRACE_CHANGE_FLAG = 'layer.changeFlag';
Expand Down Expand Up @@ -1046,7 +1046,7 @@ export default abstract class Layer<PropsT extends {} = {}> extends Component<
renderPass: RenderPass;
moduleParameters: any;
uniforms: any;
parameters: any;
parameters: DeviceParameters;
}): void {
this._updateAttributeTransition();

Expand All @@ -1069,28 +1069,19 @@ export default abstract class Layer<PropsT extends {} = {}> extends Component<
this.setShaderModuleProps({picking: {isActive, isAttribute}});
}

// Apply polygon offset to avoid z-fighting
// TODO - move to draw-layers
const {getPolygonOffset} = this.props;
const offsets = (getPolygonOffset && getPolygonOffset(uniforms)) || [0, 0];

context.device.setParametersWebGL({polygonOffset: offsets});

for (const model of this.getModels()) {
model.setParameters(parameters);
}

// Call subclass lifecycle method
context.device.withParametersWebGL(parameters, () => {
const opts = {renderPass, moduleParameters, uniforms, parameters, context};
const opts = {renderPass, moduleParameters, uniforms, parameters, context};

// extensions
for (const extension of this.props.extensions) {
extension.draw.call(this, opts, extension);
}
// extensions
for (const extension of this.props.extensions) {
extension.draw.call(this, opts, extension);
}

this.draw(opts);
});
this.draw(opts);
} finally {
this.props = currentProps;
}
Expand Down
59 changes: 35 additions & 24 deletions modules/core/src/passes/layers-pass.ts
@@ -1,4 +1,4 @@
import type {Device, RenderPassParameters} from '@luma.gl/core';
import type {Device, RenderPassParameters, Parameters} from '@luma.gl/core';
import type {Framebuffer, RenderPass} from '@luma.gl/core';

import Pass from './pass';
Expand All @@ -9,6 +9,8 @@ import type {Effect} from '../lib/effect';

export type Rect = {x: number; y: number; width: number; height: number};

export type LayerParameters = Parameters & RenderPassParameters;

export type LayersPassRenderOptions = {
/** @deprecated TODO v9 recommend we rename this to framebuffer to minimize confusion */
target?: Framebuffer | null;
Expand Down Expand Up @@ -36,7 +38,7 @@ type DrawLayerParameters = {
shouldDrawLayer: boolean;
layerRenderIndex?: number;
moduleParameters?: any;
layerParameters?: any;
layerParameters?: LayerParameters;
};

export type FilterContext = {
Expand All @@ -54,6 +56,14 @@ export type RenderStats = {
pickableCount: number;
};

const DEFAULT_PARAMETERS: LayerParameters = {
blendColorSrcFactor: 'src-alpha',
blendColorDstFactor: 'one-minus-src-alpha',
blendAlphaSrcFactor: 'one',
blendAlphaDstFactor: 'one-minus-src-alpha',
depthCompare: 'less-equal'
};

/** A Pass that renders all layers */
export default class LayersPass extends Pass {
_lastRenderIndex: number = -1;
Expand All @@ -72,9 +82,6 @@ export default class LayersPass extends Pass {
if (options.colorMask) {
parameters.colorMask = colorMask;
}
if (options.scissorRect) {
parameters.scissorRect = options.scissorRect;
}

const renderPass = this.device.beginRenderPass({
framebuffer: options.target,
Expand Down Expand Up @@ -125,6 +132,7 @@ export default class LayersPass extends Pass {
target,
moduleParameters,
viewport: subViewport,
scissorRect: options.scissorRect,
view,
pass: options.pass,
layers: options.layers
Expand Down Expand Up @@ -191,7 +199,9 @@ export default class LayersPass extends Pass {
moduleParameters
);
layerParam.layerParameters = {
...DEFAULT_PARAMETERS,
...layer.context.deck?.props.parameters,
...layer.props.parameters,
...this.getLayerParameters(layer, layerIndex, viewport)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just an idea: would it be useful if props.parameters could also accept a function to allow the application to control the final parameters? By passing in the Pass the Layer could have more control:

new Layer({
  ...,
  parameters: (pass: Pass, parameters: Parameters): Parameters {...}

})

};
}
Expand All @@ -206,27 +216,15 @@ export default class LayersPass extends Pass {
/* eslint-disable max-depth, max-statements */
private _drawLayersInViewport(
renderPass: RenderPass,
{layers, moduleParameters: globalModuleParameters, pass, target, viewport, view},
drawLayerParams
{layers, moduleParameters: globalModuleParameters, pass, target, viewport, view, scissorRect},
drawLayerParams: DrawLayerParameters[]
): RenderStats {
const glViewport = getGLViewport(this.device, {
moduleParameters: globalModuleParameters,
target,
viewport
});

// TODO v9 - remove WebGL specific logic
if (view && view.props.clear) {
const clearOpts = view.props.clear === true ? {color: true, depth: true} : view.props.clear;
this.device.withParametersWebGL(
{
scissorTest: true,
scissor: glViewport
},
() => this.device.clearWebGL(clearOpts)
);
}

// render layers in normal colors
const renderStatus = {
totalCount: layers.length,
Expand All @@ -235,7 +233,11 @@ export default class LayersPass extends Pass {
pickableCount: 0
};

renderPass.setParameters({viewport: glViewport});
renderPass.setParameters({viewport: glViewport, scissorRect: scissorRect || glViewport});
if (view?.props.clear) {
// @ts-expect-error WEBGLRenderPass protected method
renderPass.clear?.();
}

// render layers in normal colors
for (let layerIndex = 0; layerIndex < layers.length; layerIndex++) {
Expand All @@ -252,8 +254,10 @@ export default class LayersPass extends Pass {
} else if (shouldDrawLayer) {
// Draw the layer
renderStatus.visibleCount++;
// layerParameters and layerRenderIndex are always present in this context
renderPass.setParameters(layerParameters!);

this._lastRenderIndex = Math.max(this._lastRenderIndex, layerRenderIndex);
this._lastRenderIndex = Math.max(this._lastRenderIndex, layerRenderIndex!);

// overwrite layer.context.viewport with the sub viewport
moduleParameters.viewport = viewport;
Expand All @@ -268,7 +272,7 @@ export default class LayersPass extends Pass {
renderPass,
moduleParameters,
uniforms: {layerIndex: layerRenderIndex},
parameters: layerParameters
parameters: layerParameters!
});
} catch (err) {
layer.raiseError(err as Error, `drawing ${layer} to ${pass}`);
Expand All @@ -289,8 +293,15 @@ export default class LayersPass extends Pass {
return null;
}

protected getLayerParameters(layer: Layer, layerIndex: number, viewport: Viewport): any {
return layer.props.parameters;
protected getLayerParameters(
layer: Layer,
layerIndex: number,
viewport: Viewport
): LayerParameters {
const {getPolygonOffset} = layer.props;
const offsets = (getPolygonOffset && getPolygonOffset({layerIndex})) || [0, 0];
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if we should have deprecated getPolygonOffset in v9. It is strange that it is called and accessor in the docs, but is in fact a roundabout way of setting GPU parameters.

Is there any reason to keep the function? I think it would be clearer to pass depthBias(SlopeScale) in props.parameters. In addition if depthBias is passed in props.parameters it will be overwritten even if getPolygonOffset isn't specified.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I certainly agree that it should not be called an "accessor" if that is really the case, as accessors operate on data rows and this function operates on a layer.

We can still deprecate a function at any time. But I believe the functionality of being able to adjust depth bias based on layer index is needed to address Z fighting so we can't just drop it, we need to have a replacement for this function.


return {depthBias: offsets[0], depthBiasSlopeScale: offsets[1]};
}

/* Private */
Expand Down
37 changes: 16 additions & 21 deletions modules/core/src/passes/pick-layers-pass.ts
@@ -1,4 +1,9 @@
import LayersPass, {LayersPassRenderOptions, RenderStats, Rect} from './layers-pass';
import LayersPass, {
LayersPassRenderOptions,
LayerParameters,
RenderStats,
Rect
} from './layers-pass';
import type {Framebuffer, RenderPipelineParameters} from '@luma.gl/core';
import log from '../utils/log';

Expand Down Expand Up @@ -123,29 +128,19 @@
};
}

protected getLayerParameters(layer: Layer, layerIndex: number, viewport: Viewport): any {
const pickParameters = {
// TODO - When used as a custom layer in older Mapbox versions, context
// state was dirty. Mapbox fixed that; we should test and remove the workaround.
// https://github.com/mapbox/mapbox-gl-js/issues/7801
depthMask: true,
depthTest: true,
depthRange: [0, 1],
...layer.props.parameters,
// Blending
...PICKING_BLENDING,
blend: !this.pickZ
};
protected getLayerParameters(
layer: Layer,
layerIndex: number,
viewport: Viewport
): LayerParameters {
const pickParameters: LayerParameters = super.getLayerParameters(layer, layerIndex, viewport);
const {pickable, operation} = layer.props;

if (!this._colorEncoderState) {
pickParameters.blend = false;
if (!this._colorEncoderState || operation.includes('terrain')) {
pickParameters.blendColorOperation = 'none';

Check failure on line 140 in modules/core/src/passes/pick-layers-pass.ts

View workflow job for this annotation

GitHub Actions / test-python (3.8)

Type '"none"' is not assignable to type 'BlendOperation | undefined'.

Check failure on line 140 in modules/core/src/passes/pick-layers-pass.ts

View workflow job for this annotation

GitHub Actions / test-node

Type '"none"' is not assignable to type 'BlendOperation | undefined'.
} else if (pickable && operation.includes('draw')) {
pickParameters.blend = true;
pickParameters.blendColor = encodeColor(this._colorEncoderState, layer, viewport);
}
if (operation.includes('terrain')) {
pickParameters.blend = false;
Object.assign(pickParameters, PICKING_BLENDING);
pickParameters.blendConstant = encodeColor(this._colorEncoderState, layer, viewport);
}

return pickParameters;
Expand Down
14 changes: 11 additions & 3 deletions modules/core/src/passes/shadow-pass.ts
@@ -1,7 +1,7 @@
import type {Device, Framebuffer, Texture} from '@luma.gl/core';
import type Layer from '../lib/layer';
import type Viewport from '../viewports/viewport';
import LayersPass from './layers-pass';
import LayersPass, {LayerParameters} from './layers-pass';

export default class ShadowPass extends LayersPass {
shadowMap: Texture;
Expand Down Expand Up @@ -67,8 +67,16 @@
super.render({...params, clearColor, target, pass: 'shadow'});
}

protected getLayerParameters(layer: Layer<{}>, layerIndex: number, viewport: Viewport) {
return {...layer.props.parameters, blend: false, depthRange: [0, 1], depthTest: true};
protected getLayerParameters(
layer: Layer<{}>,
layerIndex: number,
viewport: Viewport
): LayerParameters {
return {
...super.getLayerParameters(layer, layerIndex, viewport),
blendColorOperation: 'none',

Check failure on line 77 in modules/core/src/passes/shadow-pass.ts

View workflow job for this annotation

GitHub Actions / test-python (3.8)

Type '"none"' is not assignable to type 'BlendOperation | undefined'.

Check failure on line 77 in modules/core/src/passes/shadow-pass.ts

View workflow job for this annotation

GitHub Actions / test-node

Type '"none"' is not assignable to type 'BlendOperation | undefined'.
depthCompare: 'less-equal'
};
}

shouldDrawLayer(layer) {
Expand Down
4 changes: 2 additions & 2 deletions modules/core/src/types/layer-props.ts
Expand Up @@ -6,7 +6,7 @@ import type {ConstructorOf, NumericArray, TypedArray} from './types';
import type {PickingInfo} from '../lib/picking/pick-info';
import type {MjolnirEvent} from 'mjolnir.js';

import type {Texture, TextureProps} from '@luma.gl/core';
import type {Texture, TextureProps, Parameters} from '@luma.gl/core';
import type {Buffer} from '@luma.gl/core';
import type {Loader} from '@loaders.gl/loader-utils';
import type {LightingModuleSettings} from '../shaderlib/index';
Expand Down Expand Up @@ -185,7 +185,7 @@ export type LayerProps = {
/**
* Override the WebGL parameters used to draw this layer. See https://luma.gl/modules/gltools/docs/api-reference/parameter-setting#parameters
*/
parameters?: any;
parameters?: Parameters;
/**
* Create smooth transitions when prop values update.
*/
Expand Down