Compression de blocs
La compression de bloc est une technique de compression de texture à perte pour réduire la taille de texture et l’empreinte mémoire, ce qui augmente les performances. Une texture compressée par bloc peut être inférieure à une texture avec 32 bits par couleur.
La compression de bloc est une technique de compression de texture pour réduire la taille de texture. Par rapport à une texture de 32 bits par couleur, une texture compressée par bloc peut être jusqu’à 75 pour cent plus petite. Les applications voient généralement une augmentation des performances lors de l’utilisation de la compression de bloc en raison de l’encombrement mémoire plus faible.
Bien que la perte, la compression de bloc fonctionne bien et est recommandée pour toutes les textures qui sont transformées et filtrées par le pipeline. Les textures qui sont directement mappées à l’écran (éléments d’interface utilisateur tels que les icônes et le texte) ne sont pas des choix appropriés pour la compression, car les artefacts sont plus visibles.
Une texture compressée en bloc doit être créée sous la forme d’un multiple de taille 4 dans toutes les dimensions et ne peut pas être utilisée comme sortie du pipeline.
Fonctionnement de la compression de bloc
La compression de bloc est une technique permettant de réduire la quantité de mémoire requise pour stocker les données de couleur. En stockant certaines couleurs dans leur taille d’origine et d’autres couleurs à l’aide d’un schéma d’encodage, vous pouvez réduire considérablement la quantité de mémoire nécessaire pour stocker l’image. Étant donné que le matériel décode automatiquement les données compressées, il n’existe aucune pénalité de performances pour l’utilisation de textures compressées.
Pour voir comment la compression fonctionne, examinez les deux exemples suivants. Le premier exemple décrit la quantité de mémoire utilisée lors du stockage de données non compressées ; le deuxième exemple décrit la quantité de mémoire utilisée lors du stockage de données compressées.
Stockage de données non compressées
L’illustration suivante représente une texture non compressée 4×4. Supposons que chaque couleur contient un composant de couleur unique (rouge par exemple) et qu’elle est stockée dans un octet de mémoire.
Les données non compressées sont disposées en mémoire de manière séquentielle et nécessitent 16 octets, comme illustré dans l’illustration suivante.
Stockage de données compressées
Maintenant que vous avez vu la quantité de mémoire utilisée par une image non compressée, examinez la quantité de mémoire enregistrée par une image compressée. Le format de compression BC4 stocke 2 couleurs (1 octet chacun) et des index 16 3 bits (48 bits ou 6 octets) utilisés pour interpoler les couleurs d’origine dans la texture, comme illustré dans l’illustration suivante.
L’espace total nécessaire pour stocker les données compressées est de 8 octets, ce qui représente une économie de mémoire de 50 pour cent sur l’exemple non compressé. Les économies sont encore plus importantes lorsque plusieurs composants de couleur sont utilisés.
Les économies substantielles de mémoire fournies par la compression de bloc peuvent entraîner une augmentation des performances. Ces performances s’accompagnent du coût de la qualité de l’image (en raison de l’interpolation de couleur) ; cependant, la qualité inférieure n’est souvent pas visible.
La section suivante montre comment Direct3D permet d’utiliser la compression de bloc dans une application.
Utilisation de la compression de bloc
Créez une texture compressée en bloc comme une texture non compressée, sauf que vous spécifiez un format compressé par bloc.
Ensuite, créez une vue pour lier la texture au pipeline, car une texture compressée par bloc ne peut être utilisée qu’en tant qu’entrée à une étape de nuanceur, vous souhaitez créer une vue nuanceur-ressource.
Utilisez une texture compressée de bloc de la même façon que vous utiliseriez une texture non compressée. Si votre application obtient un pointeur de mémoire pour bloquer les données compressées, vous devez tenir compte du remplissage de la mémoire dans un mipmap qui entraîne la différence entre la taille déclarée et la taille réelle.
Taille virtuelle par rapport à la taille physique
Si vous avez du code d’application qui utilise un pointeur de mémoire pour parcourir la mémoire d’une texture compressée de bloc, il existe une considération importante qui peut nécessiter une modification dans votre code d’application. Une texture compressée par bloc doit être un multiple de 4 dans toutes les dimensions, car les algorithmes de compression de bloc fonctionnent sur des blocs texels 4x4. Il s’agit d’un problème pour un mipmap dont les dimensions initiales sont divisibles par 4, mais les niveaux subdivisé ne sont pas. Le diagramme suivant montre la différence entre la taille virtuelle (déclarée) et la taille physique (réelle) de chaque niveau mipmap.
Le côté gauche du diagramme montre les tailles de niveau mipmap générées pour une texture non compressée 60×40. La taille de niveau supérieur est extraite de l’appel d’API qui génère la texture ; chaque niveau suivant correspond à la moitié de la taille du niveau précédent. Pour une texture non compressée, il n’existe aucune différence entre la taille virtuelle (déclarée) et la taille physique (réelle).
Le côté droit du diagramme montre les tailles de niveau mipmap générées pour la même texture 60×40 avec compression. Notez que le deuxième et le troisième niveau ont un remplissage de mémoire pour rendre les facteurs de taille de 4 sur chaque niveau. Cela est nécessaire pour que les algorithmes puissent fonctionner sur 4×4 blocs texels. Cela est particulièrement évident si vous envisagez des niveaux mipmap inférieurs à 4×4 ; la taille de ces niveaux de mipmap très petits est arrondie au facteur le plus proche de 4 lorsque la mémoire de texture est allouée.
Le matériel d’échantillonnage utilise la taille virtuelle ; lorsque la texture est échantillonné, le remplissage de la mémoire est ignoré. Pour les niveaux mipmap inférieurs à 4×4, seuls les quatre premiers texels seront utilisés pour une carte de 2×2, et seuls les premiers texels seront utilisés par un bloc 1×1. Toutefois, il n’existe aucune structure d’API qui expose la taille physique (y compris le remplissage de la mémoire).
En résumé, veillez à utiliser des blocs de mémoire alignés lors de la copie de régions qui contiennent des données compressées par bloc. Pour ce faire dans une application qui obtient un pointeur de mémoire, assurez-vous que le pointeur utilise l’emplacement de surface pour tenir compte de la taille de mémoire physique.
Algorithmes de compression
Les techniques de compression de bloc dans Direct3D décomposent les données de texture non compressées en blocs 4×4, compressent chaque bloc, puis stockent les données. Pour cette raison, les textures sont censées être compressées doivent avoir des dimensions de texture qui sont des multiples de 4.
Le diagramme précédent montre une texture partitionnée en blocs texels. Le premier bloc affiche la disposition des 16 texels étiquetés a-p, mais chaque bloc a la même organisation de données.
Direct3D implémente plusieurs schémas de compression, chacun implémente un compromis différent entre le nombre de composants stockés, le nombre de bits par composant et la quantité de mémoire consommée. Utilisez ce tableau pour vous aider à choisir le format qui fonctionne le mieux avec le type de données et la résolution de données qui convient le mieux à votre application.
Données sources | Résolution de compression des données (en bits) | Choisir ce format de compression |
---|---|---|
Couleur à trois composants et alpha | Couleur (5:6:5), Alpha (1) ou aucun alpha | BC1 |
Couleur à trois composants et alpha | Couleur (5:6:5), Alpha (4) | BC2 |
Couleur à trois composants et alpha | Couleur (5:6:5), Alpha (8) | BC3 |
Couleur d’un composant | Un composant (8) | BC4 |
Couleur à deux composants | Deux composants (8:8) | BC5 |
BC1
Utilisez le premier format de compression de bloc (BC1) (DXGI_FORMAT_BC1_TYPELESS, DXGI_FORMAT_BC1_UNORM ou DXGI_BC1_UNORM_SRGB) pour stocker des données de couleur à trois composants à l’aide d’une couleur 5:6:5 (5 bits rouge, 6 bits vert, 5 bits bleu). Cela est vrai même si les données contiennent également des valeurs alpha 1 bits. En supposant une texture 4×4 à l’aide du format de données le plus grand possible, le format BC1 réduit la mémoire requise de 48 octets (16 couleurs × 3 composants/couleurs × 1 octet/composant) à 8 octets de mémoire.
L’algorithme fonctionne sur 4×4 blocs de texels. Au lieu de stocker 16 couleurs, l’algorithme enregistre 2 couleurs de référence (color_0 et color_1) et des index de couleur 16 2 bits (blocs a-p), comme illustré dans le diagramme suivant.
Les index de couleur (a–p) sont utilisés pour rechercher les couleurs d’origine d’une table de couleurs. Le tableau de couleurs contient 4 couleurs. Les deux premières couleurs (color_0 et color_1) sont les couleurs minimales et maximales. Les deux autres couleurs, color_2 et color_3, sont des couleurs intermédiaires calculées avec une interpolation linéaire.
color_2 = 2/3*color_0 + 1/3*color_1
color_3 = 1/3*color_0 + 2/3*color_1
Les quatre couleurs sont attribuées à des valeurs d’index 2 bits qui seront enregistrées dans des blocs a-p.
color_0 = 00
color_1 = 01
color_2 = 10
color_3 = 11
Enfin, chacune des couleurs des blocs a-p est comparée aux quatre couleurs de la table de couleurs, et l’index de la couleur la plus proche est stocké dans les blocs 2 bits.
Cet algorithme se prête également aux données qui contiennent également des données alpha 1 bits. La seule différence est que color_3 est définie sur 0 (qui représente une couleur transparente) et color_2 est un mélange linéaire de color_0 et de color_1.
color_2 = 1/2*color_0 + 1/2*color_1;
color_3 = 0;
BC2
Utilisez le format BC2 (DXGI_FORMAT_BC2_TYPELESS, DXGI_FORMAT_BC2_UNORM ou DXGI_BC2_UNORM_SRGB) pour stocker des données qui contiennent des données de couleur et alpha avec une faible cohérence (utilisez BC3 pour des données alpha hautement cohérentes). Le format BC2 stocke les données RVB sous forme de couleur 5:6:5 (5 bits rouges, 6 bits vert, 5 bits bleu) et alpha comme valeur 4 bits distincte. En supposant une texture de 4×4 à l’aide du format de données le plus grand possible, cette technique de compression réduit la mémoire requise de 64 octets (16 couleurs × 4 composants/couleurs × 1 octet/composant) à 16 octets de mémoire.
Le format BC2 stocke les couleurs avec le même nombre de bits et de disposition de données que le format BC1 . Toutefois, BC2 nécessite un nombre supplémentaire de 64 bits de mémoire pour stocker les données alpha, comme illustré dans le diagramme suivant.
BC3
Utilisez le format BC3 (DXGI_FORMAT_BC3_TYPELESS, DXGI_FORMAT_BC3_UNORM ou DXGI_BC3_UNORM_SRGB) pour stocker des données de couleur hautement cohérentes (utilisez BC2 avec des données alpha moins cohérentes). Le format BC3 stocke les données de couleur à l’aide de la couleur 5:6:5 (5 bits rouge, 6 bits vert, 5 bits bleu) et des données alpha à l’aide d’un octet. En supposant une texture de 4×4 à l’aide du format de données le plus grand possible, cette technique de compression réduit la mémoire requise de 64 octets (16 couleurs × 4 composants/couleurs × 1 octet/composant) à 16 octets de mémoire.
Le format BC3 stocke les couleurs avec le même nombre de bits et de disposition de données que le format BC1 . Toutefois, BC3 nécessite un nombre supplémentaire de 64 bits de mémoire pour stocker les données alpha. Le format BC3 gère l’alpha en stockant deux valeurs de référence et en interpolant entre elles (de la même façon que BC1 stocke la couleur RVB).
L’algorithme fonctionne sur 4×4 blocs de texels. Au lieu de stocker 16 valeurs alpha, l’algorithme stocke 2 alphas de référence (alpha_0 et alpha_1) et des index de couleur 16 3 bits (alpha à p), comme illustré dans le diagramme suivant.
Le format BC3 utilise les index alpha (a–p) pour rechercher les couleurs d’origine d’une table de recherche qui contient 8 valeurs. Les deux premières valeurs ( alpha_0 et alpha_1) sont les valeurs minimales et maximales ; les six autres valeurs intermédiaires sont calculées à l’aide d’une interpolation linéaire.
L’algorithme détermine le nombre de valeurs alpha interpolées en examinant les deux valeurs alpha de référence. Si alpha_0 est supérieur à alpha_1, BC3 interpole 6 valeurs alpha ; sinon, il interpole 4. Lorsque BC3 interpole uniquement 4 valeurs alpha, il définit deux valeurs alpha supplémentaires (0 pour une transparence totale et 255 pour une opacité totale). BC3 compresse les valeurs alpha dans la zone texel 4×4 en stockant le code binaire correspondant aux valeurs alpha interpolées qui correspondent le plus étroitement à l’alpha d’origine pour un texel donné.
if( alpha_0 > alpha_1 )
{
// 6 interpolated alpha values.
alpha_2 = 6/7*alpha_0 + 1/7*alpha_1; // bit code 010
alpha_3 = 5/7*alpha_0 + 2/7*alpha_1; // bit code 011
alpha_4 = 4/7*alpha_0 + 3/7*alpha_1; // bit code 100
alpha_5 = 3/7*alpha_0 + 4/7*alpha_1; // bit code 101
alpha_6 = 2/7*alpha_0 + 5/7*alpha_1; // bit code 110
alpha_7 = 1/7*alpha_0 + 6/7*alpha_1; // bit code 111
}
else
{
// 4 interpolated alpha values.
alpha_2 = 4/5*alpha_0 + 1/5*alpha_1; // bit code 010
alpha_3 = 3/5*alpha_0 + 2/5*alpha_1; // bit code 011
alpha_4 = 2/5*alpha_0 + 3/5*alpha_1; // bit code 100
alpha_5 = 1/5*alpha_0 + 4/5*alpha_1; // bit code 101
alpha_6 = 0; // bit code 110
alpha_7 = 255; // bit code 111
}
BC4
Utilisez le format BC4 pour stocker des données de couleur à composant unique à l’aide de 8 bits pour chaque couleur. En raison de l’augmentation de la précision (par rapport à BC1), BC4 est idéal pour stocker des données à virgule flottante dans la plage de [0 à 1] à l’aide du format DXGI_FORMAT_BC4_UNORM et [-1 à +1] à l’aide du format DXGI_FORMAT_BC4_SNORM. En supposant une texture de 4×4 à l’aide du format de données le plus grand possible, cette technique de compression réduit la mémoire requise de 16 octets (16 couleurs × 1 composants/couleurs × 1 octet/composant) à 8 octets.
L’algorithme fonctionne sur 4×4 blocs de texels. Au lieu de stocker 16 couleurs, l’algorithme stocke 2 couleurs de référence (red_0 et red_1) et des index de couleur 16 3 bits (rouge à p rouge), comme illustré dans le diagramme suivant.
L’algorithme utilise les index 3 bits pour rechercher des couleurs à partir d’une table de couleurs qui contient 8 couleurs. Les deux premières couleurs ( red_0 et red_1) sont les couleurs minimales et maximales. L’algorithme calcule les couleurs restantes à l’aide de l’interpolation linéaire.
L’algorithme détermine le nombre de valeurs de couleur interpolées en examinant les deux valeurs de référence. Si red_0 est supérieur à red_1, BC4 interpole 6 valeurs de couleur ; sinon, il interpole 4. Lorsque BC4 interpole uniquement 4 valeurs de couleur, il définit deux valeurs de couleur supplémentaires (0,0f pour une couleur entièrement transparente et 1,0f pour une couleur entièrement opaque). BC4 compresse les valeurs alpha dans la zone texel 4×4 en stockant le code binaire correspondant aux valeurs alpha interpolées qui correspondent le plus étroitement à l’alpha d’origine pour un texel donné.
BC4_UNORM
L’interpolation des données à composant unique est effectuée comme dans l’exemple de code suivant.
unsigned word red_0, red_1;
if( red_0 > red_1 )
{
// 6 interpolated color values
red_2 = (6*red_0 + 1*red_1)/7.0f; // bit code 010
red_3 = (5*red_0 + 2*red_1)/7.0f; // bit code 011
red_4 = (4*red_0 + 3*red_1)/7.0f; // bit code 100
red_5 = (3*red_0 + 4*red_1)/7.0f; // bit code 101
red_6 = (2*red_0 + 5*red_1)/7.0f; // bit code 110
red_7 = (1*red_0 + 6*red_1)/7.0f; // bit code 111
}
else
{
// 4 interpolated color values
red_2 = (4*red_0 + 1*red_1)/5.0f; // bit code 010
red_3 = (3*red_0 + 2*red_1)/5.0f; // bit code 011
red_4 = (2*red_0 + 3*red_1)/5.0f; // bit code 100
red_5 = (1*red_0 + 4*red_1)/5.0f; // bit code 101
red_6 = 0.0f; // bit code 110
red_7 = 1.0f; // bit code 111
}
Les couleurs de référence sont affectées à des index 3 bits (000 à 111, car il y a 8 valeurs), qui seront enregistrées en blocs rouge par p rouge pendant la compression.
BC4_SNORM
La DXGI_FORMAT_BC4_SNORM est exactement la même, sauf que les données sont encodées dans la plage SNORM et lorsque 4 valeurs de couleur sont interpolées. L’interpolation des données à composant unique est effectuée comme dans l’exemple de code suivant.
signed word red_0, red_1;
if( red_0 > red_1 )
{
// 6 interpolated color values
red_2 = (6*red_0 + 1*red_1)/7.0f; // bit code 010
red_3 = (5*red_0 + 2*red_1)/7.0f; // bit code 011
red_4 = (4*red_0 + 3*red_1)/7.0f; // bit code 100
red_5 = (3*red_0 + 4*red_1)/7.0f; // bit code 101
red_6 = (2*red_0 + 5*red_1)/7.0f; // bit code 110
red_7 = (1*red_0 + 6*red_1)/7.0f; // bit code 111
}
else
{
// 4 interpolated color values
red_2 = (4*red_0 + 1*red_1)/5.0f; // bit code 010
red_3 = (3*red_0 + 2*red_1)/5.0f; // bit code 011
red_4 = (2*red_0 + 3*red_1)/5.0f; // bit code 100
red_5 = (1*red_0 + 4*red_1)/5.0f; // bit code 101
red_6 = -1.0f; // bit code 110
red_7 = 1.0f; // bit code 111
}
Les couleurs de référence sont affectées à des index 3 bits (000 à 111, car il y a 8 valeurs), qui seront enregistrées en blocs rouge par p rouge pendant la compression.
BC5
Utilisez le format BC5 pour stocker des données de couleur à deux composants à l’aide de 8 bits pour chaque couleur. En raison de l’augmentation de la précision (par rapport à BC1), BC5 est idéal pour stocker des données à virgule flottante dans la plage de [0 à 1] à l’aide du format DXGI_FORMAT_BC5_UNORM et [-1 à +1] à l’aide du format DXGI_FORMAT_BC5_SNORM. En supposant une texture de 4×4 à l’aide du format de données le plus grand possible, cette technique de compression réduit la mémoire requise de 32 octets (16 couleurs × 2 composants/couleurs × 1 octet/composant) à 16 octets.
L’algorithme fonctionne sur 4×4 blocs de texels. Au lieu de stocker 16 couleurs pour les deux composants, l’algorithme stocke 2 couleurs de référence pour chaque composant (red_0, red_1, green_0 et green_1) et 16 indices de couleurs 3 bits pour chaque composant (rouge à travers p rouge et vert, p vert et p vert), comme illustré dans le diagramme suivant.
L’algorithme utilise les index 3 bits pour rechercher des couleurs à partir d’une table de couleurs qui contient 8 couleurs. Les deux premières couleurs (red_0 et red_1 (ou green_0 et green_1) sont les couleurs minimales et maximales. L’algorithme calcule les couleurs restantes à l’aide de l’interpolation linéaire.
L’algorithme détermine le nombre de valeurs de couleur interpolées en examinant les deux valeurs de référence. Si red_0 est supérieur à red_1, BC5 interpole 6 valeurs de couleur ; sinon, il interpole 4. Lorsque BC5 interpole uniquement 4 valeurs de couleur, elle définit les deux autres valeurs de couleur à 0,0f et 1.0f.
BC5_UNORM
L’interpolation des données à composant unique est effectuée comme dans l’exemple de code suivant. Les calculs des composants verts sont similaires.
unsigned word red_0, red_1;
if( red_0 > red_1 )
{
// 6 interpolated color values
red_2 = (6*red_0 + 1*red_1)/7.0f; // bit code 010
red_3 = (5*red_0 + 2*red_1)/7.0f; // bit code 011
red_4 = (4*red_0 + 3*red_1)/7.0f; // bit code 100
red_5 = (3*red_0 + 4*red_1)/7.0f; // bit code 101
red_6 = (2*red_0 + 5*red_1)/7.0f; // bit code 110
red_7 = (1*red_0 + 6*red_1)/7.0f; // bit code 111
}
else
{
// 4 interpolated color values
red_2 = (4*red_0 + 1*red_1)/5.0f; // bit code 010
red_3 = (3*red_0 + 2*red_1)/5.0f; // bit code 011
red_4 = (2*red_0 + 3*red_1)/5.0f; // bit code 100
red_5 = (1*red_0 + 4*red_1)/5.0f; // bit code 101
red_6 = 0.0f; // bit code 110
red_7 = 1.0f; // bit code 111
}
Les couleurs de référence sont affectées à des index 3 bits (000 à 111, car il y a 8 valeurs), qui seront enregistrées en blocs rouge par p rouge pendant la compression.
BC5_SNORM
Le DXGI_FORMAT_BC5_SNORM est exactement le même, sauf que les données sont encodées dans la plage SNORM et lorsque 4 valeurs de données sont interpolées, les deux valeurs supplémentaires sont -1.0f et 1.0f. L’interpolation des données à composant unique est effectuée comme dans l’exemple de code suivant. Les calculs des composants verts sont similaires.
signed word red_0, red_1;
if( red_0 > red_1 )
{
// 6 interpolated color values
red_2 = (6*red_0 + 1*red_1)/7.0f; // bit code 010
red_3 = (5*red_0 + 2*red_1)/7.0f; // bit code 011
red_4 = (4*red_0 + 3*red_1)/7.0f; // bit code 100
red_5 = (3*red_0 + 4*red_1)/7.0f; // bit code 101
red_6 = (2*red_0 + 5*red_1)/7.0f; // bit code 110
red_7 = (1*red_0 + 6*red_1)/7.0f; // bit code 111
}
else
{
// 4 interpolated color values
red_2 = (4*red_0 + 1*red_1)/5.0f; // bit code 010
red_3 = (3*red_0 + 2*red_1)/5.0f; // bit code 011
red_4 = (2*red_0 + 3*red_1)/5.0f; // bit code 100
red_5 = (1*red_0 + 4*red_1)/5.0f; // bit code 101
red_6 = -1.0f; // bit code 110
red_7 = 1.0f; // bit code 111
}
Les couleurs de référence sont affectées à des index 3 bits (000 à 111, car il y a 8 valeurs), qui seront enregistrées en blocs rouge par p rouge pendant la compression.
Conversion de format
Direct3D permet des copies entre les textures préstructurées typées et les textures compressées en bloc des mêmes largeurs de bits.
Vous pouvez copier des ressources entre quelques types de format. Ce type d’opération de copie effectue un type de conversion de format qui réinterprète les données de ressource en tant que type de format différent. Prenons cet exemple qui montre la différence entre la réinterprétation des données avec la façon dont un type de conversion plus classique se comporte :
FLOAT32 f = 1.0f;
UINT32 u;
Pour réinterpréter 'f' comme le type de 'u', utilisez memcpy :
memcpy( &u, &f, sizeof( f ) ); // 'u' becomes equal to 0x3F800000.
Dans la réinterprétation précédente, la valeur sous-jacente des données ne change pas ; memcpy réinterpret le float en tant qu’entier non signé.
Pour effectuer le type de conversion plus classique, utilisez l’affectation :
u = f; // 'u' becomes 1.
Dans la conversion précédente, la valeur sous-jacente des données change.
Le tableau suivant répertorie les formats de source et de destination autorisés que vous pouvez utiliser dans ce type d’interprétation de conversion de format. Vous devez encoder correctement les valeurs pour que la réinterpretation fonctionne comme prévu.
Largeur du bit | Ressource non compressée | Ressource compressée en bloc |
---|---|---|
32 | DXGI_FORMAT_R32_UINT DXGI_FORMAT_R32_SINT |
DXGI_FORMAT_R9G9B9E5_SHAREDEXP |
64 | DXGI_FORMAT_R16G16B16A16_UINT DXGI_FORMAT_R16G16B16A16_SINT DXGI_FORMAT_R32G32_UINT DXGI_FORMAT_R32G32_SINT |
DXGI_FORMAT_BC1_UNORM[_SRGB] DXGI_FORMAT_BC4_UNORM DXGI_FORMAT_BC4_SNORM |
128 | DXGI_FORMAT_R32G32B32A32_UINT DXGI_FORMAT_R32G32B32A32_SINT |
DXGI_FORMAT_BC2_UNORM[_SRGB] DXGI_FORMAT_BC3_UNORM[_SRGB] DXGI_FORMAT_BC5_UNORM DXGI_FORMAT_BC5_SNORM |