How to use ID3D11Device::CreateTexture2D method to create texture array with mipmaps

175 Views Asked by At

I was originally going to use an atlas texture to pass a large number of textures to my shader, but the texture bleed due to mip mapping was unnacceptable. After doing some research, I decided that texture arrays would be perfect.

The code snippet below takes in an array of image buffers at full resolution (mip 0) and an array of pregenerated mipmaps for each one. The code works perfectly with either a set of mip 0 images (ArraySize = n; MipLevels = 1) or a single mip 0 image and its associated mipmaps (ArraySize = 1; MipLevels = n), but the call to CreateTexture2D( ) fails if given both array and mip levels (ArraySize = n; MipLevels = m), returning with code 0x80070057 (invalid parameter).

I have read and re-read the documentation and read every related post on the web I could find, as well as tried everything I could think of. The DirectX 11 documentation says it can be done, so I must be missing something. Any help would be appreciated.

This is the code I'm using to generate the textures. From everything I've read, it should be correct.

// Setup the description of the texture.
    textureDesc.Height = height;
    textureDesc.Width = width;
    textureDesc.MipLevels = mipLevels;
    textureDesc.ArraySize = count;
    textureDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
    textureDesc.SampleDesc.Count = 1;
    textureDesc.SampleDesc.Quality = 0;
    textureDesc.Usage = D3D11_USAGE_IMMUTABLE;
    textureDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
    textureDesc.CPUAccessFlags = 0;
    textureDesc.MiscFlags = 0;

    D3D11_SUBRESOURCE_DATA* subData = new D3D11_SUBRESOURCE_DATA[count*mipLevels];

    for( int i = 0; i < count; i++ ) {

        subData[i*mipLevels].pSysMem = imageDataArray[i*mipLevels];
        subData[i*mipLevels].SysMemPitch = (UINT)(width*4);
        subData[i*mipLevels].SysMemSlicePitch = 0;
        int w = width;
        for( int m = 0; m < mipLevels-1; m++ ) {
            w >>= 1;
            subData[i*mipLevels+m+1].pSysMem = mipsPtr[i][m];
            subData[i*mipLevels+m+1].SysMemPitch = (UINT)(w*4);
            subData[i*mipLevels+m+1].SysMemSlicePitch = 0;
        }
    }

    // Create the empty texture.
    hResult = device->CreateTexture2D(&textureDesc, (D3D11_SUBRESOURCE_DATA*)subData, &texture);
    if( FAILED(hResult) ) {

        return false;
    }
1

There are 1 best solutions below

1
On

I spent a few days trying to track down the problem with this code and knew it should work... I knew it worked, since it worked with either a set of textures or a single mipmap chain. It comes down to a single line:

subData[imipLevels].pSysMem = imageDataArray[imipLevels]; which should be: subData[i*mipLevels].pSysMem = imageDataArray[i];

Now it works! LOL.