10.10_三维纹理操作

10.10 三维纹理操作

从三维纹理中读取数据与从二维纹理中读取数据类似,但三维纹理有更多的限制条件。

·与二维纹理的维度 65536×3276865536 \times 32768 相比,三维纹理每个的维度较小,为 2048×2048×20482048 \times 2048 \times 2048

· 三维纹理操作中没有避免复制的方法,CUDA不支持设备内存上的三维纹理操作或在三维CUDA数组上的表面加载和存储操作。

除此之外,三维纹理操作基本与之前介绍的纹理操作类似。内核可以使用tex3D()指令读取三维纹理,该指令接收三个浮点参数,对应的三维CUDA数组必须使用三维内存复制操作进行数据填充。三维纹理支持三线性过滤,通过纹理坐标可读出8个纹理元素并进行插值,精度限制与一维和二维纹理操作的一样,均为9位。

三维纹理的大小限制可以通过调用cuDeviceGetAttribute()结合参数CU_DEVICE_ATTRIBUTE_TEXTURE3D_WIDTH、CU_DEVICE_ATTRIBUTE_TEXTURE3D_HEIGHT以及CU_DEVICE_ATTRIBUTE_TEXTURE3D_DEPTH进行查询,或者调用CUDAGetDevice Properties()检查CUDADeviceProp.maxTexture3D值。

由于需要的参数过多,用来创建和操作三维CUDA数组的API集与一维或二维CUDA数组的有很大不同。

函数CUDAAlloc3DArray()用来创建三维CUDA数组,其接收一个CUDAExtent结构体,而不是参数width和height。

cudaiError_t CUDAAlloc3DArray(struct CUDAArray** array, const struct CUDAChannelFormatDesc* desc, struct CUDAExtent extent, unsigned int flags _dv(0));

结构体CUDAExtent的定义如下:

structudaExtent {
    size_t width;
    size_t height;
    size_t depth;
};

三维内存复制操作非常复杂,CUDA运行时与驱动程序API均使用结构体来指定参数。运行时API使用的是CUDAMemcpy3DParams结构体,其声明如下:

structudaMemcpy3DParams {
    structudaArray *srcArray;
    structudaPos srcPos;
    structudaPitchedPtr srcPtr;
    structudaArray *dstArray;
    structudaPos dstPos;
    structudaPitchedPtr dstPtr;
    structudaExtent extent;
    enumudaMemcpyKind kind;
};

结构体中的大多数成员又是结构体,extent是包含了复制的宽度、高度和深度三个值的结构体。成员srcPos与dstPos的类型均是结构体CUDAPos,其成员分别指定了复制源和目标的起始点。

struct CUDAPos {
    size_t x;
    size_t y;
    size_t z;
};

结构体CUDAPitchedPtr是添加到三维内存复制中,并用于存储指针和步长二元组信息的。

struct CUDAPitchedPtr
{
    void *ptr; /*< Pointer to allocated memory */
    size_t pitch; /*< Pitch of allocated memory in bytes */
    size_t xsize; /*< Logical width of allocation in elements */
    size_t ysize; /*< Logical height of allocation in elements */

结构体CUDAPitchedPtr可以通过调用函数make_cudaPitchedPtr创建,该函数接受待分配内存的基指针、步长、逻辑宽度和高度。函数make_cudaPitchedPtr仅仅是将这些参数复制到输出结构体中。

structudaPitchedPtr
make_cudaPitchedPtr(void *d, size_t p, size_t xsz, size_t ysz)
{
    structudaPitchedPtr s;
    s.ptr = d;
    s.pitch = p;
    s.xsize = xsz;
    s.ysize = ysz;
    return s;
}

SDK中的样例simpleTexture3D描述了如何使用CUDA进行三维纹理操作。