Partager via


Graphiques (C++ AMP)

C++ AMP contient plusieurs API dans l’espace Concurrency::graphics de noms que vous pouvez utiliser pour accéder à la prise en charge de texture sur les GPU. Voici quelques scénarios courants :

  • Vous pouvez utiliser la texture classe comme conteneur de données pour le calcul et exploiter la localité spatiale du cache de texture et des dispositions du matériel GPU. La localité spatiale est la propriété des éléments de données physiquement proches les uns des autres.

  • Le runtime fournit une interopérabilité efficace avec des nuanceurs non calculés. Les pixels, les vertex, les pavages et les nuanceurs de coque consomment ou produisent fréquemment des textures utilisables dans les calculs C++ AMP.

  • Les API graphiques de C++ AMP fournissent d'autres moyens pour accéder aux mémoires tampons contenant des sous-mots. Les textures qui ont des formats qui représentent des texels (éléments de texture) composés de scalaires 8 bits ou 16 bits permettent d’accéder à ce stockage de données packé.

Remarque

Les en-têtes AMP C++ sont déconseillés à partir de Visual Studio 2022 version 17.0. L’inclusion d’en-têtes AMP génère des erreurs de génération. Définissez _SILENCE_AMP_DEPRECATION_WARNINGS avant d’inclure tous les en-têtes AMP pour silence les avertissements.

Les types norm et unorm

Les norm types et unorm les types sont des types scalaires qui limitent la plage de float valeurs ; il s’agit de la limitation. Ces types peuvent être explicitement construits à partir d'autres types scalaires. Dans le cast, la valeur est d’abord castée float et ensuite limitée à la région respective autorisée par norm [-1.0, 1.0] ou unorm [0.0, 1.0]. Le cast de +/- infini retourne +/-1. Le cast depuis NaN n'est pas défini. Un norm peut être implicitement construit à partir d’un unorm et il n’y a aucune perte de données. L’opérateur de conversion implicite vers lequel est float défini sur ces types. Les opérateurs binaires sont définis entre ces types et d’autres types scalaires intégrés tels que float : int, , *-, , /, , ==, , >!=, <>=<=. + Les opérateurs d’affectation composée sont également pris en charge : +=, , -=*=, /=. L’opérateur de négation unaire (-) est défini pour norm les types.

Bibliothèque de vecteurs courts

La bibliothèque de vecteurs courts fournit certaines fonctionnalités du type de vecteur défini dans HLSL et est généralement utilisée pour définir des texels. Un vecteur court est une structure de données contenant une à quatre valeurs du même type. Les types pris en charge sont double, , floatint, norm, uint, et unorm. Les noms des types sont affichés dans le tableau suivant. Pour chaque type, il existe également un correspondant typedef qui n’a pas de trait de soulignement dans le nom. Les types qui ont les traits de soulignement se trouvent dans l’espace de noms Concurrency ::graphics. Les types qui n’ont pas les traits de soulignement se trouvent dans l’espace de noms Concurrency ::graphics ::d irect3d afin qu’ils soient clairement séparés des types fondamentaux nommés de la même façon, tels que __int8 et __int16.

Type Length 2 Longueur 3 Longueur 4
double double_2

double2
double_3

double3
double_4

double4
virgule flottante float_2

float2
float_3

float3
float_4

float4
int int_2

int2
int_3

int3
int_4

int4
norm norm_2

norm2
norm_3

norm3
norm_4

norm4
uint uint_2

uint2
uint_3

uint3
uint_4

uint4
unorm unorm_2

unorm2
unorm_3

unorm3
unorm_4

unorm4

Opérateurs

Si un opérateur est défini entre deux vecteurs courts, alors il est également défini entre un vecteur court et un scalaire. De plus, l'une d'elles doit avoir la valeur True :

  • Le type scalaire doit être identique au type d’élément du vecteur court.

  • Le type scalaire peut être implicitement converti en type d’élément du vecteur à l’aide d’une seule conversion définie par l’utilisateur.

