Grafiken (C++ AMP)

C++ AMP enthält mehrere APIs im Concurrency::graphics Namespace, mit denen Sie auf die Texturunterstützung für GPUs zugreifen können. Es folgen einige gängige Szenarien:

  • Sie können die texture Klasse als Datencontainer für die Berechnung verwenden und die räumliche Lokalität des Texturcaches und layouts der GPU-Hardware nutzen. Räumliche Stelle ist die Eigenschaft von Datenelementen, die sich physisch sehr ähneln.

  • Die Runtime bietet effiziente Interoperabilität mit Shadern, die keine Compute-Shader sind. Pixel-, Eckpunkt-, Mosaik- und Hüllen-Shader verarbeiten oder produzieren häufig Texturen, die Sie in den C++ AMP-Berechnungen verwenden können.

  • Die Grafik-APIs in C++ AMP stellen alternative Methoden für den Zugriff auf Puffer bereit, die mit Teilworten gepackt sind. Texturen mit Formaten, die Texel (Texturelemente) darstellen, die aus 8-Bit- oder 16-Bit-Skalaren bestehen, ermöglichen den Zugriff auf eine solche gepackte Datenspeicherung.

Hinweis

C++AMP-Header sind ab Visual Studio 2022, Version 17.0, veraltet. Wenn Alle AMP-Header eingeschlossen werden, werden Buildfehler generiert. Definieren Sie _SILENCE_AMP_DEPRECATION_WARNINGS , bevor Sie AMP-Header einschließen, um die Warnungen zu stillen.

Die Typen "norm" und "unorm"

unorm Bei norm den Typen handelt es sich um skalare Typen, die den Wertebereich float begrenzen. Dies wird als Klammerung bezeichnet. Diese Typen können explizit aus anderen skalaren Typen erstellt werden. In Guss wird der Wert zuerst in float die jeweilige Region umgewandelt und dann an die jeweilige Region geklemmt, die von norm [-1.0, 1.0] oder .unorm [0.0, 1.0] Das Umwandeln von +/- Unendlich gibt +/-1 zurück. Das Umwandeln von NaN ist nicht definiert. Eine norm kann implizit aus einem unorm und es gibt keinen Verlust von Daten. Der implizite Konvertierungsoperator für float diese Typen wird definiert. Binäre Operatoren werden zwischen diesen Typen und anderen integrierten skalaren Typen definiert, zfloat. B. und int: +, -, *, <!===>/>=, . <= Die Zusammengesetzten Zuordnungsoperatoren werden ebenfalls unterstützt: +=, -=, *=, . /= Der unäre Negationsoperator (-) ist für norm Typen definiert.

Kurzvektorbibliothek

Die Short Vector Library bietet einige der Funktionen des in HLSL definierten Vektortyps und wird in der Regel zum Definieren von Texeln verwendet. Ein Kurzvektor ist eine Datenstruktur, die ein bis vier Werte desselben Typs enthält. Die unterstützten Typen sind double, , float, int, norm, uintund unorm. In der folgenden Tabelle werden Typnamen aufgeführt. Für jeden Typ gibt es auch einen entsprechenden typedef Unterstrich im Namen. Die Typen mit den Unterstrichen befinden sich im Concurrency::graphics-Namespace. Die Typen, die nicht über die Unterstriche verfügen, befinden sich im Concurrency::graphics::d irect3d-Namespace , sodass sie eindeutig von den ähnlich benannten Grundtypen wie __int8 und __int16.

Typ Length 2 Länge 3 Länge 4
double double_2

double2
double_3

double3
double_4

double4
float 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

Operatoren

Wenn ein Operator zwischen zwei Kurzvektoren definiert wird, wird er auch zwischen einem Kurzvektor und einem Skalar definiert. Außerdem muss eine dieser Bedingungen erfüllt sein:

  • Der Skalartyp muss mit dem Elementtyp des kurzen Vektors übereinstimmen.

  • Der Skalartyp kann implizit mithilfe einer benutzerdefinierten Konvertierung in den Elementtyp des Vektors konvertiert werden.

