mirror of
https://github.com/NVIDIA/cuda-samples.git
synced 2026-10-13 00:08:26 +08:00
CUDA 13.2 samples update (#432)
- Added Python samples for CUDA Python 1.0 release - Renamed top-level `Samples` directory to `cpp` to accommodate Python samples.
This commit is contained in:
18
cpp/3_CUDA_Features/bindlessTexture/.vscode/c_cpp_properties.json
vendored
Normal file
18
cpp/3_CUDA_Features/bindlessTexture/.vscode/c_cpp_properties.json
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Linux",
|
||||
"includePath": [
|
||||
"${workspaceFolder}/**",
|
||||
"${workspaceFolder}/../../../Common"
|
||||
],
|
||||
"defines": [],
|
||||
"compilerPath": "/usr/local/cuda/bin/nvcc",
|
||||
"cStandard": "gnu17",
|
||||
"cppStandard": "gnu++14",
|
||||
"intelliSenseMode": "linux-gcc-x64",
|
||||
"configurationProvider": "ms-vscode.makefile-tools"
|
||||
}
|
||||
],
|
||||
"version": 4
|
||||
}
|
||||
7
cpp/3_CUDA_Features/bindlessTexture/.vscode/extensions.json
vendored
Normal file
7
cpp/3_CUDA_Features/bindlessTexture/.vscode/extensions.json
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"recommendations": [
|
||||
"nvidia.nsight-vscode-edition",
|
||||
"ms-vscode.cpptools",
|
||||
"ms-vscode.makefile-tools"
|
||||
]
|
||||
}
|
||||
96
cpp/3_CUDA_Features/bindlessTexture/CMakeLists.txt
Normal file
96
cpp/3_CUDA_Features/bindlessTexture/CMakeLists.txt
Normal file
@@ -0,0 +1,96 @@
|
||||
cmake_minimum_required(VERSION 3.20)
|
||||
|
||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/../../../cmake/Modules")
|
||||
|
||||
project(bindlessTexture LANGUAGES C CXX CUDA)
|
||||
|
||||
find_package(CUDAToolkit REQUIRED)
|
||||
|
||||
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
||||
|
||||
set(CMAKE_CUDA_ARCHITECTURES 75 80 86 87 89 90 100 110 120)
|
||||
set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -Wno-deprecated-gpu-targets")
|
||||
if(ENABLE_CUDA_DEBUG)
|
||||
set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -G") # enable cuda-gdb (may significantly affect performance on some targets)
|
||||
else()
|
||||
set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -lineinfo") # add line information to all builds for debug tools (exclusive to -G option)
|
||||
endif()
|
||||
|
||||
# Include directories and libraries
|
||||
include_directories(../../../Common)
|
||||
|
||||
if(WIN32)
|
||||
set(PC_GLUT_INCLUDE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/../../../Common")
|
||||
set(PC_GLUT_LIBRARY_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/../../../Common/lib/x64")
|
||||
# The GLEW library built on Windows on Arm system is named as glew32.lib/glew32.dll by default.
|
||||
if(EXISTS "${PC_GLUT_LIBRARY_DIRS}/glew32.lib")
|
||||
set(GLEW_LIB_NAME "glew32")
|
||||
else()
|
||||
set(GLEW_LIB_NAME "glew64")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
find_package(OpenGL)
|
||||
find_package(GLUT)
|
||||
|
||||
# Source file
|
||||
if(${OpenGL_FOUND})
|
||||
if (${GLUT_FOUND})
|
||||
# Add target for bindlessTexture
|
||||
add_executable(bindlessTexture bindlessTexture.cpp bindlessTexture_kernel.cu)
|
||||
|
||||
target_compile_options(bindlessTexture PRIVATE $<$<COMPILE_LANGUAGE:CUDA>:--extended-lambda>)
|
||||
|
||||
target_compile_features(bindlessTexture PRIVATE cxx_std_17 cuda_std_17)
|
||||
|
||||
set_target_properties(bindlessTexture PROPERTIES CUDA_SEPARABLE_COMPILATION ON)
|
||||
|
||||
target_include_directories(bindlessTexture PUBLIC
|
||||
${OPENGL_INCLUDE_DIR}
|
||||
${CUDAToolkit_INCLUDE_DIRS}
|
||||
${GLUT_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
target_link_libraries(bindlessTexture
|
||||
${OPENGL_LIBRARIES}
|
||||
${GLUT_LIBRARIES}
|
||||
)
|
||||
|
||||
# Copy clock_kernel.cu to the output directory
|
||||
add_custom_command(TARGET bindlessTexture POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_directory
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/data
|
||||
${CMAKE_CURRENT_BINARY_DIR}/data
|
||||
)
|
||||
|
||||
if(WIN32)
|
||||
target_link_libraries(bindlessTexture
|
||||
${PC_GLUT_LIBRARY_DIRS}/freeglut.lib
|
||||
${PC_GLUT_LIBRARY_DIRS}/${GLEW_LIB_NAME}.lib
|
||||
)
|
||||
|
||||
add_custom_command(TARGET bindlessTexture
|
||||
POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../../bin/win64/$<CONFIGURATION>/freeglut.dll
|
||||
${CMAKE_CURRENT_BINARY_DIR}/$<CONFIGURATION>
|
||||
)
|
||||
|
||||
add_custom_command(TARGET bindlessTexture
|
||||
POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../../bin/win64/$<CONFIGURATION>/${GLEW_LIB_NAME}.dll
|
||||
${CMAKE_CURRENT_BINARY_DIR}/$<CONFIGURATION>
|
||||
)
|
||||
endif()
|
||||
|
||||
else()
|
||||
message(STATUS "GLUT not found - will not build sample 'bindlessTexture'")
|
||||
endif()
|
||||
else()
|
||||
message(STATUS "OpenGL not found - will not build sample 'bindlessTexture'")
|
||||
endif()
|
||||
|
||||
# Include installation configuration
|
||||
include(${CMAKE_CURRENT_SOURCE_DIR}/../../../cmake/InstallSamples.cmake)
|
||||
setup_samples_install()
|
||||
34
cpp/3_CUDA_Features/bindlessTexture/README.md
Normal file
34
cpp/3_CUDA_Features/bindlessTexture/README.md
Normal file
@@ -0,0 +1,34 @@
|
||||
# bindlessTexture - Bindless Texture
|
||||
|
||||
## Description
|
||||
|
||||
This example demonstrates use of cudaSurfaceObject, cudaTextureObject, and MipMap support in CUDA. A GPU with Compute Capability SM 3.0 is required to run the sample.
|
||||
|
||||
## Key Concepts
|
||||
|
||||
Graphics Interop, Texture
|
||||
|
||||
## Supported SM Architectures
|
||||
|
||||
## Supported OSes
|
||||
|
||||
Linux, Windows
|
||||
|
||||
## Supported CPU Architecture
|
||||
|
||||
x86_64, armv7l
|
||||
|
||||
## CUDA APIs involved
|
||||
|
||||
### [CUDA Runtime API](http://docs.nvidia.com/cuda/cuda-runtime-api/index.html)
|
||||
cudaMemcpy, cudaGetMipmappedArrayLevel, cudaGraphicsMapResources, cudaDestroySurfaceObject, cudaExtent, cudaDeviceSynchronize, cudaCreateSurfaceObject, cudaMallocMipmappedArray, cudaPitchedPtr, cudaGraphicsResourceGetMappedPointer, cudaCreateTextureObject, cudaGraphicsUnmapResources, cudaMallocArray, cudaFreeArray, cudaArrayGetInfo, cudaGetLastError, cudaDestroyTextureObject, cudaGraphicsGLRegisterBuffer, cudaFreeMipmappedArray, cudaFree, cudaGraphicsUnregisterResource, cudaMalloc
|
||||
|
||||
## Dependencies needed to build/run
|
||||
[X11](../../../README.md#x11), [OpenGL](../../../README.md#opengl), [Freeglut](../../../README.md#freeglut), [GLEW](../../../README.md#glew)
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Download and install the [CUDA Toolkit](https://developer.nvidia.com/cuda-downloads) for your corresponding platform.
|
||||
Make sure the dependencies mentioned in [Dependencies]() section above are installed.
|
||||
|
||||
## References (for more details)
|
||||
420
cpp/3_CUDA_Features/bindlessTexture/bindlessTexture.cpp
Normal file
420
cpp/3_CUDA_Features/bindlessTexture/bindlessTexture.cpp
Normal file
@@ -0,0 +1,420 @@
|
||||
/* Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
Bindless Texture/Surface
|
||||
|
||||
This sample generates a few 2D textures and uses cudaTextureObjects to
|
||||
perform pseudo virtual texturing for display. One 2D texture stores
|
||||
references to other textures.
|
||||
Furthermore use of mip mapping is shown using both cudaTextureObjects
|
||||
and cudaSurfaceObjects.
|
||||
|
||||
Look into the bindlessTexture_kernel.cu file for most relevant code.
|
||||
*/
|
||||
|
||||
#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>
|
||||
#ifndef glutCloseFunc
|
||||
#define glutCloseFunc glutWMCloseFunc
|
||||
#endif
|
||||
#else
|
||||
#include <GL/freeglut.h>
|
||||
#endif
|
||||
|
||||
#include <cuda_gl_interop.h>
|
||||
#include <helper_functions.h>
|
||||
|
||||
#include "bindlessTexture.h"
|
||||
|
||||
#define MAX_EPSILON_ERROR 5.0f
|
||||
#define THRESHOLD 0.15f
|
||||
|
||||
const char *sSDKsample = "CUDA bindlessTexture";
|
||||
|
||||
const char *imageFilenames[] = {
|
||||
"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);
|
||||
|
||||
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)
|
||||
|
||||
bool animate = true;
|
||||
|
||||
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;
|
||||
|
||||
int *pArgc = NULL;
|
||||
char **pArgv = NULL;
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
glutSetWindowTitle(fps);
|
||||
fpsCount = 0;
|
||||
|
||||
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));
|
||||
|
||||
// call CUDA kernel, writing results to PBO
|
||||
renderAtlasImage(windowGridSize, windowBlockSize, d_output, windowSize.x, windowSize.y, lod);
|
||||
|
||||
getLastCudaError("render_kernel failed");
|
||||
|
||||
checkCudaErrors(cudaGraphicsUnmapResources(1, &cuda_pbo_resource, 0));
|
||||
}
|
||||
|
||||
// display results using OpenGL (called by GLUT)
|
||||
void display()
|
||||
{
|
||||
sdkStartTimer(&timer);
|
||||
|
||||
render();
|
||||
|
||||
// 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);
|
||||
|
||||
glutSwapBuffers();
|
||||
glutReportErrors();
|
||||
|
||||
sdkStopTimer(&timer);
|
||||
computeFPS();
|
||||
}
|
||||
|
||||
void idle()
|
||||
{
|
||||
if (animate) {
|
||||
lod += 0.02f;
|
||||
glutPostRedisplay();
|
||||
}
|
||||
}
|
||||
|
||||
void keyboard(unsigned char key, int x, int y)
|
||||
{
|
||||
switch (key) {
|
||||
case 27:
|
||||
#if defined(__APPLE__) || defined(MACOSX)
|
||||
exit(EXIT_SUCCESS);
|
||||
#else
|
||||
glutDestroyWindow(glutGetWindow());
|
||||
return;
|
||||
#endif
|
||||
break;
|
||||
|
||||
case '=':
|
||||
case '+':
|
||||
lod += 0.25f;
|
||||
break;
|
||||
|
||||
case '-':
|
||||
lod -= 0.25f;
|
||||
break;
|
||||
|
||||
case 'r':
|
||||
randomizeAtlas();
|
||||
break;
|
||||
|
||||
case ' ':
|
||||
animate = !animate;
|
||||
lod = 0.0f;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
glutPostRedisplay();
|
||||
}
|
||||
|
||||
void reshape(int x, int y)
|
||||
{
|
||||
glViewport(0, 0, x, y);
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
|
||||
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);
|
||||
|
||||
// unregister this buffer object from CUDA C
|
||||
if (cuda_pbo_resource) {
|
||||
cudaGraphicsUnregisterResource(cuda_pbo_resource);
|
||||
glDeleteBuffers(1, &pbo);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
// 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");
|
||||
|
||||
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 (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);
|
||||
}
|
||||
|
||||
initAtlasAndImages(&images[0], images.size(), atlasSize);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Program main
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
sdkCreateTimer(&timer);
|
||||
|
||||
pArgc = &argc;
|
||||
pArgv = argv;
|
||||
|
||||
char *ref_file = NULL;
|
||||
|
||||
#if defined(__linux__)
|
||||
setenv("DISPLAY", ":0", 0);
|
||||
#endif
|
||||
|
||||
printf("%s Starting...\n\n", sSDKsample);
|
||||
|
||||
if (checkCmdLineFlag(argc, (const char **)argv, "file")) {
|
||||
fpsLimit = frameCheckNumber;
|
||||
getCmdLineArgumentString(argc, (const char **)argv, "file", &ref_file);
|
||||
}
|
||||
|
||||
srand(15234);
|
||||
|
||||
// use command-line specified CUDA device, otherwise use device with highest
|
||||
// Gflops/s
|
||||
findCudaDevice(argc, (const char **)argv);
|
||||
|
||||
if (!ref_file) {
|
||||
initGL(&argc, argv);
|
||||
|
||||
// OpenGL buffers
|
||||
initGLBuffers();
|
||||
}
|
||||
|
||||
if (!checkCudaCapabilities(3, 0)) {
|
||||
cleanup();
|
||||
|
||||
exit(EXIT_WAIVED);
|
||||
}
|
||||
|
||||
loadImageData(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");
|
||||
|
||||
#if defined(__APPLE__) || defined(MACOSX)
|
||||
atexit(cleanup_all);
|
||||
#else
|
||||
glutCloseFunc(cleanup_all);
|
||||
#endif
|
||||
|
||||
glutMainLoop();
|
||||
}
|
||||
66
cpp/3_CUDA_Features/bindlessTexture/bindlessTexture.h
Normal file
66
cpp/3_CUDA_Features/bindlessTexture/bindlessTexture.h
Normal file
@@ -0,0 +1,66 @@
|
||||
/* Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _BINDLESSTEXTURE_CU_
|
||||
#define _BINDLESSTEXTURE_CU_
|
||||
|
||||
// includes, cuda
|
||||
#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 char uchar;
|
||||
|
||||
#pragma pack(push, 4)
|
||||
struct Image
|
||||
{
|
||||
void *h_data;
|
||||
cudaExtent size;
|
||||
cudaResourceType type;
|
||||
cudaArray_t dataArray;
|
||||
cudaMipmappedArray_t mipmapArray;
|
||||
cudaTextureObject_t textureObject;
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
#define checkHost(condition) _checkHost(condition, #condition, __FILE__, __LINE__, __FUNCTION__)
|
||||
|
||||
#endif
|
||||
415
cpp/3_CUDA_Features/bindlessTexture/bindlessTexture_kernel.cu
Normal file
415
cpp/3_CUDA_Features/bindlessTexture/bindlessTexture_kernel.cu
Normal file
@@ -0,0 +1,415 @@
|
||||
/* Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
This sample has two kernels, one doing the rendering every frame, and
|
||||
another one used to generate the mip map levels at startup.
|
||||
|
||||
For rendering we use a "virtual" texturing approach, where one 2d texture
|
||||
stores pointers to the actual textures used. This can be achieved by the
|
||||
new cudaTextureObject introduced in CUDA 5.0 and requiring sm3+ hardware.
|
||||
|
||||
The mipmap generation kernel uses cudaSurfaceObject and cudaTextureObject
|
||||
passed as kernel arguments to compute the higher mip map level based on
|
||||
the lower.
|
||||
*/
|
||||
|
||||
#ifndef _BINDLESSTEXTURE_KERNEL_CU_
|
||||
#define _BINDLESSTEXTURE_KERNEL_CU_
|
||||
|
||||
#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
|
||||
|
||||
// local references to resources
|
||||
|
||||
Image atlasImage;
|
||||
std::vector<Image> contentImages;
|
||||
float highestLod = 1.0f;
|
||||
|
||||
#ifndef MAX
|
||||
#define MAX(a, b) ((a > b) ? a : b)
|
||||
#endif
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__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);
|
||||
}
|
||||
|
||||
__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);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Rendering
|
||||
|
||||
// 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;
|
||||
|
||||
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);
|
||||
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
#endif
|
||||
|
||||
d_render<<<gridSize, blockSize>>>(d_output, imageW, imageH, lod, atlasImage.textureObject);
|
||||
|
||||
checkCudaErrors(cudaGetLastError());
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// MipMap Generation
|
||||
|
||||
// A key benefit of using the new surface objects is that we don't need any
|
||||
// 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;
|
||||
|
||||
float px = 1.0 / float(imageW);
|
||||
float py = 1.0 / float(imageH);
|
||||
|
||||
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));
|
||||
|
||||
color /= 4.0;
|
||||
color *= 255.0;
|
||||
color = fminf(color, make_float4(255.0));
|
||||
|
||||
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;
|
||||
|
||||
#ifdef SHOW_MIPMAPS
|
||||
cudaArray_t levelFirst;
|
||||
checkCudaErrors(cudaGetMipmappedArrayLevel(&levelFirst, mipmapArray, 0));
|
||||
#endif
|
||||
|
||||
uint level = 0;
|
||||
|
||||
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));
|
||||
|
||||
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));
|
||||
|
||||
texRes.resType = cudaResourceTypeArray;
|
||||
texRes.res.array.array = levelFrom;
|
||||
|
||||
cudaTextureDesc texDescr;
|
||||
memset(&texDescr, 0, sizeof(cudaTextureDesc));
|
||||
|
||||
texDescr.normalizedCoords = 1;
|
||||
texDescr.filterMode = cudaFilterModeLinear;
|
||||
|
||||
texDescr.addressMode[0] = cudaAddressModeClamp;
|
||||
texDescr.addressMode[1] = cudaAddressModeClamp;
|
||||
texDescr.addressMode[2] = cudaAddressModeClamp;
|
||||
|
||||
texDescr.readMode = cudaReadModeNormalizedFloat;
|
||||
|
||||
checkCudaErrors(cudaCreateTextureObject(&texInput, &texRes, &texDescr, NULL));
|
||||
|
||||
// generate surface object for writing
|
||||
|
||||
cudaSurfaceObject_t surfOutput;
|
||||
cudaResourceDesc surfRes;
|
||||
memset(&surfRes, 0, sizeof(cudaResourceDesc));
|
||||
surfRes.resType = cudaResourceTypeArray;
|
||||
surfRes.res.array.array = levelTo;
|
||||
|
||||
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);
|
||||
|
||||
d_mipmap<<<gridSize, blockSize>>>(surfOutput, texInput, (uint)width, (uint)height);
|
||||
|
||||
checkCudaErrors(cudaDeviceSynchronize());
|
||||
checkCudaErrors(cudaGetLastError());
|
||||
|
||||
checkCudaErrors(cudaDestroySurfaceObject(surfOutput));
|
||||
|
||||
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));
|
||||
#endif
|
||||
|
||||
level++;
|
||||
}
|
||||
}
|
||||
|
||||
uint getMipMapLevels(cudaExtent size)
|
||||
{
|
||||
size_t sz = MAX(MAX(size.width, size.height), size.depth);
|
||||
|
||||
uint levels = 0;
|
||||
|
||||
while (sz) {
|
||||
sz /= 2;
|
||||
levels++;
|
||||
}
|
||||
|
||||
return levels;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Initalization
|
||||
|
||||
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++) {
|
||||
#ifdef SHOW_MIPMAPS
|
||||
h_data[i] = encodeTextureObject(contentImages[0].textureObject);
|
||||
#else
|
||||
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));
|
||||
};
|
||||
|
||||
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.textureObject) {
|
||||
checkCudaErrors(cudaDestroyTextureObject(image.textureObject));
|
||||
}
|
||||
|
||||
if (image.mipmapArray) {
|
||||
checkCudaErrors(cudaFreeMipmappedArray(image.mipmapArray));
|
||||
}
|
||||
}
|
||||
|
||||
if (atlasImage.h_data) {
|
||||
free(atlasImage.h_data);
|
||||
}
|
||||
|
||||
if (atlasImage.textureObject) {
|
||||
checkCudaErrors(cudaDestroyTextureObject(atlasImage.textureObject));
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
cudaChannelFormatDesc desc = cudaCreateChannelDesc<uchar4>();
|
||||
checkCudaErrors(cudaMallocMipmappedArray(&image.mipmapArray, &desc, image.size, levels));
|
||||
|
||||
// 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));
|
||||
|
||||
// compute rest of mipmaps based on level 0
|
||||
generateMipMaps(image.mipmapArray, image.size);
|
||||
|
||||
// generate bindless texture object
|
||||
|
||||
cudaResourceDesc resDescr;
|
||||
memset(&resDescr, 0, sizeof(cudaResourceDesc));
|
||||
|
||||
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 = 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();
|
||||
}
|
||||
|
||||
#endif // #ifndef _SIMPLETEXTURE3D_KERNEL_CU_
|
||||
3530
cpp/3_CUDA_Features/bindlessTexture/data/flower.ppm
Normal file
3530
cpp/3_CUDA_Features/bindlessTexture/data/flower.ppm
Normal file
File diff suppressed because one or more lines are too long
BIN
cpp/3_CUDA_Features/bindlessTexture/data/person.ppm
Normal file
BIN
cpp/3_CUDA_Features/bindlessTexture/data/person.ppm
Normal file
Binary file not shown.
BIN
cpp/3_CUDA_Features/bindlessTexture/data/ref_bindlessTexture.bin
Normal file
BIN
cpp/3_CUDA_Features/bindlessTexture/data/ref_bindlessTexture.bin
Normal file
Binary file not shown.
BIN
cpp/3_CUDA_Features/bindlessTexture/data/sponge.ppm
Normal file
BIN
cpp/3_CUDA_Features/bindlessTexture/data/sponge.ppm
Normal file
Binary file not shown.
BIN
cpp/3_CUDA_Features/bindlessTexture/doc/sshot_lg.JPG
Normal file
BIN
cpp/3_CUDA_Features/bindlessTexture/doc/sshot_lg.JPG
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 57 KiB |
BIN
cpp/3_CUDA_Features/bindlessTexture/doc/sshot_md.JPG
Normal file
BIN
cpp/3_CUDA_Features/bindlessTexture/doc/sshot_md.JPG
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 18 KiB |
BIN
cpp/3_CUDA_Features/bindlessTexture/doc/sshot_sm.JPG
Normal file
BIN
cpp/3_CUDA_Features/bindlessTexture/doc/sshot_sm.JPG
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 6.0 KiB |
Reference in New Issue
Block a user