3ddirectxdirectx-12

DispatchRays complains about (in)correct descriptor heap


I am trying to dispatch a compute shader before switching to my raytracing pipeline in DirectX 12 so I have two different pipeline states. One for the compute shader and one for raytracing. The raytracing pipeline has worked well previously but now I am trying to use a compute shader to generate noise for ambient occlusion and store it in a texture, then copy the texture to the descriptor heap used by the raytracing pipeline. But after switching back to the raytracing pipeline and doing my DispatchRays-call I get the following error:

D3D12 ERROR: ID3D12CommandList::DispatchRays: The descriptor heap (0x0000012094789250:'Compute Heap') containing handle 0x1868acf14000000 is different from currently set descriptor heap 0x0000012094787CE0:'DXR Heap'. [ EXECUTION ERROR #554: SET_DESCRIPTOR_HEAP_INVALID]

My descriptor heaps look like this:

Noise heap:
1 - UAV for a 2D texture

DXR heap:
1 - UAV for 2D texture for output
2 - SRV for TLAS
3 - CBV for camera properties
4 - CBV for light properties
5 - SRV for material data
6 - UAV for noise 2D texture

This is what I have tried to do for rendering:

commandList->SetPipelineState(computeShaderState);
commandList->SetComputeRootSignature(computeShaderSignature);
commandList->SetDescriptorHeaps(1, &computeHeap);
commandList->SetComputeRootDescriptorTable(0, computeHeap->GetGPUDescriptorHandleForHeapStart());

// calculate dispatch args
UINT xwidth = static_cast<UINT>(ceil(texWidth / 32.f));
UINT xheight = static_cast<UINT>(ceil(texHeight / 32.f));
commandList->Dispatch(xwidth, xheight, 1);

// copy texture from computeHeap resource to dxrHeap resource

// switch to DXR pipeline
commandList->SetPipelineState1(dxrState);
commandList->SetDescriptorHeaps(1, &dxrHeap);

// transition output texture
// compute dispatch-rays description

commandList->DispatchRays(&dxrDesc); // <- this line throws error

// switch to raster-pipeline to draw ImGUI
commandList->SetPipelineState(rasterState);
commandList->SetDescriptorHeaps(1, &rasterHeap);
// draw ImGui stuff

There are two things that confuse me, the first one is that the error I'm getting from the ray dispatch call complains that the compute heap is different from the currently set heap which is the DXR heap. But at that point I want the DXR heap to be set since it has all the resources needed for raytracing. The second thing is that I have been able to switch between raytracing and raster for the GUI previously, but now when I'm trying to also switch between a compute state I get the aforementioned error.

I found this old post which has a similar error, but in that post the current descriptor heap is null which mine is not, and I believe that my code above conforms with Chuck Walbourn's answer to that post.

Ideally I want the compute shader to be dispatched and write to the texture. Then I want to copy said texture to another texture which belongs to a different descriptor heap such that I can use the texture generated from my compute shader inside my hit shader for better randomness in secondary rays.


Solution

  • You need to set your compute root descriptor table again but pointing to dxr heap - because one that's been previously set points to different descriptor heap, so basically setting a table which contains UAV again except it is in different heap, like that:

    commandList->SetPipelineState(computeShaderState);
    commandList->SetComputeRootSignature(computeShaderSignature);
    commandList->SetDescriptorHeaps(1, &computeHeap);
    commandList->SetComputeRootDescriptorTable(0, computeHeap->GetGPUDescriptorHandleForHeapStart());
    
    // calculate dispatch args
    UINT xwidth = static_cast<UINT>(ceil(texWidth / 32.f));
    UINT xheight = static_cast<UINT>(ceil(texHeight / 32.f));
    commandList->Dispatch(xwidth, xheight, 1);
    
    // copy texture from computeHeap resource to dxrHeap resource
    
    // switch to DXR pipeline
    commandList->SetPipelineState1(dxrState);
    commandList->SetDescriptorHeaps(1, &dxrHeap);
    
    
    // HERE ; !!! dont forget to use your/correct root parameter index etc :^)
    commandList->SetComputeRootDescriptorTable(0, dxrHeap->GetGPUDescriptorHandleForHeapStart());
    
    
    // transition output texture
    // compute dispatch-rays description
    
    commandList->DispatchRays(&dxrDesc);
    
    // switch to raster-pipeline to draw ImGUI
    commandList->SetPipelineState(rasterState);
    commandList->SetDescriptorHeaps(1, &rasterHeap);
    // draw ImGui stuff
    

    The reason why previously you didn't had this error might depend on how your code looked like before, maybe you was using same descriptor heap/table's, or maybe you wasn't using these in graphics pipeline at all.. i have no idea. Im also not sure if its even needed/good idea to use different descriptor heaps, and it also might be possible to use just two PSO's created with pipeline state stream and only one heap, for example combine your dxr with graphics pipeline, and use separate PSO for compute shader noise texture generation once(at startup) or in async manner - noise generation tends to be expensive, but it might be more complicated than that so its just my speculations sorry.

    Ideally I want the compute shader to be dispatched and write to the texture. Then I want to copy said texture to another texture which belongs to a different descriptor heap such that I can use the texture generated from my compute shader inside my hit shader for better randomness in secondary rays.

    The easiest way is to just at initialization of your app create second UAV using CreateUnorderedAccessView method, or/and use already existing heap since your root signature seems to be the same anyway - so use one heap for both compute shader and dxr shader views(maybe even graphics), to avoid duplicate views.

    It might be possible to use CopyDescriptors method but its unclear to me how it works and just excessive in this situation.

    (You might also need to do use SetGraphicsRootDescriptorTable in your draw pass for your graphics pipeline resources, depending on design.)

    Hopefully i wont get downvoted, im still learning dx12 so i might be wrong sorry.