Texture2DArray

Started by
3 comments, last by pastillman8 9 years, 12 months ago

I'm wanting to draw a large number of rectangles (in the thousands), each of which displaying a particular texture from an upfront generated pool of textures(around 250, all of which are the same size/format). Whilst there are thousands of rectangles, there is only going to be around 10 - 20 different textures needed each frame, as many of the rectangles share the same texture. However, the 20 textures used in one frame could be completely different to the textures used in the next.

Currently I'm doing this using a draw call per rectangle, resulting in thousands of drawcalls per frame. I'd like to experiment with how it could be split up over fewer drawcalls. My plan is to have one giant dynamic buffer that [all/or some] of the rects get writtin to each frame, and store the textureID in the vertex data, for example each vertex would have the layout [Pos,UV, TexIndex]. I would then setup a Texture2DArray in the shader that will be updated each frame for the textures.

How do I update the Texture2DArray each frame though?

Do I really have to recreate the array each frame, resulting in passing the data of 20 textures from cpu to gpu? .. or is there a more efficient way to do it?

Ideally, it like to just load up the texture pool on the GPU, and then each frame, pluck out the ones I want to fill the texture array, is something like that possible?

Advertisement

You need to use UpdateSubresource to update it. This will require you to have a second texture with staging usage that you upload the data to (via UpdateSubresource) and then you can copy from the staging resource over to the actual texture array that you will use in your rendering.

That assumes that the data has to come from the CPU every frame. If you can create textures ahead of time for each of your tiles, then you could just copy them directly to your array and avoid the CPU completely. This is most likely the preferred way to do it.

One final note - have you considered using a texture atlas instead of an array? That would probably allow you to have access to all of your textures without messing with the texture resources every frame, and then you can just update your rect data to have the right offset into the atlas. Then you could use instancing to reduce the amount of data you are storing per rect, and it should be ready to go!

I was playing around with sprite rendering a few weeks ago. I used OpenGL, but the same technique should be supported by DirectX 11.

Basically I have 32 different sprite images, all the same format and resolution, so I create a 128x128x32 2D texture array. You only have to create the texture array once, as it should contain all the sprites you may want to use during any frame. Next I create a shader storage buffer (think they are called UAVs in DX11, but a constant buffer could also work depending on the number of sprites.) This buffer contains a transformation matrix to handle the position, scale, and rotation of the sprite, it also contains an integer to act as an index into my texture array. All you have to do each frame is update this buffer. For rendering I use instancing, so that all the sprites can be drawn with a single draw call. In the shader you index into the memory buffer using the instance id.

Can you just out all 250 items into the array at the start, and not bother about updating it?

Thanks guys, I think the Atlas approach would be more efficient

This topic is closed to new replies.

Advertisement