> ## Documentation Index
> Fetch the complete documentation index at: https://devdocs.xbox.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Vue d'ensemble de DirectStorage

> Les API DirectStorage pour XBOX Series X|S offrent des E/S de stockage NVMe à haut débit avec une faible charge processeur pour un grand nombre de petites requêtes.

## Introduction

Cet article offre une vue d'ensemble des API DirectStorage pour les
consoles XBOX Series X|S seulement. Consultez
[DirectStorage sur ordinateur de bureau](https://aka.ms/directstorage) pour obtenir des détails sur DirectStorage sur ordinateur de bureau.

Les plus récents périphériques de stockage NVMe connectés au moyen d'un bus PCIe peuvent atteindre des niveaux très
élevés de débit et d'IOPS (requêtes d'E/S par seconde). La surcharge des
API Win32 signifie que, même si la bande passante de stockage disponible peut être
utilisée, en tirer parti pourrait entraîner une utilisation du processeur
inacceptablement élevée. C'est particulièrement vrai lorsque la charge de travail se compose d'un grand
nombre de petites requêtes.

Les API DirectStorage sont conçues pour éliminer la majeure partie de la surcharge
du système d'exploitation en interagissant étroitement avec le matériel NVMe sous-jacent. Cela permet
d'obtenir une bande passante plus élevée avec une utilisation moindre du processeur. L'objectif est de permettre
le traitement de jusqu'à 50 000 requêtes par seconde tout en utilisant au plus 10 % d'un
seul cœur de processeur.

### Problèmes existants

Le contenu des jeux devient de plus en plus volumineux à mesure que le besoin de ressources
à plus haute résolution augmente à chaque génération de consoles. Le matériel et le logiciel
XBOX One existants présentent plusieurs limitations qui nuisent à la capacité des développeurs
à transférer les données du disque dur vers la mémoire pour ce contenu de nouvelle génération.

* Utilisation élevée du processeur
  * Les API Win32 existantes pourraient nécessiter un cœur de processeur complet en surcharge.
  * Cela dépend du nombre de requêtes du titre.

