PFND3DDDI_LOCKCB función de devolución de llamada (d3dumddi.h)

La función pfnLockCb bloquea una asignación y obtiene un puntero a la asignación desde el controlador de minipuerto de pantalla o el administrador de memoria de vídeo.

Sintaxis

PFND3DDDI_LOCKCB Pfnd3dddiLockcb;

HRESULT Pfnd3dddiLockcb(
  HANDLE hDevice,
  D3DDDICB_LOCK *unnamedParam2
)
{...}

Parámetros

hDevice

Identificador del dispositivo de visualización (contexto de gráficos).

unnamedParam2

pData [in, out]

Puntero a una estructura de D3DDDICB_LOCK que describe la asignación al bloqueo.

Valor devuelto

pfnLockCb devuelve uno de los siguientes valores:

Código devuelto Descripción
S_OK La asignación se bloqueó correctamente.
D3DERR_NOTAVAILABLE No había una abertura disponible.
D3DERR_WASSTILLDRAWING La asignación todavía se estaba usando para la representación.
D3DDDIERR_CANTEVICTPINNEDALLOCATION No se pudo bloquear la asignación debido a la falta de disponibilidad de una apertura deswizzling y la incapacidad de expulsar la asignación porque estaba anclada.
E_OUTOFMEMORY pfnLockCb no se pudo completar debido a memoria insuficiente (esta situación se produce cuando el sistema está en una situación de memoria extrema baja y no hay suficiente espacio para asignar la matriz de páginas).
E_INVALIDARG Los parámetros se validaron y determinaron que son incorrectos.
D3DDDIERR_DEVICEREMOVED pfnLockCb no pudo hacer que el administrador de memoria de vídeo y el controlador de minipuerto de pantalla realicen las acciones adecuadas porque se ha producido una detención de Plug and Play (PnP) o un evento de detección y recuperación de tiempo de espera (TDR). La función del controlador de visualización en modo de usuario que llamó a pfnLockCb(normalmente, la función Lock o ResourceMap ) debe devolver este código de error al tiempo de ejecución de Direct3D.
Direct3D versión 9 Nota: Para obtener más información sobre cómo devolver códigos de error, vea Devolver códigos de error recibidos de funciones en tiempo de ejecución.
Versiones 10 y 11 de Direct3D Nota: Si la función del controlador no devuelve un valor (es decir, tiene VOID para un tipo de parámetro de valor devuelto), la función de controlador llama a la función pfnSetErrorCb para enviar un código de error de nuevo al tiempo de ejecución. Para obtener más información sobre cómo controlar los códigos de error, consulte Control de errores.

Esta función también puede devolver otros valores HRESULT.

Comentarios

El controlador de pantalla en modo de usuario puede llamar a la función pfnLockCb del entorno de ejecución de Microsoft Direct3D para bloquear una asignación y obtener un puntero a la asignación desde el controlador de minipuerto de pantalla o el administrador de memoria de vídeo. El controlador de pantalla en modo de usuario normalmente llama a pfnLockCb en respuesta a una llamada a su función Lock o ResourceMap (u otras variaciones de ResourceMap , como DynamicIABufferMapDiscard) para bloquear un recurso o una superficie dentro del recurso. Antes de volver desde la llamada lock o ResourceMap , el controlador de pantalla en modo de usuario debe asignar primero el recurso o la superficie a la asignación adecuada y, a continuación, llamar a pfnLockCb para bloquear la asignación. La asignación debe bloquearse antes de que se pueda leer desde o escribir en porque se bloquea:

  • Garantiza que el intervalo de direcciones virtuales de la asignación permanece sin cambios, válidos, legibles y grabables durante el bloqueo. El administrador de memoria de vídeo proporciona esta garantía.
  • Proporciona una manera de sincronizar las operaciones de lectura y escritura de la asignación con accesos de hardware gráfico de la asignación. El administrador de memoria de vídeo y el controlador de minipuerto de pantalla realizan la sincronización.
