How do I correctly use ClearUnorderedAccessViewFloat?

42 views Asked by At

I have a 1-dimensional texture declared as RWTexture1D<float> : register(u1);. I'm writing to this texture in one ray generation shader and read from it from another. I don't need to read the from the texture on the CPU side.

Before the ray generation shader which writes to it is executed, I need to set all values contained in it to zero. I thought ClearUnorderedAccessViewFloat would be the function which does that.

Now, the heap descriptor is created is creates by the following code:

D3D12_DESCRIPTOR_HEAP_DESC desc{};
desc.NumDescriptors = /* ... */;
desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;
desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;

d3d.device->CreateDescriptorHeap(&desc, IID_PPV_ARGS(&m_descriptor_heap));

D3D12_CPU_DESCRIPTOR_HANDLE handle = m_descriptor_heap->GetCPUDescriptorHandleForHeapStart();
m_uav_desc_size = d3d.device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);

And the code for clearing is:

    CD3DX12_GPU_DESCRIPTOR_HANDLE const  gpu_handle{
        m_descriptor_heap->GetGPUDescriptorHandleForHeapStart(),
        m_descriptor_heap_size,
        m_uav_desc_size
    };

    CD3DX12_CPU_DESCRIPTOR_HANDLE const  cpu_handle{
        m_descriptor_heap->GetCPUDescriptorHandleForHeapStart(),
        m_descriptor_heap_size,
        m_uav_desc_size
    };

    FLOAT const clear_value = 0;
    m_cmd_list->ClearUnorderedAccessViewFloat(gpu_handle, cpu_handle, m_texture1d, &clear_value, 0, nullptr);

Unfortunately, this gives the following error:

D3D12 ERROR: ID3D12CommandList::ClearUnorderedAccessViewFloat: Specified descriptor handle ptr=0x0000000000000043 points to a descriptor heap type that is CPU write only, so reading it is invalid. UnorderedAccessViewCPUHandle is the issue. [ EXECUTION ERROR #646: INVALID_DESCRIPTOR_HANDLE]

In this post the same problem is described: https://stackoverflow.com/a/72889175/547231.

The answer says that I should create two descriptor heaps; one with D3D12_DESCRIPTOR_HEAP_FLAG_NONE. However, I don't get that. How do I ensure that they point to the same resources? How would I need to modify the code for ClearUnorderedAccessViewFloat?

1

There are 1 answers

0
mateeeeeee On

You need to have both shader visible and not visible heap. You create your gpu UAV from shader visible heap, and cpu UAV from not visible heap.

CD3DX12_GPU_DESCRIPTOR_HANDLE const  gpu_handle{
        gpu_descriptor_heap->GetGPUDescriptorHandleForHeapStart(),
        gpu_descriptor_heap_size,
        uav_desc_size
    };

    CD3DX12_CPU_DESCRIPTOR_HANDLE const  cpu_handle{
        cpu_descriptor_heap->GetCPUDescriptorHandleForHeapStart(),
        cpu_descriptor_heap_size,
        uav_desc_size
    };

So you will have 2 heaps, gpu_descriptor_heap and cpu_descriptor_heap. gpu_descriptor_heap will be created with D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE, the cpu_descriptor_heap with D3D12_DESCRIPTOR_HEAP_FLAG_NONE.

To ensure they are pointing to the same resource, you can call CreateUnorderedAccessView twice, passing in both cases handles from those heaps with GetCPUDescriptorHandleForHeapStart, or you can call it once for your cpu heap and then call CopyDescriptors to copy it to your shader visible heap.