Jump to content
  • Advertisement
_Camus_

DX11 D3D11 CubeMap GenerateMips only update one face.

This topic is 377 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hello, I would like to generate mipmaps for a RGBA8 texture, however it only works for one face. Here my source:

 

D3D11_TEXTURE2D_DESC desc = { 0 };
	desc.Width = this->x;
	desc.Height = this->y;

	if(cil_props & CIL_CUBE_MAP)
		desc.ArraySize = 6;
	else
		desc.ArraySize = 1;

	if (this->props&TEXT_BASIC_FORMAT::CH_ALPHA)
		desc.Format = DXGI_FORMAT_R8_UNORM;
	else
		desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;

	desc.SampleDesc.Count = 1;
	desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;	
	
	desc.MiscFlags = 0;
	if (cil_props & CIL_CUBE_MAP) {
		desc.MiscFlags = D3D11_RESOURCE_MISC_TEXTURECUBE;		
	}
	desc.MipLevels = 0;
	desc.MiscFlags |= D3D11_RESOURCE_MISC_GENERATE_MIPS;

	HRESULT hr;
	hr = D3D11Device->CreateTexture2D(&desc, nullptr, Tex.GetAddressOf());

	if (hr != S_OK) {
		this->id = -1;
		return;
	}

	D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc{};
	srvDesc.Format = desc.Format;
	if (cil_props & CIL_CUBE_MAP) {
		srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;
		srvDesc.Texture2D.MipLevels = -1;
		srvDesc.TextureCube.MipLevels = -1;
	}
	else {
		srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
		srvDesc.Texture2D.MipLevels = -1;
	}


	D3D11Device->CreateShaderResourceView(Tex.Get(), &srvDesc, pSRVTex.GetAddressOf());

	D3D11_SUBRESOURCE_DATA initData[6];
	int bufferSize = this->size/6;
	if (cil_props & CIL_CUBE_MAP) {
		unsigned char *pHead = buffer;
		for (int i = 0; i < 6; i++) {
			initData.pSysMem = pHead;
			initData.SysMemPitch = sizeof(unsigned char) * this->x * 4;
			pHead += bufferSize;
		}
	}else {
		initData[0].pSysMem = buffer;
		initData[0].SysMemPitch = sizeof(unsigned char) * this->x * 4;
	}

	if (cil_props & CIL_CUBE_MAP) {
		for (int i = 0; i < 6; i++) {
			D3D11DeviceContext->UpdateSubresource(Tex.Get(), i, 0, initData.pSysMem, initData.SysMemPitch, size); //size is the size of the entire buffer
		}
	}else {
		D3D11DeviceContext->UpdateSubresource(Tex.Get(), 0, 0, buffer, initData[0].SysMemPitch, 0);
	}


	D3D11DeviceContext->GenerateMips(pSRVTex.Get());

 

This code assume RGBA (32 bpp) and no mipmaps in the buffer. This is how it looks without mipmaps:

 

nomip.thumb.png.81be870adaaa65262456cdfbc1842923.png

This is how it looks with the code above, only one face is updated but curiously, that face alone does have mipmaps:

mipbad.thumb.png.26f8890e23b2ddac162ec0b04e330c46.png

 

Can anyone help me, I can add mipmaps offline but this should work, I would like to handle were the buffer is a cubemap and doesn't have any mipmaps. I tried on Intel and Nvidia, so I guess is not a driver issue, but something I am doing wrong.

 

Thanks!

Edited by _Camus_

Share this post


Link to post
Share on other sites
Advertisement

You seem to be updating subresource 'i' here:

D3D11DeviceContext->UpdateSubresource(Tex.Get(), i, 0, initData[i].pSysMem, initData[i].SysMemPitch, size);

Whereas you should be updating subresource index D3D11CalcSubresource(mip, slice, numMips).

The 6 mips you want to update are not subresources 0,1,2,3,4,5, but rather (0 * numMips), (1 * numMips), (2 * numMips)... etc.

Edited by ajmiles

Share this post


Link to post
Share on other sites
2 hours ago, ajmiles said:

You seem to be updating subresource 'i' here:


D3D11DeviceContext->UpdateSubresource(Tex.Get(), i, 0, initData[i].pSysMem, initData[i].SysMemPitch, size);

Whereas you should be updating subresource index D3D11CalcSubresource(mip, slice, numMips).

The 6 mips you want to update are not subresources 0,1,2,3,4,5, but rather (0 * numMips), (1 * numMips), (2 * numMips)... etc.

 

Thank you so much! I was doing it wrong, changed to:

int MipMapCount = 1 + floor(log10((float)max(this->x, this->y)) / log10(2.0));
	if (cil_props & CIL_CUBE_MAP) {
		for (int i = 0; i < 6; i++) {
			for (int j = 0; j < MipMapCount; j++) {
				D3D11DeviceContext->UpdateSubresource(Tex.Get(), D3D11CalcSubresource(j, i, MipMapCount), 0, initData[0].pSysMem, initData[0].SysMemPitch, size);
			}
		}
	}else {
		D3D11DeviceContext->UpdateSubresource(Tex.Get(), 0, 0, buffer, initData[0].SysMemPitch, 0);
	}

And now it's working just fine! 

mipmap.thumb.png.69c106d0ee36b0147590f17eb49a98ee.png

 

Thank you once again!

Share this post


Link to post
Share on other sites

If you'd like to get rid of the iffy looking calculation for "MipMapCount", just call Tex->GetDesc() and the MipCount field will be populated with the actual mip count (rather than the 0 you filled it in with to create it).

Glad it's working!

Share this post


Link to post
Share on other sites

In fact it was wrong, I was sending the same face all the time and making it for all the mipmaps is not needed. I also followed your advice and used the desc to get the mipmap count! Thanks, this is the working code:

 

D3D11_TEXTURE2D_DESC pDesc;
	Tex->GetDesc(&pDesc);
	int MipMapCount = pDesc.MipLevels;
	if (cil_props & CIL_CUBE_MAP) {
		for (int i = 0; i < 6; i++) {
				D3D11DeviceContext->UpdateSubresource(Tex.Get(), D3D11CalcSubresource(0, i, MipMapCount), 0, initData.pSysMem, initData.SysMemPitch, 0);
		}
	}else {
		D3D11DeviceContext->UpdateSubresource(Tex.Get(), 0, 0, buffer, initData[0].SysMemPitch, 0);
	}

 

And the correct output:

Correct.thumb.png.5e2f3bf12b6ec1b9a797732d24f8ddad.png

 

Again, thanks for the time.

Share this post


Link to post
Share on other sites

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!