Nota de Direct3D versión 9:

El controlador de pantalla en modo de usuario normalmente llama a las funciones pfnLockCb y pfnUnlockCb que corresponden a cada llamada a sus funciones Lock y Unlock , respectivamente, excepto cuando el controlador controla los recursos en los que se estableció la marca de campo de bits dinámico en el miembro Flags de la estructura D3DDDIARG_CREATERESOURCE cuando se crearon los recursos. El tiempo de ejecución solicita con frecuencia que el controlador bloquee estos tipos de recursos, a menudo con la marca de campo de bits NoOverwrite establecida en el miembro Flags de la estructura D3DDDIARG_LOCK . Dado que los datos de estos recursos no se deben modificar (como se indica en NoOverwrite), llamar a pfnLockCb para cada solicitud de bloqueo consume un tiempo de procesamiento excesivo. Para evitar llamar a pfnLockCb para cada solicitud de bloqueo, el controlador puede almacenar en caché el puntero de memoria virtual que devuelve en el miembro pSurfData de D3DDDIARG_LOCK cuando se llama a su función Lock con la marca de campo de bits NoOverwrite establecida. Sin embargo, el controlador puede seguir llamando a pfnLockCb cada vez que se llama a su función Lock con la marca Descartar campo de bits establecida o sin marcas establecidas.

Nota de las versiones 10 y 11 de Direct3D:

El controlador de pantalla en modo de usuario suele llamar a las funciones pfnLockCb y pfnUnlockCb que corresponden a cada llamada a sus funciones ResourceMap y ResourceUnmap (u otras variaciones de estas funciones). Esto no sucede cuando el controlador controla los recursos en los que se estableció el valor de D3D10_DDI_USAGE_DYNAMIC en el miembro Usage de la estructura D3D10DDIARG_CREATERESOURCE o D3D11DDIARG_CREATERESOURCE cuando se crearon los recursos. El tiempo de ejecución solicita con frecuencia que el controlador bloquee estos tipos de recursos, a menudo pasando el valor de D3D10_DDI_MAP_WRITE_NOOVERWRITE al parámetro DDIMap en la llamada a ResourceMap. Dado que los datos de estos recursos no se deben modificar (como se indica en D3D10_DDI_MAP_WRITE_NOOVERWRITE), llamar a pfnLockCb para cada solicitud de bloqueo consume un tiempo de procesamiento excesivo. Para evitar llamar a pfnLockCb para cada solicitud de bloqueo, el controlador puede almacenar en caché el puntero de memoria virtual que devuelve en el parámetro pMappedSubResource cuando se llama a su función ResourceMap con D3D10_DDI_MAP_WRITE_NOOVERWRITE. Sin embargo, el controlador puede seguir llamando a pfnLockCb cada vez que se llama a su función ResourceMap con el valor de D3D10_DDI_MAP_WRITE_DISCARD o 0 pasado al parámetro DDIMap .

Aunque la aplicación no contiene un bloqueo pendiente para el recurso asociado al puntero de memoria virtual, el controlador normalmente descacha el puntero de memoria virtual llamando a la función pfnUnlockCb antes de que el controlador llame a la función pfnRenderCb . Si el bloqueo no está almacenado en caché o si el bloqueo no se puede almacenar en caché porque la aplicación todavía tiene el recurso bloqueado, el hardware podría representarse desde una asignación bloqueada. El administrador de memoria de vídeo no puede admitir este modo de operación si la asignación está en memoria de vídeo local; por lo tanto, el administrador de memoria expulsa la asignación a la memoria del sistema o AGP cuando el administrador de memoria detecta esta situación. Si no se admite la asignación en el segmento de memoria del sistema o AGP, el administrador de memoria produce un error en la llamada a pfnRenderCb con D3DDDIERR_CANTRENDERLOCKEDALLOCATION. Por lo tanto, las asignaciones de búfer de vértices e índices que se asignan en respuesta a la creación de recursos en los que se establece la marca de campo de bits dinámico en el miembro Flags de D3DDDIARG_CREATERESOURCE (o el valor de D3D10_DDI_USAGE_DYNAMIC se establece en el miembro Usage de D3D10DDIARG_CREATERESOURCE o D3D11DDIARG_CREATERESOURCE) deben admitirse en segmentos del sistema o AGP.

