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.
13 Bindless Texture/Surface
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.
21 Look into the bindlessTexture_kernel.cu file for most relevant code.
32 #if defined (__APPLE__) || defined(MACOSX)
33 #include <GLUT/glut.h>
35 #include <GL/freeglut.h>
38 #include "bindlessTexture.h"
40 #include <helper_functions.h>
41 #include <cuda_gl_interop.h>
42 #include <helper_cuda_gl.h>
45 #define MAX_EPSILON_ERROR 5.0f
46 #define THRESHOLD 0.15f
48 const char *sSDKsample = "CUDA bindlessTexture";
50 const char *imageFilenames[] =
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);
62 float lod = 0.5; // texture mip map level
64 GLuint pbo; // OpenGL pixel buffer object
65 struct cudaGraphicsResource *cuda_pbo_resource = NULL; // CUDA Graphics Resource (to transfer PBO)
69 StopWatchInterface *timer = NULL;
71 uint *d_output = NULL;
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
78 unsigned int frameCount = 0;
79 unsigned int g_TotalErrors = 0;
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);
95 if (fpsCount == fpsLimit)
98 float ifps = 1.f / (sdkGetAverageTimerValue(&timer) / 1000.f);
99 sprintf(fps, "%s: %3.1f fps", sSDKsample, ifps);
101 glutSetWindowTitle(fps);
104 fpsLimit = (int)MAX(1.0f, ifps);
105 sdkResetTimer(&timer);
110 // render image using CUDA
113 // map PBO to get CUDA device pointer
114 checkCudaErrors(cudaGraphicsMapResources(1, &cuda_pbo_resource, 0));
116 checkCudaErrors(cudaGraphicsResourceGetMappedPointer((void **)&d_output, &num_bytes, cuda_pbo_resource));
118 // call CUDA kernel, writing results to PBO
119 renderAtlasImage(windowGridSize, windowBlockSize, d_output, windowSize.x, windowSize.y, lod);
121 getLastCudaError("render_kernel failed");
123 checkCudaErrors(cudaGraphicsUnmapResources(1, &cuda_pbo_resource, 0));
126 // display results using OpenGL (called by GLUT)
129 sdkStartTimer(&timer);
134 glClear(GL_COLOR_BUFFER_BIT);
136 // draw image from PBO
137 glDisable(GL_DEPTH_TEST);
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);
146 sdkStopTimer(&timer);
159 void keyboard(unsigned char key, int x, int y)
192 void reshape(int x, int y)
194 glViewport(0, 0, x, y);
196 glMatrixMode(GL_MODELVIEW);
199 glMatrixMode(GL_PROJECTION);
201 glOrtho(0.0, 1.0, 0.0, 1.0, 0.0, 1.0);
204 // Global cleanup function
205 // Shared by both GL and non-GL code paths
208 sdkDeleteTimer(&timer);
210 // unregister this buffer object from CUDA C
211 if (cuda_pbo_resource)
213 cudaGraphicsUnregisterResource(cuda_pbo_resource);
214 glDeleteBuffersARB(1, &pbo);
221 deinitAtlasAndImages();
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);
232 // register this buffer object with CUDA
233 checkCudaErrors(cudaGraphicsGLRegisterBuffer(&cuda_pbo_resource, pbo, cudaGraphicsMapFlagsWriteDiscard));
236 // Load raw data from disk
237 uchar *loadRawFile(const char *filename, size_t size)
239 FILE *fp = fopen(filename, "rb");
243 fprintf(stderr, "Error opening file '%s'\n", filename);
247 uchar *data = (uchar *) malloc(size);
248 size_t read = fread(data, 1, size, fp);
251 printf("Read '%s', %lu bytes\n", filename, read);
256 void initGL(int *argc, char **argv)
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);
270 if (!glewIsSupported("GL_VERSION_2_0 GL_ARB_pixel_buffer_object"))
272 fprintf(stderr, "Required OpenGL extensions missing.");
277 // General initialization call for CUDA Device
278 int chooseCudaDevice(int argc, char **argv, bool bUseOpenGL)
284 result = findCudaGLDevice(argc, (const char **)argv);
288 result = findCudaDevice(argc, (const char **)argv);
294 void runAutoTest(const char *ref_file, char *exec_path)
296 size_t windowBytes = windowSize.x * windowSize.y * sizeof(GLubyte)*4;
298 checkCudaErrors(cudaMalloc((void **)&d_output, windowBytes));
300 // render the volumeData
301 renderAtlasImage(windowGridSize, windowBlockSize, d_output, windowSize.x, windowSize.y, lod);
303 checkCudaErrors(cudaDeviceSynchronize());
304 getLastCudaError("render_kernel failed");
306 void *h_output = malloc(windowBytes);
307 checkCudaErrors(cudaMemcpy(h_output, d_output, windowBytes, cudaMemcpyDeviceToHost));
308 sdkDumpBin(h_output, windowBytes, "bindlessTexture.bin");
310 bool bTestResult = sdkCompareBin2BinFloat("bindlessTexture.bin", sdkFindFilePath(ref_file, exec_path), windowSize.x*windowSize.y,
311 MAX_EPSILON_ERROR, THRESHOLD, exec_path);
313 checkCudaErrors(cudaFree(d_output));
315 deinitAtlasAndImages();
318 sdkStopTimer(&timer);
319 sdkDeleteTimer(&timer);
321 exit(bTestResult ? EXIT_SUCCESS : EXIT_FAILURE);
325 void loadImageData(const char *exe_path)
327 std::vector<Image> images;
329 for (size_t i = 0; i < sizeof(imageFilenames)/sizeof(imageFilenames[0]); i++)
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];
340 imgPath = sdkFindFilePath(imgFilename, exe_path);
345 printf("Error finding image file '%s'\n", imgFilename);
349 sdkLoadPPM4(imgPath, (unsigned char **) &imgData, &imgWidth, &imgHeight);
353 printf("Error opening file '%s'\n", imgPath);
357 printf("Loaded '%s', %d x %d pixels\n", imgPath, imgWidth, imgHeight);
359 checkHost(imgWidth > 1);
360 checkHost(imgHeight > 1);
364 img.size = make_cudaExtent(imgWidth,imgHeight,0);
365 img.h_data = imgData;
366 images.push_back(img);
369 initAtlasAndImages(&images[0],images.size(),atlasSize);
373 ////////////////////////////////////////////////////////////////////////////////
375 ////////////////////////////////////////////////////////////////////////////////
377 main(int argc, char **argv)
379 sdkCreateTimer(&timer);
384 char *ref_file = NULL;
386 printf("%s Starting...\n\n", sSDKsample);
388 if (checkCmdLineFlag(argc, (const char **)argv, "file"))
390 fpsLimit = frameCheckNumber;
391 getCmdLineArgumentString(argc, (const char **)argv, "file", &ref_file);
398 chooseCudaDevice(argc, argv, false);
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.
406 // use command-line specified CUDA device, otherwise use device with highest Gflops/s
407 chooseCudaDevice(argc, argv, true);
413 if (!checkCudaCapabilities(3,0))
420 loadImageData(argv[0]);
424 runAutoTest(ref_file, argv[0]);
428 "Press space to toggle animation\n"
429 "Press '+' and '-' to change lod level\n"
430 "Press 'r' to randomize virtual atlas\n");