Der Vorgang wird für jede Komponente einzeln zwischen der jeweiligen Komponente des Kurzvektors und dem Skalar durchgeführt. Folgende Operatoren sind gültig:

Operatortyp Gültige Typen
Binäre Operatoren Gültig für alle Typen: +, , *-, , /

Gültig für ganzzahlige Typen: %, , ^|, &, , <<>>

Die beiden Vektoren müssen dieselbe Größe haben, und das Ergebnis ist ein Vektor derselben Größe.
Relationale Operatoren Gültig für alle Typen: == und !=
Zusammengesetzte Zuweisungsoperatoren Gültig für alle Typen: +=, , -=, *=/=

Gültig für ganzzahlige Typen: %=, , ^=|=, &=, , <<=>>=
Inkrementoperator und Dekrementoperator Gültig für alle Typen: ++, --

Sowohl Präfixe als auch Suffixe sind gültig.
Bitweise NOT-Operator (~) Gültig für ganzzahlige Typen.
Unärer - Operator Gültig für alle Typen außer unorm und uint.

Swizzeln von Ausdrücken

Die Kurzvektorbibliothek unterstützt das Accessorkonstrukt vector_type.identifier, um auf die Komponenten eines Kurzvektors zuzugreifen. Der identifierals Schwarmausdruck bezeichnete Ausdruck gibt die Komponenten des Vektors an. Der Ausdruck kann ein l-Wert oder ein r-Wert sein. Einzelne Zeichen im Bezeichner können sein: x, y, z und w; oder r, g, b und a. "x" und "r" bedeuten die Null-th-Komponente, "y" und "g" die erste Komponente usw. (Beachten Sie, dass "x" und "r" nicht in demselben Bezeichner verwendet werden können.) Daher geben "rgba" und "xyzw" dasselbe Ergebnis zurück. Accessoren mit einzelnen Komponenten wie "x" und "y" sind Skalarwerttypen. Zugriffsmethoden mit mehreren Komponenten sind Kurzvektortypen. Wenn Sie z. B. einen Vektor int_4 mit dem Namen fourInts und den Werten 2, 4, 6 und 8 erstellen, dann gibt fourInts.y die ganze Zahl 4 wieder, und fourInts.rg gibt ein int_2-Objekt zurück, das die Werte 2 und 4 hat.

Texturklassen

Viele GPUs haben Hardware und Caches, die für den Abruf von Pixeln und Texeln und zum Rendern von Images und Texturen optimiert sind. Die texture<T,N> Klasse, bei der es sich um eine Containerklasse für Texelobjekte handelt, macht die Texturfunktionalität dieser GPUs verfügbar. Ein Texel kann Folgendes sein:

  • Ein int, , uint, float, double, norm, oder unorm skalar.

  • Ein Kurzvektor, der zwei oder vier Komponenten enthält. Die einzige Ausnahme ist double_4, die unzulässig ist.

Das texture-Objekt kann über einen Rang von 1, 2 oder 3 verfügen. Das texture-Objekt kann nur als Verweis im Lambda eines Aufrufs auf parallel_for_each erfasst werden. Die Textur wird auf dem GPU-Computer als Direct3D-Texturobjekte gespeichert. Weitere Informationen zu Texturen und Texeln in Direct3D finden Sie unter Einführung in Texturen in Direct3D 11.

Der verwendete Texeltyp kann eines der vielen Texturformate haben, die in der Grafikprogrammierung verwendet werden. Beispielsweise kann ein RGBA-Format 32 Bit mit jeweils 8 Bit für das R-, G-, B- und A-Skalarelement verwenden. Die Texturhardware einer Grafikkarte kann auf der Grundlage des Formats auf die einzelnen Elemente zugreifen. Wenn Sie das RGBA-Format verwenden, kann die Texturhardware z. B. jedes 8-Bit-Element in ein 32-Bit-Formular extrahieren. In C++ AMP können Sie die Bits pro skalarem Element des Texels festlegen, damit Sie auf die einzelnen Skalarelemente im automatisch Code zugreifen können, ohne Bit-Verschiebung zu verwenden.

