2 * Copyright 1993-2013 NVIDIA Corporation. All rights reserved.
4 * Please refer to the NVIDIA end user license agreement (EULA) associated
5 * with this source code for terms and conditions that govern your use of
6 * this software. Any use, reproduction, disclosure, or distribution of
7 * this software and related documentation outside the terms of the EULA
8 * is strictly prohibited.
12 // OpenGL Graphics includes
14 #if defined(__APPLE__) || defined(MACOSX)
15 #include <GLUT/glut.h>
17 #include <GL/freeglut.h>
20 // CUDA utilities and system includes
21 #include <cuda_runtime.h>
22 #include <cuda_gl_interop.h>
29 #include "SobelFilter_kernels.h"
32 #include <helper_functions.h> // includes for SDK helper functions
33 #include <helper_cuda.h> // includes for cuda initialization and error checking
35 const char *filterMode[] =
44 // Cuda example code that implements the Sobel edge detection
45 // filter. This code works for 8-bit monochrome images.
47 // Use the '-' and '=' keys to change the scale factor.
51 // T: display Sobel edge detection (computed solely with texture)
52 // S: display Sobel edge detection (computed with texture and shared memory)
55 void initializeData(char *file) ;
57 #define MAX_EPSILON_ERROR 5.0f
58 #define REFRESH_DELAY 10 //ms
60 const char *sSDKsample = "CUDA Sobel Edge-Detection";
62 static int wWidth = 512; // Window width
63 static int wHeight = 512; // Window height
64 static int imWidth = 0; // Image width
65 static int imHeight = 0; // Image height
67 // Code to handle Auto verification
68 const int frameCheckNumber = 4;
69 int fpsCount = 0; // FPS count for averaging
70 int fpsLimit = 8; // FPS limit for sampling
71 unsigned int frameCount = 0;
72 unsigned int g_TotalErrors = 0;
73 StopWatchInterface *timer = NULL;
75 unsigned int g_Index = 0;
77 bool g_bQAReadback = false;
80 static GLuint pbo_buffer = 0; // Front and back CA buffers
81 struct cudaGraphicsResource *cuda_pbo_resource; // CUDA Graphics Resource (to transfer PBO)
83 static GLuint texid = 0; // Texture for display
84 unsigned char *pixels = NULL; // Image pixel data on the host
85 float imageScale = 1.f; // Image exposure
86 enum SobelDisplayMode g_SobelDisplayMode;
91 extern "C" void runAutoTest(int argc, char **argv);
93 #define OFFSET(i) ((char *)NULL + (i))
94 #define MAX(a,b) ((a > b) ? a : b)
101 if (fpsCount == fpsLimit)
104 float ifps = 1.f / (sdkGetAverageTimerValue(&timer) / 1000.f);
105 sprintf(fps, "CUDA Edge Detection (%s): %3.1f fps", filterMode[g_SobelDisplayMode], ifps);
107 glutSetWindowTitle(fps);
110 sdkResetTimer(&timer);
115 // This is the normal display path
118 sdkStartTimer(&timer);
123 // map PBO to get CUDA device pointer
124 checkCudaErrors(cudaGraphicsMapResources(1, &cuda_pbo_resource, 0));
126 checkCudaErrors(cudaGraphicsResourceGetMappedPointer((void **)&data, &num_bytes,
128 //printf("CUDA mapped PBO: May access %ld bytes\n", num_bytes);
130 sobelFilter(data, imWidth, imHeight, g_SobelDisplayMode, imageScale);
131 checkCudaErrors(cudaGraphicsUnmapResources(1, &cuda_pbo_resource, 0));
133 glClear(GL_COLOR_BUFFER_BIT);
135 glBindTexture(GL_TEXTURE_2D, texid);
136 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo_buffer);
137 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, imWidth, imHeight,
138 GL_LUMINANCE, GL_UNSIGNED_BYTE, OFFSET(0));
139 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
141 glDisable(GL_DEPTH_TEST);
142 glEnable(GL_TEXTURE_2D);
143 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
144 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
145 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
146 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
158 glBindTexture(GL_TEXTURE_2D, 0);
161 sdkStopTimer(&timer);
166 void timerEvent(int value)
169 glutTimerFunc(REFRESH_DELAY, timerEvent, 0);
172 void keyboard(unsigned char key, int /*x*/, int /*y*/)
181 printf("Shutting down...\n");
187 printf("brightness = %4.2f\n", imageScale);
192 printf("brightness = %4.2f\n", imageScale);
197 g_SobelDisplayMode = SOBELDISPLAY_IMAGE;
198 sprintf(temp, "CUDA Edge Detection (%s)", filterMode[g_SobelDisplayMode]);
199 glutSetWindowTitle(temp);
204 g_SobelDisplayMode = SOBELDISPLAY_SOBELSHARED;
205 sprintf(temp, "CUDA Edge Detection (%s)", filterMode[g_SobelDisplayMode]);
206 glutSetWindowTitle(temp);
211 g_SobelDisplayMode = SOBELDISPLAY_SOBELTEX;
212 sprintf(temp, "CUDA Edge Detection (%s)", filterMode[g_SobelDisplayMode]);
213 glutSetWindowTitle(temp);
221 void reshape(int x, int y)
223 glViewport(0, 0, x, y);
224 glMatrixMode(GL_PROJECTION);
226 glOrtho(0, 1, 0, 1, 0, 1);
227 glMatrixMode(GL_MODELVIEW);
233 cudaGraphicsUnregisterResource(cuda_pbo_resource);
235 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
236 glDeleteBuffers(1, &pbo_buffer);
237 glDeleteTextures(1, &texid);
240 sdkDeleteTimer(&timer);
243 void initializeData(char *file)
247 size_t file_length= strlen(file);
249 if (!strcmp(&file[file_length-3], "pgm"))
251 if (sdkLoadPGM<unsigned char>(file, &pixels, &w, &h) != true)
253 printf("Failed to load PGM image file: %s\n", file);
259 else if (!strcmp(&file[file_length-3], "ppm"))
261 if (sdkLoadPPM4(file, &pixels, &w, &h) != true)
263 printf("Failed to load PPM image file: %s\n", file);
277 setupTexture(imWidth, imHeight, pixels, g_Bpp);
279 memset(pixels, 0x0, g_Bpp * sizeof(Pixel) * imWidth * imHeight);
284 glGenBuffers(1, &pbo_buffer);
285 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo_buffer);
286 glBufferData(GL_PIXEL_UNPACK_BUFFER,
287 g_Bpp * sizeof(Pixel) * imWidth * imHeight,
288 pixels, GL_STREAM_DRAW);
290 glGetBufferParameteriv(GL_PIXEL_UNPACK_BUFFER, GL_BUFFER_SIZE, &bsize);
292 if ((GLuint)bsize != (g_Bpp * sizeof(Pixel) * imWidth * imHeight))
294 printf("Buffer object (%d) has incorrect size (%d).\n", (unsigned)pbo_buffer, (unsigned)bsize);
299 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
301 // register this buffer object with CUDA
302 checkCudaErrors(cudaGraphicsGLRegisterBuffer(&cuda_pbo_resource, pbo_buffer, cudaGraphicsMapFlagsWriteDiscard));
304 glGenTextures(1, &texid);
305 glBindTexture(GL_TEXTURE_2D, texid);
306 glTexImage2D(GL_TEXTURE_2D, 0, ((g_Bpp==1) ? GL_LUMINANCE : GL_BGRA),
307 imWidth, imHeight, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, NULL);
308 glBindTexture(GL_TEXTURE_2D, 0);
310 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
311 glPixelStorei(GL_PACK_ALIGNMENT, 1);
315 void loadDefaultImage(char *loc_exec)
318 printf("Reading image: lena.pgm\n");
319 const char *image_filename = "lena.pgm";
320 char *image_path = sdkFindFilePath(image_filename, loc_exec);
322 if (image_path == NULL)
324 printf("Failed to read image file: <%s>\n", image_filename);
328 initializeData(image_path);
333 void initGL(int *argc, char **argv)
335 glutInit(argc, argv);
336 glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);
337 glutInitWindowSize(wWidth, wHeight);
338 glutCreateWindow("CUDA Edge Detection");
342 if (!glewIsSupported("GL_VERSION_1_5 GL_ARB_vertex_buffer_object GL_ARB_pixel_buffer_object"))
344 fprintf(stderr, "Error: failed to get minimal extensions for demo\n");
345 fprintf(stderr, "This sample requires:\n");
346 fprintf(stderr, " OpenGL version 1.5\n");
347 fprintf(stderr, " GL_ARB_vertex_buffer_object\n");
348 fprintf(stderr, " GL_ARB_pixel_buffer_object\n");
353 void runAutoTest(int argc, char *argv[])
355 printf("[%s] (automated testing w/ readback)\n", sSDKsample);
356 int devID = findCudaDevice(argc, (const char **)argv);
358 loadDefaultImage(argv[0]);
361 checkCudaErrors(cudaMalloc((void **)&d_result, imWidth*imHeight*sizeof(Pixel)));
363 char *ref_file = NULL;
367 mode = getCmdLineArgumentInt(argc, (const char **)argv, "mode");
368 getCmdLineArgumentString(argc, (const char **)argv, "file", &ref_file);
373 g_SobelDisplayMode = SOBELDISPLAY_IMAGE;
374 sprintf(dump_file, "lena_orig.pgm");
378 g_SobelDisplayMode = SOBELDISPLAY_SOBELTEX;
379 sprintf(dump_file, "lena_tex.pgm");
383 g_SobelDisplayMode = SOBELDISPLAY_SOBELSHARED;
384 sprintf(dump_file, "lena_shared.pgm");
388 printf("Invalid Filter Mode File\n");
393 printf("AutoTest: %s <%s>\n", sSDKsample, filterMode[g_SobelDisplayMode]);
394 sobelFilter(d_result, imWidth, imHeight, g_SobelDisplayMode, imageScale);
395 checkCudaErrors(cudaDeviceSynchronize());
397 unsigned char *h_result = (unsigned char *)malloc(imWidth*imHeight*sizeof(Pixel));
398 checkCudaErrors(cudaMemcpy(h_result, d_result, imWidth*imHeight*sizeof(Pixel), cudaMemcpyDeviceToHost));
399 sdkSavePGM(dump_file, h_result, imWidth, imHeight);
401 if (!sdkComparePGM(dump_file, sdkFindFilePath(ref_file, argv[0]), MAX_EPSILON_ERROR, 0.15f, false))
406 checkCudaErrors(cudaFree(d_result));
409 if (g_TotalErrors != 0)
411 printf("Test failed!\n");
415 printf("Test passed!\n");
419 int main(int argc, char **argv)
424 printf("%s Starting...\n\n", sSDKsample);
426 if (checkCmdLineFlag(argc, (const char **)argv, "help"))
428 printf("\nUsage: SobelFilter <options>\n");
429 printf("\t\t-mode=n (0=original, 1=texture, 2=smem + texture)\n");
430 printf("\t\t-file=ref_orig.pgm (ref_tex.pgm, ref_shared.pgm)\n\n");
434 if (checkCmdLineFlag(argc, (const char **)argv, "file"))
436 g_bQAReadback = true;
437 runAutoTest(argc, argv);
440 // use command-line specified CUDA device, otherwise use device with highest Gflops/s
441 if (checkCmdLineFlag(argc, (const char **)argv, "device"))
443 printf(" This SDK does not explicitly support -device=n when running with OpenGL.\n");
444 printf(" When specifying -device=n (n=0,1,2,....) the sample must not use OpenGL.\n");
445 printf(" See details below to run without OpenGL:\n\n");
446 printf(" > %s -device=n\n\n", argv[0]);
447 printf("exiting...\n");
451 // First initialize OpenGL context, so we can properly set the GL for CUDA.
452 // This is necessary in order to achieve optimal performance with OpenGL/CUDA interop.
454 cudaGLSetGLDevice(gpuGetMaxGflopsDeviceId());
456 sdkCreateTimer(&timer);
457 sdkResetTimer(&timer);
459 glutDisplayFunc(display);
460 glutKeyboardFunc(keyboard);
461 glutReshapeFunc(reshape);
463 loadDefaultImage(argv[0]);
465 // If code is not printing the USage, then we execute this path.
466 printf("I: display Image (no filtering)\n");
467 printf("T: display Sobel Edge Detection (Using Texture)\n");
468 printf("S: display Sobel Edge Detection (Using SMEM+Texture)\n");
469 printf("Use the '-' and '=' keys to change the brightness.\n");
472 glutTimerFunc(REFRESH_DELAY, timerEvent,0);