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

feat(engine): Model.props.ignoreUnknownAttributes #1963

Merged
merged 2 commits into from
Feb 26, 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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 35 additions & 42 deletions docs/api-reference/engine/model.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
# Model

The `Model` class is the centerpiece of the luma.gl API. It brings together all the different functionality needed to run shaders and perform draw calls in a single, easy-to-use interface.
The `Model` class is the centerpiece of the luma.gl API. It brings together all GPU functionality needed to run shaders and perform draw calls, in a single, easy-to-use interface.

`Model` manages the following responsibilities:
- **render pipeline creation** -
- **attributes**
- **bindings** these can reference textures and uniform buffers
Expand All @@ -10,9 +11,9 @@ The `Model` class is the centerpiece of the luma.gl API. It brings together all
- **shader transpilation****
- **debugging** - Detailed debug logging of draw calls

The `Model` class integrates with the `@luma.gl/shadertools` shader module system: [see `Shader Assembly`]( /docs/api-reference/shadertools/shader-assembler).

(Accepts a [`Mesh`] or a [`Geometry`](/docs/- - api-reference/engine/geometry) instance, plus any additional attributes for instanced rendering)
The `Model` class integrates with
- The `@luma.gl/shadertools` shader module system: [see `Shader Assembly`]( /docs/api-reference/shadertools/shader-assembler).
- The `Geometry` classes - accepts a [`Mesh`] or a [`Geometry`](/docs/modules/engine/api-reference/geometry) instance, plus any additional attributes for instanced rendering)

## Usage

