From f81e0fcbf41f4f39766390bc00ced61f53c7d932 Mon Sep 17 00:00:00 2001 From: aaronp64 Date: Mon, 20 May 2024 19:40:39 -0400 Subject: [PATCH] Improve memory usage for image import and PortableCompressedTexture2D When importing images, we store a compressed version of the image to a .ctex file with ResourceImporterTexture::save_to_ctex_format. When importing many large images at once, this can use a large amount of memory, especially when the .ctex file uses WebP format. This change is for ResourceImporterTexture::save_to_ctex_format to use the original Image object instead of p_image->get_image_from_mipmap(0), to avoid creating a copy of the full uncompressed image when looping through the base Image and mipmaps. This reduces the import memory usage for large images by around 10% when using WebP, and 35-40% when Project Settings/Rendering/Textures/Lossless Compression/Force PNG is enabled, may vary depending on the image and number of import threads running. Same change applied to PortableCompressedTexture2D::create_from_image, which has similar logic. This helps with #92084, but does not fully resolve the issue on its own, as compressing with WebP on many threads can still use a large amount of memory - this just lowers that amount, and makes it more likely that enabling "Force PNG" will reduce memory usage enough to import the files. --- editor/import/resource_importer_texture.cpp | 6 +++--- scene/resources/portable_compressed_texture.cpp | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/editor/import/resource_importer_texture.cpp b/editor/import/resource_importer_texture.cpp index 8cf104725ad..487b8fc175c 100644 --- a/editor/import/resource_importer_texture.cpp +++ b/editor/import/resource_importer_texture.cpp @@ -269,9 +269,9 @@ void ResourceImporterTexture::save_to_ctex_format(Ref f, const Refget_mipmap_count() + 1; i++) { Vector data; if (use_webp) { - data = Image::webp_lossless_packer(p_image->get_image_from_mipmap(i)); + data = Image::webp_lossless_packer(i ? p_image->get_image_from_mipmap(i) : p_image); } else { - data = Image::png_packer(p_image->get_image_from_mipmap(i)); + data = Image::png_packer(i ? p_image->get_image_from_mipmap(i) : p_image); } int data_len = data.size(); f->store_32(data_len); @@ -289,7 +289,7 @@ void ResourceImporterTexture::save_to_ctex_format(Ref f, const Refstore_32(p_image->get_format()); for (int i = 0; i < p_image->get_mipmap_count() + 1; i++) { - Vector data = Image::webp_lossy_packer(p_image->get_image_from_mipmap(i), p_lossy_quality); + Vector data = Image::webp_lossy_packer(i ? p_image->get_image_from_mipmap(i) : p_image, p_lossy_quality); int data_len = data.size(); f->store_32(data_len); diff --git a/scene/resources/portable_compressed_texture.cpp b/scene/resources/portable_compressed_texture.cpp index 918b5c0b41a..002db30379f 100644 --- a/scene/resources/portable_compressed_texture.cpp +++ b/scene/resources/portable_compressed_texture.cpp @@ -153,14 +153,14 @@ void PortableCompressedTexture2D::create_from_image(const Ref &p_image, C for (int i = 0; i < p_image->get_mipmap_count() + 1; i++) { Vector data; if (p_compression_mode == COMPRESSION_MODE_LOSSY) { - data = Image::webp_lossy_packer(p_image->get_image_from_mipmap(i), p_lossy_quality); + data = Image::webp_lossy_packer(i ? p_image->get_image_from_mipmap(i) : p_image, p_lossy_quality); encode_uint16(DATA_FORMAT_WEBP, buffer.ptrw() + 2); } else { if (use_webp) { - data = Image::webp_lossless_packer(p_image->get_image_from_mipmap(i)); + data = Image::webp_lossless_packer(i ? p_image->get_image_from_mipmap(i) : p_image); encode_uint16(DATA_FORMAT_WEBP, buffer.ptrw() + 2); } else { - data = Image::png_packer(p_image->get_image_from_mipmap(i)); + data = Image::png_packer(i ? p_image->get_image_from_mipmap(i) : p_image); encode_uint16(DATA_FORMAT_PNG, buffer.ptrw() + 2); } }