[DDSTextureLoader] problem with CreateDDSTextureFromFile and ID3D11DeviceContext::Map


Hi developers.

I am creating a DDS texture in the following way:

HRESULT result = CreateDDSTextureFromFile(device, L"aTexture.dds", &myID3D11Resource, &myShaderResourceView);

HRESULT is OK, but when I execute the following code:

D3D11_MAPPED_SUBRESOURCE mappedSubresource; result = context->Map(myID3D11Resource, 0, D3D11_MAP_READ, 0, &mappedSubresource);

I get the error code E_INVALID_ARG.

I was researching and the problem is that Map assumes that the resource has been created with read access at least (D3D11_MAP_READ).

So I modified code inside DDSTextureLoader.cpp. For test purposes I added an argument to CreateDDSTextureFromFile and FromMemory to choose cpuAccessFlags (attached files have this modifications).

Basically I changed: desc.CPUAccessFlags = cpuAccessFlags; where cpuAccessFlags is an UINT argument. The problem of my modification is that when I execute again:

HRESULT result = CreateDDSTextureFromFile(device, L"aTexture.dds", &myID3D11Resource, &myShaderResourceView, D3D11_CPU_READ);

I got the error code E_INVALID_ARGS at this point (i.e. before ID3D11Context::Map function)

So, is there a solution? a workaround? is this a bug? I am needing to do this because I want to Map textures into a textureArray to be able to use texture2DArray in HLSL.

Closed Oct 23, 2012 at 2:38 AM by ShawnHargreaves
This behavior is how D3D11 is designed to work. See my comments about use of staging resources for CPU readback.


ShawnHargreaves wrote Oct 23, 2012 at 2:37 AM

Not sure what you mean about mapping textures into a texture array. Map is for CPU to set or readback contents of a D3D surface - what does this have to do with creating an array resource?

But anyway, this is not the correct way to read back resource contents in D3D11. Only staging pool surfaces can be mapped for CPU readback, so you must CopyResource or CopySubresourceRegion from a default pool surface into a staging resource before you can map it for CPU read.

nicobertoa wrote Oct 23, 2012 at 4:02 AM

I want to create for example 4 different textures using CreateDDSTextureFromFile and then insert them in the following array.

D3D11_TEXTURE2D_DESC textureArrayDesc;// Fill textureArrayDesc...

// Create texture arrayID3D11Texture2D* textureArray = 0;HRESULT result = device->CreateTexture2D(&textureArrayDesc, 0, &textureArray);

for (uint32_t texElement = 0; texElement { // for each mipmap level... for(uint32_t mipLevel = 0; mipLevel { D3D11_MAPPED_SUBRESOURCE mappedTex2D; result = context->Map(textures[texElement], mipLevel, D3D11_MAP_READ, 0, &mappedTex2D);
            const uint32_t subResourceIndex = D3D11CalcSubresource(mipLevel, texElement,                             textureElementDesc.MipLevels);

            context->UpdateSubresource(textureArray, subResourceIndex, 0,                     mappedTex2D.pData, mappedTex2D.RowPitch, mappedTex2D.DepthPitch);

            context->Unmap(sourceTextures[texElement], mipLevel);    }}
I want to do this because I will then set the texture array in a slot of a Texture2DArray in my shader code.How will you do that?

ShawnHargreaves wrote Oct 23, 2012 at 3:36 PM

Use CopySubresourceRegion.