DxgkCbSynchronizeExecution routine

The DxgkCbSynchronizeExecution function synchronizes a specified function, implemented by the display miniport driver, with the display miniport driver's DxgkDdiInterruptRoutine function.

Syntax


DXGKCB_SYNCHRONIZE_EXECUTION DxgkCbSynchronizeExecution;

NTSTATUS DxgkCbSynchronizeExecution(
  _In_   HANDLE DeviceHandle,
  _In_   PKSYNCHRONIZE_ROUTINE SynchronizeRoutine,
  _In_   PVOID Context,
  _In_   ULONG MessageNumber,
  _Out_  PBOOLEAN ReturnValue
)
{ ... }

Parameters

DeviceHandle [in]

A handle that represents a display adapter. The display miniport driver previously obtained this handle in the DeviceHandle member of the DXGKRNL_INTERFACE structure that was passed to DxgkDdiStartDevice.

SynchronizeRoutine [in]

A pointer to a function, implemented by the display miniport driver, that will be synchronized with DxgkDdiInterruptRoutine. The function must conform to the following prototype:


BOOLEAN SynchronizeRoutine(PVOID Context);

Context [in]

A pointer to a context block, created by the display miniport driver, that will be passed to SynchronizeRoutine.

MessageNumber [in]

The number of the interrupt message with which SynchronizeRoutine will be synchronized. If the interrupt is line-based, this parameter must be zero.

ReturnValue [out]

A pointer to a Boolean variable that receives the return value of SynchronizeRoutine.

Return value

DxgkCbSynchronizeExecution returns one of the following values:

Return codeDescription
STATUS_SUCCESS

The function succeeded.

STATUS_INVALID_PARAMETER

One of the parameters is invalid.

STATUS_UNSUCCESSFUL

The function was unable to synchronize execution, possibly because the interrupt had not been connected yet.

 

Examples

The following code example shows a submission thread that notifies the GPU scheduler about the completion of packets from the software queue.


typedef struct _SubmitParams {
    HW_DEVICE_EXTENSION *pHwDeviceExtension;
    UINT                NodeOrdinal;
    UINT                FenceID;
    UINT                PreemptionFenceID;
} SubmitParams;

VOID R200TEST_SWNode_SubmissionThread(SubmissionThreadData* pv)
{
    PHW_DEVICE_EXTENSION  pAdapter = (PHW_DEVICE_EXTENSION)pv->pAdapter;
    DWORD  EngineID = pv->EngineID;
    LARGE_INTEGER  timeout = {0, 0};
    R2_SWNODE_PACKET  Packet;
    PR2_SWNODE_PACKET  pPacket = NULL;
    NTSTATUS  status = STATUS_TIMEOUT;

    RtlZeroMemory(&Packet, sizeof(Packet));

    // Signal event to indicate that the thread started
    KeSetEvent(&pAdapter->SWNodes[EngineID]->StartThreadEvent, 0, FALSE);
    do {
        pPacket = NULL;
        timeout.QuadPart = 0;
        // Poll the queue for the next packet
        pPacket = &Packet;
        SWNode_GetPacketFromQueue(&pAdapter->SWNodes[EngineID]->SWNode_PacketsQueue, &pPacket);
        if(pPacket) {
            BOOLEAN  bRet = FALSE;
            SubmitParams  SchNotifyParams;
            RtlZeroMemory(&SchNotifyParams, sizeof(SchNotifyParams));
            timeout.QuadPart = pPacket->timeout * 10000;
            timeout.QuadPart *= (ULONGLONG)-1; // relative timeout
            KeDelayExecutionThread(KernelMode, FALSE, &timeout);
            // Check if during this packet's execution the GPU scheduler requested to preempt
            if(pAdapter->SWNodes[EngineID]->CurrPreemptFenceID != pAdapter->PrevPreemptFenceIDArray[EngineID]) {
                SchNotifyParams.PreemptionFenceID = pAdapter->SWNodes[EngineID]->CurrPreemptFenceID;
                SWNode_PreemptQueue(&pAdapter->SWNodes[EngineID]->SWNode_PacketsQueue);
            }
            // Raise IRQL to interrupt level to synchronize with the interrupt callback function.
            SchNotifyParams.pHwDeviceExtension = pAdapter;
            SchNotifyParams.FenceID = pPacket->SubmissionFenceID;
            SchNotifyParams.NodeOrdinal = EngineID; 

            pAdapter->ddiCallback.DxgkCbSynchronizeExecution(pAdapter->DeviceHandle,
                (PKSYNCHRONIZE_ROUTINE) R200TEST_SWNode_SynchronizeVidSchNotifyInt,
                (PVOID)&SchNotifyParams,
                0, &bRet);
            if(!bRet) {
                EngDebugBreak(); // this should never happen
            }
            RtlZeroMemory(pPacket, sizeof(R2_SWNODE_PACKET));
        }
        else {
            PKEVENT pEvents[3];

            //Wait for an event that indicates to exit, 
            //an event that indicates that the queue is no longer empty,
            // or en event that indicates that TDR happened
            pEvents[0] = &pAdapter->SWNodes[EngineID]->TerminateThreadEvent;
            pEvents[1] = &pAdapter->SWNodes[EngineID]->SWNode_PacketsQueue.AddPacketToQueueEvent;
            pEvents[2] = &pAdapter->SWNodes[EngineID]->TDREvent;
            status = KeWaitForMultipleObjects(3, pEvents, WaitAny, Executive, KernelMode, FALSE, NULL, NULL);
            if(status == STATUS_WAIT_0 + 2) {
                // TDREvent was signaled, which indicates a recovery from TDR
                // Signal an event for TDR recovery to proceed
                KeSetEvent(&pAdapter->SWNodes[EngineID]->ProceedWithTDRRecovery, 0, FALSE);
            }
        }
    }
    while(status != STATUS_WAIT_0);
}

Requirements

Version

Available in Windows Vista and later versions of the Windows operating systems.

Header

Dispmprt.h (include Dispmprt.h)

IRQL

<=DISPATCH_LEVEL

See also

DxgkDdiInterruptRoutine
KeSynchronizeExecution

 

 

Send comments about this topic to Microsoft

Показ:
© 2014 Microsoft