Falcor icon indicating copy to clipboard operation
Falcor copied to clipboard

asynchronous rendering of two threads

Open bryan05 opened this issue 7 years ago • 4 comments

I got an error.

D3D12 CORRUPTION: ID3D12CommandList::ClearRenderTargetView: Two threads were found to be executing methods associated with the same CommandList at the same time. This will cause corruption of memory. Appropriate thread synchronization needs to occur external to the Direct3D API. 20076 and 22772 are the implicated thread ids. [ MISCELLANEOUS CORRUPTION #18: CORRUPTED_MULTITHREADING]

The crash line on the first threads is:

    ID3D12ResourcePtr createBuffer(FBuffer::State initState, size_t size, const D3D12_HEAP_PROPERTIES& heapProps, FBuffer::BindFlags bindFlags)
    {
  ........
        ID3D12ResourcePtr pApiHandle;
        d3d_call(pDevice->CreateCommittedResource(&heapProps, D3D12_HEAP_FLAG_NONE, &bufDesc, d3dState, nullptr, IID_PPV_ARGS(&pApiHandle)));

another crash line on the second thread is:

   void RenderContext::clearRtv(const RenderTargetView* pRtv, const glm::vec4& color)
    {
        resourceBarrier(pRtv->getResource(), FResource::State::RenderTarget);
        mpLowLevelData->getCommandList()->ClearRenderTargetView(pRtv->getApiHandle()->getCpuHandle(0), glm::value_ptr(color), 0, nullptr);
        mCommandsPending = true;
    }

I try to create the two RenderContexts and swapchain in different command queues, but the problem is not solved. I want the two threads run independently, but it seems it doesn't work

bryan05 avatar Oct 18 '18 00:10 bryan05

I tried to use two ResourceAllocator for the two render context, but I found the performance deteriorate (no threading).

bryan05 avatar Oct 24 '18 21:10 bryan05

It has nothing to do with the create. My guess is that thread 1 dispatched an execute which triggered a GPU execution but doesn't block the CPU, that's why you're seeing the crash inside createBuffer.

I think the problem is that some commands always use the main command-list (by calling gpDevice->getRenderContext()). Need to make them thread aware and make sure to use the correct context

nbentyNV avatar Oct 24 '18 21:10 nbentyNV

yes I think you are right. but I have a question, the two threads both use one ResourceAllocator, right now the creation of ResourceAllocator is like this: mpResourceAllocator = ResourceAllocator::create(1024 * 1024 * 2, mpRenderContext->getLowLevelData()->getFence()); it uses the first render context'fence. But in my case the second render context's flush in another thread may be faster or slower than the first render context, so that means the fence value may be not equal to the first one. in Device::executeDeferredReleases() you use the first fence value to release the buffer, mpFrameFence->gpuSignal(mpRenderContext->getLowLevelData()->getCommandQueue()); uint64_t gpuVal = mpFrameFence->getGpuValue(); while (mDeferredReleases.size() && mDeferredReleases.front().frameID <= gpuVal) { mDeferredReleases.pop(); } I think this fence value not good for asynchronous rendering of two threads

bryan05 avatar Oct 24 '18 21:10 bryan05

Change the code so that the resource-allocator gets the Device::mpFrameFence, that will remove the dependency on the render-context

nbentyNV avatar Oct 25 '18 17:10 nbentyNV