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/5_Domain_Specific/postProcessGL/.vscode/c_cpp_properties.json
vendored
Normal file
18
cpp/5_Domain_Specific/postProcessGL/.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/5_Domain_Specific/postProcessGL/.vscode/extensions.json
vendored
Normal file
7
cpp/5_Domain_Specific/postProcessGL/.vscode/extensions.json
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"recommendations": [
|
||||
"nvidia.nsight-vscode-edition",
|
||||
"ms-vscode.cpptools",
|
||||
"ms-vscode.makefile-tools"
|
||||
]
|
||||
}
|
||||
95
cpp/5_Domain_Specific/postProcessGL/CMakeLists.txt
Normal file
95
cpp/5_Domain_Specific/postProcessGL/CMakeLists.txt
Normal file
@@ -0,0 +1,95 @@
|
||||
cmake_minimum_required(VERSION 3.20)
|
||||
|
||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/../../../cmake/Modules")
|
||||
|
||||
project(postProcessGL 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 postProcessGL
|
||||
add_executable(postProcessGL main.cpp postProcessGL.cu)
|
||||
|
||||
target_compile_options(postProcessGL PRIVATE $<$<COMPILE_LANGUAGE:CUDA>:--extended-lambda>)
|
||||
|
||||
target_compile_features(postProcessGL PRIVATE cxx_std_17 cuda_std_17)
|
||||
|
||||
set_target_properties(postProcessGL PROPERTIES CUDA_SEPARABLE_COMPILATION ON)
|
||||
|
||||
target_include_directories(postProcessGL PUBLIC
|
||||
${OPENGL_INCLUDE_DIR}
|
||||
${CUDAToolkit_INCLUDE_DIRS}
|
||||
${GLUT_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
target_link_libraries(postProcessGL
|
||||
${OPENGL_LIBRARIES}
|
||||
${GLUT_LIBRARIES}
|
||||
)
|
||||
|
||||
add_custom_command(TARGET postProcessGL POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_directory
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/data
|
||||
${CMAKE_CURRENT_BINARY_DIR}/data
|
||||
)
|
||||
|
||||
if(WIN32)
|
||||
target_link_libraries(postProcessGL
|
||||
${PC_GLUT_LIBRARY_DIRS}/freeglut.lib
|
||||
${PC_GLUT_LIBRARY_DIRS}/${GLEW_LIB_NAME}.lib
|
||||
)
|
||||
|
||||
add_custom_command(TARGET postProcessGL
|
||||
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 postProcessGL
|
||||
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 'postProcessGL'")
|
||||
endif()
|
||||
else()
|
||||
message(STATUS "OpenGL not found - will not build sample 'postProcessGL'")
|
||||
endif()
|
||||
|
||||
# Include installation configuration
|
||||
include(${CMAKE_CURRENT_SOURCE_DIR}/../../../cmake/InstallSamples.cmake)
|
||||
setup_samples_install()
|
||||
36
cpp/5_Domain_Specific/postProcessGL/README.md
Normal file
36
cpp/5_Domain_Specific/postProcessGL/README.md
Normal file
@@ -0,0 +1,36 @@
|
||||
# postProcessGL - Post-Process in OpenGL
|
||||
|
||||
## Description
|
||||
|
||||
This sample shows how to post-process an image rendered in OpenGL using CUDA.
|
||||
|
||||
## Key Concepts
|
||||
|
||||
Graphics Interop, Image Processing
|
||||
|
||||
## Supported SM Architectures
|
||||
|
||||
[SM 5.0 ](https://developer.nvidia.com/cuda-gpus) [SM 5.2 ](https://developer.nvidia.com/cuda-gpus) [SM 5.3 ](https://developer.nvidia.com/cuda-gpus) [SM 6.0 ](https://developer.nvidia.com/cuda-gpus) [SM 6.1 ](https://developer.nvidia.com/cuda-gpus) [SM 7.0 ](https://developer.nvidia.com/cuda-gpus) [SM 7.2 ](https://developer.nvidia.com/cuda-gpus) [SM 7.5 ](https://developer.nvidia.com/cuda-gpus) [SM 8.0 ](https://developer.nvidia.com/cuda-gpus) [SM 8.6 ](https://developer.nvidia.com/cuda-gpus) [SM 8.7 ](https://developer.nvidia.com/cuda-gpus) [SM 8.9 ](https://developer.nvidia.com/cuda-gpus) [SM 9.0 ](https://developer.nvidia.com/cuda-gpus)
|
||||
|
||||
## 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)
|
||||
cudaHostAlloc, cudaGraphicsUnmapResources, cudaMalloc, cudaFree, cudaGetChannelDesc, cudaGraphicsResourceGetMappedPointer, cudaGraphicsMapResources, cudaDestroyTextureObject, cudaMemcpyToArray, cudaDeviceSynchronize, cudaCreateTextureObject, cudaProcess, cudaGraphicsUnregisterResource, cudaGraphicsSubResourceGetMappedArray, cudaGraphicsGLRegisterBuffer, cudaGraphicsGLRegisterImage
|
||||
|
||||
## 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)
|
||||
181
cpp/5_Domain_Specific/postProcessGL/data/teapot_2.ppm
Normal file
181
cpp/5_Domain_Specific/postProcessGL/data/teapot_2.ppm
Normal file
File diff suppressed because one or more lines are too long
5
cpp/5_Domain_Specific/postProcessGL/data/teapot_4.ppm
Normal file
5
cpp/5_Domain_Specific/postProcessGL/data/teapot_4.ppm
Normal file
File diff suppressed because one or more lines are too long
5
cpp/5_Domain_Specific/postProcessGL/data/teapot_8.ppm
Normal file
5
cpp/5_Domain_Specific/postProcessGL/data/teapot_8.ppm
Normal file
File diff suppressed because one or more lines are too long
938
cpp/5_Domain_Specific/postProcessGL/data/teapot_orig.ppm
Normal file
938
cpp/5_Domain_Specific/postProcessGL/data/teapot_orig.ppm
Normal file
File diff suppressed because one or more lines are too long
BIN
cpp/5_Domain_Specific/postProcessGL/doc/postProcessGL_lg.gif
Normal file
BIN
cpp/5_Domain_Specific/postProcessGL/doc/postProcessGL_lg.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 53 KiB |
BIN
cpp/5_Domain_Specific/postProcessGL/doc/postProcessGL_md.gif
Normal file
BIN
cpp/5_Domain_Specific/postProcessGL/doc/postProcessGL_md.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 17 KiB |
BIN
cpp/5_Domain_Specific/postProcessGL/doc/postProcessGL_sm.gif
Normal file
BIN
cpp/5_Domain_Specific/postProcessGL/doc/postProcessGL_sm.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 6.1 KiB |
1055
cpp/5_Domain_Specific/postProcessGL/main.cpp
Normal file
1055
cpp/5_Domain_Specific/postProcessGL/main.cpp
Normal file
File diff suppressed because it is too large
Load Diff
271
cpp/5_Domain_Specific/postProcessGL/postProcessGL.cu
Normal file
271
cpp/5_Domain_Specific/postProcessGL/postProcessGL.cu
Normal file
@@ -0,0 +1,271 @@
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
// Utilities and system includes
|
||||
|
||||
#include <cooperative_groups.h>
|
||||
|
||||
namespace cg = cooperative_groups;
|
||||
|
||||
#include <helper_cuda.h>
|
||||
|
||||
cudaTextureObject_t inTexObject;
|
||||
|
||||
// clamp x to range [a, b]
|
||||
__device__ float clamp(float x, float a, float b) { return max(a, min(b, x)); }
|
||||
|
||||
__device__ int clamp(int x, int a, int b) { return max(a, min(b, x)); }
|
||||
|
||||
// convert floating point rgb color to 8-bit integer
|
||||
__device__ int rgbToInt(float r, float g, float b)
|
||||
{
|
||||
r = clamp(r, 0.0f, 255.0f);
|
||||
g = clamp(g, 0.0f, 255.0f);
|
||||
b = clamp(b, 0.0f, 255.0f);
|
||||
return (int(b) << 16) | (int(g) << 8) | int(r);
|
||||
}
|
||||
|
||||
// get pixel from 2D image, with clamping to border
|
||||
__device__ uchar4 getPixel(int x, int y, cudaTextureObject_t inTex)
|
||||
{
|
||||
#ifndef USE_TEXTURE_RGBA8UI
|
||||
float4 res = tex2D<float4>(inTex, x, y);
|
||||
uchar4 ucres = make_uchar4(res.x * 255.0f, res.y * 255.0f, res.z * 255.0f, res.w * 255.0f);
|
||||
#else
|
||||
uchar4 ucres = tex2D<uchar4>(inTex, x, y);
|
||||
#endif
|
||||
return ucres;
|
||||
}
|
||||
|
||||
// macros to make indexing shared memory easier
|
||||
#define SMEM(X, Y) sdata[(Y) * tilew + (X)]
|
||||
|
||||
/*
|
||||
2D convolution using shared memory
|
||||
- operates on 8-bit RGB data stored in 32-bit int
|
||||
- assumes kernel radius is less than or equal to block size
|
||||
- not optimized for performance
|
||||
_____________
|
||||
| : : |
|
||||
|_ _:_____:_ _|
|
||||
| | | |
|
||||
| | | |
|
||||
|_ _|_____|_ _|
|
||||
r | : : |
|
||||
|___:_____:___|
|
||||
r bw r
|
||||
<----tilew---->
|
||||
*/
|
||||
|
||||
__global__ void cudaProcess(unsigned int *g_odata,
|
||||
int imgw,
|
||||
int imgh,
|
||||
int tilew,
|
||||
int r,
|
||||
float threshold,
|
||||
float highlight,
|
||||
cudaTextureObject_t inTex)
|
||||
{
|
||||
// Handle to thread block group
|
||||
cg::thread_block cta = cg::this_thread_block();
|
||||
extern __shared__ uchar4 sdata[];
|
||||
|
||||
int tx = threadIdx.x;
|
||||
int ty = threadIdx.y;
|
||||
int bw = blockDim.x;
|
||||
int bh = blockDim.y;
|
||||
int x = blockIdx.x * bw + tx;
|
||||
int y = blockIdx.y * bh + ty;
|
||||
|
||||
#if 0
|
||||
uchar4 c4 = getPixel(x, y);
|
||||
g_odata[y*imgw+x] = rgbToInt(c4.z, c4.y, c4.x);
|
||||
#else
|
||||
// copy tile to shared memory
|
||||
// center region
|
||||
SMEM(r + tx, r + ty) = getPixel(x, y, inTex);
|
||||
|
||||
// borders
|
||||
if (threadIdx.x < r) {
|
||||
// left
|
||||
SMEM(tx, r + ty) = getPixel(x - r, y, inTex);
|
||||
// right
|
||||
SMEM(r + bw + tx, r + ty) = getPixel(x + bw, y, inTex);
|
||||
}
|
||||
|
||||
if (threadIdx.y < r) {
|
||||
// top
|
||||
SMEM(r + tx, ty) = getPixel(x, y - r, inTex);
|
||||
// bottom
|
||||
SMEM(r + tx, r + bh + ty) = getPixel(x, y + bh, inTex);
|
||||
}
|
||||
|
||||
// load corners
|
||||
if ((threadIdx.x < r) && (threadIdx.y < r)) {
|
||||
// tl
|
||||
SMEM(tx, ty) = getPixel(x - r, y - r, inTex);
|
||||
// bl
|
||||
SMEM(tx, r + bh + ty) = getPixel(x - r, y + bh, inTex);
|
||||
// tr
|
||||
SMEM(r + bw + tx, ty) = getPixel(x + bh, y - r, inTex);
|
||||
// br
|
||||
SMEM(r + bw + tx, r + bh + ty) = getPixel(x + bw, y + bh, inTex);
|
||||
}
|
||||
|
||||
// wait for loads to complete
|
||||
cg::sync(cta);
|
||||
|
||||
// perform convolution
|
||||
float rsum = 0.0f;
|
||||
float gsum = 0.0f;
|
||||
float bsum = 0.0f;
|
||||
float samples = 0.0f;
|
||||
|
||||
for (int dy = -r; dy <= r; dy++) {
|
||||
for (int dx = -r; dx <= r; dx++) {
|
||||
#if 0
|
||||
// try this to see the benefit of using shared memory
|
||||
uchar4 pixel = getPixel(x+dx, y+dy);
|
||||
#else
|
||||
uchar4 pixel = SMEM(r + tx + dx, r + ty + dy);
|
||||
#endif
|
||||
|
||||
// only sum pixels within disc-shaped kernel
|
||||
float l = dx * dx + dy * dy;
|
||||
|
||||
if (l <= r * r) {
|
||||
float r = float(pixel.x);
|
||||
float g = float(pixel.y);
|
||||
float b = float(pixel.z);
|
||||
#if 1
|
||||
// brighten highlights
|
||||
float lum = (r + g + b) / (255 * 3);
|
||||
|
||||
if (lum > threshold) {
|
||||
r *= highlight;
|
||||
g *= highlight;
|
||||
b *= highlight;
|
||||
}
|
||||
|
||||
#endif
|
||||
rsum += r;
|
||||
gsum += g;
|
||||
bsum += b;
|
||||
samples += 1.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rsum /= samples;
|
||||
gsum /= samples;
|
||||
bsum /= samples;
|
||||
// ABGR
|
||||
g_odata[y * imgw + x] = rgbToInt(rsum, gsum, bsum);
|
||||
// g_odata[y*imgw+x] = rgbToInt(x,y,0);
|
||||
#endif
|
||||
}
|
||||
|
||||
extern "C" void launch_cudaProcess(dim3 grid,
|
||||
dim3 block,
|
||||
int sbytes,
|
||||
cudaArray *g_data_array,
|
||||
unsigned int *g_odata,
|
||||
int imgw,
|
||||
int imgh,
|
||||
int tilew,
|
||||
int radius,
|
||||
float threshold,
|
||||
float highlight)
|
||||
{
|
||||
struct cudaChannelFormatDesc desc;
|
||||
checkCudaErrors(cudaGetChannelDesc(&desc, g_data_array));
|
||||
|
||||
cudaResourceDesc texRes;
|
||||
memset(&texRes, 0, sizeof(cudaResourceDesc));
|
||||
|
||||
texRes.resType = cudaResourceTypeArray;
|
||||
texRes.res.array.array = g_data_array;
|
||||
|
||||
cudaTextureDesc texDescr;
|
||||
memset(&texDescr, 0, sizeof(cudaTextureDesc));
|
||||
|
||||
texDescr.normalizedCoords = false;
|
||||
texDescr.filterMode = cudaFilterModePoint;
|
||||
texDescr.addressMode[0] = cudaAddressModeWrap;
|
||||
texDescr.readMode = cudaReadModeElementType;
|
||||
|
||||
checkCudaErrors(cudaCreateTextureObject(&inTexObject, &texRes, &texDescr, NULL));
|
||||
|
||||
#if 0
|
||||
printf("CUDA Array channel descriptor, bits per component:\n");
|
||||
printf("X %d Y %d Z %d W %d, kind %d\n",
|
||||
desc.x,desc.y,desc.z,desc.w,desc.f);
|
||||
|
||||
printf("Possible values for channel format kind: i %d, u%d, f%d:\n",
|
||||
cudaChannelFormatKindSigned, cudaChannelFormatKindUnsigned,
|
||||
cudaChannelFormatKindFloat);
|
||||
#endif
|
||||
|
||||
// printf("\n");
|
||||
#ifdef GPU_PROFILING
|
||||
StopWatchInterface *timer = 0;
|
||||
sdkCreateTimer(&timer);
|
||||
|
||||
int nIter = 30;
|
||||
|
||||
for (int i = -1; i < nIter; ++i) {
|
||||
if (i == 0) {
|
||||
sdkStartTimer(&timer);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
cudaProcess<<<grid, block, sbytes>>>(
|
||||
g_odata, imgw, imgh, block.x + (2 * radius), radius, 0.8f, 4.0f, inTexObject);
|
||||
|
||||
#ifdef GPU_PROFILING
|
||||
}
|
||||
|
||||
cudaDeviceSynchronize();
|
||||
sdkStopTimer(&timer);
|
||||
double dSeconds = sdkGetTimerValue(&timer) / ((double)nIter * 1000.0);
|
||||
double dNumTexels = (double)imgw * (double)imgh;
|
||||
double mtexps = 1.0e-6 * dNumTexels / dSeconds;
|
||||
|
||||
if (radius == 4) {
|
||||
printf("\n");
|
||||
printf("postprocessGL, Throughput = %.4f MTexels/s, Time = %.5f s, Size = "
|
||||
"%.0f Texels, NumDevsUsed = %d, Workgroup = %u\n",
|
||||
mtexps,
|
||||
dSeconds,
|
||||
dNumTexels,
|
||||
1,
|
||||
block.x * block.y);
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
Reference in New Issue
Block a user