-
Notifications
You must be signed in to change notification settings - Fork 3.6k
DumpData: Add Native override #17365
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
base: master
Are you sure you want to change the base?
Conversation
…ot assignable to type '(pixelData: Uint8Array<ArrayBufferLike>, width: number, height: number, mimeType: string, invertY: boolean, quality?: number | undefined) => Promise<...>'.
Type 'unknown' is not assignable to type 'Promise<ArrayBuffer>'.
|
Please make sure to label your PR with "bug", "new feature" or "breaking change" label(s). |
| reject(new Error("DumpData: Failed to convert canvas to blob.")); | ||
| } else if (blob.type !== mimeType) { | ||
| // The MIME type of a canvas.toBlob() output can be different from the one requested if the browser does not support the requested format | ||
| reject(new Error(`DumpData: Failed to convert canvas to blob as ${mimeType}. Got ${blob.type} instead.`)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a breaking change, but I think it makes sense to do, considering the API contract is to just return the binary data-- with the expectation that it matches the requested MIME type.
This change would also enable the changes proposed in #17366.
But there's one case that I'm not sure how to handle: when DumpData is used just to download an image, and the user doesn't care about the return type. I think ScreenshotTools is an example of this.
How should this be handled?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a breaking change, but I think it makes sense to do, considering the API contract is to just return the binary data-- with the expectation that it matches the requested MIME type.
I would say this is a bug fix so it's okay.
But there's one case that I'm not sure how to handle: when DumpData is used just to download an image, and the user doesn't care about the return type. I think ScreenshotTools is an example of this.
How should this be handled?
Maybe we can have an optional mimeType and we select the best one in the implementation?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would say this is a bug fix so it's okay.
OK, I'll leave this be. Thanks.
Maybe we can have an optional mimeType and we select the best one in the implementation?
By implementation, do you mean the implementation of ScreenshotTools? If so, it already does something like this, defaulting to PNG if no mime type is supplied.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was thinking in this function since that was my interpretation of your question. Maybe we can sync offline quickly.
|
Snapshot stored with reference name: Test environment: To test a playground add it to the URL, for example: https://snapshots-cvgtc2eugrd3cgfd.z01.azurefd.net/refs/pull/17365/merge/index.html#WGZLGJ#4600 Links to test babylon tools with this snapshot: https://playground.babylonjs.com/?snapshot=refs/pull/17365/merge To test the snapshot in the playground with a playground ID add it after the snapshot query string: https://playground.babylonjs.com/?snapshot=refs/pull/17365/merge#BCU1XR#0 |
|
WebGL2 visualization test reporter: |
|
Visualization tests for WebGPU |
| * @internal | ||
| */ | ||
| @nativeOverride | ||
| public static async EncodeImageAsync(pixelData: Uint8Array, width: number, height: number, mimeType: string, invertY: boolean, quality?: number): Promise<ArrayBuffer> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As of now, it seems the two approaches to using nativeOverride for module-level function are:
- what's here now: a helper class with static-only functions
export const EncodeImageAsync = nativeOverride(async (....) => { ... })
Is this correct? @ryantrem
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think the second bullet is a thing as far as I recall and from a quick glance at the code. I think we could make something like that work though, and avoid introducing a new class.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Gotcha. Mainly wanted to check if any existing approaches could work. I’ll stick with the class approach for now to keep the PR focused :)
| reject(new Error("DumpData: Failed to convert canvas to blob.")); | ||
| } else if (blob.type !== mimeType) { | ||
| // The MIME type of a canvas.toBlob() output can be different from the one requested if the browser does not support the requested format | ||
| reject(new Error(`DumpData: Failed to convert canvas to blob as ${mimeType}. Got ${blob.type} instead.`)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a breaking change, but I think it makes sense to do, considering the API contract is to just return the binary data-- with the expectation that it matches the requested MIME type.
I would say this is a bug fix so it's okay.
But there's one case that I'm not sure how to handle: when DumpData is used just to download an image, and the user doesn't care about the return type. I think ScreenshotTools is an example of this.
How should this be handled?
Maybe we can have an optional mimeType and we select the best one in the implementation?
| } | ||
|
|
||
| const resources = await _GetDumpResourcesAsync(); | ||
| const buffer = await EncodingHelper.EncodeImageAsync(data as Uint8Array, width, height, mimeType, invertY, quality); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it valid to convert ArrayBufferView to Uint8Array? I'm not sure this will work in all cases.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Definitely not valid :) I meant to think about this more.
On the one hand, DumpData's usage of engine.createRawTexture implies that the data is expected to be UNSIGNED_BYTE.
On the other hand, I have no clue why this hasn't been a problem yet. My guess is that DumpData is usually used in conjunction with readPixels, which returns either float array or uint8 array
| target: any, | ||
| propertyKey: string, | ||
| descriptor: TypedPropertyDescriptor<(...params: Parameters<T>) => unknown>, | ||
| descriptor: TypedPropertyDescriptor<(...params: Parameters<T>) => any>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just curious why this change was needed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a more elegant way?
| * @internal | ||
| */ | ||
| @nativeOverride | ||
| public static async EncodeImageAsync(pixelData: Uint8Array, width: number, height: number, mimeType: string, invertY: boolean, quality?: number): Promise<ArrayBuffer> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think the second bullet is a thing as far as I recall and from a quick glance at the code. I think we could make something like that work though, and avoid introducing a new class.
|
|
||
| texture.dispose(); | ||
|
|
||
| Tools.ToBlob( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we add a ToBlobAsync that is promise returning?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could. It wouldn't be as simple as replacing with ToBlob with ToBlobAsync, though, as the canvas draw + toBlob must be atomic. Guess we could use an AsyncLock?

This PR adds the glue code to enable DumpData usage in BN.
Changes:
bitmaprendererpath. I initially planned for Native to polyfill this, but that turned out to be not a good idea.