Partager via


PFND3DDDI_LOCKCB fonction de rappel (d3dumddi.h)

La fonction pfnLockCb verrouille une allocation et obtient un pointeur vers l’allocation à partir du pilote miniport d’affichage ou du gestionnaire de mémoire vidéo.

Syntaxe

PFND3DDDI_LOCKCB Pfnd3dddiLockcb;

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

Paramètres

hDevice

Handle pour le périphérique d’affichage (contexte graphique).

unnamedParam2

pData [in, out]

Pointeur vers une structure D3DDDICB_LOCK qui décrit l’allocation à verrouiller.

Valeur retournée

pfnLockCb retourne l’une des valeurs suivantes :

Code de retour Description
S_OK L’allocation a été correctement verrouillée.
D3DERR_NOTAVAILABLE Une ouverture n’était pas disponible.
D3DERR_WASSTILLDRAWING L’allocation était toujours utilisée pour le rendu.
D3DDDIERR_CANTEVICTPINNEDALLOCATION L’allocation n’a pas pu être verrouillée en raison de l’indisponibilité d’une ouverture de balayage et de l’impossibilité de supprimer l’allocation parce qu’elle a été épinglée.
E_OUTOFMEMORY pfnLockCb n’a pas pu se terminer en raison d’une mémoire insuffisante (cette situation se produit lorsque le système est dans une situation de mémoire extrêmement faible et qu’il n’y a pas suffisamment d’espace pour allouer le tableau de pages).
E_INVALIDARG Les paramètres ont été validés et déterminés comme incorrects.
D3DDDIERR_DEVICEREMOVED pfnLockCb n’a pas pu amener le gestionnaire de mémoire vidéo et le pilote miniport d’affichage à effectuer les actions appropriées, car un arrêt de Plug-and-Play (PnP) ou un événement TDR (Timeout Detection and Recovery) s’est produit. La fonction de pilote d’affichage en mode utilisateur qui a appelé pfnLockCb(généralement, la fonction Lock ou ResourceMap ) doit retourner ce code d’erreur au runtime Direct3D.
Direct3D version 9 Remarque : Pour plus d’informations sur le retour des codes d’erreur, consultez Renvoi de codes d’erreur reçus à partir de fonctions d’exécution.
Direct3D versions 10 et 11 Remarque : Si la fonction de pilote ne retourne pas de valeur (autrement dit, a VOID pour un type de paramètre de retour), la fonction de pilote appelle la fonction pfnSetErrorCb pour renvoyer un code d’erreur au runtime. Pour plus d’informations sur la gestion des codes d’erreur, consultez Gestion des erreurs.

Cette fonction peut également retourner d’autres valeurs HRESULT.

Remarques

Le pilote d’affichage en mode utilisateur peut appeler la fonction pfnLockCb du runtime Microsoft Direct3D pour verrouiller une allocation et obtenir un pointeur vers l’allocation à partir du pilote miniport d’affichage ou du gestionnaire de mémoire vidéo. Le pilote d’affichage en mode utilisateur appelle généralement pfnLockCb en réponse à un appel à sa fonction Lock ou ResourceMap (ou à d’autres variantes de ResourceMap telles que DynamicIABufferMapDiscard) pour verrouiller une ressource ou une surface dans la ressource. Avant de revenir de l’appel Lock ou ResourceMap , le pilote d’affichage en mode utilisateur doit d’abord mapper la ressource ou la surface à l’allocation appropriée, puis appeler pfnLockCb pour verrouiller l’allocation. L’allocation doit être verrouillée avant de pouvoir être lue ou écrite dans, car le verrouillage est le suivant :

  • Garantit que la plage d’adresses virtuelles pour l’allocation reste inchangée, valide, lisible et accessible en écriture pendant la durée du verrou. Le gestionnaire de mémoire vidéo fournit cette garantie.
  • Fournit un moyen de synchroniser les opérations de lecture et d’écriture de l’allocation avec les accès au matériel graphique de l’allocation. Le gestionnaire de mémoire vidéo et le pilote de miniport d’affichage effectuent la synchronisation.
