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
, , float
int
, 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
, ,float
uint
double
, ,norm
ouunorm
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
,norm
ouunorm
.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