DXGKDDI_RENDER callback function
DxgkDdiRender 根据UMD传入的 command buffer 创建一个DMA buffer。
Syntax
DXGKDDI_RENDER DxgkddiRender;
NTSTATUS DxgkddiRender(
IN_CONST_HANDLE hContext,
INOUT_PDXGKARG_RENDER pRender
)
{...}
Parameters
hContext
[in] DMA buffer和Command buffer所在的device context的句柄。之前KMD的DxgkDdiCreateContext的参数DXGKARG_CREATECONTEXT pCreateContext的成员hContext返回此句柄。
如果驱动不支持创建context,DXGK将用device的句柄来替换context的handle。之前KMD的DxgkDdiCreateDevice的参数DXGKARG_CREATEDEVICE pCreateDevice的成员hDevice 返回此句柄。
pRender
[in/out] DXGKARG_RENDER的指针,该结构包含了DMA buffer和command buffer的信息。
Return Value
DxgkDdiRender returns one of the following values:
Return code | Description |
---|---|
STATUS_SUCCESS | The entire command buffer was translated. |
STATUS_NO_MEMORY | DxgkDdiRender could not allocate memory that was required for it to complete. |
STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER | The current DMA buffer is depleted. |
STATUS_PRIVILEGED_INSTRUCTION | DxgkDdiRender detected nonprivileged instructions (that is, instructions that access memory beyond the privilege of the current central processing unit [CPU] process). |
STATUS_ILLEGAL_INSTRUCTION | DxgkDdiRender detected instructions that graphics hardware could not support. |
STATUS_INVALID_PARAMETER | DxgkDdiRender detected instruction parameters that graphics hardware could not support; however, the graphics hardware can support the instructions themselves. The driver is not required to return this error code. Instead, it can return STATUS_ILLEGAL_INSTRUCTION when it detects unsupported instruction parameters. |
STATUS_INVALID_USER_BUFFER | DxgkDdiRender detected data or instruction underrun or overrun. That is, the driver received less or more instructions or data than expected. The driver is not required to return this error code. Instead, it can return STATUS_ILLEGAL_INSTRUCTION when it detects data or instruction underrun or overrun. |
STATUS_INVALID_HANDLE | DxgkDdiRender detected an invalid handle in the command buffer. |
STATUS_GRAPHICS_DRIVER_MISMATCH | The display miniport driver is not compatible with the user-mode display driver that initiated the call to DxgkDdiRender (that is, submitted the command buffer). |
STATUS_GRAPHICS_GPU_EXCEPTION_ON_DEVICE | The display miniport driver detected an error in the DMA stream. The graphics context device is placed in a lost state if the driver returns this error code. |
Remarks
DXGK调用KMD的DxgkDdiRender函数来根据UMD 传入的 command buffer生成DMA buffer。当KMD将command buffer翻译为DMA buffer时,驱动需要validate command buffer来保证command buffer 不会包含特权命令以及会访问到不属于该process的命令。另外生成output DMA buffer时,KMD应该生成一个output patch location list。VMM使用整个list来正确的spilit和patch DMA buffer。
UMD生成的command buffer 参数pCommand 和 input patch-location list 参数pPatchLocationListIn 被allocate在用户模式地址空间并被传入到KMD中时并不会被访问。KMD必须在内容被拷贝到kernel buffer之前,使用__try / __except 代码来包含任何validate和访问 command buffer和patch-location list的代码。(即在拷贝pCommand 成员内容到pDmaBuffer,以及从pPatchLocationListIn成员到pPatchLocationListOut成员中之前。这些都是DXGKARG_RENDER的成员)
下面例子给出了KMD怎样使用 __try 和 __except 访问这些buffer的逻辑。AllocationListIn指向这些用户模式buffer。
__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;
}
Note
访问kernel buffer则不需要使用try/except代码进行保护。
如果KMD创建的DMA buufer创建的信息更合适,则KMD不需要使用UMD提供的信息。例如,如果因为UMD没有提供input patch-location list则pPatchLocationList为空,KMD能基于command buffer的内容生成pPatchLocationListOut内容。
在KMD进行kernel trasition时,UMD提供的allocation list会被validate,拷贝,并转换为kernel-mod allocation。DXGK通过转换UMD提供的指定设备的D3DKMT_HANDLE类型的句柄来实现转换每一个D3DDDI_ALLOCATIONLIST元素为DXGK_ALLOCATIONLIST元素,KMD在DxgkDdiOpenAllocation中返回这些句柄。每个allocation的index和allocation的写状态在这个转换过程中保持不变。(写状态是在WriteOperation中)
对于指定设备的句柄,DXGK还会向KMD提供了最后一次记录的每个allocation的GPU段地址。如果allocation index N被page out,DXGK会将DXGKARG_RENDER pAllocationList的SegmentId成员设置为0.如果allocation list的index N的元素的SegmentId成员没被设置为0,KMD必须是同提供的segment address信息来pre-patch生成的DMA buffer。驱动在有需要的时候必须pre-patch DMA buffer,因为DXGK可能不会调用为应该已经被pre-patch过的DMA buffer调用DxgkDdiPatch。
Note
虽然KMD的DxgkDdiRender 会pre-patch DMA buffer,驱动仍然需要将所有allocation的引用插入到output patch-location list中, 即DXGKARG_RENDER的pPatchLocationListOut成员。这个list必须包含所有allocation的引用,因为DMA buffer在被提交到GPU之前这些allocation的地址可能改变。因此DXGK将调用DxgkDdiPatch来重新patch DMA buffer。
为了unbind一个allocation,KMD能够指定allocation list中的一个元素引用一个NULL句柄,接着指定一个patch-location 元素引用一个NULL allocation。通常KMD应该使用第一个元素(index 0)作为NULL元素。
当KMD转换command buffer到DMA buffer中时,KMD和UMD应该为下列情况执行下列对应操作。
- 在guaranteed contract DMA 模型中(参考Using the Guaranteed Contract DMA buffer Model),UMD必须保证由足够的资源用于转换command,如果提供的资源不足,KMD应该拒绝该DMA buffer。
- UMD应该总是split那些可能被转换成多于单个DMA buffer的 command,因为KMD的DxgkDdiRender不能处理大于DMA buffer大小的单个command,并且这个这个command不能在DxgkDdiRender被split。
DxgkDdiRender should be made pageable.
Support for the DxgkDdiRenderKm function is added beginning with Windows 7 for display adapters that support GDI Hardware Acceleration.
Requirements
Minimum supported client | Available in Windows Vista and later versions of the Windows operating systems. |
Target Platform | Desktop |
Header | d3dkmddi.h |
IRQL | PASSIVE_LEVEL |