Remarque de Direct3D version 9 :

Le pilote d’affichage en mode utilisateur appelle généralement les fonctions pfnLockCb et pfnUnlockCb qui correspondent à chaque appel à ses fonctions Lock et Unlock , respectivement, sauf lorsque le pilote gère les ressources dans lesquelles l’indicateur de champ bit dynamique a été défini dans le membre Indicateurs de la structure D3DDDIARG_CREATERESOURCE lors de la création des ressources. Le runtime demande fréquemment que le pilote verrouille ces types de ressources, souvent avec l’indicateur de champ de bits NoOverwrite défini dans le membre Flags de la structure D3DDDIARG_LOCK . Étant donné que les données de ces ressources ne doivent pas être modifiées (comme indiqué par NoOverwrite), l’appel de pfnLockCb pour chaque demande de verrouillage consomme un temps de traitement excessif. Pour empêcher l’appel de pfnLockCb pour chaque demande de verrouillage, le pilote peut mettre en cache le pointeur de mémoire virtuelle qu’il retourne dans le membre pSurfData de D3DDDIARG_LOCK lorsque sa fonction Lock est appelée avec l’indicateur de champ de bits NoOverwrite défini. Toutefois, le pilote peut continuer à appeler pfnLockCb chaque fois que sa fonction Lock est appelée avec l’indicateur de champ de bits Discard défini ou aucun indicateur défini.

Direct3D Versions 10 et 11 Remarque :

Le pilote d’affichage en mode utilisateur appelle généralement les fonctions pfnLockCb et pfnUnlockCb qui correspondent à chaque appel à ses fonctions ResourceMap et ResourceUnmap (ou à d’autres variantes de ces fonctions). Cela ne se produit pas lorsque le pilote gère les ressources dans lesquelles la valeur D3D10_DDI_USAGE_DYNAMIC a été définie dans le membre Utilisation de la structure D3D10DDIARG_CREATERESOURCE ou D3D11DDIARG_CREATERESOURCE lors de la création des ressources. Le runtime demande fréquemment que le pilote verrouille ces types de ressources, souvent en passant la valeur D3D10_DDI_MAP_WRITE_NOOVERWRITE au paramètre DDIMap dans l’appel à ResourceMap. Étant donné que les données de ces ressources ne doivent pas être modifiées (comme indiqué par D3D10_DDI_MAP_WRITE_NOOVERWRITE), l’appel de pfnLockCb pour chaque demande de verrouillage consomme un temps de traitement excessif. Pour empêcher l’appel de pfnLockCb pour chaque demande de verrouillage, le pilote peut mettre en cache le pointeur de mémoire virtuelle qu’il retourne dans le paramètre pMappedSubResource lorsque sa fonction ResourceMap est appelée avec D3D10_DDI_MAP_WRITE_NOOVERWRITE. Toutefois, le pilote peut continuer à appeler pfnLockCb chaque fois que sa fonction ResourceMap est appelée avec la valeur D3D10_DDI_MAP_WRITE_DISCARD ou 0 passée au paramètre DDIMap .

Bien que l’application ne contienne pas de verrou en suspens pour la ressource associée au pointeur de mémoire virtuelle, le pilote désactive généralement le pointeur de mémoire virtuelle en appelant la fonction pfnUnlockCb avant que le pilote appelle la fonction pfnRenderCb . Si le verrou n’est pas mis en cache ou si le verrou ne peut pas être mis en cache, car la ressource est toujours verrouillée dans l’application, le matériel peut s’afficher à partir d’une allocation verrouillée. Le gestionnaire de mémoire vidéo ne peut pas prendre en charge ce mode de fonctionnement si l’allocation est en mémoire vidéo locale ; par conséquent, le gestionnaire de mémoire supprime l’allocation à la mémoire système ou AGP lorsque le gestionnaire de mémoire détecte cette situation. Si l’allocation n’est pas prise en charge dans le segment de mémoire système ou AGP, le gestionnaire de mémoire échoue à l’appel à pfnRenderCb avec D3DDDIERR_CANTRENDERLOCKEDALLOCATION. Par conséquent, les allocations de tampons de vertex et d’index allouées en réponse à la création de ressources dans lesquelles l’indicateur de champ binaire dynamique est défini dans le membre Indicateurs de D3DDDIARG_CREATERESOURCE (ou la valeur D3D10_DDI_USAGE_DYNAMIC est définie dans le membre Utilisation de D3D10DDIARG_CREATERESOURCE ou D3D11DDIARG_CREATERESOURCE) doivent être prises en charge dans les segments système ou AGP.

