2

我可以很容易地想到在很多情况Texture2DGetData<>(); SetData<>();更改RenderTarget2D.

有什么真正的理由为单个像素公开设置方法吗?如果没有,有没有办法在不使用上述方法的情况下修改单个像素?

4

1 回答 1

8

出于性能原因,纹理数据在初始化纹理时几乎总是由图形驱动程序复制到视频内存 (VRAM)。这使得 GPU 上运行的着色器获取纹理的速度显着加快;如果每个纹理缓存未命中都必须通过 PCIe 总线获取丢失的数据,您肯定会不高兴!

但是,正如您所注意到的,这会使 CPU 读取或修改数据变得困难和/或变慢。不仅 PCIe 总线相对较慢,而且 VRAM 通常不能被 CPU 直接寻址;数据通常必须使用特殊的低级 DMA 命令传输。这正是您在使用 XNA 时看到性能下降的原因GetData<>(),并且SetData<>():杀死您的不是函数调用开销,而是他们必须在您背后将数据来回复制到 VRAM 的事实。

如果您想修改 VRAM 中的数据,低级渲染 API(例如 OpenGL 或 Direct3D 11)为您提供了三个选项:

  1. 在更改之前临时“映射”像素数据(包括将其复制回主内存)并在编辑完成时“取消映射”它(将更改提交回 VRAM)。这可能是GetData<>()内部SetData<>()正在做的事情。
  2. 使用像 OpenGL's 这样的函数glTexSubImage2D(),它基本上跳过“映射”步骤并将新的像素数据直接复制回 VRAM,覆盖以前的内容。
  3. 通过运行将纹理写入作为渲染目标的着色器,指示 GPU 代表您进行修改。

XNA 建立在 Direct3D 之上,因此它也必须在这些限制范围内工作。所以,没有原始像素数据给你!

(顺便说一句,以上所有内容也适用于 GPU 缓冲区数据。)

于 2012-09-08T04:04:41.910 回答