Okay, with the help of a (not so) old guru, I've found the cause.
In fact D3DX11CreateTextureFromMemory is creating the resource in the RAM by default, and eventually a copy in VRAM if needed.
To fix that, I've changed to _loadds function to create the resource with D3DX11CreateTextureFromMemory, but as a temporary resource.
Then I create the "final" texture, copy the resource and release the temporary one. Now the memory usage is around 300MB where it previously was 1200MB.
Here is the modified function:
Code: Select all
void D3D11Texture::_loadDDS(DataStreamPtr &dstream)
{
HRESULT hr;
MemoryDataStream memStream(dstream,true);
D3DX11_IMAGE_LOAD_INFO loadInfo;
loadInfo.Usage = D3D11Mappings::_getUsage(mUsage);
loadInfo.CpuAccessFlags = D3D11Mappings::_getAccessFlags(mUsage);
if(mUsage & TU_DYNAMIC)
{
loadInfo.MipLevels = 1;
}
// TO DO: check cpu access flags and use loadInfo only when it is needed.
// this is the first try
ID3D11Resource *mpTempTex;
// Load the Texture
if (loadInfo.CpuAccessFlags == D3D11_CPU_ACCESS_WRITE)
{
hr = D3DX11CreateTextureFromMemory( mDevice.get(),
memStream.getPtr(),
memStream.size(),
&loadInfo,
NULL,
&mpTempTex,
NULL );
}
else
{
hr = D3DX11CreateTextureFromMemory( mDevice.get(),
memStream.getPtr(),
memStream.size(),
NULL,
NULL,
&mpTempTex,
NULL );
}
if( FAILED( hr ) )
{
LogManager::getSingleton().logMessage("D3D11 : " + mName + " Could not be loaded");
return;
}
D3D11_RESOURCE_DIMENSION dimension;
mpTempTex->GetType(&dimension);
switch (dimension)
{
case D3D11_RESOURCE_DIMENSION_TEXTURE1D:
{
ID3D11Texture1D *temp1DTex;
_queryInterface<ID3D11Resource, ID3D11Texture1D>(mpTempTex, &temp1DTex);
D3D11_TEXTURE1D_DESC desc;
temp1DTex->GetDesc(&desc);
mSrcWidth = desc.Width;
mSrcHeight = 1;
//create the real final texture
hr = mDevice->CreateTexture1D(
&desc,
NULL,// data pointer
&mp1DTex);
mDevice.GetImmediateContext()->CopyResource (mp1DTex,mpTempTex);
SAFE_RELEASE(mpTempTex);
SAFE_RELEASE(temp1DTex);
//assign the texture
_queryInterface<ID3D11Texture1D,ID3D11Resource>(mp1DTex,&mpTex);
mFormat = D3D11Mappings::_getPF(desc.Format);
mSrcFormat = mFormat;
_create2DResourceView();
}
break;
case D3D11_RESOURCE_DIMENSION_TEXTURE2D:
{
ID3D11Texture2D *temp2DTex;
_queryInterface<ID3D11Resource, ID3D11Texture2D>(mpTempTex, &temp2DTex);
D3D11_TEXTURE2D_DESC desc;
temp2DTex->GetDesc(&desc);
mSrcWidth = desc.Width;
mSrcHeight = desc.Height;
//create the real final texture
hr = mDevice->CreateTexture2D(
&desc,
NULL,// data pointer
&mp2DTex);
mDevice.GetImmediateContext()->CopyResource (mp2DTex,mpTempTex);
SAFE_RELEASE(mpTempTex);
SAFE_RELEASE(temp2DTex);
//assign the texture
_queryInterface<ID3D11Texture2D,ID3D11Resource>(mp2DTex,&mpTex);
mFormat = D3D11Mappings::_getPF(desc.Format);
mSrcFormat = mFormat;
if(desc.ArraySize % 6 == 0 && desc.MiscFlags & D3D11_RESOURCE_MISC_TEXTURECUBE)
mTextureType = TEX_TYPE_CUBE_MAP; //2darray cubemap
else if(desc.ArraySize > 1)
mTextureType = TEX_TYPE_2D_ARRAY;
else
mTextureType = TEX_TYPE_2D;
_create2DResourceView();
}
break;
case D3D11_RESOURCE_DIMENSION_TEXTURE3D:
{
ID3D11Texture3D *temp3DTex;
_queryInterface<ID3D11Resource, ID3D11Texture3D>(mpTempTex, &temp3DTex);
D3D11_TEXTURE3D_DESC desc;
temp3DTex->GetDesc(&desc);
mSrcWidth = desc.Width;
mSrcHeight = desc.Height;
mSrcDepth = desc.Depth;
//create the real final texture
hr = mDevice->CreateTexture3D(
&desc,
NULL,// data pointer
&mp3DTex);
mDevice.GetImmediateContext()->CopyResource (mp3DTex,mpTempTex);
SAFE_RELEASE(mpTempTex);
SAFE_RELEASE(temp3DTex);
//assign the texture
_queryInterface<ID3D11Texture3D,ID3D11Resource>(mp3DTex,&mpTex);
mFormat = D3D11Mappings::_getPF(desc.Format);
mSrcFormat = mFormat;
mTextureType = TEX_TYPE_3D;
_create3DResourceView();
}
break;
}
}
I don't have time right now but I'll submit a patch for it soon.