La définition de l’indicateur Ignorer le champ binaire dans le membre Indicateurs de D3DDDICB_LOCK dans un appel à pfnLockCb entraîne la création d’un instance de l’allocation verrouillée par le gestionnaire de mémoire vidéo. Le gestionnaire de mémoire vidéo représente la nouvelle instance en retournant un nouveau handle au pilote d’affichage en mode utilisateur dans le membre hAllocation de D3DDDICB_LOCK.

Note La fonction DxgkDdiCreateAllocation du pilote miniport d’affichage n’est pas appelée lorsqu’une nouvelle instance d’une allocation est créée. Les instances apparaissent pour le pilote de miniport d’affichage sous forme d’allocations qui sont simultanément paginées à plusieurs emplacements différents.
 
Le gestionnaire de mémoire vidéo peut échouer à un verrou dans lequel l’indicateur Ignorer le champ binaire est défini, car le gestionnaire de mémoire vidéo ne peut pas créer un instance ou réutiliser un instance existant d’une allocation. En cas d’échec, le pilote d’affichage en mode utilisateur doit appeler la fonction pfnRenderCb pour vider sa mémoire tampon de commandes actuelle dans le noyau. Ce vidage de la mémoire tampon de commandes peut mettre hors service certaines instances de l’allocation qui n’ont pas pu être verrouillées à l’aide de l’indicateur Ignorer le champ de bits.

Après avoir vidé sa mémoire tampon de commandes, le pilote d’affichage en mode utilisateur doit essayer de verrouiller à nouveau la surface à l’aide des indicateurs de champ binaire Discard et NoExistingReference . L’indicateur de champ de bits NoExistingReference indique au gestionnaire de mémoire vidéo que le pilote n’a actuellement aucune référence à une instance de l’allocation qui est verrouillée en file d’attente dans sa mémoire tampon de commandes. Le gestionnaire de mémoire vidéo peut ensuite réutiliser n’importe quelle instance de l’allocation pour gérer le verrou, y compris la instance actuelle.

Après un appel à pfnLockCb dans lequel l’indicateur de champ de bits Ignorer est défini, le pilote d’affichage en mode utilisateur doit toujours case activée pour une valeur de handle mise à jour dans le membre hAllocation de D3DDDICB_LOCK. Si un nouveau handle d’allocation est fourni, le pilote d’affichage en mode utilisateur doit mettre à jour sa structure de données interne pour référencer le nouveau handle d’allocation. Le pilote d’affichage en mode utilisateur doit également ajouter une version reprogrammée de l’adresse de base d’allocation verrouillée à la mémoire tampon de commande actuelle (car les instances d’allocation contiennent des adresses de base différentes). Le gestionnaire de mémoire vidéo valide l’utilisation des instances d’allocation utilisées par le pilote et rejette les mémoires tampons DMA qui utilisent les instances d’allocation de manière incorrecte (autrement dit, les appels à pfnPresentCb et pfnRenderCb échouent s’ils utilisent incorrectement des instances d’allocation). Une fois que le pilote fait référence à un instance particulier d’une allocation, il ne peut plus référencer une instance précédente de la même allocation. Par exemple, si une mémoire tampon de commandes utilise l’allocation A et utilise actuellement les instances A0 et A1, dès qu’A1 est utilisé (c’est-à-dire, apparaît dans la liste emplacement du correctif), A0 devient non valide. Le pilote de miniport d’affichage peut générer une liste d’emplacements de correctif qui fait référence à la fois à A0 et A1. Toutefois, les références doivent être triées (c’est-à-dire, A0 peut être utilisé en premier ; A0 devient non valide une fois qu’A2 est utilisé ; A1 devient non valide quand A2 est utilisé, et ainsi de suite).

