使用D3D12纹理作为D2D渲染目标触发验证错误,求助排查
我尝试将D2D/DWrite内容绘制到一个将用作D3D12着色器资源的纹理中。为此,我参考示例创建了ID3D11On12Device,但不想映射D3D12后台缓冲区,而是自行创建纹理。
资源属性定义
D3D12_RESOURCE_DESC desc; ::ZeroMemory(&desc, sizeof(desc)); desc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D; desc.MipLevels = 1; desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; desc.DepthOrArraySize = 1; desc.Flags = D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET | D3D12_RESOURCE_FLAG_ALLOW_SIMULTANEOUS_ACCESS; desc.SampleDesc.Count = 1; D3D12_HEAP_PROPERTIES heapProps; ::ZeroMemory(&heapProps, sizeof(heapProps)); heapProps.Type = D3D12_HEAP_TYPE_DEFAULT;
创建D3D12纹理
THROW_IF_FAILED(d3d12Device->CreateCommittedResource( &heapProps, D3D12_HEAP_FLAG_SHARED, &desc, D3D12_RESOURCE_STATE_ALL_SHADER_RESOURCE, &clear, ::IID_ID3D12Resource, this->d3d12Targets[i].put_void()));
我已按照相关说明设置了D3D12_RESOURCE_FLAG_ALLOW_SIMULTANEOUS_ACCESS和D3D12_HEAP_FLAG_SHARED。
创建包装资源时出错
执行以下代码创建包装资源:
D3D11_RESOURCE_FLAGS flags = { D3D11_BIND_RENDER_TARGET }; THROW_IF_FAILED(this->d3d11On12Device->CreateWrappedResource( this->d3d12Targets[i].get(), &flags, D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE, ::IID_ID3D11Resource, this->d3d11Targets[i].put_void()));
出现验证错误:
D3D12 ERROR: ID3D12CompatibilityDevice::ReflectSharedProperties: Resource provided was not shared by D3D11, or with a D3D11 desc. [ MISCELLANEOUS ERROR #916: REFLECTSHAREDPROPERTIES_INVALIDOBJECT]
请问我遗漏了什么?
问题出在共享资源的创建模式上:ID3D11On12Device::CreateWrappedResource要求使用基于NT句柄的跨API共享模式,而非普通的D3D12共享资源标记。你需要调整资源和堆的标记,使其符合D3D11兼容的共享格式。
具体调整步骤
- 修改资源标记:在原有标记基础上添加
D3D12_RESOURCE_FLAG_ALLOW_SHARED_NTHANDLE,这是D3D11On12能识别的共享标记。 - 修改堆标记:将
D3D12_HEAP_FLAG_SHARED替换为D3D12_HEAP_FLAG_SHARED_NTHANDLE,匹配资源的共享模式。 - 调整初始资源状态:因为要通过D3D11On12绘制,初始状态设为
D3D12_RESOURCE_STATE_RENDER_TARGET更合理,后续再转换为着色器资源状态。
调整后的代码
D3D12_RESOURCE_DESC desc; ::ZeroMemory(&desc, sizeof(desc)); desc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D; desc.MipLevels = 1; desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; desc.DepthOrArraySize = 1; // 添加上ALLOW_SHARED_NTHANDLE标记 desc.Flags = D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET | D3D12_RESOURCE_FLAG_ALLOW_SIMULTANEOUS_ACCESS | D3D12_RESOURCE_FLAG_ALLOW_SHARED_NTHANDLE; desc.SampleDesc.Count = 1; D3D12_HEAP_PROPERTIES heapProps; ::ZeroMemory(&heapProps, sizeof(heapProps)); heapProps.Type = D3D12_HEAP_TYPE_DEFAULT; // 使用SHARED_NTHANDLE堆标记 THROW_IF_FAILED(d3d12Device->CreateCommittedResource( &heapProps, D3D12_HEAP_FLAG_SHARED_NTHANDLE, &desc, D3D12_RESOURCE_STATE_RENDER_TARGET, &clear, ::IID_ID3D12Resource, this->d3d12Targets[i].put_void()));
核心原因
普通的D3D12共享资源(D3D12_HEAP_FLAG_SHARED)是为D3D12进程间共享设计的,无法被D3D11On12设备正确识别。而SHARED_NTHANDLE是专门为D3D11与D3D12跨API共享设计的模式,能让D3D11On12设备正确解析资源的共享属性,从而成功创建包装资源。
内容的提问来源于stack exchange,提问作者Christoph

