mirror of
https://github.com/NVIDIA/cuda-samples.git
synced 2026-10-25 22:28:17 +08:00
Apply consistent code formatting across the repo. Add clang-format and pre-commit hooks.
This commit is contained in:
@@ -34,4 +34,3 @@ Download and install the [CUDA Toolkit 12.5](https://developer.nvidia.com/cuda-d
|
||||
Make sure the dependencies mentioned in [Dependencies]() section above are installed.
|
||||
|
||||
## References (for more details)
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -28,101 +28,107 @@
|
||||
#ifndef _BICUBICTEXTURE_CU_
|
||||
#define _BICUBICTEXTURE_CU_
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <helper_math.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
// includes, cuda
|
||||
#include <helper_cuda.h>
|
||||
|
||||
typedef unsigned int uint;
|
||||
typedef unsigned int uint;
|
||||
typedef unsigned char uchar;
|
||||
|
||||
#include "bicubicTexture_kernel.cuh"
|
||||
|
||||
cudaArray *d_imageArray = 0;
|
||||
|
||||
extern "C" void initTexture(int imageWidth, int imageHeight, uchar *h_data) {
|
||||
// allocate array and copy image data
|
||||
cudaChannelFormatDesc channelDesc =
|
||||
cudaCreateChannelDesc(8, 0, 0, 0, cudaChannelFormatKindUnsigned);
|
||||
checkCudaErrors(
|
||||
cudaMallocArray(&d_imageArray, &channelDesc, imageWidth, imageHeight));
|
||||
checkCudaErrors(cudaMemcpy2DToArray(
|
||||
d_imageArray, 0, 0, h_data, imageWidth * sizeof(uchar),
|
||||
imageWidth * sizeof(uchar), imageHeight, cudaMemcpyHostToDevice));
|
||||
free(h_data);
|
||||
extern "C" void initTexture(int imageWidth, int imageHeight, uchar *h_data)
|
||||
{
|
||||
// allocate array and copy image data
|
||||
cudaChannelFormatDesc channelDesc = cudaCreateChannelDesc(8, 0, 0, 0, cudaChannelFormatKindUnsigned);
|
||||
checkCudaErrors(cudaMallocArray(&d_imageArray, &channelDesc, imageWidth, imageHeight));
|
||||
checkCudaErrors(cudaMemcpy2DToArray(d_imageArray,
|
||||
0,
|
||||
0,
|
||||
h_data,
|
||||
imageWidth * sizeof(uchar),
|
||||
imageWidth * sizeof(uchar),
|
||||
imageHeight,
|
||||
cudaMemcpyHostToDevice));
|
||||
free(h_data);
|
||||
|
||||
cudaResourceDesc texRes;
|
||||
memset(&texRes, 0, sizeof(cudaResourceDesc));
|
||||
cudaResourceDesc texRes;
|
||||
memset(&texRes, 0, sizeof(cudaResourceDesc));
|
||||
|
||||
texRes.resType = cudaResourceTypeArray;
|
||||
texRes.res.array.array = d_imageArray;
|
||||
texRes.resType = cudaResourceTypeArray;
|
||||
texRes.res.array.array = d_imageArray;
|
||||
|
||||
cudaTextureDesc texDescr;
|
||||
memset(&texDescr, 0, sizeof(cudaTextureDesc));
|
||||
cudaTextureDesc texDescr;
|
||||
memset(&texDescr, 0, sizeof(cudaTextureDesc));
|
||||
|
||||
texDescr.normalizedCoords = false;
|
||||
texDescr.filterMode = cudaFilterModeLinear;
|
||||
texDescr.addressMode[0] = cudaAddressModeClamp;
|
||||
texDescr.addressMode[1] = cudaAddressModeClamp;
|
||||
texDescr.readMode = cudaReadModeNormalizedFloat;
|
||||
texDescr.normalizedCoords = false;
|
||||
texDescr.filterMode = cudaFilterModeLinear;
|
||||
texDescr.addressMode[0] = cudaAddressModeClamp;
|
||||
texDescr.addressMode[1] = cudaAddressModeClamp;
|
||||
texDescr.readMode = cudaReadModeNormalizedFloat;
|
||||
|
||||
checkCudaErrors(
|
||||
cudaCreateTextureObject(&texObjLinear, &texRes, &texDescr, NULL));
|
||||
checkCudaErrors(cudaCreateTextureObject(&texObjLinear, &texRes, &texDescr, NULL));
|
||||
|
||||
memset(&texDescr, 0, sizeof(cudaTextureDesc));
|
||||
texDescr.normalizedCoords = false;
|
||||
texDescr.filterMode = cudaFilterModePoint;
|
||||
texDescr.addressMode[0] = cudaAddressModeClamp;
|
||||
texDescr.addressMode[1] = cudaAddressModeClamp;
|
||||
texDescr.readMode = cudaReadModeNormalizedFloat;
|
||||
memset(&texDescr, 0, sizeof(cudaTextureDesc));
|
||||
texDescr.normalizedCoords = false;
|
||||
texDescr.filterMode = cudaFilterModePoint;
|
||||
texDescr.addressMode[0] = cudaAddressModeClamp;
|
||||
texDescr.addressMode[1] = cudaAddressModeClamp;
|
||||
texDescr.readMode = cudaReadModeNormalizedFloat;
|
||||
|
||||
checkCudaErrors(
|
||||
cudaCreateTextureObject(&texObjPoint, &texRes, &texDescr, NULL));
|
||||
checkCudaErrors(cudaCreateTextureObject(&texObjPoint, &texRes, &texDescr, NULL));
|
||||
}
|
||||
|
||||
extern "C" void freeTexture() {
|
||||
checkCudaErrors(cudaDestroyTextureObject(texObjPoint));
|
||||
checkCudaErrors(cudaDestroyTextureObject(texObjLinear));
|
||||
checkCudaErrors(cudaFreeArray(d_imageArray));
|
||||
extern "C" void freeTexture()
|
||||
{
|
||||
checkCudaErrors(cudaDestroyTextureObject(texObjPoint));
|
||||
checkCudaErrors(cudaDestroyTextureObject(texObjLinear));
|
||||
checkCudaErrors(cudaFreeArray(d_imageArray));
|
||||
}
|
||||
|
||||
// render image using CUDA
|
||||
extern "C" void render(int width, int height, float tx, float ty, float scale,
|
||||
float cx, float cy, dim3 blockSize, dim3 gridSize,
|
||||
int filter_mode, uchar4 *output) {
|
||||
// call CUDA kernel, writing results to PBO memory
|
||||
switch (filter_mode) {
|
||||
extern "C" void render(int width,
|
||||
int height,
|
||||
float tx,
|
||||
float ty,
|
||||
float scale,
|
||||
float cx,
|
||||
float cy,
|
||||
dim3 blockSize,
|
||||
dim3 gridSize,
|
||||
int filter_mode,
|
||||
uchar4 *output)
|
||||
{
|
||||
// call CUDA kernel, writing results to PBO memory
|
||||
switch (filter_mode) {
|
||||
case MODE_NEAREST:
|
||||
d_render<<<gridSize, blockSize>>>(output, width, height, tx, ty, scale,
|
||||
cx, cy, texObjPoint);
|
||||
break;
|
||||
d_render<<<gridSize, blockSize>>>(output, width, height, tx, ty, scale, cx, cy, texObjPoint);
|
||||
break;
|
||||
|
||||
case MODE_BILINEAR:
|
||||
d_render<<<gridSize, blockSize>>>(output, width, height, tx, ty, scale,
|
||||
cx, cy, texObjLinear);
|
||||
break;
|
||||
d_render<<<gridSize, blockSize>>>(output, width, height, tx, ty, scale, cx, cy, texObjLinear);
|
||||
break;
|
||||
|
||||
case MODE_BICUBIC:
|
||||
d_renderBicubic<<<gridSize, blockSize>>>(output, width, height, tx, ty,
|
||||
scale, cx, cy, texObjPoint);
|
||||
break;
|
||||
d_renderBicubic<<<gridSize, blockSize>>>(output, width, height, tx, ty, scale, cx, cy, texObjPoint);
|
||||
break;
|
||||
|
||||
case MODE_FAST_BICUBIC:
|
||||
d_renderFastBicubic<<<gridSize, blockSize>>>(
|
||||
output, width, height, tx, ty, scale, cx, cy, texObjLinear);
|
||||
break;
|
||||
d_renderFastBicubic<<<gridSize, blockSize>>>(output, width, height, tx, ty, scale, cx, cy, texObjLinear);
|
||||
break;
|
||||
|
||||
case MODE_CATROM:
|
||||
d_renderCatRom<<<gridSize, blockSize>>>(output, width, height, tx, ty,
|
||||
scale, cx, cy, texObjPoint);
|
||||
break;
|
||||
}
|
||||
d_renderCatRom<<<gridSize, blockSize>>>(output, width, height, tx, ty, scale, cx, cy, texObjPoint);
|
||||
break;
|
||||
}
|
||||
|
||||
getLastCudaError("kernel failed");
|
||||
getLastCudaError("kernel failed");
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -36,30 +36,27 @@
|
||||
#ifndef _BICUBICTEXTURE_KERNEL_CUH_
|
||||
#define _BICUBICTEXTURE_KERNEL_CUH_
|
||||
|
||||
enum Mode {
|
||||
MODE_NEAREST,
|
||||
MODE_BILINEAR,
|
||||
MODE_BICUBIC,
|
||||
MODE_FAST_BICUBIC,
|
||||
MODE_CATROM
|
||||
};
|
||||
enum Mode { MODE_NEAREST, MODE_BILINEAR, MODE_BICUBIC, MODE_FAST_BICUBIC, MODE_CATROM };
|
||||
|
||||
cudaTextureObject_t texObjPoint, texObjLinear;
|
||||
|
||||
// w0, w1, w2, and w3 are the four cubic B-spline basis functions
|
||||
__host__ __device__ float w0(float a) {
|
||||
// return (1.0f/6.0f)*(-a*a*a + 3.0f*a*a - 3.0f*a + 1.0f);
|
||||
return (1.0f / 6.0f) * (a * (a * (-a + 3.0f) - 3.0f) + 1.0f); // optimized
|
||||
__host__ __device__ float w0(float a)
|
||||
{
|
||||
// return (1.0f/6.0f)*(-a*a*a + 3.0f*a*a - 3.0f*a + 1.0f);
|
||||
return (1.0f / 6.0f) * (a * (a * (-a + 3.0f) - 3.0f) + 1.0f); // optimized
|
||||
}
|
||||
|
||||
__host__ __device__ float w1(float a) {
|
||||
// return (1.0f/6.0f)*(3.0f*a*a*a - 6.0f*a*a + 4.0f);
|
||||
return (1.0f / 6.0f) * (a * a * (3.0f * a - 6.0f) + 4.0f);
|
||||
__host__ __device__ float w1(float a)
|
||||
{
|
||||
// return (1.0f/6.0f)*(3.0f*a*a*a - 6.0f*a*a + 4.0f);
|
||||
return (1.0f / 6.0f) * (a * a * (3.0f * a - 6.0f) + 4.0f);
|
||||
}
|
||||
|
||||
__host__ __device__ float w2(float a) {
|
||||
// return (1.0f/6.0f)*(-3.0f*a*a*a + 3.0f*a*a + 3.0f*a + 1.0f);
|
||||
return (1.0f / 6.0f) * (a * (a * (-3.0f * a + 3.0f) + 3.0f) + 1.0f);
|
||||
__host__ __device__ float w2(float a)
|
||||
{
|
||||
// return (1.0f/6.0f)*(-3.0f*a*a*a + 3.0f*a*a + 3.0f*a + 1.0f);
|
||||
return (1.0f / 6.0f) * (a * (a * (-3.0f * a + 3.0f) + 3.0f) + 1.0f);
|
||||
}
|
||||
|
||||
__host__ __device__ float w3(float a) { return (1.0f / 6.0f) * (a * a * a); }
|
||||
@@ -70,91 +67,99 @@ __device__ float g0(float a) { return w0(a) + w1(a); }
|
||||
__device__ float g1(float a) { return w2(a) + w3(a); }
|
||||
|
||||
// h0 and h1 are the two offset functions
|
||||
__device__ float h0(float a) {
|
||||
// note +0.5 offset to compensate for CUDA linear filtering convention
|
||||
return -1.0f + w1(a) / (w0(a) + w1(a)) + 0.5f;
|
||||
__device__ float h0(float a)
|
||||
{
|
||||
// note +0.5 offset to compensate for CUDA linear filtering convention
|
||||
return -1.0f + w1(a) / (w0(a) + w1(a)) + 0.5f;
|
||||
}
|
||||
|
||||
__device__ float h1(float a) { return 1.0f + w3(a) / (w2(a) + w3(a)) + 0.5f; }
|
||||
|
||||
// filter 4 values using cubic splines
|
||||
template <class T>
|
||||
__device__ T cubicFilter(float x, T c0, T c1, T c2, T c3) {
|
||||
T r;
|
||||
r = c0 * w0(x);
|
||||
r += c1 * w1(x);
|
||||
r += c2 * w2(x);
|
||||
r += c3 * w3(x);
|
||||
return r;
|
||||
template <class T> __device__ T cubicFilter(float x, T c0, T c1, T c2, T c3)
|
||||
{
|
||||
T r;
|
||||
r = c0 * w0(x);
|
||||
r += c1 * w1(x);
|
||||
r += c2 * w2(x);
|
||||
r += c3 * w3(x);
|
||||
return r;
|
||||
}
|
||||
|
||||
// slow but precise bicubic lookup using 16 texture lookups
|
||||
template <class T, class R> // texture data type, return type
|
||||
__device__ R tex2DBicubic(const cudaTextureObject_t tex, float x, float y) {
|
||||
x -= 0.5f;
|
||||
y -= 0.5f;
|
||||
float px = floorf(x);
|
||||
float py = floorf(y);
|
||||
float fx = x - px;
|
||||
float fy = y - py;
|
||||
template <class T, class R> // texture data type, return type
|
||||
__device__ R tex2DBicubic(const cudaTextureObject_t tex, float x, float y)
|
||||
{
|
||||
x -= 0.5f;
|
||||
y -= 0.5f;
|
||||
float px = floorf(x);
|
||||
float py = floorf(y);
|
||||
float fx = x - px;
|
||||
float fy = y - py;
|
||||
|
||||
return cubicFilter<R>(
|
||||
fy, cubicFilter<R>(
|
||||
fx, tex2D<R>(tex, px - 1, py - 1), tex2D<R>(tex, px, py - 1),
|
||||
tex2D<R>(tex, px + 1, py - 1), tex2D<R>(tex, px + 2, py - 1)),
|
||||
cubicFilter<R>(fx, tex2D<R>(tex, px - 1, py), tex2D<R>(tex, px, py),
|
||||
tex2D<R>(tex, px + 1, py), tex2D<R>(tex, px + 2, py)),
|
||||
cubicFilter<R>(fx, tex2D<R>(tex, px - 1, py + 1),
|
||||
tex2D<R>(tex, px, py + 1), tex2D<R>(tex, px + 1, py + 1),
|
||||
tex2D<R>(tex, px + 2, py + 1)),
|
||||
cubicFilter<R>(fx, tex2D<R>(tex, px - 1, py + 2),
|
||||
tex2D<R>(tex, px, py + 2), tex2D<R>(tex, px + 1, py + 2),
|
||||
tex2D<R>(tex, px + 2, py + 2)));
|
||||
return cubicFilter<R>(
|
||||
fy,
|
||||
cubicFilter<R>(fx,
|
||||
tex2D<R>(tex, px - 1, py - 1),
|
||||
tex2D<R>(tex, px, py - 1),
|
||||
tex2D<R>(tex, px + 1, py - 1),
|
||||
tex2D<R>(tex, px + 2, py - 1)),
|
||||
cubicFilter<R>(
|
||||
fx, tex2D<R>(tex, px - 1, py), tex2D<R>(tex, px, py), tex2D<R>(tex, px + 1, py), tex2D<R>(tex, px + 2, py)),
|
||||
cubicFilter<R>(fx,
|
||||
tex2D<R>(tex, px - 1, py + 1),
|
||||
tex2D<R>(tex, px, py + 1),
|
||||
tex2D<R>(tex, px + 1, py + 1),
|
||||
tex2D<R>(tex, px + 2, py + 1)),
|
||||
cubicFilter<R>(fx,
|
||||
tex2D<R>(tex, px - 1, py + 2),
|
||||
tex2D<R>(tex, px, py + 2),
|
||||
tex2D<R>(tex, px + 1, py + 2),
|
||||
tex2D<R>(tex, px + 2, py + 2)));
|
||||
}
|
||||
|
||||
// fast bicubic texture lookup using 4 bilinear lookups
|
||||
// assumes texture is set to non-normalized coordinates, point sampling
|
||||
template <class T, class R> // texture data type, return type
|
||||
__device__ R tex2DFastBicubic(const cudaTextureObject_t tex, float x, float y) {
|
||||
x -= 0.5f;
|
||||
y -= 0.5f;
|
||||
float px = floorf(x);
|
||||
float py = floorf(y);
|
||||
float fx = x - px;
|
||||
float fy = y - py;
|
||||
template <class T, class R> // texture data type, return type
|
||||
__device__ R tex2DFastBicubic(const cudaTextureObject_t tex, float x, float y)
|
||||
{
|
||||
x -= 0.5f;
|
||||
y -= 0.5f;
|
||||
float px = floorf(x);
|
||||
float py = floorf(y);
|
||||
float fx = x - px;
|
||||
float fy = y - py;
|
||||
|
||||
// note: we could store these functions in a lookup table texture, but maths
|
||||
// is cheap
|
||||
float g0x = g0(fx);
|
||||
float g1x = g1(fx);
|
||||
float h0x = h0(fx);
|
||||
float h1x = h1(fx);
|
||||
float h0y = h0(fy);
|
||||
float h1y = h1(fy);
|
||||
// note: we could store these functions in a lookup table texture, but maths
|
||||
// is cheap
|
||||
float g0x = g0(fx);
|
||||
float g1x = g1(fx);
|
||||
float h0x = h0(fx);
|
||||
float h1x = h1(fx);
|
||||
float h0y = h0(fy);
|
||||
float h1y = h1(fy);
|
||||
|
||||
R r = g0(fy) * (g0x * tex2D<R>(tex, px + h0x, py + h0y) +
|
||||
g1x * tex2D<R>(tex, px + h1x, py + h0y)) +
|
||||
g1(fy) * (g0x * tex2D<R>(tex, px + h0x, py + h1y) +
|
||||
g1x * tex2D<R>(tex, px + h1x, py + h1y));
|
||||
return r;
|
||||
R r = g0(fy) * (g0x * tex2D<R>(tex, px + h0x, py + h0y) + g1x * tex2D<R>(tex, px + h1x, py + h0y))
|
||||
+ g1(fy) * (g0x * tex2D<R>(tex, px + h0x, py + h1y) + g1x * tex2D<R>(tex, px + h1x, py + h1y));
|
||||
return r;
|
||||
}
|
||||
|
||||
// higher-precision 2D bilinear lookup
|
||||
template <class T, class R> // texture data type, return type
|
||||
__device__ R tex2DBilinear(const cudaTextureObject_t tex, float x, float y) {
|
||||
x -= 0.5f;
|
||||
y -= 0.5f;
|
||||
float px = floorf(x); // integer position
|
||||
float py = floorf(y);
|
||||
float fx = x - px; // fractional position
|
||||
float fy = y - py;
|
||||
px += 0.5f;
|
||||
py += 0.5f;
|
||||
template <class T, class R> // texture data type, return type
|
||||
__device__ R tex2DBilinear(const cudaTextureObject_t tex, float x, float y)
|
||||
{
|
||||
x -= 0.5f;
|
||||
y -= 0.5f;
|
||||
float px = floorf(x); // integer position
|
||||
float py = floorf(y);
|
||||
float fx = x - px; // fractional position
|
||||
float fy = y - py;
|
||||
px += 0.5f;
|
||||
py += 0.5f;
|
||||
|
||||
return lerp(lerp(tex2D<R>(tex, px, py), tex2D<R>(tex, px + 1.0f, py), fx),
|
||||
lerp(tex2D<R>(tex, px, py + 1.0f),
|
||||
tex2D<R>(tex, px + 1.0f, py + 1.0f), fx),
|
||||
fy);
|
||||
return lerp(lerp(tex2D<R>(tex, px, py), tex2D<R>(tex, px + 1.0f, py), fx),
|
||||
lerp(tex2D<R>(tex, px, py + 1.0f), tex2D<R>(tex, px + 1.0f, py + 1.0f), fx),
|
||||
fy);
|
||||
}
|
||||
|
||||
#if !defined(__CUDA_ARCH__) || __CUDA_ARCH__ >= 200
|
||||
@@ -174,154 +179,193 @@ __device__ R tex2DBilinear(const cudaTextureObject_t tex, float x, float y) {
|
||||
w: (0, 0)
|
||||
*/
|
||||
|
||||
template <class T, class R> // texture data type, return type
|
||||
__device__ float tex2DBilinearGather(const cudaTextureObject_t tex, float x,
|
||||
float y, int comp = 0) {
|
||||
x -= 0.5f;
|
||||
y -= 0.5f;
|
||||
float px = floorf(x); // integer position
|
||||
float py = floorf(y);
|
||||
float fx = x - px; // fractional position
|
||||
float fy = y - py;
|
||||
template <class T, class R> // texture data type, return type
|
||||
__device__ float tex2DBilinearGather(const cudaTextureObject_t tex, float x, float y, int comp = 0)
|
||||
{
|
||||
x -= 0.5f;
|
||||
y -= 0.5f;
|
||||
float px = floorf(x); // integer position
|
||||
float py = floorf(y);
|
||||
float fx = x - px; // fractional position
|
||||
float fy = y - py;
|
||||
|
||||
R samples = tex2Dgather<R>(tex, px + 0.5f, py + 0.5f, comp);
|
||||
R samples = tex2Dgather<R>(tex, px + 0.5f, py + 0.5f, comp);
|
||||
|
||||
return lerp(lerp((float)samples.w, (float)samples.z, fx),
|
||||
lerp((float)samples.x, (float)samples.y, fx), fy);
|
||||
return lerp(lerp((float)samples.w, (float)samples.z, fx), lerp((float)samples.x, (float)samples.y, fx), fy);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// Catmull-Rom interpolation
|
||||
|
||||
__host__ __device__ float catrom_w0(float a) {
|
||||
// return -0.5f*a + a*a - 0.5f*a*a*a;
|
||||
return a * (-0.5f + a * (1.0f - 0.5f * a));
|
||||
__host__ __device__ float catrom_w0(float a)
|
||||
{
|
||||
// return -0.5f*a + a*a - 0.5f*a*a*a;
|
||||
return a * (-0.5f + a * (1.0f - 0.5f * a));
|
||||
}
|
||||
|
||||
__host__ __device__ float catrom_w1(float a) {
|
||||
// return 1.0f - 2.5f*a*a + 1.5f*a*a*a;
|
||||
return 1.0f + a * a * (-2.5f + 1.5f * a);
|
||||
__host__ __device__ float catrom_w1(float a)
|
||||
{
|
||||
// return 1.0f - 2.5f*a*a + 1.5f*a*a*a;
|
||||
return 1.0f + a * a * (-2.5f + 1.5f * a);
|
||||
}
|
||||
|
||||
__host__ __device__ float catrom_w2(float a) {
|
||||
// return 0.5f*a + 2.0f*a*a - 1.5f*a*a*a;
|
||||
return a * (0.5f + a * (2.0f - 1.5f * a));
|
||||
__host__ __device__ float catrom_w2(float a)
|
||||
{
|
||||
// return 0.5f*a + 2.0f*a*a - 1.5f*a*a*a;
|
||||
return a * (0.5f + a * (2.0f - 1.5f * a));
|
||||
}
|
||||
|
||||
__host__ __device__ float catrom_w3(float a) {
|
||||
// return -0.5f*a*a + 0.5f*a*a*a;
|
||||
return a * a * (-0.5f + 0.5f * a);
|
||||
__host__ __device__ float catrom_w3(float a)
|
||||
{
|
||||
// return -0.5f*a*a + 0.5f*a*a*a;
|
||||
return a * a * (-0.5f + 0.5f * a);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
__device__ T catRomFilter(float x, T c0, T c1, T c2, T c3) {
|
||||
T r;
|
||||
r = c0 * catrom_w0(x);
|
||||
r += c1 * catrom_w1(x);
|
||||
r += c2 * catrom_w2(x);
|
||||
r += c3 * catrom_w3(x);
|
||||
return r;
|
||||
template <class T> __device__ T catRomFilter(float x, T c0, T c1, T c2, T c3)
|
||||
{
|
||||
T r;
|
||||
r = c0 * catrom_w0(x);
|
||||
r += c1 * catrom_w1(x);
|
||||
r += c2 * catrom_w2(x);
|
||||
r += c3 * catrom_w3(x);
|
||||
return r;
|
||||
}
|
||||
|
||||
// Note - can't use bilinear trick here because of negative lobes
|
||||
template <class T, class R> // texture data type, return type
|
||||
__device__ R tex2DCatRom(const cudaTextureObject_t tex, float x, float y) {
|
||||
x -= 0.5f;
|
||||
y -= 0.5f;
|
||||
float px = floorf(x);
|
||||
float py = floorf(y);
|
||||
float fx = x - px;
|
||||
float fy = y - py;
|
||||
template <class T, class R> // texture data type, return type
|
||||
__device__ R tex2DCatRom(const cudaTextureObject_t tex, float x, float y)
|
||||
{
|
||||
x -= 0.5f;
|
||||
y -= 0.5f;
|
||||
float px = floorf(x);
|
||||
float py = floorf(y);
|
||||
float fx = x - px;
|
||||
float fy = y - py;
|
||||
|
||||
return catRomFilter<R>(
|
||||
fy, catRomFilter<R>(
|
||||
fx, tex2D<R>(tex, px - 1, py - 1), tex2D<R>(tex, px, py - 1),
|
||||
tex2D<R>(tex, px + 1, py - 1), tex2D<R>(tex, px + 2, py - 1)),
|
||||
catRomFilter<R>(fx, tex2D<R>(tex, px - 1, py), tex2D<R>(tex, px, py),
|
||||
tex2D<R>(tex, px + 1, py), tex2D<R>(tex, px + 2, py)),
|
||||
catRomFilter<R>(fx, tex2D<R>(tex, px - 1, py + 1),
|
||||
tex2D<R>(tex, px, py + 1), tex2D<R>(tex, px + 1, py + 1),
|
||||
tex2D<R>(tex, px + 2, py + 1)),
|
||||
catRomFilter<R>(fx, tex2D<R>(tex, px - 1, py + 2),
|
||||
tex2D<R>(tex, px, py + 2), tex2D<R>(tex, px + 1, py + 2),
|
||||
tex2D<R>(tex, px + 2, py + 2)));
|
||||
return catRomFilter<R>(
|
||||
fy,
|
||||
catRomFilter<R>(fx,
|
||||
tex2D<R>(tex, px - 1, py - 1),
|
||||
tex2D<R>(tex, px, py - 1),
|
||||
tex2D<R>(tex, px + 1, py - 1),
|
||||
tex2D<R>(tex, px + 2, py - 1)),
|
||||
catRomFilter<R>(
|
||||
fx, tex2D<R>(tex, px - 1, py), tex2D<R>(tex, px, py), tex2D<R>(tex, px + 1, py), tex2D<R>(tex, px + 2, py)),
|
||||
catRomFilter<R>(fx,
|
||||
tex2D<R>(tex, px - 1, py + 1),
|
||||
tex2D<R>(tex, px, py + 1),
|
||||
tex2D<R>(tex, px + 1, py + 1),
|
||||
tex2D<R>(tex, px + 2, py + 1)),
|
||||
catRomFilter<R>(fx,
|
||||
tex2D<R>(tex, px - 1, py + 2),
|
||||
tex2D<R>(tex, px, py + 2),
|
||||
tex2D<R>(tex, px + 1, py + 2),
|
||||
tex2D<R>(tex, px + 2, py + 2)));
|
||||
}
|
||||
|
||||
// test functions
|
||||
|
||||
// render image using normal bilinear texture lookup
|
||||
__global__ void d_render(uchar4 *d_output, uint width, uint height, float tx,
|
||||
float ty, float scale, float cx, float cy,
|
||||
cudaTextureObject_t texObj) {
|
||||
uint x = __umul24(blockIdx.x, blockDim.x) + threadIdx.x;
|
||||
uint y = __umul24(blockIdx.y, blockDim.y) + threadIdx.y;
|
||||
uint i = __umul24(y, width) + x;
|
||||
__global__ void d_render(uchar4 *d_output,
|
||||
uint width,
|
||||
uint height,
|
||||
float tx,
|
||||
float ty,
|
||||
float scale,
|
||||
float cx,
|
||||
float cy,
|
||||
cudaTextureObject_t texObj)
|
||||
{
|
||||
uint x = __umul24(blockIdx.x, blockDim.x) + threadIdx.x;
|
||||
uint y = __umul24(blockIdx.y, blockDim.y) + threadIdx.y;
|
||||
uint i = __umul24(y, width) + x;
|
||||
|
||||
float u = (x - cx) * scale + cx + tx;
|
||||
float v = (y - cy) * scale + cy + ty;
|
||||
float u = (x - cx) * scale + cx + tx;
|
||||
float v = (y - cy) * scale + cy + ty;
|
||||
|
||||
if ((x < width) && (y < height)) {
|
||||
// write output color
|
||||
float c = tex2D<float>(texObj, u, v);
|
||||
// float c = tex2DBilinear<uchar, float>(tex, u, v);
|
||||
// float c = tex2DBilinearGather<uchar, uchar4>(tex2, u, v, 0) / 255.0f;
|
||||
d_output[i] = make_uchar4(c * 0xff, c * 0xff, c * 0xff, 0);
|
||||
}
|
||||
if ((x < width) && (y < height)) {
|
||||
// write output color
|
||||
float c = tex2D<float>(texObj, u, v);
|
||||
// float c = tex2DBilinear<uchar, float>(tex, u, v);
|
||||
// float c = tex2DBilinearGather<uchar, uchar4>(tex2, u, v, 0) / 255.0f;
|
||||
d_output[i] = make_uchar4(c * 0xff, c * 0xff, c * 0xff, 0);
|
||||
}
|
||||
}
|
||||
|
||||
// render image using bicubic texture lookup
|
||||
__global__ void d_renderBicubic(uchar4 *d_output, uint width, uint height,
|
||||
float tx, float ty, float scale, float cx,
|
||||
float cy, cudaTextureObject_t texObj) {
|
||||
uint x = __umul24(blockIdx.x, blockDim.x) + threadIdx.x;
|
||||
uint y = __umul24(blockIdx.y, blockDim.y) + threadIdx.y;
|
||||
uint i = __umul24(y, width) + x;
|
||||
__global__ void d_renderBicubic(uchar4 *d_output,
|
||||
uint width,
|
||||
uint height,
|
||||
float tx,
|
||||
float ty,
|
||||
float scale,
|
||||
float cx,
|
||||
float cy,
|
||||
cudaTextureObject_t texObj)
|
||||
{
|
||||
uint x = __umul24(blockIdx.x, blockDim.x) + threadIdx.x;
|
||||
uint y = __umul24(blockIdx.y, blockDim.y) + threadIdx.y;
|
||||
uint i = __umul24(y, width) + x;
|
||||
|
||||
float u = (x - cx) * scale + cx + tx;
|
||||
float v = (y - cy) * scale + cy + ty;
|
||||
float u = (x - cx) * scale + cx + tx;
|
||||
float v = (y - cy) * scale + cy + ty;
|
||||
|
||||
if ((x < width) && (y < height)) {
|
||||
// write output color
|
||||
float c = tex2DBicubic<uchar, float>(texObj, u, v);
|
||||
d_output[i] = make_uchar4(c * 0xff, c * 0xff, c * 0xff, 0);
|
||||
}
|
||||
if ((x < width) && (y < height)) {
|
||||
// write output color
|
||||
float c = tex2DBicubic<uchar, float>(texObj, u, v);
|
||||
d_output[i] = make_uchar4(c * 0xff, c * 0xff, c * 0xff, 0);
|
||||
}
|
||||
}
|
||||
|
||||
// render image using fast bicubic texture lookup
|
||||
__global__ void d_renderFastBicubic(uchar4 *d_output, uint width, uint height,
|
||||
float tx, float ty, float scale, float cx,
|
||||
float cy, cudaTextureObject_t texObj) {
|
||||
uint x = __umul24(blockIdx.x, blockDim.x) + threadIdx.x;
|
||||
uint y = __umul24(blockIdx.y, blockDim.y) + threadIdx.y;
|
||||
uint i = __umul24(y, width) + x;
|
||||
__global__ void d_renderFastBicubic(uchar4 *d_output,
|
||||
uint width,
|
||||
uint height,
|
||||
float tx,
|
||||
float ty,
|
||||
float scale,
|
||||
float cx,
|
||||
float cy,
|
||||
cudaTextureObject_t texObj)
|
||||
{
|
||||
uint x = __umul24(blockIdx.x, blockDim.x) + threadIdx.x;
|
||||
uint y = __umul24(blockIdx.y, blockDim.y) + threadIdx.y;
|
||||
uint i = __umul24(y, width) + x;
|
||||
|
||||
float u = (x - cx) * scale + cx + tx;
|
||||
float v = (y - cy) * scale + cy + ty;
|
||||
float u = (x - cx) * scale + cx + tx;
|
||||
float v = (y - cy) * scale + cy + ty;
|
||||
|
||||
if ((x < width) && (y < height)) {
|
||||
// write output color
|
||||
float c = tex2DFastBicubic<uchar, float>(texObj, u, v);
|
||||
d_output[i] = make_uchar4(c * 0xff, c * 0xff, c * 0xff, 0);
|
||||
}
|
||||
if ((x < width) && (y < height)) {
|
||||
// write output color
|
||||
float c = tex2DFastBicubic<uchar, float>(texObj, u, v);
|
||||
d_output[i] = make_uchar4(c * 0xff, c * 0xff, c * 0xff, 0);
|
||||
}
|
||||
}
|
||||
|
||||
// render image using Catmull-Rom texture lookup
|
||||
__global__ void d_renderCatRom(uchar4 *d_output, uint width, uint height,
|
||||
float tx, float ty, float scale, float cx,
|
||||
float cy, cudaTextureObject_t texObj) {
|
||||
uint x = __umul24(blockIdx.x, blockDim.x) + threadIdx.x;
|
||||
uint y = __umul24(blockIdx.y, blockDim.y) + threadIdx.y;
|
||||
uint i = __umul24(y, width) + x;
|
||||
__global__ void d_renderCatRom(uchar4 *d_output,
|
||||
uint width,
|
||||
uint height,
|
||||
float tx,
|
||||
float ty,
|
||||
float scale,
|
||||
float cx,
|
||||
float cy,
|
||||
cudaTextureObject_t texObj)
|
||||
{
|
||||
uint x = __umul24(blockIdx.x, blockDim.x) + threadIdx.x;
|
||||
uint y = __umul24(blockIdx.y, blockDim.y) + threadIdx.y;
|
||||
uint i = __umul24(y, width) + x;
|
||||
|
||||
float u = (x - cx) * scale + cx + tx;
|
||||
float v = (y - cy) * scale + cy + ty;
|
||||
float u = (x - cx) * scale + cx + tx;
|
||||
float v = (y - cy) * scale + cy + ty;
|
||||
|
||||
if ((x < width) && (y < height)) {
|
||||
// write output color
|
||||
float c = tex2DCatRom<uchar, float>(texObj, u, v);
|
||||
d_output[i] = make_uchar4(c * 0xff, c * 0xff, c * 0xff, 0);
|
||||
}
|
||||
if ((x < width) && (y < height)) {
|
||||
// write output color
|
||||
float c = tex2DCatRom<uchar, float>(texObj, u, v);
|
||||
d_output[i] = make_uchar4(c * 0xff, c * 0xff, c * 0xff, 0);
|
||||
}
|
||||
}
|
||||
|
||||
#endif // _BICUBICTEXTURE_KERNEL_CUH_
|
||||
#endif // _BICUBICTEXTURE_KERNEL_CUH_
|
||||
|
||||
Reference in New Issue
Block a user