Grafika (C++ AMP)

Język C++ AMP zawiera kilka interfejsów API w Concurrency::graphics przestrzeni nazw, których można użyć do uzyskiwania dostępu do obsługi tekstur na procesorach GPU. Oto niektóre typowe scenariusze:

  • Klasę texture można użyć jako kontenera danych do obliczeń i wykorzystać lokalność przestrzenną pamięci podręcznej tekstury i układów sprzętu procesora GPU. Lokalizacja przestrzenna to właściwość elementów danych, które są fizycznie blisko siebie.

  • Środowisko uruchomieniowe zapewnia wydajną współdziałanie z cieniowaniami nielicznymi. Cieniowanie pikseli, wierzchołków, tessellation i kadłuba często zużywa lub produkuje tekstury, których można używać w obliczeniach AMP języka C++.

  • Interfejsy API grafiki w języku C++ AMP zapewniają alternatywne sposoby uzyskiwania dostępu do buforów spakowanych pod wyrazami. Tekstury, które mają formaty reprezentujące texels (elementy tekstury), które składają się z 8-bitowych lub 16-bitowych skalarów, umożliwiają dostęp do takiego zapakowanego magazynu danych.

Uwaga

Nagłówki C++ AMP są przestarzałe, począwszy od programu Visual Studio 2022 w wersji 17.0. Dołączenie wszystkich nagłówków AMP spowoduje wygenerowanie błędów kompilacji. Zdefiniuj _SILENCE_AMP_DEPRECATION_WARNINGS przed dołączeniem żadnych nagłówków AMP, aby wyciszyć ostrzeżenia.

Normy i typy unorm

Typy norm i unorm to typy skalarne, które ograniczają zakres float wartości; jest to nazywane zaciskiem. Te typy można jawnie konstruować z innych typów skalarnych. W rzutowaniach wartość jest najpierw rzutowana do float , a następnie zaciśnięta do odpowiedniego regionu dozwolonego przez norm [-1.0, 1.0] lub unorm [0.0, 1.0]. Rzutowanie z +/- nieskończoność zwraca wartość +/-1. Rzutowanie z sieci NaN jest niezdefiniowane. Element norm może być niejawnie skonstruowany z obiektu unorm i nie ma utraty danych. Niejawny operator konwersji na float jest zdefiniowany na tych typach. Operatory binarne są definiowane między tymi typami a innymi wbudowanymi typami skalarnym, takimi jak i : , , >=*!=<<=/>-==+intfloat Obsługiwane są również operatory przypisania złożonego: +=, , -=*=, /=. Operator negacji jednoargumentowej (-) jest definiowany dla norm typów.

Biblioteka krótkich wektorów

Biblioteka krótkich wektorów udostępnia niektóre funkcje typu wektora zdefiniowanego w języku HLSL i są zwykle używane do definiowania texels. Krótki wektor to struktura danych, która zawiera od jednej do czterech wartości tego samego typu. Obsługiwane typy to double, , float, intnorm, uint, i unorm. Nazwy typów są wyświetlane w poniższej tabeli. Dla każdego typu istnieje również odpowiedni typedef element, który nie ma podkreślenia w nazwie. Typy, które mają podkreślenia, znajdują się w przestrzeni nazw Concurrency::graphics. Typy, które nie mają podkreśleń, znajdują się w przestrzeni nazw Concurrency::graphics::d irect3d , aby były wyraźnie oddzielone od podobnie nazwanych typów podstawowych, takich jak __int8 i __int16.

Type Długość 2 Długość 3 Długość 4
double double_2

double2
double_3

double3
double_4

double4
liczba zmiennoprzecinkowa 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

Operatory

Jeśli operator jest zdefiniowany między dwoma krótkimi wektorami, jest on również definiowany między krótkim wektorem a skalarnym. Ponadto jedna z tych wartości musi być prawdziwa:

  • Typ skalara musi być taki sam jak typ elementu krótkiego wektora.

  • Typ skalara może być niejawnie konwertowany na typ elementu wektora przy użyciu tylko jednej konwersji zdefiniowanej przez użytkownika.

Operacja jest przenoszona między poszczególnymi składnikami krótkiego wektora i skalarnego. Oto prawidłowe operatory:

Typ operatora Prawidłowe typy
Operatory binarne Prawidłowe we wszystkich typach: +, , -*, , /

Prawidłowe w typach liczb całkowitych: %, , ^|, &, , <<>>

