Udostępnij za pośrednictwem


Grafika (C++ AMP)

C++ AMP zawiera kilka interfejsów API w przestrzeni nazw Concurrency::graphics, który umożliwia dostęp do obsługi tekstur na GPU.Niektóre typowe przypadki to:

  • Można użyć klasy texture jako kontener danych dla obliczeń i wykorzystać przestrzenne umiejscowienie w pamięci podręcznej tekstury i układach sprzętowych 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 C++ AMP.

  • Interfejs graficzny API w C++ AMP zapewnia alternatywne sposoby dostępu 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-bitowe lub 16-bitowych skalarów umożliwiają dostęp do danych spakowanych w takiej pamięci.

[!UWAGA]

Interfejsy API C++ AMP nie zapewniają próbkowania tekstur i funkcji filtrowania.Należy użyć funkcji współdziałania C++ AMP i następnie napisać kod z użyciem DirectCompute i HLSL.

Typy norm i unorm

Typy skalarne norm i unorm są typami skalarnymi, które ograniczają zakres wartości 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 normę [-1.0…1.0] lub normę bez znaku [0.0…1.0].Rzutowanie z +/- nieskończoności zwraca +/- 1.Rzutowanie NaN jest niezdefiniowane.Norma może zostać niejawnie skonstruowana z normy bez znaku bez utraty danych.Operator niejawnej konwersji na typ zmiennoprzecinkowy jest zdefiniowany dla tych typów.Operatory dwuargumentowe są zdefiniowane między podanymi typami i innymi wbudowanymi typami skalarnymi takimi jak float i int: +, -, *, /, ==, !=, >, <, >=, <=.Złożone operatory przypisania są również obsługiwane: +=, -=, *=, /=.Unarny operator negacji (-) jest zdefiniowany dla norm.

Biblioteka Short Vector

Biblioteka Short Vector zawiera niektóre funkcje typu Vector zdefiniowane w HLSL i jest zazwyczaj używana do definiowania tekseli.Krótki wektor jest strukturą danych, zawierającą jedną do czterech wartości tego samego typu.Obsługiwane typy to double, float, int, norm, uint, oraz unorm.Nazwy typów przedstawiono w poniższej tabeli.Dla każdego typu jest również odpowiadające wyrażenie typedef które nie ma znaku podkreślenia w nazwie.Typy, które mają podkreślenia znajdują się w Obszar nazw CONCURRENCY::Graphics.Typy, które nie mają podkreślenia są w znajdują się w Obszar nazw CONCURRENCY::Graphics::Direct3D , dzięki czemu są wyraźnie rozdzielone od podobnie nazwanych typów podstawowych takich jak __int8 i __int16.

Length 2

Length 3

Length 4

double

double_2

double2

double_3

double3

double_4

double4

float

float_2

float2

float_3

float_3

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

Hh913015.collapse_all(pl-pl,VS.110).gifOperatory

Jeśli zdefiniowano operator pomiędzy dwoma krótkimi wektorami, jest on także zdefiniowany pomiędzy krótkim wektorem, a skalarem.Ponadto jeden z poniższych warunków musi być spełniony:

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

  • Typ skalara można niejawnie konwertować na typ elementu wektora za pomocą tylko jednej konwersji zdefiniowanej przez użytkownika.

Operacja jest wykonywana na poziomie składnika dla każdego składnika krótkiego wektora i skalara.Oto prawidłowe operatory:

Typ operatora

Prawidłowe typy

Operatory dwuargumentowe

Prawidłowe dla wszystkich typów: +, -, *, /

Prawidłowe typów całkowitych: %, ^, |, &, <<, >>

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 typów całkowitych: %=, ^=, |=, &=, <<=, >>=

Operatory inkrementacji i dekrementacji

Ważne na wszystkich typów: ++, --

Zarówno przedrostek jak i przyrostek są prawidłowe.

Bitowy operator negacji (~)

Prawidłowy dla typów całkowitych.

Jednoargumentowy operator -

Prawidłowe dla wszystkich typów z wyjątkiem unorm i uint.

Hh913015.collapse_all(pl-pl,VS.110).gifWyrażenia przemieniane

