为什么`Texture2D`没有公开它的像素数据?

ann*_*sly 2 c# graphics xna texture2d xna-4.0

我可以很容易地想到在一些情况下改变a中的单个像素是有用的Texture2D,特别是因为在不断地做GetData<>(); SetData<>();每一帧或绘图时你会遇到的性能损失和不便RenderTarget2D.

有没有真正的理由公开单个像素的setter方法?如果没有,有没有办法修改单个像素而不使用上述方法?

pos*_*ism 8

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

但是,正如您所注意到的,这使得CPU难以读取或修改数据变得困难和/或变慢.不仅PCIe总线相对较慢,而且VRAM通常不能由CPU直接寻址; 通常必须使用特殊的低级DMA命令传输数据.这就是为什么你看到使用XNA的当性能命中GetData<>()SetData<>():这是不是说的杀了你的函数调用的开销,那就是他们必须来回复制VRAM您的数据背后的事实.

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

  1. 在更改之前暂时"映射"像素数据(包括将其复制回主存储器),并在编辑完成后"取消映射"它(将更改提交回VRAM).这可能是什么GetData<>(),并SetData<>()在内部做.
  2. 使用像OpenGL这样的函数glTexSubImage2D(),它实际上跳过了"map"步骤并将新的像素数据直接复制回VRAM,覆盖了之前的内容.
  3. 通过运行将纹理写入渲染目标的着色器,指示GPU代表您进行修改.

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

(顺便说一句,上面的所有内容对于GPU缓冲区数据也是如此.)