Instanziieren von Texturobjekten

Sie können ein Texturobjekt ohne Initialisierung deklarieren. Im folgenden Codebeispiel werden mehrere Texturobjekte deklariert.

#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));
}

Sie können auch einen Konstruktor auch verwenden, um ein texture-Objekt zu deklarieren und zu initialisieren. Im folgenden Codebeispiel wird ein texture-Objekt aus einem Vektor aus float_4-Objekten instanziiert. Der Wert für die Bits pro skalarem Element wird auf den Standardwert festgelegt. Sie können diesen Konstruktor nicht mit norm, unorm oder den Kurzvektoren von norm und unorm verwenden, da sie keinen Standardwert für Bits pro skalarem Element haben.

#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());
}

Sie können ein texture-Objekt auch deklarieren und initialisieren, indem Sie eine Konstruktorüberladung verwenden, die einen Zeiger auf die Quelldaten, die Größe von Quelldaten in Bytes und die Bits pro skalarem Element verwendet.

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);
}

Die Texturen in diesen Beispielen werden in der Standardansicht des Standardbeschleunigers erstellt. Sie können auch andere Überladungen des Konstruktors verwenden, wenn Sie ein accelerator_view-Objekt angeben möchten. Sie können kein Texturobjekt für einen CPU-Beschleuniger erstellen.

Es gibt Einschränkungen zur Größe der einzelnen Dimension des texture-Objekts, die in der folgenden Tabelle dargestellt sind. Wenn Sie die Grenzwerte überschreiten, wird ein Laufzeitfehler generiert.

Struktur Größenbeschränkung pro Dimension
Textur<T,1> 16384
Textur<T,2> 16384
Textur<T,3> 2048

Lesen in Texturobjekten

Sie können aus einem texture Objekt lesen, indem Sie "texture::operator[]", "texture::operator()" oder "texture::get"-Methode verwenden. Die beiden Operatoren geben einen Wert und keinen Verweis zurück. Daher können Sie nicht mit texture in ein texture::operator\[\]-Objekt schreiben.

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();
}

Im folgenden Codebeispiel wird veranschaulicht, wie Texturchannel in einem Kurzvektor gespeichert werden und wie anschließend auf die einzelnen Skalarelemente als Eigenschaften des Kurzvektors zugegriffen wird.

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;
        });
}

In der folgenden Tabelle werden die gültigen Bits pro Kanal für jeden Vektortyp aufgeführt.

Texturdatentyp Gültige Bits pro skalarem Element
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

Schreiben in Texturobjekte

Verwenden Sie die Textur::set-Methode , um in texture Objekte zu schreiben. Ein Texturobjekt kann schreibgeschützt sein oder Lese-/Schreibzugriff aufweisen. Damit ein Texturobjekt lesbar und beschreibbar ist, müssen die folgenden Bedingungen erfüllt sein:

  • T ist nur eine skalare Komponente. (Kurzvektoren sind nicht zulässig.)

  • T ist nicht double, , normoder unorm.

  • Die texture::bits_per_scalar_element-Eigenschaft lautet 32.

Wenn alle drei Bedingungen nicht zutreffen, ist das texture-Objekt schreibgeschützt. Die ersten beiden Bedingungen werden während der Kompilierung überprüft. Ein Fehler wird generiert, wenn Sie über Code verfügen, der versucht, in ein readonly-Texturobjekt zu schreiben. Die Bedingung für texture::bits_per_scalar_element die Laufzeit wird erkannt, und die Laufzeit generiert die unsupported_feature Ausnahme, wenn Sie versuchen, in ein readonly-Objekt texture zu schreiben.

Im folgenden Codebeispiel werden Werte in ein Texturobjekt geschrieben.

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

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

Kopieren von Texturobjekten

Sie können zwischen Texturobjekten kopieren, indem Sie die Kopierfunktion oder die copy_async-Funktion verwenden, wie im folgenden Codebeispiel gezeigt.

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));
}

