ID3D12GraphicsCommandList& commandList = *com_ptr;
FLOAT values[4] = { 1,1,1,1 };
commandList.ClearUnorderedAccessViewFloat(m_gpuUavHandle, m_cpuUavHandle, m_resource.get(), values, 0, nullptr);
I'm getting the following runtime error:
Access violation reading location 0x0000000000000140
However, m_cpuUavHandle.ptr
has value 326
which is only 6 bytes after the location of the access violation 320
(=140 in hexidecimal).
Since in Direct3d12 you manually calculate the handle address, it seems that there is room for something to go wrong
m_cpuUavHandle = CD3DX12_CPU_DESCRIPTOR_HANDLE(m_descriptorHeap.get()->GetCPUDescriptorHandleForHeapStart(), offset, m_cbvSrvUavDescriptorSize);
Edit:
I succeeded reproducing this in the DirectX 12 samples (and uploaded it to github) and this time got a debug message
D3D12 ERROR: ID3D12CommandList::ClearUnorderedAccessViewFloat: Specified descriptor handle ptr=0x0000000000000021 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]
Now m_cpuUavHandle.ptr=33
and the location of the access violation is at 32 (0x0000000000000020 in hexidecimal).
In my main project I think the exception is hit before the debug message is printed due to threading issues.
Now in my main project I'm getting
Access violation reading location 0x0000000000000000.
which is still six bytes before m_cpuUavHandle.ptr = 6
, so I'm not sure if this is right
mateeeeee solved this in the comments. The docs specify that the cpu descriptor must refer to a non-shader visible heap (one created with D3D12_DESCRIPTOR_HEAP_FLAG_NONE
).
For me the solution is to just have two identical CBV_SRV_UAV heaps one created with D3D12_DESCRIPTOR_HEAP_DESC::Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE
for calling ClearUnorderedAccessViewFloat and the other created with D3D12_DESCRIPTOR_HEAP_DESC::Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE
for everything else.
It is important to note that the cpu descriptor and gpu descriptor arguments for ClearUnorderedAccessViewFloat must come from different heaps.
auto [cpu, gpu] = resources.AllocateDescriptorHandlePair();
m_uavHandle = gpu;
m_cpuUavHandle = cpu;
resources.D3D12Device().CreateUnorderedAccessView(m_resource.get(), nullptr, &uavDesc, cpu);
if (nonshader_visable)
{
m_nonshader_visable_descriptor = resources.AllocateNonVisableDescriptorHandle();
resources.D3D12Device().CreateUnorderedAccessView(m_resource.get(), nullptr, &uavDesc, *m_nonshader_visable_descriptor);
}