Fix Image.convert()
overwriting custom mipmaps
#74238
Merged
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Fixes #66848, but this probably should not be merged without some discussion and maybe some more testing.
Currently, using custom Image mipmaps doesn't work reliably. You can write custom mipmaps in the Image data, but some renderer code paths with certain image formats can cause a call to
Image.convert()
. The way image format conversion is currently implemented converts only the largest main image mipmap and then generates downsampled mipmaps from that by callingImage.generate_mipmaps()
. Naturally, this overwrites any custom mipmaps the image had before.The fix that this PR implements is to simply convert all mipmap levels individually, this way conversion preserves all custom mipmaps.
This PR breaks compatibility to some degree as calling
Image.convert()
will no longer forcefully update all image mipmap levels which some code might have (incorrectly in my opinion) relied on, so this might cause some new bugs to surface. The image results can also differ by a very small amount, as the previousconvert()
averaged the main image down to smaller mipmap levels.I also ran some benchmarks. Release editor build, clang+mingw on Windows 10, Intel i7-4790 @4.0GHz. The new convert() is usually from x1.5 to x2.6 faster when processing large non-byte images, especially floating point images where the memory bandwidth and CPU processing required by generate_mipmaps() pixel averaging is significant. When converting small images or fast byte formats the speed differences between versions are very small.
Old Image.convert() that uses generate_mipmaps():
This PR, which converts each mip level individually: