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:
@@ -32,4 +32,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)
|
||||
|
||||
|
||||
@@ -37,14 +37,12 @@
|
||||
Look into the bindlessTexture_kernel.cu file for most relevant code.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <helper_gl.h>
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <vector>
|
||||
#if defined(__APPLE__) || defined(MACOSX)
|
||||
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||
#include <GLUT/glut.h>
|
||||
@@ -55,31 +53,31 @@
|
||||
#include <GL/freeglut.h>
|
||||
#endif
|
||||
|
||||
#include <cuda_gl_interop.h>
|
||||
#include <helper_functions.h>
|
||||
|
||||
#include "bindlessTexture.h"
|
||||
|
||||
#include <helper_functions.h>
|
||||
#include <cuda_gl_interop.h>
|
||||
|
||||
#define MAX_EPSILON_ERROR 5.0f
|
||||
#define THRESHOLD 0.15f
|
||||
#define THRESHOLD 0.15f
|
||||
|
||||
const char *sSDKsample = "CUDA bindlessTexture";
|
||||
|
||||
const char *imageFilenames[] = {
|
||||
"flower.ppm", "person.ppm", "sponge.ppm",
|
||||
"flower.ppm",
|
||||
"person.ppm",
|
||||
"sponge.ppm",
|
||||
};
|
||||
|
||||
const cudaExtent atlasSize = make_cudaExtent(4, 4, 0);
|
||||
const dim3 windowSize(512, 512);
|
||||
const dim3 windowBlockSize(16, 16, 1);
|
||||
const dim3 windowGridSize(windowSize.x / windowBlockSize.x,
|
||||
windowSize.y / windowBlockSize.y);
|
||||
const dim3 windowSize(512, 512);
|
||||
const dim3 windowBlockSize(16, 16, 1);
|
||||
const dim3 windowGridSize(windowSize.x / windowBlockSize.x, windowSize.y / windowBlockSize.y);
|
||||
|
||||
float lod = 0.5; // texture mip map level
|
||||
float lod = 0.5; // texture mip map level
|
||||
|
||||
GLuint pbo; // OpenGL pixel buffer object
|
||||
struct cudaGraphicsResource *cuda_pbo_resource =
|
||||
NULL; // CUDA Graphics Resource (to transfer PBO)
|
||||
GLuint pbo; // OpenGL pixel buffer object
|
||||
struct cudaGraphicsResource *cuda_pbo_resource = NULL; // CUDA Graphics Resource (to transfer PBO)
|
||||
|
||||
bool animate = true;
|
||||
|
||||
@@ -88,330 +86,335 @@ StopWatchInterface *timer = NULL;
|
||||
uint *d_output = NULL;
|
||||
|
||||
// Auto-Verification Code
|
||||
const int frameCheckNumber = 4;
|
||||
int fpsCount = 0; // FPS count for averaging
|
||||
int fpsLimit = 1; // FPS limit for sampling
|
||||
int g_Index = 0;
|
||||
unsigned int frameCount = 0;
|
||||
unsigned int g_TotalErrors = 0;
|
||||
const int frameCheckNumber = 4;
|
||||
int fpsCount = 0; // FPS count for averaging
|
||||
int fpsLimit = 1; // FPS limit for sampling
|
||||
int g_Index = 0;
|
||||
unsigned int frameCount = 0;
|
||||
unsigned int g_TotalErrors = 0;
|
||||
|
||||
int *pArgc = NULL;
|
||||
int *pArgc = NULL;
|
||||
char **pArgv = NULL;
|
||||
|
||||
extern "C" void initAtlasAndImages(const Image *images, size_t numImages,
|
||||
cudaExtent atlasSize);
|
||||
extern "C" void initAtlasAndImages(const Image *images, size_t numImages, cudaExtent atlasSize);
|
||||
extern "C" void deinitAtlasAndImages();
|
||||
extern "C" void randomizeAtlas();
|
||||
extern "C" void renderAtlasImage(dim3 gridSize, dim3 blockSize, uint *d_output,
|
||||
uint imageW, uint imageH, float lod);
|
||||
extern "C" void renderAtlasImage(dim3 gridSize, dim3 blockSize, uint *d_output, uint imageW, uint imageH, float lod);
|
||||
|
||||
void computeFPS() {
|
||||
frameCount++;
|
||||
fpsCount++;
|
||||
void computeFPS()
|
||||
{
|
||||
frameCount++;
|
||||
fpsCount++;
|
||||
|
||||
if (fpsCount == fpsLimit) {
|
||||
char fps[256];
|
||||
float ifps = 1.f / (sdkGetAverageTimerValue(&timer) / 1000.f);
|
||||
sprintf(fps, "%s: %3.1f fps", sSDKsample, ifps);
|
||||
if (fpsCount == fpsLimit) {
|
||||
char fps[256];
|
||||
float ifps = 1.f / (sdkGetAverageTimerValue(&timer) / 1000.f);
|
||||
sprintf(fps, "%s: %3.1f fps", sSDKsample, ifps);
|
||||
|
||||
glutSetWindowTitle(fps);
|
||||
fpsCount = 0;
|
||||
glutSetWindowTitle(fps);
|
||||
fpsCount = 0;
|
||||
|
||||
fpsLimit = (int)MAX(1.0f, ifps);
|
||||
sdkResetTimer(&timer);
|
||||
}
|
||||
fpsLimit = (int)MAX(1.0f, ifps);
|
||||
sdkResetTimer(&timer);
|
||||
}
|
||||
}
|
||||
|
||||
// render image using CUDA
|
||||
void render() {
|
||||
// map PBO to get CUDA device pointer
|
||||
checkCudaErrors(cudaGraphicsMapResources(1, &cuda_pbo_resource, 0));
|
||||
size_t num_bytes;
|
||||
checkCudaErrors(cudaGraphicsResourceGetMappedPointer(
|
||||
(void **)&d_output, &num_bytes, cuda_pbo_resource));
|
||||
void render()
|
||||
{
|
||||
// map PBO to get CUDA device pointer
|
||||
checkCudaErrors(cudaGraphicsMapResources(1, &cuda_pbo_resource, 0));
|
||||
size_t num_bytes;
|
||||
checkCudaErrors(cudaGraphicsResourceGetMappedPointer((void **)&d_output, &num_bytes, cuda_pbo_resource));
|
||||
|
||||
// call CUDA kernel, writing results to PBO
|
||||
renderAtlasImage(windowGridSize, windowBlockSize, d_output, windowSize.x,
|
||||
windowSize.y, lod);
|
||||
// call CUDA kernel, writing results to PBO
|
||||
renderAtlasImage(windowGridSize, windowBlockSize, d_output, windowSize.x, windowSize.y, lod);
|
||||
|
||||
getLastCudaError("render_kernel failed");
|
||||
getLastCudaError("render_kernel failed");
|
||||
|
||||
checkCudaErrors(cudaGraphicsUnmapResources(1, &cuda_pbo_resource, 0));
|
||||
checkCudaErrors(cudaGraphicsUnmapResources(1, &cuda_pbo_resource, 0));
|
||||
}
|
||||
|
||||
// display results using OpenGL (called by GLUT)
|
||||
void display() {
|
||||
sdkStartTimer(&timer);
|
||||
void display()
|
||||
{
|
||||
sdkStartTimer(&timer);
|
||||
|
||||
render();
|
||||
render();
|
||||
|
||||
// display results
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
// display results
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
// draw image from PBO
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glRasterPos2i(0, 0);
|
||||
glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, pbo);
|
||||
glDrawPixels(windowSize.x, windowSize.y, GL_RGBA, GL_UNSIGNED_BYTE, 0);
|
||||
glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, 0);
|
||||
// draw image from PBO
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glRasterPos2i(0, 0);
|
||||
glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, pbo);
|
||||
glDrawPixels(windowSize.x, windowSize.y, GL_RGBA, GL_UNSIGNED_BYTE, 0);
|
||||
glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, 0);
|
||||
|
||||
glutSwapBuffers();
|
||||
glutReportErrors();
|
||||
glutSwapBuffers();
|
||||
glutReportErrors();
|
||||
|
||||
sdkStopTimer(&timer);
|
||||
computeFPS();
|
||||
sdkStopTimer(&timer);
|
||||
computeFPS();
|
||||
}
|
||||
|
||||
void idle() {
|
||||
if (animate) {
|
||||
lod += 0.02f;
|
||||
glutPostRedisplay();
|
||||
}
|
||||
void idle()
|
||||
{
|
||||
if (animate) {
|
||||
lod += 0.02f;
|
||||
glutPostRedisplay();
|
||||
}
|
||||
}
|
||||
|
||||
void keyboard(unsigned char key, int x, int y) {
|
||||
switch (key) {
|
||||
void keyboard(unsigned char key, int x, int y)
|
||||
{
|
||||
switch (key) {
|
||||
case 27:
|
||||
#if defined(__APPLE__) || defined(MACOSX)
|
||||
exit(EXIT_SUCCESS);
|
||||
exit(EXIT_SUCCESS);
|
||||
#else
|
||||
glutDestroyWindow(glutGetWindow());
|
||||
return;
|
||||
glutDestroyWindow(glutGetWindow());
|
||||
return;
|
||||
#endif
|
||||
break;
|
||||
break;
|
||||
|
||||
case '=':
|
||||
case '+':
|
||||
lod += 0.25f;
|
||||
break;
|
||||
lod += 0.25f;
|
||||
break;
|
||||
|
||||
case '-':
|
||||
lod -= 0.25f;
|
||||
break;
|
||||
lod -= 0.25f;
|
||||
break;
|
||||
|
||||
case 'r':
|
||||
randomizeAtlas();
|
||||
break;
|
||||
randomizeAtlas();
|
||||
break;
|
||||
|
||||
case ' ':
|
||||
animate = !animate;
|
||||
lod = 0.0f;
|
||||
break;
|
||||
animate = !animate;
|
||||
lod = 0.0f;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
glutPostRedisplay();
|
||||
glutPostRedisplay();
|
||||
}
|
||||
|
||||
void reshape(int x, int y) {
|
||||
glViewport(0, 0, x, y);
|
||||
void reshape(int x, int y)
|
||||
{
|
||||
glViewport(0, 0, x, y);
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
glOrtho(0.0, 1.0, 0.0, 1.0, 0.0, 1.0);
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
glOrtho(0.0, 1.0, 0.0, 1.0, 0.0, 1.0);
|
||||
}
|
||||
|
||||
// Global cleanup function
|
||||
// Shared by both GL and non-GL code paths
|
||||
void cleanup() {
|
||||
sdkDeleteTimer(&timer);
|
||||
void cleanup()
|
||||
{
|
||||
sdkDeleteTimer(&timer);
|
||||
|
||||
// unregister this buffer object from CUDA C
|
||||
if (cuda_pbo_resource) {
|
||||
cudaGraphicsUnregisterResource(cuda_pbo_resource);
|
||||
glDeleteBuffers(1, &pbo);
|
||||
}
|
||||
// unregister this buffer object from CUDA C
|
||||
if (cuda_pbo_resource) {
|
||||
cudaGraphicsUnregisterResource(cuda_pbo_resource);
|
||||
glDeleteBuffers(1, &pbo);
|
||||
}
|
||||
}
|
||||
|
||||
void cleanup_all() {
|
||||
cleanup();
|
||||
deinitAtlasAndImages();
|
||||
void cleanup_all()
|
||||
{
|
||||
cleanup();
|
||||
deinitAtlasAndImages();
|
||||
}
|
||||
|
||||
void initGLBuffers() {
|
||||
// create pixel buffer object
|
||||
glGenBuffers(1, &pbo);
|
||||
glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, pbo);
|
||||
glBufferData(GL_PIXEL_UNPACK_BUFFER_ARB,
|
||||
windowSize.x * windowSize.y * sizeof(GLubyte) * 4, 0,
|
||||
GL_STREAM_DRAW_ARB);
|
||||
glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, 0);
|
||||
void initGLBuffers()
|
||||
{
|
||||
// create pixel buffer object
|
||||
glGenBuffers(1, &pbo);
|
||||
glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, pbo);
|
||||
glBufferData(GL_PIXEL_UNPACK_BUFFER_ARB, windowSize.x * windowSize.y * sizeof(GLubyte) * 4, 0, GL_STREAM_DRAW_ARB);
|
||||
glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, 0);
|
||||
|
||||
// register this buffer object with CUDA
|
||||
checkCudaErrors(cudaGraphicsGLRegisterBuffer(
|
||||
&cuda_pbo_resource, pbo, cudaGraphicsMapFlagsWriteDiscard));
|
||||
// register this buffer object with CUDA
|
||||
checkCudaErrors(cudaGraphicsGLRegisterBuffer(&cuda_pbo_resource, pbo, cudaGraphicsMapFlagsWriteDiscard));
|
||||
}
|
||||
|
||||
// Load raw data from disk
|
||||
uchar *loadRawFile(const char *filename, size_t size) {
|
||||
FILE *fp = fopen(filename, "rb");
|
||||
uchar *loadRawFile(const char *filename, size_t size)
|
||||
{
|
||||
FILE *fp = fopen(filename, "rb");
|
||||
|
||||
if (!fp) {
|
||||
fprintf(stderr, "Error opening file '%s'\n", filename);
|
||||
return 0;
|
||||
}
|
||||
|
||||
uchar *data = (uchar *)malloc(size);
|
||||
size_t read = fread(data, 1, size, fp);
|
||||
fclose(fp);
|
||||
|
||||
printf("Read '%s', %zu bytes\n", filename, read);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
void initGL(int *argc, char **argv) {
|
||||
// initialize GLUT callback functions
|
||||
glutInit(argc, argv);
|
||||
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
|
||||
glutInitWindowSize(windowSize.x, windowSize.y);
|
||||
glutCreateWindow(sSDKsample);
|
||||
glutDisplayFunc(display);
|
||||
glutKeyboardFunc(keyboard);
|
||||
glutReshapeFunc(reshape);
|
||||
glutIdleFunc(idle);
|
||||
|
||||
if (!isGLVersionSupported(2, 0) ||
|
||||
!areGLExtensionsSupported("GL_ARB_pixel_buffer_object")) {
|
||||
fprintf(stderr, "Required OpenGL extensions are missing.");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
void runAutoTest(const char *ref_file, char *exec_path) {
|
||||
size_t windowBytes = windowSize.x * windowSize.y * sizeof(GLubyte) * 4;
|
||||
|
||||
checkCudaErrors(cudaMalloc((void **)&d_output, windowBytes));
|
||||
|
||||
// render the volumeData
|
||||
renderAtlasImage(windowGridSize, windowBlockSize, d_output, windowSize.x,
|
||||
windowSize.y, lod);
|
||||
|
||||
checkCudaErrors(cudaDeviceSynchronize());
|
||||
getLastCudaError("render_kernel failed");
|
||||
|
||||
void *h_output = malloc(windowBytes);
|
||||
checkCudaErrors(
|
||||
cudaMemcpy(h_output, d_output, windowBytes, cudaMemcpyDeviceToHost));
|
||||
sdkDumpBin(h_output, (unsigned int)windowBytes, "bindlessTexture.bin");
|
||||
|
||||
bool bTestResult = sdkCompareBin2BinFloat(
|
||||
"bindlessTexture.bin", sdkFindFilePath(ref_file, exec_path),
|
||||
windowSize.x * windowSize.y, MAX_EPSILON_ERROR, THRESHOLD, exec_path);
|
||||
|
||||
checkCudaErrors(cudaFree(d_output));
|
||||
free(h_output);
|
||||
deinitAtlasAndImages();
|
||||
|
||||
sdkStopTimer(&timer);
|
||||
sdkDeleteTimer(&timer);
|
||||
|
||||
exit(bTestResult ? EXIT_SUCCESS : EXIT_FAILURE);
|
||||
}
|
||||
|
||||
void loadImageData(const char *exe_path) {
|
||||
std::vector<Image> images;
|
||||
|
||||
for (size_t i = 0; i < sizeof(imageFilenames) / sizeof(imageFilenames[0]);
|
||||
i++) {
|
||||
unsigned int imgWidth = 0;
|
||||
unsigned int imgHeight = 0;
|
||||
uchar *imgData = NULL;
|
||||
const char *imgPath = 0;
|
||||
const char *imgFilename = imageFilenames[i];
|
||||
|
||||
if (exe_path) {
|
||||
imgPath = sdkFindFilePath(imgFilename, exe_path);
|
||||
if (!fp) {
|
||||
fprintf(stderr, "Error opening file '%s'\n", filename);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (imgPath == 0) {
|
||||
printf("Error finding image file '%s'\n", imgFilename);
|
||||
exit(EXIT_FAILURE);
|
||||
uchar *data = (uchar *)malloc(size);
|
||||
size_t read = fread(data, 1, size, fp);
|
||||
fclose(fp);
|
||||
|
||||
printf("Read '%s', %zu bytes\n", filename, read);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
void initGL(int *argc, char **argv)
|
||||
{
|
||||
// initialize GLUT callback functions
|
||||
glutInit(argc, argv);
|
||||
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
|
||||
glutInitWindowSize(windowSize.x, windowSize.y);
|
||||
glutCreateWindow(sSDKsample);
|
||||
glutDisplayFunc(display);
|
||||
glutKeyboardFunc(keyboard);
|
||||
glutReshapeFunc(reshape);
|
||||
glutIdleFunc(idle);
|
||||
|
||||
if (!isGLVersionSupported(2, 0) || !areGLExtensionsSupported("GL_ARB_pixel_buffer_object")) {
|
||||
fprintf(stderr, "Required OpenGL extensions are missing.");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
void runAutoTest(const char *ref_file, char *exec_path)
|
||||
{
|
||||
size_t windowBytes = windowSize.x * windowSize.y * sizeof(GLubyte) * 4;
|
||||
|
||||
checkCudaErrors(cudaMalloc((void **)&d_output, windowBytes));
|
||||
|
||||
// render the volumeData
|
||||
renderAtlasImage(windowGridSize, windowBlockSize, d_output, windowSize.x, windowSize.y, lod);
|
||||
|
||||
checkCudaErrors(cudaDeviceSynchronize());
|
||||
getLastCudaError("render_kernel failed");
|
||||
|
||||
void *h_output = malloc(windowBytes);
|
||||
checkCudaErrors(cudaMemcpy(h_output, d_output, windowBytes, cudaMemcpyDeviceToHost));
|
||||
sdkDumpBin(h_output, (unsigned int)windowBytes, "bindlessTexture.bin");
|
||||
|
||||
bool bTestResult = sdkCompareBin2BinFloat("bindlessTexture.bin",
|
||||
sdkFindFilePath(ref_file, exec_path),
|
||||
windowSize.x * windowSize.y,
|
||||
MAX_EPSILON_ERROR,
|
||||
THRESHOLD,
|
||||
exec_path);
|
||||
|
||||
checkCudaErrors(cudaFree(d_output));
|
||||
free(h_output);
|
||||
deinitAtlasAndImages();
|
||||
|
||||
sdkStopTimer(&timer);
|
||||
sdkDeleteTimer(&timer);
|
||||
|
||||
exit(bTestResult ? EXIT_SUCCESS : EXIT_FAILURE);
|
||||
}
|
||||
|
||||
void loadImageData(const char *exe_path)
|
||||
{
|
||||
std::vector<Image> images;
|
||||
|
||||
for (size_t i = 0; i < sizeof(imageFilenames) / sizeof(imageFilenames[0]); i++) {
|
||||
unsigned int imgWidth = 0;
|
||||
unsigned int imgHeight = 0;
|
||||
uchar *imgData = NULL;
|
||||
const char *imgPath = 0;
|
||||
const char *imgFilename = imageFilenames[i];
|
||||
|
||||
if (exe_path) {
|
||||
imgPath = sdkFindFilePath(imgFilename, exe_path);
|
||||
}
|
||||
|
||||
if (imgPath == 0) {
|
||||
printf("Error finding image file '%s'\n", imgFilename);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
sdkLoadPPM4(imgPath, (unsigned char **)&imgData, &imgWidth, &imgHeight);
|
||||
|
||||
if (!imgData) {
|
||||
printf("Error opening file '%s'\n", imgPath);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
printf("Loaded '%s', %d x %d pixels\n", imgPath, imgWidth, imgHeight);
|
||||
|
||||
checkHost(imgWidth > 1);
|
||||
checkHost(imgHeight > 1);
|
||||
|
||||
Image img;
|
||||
img.size = make_cudaExtent(imgWidth, imgHeight, 0);
|
||||
img.h_data = imgData;
|
||||
images.push_back(img);
|
||||
}
|
||||
|
||||
sdkLoadPPM4(imgPath, (unsigned char **)&imgData, &imgWidth, &imgHeight);
|
||||
|
||||
if (!imgData) {
|
||||
printf("Error opening file '%s'\n", imgPath);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
printf("Loaded '%s', %d x %d pixels\n", imgPath, imgWidth, imgHeight);
|
||||
|
||||
checkHost(imgWidth > 1);
|
||||
checkHost(imgHeight > 1);
|
||||
|
||||
Image img;
|
||||
img.size = make_cudaExtent(imgWidth, imgHeight, 0);
|
||||
img.h_data = imgData;
|
||||
images.push_back(img);
|
||||
}
|
||||
|
||||
initAtlasAndImages(&images[0], images.size(), atlasSize);
|
||||
initAtlasAndImages(&images[0], images.size(), atlasSize);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Program main
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
int main(int argc, char **argv) {
|
||||
sdkCreateTimer(&timer);
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
sdkCreateTimer(&timer);
|
||||
|
||||
pArgc = &argc;
|
||||
pArgv = argv;
|
||||
pArgc = &argc;
|
||||
pArgv = argv;
|
||||
|
||||
char *ref_file = NULL;
|
||||
char *ref_file = NULL;
|
||||
|
||||
#if defined(__linux__)
|
||||
setenv("DISPLAY", ":0", 0);
|
||||
setenv("DISPLAY", ":0", 0);
|
||||
#endif
|
||||
|
||||
printf("%s Starting...\n\n", sSDKsample);
|
||||
printf("%s Starting...\n\n", sSDKsample);
|
||||
|
||||
if (checkCmdLineFlag(argc, (const char **)argv, "file")) {
|
||||
fpsLimit = frameCheckNumber;
|
||||
getCmdLineArgumentString(argc, (const char **)argv, "file", &ref_file);
|
||||
}
|
||||
if (checkCmdLineFlag(argc, (const char **)argv, "file")) {
|
||||
fpsLimit = frameCheckNumber;
|
||||
getCmdLineArgumentString(argc, (const char **)argv, "file", &ref_file);
|
||||
}
|
||||
|
||||
srand(15234);
|
||||
srand(15234);
|
||||
|
||||
// use command-line specified CUDA device, otherwise use device with highest
|
||||
// Gflops/s
|
||||
findCudaDevice(argc, (const char **)argv);
|
||||
// use command-line specified CUDA device, otherwise use device with highest
|
||||
// Gflops/s
|
||||
findCudaDevice(argc, (const char **)argv);
|
||||
|
||||
if (!ref_file) {
|
||||
initGL(&argc, argv);
|
||||
if (!ref_file) {
|
||||
initGL(&argc, argv);
|
||||
|
||||
// OpenGL buffers
|
||||
initGLBuffers();
|
||||
}
|
||||
// OpenGL buffers
|
||||
initGLBuffers();
|
||||
}
|
||||
|
||||
if (!checkCudaCapabilities(3, 0)) {
|
||||
cleanup();
|
||||
if (!checkCudaCapabilities(3, 0)) {
|
||||
cleanup();
|
||||
|
||||
exit(EXIT_WAIVED);
|
||||
}
|
||||
exit(EXIT_WAIVED);
|
||||
}
|
||||
|
||||
loadImageData(argv[0]);
|
||||
loadImageData(argv[0]);
|
||||
|
||||
if (ref_file) {
|
||||
runAutoTest(ref_file, argv[0]);
|
||||
}
|
||||
if (ref_file) {
|
||||
runAutoTest(ref_file, argv[0]);
|
||||
}
|
||||
|
||||
printf(
|
||||
"Press space to toggle animation\n"
|
||||
"Press '+' and '-' to change lod level\n"
|
||||
"Press 'r' to randomize virtual atlas\n");
|
||||
printf("Press space to toggle animation\n"
|
||||
"Press '+' and '-' to change lod level\n"
|
||||
"Press 'r' to randomize virtual atlas\n");
|
||||
|
||||
#if defined(__APPLE__) || defined(MACOSX)
|
||||
atexit(cleanup_all);
|
||||
atexit(cleanup_all);
|
||||
#else
|
||||
glutCloseFunc(cleanup_all);
|
||||
glutCloseFunc(cleanup_all);
|
||||
#endif
|
||||
|
||||
glutMainLoop();
|
||||
glutMainLoop();
|
||||
}
|
||||
|
||||
@@ -29,39 +29,38 @@
|
||||
#define _BINDLESSTEXTURE_CU_
|
||||
|
||||
// includes, cuda
|
||||
#include <vector_types.h>
|
||||
#include <cuda_runtime.h>
|
||||
#include <vector_types.h>
|
||||
|
||||
// CUDA utilities and system includes
|
||||
#include <helper_cuda.h>
|
||||
#include <vector_types.h>
|
||||
|
||||
typedef unsigned int uint;
|
||||
typedef unsigned int uint;
|
||||
typedef unsigned char uchar;
|
||||
|
||||
#pragma pack(push, 4)
|
||||
struct Image {
|
||||
void *h_data;
|
||||
cudaExtent size;
|
||||
cudaResourceType type;
|
||||
cudaArray_t dataArray;
|
||||
cudaMipmappedArray_t mipmapArray;
|
||||
cudaTextureObject_t textureObject;
|
||||
struct Image
|
||||
{
|
||||
void *h_data;
|
||||
cudaExtent size;
|
||||
cudaResourceType type;
|
||||
cudaArray_t dataArray;
|
||||
cudaMipmappedArray_t mipmapArray;
|
||||
cudaTextureObject_t textureObject;
|
||||
|
||||
Image() { memset(this, 0, sizeof(Image)); }
|
||||
Image() { memset(this, 0, sizeof(Image)); }
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
inline void _checkHost(bool test, const char *condition, const char *file,
|
||||
int line, const char *func) {
|
||||
if (!test) {
|
||||
fprintf(stderr, "HOST error at %s:%d (%s) \"%s\" \n", file, line, condition,
|
||||
func);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
inline void _checkHost(bool test, const char *condition, const char *file, int line, const char *func)
|
||||
{
|
||||
if (!test) {
|
||||
fprintf(stderr, "HOST error at %s:%d (%s) \"%s\" \n", file, line, condition, func);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
#define checkHost(condition) \
|
||||
_checkHost(condition, #condition, __FILE__, __LINE__, __FUNCTION__)
|
||||
#define checkHost(condition) _checkHost(condition, #condition, __FILE__, __LINE__, __FUNCTION__)
|
||||
|
||||
#endif
|
||||
|
||||
@@ -41,26 +41,24 @@
|
||||
#ifndef _BINDLESSTEXTURE_KERNEL_CU_
|
||||
#define _BINDLESSTEXTURE_KERNEL_CU_
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <helper_cuda.h>
|
||||
#include <helper_math.h>
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <vector>
|
||||
|
||||
#include "bindlessTexture.h"
|
||||
|
||||
// set this to just see the mipmap chain of first image
|
||||
//#define SHOW_MIPMAPS
|
||||
// #define SHOW_MIPMAPS
|
||||
|
||||
// local references to resources
|
||||
|
||||
Image atlasImage;
|
||||
Image atlasImage;
|
||||
std::vector<Image> contentImages;
|
||||
float highestLod = 1.0f;
|
||||
float highestLod = 1.0f;
|
||||
|
||||
#ifndef MAX
|
||||
#define MAX(a, b) ((a > b) ? a : b)
|
||||
@@ -68,22 +66,21 @@ float highestLod = 1.0f;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__host__ __device__ __inline__ uint2 encodeTextureObject(
|
||||
cudaTextureObject_t obj) {
|
||||
return make_uint2((uint)(obj & 0xFFFFFFFF), (uint)(obj >> 32));
|
||||
__host__ __device__ __inline__ uint2 encodeTextureObject(cudaTextureObject_t obj)
|
||||
{
|
||||
return make_uint2((uint)(obj & 0xFFFFFFFF), (uint)(obj >> 32));
|
||||
}
|
||||
|
||||
__host__ __device__ __inline__ cudaTextureObject_t decodeTextureObject(
|
||||
uint2 obj) {
|
||||
return (((cudaTextureObject_t)obj.x) | ((cudaTextureObject_t)obj.y) << 32);
|
||||
__host__ __device__ __inline__ cudaTextureObject_t decodeTextureObject(uint2 obj)
|
||||
{
|
||||
return (((cudaTextureObject_t)obj.x) | ((cudaTextureObject_t)obj.y) << 32);
|
||||
}
|
||||
|
||||
__device__ __inline__ float4 to_float4(uchar4 vec) {
|
||||
return make_float4(vec.x, vec.y, vec.z, vec.w);
|
||||
}
|
||||
__device__ __inline__ float4 to_float4(uchar4 vec) { return make_float4(vec.x, vec.y, vec.z, vec.w); }
|
||||
|
||||
__device__ __inline__ uchar4 to_uchar4(float4 vec) {
|
||||
return make_uchar4((uchar)vec.x, (uchar)vec.y, (uchar)vec.z, (uchar)vec.w);
|
||||
__device__ __inline__ uchar4 to_uchar4(float4 vec)
|
||||
{
|
||||
return make_uchar4((uchar)vec.x, (uchar)vec.y, (uchar)vec.z, (uchar)vec.w);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
@@ -92,48 +89,46 @@ __device__ __inline__ uchar4 to_uchar4(float4 vec) {
|
||||
// the atlas texture stores the 64 bit cudaTextureObjects
|
||||
// we use it for "virtual" texturing
|
||||
|
||||
__global__ void d_render(uchar4 *d_output, uint imageW, uint imageH, float lod,
|
||||
cudaTextureObject_t atlasTexture) {
|
||||
uint x = blockIdx.x * blockDim.x + threadIdx.x;
|
||||
uint y = blockIdx.y * blockDim.y + threadIdx.y;
|
||||
__global__ void d_render(uchar4 *d_output, uint imageW, uint imageH, float lod, cudaTextureObject_t atlasTexture)
|
||||
{
|
||||
uint x = blockIdx.x * blockDim.x + threadIdx.x;
|
||||
uint y = blockIdx.y * blockDim.y + threadIdx.y;
|
||||
|
||||
float u = x / (float)imageW;
|
||||
float v = y / (float)imageH;
|
||||
float u = x / (float)imageW;
|
||||
float v = y / (float)imageH;
|
||||
|
||||
if ((x < imageW) && (y < imageH)) {
|
||||
// read from 2D atlas texture and decode texture object
|
||||
uint2 texCoded = tex2D<uint2>(atlasTexture, u, v);
|
||||
cudaTextureObject_t tex = decodeTextureObject(texCoded);
|
||||
if ((x < imageW) && (y < imageH)) {
|
||||
// read from 2D atlas texture and decode texture object
|
||||
uint2 texCoded = tex2D<uint2>(atlasTexture, u, v);
|
||||
cudaTextureObject_t tex = decodeTextureObject(texCoded);
|
||||
|
||||
// read from cuda texture object, use template to specify what data will be
|
||||
// returned. tex2DLod allows us to pass the lod (mip map level) directly.
|
||||
// There is other functions with CUDA 5, e.g. tex2DGrad, that allow you
|
||||
// to pass derivatives to perform automatic mipmap/anisotropic filtering.
|
||||
float4 color = tex2DLod<float4>(tex, u, 1 - v, lod);
|
||||
// In our sample tex is always valid, but for something like your own
|
||||
// sparse texturing you would need to make sure to handle the zero case.
|
||||
// read from cuda texture object, use template to specify what data will be
|
||||
// returned. tex2DLod allows us to pass the lod (mip map level) directly.
|
||||
// There is other functions with CUDA 5, e.g. tex2DGrad, that allow you
|
||||
// to pass derivatives to perform automatic mipmap/anisotropic filtering.
|
||||
float4 color = tex2DLod<float4>(tex, u, 1 - v, lod);
|
||||
// In our sample tex is always valid, but for something like your own
|
||||
// sparse texturing you would need to make sure to handle the zero case.
|
||||
|
||||
// write output color
|
||||
uint i = y * imageW + x;
|
||||
d_output[i] = to_uchar4(color * 255.0);
|
||||
}
|
||||
// write output color
|
||||
uint i = y * imageW + x;
|
||||
d_output[i] = to_uchar4(color * 255.0);
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" void renderAtlasImage(dim3 gridSize, dim3 blockSize,
|
||||
uchar4 *d_output, uint imageW, uint imageH,
|
||||
float lod) {
|
||||
// psuedo animate lod
|
||||
lod = fmodf(lod, highestLod * 2);
|
||||
lod = highestLod - fabs(lod - highestLod);
|
||||
extern "C" void renderAtlasImage(dim3 gridSize, dim3 blockSize, uchar4 *d_output, uint imageW, uint imageH, float lod)
|
||||
{
|
||||
// psuedo animate lod
|
||||
lod = fmodf(lod, highestLod * 2);
|
||||
lod = highestLod - fabs(lod - highestLod);
|
||||
|
||||
#ifdef SHOW_MIPMAPS
|
||||
lod = 0.0f;
|
||||
lod = 0.0f;
|
||||
#endif
|
||||
|
||||
d_render<<<gridSize, blockSize>>>(d_output, imageW, imageH, lod,
|
||||
atlasImage.textureObject);
|
||||
d_render<<<gridSize, blockSize>>>(d_output, imageW, imageH, lod, atlasImage.textureObject);
|
||||
|
||||
checkCudaErrors(cudaGetLastError());
|
||||
checkCudaErrors(cudaGetLastError());
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
@@ -143,287 +138,278 @@ extern "C" void renderAtlasImage(dim3 gridSize, dim3 blockSize,
|
||||
// global binding points anymore. We can directly pass them as function
|
||||
// arguments.
|
||||
|
||||
__global__ void d_mipmap(cudaSurfaceObject_t mipOutput,
|
||||
cudaTextureObject_t mipInput, uint imageW,
|
||||
uint imageH) {
|
||||
uint x = blockIdx.x * blockDim.x + threadIdx.x;
|
||||
uint y = blockIdx.y * blockDim.y + threadIdx.y;
|
||||
__global__ void d_mipmap(cudaSurfaceObject_t mipOutput, cudaTextureObject_t mipInput, uint imageW, uint imageH)
|
||||
{
|
||||
uint x = blockIdx.x * blockDim.x + threadIdx.x;
|
||||
uint y = blockIdx.y * blockDim.y + threadIdx.y;
|
||||
|
||||
float px = 1.0 / float(imageW);
|
||||
float py = 1.0 / float(imageH);
|
||||
float px = 1.0 / float(imageW);
|
||||
float py = 1.0 / float(imageH);
|
||||
|
||||
if ((x < imageW) && (y < imageH)) {
|
||||
// take the average of 4 samples
|
||||
if ((x < imageW) && (y < imageH)) {
|
||||
// take the average of 4 samples
|
||||
|
||||
// we are using the normalized access to make sure non-power-of-two textures
|
||||
// behave well when downsized.
|
||||
float4 color = (tex2D<float4>(mipInput, (x + 0) * px, (y + 0) * py)) +
|
||||
(tex2D<float4>(mipInput, (x + 1) * px, (y + 0) * py)) +
|
||||
(tex2D<float4>(mipInput, (x + 1) * px, (y + 1) * py)) +
|
||||
(tex2D<float4>(mipInput, (x + 0) * px, (y + 1) * py));
|
||||
// we are using the normalized access to make sure non-power-of-two textures
|
||||
// behave well when downsized.
|
||||
float4 color = (tex2D<float4>(mipInput, (x + 0) * px, (y + 0) * py))
|
||||
+ (tex2D<float4>(mipInput, (x + 1) * px, (y + 0) * py))
|
||||
+ (tex2D<float4>(mipInput, (x + 1) * px, (y + 1) * py))
|
||||
+ (tex2D<float4>(mipInput, (x + 0) * px, (y + 1) * py));
|
||||
|
||||
color /= 4.0;
|
||||
color *= 255.0;
|
||||
color = fminf(color, make_float4(255.0));
|
||||
color /= 4.0;
|
||||
color *= 255.0;
|
||||
color = fminf(color, make_float4(255.0));
|
||||
|
||||
surf2Dwrite(to_uchar4(color), mipOutput, x * sizeof(uchar4), y);
|
||||
}
|
||||
surf2Dwrite(to_uchar4(color), mipOutput, x * sizeof(uchar4), y);
|
||||
}
|
||||
}
|
||||
|
||||
void generateMipMaps(cudaMipmappedArray_t mipmapArray, cudaExtent size) {
|
||||
size_t width = size.width;
|
||||
size_t height = size.height;
|
||||
void generateMipMaps(cudaMipmappedArray_t mipmapArray, cudaExtent size)
|
||||
{
|
||||
size_t width = size.width;
|
||||
size_t height = size.height;
|
||||
|
||||
#ifdef SHOW_MIPMAPS
|
||||
cudaArray_t levelFirst;
|
||||
checkCudaErrors(cudaGetMipmappedArrayLevel(&levelFirst, mipmapArray, 0));
|
||||
cudaArray_t levelFirst;
|
||||
checkCudaErrors(cudaGetMipmappedArrayLevel(&levelFirst, mipmapArray, 0));
|
||||
#endif
|
||||
|
||||
uint level = 0;
|
||||
uint level = 0;
|
||||
|
||||
while (width != 1 || height != 1) {
|
||||
width /= 2;
|
||||
width = MAX((size_t)1, width);
|
||||
height /= 2;
|
||||
height = MAX((size_t)1, height);
|
||||
while (width != 1 || height != 1) {
|
||||
width /= 2;
|
||||
width = MAX((size_t)1, width);
|
||||
height /= 2;
|
||||
height = MAX((size_t)1, height);
|
||||
|
||||
cudaArray_t levelFrom;
|
||||
checkCudaErrors(cudaGetMipmappedArrayLevel(&levelFrom, mipmapArray, level));
|
||||
cudaArray_t levelTo;
|
||||
checkCudaErrors(
|
||||
cudaGetMipmappedArrayLevel(&levelTo, mipmapArray, level + 1));
|
||||
cudaArray_t levelFrom;
|
||||
checkCudaErrors(cudaGetMipmappedArrayLevel(&levelFrom, mipmapArray, level));
|
||||
cudaArray_t levelTo;
|
||||
checkCudaErrors(cudaGetMipmappedArrayLevel(&levelTo, mipmapArray, level + 1));
|
||||
|
||||
cudaExtent levelToSize;
|
||||
checkCudaErrors(cudaArrayGetInfo(NULL, &levelToSize, NULL, levelTo));
|
||||
checkHost(levelToSize.width == width);
|
||||
checkHost(levelToSize.height == height);
|
||||
checkHost(levelToSize.depth == 0);
|
||||
cudaExtent levelToSize;
|
||||
checkCudaErrors(cudaArrayGetInfo(NULL, &levelToSize, NULL, levelTo));
|
||||
checkHost(levelToSize.width == width);
|
||||
checkHost(levelToSize.height == height);
|
||||
checkHost(levelToSize.depth == 0);
|
||||
|
||||
// generate texture object for reading
|
||||
cudaTextureObject_t texInput;
|
||||
cudaResourceDesc texRes;
|
||||
memset(&texRes, 0, sizeof(cudaResourceDesc));
|
||||
// generate texture object for reading
|
||||
cudaTextureObject_t texInput;
|
||||
cudaResourceDesc texRes;
|
||||
memset(&texRes, 0, sizeof(cudaResourceDesc));
|
||||
|
||||
texRes.resType = cudaResourceTypeArray;
|
||||
texRes.res.array.array = levelFrom;
|
||||
texRes.resType = cudaResourceTypeArray;
|
||||
texRes.res.array.array = levelFrom;
|
||||
|
||||
cudaTextureDesc texDescr;
|
||||
memset(&texDescr, 0, sizeof(cudaTextureDesc));
|
||||
cudaTextureDesc texDescr;
|
||||
memset(&texDescr, 0, sizeof(cudaTextureDesc));
|
||||
|
||||
texDescr.normalizedCoords = 1;
|
||||
texDescr.filterMode = cudaFilterModeLinear;
|
||||
texDescr.normalizedCoords = 1;
|
||||
texDescr.filterMode = cudaFilterModeLinear;
|
||||
|
||||
texDescr.addressMode[0] = cudaAddressModeClamp;
|
||||
texDescr.addressMode[1] = cudaAddressModeClamp;
|
||||
texDescr.addressMode[2] = cudaAddressModeClamp;
|
||||
texDescr.addressMode[0] = cudaAddressModeClamp;
|
||||
texDescr.addressMode[1] = cudaAddressModeClamp;
|
||||
texDescr.addressMode[2] = cudaAddressModeClamp;
|
||||
|
||||
texDescr.readMode = cudaReadModeNormalizedFloat;
|
||||
texDescr.readMode = cudaReadModeNormalizedFloat;
|
||||
|
||||
checkCudaErrors(
|
||||
cudaCreateTextureObject(&texInput, &texRes, &texDescr, NULL));
|
||||
checkCudaErrors(cudaCreateTextureObject(&texInput, &texRes, &texDescr, NULL));
|
||||
|
||||
// generate surface object for writing
|
||||
// generate surface object for writing
|
||||
|
||||
cudaSurfaceObject_t surfOutput;
|
||||
cudaResourceDesc surfRes;
|
||||
memset(&surfRes, 0, sizeof(cudaResourceDesc));
|
||||
surfRes.resType = cudaResourceTypeArray;
|
||||
surfRes.res.array.array = levelTo;
|
||||
cudaSurfaceObject_t surfOutput;
|
||||
cudaResourceDesc surfRes;
|
||||
memset(&surfRes, 0, sizeof(cudaResourceDesc));
|
||||
surfRes.resType = cudaResourceTypeArray;
|
||||
surfRes.res.array.array = levelTo;
|
||||
|
||||
checkCudaErrors(cudaCreateSurfaceObject(&surfOutput, &surfRes));
|
||||
checkCudaErrors(cudaCreateSurfaceObject(&surfOutput, &surfRes));
|
||||
|
||||
// run mipmap kernel
|
||||
dim3 blockSize(16, 16, 1);
|
||||
dim3 gridSize(((uint)width + blockSize.x - 1) / blockSize.x,
|
||||
((uint)height + blockSize.y - 1) / blockSize.y, 1);
|
||||
// run mipmap kernel
|
||||
dim3 blockSize(16, 16, 1);
|
||||
dim3 gridSize(((uint)width + blockSize.x - 1) / blockSize.x, ((uint)height + blockSize.y - 1) / blockSize.y, 1);
|
||||
|
||||
d_mipmap<<<gridSize, blockSize>>>(surfOutput, texInput, (uint)width,
|
||||
(uint)height);
|
||||
d_mipmap<<<gridSize, blockSize>>>(surfOutput, texInput, (uint)width, (uint)height);
|
||||
|
||||
checkCudaErrors(cudaDeviceSynchronize());
|
||||
checkCudaErrors(cudaGetLastError());
|
||||
checkCudaErrors(cudaDeviceSynchronize());
|
||||
checkCudaErrors(cudaGetLastError());
|
||||
|
||||
checkCudaErrors(cudaDestroySurfaceObject(surfOutput));
|
||||
checkCudaErrors(cudaDestroySurfaceObject(surfOutput));
|
||||
|
||||
checkCudaErrors(cudaDestroyTextureObject(texInput));
|
||||
checkCudaErrors(cudaDestroyTextureObject(texInput));
|
||||
|
||||
#ifdef SHOW_MIPMAPS
|
||||
// we blit the current mipmap back into first level
|
||||
cudaMemcpy3DParms copyParams = {0};
|
||||
copyParams.dstArray = levelFirst;
|
||||
copyParams.srcArray = levelTo;
|
||||
copyParams.extent = make_cudaExtent(width, height, 1);
|
||||
copyParams.kind = cudaMemcpyDeviceToDevice;
|
||||
checkCudaErrors(cudaMemcpy3D(©Params));
|
||||
// we blit the current mipmap back into first level
|
||||
cudaMemcpy3DParms copyParams = {0};
|
||||
copyParams.dstArray = levelFirst;
|
||||
copyParams.srcArray = levelTo;
|
||||
copyParams.extent = make_cudaExtent(width, height, 1);
|
||||
copyParams.kind = cudaMemcpyDeviceToDevice;
|
||||
checkCudaErrors(cudaMemcpy3D(©Params));
|
||||
#endif
|
||||
|
||||
level++;
|
||||
}
|
||||
level++;
|
||||
}
|
||||
}
|
||||
|
||||
uint getMipMapLevels(cudaExtent size) {
|
||||
size_t sz = MAX(MAX(size.width, size.height), size.depth);
|
||||
uint getMipMapLevels(cudaExtent size)
|
||||
{
|
||||
size_t sz = MAX(MAX(size.width, size.height), size.depth);
|
||||
|
||||
uint levels = 0;
|
||||
uint levels = 0;
|
||||
|
||||
while (sz) {
|
||||
sz /= 2;
|
||||
levels++;
|
||||
}
|
||||
while (sz) {
|
||||
sz /= 2;
|
||||
levels++;
|
||||
}
|
||||
|
||||
return levels;
|
||||
return levels;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Initalization
|
||||
|
||||
extern "C" void randomizeAtlas() {
|
||||
uint2 *h_data = (uint2 *)atlasImage.h_data;
|
||||
extern "C" void randomizeAtlas()
|
||||
{
|
||||
uint2 *h_data = (uint2 *)atlasImage.h_data;
|
||||
|
||||
// assign random texture object handles to our atlas image tiles
|
||||
for (size_t i = 0; i < atlasImage.size.width * atlasImage.size.height; i++) {
|
||||
// assign random texture object handles to our atlas image tiles
|
||||
for (size_t i = 0; i < atlasImage.size.width * atlasImage.size.height; i++) {
|
||||
#ifdef SHOW_MIPMAPS
|
||||
h_data[i] = encodeTextureObject(contentImages[0].textureObject);
|
||||
h_data[i] = encodeTextureObject(contentImages[0].textureObject);
|
||||
#else
|
||||
h_data[i] = encodeTextureObject(
|
||||
contentImages[rand() % contentImages.size()].textureObject);
|
||||
h_data[i] = encodeTextureObject(contentImages[rand() % contentImages.size()].textureObject);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
// copy data to atlas array
|
||||
cudaMemcpy3DParms copyParams = {0};
|
||||
copyParams.srcPtr = make_cudaPitchedPtr(
|
||||
atlasImage.h_data, atlasImage.size.width * sizeof(uint2),
|
||||
atlasImage.size.width, atlasImage.size.height);
|
||||
copyParams.dstArray = atlasImage.dataArray;
|
||||
copyParams.extent = atlasImage.size;
|
||||
copyParams.extent.depth = 1;
|
||||
copyParams.kind = cudaMemcpyHostToDevice;
|
||||
checkCudaErrors(cudaMemcpy3D(©Params));
|
||||
// copy data to atlas array
|
||||
cudaMemcpy3DParms copyParams = {0};
|
||||
copyParams.srcPtr = make_cudaPitchedPtr(
|
||||
atlasImage.h_data, atlasImage.size.width * sizeof(uint2), atlasImage.size.width, atlasImage.size.height);
|
||||
copyParams.dstArray = atlasImage.dataArray;
|
||||
copyParams.extent = atlasImage.size;
|
||||
copyParams.extent.depth = 1;
|
||||
copyParams.kind = cudaMemcpyHostToDevice;
|
||||
checkCudaErrors(cudaMemcpy3D(©Params));
|
||||
};
|
||||
|
||||
extern "C" void deinitAtlasAndImages() {
|
||||
for (size_t i = 0; i < contentImages.size(); i++) {
|
||||
Image &image = contentImages[i];
|
||||
extern "C" void deinitAtlasAndImages()
|
||||
{
|
||||
for (size_t i = 0; i < contentImages.size(); i++) {
|
||||
Image &image = contentImages[i];
|
||||
|
||||
if (image.h_data) {
|
||||
free(image.h_data);
|
||||
if (image.h_data) {
|
||||
free(image.h_data);
|
||||
}
|
||||
|
||||
if (image.textureObject) {
|
||||
checkCudaErrors(cudaDestroyTextureObject(image.textureObject));
|
||||
}
|
||||
|
||||
if (image.mipmapArray) {
|
||||
checkCudaErrors(cudaFreeMipmappedArray(image.mipmapArray));
|
||||
}
|
||||
}
|
||||
|
||||
if (image.textureObject) {
|
||||
checkCudaErrors(cudaDestroyTextureObject(image.textureObject));
|
||||
if (atlasImage.h_data) {
|
||||
free(atlasImage.h_data);
|
||||
}
|
||||
|
||||
if (image.mipmapArray) {
|
||||
checkCudaErrors(cudaFreeMipmappedArray(image.mipmapArray));
|
||||
if (atlasImage.textureObject) {
|
||||
checkCudaErrors(cudaDestroyTextureObject(atlasImage.textureObject));
|
||||
}
|
||||
}
|
||||
|
||||
if (atlasImage.h_data) {
|
||||
free(atlasImage.h_data);
|
||||
}
|
||||
|
||||
if (atlasImage.textureObject) {
|
||||
checkCudaErrors(cudaDestroyTextureObject(atlasImage.textureObject));
|
||||
}
|
||||
|
||||
if (atlasImage.dataArray) {
|
||||
checkCudaErrors(cudaFreeArray(atlasImage.dataArray));
|
||||
}
|
||||
if (atlasImage.dataArray) {
|
||||
checkCudaErrors(cudaFreeArray(atlasImage.dataArray));
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" void initAtlasAndImages(const Image *images, size_t numImages,
|
||||
cudaExtent atlasSize) {
|
||||
// create individual textures
|
||||
contentImages.resize(numImages);
|
||||
extern "C" void initAtlasAndImages(const Image *images, size_t numImages, cudaExtent atlasSize)
|
||||
{
|
||||
// create individual textures
|
||||
contentImages.resize(numImages);
|
||||
|
||||
for (size_t i = 0; i < numImages; i++) {
|
||||
Image &image = contentImages[i];
|
||||
image.size = images[i].size;
|
||||
image.size.depth = 0;
|
||||
image.type = cudaResourceTypeMipmappedArray;
|
||||
for (size_t i = 0; i < numImages; i++) {
|
||||
Image &image = contentImages[i];
|
||||
image.size = images[i].size;
|
||||
image.size.depth = 0;
|
||||
image.type = cudaResourceTypeMipmappedArray;
|
||||
|
||||
// how many mipmaps we need
|
||||
uint levels = getMipMapLevels(image.size);
|
||||
highestLod = MAX(highestLod, (float)levels - 1);
|
||||
// how many mipmaps we need
|
||||
uint levels = getMipMapLevels(image.size);
|
||||
highestLod = MAX(highestLod, (float)levels - 1);
|
||||
|
||||
cudaChannelFormatDesc desc = cudaCreateChannelDesc<uchar4>();
|
||||
checkCudaErrors(cudaMallocMipmappedArray(&image.mipmapArray, &desc,
|
||||
image.size, levels));
|
||||
cudaChannelFormatDesc desc = cudaCreateChannelDesc<uchar4>();
|
||||
checkCudaErrors(cudaMallocMipmappedArray(&image.mipmapArray, &desc, image.size, levels));
|
||||
|
||||
// upload level 0
|
||||
cudaArray_t level0;
|
||||
checkCudaErrors(cudaGetMipmappedArrayLevel(&level0, image.mipmapArray, 0));
|
||||
// upload level 0
|
||||
cudaArray_t level0;
|
||||
checkCudaErrors(cudaGetMipmappedArrayLevel(&level0, image.mipmapArray, 0));
|
||||
|
||||
cudaMemcpy3DParms copyParams = {0};
|
||||
copyParams.srcPtr =
|
||||
make_cudaPitchedPtr(images[i].h_data, image.size.width * sizeof(uchar4),
|
||||
image.size.width, image.size.height);
|
||||
copyParams.dstArray = level0;
|
||||
copyParams.extent = image.size;
|
||||
copyParams.extent.depth = 1;
|
||||
copyParams.kind = cudaMemcpyHostToDevice;
|
||||
checkCudaErrors(cudaMemcpy3D(©Params));
|
||||
cudaMemcpy3DParms copyParams = {0};
|
||||
copyParams.srcPtr = make_cudaPitchedPtr(
|
||||
images[i].h_data, image.size.width * sizeof(uchar4), image.size.width, image.size.height);
|
||||
copyParams.dstArray = level0;
|
||||
copyParams.extent = image.size;
|
||||
copyParams.extent.depth = 1;
|
||||
copyParams.kind = cudaMemcpyHostToDevice;
|
||||
checkCudaErrors(cudaMemcpy3D(©Params));
|
||||
|
||||
// compute rest of mipmaps based on level 0
|
||||
generateMipMaps(image.mipmapArray, image.size);
|
||||
// compute rest of mipmaps based on level 0
|
||||
generateMipMaps(image.mipmapArray, image.size);
|
||||
|
||||
// generate bindless texture object
|
||||
// generate bindless texture object
|
||||
|
||||
cudaResourceDesc resDescr;
|
||||
memset(&resDescr, 0, sizeof(cudaResourceDesc));
|
||||
cudaResourceDesc resDescr;
|
||||
memset(&resDescr, 0, sizeof(cudaResourceDesc));
|
||||
|
||||
resDescr.resType = cudaResourceTypeMipmappedArray;
|
||||
resDescr.res.mipmap.mipmap = image.mipmapArray;
|
||||
resDescr.resType = cudaResourceTypeMipmappedArray;
|
||||
resDescr.res.mipmap.mipmap = image.mipmapArray;
|
||||
|
||||
cudaTextureDesc texDescr;
|
||||
memset(&texDescr, 0, sizeof(cudaTextureDesc));
|
||||
|
||||
texDescr.normalizedCoords = 1;
|
||||
texDescr.filterMode = cudaFilterModeLinear;
|
||||
texDescr.mipmapFilterMode = cudaFilterModeLinear;
|
||||
|
||||
texDescr.addressMode[0] = cudaAddressModeClamp;
|
||||
texDescr.addressMode[1] = cudaAddressModeClamp;
|
||||
texDescr.addressMode[2] = cudaAddressModeClamp;
|
||||
|
||||
texDescr.maxMipmapLevelClamp = float(levels - 1);
|
||||
|
||||
texDescr.readMode = cudaReadModeNormalizedFloat;
|
||||
|
||||
checkCudaErrors(cudaCreateTextureObject(&image.textureObject, &resDescr, &texDescr, NULL));
|
||||
}
|
||||
|
||||
// create atlas array
|
||||
cudaChannelFormatDesc channelDesc = cudaCreateChannelDesc<uint2>();
|
||||
checkCudaErrors(cudaMallocArray(&atlasImage.dataArray, &channelDesc, atlasSize.width, atlasSize.height));
|
||||
atlasImage.h_data = malloc(atlasSize.width * atlasSize.height * sizeof(uint2));
|
||||
atlasImage.type = cudaResourceTypeArray;
|
||||
atlasImage.size = atlasSize;
|
||||
|
||||
cudaResourceDesc texRes;
|
||||
memset(&texRes, 0, sizeof(cudaResourceDesc));
|
||||
|
||||
texRes.resType = cudaResourceTypeArray;
|
||||
texRes.res.array.array = atlasImage.dataArray;
|
||||
|
||||
cudaTextureDesc texDescr;
|
||||
memset(&texDescr, 0, sizeof(cudaTextureDesc));
|
||||
|
||||
texDescr.normalizedCoords = 1;
|
||||
texDescr.filterMode = cudaFilterModeLinear;
|
||||
texDescr.mipmapFilterMode = cudaFilterModeLinear;
|
||||
texDescr.normalizedCoords = true;
|
||||
texDescr.filterMode = cudaFilterModePoint;
|
||||
texDescr.addressMode[0] = cudaAddressModeClamp;
|
||||
texDescr.addressMode[1] = cudaAddressModeClamp;
|
||||
texDescr.addressMode[1] = cudaAddressModeClamp;
|
||||
texDescr.readMode = cudaReadModeElementType;
|
||||
|
||||
texDescr.addressMode[0] = cudaAddressModeClamp;
|
||||
texDescr.addressMode[1] = cudaAddressModeClamp;
|
||||
texDescr.addressMode[2] = cudaAddressModeClamp;
|
||||
checkCudaErrors(cudaCreateTextureObject(&atlasImage.textureObject, &texRes, &texDescr, NULL));
|
||||
|
||||
texDescr.maxMipmapLevelClamp = float(levels - 1);
|
||||
|
||||
texDescr.readMode = cudaReadModeNormalizedFloat;
|
||||
|
||||
checkCudaErrors(cudaCreateTextureObject(&image.textureObject, &resDescr,
|
||||
&texDescr, NULL));
|
||||
}
|
||||
|
||||
// create atlas array
|
||||
cudaChannelFormatDesc channelDesc = cudaCreateChannelDesc<uint2>();
|
||||
checkCudaErrors(cudaMallocArray(&atlasImage.dataArray, &channelDesc,
|
||||
atlasSize.width, atlasSize.height));
|
||||
atlasImage.h_data =
|
||||
malloc(atlasSize.width * atlasSize.height * sizeof(uint2));
|
||||
atlasImage.type = cudaResourceTypeArray;
|
||||
atlasImage.size = atlasSize;
|
||||
|
||||
cudaResourceDesc texRes;
|
||||
memset(&texRes, 0, sizeof(cudaResourceDesc));
|
||||
|
||||
texRes.resType = cudaResourceTypeArray;
|
||||
texRes.res.array.array = atlasImage.dataArray;
|
||||
|
||||
cudaTextureDesc texDescr;
|
||||
memset(&texDescr, 0, sizeof(cudaTextureDesc));
|
||||
|
||||
texDescr.normalizedCoords = true;
|
||||
texDescr.filterMode = cudaFilterModePoint;
|
||||
texDescr.addressMode[0] = cudaAddressModeClamp;
|
||||
texDescr.addressMode[1] = cudaAddressModeClamp;
|
||||
texDescr.addressMode[1] = cudaAddressModeClamp;
|
||||
texDescr.readMode = cudaReadModeElementType;
|
||||
|
||||
checkCudaErrors(cudaCreateTextureObject(&atlasImage.textureObject, &texRes,
|
||||
&texDescr, NULL));
|
||||
|
||||
randomizeAtlas();
|
||||
randomizeAtlas();
|
||||
}
|
||||
|
||||
#endif // #ifndef _SIMPLETEXTURE3D_KERNEL_CU_
|
||||
#endif // #ifndef _SIMPLETEXTURE3D_KERNEL_CU_
|
||||
|
||||
Reference in New Issue
Block a user