[D3D12] ClearUnorderedAccessViewFloat fails

Started by
4 comments, last by _void_ 8 years, 6 months ago
Hello,
I am getting the following error while calling ClearUnorderedAccessViewFloat on a resource.
D3D12 ERROR: ID3D12CommandList::ClearUnorderedAccessViewFloat: Specified descriptor handle ptr=0x00D9A488 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]
I cannot really sort this out on my own and would like to ask about your assistance :-)

?This is my wrapper around DX descriptor heap.

DXDescriptorHeapDesc::DXDescriptorHeapDesc(D3D12_DESCRIPTOR_HEAP_TYPE type, UINT numDescriptors, bool shaderVisible)
{
	Type = type;
	NumDescriptors = numDescriptors;
	Flags = shaderVisible ? D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE : D3D12_DESCRIPTOR_HEAP_FLAG_NONE;
	NodeMask = 0;
}

DXDescriptorHeap::DXDescriptorHeap(DXDevice* pDevice, const DXDescriptorHeapDesc* pDesc, LPCWSTR pName)
{
	DXVerify(pDevice->GetDXObject()->CreateDescriptorHeap(pDesc, IID_PPV_ARGS(GetDXObjectAddress())));
		
	mHeapStartCPUDescriptor = GetDXObject()->GetCPUDescriptorHandleForHeapStart();

	if (pDesc->Flags & D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE)
		mHeapStartGPUDescriptor = GetDXObject()->GetGPUDescriptorHandleForHeapStart();
	else
		mHeapStartGPUDescriptor.ptr = 0;

	mDescriptorIncrementSize = pDevice->GetDXObject()->GetDescriptorHandleIncrementSize(pDesc->Type);

#ifdef _DEBUG
	SetName(pName);
#endif
}

D3D12_CPU_DESCRIPTOR_HANDLE DXDescriptorHeap::GetCPUDescriptor(UINT index)
{
	D3D12_CPU_DESCRIPTOR_HANDLE descriptor;
	descriptor.ptr = mHeapStartCPUDescriptor.ptr + index * mDescriptorIncrementSize;
	return descriptor;
}

D3D12_GPU_DESCRIPTOR_HANDLE DXDescriptorHeap::GetGPUDescriptor(UINT index)
{
	D3D12_GPU_DESCRIPTOR_HANDLE descriptor;
	descriptor.ptr = mHeapStartGPUDescriptor.ptr + index * mDescriptorIncrementSize;
	return descriptor;
}

Creating descriptor heap for UAV and UAV


DXDescriptorHeapDesc uavHeapDesc(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, 1, true);
mpUAVHeap = new DXDescriptorHeap(mpDevice, &uavHeapDesc, L"mpUAVHeap");

// And other init stuff
mpDevice->CreateUnorderedAccessView(mpBlendTexture, nullptr, &uavDesc, mpUAVHeap->GetCPUDescriptor(kRootParamBlendTexture));

Calling clear operation


const FLOAT clearValue[4] = {0.4f, 0.4f, 0.4f, 1.0f};
D3D12_GPU_DESCRIPTOR_HANDLE gpuHandle = mpUAVHeap->GetGPUDescriptor(kRootParamBlendTexture);
D3D12_CPU_DESCRIPTOR_HANDLE cpuHandle = mpUAVHeap->GetCPUDescriptor(kRootParamBlendTexture);
mpCommandList->ClearUnorderedAccessViewFloat(gpuHandle, cpuHandle, mpBlendTexture, clearValue);

MSDN documentation (https://msdn.microsoft.com/en-us/library/windows/desktop/dn903849(v=vs.85).aspx) states that cpu handle "Describes the CPU descriptor handle that represents the start of the heap for the render target to clear."

Initially, I thought that it is a typo as they mention render target here but after getting this error I am not sure.

Do you have any idea why I might be getting the error? Is it really a typo with the render target? Or they refer to UAV as render target in general not RTV specifically?

Many thanks indeed!

?

Advertisement

I found this table at the very bottom of https://msdn.microsoft.com/en-us/library/windows/desktop/dn899199(v=vs.85).aspx

I ?was assuming that when you create a descriptor heap then it will be always CPU visible. And if you specify D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE, it will be both CPU and GPU visible.

In that MSDN table they have to columns: shader visible, CPU write only and non shader visible, CPU read/write for descriptor heap.

The error I have "Specified descriptor handle ptr=0x00D9A488 points to a descriptor heap type that is CPU write only, so reading it is invalid."? seems to indicate that I have the first type of descriptor heap. Probably, I have to create one more descriptor heap with D3D12_DESCRIPTOR_HEAP_FLAG_NONE and call CreateUnorderedAccessView on it?

In D3D12HelloTexture sample they are using the same descriptor heap, created with D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE flag, for working with both GPU and CPU descriptor handle for SRV. I thought that it should be applicable to UAV as well.

?

Any input from your side will be more then welcome :-)?

Hi,

In order to clear an UAV, you need two descriptors from two different heaps:

- The CPU descriptor from a non shader visible heap

- The GPU descriptor from a shader visible heap

For what I know, this is because some GPUs require the descriptor in GPU visible memory, while others use the data that is copy to the command list when you call the method (clear in this case), so the API force you to have both so it will run on any GPU.

As a side note, CPU handles, from a non shader visible heaps, are copied to the command list when you call a method that use it (in this case ClearUnorderedAccessViewFloat) and for that it needs to be in CPU readable memory.

I hope it helps!

@Sergio J. de los Santos, definitely, it helps! Many thanks!

Just to ensure that I have understood correctly

Regarding descriptor heap creation flags.

1.D3D12_DESCRIPTOR_HEAP_FLAG_NONE descriptor heap will be non-shader visible and CPU read/write.

2.D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE descriptor heap will be shader visible and CPU write only.

When I call CreateShaderResourceView() or CreateUnorderedAccessView(), descriptor from CPU write only heap is sufficient.

Right?

Yes, because the create methods (for SRV, UAV, CBV) just write to that memory, and that memory is read by the GPU when you dispatch the drawcalls, but is not copied to the command list, like the RTV, DSV are. Again, the UAV is a special case for clear, but not for normal rendering when you just bind the table.

But if you want to copy descriptors (SRV, UAV, CBV), the source must be a non shader visible (so, read/write) heap. The target can be (and most likely be) a shader visible (cpu read only) heap.

@Sergio J. de los Santos, thanks again!

This topic is closed to new replies.

Advertisement