ASTC纹理压缩耗时太长,是哪里设置有问题吗

  • Creator 版本: 3.8.2

  • 目标平台: mac creator编辑器

项目配置了多张图片压缩纹理,小游戏平台统一配置为ASTC8x8 medium和PNG,构建微信小游戏时查看构建日志,total time显示只有0.0125s,但是都要间隔4s以上日志才会显示压缩下一张图,导致图片多时构建极慢,这个是哪里配置有问题吗?有办法优化吗?

首次久,下次就快了又缓存

算快了,etc2, 10 分钟一图我都见过,我们项目不使用缓存,完整压一遍要 1 天多 :rofl:

给我的感觉是压缩任务没有做并行处理而是一个个依次压缩,这样挺影响开发效率的 :joy:

那确实是,理论上并行压缩很容易做的

压缩器线程本身并行了。你看Compressor thread count 是16,如果再多开几个进程就要挤兑cpu了。
每次开启压缩器进程本身就要耗费一定时间。要压的快,看看有没有批量传文件列表到压缩器的方式,省去每个文件开关进程的部分时间。
可以把文件列表(src -> dest)放在一个json里面,然后修改压缩器,使其支持从配置文件里面读取文件列表批量操作就行了。

是需要修改astcenc吗?门槛有点高呀 :flushed:

看日志的话压缩时只有一个task在进程里
astc_8x89d90b3b266.astc

2024-10-24 11:23:08 - debug: astc compressed command: astcenc -cl /Users/admin/Documents/xx/Project/library/0b/0b6b0e5e-6317-4678-8811-859d90b3b266.jpg /Users/admin/Documents/xx/Project/temp/builder/CompressTexture/0b/0b6b0e5e-6317-4678-8811-859d90b3b266.astc 8x8 -medium

Source:                     /Users/admin/Documents/xx/Project/library/0b/0b6b0e5    Coding rate:                10.4116 MT/s ids

2024-10-24 11:23:11 - debug: [compress astc]Child process exit width code 0

2024-10-24 11:23:11 - log: Compress astc success {link(/Users/admin/Documents/xx/Project/temp/builder/CompressTexture/0b/0b6b0e5e-6317-4678-8811-859d90b3b266.astc)}

2024-10-24 11:23:11 - debug: execute compress task 828/1608, 1 in progress}, progress: 28%

2024-10-24 11:23:11 - debug: [compress astc]Child process exit width code 0

我这边用child_process试了是可以并行压缩的,压缩276个文件只要1.72s,creator一个个压的话就要十多分钟。
import { spawn } from “child_process”;
import { readdir } from “fs/promises”;
import path from “path”;

async function compressImages() {
    const directoryPath = "/Users/admin/Downloads/test/astccompress/Box"; // 替换为你的图片目录
    const files = await readdir(directoryPath);

    const iStartTime = performance.now();
    const tPromises = files
        .filter((file) => file.endsWith(".png")) // 只处理 .png 文件
        .map((file) => {
            const inputPath = path.join(directoryPath, file);
            const outputPath = path.join(directoryPath, `${path.parse(file).name}.astc`);

            return new Promise<void>((resolve, reject) => {
                const astcProcess = spawn("/Applications/Cocos/Creator/3.8.2/CocosCreator.app/Contents/Resources/tools/astc-encoder/astcenc", [
                    "-cl",
                    inputPath,
                    outputPath,
                    "8x8",
                    "-medium",
                ]);

                astcProcess.stdout.on("data", (data) => {
                    console.log(`Output: ${data}`);
                });

                astcProcess.stderr.on("data", (data) => {
                    console.error(`Error: ${data}`);
                });

                astcProcess.on("close", (code) => {
                    if (code === 0) {
                        console.log(`Compressed: ${file}`);
                        resolve();
                    } else {
                        reject(`Compression failed for ${file} with code ${code}`);
                    }
                });
            });
        });

    await Promise.all(tPromises);
    console.log("All images compressed.");
    const iEndTime = performance.now();
    console.log(`总耗时:${(iEndTime - iStartTime) / 1000} s. 转换文件数:${tPromises.length}`);
}

compressImages().catch(console.error);
1赞

那挺好的啊,就让引擎组加入进去吧。
如果引擎组不改编辑器的话,也可以在纹理压缩那里做个假的纹理压缩器,用来记录参数到json里面,build后用外部脚本来批量压缩到temp目录里面并且拷贝到工程。

1赞

记录一下最后的解决方法,后面有碰到的小伙伴可以参考一下。
在自定义构建扩展的钩子函数compressTextures里记录所有astc压缩的task的路径,保存到json里,再额外执行js脚本,脚本里读取json,内容跟上面代码差不多就是并行压缩。没有直接在compressTextures里执行是因为直接执行会跟原来一样慢,估计是有资源竞争,放在脚本执行就很快了,800个文件耗时18s。压缩的时候资源占满导致电脑卡顿,不过总比等半天好。