Skip to main content
GameDev.net gamedev.net
🔒 Locked

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

Started by Rancid Oct 23, 2023 at 3:54 AM 2 replies 7.6k views
Original Post
Rancid
Rancid

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

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?

Rancid
Rancid

@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!

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.