L'opération est portée entre chaque composant du vecteur court et la variable scalaire. Voici les opérateurs valides :

Type d’opérateur Types valides
Opérateurs binaires Valide sur tous les types : +, , -*, /

Valide sur les types entiers : %, , &^|, , <<>>

Les deux vecteurs doivent avoir la même taille et le résultat doit être un vecteur de la même taille.
Opérateurs relationnels Valide sur tous les types : == et !=
Opérateur d'assignation composée Valide sur tous les types : +=, -=, *=, /=

Valide sur les types entiers : %=, , &=^=|=, , <<=>>=
Opérateurs d'incrémentation et de décrémentation Valide sur tous les types : ++, --

Le préfixe et le suffixe sont valides.
Opérateur NOT au niveau du bit (~) Valide sur les types d'entiers.
Opérateur unaire - Valide sur tous les types hormis unorm et uint.

Expressions de swizzling

La bibliothèque de vecteurs courts prend en charge la construction de l'accesseur vector_type.identifier pour accéder aux composants d'un vecteur court. Le identifier, appelé expression swizzling, spécifie les composants du vecteur. L'expression peut être une l-value ou une r-value. Les caractères individuels de l’identificateur peuvent être : x, y, z et w ; ou r, g, b, et a. « x » et « r » signifient le zéro-ième composant, « y » et « g » signifient le premier composant, et ainsi de suite. (Notez que « x » et « r » ne peuvent pas être utilisés dans le même identificateur.) Par conséquent, « rgba » et « xyzw » retournent le même résultat. Les accesseurs à un composant tels que « x » et « y » sont des types de valeur scalaire. Les accesseurs à plusieurs composants sont des types de vecteurs courts. Par exemple, si vous construisez un vecteur int_4 nommé fourInts et ayant les valeurs 2, 4, 6 et 8, alors fourInts.y retourne l'entier 4 et fourInts.rg retourne un objet int_2 ayant les valeurs 2 et 4.

Classes de texture

De nombreux GPU ont un matériel et des caches optimisées pour récupérer des pixels et des texels afin d'afficher des images et des textures. La texture<T,N> classe, qui est une classe de conteneur pour les objets texels, expose les fonctionnalités de texture de ces GPU. Un texel peut être :

  • Un int, , floatuintdouble, , normou unorm scalaire.

  • Un vecteur court ayant deux ou quatre composants. La seule exception est double_4, qui n'est pas autorisée.

L'objet texture peut avoir un rang de 1, 2 ou 3. L'objet texture peut être capturé uniquement par référence dans le lambda d'un appel à parallel_for_each. La texture est stockée sur le GPU en tant qu'objet de texture Direct3D. Pour plus d’informations sur les textures et les texels dans Direct3D, consultez Présentation des textures dans Direct3D 11.

Le type de texel que vous utilisez peut être l'un des nombreux formats de texture utilisés dans la programmation graphique. Par exemple, un format RVBA peut utiliser 32 bits, avec 8 bits pour chacun des éléments scalaires R, G, B et A. Le matériel de texture d'une carte graphique peut accéder à chaque élément selon son format. Par exemple, si vous utilisez le format RVBA, le matériel de texture peut extraire chaque élément de 8 bits dans une forme 32 bits. En C++ AMP, vous pouvez définir des bits par élément scalaire de votre texel afin d'accéder automatiquement aux éléments scalaires individuels dans le code sans utiliser le décalage de bits.

Instanciation d'objets de texture

Vous pouvez déclarer un objet de texture sans l'initialiser. L'exemple de code suivant déclare plusieurs objets de texture.

#include <amp.h>
#include <amp_graphics.h>
using namespace concurrency;
using namespace concurrency::graphics;

void declareTextures() {
    // Create a 16-texel texture of int.
    texture<int, 1> intTexture1(16);
    texture<int, 1> intTexture2(extent<1>(16));

    // Create a 16 x 32 texture of float_2.
    texture<float_2, 2> floatTexture1(16, 32);
    texture<float_2, 2> floatTexture2(extent<2>(16, 32));

    // Create a 2 x 4 x 8 texture of uint_4.
    texture<uint_4, 3> uintTexture1(2, 4, 8);
    texture<uint_4, 3> uintTexture2(extent<3>(2, 4, 8));
}

