DXGKDDI_RENDER回调函数 (d3dkmddi.h)
DxgkDdiRender 函数从用户模式显示驱动程序传递的命令缓冲区 (DMA) 缓冲区生成直接内存访问。
语法
DXGKDDI_RENDER DxgkddiRender;
NTSTATUS DxgkddiRender(
[in] IN_CONST_HANDLE hContext,
[in/out] INOUT_PDXGKARG_RENDER pRender
)
{...}
参数
[in] hContext
DMA 和命令缓冲区的设备上下文的句柄。 显示微型端口驱动程序的 DxgkDdiCreateContext 函数之前在 dxgkDdiCreateContext 的 pCreateContext 参数指向的 DXGKARG_CREATECONTEXT 结构的 hContext 成员中返回此句柄。
如果驱动程序不支持创建上下文,Microsoft DirectX 图形内核子系统会将上下文的句柄替换为设备的句柄。 显示微型端口驱动程序的 DxgkDdiCreateDevice 函数之前返回了 dxgkDdiCreateDevice 的 pCreateDevice 参数指向的 DXGKARG_CREATEDEVICE 结构的 hDevice 成员中的设备句柄。
[in/out] pRender
指向 DXGKARG_RENDER 结构的指针,该结构包含有关 DMA 和命令缓冲区的信息。
返回值
DxgkDdiRender 返回以下值之一:
返回代码 | 说明 |
---|---|
STATUS_SUCCESS | 已转换整个命令缓冲区。 |
STATUS_NO_MEMORY | DxgkDdiRender 无法分配完成该操作所需的内存。 |
STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER | 当前 DMA 缓冲区已耗尽。 |
STATUS_PRIVILEGED_INSTRUCTION | DxgkDdiRender 检测到非特权指令 (即访问超出当前中央处理单元 [CPU] 进程) 特权的内存的指令。 |
STATUS_ILLEGAL_INSTRUCTION | DxgkDdiRender 检测到图形硬件无法支持的指令。 |
STATUS_INVALID_PARAMETER | DxgkDdiRender 检测到图形硬件不支持的指令参数;但是,图形硬件本身可以支持指令。 驱动程序不需要返回此错误代码。 相反,它可以在检测到不受支持的指令参数时返回STATUS_ILLEGAL_INSTRUCTION。 |
STATUS_INVALID_USER_BUFFER | DxgkDdiRender 检测到数据或指令不足或溢出。 也就是说,驱动程序收到的指令或数据比预期少或多。 驱动程序不需要返回此错误代码。 相反,它可以在检测到数据或指令不足或溢出时返回STATUS_ILLEGAL_INSTRUCTION。 |
STATUS_INVALID_HANDLE | DxgkDdiRender 在命令缓冲区中检测到无效句柄。 |
STATUS_GRAPHICS_DRIVER_MISMATCH | 显示微型端口驱动程序与发起了对 DxgkDdiRender ((即提交命令缓冲区) )调用的用户模式显示驱动程序不兼容。 |
STATUS_GRAPHICS_GPU_EXCEPTION_ON_DEVICE | 显示微型端口驱动程序在 DMA 流中检测到错误。 如果驱动程序返回此错误代码,则图形上下文设备将处于丢失状态。 |
注解
DirectX 图形内核子系统调用显示微型端口驱动程序的 DxgkDdiRender 函数,以从用户模式显示驱动程序传递的命令缓冲区生成 DMA 缓冲区。 当显示微型端口驱动程序从命令缓冲区转换为 DMA 缓冲区时,驱动程序还应验证命令缓冲区,以确保命令缓冲区不包含可用于访问不属于进程的内存的任何特权命令或命令。 除了输出 DMA 缓冲区外,显示微型端口驱动程序还应生成输出修补程序位置的列表。 视频内存管理器使用此列表相应地拆分和修补 DMA 缓冲区。
用户模式显示驱动程序生成的命令缓冲区 pCommand 和输入补丁位置列表 pPatchLocationListIn 均从用户模式地址空间中分配,并传递到显示微型端口驱动程序,且不受影响。 显示微型端口驱动程序必须在任何访问缓冲区和列表时使用__try/__except
代码,并且必须在将内容复制到相应的内核缓冲区之前验证缓冲区和列表的内容, (也就是说,在将 pCommand 成员的内容复制到 pDmaBuffer 成员,并将 pPatchLocationListIn 成员的内容复制到 pPatchLocationListOut 成员之前, 它们是 pRender 参数指向 ) DXGKARG_RENDER结构的所有成员。
下面是显示微型端口驱动程序应如何使用 和 __except
逻辑访问这些缓冲区__try
的示例。 AllocationListIn 指向用户模式缓冲区。
__try
{
for (Index = 0; Index < AllocationListInSize; AllocationTable++,
AllocationListIn++, AllocationListOut++, Index++)
{
D3DKMT_HANDLE AllocationHandle = AllocationListIn->hAllocation;
. . .
}
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
Status = STATUS_INVALID_PARAMETER;
SAMPLE_LOG_ERROR(
"Exception occurred accessing user-mode allocation list. Returning Status=0x%I64x",
Status);
goto cleanup;
}
注意
对内核缓冲区的访问不需要代码保护 try/except
。
如果重新创建信息更理想,则显示微型端口驱动程序不需要使用用户模式显示驱动程序提供的信息。 例如,如果 pPatchLocationListIn 为空,因为用户模式显示驱动程序未提供输入补丁位置列表,则显示微型端口驱动程序可以基于命令缓冲区的内容生成 pPatchLocationListOut 的内容。
在内核转换期间,用户模式显示驱动程序提供的分配列表经过验证、复制并转换为内核模式分配列表。 DirectX 图形内核子系统通过将用户模式显示驱动程序提供的D3DKMT_HANDLE类型句柄转换为显示微型端口驱动程序的 DxgkDdiOpenAllocation 函数返回的特定于设备的句柄,将每个D3DDDI_ALLOCATIONLIST元素转换为DXGK_ALLOCATIONLIST元素。 每个分配的索引和分配 (的写入状态,即 ,在转换期间,WriteOperation 位字段标志) 的设置保持不变。
除了特定于设备的句柄外,DirectX 图形内核子系统还为显示微型端口驱动程序提供每个分配的最后一个已知 GPU 段地址。 如果分配索引 N 当前已分页,则 DirectX 图形内核子系统将 DXGKARG_RENDERpAllocationList 成员的 N个元素的 SegmentId 成员设置为零。 如果分配列表的第 N个元素的 SegmentId 成员未设置为零,则显示微型端口驱动程序必须使用提供的段地址信息预先修补生成的 DMA 缓冲区。 驱动程序必须在请求时预先修补,因为 DirectX 图形内核子系统可能不会在驱动程序应正确预修补的 DMA 缓冲区上调用 DxgkDdiPatch 函数。
注意
即使驱动程序的 DxgkDdiRender 函数预先修补 DMA 缓冲区,驱动程序仍必须将对分配的所有引用插入到DXGKARG_RENDER的 pPatchLocationListOut 成员指定的输出修补程序位置列表中。 此列表必须包含所有引用,因为在将 DMA 缓冲区提交到 GPU 之前,分配的地址可能会更改;因此,DirectX 图形内核子系统将调用 DxgkDdiPatch 函数来重新绘制 DMA 缓冲区。
若要取消绑定分配,显示微型端口驱动程序可以在分配列表中指定引用 NULL 句柄的元素,然后使用引用该 NULL 分配的修补位置元素。 通常,驱动程序应使用分配列表的第一个元素 (元素 0) 作为 NULL 元素。
当显示微型端口驱动程序将命令缓冲区转换为 DMA 缓冲区时,显示微型端口驱动程序和用户模式显示驱动程序应针对以下情况执行以下操作:
有关详细信息,请参阅 使用保证协定 DMA 缓冲区模型) ,在保证协定 DMA 模式 (中,用户模式显示驱动程序必须保证翻译命令有足够的资源。 如果没有足够的资源用于转换,则显示微型端口驱动程序必须拒绝 DMA 缓冲区。
用户模式显示驱动程序应始终拆分可能转换为大于单个 DMA 缓冲区大小的命令,因为显示微型端口驱动程序的 DxgkDdiRender 函数无法处理大于 DMA 缓冲区大小且无法拆分的单个命令。
应使 DxgkDdiRender 可分页。
从 Windows 7 开始,为支持 GDI 硬件加速的显示适配器添加了对 DxgkDdiRenderKm 函数的支持。
要求
要求 | 值 |
---|---|
最低受支持的客户端 | 从 Windows Vista 开始可用 |
目标平台 | 桌面 |
标头 | d3dkmddi.h |
IRQL | PASSIVE_LEVEL |