Expand All @@ -36,6 +37,7 @@ const model = new Model(device, {
},
})
```

### Provide attribute data using Buffer

When using `Buffer` objects, data remains on GPU and same `Buffer` object can be shared between multiple models.
Expand Down Expand Up @@ -77,19 +79,21 @@ const model = new Model(device, {

## Types

### ModelProps
### `ModelProps`

| Property | Type | Description |
| ------------------ | ---------------------------------------------- | ----------------------------------------------------------------------------------- |
| `vs` | `Shader` \| _string_ | A vertex shader object, or source as a string. |
| `fs` | `Shader` \| _string_ | A fragment shader object, or source as a string. |
| `modules` | | shader modules to be applied (shadertools). |
| `pipelineFactory?` | | `PipelineFactory` to use for program creation and caching. |
| `varyings?` | `string[]` | WebGL 2: Array of vertex shader output variables (used in TransformFeedback flow). |
| `bufferMode` | | WebGL 2: Mode for recording vertex shader outputs (used in TransformFeedback flow). |
| `debugShaders?` | `'error' \| 'never' \| 'warnings' \| 'always'` | Specify in what triggers the display shader compilation log (default: `'error'`). |
| Property | Type | Description |
| ------------------ | ---------------------------------------------- | --------------------------------------------------------------------------------- |
| `vs` | `Shader` \| _string_ | A vertex shader object, or source as a string. |
| `fs` | `Shader` \| _string_ | A fragment shader object, or source as a string. |
| `modules` | | shader modules to be applied (shadertools). |
| `pipelineFactory?` | | `PipelineFactory` to use for program creation and caching. |
| `debugShaders?` | `'error' \| 'never' \| 'warnings' \| 'always'` | Specify in what triggers the display shader compilation log (default: `'error'`). |
| `onBeforeRender?` | `Function` | function to be called before every time this model is drawn. |
| `onAfterRender?` | `Function` | function to be called after every time this model is drawn. |
| `varyings?` | `string[]` | WebGL: Array of vertex shader output variables (used in TransformFeedback flow). |
| `bufferMode?` | | WebGL: Mode for recording vertex shader outputs (used in TransformFeedback flow). |

`ModelProps` passes through `RenderPipelineProps`
`ModelProps` also include `RenderPipelineProps`, which are passed through to the `RenderPipeline` constructor, e.g:

| Property | Type | Description |
| ----------------- | -------------------------- | --------------------------------------------------------------------------------------- |
Expand All @@ -103,19 +107,12 @@ const model = new Model(device, {
| `bindings?` | `Record<string, any>` | |
| `buffers?` | `Record<string, Buffer>` | |

## Properties

### renderPipeline: RenderPipeline

Get model's `RenderPipeline` instance

### onBeforeRender

function to be called before every time this model is drawn.
## Fields

### onAfterRender
### `renderPipeline: RenderPipeline`

function to be called after every time this model is drawn.
The model's `RenderPipeline` instance

### instanceCount: number

Expand All @@ -127,15 +124,15 @@ when not provided will be deduced from `geometry` object.

## Methods

### constructor(device: Device, props: ModelProps)
### `constructor(device: Device, props: ModelProps)`

The constructor for the Model class. Use this to create a new Model.

### destroy(): void
### `destroy(): void`

Free GPU resources associated with this model immediately, instead of waiting for garbage collection.

### draw(options: DrawOptions): boolean
### `draw(options: DrawOptions): boolean`

Renders the model with provided uniforms, attributes and samplers

Expand Down Expand Up @@ -169,31 +166,27 @@ The remaining draw options are passed directly to `Program.draw()`:
- `transformFeedback` - an instance `TranformFeedback` object, that gets activated for this rendering.
- `vertexArray` - an instance of `VertexArray` object, that holds required buffer bindings for vertex shader inputs.


### setVertexCount(); this
### `setVertexCount(): void`

Sets the number of vertices

### setInstanceCount(); this
### `setInstanceCount(); void`

How many instances will be rendered

### setGeometry(); this
### `setGeometry(); void`

Use a `Geometry` instance to define attribute buffers

### setAttributes(attributes: object); this

Sets map of attributes (passes through to [VertexArray.setAttributes](/docs/api-reference/core/resources/vertex-array))

### setUniforms(uniforms: object): void

Stores named uniforms key, value
### `setAttributes(attributes: object, options?): void`

Sets map of attributes (via [VertexArray.setAttributes](/docs/api-reference/core/resources/vertex-array))

### updateModuleSettings(moduleSettings: object): void
- `attributes` (Object) - map of attribute names to values.
- `options.ignoreMissingAttributes` (boolean) - if `true`, allows the function to silently ignore missing attributes.

### `setUniforms(uniforms: object): void` (Deprecated)

## Remarks
Global uniforms key, value. Only works on WebGL, for portable code, use uniform buffers and `model.setBindings()` instead.

- The `Model` class is arguably the most useful class for typical applications. It manages the WebGL resources needed to perform draw calls and provide additional functionality as described below.
### `updateModuleSettings(moduleSettings: object): void` (Deprecated)
18 changes: 10 additions & 8 deletions modules/engine/src/model/model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@ export type ModelProps = Omit<RenderPipelineProps, 'vs' | 'fs'> & {
attributes?: Record<string, Buffer>;
/** */
constantAttributes?: Record<string, TypedArray>;
/** Some applications intentionally supply unused attributes */
ignoreUnknownAttributes?: boolean;

/** @internal For use with {@link TransformFeedback}, WebGL only. */
varyings?: string[];
Expand Down Expand Up @@ -113,7 +115,8 @@ export class Model {
transformFeedback: undefined,
shaderAssembler: ShaderAssembler.getDefaultShaderAssembler(),

debugShaders: undefined
debugShaders: undefined,
ignoreUnknownAttributes: undefined
};

readonly device: Device;
Expand Down Expand Up @@ -237,8 +240,7 @@ export class Model {

this.pipelineFactory =
props.pipelineFactory || PipelineFactory.getDefaultPipelineFactory(this.device);
this.shaderFactory =
props.shaderFactory || ShaderFactory.getDefaultShaderFactory(this.device);
this.shaderFactory = props.shaderFactory || ShaderFactory.getDefaultShaderFactory(this.device);

// Create the pipeline
// @note order is important
Expand Down Expand Up @@ -268,7 +270,7 @@ export class Model {
this.setIndexBuffer(props.indexBuffer);
}
if (props.attributes) {
this.setAttributes(props.attributes);
this.setAttributes(props.attributes, {ignoreUnknownAttributes: props.ignoreUnknownAttributes});
}
if (props.constantAttributes) {
this.setConstantAttributes(props.constantAttributes);
Expand Down Expand Up @@ -376,8 +378,8 @@ export class Model {
// TODO - delete previous geometry?
this.vertexCount = gpuGeometry.vertexCount;
this.setIndexBuffer(gpuGeometry.indices);
this.setAttributes(gpuGeometry.attributes, 'ignore-unknown');
this.setAttributes(attributes);
this.setAttributes(gpuGeometry.attributes, {ignoreUnknownAttributes: true});
this.setAttributes(attributes, {ignoreUnknownAttributes: this.props.ignoreUnknownAttributes});
}

/**
Expand Down Expand Up @@ -526,7 +528,7 @@ export class Model {
* Sets attributes (buffers)
* @note Overrides any attributes previously set with the same name
*/
setAttributes(buffers: Record<string, Buffer>, _option?: 'ignore-unknown'): void {
setAttributes(buffers: Record<string, Buffer>, options?: {ignoreUnknownAttributes?: boolean}): void {
if (buffers.indices) {
log.warn(
`Model:${this.id} setAttributes() - indexBuffer should be set using setIndexBuffer()`
Expand All @@ -551,7 +553,7 @@ export class Model {
set = true;
}
}
if (!set && _option !== 'ignore-unknown') {
if (!set && (options?.ignoreUnknownAttributes || this.props.ignoreUnknownAttributes)) {
log.warn(
`Model(${this.id}): Ignoring buffer "${buffer.id}" for unknown attribute "${bufferName}"`
)();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ export const ENUM_STYLE_SETTINGS_SET2: GLParameters = {
// [GL.FRAGMENT_SHADER_DERIVATIVE_HINT]: GL.NICEST,
// [GL.RASTERIZER_DISCARD]: false,

// WEBGL1 PIXEL PACK/UNPACK MODES
// PIXEL PACK/UNPACK MODES
[GL.PACK_ALIGNMENT]: 2,
[GL.UNPACK_ALIGNMENT]: 2,
[GL.UNPACK_FLIP_Y_WEBGL]: false,
Expand Down
38 changes: 18 additions & 20 deletions modules/webgpu/src/adapter/resources/webgpu-render-pipeline.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,26 +62,24 @@ export class WebGPURenderPipeline extends RenderPipeline {
// this._indexBuffer = cast<WebGPUBuffer>(indexBuffer);
// }

/*
setAttributes(attributes: Record<string, Buffer>): void {
for (const [name, buffer] of Object.entries(attributes)) {
const bufferIndex = this._bufferSlots[name];
if (bufferIndex >= 0) {
this._buffers[bufferIndex] = buffer;
} else {
throw new Error(
`Setting attribute '${name}' not listed in shader layout for program ${this.id}`
);
}
}
// for (let i = 0; i < this._bufferSlots.length; ++i) {
// const bufferName = this._bufferSlots[i];
// if (attributes[bufferName]) {
// this.handle
// }
// }
}
*/
// setAttributes(attributes: Record<string, Buffer>): void {
// for (const [name, buffer] of Object.entries(attributes)) {
// const bufferIndex = this._bufferSlots[name];
// if (bufferIndex >= 0) {
// this._buffers[bufferIndex] = buffer;
// } else {
// throw new Error(
// `Setting attribute '${name}' not listed in shader layout for program ${this.id}`
// );
// }
// }
// // for (let i = 0; i < this._bufferSlots.length; ++i) {
// // const bufferName = this._bufferSlots[i];
// // if (attributes[bufferName]) {
// // this.handle
// // }
// // }
// }

setBindings(bindings: Record<string, Binding>): void {
// if (isObjectEmpty(bindings)) {
Expand Down
Loading