Mapping a loaded resource fails

Started by
5 comments, last by Hawkblood 7 years, 10 months ago

I have been trying to get my head around DX11, but some things don't make sense. I can load and display textures. I can create, set the data within the texture, and display those textures. I can't seem to lock (map) a loaded texture to save my life!

This is the relevant line for loading (this part works fine):


D3DX11CreateShaderResourceViewFromFileW(ge->Graphics.dev, filename, NULL, NULL, &m_texture, NULL);

Then I try to get to the data:


	HRESULT hr;
	ID3D11Resource *ppResource=NULL;
	gGE.TextureList[Texture].m_texture->GetResource(&ppResource);
	ID3D11Texture2D *pTexture=NULL;
	pTexture=reinterpret_cast<ID3D11Texture2D*>( ppResource );
	D3D11_MAPPED_SUBRESOURCE mappedrec;
	hr=gGE.Graphics.devcon->Map(pTexture,0,D3D11_MAP_READ,NULL,&mappedrec);
	if (FAILED(hr)) MessageBoxW(ghWnd,L"Texture Map",L"mapping failed",MB_OK);

It fails when I try to Map the subresource. Does anyone have example code or can tell me what I'm doing wrong?

Advertisement

Check the hr, please.

void hurrrrrrrr() {__asm sub [ebp+4],5;}

There are ten kinds of people in this world: those who understand binary and those who don't.

it throws a negative number. -2147024809.

XD

That matches one of the error codes in the documentation: https://msdn.microsoft.com/en-us/library/windows/desktop/ff476457%28v=vs.85%29.aspx

Looks like "invalid argument".

Is it possible that the texture does not have mappable usage? http://gamedev.stackexchange.com/questions/102530/how-to-access-raw-texture-data-in-directx-11

void hurrrrrrrr() {__asm sub [ebp+4],5;}

There are ten kinds of people in this world: those who understand binary and those who don't.

E_INVALIDARG

That doesn't help...... It has something to do with the way DX11 does resources.

Here is what I'm wanting to do:

-load a texture from the disk

-make a "collision map" by sampling the alpha channel.

I'm using the texture as a sprite for purposes of a GUI. I don't want to have to deal with only rectangular buttons so I need a collision map for the mouse.

You pass a NULL D3DX11_IMAGE_LOAD_INFO struct when loading the image. Instead, make one of these so you can add some extra options to how the texture is created. Specifically, you want to set the Usage and CpuAccessFlags fields.

However... if you want to load this image data to the CPU, then D3DX11CreateShaderResourceViewFromFileW is a bad way to go about it. This function loads the image data to the CPU, copies it to the GPU, and throws away the CPU copy... then you go and ask D3D11 to copy the data from the GPU back to the CPU for you to read... which is possible, but requires these extra creation options I mentioned above, which will disable the driver from optimizing the GPU memory location/format of this texture...

It would be better to use a different image loading library.

*****SOLUTION******


	HRESULT hr;
	ID3D11Resource *ppResource;
	gGE.TextureList[Texture].m_texture->GetResource(&ppResource);
	D3D11_RESOURCE_DIMENSION pResourceDimension;
	ppResource->GetType(&pResourceDimension);

	auto txt=reinterpret_cast<ID3D11Texture2D*>( ppResource );

	D3D11_TEXTURE2D_DESC desc;
	txt->GetDesc(&desc);
	desc.Usage = D3D11_USAGE_STAGING;
	desc.BindFlags = 0;
	desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
	
	ID3D11Texture2D *pTexture = NULL;
	hr=gGE.Graphics.dev->CreateTexture2D( &desc, NULL, &pTexture );
	if (hr==D3DERR_INVALIDCALL) MessageBoxW(ghWnd,L"Texture Map",L"D3DERR_INVALIDCALL",MB_OK);
	if (hr==E_FAIL) MessageBoxW(ghWnd,L"Texture Map",L"E_FAIL",MB_OK);
	if (hr==E_INVALIDARG) MessageBoxW(ghWnd,L"Texture Map",L"E_INVALIDARG",MB_OK);
	if (hr==E_OUTOFMEMORY) MessageBoxW(ghWnd,L"Texture Map",L"E_OUTOFMEMORY",MB_OK);
	if (hr==E_NOTIMPL) MessageBoxW(ghWnd,L"Texture Map",L"E_NOTIMPL",MB_OK);
	if (hr==S_FALSE) MessageBoxW(ghWnd,L"Texture Map",L"S_FALSE",MB_OK);
	gGE.Graphics.devcon->CopyResource(pTexture,txt);
	D3D11_MAPPED_SUBRESOURCE mappedrec;
	hr=gGE.Graphics.devcon->Map(pTexture,0,D3D11_MAP_READ,NULL,&mappedrec);
	if (FAILED(hr)) MessageBoxW(ghWnd,L"Texture Map",L"mapping failed",MB_OK);

	sx=gGE.TextureList[Texture].Width;
	sy=gGE.TextureList[Texture].Height;
	UINT W=UINT(sx);
	UINT H=UINT(sy);

	CollisionMap=new byte*[W];
	for (UINT i=0;i<W;i++) CollisionMap[i]=new byte[H];
	
	COLOR *C=(COLOR*)mappedrec.pData;
	for (UINT x=0;x<W;x++){
		for (UINT y=0;y<H;y++){
			UINT Loc=(y*W)+x;
			CollisionMap[x][y]=C[Loc].a;

		}
	}
	gGE.Graphics.devcon->Unmap(pTexture,0);
	pTexture->Release();

The key was in the D3D11_TEXTURE2D_DESC. I had to set the BindFlags to 0 because everything else gave me errors. I suppose that's right. The other two parameters I found from reading LOTS of Microsoft DX11 pages. Also, if you set :


desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ|D3D11_CPU_ACCESS_WRITE;

and


hr=gGE.Graphics.devcon->Map(pTexture,0,D3D11_MAP_READ_WRITE,NULL,&mappedrec);

you can do both read and write to that texture (resource)......

This topic is closed to new replies.

Advertisement