X-Git-Url: http://git.euphorik.ch/?p=GPU.git;a=blobdiff_plain;f=WCudaMSE%2FStudent_Cuda_Image%2Fsrc%2Fcpp%2Fcore%2F06_Convolution%2Fmoo%2Fdevice%2FConvolutionDevice.cu;fp=WCudaMSE%2FStudent_Cuda_Image%2Fsrc%2Fcpp%2Fcore%2F06_Convolution%2Fmoo%2Fdevice%2FConvolutionDevice.cu;h=0cfc48f8b657779c3a5c4650106df5f0757c72cf;hp=640d8a9e5248336115910f84ce446347891d3881;hb=52f4366920a116060ee62b84a2ed8b42f3c2d382;hpb=4182eb3a07b7143afb8ebebfe77e8ef8e8abc266 diff --git a/WCudaMSE/Student_Cuda_Image/src/cpp/core/06_Convolution/moo/device/ConvolutionDevice.cu b/WCudaMSE/Student_Cuda_Image/src/cpp/core/06_Convolution/moo/device/ConvolutionDevice.cu index 640d8a9..0cfc48f 100644 --- a/WCudaMSE/Student_Cuda_Image/src/cpp/core/06_Convolution/moo/device/ConvolutionDevice.cu +++ b/WCudaMSE/Student_Cuda_Image/src/cpp/core/06_Convolution/moo/device/ConvolutionDevice.cu @@ -9,17 +9,72 @@ using namespace std; #include "ConvolutionDevice.h" +// Le kernel de la convolution en constant memory. +__constant__ float TAB_KERNEL[KERNEL_SIZE][KERNEL_SIZE]; + +// L'image source accédée comme une texture. +texture textureImageSource; + +ConstantMemoryLink constantMemoryKernelLink() + { + float* ptrDevTabData; + size_t sizeAll = KERNEL_SIZE * KERNEL_SIZE * sizeof(float); + HANDLE_ERROR(cudaGetSymbolAddress((void**)&ptrDevTabData, TAB_KERNEL)); + ConstantMemoryLink cmLink = + { + (void**)ptrDevTabData, KERNEL_SIZE * KERNEL_SIZE, sizeAll + }; + return cmLink; + } + +void bindSouceAsTexture(uchar4* source, int w, int h) + { + // Propriétés de la texture (image en entrée). + textureImageSource.addressMode[0] = cudaAddressModeClamp; + textureImageSource.addressMode[1] = cudaAddressModeClamp; + textureImageSource.filterMode = cudaFilterModePoint; + textureImageSource.normalized = false; + + const size_t pitch = w * sizeof(uchar4); // Taille d'une ligne. + cudaChannelFormatDesc channelDesc = cudaCreateChannelDesc(); + HANDLE_ERROR(cudaBindTexture2D(NULL, textureImageSource, source, channelDesc, w, h, pitch)); + } + +void unbindSouceAsTexture() + { + HANDLE_ERROR(cudaUnbindTexture(textureImageSource)); + } + __global__ -void convolution(uchar4* ptrDevPixels, int w, int h, float t) +void toGrayscale(uchar4* ptrDevPixels, int w, int h) { const int TID = Indice2D::tid(); const int NB_THREAD = Indice2D::nbThread(); const int WH = w * h; - uchar4 color; - color.w = 255; // Par défaut, l'image est opaque. + int pixelI, pixelJ; + + int s = TID; + while (s < WH) + { + IndiceTools::toIJ(s, w, &pixelI, &pixelJ); + + const uchar average = (uchar)(((int)ptrDevPixels[s].x + (int)ptrDevPixels[s].y + (int)ptrDevPixels[s].z) / 3); + ptrDevPixels[s].x = average; + ptrDevPixels[s].y = average; + ptrDevPixels[s].z = average; + + s += NB_THREAD; + } + } + +__global__ +void convolution(uchar4* ptrDevOutput, int w, int h) + { + const int TID = Indice2D::tid(); + const int NB_THREAD = Indice2D::nbThread(); + const int WH = w * h; - double x, y; int pixelI, pixelJ; int s = TID; @@ -27,13 +82,22 @@ void convolution(uchar4* ptrDevPixels, int w, int h, float t) { IndiceTools::toIJ(s, w, &pixelI, &pixelJ); // update (pixelI, pixelJ) - // (i,j) domaine écran. - // (x,y) domaine math. - // domaineMath.toXY(pixelI, pixelJ, &x, &y); // (i,j) -> (x,y). + // La somme des produits du kernel avec l'image source. + float sum = 0; + for (int i = -4; i <= 4; i++) + for (int j = -4; j <= 4; j++) + { + uchar4 valueSource = tex2D(textureImageSource, pixelJ + j, pixelI + i); + sum += (float)valueSource.x * TAB_KERNEL[i + 4][j + 4]; // Comme c'est une image en niveau de gris on ne prend qu'une composante. + } + + sum /= 100; // Comme défini dans la donnée. - // newtonMath.colorXY(&color, x, y); + const float finalValue = (uchar)(sum * 50); - ptrDevPixels[s] = color; + ptrDevOutput[s].x = finalValue; + ptrDevOutput[s].y = finalValue; + ptrDevOutput[s].z = finalValue; s += NB_THREAD; }