Compartir a través de


DXGKDDI_BUILDPAGINGBUFFER función de devolución de llamada (d3dkmddi.h)

La función DxgkDdiBuildPagingBuffer compila búferes de paginación para las operaciones de memoria.

Sintaxis

DXGKDDI_BUILDPAGINGBUFFER DxgkddiBuildpagingbuffer;

NTSTATUS DxgkddiBuildpagingbuffer(
  [in]     IN_CONST_HANDLE hAdapter,
  [in/out] IN_PDXGKARG_BUILDPAGINGBUFFER pBuildPagingBuffer
)
{...}

Parámetros

[in] hAdapter

Identificador de un bloque de contexto asociado a un adaptador de pantalla. El controlador de minipuerto de pantalla proporcionó anteriormente este identificador al subsistema del kernel de gráficos de Microsoft DirectX en la función MiniportDeviceContext parámetro de salida del DxgkDdiAddDevice.

[in/out] pBuildPagingBuffer

Puntero a una estructura de DXGKARG_BUILDPAGINGBUFFER que contiene información para crear un búfer de paginación.

Valor devuelto

DxgkDdiBuildPagingBuffer devuelve uno de los siguientes valores:

código de retorno descripción
STATUS_SUCCESS DxgkDdiBuildPagingBuffersuccess se creó correctamente un búfer de paginación.
STATUS_GRAPHICS_ALLOCATION_BUSY La GPU usa actualmente la asignación del búfer de paginación.
STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER Se requiere más espacio en el búfer de paginación (es decir, en el miembro pDmaBuffer de la estructura DXGKARG_BUILDPAGINGBUFFER a la que apunta el parámetro pBuildPagingBuffer).

Observaciones

Se llama a la función dxgkDdiBuildPagingBuffer para crear búferes de acceso directo a memoria (DMA) de propósito especial que se conocen como búferes de paginación . Un búfer de paginación contiene una operación que mueve el contenido de partes de asignaciones:

  • Dentro de un segmento de una asignación.
  • Entre segmentos de asignaciones.
  • Desde un segmento de una asignación a la memoria del sistema.
  • Desde la memoria del sistema hasta un segmento de una asignación.

El controlador de miniporte de pantalla debe escribir la instrucción de unidad de procesamiento de gráficos (GPU) adecuada en el búfer de paginación proporcionado (en el pDmaBuffer miembro de DXGKARG_BUILDPAGINGBUFFER) según la operación de paginación solicitada; y, a continuación, el controlador debe devolver el búfer de paginación al administrador de memoria de vídeo (que forma parte de Dxgkrnl.sys). El programador de GPU (que también forma parte de Dxgkrnl.sys) llama posteriormente a la función dxgkDdiSubmitComm and del controlador para solicitar que el controlador envíe el búfer de paginación como un búfer DMA normal a la GPU.

Nota Antes de que el administrador de memoria de vídeo envíe el búfer de paginación, llama a la función DxgkDdiPatch del controlador para asignar (es decir, ) direcciones físicas al búfer de paginación; Sin embargo, en la llamada a DxgkDdiPatch, el administrador de memoria de vídeo no proporciona listas de ubicación de revisión. La función DxgkDdiPa tch del controlador puede realizar actualizaciones de última hora en el búfer de paginación; sin embargo, la función DxgkDdiPatch del controlador no puede cambiar el tamaño del búfer de paginación.
 
Cuando el controlador compila correctamente el búfer de paginación, el DxgkDdiBuildPagingBuffer debe actualizar pDmaBuffer para apuntar más allá del último byte que se escribe en el búfer de paginación y, a continuación, devolver STATUS_SUCCESS. Dado que DxgkDdiBuildPagingBuffer solo puede producir un error si se queda sin espacio en el búfer de paginación, el controlador siempre debe comprobar que el búfer de paginación tiene suficiente espacio restante antes de escribir en el búfer. Si no hay suficiente espacio en el búfer de paginación, el controlador debe devolver STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER. Después, el administrador de memoria de vídeo adquiriría un nuevo búfer de paginación y llamaría al DxgkDdiBuildPagingBuffer función para rellenar el nuevo búfer de paginación según la operación de paginación solicitada. Tenga en cuenta que, para una operación de paginación solicitada determinada que rellena varios búferes de paginación, el programador llama al DxgkDdiSubmitCommand función varias veces para que cada búfer de paginación parcial envíe cada búfer de paginación parcial de forma independiente.

