Grafika (C++ AMP)
Biblioteka C++ AMP zawiera kilka interfejsów API w przestrzeni nazw Concurrency::graphics, które umożliwiają dostęp do obsługi tekstur w procesorach GPU.Niektóre typowe przypadki to:
Można użyć klasy texture jako kontenera danych dla obliczeń i wykorzystać przestrzenne umiejscowienie w pamięci podręcznej tekstury oraz układy w sprzęcie procesora GPU.Przestrzenne umiejscowienie jest właściwością elementów danych, które są fizycznie blisko siebie.
Środowisko wykonawcze zapewnia skuteczne współdziałanie z modułami cieniującymi wszystkich typów poza obliczeniowymi.Moduły cieniujące pikseli, wierzchołków, teselacji oraz płatów powierzchni często tworzą lub wykorzystują tekstury które, można wykorzystać w obliczeniach w bibliotece C++ AMP.
Interfejs graficzny API w bibliotece C++ AMP zapewnia alternatywne sposoby dostępu do buforów z danymi rozmieszczonymi na poziomie niższym niż słowo.Tekstury, które mają formaty reprezentujące teksele (elementy tekstury), które składają się z 8-bitowych lub 16-bitowych wartości skalarnych, umożliwiają dostęp do takiej pamięci spakowanych danych.
Typy norm i unorm
Typy norm i unorm są typami skalarnymi, które ograniczają zakres wartości typu float; jest to znane jako obcinanie.Te typy można jawnie zbudować z innych typów skalarnych.Podczas rzutowania wartość jest najpierw rzutowana na typ float, a następnie obcinana do odpowiedniego regionu dozwolonego przez typ norm [-1.0…1.0] lub unorm [0.0…1.0].Rzutowanie z +/- nieskończoności zwraca wartość +/- 1.Rzutowanie z obiektu NaN jest niezdefiniowane.Typ norm może zostać niejawnie skonstruowany z typu unorm bez utraty danych.Operator niejawnej konwersji na typ zmiennoprzecinkowy jest zdefiniowany dla tych typów.Operatory dwuargumentowe są zdefiniowane między tymi typami i innymi wbudowanymi typami skalarnymi, takimi jak float i int: +, -, *, /, ==, !=, >, <, >=, <=.Złożone operatory przypisania są również obsługiwane: +=, -=, *=, /=.Jednoargumentowy operator zaprzeczenia (-) jest zdefiniowany dla typów norm.
Biblioteka krótkich wektorów
Biblioteka krótkich wektorów zawiera niektóre funkcje typu Wektor zdefiniowane w języku HLSL i jest zazwyczaj używana do definiowania tekseli.Krótki wektor jest strukturą danych zawierającą od jednej do czterech wartości tego samego typu.Obsługiwane typy to double, float, int, norm, uint i unorm.Nazwy typów przedstawiono w poniższej tabeli.Dla każdego typu jest również odpowiadające słowo kluczowe typedef, które nie ma znaku podkreślenia w nazwie.Typy, które mają podkreślenia, znajdują się w Concurrency::graphics — Przestrzeń nazw.Typy, które nie mają podkreślenia, znajdują się w Concurrency::graphics::direct3d — Przestrzeń nazw, dzięki czemu są wyraźnie rozdzielone od podobnie nazwanych typów podstawowych, takich jak __int8 i __int16.
Długość 2 |
Długość 3 |
Długość 4 |
|
---|---|---|---|
double |
double_2 double2 |
double_3 double3 |
double_4 double4 |
typ 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 |
Operatory
Jeśli zdefiniowano operator pomiędzy dwoma krótkimi wektorami, jest on także zdefiniowany pomiędzy krótkim wektorem a wektorem skalarnym.Ponadto jeden z poniższych warunków musi być spełniony:
Typ wartości skalarnej musi być taki sam, jak typ elementu krótkiego wektora.
Typ wartości skalarnej może być niejawnie konwertowany na typ elementu wektora za pomocą tylko jednej konwersji zdefiniowanej przez użytkownika.
Operacja jest wykonywana między wszystkimi składnikami krótkiego wektora i wartości skalarnej.Oto prawidłowe operatory:
Typ operatora |
Prawidłowe typy |
---|---|
Operatory dwuargumentowe |
Prawidłowe dla wszystkich typów: +, -, *, /, Prawidłowe dla typów całkowitoliczbowych: %, ^, |, &, <<, >> Dwa wektory muszą mieć taki sam rozmiar, a wynik jest wektorem tej samej wielkości. |
Operatory relacyjne |
Prawidłowe dla wszystkich typów: == i != |
Złożony operator przypisania |
Prawidłowe dla wszystkich typów: +=, -=, *=, /= Prawidłowe dla typów całkowitoliczbowych: %=, ^=, |=, &=, <<=, >>= |
Operatory inkrementacji i dekrementacji |
Prawidłowe dla wszystkich typów: ++, -- Zarówno przedrostek, jak i przyrostek są prawidłowe. |
Bitowy operator NOT (~) |
Prawidłowe dla typów całkowitoliczbowych. |
Jednoargumentowy operator |
Prawidłowe dla wszystkich typów z wyjątkiem unorm i uint. |
Wyrażenia przemieniane
Biblioteka krótkich wektorów obsługuje dostęp do składników krótkiego wektora za pomocą metody dostępu vector_type.identifier.identifier, który jest znany jako wyrażenie przemieniane, określa składniki wektora.Wyrażenie może być wartością lvalue lub rvalue.Poszczególne znaki w identyfikatorze mogą być: x, y, z oraz w; lub r, g, b oraz a. Znaki "x" oraz "r" oznaczają składnik zerowy, "y" oraz "g" oznaczają pierwszy składnik i tak dalej. (Zauważ, że „x” i „r” nie mogą zostać użyte w tym samym identyfikatorze). „rgba” i „xyzw” zwracają więc ten sam wynik.Jednoskładnikowe metody dostępu, takie jak „x” i „y”, są typami wartości skalarnych.Wieloskładnikowe metody dostępu są krótkimi wektorami.Na przykład można utworzyć wektor int_4 o nazwie fourInts i zawiera wartości 2, 4, 6 i 8. Wówczas funkcja fourInts.y zwraca liczbę całkowitą 4, a funkcja fourInts.rg zwraca obiekt int_2, który zawiera wartości 2 i 4.
Klasy tekstur
Wiele procesorów GPU ma sprzęt i pamięci podręczne, które są zoptymalizowane do pobrania pikseli i tekseli oraz do renderowania obrazów i tekstur.Klasa texture<T,N>, która jest klasą kontenera dla obiektów tekseli, udostępnia funkcjonalność obsługi tekstur tych procesorów GPU.Teksel może być:
Wartość skalarna int, uint, float, double, norm lub unorm.
Krótki wektor, który ma dwa lub cztery składniki.Jedynym wyjątkiem jest typ double_4, który jest niedozwolony.
Obiekt texture może mieć rangę 1, 2 lub 3.Obiekt texture może być przechwytywany jedynie poprzez odwołanie w wyrażeniu lambda wywołania funkcji parallel_for_each.Tekstury są przechowywane w procesorze GPU jako obiekty tekstury Direct3D.Aby uzyskać więcej informacji na temat tekstur i tekseli w Direct3D, zobacz Wprowadzenie do tekstur w Direct3D 11.
Użyty typ teksela może być jednym z wielu formatów tekstury, które są używane w programowaniu grafiki.Na przykład format RGBA może używać 32 bitów, po 8 bitów na każdy element skalarny R, G, B oraz A.Sprzęt teksturujący karty graficznej może uzyskać dostęp do poszczególnych elementów w oparciu o format.Na przykład jeśli używasz formatu RGBA, sprzęt teksturujący może wyodrębnić każdy element 8-bitowy do formy 32-bitowej.W bibliotece C++ AMP można ustawić bity dla elementu skalarnego w tekselu, tak aby automatycznie uzyskiwać dostęp do poszczególnych elementów skalarnych w kodzie bez wykorzystywania przesunięć bitowych.
Tworzenie wystąpień obiektów tekstury
Można zadeklarować obiekt tekstury bez inicjowania.Poniższy przykład kodu deklaruje kilka obiektów tekstur.
#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 także użyć konstruktora do zadeklarowania i zainicjowania obiektu texture.Poniższy przykład kodu tworzy obiekt texture z wektora obiektów float_4.Element bity na skalar jest ustawiony na domyślny.Nie można użyć tego konstruktora z typami norm, unorm ani krótkimi wektorami typów norm i unorm, ponieważ nie posiadają domyślnej liczby bitów na element skalarny.
#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ć obiekt texture za pomocą przeciążenia konstruktora, które przyjmuje wskaźnik do danych źródłowych, rozmiar danych źródłowych w bajtach i liczbę bitów 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 domyślnym widoku akceleratora domyślnego.Można używać innych przeciążeń konstruktora, jeśli chcesz określić obiekt accelerator_view.Nie można utworzyć obiektu tekstury na akceleratorze CPU.
Obowiązują ograniczenia rozmiaru każdego wymiaru obiektu texture, zgodnie z danymi w poniższej tabeli.Błąd czasu wykonania jest generowany, jeśli limity zostaną przekroczone.
Tekstura |
Ograniczenie rozmiaru |
---|---|
texture<T,1> |
16384 |
texture<T,2> |
16384 |
texture<T,2> |
2048 |
Czytanie z obiektów tekstur
Można czytać z obiektu texture, używając obiektu texture::operator[] Operator, texture::operator() Operator lub texture::get — Metoda.Funkcje texture::operator[] Operator i texture::operator() Operator zwracają wartość, a nie odwołanie.Dlatego nie można zapisywać do obiektu texture za pomocą texture::operator[] 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();
}
Poniższy przykład kodu demonstruje, jak przechowywać kanały tekstury w krótkim wektorze, a także 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;
});
}
Poniższa tabela zawiera prawidłowe liczby bitów 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 |
double, double_2 |
64 |
norm, norm_2, norm_4 unorm, unorm_2, unorm, 4 |
8, 16 |
Zapisywanie do obiektów tekstury
Użyj metody texture::set, aby zapisywać do obiektów texture.Obiekt tekstury może być tylko do odczytu lub do odczytu i zapisu.Aby do obiektu tekstury można było zapisywać dane i czytać z niego, następujące warunki muszą być spełnione:
T ma tylko jeden składnik skalarny. (Krótkie wektory nie są dozwolone).
T nie jest typem double, norm ani unorm.
Właściwość texture::bits_per_scalar_element wynosi 32.
Jeśli którykolwiek z tych trzech warunków nie jest spełniony, obiekt texture jest tylko do odczytu.Pierwsze dwa warunki są sprawdzane podczas kompilacji.Błąd kompilacji jest generowany, jeśli kod próbuje zapisać do obiektu tekstury readonly.Warunek dla texture::bits_per_scalar_element jest wykrywany w trakcie wykonania i środowisko wykonawcze zgłasza wyjątek unsupported_feature podczas próby zapisu w obiekcie texture przeznaczonym tylko do odczytu.
Poniższy przykład kodu zapisuje wartości do obiektu 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 tekstur
Można kopiować między obiektami tekstur przy użyciu funkcji copy lub 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żna również kopiować z jednej tekstury do innej za pomocą metody texture::copy_to.Dwie tekstury mogą znajdować się w różnych widokach akceleratora.Przy kopiowaniu do obiektu writeonly_texture_view dane są kopiowane do źródłowego obiektu texture.Bity na element skalarny oraz zakres muszą być takie sam dla obiektów texture źródłowego i docelowego.Jeśli te wymagania nie są spełnione, środowisko wykonawcze zgłasza wyjątek.
Klasy widoku tekstury
Biblioteka C++ AMP wprowadza klasę texture_view — Klasa do programu Visual Studio 2013.Widoki tekstury obsługują takie same typy i rangi texeli, jak texture — Klasa, ale w przeciwieństwie do tekstur, zapewniają dostęp do dodatkowych funkcji sprzętowych, takich jak próbkowanie tekstur i mipmapy.Widoki tekstury obsługują dostęp tylko do odczytu, tylko do zapisu oraz odczytu i zapisu danych źródłowych tekstury.
Dostęp tylko do odczytu jest zapewniany przez specjalizację szablonu texture_view<const T, N>, obsługującą elementy, które mają 1, 2 lub 4 składniki, pobieranie próbek tekstury i dynamiczny dostęp do szeregu poziomów mipmappingu, które są określane podczas konkretyzacji widoku.
Dostęp tylko do zapisu jest zapewniany przez niewyspecjalizowaną klasę szablonu texture_view<T, N>, obsługującą elementy, które mają 2 lub 4 składniki i mogą uzyskać dostęp do jednego poziomu mipmappingu, określanego podczas konkretyzacji tego widoku.Nie obsługuje pobierania próbek.
Dostęp do odczytu i zapisu jest zapewniany przez niewyspecjalizowaną klasę szablonu texture_view<T, N>, podobnie jak tekstury obsługującą elementy, które mają tylko jeden składnik, widok może uzyskać dostęp do jednego poziomu mipmappingu, który jest określany podczas konkretyzacji.Nie obsługuje pobierania próbek.
Widoki tekstury są analogiczne do widoków tablicy, ale nie zapewniają funkcji automatycznego zarządzania danymi i ich przepływu, które array_view — Klasa zapewnia przez array — Klasa.Obiekt texture_view jest dostępny tylko w widoku akceleratora, gdzie znajdują się dane podstawowe tekstury.
writeonly_texture_view Przestarzałe
Dla Visual Studio 2013, C++ AMP wprowadza lepszą obsługę funkcji tekstury sprzętowej, takich jak pobieranie próbek i mipmapy, które nie były obsługiwane przez writeonly_texture_view — Klasa.Nowo wprowadzona klasa texture_view obsługuje nadzbiór funkcji w writeonly_texture_view; w rezultacie writeonly_texture_view jest przestarzała.
Firma Microsoft zaleca — co najmniej dla nowego kodu — aby używać texture_view do dostępu do funkcjonalności, wcześniej zapewnianej przez writeonly_texture_view.Porównaj poniższe dwa przykłady kodu, które zapisują w obiekcie tekstury, który ma dwa składniki (int_2).Zwróć uwagę, że w obu przypadkach widok, wo_tv4, musi być przechwycony przez wartość w wyrażeniu lambda.Oto przykład, który używa nowej klasy 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));
});
}
A oto przestarzała klasa writeonly_texture_view:
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 zapisujesz do podstawowego poziomu mipmapowania.Jeśli użyłeś writeonly_texture_view w istniejącym kodzie, a nie planujesz optymalizacji kodu, nie musisz tego zmieniać.Jednak jeśli rozważasz dalsze prace nad kodem, zalecamy przepisać go tak, aby używał texture_view, ponieważ jego ulepszenia obsługują nowe funkcje tekstur sprzętowych.Czytaj dalej, aby uzyskać więcej informacji o tych nowych funkcjach.
Aby uzyskać więcej informacji dotyczących zaniechania stosowania flagi writeonly_texture_view, zobacz Omówienie projektu widoku tekstury w języku C++ AMP dotyczące programowania równoległego w kodzie macierzystym blogu.
Tworzenie wystąpień obiektów widoku tekstury
Deklarowanie texture_view jest podobne do deklarowania array_view, który jest skojarzony z array .Poniższy przykład kodu deklaruje kilka obiektów texture i obiektów texture_view, które są skojarzone z nimi.
#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ę, jak widok tekstury, którego typ elementu jest niestały i który ma jeden składnik, jest dostępny do odczytu i zapisu, natomiast widok tekstury, którego typ elementu jest niestały, ale ma on więcej niż jeden składnik, jest tylko do zapisu.Widoki tekstury typów stałych elementów są zawsze tylko do odczytu, ale jeśli typ elementu jest niestały, to liczba składników w elemencie określa, czy jest do odczytu i zapisu (1 składnik), czy tylko do zapisu (wiele składników).
Typ elementu texture_view— jego stałość i liczba składników — również odgrywa rolę w określaniu, czy widok obsługuje pobieranie próbek tekstury i jak uzyskać dostęp do poziomów mipmappingu:
Typ |
Składniki |
Przeczytaj |
Pisz |
Próbkowanie |
Dostęp do mipmappingu |
---|---|---|---|---|---|
texture_view<const T, N> |
1, 2, 4 |
Tak |
Nie (1) |
Tak |
Tak, można indeksować.Zakres jest określany w konkretyzacji. |
Texture_view<T, N> |
1 2, 4 |
Tak Nie (2) |
Tak Tak |
Nie (1) Nie (1) |
Tak, jeden poziom.Poziom jest określany w konkretyzacji. Tak, jeden poziom.Poziom jest określany w konkretyzacji. |
W tej tabeli można zobaczyć, że widoki tekstury tylko do odczytu w pełni obsługują nowe możliwości w zamian za brak możliwości zapisu do widoku.Zapisywalne widoki tekstury są ograniczone w taki sposób, że mają dostęp tylko do jednego poziomu mipmappingu.Widoki tekstury do odczytu i zapisu są jeszcze bardziej wyspecjalizowane niż te zapisywalne, ponieważ dodają wymóg, aby typ elementu widoku tekstury miał tylko jeden składnik.Zwróć uwagę, że pobieranie próbek nie jest obsługiwane dla widoków tekstury do zapisu, ponieważ jest to operacja zorientowana na odczyt.
Czytanie z obiektów widoku tekstury
Odczytywanie niepróbkowanych danych tekstury za pomocą widoku tekstury jest jak odczytywanie ich z samej tekstury, z tą różnicą, że tekstury są przechwytywane przez odniesienie, a widoki tekstury są przechwytywane przez wartość.W poniższych dwóch przykładach kodu pokazano; po pierwsze, za pomocą 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));
});
}
A oto ten sam przykład, z wyjątkiem tego, że teraz używa klasy 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));
});
}
Widoki tekstury, których elementy są oparte na typach zmiennopozycyjnych — na przykład, float, float_2 lub float_4 — można również odczytywać za pomocą pobierania próbek tekstury, aby wykorzystać zalety obsługi sprzętowej różnych trybów filtrowania i adresowania.Biblioteka C++ AMP obsługuje dwa tryby filtrowania, które są najbardziej rozpowszechnione w scenariuszach obliczeniowych — filtrowanie punktowe (wg najbliższego sąsiada) i filtrowanie liniowe (wg średniej ważonej) — i cztery tryby adresowania — zapakowane, dublowane, zaciśnięte i obramowanie.Aby uzyskać więcej informacji na temat trybów filtrowania, zobacz filter_mode — Wyliczenie; aby uzyskać więcej informacji na temat trybów adresowania, zobacz address_mode — Wyliczenie.
Oprócz trybów, które C++ AMP obsługuje bezpośrednio, możesz uzyskać dostęp do innych trybów filtrowania i adresowania bazowej platformy za pomocą międzyoperacyjnych interfejsów API do przyjęcia próbnika tekstur, który został utworzony bezpośrednio przy użyciu interfejsów API platformy.Na przykład, Direct3D obsługuje inne tryby filtrowania, takie jak filtrowanie anizotropowe, i może zastosować inny tryb adresowania do każdego wymiaru tekstury.Możesz utworzyć próbnik tekstury, którego współrzędne są owinięte pionowo, odbite poziomo, pobierane z filtrowaniem anizotropowymo przy użyciu interfejsów API Direct3D, a następnie wykorzystać próbnik w kodzie C++ AMP przy użyciu interoperacyjnego API make_sampler.Aby uzyskać więcej informacji, zobacz wpis Próbkowanie tekstury w bibliotece C++ AMP na blogu dotyczącym programowania równoległego w kodzie natywnym.
Widoki tekstury obsługują także odczyt mipmap.Widoki tekstury tylko do odczytu (te, które mają stały typ elementu) oferują największą elastyczność, ponieważ zakres poziomów mipmappingu, ustalony przy konkretyzacji, może być dynamicznie próbkowany, a elementy, które mają 1, 2 lub 4 składniki, są obsługiwane.Widoki tekstury do odczytu i zapisu, które mają elementy z jednym składnikiem, również obsługują mipmapy, ale tylko poziomu określonego przy konkretyzacji.Aby uzyskać więcej informacji, zobacz wpis Tekstura z mipmappingiem na blogu dotyczącym programowania równoległego w kodzie macierzystym.
Zapisywanie do obiektów widoku tekstury
Użyj texture_view::get — Metoda do zapisu do podstawowej texture przez obiekt texture_view.Widok tekstury może być tylko do odczytu, odczytu i zapisu lub tylko do zapisu.Aby widok tekstury pozwalał na zapis, musi on mieć niestały typ elementu; aby widok tekstury pozwalał na odczyt i zapis, jego typ elementu musi mieć także tylko jeden składnik.W przeciwnym razie widok tekstury jest tylko do odczytu.W jednym momencie możesz za pomocą widoku tekstury uzyskać dostęp tylko do jednego poziomu mipmappingu tekstury, a poziom jest określany w momencie konkretyzacji widoku.
Ten przykład pokazuje, jak napisać do drugiego największego poziomu szczegółowości mipmappingu tekstury, która ma 4 poziomy mipmap.Najbardziej szczegółowy poziom mipmappingu to 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 texture<T,1> i interfejsem ID3D11Texture1D, między texture<T,2> i interfejsem ID3D11Texture2D oraz między texture<T,3> i interfejsem ID3D11Texture3D.Metoda get_texture pobiera obiekt texture i zwraca interfejs IUnknown.Metoda make_texture pobiera interfejs IUnknown i obiekt accelerator_view i zwraca obiekt texture.