Skip to content

Commit

Permalink
fix(engine) Workaround for deck.gl attribute access (#1778)
Browse files Browse the repository at this point in the history
  • Loading branch information
ibgreen committed Aug 12, 2023
1 parent 1db7296 commit 3af6827
Show file tree
Hide file tree
Showing 5 changed files with 297 additions and 43 deletions.
3 changes: 3 additions & 0 deletions modules/api/src/adapter/resources/render-pipeline.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// luma.gl, MIT license
import type {Device} from '../device';
import type {TypedArray} from '../../types';
import type {PrimitiveTopology, RenderPipelineParameters} from '../types/parameters';
import type {ShaderLayout, BufferMapping, Binding} from '../types/shader-layout';
// import {normalizeAttributeMap} from '../helpers/attribute-bindings';
Expand Down Expand Up @@ -104,6 +105,8 @@ export abstract class RenderPipeline extends Resource<RenderPipelineProps> {
abstract setIndexBuffer(indices: Buffer): void;
/** Set attributes (stored on pipeline and set before each call) */
abstract setAttributes(attributes: Record<string, Buffer>): void;
/** Set constant attributes (WebGL only) */
abstract setConstantAttributes(attributes: Record<string, TypedArray>): void;
/** Set bindings (stored on pipeline and set before each call) */
abstract setBindings(bindings: Record<string, Binding>): void;
/** Uniforms (only supported on WebGL devices. Reset before each call to enable pipeline sharing) */
Expand Down
87 changes: 73 additions & 14 deletions modules/engine/src/model/model.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,19 @@
// luma.gl, MIT license

import type {Device, Buffer, RenderPipelineProps, RenderPass, Binding, PrimitiveTopology} from '@luma.gl/api';
import {
Device,
Buffer,
RenderPipelineProps,
RenderPass,
Binding,
PrimitiveTopology
} from '@luma.gl/api';
import {RenderPipeline} from '@luma.gl/api';
import type { ShaderModule } from '@luma.gl/shadertools';
import type {ShaderModule} from '@luma.gl/shadertools';
import type {Geometry} from '../geometry/geometry';
import {getAttributeBuffersFromGeometry, getIndexBufferFromGeometry} from './model-utils';
import {PipelineFactory} from '../lib/pipeline-factory';
import {TypedArray} from '@math.gl/core';

export type ModelProps = Omit<RenderPipelineProps, 'vs' | 'fs'> & {
// Model also accepts a string
Expand Down Expand Up @@ -57,7 +65,7 @@ export class Model {
this.device = device;

Object.assign(this.userData, this.props.userData);

// Create the pipeline
if (!props.vs) {
throw new Error('no vertex shader');
Expand All @@ -75,7 +83,8 @@ export class Model {
this.topology = this.props.geometry.topology || 'triangle-list';
}

this.pipelineFactory = this.props.pipelineFactory || PipelineFactory.getDefaultPipelineFactory(this.device);
this.pipelineFactory =
this.props.pipelineFactory || PipelineFactory.getDefaultPipelineFactory(this.device);
const {pipeline, getUniforms} = this.pipelineFactory.createRenderPipeline({
...this.props,
vs: this.vs,
Expand All @@ -92,7 +101,7 @@ export class Model {
if (this.props.geometry) {
this._setGeometry(this.props.geometry);
}
this.setUniforms(this._getModuleUniforms()) // Get all default module uniforms
this.setUniforms(this._getModuleUniforms()); // Get all default module uniforms
this.setProps(this.props);
}

Expand Down Expand Up @@ -140,17 +149,67 @@ export class Model {
return this;
}

setAttributes(attributes: Record<string, Buffer>): this {
// Temporary hack to support deck.gl's dependency on luma.gl v8 Model attribute API.
_splitAttributes(
attributes: Record<string, Buffer | TypedArray>,
filterBuffers?: boolean
): {
bufferAttributes: Record<string, Buffer>;
constantAttributes: Record<string, TypedArray>;
indices?: Buffer;
} {
const bufferAttributes: Record<string, Buffer> = {};
const constantAttributes: Record<string, TypedArray> = {};
const indices: Buffer | undefined = attributes.indices as Buffer;

delete attributes.indices;

for (const name in attributes) {
let attribute = attributes[name];

if (attribute instanceof Buffer) {
bufferAttributes[name] = attribute;
continue;

Check warning on line 172 in modules/engine/src/model/model.ts

View workflow job for this annotation

GitHub Actions / test (16)

Unexpected use of continue statement
}

// The `getValue` call provides support for deck.gl `Attribute` class
// TODO - remove once deck refactoring completes
// @ts-ignore
if (attribute.getValue) {
// @ts-ignore
attribute = attribute.getValue();
console.warn(`attribute ${name}: getValue() will be removed`);

Check warning on line 181 in modules/engine/src/model/model.ts

View workflow job for this annotation

GitHub Actions / test (16)

Unexpected console statement
}

if (ArrayBuffer.isView(attribute) && !attribute) {
constantAttributes[name] = attribute as unknown as TypedArray;
continue;

Check warning on line 186 in modules/engine/src/model/model.ts

View workflow job for this annotation

GitHub Actions / test (16)

Unexpected use of continue statement
}

// @ts-ignore
if (filterBuffers && attribute[name]._buffer) {
// @ts-ignore
buffer[name] = attribute[name]._buffer;

Check warning on line 192 in modules/engine/src/model/model.ts

View workflow job for this annotation

GitHub Actions / test (16)

'buffer' is not defined
}
}

return {bufferAttributes, constantAttributes, indices};
}

setAttributes(attributes: Record<string, Buffer | TypedArray>, filterBuffers?: boolean): void {
const {bufferAttributes, constantAttributes, indices} = this._splitAttributes(attributes, filterBuffers);

// Temporary HACK since deck.gl v9 sets indices as part of attributes
if (attributes.indices) {
this.setIndexBuffer(attributes.indices);
attributes = {...attributes};
delete attributes.indices;
console.warn('luma.gl: indices should not be part of attributes')
if (indices) {
this.setIndexBuffer(indices);
console.warn('luma.gl: indices should not be part of attributes');

Check warning on line 205 in modules/engine/src/model/model.ts

View workflow job for this annotation

GitHub Actions / test (16)

Unexpected console statement
}
this.pipeline.setAttributes(attributes);
Object.assign(this.props.attributes, attributes);
return this;

this.pipeline.setAttributes(bufferAttributes);
// TODO - WebGL only. We may have to allocate buffers on WebGPU
this.pipeline.setConstantAttributes(constantAttributes);

Object.assign(this.props.attributes, bufferAttributes, constantAttributes);
}

/** Set the bindings */
Expand Down
Loading

0 comments on commit 3af6827

Please sign in to comment.