Al establecer la marca Descartar campo de bits en el miembro Flags de D3DDDICB_LOCK en una llamada a pfnLockCb , el administrador de memoria de vídeo crea una nueva instancia de la asignación que se está bloqueando. El administrador de memoria de vídeo representa la nueva instancia devolviendo un nuevo identificador al controlador de pantalla en modo de usuario en el miembro hAllocation de D3DDDICB_LOCK.

Nota No se llama a la función DxgkDdiCreateAllocation del controlador display miniport cuando se crea una nueva instancia de una asignación. Las instancias aparecen en el controlador de minipuerto para mostrar como asignaciones que se paginan simultáneamente en varias ubicaciones diferentes.
 
El administrador de memoria de vídeo puede producir un error en un bloqueo en el que se establece la marca Descartar campo de bits porque el administrador de memoria de vídeo no puede crear una nueva instancia o reutilizar una instancia existente de una asignación. Cuando se produce este error, el controlador de pantalla en modo de usuario debe llamar a la función pfnRenderCb para vaciar su búfer de comandos actual en el kernel. Este vaciado del búfer de comandos puede retirar algunas instancias de la asignación que no se pudieron bloquear mediante la marca Descartar campo de bits.

Después de vaciar su búfer de comandos, el controlador de pantalla en modo de usuario debe intentar bloquear la superficie de nuevo mediante las marcas de campo de bits Descartar y NoExistingReference . La marca de campo de bits NoExistingReference indica al administrador de memoria de vídeo que el controlador no tiene actualmente una referencia a ninguna instancia de la asignación bloqueada en cola en su búfer de comandos. Después, el administrador de memoria de vídeo puede reutilizar cualquier instancia de la asignación para controlar el bloqueo, incluida la instancia actual.