* Bande passante maximale insuffisante du disque
  * Le livre blanc [Maximiser les performances des fichiers sur XBOX Series X|S (rubrique sous NDA)](https://learn.microsoft.com/gaming/gdk/docs/gdk-dev/console-dev/overviews/file-system/Maximizing_File_Performance_Win32_Scarlett) et [Maximiser les performances des fichiers sur XBOX One (rubrique sous NDA)](https://learn.microsoft.com/gaming/gdk/docs/gdk-dev/console-dev/overviews/file-system/Maximizing_File_Performance_Win32_Xbox_One) traite de ce sujet en détail.

* Impossibilité de prioriser les requêtes de disque
  * Sans la capacité de prioriser les requêtes du titre, il peut être difficile de créer un
    système de diffusion en continu réactif.

* Impossibilité d'annuler les requêtes de disque
  * Sans la capacité d'annuler des requêtes, il peut être difficile de créer un
    système de lecture spéculative.

* Aucune décompression accélérée par le matériel
  * Sans décompression accélérée par le matériel, la décompression logicielle peut exiger
    beaucoup de ressources processeur.

L'ensemble d'API DirectStorage règle directement chacun de ces problèmes. L'effet
global est une augmentation radicale des performances du système de fichiers XBOX.

### Utilisation du processeur

Le principal objectif de conception de DirectStorage est de permettre à un titre de soutenir 50 000 IOPS
en n'utilisant qu'entre 5 % et 10 % d'un seul cœur de processeur. Cela permet
au titre d'obtenir la bande passante maximale du sous-système de stockage NVMe, tout en
permettant au processeur d'être utilisé pour d'autres besoins du titre.

DirectStorage ajoute également la prise en charge de la décompression matérielle. Chaque requête de lecture
peut être acheminée directement du lecteur NVMe vers le bloc de décompression matérielle
intégré. Cela élimine le besoin pour un titre de consacrer des ressources processeur
à la décompression.

### Modèle de pipeline en file d'attente

DirectStorage utilise une méthode par lots, dans laquelle plusieurs requêtes sont ajoutées à une file d'attente.
Plus tard, la file d'attente est vidée vers l'étape suivante du pipeline. Cela
réduit immédiatement le coût processeur global d'une transition entre les étapes
du pipeline. Avec l'ensemble d'API Win32 existant, il y a une transition pour chaque requête.
Les files d'attente DirectStorage utilisent des algorithmes sans verrou pour réduire la contention.
Le titre contrôle le moment où chaque file d'attente est vidée.

Dans de nombreux cas avec les API Win32, les données du disque pourraient devoir être copiées
dans une autre mémoire tampon. Dans certains cas, les données pourraient devoir être copiées plus d'une fois.
DirectStorage élimine ce problème en mappant la mémoire tampon de destination fournie par le titre
directement dans chaque couche du pipeline. Le matériel écrit directement dans
la mémoire tampon fournie par le titre.

Ces changements contribuent à des réductions importantes de la surcharge du processeur.

### Décompression

La capacité du matériel à décompresser les données a été accrue. Il peut maintenant
gérer une plus grande variété de formats, à une vitesse supérieure à celle à laquelle le sous-système NVMe
peut fournir les données. De plus, DirectStorage prend en charge la décompression sur place, ce qui
élimine le besoin de gérer des mémoires tampons distinctes pour les données compressées et
décompressées.

Le matériel prend en charge `BCPACK` et `DEFLATE`, et offre la capacité de réorganiser (swizzle) le
contenu final. Ces formats ne sont pas mutuellement exclusifs. Il est possible d'appliquer
les trois aux données. Cela donne au titre la capacité de choisir la
méthode qui lui offre le meilleur taux de compression et les meilleures performances. Différentes ressources
peuvent utiliser différents paramètres de compression et de réorganisation.

### Profondeur de file d'attente

La recommandation précédente était de ne maintenir que 12 à 16 requêtes asynchrones
en cours à la fois sur un disque rotatif. Aller au-delà n'apportait aucun avantage sur les performances, et
aller en deçà nuisait considérablement aux performances. Cela amenait les titres
à effectuer du travail supplémentaire pour équilibrer leurs requêtes de lecture en attente afin de rester dans
la cible recommandée.

Avec l'objectif de DirectStorage de permettre à un titre d'atteindre 50 000 IOPS, notre
recommandation a changé. Le titre n'a plus besoin d'essayer d'équilibrer le
travail en attente et la profondeur de file d'attente. Le titre devrait soumettre toutes ses requêtes
en attente. Il n'y a aucun avantage à retenir certaines requêtes. Dans de nombreux cas,
retenir des requêtes pourrait nuire aux performances, car le matériel est bloqué en attendant
de nouvelles requêtes.

Le système d'exploitation doit encore, dans certains cas, diviser les grandes requêtes de lecture en
plusieurs requêtes plus petites (par exemple, pour gérer la fragmentation du disque).
Toutefois, cela a été pris en compte dans l'architecture de DirectStorage. L'objectif de conception de
50 000 IOPS est basé sur le nombre d'opérations d'E/S du titre et non sur les requêtes
finales envoyées au matériel.

### Notification

Dans l'architecture Win32, une quantité importante de surcharge est consacrée aux
notifications de fin de lecture. Le titre peut interroger une structure *OVERLAPPED*,
attendre un handle d'Event associé, ou effectuer une lecture
bloquante synchrone. Globalement, cela augmente les besoins en ressources de chaque requête
de lecture.

DirectStorage conserve les deux concepts asynchrones de notification tout en
ajoutant une troisième méthode. Les lectures bloquantes synchrones ne sont pas prises en charge dans
DirectStorage. Il est possible pour un titre d'implémenter son propre système. Toutefois,
ce n'est pas recommandé.

La première méthode asynchrone est implémentée au moyen d'un bloc d'état qui est défini
lorsque les requêtes associées sont terminées. Le titre peut interroger le bloc au
besoin pour déterminer quand les lectures sont terminées. C'est semblable à la méthode Win32
qui consiste à interroger une structure *OVERLAPPED* pour vérifier la fin.

La deuxième méthode asynchrone utilise un objet `Event` Windows pour signaler la fin.
C'est semblable à l'utilisation d'une structure *OVERLAPPED* avec un objet `Event` correspondant.
Le titre peut utiliser la méthode [WaitForSingleObject](https://learn.microsoft.com/windows/win32/api/synchapi/nf-synchapi-waitforsingleobject)
pour suspendre le thread appelant jusqu'à ce que les opérations de lecture soient terminées.

La troisième méthode asynchrone est implémentée au moyen d'un [ID3D12Fence](https://learn.microsoft.com/windows/win32/api/d3d12/nn-d3d12-id3d12fence). Le titre
peut se suspendre en attendant la clôture ou interroger la clôture au besoin.
Il y a également l'avantage que le GPU peut utiliser la clôture pour être notifié directement
des requêtes terminées.

Le système de notification de DirectStorage n'est pas lié à une seule requête de lecture. Il s'agit
d'une entrée placée dans la file d'attente, qui est signalée lorsque toutes les requêtes de lecture
précédentes sont terminées. Cela donne au titre le contrôle sur le degré de granularité
dont il a besoin pour les notifications. Les notifications sont toujours signalées dans l'ordre de la file d'attente.
La file d'attente peut être considérée comme une file FIFO (premier entré, premier sorti). Le titre n'a
qu'à interroger la dernière notification pertinente. Toutes les requêtes mises en file d'attente précédemment
sont garanties d'être terminées.

### Décompression de mémoire à mémoire

DirectStorage fournit un type de file d'attente permettant d'invoquer le matériel de décompression avec
une source de décompression en mémoire plutôt qu'un fichier sur disque. Cela permet d'utiliser
le matériel de décompression si la ressource compressée ne provient pas
d'un fichier ou si elle a été lue précédemment et conservée en mémoire comme cache. Une
file d'attente dont la source est la mémoire n'accepte que des requêtes dont la source est la mémoire, et une file d'attente
dont la source est un fichier n'accepte que des requêtes dont la source est un fichier.

Si aucune option de décompression n'est spécifiée dans une requête dont la source est la mémoire, le
matériel de décompression peut également agir comme moteur de copie DMA.

Bien que DirectStorage garantisse que les notifications de fin sont dans l'ordre,
DirectStorage ne fournit aucune garantie quant au moment où le traitement des requêtes commence.
Par conséquent, il ne doit y avoir aucune dépendance de données entre les requêtes en attente. Autrement
dit, la destination de la requête A ne peut pas servir de source à la requête B, à moins que la requête
B ne soit mise en file d'attente après la fin de la requête A.

Les files d'attente dont la source est la mémoire doivent être créées avec la priorité en temps réel. De plus,
les requêtes en temps réel dont la source est la mémoire sont toujours traitées par le matériel de décompression
avant les requêtes dont la source est le disque qui nécessitent une décompression.
Si les files d'attente dont la source est le disque ne contiennent aucune requête de décompression, les deux
types de files d'attente sont traités entièrement en parallèle sans affecter l'autre type.

### Priorité

DirectStorage permet d'attribuer un niveau de priorité à chaque file d'attente. Chaque entrée de
la file d'attente hérite de la priorité de la file d'attente. Quatre niveaux de priorité différents sont
fournis : temps réel, élevée, normale et basse. Les requêtes sont traitées selon un tourniquet
pondéré. Par exemple, traiter X requêtes de priorité élevée avant de traiter
une requête de priorité normale. Traiter Y requêtes de priorité normale avant de
traiter une requête de priorité basse.

La pondération des priorités est calculée en fonction de la taille de chaque requête. La pondération par défaut
entre chaque priorité est d'environ 10x. Cela signifie que pour chaque 1 Ko de requête de priorité basse,
10 Ko de requête de priorité moyenne et 100 Ko de requête de priorité élevée
auraient été traités.

Les requêtes de lecture Win32 existantes sont acheminées par le même système de priorité. Toutes
les requêtes Win32 sont considérées comme étant de priorité normale.

Les files d'attente dont la source est la mémoire doivent être créées avec la priorité en temps réel.

### Annulation

Chaque requête de lecture DirectStorage est associée à un masque de 64 bits fourni par le titre.
Cela permet de prendre en charge l'annulation des requêtes de lecture en attente. Le titre peut
annuler les requêtes qui correspondent à un ensemble précis d'indicateurs dans le masque.

Même avec la prise en charge de l'annulation, il est toujours possible qu'une requête de lecture soit
traitée par le matériel. La requête d'annulation du titre est une tentative
au mieux. Si la requête est déjà en cours de traitement par le matériel, elle
ne peut pas être annulée.

Comme la requête d'annulation est effectuée au mieux, le titre doit attendre d'être
notifié que le traitement de la requête de lecture est terminé. Le titre
ne peut libérer aucune des ressources nécessaires avant de recevoir une notification ultérieure dans la file d'attente.
Toutefois, pendant ce temps, de nouvelles requêtes correspondant aux indicateurs qui ont été
utilisés dans une requête d'annulation précédente peuvent être mises en file d'attente et ne seront pas annulées.

Lorsqu'une requête annulée se termine, elle est considérée comme une **réussite**, même si elle
a été annulée et n'a pas produit le résultat complet. Autrement dit, si
une annulation est tentée sur une requête, le titre ne peut plus utiliser le
résultat de la requête potentiellement annulée une fois celle-ci terminée.

### Garantie

Les consoles XBOX One et XBOX One S avaient une garantie minimale de 40 Mo/s. La
console XBOX One X a augmenté la garantie minimale à 60 Mo/s. Ces chiffres sont
bien inférieurs aux limites réelles du matériel, qui se situent autour de 130 Mo/s. Cela était
entièrement dû à la surcharge causée par le système d'exploitation.

DirectStorage élimine la majeure partie de la surcharge causée par le système d'exploitation. Cela
permet une garantie minimale plus proche des limites du matériel. La nouvelle garantie
de performance minimale est de 2,0 Go/s sur une fenêtre de 250 ms pour les données brutes. L'utilisation de
la décompression sur le contenu permettra d'augmenter encore la bande passante finale.

Les futures consoles XBOX prendront en charge l'ajout de lecteurs dynamiques installables par l'utilisateur
qui sont également basés sur NVMe. La même garantie de performance minimale que celle
fournie pour le lecteur interne est également fournie pour le lecteur installable par l'utilisateur.

## Vue d'ensemble de l'API

Les interfaces DirectStorage suivent le même modèle que les interfaces Direct3D.
Le titre obtient d'abord une fabrique singleton. La fabrique sert à créer des
files d'attente de requêtes et à ouvrir des fichiers; chacun de ces objets est mappé
directement au matériel. Les requêtes individuelles sont ensuite mises dans une file d'attente pour
être soumises au matériel.

### IDStorageFactoryX

`IDStorageFactoryX` est l'interface principale pour créer des files d'attente, ouvrir des fichiers et
soumettre des requêtes en attente.

L'objet `IDStorageFactoryX `possède les méthodes suivantes.

* [OpenFile](/fr-CA/reference/system/dstorage/interfaces/IDStorageFactoryX/methods/idstoragefactoryx_openfile)
  * Crée un objet `IDStorageFileX `, qui représente un fichier.

* [CreateQueue](/fr-CA/reference/system/dstorage/interfaces/IDStorageFactoryX/methods/idstoragefactoryx_createqueue)
  * Crée un objet `IDStorageQueueX`. Sert à créer des requêtes de lecture.

* [CreateStatusArray](/fr-CA/reference/system/dstorage/interfaces/IDStorageFactoryX/methods/idstoragefactoryx_createstatusarray)
  * Crée un objet `IDStorageStatusArray`, qui gère les indicateurs d'état
    de fin.

* [SetCPUAffinity](/fr-CA/reference/system/dstorage/interfaces/IDStorageFactoryX/methods/idstoragefactoryx_setcpuaffinity)
  * Limite le travail de DirectStorage effectué hors du thread appelant à un ensemble de
    cœurs de processeur défini par le titre.
  * **REMARQUE** DirectStorage essaie d'effectuer la majeure partie du travail dans
    le thread appelant. Le travail hors du thread appelant ne se produit que lorsqu'il ne peut pas être
    effectué dans le thread appelant. Voici des exemples.
    * Le pipeline de ressources sous-jacent est plein pendant `IDStorageQueueX::Submit`,
      et les requêtes de la file d'attente ne peuvent pas toutes être poussées vers l'avant. Les requêtes
      restantes seront traitées plus tard, lorsque les ressources se libéreront, et ce
      traitement est effectué dans un thread de travail DirectStorage.
    * Traitement de la fin des requêtes dans `ID3DFence` ou `IDStorageStatusArray`.

* [SetDebugFlags](/fr-CA/reference/system/dstorage/interfaces/IDStorageFactoryX/methods/idstoragefactoryx_setdebugflags)
  * Contrôle si DirectStorage effectue des validations supplémentaires au moment de la mise
    en file d'attente des requêtes pour faciliter le débogage.

* [SetStagingBufferSize](/fr-CA/reference/system/dstorage/interfaces/IDStorageFactoryX/methods/idstoragefactoryx_setstagingbuffersize)
  * Définit la taille de la mémoire tampon intermédiaire utilisée pour stocker temporairement le contenu chargé
    à partir du périphérique de stockage avant qu'il soit déchiffré/décompressé. Si seules des
    files d'attente dont la source est la mémoire sont utilisées, la mémoire tampon intermédiaire peut avoir une taille de 0.

### IDStorageFactoryX1

L'interface `IDStorageFactoryX1` étend l'interface `IDStorageFactoryX` avec
une méthode [GetStats](/fr-CA/reference/system/dstorage/interfaces/IDStorageFactoryX1/methods/idstoragefactoryx1_getstats).

* [GetStats](/fr-CA/reference/system/dstorage/interfaces/IDStorageFactoryX1/methods/idstoragefactoryx1_getstats)
  * Obtient les statistiques de DirectStorage. Cette fonction peut servir à intégrer
    DirectStorage aux pipelines de diagnostic et de télémétrie existants.
    Elle effectue un traitement minimal et peut donc être appelée souvent. Les statistiques
    n'incluent pas les opérations d'E/S de fichiers Win32.

### IDStorageFactoryX2

L'interface `IDStorageFactoryX2` étend l'interface \`IDStorageFactoryX1 avec
une méthode [CreateQueue1](/fr-CA/reference/system/dstorage/interfaces/IDStorageFactoryX2/methods/idstoragefactoryx_createqueue1).

* [CreateQueue1](/fr-CA/reference/system/dstorage/interfaces/IDStorageFactoryX2/methods/idstoragefactoryx_createqueue1)
  * Crée un objet `IDStorageQueueX2`. Utilise une nouvelle structure pour permettre
    des options supplémentaires lors de la création de la file d'attente, y compris la capacité de remplacer
    la fonctionnalité de soumission automatique d'une file d'attente.

### IDStorageFileX

Tous les fichiers doivent d'abord être ouverts par DirectStorage au moyen de
l'objet `IDStorageFactoryX`. C'est l'équivalent de l'utilisation de `CreateFile` dans les interfaces
API Win32.

Les fichiers sont ouverts avec l'autorisation `FILE_SHARED_READ`. Au besoin, les titres peuvent
ouvrir simultanément le fichier au moyen des API Win32, à condition que les autorisations
appropriées soient respectées. Pendant le développement, les déploiements libres et empaquetés sont pris en charge.

Les fichiers sont fermés soit en appelant explicitement la fonction [Close](/fr-CA/reference/system/dstorage/interfaces/IDStorageFileX/methods/idstoragefilex_close)
sur l'objet fichier, soit lorsque la dernière référence à l'objet
`IDStorageFileX` correspondant est libérée. Toutefois, toutes les opérations d'E/S en cours doivent
être terminées avant que le fichier puisse être fermé. Cela signifie que les deux méthodes de fermeture
d'un fichier bloquent jusqu'à ce que toutes les opérations d'E/S en cours sur ce fichier soient terminées.

Le jeu peut obtenir un handle Win32 vers un fichier représenté par un objet `IDStorageFileX`
en appelant la fonction [GetHandle](/fr-CA/reference/system/dstorage/interfaces/IDStorageFileX/methods/idstoragefilex_gethandle).
Le handle est ouvert avec les autorisations `GENERIC_READ` et le mode de partage `FILE_SHARE_READ`.
Il peut servir à interroger la taille du fichier, etc. Le handle doit être fermé
avec `CloseHandle()` lorsqu'il n'est plus nécessaire.

### IDStorageQueueX

Les requêtes de lecture sont soumises au NVMe au moyen d'un objet `IDStorageQueueX`.
Toutefois, les requêtes ne sont pas soumises au périphérique tant que le titre n'appelle pas
[Submit](/fr-CA/reference/system/dstorage/interfaces/IDStorageQueueX/methods/idstoragequeuex_submit) sur la file d'attente, ou tant qu'une des méthodes Enqueue
n'a pas rempli plus de la moitié de la capacité de la file d'attente depuis la dernière soumission, déclenchant
une soumission automatique. Les soumissions sont traitées comme une seule transition vers
l'étape suivante du pipeline. Cela permet au titre de contrôler le moment où se produit le coût processeur
de la transition entre le titre et le noyau.

Les objets `IDStorageQueueX` possèdent quatre propriétés.

* [SourceType](/fr-CA/reference/system/dstorage/enums/dstorage_request_source_type)
  * Spécifie si la file d'attente peut recevoir des requêtes dont la source est un fichier ou
    des requêtes dont la source est la mémoire.

* [Priority](/fr-CA/reference/system/dstorage/enums/dstorage_priority)
  * La priorité de toutes les requêtes soumises à la file d'attente : temps réel, élevée, normale ou basse.
  * Les files d'attente dont la source est la mémoire doivent être créées avec la priorité en temps réel.
  * Les requêtes sont traitées selon un tourniquet pondéré basé sur la priorité.
  * Les requêtes Win32 sont traitées au niveau de priorité normale.

* **Capacity**
  * Le nombre maximal de requêtes en attente que la file d'attente peut contenir.
  * Tenter de mettre une requête en file d'attente lorsque la file d'attente est à pleine capacité bloque
    jusqu'à ce que des entrées soient terminées par le matériel.
  * La quantité de mémoire nécessaire pour une file d'attente correspond approximativement à la capacité de la file d'attente
    multipliée par la taille d'une `DSTORAGE_REQUEST`.

* **Name**
  * Sert uniquement à faciliter le débogage. Le nom n'est utilisé par aucune partie du
    code DirectStorage, mais il est visible dans les outils de développement, comme
    [PIX (rubrique sous NDA)](/fr-CA/tools/tools-console/pix/pix-directstorage).

Le matériel traite les requêtes de façon asynchrone pour obtenir le débit
le plus élevé. Toutefois, contrairement à Win32, le titre est notifié de la fin dans l'ordre
FIFO. À la notification de fin, il est garanti que toutes les requêtes précédentes
adressées à la même file d'attente sont également terminées.

### IDStorageQueueX1

L'interface `IDStorageQueueX1` étend l'interface `IDStorageQueueX` avec la
méthode [EnqueueSetEvent](/fr-CA/reference/system/dstorage/interfaces/IDStorageQueueX1/methods/idstoragequeuex_enqueuesetevent).

### IDStorageQueueX2

L'interface `IDStorageQueueX2` étend l'interface \`IDStorageQueueX1 avec la méthode [CreateQueue1](/fr-CA/reference/system/dstorage/interfaces/IDStorageFactoryX2/methods/idstoragefactoryx_createqueue1).

Et une propriété supplémentaire.

* [Options](/fr-CA/reference/system/dstorage/structs/dstorage_queue_options)
  * Indicateurs servant à contrôler le comportement de la file d'attente, y compris la désactivation de la soumission automatique.

### EnqueueRequest

Cette interface est fonctionnellement identique à l'interface Win32 `ReadFile`.
Des requêtes de lecture individuelles sont créées et soumises à la file d'attente. La principale
différence est que DirectStorage permet de mettre de nombreuses requêtes en file d'attente avant
la soumission, prend en charge la décompression matérielle et prend en charge l'annulation.

Les requêtes possèdent plusieurs propriétés principales.

**Source de la requête**
Selon la combinaison de `Options.SourceType` et de
`Options.SourceIsPhysicalPages`, DirectStorage utilise l'un des trois
groupes de propriétés suivants pour spécifier l'emplacement des données sources.

* **File** et **FileOffset**
  * Ce groupe est utilisé lorsque `Options.SourceType` est `DSTORAGE_REQUEST_SOURCE_FILE`
  * **File** est préalablement ouvert avec `IDStorageFactoryX::OpenFile`.
  * **FileOffset** doit être aligné sur 16 octets si la décompression est utilisée, ou
    n'a aucune exigence d'alignement si la décompression n'est pas utilisée.
    * Il s'agit d'un changement majeur par rapport à Win32, qui exigeait un alignement de 4 Kio dans
      le fichier pour les lectures asynchrones.

* **Source**
  * Ce groupe est utilisé lorsque `Options.SourceType` est `DSTORAGE_REQUEST_SOURCE_MEMORY`
    et que `Options.SourceIsPhysicalPages` est `FALSE`.
  * La mémoire tampon contenant les données à décompresser.

* **SourcePageArray** et **SourcePageOffset**
  * Ce groupe est utilisé lorsque `Options.SourceType` est `DSTORAGE_REQUEST_SOURCE_MEMORY`
    et que `Options.SourceIsPhysicalPages` est `TRUE`.
  * Semblable à `Source`, mais fournit la mémoire tampon source sous la forme d'un
    tableau de pages physiques de 64 Ko et du décalage en octets dans la première page.
  * Les pages physiques de 64 Ko peuvent être allouées par `XMemAllocatePhysicalPages`.

**SourceSize**

* Taille, en octets, des données sources à lire, à partir d'une mémoire tampon
  ou d'un fichier.

**IntermediateSize**

* Lorsque la décompression `zlib` et la décompression `BCPACK` sont toutes deux activées dans cette requête,
  `IntermediateSize` sert à spécifier la taille intermédiaire vers laquelle les données
  sources sont décompressées par zlib (et à partir de laquelle elles sont décompressées par BCPACK).
* Sinon, elle doit être définie à 0.

**Destination de la requête**
Selon `Options.DestinationIsPhysicalPages`, DirectStorage utilise l'un des
deux groupes de propriétés suivants pour spécifier l'emplacement de la destination.

* **Destination**
  * Ce groupe est utilisé lorsque `Options.DestinationIsPhysicalPages` est `FALSE`.
  * La mémoire tampon de destination pour les données finales chargées.
  * La décompression s'effectue au moyen de mémoires tampons internes partagées et peut être considérée
    comme une décompression sur place.

* **DestinationPageArray** et **DestinationPageOffset**
  * Ce groupe est utilisé lorsque `Options.DestinationIsPhysicalPages` est `TRUE`.
  * Semblable à `Destination`, mais fournit la mémoire tampon de destination sous la
    forme d'un tableau de pages physiques de 64 Ko et du décalage en octets dans la première
    page.
  * Les pages physiques de 64 Ko peuvent être allouées par `XMemAllocatePhysicalPages`.

**DestinationSize**

* Taille attendue, en octets, du contenu final chargé. La destination doit
  contenir suffisamment d'espace pour l'opération.
* La taille doit être égale à **SourceSize** lorsque la décompression n'est pas utilisée, ou
  supérieure à **SourceSize** lorsque la décompression est utilisée.

**CancellationTag**

* Une balise arbitraire de 64 bits définie par le titre.
* Cette balise sert de masque pour les requêtes d'annulation.

**Name**

* Chaîne facultative pour faciliter le débogage. Le nom peut apparaître dans les outils
  de développement, comme [PIX (rubrique sous NDA)](/fr-CA/tools/tools-console/pix/pix-directstorage), ou dans l'enregistrement d'erreur
  obtenu à partir de `IDStorageQueueX::RetrieveErrorRecord`. La chaîne `Name` doit
  être accessible pendant toute la durée de vie de la requête.

**Options**

* **ZlibDecompress**
  * Indique que les données doivent être décompressées au moyen de la norme de
    décompression RFC 1950.
* **BcpackMode**
  * Indique quel mode de `BCPACK` doit être utilisé pour décompresser les données.
  * None est une option valide et signifie que les données ne sont pas compressées avec `BCPACK`.
* **SwizzleMode**
  * Indique comment les données finales doivent être réorganisées (swizzle) en mémoire.
* **DestinationIsPhysicalPages**
  * Indique que la mémoire tampon de destination est spécifiée au moyen de
    **DestinationPageArray** et de **DestinationPageOffset** plutôt que de
    **Destination**.
* **SourceType**
  * Une requête peut avoir comme source la mémoire, et possède alors les propriétés `Source`/
    `SourcePageArray` et `SourcePageOffset`, ou avoir comme source un fichier, et possède alors
    les propriétés `File`/`FileOffset`.
* **SourceIsPhysicalPages**
  * Indique que la mémoire tampon source est spécifiée au moyen de **SourcePageArray**
    et de **SourcePageOffset** plutôt que de **Source**.

### EnqueueStatus/EnqueueSignal/EnqueueSetEvent

Les requêtes peuvent être mises en file d'attente et traitées comme une série de requêtes liées. Cela se
fait en mettant en file d'attente une notification lorsque le traitement atteint un certain point
dans la file d'attente. Les notifications ne sont traitées que lorsque toutes les requêtes de lecture précédentes
sont terminées. Cela garantit que les données de toutes les requêtes précédentes sont immédiatement
disponibles.

Le titre dispose de deux méthodes d'interrogation et d'une méthode d'attente pour la notification. Le
titre peut insérer un objet `ID3D12Fence`, un objet `IDStorageStatusArrayX` ou une
opération de définition d'événement. Le `ID3D12Fence` se comporte comme prévu pour un objet
`ID3D12Fence`. Un thread du titre peut attendre un `Event`, le processeur peut interroger la clôture, et le
GPU peut interroger la clôture. L'objet `IDStorageStatusArrayX` permet au processeur d'interroger
la fin et d'accéder aux éventuels échecs de lecture. La méthode `EnqueueSetEvent`
permet à un thread du titre d'attendre l'événement spécifié plutôt que d'effectuer une interrogation.
Cela diffère de `ID3D12Fence::SetEventOnCompletion`, car l'implémentation XBOX
de `ID3D12Fence::SetEventOnCompletion` tourne en boucle sur la clôture jusqu'à ce qu'elle soit signalée,
consommant ainsi le thread matériel du processeur jusqu'au signal, alors que `EnqueueSetEvent`
permet au thread du titre d'utiliser `WaitForSingleObject`/`WaitForMultipleObjects` pour
céder le processeur à d'autres threads jusqu'à ce que l'événement soit signalé.

Comme mentionné précédemment, toutes les requêtes se terminent dans l'ordre, même si le matériel
sous-jacent décide de les réorganiser pour des raisons de performances. Les notifications ne sont pas signalées
tant que toutes les requêtes mises en file d'attente précédemment dans la file d'attente ne sont pas terminées.

### Décompression

La décompression est gérée par du matériel dédié. Cela élimine la surcharge du processeur
liée aux algorithmes de décompression traditionnels. DirectStorage alloue un bloc fixe
de mémoire pendant l'initialisation pour l'utiliser comme mémoire tampon de travail pour la décompression.
Cela permet la décompression sur place et élimine le besoin de conserver à la fois les
données compressées et décompressées en mémoire en même temps.

Le matériel de décompression prend en charge trois modes de fonctionnement. Les modes ne sont pas
mutuellement exclusifs, de sorte que toute combinaison de modes peut être spécifiée. Les modes de
décompression sont appliqués dans l'ordre suivant : `DEFLATE`, `BCPACK` et `Swizzle`.

* `ZLibDecompress`
  * Il s'agit de la norme de compression [IETF RFC 1950](https://www.ietf.org/rfc/rfc1950.txt).

* `BCPack`
  * `BCPack` est un codeur entropique personnalisé conçu spécifiquement pour les données BCn.
    En général, cela signifie que les extrémités de couleur sont séparées des
    indices de palette (c'est-à-dire les poids) et compressées au moyen d'un algorithme rANS.

* `Swizzle`
  * Les modes `Swizzle` et de brassage (shuffle) peuvent fournir des optimisations supplémentaires dans les pipelines de contenu.

Lorsque des données à entropie élevée sont compressées, il est possible que la compression
augmente en fait la taille. À l'inverse, la décompression correspondante réduira
la taille. DirectStorage ne permet pas une décompression qui réduit la taille, et il revient
au titre de détecter les données à entropie élevée qui sont incompressibles et d'éviter
de compresser ces ressources. Pour plus de détails, consultez le guide [Optimiser
le contenu compressé avec DirectStorage et XBTC (rubrique sous NDA)](/fr-CA/build/console-features/storage/directstorage/directstorage-compression).

### Mémoire tampon intermédiaire

DirectStorage utilise en interne une mémoire tampon pour placer temporairement tout le contenu lu à partir du stockage
NVMe brut avant d'effectuer des opérations comme le déchiffrement et la
décompression. Cette mémoire tampon intermédiaire permet au lecteur NVMe et au circuit de déchiffrement/décompression de travailler en pipeline, en parallèle. Sa taille par défaut est de 32 Mio,
et elle est allouée lorsque le premier pointeur de fabrique DirectStorage est récupéré.

Si un titre utilise DirectStorage uniquement pour des opérations de décompression de mémoire à mémoire,
la mémoire tampon intermédiaire n'est pas nécessaire, et
[SetStagingBufferSize](/fr-CA/reference/system/dstorage/interfaces/IDStorageFactoryX/methods/idstoragefactoryx_setstagingbuffersize) peut être appelée
pour définir la taille de la mémoire tampon intermédiaire à 0.

La version actuelle de DirectStorage prend en charge des tailles de mémoire tampon intermédiaire de 0, 16, 20, 24, 28 et 32 Mio. Une taille inférieure à la valeur par défaut permettra au titre d'économiser de la mémoire, mais pourrait nuire aux performances de lecture globales.

**REMARQUE :** [SetStagingBufferSize](/fr-CA/reference/system/dstorage/interfaces/IDStorageFactoryX/methods/idstoragefactoryx_setstagingbuffersize)
ne peut être appelée que lorsqu'aucun objet `IDStorageQueueX` ni aucun objet `IDStorageFileX` n'existe; sinon, elle génère une erreur.

### CancelRequestsWithTag

DirectStorage prend en charge l'annulation des requêtes. Chaque requête est associée à une balise de 64 bits
définie par le titre. Son but est de servir de masque de bits pour déterminer
les requêtes à annuler. Le titre fournit un masque et une valeur pour
l'annulation. La file d'attente tente d'annuler toutes les requêtes qui correspondent au
critère : `tag & mask == value`.

L'annulation est une opération effectuée au mieux. Selon l'emplacement de la requête dans
le pipeline, il pourrait être impossible de l'annuler. Par exemple, la requête pourrait
être en cours de décompression par le matériel, ce qui ne peut pas être annulé. L'API
retourne immédiatement et ne bloque pas en attendant que toutes les requêtes annulées soient
traitées. Les titres doivent attendre qu'une notification ultérieure dans la file d'attente soit signalée
avant de libérer les ressources associées aux requêtes annulées.

Il faut prendre soin d'éviter d'ajouter des requêtes à une file d'attente au moment même où
[CancelRequestsWithTag](/fr-CA/reference/system/dstorage/interfaces/IDStorageQueueX/methods/idstoragequeuex_cancelrequestswithtag) est appelée.
Dans ce cas, le comportement n'est pas défini. Toutefois, les requêtes ajoutées à la file d'attente
après le retour de l'appel à [CancelRequestsWithTag](/fr-CA/reference/system/dstorage/interfaces/IDStorageQueueX/methods/idstoragequeuex_cancelrequestswithtag)
ne seront pas annulées, même si elles correspondent aux critères. Seules les requêtes mises en file d'attente
précédemment seront annulées.

### GetErrorEvent/RetrieveErrorRecord

Si une lecture cause une erreur, cette lecture est marquée comme terminée. Les notifications
ultérieures dans la file d'attente ne sont pas empêchées d'être signalées. La notification des erreurs
est gérée au moyen d'un objet `Event` associé à la file d'attente, qui peut être
récupéré avec [GetErrorEvent](/fr-CA/reference/system/dstorage/interfaces/IDStorageQueueX/methods/idstoragequeuex_geterrorevent). Le titre peut
utiliser **WaitForSingleObject** sur l'`Event` retourné par
[GetErrorEvent](/fr-CA/reference/system/dstorage/interfaces/IDStorageQueueX/methods/idstoragequeuex_geterrorevent). Si l'événement est signalé,
le titre peut obtenir la première erreur survenue depuis le dernier appel à
la fonction [RetrieveErrorRecord](/fr-CA/reference/system/dstorage/interfaces/IDStorageQueueX/methods/idstoragequeuex_retrieveerrorrecord)
en appelant la fonction [RetrieveErrorRecord](/fr-CA/reference/system/dstorage/interfaces/IDStorageQueueX/methods/idstoragequeuex_retrieveerrorrecord).

L'enregistrement d'erreur retourné par
[RetrieveErrorRecord](/fr-CA/reference/system/dstorage/interfaces/IDStorageQueueX/methods/idstoragequeuex_retrieveerrorrecord) ne contient que les données
de la première requête ayant échoué dans la file d'attente depuis le dernier appel à
[RetrieveErrorRecord](/fr-CA/reference/system/dstorage/interfaces/IDStorageQueueX/methods/idstoragequeuex_retrieveerrorrecord). Les données de
l'enregistrement d'erreur ne sont pas définies si l'`Event` d'erreur n'est pas signalé ou si les données ont
déjà été récupérées.

### Query

Obtient des renseignements sur la file d'attente. Cela comprend les structures [DSTORAGE\_QUEUE\_DESC](/fr-CA/reference/system/dstorage/structs/dstorage_queue_desc) ou [DSTORAGE\_QUEUE\_DESC1](/fr-CA/reference/system/dstorage/structs/dstorage_queue_desc1)
utilisées pour la création de la file d'attente, ainsi que le nombre d'emplacements vides
et le nombre d'entrées qui doivent être mises en file d'attente pour déclencher une soumission
automatique.

## Meilleures pratiques

Les mêmes conseils de meilleures pratiques donnés pour Win32 s'appliquent également à DirectStorage.
Les seuils de performance optimale ont changé radicalement.

### Tailles de lecture

Le conseil d'origine pour un disque rotatif était de lire par blocs d'au moins 128 Kio.
Les performances continuent d'augmenter avec des tailles de bloc plus grandes. Les blocs de 512
Kio offraient les meilleures performances.

L'absence de pièces mobiles dans le NVMe crée un seuil beaucoup plus bas. Les performances
de lecture font un grand bond à partir de lectures de 32 Kio et commencent à plafonner
à 64 Kio. Lire des blocs plus grands n'augmente pas les performances. Cela signifie
qu'il faut moins d'efforts pour fusionner les données en blocs plus grands dans le
package afin d'obtenir des performances optimales.

Au-delà de 512 Kio, si la décompression est utilisée, préférez des requêtes plus petites mais plus nombreuses en
parallèle plutôt qu'une seule requête énorme. Une seule requête énorme forcera la
sérialisation de la décompression, tandis que plusieurs requêtes simultanées permettent
à plusieurs unités matérielles de décompression de travailler en parallèle et d'atteindre le plein
débit.

Dans la version d'octobre 2022 du Microsoft Game Development Kit (GDK), la taille maximale d'une seule requête
est passée de 32 Mio comme destination à 1 Gio pour l'utilisation combinée de la mémoire (source plus
destination). Cette augmentation vise à faciliter le portage à partir d'autres API de stockage
qui permettent de grandes tailles de lecture. Mais la recommandation de taille précédente pour atteindre
le débit maximal demeure la même, car les grandes requêtes ne permettent pas à
plusieurs unités matérielles de décompression de travailler en parallèle.

### Ordre

Auparavant, avec les disques rotatifs, des efforts étaient consacrés à ordonner l'emplacement des
lectures sur le disque. La situation idéale était de lire à partir d'emplacements séquentiels sur
le disque. Cela réduisait au minimum le mouvement de la tête du disque, ce qui
éliminait le temps de recherche comme facteur. Cela pouvait augmenter les performances d'un ordre
de grandeur. Il y avait même un avantage à soumettre des lectures aléatoires triées par
emplacement, et dans certains cas, elles étaient 2 fois plus rapides.

Il est toujours utile d'ordonner les requêtes de lecture de façon aussi séquentielle que possible sur un
lecteur NVMe. Le lecteur NVMe lit par blocs alignés sur 64 Kio. Pour cette raison,
de la bande passante peut être gaspillée à lire des sections inutilisées d'un bloc de 64 Kio. Si une
requête de lecture ne porte que sur 4 Kio, 60 Kio de bande passante seront gaspillés. Le
NVMe réutilisera ces 60 Kio supplémentaires pour satisfaire d'autres requêtes en attente, si possible.
Par exemple, si vous avez deux lectures séquentielles, une de 32 Kio suivie d'une de 8 Kio,
il n'y a toujours qu'une seule lecture de 64 Kio à partir du lecteur.

### Gestion des files d'attente

La recommandation avec les disques rotatifs était d'avoir une taille de file d'attente entre 12 et
16\. Il n'y avait aucun avantage à une profondeur de file d'attente plus grande, et la baisse
de performances causée par l'utilisation de profondeurs de file d'attente plus petites était importante.

La spécification NVMe indique qu'un lecteur NVMe doit prendre en charge plusieurs files d'attente d'une
profondeur allant jusqu'à 65 536 entrées par file d'attente. DirectStorage prend en charge cette exigence,
permettant ainsi au titre de soumettre des milliers de requêtes à la fois.

Auparavant, avec les disques rotatifs, les titres mettaient en mémoire tampon les requêtes en attente pour maintenir une
profondeur de file d'attente dans la plage de 12 à 16. La recommandation pour DirectStorage est de
ne pas mettre les requêtes en mémoire tampon, mais de les mettre en file d'attente dès leur création. L'ensemble du
système est un pipeline, et la mise en mémoire tampon par le titre créera des bulles dans le pipeline,
ce qui peut nuire gravement aux performances.

Une autre recommandation consiste à créer une file d'attente dont la capacité est au moins quatre fois
supérieure au plus grand nombre de requêtes créées par image. Cela devrait offrir suffisamment de
capacité pour que de nouvelles requêtes puissent être ajoutées sans blocage, en attendant que les requêtes existantes
se terminent.

### Gestion des notifications

En général, moins il y a de requêtes de notification ajoutées à la file d'attente, mieux c'est. La
recommandation est de trouver un équilibre entre les besoins du titre et le maintien au minimum des requêtes
de notification mises en file d'attente. Mettre une notification en file d'attente après chaque requête
ne fera que nuire aux performances globales en raison de la surcharge accrue du traitement
de ces notifications.

Un exemple pourrait être le regroupement par contenu. Par exemple, les textures SFS, les besoins
du terrain (par exemple, maillage et texture) et les besoins des acteurs (par exemple, maillage,
texture et animation). Cela permet de lier une seule notification à la
disponibilité de toutes les ressources nécessaires pour créer un objet.

Le choix entre l'utilisation d'un `ID3D12Fence` ou d'un tableau d'état dépend
des besoins du titre. Les données doivent-elles être utilisées immédiatement par le GPU? Est-il
acceptable que le thread de vérification soit suspendu jusqu'à ce que les lectures soient terminées? Une interrogation
périodique est-elle suffisante parce que les données ne peuvent être traitées qu'à certains moments de
l'image?

### Considérations

Avec la possibilité d'un nombre beaucoup plus élevé de requêtes en cours, il faut
prendre soin d'éviter de créer des goulots d'étranglement dans d'autres parties du titre. Les coûts
de gestion des requêtes par le titre pourraient rapidement dépasser les économies
réalisées par DirectStorage. La recommandation est d'examiner tout le code de soutien
par requête et de déterminer ce qui peut être réduit.

Chaque requête exige-t-elle l'allocation d'un nouveau bloc de mémoire?

* Le système de mémoire a une surcharge pour trouver un nouveau bloc et mettre à jour les listes internes.
* Envisagez de réutiliser les blocs de mémoire autant que possible.

Un verrou est-il nécessaire pour mettre à jour les gestionnaires?

* Cela crée plus de contention à mesure que plus de mises à jour sont effectuées.
* Envisagez de vous passer de verrous autant que possible.

Le chargement spéculatif est-il utilisé?

* L'annulation est prise en charge, ce qui pourrait entraîner la création de plus de requêtes.
* Toutefois, de la mémoire doit être disponible pour la spéculation.
* Envisagez des limites strictes pour les seuils de spéculation.

## Voir aussi

[DirectStorage](/fr-CA/build/console-features/storage/directstorage-toc)
[Utilisation et détails internes de DirectStorage (rubrique sous NDA)](/fr-CA/build/console-features/storage/directstorage/directstorage-white-paper)
[Optimiser le contenu compressé avec DirectStorage et XBTC (rubrique sous NDA)](/fr-CA/build/console-features/storage/directstorage/directstorage-compression)
[Analyser les performances de DirectStorage (rubrique sous NDA)](/fr-CA/tools/tools-console/pix/pix-directstorage)


## Related topics

- [Vue d'ensemble de XBOX Series X|S](/fr/paths/series-xs/overview.md)
- [Vue d'ensemble de Play Anywhere (console + PC)](/fr/paths/play-anywhere/overview.md)
- [Vue d'ensemble de l'accessibilité GDK](/fr/build/game-principles/accessibility/accessibility-overview.md)
- [Vue d'ensemble de Windows & ROG XBOX Ally](/fr/paths/windows/overview.md)
- [Vue d'ensemble de Godot et des moteurs communautaires](/fr/paths/community-engines/overview.md)
