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

Small optimizations: pre upload geometry, textures before rendering with them #490

Open
gkjohnson opened this issue Feb 22, 2024 · 2 comments
Milestone

Comments

@gkjohnson
Copy link
Contributor

gkjohnson commented Feb 22, 2024

First measure the potential performance impact of these upload times. They may be small / not worthwhile considering the size of geometry and textures in the typical tile. But this could skip the waiting on render before upload.

@gkjohnson gkjohnson added this to the v0.3.26 milestone Feb 22, 2024
@gkjohnson gkjohnson modified the milestones: v0.3.26, v0.3.27, v0.3.28 Feb 29, 2024
@gkjohnson gkjohnson modified the milestones: v0.3.28, v0.3.29, v0.3.30 Mar 11, 2024
@gkjohnson gkjohnson modified the milestones: v0.3.31, v0.3.32 Mar 25, 2024
@gkjohnson gkjohnson modified the milestones: v0.3.32, v0.3.33 Apr 24, 2024
@Nmzik
Copy link
Contributor

Nmzik commented May 5, 2024

@gkjohnson
Do you mean by "pre-uploading" sending data (geometry and textures) bufferData() compressedTexImage2D() to the GPU driver? Or do you simply mean calling initTexture() in threeJS on each texture as soon as GLTF is parsed and before re-rendering the scene?

Regarding uploading to the GPU driver, uploading geometry is mostly fine for me (around 0.60ms is spent on bufferData - each tile geometry is around 3MB of vertex data).

However, regarding textures, I've encountered a completely different result - over 20ms is spent on uploading a 4096x4096 KTX2 texture to WebGL (on Windows, essentially on DirectX 11). The issue is, I haven't found a proper way in threeJS to upload part of a texture to the preallocated buffer (for example, 2MB of the texture per frame) and when the texture is uploaded to the buffer (after a few frames), create a texture (webGL object) and copy asynchronously from the buffer to the texture.
DataTexture in threeJS seems to upload the texture fully onto the GPU, which can cause stalls. Partial updates are not supported for compressed textures (correct me if I'm wrong).
The only solution I've found is to create a PBO and do it this way. (But again, this requires a threeJS patch/PR).

My apologies if I misunderstood your issue.

@gkjohnson
Copy link
Contributor Author

Do you mean by "pre-uploading" sending data (geometry and textures) bufferData() compressedTexImage2D() to the GPU driver? Or do you simply mean calling initTexture() in threeJS on each texture as soon as GLTF is parsed and before re-rendering the scene?

Originally I was imagining it might be possible to asynchronously uploading the geometry and textures and then only render once they have been uploaded so no blocking on rendering occurs (similar to compileAsync for materials) but this likely isn't how data upload can work in WebGL 2.

What we can do, though, is only upload 1 texture per frame or a certain amount of texture MB to limit the amount of stalling due to uploading at a time, which should help at least some.

However, regarding textures, I've encountered a completely different result - over 20ms is spent on uploading a 4096x4096 KTX2 texture to WebGL (on Windows, essentially on DirectX 11).

4K textures may not be ideal for something like 3d tiles where they're being uploaded and disposed consistently for this reason. If I recall correctly in our Mars 3d tiles our texture dimensions are limited to 256 and mipmaps are disabled to save time on generation with the understanding that as the camera gets closer and the texture becomes more visible, multiple new tiles and therefore more texture resolution will become visible.

Likewise using textures that are compatible with being loaded as an ImageBitmap (KTX2 is not I don't believe) can help improve upload times as far as I know. Hopefully there's still more we can do to decrease the hiccups on upload but even so there's a balance to strike between asset download sizes and performance of GPU upload.

The issue is, I haven't found a proper way in threeJS to upload part of a texture to the preallocated buffer

I don't know about how it works with compressed textures but with my recent copyTextureToTexture PR images and data textures and be progressively uploaded by copying chunks of an image at a time to a GPU-bound texture. If uploading one texture per frame still isn't good enough then it may be possible to progressively upload texture data.

Very happy to have some help thinking through some of these problems. It would be great to get something like the Google Earth example loading more smoothly with fewer frame drops!

@gkjohnson gkjohnson modified the milestones: v0.3.33, v0.3.34 May 14, 2024
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

No branches or pull requests

2 participants