windows C++ 并行编程-C++ AMP 图形(一)

下文中的"显存"还没有找到合适的中文翻译,它的英文名称是texture, 在应用开发者来看,texture是一个名词,在物理上指的是 GPU显存中一段连续的空间。

C++ AMP 在 Concurrency::graphics 命名空间中包含一些 API,可以用来访问 GPU 上的显存支持。 一些常见的情况有:

你可以使用 texture 类作为计算的数据容器,并利用显存缓存的“空间局部性”以及 GPU 硬件的布局。 空间局部性是相距较近的数据元素的属性。

运行时可以实现与非计算着色器的高效互操作。 像素、顶点、分割和外壳着色器经常使用或生成一些可在你的 C++ AMP 计算中使用的显存。

C++ AMP 中的图形 API 提供访问子字已打包缓冲区的替代方法。 一些显存的格式代表由 8 位或 16 位标量组成的“显存”(显存元素),使用这些显存可以访问此类已打包数据存储。

orm 和 unorm 类型

norm 和 unorm 类型是用于限制 float 值范围的标量类型;这称为“钳位”。 这些类型可从其他标量类型显式构造。 在强制转换时,值首先转换为 float,然后限制到 norm [-1.0, 1.0] 或 unorm [0.0, 1.0] 所允许的各自区域。 从 +/- 无穷强制转换时将返回 +/-1。 未定义从 NaN 的强制转换。 可以从 unorm 隐式构造 norm,而且不会丢失数据。 这些类型已定义到 float 的隐式转换运算符。 这些类型与其他内置标量类型(如 float 和 int)已定义二元运算符:+、-、*、/、==、!=、>、<、>=、<=。 此外还支持复合赋值运算符:+=、-=、*=、/=。 norm 类型已定义一元求反运算符 (-)。

短矢量库

短矢量库提供一些在 HLSL 中定义的矢量类型功能,通常用于定义纹素。 短矢量是一种可保留 1-4 个相同类型值的数据结构。 支持的类型包括 double、float、int、norm、uint 和 unorm。 下表中显示了这些类型名称。 对于每种类型,同时有一个名称中不含下划线的对应 typedef。 具有下划线的类型位于 Concurrency::graphics 命名空间 内。 没有下划线的类型位于 Concurrency::graphics::direct3d 命名空间 内,以便与命名方式类似的基础类型(如 __int8 和 __int16)明确区分。

运算符

如果在两个短矢量之间定义一个运算符,则也会在短矢量和标量之间定义此运算符。 此外,必须符合以下条件之一:

  • 标量的类型必须与短矢量的元素类型相同。

  • 通过使用用户定义的转换,可将标量的类型隐式转换为矢量的元素类型。

运算是在短矢量和标量的每个组件之间进行的组件级运算。 以下一些有效的运算符:

Swizzling 表达式

短矢量库支持 vector_type.identifier 访问器构造来访问短矢量的组件。 identifier(称为“swizzling 表达式”)用于指定矢量的组件。 此表达式可以是左值或右值。 标识符中的各个字符可能是:x、y、z 和 w;或 r、g、b 和 a。 “x”和“r”表示第零个组件,“y”和“g”表示第一个组件,以此类推。 (请注意,“x”和“r”不能在同一标识符中使用。)因此,“rgba”和“xyzw”将返回相同的结果。 诸如“x”和“y”等单组件访问器属于标量值类型。 多组件访问器属于短矢量类型。 例如,如果构造一个名为 int_4 且值为 2、4、6、8 的 fourInts 矢量,则 fourInts.y 将返回整数 4,而 fourInts.rg 将返回一个值为 2、4 的 int_2 对象。

显存类

许多 GPU 具有已进行优化的硬件和缓存,适用于获取像素和纹素以及呈现图像和显存。 texture<T,N> 类是纹素对象的容器类,用于公开这些 GPU 的显存功能。 纹素可以是:

int、uint、float、double、norm 或 unorm 标量。

具有两个或四个组件的短矢量。 唯一的例外是 double_4,不允许使用此短矢量。

texture 对象的秩可以是 1、2 或 3。 在 texture 调用的 lambda 中,parallel_for_each 对象只能通过引用来捕获。 显存存储作为 Direct3D 显存对象存储在 GPU 中。 有关 Direct3D 中显存和纹素的更多信息,请参阅 Direct3D 11 中的显存简介。

你所使用的纹素类型可以是图形编程中使用的众多显存格式中的一种。 例如,RGBA 格式可以使用 32 位,其中,R、G、B 和 A 标量元素各 8 位。 图形卡的显存硬件可以访问基于格式的各个元素。 例如,如果你使用的是 RGBA 格式,则显存硬件可以提取每个 8 位组件形成 32 位窗体。 在 C++ AMP 中,你可以设置每个显存标量元素的位数,以便自动访问代码中的各个标量元素,而不必进行移位。

实例化显存对象

你可以声明显存对象而不初始化。 下面的代码示例声明了多个显存对象。

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

你还可以使用构造函数来声明和初始化 texture 对象。 下面的代码示例从 texture 对象的一个矢量实例化了一个 float_4 对象。 每个标量元素的位数设置为默认值。 你不能将此构造函数用于 norm、unorm 或 norm 及 unorm 的短矢量,因为它们的每标量元素位数不是默认值。

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

通过使用指针指向源数据、源数据的字节大小和每标量元素位数的构造函数重载,你可以声明和初始化 texture 对象。

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

 这些示例中的显存是在默认快捷键的默认视图中创建的。 如果要指定 accelerator_view 对象,则可以使用构造函数的其他重载。 你不能在 CPU 快捷键上创建显存对象。

如下表所示,texture 对象的每个维度具有大小限制。 如果超出限制,就会产生运行时错误。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值