Sie können auch von einer Textur in eine andere kopieren, indem Sie die "texture::copy_to "-Methode verwenden. Die beiden Texturen können sich auf unterschiedlichen accelerator_views befinden. Wenn Sie in ein writeonly_texture_view-Objekt kopieren, werden die Daten in das zugrunde liegende texture-Objekt kopiert. Folgender Wert für Bits pro skalarem Element und Wertebereich müssen auf den Quell- und Ziel-texture-Objekten identisch sein. Wenn diese Anforderungen nicht erfüllt werden, löst die Laufzeit eine Ausnahme aus.

Texturansichtsklassen

C++ AMP führt die texture_view Klasse in Visual Studio 2013 ein. Texturansichten unterstützen dieselben Texeltypen und Rangfolgen wie die Texturklasse, aber im Gegensatz zu Texturen bieten sie Zugriff auf zusätzliche Hardwarefeatures wie Textursampling und Mipmaps. Texturansichten unterstützen schreibgeschützten, lesegeschützten und Lese-Schreibzugriff auf die zugrunde liegenden Texturdaten.

  • Schreibgeschützter Zugriff wird durch die texture_view<const T, N>-Vorlagenspezialisierung geboten, die Elemente mit 1, 2 oder 4 Komponenten, Textursampling und dynamischem Zugriff auf einen Bereich von Mipmapebenen unterstützt, die bei der Instanziierung der Ansicht bestimmt werden.

  • Lesegeschützter Zugriff wird von der unspezialisierten Vorlagenklasse texture_view<T, N> ermöglicht, die Elemente unterstützt, die entweder 2 oder 4 Komponenten haben und auf eine einzelne Mipmapebene zugreifen können, die bei der Instanziierung der Ansicht bestimmt wird. Sampling wird nicht unterstützt.

  • Lese-/Schreibzugriff wird von der unspezialisierten Vorlagenklasse texture_view<T, N>, wie z. B. Texturen, ermöglicht, die Elemente unterstützt, die nur eine Komponente haben. Die Ansicht kann auf eine einzelne Mipmapebene zugreifen, die bei der Instanziierung bestimmt wird. Sampling wird nicht unterstützt.

Texturansichten sind analog zu Arrayansichten, bieten jedoch nicht die automatische Datenverwaltungs- und Bewegungsfunktionalität, die die array_view Class über die Arrayklasse bereitstellt. Auf texture_view kann nur in der Beschleunigeransicht zugegriffen werden, in der sich die zugrunde liegenden Texturdaten befinden.

writeonly_texture_view veraltet

Für Visual Studio 2013 bietet C++ AMP eine bessere Unterstützung für Hardwaretexturfeatures wie Sampling und Mipmaps, die von der writeonly_texture_view-Klasse nicht unterstützt werden konnten. Die neu eingeführte texture_view-Klasse unterstützt eine Obermenge der Funktionen in writeonly_texture_view; daher ist writeonly_texture_view veraltet.

Es empfiehlt sich, dass Sie – zumindest für einen Code – texture_view für den Zugriff auf Funktionen zu verwenden, die zuvor von writeonly_texture_view bereitgestellt wurde. Vergleichen Sie die folgenden beiden Codebeispiele, in denen ein Texturobjekt geschrieben wird, das über zwei Komponenten (int_2) verfügt. Beachten Sie in beiden Fällen, dass die Ansicht, wo_tv4, durch den Wert im Lambdaausdruck erfasst werden muss. Es folgt ein Beispiel, in dem die neue Klasse texture_view verwendet wird:

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));
    });
}

Und hier sehen Sie ein Beispiel für die veraltete writeonly_texture_view-Klasse:

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));
    });
}

