Skip to content

Unity Tracy #16

@nzcv

Description

@nzcv

查找图像压缩算法的实现细节:

[3 tools called]

查看客户端如何处理图像压缩:

[3 tools called]

查看 DXT1 压缩的具体实现:

[3 tools called]

Tracy 使用两阶段压缩来处理图像数据:

图像压缩算法详解

一、第一阶段:DXT1 纹理压缩(客户端)

1. 压缩位置

在客户端,由专门的压缩线程处理:

                const auto csz = size_t( w * h / 2 );
                auto etc1buf = (char*)tracy_malloc( csz );
                CompressImageDxt1( (const char*)fi->image, etc1buf, w, h );

2. DXT1 压缩特性

  • 算法:S3 纹理压缩(DXT1/BC1)
  • 压缩比:8:1(每像素从 32 位压缩到 4 位)
  • 格式:从 RGBA8888(4 字节/像素)→ DXT1(0.5 字节/像素)
  • 类型:有损压缩,质量损失较小
  • 块大小:4×4 像素块 = 8 字节

3. 性能优化

支持 SIMD 加速,性能数据(320×180 图像):

实现 所需定义 压缩时间
x86 参考实现 --- 198.2 μs
x86 SSE4.1 __SSE4_1__ 25.4 μs
x86 AVX2 __AVX2__ 17.4 μs
ARM 参考实现 --- 1.04 ms
ARM32 NEON __ARM_NEON 529 μs
ARM64 NEON __ARM_NEON 438 μs

4. 处理流程

  1. 用户调用 FrameImage() 传入 RGBA 数据
  2. 数据存入 m_fiQueue 队列
  3. 压缩线程从队列取出图像
  4. 调用 CompressImageDxt1() 进行 DXT1 压缩
  5. 压缩后的数据通过网络发送到服务器

二、第二阶段:ZSTD 压缩(服务器端)

1. 压缩位置

在服务器端接收数据后进行进一步压缩:

    m_texcomp.FixOrder( (char*)dst, sz/8 );
    m_texcomp.Rdo( (char*)dst, sz/8 );
    m_pendingFrameImageData.image = m_texcomp.Pack( m_frameImageBuffer, sz, m_pendingFrameImageData.csz, m_slab );

2. ZSTD 压缩参数

uint32_t TextureCompression::Pack( struct ZSTD_CCtx_s* ctx, char*& buf, size_t& bufsz, const char* image, uint32_t inBytes )
{
    const auto maxout = ZSTD_COMPRESSBOUND( inBytes );
    if( bufsz < maxout )
    {
        bufsz = maxout;
        delete[] buf;
        buf = new char[maxout];
    }
    assert( ctx );
    auto ret = (uint32_t)ZSTD_compressCCtx( ctx, buf, maxout, image, inBytes, 3 );
  • 算法:ZSTD(Zstandard)
  • 压缩级别:3(平衡压缩比与速度)
  • 类型:无损压缩
  • 对象:对 DXT1 压缩后的数据再次压缩

3. 服务器端优化处理

在 ZSTD 压缩前,还进行了两项优化:

  1. FixOrder():调整 DXT1 块的数据顺序,提高压缩效率
  2. Rdo():基于视觉的 RDO(Rate Distortion Optimization),在保持视觉质量的前提下进一步优化压缩

三、完整压缩流程

用户提供RGBA图像
    ↓
[客户端] FrameImage() - 存储到队列
    ↓
[客户端] 压缩线程 - DXT1压缩 (8:1)
    ├─ 32位/像素 → 4位/像素
    ├─ 支持SIMD加速
    └─ 质量轻微下降
    ↓
[网络传输] DXT1压缩数据
    ↓
[服务器] 接收数据
    ↓
[服务器] FixOrder() - 优化数据排列
    ↓
[服务器] Rdo() - 视觉优化压缩
    ↓
[服务器] ZSTD压缩 (级别3) - 进一步压缩
    └─ 无损压缩
    ↓
[服务器] 存储压缩后的数据

四、压缩效果

1. 理论压缩比

  • DXT1:8:1(32 位 → 4 位)
  • ZSTD:通常 2-4:1(取决于图像内容)

综合压缩比通常为 16-32:1

2. 实际示例

对于 320×180 的图像:

  • 原始 RGBA:320 × 180 × 4 = 230,400 字节(约 225 KB)
  • DXT1 压缩后:320 × 180 / 2 = 28,800 字节(约 28 KB)
  • ZSTD 进一步压缩后:通常 < 10 KB

3. 限制

  • 单帧图像压缩后不能超过 256 KB(网络缓冲限制)
  • 960×540 的图像可以满足此限制

五、关键代码位置

  1. 客户端 DXT1 压缩:

    • public/client/TracyDxt1.cpp - DXT1 压缩实现
    • public/client/TracyProfiler.cpp:2288 - 调用压缩函数
  2. 服务器端 ZSTD 压缩:

    • server/TracyTextureCompression.cpp - ZSTD 压缩实现
    • server/TracyWorker.cpp:3887 - 调用压缩函数
  3. 服务器端解压:

    • server/TracyTextureCompression.cpp:62-80 - 解压函数

六、总结

Tracy 使用两阶段压缩:

  1. DXT1 纹理压缩(客户端,有损)

    • 8:1 压缩比
    • 支持 SIMD 加速
    • 质量损失小
  2. ZSTD 压缩(服务器端,无损)

    • 对 DXT1 数据再次压缩
    • 压缩级别 3
    • 进一步减小存储空间

该方案在保持视觉质量的同时,显著减少内存和网络传输开销。

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions