Schnappi
Schnappi

Reputation: 125

DirectX11 - Textures and dynamic changes

I have a few questions about DirectX 11.

When I create texture via CreateTexture2D and I specify DEFAULT usage I should be able to use UpdateSubresource, right?

a) Does the memory update must be in the same format as the original texture? I mean when I CreateTexture with DDS DXT1, does the UpdateSubresource data have to be DDS DXT1 too?

b) When is it possible to update resource? In DX12 you can update resoruce before you finish command list. Otherwise nothing happens.

c) I should update each mip with update where each index of subresource is index*miplevels, right?

Or should I use map unmap instead? Is there any good example with all the rules that are necessary for sucessful update?

Upvotes: 1

Views: 4058

Answers (2)

Schnappi
Schnappi

Reputation: 125

So what I found including my solution:

If the texture is created as DYNAMIC you can't Map it if it has more than one mips. (I had more mips in my textures so I had to do it other way)

So I had to go with DEFAULT textures on creation. Then UpdateSubresource and D3D11CalcSubresource in for loop where I updated all mips in the texture. So in my case with simple multi mip-map 2D textures: D3D11CalcSubresource( i, 0, totalMipsInTexture). I managed to update the textures before Present was called (beware of multithreading).

My final recommendation: if you struggle, enable debug layer in DirectX (when you create device pass). It will tell you what are you doing wrong.

Upvotes: 1

Chuck Walbourn
Chuck Walbourn

Reputation: 41087

This most efficient method for loading a texture is to use initData when you create it. You can make it DEFAULT or IMMUTABLE.

The other approach is to use DEFAULT textures and a smaller set of STAGING textures. You load your data into the STAGING textures via Map and then copy via CopyResource. Ideally you reuse STAGING textures (same size, mips, format, etc.). UpdateSubresource works, but is not as efficient--it's most often used for Constant Buffers.

Dynamic textures are really only for things you plan to update every frame or every few frames. Depending on the hardware, they are put into slightly less efficient (for rendering) memory that the GPU and CPU can both access.

Use the helper D3D11CalcSubresource defined in d3d11.h to figure out the subresource:

UINT D3D11CalcSubresource( UINT MipSlice, UINT ArraySlice, UINT MipLevels )
{
    return MipSlice + ArraySlice * MipLevels;
}

This is covered on MSDN in the Programming Guide:

How to: Initialize a Texture Programmatically
How to: Use dynamic resources

See also DDSTextureLoader and WICTextureLoader

Note that you can get some sense of how inefficient UpdateSubresource is by taking a look at the DirectX 12 helper that implements that functionality here.

Upvotes: 4

Related Questions