Dwa wektory muszą mieć ten sam rozmiar, a wynik jest wektorem o tym samym rozmiarze.
Operatory relacyjne Prawidłowe we wszystkich typach: == i !=
Operator przypisania złożonego Prawidłowe we wszystkich typach: +=, , -=, *=/=

Prawidłowe w typach liczb całkowitych: %=, , ^=|=, &=, , <<=>>=
Operatory inkrementacji i dekrementacji Prawidłowe we wszystkich typach: ++, --

Zarówno prefiks, jak i postfiks są prawidłowe.
Operator BITOWY NOT (~) Prawidłowe w typach całkowitych.
Operator jednoargumentowy - Prawidłowe we wszystkich typach z wyjątkiem unorm i uint.

Wyrażeniawizzling

Biblioteka krótkich wektorów obsługuje konstrukcję vector_type.identifier dostępu w celu uzyskania dostępu do składników krótkiego wektora. , identifierktóry jest znany jako wyrażeniewizzling, określa składniki wektora. Wyrażenie może być wartością l lub wartością r. Poszczególne znaki w identyfikatorze mogą być następujące: x, y, z i w; lub r, g, b i a. "x" i "r" oznaczają składnik zerowy, "y" i "g" oznaczają pierwszy składnik itd. (Zwróć uwagę, że nie można używać wartości "x" i "r" w tym samym identyfikatorze). W związku z tym "rgba" i "xyzw" zwracają ten sam wynik. Metody dostępu jednoskładnikowe, takie jak "x" i "y" to typy wartości skalarnych. Metody dostępu wieloskładnikowe są krótkimi typami wektorów. Jeśli na przykład skonstruujesz int_4 wektor o nazwie fourInts i ma wartości 2, 4, 6 i 8, zwraca fourInts.y liczbę całkowitą 4 i fourInts.rg zwraca int_2 obiekt zawierający wartości 2 i 4.

Klasy tekstur

Wiele procesorów GPU ma sprzęt i pamięci podręczne zoptymalizowane pod kątem pobierania pikseli i texels oraz renderowania obrazów i tekstur. Klasa texture<T,N> , która jest klasą kontenera dla obiektów texel, uwidacznia funkcje tekstur tych procesorów GPU. Texel może być:

  • Skalarny , , doublefloat, norm, lub unorm .intuint

  • Krótki wektor, który ma dwa lub cztery składniki. Jedynym wyjątkiem jest double_4, który nie jest dozwolony.

Obiekt texture może mieć rangę 1, 2 lub 3. Obiekt texture można przechwycić tylko za pomocą odwołania do metody lambda wywołania metody parallel_for_each. Tekstura jest przechowywana na procesorze GPU jako obiekty tekstury Direct3D. Aby uzyskać więcej informacji na temat tekstur i texels w direct3D, zobacz Wprowadzenie do tekstur w direct3D 11.

Używany typ texel może być jednym z wielu formatów tekstur, które są używane w programowaniu graficznym. Na przykład format RGBA może używać 32 bitów z 8 bitami dla elementów R, G, B i A. Sprzęt tekstury karty graficznej może uzyskiwać dostęp do poszczególnych elementów w oparciu o format. Jeśli na przykład używasz formatu RGBA, sprzęt tekstury może wyodrębnić każdy element 8-bitowy do formularza 32-bitowego. W języku C++ AMP można ustawić bity na element skalarny texel, aby automatycznie uzyskać dostęp do poszczególnych elementów skalarnych w kodzie bez użycia przesunięcia bitowego.

Tworzenie wystąpień obiektów tekstury

Obiekt tekstury można zadeklarować bez inicjowania. Poniższy przykład kodu deklaruje kilka obiektów tekstury.

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

Można również użyć konstruktora do deklarowania i inicjowania texture obiektu. Poniższy przykład kodu tworzy wystąpienie texture obiektu z wektora float_4 obiektów. Bity na element skalarny jest ustawiony na wartość domyślną. Nie można użyć tego konstruktora z elementami norm, unormlub krótkimi wektorami i unorm, ponieważ nie mają one bitów norm domyślnych dla elementu skalarnego.

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

Można również zadeklarować i zainicjować texture obiekt przy użyciu przeciążenia konstruktora, które pobiera wskaźnik do danych źródłowych, rozmiar danych źródłowych w bajtach i bity na element skalarny.

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

Tekstury w tych przykładach są tworzone w widoku domyślnym akceleratora domyślnego. Możesz użyć innych przeciążeń konstruktora, jeśli chcesz określić accelerator_view obiekt. Nie można utworzyć obiektu tekstury w akceleratorze procesora CPU.

