window显示驱动开发—支持 DXGI DDI(二)
Direct3D 版本 10 DXGI 函数
本部分介绍用户模式显示驱动程序 DLL 提供给 Microsoft Direct3D 版本 10 运行时的 Microsoft DirectX 图形基础结构 (DXGI) 函数。 驱动程序在调用用户模式显示驱动程序的 CreateDevice (D3D10 ) 函数时,通过 DXGI_DDI_BASE_FUNCTIONS 结构的成员提供指向 DXGI 函数的指针。
BltDXGI:GetGammaCapsDXGI
PresentDXGI:QueryResourceResidencyDXGI
ResolveSharedResourceDXGI:RotateResourceIdentitiesDXGI
SetDisplayModeDXGI:SetResourcePriorityDXGI
1. 函数概览与职责划分
以下是驱动必须实现的DXGI DDI函数列表及其核心职责:
BltDXGI
GetGammaCapsDXGI
PresentDXGI
QueryResourceResidencyDXGI
ResolveSharedResourceDXGI
D3D10_DDI_RESOURCE_MISC_SHARED
标志使用)RotateResourceIdentitiesDXGI
SetDisplayModeDXGI
SetResourcePriorityDXGI
2. 关键函数实现指南
(1) PresentDXGI - 帧提交核心函数
输入结构:
typedef struct DXGI_DDI_ARG_PRESENT { DXGI_DDI_HDEVICE hDevice; DXGI_DDI_HSURFACE hSurface; // 要呈现的资源 UINT SubResourceIndex; // 子资源索引 DXGI_DDI_HDEVICE hDstDevice; // 目标设备(跨设备时有效) UINT DstSubResourceIndex; DXGI_DDI_PRESENT_FLAGS Flags; // 如DXGI_DDI_PRESENT_STEREO} DXGI_DDI_ARG_PRESENT;
驱动实现要点:
HRESULT APIENTRY PresentDXGI(DXGI_DDI_ARG_PRESENT* pPresentData) { // 1. 验证资源有效性 MySurface* pSurface = (MySurface*)pPresentData->hSurface.pDrvPrivate; if (!pSurface) return E_INVALIDARG; // 2. 处理立体呈现(3D Stereo) if (pPresentData->Flags.Stereo) { SubmitStereoFrame(pSurface); } else { SubmitMonoFrame(pSurface); } // 3. 触发Flip或Copy操作 if (UseHardwareFlip()) { QueueFlipCommand(pSurface->hKMSurface); } else { CopyToBackBuffer(pSurface); } return S_OK;}
(2) SetResourcePriorityDXGI - 资源优先级管理
典型场景:游戏动态加载纹理时提升前景物体优先级。
实现示例:
void APIENTRY SetResourcePriorityDXGI( DXGI_DDI_ARG_SETRESOURCEPRIORITY* pPriorityData) { MyResource* pRes = (MyResource*)pPriorityData->hResource.pDrvPrivate; pRes->currentPriority = pPriorityData->Priority; // 更新GPU内存管理器(如NVIDIA的PTE分组) UpdateGPUMemoryPriority(pRes->videoAddress, pPriorityData->Priority);}
(3) ResolveSharedResourceDXGI - 共享资源同步
跨进程共享流程:
Process A创建共享资源 → 驱动生成GDI句柄 → Process B通过OpenResource获取 → ResolveSharedResource同步数据
Process A创建共享资源 → 驱动生成GDI句柄 →
Process B通过OpenResource获取 → ResolveSharedResource同步数据
驱动关键操作:
HRESULT APIENTRY ResolveSharedResourceDXGI( DXGI_DDI_ARG_RESOLVESHAREDRESOURCE* pResolveData) { // 1. 获取共享资源元数据 MySharedResource* pShared = (MySharedResource*)pResolveData->hResource.pDrvPrivate; // 2. 执行GPU端同步(如刷新缓存) FlushGPUWriteCache(pShared->gpuAddress); // 3. 通知内核模式驱动 pCtx->pKMCallbacks->pfnSyncSharedResource(pShared->hKMHandle); return S_OK;}
3.软件光栅器特殊处理
当驱动运行在软件模拟模式时(如WARP驱动),需:
禁用硬件加速路径:返回 DXGI_STATUS_NO_REDIRECTION。
实现CPU端Present:
HRESULT APIENTRY SoftwarePresentDXGI(DXGI_DDI_ARG_PRESENT* pData) { // CPU内存拷贝到DWM兼容缓冲区 BYTE* pSrc = LockSoftwareSurface(pData->hSurface); BYTE* pDst = GetDWMBuffer(); memcpy(pDst, pSrc, pData->pPresentInfo->BufferDesc.Width * pData->pPresentInfo->BufferDesc.Height * 4); UnlockSoftwareSurface(pData->hSurface); return S_OK;}
4. 多显示器与HDR支持
(1) SetDisplayModeDXGI 扩展
HRESULT APIENTRY SetDisplayModeDXGI( DXGI_DDI_ARG_SETDISPLAYMODE* pModeData) { // HDR元数据传递(DXGI 1.4+) if (pModeData->Flags.HDR) { ConfigureHDRMetadata(pModeData->hMonitor, &pModeData->HDRMetaData); } // 切换显示模式 return ChangeDisplayMode(pModeData->hMonitor, pModeData->Mode);}
(2) 伽玛控制 (GetGammaCapsDXGI)
void APIENTRY GetGammaCapsDXGI( DXGI_DDI_ARG_GETGAMMACAPS* pCapsData) { pCapsData->GammaCaps->ScaleAndOffsetSupported = FALSE; // 是否支持scRGB pCapsData->GammaCaps->MaxConvertedValue = 1.0f; // 传统Gamma范围 pCapsData->GammaCaps->NumLUTEntries = 256; // 硬件LUT精度}
5. 性能优化建议
DXGI_DDI_PRESENT_DO_NOT_WAIT
标志避免CPU阻塞QueryResourceResidencyDXGI
结果,减少GPU同步RotateResourceIdentitiesDXGI
中预旋转纹理以减少运行时开销6. 调试与验证
PIX工具:捕获 PresentDXGI 调用链,分析帧间隔和资源状态。
Direct3D调试层:启用 D3D10_DEBUG_DDI 检测参数错误。
- WDK日志:使用 DbgPrintEx 输出DXGI DDI调用序列。
- 关键提示:所有DXGI DDI函数必须保证线程安全,运行时可能在任意线程上下文调用它们。