Le pilote d’affichage en mode utilisateur peut appeler pfnLockCb pour les allocations de mémoire système, même si la mémoire n’a pas été préallouée, car le pilote de miniport d’affichage peut être en cours d’envoi, via DMA, ou de transfert asynchrone de ces allocations vers du matériel graphique. Par conséquent, avant qu’une application ne soit autorisée à écrire sur la surface, le pilote miniport d’affichage et le gestionnaire de mémoire vidéo doivent être avertis afin qu’ils puissent bloquer le verrou si nécessaire.

Le pilote d’affichage en mode utilisateur peut également verrouiller les sous-régions d’une allocation. Ce type de verrou n’est généralement pas nécessaire lorsqu’une ouverture matérielle de déverrouillage ou de linéarisation est disponible, car, dans ce cas, le pilote d’affichage en mode utilisateur peut traduire un verrou sur l’ensemble de l’allocation en sous-région en désactivant le pointeur. Toutefois, lorsque pfnLockCb échoue en utilisant D3DERR_NOTAVAILABLE pour indiquer qu’une ouverture n’est pas disponible, le gestionnaire de mémoire demande au pilote d’affichage en mode utilisateur de copier le contenu de la mémoire vidéo. Le pilote d’affichage en mode utilisateur désactive ou linéarise le contenu de la mémoire vidéo lors de sa copie dans une autre zone de mémoire. Dans ce cas, le pilote d’affichage en mode utilisateur peut fournir une liste de pages à copier pour économiser de grandes quantités de copie lors du verrouillage de petites sous-régions dans une allocation importante. Notez que le gestionnaire de mémoire échoue à un appel à pfnLockCb avec D3DERR_NOTAVAILABLE si le pilote d’affichage en mode utilisateur n’a pas défini l’indicateur de champ binaire LockEntire dans le membre Flags de la structure D3DDDICB_LOCK et n’a pas spécifié de liste de pages dans le membre pPages de D3DDDICB_LOCK. Si le pilote d’affichage en mode utilisateur définit l’indicateur de champ de bits LockEntire , il doit également définir les membres NumPages et pPages de D3DDDICB_LOCK sur 0 et NULL, respectivement. Le pilote d’affichage en mode utilisateur doit toujours fournir une liste de pages dans pPages lors du verrouillage d’une allocation qui a été créée avec un magasin de stockage permanent. Dans ce cas, le gestionnaire de mémoire utilise la liste des pages pour marquer comme sale uniquement des pages spécifiques et n’est pas tenu de copier l’intégralité de l’allocation à partir du magasin de stockage lorsqu’elle est utilisée pour le rendu.

Le pilote d’affichage en mode utilisateur peut appeler pfnLockCb pour acquérir plusieurs plages swizzling pour une seule allocation (par exemple, une plage swizzling pour chaque niveau MIP). Si le pilote ne peut acquérir aucune des plages, le runtime Direct3D supprime l’allocation entière pour gérer le verrou (tous les niveaux MIP) et récupère toutes les plages swizzling.

Lorsque le pilote d’affichage en mode utilisateur demande qu’une plage swizzling soit affectée à l’allocation, le pilote demande effectivement l’accès aux bits nonwizzled de l’allocation. Pour ces demandes, le gestionnaire de mémoire vidéo effectue des pages dans l’allocation dans un segment de mémoire et configure une plage de balayage pour accéder à l’allocation ou aux pages de l’allocation dans un segment de mémoire, puis supprime l’allocation à la mémoire système tout en demandant au pilote de déwizzler l’allocation sur le chemin de la mémoire système. Une allocation qui a été nonwizzled à la mémoire système est reswizzled (en étant paginée dans la mémoire vidéo) avant que le GPU utilise à nouveau l’allocation. Par conséquent, le pilote ne peut pas demander un verrou de type sans remplacement (en définissant l’indicateur de champ binaire DonotWait ) lorsqu’il acquiert une plage swizzling. De même, le pilote ne peut pas référencer un verrou d’allocation d’une telle manière dans une mémoire tampon DMA qui est envoyée au GPU (car la mémoire tampon DMA sera rejetée).