Vous pouvez également utiliser un constructeur pour déclarer et initialiser un objet texture. L'exemple de code suivant instancie un objet texture à partir d'un vecteur d'objets float_4. Les bits par élément scalaire sont définis à la valeur par défaut. Vous ne pouvez pas utiliser ce constructeur avec norm, unorm ou les vecteurs courts de norm et de unorm, car ils n'ont pas de bits par défaut par élément scalaire.

#include <amp.h>
#include <amp_graphics.h>
#include <vector>
using namespace concurrency;
using namespace concurrency::graphics;

void initializeTexture() {
    std::vector<int_4> texels;
    for (int i = 0; i < 768 * 1024; i++) {
        int_4 i4(i, i, i, i);
        texels.push_back(i4);
    }

    texture<int_4, 2> aTexture(768, 1024, texels.begin(), texels.end());
}

Vous pouvez également déclarer et initialiser un objet texture à l'aide d'une surcharge de constructeur renvoyant un pointeur vers les données sources, la taille en octets des données sources et les bits par élément scalaire.

void createTextureWithBPC() { // Create the source data.
    float source[1024* 2];
    for (int i = 0; i <1024* 2; i++) {
        source[i] = (float)i;
    }
    // Initialize the texture by using the size of source in bytes // and bits per scalar element.
    texture<float_2, 1> floatTexture(1024, source, (unsigned int)sizeof(source), 32U);
}

Les textures dans ces exemples sont créées sur la vue par défaut de l'accélérateur par défaut. Vous pouvez utiliser d'autres surcharges du constructeur si vous souhaitez spécifier un objet accelerator_view. Vous ne pouvez pas créer un objet de texture sur un accélérateur CPU.

Il existe des limites sur la taille de chaque dimension de l'objet texture, comme l'indique le tableau suivant. Une erreur d'exécution est générée si vous dépassez les limites.

Texture Limitation de taille par dimension
texture<T,1> 16384
texture<T,2> 16384
texture<T,3> 2 048

Lecture des objets de texture

Vous pouvez lire à partir d’un texture objet à l’aide de texture ::operator[], d’opérateur texture ::operator() ou de texture ::get, méthode. Les deux opérateurs retournent une valeur, et non une référence. Par conséquent, vous ne pouvez pas écrire dans un objet texture à l'aide de texture::operator\[\].

void readTexture() {
    std::vector<int_2> src;
    for (int i = 0; i <16 *32; i++) {
        int_2 i2(i, i);

        src.push_back(i2);
    }

    std::vector<int_2> dst(16* 32);

    array_view<int_2, 2> arr(16, 32, dst);

    arr.discard_data();

    const texture<int_2, 2> tex9(16, 32, src.begin(), src.end());

    parallel_for_each(tex9.extent, [=, &tex9] (index<2> idx) restrict(amp) { // Use the subscript operator.
        arr[idx].x += tex9[idx].x; // Use the function () operator.
        arr[idx].x += tex9(idx).x; // Use the get method.
        arr[idx].y += tex9.get(idx).y; // Use the function () operator.
        arr[idx].y += tex9(idx[0], idx[1]).y;
    });

    arr.synchronize();
}

L'exemple de code suivant montre comment inscrire des canaux de texture dans un vecteur court, puis comment accéder aux éléments scalaires individuels en tant que propriétés du vecteur court.

