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

chore(core) new device props api #2100

Merged
merged 24 commits into from
Aug 14, 2024
Merged

chore(core) new device props api #2100

merged 24 commits into from
Aug 14, 2024

Conversation

chrisgervang
Copy link
Contributor

@chrisgervang chrisgervang commented Jun 13, 2024

For visgl/deck.gl#8945

Background

DeviceProps API Changes:

For both devices,

  • Nest device specific props.
  • Allow setting more default canvas context props when creating a device.

For webgl,

  • remove onContextLost. Use device.lost instead.
  • remove onContextRestore. Luma 9 doesn't support restoring context.

For WebGPU,

  • Allow setting more default canvas context props when creating a WebGPU device.

Taking a stab at documenting device props per device and type hinting CreateDeviceProps. Feel free to make corrections or clarifications around the intent behind some of these props, when I was unsure I went off of how the current implementation is written (even though knowing it may be incomplete)

I think deck should use CreateDeviceProps, so I've exported that as well.

Change List

  • types
  • docs

Signed-off-by: Chris Gervang <chris@gervang.com>
Signed-off-by: Chris Gervang <chris@gervang.com>
};

export type WebGPUDeviceProps = _DeviceProps & {
/** Request a Device with the highest limits supported by platform. WebGPU: devices can be created with minimal limits. */
requestMaxLimits?: boolean;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is intended to be WebGPU only? It isn't used by WebGL

modules/core/src/adapter/device.ts Outdated Show resolved Hide resolved
modules/core/src/adapter/luma.ts Show resolved Hide resolved
modules/core/src/adapter/device.ts Outdated Show resolved Hide resolved
Copy link
Collaborator

@ibgreen ibgreen left a comment

Choose a reason for hiding this comment

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

Not quite convinced that this is worth the extra complexity in term of types etc, compared to just adding two WebGL/WebGPU columns to the DeviceProps docs table.

Also seems to limit the ability to specify WebGL/WebGPU options when using best-available (though I assume that is fixable).

@@ -128,11 +128,13 @@ export class WebGLDevice extends Device {

this.handle = createBrowserContext(this.canvasContext.canvas, {
...props,
onContextLost: (event: Event) =>
onContextLost: (event: Event) => {
Copy link
Collaborator

Choose a reason for hiding this comment

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

What are these changes? Some editor auto correct?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This calls the users onContextLost, if provided

Copy link
Collaborator

Choose a reason for hiding this comment

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

This calls the users onContextLost, if provided

I see. Adding a one line bug fix in to a bigger API change is a bit risky, can slip through the review, and can get lost if API change is not approved...

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Happy to split this out. I didn't mean to put anything risky in here. The reason I included this is get clarity on the intended API. It's unclear to me what the intent is.

If users shouldn't be able to provide onContextLost by design, then the API types need to be adjusted a bit. If we can agree the user should be able to provide onContextLost, then this is a bug and I'll pull that into another PR.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Now that you shine a light on it, I think we should completely drop support for onContextLost. Such callback code tends to be surprisingly messy to keep working across devices and it doesn't add value.

We don't talk about contexts anymore, just devices. and we have the replacement in the WebGPU style promise API: device.lost

App can register its onContextLost callback with device.lost.then(onContextLost).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I agree. device.lost sounds better since it the same API for both devices, making this redundant.

Is there a device equivalent for onContextRestore as well?

Copy link
Collaborator

Choose a reason for hiding this comment

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

No, context restore is not supported by luma.gl v9.

The problems is that properly handling context restore in non-trivial apps is very tricky, since all resources are lost and have to be recreated, and the data that was used to create buffers and textures may not have been saved.

\Showing a message asking the user to just refresh the page is usually best way out.

WebGPU doesn't support restore.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Should the onContextRestore code in the WebGL device be removed then?

Copy link
Collaborator

Choose a reason for hiding this comment

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

Yes. I would vote for that. It is not impossible for an app to register the callback even if luma.gl API doesn't support it, they will just need to get the context and add an event handler themselves.

@chrisgervang
Copy link
Contributor Author

The vision here makes sense to me, that one day we’ll be able to use best-available and luma will match the default behaviors between the devices as best as it can. However, I still believe there’s a need for discriminated union types.

The complex typing reflects a complex API; deviceProps are effectively two different objects (or the union of those) depending on their use case, and then another union with additional properties for createDevice. These APIs are challenging to explain, but types can help.

I think these types should be as helpful to users as possible. It defeats the purpose if users need to constantly refer to the documentation just to know which properties they can use, especially when they are explicitly using WebGL or WebGPU.

I think the goal should be to provide clarity and reduce the cognitive load, and I'm open simpler implementations if they exist.

@ibgreen
Copy link
Collaborator

ibgreen commented Jun 18, 2024

The vision here makes sense to me, that one day we’ll be able to use best-available and luma will match the default behaviors between the devices as best as it can. However, I still believe there’s a need for discriminated union types.

The complex typing reflects a complex API; deviceProps are effectively two different objects (or the union of those) depending on their use case, and then another union with additional properties for createDevice. These APIs are challenging to explain, but types can help.

I think these types should be as helpful to users as possible. It defeats the purpose if users need to constantly refer to the documentation just to know which properties they can use, especially when they are explicitly using WebGL or WebGPU.

I think the goal should be to provide clarity and reduce the cognitive load, and I'm open simpler implementations if they exist.

In loaders.gl we have options sub-objects for each loader, the same model could work here:

luma.createDevice({
 // common options
 webgl: {
   // webgl specific options,
 },
 webgpu: {
   // webgpu specific options
 }
};

It would be slightly breaking but make it very clear what is going on.

Signed-off-by: Chris Gervang <chris@gervang.com>
Signed-off-by: Chris Gervang <chris@gervang.com>
@chrisgervang chrisgervang changed the title chore(core) document device props per device chore(core) new device props Jun 20, 2024
@chrisgervang chrisgervang changed the title chore(core) new device props chore(core) new device props api Jun 20, 2024
@ibgreen
Copy link
Collaborator

ibgreen commented Aug 13, 2024

OK I have made another pass on this. Decided to go with some technically breaking changes to clean up the API, shouldn't lead to any subtle issues.

  • Collected webgl specific props in DeviceProps.webgl
  • Collected canvasContext specific props in DeviceProps.canvasContext
  • Sets preserveDrawingBuffers to true by default (presumably the reason why this big change was started anyways)

Copy link
Contributor Author

@chrisgervang chrisgervang left a comment

Choose a reason for hiding this comment

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

Nice progress! Left a few comments. I'm wondering if we should warn when features that are only WebGL or only WebGPU are used on an incompatible device, like "debug"? When the lib does nothing I can foresee that being a long debugging session to learn what exactly is and isn't supported, specifically for any potentially ambiguous top-level device props. What do you think?

docs/api-reference/webgl/README.md Outdated Show resolved Hide resolved
docs/api-reference/webgpu/README.md Outdated Show resolved Hide resolved
modules/webgl/src/adapter/webgl-device.ts Outdated Show resolved Hide resolved
modules/core/src/adapter/luma.ts Show resolved Hide resolved
docs/legacy/porting-guide.md Outdated Show resolved Hide resolved
docs/legacy/porting-guide.md Outdated Show resolved Hide resolved
modules/core/test/adapter/luma.spec.ts Outdated Show resolved Hide resolved
docs/api-reference/core/device.md Outdated Show resolved Hide resolved
docs/api-reference/core/device.md Outdated Show resolved Hide resolved
@ibgreen
Copy link
Collaborator

ibgreen commented Aug 13, 2024

Nice progress! Left a few comments. I'm wondering if we should warn when features that are only WebGL or only WebGPU are used on an incompatible device, like "debug"? When the lib does nothing I can foresee that being a long debugging session to learn what exactly is and isn't supported, specifically for any potentially ambiguous top-level device props. What do you think?

  • While developer experience is important, there is a real bundle size overhead to sprinkling the code with checks and error messages, which makes me hesitate.
  • I cleaned up the options and their naming which should make things much clearer.
  • And also added clear TSDoc comments (which should be visible in e,g, vscode when hovering over props) to indicate what is device specific.

@ibgreen
Copy link
Collaborator

ibgreen commented Aug 13, 2024

Have a few test failures, plan to merge when they are sorted.

Copy link
Contributor Author

@chrisgervang chrisgervang left a comment

Choose a reason for hiding this comment

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

I like the new names, and the docstrings are very helpful! Thanks for pushing this forward.

docs/api-reference/webgpu/README.md Outdated Show resolved Hide resolved
docs/developer-guide/debugging.md Show resolved Hide resolved
modules/core/src/index.ts Show resolved Hide resolved
docs/api-reference/core/device.md Show resolved Hide resolved
docs/developer-guide/debugging.md Show resolved Hide resolved
docs/api-reference/core/device.md Show resolved Hide resolved
| `_requestMaxLimits?: boolean` | `true` | Ensures that the Device exposes the highest `DeviceLimits` supported by platform (WebGPU). |
| `_initializeFeatures?: boolean` | `true` | Initialize all `DeviceFeatures` on startup. 🧪 |
| `_disabledFeatures?: Record<DeviceFeature, boolean>` | `{ 'compilation-status-async-webgl': true }` | Disable specific `DeviceFeatures`. 🧪 |
| `_factoryDestroyPolicy?: string` | `'unused'` | `'unused' \| 'never'` Never destroy cached shaders and pipelines. 🧪 |
Copy link
Contributor Author

@chrisgervang chrisgervang Aug 13, 2024

Choose a reason for hiding this comment

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

Why might someone use this?

It is a tradeoff between reuse/speed and memory. I added it to unblock things until we find the right balance.

| `depth24unorm-stencil8` | Removed | `depth24plus-stencil8` | The `TextureFormat` was removed from the WebGPU spec |
| `rgb8unorm-unsized` | Removed | `rgb8unorm` | No longer support unsized WebGL1 `TextureFormat` |
| `rgba8unorm-unsized` | Removed | `rgb8aunorm` | No longer support unsized WebGL1 `TextureFormat` |
| Updated API | Status | Replacement | Comment |
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Might be good to document the renamed device props and removal of "break" before merging

@ibgreen
Copy link
Collaborator

ibgreen commented Aug 14, 2024

I like the new names, and the docstrings are very helpful! Thanks for pushing this forward.

Great review, you are really paying attention to this! Agree with all your proposals. Would you mind applying your changes? Landing this PR has become a pretty big effort, so teamwork is appreciated.

@ibgreen
Copy link
Collaborator

ibgreen commented Aug 14, 2024

@chrisgervang This is passing CI after lots of iterations. Will land and we can take your suggestions in a follow up PR.

@ibgreen ibgreen merged commit 3ca7bbc into master Aug 14, 2024
2 checks passed
@ibgreen ibgreen deleted the chr/device-props branch August 14, 2024 14:35
@ibgreen ibgreen mentioned this pull request Aug 14, 2024
22 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants