Compartilhar via


Elementos gráficos (C++ AMP)

O Concurrency::graphics C++ AMP contém várias APIs no namespace que você pode usar para acessar o suporte a texturas em GPUs. Os dois cenários mais comuns são:

  • Você pode usar a texture classe como um contêiner de dados para computação e explorar a localidade espacial do cache de textura e layouts do hardware da GPU. A localidade espacial é a propriedade dos elementos de dados que estão fisicamente próximos um do outro.

  • O runtime fornece interoperabilidade eficiente com sombreadores não computados. Pixel, vértice, mosaico e sombreadores de casco frequentemente consomem ou produzem texturas que podem ser usadas em seus cálculos de C++ AMP.

  • As APIs gráficas em C++ AMP fornecem maneiras alternativas de acessar buffers empacotados com sub-palavras. Texturas que têm formatos que representam texels (elementos de textura) compostos por escalares de 8 ou 16 bits permitem acesso a esse armazenamento de dados empacotado.

Observação

Os cabeçalhos C++ AMP foram preteridos a partir do Visual Studio 2022 versão 17.0. Incluir todos os cabeçalhos AMP gerará erros de build. Defina _SILENCE_AMP_DEPRECATION_WARNINGS antes de incluir qualquer cabeçalho AMP para silenciar os avisos.

Os Tipos de norm e unorm

Os tipos norm e unorm são tipos escalares que limitam o intervalo de valores float; isso é conhecido como fixação. Esses tipos podem ser construídos explicitamente a partir de outros tipos escalares. Na conversão, o valor é primeiro convertido em float e, em seguida, fixado na respectiva região permitida por norm [-1.0, 1.0] ou unorm [0.0, 1.0]. A conversão de infinito +/- retorna +/-1. A conversão de NaN é indefinida. Um norm pode ser construído implicitamente a partir de um unorm e não há perda de dados. O operador de conversão implícita para float é definido nesses tipos. Os operadores binários são definidos entre esses tipos e outros tipos escalares internos, como float e int: +, -, *, /, ==, !=, >, <, >=, <=. Os operadores de atribuição composta também têm suporte: +=, -=, *=, /=. O operador de negação unário (-) é definido para tipos norm.

Biblioteca de vetores curtos

A Biblioteca de vetores curtos fornece algumas das funcionalidades do Tipo de Vetor definido no HLSL e normalmente é usada para definir texels. Um vetor curto é uma estrutura de dados que contém de um a quatro valores do mesmo tipo. Os tipos com suporte são double, float, int, norm, uint e unorm. Os nomes de tipo são mostrados na tabela a seguir. Para cada tipo, também há um typedef correspondente que não tem um sublinhado no nome. Os tipos que têm os sublinhados estão no Namespace Concurrency::graphics. Os tipos que não têm os sublinhados estão no Namespace Concurrency::graphics::d irect3d para que eles sejam claramente separados dos tipos fundamentais de nome semelhante, como __int8 e __int16.

Tipo Comprimento 2 Comprimento 3 Comprimento 4
duplo double_2

double2
double_3

double3
double_4

double4
float float_2

float2
float_3

float3
float_4

float4
int int_2

int2
int_3

int3
int_4

int4
norm norm_2

norm2
norm_3

norm3
norm_4

norm4
uint uint_2

uint2
uint_3

uint3
uint_4

uint4
unorm unorm_2

unorm2
unorm_3

unorm3
unorm_4

unorm4

Operadores

Se um operador for definido entre dois vetores curtos, ele também será definido entre um vetor curto e um escalar. Além disso, um deles deve ser verdadeiro:

  • O tipo escalar deve ser o mesmo que o tipo de elemento do vetor curto.

  • O tipo do escalar pode ser convertido implicitamente no tipo de elemento do vetor usando apenas uma conversão definida pelo usuário.

A operação é realizada em termos de componentes entre cada componente do vetor curto e o escalar. Aqui estão os operadores válidos:

Tipo de operador Tipos válidos
Operadores binários Válido em todos os tipos: +, -, *, /

Válido em tipos inteiros: %, ^, |, &, <<, >>

Os dois vetores devem ter o mesmo tamanho e o resultado é um vetor do mesmo tamanho.
Operadores relacionais Válido em todos os tipos: == e !=
Operador de atribuição composto Válido em todos os tipos: +=, -=, *=, /=

Válido em tipos inteiros: %=, ^=, |=, &=, <<=, >>=
Operadores de incremento e de decremento Válido em todos os tipos: ++, --

O prefixo e o postfix são válidos.
Operador NOT bit a bit (~) Válido em tipos inteiros.
Operador - unário Válido em todos os tipos, exceto unorm e uint.

Expressões de swizzling