void UseBitsPerScalarElement() { // Create the image data. // Each unsigned int (32-bit) represents four 8-bit scalar elements(r,g,b,a values).
    const int image_height = 16;
    const int image_width = 16;
    std::vector<unsigned int> image(image_height* image_width);

    extent<2> image_extent(image_height, image_width);

    // By using uint_4 and 8 bits per channel, each 8-bit channel in the data source is // stored in one 32-bit component of a uint_4.
    texture<uint_4, 2> image_texture(image_extent, image.data(), image_extent.size()* 4U,  8U);

    // Use can access the RGBA values of the source data by using swizzling expressions of the uint_4.
    parallel_for_each(image_extent,
        [&image_texture](index<2> idx) restrict(amp)
        { // 4 bytes are automatically extracted when reading.
            uint_4 color = image_texture[idx];
            unsigned int r = color.r;
            unsigned int g = color.g;
            unsigned int b = color.b;
            unsigned int a = color.a;
        });
}

Le tableau suivant répertorie les bits valides par canal pour chaque type de vecteur de tri.

Type de données de texture Bits valides par élément scalaire
int, int_2, int_4

uint, uint_2, uint_4
8, 16, 32
int_3, uint_3 32
float, float_2, float_4 16, 32
float_3 32
double, double_2 64
norm, norm_2, norm_4

unorm, unorm_2, unorm, 4
8, 16

Écrire dans des objets de texture

Utilisez la méthode texture ::set pour écrire dans des texture objets. Un objet de texture peut être accessible en lecture seule ou en lecture/écriture. Pour qu'un objet de texture soit lisible et accessible en écriture, les conditions suivantes doivent être remplies :

  • T possède seulement un composant scalaire. (Les vecteurs courts ne sont pas autorisés.)

  • T n’est pas double, normou unorm.

  • La propriété texture::bits_per_scalar_element est 32.

Si toutes trois ne sont pas vraies, l'objet texture est accessible en lecture seule. Les deux premières conditions sont vérifiées pendant la compilation. Une erreur de compilation est générée si votre code essaie d'écrire dans un objet de texture readonly. La condition pour texture::bits_per_scalar_element laquelle est détectée au moment de l’exécution et le runtime génère l’exception unsupported_feature si vous essayez d’écrire dans un objet en lecture seule texture .

L'exemple de code suivant écrit des valeurs dans un objet de texture.

void writeTexture() {
    texture<int, 1> tex1(16);

    parallel_for_each(tex1.extent, [&tex1] (index<1> idx) restrict(amp) {
        tex1.set(idx, 0);
    });
}

Copie d'objets de texture

Vous pouvez copier entre des objets de texture à l’aide de la fonction de copie ou de la fonction copy_async , comme illustré dans l’exemple de code suivant.

void copyHostArrayToTexture() { // Copy from source array to texture object by using the copy function.
    float floatSource[1024* 2];
    for (int i = 0; i <1024* 2; i++) {
        floatSource[i] = (float)i;
    }
    texture<float_2, 1> floatTexture(1024);

    copy(floatSource, (unsigned int)sizeof(floatSource), floatTexture);

    // Copy from source array to texture object by using the copy function.
    char charSource[16* 16];
    for (int i = 0; i <16* 16; i++) {
        charSource[i] = (char)i;
    }
    texture<int, 2> charTexture(16, 16, 8U);

    copy(charSource, (unsigned int)sizeof(charSource), charTexture);
    // Copy from texture object to source array by using the copy function.
    copy(charTexture, charSource, (unsigned int)sizeof(charSource));
}

Vous pouvez également copier d’une texture vers une autre à l’aide de la méthode texture ::copy_to . Les deux textures peuvent être sur des accelerator_views différents. Lorsque vous effectuez une copie vers un objet writeonly_texture_view, les données sont copiées dans l'objet texture sous-jacent. Les bits par élément scalaire et l'extent doivent être identiques sur les objets texture sources et de destination. Si ces exigences ne sont pas satisfaites, le runtime lève une exception.

Classes d'affichage de texture

