gpt4 book ai didi

ios - 在 iOS 4+ 上优化调色板纹理到 RGB565 的转换(使用查找表)

转载 作者:塔克拉玛干 更新时间:2023-11-02 10:15:05 34 4
gpt4 key购买 nike

我正在转换的游戏在 8 位调色板纹理上运行,几乎每一帧我都必须将该纹理的一部分更新为 OpenGL 纹理以进行渲染。它看起来像这样:

unsigned short RGB565PaletteLookupTable[256];   // Lookup table

unsigned char* Src; // Source data
unsigned short* Dst; // Destination buffer
int SrcPitch; // Source data row length
int OriginX, OriginY, Width, Height; // Subrectangle to copy

assert( Width % 4 == 0 );

int SrcOffset = SrcPitch-Width;
Src += OriginY*SrcPitch+OriginX;

int x, y;

for( y = OriginY; y < OriginY+Height; ++y, Src += SrcOffset )
{
for( x = OriginX; x < OriginX+Width; x += 4 )
{
*Dst++ = RGB565PaletteLookupTable[*Src++];
*Dst++ = RGB565PaletteLookupTable[*Src++];
*Dst++ = RGB565PaletteLookupTable[*Src++];
*Dst++ = RGB565PaletteLookupTable[*Src++];
}
}

此代码在游戏期间占用主线程时间的 17%,因此我正在寻找加快速度的方法。数据直接进入 glTexSubImage2D(),因此我无法更改目标缓冲区中的任何内容。它来自游戏中的代码,这些代码是古老的且没有记录,而且没有人知道它是如何工作的,所以我也不能乱搞它。查找表也是由这个古老的代码提供的,并且可以在游戏过程中改变。

是否可以使用 Accelerate 框架/汇编指令/任何其他方式来加速此代码?我阅读了 RGB888 直接转换为 RGB565 的示例,但这些不需要使用查找表。我应该从哪里了解如何以最佳方式加快速度?

更新:我发现 OriginX 也是 4 对齐的,并且能够以这种方式改进代码:

unsigned long RGB565PaletteLookupTable[256];   // Lookup table

unsigned char* Src; // Source data
unsigned long* Dst; // Destination buffer
int SrcPitch; // Source data row length
int OriginX, OriginY, Width, Height; // Subrectangle to copy

assert( Width % 4 == 0 );

int SrcOffset = SrcPitch-Width;
Src += OriginY*SrcPitch+OriginX;
SrcOffset >>= 2;

int x, y;

unsigned long* LSrc = (unsigned long*)Src;

for( y = OriginY; y < OriginY+Height; ++y, LSrc += SrcOffset )
{
for( x = OriginX; x < OriginX+Width; x += 4 )
{
unsigned long Indexes = *LSrc++;
unsigned long Result = RGB565PaletteLookupTable[ Indexes & 0xFF ];
Indexes >>= 8;
Result |= ( RGB565PaletteLookupTable[ Indexes & 0xFF ] << 16 );
*Dst++ = Result;
Indexes >>= 8;
Result = RGB565PaletteLookupTable[ Indexes & 0xFF ];
Indexes >>= 8;
Result |= ( RGB565PaletteLookupTable[ Indexes & 0xFF ] << 16 );
*Dst++ = Result;
}
}

据我所知,这段代码没有使用任何未对齐的内存访问。它稍微提高了性能,也就是说,它现在占用主线程时间的 15.5%。不过,我希望能有更多的加速。

从理论上讲,每个查找表操作都独立于之前的和后续的操作(除了每个操作都从同一个查找表中读取这一事实),所以我期待会有一些 SIMD 指令,或者也许是允许并行查找许多像素的汇编指令。有点像

_mm_movemask_ps( _mm_cmpneq_ps( _mm_loadu_ps( cmp1 ), _mm_loadu_ps( cmp2 ) ) ) )

在 Mac 上,它与 memcmp( cmp1, cmp2,​​ 16 ) 做同样的事情,仅快 8 倍。

我现在会继续寻找它。

更新:我确定似乎没有办法使用 NEON 指令集来加速表查找。该表需要 512 字节大,无法将其完全放入 ARM 寄存器中,VTBX NEON 指令一次最多可以处理 32 字节,并且它还假定查找结果的大小必须等于索引。 http://forums.arm.com/index.php?/topic/15521-8bit-look-up-table-by-neon-code/ 中描述的类似问题的解决方案可能会解决一些问题,但它不适合我的。因此确保所有操作数的对齐都是正确的似乎是这个问题的最佳答案。

最佳答案

问题出在缓存上。您从 Src 进行了大量读取,如果它有四个未对齐(可能是这种情况,因为 OriginX 很可能是任意的),(*Src++) 会在未对齐读取上浪费周期。

尝试强制执行 (OriginX % 4 == 0) 并将剩余的 (OriginX % 4) 像素复制到主循环之外。

与 "*Dst++ = "相同 - Dst 未对齐,这是不好的。尝试将 RGB565 对(两个连续的 *Dst 写入)组合成一个 32 位副本。您甚至可以尝试覆盖更多像素以使循环更简单,然后再处理边界像素。

希望你明白了。

第二种方式:将转换卸载到 GPU。

为 RGB565PaletteLookupTable 创建一维纹理并编写一个简单的片段着色器,它采用 (Src + RGB565PaletteLookupTable) 并输出 Dst(然后 glTexImage2D 将更新 Src 纹理,而不是像现在那样更新 Dst)

关于ios - 在 iOS 4+ 上优化调色板纹理到 RGB565 的转换(使用查找表),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11215667/

34 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com