DXGKDDI_BUILDPAGINGBUFFER - NtDoc

Native API online documentation, based on the System Informer (formerly Process Hacker) phnt headers
// d3dkmddi.h

DXGKDDI_BUILDPAGINGBUFFER DxgkddiBuildpagingbuffer;

NTSTATUS DxgkddiBuildpagingbuffer(
  [in]     IN_CONST_HANDLE hAdapter,
  [in/out] IN_PDXGKARG_BUILDPAGINGBUFFER pBuildPagingBuffer
)
{...}
View the official Windows Driver Kit DDI reference

NtDoc

No description available.

Windows Driver Kit DDI reference (nc-d3dkmddi-dxgkddi_buildpagingbuffer)

DXGKDDI_BUILDPAGINGBUFFER callback function

Description

The DxgkDdiBuildPagingBuffer function builds paging buffers for memory operations.

Parameters

hAdapter [in]

A handle to a context block that is associated with a display adapter. The display miniport driver previously provided this handle to the Microsoft DirectX graphics kernel subsystem in the MiniportDeviceContext output parameter of the DxgkDdiAddDevice function.

pBuildPagingBuffer [in/out]

A pointer to a DXGKARG_BUILDPAGINGBUFFER structure that contains information for building a paging buffer.

Return value

DxgkDdiBuildPagingBuffer returns one of the following values:

Return code Description
STATUS_SUCCESS DxgkDdiBuildPagingBuffersuccessfully built a paging buffer.
STATUS_GRAPHICS_ALLOCATION_BUSY The GPU is currently using the allocation for the paging buffer.
STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER More space is required in the paging buffer (that is, in the pDmaBuffer member of the DXGKARG_BUILDPAGINGBUFFER structure that the pBuildPagingBuffer parameter points to).

Remarks

The DxgkDdiBuildPagingBuffer function is called to build special purpose direct memory access (DMA) buffers that are known as paging buffers. A paging buffer contains an operation that moves the content of portions of allocations:

The display miniport driver must write the appropriate graphics processing unit (GPU) instruction in the provided paging buffer (in the pDmaBuffer member of DXGKARG_BUILDPAGINGBUFFER) according to the requested paging operation; and then the driver must return the paging buffer back to the video memory manager (which is part of Dxgkrnl.sys). The GPU scheduler (which is also part of Dxgkrnl.sys) subsequently calls the driver's DxgkDdiSubmitCommand function to request that the driver submit the paging buffer as a regular DMA buffer to the GPU.

Note Before the video memory manager submits the paging buffer, it calls the driver's DxgkDdiPatch function to assign (that is, patch) physical addresses to the paging buffer; however, in the call to DxgkDdiPatch, the video memory manager does not provide patch-location lists. The driver's DxgkDdiPatch function can perform last-minute updates to the paging buffer; however, the driver's DxgkDdiPatch function cannot change the size of the paging buffer.

When the driver successfully builds the paging buffer, the driver's DxgkDdiBuildPagingBuffer should update pDmaBuffer to point past the last byte that is written to the paging buffer and then return STATUS_SUCCESS. Because DxgkDdiBuildPagingBuffer can fail only if it runs out of space in the paging buffer, the driver should always verify that the paging buffer has enough space remaining before it writes to the buffer. If not enough space remains in the paging buffer, the driver should return STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER. The video memory manager would then acquire a new paging buffer and call the driver's DxgkDdiBuildPagingBuffer function again to fill the new paging buffer according to the requested paging operation. Note that for a given requested paging operation that fills multiple paging buffers, the scheduler calls the driver's DxgkDdiSubmitCommand function multiple times for each partial paging buffer to submit each buffer independently.

If DxgkDdiBuildPagingBuffer determines that a paging operation requires more than one paging buffer, the driver can specify information in the MultipassOffset member of DXGKARG_BUILDPAGINGBUFFER and can use this information across multiple iterations of the paging operation. The video memory manager initializes the information in MultipassOffset to zero before the first paging operation request and does not modify the information in MultipassOffset between iterations. Therefore, the driver can use MultipassOffset to save the progress between iterations. For example, the driver can store the page number that was last transferred for a paged-based transfer.

A paging buffer is currently built for the following types of operations:

Note that if the driver must use a hardware aperture to linearize a swizzled allocation that an application can directly access, the driver must unswizzle that allocation while the driver transfers the allocation to system memory to maintain the coherency of the allocation's virtual address. The driver must unswizzle the allocation because an eviction might occur while the application is accessing the allocation.

The system's memory manager ensures that the transfer is invisible to the application. However, because the allocation is in system memory and the allocation's virtual address can no longer go through the hardware aperture, the driver must ensure the byte ordering into system memory matches what was visible through the aperture.

DxgkDdiBuildPagingBuffer should be made pageable.

Examples

The following code example shows how to use DxgkDdiBuildPagingBuffer.

NTSTATUS ntStatus;
DXGKARG_BUILDPAGINGBUFFER param;

// The driver receives the following paging operation to build:
//
param.Flags = 0;
param.pDmaBuffer= CurrentPagingBuffer;
param.DmaSize = CurrentPagingBufferSizeLeft;
param.pDmaBufferPrivateData = CurrentPagingBufferPrivateData;
param.DmaBufferPrivateDataSize = CurrentPagingBufferPrivateDataSizeLeft;
param.Operation = DXGK_OPERATION_TRANSFER;
param.Transfer.Flags = 0;
param.Transfer.TransferOffset = CurrentOffsetInAllocationBeingTransfered;
param.Transfer.hAllocation = DriverContextForAllocationBeingMoved;
param.Transfer.Source.SegmentId = 0; // Source is an MDL.
param.Transfer.Source.pMdl = MDLDescribingPagesForAllocationBeingMoved;
param.Transfer.Destination.SegmentId = 1; // Source to segment #1.
param.Transfer.Destination.SegmentAddress = 0; // Source to offset 0 of segment #1.

// The driver receives MultipassOffset when it is initialized to zero
// and uses it for multiple iterations of the paging operation.
//
param.MultipassOffset = 0;

do {
    // Call the driver's BuildPagingBuffer function to build a paging buffer.
    //
    ntStatus = BuildPagingBuffer(hAdapter, &param);
    // BuildPagingBuffer updates the size that is left in the
    //  paging buffer with the amount of bytes that were written.
    //
    if (NT_SUCCESS(ntStatus)) {
        //
        // If STATUS_SUCCESS, batch the paging buffer to the
        // scheduler after multiple paging operations are batched.
    }
    else if (ntStatus == STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER) {

        //
        // If STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER, submit the current paging buffer to the scheduler to let
        // the GPU start working on a partial transfer.

        VidSchSubmitPagingBuffer(CurrentPagingBuffer, CurrentPagingBufferSizeLeft);

        // Acquire a new paging buffer to complete the transfer.
        //
        VidMmAcquirePagingBuffer(&CurrentPagingBuffer, &CurrentPagingBufferSizeLeft);
    }
    else {
        //
        // A critical failure occurred, so bugcheck the system.
        // This situation should never occur because the driver can
        // fail the call only if it requires more DMA buffer space.
    }
} while(!NT_SUCCESS(ntStatus))

See also

DXGKARG_BUILDPAGINGBUFFER

DxgkDdiAddDevice

DxgkDdiPatch

DxgkDdiSubmitCommand

pfnLockCb