C++ AMP présente la classe texture_view dans Visual Studio 2013. Les vues de texture prennent en charge les mêmes types et rangs texels que la classe de texture, mais contrairement aux textures, elles permettent d’accéder à d’autres fonctionnalités matérielles telles que l’échantillonnage de texture et les mipmaps. Les vues de texture prennent en charge l'accès en lecture seule, en écriture seule et en lecture-écriture aux données de texture sous-jacentes.

  • L'accès en lecture seule est fourni par une spécialisation de modèle texture_view<const T, N>, qui prend en charge des éléments comportant 1, 2 ou 4 composants, un échantillonnage de texture et un accès dynamique à une plage de niveaux de mipmaps qui sont déterminés lorsque la vue est instanciée.

  • L'accès en écriture seule est fournie par la classe de modèles non spécialisée texture_view<T, N>, qui prend en charge les éléments comportant 2 ou 4 composants et peut accéder à un niveau de mipmap qui est déterminé lorsque la vue est instanciée. L'échantillonnage n'est pas pris en charge.

  • L'accès en lecture-écriture est fourni par la classe de modèles non spécialisée texture_view<T, N>, qui, comme les textures, prend en charge les éléments comportant uniquement un composant ; la vue peut accéder à un niveau de mipmap qui est déterminé lorsque la vue est instanciée. L'échantillonnage n'est pas pris en charge.

Les vues de texture sont analogues aux vues de tableau, mais ne fournissent pas les fonctionnalités de gestion et de déplacement automatiques des données que la classe array_view fournit sur la classe de tableau. texture_view est accessible uniquement sur la vue d'accélérateur où les données de texture sous-jacentes résident.

writeonly_texture_view déconseillé

Pour Visual Studio 2013, C++ AMP introduit une meilleure prise en charge des fonctionnalités de texture matérielle telles que l’échantillonnage et les mipmaps, qui ne peuvent pas être pris en charge par la classe writeonly_texture_view. La classe texture_view récemment introduite, prend en charge un sur-ensemble de la fonctionnalité dans writeonly_texture_view; par conséquent, writeonly_texture_view est déconseillé.

Nous vous recommandons (au moins pour le nouveau code) d'utiliser texture_view pour accéder aux fonctionnalités qui ont été précédemment fournies par writeonly_texture_view. Comparez les deux exemples de code suivants qui accèdent en écriture à l'objet de texture comportant deux composants (int_2). Notez que dans les deux cas, la vue, wo_tv4, doit être capturée par la valeur de l’expression lambda. Voici l'exemple qui utilise la nouvelle classe texture_view :

void write2ComponentTexture() {
    texture<int_2, 1> tex4(16);

    texture_view<int_2, 1> wo_tv4(tex4);

    parallel_for_each(extent<1>(16), [=] (index<1> idx) restrict(amp) {
        wo_tv4.set(idx, int_2(1, 1));
    });
}

Et voici la classe writeonly_texture_view déconseillée :

void write2ComponentTexture() {
    texture<int_2, 1> tex4(16);

    writeonly_texture_view<int_2, 1> wo_tv4(tex4);

    parallel_for_each(extent<1>(16), [=] (index<1> idx) restrict(amp) {
        wo_tv4.set(idx, int_2(1, 1));
    });
}

Comme vous pouvez le voir, les deux exemples de code sont quasiment identiques lorsque vous vous contentez d'accéder en écriture au niveau de mipmap principal. Si vous avez utilisé writeonly_texture_view dans le code existant et que vous n'envisagez pas d'améliorer ce code, vous ne devez pas le modifier. Toutefois, si vous pensez présenter ce code, nous vous suggérons de le réécrire pour utiliser texture_view car ses améliorations prennent en charge les nouvelles fonctionnalités de texture matérielles. Lisez la suite pour plus d'informations sur ces nouvelles fonctionnalités.

Pour plus d’informations sur la dépréciation de writeonly_texture_view, consultez Vue d’ensemble de la conception de la vue de texture en C++ AMP sur le blog de programmation parallèle dans le code natif.

Instanciation d'objets de la vue Texture

La déclaration d’un est texture_view similaire à la déclaration d’un array_view élément associé à un tableau. L'exemple de code suivant déclare plusieurs objets texture et objets texture_view qui leur sont associés.

#include <amp.h>
#include <amp_graphics.h>
using namespace concurrency;
using namespace concurrency::graphics;