Istnieją ograniczenia dotyczące rozmiaru każdego wymiaru texture obiektu, jak pokazano w poniższej tabeli. W przypadku przekroczenia limitów zostanie wygenerowany błąd czasu wykonywania.

Tekstura Ograniczenie rozmiaru na wymiar
tekstura<T,1> 16384
tekstura<T,2> 16384
tekstura<T,3> 2048

Odczytywanie z obiektów tekstury

Możesz odczytać z texture obiektu za pomocą metody texture::operator[], texture::operator() lub texture::get, metoda. Oba operatory zwracają wartość, a nie odwołanie. W związku z tym nie można zapisać w texture obiekcie przy użyciu polecenia 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();
}

W poniższym przykładzie kodu pokazano, jak przechowywać kanały tekstur w krótkim wektorze, a następnie uzyskiwać dostęp do poszczególnych elementów skalarnych jako właściwości krótkiego wektora.

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

W poniższej tabeli wymieniono prawidłowe bity na kanał dla każdego typu wektora sortowania.

Typ danych tekstury Prawidłowe bity na element skalarny
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
podwójna, double_2 64
norm, norm_2, norm_4

unorm, unorm_2, unorm, 4
8, 16

Zapisywanie w obiektach tekstury

Użyj metody texture::set, aby zapisywać w texture obiektach. Obiekt tekstury można odczytywać lub zapisywać. Aby obiekt tekstury był czytelny i zapisywalny, muszą być spełnione następujące warunki:

  • T ma tylko jeden składnik skalarny. (Wektory krótkie są niedozwolone).

  • T nie doublejest , normlub unorm.

  • Obiekt texture::bits_per_scalar_element ma wartość 32.

Jeśli wszystkie trzy nie są prawdziwe, texture obiekt jest tylko do odczytu. Pierwsze dwa warunki są sprawdzane podczas kompilacji. Jeśli masz kod, który próbuje zapisać w readonly obiekcie tekstury, jest generowany błąd kompilacji. Warunek jest texture::bits_per_scalar_element wykrywany w czasie wykonywania, a środowisko uruchomieniowe generuje wyjątek unsupported_feature , jeśli próbujesz zapisać w obiekcie readonly texture .

Poniższy przykład kodu zapisuje wartości w obiekcie tekstury.

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

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

Kopiowanie obiektów tekstury

Można skopiować między obiektami tekstury przy użyciu funkcji copy lub funkcji copy_async , jak pokazano w poniższym przykładzie kodu.

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

Możesz również skopiować jedną teksturę do innej przy użyciu metody texture::copy_to . Dwie tekstury mogą znajdować się na różnych accelerator_views. Podczas kopiowania writeonly_texture_view do obiektu dane są kopiowane do obiektu bazowego texture . Bity na element skalarny i zakres muszą być takie same w obiektach źródłowych i docelowych texture . Jeśli te wymagania nie zostaną spełnione, środowisko uruchomieniowe zgłosi wyjątek.

Klasy widoku tekstury

Język C++ AMP wprowadza klasę texture_view w programie Visual Studio 2013. Widoki tekstur obsługują te same typy texel i klasy tekstury, ale w przeciwieństwie do tekstur, zapewniają dostęp do dodatkowych funkcji sprzętowych, takich jak próbkowanie tekstur i mipmapy. Widoki tekstur obsługują dostęp tylko do odczytu, tylko do zapisu i odczytu do danych tekstury.

  • Dostęp tylko do odczytu jest zapewniany przez specjalizację texture_view<const T, N> szablonu, która obsługuje elementy, które mają 1, 2 lub 4 składniki, próbkowanie tekstur i dynamiczny dostęp do zakresu poziomów mipmap, które są określane podczas tworzenia wystąpienia widoku.

  • Dostęp tylko do zapisu jest zapewniany przez nie wyspecjalizowaną klasę texture_view<T, N>szablonów , która obsługuje elementy, które mają 2 lub 4 składniki i mogą uzyskać dostęp do jednego poziomu mipmap określonego podczas tworzenia wystąpienia widoku. Nie obsługuje próbkowania.

  • Dostęp do odczytu i zapisu jest udostępniany przez niespecyjną klasę texture_view<T, N>szablonów, która, na przykład tekstury, obsługuje elementy, które mają tylko jeden składnik. Widok może uzyskać dostęp do jednego poziomu mipmap określonego podczas tworzenia wystąpienia. Nie obsługuje próbkowania.

