D2D1Factory::CreateDxgiSurfaceRenderTarget正确参数及注入场景调用失败排查
问题排查与正确配置方案
一、前置参数合法性校验
注入第三方应用场景下,首先排查以下容易被忽略的前置条件,这是无效参数报错的最高发原因:
- 确保你创建的D2D工厂是
D2D1_FACTORY_TYPE_MULTI_THREADED类型,若目标应用使用多线程渲染,单线程工厂会直接返回无效参数 - 调用
swapchain->GetBuffer后先校验返回的HRESULT,确认dxgiBackbuffer指针非空、后台缓冲区获取成功 - 确认注入时机是交换链初始化完成后、Present调用前,避免在缓冲区被锁定/占用的状态下调用创建接口
二、通用适配型正确配置写法
不要硬编码像素格式、DPI等参数,直接从DXGI表面读取属性自动适配,正确代码如下:
// 1. 读取DXGI表面的原生描述 DXGI_SURFACE_DESC surfDesc = {}; hr = dxgiBackbuffer->GetDesc(&surfDesc); if (FAILED(hr)) { // 先处理表面描述获取失败逻辑 } // 2. 配置完全适配DXGI表面的渲染目标属性 D2D1_RENDER_TARGET_PROPERTIES rtProps = D2D1::RenderTargetProperties( D2D1_RENDER_TARGET_TYPE_HARDWARE, // 强制和D3D上下文匹配的硬件渲染类型,避免软渲染冲突 D2D1::PixelFormat( surfDesc.Format, D2D1_ALPHA_MODE_IGNORE // 直接输出到屏幕的后台缓冲区不需要Alpha预乘,直接忽略Alpha即可 ), 0.0f, 0.0f, // 填0自动继承DXGI表面的DPI配置,不需要手动读取桌面DPI D2D1_RENDER_TARGET_USAGE_NONE, D2D1_FEATURE_LEVEL_DEFAULT ); // 3. 创建渲染目标 hr = factory->CreateDxgiSurfaceRenderTarget( dxgiBackbuffer, &rtProps, &d2dRenderTarget );
三、极端场景兼容方案
如果上述写法依然报错,改用复用目标应用D3D设备的方案,兼容性更强:
// 从目标应用的D3D设备获取DXGI设备 IDXGIDevice* dxgiDevice = nullptr; hr = d3dDevice->QueryInterface(IID_PPV_ARGS(&dxgiDevice)); if (SUCCEEDED(hr)) { // 基于目标应用的DXGI设备创建D2D设备 ID2D1Device* d2dDevice = nullptr; hr = factory->CreateDevice(dxgiDevice, &d2dDevice); if (SUCCEEDED(hr)) { // 创建D2D设备上下文 ID2D1DeviceContext* d2dContext = nullptr; hr = d2dDevice->CreateDeviceContext(D2D1_DEVICE_CONTEXT_OPTIONS_NONE, &d2dContext); if (SUCCEEDED(hr)) { // 直接从DXGI表面创建渲染位图,不需要额外配置属性 ID2D1Bitmap1* targetBitmap = nullptr; hr = d2dContext->CreateBitmapFromDxgiSurface( dxgiBackbuffer, nullptr, &targetBitmap ); if (SUCCEEDED(hr)) { d2dContext->SetTarget(targetBitmap); // 后续直接用d2dContext渲染即可,无需单独创建渲染目标 targetBitmap->Release(); } } d2dDevice->Release(); } dxgiDevice->Release(); }
该方案完全复用目标应用的渲染上下文,不需要手动匹配渲染属性,适配度远高于直接调用CreateDxgiSurfaceRenderTarget。
内容的提问来源于stack exchange,提问作者Giannis
相关产品推荐
相关产品推荐