void declareTextureViews()
{
    // Create a 16-texel texture of int, with associated texture_views.
    texture<int, 1> intTexture(16);
    texture_view<const int, 1> intTextureViewRO(intTexture);  // read-only
    texture_view<int, 1> intTextureViewRW(intTexture);        // read-write

    // Create a 16 x 32 texture of float_2, with associated texture_views.
    texture<float_2, 2> floatTexture(16, 32);
    texture_view<const float_2, 2> floatTextureViewRO(floatTexture);  // read-only
    texture_view<float_2, 2> floatTextureViewRO(floatTexture);        // write-only

    // Create a 2 x 4 x 8 texture of uint_4, with associated texture_views.
    texture<uint_4, 3> uintTexture(2, 4, 8);
    texture_view<const uint_4, 3> uintTextureViewRO(uintTexture);  // read-only
    texture_view<uint_4, 3> uintTextureViewWO(uintTexture);        // write-only
}

Notez comment une vue de texture dont le type d'élément est non const avec un composant qui est en lecture-écriture, et qu'une vue de texture dont le type d'élément est non const avec plusieurs composants, sont accessibles en écriture seule. Les vues de texture des types d'élément const sont toujours en lecture seule, mais si le type d'élément est non const, le nombre de composants dans l'élément détermine s'il est accessible en lecture-écriture (1 composant) ou en écriture seule (plusieurs composants).