Después de una llamada a pfnLockCb en la que se establece la marca Descartar campo de bits, el controlador de pantalla en modo usuario siempre debe comprobar si hay un valor de identificador actualizado en el miembro hAllocation de D3DDDICB_LOCK. Si se proporciona un nuevo identificador de asignación, el controlador de pantalla en modo de usuario debe actualizar su estructura de datos interna para hacer referencia al nuevo identificador de asignación. El controlador de pantalla en modo de usuario también debe agregar una versión programada de la dirección base de asignación bloqueada al búfer de comandos actual (porque las instancias de asignación contienen diferentes direcciones base). El administrador de memoria de vídeo valida el uso de instancias de asignación que usa el controlador y rechaza los búferes DMA que usan las instancias de asignación incorrectamente (es decir, las llamadas a pfnPresentCb y pfnRenderCb producen un error si usan instancias de asignación incorrectamente). Después de que el controlador haga referencia a una instancia determinada de una asignación, el controlador ya no puede hacer referencia a una instancia anterior de la misma asignación. Por ejemplo, si un búfer de comandos usa la asignación A y actualmente usa instancias A0 y A1, en cuanto se usa A1 (es decir, aparece en la lista de ubicación de revisión), A0 deja de ser válido. El controlador de miniporte de pantalla puede generar una lista de ubicaciones de revisión que haga referencia a A0 y A1. Sin embargo, las referencias deben ordenarse (es decir, se puede usar A0 primero; A0 deja de ser válido una vez que se usa A2; A1 deja de ser válido cuando se usa A2, etc.

El controlador de pantalla en modo de usuario puede llamar a pfnLockCb para las asignaciones de memoria del sistema, incluso si la memoria no se ha asignado previamente, ya que el controlador de minipuerto de pantalla podría estar realmente en proceso de envío, a través de DMA o transferir de forma asincrónica esas asignaciones al hardware gráfico. Por lo tanto, antes de que una aplicación pueda escribir en la superficie, se debe notificar al controlador de miniporte de pantalla y al administrador de memoria de vídeo para que puedan bloquear el bloqueo si es necesario.

El controlador de pantalla en modo de usuario también puede bloquear las subregiones de una asignación. Normalmente, este tipo de bloqueo no es necesario cuando hay una apertura de hardware desenfadada o linealización porque, en esta situación, el controlador de pantalla en modo usuario puede traducir un bloqueo en toda la asignación a la subregión desplazando el puntero. Sin embargo, cuando pfnLockCb produce un error mediante D3DERR_NOTAVAILABLE para indicar que una apertura no está disponible, el administrador de memoria solicita al controlador de pantalla en modo de usuario que copie el contenido de la memoria de vídeo. El controlador de pantalla en modo de usuario desenlaza o linealiza el contenido de la memoria de vídeo mientras los copia en otra área de memoria. En esta situación, el controlador de pantalla en modo de usuario puede proporcionar una lista de páginas para copiar para ahorrar grandes cantidades de copia al bloquear pequeñas subregiones en una asignación grande. Tenga en cuenta que el administrador de memoria produce un error en una llamada a pfnLockCb con D3DERR_NOTAVAILABLE si el controlador de pantalla en modo de usuario no estableció la marca de campo de bits LockEntire en el miembro Flags de la estructura D3DDDICB_LOCK y no especificó una lista de páginas en el miembro pPages de D3DDDICB_LOCK. Si el controlador de pantalla en modo de usuario establece la marca de campo de bits LockEntire , también debe establecer los miembros NumPages y pPages de D3DDDICB_LOCK en 0 y NULL, respectivamente. El controlador de pantalla en modo de usuario siempre debe proporcionar una lista de páginas en pPages al bloquear una asignación que se creó con un almacén de respaldo permanente. En esta situación, el administrador de memoria usa la lista de páginas para marcar como páginas específicas y no es necesario copiar toda la asignación desde el almacén de respaldo cuando se usa para la representación.

El controlador de pantalla en modo de usuario puede llamar a pfnLockCb para adquirir varios rangos de giro para una sola asignación (por ejemplo, un intervalo de giro para cada nivel de MIP). Si el controlador no puede adquirir ninguno de los intervalos, el tiempo de ejecución de Direct3D expulsa toda la asignación para controlar el bloqueo (todos los niveles de MIP) y reclama todos los intervalos girantes.

Cuando el controlador de visualización en modo de usuario solicita que se asigne un intervalo de desenredado a la asignación, el controlador solicita efectivamente acceso a los bits desenredados de la asignación. Para estas solicitudes, el administrador de memoria de vídeo ya sea páginas de la asignación en un segmento de memoria y configura un intervalo de desenlazamiento para acceder a la asignación o páginas de la asignación en un segmento de memoria y, a continuación, expulsa la asignación a la memoria del sistema mientras solicita que el controlador deswizzle la asignación en la forma de memoria del sistema. Una asignación que no se desenredó a la memoria del sistema se vuelve a activar (al paginarse en la memoria de vídeo) antes de que la GPU vuelva a usar la asignación. Como resultado, el controlador no puede solicitar un bloqueo de tipo sin sobrescritura (estableciendo la marca de campo de bits DonotWait ) cuando adquiere un intervalo de desenfoque. Del mismo modo, el controlador no puede hacer referencia a un bloqueo de asignación de tal manera en un búfer DMA que se envía a la GPU (porque se rechazará el búfer DMA).

El controlador de pantalla en modo de usuario podría bloquear una asignación desenredada sin adquirir un intervalo de desenredado si el controlador debe tener acceso a los bits de la asignación en un formato desenredado. En esta situación, el administrador de memoria de vídeo proporciona al controlador un puntero a los bits desenredados de la asignación. Sin embargo, el controlador no puede solicitar un puntero a los bits desenredados de la asignación mientras una solicitud de los bits desenredados está pendiente y viceversa (es decir, un bloqueo está pendiente actualmente en la asignación con un intervalo de desenredado adquirido).

El controlador de pantalla en modo de usuario debe pasar la marca Descartar campo de bits en el miembro Flags de D3DDDICB_LOCK en la llamada pfnLockCb en las situaciones siguientes:

  • Cuando el tiempo de ejecución de Direct3D pasa la marca descartar campo de bits en el miembro Flags de la estructura D3DDDIARG_LOCK de la llamada a la función Lock del controlador de pantalla en modo de usuario
  • Cuando el tiempo de ejecución pasa el valor de D3D10_DDI_MAP_WRITE_DISCARD al parámetro DDIMap en la llamada a la función ResourceMap del controlador
Al establecer la marca Descartar campo de bits, el administrador de memoria determina si debe cambiar el nombre de la asignación o debe hacer que el subproceso de la aplicación se detenga hasta que la asignación esté inactiva. Para obtener más información sobre cómo cambiar el nombre de una asignación, vea Solicitar cambiar el nombre de una asignación. El controlador puede usar su propia compatibilidad de cambio de nombre o la compatibilidad de cambio de nombre del administrador de memoria. Para usar su propia compatibilidad con el cambio de nombre, el controlador establece la marca de campo de bits DonotWait , en respuesta a una llamada de bloqueo con la marca Descartar campo de bits establecida o en respuesta a una llamada resourceMap con el valor D3D10_DDI_MAP_WRITE_DISCARD establecido. Al establecer la marca de campo de bits DonotWait , el administrador de memoria producirá un error en la llamada a pfnLockCb con D3DERR_WASSTILLDRAWING si el hardware gráfico sigue usando la asignación. Este error indica que el controlador de pantalla en modo de usuario cambia el nombre o el búfer múltiple de la asignación.
Nota La marca de campo de bits DonotWait no tiene ningún efecto en el administrador de memoria si también se establece la marca Descartar campo de bits.
 
El controlador de pantalla en modo de usuario debe establecer la marca de campo de bits IgnoreSync en el miembro Flags de D3DDDICB_LOCK cuando no requiere que el administrador de memoria compruebe si el hardware gráfico está usando la asignación. El controlador de pantalla en modo de usuario debe sincronizar correctamente el acceso a la asignación. Si no se especifica la marca de campo de bits DonotWait con la marca de campo de bits IgnoreSync , el administrador de memoria omite la marca de campo de bits IgnoreSync .
Nota La marca de campo de bits IgnoreSync no tiene ningún efecto en el administrador de memoria si también se establece la marca Descartar campo de bits.
 
Ejemplo

En el ejemplo de código siguiente se muestra cómo se usa la marca descartar campo de bits en una llamada a pfnLockCb.

HRESULT hr;
D3DDDICB_LOCK LockData;
LockData.hAllocation = AllocationToLock;
LockData.Flags.Discard = TRUE;
hr = pfnLockCb(&LockData)
if (FAILED(hr)) {
    FlushAccumulatedCommandBufferToKernel();
    LockData.Flags.Discard = TRUE;
    LockData.Flags.NoExistingReference = TRUE;
    hr = pfnLockCb(&LockData);
    if (FAILED(hr)) {
        // Fails the lock to the application
    }
}
UpdateAllocationHandleInUMDDataStructure(LockData.hAllocation);
ProgramSurfaceBaseAddressInCurrentCommandBuffer(LockData.hAllocation);

Requisitos

Requisito Value
Cliente mínimo compatible Disponible en Windows Vista y versiones posteriores de los sistemas operativos Windows.
Plataforma de destino Escritorio
Encabezado d3dumddi.h (incluya D3dumddi.h)

Consulte también

D3D10DDIARG_CREATERESOURCE

D3D11DDIARG_CREATERESOURCE

D3DDDIARG_LOCK

D3DDDICB_LOCK

D3DDDI_DEVICECALLBACKS

Bloquear

ResourceMap

ResourceUnmap