Biblioteka Short Vector obsługuje dostęp do składników krótkiego wektora za pomocą akcesora vector_type.identifier.identifier, który jest znany jako wyrażenie przemieniane, określa składniki wektora.Wyrażenie może być l-wartością lub r-wartością.Pojedyncze znaki w identyfikatorze mogą być jednymi z: x, y, z oraz w lub r, g, b oraz a. "x" oraz "r" oznaczają zerowy składnik, "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.Akcesory pojedynczego składnika takie jak "x" i "y" są skalarnymi typami wartości.Akcesory wielu składników 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 fourInts.y zwraca liczbę całkowitą 4, a fourInts.rg zwraca obiekt int_2, który zawiera wartości 2 i 4.

Klasy tekstur

Wiele GPU ma sprzętowe 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 obiektów texel, eksponuje funkcjonalność GPU dla tekstur.Texel może być:

  • Skalarem int, uint, float, double, norm, or unorm.

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

Obiekt texture może mieć rangi 1, 2 lub 3.Obiekt texture może być przechwytywany jedynie poprzez odwołanie w lambda wywołaniu parallel_for_each.Tekstury są przechowywane na GPU jako obiekty tekstury Direct3D.Aby uzyskać więcej informacji na temat tekstur i tekseli w Direct3d, zobacz Wprowadzenie do tekstur w Direct3D 11.

Typ teksela może być jednym z wielu formatów tekstury, które są używane w programowania grafiki.Na przykład format RGBA może używać 32 bity, 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 w formie 32-bitowej.W C++ AMP można ustawić bity po elemencie skalarnym w tekselu tak, aby automatycznie uzyskiwać dostęp do poszczególnych elementów skalarnych w kodzie bez wykorzystywania przesunięć bitowych.

Hh913015.collapse_all(pl-pl,VS.110).gifTworzenie wystąpień obiektów tekstury

Można zadeklarować obiekt tekstury bez inicjalizacji.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 norm, unorm, lub wektorem krótki 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ą przeładowania konstruktora, który przyjmuje wskaźnik do danych źródłowych, rozmiar źródła danych w bajtach rozmiar 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.

Ograniczenia na rozmiar każdego wymiaru obiektu texture obowiązują zgodnie z danymi w poniższej tabeli.Błąd czasu wykonania jest generowany jeśli zakresy zostaną przekroczone.

Tekstura

Ograniczenie rozmiaru

texture<T,1>

16384

texture<T,2>

16384

texture<T,2>

2048

Hh913015.collapse_all(pl-pl,VS.110).gifCzytanie z obiektów tekstur

Można czytać z obiektu texture używając Tekstura::operator[] operatora, Tekstura:: (operator) Operator, lub Metoda Texture::Get.Tekstura::operator[] operatora i Tekstura:: (operator) Operator zwracają wartość, a nie odwołanie.Dlatego nie można zapisywać do obiektu texture za pomocą Tekstura::operator[] operatora.

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 tektsury 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 lista 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

float, float_2, float_4

16, 32

double, double_2

64

norm, norm_2, norm_4

unorm, unorm_2, unorm, 4

8, 16

Hh913015.collapse_all(pl-pl,VS.110).gifZapisywanie 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 trzech 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, który jest 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 obiektu texture przeznaczonego 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); 
    });

}

Hh913015.collapse_all(pl-pl,VS.110).gifZa pomocą obiektu writeonly_texture_view

Klasa writeonly_texture_view zawiera widok writeonly obiektu tekstury.Obiekt writeonly_texture_view musi zostać przechwycony przez wartość w wyrażeniu lambda.Następujący przykład kodu wykorzystuje obiekt writeonly_texture_view aby zapisać do obiektu texture, który ma dwa składniki (int_2).

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

Hh913015.collapse_all(pl-pl,VS.110).gifKopiowanie 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ż skopiować z jednej tekstury do innej za pomocą metody texture::copy_to.Dwie tekstury mogą znajdować się na różnych widokach akceleratora.Przy kopiowaniu obiektu writeonly_texture_view, dane są kopiowane do źródłowych obiektów texture.Bity na element skalarny oraz zakres musi być taka sam dla obiektu źródłowego i docelowego texture.Jeśli te wymagania nie są spełnione, środowisko wykonawcze zgłasza wyjątek.

Współdziałanie

Środowisko wykonawcze C++ AMP obsługuje współdziałanie między texture<T,1> i interfejsem ID3D11Texture1D, między texture<T,2> i interfejsem ID3D11Texture2Di 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.

Zobacz też

Informacje

Klasa 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

Struktura short_vector

Struktura short_vector_traits

Klasa uint_2

Klasa uint_3

Klasa uint_4

Klasa unorm_2

Klasa unorm_3

Klasa unorm_4