在使用纹理内存时,我遇到了以下代码: -
uint f = (blockIdx.x * blockDim.x) + threadIdx.x;
uint c = (blockIdx.y * blockDim.y) + threadIdx.y;
uint read = tex2D( refTex, c+0.5f, f+0.5f);
我的问题是为什么我们为0.5f
和c
添加f
?
这让我很困惑..
三江源
答案 0 :(得分:15)
在图形中,纹理是一组描述曲面视觉外观的样本。样本是一个点。也就是说,它没有尺寸(与具有物理尺寸的像素相反)。使用样本确定像素的颜色时,每个样本都位于其对应像素的精确中心。当使用整数坐标寻址像素时,给定像素的精确中心变为其整数坐标加上0.5的偏移(在每个维度中)。
换句话说,向纹理坐标添加0.5可确保在从这些坐标读取时,返回该像素的样本的确切值。
但是,只有当纹理的filterMode
设置为cudaFilterModeLinear
时,从纹理读取的值才会在像素内变化。在该模式中,从不在像素的精确中心的坐标读取返回在给定像素的样本和相邻像素的样本之间插值的值。因此,将0.5添加到整数坐标实际上会否定cudaFilterModeLinear
模式。但是,由于在纹理坐标中添加0.5会占用内核中的周期,因此最好通过将filterMode
设置为cudaFilterModePoint
来简单地关闭插值。然后,从像素内的任何坐标读取都会返回该像素的精确纹理样本值,因此,可以使用整数直接读取纹理样本。
使用cudaFilterModePoint
时,如果计算纹理坐标涉及任何浮点数学,必须注意确保浮点不准确不会导致纹理坐标超出预期目标的范围像素。
此外,正如评论中提到的,您的代码可能存在问题。在纹理坐标上添加0.5f意味着正在使用cudaFilterModeLinear
模式,但该模式返回一个浮点数,而不是一个int。
答案 1 :(得分:1)
根据纹理属性,tex2D
返回的值可以线性插值。在这种情况下,“索引”f
和c
不应该是整数,而应该是每个维度的限制之间的连续值。
这个例子中有点奇怪的是返回值是一个整数,无论如何都会使任何线性插值分段常数。
有关更多详细信息,请参阅“CUDA编程指南”的第3.2.10节。