For some unknown reason, I get corrupted vertex/index/texture buffers (leading to glitchy rendering) in some rare cases when I concurrently create those resources while rendering in a different thread.
Here's a breakdown:
I have a render thread that renders some UI stuff (e.g. a loading progress bar) while a loader thread loads data off the disk. The loader thread calls some D3D11Device Create functions with initialization data (pSysMem of D3D11_SUBRESOURCE_DATA is valid). For some hair pulling reason, some buffers that are initialized this way end up getting corrupted at some point. I am 100% sure that the data being passed in is correct (I verify it before calling Create). When I copy and stage the data to read it back from the CPU (after all loading has completed), indeed the buffer data is not the original data I initialized it to. The buffer device objects themselves are perfectly fine (GetDesc returns the correct creation params).
The buffers that get corrupted are completely random. If I reload the same scene over and over again, it will be a different buffer that gets corrupted each time. This indicates some sort of race condition. The code never crashes, so probably no CPU side stacks/heaps are being corrupted.
I've verified that I never access the ImmediateDeviceContext (of the Render thread) from the Loader thread (or DXGI stuff either). I've remarked all Map/UpdateSubresource calls to ensure I'm not accidentally writing passed buffer ends. The device is being created with the correct flags (i.e. no SINGLE_THREADED flag is set).
This problem does not occur if I load synchronously (i.e. block rendering while loading).
A workaround to this problem is to create a DeferredDeviceContext and use UpdateSubresource to initialize the buffers through the DeferredDeviceContext then flush it in the main render thread when the Loader completes. I lose the ability of defining the buffers as IMMUTABLE and possibly some concurrent driver cleverness in getting the data to the GPU since the copies are really happening when the DeferedContext is flushed in the main render thread.
I've been able to reproduce this problem on different devices (GTX 970 and 680) albeit on the same system.
Has anyone encountered this problem before or have any insights? The documentation makes clear that D3D11Device Create functions are supposed to be re-entrant safe. What could possibly corrupt buffer data on the device?
Many thanks in advance.