Widoki tekstur są analogiczne do widoków tablic, ale nie zapewniają funkcji automatycznego zarządzania danymi i przenoszenia danych, które klasa array_view zapewnia w klasie tablicy. Dostęp texture_view do obiektu można uzyskać tylko w widoku akceleratora, w którym znajdują się bazowe dane tekstury.

writeonly_texture_view przestarzałe

W przypadku programu Visual Studio 2013 język C++ AMP wprowadza lepszą obsługę funkcji tekstur sprzętowych, takich jak próbkowanie i mapy mipmap, które nie mogą być obsługiwane przez klasę writeonly_texture_view. Nowo wprowadzona texture_view klasa obsługuje nadzbiór funkcji w systemie writeonly_texture_view; w związku writeonly_texture_view z tym jest przestarzały.

Zalecamy , przynajmniej w przypadku nowego kodu, który jest używany texture_view do uzyskiwania dostępu do funkcji, które były wcześniej udostępniane przez writeonly_texture_viewprogram . Porównaj dwa poniższe przykłady kodu, które zapisują do obiektu tekstury, który ma dwa składniki (int_2). Zwróć uwagę, że w obu przypadkach widok , wo_tv4musi zostać przechwycony przez wartość w wyrażeniu lambda. Oto przykład, który używa nowej texture_view klasy:

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

A oto przestarzała writeonly_texture_view klasa:

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

Jak widać, dwa przykłady kodu są prawie identyczne, gdy wszystko, co robisz, to pisanie na podstawowym poziomie mipmap. Jeśli używasz writeonly_texture_view istniejącego kodu i nie planujesz ulepszyć tego kodu, nie musisz go zmieniać. Jeśli jednak myślisz o przesłaniu tego kodu do przodu, zalecamy ponowne zapisywanie go do użycia texture_view , ponieważ ulepszenia w nim obsługują nowe funkcje tekstur sprzętu. Przeczytaj, aby uzyskać więcej informacji na temat tych nowych możliwości.

Aby uzyskać więcej informacji na temat wycofywania programu writeonly_texture_view, zobacz Omówienie projektu widoku tekstury w języku C++ AMP w blogu Programowanie równoległe w kodzie natywnym.

Tworzenie wystąpień obiektów widoku tekstury

Deklarowanie obiektu texture_view jest podobne do deklarowania array_view obiektu skojarzonego z tablicą. Poniższy przykład kodu deklaruje kilka texture obiektów i texture_view obiektów, które są z nimi skojarzone.

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

Zwróć uwagę, że widok tekstury, którego typ elementu jest inny niż const i ma jeden składnik jest odczyt-zapis, ale widok tekstury, którego typ elementu jest inny niż const, ale ma więcej niż jeden składnik jest tylko do zapisu. Widoki tekstur typów elementów const są zawsze tylko do odczytu, ale jeśli typ elementu jest inny niż const, to liczba składników w elemencie określa, czy jest to odczyt-zapis (1 składnik) lub tylko do zapisu (wiele składników).

Typ texture_viewelementu — jego const-ness, a także liczba składników, które ma — odgrywa również rolę w określaniu, czy widok obsługuje próbkowanie tekstur i jak można uzyskać dostęp do poziomów mipmap:

Type Elementy Odczyt Zapisywanie Próbkowanie Dostęp mipmap
<texture_view const T, N> 1, 2, 4 Tak Nie (1) Tak Tak, indeksowalne. Zakres jest określany podczas tworzenia wystąpienia.
<Texture_view T, N> 1

2, 4
Tak

Nie (2)
Tak

Tak
Nie (1)

Nie (1)
Tak, jeden poziom. Poziom jest określany podczas tworzenia wystąpienia.

Tak, jeden poziom. Poziom jest określany podczas tworzenia wystąpienia.

W tej tabeli widać, że widoki tekstur tylko do odczytu w pełni obsługują nowe funkcje w zamian za brak możliwości zapisu w widoku. Widoki tekstur zapisywalnych są ograniczone, ponieważ mogą uzyskiwać dostęp tylko do jednego poziomu mipmap. Widoki tekstur odczytu i zapisu są jeszcze bardziej wyspecjalizowane niż zapisywalne, ponieważ dodają wymóg, że typ elementu widoku tekstury ma tylko jeden składnik. Zwróć uwagę, że próbkowanie nie jest obsługiwane w przypadku widoków tekstur zapisywalnych, ponieważ jest to operacja zorientowana na odczyt.