A Biblioteca de Vetores Curtos dá suporte ao construtor do acessador vector_type.identifier para acessar os componentes de um vetor curto. O identifier, que é conhecido como expressão swizzling, especifica os componentes do vetor. A expressão pode ser um valor l ou um valor r. Caracteres individuais no identificador podem ser: x, y, z e w; ou r, g, b, e a. "x" e "r" significam o componente de 0 a zero, "y" e "g" significam o primeiro componente e assim por diante. (Observe que "x" e "r" não podem ser usados no mesmo identificador.) Portanto, "rgba" e "xyzw" retornam o mesmo resultado. Os acessadores de componente único, como "x" e "y", são tipos de valor escalar. Os acessadores de vários componentes são tipos de vetores curtos. Por exemplo, se você construir um vetor int_4 nomeado fourInts e tiver os valores 2, 4, 6 e 8, fourInts.y retornará o inteiro 4 e fourInts.rg retornará um objeto int_2 que tem os valores 2 e 4.

Classe de textura

Muitas GPUs têm hardware e caches otimizados para buscar pixels e texels e renderizar imagens e texturas. A texture<T,N> classe, que é uma classe de contêiner para objetos texel, expõe a funcionalidade de textura dessas GPUs. Um texel pode ser:

  • Um int, uint, float, double, norm ou unorm escalar.

  • Um vetor curto que tem dois ou quatro componentes. A única exceção é double_4, o que não é permitido.

O objeto texture pode ter uma classificação de 1, 2 ou 3. O objeto texture só pode ser capturado por referência no lambda de uma chamada para parallel_for_each. A textura é armazenada na GPU como objetos de textura Direct3D. Para obter mais informações sobre texturas e texels no Direct3D, consulte Introdução às texturas no Direct3D 11.

O tipo texel usado pode ser um dos muitos formatos de textura usados na programação gráfica. Por exemplo, um formato RGBA poderia usar 32 bits, com 8 bits cada para os elementos R, G, B e A escalares. O hardware de textura de uma placa gráfica pode acessar os elementos individuais com base no formato. Por exemplo, se você estiver usando o formato RGBA, o hardware de textura poderá extrair cada elemento de 8 bits em uma forma de 32 bits. Em C++ AMP, você pode definir os bits por elemento escalar do texel para que possa acessar automaticamente os elementos escalares individuais no código sem usar a mudança de bit.

Instanciando objetos de textura

Você pode declarar um objeto de textura sem inicialização. O exemplo de código a seguir declara vários objetos de textura.

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

Você também pode usar um construtor para declarar e inicializar um objeto texture. O exemplo de código a seguir cria uma instância de um objeto texture de um vetor de objetos float_4. Os bits por elemento escalar são definidos como padrão. Você não pode usar esse construtor com norm, unorm ou com os vetores curtos de norm e unorm, porque eles não têm bits por elemento escalar padrão.

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

Você também pode declarar e inicializar um objeto texture usando uma sobrecarga de construtor que leva um ponteiro para os dados de origem, o tamanho dos dados de origem em bytes e os bits por elemento escalar.

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

As texturas nesses exemplos são criadas na exibição padrão do acelerador padrão. Você pode usar outras sobrecargas do construtor se quiser especificar um objeto accelerator_view. Não é possível criar um objeto de textura em um acelerador de CPU.

Há limites no tamanho de cada dimensão do objeto texture, conforme mostrado na tabela a seguir. Um erro em tempo de execução será gerado se você exceder os limites.

Textura Limitação de tamanho por dimensão
texture<T,1> 16384
texture<T,2> 16384
texture<T,3> 2048

Leitura de objetos texture

Você pode ler de um objeto texture usando texture::operator[], texture::operator() ou texture::get Method. Os dois operadores retornam um valor, não uma referência. Portanto, você não pode gravar em um objeto texture usando 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();
}

O exemplo de código a seguir demonstra como armazenar canais de textura em um vetor curto e, em seguida, acessar os elementos escalares individuais como propriedades do vetor curto.

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

A tabela a seguir lista os bits válidos por canal para cada tipo de vetor de classificação.

Tipo de dados de textura Bits válidos por elemento escalar
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

Gravando em objetos texture

Use o método texture::set para gravar em objetos texture. Um objeto de textura pode ser lido ou lido/gravado. Para que um objeto de textura seja legível e gravável, as seguintes condições devem ser verdadeiras:

  • T tem apenas um componente escalar. (Vetores curtos não são permitidos.)

  • T não é double, norm ou unorm.

  • A propriedade texture::bits_per_scalar_element é 32.