Wie Sie sehen können, sind die beiden Codebeispiele fast identisch, wenn Sie nur in die primäre Mipmapebene schreiben. Wenn Sie im vorhandenen Code writeonly_texture_view verwendet haben und diesen Code nicht verbessern möchten, müssen Sie ihn nicht ändern. Wenn Sie den Code jedoch weiterentwickeln möchten, empfiehlt es sich, ihn umzuschreiben und texture_view zu verwenden, da die hier enthaltenen Erweiterungen neue Hardwaretexturfunktionen unterstützen. Es folgen weitere Informationen zu diesen neuen Funktionen.

Weitere Informationen zum Veralteten writeonly_texture_viewfinden Sie im Blog "Parallel Programming" im Blog "Native Code" unter "Übersicht über das Design der Texturansicht" in C++ AMP .

Instanziieren von Texturansichtsobjekten

Das Deklarieren eines texture_view Elements ähnelt dem Deklarieren eines array_view Arrays, das einem Array zugeordnet ist. Im folgenden Codebeispiel werden mehrere texture-Objekte und texture_view-Objekte deklariert, die ihnen zugeordnet werden.

#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
}

Beachten Sie, wie eine Texturansicht mit nicht konstantem Elementtyp und einer Komponente Lese-/Schreibzugriff hat. Dagegen ist eine Texturansicht mit nicht konstantem Elementtyp und mehr als einer Komponente lesegeschützt. Texturansichten mit konstanten Elementtypen sind stets schreibgeschützt. Ist der Elementtyp jedoch nicht konstant, bestimmt die Anzahl von Komponenten im Element, ob die Ansicht Lese-/Schreibzugriff (1 Komponente) hat oder lesegeschützt (mehrere Komponenten) ist.

Der Elementtyp texture_view (seine Konstanz sowie die Anzahl der Komponenten) spielt ebenfalls eine Rolle bei der Frage, ob die Ansicht Textursampling unterstützt und wie auf Mipmapebenen zugegriffen werden kann:

Typ Komponenten Lesen Schreiben Stichprobenentnahme Mipmapzugriff
<texture_view T, N> 1, 2, 4 Ja Nein (1) Ja Ja, kann indexiert werden. Bereich wird bei der Instanziierung bestimmt.
<Texture_view T, N> 1

2, 4
Ja

Nein (2)
Ja

Ja
Nein (1)

Nein (1)
Ja, eine Ebene. Ebene wird bei der Instanziierung bestimmt.

Ja, eine Ebene. Ebene wird bei der Instanziierung bestimmt.

In dieser Tabelle sehen Sie, dass schreibgeschützte Texturansichten die neuen Funktionen vollständig unterstützen, aber nicht in die Ansicht schreiben können. Beschreibbare Texturansichten sind insofern beschränkt, als dass sie auf eine Mipmapebene nur zugreifen können. Texturansichten mit Lese-/Schreibzugriff sind sogar spezialisierter als die beschreibbaren Ansichten, da für sie zusätzlich die Anforderung gilt, dass der Elementtyp der Texturansicht nur über eine Komponente verfügt. Beachten Sie, dass das Sampling nicht in beschreibbaren Texturansichten unterstützt wird, da es sich um einen auf das Lesen ausgerichteten Vorgang handelt.

Lesen in Texturansichtsobjekten

Wenn über eine Texturansicht in Texturdaten ohne Sampling gelesen wird, ähnelt dies dem Lesen in der Textur selbst mit der Ausnahme, dass Texturen durch eine Referenz erfasst werden, während Texturansichten durch einen Wert erfasst werden. Die folgenden beiden Codebeispiele veranschaulichen dies zunächst nur mit der 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));
    });
}

Es folgt das gleiche Beispiel, nun jedoch mit der texture_view-Klasse:

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));
    });
}

Texturansichten, deren Elemente auf Gleitkommatypen basieren, z. B.float, float_2 oder float_4, sind auch mithilfe von Textursampling lesbar, sodass Hardwareunterstützung für unterschiedliche Filter- und Adressierungsmodi genutzt werden kann. C++ AMP unterstützt die beiden Filtermodi, die in Berechnungsszenarien am häufigsten verwendet werden – Punktfilterung (nächster Nachbar) und lineare Filterung (gewichteter Durchschnitt) – und die vier Adressierungsmodi Wrap, Mirror, Clamp und Border. Weitere Informationen zu Adressierungsmodi finden Sie unter address_mode Enumeration.

