Advertisement

ID3D11Device::CreateTexture2D method fails to create texture array with mipmaps

Started by October 23, 2023 03:54 AM
2 comments, last by Rancid 1 year, 1 month ago

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.

// 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;
	}

Does the creation call fail when not specifying initial data? If not, have you tried creating it empty and then incrementally filling it with CopySubresourceRegion for each mip for diagnostic purposes? Also, is the level 0 width an even power of two, such that your bitshift doesn't create any rounding error disparity to what D3D11 runtime expects for the mip data dimensions? Have you verified with runtime asserts that none of the entries in mipsPtr are nullptr?

Advertisement

@Annisquam17 OMG, I had gone over the code a million times, and going through the code one more time to add a few mor debugging statements and make sure everything was right, I noticed this line:

subData[i*mipLevels].pSysMem = imageDataArray[i*mipLevels];

that should read:

subData[i*mipLevels].pSysMem = imageDataArray[i];

It works perfectly now!

This topic is closed to new replies.

Advertisement