OSDN Git Service

new file: Integration/Tomography/Makefile.recent
[eos/hostdependX86LINUX64.git] / util / X86MAC64 / cuda / samples / 2_Graphics / bindlessTexture / bindlessTexture.cpp
1 /*
2 * Copyright 1993-2013 NVIDIA Corporation.  All rights reserved.
3 *
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.
9 *
10 */
11
12 /*
13     Bindless Texture/Surface
14
15     This sample generates a few 2D textures and uses cudaTextureObjects to
16     perform pseudo virtual texturing for display. One 2D texture stores
17     references to other textures.
18     Furthermore use of mip mapping is shown using both cudaTextureObjects
19     and cudaSurfaceObjects.
20
21     Look into the bindlessTexture_kernel.cu file for most relevant code.
22 */
23
24 #include <stdlib.h>
25 #include <stdio.h>
26 #include <string.h>
27 #include <math.h>
28 #include <GL/glew.h>
29
30 #include <vector>
31
32 #if defined (__APPLE__) || defined(MACOSX)
33 #include <GLUT/glut.h>
34 #else
35 #include <GL/freeglut.h>
36 #endif
37
38 #include "bindlessTexture.h"
39
40 #include <helper_functions.h>
41 #include <cuda_gl_interop.h>
42 #include <helper_cuda_gl.h>
43
44
45 #define MAX_EPSILON_ERROR 5.0f
46 #define THRESHOLD         0.15f
47
48 const char *sSDKsample = "CUDA bindlessTexture";
49
50 const char *imageFilenames[] =
51 {
52     "flower.ppm",
53     "person.ppm",
54     "sponge.ppm",
55 };
56
57 const cudaExtent atlasSize  = make_cudaExtent(4, 4, 0);
58 const dim3 windowSize(512, 512);
59 const dim3 windowBlockSize(16, 16, 1);
60 const dim3 windowGridSize(windowSize.x / windowBlockSize.x, windowSize.y / windowBlockSize.y);
61
62 float lod = 0.5;    // texture mip map level
63
64 GLuint pbo;         // OpenGL pixel buffer object
65 struct cudaGraphicsResource *cuda_pbo_resource = NULL; // CUDA Graphics Resource (to transfer PBO)
66
67 bool animate = true;
68
69 StopWatchInterface *timer = NULL;
70
71 uint *d_output = NULL;
72
73 // Auto-Verification Code
74 const int frameCheckNumber = 4;
75 int fpsCount = 0;  // FPS count for averaging
76 int fpsLimit = 1;  // FPS limit for sampling
77 int g_Index = 0;
78 unsigned int frameCount = 0;
79 unsigned int g_TotalErrors = 0;
80
81 int *pArgc = NULL;
82 char **pArgv = NULL;
83
84 extern "C" void initAtlasAndImages(const Image *images, size_t numImages, cudaExtent atlasSize);
85 extern "C" void deinitAtlasAndImages();
86 extern "C" void randomizeAtlas();
87 extern "C" void renderAtlasImage(dim3 gridSize, dim3 blockSize, uint *d_output, uint imageW, uint imageH, float lod);
88
89
90 void computeFPS()
91 {
92     frameCount++;
93     fpsCount++;
94
95     if (fpsCount == fpsLimit)
96     {
97         char fps[256];
98         float ifps = 1.f / (sdkGetAverageTimerValue(&timer) / 1000.f);
99         sprintf(fps, "%s: %3.1f fps", sSDKsample, ifps);
100
101         glutSetWindowTitle(fps);
102         fpsCount = 0;
103
104         fpsLimit = (int)MAX(1.0f, ifps);
105         sdkResetTimer(&timer);
106     }
107 }
108
109
110 // render image using CUDA
111 void render()
112 {
113     // map PBO to get CUDA device pointer
114     checkCudaErrors(cudaGraphicsMapResources(1, &cuda_pbo_resource, 0));
115     size_t num_bytes;
116     checkCudaErrors(cudaGraphicsResourceGetMappedPointer((void **)&d_output, &num_bytes, cuda_pbo_resource));
117
118     // call CUDA kernel, writing results to PBO
119     renderAtlasImage(windowGridSize, windowBlockSize, d_output, windowSize.x, windowSize.y, lod);
120
121     getLastCudaError("render_kernel failed");
122
123     checkCudaErrors(cudaGraphicsUnmapResources(1, &cuda_pbo_resource, 0));
124 }
125
126 // display results using OpenGL (called by GLUT)
127 void display()
128 {
129     sdkStartTimer(&timer);
130
131     render();
132
133     // display results
134     glClear(GL_COLOR_BUFFER_BIT);
135
136     // draw image from PBO
137     glDisable(GL_DEPTH_TEST);
138     glRasterPos2i(0, 0);
139     glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, pbo);
140     glDrawPixels(windowSize.x, windowSize.y, GL_RGBA, GL_UNSIGNED_BYTE, 0);
141     glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0);
142
143     glutSwapBuffers();
144     glutReportErrors();
145
146     sdkStopTimer(&timer);
147     computeFPS();
148 }
149
150 void idle()
151 {
152     if (animate)
153     {
154         lod += 0.02f;
155         glutPostRedisplay();
156     }
157 }
158
159 void keyboard(unsigned char key, int x, int y)
160 {
161     switch (key)
162     {
163         case 27:
164             exit(EXIT_SUCCESS);
165             break;
166
167         case '=':
168         case '+':
169             lod += 0.25f;
170             break;
171
172         case '-':
173             lod -= 0.25f;
174             break;
175
176         case 'r':
177             randomizeAtlas();
178             break;
179
180         case ' ':
181             animate = !animate;
182             lod = 0.0f;
183             break;
184
185         default:
186             break;
187     }
188
189     glutPostRedisplay();
190 }
191
192 void reshape(int x, int y)
193 {
194     glViewport(0, 0, x, y);
195
196     glMatrixMode(GL_MODELVIEW);
197     glLoadIdentity();
198
199     glMatrixMode(GL_PROJECTION);
200     glLoadIdentity();
201     glOrtho(0.0, 1.0, 0.0, 1.0, 0.0, 1.0);
202 }
203
204 // Global cleanup function
205 // Shared by both GL and non-GL code paths
206 void cleanup()
207 {
208     sdkDeleteTimer(&timer);
209
210     // unregister this buffer object from CUDA C
211     if (cuda_pbo_resource)
212     {
213         cudaGraphicsUnregisterResource(cuda_pbo_resource);
214         glDeleteBuffersARB(1, &pbo);
215     }
216 }
217
218 void cleanup_all()
219 {
220     cleanup();
221     deinitAtlasAndImages();
222 }
223
224 void initGLBuffers()
225 {
226     // create pixel buffer object
227     glGenBuffersARB(1, &pbo);
228     glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, pbo);
229     glBufferDataARB(GL_PIXEL_UNPACK_BUFFER_ARB, windowSize.x*windowSize.y*sizeof(GLubyte)*4, 0, GL_STREAM_DRAW_ARB);
230     glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0);
231
232     // register this buffer object with CUDA
233     checkCudaErrors(cudaGraphicsGLRegisterBuffer(&cuda_pbo_resource, pbo, cudaGraphicsMapFlagsWriteDiscard));
234 }
235
236 // Load raw data from disk
237 uchar *loadRawFile(const char *filename, size_t size)
238 {
239     FILE *fp = fopen(filename, "rb");
240
241     if (!fp)
242     {
243         fprintf(stderr, "Error opening file '%s'\n", filename);
244         return 0;
245     }
246
247     uchar *data = (uchar *) malloc(size);
248     size_t read = fread(data, 1, size, fp);
249     fclose(fp);
250
251     printf("Read '%s', %lu bytes\n", filename, read);
252
253     return data;
254 }
255
256 void initGL(int *argc, char **argv)
257 {
258     // initialize GLUT callback functions
259     glutInit(argc, argv);
260     glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
261     glutInitWindowSize(windowSize.x, windowSize.y);
262     glutCreateWindow(sSDKsample);
263     glutDisplayFunc(display);
264     glutKeyboardFunc(keyboard);
265     glutReshapeFunc(reshape);
266     glutIdleFunc(idle);
267
268     glewInit();
269
270     if (!glewIsSupported("GL_VERSION_2_0 GL_ARB_pixel_buffer_object"))
271     {
272         fprintf(stderr, "Required OpenGL extensions missing.");
273         exit(EXIT_FAILURE);
274     }
275 }
276
277 // General initialization call for CUDA Device
278 int chooseCudaDevice(int argc, char **argv, bool bUseOpenGL)
279 {
280     int result = 0;
281
282     if (bUseOpenGL)
283     {
284         result = findCudaGLDevice(argc, (const char **)argv);
285     }
286     else
287     {
288         result = findCudaDevice(argc, (const char **)argv);
289     }
290
291     return result;
292 }
293
294 void runAutoTest(const char *ref_file, char *exec_path)
295 {
296     size_t windowBytes = windowSize.x * windowSize.y * sizeof(GLubyte)*4;
297
298     checkCudaErrors(cudaMalloc((void **)&d_output, windowBytes));
299
300     // render the volumeData
301     renderAtlasImage(windowGridSize, windowBlockSize, d_output, windowSize.x, windowSize.y, lod);
302
303     checkCudaErrors(cudaDeviceSynchronize());
304     getLastCudaError("render_kernel failed");
305
306     void *h_output = malloc(windowBytes);
307     checkCudaErrors(cudaMemcpy(h_output, d_output, windowBytes, cudaMemcpyDeviceToHost));
308     sdkDumpBin(h_output, windowBytes, "bindlessTexture.bin");
309
310     bool bTestResult = sdkCompareBin2BinFloat("bindlessTexture.bin", sdkFindFilePath(ref_file, exec_path), windowSize.x*windowSize.y,
311                                               MAX_EPSILON_ERROR, THRESHOLD, exec_path);
312
313     checkCudaErrors(cudaFree(d_output));
314     free(h_output);
315     deinitAtlasAndImages();
316
317     cudaDeviceReset();
318     sdkStopTimer(&timer);
319     sdkDeleteTimer(&timer);
320
321     exit(bTestResult ? EXIT_SUCCESS : EXIT_FAILURE);
322 }
323
324
325 void loadImageData(const char *exe_path)
326 {
327     std::vector<Image> images;
328
329     for (size_t i = 0; i < sizeof(imageFilenames)/sizeof(imageFilenames[0]); i++)
330     {
331
332         unsigned int imgWidth  = 0;
333         unsigned int imgHeight = 0;
334         uchar *imgData = NULL;
335         const char *imgPath = 0;
336         const char *imgFilename = imageFilenames[i];
337
338         if (exe_path)
339         {
340             imgPath = sdkFindFilePath(imgFilename, exe_path);
341         }
342
343         if (imgPath == 0)
344         {
345             printf("Error finding image file '%s'\n", imgFilename);
346             exit(EXIT_FAILURE);
347         }
348
349         sdkLoadPPM4(imgPath, (unsigned char **) &imgData, &imgWidth, &imgHeight);
350
351         if (!imgData)
352         {
353             printf("Error opening file '%s'\n", imgPath);
354             exit(EXIT_FAILURE);
355         }
356
357         printf("Loaded '%s', %d x %d pixels\n", imgPath, imgWidth, imgHeight);
358
359         checkHost(imgWidth  > 1);
360         checkHost(imgHeight > 1);
361
362
363         Image img;
364         img.size = make_cudaExtent(imgWidth,imgHeight,0);
365         img.h_data = imgData;
366         images.push_back(img);
367     }
368
369     initAtlasAndImages(&images[0],images.size(),atlasSize);
370 }
371
372
373 ////////////////////////////////////////////////////////////////////////////////
374 // Program main
375 ////////////////////////////////////////////////////////////////////////////////
376 int
377 main(int argc, char **argv)
378 {
379     sdkCreateTimer(&timer);
380
381     pArgc = &argc;
382     pArgv = argv;
383
384     char *ref_file = NULL;
385
386     printf("%s Starting...\n\n", sSDKsample);
387
388     if (checkCmdLineFlag(argc, (const char **)argv, "file"))
389     {
390         fpsLimit = frameCheckNumber;
391         getCmdLineArgumentString(argc, (const char **)argv, "file", &ref_file);
392     }
393
394     srand(15234);
395
396     if (ref_file)
397     {
398         chooseCudaDevice(argc, argv, false);
399     }
400     else
401     {
402         // First initialize OpenGL context, so we can properly set the GL for CUDA.
403         // This is necessary in order to achieve optimal performance with OpenGL/CUDA interop.
404         initGL(&argc, argv);
405
406         // use command-line specified CUDA device, otherwise use device with highest Gflops/s
407         chooseCudaDevice(argc, argv, true);
408
409         // OpenGL buffers
410         initGLBuffers();
411     }
412
413     if (!checkCudaCapabilities(3,0))
414     {
415         cleanup();
416         cudaDeviceReset();
417         exit(EXIT_SUCCESS);
418     }
419
420     loadImageData(argv[0]);
421
422     if (ref_file)
423     {
424         runAutoTest(ref_file, argv[0]);
425     }
426
427     printf(
428         "Press space to toggle animation\n"
429         "Press '+' and '-' to change lod level\n"
430         "Press 'r' to randomize virtual atlas\n");
431
432     atexit(cleanup_all);
433
434     glutMainLoop();
435
436     cudaDeviceReset();
437     exit(EXIT_SUCCESS);
438 }