如何正确使用ClearUnorderedAccessViewFloat?D3D12 UAV清除报错解决
解决D3D12 ClearUnorderedAccessViewFloat 无效描述符错误
问题根源
你使用的D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE标志描述符堆是CPU仅写、GPU只读的,而ClearUnorderedAccessViewFloat函数要求CPU能读取UAV描述符,直接复用同一个堆会触发错误。需要创建两个独立的描述符堆:
- 带
D3D12_DESCRIPTOR_HEAP_FLAG_NONE:供CPU操作(如Clear),CPU可读可写 - 带
D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE:供GPU着色器访问
修改步骤
1. 创建双描述符堆
分别创建CPU可见和GPU可见的UAV堆:
// CPU可见UAV堆(用于Clear操作) D3D12_DESCRIPTOR_HEAP_DESC cpu_uav_heap_desc{}; cpu_uav_heap_desc.NumDescriptors = 1; // 根据实际资源数调整 cpu_uav_heap_desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV; cpu_uav_heap_desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE; d3d.device->CreateDescriptorHeap(&cpu_uav_heap_desc, IID_PPV_ARGS(&m_cpu_uav_heap)); // GPU可见UAV堆(用于着色器访问) D3D12_DESCRIPTOR_HEAP_DESC gpu_uav_heap_desc{}; gpu_uav_heap_desc.NumDescriptors = /* 你的资源数量 */; gpu_uav_heap_desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV; gpu_uav_heap_desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE; d3d.device->CreateDescriptorHeap(&gpu_uav_heap_desc, IID_PPV_ARGS(&m_gpu_uav_heap)); // 获取描述符增量大小 m_uav_desc_size = d3d.device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
2. 为同一纹理创建双UAV描述符
给两个堆分别创建指向m_texture1d的UAV描述符,确保关联同一资源:
// 定义UAV参数(匹配RWTexture1D<float>) D3D12_UNORDERED_ACCESS_VIEW_DESC uav_desc{}; uav_desc.Format = DXGI_FORMAT_R32_FLOAT; uav_desc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE1D; uav_desc.Texture1D.MipSlice = 0; // 给CPU堆创建UAV描述符 D3D12_CPU_DESCRIPTOR_HANDLE cpu_uav_handle = m_cpu_uav_heap->GetCPUDescriptorHandleForHeapStart(); d3d.device->CreateUnorderedAccessView(m_texture1d, nullptr, &uav_desc, cpu_uav_handle); // 给GPU堆创建UAV描述符 D3D12_CPU_DESCRIPTOR_HANDLE gpu_uav_cpu_handle = m_gpu_uav_heap->GetCPUDescriptorHandleForHeapStart(); d3d.device->CreateUnorderedAccessView(m_texture1d, nullptr, &uav_desc, gpu_uav_cpu_handle);
3. 修正Clear函数调用
传入对应堆的句柄,满足CPU读、GPU访问的要求:
// 获取GPU堆的GPU句柄(供着色器使用) CD3DX12_GPU_DESCRIPTOR_HANDLE gpu_handle( m_gpu_uav_heap->GetGPUDescriptorHandleForHeapStart(), 0, // UAV在堆中的索引,按需调整 m_uav_desc_size ); // 获取CPU堆的CPU句柄(供Clear使用) CD3DX12_CPU_DESCRIPTOR_HANDLE cpu_handle( m_cpu_uav_heap->GetCPUDescriptorHandleForHeapStart(), 0, // 对应索引 m_uav_desc_size ); FLOAT const clear_value = 0; m_cmd_list->ClearUnorderedAccessViewFloat( gpu_handle, cpu_handle, m_texture1d, &clear_value, 0, nullptr );
4. 绑定GPU堆到命令列表
执行着色器前,将GPU可见堆绑定到命令列表:
ID3D12DescriptorHeap* heaps[] = { m_gpu_uav_heap }; m_cmd_list->SetDescriptorHeaps(_countof(heaps), heaps);
核心说明
两个堆的UAV描述符均指向同一个m_texture1d资源,只是分工不同:CPU堆满足Clear函数的读取要求,GPU堆保障着色器的访问权限。
内容的提问来源于stack exchange,提问作者0xbadf00d
相关产品推荐
相关产品推荐

