Unmap by deffered contex causes NULL pointer exception on NVIDIA cards. Possible driver error

Hello.
There is a problem on NVIDIA cards when we call FinishCommandList between Map and Unmap calls on deffered context. Unmap crashes then in 100% cases.

pDefferedContext->Map(pTexture,0,D3D11_MAP_WRITE_DISCARD,0,&mapRes);
pDefferedContext->FinishCommandList(FALSE,&m_commandlist);
...
pDefferedContext->Unmap(pTexture,0);//this lina throws 0xC0000005: Access violation reading location 0x00000000.

All pointers are valid and Map and FinishCommandList succeed. Also this code works perfectly on AMD cards. pTexture during this code is not used anywere in rendering pipline. Also DirectX11 documentation doesn’t says that it is not allowed to have mapped textures when FinishCommndList is called. So in my opinion there is a bug on nvidia drivers side and something which shouldn’t be freed is freed during FinishCommandList.

You might want to check the driver command list support on AMD cards, using ID3D11Device::CheckFeatureSupport() with an argument of D3D11_FEATURE_THREADING. I don’t believe AMD drivers use driver command lists, instead letting the D3D11 API build command lists for the driver, whereas the GeForce drivers do support that D3D11 feature. That’s probably where the difference in behaviour stems from.

The actual problem with the Map/Unmap is I believe related to how deferred command lists treat mapping dynamic resources. My understanding is deferred maps with discard aren’t actually deferred and occur the same way an immediate map with discard will, creating a temporary resource that is then swapped with the actual resource later. That way you can map and modify the resource while it’s still being used by the GPU on previous draw commands, without causing a stall.

When you call FinishCommandList on a deferred context, I believe it’s resetting all associations with that context, including associations to any temporary aliases of resources you mapped. FinishCommandList essentially makes a deferred context’s relationship to any calls made prior to FinishCommandList the same as it’s relationship to an entirely different deferred context. So trying to Unmap a resource after calling FinishCommandList is like trying to Unmap a resource mapped by a different deferred context.

So the difference in behaviour you’re seeing is just different responses to an illegal Unmap call. With an AMD driver it is D3D11 handling command list creation and possibly deals with the mapped resource differently to the nvidia driver’s own command list creation. It seems D3D11 deals with it more graciously.

In short, to my understanding, you should treat command lists generated by the same deferred context the same as you would with command lists generated by seperate deferred contexts. It’s also my understanding that due to the way mapping with discard works regarding temporary resource aliasing, you should always unmap dynamic resources within the same command list you map them with, or map/unmap with the immediate context directly.

More info:

API level discussion of map/unmap: http://msdn.microsoft.com/en-us/library/windows/desktop/ff476880(v=vs.85).aspx
Driver level discussion of map/unmap: http://msdn.microsoft.com/en-us/library/windows/hardware/ff568288(v=vs.85).aspx

Quick Edit:

It’s also worth mentioning that, because deferred map creates an alias of the resource, it has an immediate memory cost. The memory that the deferred map allocates may only be freed upon releasing the command list. That presents a serious memory problem if you’re re-using a commandlist that contains a resource map, so I think it’s best practise to release any mapping commandlist every frame. If you want to re-use a command list rather than release and re-create, you should move any map calls to the immediate context (or a commandlist you will release after executing).

Nevermind, I was thinking about where I’d remembered that from, and cant find any mention. It is apparently faster to do your mapping on the immediate context though, since in D3D11 command lists (non-driver) the deferred mapped resource data is copied twice (once on the deferred context to a temp location, second time during commandlist execution on the immediate context it’s copied from the temp location to the GPU driver). I’m not certain but I think the same penalty doesn’t apply on nvidia GPUs since the deferred map can interact directly with the GPU driver. That probably also explains why your illegal unmap call only causes an exception on nvidia GPUs.

hello. Thank you for your response. What I see from what you are writing is that the problem lays in different interpretations what FinishCommandList should do. My understanding of DX documentation is similar to what really happens when you let DX manage command list, because, as you wrote, that is happening on AMD. So in that case FinishCommandList is not resetting associations and it works fine.
In my case this texture was just newly created and it was never associated to any stage of rendering pipeline so it shouldn’t cause any stall.
Anyway thanks for answer. After that I knew that it was not treated as a bug and it would work the same in the future, so I made workaround and it’s working.
Cheers