Si DxgkDdiBuildPagingBuffer determina que una operación de paginación requiere más de un búfer de paginación, el controlador puede especificar información en el miembro MultipassOffset de DXGKARG_BUILDPAGINGBUFFER y puede usar esta información en varias iteraciones de la operación de paginación. El administrador de memoria de vídeo inicializa la información de MultipassOffset a cero antes de la primera solicitud de operación de paginación y no modifica la información de MultipassOffset entre iteraciones. Por lo tanto, el controlador puede usar multipassOffset para guardar el progreso entre iteraciones. Por ejemplo, el controlador puede almacenar el número de página que se transfirió por última vez para una transferencia basada en paginados.

Actualmente se compila un búfer de paginación para los siguientes tipos de operaciones:

  • Transferencia

    La operación de transferencia mueve el contenido de una asignación de una ubicación a otra. Esta operación es el tipo de operación de memoria más común.

    Una asignación siempre se transfiere completamente de una ubicación a otra. Sin embargo, debido a las restricciones de memoria, la transferencia de una asignación se puede dividir en varias sub-transferencias (es decir, una parte de la asignación se mueve de la ubicación A a B y, a continuación, se mueve la siguiente parte, etc., hasta que se transfiere toda la asignación). La primera sub-transferencia de una asignación se marca con la marca transferstart de bit en el miembro Flags del miembro Transfer de DXGKARG_BUILDPAGINGBUFFER; la última sub-transferencia de una asignación se marca con la marca de TransferEnd campo de bits. Se garantiza que el controlador reciba el final de una transferencia pendiente (es decir, la última subinferencia) antes de que el controlador reciba el inicio de una nueva transferencia.

    Cada sub-transferencia puede requerir varias llamadas a DxgkDdiBuildPagingBuffer completar (por ejemplo, el controlador podría agotarse del espacio de búfer DMA). Por lo tanto, el controlador puede recibir la marca transferStart de en varias llamadas a DxgkDdiBuildPagingBuffer hasta que el controlador reciba la marca TransferEnd en una llamada a DxgkDdiBuildPagingBuffer. La recepción del TransferStart marca varias veces no indica el inicio de varias transferencias nuevas; indica que las sub-transferencias para la asignación requieren varias iteraciones (por ejemplo, si el controlador se quedó sin espacio de búfer DMA). El controlador puede usar el miembro MultipassOffset de DXGKARG_BUILDPAGINGBUFFER para realizar un seguimiento del progreso de una sub-transferencia determinada en varias iteraciones de DxgkDdiBuildPagingBuffer.

    Normalmente, una transferencia se produce en una sola operación. En esta situación, se establecen las marcas de TransferStart y TransferEnd campo de bits.

    En algunos escenarios, es posible que sea necesario que el controlador configure recursos de hardware cuando determinadas asignaciones se paginan en o no memoria. De forma predeterminada, la GPU podría usar la asignación a la que se hace referencia durante la llamada a DxgkDdiBuildPagingBuffer. En estos escenarios, es posible que el controlador requiera que la asignación esté inactiva antes de que los controladores programas los recursos de hardware necesarios (es decir, programar los recursos de hardware no se pueden poner en cola en el búfer DMA proporcionado). En estos escenarios, el controlador puede producir un error en la llamada a DxgkDdiBuildPagingBuffer con STATUS_GRAPHICS_ALLOCATION_BUSY.

    Si el controlador devuelve STATUS_GRAPHICS_ALLOCATION_BUSY, el administrador de memoria de vídeo espera hasta que la GPU se realiza con cualquier referencia a la asignación actual y, a continuación, llama a la función DxgkDdiBuildPagingBuffer función. En la segunda llamada a DxgkDdiBuildPagingBuffer, el administrador de memoria de vídeo establece el AllocationIsIdle marca de campo de bits en el miembro Flags miembro del Transfer miembro de DXGKARG_BUILDPAGINGBUFFER para indicar que la asignación a la que se hace referencia está inactiva. Si no se establece la marca de inactividad, el controlador siempre debe determinar que la asignación está ocupada actualmente o que pronto podría estar ocupada. Si se establece la marca de inactividad, el administrador de memoria de vídeo garantiza que la asignación a la que se hace referencia permanece inactiva durante la llamada a DxgkDdiBuildPagingBuffer.

    Si el hAllocation miembro de DXGKARG_BUILDPAGINGBUFFER es NULL, el controlador debe copiar los datos del origen en el destino sin realizar ninguna rotación o mosaico.

  • Llenar

    La operación de relleno rellena una asignación con un patrón especificado. La operación de relleno se usa para configurar el contenido inicial de una asignación. Cuando se rellena el contenido de la asignación, se garantiza que la asignación está inactiva (es decir, no está en uso por la GPU). La operación de relleno solo se puede realizar en un segmento de memoria. El administrador de memoria de vídeo nunca solicita que el controlador de miniporte de pantalla rellene un segmento de apertura.

  • Descartar contenido

    La operación de descarte-contenido notifica al controlador que se descarta una asignación de la ubicación actual de la asignación en un segmento de memoria. Es decir, la asignación se expulsa y no se copia en la memoria del sistema.

    En algunos escenarios, es posible que sea necesario que el controlador configure recursos de hardware cuando determinadas asignaciones se paginan en o no memoria. De forma predeterminada, la GPU puede usar la asignación a la que se hace referencia durante la llamada a DxgkDdiBuildPagingBuffer. En estos escenarios, es posible que el controlador requiera que la asignación esté inactiva antes de que los controladores programas los recursos de hardware necesarios (es decir, programar los recursos de hardware no se pueden poner en cola en el búfer DMA proporcionado). En estos escenarios, el controlador puede producir un error en la llamada a DxgkDdiBuildPagingBuffer con STATUS_GRAPHICS_ALLOCATION_BUSY.

    Si el controlador devuelve STATUS_GRAPHICS_ALLOCATION_BUSY, el administrador de memoria de vídeo espera hasta que la GPU se realiza con cualquier referencia a la asignación actual y, a continuación, llama a la función DxgkDdiBuildPagingBuffer función. En la segunda llamada a DxgkDdiBuildPagingBuffer, el administrador de memoria de vídeo establece el AllocationIsIdle marca de campo de bits en el Flags miembro del DiscardContent de la estructura DXGKARG_BUILDPAGINGBUFFER para indicar que la asignación a la que se hace referencia está inactiva. Si no se establece la marca de inactividad, el controlador siempre debe determinar que la asignación está ocupada actualmente o que pronto podría estar ocupada. Si se establece la marca de inactividad, el administrador de memoria de vídeo garantiza que la asignación a la que se hace referencia permanece inactiva durante la llamada a DxgkDdiBuildPagingBuffer.

  • Lectura física

    La operación de lectura física lee de una dirección de memoria física especificada. Se solicita al controlador programar la GPU para la operación. El tamaño de la memoria física para acceder a la lectura puede ser de 1 byte a 8 bytes. Dado que los datos leídos son irrelevantes, no es necesario dxgkDdiBuildPagingBuffer para devolver los datos. Sin embargo, en escenarios en los que la CPU intenta leer de la memoria AGP después de que la GPU escribe en esa memoria de AGP, la operación de lectura física es fundamental para garantizar la coherencia de memoria.

  • Escritura física

    La operación física de escritura escribe en una dirección física especificada. Se solicita al controlador programar la GPU para la operación. El tamaño de la memoria física a la que acceder para la operación de escritura puede ser de 1 byte a 8 bytes. Dado que los datos escritos son irrelevantes, DxgkDdiBuildPagingBuffer puede escribir datos en la memoria. Sin embargo, en escenarios en los que la CPU intenta leer de la memoria AGP después de que la GPU escribe en esa memoria de AGP, la operación física de escritura es fundamental para garantizar la coherencia de memoria.

  • Segmento de apertura del mapa

    La operación map-aperture-segment asigna una lista de descriptores de memoria (MDL) especificada a un segmento de apertura especificado en un desplazamiento de segmento especificado para un número especificado de páginas. Si la marca CacheCoherent campo de bits se establece en el miembro Flags del miembro MapApertureSegment de la estructura de DXGKARG_BUILDPAGINGBUFFER, el controlador debe asegurarse de que la coherencia de caché se aplica en las páginas asignadas; De lo contrario, no se requiere la coherencia de caché para las páginas asignadas.

    Nota La CacheCoherent marca de campo de bits solo se establece cuando la memoria caché se asigna a un segmento de apertura coherente con la memoria caché y nunca se establece en un segmento de apertura no coherente con caché o en una asignación combinada de escritura asignada a un segmento coherente con la memoria caché.
     
    El controlador puede usar opcionalmente E/S asignado a memoria (MMIO) para configurar un segmento de apertura. La GPU no accederá al intervalo de apertura en el momento de la configuración. Sin embargo, esta configuración de apertura no debe interferir con la ejecución de la GPU. La GPU no estará inactiva cuando se llame dxgkDdiBuildPagingBuffer con el tipo de operación DXGK_OPERATION_MAP_APERTURE_SEGMENT establecido y la GPU podría estar ocupada accediendo a otras partes del segmento de apertura que se está reconfigurando.
  • Desasignación del segmento de apertura

    La operación unmap-aperture-segment desasigna un rango asignado previamente de un segmento de apertura especificado. El controlador debe asignar el intervalo que no está asignado a la página ficticia que especifica el miembro DummyPage del UnmapApertureSegment miembro de la estructura de DXGKARG_BUILDPAGINGBUFFER.

    Nota Cuando el controlador desasignación a la página ficticia, el controlador debe habilitar los accesos de GPU a través del intervalo de apertura especificado para que el subsistema del kernel gráfico de DirectX pueda detectar problemas de daños. Existen pruebas de conformidad para comprobar esta situación.
     
    El administrador de memoria de vídeo usa la página ficticia que se encuentra en la parte no asignada de la abertura para determinar las dificultades que el administrador de memoria tiene acceso al segmento de apertura.

    Opcionalmente, el controlador puede usar MMIO para configurar un segmento de apertura. La GPU no accederá al intervalo de apertura en el momento de la configuración. Sin embargo, esta configuración de apertura no debe interferir con la ejecución de la GPU. La GPU no estará inactiva cuando se llame a dxgkDdiBuildPagingBuffer con el tipo de operación DXGK_OPERATION_UNMAP_APERTURE_SEGMENT establecido y la GPU podría estar ocupada accediendo a otras partes del segmento de apertura que se está reconfigurando.

  • Transferencia de bloqueo especial

    La operación especial-lock-transfer es similar a la operación de transferencia normal. Sin embargo, en lugar de transferir el contenido de la asignación desde o al almacén de respaldo normal de la asignación, la operación especial de transferencia de bloqueo transfiere el contenido de la asignación desde o a la dirección virtual alternativa configurada para la asignación cuando se llamó a la función de pfnLockCb con el UseAlternateVA conjunto de marcas de campo de bits.

    La operación especial-lock-transfer se produce solo en uno de los escenarios siguientes:

    • Actualmente, la asignación es accesible para la CPU con una dirección virtual alternativa y se está expulsando.
    • Una asignación que se desalodó anteriormente, como la situación que se describe en la viñeta anterior, se vuelve a paginar.
    No se llamará a los controladores que no admiten el uso del UseAlternateVA marca de campo de bits para realizar una operación especial de transferencia de bloqueo.

    En algunos escenarios, es posible que sea necesario que el controlador configure recursos de hardware cuando determinadas asignaciones se paginan en o no memoria. De forma predeterminada, la GPU podría usar la asignación a la que se hace referencia durante la llamada a DxgkDdiBuildPagingBuffer. En estos escenarios, es posible que el controlador requiera que la asignación esté inactiva antes de que los controladores programas los recursos de hardware necesarios (es decir, programar los recursos de hardware no se pueden poner en cola en el búfer DMA proporcionado). En estos escenarios, el controlador puede producir un error en la llamada a DxgkDdiBuildPagingBuffer con STATUS_GRAPHICS_ALLOCATION_BUSY.

    Si el controlador devuelve STATUS_GRAPHICS_ALLOCATION_BUSY, el administrador de memoria de vídeo espera hasta que la GPU se realiza con cualquier referencia a la asignación actual y, a continuación, llama a la función DxgkDdiBuildPagingBuffer función. En la segunda llamada a DxgkDdiBuildPagingBuffer, el administrador de memoria de vídeo establece el AllocationIsIdle marca de campo de bits en el Flags miembro del SpecialLockTransfer miembro de la estructura DXGKARG_BUILDPAGINGBUFFER para indicar que la asignación a la que se hace referencia está inactiva. Si no se establece la marca de inactividad, el controlador siempre debe determinar que la asignación está ocupada actualmente o que pronto podría estar ocupada. Si se establece la marca de inactividad, el administrador de memoria de vídeo garantiza que la asignación a la que se hace referencia permanece inactiva durante la llamada a DxgkDdiBuildPagingBuffer.

Tenga en cuenta que si el controlador debe usar una apertura de hardware para linealizar una asignación desenredada a la que una aplicación puede acceder directamente, el controlador debe desenredar esa asignación mientras el controlador transfiere la asignación a la memoria del sistema para mantener la coherencia de la dirección virtual de la asignación. El controlador debe desenredar la asignación porque puede producirse una expulsión mientras la aplicación accede a la asignación.

El administrador de memoria del sistema garantiza que la transferencia sea invisible para la aplicación. Sin embargo, dado que la asignación está en memoria del sistema y la dirección virtual de la asignación ya no puede pasar por la apertura de hardware, el controlador debe asegurarse de que el orden de bytes en la memoria del sistema coincide con lo que era visible a través de la apertura.

dxgkDdiBuildPagingBuffer debe ser paginable.

Ejemplos

En el ejemplo de código siguiente se muestra cómo usar 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))

Requisitos

Requisito Valor
cliente mínimo admitido Windows Vista
de la plataforma de destino de Escritorio
encabezado de d3dkmddi.h
irQL PASSIVE_LEVEL

Consulte también

DXGKARG_BUILDPAGINGBUFFER

dxgkDdiAddDevice

dxgkDdiPatch de

dxgkDdiSubmitCommand

pfnLockCb