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

Prefer ImageBitmapLoader and dispose of textures after GPU upload #21

Merged
merged 8 commits into from
Apr 8, 2019

Conversation

netpro2k
Copy link

@netpro2k netpro2k commented Apr 5, 2019

This is built on top for ThreeJS 103 changes. It does 2 independent things that both touch similar code and seem easier to test together:

  • TextureLoader will use ImageBitmapLoader by default if createImageBitmap is available. Since Firefox does not support createImageBitmap options, we also turn off flipY on the textures we create. This is already the default in GLTFLoader but an option also needed to be exposed for the uvs generated in PlaneGeometry and PlaneBufferGeometry since Hubs uses those directly.
  • The image for a texture will be disposed of after upload to the GPU. This probably warrants a configurable option on the loader eventually, but nothing in Hubs currently cares about the image after the fact. This will likely change if we move our fonts or our 9patch images to actually using a TextureLoader instead of an a-asset-item, since both of these look at the texture's image to get dimensions.

There are some discussions in flight in THREE mainline about better ways to configure loaders, so its likely we might change how we are doing this if/when those things land, but this seems like a pretty maintainable patch in the meantime.

Copy link

@johnshaughnessy johnshaughnessy left a comment

Choose a reason for hiding this comment

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

edit: I can't change ✅ to 💬 but I'd like to because of the question I posed about a possible bug. See comments.

Looks good. May want to remove logging before merge. Nice that ImageBitmapLoader existed for us to take advantage of. Too bad it's unavailable in safari.

texture.onUpdate = function () {

console.info( "Removing texture", texture.id, url );
Cache.remove( cacheKey );
Copy link

@johnshaughnessy johnshaughnessy Apr 6, 2019

Choose a reason for hiding this comment

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

So here we remove the ImageBitmap we stored in the cache because we are going to dispose all of its associated resources. Should we instead just never put it in the cache? Perhaps it doesn't matter, since you can call texture.image.close() and delete texture.image twice without throwing an error, and if we happen to make use of the cache in the window between load and onUpdate that seems good. Do we expect that ever to happen?

Copy link

@johnshaughnessy johnshaughnessy Apr 6, 2019

Choose a reason for hiding this comment

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

Related question: Is it possible for two textures to share a url to an image and have the following issue:

Texture 1 loads image, puts url: ImageBitmap into the cache.
Texture 2 loads image, pulls from the cache.
Texture 1 is uploaded to the GPU, uses texture.image.data, calls onUpdate to close the image and remove it from the cache.
Texture 2 is uploaded to the GPU, tries to use texture.image.data but fails, because the image was closed.

Choose a reason for hiding this comment

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

Do we ever expect to have to upload a texture to the GPU multiple times?

Copy link
Author

Choose a reason for hiding this comment

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

Re: "Should we instead just never push it in the cache", yeah probably, did it this way mostly to keep the patch small and localized to avoid future merge issues, but like we discussed (and as you pointed out above) there could be an issue with textures sharing the same Image.

Copy link
Author

Choose a reason for hiding this comment

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

Resolved this possible race condition by removing the image from the cache righ as onLoad is called. This happens immediately after it is added to the cache so there is no chance for the cached image to get picked up. Might be slightly cleaner to just not add the image to the cache, but again trying to keep the diff small here since I expect this change to move into Hubs once GLTFLoader hooks land.

@@ -1669,6 +1669,8 @@ THREE.GLTFLoader = ( function () {

onLoad( result );

parser.cache.removeAll();

Choose a reason for hiding this comment

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

What's this?

Copy link
Author

Choose a reason for hiding this comment

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

The gltf parser also keeps a cache of things while its loading, don't see any reason we would want to keep it around after load, and it was retaining things.

@netpro2k netpro2k merged commit 796fdfe into three-103 Apr 8, 2019
@takahirox takahirox deleted the texture-loading-changes branch April 4, 2022 19:35
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