Neben den Modi, die C++ AMP direkt unterstützt, können Sie auf andere Filtermodi und Adressierungsmodi der zugrunde liegenden Plattform zugreifen, indem Sie die Interop-APIs verwenden, um einen Textursampler anzunehmen, der unter direkter Verwendung der Plattform-APIs erstellt wurde. Beispielsweise unterstützt Direct3D andere Filtermodi wie z. B. anisotropische Filterung und kann für jede Dimension einer Textur eine andere Adressierung anwenden. Sie können einen Textursampler erstellen, dessen Koordinaten vertikal eingeschlossen, horizontal gespiegelt sind und für den mit anisotroper Filterung Stichproben erstellt wurden, indem Sie die Direct3D-APIs verwenden und dann den Sampler im C++ AMP-Code mit der Interop-API make_sampler nutzen. Weitere Informationen finden Sie im Blog "Parallel Programming" im Blog "Parallel Programming" in C++ AMP .

Texturansichten unterstützen auch das Lesen von Mipmaps. Schreibgeschützte Texturansichten (die einen konstanten Elementtyp haben) bieten die höchste Flexibilität, da für eine Reihe von MIP-Ebenen, die bei der Instanziierung bestimmt werden, dynamisch eine Stichprobe erstellt werden kann und Elemente mit 1, 2 oder 4 Komponenten unterstützt werden. Texturansichten mit Lese/Schreibzugriff mit Elementen mit einer einzelnen Komponente unterstützen ebenfalls Mipmaps, jedoch nur auf einer Ebene, die bei der Instanziierung bestimmt wird. Weitere Informationen finden Sie unter "Texture with Mipmaps " im Blog "Parallel Programming in Native Code".

Schreiben in Texturansichtsobjekten

Verwenden Sie die texture_view::get-Methode, um in das texture_view zugrunde liegende texture Objekt zu schreiben. Eine Texturansicht kann Lese-/Schreibzugriff haben, schreibgeschützt oder lesegeschützt sein. Damit eine Texturansicht beschreibbar ist, muss sie einen nicht konstanten Elementtyp haben. Damit eine Texturansicht lesbar und beschreibbar ist, darf der entsprechende Elementtyp nur eine Komponente haben. Anderenfalls ist die Texturansicht schreibgeschützt. Sie können zu einem bestimmten Zeitpunkt nur auf eine einzelne Mipmapebene einer Textur über eine Texturansicht zugreifen, und die Ebene wird bei der Instanziierung der Ansicht bestimmt.

Dieses Beispiel zeigt, wie in die zweitausführlichste Mipmapebene einer Textur mit 4 Mipmapebenen geschrieben wird. Die ausführlichste Mipmapebene ist Ebene 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);
});

Interoperabilität

Die C++AMP-Laufzeit unterstützt die Interoperabilität zwischen und der ID3D11Texture1D-Schnittstelle, zwischen texture<T,2> und der ID3D11Texture2D-Schnittstelle sowie zwischen texture<T,3> und der ID3D11Texture3D-Schnittstelle.texture<T,1> Die get_texture-Methode verwendet ein texture Objekt und gibt eine IUnknown Schnittstelle zurück. Die make_texture-Methode verwendet eine IUnknown Schnittstelle und ein accelerator_view Objekt und gibt ein texture Objekt zurück.

Siehe auch

double_2-Klasse
double_3-Klasse
double_4-Klasse
float_2-Klasse
float_3-Klasse
float_4-Klasse
int_2-Klasse
int_3-Klasse
int_4-Klasse
norm_2-Klasse
norm_3-Klasse
norm_4-Klasse
short_vector-Struktur
short_vector_traits-Struktur
uint_2-Klasse
uint_3-Klasse
uint_4-Klasse
unorm_2-Klasse
unorm_3-Klasse
unorm_4-Klasse