Le pilote d’affichage en mode utilisateur peut verrouiller une allocation swizzled sans acquérir une plage de balayage si le pilote doit accéder aux bits de l’allocation dans un format swizzled. Dans ce cas, le gestionnaire de mémoire vidéo fournit au pilote un pointeur vers les bits swizzled de l’allocation. Toutefois, le pilote ne peut pas demander de pointeur vers les bits swizzled de l’allocation alors qu’une demande pour les bits nonwizzled est en attente, et vice versa (autrement dit, un verrou est actuellement en attente sur l’allocation avec une plage swizzling acquise).

Le pilote d’affichage en mode utilisateur doit passer l’indicateur de champ de bits Ignorer dans le membre Flags de D3DDDICB_LOCK dans l’appel pfnLockCb dans les situations suivantes :

  • Lorsque le runtime Direct3D transmet l’indicateur ignorer le champ bit dans le membre Indicateurs de la structure D3DDDIARG_LOCK dans l’appel à la fonction Lock du pilote d’affichage en mode utilisateur
  • Lorsque le runtime transmet la valeur D3D10_DDI_MAP_WRITE_DISCARD au paramètre DDIMap dans l’appel à la fonction ResourceMap du pilote
La définition de l’indicateur Ignorer le champ de bits permet au gestionnaire de mémoire de déterminer s’il doit renommer l’allocation ou si le thread d’application se bloque jusqu’à ce que l’allocation soit inactive. Pour plus d’informations sur le renommage d’une allocation, consultez Demande de renommer une allocation. Le pilote peut utiliser sa propre prise en charge du renommage ou la prise en charge du renommage du gestionnaire de mémoire. Pour utiliser sa propre prise en charge du renommage, le pilote définit l’indicateur de champ de bits DonotWait , en réponse à un appel lock avec l’indicateur Ignorer le champ de bits, ou en réponse à un appel ResourceMap avec le D3D10_DDI_MAP_WRITE_DISCARD valeur définie. La définition de l’indicateur de champ de bits DonotWait entraîne l’échec de l’appel à pfnLockCb avec D3DERR_WASSTILLDRAWING si le matériel graphique utilise toujours l’allocation. Un tel échec indique au pilote d’affichage en mode utilisateur le renommage ou la mise en mémoire tampon multiple de l’allocation.
Note L’indicateur de champ de bits DonotWait n’a aucun effet sur le gestionnaire de mémoire si l’indicateur ignorer le champ de bits est également défini.
 
Le pilote d’affichage en mode utilisateur doit définir l’indicateur de champ de bits IgnoreSync dans le membre Indicateurs de D3DDDICB_LOCK lorsqu’il ne nécessite pas que le gestionnaire de mémoire case activée si le matériel graphique utilise l’allocation. Le pilote d’affichage en mode utilisateur doit ensuite synchroniser correctement l’accès à l’allocation. Si l’indicateur de champ de bits DonotWait n’est pas spécifié avec l’indicateur de champ de bits IgnoreSync , le gestionnaire de mémoire ignore l’indicateur de champ de bits IgnoreSync .
Note L’indicateur de champ de bits IgnoreSync n’a aucun effet sur le gestionnaire de mémoire si l’indicateur de champ de bits Ignorer est également défini.
 
Exemple

L’exemple de code suivant montre comment l’indicateur Ignorer le champ de bits est utilisé dans un appel à 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);

Configuration requise

Condition requise Valeur
Client minimal pris en charge Disponible dans Windows Vista et les versions ultérieures des systèmes d’exploitation Windows.
Plateforme cible Desktop (Expérience utilisateur)
En-tête d3dumddi.h (inclure D3dumddi.h)

Voir aussi

D3D10DDIARG_CREATERESOURCE

D3D11DDIARG_CREATERESOURCE

D3DDDIARG_LOCK

D3DDDICB_LOCK

D3DDDI_DEVICECALLBACKS

Verrou

ResourceMap

ResourceUnmap