KIM CHANGJUN
KIM CHANGJUN

Reputation: 129

error when creating 2d texture with dynamic format

i am pretty newbie on directx. and i am stumbling with handling resource.

Okay First, i created texture that i can read/write in GPU, and it worked well. And now, as you can check in my code, i wanted to read this texture in CPU as well(reading from application side), so i edited the usage from USAGE_DEFAULT to USAGE_DYNAMIC.

Microsoft::WRL::ComPtr<ID3D11Texture2D> outputTexture;

D3D11_TEXTURE2D_DESC outputTex_desc;
outputTex_desc.Format = DXGI_FORMAT_R32_FLOAT;
outputTex_desc.Width = 3;
outputTex_desc.Height = 3;
outputTex_desc.MipLevels = 1;
outputTex_desc.ArraySize = 1;
outputTex_desc.BindFlags = D3D11_BIND_UNORDERED_ACCESS | 
                           D3D11_BIND_SHADER_RESOURCE;
outputTex_desc.SampleDesc.Count = msCount;
outputTex_desc.SampleDesc.Quality = msQuality;
outputTex_desc.Usage = D3D11_USAGE_DYNAMIC;
outputTex_desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
outputTex_desc.MiscFlags = 0;

// CREATE 'TEXTURE'
device->CreateTexture2D(      // FAIL HERE !!!
            &outputTex_desc,
            nullptr,
            outputTexture.GetAddressOf());
// CREATE 'SRV'
...
// CREATE 'UAV'
...

and it starts failing exactly when it executes the 'device->CreateTexture2D()'

any advice would be amazing.

Upvotes: 0

Views: 1724

Answers (2)

mrvux
mrvux

Reputation: 8963

In order to access a texture from cpu (read mode), you need you create a separate staging texture, then copy your texture into it.

These are the flags for the gpu only texture (please note I force sample count to 1, as UAV access is not allowed for multisampled textures)

D3D11_TEXTURE2D_DESC gpuTexDesc;
gpuTexDesc.Format = DXGI_FORMAT_R32_FLOAT;
gpuTexDesc.Width = 3;
gpuTexDesc.Height = 3;
gpuTexDesc.MipLevels = 1;
gpuTexDesc.ArraySize = 1;
gpuTexDesc.BindFlags = D3D11_BIND_UNORDERED_ACCESS | 
                       D3D11_BIND_SHADER_RESOURCE;
gpuTexDesc.SampleDesc.Count = 1;
gpuTexDesc.SampleDesc.Quality = 0;
gpuTexDesc.Usage = D3D11_USAGE_DEFAULT;
gpuTexDesc.CPUAccessFlags = D3D11_CPU_ACCESS_NONE;
gpuTexDesc.MiscFlags = 0;

Then you create a second texture for reading

D3D11_TEXTURE2D_DESC readTexDesc;
readTexDesc.Format = DXGI_FORMAT_R32_FLOAT;
readTexDesc.Width = 3;
readTexDesc.Height = 3;
readTexDesc.MipLevels = 1;
readTexDesc.ArraySize = 1;
readTexDesc.BindFlags = 0; //No bind flags allowed for staging
readTexDesc.SampleDesc.Count = 1;
readTexDesc.SampleDesc.Quality = 0;
readTexDesc.Usage = D3D11_USAGE_STAGING; //need staging flag for read
readTexDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
readTexDesc.MiscFlags = 0;

then you can use CopyResource:

deviceContext->CopyResource(readTex, gpuTex);

Once done, you can finally access texture data for reading using Map

D3D11_MAPPED_SUBRESOURCE MappedResource;
deviceContext->Map(readTex, 0, D3D11_MAP_READ, 0, &MappedResource);

MappedResource will give you access to data in cpu, once you done processing, don't forget to Unmap the resource.

deviceContext->Unmap(readTex, 0);

Upvotes: 0

Chuck Walbourn
Chuck Walbourn

Reputation: 41087

The first two steps in debugging any Direct3D 11 program is:

  1. Make sure you are checking every HRESULT for either success (SUCCEEDED macro) or failure (FAILED macro). If it is safe to ignore the return value at runtime, then the function returns void. See ThrowIfFailed.
  2. Enable the Direct3D debug device and look for debug output (a.k.a. use D3D11_CREATE_DEVICE_DEBUG in your Debug configuration).

If you enable the Direct3D debug device, you'll get detailed information on why the API returns failure codes in many cases.

If you did that, you'd see the error for this code:

D3D11 ERROR: ID3D11Device::CreateTexture2D: A D3D11_USAGE_DYNAMIC Resource
may only have the D3D11_CPU_ACCESS_WRITE CPUAccessFlags set.
[ STATE_CREATION ERROR #98: CREATETEXTURE2D_INVALIDCPUACCESSFLAGS]

In order to READ it on the CPU, you must copy to a D3D11_USAGE_STAGING Resource first. For example source code on doing that, see the ScreenGrab code from DirectX Tool Kit.

You don't mention what your msCount or msQuality values are here. I assumed 1, and 0 respectively. If you use any other values, you'll get:

D3D11 ERROR: ID3D11Device::CreateTexture2D: Multisampling is not supported
with the D3D11_BIND_UNORDERED_ACCESS BindFlag.  SampleDesc.Count must be 1
and SampleDesc.Quality must be 0.
[ STATE_CREATION ERROR #99: CREATETEXTURE2D_INVALIDBINDFLAGS]

Upvotes: 1

Related Questions