Le type d'élément d'une texture_view (son attribut const/non const et aussi le nombre de composants qu'il comporte) joue également un rôle pour déterminer si la vue prend en charge l'échantillonnage, et comment les niveaux de mipmap sont accessibles :

Type Composants Lire Écrire Échantillonnage Accès aux mipmaps
<texture_view const T, N> 1, 2, 4 Oui Non (1) Oui Oui, indexable. La plage est déterminée à l'instanciation.
<Texture_view T, N> 1

2, 4
Oui

Non (2)
Oui

Oui
Non (1)

Non (1)
Oui, un niveau. Le niveau est déterminé à l'instanciation.

Oui, un niveau. Le niveau est déterminé à l'instanciation.

Dans ce tableau, vous pouvez constater que les vues de texture en lecture seule prennent en charge les nouvelles fonctions pour compenser l'impossibilité d'accéder en écriture à la vue. Les vues de texture accessibles en écriture sont limitées car elles peuvent uniquement accéder à un niveau de mipmap. Les vues de texture en lecture-écriture sont encore plus spécialisées que celles accessibles en écriture, car elles ajoutent l’exigence que le type d’élément de la vue de texture comporte uniquement un seul composant. Notez que l'exemple n'est pas pris en charge pour les vues de texture accessibles en écriture, car il s'agit d'une opération orientée lecture seule.

Lecture des objets de la vue Texture

La lecture de données de texture non échantillonnées via un affichage de texture revient à effectuer la lecture depuis la texture elle-même, mais les textures sont capturées par référence, alors que les vues de texture sont capturées par valeur. Voici deux exemples de code. Le premier utilise uniquement texture :

void write2ComponentTexture() {
    texture<int_2, 1> text_data(16);

    parallel_for_each(extent<1>(16), [&] (index<1> idx) restrict(amp) {
        tex_data.set(idx, int_2(1, 1));
    });
}

Et voici le même exemple, sauf qu'il utilise maintenant la classe texture_view :

void write2ComponentTexture() {
    texture<int_2, 1> tex_data(16);

    texture_view<int_2, 1> tex_view(tex_data);

    parallel_for_each(extent<1>(16), [=] (index<1> idx) restrict(amp) {
        tex_view.set(idx, int_2(1, 1));
    });
}

Les vues de texture dont les éléments sont basés sur les types à virgule flottante (par exemple, float, float_2 ou float_4) peuvent également être lues à l'aide de l'échantillonnage de texture afin de tirer parti de la prise en charge matérielle des différents modes de filtrage et modes d'adressage. C++ AMP prend en charge les deux modes de filtrage qui sont les plus courants dans les scénarios de calcul - le filtrage des points (voisin le plus proche) et le filtrage linéaire (moyenne pondérée) - et les quatre modes d'adressage - encapsulé, mis en miroir, ancré et associé à une bordure. Pour plus d’informations sur les modes d’adressage, consultez address_mode Énumération.

Outre les modes que C++ AMP prend directement en charge, vous pouvez accéder à d'autres modes de filtrage et modes d'adressage de la plateforme sous-jacente à l'aide des API d'interopérabilité pour adopter un échantillonneur de texture créé en utilisant directement les API de plateforme. Par exemple, Direct3D prend en charge d'autres vues de filtrage, telles que le filtrage anisotropique, et peut appliquer un mode d'adressage différent à chaque dimension d'une texture. Vous pouvez créer un échantillonnage de texture dont les coordonnées sont encapsulées verticalement, mises en miroir horizontalement et échantillonnées avec le filtrage anisotropique à l'aide des API Direct3D, puis tirer parti de l'échantillonneur dans votre code C++ AMP en utilisant l'API d'interopérabilité make_sampler. Pour plus d’informations, consultez l’échantillonnage de texture en C++ AMP sur le blog de programmation parallèle dans le code natif.

Les vues de texture prennent également en charge la lecture des mipmaps. Les vues de texture en lecture seule (celles qui ont un type d'élément const) offrent le plus de flexibilité car une plage de niveaux mip qui est déterminée à l'instanciation peut être dynamiquement échantillonnée, et parce que les éléments comportant 1, 2 ou 4 composants sont pris en charge. Les vues de texture en lecture-écriture qui ont des éléments comportant un composant prennent également en charge les mipmaps, mais uniquement d'un niveau qui est déterminé à l'instanciation. Pour plus d’informations, consultez Texture avec Mipmaps sur le blog de programmation parallèle dans le code natif.

Écriture dans des objets de la vue Texture

Utilisez la méthode texture_view ::get pour écrire dans le sous-jacent texture via l’objet texture_view . Une vue de texture peut être accessible en lecture seule, en lecture-écriture ou en écriture seule. Pour qu'une vue de texture soit accessible en écriture, elle doit avoir un type d'élément non const ; pour qu'une vue de texture soit lisible et accessible en écriture, son type d'élément doit également avoir qu'un composant. Autrement, la vue de texture n'est accessible qu'en lecture seule. Vous ne pouvez accéder qu'à un niveau de mipmap d'une texture à la fois via une vue de texture, et le niveau est spécifié lorsque la vue est instanciée.

Cet exemple montre comment accéder en écriture au deuxième niveau de mipmap le plus détaillé d'une texture comportant 4 niveaux de mipmaps. Le niveau de mipmap le plus détaillé est le niveau 0.

// Create a texture that has 4 mipmap levels : 16x16, 8x8, 4x4, 2x2
texture<int, 2> tex(extent<2>(16, 16), 16U, 4);

// Create a writable texture view to the second mipmap level :4x4
texture_view<int, 2> w_view(tex, 1);

parallel_for_each(w_view.extent, [=](index<2> idx) restrict(amp)
{
    w_view.set(idx, 123);
});

Interopérabilité

Le runtime AMP C++ prend en charge l’interopérabilité entre texture<T,1> et l’interface ID3D11Texture1D, entre texture<T,2> et l’interface ID3D11Texture2D, et entre texture<T,3> et l’interface ID3D11Texture3D. La méthode get_texture prend un texture objet et retourne une IUnknown interface. La méthode make_texture prend une IUnknown interface et un accelerator_view objet et retourne un texture objet.

Voir aussi

double_2, classe
double_3, classe
double_4, classe
float_2, classe
float_3, classe
float_4, classe
int_2, classe
int_3, classe
int_4, classe
norm_2, classe
norm_3, classe
norm_4, classe
short_vector, structure
short_vector_traits, structure
uint_2, classe
uint_3, classe
uint_4, classe
unorm_2, classe
unorm_3, classe
unorm_4, classe