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 : , , >=
*
!=
<
<=
/
>
-
==
+
int
float
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
, int
norm
, 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. , identifier
któ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 , ,
double
float
,norm
, lubunorm
.int
uint
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
, unorm
lub 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
double
jest ,norm
lubunorm
.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_view
program . 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_tv4
musi 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_view
elementu — 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
Opinia
https://aka.ms/ContentUserFeedback.
Dostępne już wkrótce: W 2024 r. będziemy stopniowo wycofywać zgłoszenia z serwisu GitHub jako mechanizm przesyłania opinii na temat zawartości i zastępować go nowym systemem opinii. Aby uzyskać więcej informacji, sprawdź:Prześlij i wyświetl opinię dla