annonymously
annonymously

Reputation: 4708

Why doesn't `Texture2D` expose its pixel data?

I can easily think of a number of situations where it would be useful to change a single pixel in a Texture2D, especially because of the performance hit and inconvenience you get when constantly doing GetData<>(); SetData<>(); every frame or drawing to a RenderTarget2D.

Is there any real reason not to expose setter methods for single pixels? If not, is there a way to modify a single pixel without using the methods above?

Upvotes: 1

Views: 419

Answers (1)

user1628856
user1628856

Reputation:

Texture data is almost always copied to video memory (VRAM) by the graphics driver when the texture is initialized, for performance reasons. This makes texture fetches by the shaders running on the GPU significantly faster; you would definitely not be happy if every texture cache miss had to fetch the missing data over the PCIe bus!

However, as you've noticed, this makes it difficult and/or slow for the CPU to read or modify the data. Not only is the PCIe bus relatively slow, but VRAM is generally not directly addressable by the CPU; data must usually be transferred using special low-level DMA commands. This is exactly why you see a performance hit when using XNA's GetData<>() and SetData<>(): it's not the function call overhead that's killing you, it's the fact that they have to copy data back and forth to VRAM behind your back.

If you want to modify data in VRAM, the low-level rendering API (e.g. OpenGL or Direct3D 11) gives you three options:

  1. Temporarily "map" the pixel data before your changes (which involves copying it back to main memory) and "unmap" it when your edits are complete (to commit the changes back to VRAM). This is probably what GetData<>() and SetData<>() are doing internally.
  2. Use a function like OpenGL's glTexSubImage2D(), which essentially skips the "map" step and copies the new pixel data directly back to VRAM, overwriting the previous contents.
  3. Instruct the GPU to make the modifications on your behalf, by running a shader that writes to the texture as a render target.

XNA is built on top of Direct3D, so it has to work within these limitations as well. So, no raw pixel data for you!

(As an aside, everything above is also true for GPU buffer data.)

Upvotes: 8

Related Questions