6个版本 (3个破坏性更新)
0.4.0 | 2024年8月16日 |
---|---|
0.3.2 | 2024年3月17日 |
0.3.1 | 2023年3月8日 |
0.3.0 | 2022年7月25日 |
0.1.0 | 2021年11月17日 |
#18 in 数据格式
240 每月下载量
用于 4 个crate(2个直接使用)
8.5MB
2.5K SLoC
tegra_swizzle
适用于任天堂Switch中Tegra X1的纹理表面的块线性内存布局算法的纯Rust安全高效实现。
上图显示了一个16x16x16像素的平铺RGBA 3D查找表。不同颜色的块对应于16x2的GOB网格(来自Tegra TRM的“字节组”)。GOB是64x8字节(共512字节),在这个例子中是16x8像素。下面显示了未平铺或线性的版本。
内存平铺
GPU纹理通常以平铺内存布局存储,以便使纹理访问更加缓存友好。标准的线性或行主序内存排序仅在以行主序访问数据时才是缓存友好的。对于模型图像纹理来说,这种情况很少,因此表面的字节被重新排列,使用某种形式的平铺算法来提高缓存未命中数。
需要注意的是,平铺会影响内存寻址,因此应将表面视为二维或三维字节数组,而不是像素或4x4像素块。平铺算法与数据是RGBA8还是BC7压缩无关。该格式仅用于将表面尺寸从像素转换为字节。这避免了关于像素或压缩块大小与平铺算法之间关系的主观假设,并导致代码更加高效。平铺表面的字节尺寸向上舍入到整数维度的GOB(64x8)字节。对于平铺能够正确工作,表面尺寸在像素上不需要是2的幂。
这种技术通常在Switch破解社区中被称作“交换”、“反交换”、“解交换”或“反-交换”。将块线性地址位描述为从线性地址位重新排列或“交换”并不准确,这并不适用于所有纹理大小的块。幸运的是,在破解社区中,“交换”一词的常见用法几乎总是特指块线性内存布局算法。为了提高可发现性,在库和函数名称中保留了“交换”一词,因为这是大多数程序员可能搜索的内容。
构建
要通过C FFI在其它语言中使用库,首先使用以下命令构建库:
cargo rustc --release --crate-type=cdylib --features=ffi
。这需要安装Rust工具链。生成的tegra_swizzle.dll
、libtegra_swizzle.dylib
或tegra_swizzle.so
(取决于平台)可以像任何其他编译的C库一样使用。请参阅docs.rs链接中的ffi模块以获取文档。
有关为Nintendo Switch构建插件的说明,请参阅skyline。
测试数据
该存储库包含示例数据以测试平铺和非平铺。由于在实际硬件上进行测试困难,这些文件使用Ryujinx模拟器的实现生成。有关tegra_swizzle使用的其他测试,请参阅源代码和fuzz目录。
可以通过生成一个二进制纹理文件并按升序将4字节整数分配给图像数据的每个4字节块来生成新的测试数据。这些索引的范围是[0, surface_size / 4]
表示每个输入位置的线性或行主顺序地址。在模拟器中加载并使用如RenderDoc之类的程序调试时,纹理表面数据将包含解交换的数据。使用整数索引作为输入使得通过比较输入文件中的整数与从调试器中提取的原始纹理数据,可以定义从“交换”地址到线性地址的映射。请参阅提供的测试文件以了解不同表面尺寸和格式的示例。
文档
有关平铺的更正式描述,请参阅平铺页面。虽然这并不足以被认为是证明,但它有助于解释应用到此库的一些技术和优化。关于平铺和交换的博客文章也提供了一些额外的见解。请注意,tegra_swizzle没有使用博客文章中描述的位交错技巧。