Access Nearest-neighbor in Linear Texture-read Mode

You may not have noticed that, in either Cuda or OpenCL, you can perform nearest-neighbor texture lookup (like cudaFilterModePoint) on textures that are already set in linear access mode (cudaFilterModeLinear). Why not just use texture in nearest-neighbor mode? Because there are cases in one texture there are channels that should not be linear-interpolated but others are needed (in this way you can more efficiently cache the texture data). Also you don't want to do you own linear interpolation because that will reduce the performance (roughly by half).

Suppose your texture lookup code for point access mode is as follows:


float2 data = tex3D(tex, x,y,z);
id = data.x;
alpha = data.y

id is the color ID for later lookup and cannot be blended.

You want to do interpolation on first channel but not on second channel, here is the way for the texture with cudaFilterModeLinear and cudaReadModeElementType (do not normalize the coordinates) mode:

id = tex3D(tex, floor(x+.5f)+.5f, floor(y+.5f)+.5f, floor(z+.5f)+.5f).x; // nearest neighbor
alpha = tex3D(tex, x,y,z).y; // linear

The .5f in floor is for rounding into nearest integer instead of round down.
The outter .5f is to access the un-interpolated color in the device texture.
Suppose that x,y,z are not normalized

For normalized coordinates (cudaReadModeNormalizedFloat), it's more complex and I would not recommend:

id = tex3D(tex, (floor(x+.5f)+.5f)/w, (floor(y*h+.5f))+.5f)/h, (floor(z+.5f)+.5f)/d ).x; // nearest neighbor
alpha = tex3D(tex, x/w, y/h, z/d).y; // linear


Although there are more computation to perform, the performance will still be much better than doing your own interpolation. One drawback is that you lose the quality compared to if you manually interpolate the 6 neighbors colors referenced by IDs around the access point.

0 comments: