设置像素数据的最佳方法?

时间:2013-04-16 21:31:53

标签: c# performance xna xna-4.0 texture2d

我正在研究一种“落砂”式的游戏。

我尝试了很多方法将沙子绘制到屏幕上,然而,每种方式似乎都会以某种形式产生一些问题。

我完成的事情清单:

  1. 从像素大小的纹理中一次一个地绘制每个像素。问题:每次更新大约100,000个像素后,速度变慢。

  2. 将每个像素绘制到一个大的texture2d,绘制texture2d,然后清除数据。问题:使用texture.SetPixel()非常慢,即使处理了旧的纹理,它也会导致一个小的内存泄漏(大约每秒30kb,加起来很快),即使在对象上调用dispose之后也是如此。我根本无法弄清楚如何阻止它。但总的来说,这是最好的方法(到目前为止)。如果有办法阻止泄漏,我想听听。

  3. 使用位图中的Lockbits。从位图的角度来看,这非常有效,但不幸的是,我仍然需要将位图转换回texture2d,这会导致帧速率降至小于1。因此,如果我能找到一种在xna中绘制位图而无需转换它(或其他东西)的方法,这有可能很好地工作。

  4. 通过用透明像素替换像素的“旧”位置,将每个像素设置为具有设置像素的texture2d,然后使用正确的颜色设置新位置。这使完成作业所需的像素集数量增加了一倍,并且比使用数字2慢得多。

  5. 所以,我的问题是,还有更好的想法吗?或者关于如何修复样式2或3的想法?

1 个答案:

答案 0 :(得分:1)

我的想法是你正在拖延GPU管道。 GPU可以拥有一个落后于您发出的命令几帧的管道。

因此,如果您发出一个命令来设置纹理上的数据,并且GPU当前正在使用该纹理来渲染旧帧,那么它必须先完成所有渲染才能接受新的纹理数据。所以它等待,杀死你的表现。

此解决方法可能是在双(或甚至三重或四重)缓冲区排列中使用多个纹理。不要尝试写入刚刚用于渲染的纹理。

此外 - 您可以从渲染线程以外的线程写入纹理。这可能会派上用场,特别是对于清除纹理。

正如您似乎发现的那样,在大块中SetData实际上更快,而不是发出许多小SetData次呼叫。确定“块”的理想大小在GPU之间有所不同 - 但它比单个像素大一点。

另外,在原始性能方面(如果忽略我刚才描述的管道效果),创建纹理比重用纹理要慢得多;所以重用那个纹理。

值得一提的是,“像素精灵”需要向GPU发送每像素数据的30倍,而不是纹理。

另请参阅this answer,如果您想深入了解,还有一些详细信息和一些深入的链接。