10.10_三维纹理操作
10.10 三维纹理操作
从三维纹理中读取数据与从二维纹理中读取数据类似,但三维纹理有更多的限制条件。
·与二维纹理的维度 相比,三维纹理每个的维度较小,为 ;
· 三维纹理操作中没有避免复制的方法,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进行三维纹理操作。