Se os três não forem verdadeiros, o objeto texture será somente leitura. As duas primeiras condições são verificadas durante a compilação. Um erro de compilação será gerado se você tiver um código que tente gravar em um objeto de textura readonly. A condição para texture::bits_per_scalar_element é detectada em tempo de execução e o runtime gera a exceção unsupported_feature se você tentar gravar em um objeto texture somente leitura.

O exemplo de código a seguir grava valores em um objeto de textura.

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

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

Copiar objetos de textura

Você pode copiar entre objetos de textura usando a função copy ou a função copy_async, conforme mostrado no exemplo de código a seguir.

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

Você também pode copiar de uma textura para outra usando o método texture::copy_to. As duas texturas podem estar em accelerator_views diferentes. Quando você copia para um objeto writeonly_texture_view, os dados são copiados para o objeto subjacente texture. Os bits por elemento escalar e a extensão devem ser os mesmos nos objetos de origem e destino texture. Se esses requisitos não forem atendidos, o runtime gerará uma exceção.

Classes de exibição de textura

C++ AMP apresenta a Classe texture_view no Visual Studio 2013. As exibições de textura dão suporte aos mesmos tipos texel e classificações como a Classe de textura, mas ao contrário das texturas, elas fornecem acesso a recursos de hardware adicionais, como amostragem de textura e mipmaps. As exibições de textura dão suporte ao acesso somente leitura, somente gravação e leitura-gravação aos dados de textura subjacentes.

  • O acesso somente leitura é fornecido pela especialização de modelo texture_view<const T, N>, que dá suporte a elementos que têm 1, 2 ou 4 componentes, amostragem de textura e acesso dinâmico a um intervalo de níveis de mipmap que são determinados quando a exibição é instanciada.

  • O acesso somente gravação é fornecido pela classe de modelo texture_view<T, N> não especializada, que dá suporte a elementos que têm 2 ou 4 componentes e podem acessar um nível de mipmap determinado quando a exibição é instanciada. Ela não dá suporte a a amostragem.

  • O acesso somente leitura é fornecido pela classe de modelo texture_view<T, N> não especializada, que dá suporte a elementos que têm apenas um componente; a exibição pode acessar um nível de mipmap que é determinado quando ela é instanciada. Ela não dá suporte a a amostragem.

Exibições de textura são análogas às exibições de matriz, mas não fornecem a funcionalidade automática de gerenciamento de dados e movimentação que a Classe array_view fornece sobre a classe de matriz. Uma texture_view só pode ser acessada na exibição do acelerador em que residem os dados de textura subjacentes.

writeonly_texture_view preterido

Para Visual Studio 2013, C++ AMP apresenta melhor suporte para recursos de textura de hardware, como amostragem e mipmaps, que não puderam ser suportados pela Classe writeonly_texture_view. A classe texture_view recém-introduzida dá suporte a um superconjunto da funcionalidade em writeonly_texture_view; como resultado, writeonly_texture_view é preterida.

É recomendável, pelo menos para um novo código, que você use texture_view para acessar a funcionalidade fornecida anteriormente por writeonly_texture_view. Compare os dois exemplos de código a seguir que gravam em um objeto de textura que tem dois componentes (int_2). Observe que, em ambos os casos, a exibição wo_tv4 deve ser capturada por valor na expressão lambda. Este é o exemplo que usa a nova classe 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));
    });
}

E essa é a classe preterida 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));
    });
}

Como você pode ver, os dois exemplos de código são quase idênticos quando tudo o que você está fazendo é gravar no nível de mipmap primário. Se você usou writeonly_texture_view no código existente e não planeja aprimorar esse código, não precisa alterá-lo. No entanto, se você estiver pensando em levar esse código adiante, sugerimos que você o reescreva para usar texture_view porque os aprimoramentos nele dão suporte a novos recursos de textura de hardware. Continue a leitura para obter mais informações sobre esses novos recursos.

Para obter mais informações sobre o preterimento de writeonly_texture_view, consulte Visão geral do design de exibição de textura em C++ AMP no blog Programação Paralela no Código Nativo.

Instanciando objetos de exibição de textura

Declarar um texture_view é semelhante a declarar um array_view associado a uma matriz. O exemplo de código a seguir declara vários objetos texture e objetos texture_view associados a eles.

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

Observe como uma exibição de textura cujo tipo de elemento não é const e tem um componente é leitura-gravação, mas uma exibição de textura cujo tipo de elemento não é const, mas tem mais de um componenente são somente gravação. Exibições de textura de tipos de elemento const são sempre somente leitura, mas se o tipo de elemento não for const, o número de componentes no elemento determina se ele é leitura-gravação (1 componente) ou somente gravação (vários componentes).

O tipo de elemento de um texture_view, sua const-ness e também o número de componentes que ele tem, também desempenha um papel para determinar se o modo de exibição dá suporte à amostragem de textura e como os níveis de mipmap podem ser acessados:

Tipo Componentes Leitura Gravar Amostragem Acesso mipmap
texture_view<const T, N> 1, 2, 4 Sim No (1) Sim Yes, indexável O intervalo é determinado na instanciação.
Texture_view<T, N> 1

2, 4
Sim

No (2)
Sim

Sim
No (1)

No (1)
Yes, voltar um nível. O nível é determinado na instanciação.

Yes, voltar um nível. O nível é determinado na instanciação.

Nessa tabela, você pode ver que as exibições de textura somente leitura dão suporte total aos novos recursos em troca de não poderem gravar no modo de exibição. As exibições de textura graváveis são limitadas, pois só podem acessar um nível de mipmap. As exibições de textura de leitura/gravação são ainda mais especializadas do que as graváveis, pois adicionam o requisito de que o tipo de elemento da exibição de textura tenha apenas um componente. Observe que a amostragem não tem suporte para exibições de textura graváveis porque é uma operação orientada para leitura.

Lendo objetos de exibição de textura

Ler dados de textura não amostrados por meio de uma exibição de textura é como lê-los da própria textura, exceto que as texturas são capturadas por referência, enquanto as exibições de textura são capturadas por valor. Os dois exemplos de código a seguir demonstram; primeiro, usando texture apenas:

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

E esse é o mesmo exemplo, exceto que agora ele usa a classe 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));
    });
}

Exibições de textura cujos elementos se baseiam em tipos de ponto flutuante, por exemplo, float, float_2 ou float_4, também podem ser lidas usando a amostragem de textura para aproveitar o suporte de hardware para vários modos de filtragem e modos de endereçamento. C++ AMP dá suporte aos dois modos de filtragem mais comuns em cenários de computação: filtragem de ponto (vizinho mais próximo) e filtragem linear (média ponderada) e quatro modos de endereçamento, encapsulados, espelhados, fixados e borda. Para obter mais informações sobre modos de endereçamento, consulte Enumeração address_mode.

Além dos modos que C++ AMP dá suporte diretamente, você pode acessar outros modos de filtragem e modos de endereçamento da plataforma subjacente usando as APIs de interoperabilidade para adotar um sampler de textura criado usando as APIs da plataforma diretamente. Por exemplo, o Direct3D dá suporte a outros modos de filtragem, como filtragem anisotrópica, e pode aplicar um modo de endereçamento diferente a cada dimensão de uma textura. Você pode criar um sampler de textura cujas coordenadas são encapsuladas verticalmente, espelhadas horizontalmente e amostradas com filtragem anisotrópica usando as APIs Direct3D e, em seguida, aproveitar o sampler em seu código C++ AMP usando a API de interoperabilidade make_sampler. Para obter mais informações, consulte Amostragem de textura em C++ AMP no blog Programação paralela no código nativo.

Exibições de textura também dão suporte à leitura de mipmaps. Exibições de textura somente leitura (aquelas que têm um tipo de elemento const) oferecem mais flexibilidade porque um intervalo de níveis de mip que é determinado na instanciação pode ser amostrado dinamicamente e porque elementos que têm 1, 2 ou 4 componentes têm suporte. Exibições de textura de leitura/gravação que têm elementos que têm um componente também dão suporte a mipmaps, mas apenas de um nível determinado na instanciação. Para obter mais informações, consulte Textura com mipmaps no blog Programação paralela no código nativo.

Gravação em objetos de exibição de textura

Use o método texture_view::get para gravar no texture subjacente por meio do objeto texture_view. Uma exibição de textura pode ser somente leitura, leitura-gravação ou somente gravação. Para que uma exibição de textura seja gravável, ela deve ter um tipo de elemento que não seja const; para que uma exibição de textura seja legível e gravável, seu tipo de elemento também deve ter apenas um componente. Caso contrário, o modo de exibição de textura é somente leitura. Você só pode acessar um nível mipmap de uma textura por vez por meio de uma exibição de textura e o nível é especificado quando a exibição é instanciada.

Este exemplo mostra como gravar no segundo nível de mipmap mais detalhado de uma textura que tem 4 níveis de mipmap. O nível de mipmap mais detalhado é o nível 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);
});

Interoperabilidade

O runtime C++ AMP dá suporte à interoperabilidade entre texture<T,1> e a interface ID3D11Texture1D, entre texture<T,2> e a interface ID3D11Texture2D e entre texture<T,3> e a interface ID3D11Texture3D. O método get_texture usa um objeto texture e retorna uma interface IUnknown. O método make_texture usa uma interface IUnknown e um objeto accelerator_view e retorna um objeto texture.

Confira também

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