Odczytywanie z obiektów widoku tekstury

Odczytywanie nieprzykładowanych danych tekstury za pośrednictwem widoku tekstury przypomina odczytywanie ich z samej tekstury, z tą różnicą, że tekstury są przechwytywane przez odwołanie, podczas gdy widoki tekstur są przechwytywane przez wartość. Poniżej przedstawiono dwa przykłady kodu; najpierw, używając tylko: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));
    });
}

Oto ten sam przykład, z tą różnicą texture_view , że teraz używa klasy :

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

Widoki tekstur, których elementy są oparte na typach zmiennoprzecinkowych — na przykład zmiennoprzecinkowych, float_2 lub float_4 — można również odczytywać przy użyciu próbkowania tekstur, aby korzystać z obsługi sprzętu dla różnych trybów filtrowania i trybów adresowania. Język C++ AMP obsługuje dwa tryby filtrowania, które są najczęściej używane w scenariuszach obliczeniowych — filtrowanie punktów (najbliższy sąsiad) i filtrowanie liniowe (średnia ważona) i cztery tryby adresowania — opakowane, dublowane, zaciskane i obramowanie. Aby uzyskać więcej informacji na temat trybów adresowania, zobacz address_mode Wyliczenie.

Oprócz trybów, które obsługuje bezpośrednio język C++ AMP, można uzyskać dostęp do innych trybów filtrowania i trybów adresowania bazowej platformy przy użyciu interfejsów API międzyoperacyjności w celu wdrożenia próbkatora tekstury utworzonego bezpośrednio przy użyciu interfejsów API platformy. Na przykład funkcja Direct3D obsługuje inne tryby filtrowania, takie jak filtrowanie anisotropowe, i może stosować inny tryb adresowania do każdego wymiaru tekstury. Można utworzyć próbkator tekstury, którego współrzędne są opakowane pionowo, dublowane w poziomie i próbkowane z filtrowaniem anisotropowym przy użyciu interfejsów API Direct3D, a następnie wykorzystać próbkator w kodzie C++ AMP przy użyciu interfejsu make_sampler API międzyoperacyjności. Aby uzyskać więcej informacji, zobacz Próbkowanie tekstur w języku C++ AMP w blogu Programowanie równoległe w kodzie natywnym.

Widoki tekstur obsługują również odczytywanie mipmap. Widoki tekstur tylko do odczytu (te, które mają typ elementu const) oferują największą elastyczność, ponieważ obsługiwany jest zakres poziomów mip określonych podczas tworzenia wystąpienia, a elementy, które mają 1, 2 lub 4 składniki. Widoki tekstur do odczytu i zapisu, które zawierają elementy, które mają jeden składnik, obsługują również mapy mipmap, ale tylko na poziomie określonym podczas tworzenia wystąpienia. Aby uzyskać więcej informacji, zobacz Tekstura z mipmapami na blogu Programowanie równoległe w kodzie natywnym.

Zapisywanie w obiektach widoku tekstury

Użyj metody texture_view::get, aby zapisać element źródłowy texture za pośrednictwem texture_view obiektu . Widok tekstury może być tylko do odczytu, do odczytu i zapisu lub tylko do zapisu. Aby widok tekstury mógł być zapisywalny, musi mieć typ elementu, który nie jest const; aby widok tekstury był czytelny i zapisywalny, jego typ elementu musi również zawierać tylko jeden składnik. W przeciwnym razie widok tekstury jest tylko do odczytu. Dostęp do jednego poziomu mipmap tekstury jednocześnie można uzyskać za pośrednictwem widoku tekstury, a poziom jest określany po utworzeniu wystąpienia widoku.

W tym przykładzie pokazano, jak zapisywać dane na drugim najbardziej szczegółowym poziomie mipmap tekstury, która ma 4 poziomy mipmap. Najbardziej szczegółowy poziom mipmap to poziom 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);
});

Współdziałanie

Środowisko uruchomieniowe C++ AMP obsługuje współdziałanie między interfejsem texture<T,1>ID3D11Texture1D między texture<T,2> a interfejsem ID3D11Texture2D oraz między texture<T,3> a interfejsem ID3D11Texture3D. Metoda get_texture przyjmuje texture obiekt i zwraca IUnknown interfejs. Metoda make_texture przyjmuje IUnknown interfejs i accelerator_view obiekt i zwraca texture obiekt.

Zobacz też

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