add and update samples for CUDA 11.6

This commit is contained in:
Rutwik Choughule
2022-01-13 11:35:24 +05:30
parent 11de19f00c
commit 2e41896e1b
4615 changed files with 178150 additions and 181350 deletions

View 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
}

View File

@@ -0,0 +1,7 @@
{
"recommendations": [
"nvidia.nsight-vscode-edition",
"ms-vscode.cpptools",
"ms-vscode.makefile-tools"
]
}

View File

@@ -0,0 +1,10 @@
{
"configurations": [
{
"name": "CUDA C++: Launch",
"type": "cuda-gdb",
"request": "launch",
"program": "${workspaceFolder}/EGLStream_CUDA_CrossGPU"
}
]
}

View File

@@ -0,0 +1,15 @@
{
"version": "2.0.0",
"tasks": [
{
"label": "sample",
"type": "shell",
"command": "make dbg=1",
"problemMatcher": ["$nvcc"],
"group": {
"kind": "build",
"isDefault": true
}
}
]
}

View File

@@ -0,0 +1,432 @@
################################################################################
# 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.
#
################################################################################
#
# Makefile project only supported on Mac OS X and Linux Platforms)
#
################################################################################
# Location of the CUDA Toolkit
CUDA_PATH ?= /usr/local/cuda
##############################
# start deprecated interface #
##############################
ifeq ($(x86_64),1)
$(info WARNING - x86_64 variable has been deprecated)
$(info WARNING - please use TARGET_ARCH=x86_64 instead)
TARGET_ARCH ?= x86_64
endif
ifeq ($(ARMv7),1)
$(info WARNING - ARMv7 variable has been deprecated)
$(info WARNING - please use TARGET_ARCH=armv7l instead)
TARGET_ARCH ?= armv7l
endif
ifeq ($(aarch64),1)
$(info WARNING - aarch64 variable has been deprecated)
$(info WARNING - please use TARGET_ARCH=aarch64 instead)
TARGET_ARCH ?= aarch64
endif
ifeq ($(ppc64le),1)
$(info WARNING - ppc64le variable has been deprecated)
$(info WARNING - please use TARGET_ARCH=ppc64le instead)
TARGET_ARCH ?= ppc64le
endif
ifneq ($(GCC),)
$(info WARNING - GCC variable has been deprecated)
$(info WARNING - please use HOST_COMPILER=$(GCC) instead)
HOST_COMPILER ?= $(GCC)
endif
ifneq ($(abi),)
$(error ERROR - abi variable has been removed)
endif
############################
# end deprecated interface #
############################
# architecture
HOST_ARCH := $(shell uname -m)
TARGET_ARCH ?= $(HOST_ARCH)
ifneq (,$(filter $(TARGET_ARCH),x86_64 aarch64 sbsa ppc64le armv7l))
ifneq ($(TARGET_ARCH),$(HOST_ARCH))
ifneq (,$(filter $(TARGET_ARCH),x86_64 aarch64 sbsa ppc64le))
TARGET_SIZE := 64
else ifneq (,$(filter $(TARGET_ARCH),armv7l))
TARGET_SIZE := 32
endif
else
TARGET_SIZE := $(shell getconf LONG_BIT)
endif
else
$(error ERROR - unsupported value $(TARGET_ARCH) for TARGET_ARCH!)
endif
# sbsa and aarch64 systems look similar. Need to differentiate them at host level for now.
ifeq ($(HOST_ARCH),aarch64)
ifeq ($(CUDA_PATH)/targets/sbsa-linux,$(shell ls -1d $(CUDA_PATH)/targets/sbsa-linux 2>/dev/null))
HOST_ARCH := sbsa
TARGET_ARCH := sbsa
endif
endif
ifneq ($(TARGET_ARCH),$(HOST_ARCH))
ifeq (,$(filter $(HOST_ARCH)-$(TARGET_ARCH),aarch64-armv7l x86_64-armv7l x86_64-aarch64 x86_64-sbsa x86_64-ppc64le))
$(error ERROR - cross compiling from $(HOST_ARCH) to $(TARGET_ARCH) is not supported!)
endif
endif
# When on native aarch64 system with userspace of 32-bit, change TARGET_ARCH to armv7l
ifeq ($(HOST_ARCH)-$(TARGET_ARCH)-$(TARGET_SIZE),aarch64-aarch64-32)
TARGET_ARCH = armv7l
endif
# operating system
HOST_OS := $(shell uname -s 2>/dev/null | tr "[:upper:]" "[:lower:]")
TARGET_OS ?= $(HOST_OS)
ifeq (,$(filter $(TARGET_OS),linux darwin qnx android))
$(error ERROR - unsupported value $(TARGET_OS) for TARGET_OS!)
endif
# host compiler
ifeq ($(TARGET_OS),darwin)
ifeq ($(shell expr `xcodebuild -version | grep -i xcode | awk '{print $$2}' | cut -d'.' -f1` \>= 5),1)
HOST_COMPILER ?= clang++
endif
else ifneq ($(TARGET_ARCH),$(HOST_ARCH))
ifeq ($(HOST_ARCH)-$(TARGET_ARCH),x86_64-armv7l)
ifeq ($(TARGET_OS),linux)
HOST_COMPILER ?= arm-linux-gnueabihf-g++
else ifeq ($(TARGET_OS),qnx)
ifeq ($(QNX_HOST),)
$(error ERROR - QNX_HOST must be passed to the QNX host toolchain)
endif
ifeq ($(QNX_TARGET),)
$(error ERROR - QNX_TARGET must be passed to the QNX target toolchain)
endif
export QNX_HOST
export QNX_TARGET
HOST_COMPILER ?= $(QNX_HOST)/usr/bin/arm-unknown-nto-qnx6.6.0eabi-g++
else ifeq ($(TARGET_OS),android)
HOST_COMPILER ?= arm-linux-androideabi-g++
endif
else ifeq ($(TARGET_ARCH),aarch64)
ifeq ($(TARGET_OS), linux)
HOST_COMPILER ?= aarch64-linux-gnu-g++
else ifeq ($(TARGET_OS),qnx)
ifeq ($(QNX_HOST),)
$(error ERROR - QNX_HOST must be passed to the QNX host toolchain)
endif
ifeq ($(QNX_TARGET),)
$(error ERROR - QNX_TARGET must be passed to the QNX target toolchain)
endif
export QNX_HOST
export QNX_TARGET
HOST_COMPILER ?= $(QNX_HOST)/usr/bin/q++
else ifeq ($(TARGET_OS), android)
HOST_COMPILER ?= aarch64-linux-android-clang++
endif
else ifeq ($(TARGET_ARCH),sbsa)
HOST_COMPILER ?= aarch64-linux-gnu-g++
else ifeq ($(TARGET_ARCH),ppc64le)
HOST_COMPILER ?= powerpc64le-linux-gnu-g++
endif
endif
HOST_COMPILER ?= g++
NVCC := $(CUDA_PATH)/bin/nvcc -ccbin $(HOST_COMPILER)
# internal flags
NVCCFLAGS := -m${TARGET_SIZE}
CCFLAGS :=
LDFLAGS :=
# build flags
ifeq ($(TARGET_OS),darwin)
LDFLAGS += -rpath $(CUDA_PATH)/lib
CCFLAGS += -arch $(HOST_ARCH)
else ifeq ($(HOST_ARCH)-$(TARGET_ARCH)-$(TARGET_OS),x86_64-armv7l-linux)
LDFLAGS += --dynamic-linker=/lib/ld-linux-armhf.so.3
CCFLAGS += -mfloat-abi=hard
else ifeq ($(TARGET_OS),android)
LDFLAGS += -pie
CCFLAGS += -fpie -fpic -fexceptions
endif
ifneq ($(TARGET_ARCH),$(HOST_ARCH))
ifeq ($(TARGET_ARCH)-$(TARGET_OS),armv7l-linux)
ifneq ($(TARGET_FS),)
GCCVERSIONLTEQ46 := $(shell expr `$(HOST_COMPILER) -dumpversion` \<= 4.6)
ifeq ($(GCCVERSIONLTEQ46),1)
CCFLAGS += --sysroot=$(TARGET_FS)
endif
LDFLAGS += --sysroot=$(TARGET_FS)
LDFLAGS += -rpath-link=$(TARGET_FS)/lib
LDFLAGS += -rpath-link=$(TARGET_FS)/usr/lib
LDFLAGS += -rpath-link=$(TARGET_FS)/usr/lib/arm-linux-gnueabihf
endif
endif
ifeq ($(TARGET_ARCH)-$(TARGET_OS),aarch64-linux)
ifneq ($(TARGET_FS),)
GCCVERSIONLTEQ46 := $(shell expr `$(HOST_COMPILER) -dumpversion` \<= 4.6)
ifeq ($(GCCVERSIONLTEQ46),1)
CCFLAGS += --sysroot=$(TARGET_FS)
endif
LDFLAGS += --sysroot=$(TARGET_FS)
LDFLAGS += -rpath-link=$(TARGET_FS)/lib -L$(TARGET_FS)/lib
LDFLAGS += -rpath-link=$(TARGET_FS)/lib/aarch64-linux-gnu -L$(TARGET_FS)/lib/aarch64-linux-gnu
LDFLAGS += -rpath-link=$(TARGET_FS)/usr/lib -L$(TARGET_FS)/usr/lib
LDFLAGS += -rpath-link=$(TARGET_FS)/usr/lib/aarch64-linux-gnu -L$(TARGET_FS)/usr/lib/aarch64-linux-gnu
LDFLAGS += --unresolved-symbols=ignore-in-shared-libs
CCFLAGS += -isystem=$(TARGET_FS)/usr/include -I$(TARGET_FS)/usr/include -I$(TARGET_FS)/usr/include/libdrm
CCFLAGS += -isystem=$(TARGET_FS)/usr/include/aarch64-linux-gnu -I$(TARGET_FS)/usr/include/aarch64-linux-gnu
endif
endif
ifeq ($(TARGET_ARCH)-$(TARGET_OS),aarch64-qnx)
NVCCFLAGS += -D_QNX_SOURCE
NVCCFLAGS += --qpp-config 8.3.0,gcc_ntoaarch64le
CCFLAGS += -DWIN_INTERFACE_CUSTOM -I/usr/include/aarch64-qnx-gnu
LDFLAGS += -lsocket
LDFLAGS += -L/usr/lib/aarch64-qnx-gnu
CCFLAGS += "-Wl\,-rpath-link\,/usr/lib/aarch64-qnx-gnu"
ifdef TARGET_OVERRIDE
LDFLAGS += -lslog2
endif
ifneq ($(TARGET_FS),)
LDFLAGS += -L$(TARGET_FS)/usr/lib
CCFLAGS += "-Wl\,-rpath-link\,$(TARGET_FS)/usr/lib"
LDFLAGS += -L$(TARGET_FS)/usr/libnvidia
CCFLAGS += "-Wl\,-rpath-link\,$(TARGET_FS)/usr/libnvidia"
CCFLAGS += -I$(TARGET_FS)/../include
endif
endif
endif
ifdef TARGET_OVERRIDE # cuda toolkit targets override
NVCCFLAGS += -target-dir $(TARGET_OVERRIDE)
endif
# Install directory of different arch
CUDA_INSTALL_TARGET_DIR :=
ifeq ($(TARGET_ARCH)-$(TARGET_OS),armv7l-linux)
CUDA_INSTALL_TARGET_DIR = targets/armv7-linux-gnueabihf/
else ifeq ($(TARGET_ARCH)-$(TARGET_OS),aarch64-linux)
CUDA_INSTALL_TARGET_DIR = targets/aarch64-linux/
else ifeq ($(TARGET_ARCH)-$(TARGET_OS),sbsa-linux)
CUDA_INSTALL_TARGET_DIR = targets/sbsa-linux/
else ifeq ($(TARGET_ARCH)-$(TARGET_OS),armv7l-android)
CUDA_INSTALL_TARGET_DIR = targets/armv7-linux-androideabi/
else ifeq ($(TARGET_ARCH)-$(TARGET_OS),aarch64-android)
CUDA_INSTALL_TARGET_DIR = targets/aarch64-linux-androideabi/
else ifeq ($(TARGET_ARCH)-$(TARGET_OS),armv7l-qnx)
CUDA_INSTALL_TARGET_DIR = targets/ARMv7-linux-QNX/
else ifeq ($(TARGET_ARCH)-$(TARGET_OS),aarch64-qnx)
CUDA_INSTALL_TARGET_DIR = targets/aarch64-qnx/
else ifeq ($(TARGET_ARCH),ppc64le)
CUDA_INSTALL_TARGET_DIR = targets/ppc64le-linux/
endif
# Debug build flags
ifeq ($(dbg),1)
NVCCFLAGS += -g -G
BUILD_TYPE := debug
else
BUILD_TYPE := release
endif
ALL_CCFLAGS :=
ALL_CCFLAGS += $(NVCCFLAGS)
ALL_CCFLAGS += $(EXTRA_NVCCFLAGS)
ALL_CCFLAGS += $(addprefix -Xcompiler ,$(CCFLAGS))
ALL_CCFLAGS += $(addprefix -Xcompiler ,$(EXTRA_CCFLAGS))
UBUNTU = $(shell lsb_release -i -s 2>/dev/null | grep -i ubuntu)
SAMPLE_ENABLED := 1
# This sample is not supported on Mac OSX
ifeq ($(TARGET_OS),darwin)
$(info >>> WARNING - EGLStream_CUDA_CrossGPU is not supported on Mac OSX - waiving sample <<<)
SAMPLE_ENABLED := 0
endif
# This sample is not supported on android
ifeq ($(TARGET_OS),android)
$(info >>> WARNING - EGLStream_CUDA_CrossGPU is not supported on android - waiving sample <<<)
SAMPLE_ENABLED := 0
endif
ALL_LDFLAGS :=
ALL_LDFLAGS += $(ALL_CCFLAGS)
ALL_LDFLAGS += $(addprefix -Xlinker ,$(LDFLAGS))
ALL_LDFLAGS += $(addprefix -Xlinker ,$(EXTRA_LDFLAGS))
# Common includes and paths for CUDA
INCLUDES := -I../../../Common
LIBRARIES :=
################################################################################
# Makefile include to help find EGL Libraries
include ./findegl.mk
# EGL specific libraries
ifneq ($(TARGET_OS),darwin)
LIBRARIES += -lEGL
endif
# Gencode arguments
ifeq ($(TARGET_ARCH),$(filter $(TARGET_ARCH),armv7l aarch64 sbsa))
SMS ?= 53 61 70 72 75 80 86 87
else
SMS ?= 35 37 50 52 60 61 70 75 80 86
endif
ifeq ($(SMS),)
$(info >>> WARNING - no SM architectures have been specified - waiving sample <<<)
SAMPLE_ENABLED := 0
endif
ifeq ($(GENCODE_FLAGS),)
# Generate SASS code for each SM architecture listed in $(SMS)
$(foreach sm,$(SMS),$(eval GENCODE_FLAGS += -gencode arch=compute_$(sm),code=sm_$(sm)))
# Generate PTX code from the highest SM architecture in $(SMS) to guarantee forward-compatibility
HIGHEST_SM := $(lastword $(sort $(SMS)))
ifneq ($(HIGHEST_SM),)
GENCODE_FLAGS += -gencode arch=compute_$(HIGHEST_SM),code=compute_$(HIGHEST_SM)
endif
endif
ifeq ($(TARGET_OS),darwin)
ALL_LDFLAGS += -Xcompiler -F/Library/Frameworks -Xlinker -framework -Xlinker CUDA
else
ifeq ($(TARGET_ARCH),x86_64)
CUDA_SEARCH_PATH ?= $(CUDA_PATH)/lib64/stubs
CUDA_SEARCH_PATH += $(CUDA_PATH)/lib/stubs
CUDA_SEARCH_PATH += $(CUDA_PATH)/targets/x86_64-linux/lib/stubs
endif
ifeq ($(TARGET_ARCH)-$(TARGET_OS),armv7l-linux)
CUDA_SEARCH_PATH ?= $(CUDA_PATH)/targets/armv7-linux-gnueabihf/lib/stubs
endif
ifeq ($(TARGET_ARCH)-$(TARGET_OS),aarch64-linux)
CUDA_SEARCH_PATH ?= $(CUDA_PATH)/targets/aarch64-linux/lib/stubs
endif
ifeq ($(TARGET_ARCH)-$(TARGET_OS),sbsa-linux)
CUDA_SEARCH_PATH ?= $(CUDA_PATH)/targets/sbsa-linux/lib/stubs
endif
ifeq ($(TARGET_ARCH)-$(TARGET_OS),armv7l-android)
CUDA_SEARCH_PATH ?= $(CUDA_PATH)/targets/armv7-linux-androideabi/lib/stubs
endif
ifeq ($(TARGET_ARCH)-$(TARGET_OS),aarch64-android)
CUDA_SEARCH_PATH ?= $(CUDA_PATH)/targets/aarch64-linux-androideabi/lib/stubs
endif
ifeq ($(TARGET_ARCH)-$(TARGET_OS),armv7l-qnx)
CUDA_SEARCH_PATH ?= $(CUDA_PATH)/targets/ARMv7-linux-QNX/lib/stubs
endif
ifeq ($(TARGET_ARCH)-$(TARGET_OS),aarch64-qnx)
CUDA_SEARCH_PATH ?= $(CUDA_PATH)/targets/aarch64-qnx/lib/stubs
ifdef TARGET_OVERRIDE
CUDA_SEARCH_PATH := $(CUDA_PATH)/targets/$(TARGET_OVERRIDE)/lib/stubs
endif
endif
ifeq ($(TARGET_ARCH),ppc64le)
CUDA_SEARCH_PATH ?= $(CUDA_PATH)/targets/ppc64le-linux/lib/stubs
endif
ifeq ($(HOST_ARCH),ppc64le)
CUDA_SEARCH_PATH += $(CUDA_PATH)/lib64/stubs
endif
CUDALIB ?= $(shell find -L $(CUDA_SEARCH_PATH) -maxdepth 1 -name libcuda.so 2> /dev/null)
ifeq ("$(CUDALIB)","")
$(info >>> WARNING - libcuda.so not found, CUDA Driver is not installed. Please re-install the driver. <<<)
SAMPLE_ENABLED := 0
else
CUDALIB := $(shell echo $(CUDALIB) | sed "s/ .*//" | sed "s/\/libcuda.so//" )
LIBRARIES += -L$(CUDALIB) -lcuda
endif
endif
ALL_CCFLAGS += --threads 0 --std=c++11
ifeq ($(SAMPLE_ENABLED),0)
EXEC ?= @echo "[@]"
endif
################################################################################
# Target rules
all: build
build: EGLStream_CUDA_CrossGPU
check.deps:
ifeq ($(SAMPLE_ENABLED),0)
@echo "Sample will be waived due to the above missing dependencies"
else
@echo "Sample is ready - all dependencies have been met"
endif
cuda_consumer.o:cuda_consumer.cpp
$(EXEC) $(NVCC) $(INCLUDES) $(ALL_CCFLAGS) $(GENCODE_FLAGS) -o $@ -c $<
cuda_producer.o:cuda_producer.cpp
$(EXEC) $(NVCC) $(INCLUDES) $(ALL_CCFLAGS) $(GENCODE_FLAGS) -o $@ -c $<
eglstrm_common.o:eglstrm_common.cpp
$(EXEC) $(NVCC) $(INCLUDES) $(ALL_CCFLAGS) $(GENCODE_FLAGS) -o $@ -c $<
kernel.o:kernel.cu
$(EXEC) $(NVCC) $(INCLUDES) $(ALL_CCFLAGS) $(GENCODE_FLAGS) -o $@ -c $<
main.o:main.cpp
$(EXEC) $(NVCC) $(INCLUDES) $(ALL_CCFLAGS) $(GENCODE_FLAGS) -o $@ -c $<
EGLStream_CUDA_CrossGPU: cuda_consumer.o cuda_producer.o eglstrm_common.o kernel.o main.o
$(EXEC) $(NVCC) $(ALL_LDFLAGS) $(GENCODE_FLAGS) -o $@ $+ $(LIBRARIES)
$(EXEC) mkdir -p ../../../bin/$(TARGET_ARCH)/$(TARGET_OS)/$(BUILD_TYPE)
$(EXEC) cp $@ ../../../bin/$(TARGET_ARCH)/$(TARGET_OS)/$(BUILD_TYPE)
run: build
$(EXEC) ./EGLStream_CUDA_CrossGPU
testrun: build
clean:
rm -f EGLStream_CUDA_CrossGPU cuda_consumer.o cuda_producer.o eglstrm_common.o kernel.o main.o
rm -rf ../../../bin/$(TARGET_ARCH)/$(TARGET_OS)/$(BUILD_TYPE)/EGLStream_CUDA_CrossGPU
clobber: clean

View File

@@ -0,0 +1,101 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE entry SYSTEM "SamplesInfo.dtd">
<entry>
<name>EGLStream_CUDA_CrossGPU</name>
<cuda_api_list>
<driver>cuEGLStreamConsumerConnect</driver>
<driver>cuMemFree</driver>
<driver>cuInit</driver>
<driver>cuStreamCreate</driver>
<driver>cuCtxCreate</driver>
<driver>cuGraphicsResourceGetMappedEglFrame</driver>
<driver>cuDeviceGetName</driver>
<driver>cuCtxSynchronize</driver>
<driver>cuEGLStreamConsumerAcquireFrame</driver>
<driver>cuDeviceGet</driver>
<driver>cuDeviceGetAttribute</driver>
<driver>cuMemAlloc</driver>
<driver>cuEGLStreamConsumerReleaseFrame</driver>
<driver>cuEGLStreamProducerDisconnect</driver>
<driver>cuEGLStreamProducerConnect</driver>
<driver>cuEGLStreamConsumerDisconnect</driver>
<driver>cuMemcpyHtoD</driver>
<driver>cuEGLStreamProducerReturnFrame</driver>
<driver>cuCtxPushCurrent</driver>
<driver>cuCtxPopCurrent</driver>
<driver>cuEGLStreamProducerPresentFrame</driver>
<toolkit>cudaDeviceCreateConsumer</toolkit>
<toolkit>cudaFree</toolkit>
<toolkit>cudaConsumerReleaseFrame</toolkit>
<toolkit>cudaDeviceSynchronize</toolkit>
<toolkit>cudaGetValueMismatch</toolkit>
<toolkit>cudaProducerDeinit</toolkit>
<toolkit>cudaProducerPresentFrame</toolkit>
<toolkit>cudaMalloc</toolkit>
<toolkit>cudaProducerInit</toolkit>
<toolkit>cudaProducerReturnFrame</toolkit>
<toolkit>cudaProducerPrepareFrame</toolkit>
<toolkit>cudaConsumerAcquireFrame</toolkit>
<toolkit>cudaMemcpy</toolkit>
<toolkit>cudaGetErrorString</toolkit>
<toolkit>cudaDeviceCreateProducer</toolkit>
</cuda_api_list>
<description><![CDATA[Demonstrates CUDA and EGL Streams interop, where consumer's EGL Stream is on one GPU and producer's on other and both consumer-producer are different processes.]]></description>
<devicecompilation>whole</devicecompilation>
<includepaths>
<path>./</path>
<path>../</path>
<path>../../../Common</path>
</includepaths>
<keyconcepts>
<concept level="basic">EGLStreams Interop</concept>
</keyconcepts>
<keywords>
<keyword>EGL Streams</keyword>
</keywords>
<libraries>
<library os="linux">cuda</library>
<library framework="true" os="macosx">CUDA</library>
</libraries>
<librarypaths>
</librarypaths>
<nsight_eclipse>true</nsight_eclipse>
<primary_file>main.cpp</primary_file>
<required_dependencies>
<dependency>EGL</dependency>
</required_dependencies>
<scopes>
<scope>1:CUDA Advanced Topics</scope>
<scope>2:Graphics Interop</scope>
</scopes>
<sm-arch>sm35</sm-arch>
<sm-arch>sm37</sm-arch>
<sm-arch>sm50</sm-arch>
<sm-arch>sm52</sm-arch>
<sm-arch>sm53</sm-arch>
<sm-arch>sm60</sm-arch>
<sm-arch>sm61</sm-arch>
<sm-arch>sm70</sm-arch>
<sm-arch>sm72</sm-arch>
<sm-arch>sm75</sm-arch>
<sm-arch>sm80</sm-arch>
<sm-arch>sm86</sm-arch>
<sm-arch>sm87</sm-arch>
<supported_envs>
<env>
<arch>x86_64</arch>
<platform>linux</platform>
</env>
<env>
<arch>arm</arch>
</env>
<env>
<arch>sbsa</arch>
</env>
</supported_envs>
<supported_sm_architectures>
<include>all</include>
</supported_sm_architectures>
<title>EGLStream_CUDA_CrossGPU</title>
<type>exe</type>
</entry>

View File

@@ -0,0 +1,67 @@
# EGLStream_CUDA_CrossGPU - EGLStream_CUDA_CrossGPU
## Description
Demonstrates CUDA and EGL Streams interop, where consumer's EGL Stream is on one GPU and producer's on other and both consumer-producer are different processes.
## Key Concepts
EGLStreams Interop
## Supported SM Architectures
[SM 3.5 ](https://developer.nvidia.com/cuda-gpus) [SM 3.7 ](https://developer.nvidia.com/cuda-gpus) [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)
## Supported OSes
Linux
## Supported CPU Architecture
x86_64, armv7l
## CUDA APIs involved
### [CUDA Driver API](http://docs.nvidia.com/cuda/cuda-driver-api/index.html)
cuEGLStreamConsumerConnect, cuMemFree, cuInit, cuStreamCreate, cuCtxCreate, cuGraphicsResourceGetMappedEglFrame, cuDeviceGetName, cuCtxSynchronize, cuEGLStreamConsumerAcquireFrame, cuDeviceGet, cuDeviceGetAttribute, cuMemAlloc, cuEGLStreamConsumerReleaseFrame, cuEGLStreamProducerDisconnect, cuEGLStreamProducerConnect, cuEGLStreamConsumerDisconnect, cuMemcpyHtoD, cuEGLStreamProducerReturnFrame, cuCtxPushCurrent, cuCtxPopCurrent, cuEGLStreamProducerPresentFrame
### [CUDA Runtime API](http://docs.nvidia.com/cuda/cuda-runtime-api/index.html)
cudaDeviceCreateConsumer, cudaFree, cudaConsumerReleaseFrame, cudaDeviceSynchronize, cudaGetValueMismatch, cudaProducerDeinit, cudaProducerPresentFrame, cudaMalloc, cudaProducerInit, cudaProducerReturnFrame, cudaProducerPrepareFrame, cudaConsumerAcquireFrame, cudaMemcpy, cudaGetErrorString, cudaDeviceCreateProducer
## Dependencies needed to build/run
[EGL](../../README.md#egl)
## Prerequisites
Download and install the [CUDA Toolkit 11.6](https://developer.nvidia.com/cuda-downloads) for your corresponding platform.
Make sure the dependencies mentioned in [Dependencies]() section above are installed.
## Build and Run
### Linux
The Linux samples are built using makefiles. To use the makefiles, change the current directory to the sample directory you wish to build, and run make:
```
$ cd <sample_dir>
$ make
```
The samples makefiles can take advantage of certain options:
* **TARGET_ARCH=<arch>** - cross-compile targeting a specific architecture. Allowed architectures are x86_64, armv7l.
By default, TARGET_ARCH is set to HOST_ARCH. On a x86_64 machine, not setting TARGET_ARCH is the equivalent of setting TARGET_ARCH=x86_64.<br/>
`$ make TARGET_ARCH=x86_64` <br/> `$ make TARGET_ARCH=armv7l` <br/>
See [here](http://docs.nvidia.com/cuda/cuda-samples/index.html#cross-samples) for more details.
* **dbg=1** - build with debug symbols
```
$ make dbg=1
```
* **SMS="A B ..."** - override the SM architectures for which the sample will be built, where `"A B ..."` is a space-delimited list of SM architectures. For example, to generate SASS for SM 50 and SM 60, use `SMS="50 60"`.
```
$ make SMS="50 60"
```
* **HOST_COMPILER=<host_compiler>** - override the default g++ host compiler. See the [Linux Installation Guide](http://docs.nvidia.com/cuda/cuda-installation-guide-linux/index.html#system-requirements) for a list of supported host compilers.
```
$ make HOST_COMPILER=g++
```
## References (for more details)

View File

@@ -0,0 +1,258 @@
/* 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.
*/
//
// DESCRIPTION: Simple CUDA consumer rendering sample app
//
#include <cuda_runtime.h>
#include "cuda_consumer.h"
#include "eglstrm_common.h"
#include <math.h>
#include <unistd.h>
#if defined(EXTENSION_LIST)
EXTENSION_LIST(EXTLST_EXTERN)
#endif
CUgraphicsResource cudaResource;
static int count_acq = 0;
static double acquire_time[25000] = {0}, total_time_acq = 0;
static int count_rel = 0;
static double rel_time[25000] = {0}, total_time_rel = 0;
void acquireApiStat(void);
void acquireApiStat(void) {
int i = 0;
double min = 10000000, max = 0;
double average_launch_time = 0, standard_deviation = 0;
if (count_acq == 0) return;
// lets compute the standard deviation
min = max = acquire_time[1];
average_launch_time = (total_time_acq - acquire_time[0]) / count_acq;
for (i = 1; i < count_acq; i++) {
standard_deviation += (acquire_time[i] - average_launch_time) *
(acquire_time[i] - average_launch_time);
if (acquire_time[i] < min) min = acquire_time[i];
if (acquire_time[i] > max) max = acquire_time[i];
}
standard_deviation = sqrt(standard_deviation / count_acq);
printf("acquire Avg: %lf\n", average_launch_time);
printf("acquire SD: %lf\n", standard_deviation);
printf("acquire min: %lf\n", min);
printf("acquire max: %lf\n", max);
min = max = rel_time[1];
average_launch_time = (total_time_rel - rel_time[0]) / count_rel;
for (i = 1; i < count_rel; i++) {
standard_deviation += (rel_time[i] - average_launch_time) *
(rel_time[i] - average_launch_time);
if (rel_time[i] < min) min = rel_time[i];
if (rel_time[i] > max) max = rel_time[i];
}
standard_deviation = sqrt(standard_deviation / count_rel);
printf("release Avg: %lf\n", average_launch_time);
printf("release SD: %lf\n", standard_deviation);
printf("release min: %lf\n", min);
printf("release max: %lf\n", max);
}
CUresult cudaConsumerAcquireFrame(test_cuda_consumer_s *cudaConsumer,
int frameNumber) {
CUresult cuStatus = CUDA_SUCCESS;
CUeglFrame cudaEgl;
struct timespec start, end;
EGLint streamState = 0;
double curTime;
if (!cudaConsumer) {
printf("%s: Bad parameter\n", __func__);
goto done;
}
while (1) {
if (!eglQueryStreamKHR(cudaConsumer->eglDisplay, cudaConsumer->eglStream,
EGL_STREAM_STATE_KHR, &streamState)) {
printf("Cuda Consumer: eglQueryStreamKHR EGL_STREAM_STATE_KHR failed\n");
cuStatus = CUDA_ERROR_UNKNOWN;
goto done;
}
if (streamState == EGL_STREAM_STATE_DISCONNECTED_KHR) {
printf("Cuda Consumer: EGL_STREAM_STATE_DISCONNECTED_KHR received\n");
cuStatus = CUDA_ERROR_UNKNOWN;
goto done;
}
if (streamState == EGL_STREAM_STATE_NEW_FRAME_AVAILABLE_KHR) {
break;
}
}
if (cudaConsumer->profileAPI) {
getTime(&start);
}
cuStatus =
cuEGLStreamConsumerAcquireFrame(&(cudaConsumer->cudaConn), &cudaResource,
&cudaConsumer->consCudaStream, 16000);
if (cudaConsumer->profileAPI) {
getTime(&end);
curTime = TIME_DIFF(end, start);
acquire_time[count_acq++] = curTime;
if (count_acq == 25000) count_acq = 0;
total_time_acq += curTime;
}
if (cuStatus == CUDA_SUCCESS) {
CUdeviceptr pDevPtr = 0;
cudaError_t err;
cuStatus =
cuGraphicsResourceGetMappedEglFrame(&cudaEgl, cudaResource, 0, 0);
if (cuStatus != CUDA_SUCCESS) {
printf("Cuda get resource failed with %d\n", cuStatus);
goto done;
}
pDevPtr = (CUdeviceptr)cudaEgl.frame.pPitch[0];
err = cudaConsumer_filter(cudaConsumer->consCudaStream, (char *)pDevPtr,
WIDTH * 4, HEIGHT, PROD_DATA + frameNumber,
CONS_DATA + frameNumber, frameNumber);
if (err != cudaSuccess) {
printf("Cuda Consumer: kernel failed with: %s\n",
cudaGetErrorString(err));
goto done;
}
}
done:
return cuStatus;
}
CUresult cudaConsumerReleaseFrame(test_cuda_consumer_s *cudaConsumer,
int frameNumber) {
CUresult cuStatus = CUDA_SUCCESS;
struct timespec start, end;
double curTime;
if (!cudaConsumer) {
printf("%s: Bad parameter\n", __func__);
goto done;
}
if (cudaConsumer->profileAPI) {
getTime(&start);
}
cuStatus = cuEGLStreamConsumerReleaseFrame(
&cudaConsumer->cudaConn, cudaResource, &cudaConsumer->consCudaStream);
if (cudaConsumer->profileAPI) {
getTime(&end);
curTime = TIME_DIFF(end, start);
rel_time[count_rel++] = curTime;
if (count_rel == 25000) count_rel = 0;
total_time_rel += curTime;
}
if (cuStatus != CUDA_SUCCESS) {
printf("cuEGLStreamConsumerReleaseFrame failed, status:%d\n", cuStatus);
goto done;
}
done:
return cuStatus;
}
CUresult cudaDeviceCreateConsumer(test_cuda_consumer_s *cudaConsumer) {
CUdevice device;
CUresult status = CUDA_SUCCESS;
if (CUDA_SUCCESS != (status = cuInit(0))) {
printf("Failed to initialize CUDA\n");
return status;
}
if (CUDA_SUCCESS !=
(status = cuDeviceGet(&device, cudaConsumer->cudaDevId))) {
printf("failed to get CUDA device\n");
return status;
}
if (CUDA_SUCCESS !=
(status = cuCtxCreate(&cudaConsumer->context, 0, device))) {
printf("failed to create CUDA context\n");
return status;
}
int major = 0, minor = 0;
char deviceName[256];
cuDeviceGetAttribute(&major, CU_DEVICE_ATTRIBUTE_COMPUTE_CAPABILITY_MAJOR,
device);
cuDeviceGetAttribute(&minor, CU_DEVICE_ATTRIBUTE_COMPUTE_CAPABILITY_MINOR,
device);
cuDeviceGetName(deviceName, 256, device);
printf(
"CUDA Consumer on GPU Device %d: \"%s\" with compute capability "
"%d.%d\n\n",
device, deviceName, major, minor);
cuCtxPopCurrent(&cudaConsumer->context);
if (major < 6) {
printf(
"EGLStream_CUDA_CrossGPU requires SM 6.0 or higher arch GPU. "
"Exiting...\n");
exit(2); // EXIT_WAIVED
}
return status;
}
CUresult cuda_consumer_init(test_cuda_consumer_s *cudaConsumer,
TestArgs *args) {
CUresult status = CUDA_SUCCESS;
int bufferSize;
cudaConsumer->charCnt = args->charCnt;
bufferSize = args->charCnt;
cudaConsumer->pCudaCopyMem = (unsigned char *)malloc(bufferSize);
if (cudaConsumer->pCudaCopyMem == NULL) {
printf("Cuda Consumer: malloc failed\n");
goto done;
}
status = cuStreamCreate(&cudaConsumer->consCudaStream, 0);
if (status != CUDA_SUCCESS) {
printf("Cuda Consumer: cuStreamCreate failed, status:%d\n", status);
goto done;
}
atexit(acquireApiStat);
done:
return status;
}
CUresult cuda_consumer_Deinit(test_cuda_consumer_s *cudaConsumer) {
if (cudaConsumer->pCudaCopyMem) {
free(cudaConsumer->pCudaCopyMem);
}
return cuEGLStreamConsumerDisconnect(&cudaConsumer->cudaConn);
}

View 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.
*/
//
// DESCRIPTION: CUDA consumer header file
//
#ifndef _CUDA_CONSUMER_H_
#define _CUDA_CONSUMER_H_
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "cudaEGL.h"
#include "eglstrm_common.h"
#include <cuda_runtime.h>
#include <cuda.h>
typedef struct _test_cuda_consumer_s {
CUcontext context;
CUeglStreamConnection cudaConn;
int cudaDevId;
EGLDisplay eglDisplay;
EGLStreamKHR eglStream;
unsigned int charCnt;
char *cudaBuf;
bool profileAPI;
unsigned char *pCudaCopyMem;
CUstream consCudaStream;
} test_cuda_consumer_s;
CUresult cuda_consumer_init(test_cuda_consumer_s *cudaConsumer, TestArgs *args);
CUresult cuda_consumer_Deinit(test_cuda_consumer_s *cudaConsumer);
CUresult cudaConsumerAcquireFrame(test_cuda_consumer_s *data, int frameNumber);
CUresult cudaConsumerReleaseFrame(test_cuda_consumer_s *data, int frameNumber);
CUresult cudaDeviceCreateConsumer(test_cuda_consumer_s *cudaConsumer);
cudaError_t cudaConsumer_filter(CUstream cStream, char *pSrc, int width,
int height, char expectedVal, char newVal,
int frameNumber);
cudaError_t cudaGetValueMismatch(void);
#endif

View File

@@ -0,0 +1,288 @@
/* 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.
*/
//
// DESCRIPTION: Simple cuda EGL stream producer app
//
#include "cudaEGL.h"
#include "cuda_producer.h"
#include "eglstrm_common.h"
#include <cuda_runtime.h>
#if defined(EXTENSION_LIST)
EXTENSION_LIST(EXTLST_EXTERN)
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <string.h>
#include "cuda_runtime.h"
#include "math.h"
int cudaPresentReturnData = INIT_DATA;
int fakePresent = 0;
CUeglFrame fakeFrame;
CUdeviceptr cudaPtrFake;
extern bool isCrossDevice;
void cudaProducerPrepareFrame(CUeglFrame *cudaEgl, CUdeviceptr cudaPtr,
int bufferSize) {
cudaEgl->frame.pPitch[0] = (void *)cudaPtr;
cudaEgl->width = WIDTH;
cudaEgl->depth = 0;
cudaEgl->height = HEIGHT;
cudaEgl->pitch = WIDTH * 4;
cudaEgl->frameType = CU_EGL_FRAME_TYPE_PITCH;
cudaEgl->planeCount = 1;
cudaEgl->numChannels = 4;
cudaEgl->eglColorFormat = CU_EGL_COLOR_FORMAT_ARGB;
cudaEgl->cuFormat = CU_AD_FORMAT_UNSIGNED_INT8;
}
static int count_present = 0, count_return = 0;
static double present_time[25000] = {0}, total_time_present = 0;
static double return_time[25000] = {0}, total_time_return = 0;
void presentApiStat(void);
void presentApiStat(void) {
int i = 0;
double min = 10000000, max = 0;
double average_launch_time = 0, standard_deviation = 0;
if (count_present == 0) return;
// lets compute the standard deviation
min = max = present_time[1];
average_launch_time = (total_time_present) / count_present;
for (i = 1; i < count_present; i++) {
standard_deviation += (present_time[i] - average_launch_time) *
(present_time[i] - average_launch_time);
if (present_time[i] < min) min = present_time[i];
if (present_time[i] > max) max = present_time[i];
}
standard_deviation = sqrt(standard_deviation / count_present);
printf("present Avg: %lf\n", average_launch_time);
printf("present SD: %lf\n", standard_deviation);
printf("present min: %lf\n", min);
printf("present max: %lf\n", max);
min = max = return_time[1];
average_launch_time = (total_time_return - return_time[0]) / count_return;
for (i = 1; i < count_return; i++) {
standard_deviation += (return_time[i] - average_launch_time) *
(return_time[i] - average_launch_time);
if (return_time[i] < min) min = return_time[i];
if (return_time[i] > max) max = return_time[i];
}
standard_deviation = sqrt(standard_deviation / count_return);
printf("return Avg: %lf\n", average_launch_time);
printf("return SD: %lf\n", standard_deviation);
printf("return min: %lf\n", min);
printf("return max: %lf\n", max);
}
CUresult cudaProducerPresentFrame(test_cuda_producer_s *cudaProducer,
CUeglFrame cudaEgl, int t) {
static int flag = 0;
CUresult status = CUDA_SUCCESS;
struct timespec start, end;
double curTime;
CUdeviceptr pDevPtr = (CUdeviceptr)cudaEgl.frame.pPitch[0];
cudaProducer_filter(cudaProducer->prodCudaStream, (char *)pDevPtr, WIDTH * 4,
HEIGHT, cudaPresentReturnData, PROD_DATA + t, t);
if (cudaProducer->profileAPI) {
getTime(&start);
}
status = cuEGLStreamProducerPresentFrame(&cudaProducer->cudaConn, cudaEgl,
&cudaProducer->prodCudaStream);
if (status != CUDA_SUCCESS) {
printf("Cuda Producer: Present frame failed, status:%d\n", status);
goto done;
}
flag++;
if (cudaProducer->profileAPI && flag > 10) {
getTime(&end);
curTime = TIME_DIFF(end, start);
present_time[count_present++] = curTime;
if (count_present == 25000) count_present = 0;
total_time_present += curTime;
}
done:
return status;
}
int flag = 0;
CUresult cudaProducerReturnFrame(test_cuda_producer_s *cudaProducer,
CUeglFrame cudaEgl, int t) {
CUresult status = CUDA_SUCCESS;
struct timespec start, end;
double curTime;
CUdeviceptr pDevPtr = 0;
pDevPtr = (CUdeviceptr)cudaEgl.frame.pPitch[0];
if (cudaProducer->profileAPI) {
getTime(&start);
}
while (1) {
status = cuEGLStreamProducerReturnFrame(&cudaProducer->cudaConn, &cudaEgl,
&cudaProducer->prodCudaStream);
if (status == CUDA_ERROR_LAUNCH_TIMEOUT) {
continue;
} else if (status != CUDA_SUCCESS) {
printf("Cuda Producer: Return frame failed, status:%d\n", status);
goto done;
}
break;
}
if (cudaProducer->profileAPI) {
getTime(&end);
curTime = TIME_DIFF(end, start);
return_time[count_return++] = curTime;
if (count_return == 25000) count_return = 0;
total_time_return += curTime;
}
if (flag % 2 == 0) {
cudaPresentReturnData++;
}
cudaProducer_filter(cudaProducer->prodCudaStream, (char *)pDevPtr, WIDTH * 4,
HEIGHT, CONS_DATA + t, cudaPresentReturnData, t);
flag++;
done:
return status;
}
CUresult cudaDeviceCreateProducer(test_cuda_producer_s *cudaProducer) {
CUdevice device;
CUresult status = CUDA_SUCCESS;
if (CUDA_SUCCESS != (status = cuInit(0))) {
printf("Failed to initialize CUDA\n");
return status;
}
if (CUDA_SUCCESS !=
(status = cuDeviceGet(&device, cudaProducer->cudaDevId))) {
printf("failed to get CUDA device\n");
return status;
}
if (CUDA_SUCCESS !=
(status = cuCtxCreate(&cudaProducer->context, 0, device))) {
printf("failed to create CUDA context\n");
return status;
}
int major = 0, minor = 0;
char deviceName[256];
cuDeviceGetAttribute(&major, CU_DEVICE_ATTRIBUTE_COMPUTE_CAPABILITY_MAJOR,
device);
cuDeviceGetAttribute(&minor, CU_DEVICE_ATTRIBUTE_COMPUTE_CAPABILITY_MINOR,
device);
cuDeviceGetName(deviceName, 256, device);
printf(
"CUDA Producer on GPU Device %d: \"%s\" with compute capability "
"%d.%d\n\n",
device, deviceName, major, minor);
cuCtxPopCurrent(&cudaProducer->context);
if (major < 6) {
printf(
"EGLStream_CUDA_CrossGPU requires SM 6.0 or higher arch GPU. "
"Exiting...\n");
exit(2); // EXIT_WAIVED
}
return status;
}
CUresult cudaProducerInit(test_cuda_producer_s *cudaProducer, TestArgs *args) {
CUresult status = CUDA_SUCCESS;
int bufferSize;
cudaProducer->charCnt = args->charCnt;
bufferSize = cudaProducer->charCnt;
cudaProducer->tempBuff = (char *)malloc(bufferSize);
if (!cudaProducer->tempBuff) {
printf("Cuda Producer: Failed to allocate image buffer\n");
status = CUDA_ERROR_UNKNOWN;
goto done;
}
memset((void *)cudaProducer->tempBuff, INIT_DATA, cudaProducer->charCnt);
// Fill this init data
status = cuMemAlloc(&cudaProducer->cudaPtr, bufferSize);
if (status != CUDA_SUCCESS) {
printf("Cuda Producer: cuda Malloc failed, status:%d\n", status);
goto done;
}
status = cuMemcpyHtoD(cudaProducer->cudaPtr, (void *)(cudaProducer->tempBuff),
bufferSize);
if (status != CUDA_SUCCESS) {
printf("Cuda Producer: cuMemCpy failed, status:%d\n", status);
goto done;
}
// Fill this init data
status = cuMemAlloc(&cudaProducer->cudaPtr1, bufferSize);
if (status != CUDA_SUCCESS) {
printf("Cuda Producer: cuda Malloc failed, status:%d\n", status);
goto done;
}
status = cuMemcpyHtoD(cudaProducer->cudaPtr1,
(void *)(cudaProducer->tempBuff), bufferSize);
if (status != CUDA_SUCCESS) {
printf("Cuda Producer: cuMemCpy failed, status:%d\n", status);
goto done;
}
status = cuStreamCreate(&cudaProducer->prodCudaStream, 0);
if (status != CUDA_SUCCESS) {
printf("Cuda Producer: cuStreamCreate failed, status:%d\n", status);
goto done;
}
// Fill this init data
status = cuMemAlloc(&cudaPtrFake, 100);
if (status != CUDA_SUCCESS) {
printf("Cuda Producer: cuda Malloc failed, status:%d\n", status);
goto done;
}
atexit(presentApiStat);
done:
return status;
}
CUresult cudaProducerDeinit(test_cuda_producer_s *cudaProducer) {
if (cudaProducer->tempBuff) {
free(cudaProducer->tempBuff);
}
if (cudaProducer->cudaPtr) {
cuMemFree(cudaProducer->cudaPtr);
}
return cuEGLStreamProducerDisconnect(&cudaProducer->cudaConn);
}

View File

@@ -0,0 +1,68 @@
/* 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.
*/
//
// DESCRIPTION: Simple cuda producer header file
//
#ifndef _CUDA_PRODUCER_H_
#define _CUDA_PRODUCER_H_
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include "cudaEGL.h"
#include "eglstrm_common.h"
#include <cuda_runtime.h>
#include <cuda.h>
typedef struct _test_cuda_producer_s {
// Stream params
CUcontext context;
CUeglStreamConnection cudaConn;
int cudaDevId;
EGLStreamKHR eglStream;
EGLDisplay eglDisplay;
unsigned int charCnt;
bool profileAPI;
char *tempBuff;
CUdeviceptr cudaPtr;
CUdeviceptr cudaPtr1;
CUstream prodCudaStream;
} test_cuda_producer_s;
CUresult cudaProducerInit(test_cuda_producer_s *cudaProducer, TestArgs *args);
CUresult cudaProducerPresentFrame(test_cuda_producer_s *parserArg,
CUeglFrame cudaEgl, int t);
CUresult cudaProducerReturnFrame(test_cuda_producer_s *parserArg,
CUeglFrame cudaEgl, int t);
CUresult cudaProducerDeinit(test_cuda_producer_s *cudaProducer);
CUresult cudaDeviceCreateProducer(test_cuda_producer_s *cudaProducer);
cudaError_t cudaProducer_filter(CUstream cStream, char *pSrc, int width,
int height, char expectedVal, char newVal,
int frameNumber);
void cudaProducerPrepareFrame(CUeglFrame *cudaEgl, CUdeviceptr cudaPtr,
int bufferSize);
#endif

View File

@@ -0,0 +1,423 @@
/* 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.
*/
//
// DESCRIPTION: Common egl stream functions
//
#include "eglstrm_common.h"
EGLStreamKHR g_producerEglStream = EGL_NO_STREAM_KHR;
EGLStreamKHR g_consumerEglStream = EGL_NO_STREAM_KHR;
EGLDisplay g_producerEglDisplay = EGL_NO_DISPLAY;
EGLDisplay g_consumerEglDisplay = EGL_NO_DISPLAY;
int cudaDevIndexProd = -1;
int cudaDevIndexCons = -1;
#if defined(EXTENSION_LIST)
EXTENSION_LIST(EXTLST_DECL)
typedef void (*extlst_fnptr_t)(void);
static struct {
extlst_fnptr_t *fnptr;
char const *name;
bool is_dgpu; // This function is need only for dgpu case
} extensionList[] = {EXTENSION_LIST(EXTLST_ENTRY)};
int eglSetupExtensions(bool isCrossDevice) {
unsigned int i;
for (i = 0; i < (sizeof(extensionList) / sizeof(*extensionList)); i++) {
// load the dgpu function only if we are running cross device test
if ((!extensionList[i].is_dgpu) ||
(extensionList[i].is_dgpu == isCrossDevice)) {
*extensionList[i].fnptr = eglGetProcAddress(extensionList[i].name);
if (*extensionList[i].fnptr == NULL) {
printf("Couldn't get address of %s()\n", extensionList[i].name);
return 0;
}
}
}
return 1;
}
int EGLStreamInit(bool isCrossDevice, int isConsumer,
EGLNativeFileDescriptorKHR fileDesc) {
static const EGLint streamAttrFIFOMode[] = {
EGL_STREAM_FIFO_LENGTH_KHR, 5, EGL_SUPPORT_REUSE_NV, EGL_FALSE, EGL_NONE};
EGLDisplay eglDisplay[2] = {0};
EGLStreamKHR eglStream[2] = {0};
EGLBoolean eglStatus;
#define MAX_EGL_DEVICES 4
EGLDeviceEXT devices[MAX_EGL_DEVICES];
EGLint numDevices = 0;
eglStatus = eglQueryDevicesEXT(MAX_EGL_DEVICES, devices, &numDevices);
if (eglStatus != EGL_TRUE) {
printf("Error querying EGL devices\n");
goto Done;
}
if (numDevices == 0) {
printf("No EGL devices found\n");
eglStatus = EGL_FALSE;
goto Done;
}
// If cross device, create discrete GPU stream first and then create the
// integrated GPU stream to connect to it via fd. The other way round fails
// in producer connect.
//
// TODO: Find out if this EGL behavior is by design.
if (isConsumer) {
int egl_device_id = 0;
for (egl_device_id = 0; egl_device_id < numDevices; egl_device_id++) {
EGLAttrib cuda_device;
eglStatus = eglQueryDeviceAttribEXT(devices[egl_device_id],
EGL_CUDA_DEVICE_NV, &cuda_device);
if (eglStatus == EGL_TRUE) {
cudaDevIndexCons = cuda_device; // We select first EGL-CUDA Capable
// device for consumer.
printf(
"Found EGL-CUDA Capable device with CUDA Device id = %d out of "
"egl_device_id = %d\n",
(int)cudaDevIndexCons, egl_device_id);
break;
}
}
if (egl_device_id >= numDevices) {
printf("No CUDA Capable EGL Device found.. Waiving execution\n");
goto Done;
}
g_consumerEglDisplay = eglGetPlatformDisplayEXT(
EGL_PLATFORM_DEVICE_EXT, (void *)devices[egl_device_id], NULL);
if (g_consumerEglDisplay == EGL_NO_DISPLAY) {
printf("Could not get EGL display from device. \n");
eglStatus = EGL_FALSE;
goto Done;
}
eglStatus = eglInitialize(g_consumerEglDisplay, 0, 0);
if (!eglStatus) {
printf("EGL failed to initialize. \n");
eglStatus = EGL_FALSE;
goto Done;
}
g_consumerEglStream =
eglCreateStreamKHR(g_consumerEglDisplay, streamAttrFIFOMode);
if (g_consumerEglStream == EGL_NO_STREAM_KHR) {
printf("Could not create EGL stream.\n");
eglStatus = EGL_FALSE;
goto Done;
}
eglStatus = eglStreamAttribKHR(g_consumerEglDisplay, g_consumerEglStream,
EGL_CONSUMER_LATENCY_USEC_KHR, 16000);
if (eglStatus != EGL_TRUE) {
printf("eglStreamAttribKHR EGL_CONSUMER_LATENCY_USEC_KHR failed\n");
goto Done;
}
eglStatus =
eglStreamAttribKHR(g_consumerEglDisplay, g_consumerEglStream,
EGL_CONSUMER_ACQUIRE_TIMEOUT_USEC_KHR, 16000);
if (eglStatus != EGL_TRUE) {
printf(
"eglStreamAttribKHR EGL_CONSUMER_ACQUIRE_TIMEOUT_USEC_KHR failed\n");
goto Done;
}
}
if (!isConsumer) { // Producer
if (fileDesc == EGL_NO_FILE_DESCRIPTOR_KHR) {
printf("Cuda Producer received bad file descriptor\n");
eglStatus = EGL_FALSE;
goto Done;
}
int egl_device_id = 0;
int egl_cuda_devices = 0;
for (egl_device_id = 0; egl_device_id < numDevices; egl_device_id++) {
EGLAttrib cuda_device = -1;
eglStatus = eglQueryDeviceAttribEXT(devices[egl_device_id],
EGL_CUDA_DEVICE_NV, &cuda_device);
if (eglStatus == EGL_TRUE) {
egl_cuda_devices++;
if (isCrossDevice && (egl_cuda_devices > 1)) {
// We select second EGL-CUDA Capable device for producer.
cudaDevIndexProd = (int)cuda_device;
printf(
"Found EGL-CUDA Capable device with CUDA Device id = %d "
"egl_device_id = %d \n",
(int)cudaDevIndexProd, egl_device_id);
break;
}
if (!isCrossDevice) {
// We select first EGL-CUDA Capable device for producer same as
// consumer.
cudaDevIndexProd = (int)cuda_device;
printf(
"Found EGL-CUDA Capable device with CUDA Device id = %d "
"egl_device_id = %d \n",
(int)cudaDevIndexProd, egl_device_id);
break;
}
}
}
if (egl_device_id >= numDevices) {
printf("No CUDA Capable EGL Device found.. Waiving execution\n");
goto Done;
}
g_producerEglDisplay = eglGetPlatformDisplayEXT(
EGL_PLATFORM_DEVICE_EXT, (void *)devices[egl_device_id], NULL);
if (g_producerEglDisplay == EGL_NO_DISPLAY) {
printf("Could not get EGL display from device. \n");
eglStatus = EGL_FALSE;
goto Done;
}
eglStatus = eglInitialize(g_producerEglDisplay, 0, 0);
if (!eglStatus) {
printf("EGL failed to initialize. \n");
eglStatus = EGL_FALSE;
goto Done;
}
g_producerEglStream =
eglCreateStreamFromFileDescriptorKHR(g_producerEglDisplay, fileDesc);
close(fileDesc);
if (g_producerEglStream == EGL_NO_STREAM_KHR) {
printf("CUDA Producer Could not create EGL stream.\n");
eglStatus = EGL_FALSE;
goto Done;
} else {
printf("Producer created EGLStream for the GPU.\n");
}
}
Done:
return eglStatus == EGL_TRUE ? 1 : 0;
}
void EGLStreamFini(void) {
if (g_producerEglStream != EGL_NO_STREAM_KHR) {
eglDestroyStreamKHR(g_producerEglDisplay, g_producerEglStream);
}
if (g_consumerEglStream != g_producerEglStream) {
if (g_consumerEglStream != EGL_NO_STREAM_KHR) {
eglDestroyStreamKHR(g_consumerEglDisplay, g_consumerEglStream);
}
}
}
int UnixSocketConnect(const char *socket_name) {
int sock_fd = -1;
struct sockaddr_un sock_addr;
int wait_loop = 0;
sock_fd = socket(PF_UNIX, SOCK_STREAM, 0);
if (sock_fd < 0) {
printf("%s: socket create failed.\n", __func__);
return -1;
}
if (verbose) printf("%s: send_fd: sock_fd: %d\n", __func__, sock_fd);
memset(&sock_addr, 0, sizeof(struct sockaddr_un));
sock_addr.sun_family = AF_UNIX;
strncpy(sock_addr.sun_path, socket_name, sizeof(sock_addr.sun_path) - 1);
while (connect(sock_fd, (const struct sockaddr *)&sock_addr,
sizeof(struct sockaddr_un))) {
if (wait_loop < 60) {
if (!wait_loop)
printf("Waiting for EGL stream producer ");
else
printf(".");
fflush(stdout);
sleep(1);
wait_loop++;
} else {
printf("\n%s: Waiting timed out\n", __func__);
return -1;
}
}
if (wait_loop) printf("\n");
if (verbose) printf("%s: Wait is done\n", __func__);
return sock_fd;
}
/* Send <fd_to_send> (a file descriptor) to another process */
/* over a unix domain socket named <socket_name>. */
/* <socket_name> can be any nonexistant filename. */
int EGLStreamSendfd(int send_fd, int fd_to_send) {
struct msghdr msg;
struct iovec iov[1];
char ctrl_buf[CMSG_SPACE(sizeof(int))];
struct cmsghdr *cmsg = NULL;
void *data;
int res;
memset(&msg, 0, sizeof(msg));
iov[0].iov_len = 1; // must send at least 1 byte
iov[0].iov_base = (void *)"x"; // any byte value (value ignored)
msg.msg_iov = iov;
msg.msg_iovlen = 1;
memset(ctrl_buf, 0, sizeof(ctrl_buf));
msg.msg_control = ctrl_buf;
msg.msg_controllen = sizeof(ctrl_buf);
cmsg = CMSG_FIRSTHDR(&msg);
cmsg->cmsg_level = SOL_SOCKET;
cmsg->cmsg_type = SCM_RIGHTS;
cmsg->cmsg_len = CMSG_LEN(sizeof(int));
data = CMSG_DATA(cmsg);
*(int *)data = fd_to_send;
msg.msg_controllen = cmsg->cmsg_len;
res = sendmsg(send_fd, &msg, 0);
if (res <= 0) {
printf("%s: sendmsg failed", __func__);
return -1;
}
return 0;
}
/* Listen on a unix domain socket named <socket_name>. */
/* Connect to it and return connect_fd */
int UnixSocketCreate(const char *socket_name) {
int listen_fd;
struct sockaddr_un sock_addr;
int connect_fd;
struct sockaddr_un connect_addr;
socklen_t connect_addr_len = 0;
listen_fd = socket(PF_UNIX, SOCK_STREAM, 0);
if (listen_fd < 0) {
printf("%s: socket create failed", __func__);
return -1;
}
if (verbose) printf("%s: listen_fd: %d\n", __func__, listen_fd);
unlink(socket_name);
memset(&sock_addr, 0, sizeof(struct sockaddr_un));
sock_addr.sun_family = AF_UNIX;
strncpy(sock_addr.sun_path, socket_name, sizeof(sock_addr.sun_path) - 1);
if (bind(listen_fd, (const struct sockaddr *)&sock_addr,
sizeof(struct sockaddr_un))) {
printf("i%s: bind error", __func__);
return -1;
}
if (listen(listen_fd, 1)) {
printf("%s: listen error", __func__);
return -1;
}
connect_fd =
accept(listen_fd, (struct sockaddr *)&connect_addr, &connect_addr_len);
if (verbose) printf("%s: connect_fd: %d\n", __func__, connect_fd);
close(listen_fd);
unlink(socket_name);
if (connect_fd < 0) {
printf("%s: accept failed\n", __func__);
return -1;
}
return connect_fd;
}
/* receive a file descriptor from another process. */
/* Returns the file descriptor. Note: the integer value */
/* of the file descriptor may be different from the */
/* integer value in the other process, but the file */
/* descriptors in each process will refer to the same file */
/* object in the kernel. */
int EGLStreamReceivefd(int connect_fd) {
struct msghdr msg;
struct iovec iov[1];
char msg_buf[1];
char ctrl_buf[CMSG_SPACE(sizeof(int))];
struct cmsghdr *cmsg;
void *data;
int recvfd;
memset(&msg, 0, sizeof(msg));
iov[0].iov_base = msg_buf;
iov[0].iov_len = sizeof(msg_buf);
msg.msg_iov = iov;
msg.msg_iovlen = 1;
msg.msg_control = ctrl_buf;
msg.msg_controllen = sizeof(ctrl_buf);
if (recvmsg(connect_fd, &msg, 0) <= 0) {
printf("%s: recvmsg failed", __func__);
return -1;
}
cmsg = CMSG_FIRSTHDR(&msg);
if (!cmsg) {
printf("%s: NULL message header\n", __func__);
return -1;
}
if (cmsg->cmsg_level != SOL_SOCKET) {
printf("%s: Message level is not SOL_SOCKET\n", __func__);
return -1;
}
if (cmsg->cmsg_type != SCM_RIGHTS) {
printf("%s: Message type is not SCM_RIGHTS\n", __func__);
return -1;
}
data = CMSG_DATA(cmsg);
recvfd = *(int *)data;
return recvfd;
}
#endif

View File

@@ -0,0 +1,113 @@
/* 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.
*/
//
// DESCRIPTION: Common EGL stream functions header file
//
#ifndef _EGLSTRM_COMMON_H_
#define _EGLSTRM_COMMON_H_
#include <signal.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/un.h>
#include <time.h>
#include <unistd.h>
#include "cuda.h"
#include "cudaEGL.h"
#define TIME_DIFF(end, start) (getMicrosecond(end) - getMicrosecond(start))
extern EGLStreamKHR g_producerEglStream;
extern EGLStreamKHR g_consumerEglStream;
extern EGLDisplay g_producerEglDisplay;
extern EGLDisplay g_consumerEglDisplay;
extern int cudaDevIndexCons;
extern int cudaDevIndexProd;
extern bool verbose;
#define EXTENSION_LIST(T) \
T(PFNEGLCREATESTREAMKHRPROC, eglCreateStreamKHR) \
T(PFNEGLDESTROYSTREAMKHRPROC, eglDestroyStreamKHR) \
T(PFNEGLQUERYSTREAMKHRPROC, eglQueryStreamKHR) \
T(PFNEGLQUERYSTREAMU64KHRPROC, eglQueryStreamu64KHR) \
T(PFNEGLQUERYSTREAMTIMEKHRPROC, eglQueryStreamTimeKHR) \
T(PFNEGLSTREAMATTRIBKHRPROC, eglStreamAttribKHR) \
T(PFNEGLSTREAMCONSUMERACQUIREKHRPROC, eglStreamConsumerAcquireKHR) \
T(PFNEGLSTREAMCONSUMERRELEASEKHRPROC, eglStreamConsumerReleaseKHR) \
T(PFNEGLSTREAMCONSUMERGLTEXTUREEXTERNALKHRPROC, \
eglStreamConsumerGLTextureExternalKHR) \
T(PFNEGLQUERYDEVICESEXTPROC, eglQueryDevicesEXT) \
T(PFNEGLGETPLATFORMDISPLAYEXTPROC, eglGetPlatformDisplayEXT) \
T(PFNEGLGETSTREAMFILEDESCRIPTORKHRPROC, eglGetStreamFileDescriptorKHR) \
T(PFNEGLQUERYDEVICEATTRIBEXTPROC, eglQueryDeviceAttribEXT) \
T(PFNEGLCREATESTREAMFROMFILEDESCRIPTORKHRPROC, \
eglCreateStreamFromFileDescriptorKHR)
#define EXTLST_DECL(tx, x) tx x = NULL;
#define EXTLST_EXTERN(tx, x) extern tx x;
#define EXTLST_ENTRY(tx, x) {(extlst_fnptr_t *)&x, #x},
#define MAX_STRING_SIZE 256
#define INIT_DATA 0x01
#define PROD_DATA 0x07
#define CONS_DATA 0x04
#define SOCK_PATH "/tmp/tegra_sw_egl_socket"
typedef struct _TestArgs {
unsigned int charCnt;
bool isProducer;
} TestArgs;
extern int WIDTH, HEIGHT;
int eglSetupExtensions(bool is_dgpu);
int EGLStreamInit(bool isCrossDevice, int isConsumer,
EGLNativeFileDescriptorKHR fileDesc);
void EGLStreamFini(void);
int EGLStreamSetAttr(EGLDisplay display, EGLStreamKHR eglStream);
int UnixSocketConnect(const char *socket_name);
int EGLStreamSendfd(int send_fd, int fd_to_send);
int UnixSocketCreate(const char *socket_name);
int EGLStreamReceivefd(int connect_fd);
static clockid_t clock_id = CLOCK_MONOTONIC; // CLOCK_PROCESS_CPUTIME_ID;
static double getMicrosecond(struct timespec t) {
return ((t.tv_sec) * 1000000.0 + (t.tv_nsec) / 1.0e3);
}
static inline void getTime(struct timespec *t) { clock_gettime(clock_id, t); }
#endif

View File

@@ -0,0 +1,160 @@
################################################################################
# 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.
#
################################################################################
#
# findegl.mk is used to find the necessary EGL Libraries for specific distributions
# this is supported on Linux
#
################################################################################
# Determine OS platform and unix distribution
ifeq ("$(TARGET_OS)","linux")
# first search lsb_release
DISTRO = $(shell lsb_release -i -s 2>/dev/null | tr "[:upper:]" "[:lower:]")
ifeq ("$(DISTRO)","")
# second search and parse /etc/issue
DISTRO = $(shell more /etc/issue | awk '{print $$1}' | sed '1!d' | sed -e "/^$$/d" 2>/dev/null | tr "[:upper:]" "[:lower:]")
# ensure data from /etc/issue is valid
ifeq (,$(filter $(DISTRO),ubuntu fedora red rhel centos suse))
DISTRO =
endif
ifeq ("$(DISTRO)","")
# third, we can search in /etc/os-release or /etc/{distro}-release
DISTRO = $(shell awk '/ID/' /etc/*-release | sed 's/ID=//' | grep -v "VERSION" | grep -v "ID" | grep -v "DISTRIB")
endif
endif
endif
ifeq ("$(TARGET_OS)","linux")
# $(info) >> findegl.mk -> LINUX path <<<)
# Each set of Linux Distros have different paths for where to find their OpenGL libraries reside
UBUNTU = $(shell echo $(DISTRO) | grep -i ubuntu >/dev/null 2>&1; echo $$?)
FEDORA = $(shell echo $(DISTRO) | grep -i fedora >/dev/null 2>&1; echo $$?)
RHEL = $(shell echo $(DISTRO) | grep -i 'red\|rhel' >/dev/null 2>&1; echo $$?)
CENTOS = $(shell echo $(DISTRO) | grep -i centos >/dev/null 2>&1; echo $$?)
SUSE = $(shell echo $(DISTRO) | grep -i 'suse\|sles' >/dev/null 2>&1; echo $$?)
ifeq ("$(UBUNTU)","0")
ifeq ($(HOST_ARCH)-$(TARGET_ARCH),x86_64-armv7l)
GLPATH := /usr/arm-linux-gnueabihf/lib
GLLINK := -L/usr/arm-linux-gnueabihf/lib
ifneq ($(TARGET_FS),)
GLPATH += $(TARGET_FS)/usr/lib/arm-linux-gnueabihf
GLLINK += -L$(TARGET_FS)/usr/lib/arm-linux-gnueabihf
endif
else ifeq ($(HOST_ARCH)-$(TARGET_ARCH),x86_64-aarch64)
GLPATH := /usr/aarch64-linux-gnu/lib
GLLINK := -L/usr/aarch64-linux-gnu/lib
ifneq ($(TARGET_FS),)
GLPATH += $(TARGET_FS)/usr/lib
GLPATH += $(TARGET_FS)/usr/lib/aarch64-linux-gnu
GLLINK += -L$(TARGET_FS)/usr/lib/aarch64-linux-gnu
endif
else
UBUNTU_PKG_NAME = $(shell which dpkg >/dev/null 2>&1 && dpkg -l 'nvidia-*' | grep '^ii' | awk '{print $$2}' | head -1)
ifneq ("$(UBUNTU_PKG_NAME)","")
GLPATH ?= /usr/lib/$(UBUNTU_PKG_NAME)
GLLINK ?= -L/usr/lib/$(UBUNTU_PKG_NAME)
endif
DFLT_PATH ?= /usr/lib
endif
endif
ifeq ("$(SUSE)","0")
GLPATH ?= /usr/X11R6/lib64
GLLINK ?= -L/usr/X11R6/lib64
DFLT_PATH ?= /usr/lib64
endif
ifeq ("$(FEDORA)","0")
GLPATH ?= /usr/lib64/nvidia
GLLINK ?= -L/usr/lib64/nvidia
DFLT_PATH ?= /usr/lib64
endif
ifeq ("$(RHEL)","0")
GLPATH ?= /usr/lib64/nvidia
GLLINK ?= -L/usr/lib64/nvidia
DFLT_PATH ?= /usr/lib64
endif
ifeq ("$(CENTOS)","0")
GLPATH ?= /usr/lib64/nvidia
GLLINK ?= -L/usr/lib64/nvidia
DFLT_PATH ?= /usr/lib64
endif
EGLLIB := $(shell find -L $(GLPATH) $(DFLT_PATH) -name libEGL.so -print 2>/dev/null)
ifeq ("$(EGLLIB)","")
$(info >>> WARNING - libEGL.so not found, please install libEGL.so <<<)
SAMPLE_ENABLED := 0
endif
HEADER_SEARCH_PATH ?= $(TARGET_FS)/usr/include
ifeq ($(HOST_ARCH)-$(TARGET_ARCH)-$(TARGET_OS),x86_64-armv7l-linux)
HEADER_SEARCH_PATH += /usr/arm-linux-gnueabihf/include
else ifeq ($(HOST_ARCH)-$(TARGET_ARCH)-$(TARGET_OS),x86_64-aarch64-linux)
HEADER_SEARCH_PATH += /usr/aarch64-linux-gnu/include
endif
EGLHEADER := $(shell find -L $(HEADER_SEARCH_PATH) -name egl.h -print 2>/dev/null)
EGLEXTHEADER := $(shell find -L $(HEADER_SEARCH_PATH) -name eglext.h -print 2>/dev/null)
ifeq ("$(EGLHEADER)","")
$(info >>> WARNING - egl.h not found, please install egl.h <<<)
SAMPLE_ENABLED := 0
endif
ifeq ("$(EGLEXTHEADER)","")
$(info >>> WARNING - eglext.h not found, please install eglext.h <<<)
SAMPLE_ENABLED := 0
endif
else
endif
ifeq ("$(TARGET_OS)","qnx")
HOST_CCFLAGS := -V8.3.0,gcc_ntoaarch64le
endif
# Attempt to compile a minimal EGL application and run to check if EGL_SUPPORT_REUSE_NV is supported in the EGL headers available.
ifneq ($(SAMPLE_ENABLED), 0)
$(shell printf "#include <EGL/egl.h>\n#include <EGL/eglext.h>\nint main() {\n#ifdef EGL_SUPPORT_REUSE_NV \n #error \"Compatible EGL header found\" \n return 0;\n#endif \n return 1;\n}" > test.c; )
EGL_DEFINES := $(shell $(HOST_COMPILER) $(HOST_CCFLAGS) $(CCFLAGS) $(EXTRA_CCFLAGS) -lEGL test.c -c 2>&1 | grep -ic "Compatible EGL header found";)
SHOULD_WAIVE := 0
ifeq ($(EGL_DEFINES),0)
SHOULD_WAIVE := 1
endif
ifeq ($(SHOULD_WAIVE),1)
$(info -----------------------------------------------------------------------------------------------)
$(info WARNING - NVIDIA EGL EXTENSIONS are not available in the present EGL headers)
$(info -----------------------------------------------------------------------------------------------)
$(info This CUDA Sample cannot be built if the EGL NVIDIA EXTENSIONS like EGL_SUPPORT_REUSE_NV are not supported in EGL headers.)
$(info This will be a dry-run of the Makefile.)
$(info Please install the latest khronos EGL headers and libs to build this sample)
$(info -----------------------------------------------------------------------------------------------)
SAMPLE_ENABLED := 0
endif
$(shell rm test.o test.c 2>/dev/null)
endif

View File

@@ -0,0 +1,221 @@
/* 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.
*/
#include "eglstrm_common.h"
#if defined(EXTENSION_LIST)
EXTENSION_LIST(EXTLST_EXTERN)
#endif
#include <cuda.h>
int parseCmdLine(int argc, char *argv[], TestArgs *args);
void printUsage(void);
int NUMTRIALS = 10;
int profileAPIs = 0;
bool verbose = 0;
bool isCrossDevice = 0;
// Parse the command line options. Returns FAILURE on a parse error, SUCCESS
// otherwise.
int parseCmdLine(int argc, char *argv[], TestArgs *args) {
int i;
for (i = 1; i < argc; i++) {
if (strcmp(argv[i], "-h") == 0) {
printUsage();
exit(0);
} else if (strcmp(argv[i], "-n") == 0) {
++i;
if (sscanf(argv[i], "%d", &NUMTRIALS) != 1 || NUMTRIALS <= 0) {
printf("Invalid trial count: %s should be > 0\n", argv[i]);
return -1;
}
} else if (strcmp(argv[i], "-profile") == 0) {
profileAPIs = 1;
} else if (strcmp(argv[i], "-crossdev") == 0) {
isCrossDevice = 1;
} else if (strcmp(argv[i], "-width") == 0) {
++i;
if (sscanf(argv[i], "%d", &WIDTH) != 1 || (WIDTH <= 0)) {
printf("Width should be greater than 0\n");
return -1;
}
} else if (strcmp(argv[i], "-height") == 0) {
++i;
if (sscanf(argv[i], "%d", &HEIGHT) != 1 || (HEIGHT <= 0)) {
printf("Width should be greater than 0\n");
return -1;
}
} else if (0 == strcmp(&argv[i][1], "proctype")) {
++i;
if (!strcasecmp(argv[i], "prod")) {
args->isProducer = 1;
} else if (!strcasecmp(argv[i], "cons")) {
args->isProducer = 0;
} else {
printf("%s: Bad Process Type: %s\n", __func__, argv[i]);
return 1;
}
} else if (strcmp(argv[i], "-v") == 0) {
verbose = 1;
} else {
printf("Unknown option: %s\n", argv[i]);
return -1;
}
}
if (isCrossDevice) {
int deviceCount = 0;
CUresult error_id = cuInit(0);
if (error_id != CUDA_SUCCESS) {
printf("cuInit(0) returned %d\n", error_id);
printf("Result = FAIL\n");
exit(EXIT_FAILURE);
}
error_id = cuDeviceGetCount(&deviceCount);
if (error_id != CUDA_SUCCESS) {
printf("cuDeviceGetCount returned %d\n", (int)error_id);
printf("Result = FAIL\n");
exit(EXIT_FAILURE);
}
int iGPUexists = 0;
CUdevice dev;
for (dev = 0; dev < deviceCount; ++dev) {
int integrated = 0;
CUresult error_result = cuDeviceGetAttribute(
&integrated, CU_DEVICE_ATTRIBUTE_INTEGRATED, dev);
if (error_result != CUDA_SUCCESS) {
printf("cuDeviceGetAttribute returned error : %d\n", (int)error_result);
exit(EXIT_FAILURE);
}
if (integrated) {
iGPUexists = 1;
}
}
if (!iGPUexists) {
printf("No Integrated GPU found in the system.\n");
printf(
"-crossdev option is only supported on systems with an Integrated "
"GPU and a Discrete GPU\n");
printf("Waiving the execution\n");
exit(EXIT_SUCCESS);
}
}
if (!eglSetupExtensions(isCrossDevice)) {
printf("SetupExtentions failed \n");
exit(EXIT_FAILURE);
}
#define MAX_EGL_DEVICES 4
EGLDeviceEXT devices[MAX_EGL_DEVICES];
EGLint numDevices = 0;
EGLBoolean eglStatus =
eglQueryDevicesEXT(MAX_EGL_DEVICES, devices, &numDevices);
if (eglStatus != EGL_TRUE) {
printf("Error querying EGL devices\n");
exit(EXIT_FAILURE);
}
if (numDevices == 0) {
printf("No EGL devices found\n");
eglStatus = EGL_FALSE;
exit(2); // EXIT_WAIVED
}
int egl_device_id = 0;
for (egl_device_id = 0; egl_device_id < numDevices; egl_device_id++) {
EGLAttrib cuda_device;
eglStatus = eglQueryDeviceAttribEXT(devices[egl_device_id],
EGL_CUDA_DEVICE_NV, &cuda_device);
if (eglStatus == EGL_TRUE) {
break;
}
}
if (egl_device_id >= numDevices) {
printf("No CUDA Capable EGL Device found.. Waiving execution\n");
exit(2); // EXIT_WAIVED
}
if (isCrossDevice) {
if (numDevices == 1) {
printf(
"Found only one EGL device, cannot setup cross GPU streams. "
"Waiving\n");
eglStatus = EGL_FALSE;
exit(2); // EXIT_WAIVED
}
}
return 0;
}
void launchProducer(TestArgs *args) {
/* Cross-process creation of producer */
char argsProducer[1024];
char str[256];
strcpy(argsProducer, "./EGLStream_CUDA_CrossGPU -proctype prod ");
if (isCrossDevice) {
sprintf(str, "-crossdev ");
strcat(argsProducer, str);
}
if (verbose) {
sprintf(str, "-v ");
strcat(argsProducer, str);
}
/*Make the process run in bg*/
strcat(argsProducer, "& ");
printf("\n%s: Crossproc Producer command: %s \n", __func__, argsProducer);
/*Create crossproc Producer*/
system(argsProducer);
/*Enable crossproc Consumer in the same process */
args->isProducer = 0;
}
void printUsage(void) {
printf("Usage:\n");
printf(" -h Print this help message\n");
printf(" -n n Exit after running n trials. Set to 10 by default\n");
printf(
" -profile Profile time taken by ReleaseAPI. Not set by default\n");
printf(" -crossdev Run with producer on idgpu and consumer on dgpu\n");
printf(" -dgpu (same as -crossdev, deprecated)\n");
printf(" -v verbose output\n");
}

View File

@@ -0,0 +1,140 @@
/* 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.
*/
//
// DESCRIPTION: Simple CUDA consumer rendering sample app
//
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include <cuda.h>
#include <cuda_runtime.h>
#include <stdio.h>
#include <string.h>
#include "eglstrm_common.h"
extern bool isCrossDevice;
__device__ static unsigned int numErrors = 0, errorFound = 0;
__device__ void checkProducerDataGPU(char *data, int size, char expectedVal,
int frameNumber) {
if ((data[blockDim.x * blockIdx.x + threadIdx.x] != expectedVal) &&
(!errorFound)) {
printf("Producer FOUND:%d expected: %d at %d for trial %d %d\n",
data[blockDim.x * blockIdx.x + threadIdx.x], expectedVal,
(blockDim.x * blockIdx.x + threadIdx.x), frameNumber, numErrors);
numErrors++;
errorFound = 1;
return;
}
}
__device__ void checkConsumerDataGPU(char *data, int size, char expectedVal,
int frameNumber) {
if ((data[blockDim.x * blockIdx.x + threadIdx.x] != expectedVal) &&
(!errorFound)) {
printf("Consumer FOUND:%d expected: %d at %d for trial %d %d\n",
data[blockDim.x * blockIdx.x + threadIdx.x], expectedVal,
(blockDim.x * blockIdx.x + threadIdx.x), frameNumber, numErrors);
numErrors++;
errorFound = 1;
return;
}
}
__global__ void writeDataToBuffer(char *pSrc, char newVal) {
pSrc[blockDim.x * blockIdx.x + threadIdx.x] = newVal;
}
__global__ void testKernelConsumer(char *pSrc, char size, char expectedVal,
char newVal, int frameNumber) {
checkConsumerDataGPU(pSrc, size, expectedVal, frameNumber);
}
__global__ void testKernelProducer(char *pSrc, char size, char expectedVal,
char newVal, int frameNumber) {
checkProducerDataGPU(pSrc, size, expectedVal, frameNumber);
}
__global__ void getNumErrors(int *numErr) { *numErr = numErrors; }
cudaError_t cudaProducer_filter(cudaStream_t pStream, char *pSrc, int width,
int height, char expectedVal, char newVal,
int frameNumber) {
// in case where consumer is on dgpu and producer is on igpu when return is
// called the frame is not copied back to igpu. So the consumer changes is not
// visible to producer
if (isCrossDevice == 0) {
testKernelProducer<<<(width * height) / 1024, 1024, 1, pStream>>>(
pSrc, width * height, expectedVal, newVal, frameNumber);
}
writeDataToBuffer<<<(width * height) / 1024, 1024, 1, pStream>>>(pSrc,
newVal);
return cudaSuccess;
};
cudaError_t cudaConsumer_filter(cudaStream_t cStream, char *pSrc, int width,
int height, char expectedVal, char newVal,
int frameNumber) {
testKernelConsumer<<<(width * height) / 1024, 1024, 1, cStream>>>(
pSrc, width * height, expectedVal, newVal, frameNumber);
writeDataToBuffer<<<(width * height) / 1024, 1024, 1, cStream>>>(pSrc,
newVal);
return cudaSuccess;
};
cudaError_t cudaGetValueMismatch() {
int numErr_h;
int *numErr_d = NULL;
cudaError_t err = cudaSuccess;
err = cudaMalloc(&numErr_d, sizeof(int));
if (err != cudaSuccess) {
printf("Cuda Main: cudaMalloc failed with %s\n", cudaGetErrorString(err));
return err;
}
getNumErrors<<<1, 1>>>(numErr_d);
err = cudaDeviceSynchronize();
if (err != cudaSuccess) {
printf("Cuda Main: cudaDeviceSynchronize failed with %s\n",
cudaGetErrorString(err));
}
err = cudaMemcpy(&numErr_h, numErr_d, sizeof(int), cudaMemcpyDeviceToHost);
if (err != cudaSuccess) {
printf("Cuda Main: cudaMemcpy failed with %s\n", cudaGetErrorString(err));
cudaFree(numErr_d);
return err;
}
err = cudaFree(numErr_d);
if (err != cudaSuccess) {
printf("Cuda Main: cudaFree failed with %s\n", cudaGetErrorString(err));
return err;
}
if (numErr_h > 0) {
return cudaErrorUnknown;
}
return cudaSuccess;
}

View File

@@ -0,0 +1,392 @@
/* 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.
*/
#include "cudaEGL.h"
#include "cuda_consumer.h"
#include "cuda_producer.h"
#include "eglstrm_common.h"
#include "helper.h"
#if defined(EXTENSION_LIST)
EXTENSION_LIST(EXTLST_EXTERN)
#endif
bool signal_stop = 0;
extern bool verbose;
static void sig_handler(int sig) {
signal_stop = 1;
printf("Signal: %d\n", sig);
}
void DoneCons(int consumerStatus, int send_fd) {
EGLStreamFini();
// get the final status from producer, combine and print
int producerStatus = -1;
if (-1 == recv(send_fd, (void *)&producerStatus, sizeof(int), 0)) {
printf("%s: Cuda Consumer could not receive status from producer.\n",
__func__);
}
close(send_fd);
if (producerStatus == 0 && consumerStatus == 0) {
printf("&&&& EGLStream_CUDA_CrossGPU PASSED\n");
exit(EXIT_SUCCESS);
} else {
printf("&&&& EGLStream_CUDA_CrossGPU FAILED\n");
exit(EXIT_FAILURE);
}
}
void DoneProd(int producerStatus, int connect_fd) {
EGLStreamFini();
if (-1 == send(connect_fd, (void *)&producerStatus, sizeof(int), 0)) {
printf("%s: Cuda Producer could not send status to consumer.\n", __func__);
}
close(connect_fd);
if (producerStatus == 0) {
exit(EXIT_SUCCESS);
} else {
exit(EXIT_FAILURE);
}
}
int WIDTH = 8192, HEIGHT = 8192;
int main(int argc, char **argv) {
TestArgs args = {0, false};
CUresult curesult = CUDA_SUCCESS;
unsigned int j = 0;
cudaError_t err = cudaSuccess;
EGLNativeFileDescriptorKHR fileDescriptor = EGL_NO_FILE_DESCRIPTOR_KHR;
struct timespec start, end;
CUeglFrame cudaEgl1, cudaEgl2;
int consumerStatus = 0;
int send_fd = -1;
if (parseCmdLine(argc, argv, &args) < 0) {
printUsage();
curesult = CUDA_ERROR_UNKNOWN;
DoneCons(consumerStatus, send_fd);
}
printf("Width : %u, height: %u and iterations: %u\n", WIDTH, HEIGHT,
NUMTRIALS);
if (!args.isProducer) // Consumer code
{
test_cuda_consumer_s cudaConsumer;
memset(&cudaConsumer, 0, sizeof(test_cuda_consumer_s));
cudaConsumer.profileAPI = profileAPIs;
// Hook up Ctrl-C handler
signal(SIGINT, sig_handler);
if (!EGLStreamInit(isCrossDevice, !args.isProducer,
EGL_NO_FILE_DESCRIPTOR_KHR)) {
printf("EGLStream Init failed.\n");
curesult = CUDA_ERROR_UNKNOWN;
consumerStatus = -1;
DoneCons(consumerStatus, send_fd);
}
cudaConsumer.cudaDevId = cudaDevIndexCons;
curesult = cudaDeviceCreateConsumer(&cudaConsumer);
if (curesult != CUDA_SUCCESS) {
consumerStatus = -1;
DoneCons(consumerStatus, send_fd);
}
cuCtxPushCurrent(cudaConsumer.context);
launchProducer(&args);
args.charCnt = WIDTH * HEIGHT * 4;
curesult = cuda_consumer_init(&cudaConsumer, &args);
if (curesult != CUDA_SUCCESS) {
printf("Cuda Consumer: Init failed, status: %d\n", curesult);
consumerStatus = -1;
DoneCons(consumerStatus, send_fd);
}
cuCtxPopCurrent(&cudaConsumer.context);
send_fd = UnixSocketConnect(SOCK_PATH);
if (-1 == send_fd) {
printf("%s: Cuda Consumer cannot create socket %s\n", __func__,
SOCK_PATH);
consumerStatus = -1;
DoneCons(consumerStatus, send_fd);
}
cuCtxPushCurrent(cudaConsumer.context);
cudaConsumer.eglStream = g_consumerEglStream;
cudaConsumer.eglDisplay = g_consumerEglDisplay;
// Send the EGL stream FD to producer
fileDescriptor = eglGetStreamFileDescriptorKHR(cudaConsumer.eglDisplay,
cudaConsumer.eglStream);
if (EGL_NO_FILE_DESCRIPTOR_KHR == fileDescriptor) {
printf("%s: Cuda Consumer could not get EGL file descriptor.\n",
__func__);
eglDestroyStreamKHR(cudaConsumer.eglDisplay, cudaConsumer.eglStream);
consumerStatus = -1;
DoneCons(consumerStatus, send_fd);
}
if (verbose)
printf("%s: Cuda Consumer EGL stream FD obtained : %d.\n", __func__,
fileDescriptor);
int res = -1;
res = EGLStreamSendfd(send_fd, fileDescriptor);
if (-1 == res) {
printf("%s: Cuda Consumer could not send EGL file descriptor.\n",
__func__);
consumerStatus = -1;
close(fileDescriptor);
}
if (CUDA_SUCCESS !=
(curesult = cuEGLStreamConsumerConnect(&(cudaConsumer.cudaConn),
cudaConsumer.eglStream))) {
printf("FAILED Connect CUDA consumer with error %d\n", curesult);
consumerStatus = -1;
DoneCons(consumerStatus, send_fd);
}
j = 0;
for (j = 0; j < NUMTRIALS; j++) {
curesult = cudaConsumerAcquireFrame(&cudaConsumer, j);
if (curesult != CUDA_SUCCESS) {
printf("Cuda Consumer Test failed for frame = %d\n", j + 1);
consumerStatus = -1;
DoneCons(consumerStatus, send_fd);
}
curesult = cudaConsumerReleaseFrame(&cudaConsumer, j);
if (curesult != CUDA_SUCCESS) {
printf("Cuda Consumer Test failed for frame = %d\n", j + 1);
consumerStatus = -1;
DoneCons(consumerStatus, send_fd);
}
curesult = cudaConsumerAcquireFrame(&cudaConsumer, j);
if (curesult != CUDA_SUCCESS) {
printf("Cuda Consumer Test failed for frame = %d\n", j + 1);
consumerStatus = -1;
DoneCons(consumerStatus, send_fd);
}
curesult = cudaConsumerReleaseFrame(&cudaConsumer, j);
if (curesult != CUDA_SUCCESS) {
printf("Cuda Consumer Test failed for frame = %d\n", j + 1);
consumerStatus = -1;
DoneCons(consumerStatus, send_fd);
}
}
cuCtxSynchronize();
close(fileDescriptor);
err = cudaGetValueMismatch();
if (err != cudaSuccess) {
printf("Consumer: App failed with value mismatch\n");
curesult = CUDA_ERROR_UNKNOWN;
consumerStatus = -1;
DoneCons(consumerStatus, send_fd);
}
EGLint streamState = 0;
if (!eglQueryStreamKHR(cudaConsumer.eglDisplay, cudaConsumer.eglStream,
EGL_STREAM_STATE_KHR, &streamState)) {
printf("Main, eglQueryStreamKHR EGL_STREAM_STATE_KHR failed\n");
curesult = CUDA_ERROR_UNKNOWN;
consumerStatus = -1;
DoneCons(consumerStatus, send_fd);
}
if (streamState != EGL_STREAM_STATE_DISCONNECTED_KHR) {
if (CUDA_SUCCESS != (curesult = cuda_consumer_Deinit(&cudaConsumer))) {
printf("Consumer Disconnect FAILED.\n");
consumerStatus = -1;
DoneCons(consumerStatus, send_fd);
}
}
} else // Producer
{
test_cuda_producer_s cudaProducer;
memset(&cudaProducer, 0, sizeof(test_cuda_producer_s));
cudaProducer.profileAPI = profileAPIs;
int producerStatus = 0;
setenv("CUDA_EGL_PRODUCER_RETURN_WAIT_TIMEOUT", "1600", 0);
int connect_fd = -1;
// Hook up Ctrl-C handler
signal(SIGINT, sig_handler);
// Create connection to Consumer
connect_fd = UnixSocketCreate(SOCK_PATH);
if (-1 == connect_fd) {
printf("%s: Cuda Producer could not create socket: %s.\n", __func__,
SOCK_PATH);
producerStatus = -1;
DoneProd(producerStatus, connect_fd);
}
// Get the file descriptor of the stream from the consumer process
// and re-create the EGL stream from it
fileDescriptor = EGLStreamReceivefd(connect_fd);
if (-1 == fileDescriptor) {
printf("%s: Cuda Producer could not receive EGL file descriptor \n",
__func__);
producerStatus = -1;
DoneProd(producerStatus, connect_fd);
}
if (!EGLStreamInit(isCrossDevice, 0, fileDescriptor)) {
printf("EGLStream Init failed.\n");
producerStatus = -1;
curesult = CUDA_ERROR_UNKNOWN;
DoneProd(producerStatus, connect_fd);
}
cudaProducer.eglDisplay = g_producerEglDisplay;
cudaProducer.eglStream = g_producerEglStream;
cudaProducer.cudaDevId = cudaDevIndexProd;
curesult = cudaDeviceCreateProducer(&cudaProducer);
if (curesult != CUDA_SUCCESS) {
producerStatus = -1;
DoneProd(producerStatus, connect_fd);
}
args.charCnt = WIDTH * HEIGHT * 4;
cuCtxPushCurrent(cudaProducer.context);
curesult = cudaProducerInit(&cudaProducer, &args);
if (curesult != CUDA_SUCCESS) {
printf("Cuda Producer: Init failed, status: %d\n", curesult);
producerStatus = -1;
DoneProd(producerStatus, connect_fd);
}
// wait for consumer to connect first
int err = 0;
int wait_loop = 0;
EGLint streamState = 0;
do {
err = eglQueryStreamKHR(cudaProducer.eglDisplay, cudaProducer.eglStream,
EGL_STREAM_STATE_KHR, &streamState);
if ((0 != err) && (EGL_STREAM_STATE_CONNECTING_KHR != streamState)) {
sleep(1);
wait_loop++;
}
} while ((wait_loop < 10) && (0 != err) &&
(streamState != EGL_STREAM_STATE_CONNECTING_KHR));
if ((0 == err) || (wait_loop >= 10)) {
printf(
"%s: Cuda Producer eglQueryStreamKHR EGL_STREAM_STATE_KHR failed.\n",
__func__);
producerStatus = -1;
DoneProd(producerStatus, connect_fd);
}
if (CUDA_SUCCESS != (curesult = cuEGLStreamProducerConnect(
&(cudaProducer.cudaConn), cudaProducer.eglStream,
WIDTH, HEIGHT))) {
printf("Connect CUDA producer FAILED with error %d\n", curesult);
producerStatus = -1;
DoneProd(producerStatus, connect_fd);
}
printf("main - Cuda Producer and Consumer Initialized.\n");
cudaProducerPrepareFrame(&cudaEgl1, cudaProducer.cudaPtr, args.charCnt);
cudaProducerPrepareFrame(&cudaEgl2, cudaProducer.cudaPtr1, args.charCnt);
j = 0;
for (j = 0; j < NUMTRIALS; j++) {
curesult = cudaProducerPresentFrame(&cudaProducer, cudaEgl1, j);
if (curesult != CUDA_SUCCESS) {
printf("Cuda Producer Test failed for frame = %d with cuda error:%d\n",
j + 1, curesult);
producerStatus = -1;
DoneProd(producerStatus, connect_fd);
}
curesult = cudaProducerPresentFrame(&cudaProducer, cudaEgl2, j);
if (curesult != CUDA_SUCCESS) {
printf("Cuda Producer Test failed for frame = %d with cuda error:%d\n",
j + 1, curesult);
producerStatus = -1;
DoneProd(producerStatus, connect_fd);
}
curesult = cudaProducerReturnFrame(&cudaProducer, cudaEgl1, j);
if (curesult != CUDA_SUCCESS) {
printf("Cuda Producer Test failed for frame = %d with cuda error:%d\n",
j + 1, curesult);
producerStatus = -1;
DoneProd(producerStatus, connect_fd);
}
curesult = cudaProducerReturnFrame(&cudaProducer, cudaEgl2, j);
if (curesult != CUDA_SUCCESS) {
printf("Cuda Producer Test failed for frame = %d with cuda error:%d\n",
j + 1, curesult);
producerStatus = -1;
DoneProd(producerStatus, connect_fd);
}
}
cuCtxSynchronize();
err = cudaGetValueMismatch();
if (err != cudaSuccess) {
printf("Prod: App failed with value mismatch\n");
curesult = CUDA_ERROR_UNKNOWN;
producerStatus = -1;
DoneProd(producerStatus, connect_fd);
}
printf("Tear Down Start.....\n");
if (!eglQueryStreamKHR(cudaProducer.eglDisplay, cudaProducer.eglStream,
EGL_STREAM_STATE_KHR, &streamState)) {
printf("Main, eglQueryStreamKHR EGL_STREAM_STATE_KHR failed\n");
curesult = CUDA_ERROR_UNKNOWN;
producerStatus = -1;
DoneProd(producerStatus, connect_fd);
}
if (streamState != EGL_STREAM_STATE_DISCONNECTED_KHR) {
if (CUDA_SUCCESS != (curesult = cudaProducerDeinit(&cudaProducer))) {
printf("Producer Disconnect FAILED with %d\n", curesult);
producerStatus = -1;
DoneProd(producerStatus, connect_fd);
}
}
unsetenv("CUDA_EGL_PRODUCER_RETURN_WAIT_TIMEOUT");
}
return 0;
}

View 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
}

View File

@@ -0,0 +1,7 @@
{
"recommendations": [
"nvidia.nsight-vscode-edition",
"ms-vscode.cpptools",
"ms-vscode.makefile-tools"
]
}

View File

@@ -0,0 +1,10 @@
{
"configurations": [
{
"name": "CUDA C++: Launch",
"type": "cuda-gdb",
"request": "launch",
"program": "${workspaceFolder}/EGLStream_CUDA_Interop"
}
]
}

View File

@@ -0,0 +1,15 @@
{
"version": "2.0.0",
"tasks": [
{
"label": "sample",
"type": "shell",
"command": "make dbg=1",
"problemMatcher": ["$nvcc"],
"group": {
"kind": "build",
"isDefault": true
}
}
]
}

View File

@@ -0,0 +1,412 @@
################################################################################
# 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.
#
################################################################################
#
# Makefile project only supported on Mac OS X and Linux Platforms)
#
################################################################################
# Location of the CUDA Toolkit
CUDA_PATH ?= /usr/local/cuda
##############################
# start deprecated interface #
##############################
ifeq ($(x86_64),1)
$(info WARNING - x86_64 variable has been deprecated)
$(info WARNING - please use TARGET_ARCH=x86_64 instead)
TARGET_ARCH ?= x86_64
endif
ifeq ($(ARMv7),1)
$(info WARNING - ARMv7 variable has been deprecated)
$(info WARNING - please use TARGET_ARCH=armv7l instead)
TARGET_ARCH ?= armv7l
endif
ifeq ($(aarch64),1)
$(info WARNING - aarch64 variable has been deprecated)
$(info WARNING - please use TARGET_ARCH=aarch64 instead)
TARGET_ARCH ?= aarch64
endif
ifeq ($(ppc64le),1)
$(info WARNING - ppc64le variable has been deprecated)
$(info WARNING - please use TARGET_ARCH=ppc64le instead)
TARGET_ARCH ?= ppc64le
endif
ifneq ($(GCC),)
$(info WARNING - GCC variable has been deprecated)
$(info WARNING - please use HOST_COMPILER=$(GCC) instead)
HOST_COMPILER ?= $(GCC)
endif
ifneq ($(abi),)
$(error ERROR - abi variable has been removed)
endif
############################
# end deprecated interface #
############################
# architecture
HOST_ARCH := $(shell uname -m)
TARGET_ARCH ?= $(HOST_ARCH)
ifneq (,$(filter $(TARGET_ARCH),x86_64 aarch64 sbsa ppc64le armv7l))
ifneq ($(TARGET_ARCH),$(HOST_ARCH))
ifneq (,$(filter $(TARGET_ARCH),x86_64 aarch64 sbsa ppc64le))
TARGET_SIZE := 64
else ifneq (,$(filter $(TARGET_ARCH),armv7l))
TARGET_SIZE := 32
endif
else
TARGET_SIZE := $(shell getconf LONG_BIT)
endif
else
$(error ERROR - unsupported value $(TARGET_ARCH) for TARGET_ARCH!)
endif
# sbsa and aarch64 systems look similar. Need to differentiate them at host level for now.
ifeq ($(HOST_ARCH),aarch64)
ifeq ($(CUDA_PATH)/targets/sbsa-linux,$(shell ls -1d $(CUDA_PATH)/targets/sbsa-linux 2>/dev/null))
HOST_ARCH := sbsa
TARGET_ARCH := sbsa
endif
endif
ifneq ($(TARGET_ARCH),$(HOST_ARCH))
ifeq (,$(filter $(HOST_ARCH)-$(TARGET_ARCH),aarch64-armv7l x86_64-armv7l x86_64-aarch64 x86_64-sbsa x86_64-ppc64le))
$(error ERROR - cross compiling from $(HOST_ARCH) to $(TARGET_ARCH) is not supported!)
endif
endif
# When on native aarch64 system with userspace of 32-bit, change TARGET_ARCH to armv7l
ifeq ($(HOST_ARCH)-$(TARGET_ARCH)-$(TARGET_SIZE),aarch64-aarch64-32)
TARGET_ARCH = armv7l
endif
# operating system
HOST_OS := $(shell uname -s 2>/dev/null | tr "[:upper:]" "[:lower:]")
TARGET_OS ?= $(HOST_OS)
ifeq (,$(filter $(TARGET_OS),linux darwin qnx android))
$(error ERROR - unsupported value $(TARGET_OS) for TARGET_OS!)
endif
# host compiler
ifeq ($(TARGET_OS),darwin)
ifeq ($(shell expr `xcodebuild -version | grep -i xcode | awk '{print $$2}' | cut -d'.' -f1` \>= 5),1)
HOST_COMPILER ?= clang++
endif
else ifneq ($(TARGET_ARCH),$(HOST_ARCH))
ifeq ($(HOST_ARCH)-$(TARGET_ARCH),x86_64-armv7l)
ifeq ($(TARGET_OS),linux)
HOST_COMPILER ?= arm-linux-gnueabihf-g++
else ifeq ($(TARGET_OS),qnx)
ifeq ($(QNX_HOST),)
$(error ERROR - QNX_HOST must be passed to the QNX host toolchain)
endif
ifeq ($(QNX_TARGET),)
$(error ERROR - QNX_TARGET must be passed to the QNX target toolchain)
endif
export QNX_HOST
export QNX_TARGET
HOST_COMPILER ?= $(QNX_HOST)/usr/bin/arm-unknown-nto-qnx6.6.0eabi-g++
else ifeq ($(TARGET_OS),android)
HOST_COMPILER ?= arm-linux-androideabi-g++
endif
else ifeq ($(TARGET_ARCH),aarch64)
ifeq ($(TARGET_OS), linux)
HOST_COMPILER ?= aarch64-linux-gnu-g++
else ifeq ($(TARGET_OS),qnx)
ifeq ($(QNX_HOST),)
$(error ERROR - QNX_HOST must be passed to the QNX host toolchain)
endif
ifeq ($(QNX_TARGET),)
$(error ERROR - QNX_TARGET must be passed to the QNX target toolchain)
endif
export QNX_HOST
export QNX_TARGET
HOST_COMPILER ?= $(QNX_HOST)/usr/bin/q++
else ifeq ($(TARGET_OS), android)
HOST_COMPILER ?= aarch64-linux-android-clang++
endif
else ifeq ($(TARGET_ARCH),sbsa)
HOST_COMPILER ?= aarch64-linux-gnu-g++
else ifeq ($(TARGET_ARCH),ppc64le)
HOST_COMPILER ?= powerpc64le-linux-gnu-g++
endif
endif
HOST_COMPILER ?= g++
NVCC := $(CUDA_PATH)/bin/nvcc -ccbin $(HOST_COMPILER)
# internal flags
NVCCFLAGS := -m${TARGET_SIZE}
CCFLAGS :=
LDFLAGS :=
# build flags
ifeq ($(TARGET_OS),darwin)
LDFLAGS += -rpath $(CUDA_PATH)/lib
CCFLAGS += -arch $(HOST_ARCH)
else ifeq ($(HOST_ARCH)-$(TARGET_ARCH)-$(TARGET_OS),x86_64-armv7l-linux)
LDFLAGS += --dynamic-linker=/lib/ld-linux-armhf.so.3
CCFLAGS += -mfloat-abi=hard
else ifeq ($(TARGET_OS),android)
LDFLAGS += -pie
CCFLAGS += -fpie -fpic -fexceptions
endif
ifneq ($(TARGET_ARCH),$(HOST_ARCH))
ifeq ($(TARGET_ARCH)-$(TARGET_OS),armv7l-linux)
ifneq ($(TARGET_FS),)
GCCVERSIONLTEQ46 := $(shell expr `$(HOST_COMPILER) -dumpversion` \<= 4.6)
ifeq ($(GCCVERSIONLTEQ46),1)
CCFLAGS += --sysroot=$(TARGET_FS)
endif
LDFLAGS += --sysroot=$(TARGET_FS)
LDFLAGS += -rpath-link=$(TARGET_FS)/lib
LDFLAGS += -rpath-link=$(TARGET_FS)/usr/lib
LDFLAGS += -rpath-link=$(TARGET_FS)/usr/lib/arm-linux-gnueabihf
endif
endif
ifeq ($(TARGET_ARCH)-$(TARGET_OS),aarch64-linux)
ifneq ($(TARGET_FS),)
GCCVERSIONLTEQ46 := $(shell expr `$(HOST_COMPILER) -dumpversion` \<= 4.6)
ifeq ($(GCCVERSIONLTEQ46),1)
CCFLAGS += --sysroot=$(TARGET_FS)
endif
LDFLAGS += --sysroot=$(TARGET_FS)
LDFLAGS += -rpath-link=$(TARGET_FS)/lib -L$(TARGET_FS)/lib
LDFLAGS += -rpath-link=$(TARGET_FS)/lib/aarch64-linux-gnu -L$(TARGET_FS)/lib/aarch64-linux-gnu
LDFLAGS += -rpath-link=$(TARGET_FS)/usr/lib -L$(TARGET_FS)/usr/lib
LDFLAGS += -rpath-link=$(TARGET_FS)/usr/lib/aarch64-linux-gnu -L$(TARGET_FS)/usr/lib/aarch64-linux-gnu
LDFLAGS += --unresolved-symbols=ignore-in-shared-libs
CCFLAGS += -isystem=$(TARGET_FS)/usr/include -I$(TARGET_FS)/usr/include -I$(TARGET_FS)/usr/include/libdrm
CCFLAGS += -isystem=$(TARGET_FS)/usr/include/aarch64-linux-gnu -I$(TARGET_FS)/usr/include/aarch64-linux-gnu
endif
endif
ifeq ($(TARGET_ARCH)-$(TARGET_OS),aarch64-qnx)
NVCCFLAGS += -D_QNX_SOURCE
NVCCFLAGS += --qpp-config 8.3.0,gcc_ntoaarch64le
CCFLAGS += -DWIN_INTERFACE_CUSTOM -I/usr/include/aarch64-qnx-gnu
LDFLAGS += -lsocket
LDFLAGS += -L/usr/lib/aarch64-qnx-gnu
CCFLAGS += "-Wl\,-rpath-link\,/usr/lib/aarch64-qnx-gnu"
ifdef TARGET_OVERRIDE
LDFLAGS += -lslog2
endif
ifneq ($(TARGET_FS),)
LDFLAGS += -L$(TARGET_FS)/usr/lib
CCFLAGS += "-Wl\,-rpath-link\,$(TARGET_FS)/usr/lib"
LDFLAGS += -L$(TARGET_FS)/usr/libnvidia
CCFLAGS += "-Wl\,-rpath-link\,$(TARGET_FS)/usr/libnvidia"
CCFLAGS += -I$(TARGET_FS)/../include
endif
endif
endif
ifdef TARGET_OVERRIDE # cuda toolkit targets override
NVCCFLAGS += -target-dir $(TARGET_OVERRIDE)
endif
# Install directory of different arch
CUDA_INSTALL_TARGET_DIR :=
ifeq ($(TARGET_ARCH)-$(TARGET_OS),armv7l-linux)
CUDA_INSTALL_TARGET_DIR = targets/armv7-linux-gnueabihf/
else ifeq ($(TARGET_ARCH)-$(TARGET_OS),aarch64-linux)
CUDA_INSTALL_TARGET_DIR = targets/aarch64-linux/
else ifeq ($(TARGET_ARCH)-$(TARGET_OS),sbsa-linux)
CUDA_INSTALL_TARGET_DIR = targets/sbsa-linux/
else ifeq ($(TARGET_ARCH)-$(TARGET_OS),armv7l-android)
CUDA_INSTALL_TARGET_DIR = targets/armv7-linux-androideabi/
else ifeq ($(TARGET_ARCH)-$(TARGET_OS),aarch64-android)
CUDA_INSTALL_TARGET_DIR = targets/aarch64-linux-androideabi/
else ifeq ($(TARGET_ARCH)-$(TARGET_OS),armv7l-qnx)
CUDA_INSTALL_TARGET_DIR = targets/ARMv7-linux-QNX/
else ifeq ($(TARGET_ARCH)-$(TARGET_OS),aarch64-qnx)
CUDA_INSTALL_TARGET_DIR = targets/aarch64-qnx/
else ifeq ($(TARGET_ARCH),ppc64le)
CUDA_INSTALL_TARGET_DIR = targets/ppc64le-linux/
endif
# Debug build flags
ifeq ($(dbg),1)
NVCCFLAGS += -g -G
BUILD_TYPE := debug
else
BUILD_TYPE := release
endif
ALL_CCFLAGS :=
ALL_CCFLAGS += $(NVCCFLAGS)
ALL_CCFLAGS += $(EXTRA_NVCCFLAGS)
ALL_CCFLAGS += $(addprefix -Xcompiler ,$(CCFLAGS))
ALL_CCFLAGS += $(addprefix -Xcompiler ,$(EXTRA_CCFLAGS))
UBUNTU = $(shell lsb_release -i -s 2>/dev/null | grep -i ubuntu)
SAMPLE_ENABLED := 1
# This sample is not supported on Mac OSX
ifeq ($(TARGET_OS),darwin)
$(info >>> WARNING - EGLStream_CUDA_Interop is not supported on Mac OSX - waiving sample <<<)
SAMPLE_ENABLED := 0
endif
# This sample is not supported on ARMv7
ifeq ($(TARGET_ARCH),armv7l)
$(info >>> WARNING - EGLStream_CUDA_Interop is not supported on ARMv7 - waiving sample <<<)
SAMPLE_ENABLED := 0
endif
# This sample is not supported on android
ifeq ($(TARGET_OS),android)
$(info >>> WARNING - EGLStream_CUDA_Interop is not supported on android - waiving sample <<<)
SAMPLE_ENABLED := 0
endif
ALL_LDFLAGS :=
ALL_LDFLAGS += $(ALL_CCFLAGS)
ALL_LDFLAGS += $(addprefix -Xlinker ,$(LDFLAGS))
ALL_LDFLAGS += $(addprefix -Xlinker ,$(EXTRA_LDFLAGS))
# Common includes and paths for CUDA
INCLUDES := -I../../../Common
LIBRARIES :=
################################################################################
# Makefile include to help find EGL Libraries
include ./findegl.mk
# EGL specific libraries
ifneq ($(TARGET_OS),darwin)
LIBRARIES += -lEGL
endif
ifeq ($(TARGET_OS),darwin)
ALL_LDFLAGS += -Xcompiler -F/Library/Frameworks -Xlinker -framework -Xlinker CUDA
else
ifeq ($(TARGET_ARCH),x86_64)
CUDA_SEARCH_PATH ?= $(CUDA_PATH)/lib64/stubs
CUDA_SEARCH_PATH += $(CUDA_PATH)/lib/stubs
CUDA_SEARCH_PATH += $(CUDA_PATH)/targets/x86_64-linux/lib/stubs
endif
ifeq ($(TARGET_ARCH)-$(TARGET_OS),armv7l-linux)
CUDA_SEARCH_PATH ?= $(CUDA_PATH)/targets/armv7-linux-gnueabihf/lib/stubs
endif
ifeq ($(TARGET_ARCH)-$(TARGET_OS),aarch64-linux)
CUDA_SEARCH_PATH ?= $(CUDA_PATH)/targets/aarch64-linux/lib/stubs
endif
ifeq ($(TARGET_ARCH)-$(TARGET_OS),sbsa-linux)
CUDA_SEARCH_PATH ?= $(CUDA_PATH)/targets/sbsa-linux/lib/stubs
endif
ifeq ($(TARGET_ARCH)-$(TARGET_OS),armv7l-android)
CUDA_SEARCH_PATH ?= $(CUDA_PATH)/targets/armv7-linux-androideabi/lib/stubs
endif
ifeq ($(TARGET_ARCH)-$(TARGET_OS),aarch64-android)
CUDA_SEARCH_PATH ?= $(CUDA_PATH)/targets/aarch64-linux-androideabi/lib/stubs
endif
ifeq ($(TARGET_ARCH)-$(TARGET_OS),armv7l-qnx)
CUDA_SEARCH_PATH ?= $(CUDA_PATH)/targets/ARMv7-linux-QNX/lib/stubs
endif
ifeq ($(TARGET_ARCH)-$(TARGET_OS),aarch64-qnx)
CUDA_SEARCH_PATH ?= $(CUDA_PATH)/targets/aarch64-qnx/lib/stubs
ifdef TARGET_OVERRIDE
CUDA_SEARCH_PATH := $(CUDA_PATH)/targets/$(TARGET_OVERRIDE)/lib/stubs
endif
endif
ifeq ($(TARGET_ARCH),ppc64le)
CUDA_SEARCH_PATH ?= $(CUDA_PATH)/targets/ppc64le-linux/lib/stubs
endif
ifeq ($(HOST_ARCH),ppc64le)
CUDA_SEARCH_PATH += $(CUDA_PATH)/lib64/stubs
endif
CUDALIB ?= $(shell find -L $(CUDA_SEARCH_PATH) -maxdepth 1 -name libcuda.so 2> /dev/null)
ifeq ("$(CUDALIB)","")
$(info >>> WARNING - libcuda.so not found, CUDA Driver is not installed. Please re-install the driver. <<<)
SAMPLE_ENABLED := 0
else
CUDALIB := $(shell echo $(CUDALIB) | sed "s/ .*//" | sed "s/\/libcuda.so//" )
LIBRARIES += -L$(CUDALIB) -lcuda
endif
endif
ALL_CCFLAGS += --threads 0 --std=c++11
ifeq ($(SAMPLE_ENABLED),0)
EXEC ?= @echo "[@]"
endif
################################################################################
# Target rules
all: build
build: EGLStream_CUDA_Interop
check.deps:
ifeq ($(SAMPLE_ENABLED),0)
@echo "Sample will be waived due to the above missing dependencies"
else
@echo "Sample is ready - all dependencies have been met"
endif
cuda_consumer.o:cuda_consumer.cpp
$(EXEC) $(NVCC) $(INCLUDES) $(ALL_CCFLAGS) $(GENCODE_FLAGS) -o $@ -c $<
cuda_producer.o:cuda_producer.cpp
$(EXEC) $(NVCC) $(INCLUDES) $(ALL_CCFLAGS) $(GENCODE_FLAGS) -o $@ -c $<
eglstrm_common.o:eglstrm_common.cpp
$(EXEC) $(NVCC) $(INCLUDES) $(ALL_CCFLAGS) $(GENCODE_FLAGS) -o $@ -c $<
main.o:main.cpp
$(EXEC) $(NVCC) $(INCLUDES) $(ALL_CCFLAGS) $(GENCODE_FLAGS) -o $@ -c $<
EGLStream_CUDA_Interop: cuda_consumer.o cuda_producer.o eglstrm_common.o main.o
$(EXEC) $(NVCC) $(ALL_LDFLAGS) $(GENCODE_FLAGS) -o $@ $+ $(LIBRARIES)
$(EXEC) mkdir -p ../../../bin/$(TARGET_ARCH)/$(TARGET_OS)/$(BUILD_TYPE)
$(EXEC) cp $@ ../../../bin/$(TARGET_ARCH)/$(TARGET_OS)/$(BUILD_TYPE)
run: build
$(EXEC) ./EGLStream_CUDA_Interop
testrun: build
clean:
rm -f EGLStream_CUDA_Interop cuda_consumer.o cuda_producer.o eglstrm_common.o main.o
rm -rf ../../../bin/$(TARGET_ARCH)/$(TARGET_OS)/$(BUILD_TYPE)/EGLStream_CUDA_Interop
clobber: clean

View File

@@ -0,0 +1,80 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE entry SYSTEM "SamplesInfo.dtd">
<entry>
<name>EGLStream_CUDA_Interop</name>
<cuda_api_list>
<driver>cuDeviceGet</driver>
<driver>cuDeviceGetAttribute</driver>
<driver>cuDeviceComputeCapability</driver>
<driver>cuDeviceGetCount</driver>
<driver>cuDeviceGetName</driver>
<driver>cuGraphicsResourceGetMappedEglFrame</driver>
<driver>cuEGLStreamConsumerAcquireFrame</driver>
<driver>cuEGLStreamConsumerReleaseFrame</driver>
<driver>cuEGLStreamProducerPresentFrame</driver>
<driver>cuCtxCreate</driver>
<driver>cuMemAlloc</driver>
<driver>cuMemFree</driver>
<driver>cuMemcpy3D</driver>
<driver>cuStreamCreate</driver>
<driver>cuCtxPushCurrent</driver>
<driver>cuCtxPopCurrent</driver>
<driver>cuCtxDestroy</driver>
</cuda_api_list>
<description><![CDATA[Demonstrates data exchange between CUDA and EGL Streams.]]></description>
<devicecompilation>whole</devicecompilation>
<includepaths>
<path>./</path>
<path>../</path>
<path>../../../Common</path>
</includepaths>
<keyconcepts>
<concept level="basic">EGLStreams Interop</concept>
</keyconcepts>
<keywords>
<keyword>EGL Streams</keyword>
</keywords>
<libraries>
<library os="linux">cuda</library>
<library framework="true" os="macosx">CUDA</library>
</libraries>
<librarypaths>
</librarypaths>
<nsight_eclipse>true</nsight_eclipse>
<primary_file>main.cpp</primary_file>
<required_dependencies>
<dependency>EGL</dependency>
</required_dependencies>
<scopes>
<scope>1:CUDA Basic Topics</scope>
<scope>2:Graphics Interop</scope>
</scopes>
<sm-arch>sm35</sm-arch>
<sm-arch>sm37</sm-arch>
<sm-arch>sm50</sm-arch>
<sm-arch>sm52</sm-arch>
<sm-arch>sm60</sm-arch>
<sm-arch>sm61</sm-arch>
<sm-arch>sm70</sm-arch>
<sm-arch>sm72</sm-arch>
<sm-arch>sm75</sm-arch>
<sm-arch>sm80</sm-arch>
<sm-arch>sm86</sm-arch>
<supported_envs>
<env>
<arch>x86_64</arch>
<platform>linux</platform>
</env>
<env>
<arch>aarch64</arch>
</env>
<env>
<arch>sbsa</arch>
</env>
</supported_envs>
<supported_sm_architectures>
<include>all</include>
</supported_sm_architectures>
<title>EGLStream CUDA Interop</title>
<type>exe</type>
</entry>

View File

@@ -0,0 +1,67 @@
# EGLStream_CUDA_Interop - EGLStream CUDA Interop
## Description
Demonstrates data exchange between CUDA and EGL Streams.
## Key Concepts
EGLStreams Interop
## Supported SM Architectures
[SM 3.5 ](https://developer.nvidia.com/cuda-gpus) [SM 3.7 ](https://developer.nvidia.com/cuda-gpus) [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)
## Supported OSes
Linux
## Supported CPU Architecture
x86_64, aarch64
## CUDA APIs involved
### [CUDA Driver API](http://docs.nvidia.com/cuda/cuda-driver-api/index.html)
cuEGLStreamConsumerConnect, cuArrayDestroy, cuMemFree, cuInit, cuCtxCreate, cuGraphicsResourceGetMappedEglFrame, cuDeviceGetName, cuCtxSynchronize, cuEGLStreamConsumerAcquireFrame, cuDeviceGetAttribute, cuMemcpy, cuMemAlloc, cuEGLStreamConsumerReleaseFrame, cuEGLStreamProducerDisconnect, cuEGLStreamProducerConnect, cuEGLStreamConsumerDisconnect, cuDeviceGetCount, cuEGLStreamProducerReturnFrame, cuCtxPushCurrent, cuCtxPopCurrent, cuMemcpyDtoH, cuEGLStreamProducerPresentFrame
### [CUDA Runtime API](http://docs.nvidia.com/cuda/cuda-runtime-api/index.html)
cudaDeviceCreateConsumer, cudaConsumerTest, cudaProducerDeinit, cudaProducerInit, cudaProducerReadYUVFrame, cudaProducerTest, cudaProducerReadARGBFrame, cudaDeviceCreateProducer
## Dependencies needed to build/run
[EGL](../../README.md#egl)
## Prerequisites
Download and install the [CUDA Toolkit 11.6](https://developer.nvidia.com/cuda-downloads) for your corresponding platform.
Make sure the dependencies mentioned in [Dependencies]() section above are installed.
## Build and Run
### Linux
The Linux samples are built using makefiles. To use the makefiles, change the current directory to the sample directory you wish to build, and run make:
```
$ cd <sample_dir>
$ make
```
The samples makefiles can take advantage of certain options:
* **TARGET_ARCH=<arch>** - cross-compile targeting a specific architecture. Allowed architectures are x86_64, aarch64.
By default, TARGET_ARCH is set to HOST_ARCH. On a x86_64 machine, not setting TARGET_ARCH is the equivalent of setting TARGET_ARCH=x86_64.<br/>
`$ make TARGET_ARCH=x86_64` <br/> `$ make TARGET_ARCH=aarch64` <br/>
See [here](http://docs.nvidia.com/cuda/cuda-samples/index.html#cross-samples) for more details.
* **dbg=1** - build with debug symbols
```
$ make dbg=1
```
* **SMS="A B ..."** - override the SM architectures for which the sample will be built, where `"A B ..."` is a space-delimited list of SM architectures. For example, to generate SASS for SM 50 and SM 60, use `SMS="50 60"`.
```
$ make SMS="50 60"
```
* **HOST_COMPILER=<host_compiler>** - override the default g++ host compiler. See the [Linux Installation Guide](http://docs.nvidia.com/cuda/cuda-installation-guide-linux/index.html#system-requirements) for a list of supported host compilers.
```
$ make HOST_COMPILER=g++
```
## References (for more details)

View File

@@ -0,0 +1,318 @@
/* 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.
*/
//
// DESCRIPTION: Simple CUDA consumer rendering sample app
//
#include "cuda_consumer.h"
#include <helper_cuda_drvapi.h>
#include "eglstrm_common.h"
#if defined(EXTENSION_LIST)
EXTENSION_LIST(EXTLST_EXTERN)
#endif
int checkbuf(FILE *fp1, FILE *fp2);
CUresult cudaConsumerTest(test_cuda_consumer_s *data, char *fileName) {
CUresult cuStatus = CUDA_SUCCESS;
CUarray cudaArr = NULL;
CUeglFrame cudaEgl;
CUgraphicsResource cudaResource;
unsigned int i;
int check_result;
FILE *pInFile1 = NULL, *pInFile2 = NULL, *file_p = NULL;
EGLint streamState = 0;
if (!data) {
printf("%s: Bad parameter\n", __func__);
goto done;
}
if (!eglQueryStreamKHR(g_display, eglStream, EGL_STREAM_STATE_KHR,
&streamState)) {
printf("Cuda consumer, eglQueryStreamKHR EGL_STREAM_STATE_KHR failed\n");
}
if (streamState == EGL_STREAM_STATE_DISCONNECTED_KHR) {
printf("CUDA Consumer: - EGL_STREAM_STATE_DISCONNECTED_KHR received\n");
}
if (streamState == EGL_STREAM_STATE_NEW_FRAME_AVAILABLE_KHR) {
cuStatus = cuEGLStreamConsumerAcquireFrame(&(data->cudaConn), &cudaResource,
NULL, 16000);
if (cuStatus == CUDA_SUCCESS) {
CUdeviceptr pDevPtr = 0;
int bufferSize;
unsigned char *pCudaCopyMem = NULL;
unsigned int copyWidthInBytes = 0, copyHeight = 0;
file_p = fopen(fileName, "wb+");
if (!file_p) {
printf("WriteFrame: file open failed %s\n", fileName);
cuStatus = CUDA_ERROR_UNKNOWN;
goto done;
}
cuStatus =
cuGraphicsResourceGetMappedEglFrame(&cudaEgl, cudaResource, 0, 0);
if (cuStatus != CUDA_SUCCESS) {
printf("Cuda get resource failed with %d\n", cuStatus);
goto done;
}
cuStatus = cuCtxSynchronize();
if (cuStatus != CUDA_SUCCESS) {
printf("cuCtxSynchronize failed \n");
goto done;
}
if (!(cudaEgl.planeCount >= 1 && cudaEgl.planeCount <= 3)) {
printf("Plane count is invalid\nExiting\n");
goto done;
}
for (i = 0; i < cudaEgl.planeCount; i++) {
if (cudaEgl.frameType == CU_EGL_FRAME_TYPE_PITCH) {
pDevPtr = (CUdeviceptr)cudaEgl.frame.pPitch[i];
if (cudaEgl.planeCount == 1) {
bufferSize = cudaEgl.pitch * cudaEgl.height;
copyWidthInBytes = cudaEgl.pitch;
copyHeight = data->height;
} else if (i == 1 && cudaEgl.planeCount == 2) { // YUV 420
// semi-planar
bufferSize = cudaEgl.pitch * cudaEgl.height / 2;
copyWidthInBytes = cudaEgl.pitch;
copyHeight = data->height / 2;
} else {
bufferSize = data->width * data->height;
copyWidthInBytes = data->width;
copyHeight = data->height;
if (i > 0) {
bufferSize >>= 2;
copyWidthInBytes >>= 1;
copyHeight >>= 1;
}
}
} else {
cudaArr = cudaEgl.frame.pArray[i];
if (cudaEgl.planeCount == 1) {
bufferSize = data->width * data->height * 4;
copyWidthInBytes = data->width * 4;
copyHeight = data->height;
} else if (i == 1 && cudaEgl.planeCount == 2) { // YUV 420
// semi-planar
bufferSize = data->width * data->height / 2;
copyWidthInBytes = data->width;
copyHeight = data->height / 2;
} else {
bufferSize = data->width * data->height;
copyWidthInBytes = data->width;
copyHeight = data->height;
if (i > 0) {
bufferSize >>= 2;
copyWidthInBytes >>= 1;
copyHeight >>= 1;
}
}
}
if (i == 0) {
pCudaCopyMem = (unsigned char *)malloc(bufferSize);
if (pCudaCopyMem == NULL) {
printf("pCudaCopyMem malloc failed\n");
goto done;
}
}
memset(pCudaCopyMem, 0, bufferSize);
if (data->pitchLinearOutput) {
cuStatus = cuMemcpyDtoH(pCudaCopyMem, pDevPtr, bufferSize);
if (cuStatus != CUDA_SUCCESS) {
printf(
"cuda_consumer: pitch linear Memcpy failed, bufferSize =%d\n",
bufferSize);
goto done;
}
cuStatus = cuCtxSynchronize();
if (cuStatus != CUDA_SUCCESS) {
printf("cuda_consumer: cuCtxSynchronize failed after memcpy \n");
goto done;
}
} else {
CUDA_MEMCPY3D cpdesc;
memset(&cpdesc, 0, sizeof(cpdesc));
cpdesc.srcXInBytes = cpdesc.srcY = cpdesc.srcZ = cpdesc.srcLOD = 0;
cpdesc.srcMemoryType = CU_MEMORYTYPE_ARRAY;
cpdesc.srcArray = cudaArr;
cpdesc.dstXInBytes = cpdesc.dstY = cpdesc.dstZ = cpdesc.dstLOD = 0;
cpdesc.dstMemoryType = CU_MEMORYTYPE_HOST;
cpdesc.dstHost = (void *)pCudaCopyMem;
cpdesc.WidthInBytes = copyWidthInBytes; // data->width * 4;
cpdesc.Height = copyHeight; // data->height;
cpdesc.Depth = 1;
cuStatus = cuMemcpy3D(&cpdesc);
if (cuStatus != CUDA_SUCCESS) {
printf(
"Cuda consumer: cuMemCpy3D failed, copyWidthInBytes=%d, "
"copyHight=%d\n",
copyWidthInBytes, copyHeight);
}
cuStatus = cuCtxSynchronize();
if (cuStatus != CUDA_SUCCESS) {
printf("cuCtxSynchronize failed after memcpy \n");
}
}
if (cuStatus == CUDA_SUCCESS) {
if (fwrite(pCudaCopyMem, bufferSize, 1, file_p) != 1) {
printf("Cuda consumer: output file write failed\n");
cuStatus = CUDA_ERROR_UNKNOWN;
goto done;
}
}
}
pInFile1 = fopen(data->fileName1, "rb");
if (!pInFile1) {
printf("Failed to open file :%s\n", data->fileName1);
goto done;
}
pInFile2 = fopen(data->fileName2, "rb");
if (!pInFile2) {
printf("Failed to open file :%s\n", data->fileName2);
goto done;
}
rewind(file_p);
check_result = checkbuf(file_p, pInFile1);
if (check_result == -1) {
rewind(file_p);
check_result = checkbuf(file_p, pInFile2);
if (check_result == -1) {
printf("Frame received does not match any valid image: FAILED\n");
} else {
printf("Frame check Passed\n");
}
} else {
printf("Frame check Passed\n");
}
if (pCudaCopyMem) {
free(pCudaCopyMem);
pCudaCopyMem = NULL;
}
cuStatus =
cuEGLStreamConsumerReleaseFrame(&data->cudaConn, cudaResource, NULL);
if (cuStatus != CUDA_SUCCESS) {
printf("cuEGLStreamConsumerReleaseFrame failed with cuStatus = %d\n",
cuStatus);
goto done;
}
} else {
printf("cuda AcquireFrame FAILED with cuStatus=%d\n", cuStatus);
goto done;
}
}
done:
if (file_p) {
fclose(file_p);
file_p = NULL;
}
if (pInFile1) {
fclose(pInFile1);
pInFile1 = NULL;
}
if (pInFile1) {
fclose(pInFile2);
pInFile2 = NULL;
}
return cuStatus;
}
int checkbuf(FILE *fp1, FILE *fp2) {
int match = 0;
int ch1, ch2;
if (fp1 == NULL) {
printf("Invalid file pointer for first file\n");
return -1;
} else if (fp2 == NULL) {
printf("Invalid file pointer for second file\n");
return -1;
} else {
ch1 = getc(fp1);
ch2 = getc(fp2);
while ((ch1 != EOF) && (ch2 != EOF) && (ch1 == ch2)) {
ch1 = getc(fp1);
ch2 = getc(fp2);
}
if (ch1 == ch2) {
match = 1;
} else if (ch1 != ch2) {
match = -1;
}
}
return match;
}
CUresult cudaDeviceCreateConsumer(test_cuda_consumer_s *cudaConsumer,
CUdevice device) {
CUresult status = CUDA_SUCCESS;
if (CUDA_SUCCESS != (status = cuInit(0))) {
printf("Failed to initialize CUDA\n");
return status;
}
int major = 0, minor = 0;
char deviceName[256];
checkCudaErrors(cuDeviceGetAttribute(
&major, CU_DEVICE_ATTRIBUTE_COMPUTE_CAPABILITY_MAJOR, device));
checkCudaErrors(cuDeviceGetAttribute(
&minor, CU_DEVICE_ATTRIBUTE_COMPUTE_CAPABILITY_MINOR, device));
checkCudaErrors(cuDeviceGetName(deviceName, 256, device));
printf(
"CUDA Consumer on GPU Device %d: \"%s\" with compute capability "
"%d.%d\n\n",
device, deviceName, major, minor);
if (CUDA_SUCCESS !=
(status = cuCtxCreate(&cudaConsumer->context, 0, device))) {
printf("failed to create CUDA context\n");
return status;
}
checkCudaErrors(cuCtxPopCurrent(&cudaConsumer->context));
return status;
}
void cuda_consumer_init(test_cuda_consumer_s *cudaConsumer, TestArgs *args) {
cudaConsumer->pitchLinearOutput = args->pitchLinearOutput;
cudaConsumer->width = args->inputWidth;
cudaConsumer->height = args->inputHeight;
cudaConsumer->fileName1 = args->infile1;
cudaConsumer->fileName2 = args->infile2;
cudaConsumer->outFile1 = "cuda_out1.yuv";
cudaConsumer->outFile2 = "cuda_out2.yuv";
}
CUresult cuda_consumer_deinit(test_cuda_consumer_s *cudaConsumer) {
return cuEGLStreamConsumerDisconnect(&cudaConsumer->cudaConn);
}

View File

@@ -0,0 +1,62 @@
/* 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.
*/
//
// DESCRIPTION: CUDA consumer header file
//
#ifndef _CUDA_CONSUMER_H_
#define _CUDA_CONSUMER_H_
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "cudaEGL.h"
#include "eglstrm_common.h"
extern EGLStreamKHR eglStream;
extern EGLDisplay g_display;
typedef struct _test_cuda_consumer_s {
CUcontext context;
CUeglStreamConnection cudaConn;
bool pitchLinearOutput;
unsigned int width;
unsigned int height;
char *fileName1;
char *fileName2;
char *outFile1;
char *outFile2;
unsigned int frameCount;
} test_cuda_consumer_s;
void cuda_consumer_init(test_cuda_consumer_s *cudaConsumer, TestArgs *args);
CUresult cuda_consumer_deinit(test_cuda_consumer_s *cudaConsumer);
CUresult cudaConsumerTest(test_cuda_consumer_s *data, char *outFile);
CUresult cudaDeviceCreateConsumer(test_cuda_consumer_s *cudaConsumer,
CUdevice device);
#endif

View File

@@ -0,0 +1,406 @@
/* 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.
*/
//
// DESCRIPTION: Simple cuda EGL stream producer app
//
#include "cuda_producer.h"
#include <helper_cuda_drvapi.h>
#include "cudaEGL.h"
#include "eglstrm_common.h"
#if defined(EXTENSION_LIST)
EXTENSION_LIST(EXTLST_EXTERN)
#endif
static CUresult cudaProducerReadYUVFrame(FILE *file, unsigned int frameNum,
unsigned int width,
unsigned int height,
unsigned char *pBuff) {
int bOrderUV = 0;
unsigned char *pYBuff, *pUBuff, *pVBuff, *pChroma;
unsigned int frameSize = (width * height * 3) / 2;
CUresult ret = CUDA_SUCCESS;
unsigned int i;
if (!pBuff || !file) return CUDA_ERROR_FILE_NOT_FOUND;
pYBuff = pBuff;
// YVU order in the buffer
pVBuff = pYBuff + width * height;
pUBuff = pVBuff + width * height / 4;
if (fseek(file, frameNum * frameSize, SEEK_SET)) {
printf("ReadYUVFrame: Error seeking file: %p\n", file);
ret = CUDA_ERROR_NOT_PERMITTED;
goto done;
}
// read Y U V separately
for (i = 0; i < height; i++) {
if (fread(pYBuff, width, 1, file) != 1) {
printf("ReadYUVFrame: Error reading file: %p\n", file);
ret = CUDA_ERROR_NOT_PERMITTED;
goto done;
}
pYBuff += width;
}
pChroma = bOrderUV ? pUBuff : pVBuff;
for (i = 0; i < height / 2; i++) {
if (fread(pChroma, width / 2, 1, file) != 1) {
printf("ReadYUVFrame: Error reading file: %p\n", file);
ret = CUDA_ERROR_NOT_PERMITTED;
goto done;
}
pChroma += width / 2;
}
pChroma = bOrderUV ? pVBuff : pUBuff;
for (i = 0; i < height / 2; i++) {
if (fread(pChroma, width / 2, 1, file) != 1) {
printf("ReadYUVFrame: Error reading file: %p\n", file);
ret = CUDA_ERROR_NOT_PERMITTED;
goto done;
}
pChroma += width / 2;
}
done:
return ret;
}
static CUresult cudaProducerReadARGBFrame(FILE *file, unsigned int frameNum,
unsigned int width,
unsigned int height,
unsigned char *pBuff) {
unsigned int frameSize = width * height * 4;
CUresult ret = CUDA_SUCCESS;
if (!pBuff || !file) return CUDA_ERROR_FILE_NOT_FOUND;
if (fseek(file, frameNum * frameSize, SEEK_SET)) {
printf("ReadYUVFrame: Error seeking file: %p\n", file);
ret = CUDA_ERROR_NOT_PERMITTED;
goto done;
}
// read ARGB data
if (fread(pBuff, frameSize, 1, file) != 1) {
if (feof(file))
printf("ReadARGBFrame: file read to the end\n");
else
printf("ReadARGBFrame: Error reading file: %p\n", file);
ret = CUDA_ERROR_NOT_PERMITTED;
goto done;
}
done:
return ret;
}
CUresult cudaProducerTest(test_cuda_producer_s *cudaProducer, char *file) {
int framenum = 0;
CUarray cudaArr[3] = {0};
CUdeviceptr cudaPtr[3] = {0, 0, 0};
unsigned int bufferSize;
CUresult cuStatus = CUDA_SUCCESS;
unsigned int i, surfNum, uvOffset[3] = {0};
unsigned int copyWidthInBytes[3] = {0, 0, 0}, copyHeight[3] = {0, 0, 0};
CUeglColorFormat eglColorFormat;
FILE *file_p;
CUeglFrame cudaEgl;
CUcontext oldContext;
file_p = fopen(file, "rb");
if (!file_p) {
printf("CudaProducer: Error opening file: %s\n", file);
goto done;
}
if (cudaProducer->pitchLinearOutput) {
if (cudaProducer->isARGB) {
cudaPtr[0] = cudaProducer->cudaPtrARGB[0];
} else { // YUV case
for (i = 0; i < 3; i++) {
if (i == 0) {
bufferSize = cudaProducer->width * cudaProducer->height;
} else {
bufferSize = cudaProducer->width * cudaProducer->height / 4;
}
cudaPtr[i] = cudaProducer->cudaPtrYUV[i];
}
}
} else {
if (cudaProducer->isARGB) {
cudaArr[0] = cudaProducer->cudaArrARGB[0];
} else {
for (i = 0; i < 3; i++) {
cudaArr[i] = cudaProducer->cudaArrYUV[i];
}
}
}
uvOffset[0] = 0;
if (cudaProducer->isARGB) {
if (CUDA_SUCCESS !=
cudaProducerReadARGBFrame(file_p, framenum, cudaProducer->width,
cudaProducer->height, cudaProducer->pBuff)) {
printf("cuda producer, read ARGB frame failed\n");
goto done;
}
copyWidthInBytes[0] = cudaProducer->width * 4;
copyHeight[0] = cudaProducer->height;
surfNum = 1;
eglColorFormat = CU_EGL_COLOR_FORMAT_ARGB;
} else {
if (CUDA_SUCCESS !=
cudaProducerReadYUVFrame(file_p, framenum, cudaProducer->width,
cudaProducer->height, cudaProducer->pBuff)) {
printf("cuda producer, reading YUV frame failed\n");
goto done;
}
surfNum = 3;
eglColorFormat = CU_EGL_COLOR_FORMAT_YUV420_PLANAR;
copyWidthInBytes[0] = cudaProducer->width;
copyHeight[0] = cudaProducer->height;
copyWidthInBytes[1] = cudaProducer->width / 2;
copyHeight[1] = cudaProducer->height / 2;
copyWidthInBytes[2] = cudaProducer->width / 2;
copyHeight[2] = cudaProducer->height / 2;
uvOffset[1] = cudaProducer->width * cudaProducer->height;
uvOffset[2] =
uvOffset[1] + cudaProducer->width / 2 * cudaProducer->height / 2;
}
if (cudaProducer->pitchLinearOutput) {
for (i = 0; i < surfNum; i++) {
cuStatus =
cuMemcpy(cudaPtr[i], (CUdeviceptr)(cudaProducer->pBuff + uvOffset[i]),
copyWidthInBytes[i] * copyHeight[i]);
if (cuStatus != CUDA_SUCCESS) {
printf("Cuda producer: cuMemCpy pitchlinear failed, cuStatus =%d\n",
cuStatus);
goto done;
}
}
} else {
// copy cudaProducer->pBuff to cudaArray
CUDA_MEMCPY3D cpdesc;
for (i = 0; i < surfNum; i++) {
memset(&cpdesc, 0, sizeof(cpdesc));
cpdesc.srcXInBytes = cpdesc.srcY = cpdesc.srcZ = cpdesc.srcLOD = 0;
cpdesc.srcMemoryType = CU_MEMORYTYPE_HOST;
cpdesc.srcHost = (void *)(cudaProducer->pBuff + uvOffset[i]);
cpdesc.dstXInBytes = cpdesc.dstY = cpdesc.dstZ = cpdesc.dstLOD = 0;
cpdesc.dstMemoryType = CU_MEMORYTYPE_ARRAY;
cpdesc.dstArray = cudaArr[i];
cpdesc.WidthInBytes = copyWidthInBytes[i];
cpdesc.Height = copyHeight[i];
cpdesc.Depth = 1;
cuStatus = cuMemcpy3D(&cpdesc);
if (cuStatus != CUDA_SUCCESS) {
printf("Cuda producer: cuMemCpy failed, cuStatus =%d\n", cuStatus);
goto done;
}
}
}
for (i = 0; i < surfNum; i++) {
if (cudaProducer->pitchLinearOutput)
cudaEgl.frame.pPitch[i] = (void *)cudaPtr[i];
else
cudaEgl.frame.pArray[i] = cudaArr[i];
}
cudaEgl.width = copyWidthInBytes[0];
cudaEgl.depth = 1;
cudaEgl.height = copyHeight[0];
cudaEgl.pitch = cudaProducer->pitchLinearOutput ? cudaEgl.width : 0;
cudaEgl.frameType = cudaProducer->pitchLinearOutput ? CU_EGL_FRAME_TYPE_PITCH
: CU_EGL_FRAME_TYPE_ARRAY;
cudaEgl.planeCount = surfNum;
cudaEgl.numChannels = (eglColorFormat == CU_EGL_COLOR_FORMAT_ARGB) ? 4 : 1;
cudaEgl.eglColorFormat = eglColorFormat;
cudaEgl.cuFormat = CU_AD_FORMAT_UNSIGNED_INT8;
static int numFramesPresented = 0;
// If there is a frame presented before we check if consumer
// is done with it using cuEGLStreamProducerReturnFrame.
while (numFramesPresented) {
CUeglFrame returnedCudaEgl;
cuStatus = cuEGLStreamProducerReturnFrame(&cudaProducer->cudaConn,
&returnedCudaEgl, NULL);
if (cuStatus == CUDA_ERROR_LAUNCH_TIMEOUT) {
continue;
} else if (cuStatus != CUDA_SUCCESS) {
printf("cuda Producer return frame FAILED with custatus= %d\n", cuStatus);
return cuStatus;
} else {
numFramesPresented--;
}
}
cuStatus =
cuEGLStreamProducerPresentFrame(&cudaProducer->cudaConn, cudaEgl, NULL);
if (cuStatus != CUDA_SUCCESS) {
printf("cuda Producer present frame FAILED with custatus= %d\n", cuStatus);
goto done;
}
numFramesPresented++;
done:
if (file_p) {
fclose(file_p);
file_p = NULL;
}
return cuStatus;
}
CUresult cudaDeviceCreateProducer(test_cuda_producer_s *cudaProducer,
CUdevice device) {
CUresult status = CUDA_SUCCESS;
if (CUDA_SUCCESS != (status = cuInit(0))) {
printf("Failed to initialize CUDA\n");
return status;
}
int major = 0, minor = 0;
char deviceName[256];
checkCudaErrors(cuDeviceGetAttribute(
&major, CU_DEVICE_ATTRIBUTE_COMPUTE_CAPABILITY_MAJOR, device));
checkCudaErrors(cuDeviceGetAttribute(
&minor, CU_DEVICE_ATTRIBUTE_COMPUTE_CAPABILITY_MINOR, device));
checkCudaErrors(cuDeviceGetName(deviceName, 256, device));
printf(
"CUDA Producer on GPU Device %d: \"%s\" with compute capability "
"%d.%d\n\n",
device, deviceName, major, minor);
if (major < 6) {
printf(
"EGLStreams_CUDA_Interop requires SM 6.0 or higher arch GPU. "
"Exiting...\n");
exit(2); // EXIT_WAIVED
}
if (CUDA_SUCCESS !=
(status = cuCtxCreate(&cudaProducer->context, 0, device))) {
printf("failed to create CUDA context\n");
return status;
}
status = cuMemAlloc(&cudaProducer->cudaPtrARGB[0], (WIDTH * HEIGHT * 4));
if (status != CUDA_SUCCESS) {
printf("Create CUDA pointer failed, cuStatus=%d\n", status);
return status;
}
status = cuMemAlloc(&cudaProducer->cudaPtrYUV[0], (WIDTH * HEIGHT));
if (status != CUDA_SUCCESS) {
printf("Create CUDA pointer failed, cuStatus=%d\n", status);
return status;
}
status = cuMemAlloc(&cudaProducer->cudaPtrYUV[1], (WIDTH * HEIGHT) / 4);
if (status != CUDA_SUCCESS) {
printf("Create CUDA pointer failed, cuStatus=%d\n", status);
return status;
}
status = cuMemAlloc(&cudaProducer->cudaPtrYUV[2], (WIDTH * HEIGHT) / 4);
if (status != CUDA_SUCCESS) {
printf("Create CUDA pointer failed, cuStatus=%d\n", status);
return status;
}
CUDA_ARRAY3D_DESCRIPTOR desc = {0};
desc.Format = CU_AD_FORMAT_UNSIGNED_INT8;
desc.Depth = 1;
desc.Flags = CUDA_ARRAY3D_SURFACE_LDST;
desc.NumChannels = 4;
desc.Width = WIDTH * 4;
desc.Height = HEIGHT;
status = cuArray3DCreate(&cudaProducer->cudaArrARGB[0], &desc);
if (status != CUDA_SUCCESS) {
printf("Create CUDA array failed, cuStatus=%d\n", status);
return status;
}
for (int i = 0; i < 3; i++) {
if (i == 0) {
desc.NumChannels = 1;
desc.Width = WIDTH;
desc.Height = HEIGHT;
} else { // U/V surface as planar
desc.NumChannels = 1;
desc.Width = WIDTH / 2;
desc.Height = HEIGHT / 2;
}
status = cuArray3DCreate(&cudaProducer->cudaArrYUV[i], &desc);
if (status != CUDA_SUCCESS) {
printf("Create CUDA array failed, cuStatus=%d\n", status);
return status;
}
}
cudaProducer->pBuff = (unsigned char *)malloc((WIDTH * HEIGHT * 4));
if (!cudaProducer->pBuff) {
printf("CudaProducer: Failed to allocate image buffer\n");
}
checkCudaErrors(cuCtxPopCurrent(&cudaProducer->context));
return status;
}
void cudaProducerInit(test_cuda_producer_s *cudaProducer, EGLDisplay eglDisplay,
EGLStreamKHR eglStream, TestArgs *args) {
cudaProducer->fileName1 = args->infile1;
cudaProducer->fileName2 = args->infile2;
cudaProducer->frameCount = 2;
cudaProducer->width = args->inputWidth;
cudaProducer->height = args->inputHeight;
cudaProducer->isARGB = args->isARGB;
cudaProducer->pitchLinearOutput = args->pitchLinearOutput;
// Set cudaProducer default parameters
cudaProducer->eglDisplay = eglDisplay;
cudaProducer->eglStream = eglStream;
}
CUresult cudaProducerDeinit(test_cuda_producer_s *cudaProducer) {
if (cudaProducer->pBuff) free(cudaProducer->pBuff);
checkCudaErrors(cuMemFree(cudaProducer->cudaPtrARGB[0]));
checkCudaErrors(cuMemFree(cudaProducer->cudaPtrYUV[0]));
checkCudaErrors(cuMemFree(cudaProducer->cudaPtrYUV[1]));
checkCudaErrors(cuMemFree(cudaProducer->cudaPtrYUV[2]));
checkCudaErrors(cuArrayDestroy(cudaProducer->cudaArrARGB[0]));
checkCudaErrors(cuArrayDestroy(cudaProducer->cudaArrYUV[0]));
checkCudaErrors(cuArrayDestroy(cudaProducer->cudaArrYUV[1]));
checkCudaErrors(cuArrayDestroy(cudaProducer->cudaArrYUV[2]));
return cuEGLStreamProducerDisconnect(&cudaProducer->cudaConn);
}

View File

@@ -0,0 +1,68 @@
/* 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.
*/
//
// DESCRIPTION: Simple cuda producer header file
//
#ifndef _CUDA_PRODUCER_H_
#define _CUDA_PRODUCER_H_
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include "cudaEGL.h"
#include "eglstrm_common.h"
extern EGLStreamKHR eglStream;
extern EGLDisplay g_display;
typedef struct _test_cuda_producer_s {
// Stream params
char *fileName1;
char *fileName2;
unsigned char *pBuff;
int frameCount;
bool isARGB;
bool pitchLinearOutput;
unsigned int width;
unsigned int height;
CUcontext context;
CUeglStreamConnection cudaConn;
CUdeviceptr cudaPtrARGB[1];
CUdeviceptr cudaPtrYUV[3];
CUarray cudaArrARGB[1];
CUarray cudaArrYUV[3];
EGLStreamKHR eglStream;
EGLDisplay eglDisplay;
} test_cuda_producer_s;
void cudaProducerInit(test_cuda_producer_s *cudaProducer, EGLDisplay eglDisplay,
EGLStreamKHR eglStream, TestArgs *args);
CUresult cudaProducerTest(test_cuda_producer_s *parserArg, char *file);
CUresult cudaProducerDeinit(test_cuda_producer_s *cudaProducer);
CUresult cudaDeviceCreateProducer(test_cuda_producer_s *cudaProducer,
CUdevice device);
#endif

View File

@@ -0,0 +1,139 @@
/* 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.
*/
//
// DESCRIPTION: Common egl stream functions
//
#include "eglstrm_common.h"
EGLStreamKHR eglStream;
EGLDisplay g_display;
EGLAttrib cudaIndex;
#if defined(EXTENSION_LIST)
EXTENSION_LIST(EXTLST_DECL)
typedef void (*extlst_fnptr_t)(void);
static struct {
extlst_fnptr_t *fnptr;
char const *name;
} extensionList[] = {EXTENSION_LIST(EXTLST_ENTRY)};
int eglSetupExtensions(void) {
unsigned int i;
for (i = 0; i < (sizeof(extensionList) / sizeof(*extensionList)); i++) {
*extensionList[i].fnptr = eglGetProcAddress(extensionList[i].name);
if (*extensionList[i].fnptr == NULL) {
printf("Couldn't get address of %s()\n", extensionList[i].name);
return 0;
}
}
return 1;
}
int EGLStreamInit(int *cuda_device) {
static const EGLint streamAttrMailboxMode[] = {EGL_SUPPORT_REUSE_NV,
EGL_FALSE, EGL_NONE};
EGLBoolean eglStatus;
#define MAX_EGL_DEVICES 4
EGLint numDevices = 0;
EGLDeviceEXT devices[MAX_EGL_DEVICES];
eglStatus = eglQueryDevicesEXT(MAX_EGL_DEVICES, devices, &numDevices);
if (eglStatus != EGL_TRUE) {
printf("Error querying EGL devices\n");
exit(EXIT_FAILURE);
}
if (numDevices == 0) {
printf("No EGL devices found.. Waiving\n");
eglStatus = EGL_FALSE;
exit(EXIT_WAIVED);
}
int egl_device_id = 0;
for (egl_device_id = 0; egl_device_id < numDevices; egl_device_id++) {
eglStatus = eglQueryDeviceAttribEXT(devices[egl_device_id],
EGL_CUDA_DEVICE_NV, &cudaIndex);
if (eglStatus == EGL_TRUE) {
*cuda_device = cudaIndex; // We select first EGL-CUDA Capable device.
printf("Found EGL-CUDA Capable device with CUDA Device id = %d\n",
(int)cudaIndex);
break;
}
}
if (egl_device_id >= numDevices) {
printf("No CUDA Capable EGL Device found.. Waiving execution\n");
exit(EXIT_WAIVED);
}
g_display = eglGetPlatformDisplayEXT(EGL_PLATFORM_DEVICE_EXT,
(void *)devices[egl_device_id], NULL);
if (g_display == EGL_NO_DISPLAY) {
printf("Could not get EGL display from device. \n");
eglStatus = EGL_FALSE;
exit(EXIT_FAILURE);
}
eglStatus = eglInitialize(g_display, 0, 0);
if (!eglStatus) {
printf("EGL failed to initialize. \n");
eglStatus = EGL_FALSE;
exit(EXIT_FAILURE);
}
eglStream = eglCreateStreamKHR(g_display, streamAttrMailboxMode);
if (eglStream == EGL_NO_STREAM_KHR) {
printf("Could not create EGL stream.\n");
eglStatus = EGL_FALSE;
exit(EXIT_FAILURE);
}
printf("Created EGLStream %p\n", eglStream);
// Set stream attribute
if (!eglStreamAttribKHR(g_display, eglStream, EGL_CONSUMER_LATENCY_USEC_KHR,
16000)) {
printf(
"Consumer: eglStreamAttribKHR EGL_CONSUMER_LATENCY_USEC_KHR failed\n");
return 0;
}
if (!eglStreamAttribKHR(g_display, eglStream,
EGL_CONSUMER_ACQUIRE_TIMEOUT_USEC_KHR, 16000)) {
printf(
"Consumer: eglStreamAttribKHR EGL_CONSUMER_ACQUIRE_TIMEOUT_USEC_KHR "
"failed\n");
return 0;
}
printf("EGLStream initialized\n");
return 1;
}
void EGLStreamFini(void) { eglDestroyStreamKHR(g_display, eglStream); }
#endif

View File

@@ -0,0 +1,103 @@
/* 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.
*/
//
// DESCRIPTION: Common EGL stream functions header file
//
#ifndef _EGLSTRM_COMMON_H_
#define _EGLSTRM_COMMON_H_
#include <signal.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <unistd.h>
#include "cuda.h"
#include "cudaEGL.h"
#include "helper_cuda_drvapi.h"
#define EXTENSION_LIST(T) \
T(PFNEGLCREATESTREAMKHRPROC, eglCreateStreamKHR) \
T(PFNEGLDESTROYSTREAMKHRPROC, eglDestroyStreamKHR) \
T(PFNEGLQUERYSTREAMKHRPROC, eglQueryStreamKHR) \
T(PFNEGLQUERYSTREAMU64KHRPROC, eglQueryStreamu64KHR) \
T(PFNEGLQUERYSTREAMTIMEKHRPROC, eglQueryStreamTimeKHR) \
T(PFNEGLSTREAMATTRIBKHRPROC, eglStreamAttribKHR) \
T(PFNEGLSTREAMCONSUMERACQUIREKHRPROC, eglStreamConsumerAcquireKHR) \
T(PFNEGLSTREAMCONSUMERRELEASEKHRPROC, eglStreamConsumerReleaseKHR) \
T(PFNEGLSTREAMCONSUMERGLTEXTUREEXTERNALKHRPROC, \
eglStreamConsumerGLTextureExternalKHR) \
T(PFNEGLGETSTREAMFILEDESCRIPTORKHRPROC, eglGetStreamFileDescriptorKHR) \
T(PFNEGLQUERYDEVICESEXTPROC, eglQueryDevicesEXT) \
T(PFNEGLGETPLATFORMDISPLAYEXTPROC, eglGetPlatformDisplayEXT) \
T(PFNEGLQUERYDEVICEATTRIBEXTPROC, eglQueryDeviceAttribEXT) \
T(PFNEGLCREATESTREAMFROMFILEDESCRIPTORKHRPROC, \
eglCreateStreamFromFileDescriptorKHR)
#define eglCreateStreamKHR my_eglCreateStreamKHR
#define eglDestroyStreamKHR my_eglDestroyStreamKHR
#define eglQueryStreamKHR my_eglQueryStreamKHR
#define eglQueryStreamu64KHR my_eglQueryStreamu64KHR
#define eglQueryStreamTimeKHR my_eglQueryStreamTimeKHR
#define eglStreamAttribKHR my_eglStreamAttribKHR
#define eglStreamConsumerAcquireKHR my_eglStreamConsumerAcquireKHR
#define eglStreamConsumerReleaseKHR my_eglStreamConsumerReleaseKHR
#define eglStreamConsumerGLTextureExternalKHR \
my_eglStreamConsumerGLTextureExternalKHR
#define eglGetStreamFileDescriptorKHR my_eglGetStreamFileDescriptorKHR
#define eglCreateStreamFromFileDescriptorKHR \
my_eglCreateStreamFromFileDescriptorKHR
#define eglQueryDevicesEXT my_eglQueryDevicesEXT
#define eglGetPlatformDisplayEXT my_eglGetPlatformDisplayEXT
#define eglQueryDeviceAttribEXT my_eglQueryDeviceAttribEXT
#define EXTLST_DECL(tx, x) tx my_##x = NULL;
#define EXTLST_EXTERN(tx, x) extern tx my_##x;
#define EXTLST_ENTRY(tx, x) {(extlst_fnptr_t *)&my_##x, #x},
#define MAX_STRING_SIZE 256
#define WIDTH 720
#define HEIGHT 480
typedef struct _TestArgs {
char *infile1;
char *infile2;
bool isARGB;
unsigned int inputWidth;
unsigned int inputHeight;
bool pitchLinearOutput;
} TestArgs;
int eglSetupExtensions(void);
int EGLStreamInit(int *dev);
void EGLStreamFini(void);
#endif

View File

@@ -0,0 +1,160 @@
################################################################################
# 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.
#
################################################################################
#
# findegl.mk is used to find the necessary EGL Libraries for specific distributions
# this is supported on Linux
#
################################################################################
# Determine OS platform and unix distribution
ifeq ("$(TARGET_OS)","linux")
# first search lsb_release
DISTRO = $(shell lsb_release -i -s 2>/dev/null | tr "[:upper:]" "[:lower:]")
ifeq ("$(DISTRO)","")
# second search and parse /etc/issue
DISTRO = $(shell more /etc/issue | awk '{print $$1}' | sed '1!d' | sed -e "/^$$/d" 2>/dev/null | tr "[:upper:]" "[:lower:]")
# ensure data from /etc/issue is valid
ifeq (,$(filter $(DISTRO),ubuntu fedora red rhel centos suse))
DISTRO =
endif
ifeq ("$(DISTRO)","")
# third, we can search in /etc/os-release or /etc/{distro}-release
DISTRO = $(shell awk '/ID/' /etc/*-release | sed 's/ID=//' | grep -v "VERSION" | grep -v "ID" | grep -v "DISTRIB")
endif
endif
endif
ifeq ("$(TARGET_OS)","linux")
# $(info) >> findegl.mk -> LINUX path <<<)
# Each set of Linux Distros have different paths for where to find their OpenGL libraries reside
UBUNTU = $(shell echo $(DISTRO) | grep -i ubuntu >/dev/null 2>&1; echo $$?)
FEDORA = $(shell echo $(DISTRO) | grep -i fedora >/dev/null 2>&1; echo $$?)
RHEL = $(shell echo $(DISTRO) | grep -i 'red\|rhel' >/dev/null 2>&1; echo $$?)
CENTOS = $(shell echo $(DISTRO) | grep -i centos >/dev/null 2>&1; echo $$?)
SUSE = $(shell echo $(DISTRO) | grep -i 'suse\|sles' >/dev/null 2>&1; echo $$?)
ifeq ("$(UBUNTU)","0")
ifeq ($(HOST_ARCH)-$(TARGET_ARCH),x86_64-armv7l)
GLPATH := /usr/arm-linux-gnueabihf/lib
GLLINK := -L/usr/arm-linux-gnueabihf/lib
ifneq ($(TARGET_FS),)
GLPATH += $(TARGET_FS)/usr/lib/arm-linux-gnueabihf
GLLINK += -L$(TARGET_FS)/usr/lib/arm-linux-gnueabihf
endif
else ifeq ($(HOST_ARCH)-$(TARGET_ARCH),x86_64-aarch64)
GLPATH := /usr/aarch64-linux-gnu/lib
GLLINK := -L/usr/aarch64-linux-gnu/lib
ifneq ($(TARGET_FS),)
GLPATH += $(TARGET_FS)/usr/lib
GLPATH += $(TARGET_FS)/usr/lib/aarch64-linux-gnu
GLLINK += -L$(TARGET_FS)/usr/lib/aarch64-linux-gnu
endif
else
UBUNTU_PKG_NAME = $(shell which dpkg >/dev/null 2>&1 && dpkg -l 'nvidia-*' | grep '^ii' | awk '{print $$2}' | head -1)
ifneq ("$(UBUNTU_PKG_NAME)","")
GLPATH ?= /usr/lib/$(UBUNTU_PKG_NAME)
GLLINK ?= -L/usr/lib/$(UBUNTU_PKG_NAME)
endif
DFLT_PATH ?= /usr/lib
endif
endif
ifeq ("$(SUSE)","0")
GLPATH ?= /usr/X11R6/lib64
GLLINK ?= -L/usr/X11R6/lib64
DFLT_PATH ?= /usr/lib64
endif
ifeq ("$(FEDORA)","0")
GLPATH ?= /usr/lib64/nvidia
GLLINK ?= -L/usr/lib64/nvidia
DFLT_PATH ?= /usr/lib64
endif
ifeq ("$(RHEL)","0")
GLPATH ?= /usr/lib64/nvidia
GLLINK ?= -L/usr/lib64/nvidia
DFLT_PATH ?= /usr/lib64
endif
ifeq ("$(CENTOS)","0")
GLPATH ?= /usr/lib64/nvidia
GLLINK ?= -L/usr/lib64/nvidia
DFLT_PATH ?= /usr/lib64
endif
EGLLIB := $(shell find -L $(GLPATH) $(DFLT_PATH) -name libEGL.so -print 2>/dev/null)
ifeq ("$(EGLLIB)","")
$(info >>> WARNING - libEGL.so not found, please install libEGL.so <<<)
SAMPLE_ENABLED := 0
endif
HEADER_SEARCH_PATH ?= $(TARGET_FS)/usr/include
ifeq ($(HOST_ARCH)-$(TARGET_ARCH)-$(TARGET_OS),x86_64-armv7l-linux)
HEADER_SEARCH_PATH += /usr/arm-linux-gnueabihf/include
else ifeq ($(HOST_ARCH)-$(TARGET_ARCH)-$(TARGET_OS),x86_64-aarch64-linux)
HEADER_SEARCH_PATH += /usr/aarch64-linux-gnu/include
endif
EGLHEADER := $(shell find -L $(HEADER_SEARCH_PATH) -name egl.h -print 2>/dev/null)
EGLEXTHEADER := $(shell find -L $(HEADER_SEARCH_PATH) -name eglext.h -print 2>/dev/null)
ifeq ("$(EGLHEADER)","")
$(info >>> WARNING - egl.h not found, please install egl.h <<<)
SAMPLE_ENABLED := 0
endif
ifeq ("$(EGLEXTHEADER)","")
$(info >>> WARNING - eglext.h not found, please install eglext.h <<<)
SAMPLE_ENABLED := 0
endif
else
endif
ifeq ("$(TARGET_OS)","qnx")
HOST_CCFLAGS := -V8.3.0,gcc_ntoaarch64le
endif
# Attempt to compile a minimal EGL application and run to check if EGL_SUPPORT_REUSE_NV is supported in the EGL headers available.
ifneq ($(SAMPLE_ENABLED), 0)
$(shell printf "#include <EGL/egl.h>\n#include <EGL/eglext.h>\nint main() {\n#ifdef EGL_SUPPORT_REUSE_NV \n #error \"Compatible EGL header found\" \n return 0;\n#endif \n return 1;\n}" > test.c; )
EGL_DEFINES := $(shell $(HOST_COMPILER) $(HOST_CCFLAGS) $(CCFLAGS) $(EXTRA_CCFLAGS) -lEGL test.c -c 2>&1 | grep -ic "Compatible EGL header found";)
SHOULD_WAIVE := 0
ifeq ($(EGL_DEFINES),0)
SHOULD_WAIVE := 1
endif
ifeq ($(SHOULD_WAIVE),1)
$(info -----------------------------------------------------------------------------------------------)
$(info WARNING - NVIDIA EGL EXTENSIONS are not available in the present EGL headers)
$(info -----------------------------------------------------------------------------------------------)
$(info This CUDA Sample cannot be built if the EGL NVIDIA EXTENSIONS like EGL_SUPPORT_REUSE_NV are not supported in EGL headers.)
$(info This will be a dry-run of the Makefile.)
$(info Please install the latest khronos EGL headers and libs to build this sample)
$(info -----------------------------------------------------------------------------------------------)
SAMPLE_ENABLED := 0
endif
$(shell rm test.o test.c 2>/dev/null)
endif

View File

@@ -0,0 +1,231 @@
/* 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.
*/
//
// DESCRIPTION: Simple EGL stream sample app
//
//
//#define EGL_EGLEXT_PROTOTYPES
#include "cudaEGL.h"
#include "cuda_consumer.h"
#include "cuda_producer.h"
#include "eglstrm_common.h"
/* ------ globals ---------*/
#if defined(EXTENSION_LIST)
EXTENSION_LIST(EXTLST_EXTERN)
#endif
#define NUM_TRAILS 4
bool signal_stop = 0;
static void sig_handler(int sig) {
signal_stop = 1;
printf("Signal: %d\n", sig);
}
int main(int argc, char **argv) {
TestArgs args;
CUresult curesult = CUDA_SUCCESS;
unsigned int i, j;
EGLint streamState = 0;
test_cuda_consumer_s cudaConsumer;
test_cuda_producer_s cudaProducer;
memset(&cudaProducer, 0, sizeof(test_cuda_producer_s));
memset(&cudaConsumer, 0, sizeof(test_cuda_consumer_s));
// Hook up Ctrl-C handler
signal(SIGINT, sig_handler);
if (!eglSetupExtensions()) {
printf("SetupExtentions failed \n");
curesult = CUDA_ERROR_UNKNOWN;
goto done;
}
checkCudaErrors(cuInit(0));
int count;
checkCudaErrors(cuDeviceGetCount(&count));
printf("Found %d cuda devices\n", count);
CUdevice devId;
if (!EGLStreamInit(&devId)) {
printf("EGLStream Init failed.\n");
curesult = CUDA_ERROR_UNKNOWN;
goto done;
}
curesult = cudaDeviceCreateProducer(&cudaProducer, devId);
if (curesult != CUDA_SUCCESS) {
goto done;
}
curesult = cudaDeviceCreateConsumer(&cudaConsumer, devId);
if (curesult != CUDA_SUCCESS) {
goto done;
}
checkCudaErrors(cuCtxPushCurrent(cudaConsumer.context));
if (CUDA_SUCCESS != (curesult = cuEGLStreamConsumerConnect(
&(cudaConsumer.cudaConn), eglStream))) {
printf("FAILED Connect CUDA consumer with error %d\n", curesult);
goto done;
} else {
printf("Connected CUDA consumer, CudaConsumer %p\n", cudaConsumer.cudaConn);
}
checkCudaErrors(cuCtxPopCurrent(&cudaConsumer.context));
checkCudaErrors(cuCtxPushCurrent(cudaProducer.context));
if (CUDA_SUCCESS ==
(curesult = cuEGLStreamProducerConnect(&(cudaProducer.cudaConn),
eglStream, WIDTH, HEIGHT))) {
printf("Connect CUDA producer Done, CudaProducer %p\n",
cudaProducer.cudaConn);
} else {
printf("Connect CUDA producer FAILED with error %d\n", curesult);
goto done;
}
checkCudaErrors(cuCtxPopCurrent(&cudaProducer.context));
// Initialize producer
for (i = 0; i < NUM_TRAILS; i++) {
if (streamState != EGL_STREAM_STATE_CONNECTING_KHR) {
if (!eglQueryStreamKHR(g_display, eglStream, EGL_STREAM_STATE_KHR,
&streamState)) {
printf("main: eglQueryStreamKHR EGL_STREAM_STATE_KHR failed\n");
curesult = CUDA_ERROR_UNKNOWN;
goto done;
}
}
args.inputWidth = WIDTH;
args.inputHeight = HEIGHT;
if (i % 2 != 0) {
args.isARGB = 1;
args.infile1 = sdkFindFilePath("cuda_f_1.yuv", argv[0]);
args.infile2 = sdkFindFilePath("cuda_f_2.yuv", argv[0]);
} else {
args.isARGB = 0;
args.infile1 = sdkFindFilePath("cuda_yuv_f_1.yuv", argv[0]);
args.infile2 = sdkFindFilePath("cuda_yuv_f_2.yuv", argv[0]);
}
if ((i % 4) < 2) {
args.pitchLinearOutput = 1;
} else {
args.pitchLinearOutput = 0;
}
checkCudaErrors(cuCtxPushCurrent(cudaProducer.context));
cudaProducerInit(&cudaProducer, g_display, eglStream, &args);
checkCudaErrors(cuCtxPopCurrent(&cudaProducer.context));
checkCudaErrors(cuCtxPushCurrent(cudaConsumer.context));
cuda_consumer_init(&cudaConsumer, &args);
checkCudaErrors(cuCtxPopCurrent(&cudaConsumer.context));
printf("main - Cuda Producer and Consumer Initialized.\n");
for (j = 0; j < 2; j++) {
printf("Running for %s frame and %s input\n",
args.isARGB ? "ARGB" : "YUV",
args.pitchLinearOutput ? "Pitchlinear" : "BlockLinear");
if (j == 0) {
checkCudaErrors(cuCtxPushCurrent(cudaProducer.context));
curesult = cudaProducerTest(&cudaProducer, cudaProducer.fileName1);
if (curesult != CUDA_SUCCESS) {
printf("Cuda Producer Test failed for frame = %d\n", j + 1);
goto done;
}
checkCudaErrors(cuCtxPopCurrent(&cudaProducer.context));
checkCudaErrors(cuCtxPushCurrent(cudaConsumer.context));
curesult = cudaConsumerTest(&cudaConsumer, cudaConsumer.outFile1);
if (curesult != CUDA_SUCCESS) {
printf("Cuda Consumer Test failed for frame = %d\n", j + 1);
goto done;
}
checkCudaErrors(cuCtxPopCurrent(&cudaConsumer.context));
} else {
checkCudaErrors(cuCtxPushCurrent(cudaProducer.context));
curesult = cudaProducerTest(&cudaProducer, cudaProducer.fileName2);
if (curesult != CUDA_SUCCESS) {
printf("Cuda Producer Test failed for frame = %d\n", j + 1);
goto done;
}
checkCudaErrors(cuCtxPopCurrent(&cudaProducer.context));
checkCudaErrors(cuCtxPushCurrent(cudaConsumer.context));
curesult = cudaConsumerTest(&cudaConsumer, cudaConsumer.outFile2);
if (curesult != CUDA_SUCCESS) {
printf("Cuda Consumer Test failed for frame = %d\n", j + 1);
goto done;
}
checkCudaErrors(cuCtxPopCurrent(&cudaConsumer.context));
}
}
}
checkCudaErrors(cuCtxPushCurrent(cudaProducer.context));
if (CUDA_SUCCESS != (curesult = cudaProducerDeinit(&cudaProducer))) {
printf("Producer Disconnect FAILED. \n");
goto done;
}
checkCudaErrors(cuCtxPopCurrent(&cudaProducer.context));
if (!eglQueryStreamKHR(g_display, eglStream, EGL_STREAM_STATE_KHR,
&streamState)) {
printf("Cuda consumer, eglQueryStreamKHR EGL_STREAM_STATE_KHR failed\n");
curesult = CUDA_ERROR_UNKNOWN;
goto done;
}
if (streamState != EGL_STREAM_STATE_DISCONNECTED_KHR) {
if (CUDA_SUCCESS != (curesult = cuda_consumer_deinit(&cudaConsumer))) {
printf("Consumer Disconnect FAILED.\n");
goto done;
}
}
printf("Producer and Consumer Disconnected \n");
done:
if (!eglQueryStreamKHR(g_display, eglStream, EGL_STREAM_STATE_KHR,
&streamState)) {
printf("Cuda consumer, eglQueryStreamKHR EGL_STREAM_STATE_KHR failed\n");
curesult = CUDA_ERROR_UNKNOWN;
}
if (streamState != EGL_STREAM_STATE_DISCONNECTED_KHR) {
EGLStreamFini();
}
if (curesult == CUDA_SUCCESS) {
printf("&&&& EGLStream interop test PASSED\n");
} else {
printf("&&&& EGLStream interop test FAILED\n");
}
return 0;
}

View 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
}

View File

@@ -0,0 +1,7 @@
{
"recommendations": [
"nvidia.nsight-vscode-edition",
"ms-vscode.cpptools",
"ms-vscode.makefile-tools"
]
}

View File

@@ -0,0 +1,10 @@
{
"configurations": [
{
"name": "CUDA C++: Launch",
"type": "cuda-gdb",
"request": "launch",
"program": "${workspaceFolder}/EGLSync_CUDAEvent_Interop"
}
]
}

View File

@@ -0,0 +1,15 @@
{
"version": "2.0.0",
"tasks": [
{
"label": "sample",
"type": "shell",
"command": "make dbg=1",
"problemMatcher": ["$nvcc"],
"group": {
"kind": "build",
"isDefault": true
}
}
]
}

View File

@@ -0,0 +1,783 @@
/* 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.
*/
// Simple interop app demonstrating EGLImage + EGLSync interop with CUDA.
// Using EGLSync - CUDA Event interop one can achieve synchronization on GPU
// itself for GL-EGL-CUDA operations instead of blocking CPU for
// synchronization. This app requires GLES 3.2 or higher
//---------------------------INCLUDES---------------------------------//
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include "graphics_interface.h"
#include <cuda.h>
#include <helper_cuda_drvapi.h>
#include <cudaEGL.h>
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include <GLES3/gl32.h>
#include "egl_common.h"
//---------------------------DEFINES---------------------------------//
#define MAX_ITR 100
#define FAILURE 0
#define SUCCESS 1
#define WAIVED 2
#define BLOCK_SIZE 16
#define GL_READ 0
#define GL_WRITE 1
//---------------------------MACROS---------------------------------//
// Error-checking wrapper around GL calls
#define GL_SAFE_CALL(call) \
{ \
GLenum err; \
call; \
err = glGetError(); \
if (err != GL_NO_ERROR) { \
fprintf(stderr, "%s:%d GL error: %d\n", __FILE__, __LINE__, err); \
cleanup(FAILURE); \
} \
}
#define GL_SAFE_CALL_NO_CLEANUP(call, err) \
{ \
GLenum status; \
call; \
status = glGetError(); \
if (status != GL_NO_ERROR) { \
fprintf(stderr, "%s:%d GL error: %d\n", __FILE__, __LINE__, status); \
err = status; \
} \
}
// Error-checking wrapper around CUDA calls (taken from cutil.h)
#define CUDA_SAFE_CALL(call) \
do { \
cudaError err = call; \
if (cudaSuccess != err) { \
fprintf(stderr, "Cuda error in file '%s' in line %i : %s.\n", __FILE__, \
__LINE__, cudaGetErrorString(err)); \
cleanup(FAILURE); \
} \
} while (0)
#define CUDA_SAFE_CALL_NO_CLEANUP(call, err) \
do { \
cudaError status = call; \
if (cudaSuccess != status) { \
fprintf(stderr, "Cuda error in file '%s' in line %i : %s.\n", __FILE__, \
__LINE__, cudaGetErrorString(status)); \
err = status; \
} \
} while (0)
#if defined(EXTENSION_LIST)
EXTENSION_LIST(EXTLST_DECL)
typedef void (*extlst_fnptr_t)(void);
static struct {
extlst_fnptr_t *fnptr;
char const *name;
} extensionList[] = {EXTENSION_LIST(EXTLST_ENTRY)};
int eglSetupExtensions(void) {
unsigned int i;
for (i = 0; i < (sizeof(extensionList) / sizeof(*extensionList)); i++) {
*extensionList[i].fnptr = eglGetProcAddress(extensionList[i].name);
if (*extensionList[i].fnptr == NULL) {
printf("Couldn't get address of %s()\n", extensionList[i].name);
return 0;
}
}
return 1;
}
#endif
#if defined(EXTENSION_LIST)
EXTENSION_LIST(EXTLST_EXTERN)
#endif
//------------------------GLOBAL VARIABLES--------------------------//
// GL texture
GLuint tex[2] = {0};
// Used to catch unexpected termination from GLUT
int cleanExit = 0;
// Use CPU Sync or GPU sync; Default GPU
int useGpu = 1;
// CUDA Resource
CUgraphicsResource writeResource = NULL;
CUgraphicsResource readResource = NULL;
CUarray writeArray, readArray;
CUdevice device;
CUcontext context;
// Which device to run on
unsigned int dev = 0;
// Default width, height, and iterations value
int width = 2048;
int height = 2048;
int itr = MAX_ITR;
// Error check variable
__device__ static unsigned int numErrors = 0;
//-----------------------FUNCTION PROTOTYPES------------------------//
void checkSync(int argc, char **argv);
int parseCmdLine(int argc, char **argv);
void printUsage(void);
void cleanup(int status);
void exitHandler(void);
void printStatus(int status);
void checkSyncOnCPU(void);
void checkSyncOnGPU(EGLDisplay dpy);
__global__ void verify_and_update_kernel(CUsurfObject write, CUsurfObject read,
char expected, char newval, int width,
int height);
extern "C" cudaError_t cudaGetValueMismatch();
//-----------------------FUNCTION DEFINITIONS------------------------//
int main(int argc, char *argv[]) {
#if defined(__linux__)
setenv("DISPLAY", ":0", 0);
#endif
parseCmdLine(argc, argv);
atexit(exitHandler);
checkSync(argc, argv);
return 0;
}
int parseCmdLine(int argc, char **argv) {
int i;
for (i = 1; i < argc; i++) {
if (strcmp(argv[i], "-cpu") == 0) {
useGpu = 0;
}
if (strcmp(argv[i], "-h") == 0) {
printUsage();
cleanup(SUCCESS);
}
if (strcmp(argv[i], "-width") == 0) {
++i;
if (i == argc) {
printf("width option must be followed by value\n");
return FAILURE;
}
if (sscanf(argv[i], "%d", &width) != 1) {
printf("Error: invalid width value\n");
return FAILURE;
}
}
if (strcmp(argv[i], "-height") == 0) {
++i;
if (i == argc) {
printf("height option must be followed by value\n");
return FAILURE;
}
if (sscanf(argv[i], "%d", &height) != 1) {
printf("Error: invalid height value\n");
return FAILURE;
}
}
if (strcmp(argv[i], "-itr") == 0) {
++i;
if (i == argc) {
printf("itr option must be followed by iteration value\n");
return FAILURE;
}
if (sscanf(argv[i], "%d", &itr) != 1) {
printf("Error: invalid iteration value\n");
return FAILURE;
}
}
}
return SUCCESS;
}
void printUsage(void) {
printf("Usage:\n");
printf("\t-h\tPrint command line options\n");
printf("\t-cpu\tSync on the CPU instead of the GPU\n");
printf("\t-width w\tSet the width to w\n");
printf("\t-height h\tSet the height to h\n");
printf("\t-itr i\tSet number of iterations to i\n");
}
void checkSync(int argc, char **argv) {
int x, y;
int bufferSize = width * height * 4;
unsigned char *pSurf_read = NULL, *pSurf_write = NULL;
int integrated;
CUresult status = CUDA_SUCCESS;
// Init values for variables
x = y = 0;
if (CUDA_SUCCESS != (status = cuInit(0))) {
printf("Failed to initialize CUDA\n");
}
device = findCudaDeviceDRV(argc, (const char **)argv);
if (CUDA_SUCCESS != (status = cuCtxCreate(&context, 0, device))) {
printf("failed to create CUDA context\n");
}
cuCtxPushCurrent(context);
status =
cuDeviceGetAttribute(&integrated, CU_DEVICE_ATTRIBUTE_INTEGRATED, device);
if (status != CUDA_SUCCESS) {
printf("Failed to get device attribute CU_DEVICE_ATTRIBUTE_INTEGRATED\n");
cleanup(FAILURE);
}
if (integrated != 1) {
printf(
"EGLSync_CUDAEvent_Interop does not support dGPU. Waiving sample.\n");
cleanup(WAIVED);
}
#if (defined(__arm__) || defined(__aarch64__)) && defined(__linux__)
graphics_setup_window(0, 0, width, height, "EGLSync_CUDA_Interop");
#endif
pSurf_read = (unsigned char *)malloc(bufferSize);
pSurf_write = (unsigned char *)malloc(bufferSize);
if (pSurf_read == NULL || pSurf_write == NULL) {
printf("malloc failed\n");
cleanup(FAILURE);
}
for (x = 0; x < width; x++) {
for (y = 0; y < height; y++) {
pSurf_read[(y * width + x) * 4] = 1;
pSurf_read[(y * width + x) * 4 + 1] = 1;
pSurf_read[(y * width + x) * 4 + 2] = 1;
pSurf_read[(y * width + x) * 4 + 3] = 1;
pSurf_write[(y * width + x) * 4] = 0;
pSurf_write[(y * width + x) * 4 + 1] = 0;
pSurf_write[(y * width + x) * 4 + 2] = 0;
pSurf_write[(y * width + x) * 4 + 3] = 0;
}
}
// NOP call to error-check the above glut calls
GL_SAFE_CALL({});
// Init texture
GL_SAFE_CALL(glGenTextures(2, tex));
GL_SAFE_CALL(glBindTexture(GL_TEXTURE_2D, tex[GL_READ]));
GL_SAFE_CALL(
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST));
GL_SAFE_CALL(
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST));
GL_SAFE_CALL(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0,
GL_RGBA, GL_UNSIGNED_BYTE, pSurf_read));
GL_SAFE_CALL(glBindTexture(GL_TEXTURE_2D, 0));
GL_SAFE_CALL(glBindTexture(GL_TEXTURE_2D, tex[GL_WRITE]));
GL_SAFE_CALL(
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST));
GL_SAFE_CALL(
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST));
GL_SAFE_CALL(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0,
GL_RGBA, GL_UNSIGNED_BYTE, pSurf_write));
GL_SAFE_CALL(glBindTexture(GL_TEXTURE_2D, 0));
glFinish();
EGLDisplay eglDisplayHandle = eglGetCurrentDisplay();
if (eglDisplayHandle == EGL_NO_DISPLAY) {
printf("eglDisplayHandle failed \n");
cleanup(FAILURE);
} else {
printf("eglDisplay Handle created \n");
}
if (!eglSetupExtensions()) {
printf("SetupExtentions failed \n");
cleanup(FAILURE);
}
EGLContext eglCtx = eglGetCurrentContext();
if (eglCtx == EGL_NO_CONTEXT) {
printf("Context1 create failed with error %d\n", eglGetError());
cleanup(FAILURE);
}
// Create the EGL_Image
EGLint eglImgAttrs[] = {EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE,
EGL_NONE};
EGLImageKHR eglImage1 =
eglCreateImageKHR(eglDisplayHandle, eglCtx, EGL_GL_TEXTURE_2D_KHR,
(EGLClientBuffer)(intptr_t)tex[GL_READ], eglImgAttrs);
if (eglImage1 == EGL_NO_IMAGE_KHR) {
printf("EGLImage create failed for read texture with error %d\n",
eglGetError());
cleanup(FAILURE);
} else {
printf("EGLImage1 created \n");
}
EGLImageKHR eglImage2 =
eglCreateImageKHR(eglDisplayHandle, eglCtx, EGL_GL_TEXTURE_2D_KHR,
(EGLClientBuffer)(intptr_t)tex[GL_WRITE], eglImgAttrs);
if (eglImage2 == EGL_NO_IMAGE_KHR) {
printf("EGLImage create failed for write texture with error %d\n",
eglGetError());
cleanup(FAILURE);
} else {
printf("EGLImage2 created \n");
}
glFinish();
status = cuGraphicsEGLRegisterImage(&writeResource, eglImage1,
CU_GRAPHICS_REGISTER_FLAGS_NONE);
if (status != CUDA_SUCCESS) {
printf("cuGraphicsEGLRegisterImage failed with Texture 1\n");
cleanup(FAILURE);
} else {
printf(
"cuGraphicsEGLRegisterImage Passed, writeResource created with texture "
"1\n");
}
status =
cuGraphicsSubResourceGetMappedArray(&writeArray, writeResource, 0, 0);
if (status != CUDA_SUCCESS) {
printf(
"cuGraphicsSubResourceGetMappedArray failed for writeResource with "
"texture 1\n");
cleanup(FAILURE);
}
status = cuGraphicsEGLRegisterImage(&readResource, eglImage2,
CU_GRAPHICS_REGISTER_FLAGS_NONE);
if (status != CUDA_SUCCESS) {
printf(
"cuGraphicsEGLRegisterImage failed for readResource with Texture 2\n");
cleanup(FAILURE);
} else {
printf(
"cuGraphicsEGLRegisterImage Passed, readResource created with texture "
"2\n");
}
status = cuGraphicsSubResourceGetMappedArray(&readArray, readResource, 0, 0);
if (status != CUDA_SUCCESS) {
printf("cuGraphicsSubResourceGetMappedArray failed for texture 2\n");
cleanup(FAILURE);
}
if (useGpu) {
printf("Using GPU Sync path\n");
checkSyncOnGPU(eglDisplayHandle);
} else {
printf("Using CPU Sync path\n");
checkSyncOnCPU();
}
free(pSurf_read);
free(pSurf_write);
cleanup(SUCCESS);
}
void checkSyncOnCPU(void) {
int z = 0;
unsigned char expectedData, newData;
CUresult status = CUDA_SUCCESS;
CUDA_RESOURCE_DESC wdsc, rdsc;
memset(&wdsc, 0, sizeof(wdsc));
memset(&rdsc, 0, sizeof(rdsc));
expectedData = 0;
newData = 1;
wdsc.resType = CU_RESOURCE_TYPE_ARRAY;
wdsc.res.array.hArray = writeArray;
CUsurfObject writeSurface;
rdsc.resType = CU_RESOURCE_TYPE_ARRAY;
rdsc.res.array.hArray = readArray;
CUsurfObject readSurface;
status = cuSurfObjectCreate(&writeSurface, &wdsc);
if (status != CUDA_SUCCESS) {
printf("Surface bounding failed with status %d\n", status);
cleanup(FAILURE);
}
status = cuSurfObjectCreate(&readSurface, &rdsc);
if (status != CUDA_SUCCESS) {
printf("Surface bounding failed\n");
cleanup(FAILURE);
}
for (z = 0; z < itr; z++) {
// GL call to copy from read texture to write texture
GL_SAFE_CALL(glCopyImageSubData(tex[GL_READ], GL_TEXTURE_2D, 0, 0, 0, 0,
tex[GL_WRITE], GL_TEXTURE_2D, 0, 0, 0, 0,
width, height, 1));
glFinish();
newData++;
expectedData++;
verify_and_update_kernel<<<(width * height) / 256, 256>>>(
writeSurface, readSurface, expectedData, newData, width, height);
status = cuCtxSynchronize();
if (status != CUDA_SUCCESS) {
printf("cuCtxSynchronize failed \n");
}
}
cudaError_t err = cudaGetValueMismatch();
if (err != cudaSuccess) {
printf("Value mismatch seen when using CPU sync\n");
cleanup(FAILURE);
}
// Clean up CUDA writeResource
status = cuGraphicsUnregisterResource(writeResource);
if (status != CUDA_SUCCESS) {
printf("Failed to unregister %d", status);
cleanup(FAILURE);
} else {
printf("Unregistered writeResource. \n");
}
// Clean up CUDA readResource
status = cuGraphicsUnregisterResource(readResource);
if (status != CUDA_SUCCESS) {
printf("Failed to unregister %d", status);
cleanup(FAILURE);
} else {
printf("Unregistered readResource. \n");
}
}
/*
Performs same function as checkSyncOnCPU
Here instead of glFinish() and cuCtxSynchronize like in checkSyncOnCPU,
we make use of EGLSync, CUDA Event and cuStreamWaitEvent, eglWaitSyncKHR to
achieve the synchronization due to this CPU is not blocked for any
synchronization needed between GL-EGL & CUDA operations all synchronizations
happens on the GPU only.
*/
void checkSyncOnGPU(EGLDisplay dpy) {
int z = 0;
unsigned char expectedData, newData;
cudaError_t err;
CUresult status = CUDA_SUCCESS;
CUstream stream;
CUevent timingDisabledEvent;
CUDA_RESOURCE_DESC wdsc, rdsc;
memset(&wdsc, 0, sizeof(wdsc));
memset(&rdsc, 0, sizeof(rdsc));
expectedData = 0;
newData = 1;
wdsc.resType = CU_RESOURCE_TYPE_ARRAY;
wdsc.res.array.hArray = writeArray;
CUsurfObject writeSurface;
rdsc.resType = CU_RESOURCE_TYPE_ARRAY;
rdsc.res.array.hArray = readArray;
CUsurfObject readSurface;
status = cuSurfObjectCreate(&writeSurface, &wdsc);
if (status != CUDA_SUCCESS) {
printf("Surface bounding failed with status %d\n", status);
cleanup(FAILURE);
}
status = cuSurfObjectCreate(&readSurface, &rdsc);
if (status != CUDA_SUCCESS) {
printf("Surface bounding failed\n");
cleanup(FAILURE);
}
status = cuStreamCreate(&stream, CU_STREAM_DEFAULT);
if (status != CUDA_SUCCESS) {
printf("Stream creation failed\n");
cleanup(FAILURE);
}
// Creates timing disabled event which uses non-blocking synchronization
status = cuEventCreate(&timingDisabledEvent, CU_EVENT_DISABLE_TIMING);
if (status != CUDA_SUCCESS) {
printf("Default event creation failed\n");
cleanup(FAILURE);
}
/*
1. We perform texture-to-texture copy in GLES which is async function
2. Followed by creating EGLSync and a CUDA Event from that EGLSync object
3. Using cuStreamWaitEvent() we wait in GPU for the GLES to finish texture
copy.
4. CUDA kernel verfiy_and_update_kernel verifies if the copied data by
GLES is correct, and it updates the buffer with new values.
5. This is followed by eglWaitSyncKHR() which waits for the cuda kernel to
finish, so that in the next iteration GLES can perform the copying of the
updated buffer to write texture,
*/
for (z = 0; z < itr; z++) {
// GL call to copy from read texture to write texture
GL_SAFE_CALL(glCopyImageSubData(tex[GL_READ], GL_TEXTURE_2D, 0, 0, 0, 0,
tex[GL_WRITE], GL_TEXTURE_2D, 0, 0, 0, 0,
width, height, 1));
EGLSyncKHR eglSyncForGL, eglSyncForCuda;
EGLBoolean egl_status = EGL_TRUE;
EGLAttribKHR eglattrib[] = {EGL_CUDA_EVENT_HANDLE_NV,
(EGLAttrib)timingDisabledEvent, EGL_NONE};
CUevent cudaEGLSyncEvent;
eglSyncForGL = eglCreateSyncKHR(dpy, EGL_SYNC_FENCE_KHR, NULL);
if (eglSyncForGL == EGL_NO_SYNC_KHR) {
printf(" EGL Sync creation failed\n");
cleanup(FAILURE);
}
status = cuEventCreateFromEGLSync(&cudaEGLSyncEvent, eglSyncForGL,
CU_EVENT_DEFAULT);
if (status != CUDA_SUCCESS) {
printf("CUDA event creation from EGLSync failed\n");
cleanup(FAILURE);
}
// We wait from CUDA in GPU for GL-EGL operation completion
status = cuStreamWaitEvent(stream, cudaEGLSyncEvent, 0);
if (status != CUDA_SUCCESS) {
printf("Stream wait for event created from EGLSync failed\n");
cleanup(FAILURE);
}
egl_status = eglDestroySyncKHR(dpy, eglSyncForGL);
if (egl_status != EGL_TRUE) {
printf("EGL sync object destruction failed\n");
cleanup(FAILURE);
}
newData++;
expectedData++;
// Verifies the values in readSurface which is copied by
// glCopyImageSubData() And writes value of newData into writeSurface
verify_and_update_kernel<<<(width * height) / 256, 256, 0, stream>>>(
writeSurface, readSurface, expectedData, newData, width, height);
status = cuEventDestroy(cudaEGLSyncEvent);
if (status != CUDA_SUCCESS) {
printf("Event Destroy failed\n");
cleanup(FAILURE);
}
status = cuEventRecord(timingDisabledEvent, stream);
if (status != CUDA_SUCCESS) {
printf("Event Record failed\n");
cleanup(FAILURE);
}
// creating an EGL sync object linked to a CUDA event object
eglSyncForCuda = eglCreateSync64KHR(dpy, EGL_SYNC_CUDA_EVENT_NV, eglattrib);
// We wait from EGL for CUDA operation completion
egl_status = eglWaitSyncKHR(dpy, eglSyncForCuda, 0);
if (egl_status != EGL_TRUE) {
printf("eglWaitSyncKHR failed\n");
cleanup(FAILURE);
}
egl_status = eglDestroySyncKHR(dpy, eglSyncForCuda);
if (egl_status != EGL_TRUE) {
printf("EGL sync object destruction failed\n");
cleanup(FAILURE);
}
}
err = cudaGetValueMismatch();
if (err != cudaSuccess) {
printf("Value mismatch seen when using GPU sync\n");
cleanup(FAILURE);
}
// Clean up CUDA writeResource
status = cuGraphicsUnregisterResource(writeResource);
if (status != CUDA_SUCCESS) {
printf("Failed to unregister %d", status);
cleanup(FAILURE);
} else {
printf("Unregistered writeResource. \n");
}
// Clean up CUDA readResource
status = cuGraphicsUnregisterResource(readResource);
if (status != CUDA_SUCCESS) {
printf("Failed to unregister %d", status);
cleanup(FAILURE);
} else {
printf("Unregistered readResource. \n");
}
}
// Verifies the values in readSurface whether they are expected ones
// And writes value of newData into writeSurface
__global__ void verify_and_update_kernel(CUsurfObject write, CUsurfObject read,
char expected, char newval, int width,
int height) {
unsigned int x = blockDim.x * blockIdx.x + threadIdx.x;
unsigned int y = blockDim.y * blockIdx.y + threadIdx.y;
if (x < width && y < height) {
uchar4 check;
surf2Dread(&check, read, x * 4, y);
if (check.x != expected || check.y != expected || check.z != expected ||
check.w != expected) {
printf(
"Mismatch found in values read[0]= %u read[1]= %u read[2]= %u "
"read[3]= %u expected is %u\n",
check.x, check.y, check.z, check.w, expected);
numErrors++;
return;
}
uchar4 data = make_uchar4(newval, newval, newval, newval);
surf2Dwrite(data, write, x * 4, y);
}
}
__global__ void getNumErrors(int *numErr) { *numErr = numErrors; }
extern "C" cudaError_t cudaGetValueMismatch() {
int numErr_h;
int *numErr_d = NULL;
cudaError_t err = cudaSuccess;
err = cudaMalloc(&numErr_d, sizeof(int));
if (err != cudaSuccess) {
printf("Cuda Main: cudaMemcpy failed with %s\n", cudaGetErrorString(err));
cudaFree(numErr_d);
return err;
}
getNumErrors<<<1, 1>>>(numErr_d);
err = cudaDeviceSynchronize();
if (err != cudaSuccess) {
printf("Cuda Main: cudaDeviceSynchronize failed with %s\n",
cudaGetErrorString(err));
}
err = cudaMemcpy(&numErr_h, numErr_d, sizeof(int), cudaMemcpyDeviceToHost);
if (err != cudaSuccess) {
printf("Cuda Main: cudaMemcpy failed with %s\n", cudaGetErrorString(err));
cudaFree(numErr_d);
return err;
}
err = cudaFree(numErr_d);
if (err != cudaSuccess) {
printf("Cuda Main: cudaFree failed with %s\n", cudaGetErrorString(err));
return err;
}
if (numErr_h > 0) {
return cudaErrorUnknown;
}
return cudaSuccess;
}
// Clean up state and exit. If status is SUCCESS, regression success is printed
// to stdout. This will happen if the glut timer is triggered. If status is
// anything else, the regression failure message is printed.
void cleanup(int status) {
GLenum glErr = GL_NO_ERROR;
cudaError cudaErr = cudaSuccess;
int exitStatus = status;
// Clean up GL
if (*tex) {
GL_SAFE_CALL_NO_CLEANUP(glDeleteTextures(2, tex), glErr);
}
// Print test status and exit
if (glErr != GL_NO_ERROR || cudaErr != cudaSuccess) exitStatus = FAILURE;
printStatus(exitStatus);
cleanExit = 1;
graphics_close_window();
if (exitStatus == FAILURE) exit(EXIT_FAILURE);
if (exitStatus == WAIVED) exit(EXIT_WAIVED);
exit(0);
}
void exitHandler(void) {
if (!cleanExit) {
printf("&&&& EGLSync_CUDAEvent_Interop unexpected failure \n");
printStatus(FAILURE);
}
}
// Print test success or fail for regression testing
void printStatus(int status) {
switch (status) {
case SUCCESS:
printf("&&&& EGLSync_CUDAEvent_Interop PASSED\n");
break;
case WAIVED:
printf("&&&& EGLSync_CUDAEvent_Interop WAIVED\n");
break;
default:
printf("&&&& EGLSync_CUDAEvent_Interop FAILED\n");
break;
}
fflush(stdout);
}

View File

@@ -0,0 +1,442 @@
################################################################################
# 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.
#
################################################################################
#
# Makefile project only supported on Mac OS X and Linux Platforms)
#
################################################################################
# Location of the CUDA Toolkit
CUDA_PATH ?= /usr/local/cuda
##############################
# start deprecated interface #
##############################
ifeq ($(x86_64),1)
$(info WARNING - x86_64 variable has been deprecated)
$(info WARNING - please use TARGET_ARCH=x86_64 instead)
TARGET_ARCH ?= x86_64
endif
ifeq ($(ARMv7),1)
$(info WARNING - ARMv7 variable has been deprecated)
$(info WARNING - please use TARGET_ARCH=armv7l instead)
TARGET_ARCH ?= armv7l
endif
ifeq ($(aarch64),1)
$(info WARNING - aarch64 variable has been deprecated)
$(info WARNING - please use TARGET_ARCH=aarch64 instead)
TARGET_ARCH ?= aarch64
endif
ifeq ($(ppc64le),1)
$(info WARNING - ppc64le variable has been deprecated)
$(info WARNING - please use TARGET_ARCH=ppc64le instead)
TARGET_ARCH ?= ppc64le
endif
ifneq ($(GCC),)
$(info WARNING - GCC variable has been deprecated)
$(info WARNING - please use HOST_COMPILER=$(GCC) instead)
HOST_COMPILER ?= $(GCC)
endif
ifneq ($(abi),)
$(error ERROR - abi variable has been removed)
endif
############################
# end deprecated interface #
############################
# architecture
HOST_ARCH := $(shell uname -m)
TARGET_ARCH ?= $(HOST_ARCH)
ifneq (,$(filter $(TARGET_ARCH),x86_64 aarch64 sbsa ppc64le armv7l))
ifneq ($(TARGET_ARCH),$(HOST_ARCH))
ifneq (,$(filter $(TARGET_ARCH),x86_64 aarch64 sbsa ppc64le))
TARGET_SIZE := 64
else ifneq (,$(filter $(TARGET_ARCH),armv7l))
TARGET_SIZE := 32
endif
else
TARGET_SIZE := $(shell getconf LONG_BIT)
endif
else
$(error ERROR - unsupported value $(TARGET_ARCH) for TARGET_ARCH!)
endif
# sbsa and aarch64 systems look similar. Need to differentiate them at host level for now.
ifeq ($(HOST_ARCH),aarch64)
ifeq ($(CUDA_PATH)/targets/sbsa-linux,$(shell ls -1d $(CUDA_PATH)/targets/sbsa-linux 2>/dev/null))
HOST_ARCH := sbsa
TARGET_ARCH := sbsa
endif
endif
ifneq ($(TARGET_ARCH),$(HOST_ARCH))
ifeq (,$(filter $(HOST_ARCH)-$(TARGET_ARCH),aarch64-armv7l x86_64-armv7l x86_64-aarch64 x86_64-sbsa x86_64-ppc64le))
$(error ERROR - cross compiling from $(HOST_ARCH) to $(TARGET_ARCH) is not supported!)
endif
endif
# When on native aarch64 system with userspace of 32-bit, change TARGET_ARCH to armv7l
ifeq ($(HOST_ARCH)-$(TARGET_ARCH)-$(TARGET_SIZE),aarch64-aarch64-32)
TARGET_ARCH = armv7l
endif
# operating system
HOST_OS := $(shell uname -s 2>/dev/null | tr "[:upper:]" "[:lower:]")
TARGET_OS ?= $(HOST_OS)
ifeq (,$(filter $(TARGET_OS),linux darwin qnx android))
$(error ERROR - unsupported value $(TARGET_OS) for TARGET_OS!)
endif
# host compiler
ifeq ($(TARGET_OS),darwin)
ifeq ($(shell expr `xcodebuild -version | grep -i xcode | awk '{print $$2}' | cut -d'.' -f1` \>= 5),1)
HOST_COMPILER ?= clang++
endif
else ifneq ($(TARGET_ARCH),$(HOST_ARCH))
ifeq ($(HOST_ARCH)-$(TARGET_ARCH),x86_64-armv7l)
ifeq ($(TARGET_OS),linux)
HOST_COMPILER ?= arm-linux-gnueabihf-g++
else ifeq ($(TARGET_OS),qnx)
ifeq ($(QNX_HOST),)
$(error ERROR - QNX_HOST must be passed to the QNX host toolchain)
endif
ifeq ($(QNX_TARGET),)
$(error ERROR - QNX_TARGET must be passed to the QNX target toolchain)
endif
export QNX_HOST
export QNX_TARGET
HOST_COMPILER ?= $(QNX_HOST)/usr/bin/arm-unknown-nto-qnx6.6.0eabi-g++
else ifeq ($(TARGET_OS),android)
HOST_COMPILER ?= arm-linux-androideabi-g++
endif
else ifeq ($(TARGET_ARCH),aarch64)
ifeq ($(TARGET_OS), linux)
HOST_COMPILER ?= aarch64-linux-gnu-g++
else ifeq ($(TARGET_OS),qnx)
ifeq ($(QNX_HOST),)
$(error ERROR - QNX_HOST must be passed to the QNX host toolchain)
endif
ifeq ($(QNX_TARGET),)
$(error ERROR - QNX_TARGET must be passed to the QNX target toolchain)
endif
export QNX_HOST
export QNX_TARGET
HOST_COMPILER ?= $(QNX_HOST)/usr/bin/q++
else ifeq ($(TARGET_OS), android)
HOST_COMPILER ?= aarch64-linux-android-clang++
endif
else ifeq ($(TARGET_ARCH),sbsa)
HOST_COMPILER ?= aarch64-linux-gnu-g++
else ifeq ($(TARGET_ARCH),ppc64le)
HOST_COMPILER ?= powerpc64le-linux-gnu-g++
endif
endif
HOST_COMPILER ?= g++
NVCC := $(CUDA_PATH)/bin/nvcc -ccbin $(HOST_COMPILER)
# internal flags
NVCCFLAGS := -m${TARGET_SIZE}
CCFLAGS :=
LDFLAGS :=
# build flags
ifeq ($(TARGET_OS),darwin)
LDFLAGS += -rpath $(CUDA_PATH)/lib
CCFLAGS += -arch $(HOST_ARCH)
else ifeq ($(HOST_ARCH)-$(TARGET_ARCH)-$(TARGET_OS),x86_64-armv7l-linux)
LDFLAGS += --dynamic-linker=/lib/ld-linux-armhf.so.3
CCFLAGS += -mfloat-abi=hard
else ifeq ($(TARGET_OS),android)
LDFLAGS += -pie
CCFLAGS += -fpie -fpic -fexceptions
endif
ifneq ($(TARGET_ARCH),$(HOST_ARCH))
ifeq ($(TARGET_ARCH)-$(TARGET_OS),armv7l-linux)
ifneq ($(TARGET_FS),)
GCCVERSIONLTEQ46 := $(shell expr `$(HOST_COMPILER) -dumpversion` \<= 4.6)
ifeq ($(GCCVERSIONLTEQ46),1)
CCFLAGS += --sysroot=$(TARGET_FS)
endif
LDFLAGS += --sysroot=$(TARGET_FS)
LDFLAGS += -rpath-link=$(TARGET_FS)/lib
LDFLAGS += -rpath-link=$(TARGET_FS)/usr/lib
LDFLAGS += -rpath-link=$(TARGET_FS)/usr/lib/arm-linux-gnueabihf
endif
endif
ifeq ($(TARGET_ARCH)-$(TARGET_OS),aarch64-linux)
ifneq ($(TARGET_FS),)
GCCVERSIONLTEQ46 := $(shell expr `$(HOST_COMPILER) -dumpversion` \<= 4.6)
ifeq ($(GCCVERSIONLTEQ46),1)
CCFLAGS += --sysroot=$(TARGET_FS)
endif
LDFLAGS += --sysroot=$(TARGET_FS)
LDFLAGS += -rpath-link=$(TARGET_FS)/lib -L$(TARGET_FS)/lib
LDFLAGS += -rpath-link=$(TARGET_FS)/lib/aarch64-linux-gnu -L$(TARGET_FS)/lib/aarch64-linux-gnu
LDFLAGS += -rpath-link=$(TARGET_FS)/usr/lib -L$(TARGET_FS)/usr/lib
LDFLAGS += -rpath-link=$(TARGET_FS)/usr/lib/aarch64-linux-gnu -L$(TARGET_FS)/usr/lib/aarch64-linux-gnu
LDFLAGS += --unresolved-symbols=ignore-in-shared-libs
CCFLAGS += -isystem=$(TARGET_FS)/usr/include -I$(TARGET_FS)/usr/include -I$(TARGET_FS)/usr/include/libdrm
CCFLAGS += -isystem=$(TARGET_FS)/usr/include/aarch64-linux-gnu -I$(TARGET_FS)/usr/include/aarch64-linux-gnu
endif
endif
ifeq ($(TARGET_ARCH)-$(TARGET_OS),aarch64-qnx)
NVCCFLAGS += -D_QNX_SOURCE
NVCCFLAGS += --qpp-config 8.3.0,gcc_ntoaarch64le
CCFLAGS += -DWIN_INTERFACE_CUSTOM -I/usr/include/aarch64-qnx-gnu
LDFLAGS += -lsocket
LDFLAGS += -L/usr/lib/aarch64-qnx-gnu
CCFLAGS += "-Wl\,-rpath-link\,/usr/lib/aarch64-qnx-gnu"
ifdef TARGET_OVERRIDE
LDFLAGS += -lslog2
endif
ifneq ($(TARGET_FS),)
LDFLAGS += -L$(TARGET_FS)/usr/lib
CCFLAGS += "-Wl\,-rpath-link\,$(TARGET_FS)/usr/lib"
LDFLAGS += -L$(TARGET_FS)/usr/libnvidia
CCFLAGS += "-Wl\,-rpath-link\,$(TARGET_FS)/usr/libnvidia"
CCFLAGS += -I$(TARGET_FS)/../include
endif
endif
endif
ifdef TARGET_OVERRIDE # cuda toolkit targets override
NVCCFLAGS += -target-dir $(TARGET_OVERRIDE)
endif
# Install directory of different arch
CUDA_INSTALL_TARGET_DIR :=
ifeq ($(TARGET_ARCH)-$(TARGET_OS),armv7l-linux)
CUDA_INSTALL_TARGET_DIR = targets/armv7-linux-gnueabihf/
else ifeq ($(TARGET_ARCH)-$(TARGET_OS),aarch64-linux)
CUDA_INSTALL_TARGET_DIR = targets/aarch64-linux/
else ifeq ($(TARGET_ARCH)-$(TARGET_OS),sbsa-linux)
CUDA_INSTALL_TARGET_DIR = targets/sbsa-linux/
else ifeq ($(TARGET_ARCH)-$(TARGET_OS),armv7l-android)
CUDA_INSTALL_TARGET_DIR = targets/armv7-linux-androideabi/
else ifeq ($(TARGET_ARCH)-$(TARGET_OS),aarch64-android)
CUDA_INSTALL_TARGET_DIR = targets/aarch64-linux-androideabi/
else ifeq ($(TARGET_ARCH)-$(TARGET_OS),armv7l-qnx)
CUDA_INSTALL_TARGET_DIR = targets/ARMv7-linux-QNX/
else ifeq ($(TARGET_ARCH)-$(TARGET_OS),aarch64-qnx)
CUDA_INSTALL_TARGET_DIR = targets/aarch64-qnx/
else ifeq ($(TARGET_ARCH),ppc64le)
CUDA_INSTALL_TARGET_DIR = targets/ppc64le-linux/
endif
# Debug build flags
ifeq ($(dbg),1)
NVCCFLAGS += -g -G
BUILD_TYPE := debug
else
BUILD_TYPE := release
endif
ALL_CCFLAGS :=
ALL_CCFLAGS += $(NVCCFLAGS)
ALL_CCFLAGS += $(EXTRA_NVCCFLAGS)
ALL_CCFLAGS += $(addprefix -Xcompiler ,$(CCFLAGS))
ALL_CCFLAGS += $(addprefix -Xcompiler ,$(EXTRA_CCFLAGS))
UBUNTU = $(shell lsb_release -i -s 2>/dev/null | grep -i ubuntu)
SAMPLE_ENABLED := 1
# This sample is not supported on Linux x86_64
ifeq ($(TARGET_OS),linux)
ifeq ($(TARGET_ARCH),x86_64)
$(info >>> WARNING - EGLSync_CUDAEvent_Interop is not supported on Linux x86_64 - waiving sample <<<)
SAMPLE_ENABLED := 0
endif
endif
# This sample is not supported on Mac OSX
ifeq ($(TARGET_OS),darwin)
$(info >>> WARNING - EGLSync_CUDAEvent_Interop is not supported on Mac OSX - waiving sample <<<)
SAMPLE_ENABLED := 0
endif
# This sample is not supported on sbsa
ifeq ($(TARGET_ARCH),sbsa)
$(info >>> WARNING - EGLSync_CUDAEvent_Interop is not supported on sbsa - waiving sample <<<)
SAMPLE_ENABLED := 0
endif
# This sample is not supported on android
ifeq ($(TARGET_OS),android)
$(info >>> WARNING - EGLSync_CUDAEvent_Interop is not supported on android - waiving sample <<<)
SAMPLE_ENABLED := 0
endif
# This sample is not supported on QNX
ifeq ($(TARGET_OS),qnx)
$(info >>> WARNING - EGLSync_CUDAEvent_Interop is not supported on QNX - waiving sample <<<)
SAMPLE_ENABLED := 0
endif
ALL_LDFLAGS :=
ALL_LDFLAGS += $(ALL_CCFLAGS)
ALL_LDFLAGS += $(addprefix -Xlinker ,$(LDFLAGS))
ALL_LDFLAGS += $(addprefix -Xlinker ,$(EXTRA_LDFLAGS))
# Common includes and paths for CUDA
INCLUDES := -I../../../Common
LIBRARIES :=
################################################################################
# Makefile include to help find EGL Libraries
include ./findegl.mk
# EGL specific libraries
ifneq ($(TARGET_OS),darwin)
LIBRARIES += -lEGL
endif
# Gencode arguments
ifeq ($(TARGET_ARCH),$(filter $(TARGET_ARCH),armv7l aarch64 sbsa))
SMS ?= 53 61 70 72 75 80 86 87
else
SMS ?= 35 37 50 52 60 61 70 75 80 86
endif
ifeq ($(SMS),)
$(info >>> WARNING - no SM architectures have been specified - waiving sample <<<)
SAMPLE_ENABLED := 0
endif
ifeq ($(GENCODE_FLAGS),)
# Generate SASS code for each SM architecture listed in $(SMS)
$(foreach sm,$(SMS),$(eval GENCODE_FLAGS += -gencode arch=compute_$(sm),code=sm_$(sm)))
# Generate PTX code from the highest SM architecture in $(SMS) to guarantee forward-compatibility
HIGHEST_SM := $(lastword $(sort $(SMS)))
ifneq ($(HIGHEST_SM),)
GENCODE_FLAGS += -gencode arch=compute_$(HIGHEST_SM),code=compute_$(HIGHEST_SM)
endif
endif
ifeq ($(TARGET_OS),darwin)
ALL_LDFLAGS += -Xcompiler -F/Library/Frameworks -Xlinker -framework -Xlinker CUDA
else
ifeq ($(TARGET_ARCH),x86_64)
CUDA_SEARCH_PATH ?= $(CUDA_PATH)/lib64/stubs
CUDA_SEARCH_PATH += $(CUDA_PATH)/lib/stubs
CUDA_SEARCH_PATH += $(CUDA_PATH)/targets/x86_64-linux/lib/stubs
endif
ifeq ($(TARGET_ARCH)-$(TARGET_OS),armv7l-linux)
CUDA_SEARCH_PATH ?= $(CUDA_PATH)/targets/armv7-linux-gnueabihf/lib/stubs
endif
ifeq ($(TARGET_ARCH)-$(TARGET_OS),aarch64-linux)
CUDA_SEARCH_PATH ?= $(CUDA_PATH)/targets/aarch64-linux/lib/stubs
endif
ifeq ($(TARGET_ARCH)-$(TARGET_OS),sbsa-linux)
CUDA_SEARCH_PATH ?= $(CUDA_PATH)/targets/sbsa-linux/lib/stubs
endif
ifeq ($(TARGET_ARCH)-$(TARGET_OS),armv7l-android)
CUDA_SEARCH_PATH ?= $(CUDA_PATH)/targets/armv7-linux-androideabi/lib/stubs
endif
ifeq ($(TARGET_ARCH)-$(TARGET_OS),aarch64-android)
CUDA_SEARCH_PATH ?= $(CUDA_PATH)/targets/aarch64-linux-androideabi/lib/stubs
endif
ifeq ($(TARGET_ARCH)-$(TARGET_OS),armv7l-qnx)
CUDA_SEARCH_PATH ?= $(CUDA_PATH)/targets/ARMv7-linux-QNX/lib/stubs
endif
ifeq ($(TARGET_ARCH)-$(TARGET_OS),aarch64-qnx)
CUDA_SEARCH_PATH ?= $(CUDA_PATH)/targets/aarch64-qnx/lib/stubs
ifdef TARGET_OVERRIDE
CUDA_SEARCH_PATH := $(CUDA_PATH)/targets/$(TARGET_OVERRIDE)/lib/stubs
endif
endif
ifeq ($(TARGET_ARCH),ppc64le)
CUDA_SEARCH_PATH ?= $(CUDA_PATH)/targets/ppc64le-linux/lib/stubs
endif
ifeq ($(HOST_ARCH),ppc64le)
CUDA_SEARCH_PATH += $(CUDA_PATH)/lib64/stubs
endif
CUDALIB ?= $(shell find -L $(CUDA_SEARCH_PATH) -maxdepth 1 -name libcuda.so 2> /dev/null)
ifeq ("$(CUDALIB)","")
$(info >>> WARNING - libcuda.so not found, CUDA Driver is not installed. Please re-install the driver. <<<)
SAMPLE_ENABLED := 0
else
CUDALIB := $(shell echo $(CUDALIB) | sed "s/ .*//" | sed "s/\/libcuda.so//" )
LIBRARIES += -L$(CUDALIB) -lcuda
endif
endif
ALL_CCFLAGS += --threads 0 --std=c++11
LIBRARIES += -lX11 -lGLESv2
ifeq ($(SAMPLE_ENABLED),0)
EXEC ?= @echo "[@]"
endif
################################################################################
# Target rules
all: build
build: EGLSync_CUDAEvent_Interop
check.deps:
ifeq ($(SAMPLE_ENABLED),0)
@echo "Sample will be waived due to the above missing dependencies"
else
@echo "Sample is ready - all dependencies have been met"
endif
EGLSync_CUDAEvent_Interop.o:EGLSync_CUDAEvent_Interop.cu
$(EXEC) $(NVCC) $(INCLUDES) $(ALL_CCFLAGS) $(GENCODE_FLAGS) -o $@ -c $<
EGLSync_CUDAEvent_Interop: EGLSync_CUDAEvent_Interop.o
$(EXEC) $(NVCC) $(ALL_LDFLAGS) $(GENCODE_FLAGS) -o $@ $+ $(LIBRARIES)
$(EXEC) mkdir -p ../../../bin/$(TARGET_ARCH)/$(TARGET_OS)/$(BUILD_TYPE)
$(EXEC) cp $@ ../../../bin/$(TARGET_ARCH)/$(TARGET_OS)/$(BUILD_TYPE)
run: build
$(EXEC) ./EGLSync_CUDAEvent_Interop
testrun: build
clean:
rm -f EGLSync_CUDAEvent_Interop EGLSync_CUDAEvent_Interop.o
rm -rf ../../../bin/$(TARGET_ARCH)/$(TARGET_OS)/$(BUILD_TYPE)/EGLSync_CUDAEvent_Interop
clobber: clean

View File

@@ -0,0 +1,85 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE entry SYSTEM "SamplesInfo.dtd">
<entry>
<name>EGLSync_CUDAEvent_Interop</name>
<cuda_api_list>
<driver>cuGraphicsEGLRegisterImage</driver>
<driver>cuStreamCreate</driver>
<driver>cuEventCreate</driver>
<driver>cuCtxCreate</driver>
<driver>cuGraphicsSubResourceGetMappedArray</driver>
<driver>cuGraphicsUnregisterResource</driver>
<driver>cuCtxSynchronize</driver>
<driver>cuEventCreateFromEGLSync</driver>
<driver>cuEventDestroy</driver>
<driver>cuStreamWaitEvent</driver>
<driver>cuCtxPushCurrent</driver>
<driver>cuSurfObjectCreate</driver>
<driver>cuInit</driver>
<driver>cuEventRecord</driver>
<driver>cuDeviceGetAttribute</driver>
<toolkit>cudaFree</toolkit>
<toolkit>cudaDeviceSynchronize</toolkit>
<toolkit>cudaGetValueMismatch</toolkit>
<toolkit>cudaMalloc</toolkit>
<toolkit>cudaMemcpy</toolkit>
<toolkit>cudaGetErrorString</toolkit>
</cuda_api_list>
<description><![CDATA[Demonstrates interoperability between CUDA Event and EGL Sync/EGL Image using which one can achieve synchronization on GPU itself for GL-EGL-CUDA operations instead of blocking CPU for synchronization.]]></description>
<devicecompilation>whole</devicecompilation>
<includepaths>
<path>./</path>
<path>../</path>
<path>../../../Common</path>
</includepaths>
<keyconcepts>
<concept level="basic">EGLSync-CUDAEvent Interop</concept>
<concept level="basic">EGLImage-CUDA Interop</concept>
</keyconcepts>
<keywords>
<keyword>EGL Sync</keyword>
</keywords>
<libraries>
<library os="linux">cuda</library>
<library framework="true" os="macosx">CUDA</library>
<library>X11</library>
<library>GLESv2</library>
</libraries>
<librarypaths>
</librarypaths>
<nsight_eclipse>true</nsight_eclipse>
<primary_file>EGLSync_CUDAEvent_Interop.cu</primary_file>
<required_dependencies>
<dependency>EGL</dependency>
<dependency>EGLSync</dependency>
<dependency>X11</dependency>
<dependency>GLES</dependency>
</required_dependencies>
<scopes>
<scope>1:CUDA Basic Topics</scope>
<scope>2:Graphics Interop</scope>
</scopes>
<sm-arch>sm35</sm-arch>
<sm-arch>sm37</sm-arch>
<sm-arch>sm50</sm-arch>
<sm-arch>sm52</sm-arch>
<sm-arch>sm53</sm-arch>
<sm-arch>sm60</sm-arch>
<sm-arch>sm61</sm-arch>
<sm-arch>sm70</sm-arch>
<sm-arch>sm72</sm-arch>
<sm-arch>sm75</sm-arch>
<sm-arch>sm80</sm-arch>
<sm-arch>sm86</sm-arch>
<sm-arch>sm87</sm-arch>
<supported_envs>
<env>
<arch>arm</arch>
</env>
</supported_envs>
<supported_sm_architectures>
<include>all</include>
</supported_sm_architectures>
<title>EGLSync CUDA Event Interop</title>
<type>exe</type>
</entry>

View File

@@ -0,0 +1,67 @@
# EGLSync_CUDAEvent_Interop - EGLSync CUDA Event Interop
## Description
Demonstrates interoperability between CUDA Event and EGL Sync/EGL Image using which one can achieve synchronization on GPU itself for GL-EGL-CUDA operations instead of blocking CPU for synchronization.
## Key Concepts
EGLSync-CUDAEvent Interop, EGLImage-CUDA Interop
## Supported SM Architectures
[SM 3.5 ](https://developer.nvidia.com/cuda-gpus) [SM 3.7 ](https://developer.nvidia.com/cuda-gpus) [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)
## Supported OSes
Linux
## Supported CPU Architecture
armv7l
## CUDA APIs involved
### [CUDA Driver API](http://docs.nvidia.com/cuda/cuda-driver-api/index.html)
cuGraphicsEGLRegisterImage, cuStreamCreate, cuEventCreate, cuCtxCreate, cuGraphicsSubResourceGetMappedArray, cuGraphicsUnregisterResource, cuCtxSynchronize, cuEventCreateFromEGLSync, cuEventDestroy, cuStreamWaitEvent, cuCtxPushCurrent, cuSurfObjectCreate, cuInit, cuEventRecord, cuDeviceGetAttribute
### [CUDA Runtime API](http://docs.nvidia.com/cuda/cuda-runtime-api/index.html)
cudaFree, cudaDeviceSynchronize, cudaGetValueMismatch, cudaMalloc, cudaMemcpy, cudaGetErrorString
## Dependencies needed to build/run
[EGL](../../README.md#egl), [EGLSync](../../README.md#eglsync), [X11](../../README.md#x11), [GLES](../../README.md#gles)
## Prerequisites
Download and install the [CUDA Toolkit 11.6](https://developer.nvidia.com/cuda-downloads) for your corresponding platform.
Make sure the dependencies mentioned in [Dependencies]() section above are installed.
## Build and Run
### Linux
The Linux samples are built using makefiles. To use the makefiles, change the current directory to the sample directory you wish to build, and run make:
```
$ cd <sample_dir>
$ make
```
The samples makefiles can take advantage of certain options:
* **TARGET_ARCH=<arch>** - cross-compile targeting a specific architecture. Allowed architectures are armv7l.
By default, TARGET_ARCH is set to HOST_ARCH. On a x86_64 machine, not setting TARGET_ARCH is the equivalent of setting TARGET_ARCH=x86_64.<br/>
`$ make TARGET_ARCH=armv7l` <br/>
See [here](http://docs.nvidia.com/cuda/cuda-samples/index.html#cross-samples) for more details.
* **dbg=1** - build with debug symbols
```
$ make dbg=1
```
* **SMS="A B ..."** - override the SM architectures for which the sample will be built, where `"A B ..."` is a space-delimited list of SM architectures. For example, to generate SASS for SM 50 and SM 60, use `SMS="50 60"`.
```
$ make SMS="50 60"
```
* **HOST_COMPILER=<host_compiler>** - override the default g++ host compiler. See the [Linux Installation Guide](http://docs.nvidia.com/cuda/cuda-installation-guide-linux/index.html#system-requirements) for a list of supported host compilers.
```
$ make HOST_COMPILER=g++
```
## References (for more details)

View File

@@ -0,0 +1,71 @@
/* 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.
*/
//
// DESCRIPTION: Common EGL functions header file
//
#ifndef _EGL_COMMON_H_
#define _EGL_COMMON_H_
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <signal.h>
#include "cuda.h"
#include "cudaEGL.h"
EGLImageKHR eglImage;
#define EXTENSION_LIST(T) \
T(PFNEGLCREATEIMAGEKHRPROC, eglCreateImageKHR) \
T(PFNEGLDESTROYIMAGEKHRPROC, eglDestroyImageKHR) \
T(PFNEGLCREATESYNCKHRPROC, eglCreateSyncKHR) \
T(PFNEGLDESTROYSYNCKHRPROC, eglDestroySyncKHR) \
T(PFNEGLCLIENTWAITSYNCKHRPROC, eglClientWaitSyncKHR) \
T(PFNEGLGETSYNCATTRIBKHRPROC, eglGetSyncAttribKHR) \
T(PFNEGLCREATESYNC64KHRPROC, eglCreateSync64KHR) \
T(PFNEGLWAITSYNCKHRPROC, eglWaitSyncKHR)
#define eglCreateImageKHR my_eglCreateImageKHR
#define eglDestroyImageKHR my_eglDestroyImageKHR
#define eglCreateSyncKHR my_eglCreateSyncKHR
#define eglDestroySyncKHR my_eglDestroySyncKHR
#define eglClientWaitSyncKHR my_eglClientWaitSyncKHR
#define eglGetSyncAttribKHR my_eglGetSyncAttribKHR
#define eglCreateSync64KHR my_eglCreateSync64KHR
#define eglWaitSyncKHR my_eglWaitSyncKHR
#define EXTLST_DECL(tx, x) tx my_##x = NULL;
#define EXTLST_EXTERN(tx, x) extern tx my_##x;
#define EXTLST_ENTRY(tx, x) {(extlst_fnptr_t *)&my_##x, #x},
int eglSetupExtensions(void);
#endif

View File

@@ -0,0 +1,160 @@
################################################################################
# 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.
#
################################################################################
#
# findegl.mk is used to find the necessary EGL Libraries for specific distributions
# this is supported on Linux
#
################################################################################
# Determine OS platform and unix distribution
ifeq ("$(TARGET_OS)","linux")
# first search lsb_release
DISTRO = $(shell lsb_release -i -s 2>/dev/null | tr "[:upper:]" "[:lower:]")
ifeq ("$(DISTRO)","")
# second search and parse /etc/issue
DISTRO = $(shell more /etc/issue | awk '{print $$1}' | sed '1!d' | sed -e "/^$$/d" 2>/dev/null | tr "[:upper:]" "[:lower:]")
# ensure data from /etc/issue is valid
ifeq (,$(filter $(DISTRO),ubuntu fedora red rhel centos suse))
DISTRO =
endif
ifeq ("$(DISTRO)","")
# third, we can search in /etc/os-release or /etc/{distro}-release
DISTRO = $(shell awk '/ID/' /etc/*-release | sed 's/ID=//' | grep -v "VERSION" | grep -v "ID" | grep -v "DISTRIB")
endif
endif
endif
ifeq ("$(TARGET_OS)","linux")
# $(info) >> findegl.mk -> LINUX path <<<)
# Each set of Linux Distros have different paths for where to find their OpenGL libraries reside
UBUNTU = $(shell echo $(DISTRO) | grep -i ubuntu >/dev/null 2>&1; echo $$?)
FEDORA = $(shell echo $(DISTRO) | grep -i fedora >/dev/null 2>&1; echo $$?)
RHEL = $(shell echo $(DISTRO) | grep -i 'red\|rhel' >/dev/null 2>&1; echo $$?)
CENTOS = $(shell echo $(DISTRO) | grep -i centos >/dev/null 2>&1; echo $$?)
SUSE = $(shell echo $(DISTRO) | grep -i 'suse\|sles' >/dev/null 2>&1; echo $$?)
ifeq ("$(UBUNTU)","0")
ifeq ($(HOST_ARCH)-$(TARGET_ARCH),x86_64-armv7l)
GLPATH := /usr/arm-linux-gnueabihf/lib
GLLINK := -L/usr/arm-linux-gnueabihf/lib
ifneq ($(TARGET_FS),)
GLPATH += $(TARGET_FS)/usr/lib/arm-linux-gnueabihf
GLLINK += -L$(TARGET_FS)/usr/lib/arm-linux-gnueabihf
endif
else ifeq ($(HOST_ARCH)-$(TARGET_ARCH),x86_64-aarch64)
GLPATH := /usr/aarch64-linux-gnu/lib
GLLINK := -L/usr/aarch64-linux-gnu/lib
ifneq ($(TARGET_FS),)
GLPATH += $(TARGET_FS)/usr/lib
GLPATH += $(TARGET_FS)/usr/lib/aarch64-linux-gnu
GLLINK += -L$(TARGET_FS)/usr/lib/aarch64-linux-gnu
endif
else
UBUNTU_PKG_NAME = $(shell which dpkg >/dev/null 2>&1 && dpkg -l 'nvidia-*' | grep '^ii' | awk '{print $$2}' | head -1)
ifneq ("$(UBUNTU_PKG_NAME)","")
GLPATH ?= /usr/lib/$(UBUNTU_PKG_NAME)
GLLINK ?= -L/usr/lib/$(UBUNTU_PKG_NAME)
endif
DFLT_PATH ?= /usr/lib
endif
endif
ifeq ("$(SUSE)","0")
GLPATH ?= /usr/X11R6/lib64
GLLINK ?= -L/usr/X11R6/lib64
DFLT_PATH ?= /usr/lib64
endif
ifeq ("$(FEDORA)","0")
GLPATH ?= /usr/lib64/nvidia
GLLINK ?= -L/usr/lib64/nvidia
DFLT_PATH ?= /usr/lib64
endif
ifeq ("$(RHEL)","0")
GLPATH ?= /usr/lib64/nvidia
GLLINK ?= -L/usr/lib64/nvidia
DFLT_PATH ?= /usr/lib64
endif
ifeq ("$(CENTOS)","0")
GLPATH ?= /usr/lib64/nvidia
GLLINK ?= -L/usr/lib64/nvidia
DFLT_PATH ?= /usr/lib64
endif
EGLLIB := $(shell find -L $(GLPATH) $(DFLT_PATH) -name libEGL.so -print 2>/dev/null)
ifeq ("$(EGLLIB)","")
$(info >>> WARNING - libEGL.so not found, please install libEGL.so <<<)
SAMPLE_ENABLED := 0
endif
HEADER_SEARCH_PATH ?= $(TARGET_FS)/usr/include
ifeq ($(HOST_ARCH)-$(TARGET_ARCH)-$(TARGET_OS),x86_64-armv7l-linux)
HEADER_SEARCH_PATH += /usr/arm-linux-gnueabihf/include
else ifeq ($(HOST_ARCH)-$(TARGET_ARCH)-$(TARGET_OS),x86_64-aarch64-linux)
HEADER_SEARCH_PATH += /usr/aarch64-linux-gnu/include
endif
EGLHEADER := $(shell find -L $(HEADER_SEARCH_PATH) -name egl.h -print 2>/dev/null)
EGLEXTHEADER := $(shell find -L $(HEADER_SEARCH_PATH) -name eglext.h -print 2>/dev/null)
ifeq ("$(EGLHEADER)","")
$(info >>> WARNING - egl.h not found, please install egl.h <<<)
SAMPLE_ENABLED := 0
endif
ifeq ("$(EGLEXTHEADER)","")
$(info >>> WARNING - eglext.h not found, please install eglext.h <<<)
SAMPLE_ENABLED := 0
endif
else
endif
ifeq ("$(TARGET_OS)","qnx")
HOST_CCFLAGS := -V8.3.0,gcc_ntoaarch64le
endif
# Attempt to compile a minimal EGL application and run to check if EGL_SUPPORT_REUSE_NV is supported in the EGL headers available.
ifneq ($(SAMPLE_ENABLED), 0)
$(shell printf "#include <EGL/egl.h>\n#include <EGL/eglext.h>\nint main() {\n#ifdef EGL_SUPPORT_REUSE_NV \n #error \"Compatible EGL header found\" \n return 0;\n#endif \n return 1;\n}" > test.c; )
EGL_DEFINES := $(shell $(HOST_COMPILER) $(HOST_CCFLAGS) $(CCFLAGS) $(EXTRA_CCFLAGS) -lEGL test.c -c 2>&1 | grep -ic "Compatible EGL header found";)
SHOULD_WAIVE := 0
ifeq ($(EGL_DEFINES),0)
SHOULD_WAIVE := 1
endif
ifeq ($(SHOULD_WAIVE),1)
$(info -----------------------------------------------------------------------------------------------)
$(info WARNING - NVIDIA EGL EXTENSIONS are not available in the present EGL headers)
$(info -----------------------------------------------------------------------------------------------)
$(info This CUDA Sample cannot be built if the EGL NVIDIA EXTENSIONS like EGL_SUPPORT_REUSE_NV are not supported in EGL headers.)
$(info This will be a dry-run of the Makefile.)
$(info Please install the latest khronos EGL headers and libs to build this sample)
$(info -----------------------------------------------------------------------------------------------)
SAMPLE_ENABLED := 0
endif
$(shell rm test.o test.c 2>/dev/null)
endif

View File

@@ -0,0 +1,204 @@
/* 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.
*/
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
Display *display;
int screen;
Window win = 0;
void error_exit(const char *format, ...) {
va_list args;
va_start(args, format);
vfprintf(stderr, format, args);
va_end(args);
exit(1);
}
#include <EGL/egl.h>
#include <EGL/eglext.h>
#define GET_GLERROR(ret) \
{ \
GLenum err = glGetError(); \
if (err != GL_NO_ERROR) { \
fprintf(stderr, "[%s line %d] OpenGL Error: 0x%x\n", __FILE__, __LINE__, \
err); \
fflush(stderr); \
\
switch (err) { \
case GL_INVALID_ENUM: \
printf("GL_INVALID_ENUM\n"); \
break; \
case GL_INVALID_VALUE: \
printf("GL_INVALID_VALUE\n"); \
break; \
case GL_INVALID_OPERATION: \
printf("GL_INVALID_OPERATION\n"); \
break; \
case GL_OUT_OF_MEMORY: \
printf("GL_OUT_OF_MEMORY\n"); \
break; \
case GL_INVALID_FRAMEBUFFER_OPERATION: \
printf("GL_INVALID_FRAMEBUFFER_OPERATION\n"); \
break; \
default: \
printf("UKNOWN OPENGL ERROR CODE 0x%x\n", err); \
}; \
} \
}
EGLDisplay eglDisplay = EGL_NO_DISPLAY;
EGLSurface eglSurface = EGL_NO_SURFACE;
EGLContext eglContext = EGL_NO_CONTEXT;
int graphics_setup_window(int xpos, int ypos, int width, int height,
const char *windowname) {
EGLint configAttrs[] = {
EGL_RED_SIZE, 1, EGL_GREEN_SIZE, 1, EGL_BLUE_SIZE, 1, EGL_DEPTH_SIZE, 16,
EGL_SAMPLE_BUFFERS, 0, EGL_SAMPLES, 0,
// EGL_CONFORMANT, EGL_OPENGL_BIT,
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, // 3_BIT_KHR,
EGL_NONE};
EGLint contextAttrs[] = {EGL_CONTEXT_CLIENT_VERSION, 3, EGL_NONE};
EGLConfig *configList = NULL;
EGLint configCount;
display = XOpenDisplay(NULL);
if (!display) error_exit("Error opening X display.\n");
screen = DefaultScreen(display);
eglDisplay = eglGetDisplay(0);
if (eglDisplay == EGL_NO_DISPLAY)
error_exit("EGL failed to obtain display\n");
if (!eglInitialize(eglDisplay, 0, 0))
error_exit("EGL failed to initialize\n");
if (!eglChooseConfig(eglDisplay, configAttrs, NULL, 0, &configCount) ||
!configCount)
error_exit("EGL failed to return any matching configurations\n");
configList = (EGLConfig *)malloc(configCount * sizeof(EGLConfig));
if (!eglChooseConfig(eglDisplay, configAttrs, configList, configCount,
&configCount) ||
!configCount)
error_exit("EGL failed to populate configuration list\n");
Window xRootWindow = DefaultRootWindow(display);
XSetWindowAttributes xCreateWindowAttributes;
xCreateWindowAttributes.event_mask = ExposureMask;
win = XCreateWindow(display, xRootWindow, 0, 0, width, height, 0,
CopyFromParent, InputOutput, CopyFromParent, CWEventMask,
&xCreateWindowAttributes);
XMapWindow(display, win);
Atom netWmStateAtom = XInternAtom(display, "_NET_WM_STATE", false);
XEvent xEvent;
memset(&xEvent, 0, sizeof(xEvent));
xEvent.type = ClientMessage;
xEvent.xclient.window = win;
xEvent.xclient.message_type = netWmStateAtom;
xEvent.xclient.format = 32;
xEvent.xclient.data.l[0] = 1;
xEvent.xclient.data.l[1] = false;
XSendEvent(display, xRootWindow, false, SubstructureNotifyMask, &xEvent);
XStoreName(display, win, windowname);
XSelectInput(display, win,
ExposureMask | KeyPressMask | ButtonPressMask |
ButtonReleaseMask | KeyReleaseMask | VisibilityChangeMask |
PointerMotionMask);
EGLint windowAttrs[] = {EGL_NONE};
eglSurface = eglCreateWindowSurface(eglDisplay, configList[0],
(EGLNativeWindowType)win, windowAttrs);
if (!eglSurface) error_exit("EGL couldn't create window\n");
eglBindAPI(EGL_OPENGL_ES_API);
eglContext = eglCreateContext(eglDisplay, configList[0], NULL, contextAttrs);
if (!eglContext) error_exit("EGL couldn't create context\n");
if (!eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext))
error_exit("EGL couldn't make context/surface current\n");
EGLint Context_RendererType;
eglQueryContext(eglDisplay, eglContext, EGL_CONTEXT_CLIENT_TYPE,
&Context_RendererType);
switch (Context_RendererType) {
case EGL_OPENGL_API:
printf("Using OpenGL API is not supported\n");
exit(EXIT_FAILURE);
break;
case EGL_OPENGL_ES_API:
printf("Using OpenGL ES API\n");
break;
case EGL_OPENVG_API:
error_exit("Context Query Returned OpenVG. This is Unsupported\n");
default:
error_exit("Unknown Context Type. %04X\n", Context_RendererType);
}
return 1;
}
void graphics_set_windowtitle(const char *windowname) {
XStoreName(display, win, windowname);
}
void graphics_swap_buffers() { eglSwapBuffers(eglDisplay, eglSurface); }
void graphics_close_window() {
if (eglDisplay != EGL_NO_DISPLAY) {
eglMakeCurrent(eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
if (eglContext != EGL_NO_CONTEXT) eglDestroyContext(eglDisplay, eglContext);
if (eglSurface != EGL_NO_SURFACE) eglDestroySurface(eglDisplay, eglSurface);
eglTerminate(eglDisplay);
}
if (display) {
if (win) XDestroyWindow(display, win);
XCloseDisplay(display);
}
}

View 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
}

View File

@@ -0,0 +1,7 @@
{
"recommendations": [
"nvidia.nsight-vscode-edition",
"ms-vscode.cpptools",
"ms-vscode.makefile-tools"
]
}

View File

@@ -0,0 +1,10 @@
{
"configurations": [
{
"name": "CUDA C++: Launch",
"type": "cuda-gdb",
"request": "launch",
"program": "${workspaceFolder}/FunctionPointers"
}
]
}

View File

@@ -0,0 +1,15 @@
{
"version": "2.0.0",
"tasks": [
{
"label": "sample",
"type": "shell",
"command": "make dbg=1",
"problemMatcher": ["$nvcc"],
"group": {
"kind": "build",
"isDefault": true
}
}
]
}

View File

@@ -0,0 +1,510 @@
/* 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.
*/
// OpenGL Graphics includes
#include <helper_gl.h>
#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
// Includes
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <helper_functions.h> // helper functions for timing, string parsing
#include <cuda_runtime.h> // CUDA Runtime
#include <cuda_gl_interop.h> // CUDA OpenGL interop
#include <helper_cuda.h> // includes for CUDA initialization and error checking
#include "FunctionPointers_kernels.h"
#define EXIT_WAIVED 2
//
// Cuda example code that implements the Sobel edge detection
// filter. This code works for 8-bit monochrome images.
//
// Use the '-' and '=' keys to change the scale factor.
//
// Other keys:
// I: display image
// T: display Sobel Edge Detection (computed solely with texture)
// S: display Sobel Edge Detection (computed with texture and shared memory)
void cleanup(void);
void initializeData(char *file);
#define MAX_EPSILON_ERROR 5.0f
static const char *sSDKsample = "CUDA Function Pointers (SobelFilter)";
const char *filterMode[] = {"No Filtering", "Sobel Texture",
"Sobel SMEM+Texture", NULL};
static int wWidth = 512; // Window width
static int wHeight = 512; // Window height
static int imWidth = 0; // Image width
static int imHeight = 0; // Image height
static int blockOp = 0;
static int pointOp = 1;
// Code to handle Auto verification
const int frameCheckNumber = 4;
int fpsCount = 0; // FPS count for averaging
int fpsLimit = 8; // FPS limit for sampling
unsigned int frameCount = 0;
StopWatchInterface *timer = NULL;
unsigned int g_Bpp;
int g_TotalErrors = 0;
int *pArgc = NULL;
char **pArgv = NULL;
bool g_bQAReadback = false;
// Display Data
static GLuint pbo_buffer = 0; // Front and back CA buffers
struct cudaGraphicsResource
*cuda_pbo_resource; // CUDA Graphics Resource (to transfer PBO)
static GLuint texid = 0; // Texture for display
unsigned char *pixels = NULL; // Image pixel data on the host
float imageScale = 1.f; // Image exposure
enum SobelDisplayMode g_SobelDisplayMode;
#define OFFSET(i) ((char *)NULL + (i))
#define MAX(a, b) ((a > b) ? a : b)
#define REFRESH_DELAY 10 // ms
void computeFPS() {
frameCount++;
fpsCount++;
if (fpsCount == fpsLimit) {
char fps[256];
float ifps = 1.f / (sdkGetAverageTimerValue(&timer) / 1000.f);
sprintf(fps, "FunctionPointers [CUDA Edge Detection] (%s): %3.1f fps",
filterMode[g_SobelDisplayMode], ifps);
glutSetWindowTitle(fps);
fpsCount = 0;
fpsLimit = (int)MAX(ifps, 1.f);
sdkResetTimer(&timer);
}
}
// This is the normal display path
void display(void) {
sdkStartTimer(&timer);
// Sobel operation
Pixel *data = NULL;
// map PBO to get CUDA device pointer
checkCudaErrors(cudaGraphicsMapResources(1, &cuda_pbo_resource, 0));
size_t num_bytes;
checkCudaErrors(cudaGraphicsResourceGetMappedPointer(
(void **)&data, &num_bytes, cuda_pbo_resource));
// printf("CUDA mapped PBO: May access %ld bytes\n", num_bytes);
sobelFilter(data, imWidth, imHeight, g_SobelDisplayMode, imageScale, blockOp,
pointOp);
checkCudaErrors(cudaGraphicsUnmapResources(1, &cuda_pbo_resource, 0));
glClear(GL_COLOR_BUFFER_BIT);
glBindTexture(GL_TEXTURE_2D, texid);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo_buffer);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, imWidth, imHeight, GL_LUMINANCE,
GL_UNSIGNED_BYTE, OFFSET(0));
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
glDisable(GL_DEPTH_TEST);
glEnable(GL_TEXTURE_2D);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glBegin(GL_QUADS);
glVertex2f(0, 0);
glTexCoord2f(0, 0);
glVertex2f(0, 1);
glTexCoord2f(1, 0);
glVertex2f(1, 1);
glTexCoord2f(1, 1);
glVertex2f(1, 0);
glTexCoord2f(0, 1);
glEnd();
glBindTexture(GL_TEXTURE_2D, 0);
glutSwapBuffers();
sdkStopTimer(&timer);
computeFPS();
}
void timerEvent(int value) {
if (glutGetWindow()) {
glutPostRedisplay();
glutTimerFunc(REFRESH_DELAY, timerEvent, 0);
}
}
void keyboard(unsigned char key, int /*x*/, int /*y*/) {
char temp[256];
switch (key) {
case 27:
#if defined(__APPLE__) || defined(MACOSX)
exit(EXIT_SUCCESS);
#else
glutDestroyWindow(glutGetWindow());
return;
#endif
break;
case '-':
imageScale -= 0.1f;
printf("brightness = %4.2f\n", imageScale);
break;
case '=':
imageScale += 0.1f;
printf("brightness = %4.2f\n", imageScale);
break;
case 'i':
case 'I':
g_SobelDisplayMode = SOBELDISPLAY_IMAGE;
sprintf(temp, "Function Pointers [CUDA Edge Detection] (%s)",
filterMode[g_SobelDisplayMode]);
glutSetWindowTitle(temp);
break;
case 's':
case 'S':
g_SobelDisplayMode = SOBELDISPLAY_SOBELSHARED;
sprintf(temp, "Function Pointers [CUDA Edge Detection] (%s)",
filterMode[g_SobelDisplayMode]);
glutSetWindowTitle(temp);
break;
case 't':
case 'T':
g_SobelDisplayMode = SOBELDISPLAY_SOBELTEX;
sprintf(temp, "Function Pointers [CUDA Edge Detection] (%s)",
filterMode[g_SobelDisplayMode]);
glutSetWindowTitle(temp);
break;
case 'b':
case 'B':
blockOp = (blockOp + 1) % LAST_BLOCK_FILTER;
break;
case 'p':
case 'P':
pointOp = (pointOp + 1) % LAST_POINT_FILTER;
break;
default:
break;
}
}
void reshape(int x, int y) {
glViewport(0, 0, x, y);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, 1, 0, 1, 0, 1);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
void cleanup(void) {
cudaGraphicsUnregisterResource(cuda_pbo_resource);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
glDeleteBuffers(1, &pbo_buffer);
glDeleteTextures(1, &texid);
deleteTexture();
sdkDeleteTimer(&timer);
}
void initializeData(char *file) {
GLint bsize;
unsigned int w, h;
size_t file_length = strlen(file);
if (!strcmp(&file[file_length - 3], "pgm")) {
if (sdkLoadPGM<unsigned char>(file, &pixels, &w, &h) != true) {
printf("Failed to load PGM image file: %s\n", file);
exit(EXIT_FAILURE);
}
g_Bpp = 1;
} else if (!strcmp(&file[file_length - 3], "ppm")) {
if (sdkLoadPPM4(file, &pixels, &w, &h) != true) {
printf("Failed to load PPM image file: %s\n", file);
exit(EXIT_FAILURE);
}
g_Bpp = 4;
} else {
exit(EXIT_FAILURE);
}
imWidth = (int)w;
imHeight = (int)h;
setupTexture(imWidth, imHeight, pixels, g_Bpp);
// copy function pointer tables to host side for later use
setupFunctionTables();
memset(pixels, 0x0, g_Bpp * sizeof(Pixel) * imWidth * imHeight);
if (!g_bQAReadback) {
// use OpenGL Path
glGenBuffers(1, &pbo_buffer);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo_buffer);
glBufferData(GL_PIXEL_UNPACK_BUFFER,
g_Bpp * sizeof(Pixel) * imWidth * imHeight, pixels,
GL_STREAM_DRAW);
glGetBufferParameteriv(GL_PIXEL_UNPACK_BUFFER, GL_BUFFER_SIZE, &bsize);
if ((GLuint)bsize != (g_Bpp * sizeof(Pixel) * imWidth * imHeight)) {
printf("Buffer object (%d) has incorrect size (%d).\n",
(unsigned)pbo_buffer, (unsigned)bsize);
exit(EXIT_FAILURE);
}
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
// register this buffer object with CUDA
checkCudaErrors(cudaGraphicsGLRegisterBuffer(
&cuda_pbo_resource, pbo_buffer, cudaGraphicsMapFlagsWriteDiscard));
glGenTextures(1, &texid);
glBindTexture(GL_TEXTURE_2D, texid);
glTexImage2D(GL_TEXTURE_2D, 0, ((g_Bpp == 1) ? GL_LUMINANCE : GL_BGRA),
imWidth, imHeight, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, NULL);
glBindTexture(GL_TEXTURE_2D, 0);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glPixelStorei(GL_PACK_ALIGNMENT, 1);
}
}
void loadDefaultImage(char *loc_exec) {
printf("Reading image: teapot512.pgm\n");
const char *image_filename = "teapot512.pgm";
char *image_path = sdkFindFilePath(image_filename, loc_exec);
if (image_path == NULL) {
printf("Failed to read image file: <%s>\n", image_filename);
exit(EXIT_FAILURE);
}
initializeData(image_path);
free(image_path);
}
void initGL(int *argc, char **argv) {
glutInit(argc, argv);
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);
glutInitWindowSize(wWidth, wHeight);
glutCreateWindow("Function Pointers [CUDA Edge Detection]n");
if (!isGLVersionSupported(1, 5) ||
!areGLExtensionsSupported(
"GL_ARB_vertex_buffer_object GL_ARB_pixel_buffer_object")) {
fprintf(stderr, "Error: failed to get minimal extensions for demo\n");
fprintf(stderr, "This sample requires:\n");
fprintf(stderr, " OpenGL version 1.5\n");
fprintf(stderr, " GL_ARB_vertex_buffer_object\n");
fprintf(stderr, " GL_ARB_pixel_buffer_object\n");
exit(EXIT_WAIVED);
}
}
void runAutoTest(int argc, char *argv[]) {
printf("[%s] (automated testing w/ readback)\n", sSDKsample);
int devID = findCudaDevice(argc, (const char **)argv);
loadDefaultImage(argv[0]);
Pixel *d_result;
checkCudaErrors(
cudaMalloc((void **)&d_result, imWidth * imHeight * sizeof(Pixel)));
char *ref_file = NULL;
char dump_file[256];
int mode = 0;
mode = getCmdLineArgumentInt(argc, (const char **)argv, "mode");
getCmdLineArgumentString(argc, (const char **)argv, "file", &ref_file);
switch (mode) {
case 0:
g_SobelDisplayMode = SOBELDISPLAY_IMAGE;
sprintf(dump_file, "teapot512_orig.pgm");
break;
case 1:
g_SobelDisplayMode = SOBELDISPLAY_SOBELTEX;
sprintf(dump_file, "teapot512_tex.pgm");
break;
case 2:
g_SobelDisplayMode = SOBELDISPLAY_SOBELSHARED;
sprintf(dump_file, "teapot512_shared.pgm");
break;
default:
printf("Invalid Filter Mode File\n");
exit(EXIT_FAILURE);
break;
}
printf("AutoTest: %s <%s>\n", sSDKsample, filterMode[g_SobelDisplayMode]);
sobelFilter(d_result, imWidth, imHeight, g_SobelDisplayMode, imageScale,
blockOp, pointOp);
checkCudaErrors(cudaDeviceSynchronize());
unsigned char *h_result =
(unsigned char *)malloc(imWidth * imHeight * sizeof(Pixel));
checkCudaErrors(cudaMemcpy(h_result, d_result,
imWidth * imHeight * sizeof(Pixel),
cudaMemcpyDeviceToHost));
sdkSavePGM(dump_file, h_result, imWidth, imHeight);
if (!sdkComparePGM(dump_file, sdkFindFilePath(ref_file, argv[0]),
MAX_EPSILON_ERROR, 0.15f, false)) {
g_TotalErrors++;
}
checkCudaErrors(cudaFree(d_result));
free(h_result);
if (g_TotalErrors != 0) {
printf("Test failed!\n");
exit(EXIT_FAILURE);
}
printf("Test passed!\n");
exit(EXIT_SUCCESS);
}
int main(int argc, char **argv) {
pArgc = &argc;
pArgv = argv;
#if defined(__linux__)
setenv("DISPLAY", ":0", 0);
#endif
printf("%s Starting...\n\n", argv[0]);
if (checkCmdLineFlag(argc, (const char **)argv, "help")) {
printf("\nUsage: FunctionPointers (SobelFilter) <options>\n");
printf("\t\t-mode=n (0=original, 1=texture, 2=smem + texture)\n");
printf("\t\t-file=ref_orig.pgm (ref_tex.pgm, ref_shared.pgm)\n\n");
exit(EXIT_WAIVED);
}
if (checkCmdLineFlag(argc, (const char **)argv, "file")) {
g_bQAReadback = true;
runAutoTest(argc, argv);
}
// use command-line specified CUDA device, otherwise use device with highest
// Gflops/s
if (checkCmdLineFlag(argc, (const char **)argv, "device")) {
printf(
" This SDK does not explicitly support -device=n when running with "
"OpenGL.\n");
printf(
" When specifying -device=n (n=0,1,2,....) the sample must not use "
"OpenGL.\n");
printf(" See details below to run without OpenGL:\n\n");
printf(" > %s -device=n\n\n", argv[0]);
printf("exiting...\n");
exit(EXIT_WAIVED);
}
if (!g_bQAReadback) {
// First initialize OpenGL context, so we can properly set the GL for CUDA.
// This is necessary in order to achieve optimal performance with
// OpenGL/CUDA interop.
initGL(&argc, argv);
int dev = findCudaDevice(argc, (const char **)argv);
sdkCreateTimer(&timer);
sdkResetTimer(&timer);
glutDisplayFunc(display);
glutKeyboardFunc(keyboard);
glutReshapeFunc(reshape);
loadDefaultImage(argv[0]);
// If code is not printing the USage, then we execute this path.
printf("I: display Image (no filtering)\n");
printf("T: display Sobel Edge Detection (Using Texture)\n");
printf("S: display Sobel Edge Detection (Using SMEM+Texture)\n");
printf("Use the '-' and '=' keys to change the brightness.\n");
printf("b: switch block filter operation (Mean/Sobel)\n");
printf("p: switch point filter operation (Threshold ON/OFF)\n");
fflush(stdout);
#if defined(__APPLE__) || defined(MACOSX)
atexit(cleanup);
#else
glutCloseFunc(cleanup);
#endif
glutTimerFunc(REFRESH_DELAY, timerEvent, 0);
glutMainLoop();
}
}

View File

@@ -0,0 +1,402 @@
/* 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.
*/
#include <stdio.h>
#include <stdlib.h>
#include <cooperative_groups.h>
namespace cg = cooperative_groups;
#include <helper_cuda.h>
#include "FunctionPointers_kernels.h"
// Texture object for reading image
cudaTextureObject_t tex;
extern __shared__ unsigned char LocalBlock[];
static cudaArray *array = NULL;
#define RADIUS 1
// pixel value used for thresholding function,
// works well with sample image 'teapot512'
#define THRESHOLD 150.0f
#ifdef FIXED_BLOCKWIDTH
#define BlockWidth 80
#define SharedPitch 384
#endif
// A function pointer can be declared explicitly like this line:
//__device__ unsigned char (*pointFunction)(unsigned char, float ) = NULL;
// or by using typedef's like below:
typedef unsigned char (*blockFunction_t)(unsigned char, unsigned char,
unsigned char, unsigned char,
unsigned char, unsigned char,
unsigned char, unsigned char,
unsigned char, float);
typedef unsigned char (*pointFunction_t)(unsigned char, float);
__device__ blockFunction_t blockFunction;
__device__ unsigned char ComputeSobel(unsigned char ul, // upper left
unsigned char um, // upper middle
unsigned char ur, // upper right
unsigned char ml, // middle left
unsigned char mm, // middle (unused)
unsigned char mr, // middle right
unsigned char ll, // lower left
unsigned char lm, // lower middle
unsigned char lr, // lower right
float fScale) {
short Horz = ur + 2 * mr + lr - ul - 2 * ml - ll;
short Vert = ul + 2 * um + ur - ll - 2 * lm - lr;
short Sum = (short)(fScale * (abs((int)Horz) + abs((int)Vert)));
return (unsigned char)((Sum < 0) ? 0 : ((Sum > 255) ? 255 : Sum));
}
// define a function pointer and initialize to NULL
__device__ unsigned char (*varFunction)(unsigned char, unsigned char,
unsigned char, unsigned char,
unsigned char, unsigned char,
unsigned char, unsigned char,
unsigned char, float x) = NULL;
__device__ unsigned char ComputeBox(unsigned char ul, // upper left
unsigned char um, // upper middle
unsigned char ur, // upper right
unsigned char ml, // middle left
unsigned char mm, // middle...middle
unsigned char mr, // middle right
unsigned char ll, // lower left
unsigned char lm, // lower middle
unsigned char lr, // lower right
float fscale) {
short Sum = (short)(ul + um + ur + ml + mm + mr + ll + lm + lr) / 9;
Sum *= fscale;
return (unsigned char)((Sum < 0) ? 0 : ((Sum > 255) ? 255 : Sum));
}
__device__ unsigned char Threshold(unsigned char in, float thresh) {
if (in > thresh) {
return 0xFF;
} else {
return 0;
}
}
// Declare function tables, one for the point function chosen, one for the
// block function chosen. The number of entries is determined by the
// enum in FunctionPointers_kernels.h
__device__ blockFunction_t blockFunction_table[LAST_BLOCK_FILTER];
__device__ pointFunction_t pointFunction_table[LAST_POINT_FILTER];
// Declare device side function pointers. We retrieve them later with
// cudaMemcpyFromSymbol to set our function tables above in some
// particular order specified at runtime.
__device__ blockFunction_t pComputeSobel = ComputeSobel;
__device__ blockFunction_t pComputeBox = ComputeBox;
__device__ pointFunction_t pComputeThreshold = Threshold;
// Allocate host side tables to mirror the device side, and later, we
// fill these tables with the function pointers. This lets us send
// the pointers to the kernel on invocation, as a method of choosing
// which function to run.
blockFunction_t h_blockFunction_table[2];
pointFunction_t h_pointFunction_table[2];
// Perform a filter operation on the data, using shared memory
// The actual operation performed is
// determined by the function pointer "blockFunction" and selected
// by the integer argument "blockOperation" and has access
// to an apron around the current pixel being processed.
// Following the block operation, a per-pixel operation,
// pointed to by pPointFunction is performed before the final
// pixel is produced.
__global__ void SobelShared(uchar4 *pSobelOriginal, unsigned short SobelPitch,
#ifndef FIXED_BLOCKWIDTH
short BlockWidth, short SharedPitch,
#endif
short w, short h, float fScale, int blockOperation,
pointFunction_t pPointFunction,
cudaTextureObject_t tex) {
// Handle to thread block group
cg::thread_block cta = cg::this_thread_block();
short u = 4 * blockIdx.x * BlockWidth;
short v = blockIdx.y * blockDim.y + threadIdx.y;
short ib;
int SharedIdx = threadIdx.y * SharedPitch;
for (ib = threadIdx.x; ib < BlockWidth + 2 * RADIUS; ib += blockDim.x) {
LocalBlock[SharedIdx + 4 * ib + 0] = tex2D<unsigned char>(
tex, (float)(u + 4 * ib - RADIUS + 0), (float)(v - RADIUS));
LocalBlock[SharedIdx + 4 * ib + 1] = tex2D<unsigned char>(
tex, (float)(u + 4 * ib - RADIUS + 1), (float)(v - RADIUS));
LocalBlock[SharedIdx + 4 * ib + 2] = tex2D<unsigned char>(
tex, (float)(u + 4 * ib - RADIUS + 2), (float)(v - RADIUS));
LocalBlock[SharedIdx + 4 * ib + 3] = tex2D<unsigned char>(
tex, (float)(u + 4 * ib - RADIUS + 3), (float)(v - RADIUS));
}
if (threadIdx.y < RADIUS * 2) {
//
// copy trailing RADIUS*2 rows of pixels into shared
//
SharedIdx = (blockDim.y + threadIdx.y) * SharedPitch;
for (ib = threadIdx.x; ib < BlockWidth + 2 * RADIUS; ib += blockDim.x) {
LocalBlock[SharedIdx + 4 * ib + 0] =
tex2D<unsigned char>(tex, (float)(u + 4 * ib - RADIUS + 0),
(float)(v + blockDim.y - RADIUS));
LocalBlock[SharedIdx + 4 * ib + 1] =
tex2D<unsigned char>(tex, (float)(u + 4 * ib - RADIUS + 1),
(float)(v + blockDim.y - RADIUS));
LocalBlock[SharedIdx + 4 * ib + 2] =
tex2D<unsigned char>(tex, (float)(u + 4 * ib - RADIUS + 2),
(float)(v + blockDim.y - RADIUS));
LocalBlock[SharedIdx + 4 * ib + 3] =
tex2D<unsigned char>(tex, (float)(u + 4 * ib - RADIUS + 3),
(float)(v + blockDim.y - RADIUS));
}
}
cg::sync(cta);
u >>= 2; // index as uchar4 from here
uchar4 *pSobel = (uchar4 *)(((char *)pSobelOriginal) + v * SobelPitch);
SharedIdx = threadIdx.y * SharedPitch;
blockFunction = blockFunction_table[blockOperation];
for (ib = threadIdx.x; ib < BlockWidth; ib += blockDim.x) {
uchar4 out;
unsigned char pix00 = LocalBlock[SharedIdx + 4 * ib + 0 * SharedPitch + 0];
unsigned char pix01 = LocalBlock[SharedIdx + 4 * ib + 0 * SharedPitch + 1];
unsigned char pix02 = LocalBlock[SharedIdx + 4 * ib + 0 * SharedPitch + 2];
unsigned char pix10 = LocalBlock[SharedIdx + 4 * ib + 1 * SharedPitch + 0];
unsigned char pix11 = LocalBlock[SharedIdx + 4 * ib + 1 * SharedPitch + 1];
unsigned char pix12 = LocalBlock[SharedIdx + 4 * ib + 1 * SharedPitch + 2];
unsigned char pix20 = LocalBlock[SharedIdx + 4 * ib + 2 * SharedPitch + 0];
unsigned char pix21 = LocalBlock[SharedIdx + 4 * ib + 2 * SharedPitch + 1];
unsigned char pix22 = LocalBlock[SharedIdx + 4 * ib + 2 * SharedPitch + 2];
out.x = (*blockFunction)(pix00, pix01, pix02, pix10, pix11, pix12, pix20,
pix21, pix22, fScale);
pix00 = LocalBlock[SharedIdx + 4 * ib + 0 * SharedPitch + 3];
pix10 = LocalBlock[SharedIdx + 4 * ib + 1 * SharedPitch + 3];
pix20 = LocalBlock[SharedIdx + 4 * ib + 2 * SharedPitch + 3];
out.y = (*blockFunction)(pix01, pix02, pix00, pix11, pix12, pix10, pix21,
pix22, pix20, fScale);
pix01 = LocalBlock[SharedIdx + 4 * ib + 0 * SharedPitch + 4];
pix11 = LocalBlock[SharedIdx + 4 * ib + 1 * SharedPitch + 4];
pix21 = LocalBlock[SharedIdx + 4 * ib + 2 * SharedPitch + 4];
out.z = (*blockFunction)(pix02, pix00, pix01, pix12, pix10, pix11, pix22,
pix20, pix21, fScale);
pix02 = LocalBlock[SharedIdx + 4 * ib + 0 * SharedPitch + 5];
pix12 = LocalBlock[SharedIdx + 4 * ib + 1 * SharedPitch + 5];
pix22 = LocalBlock[SharedIdx + 4 * ib + 2 * SharedPitch + 5];
out.w = (*blockFunction)(pix00, pix01, pix02, pix10, pix11, pix12, pix20,
pix21, pix22, fScale);
if (pPointFunction != NULL) {
out.x = (*pPointFunction)(out.x, THRESHOLD);
out.y = (*pPointFunction)(out.y, THRESHOLD);
out.z = (*pPointFunction)(out.z, THRESHOLD);
out.w = (*pPointFunction)(out.w, THRESHOLD);
}
if (u + ib < w / 4 && v < h) {
pSobel[u + ib] = out;
}
}
cg::sync(cta);
}
__global__ void SobelCopyImage(Pixel *pSobelOriginal, unsigned int Pitch, int w,
int h, float fscale, cudaTextureObject_t tex) {
unsigned char *pSobel =
(unsigned char *)(((char *)pSobelOriginal) + blockIdx.x * Pitch);
for (int i = threadIdx.x; i < w; i += blockDim.x) {
pSobel[i] = min(
max((tex2D<unsigned char>(tex, (float)i, (float)blockIdx.x) * fscale),
0.f),
255.f);
}
}
// Perform block and pointer filtering using texture lookups.
// The block and point operations are determined by the
// input argument (see comment above for "SobelShared" function)
__global__ void SobelTex(Pixel *pSobelOriginal, unsigned int Pitch, int w,
int h, float fScale, int blockOperation,
pointFunction_t pPointOperation,
cudaTextureObject_t tex) {
unsigned char *pSobel =
(unsigned char *)(((char *)pSobelOriginal) + blockIdx.x * Pitch);
unsigned char tmp = 0;
for (int i = threadIdx.x; i < w; i += blockDim.x) {
unsigned char pix00 =
tex2D<unsigned char>(tex, (float)i - 1, (float)blockIdx.x - 1);
unsigned char pix01 =
tex2D<unsigned char>(tex, (float)i + 0, (float)blockIdx.x - 1);
unsigned char pix02 =
tex2D<unsigned char>(tex, (float)i + 1, (float)blockIdx.x - 1);
unsigned char pix10 =
tex2D<unsigned char>(tex, (float)i - 1, (float)blockIdx.x + 0);
unsigned char pix11 =
tex2D<unsigned char>(tex, (float)i + 0, (float)blockIdx.x + 0);
unsigned char pix12 =
tex2D<unsigned char>(tex, (float)i + 1, (float)blockIdx.x + 0);
unsigned char pix20 =
tex2D<unsigned char>(tex, (float)i - 1, (float)blockIdx.x + 1);
unsigned char pix21 =
tex2D<unsigned char>(tex, (float)i + 0, (float)blockIdx.x + 1);
unsigned char pix22 =
tex2D<unsigned char>(tex, (float)i + 1, (float)blockIdx.x + 1);
tmp = (*(blockFunction_table[blockOperation]))(
pix00, pix01, pix02, pix10, pix11, pix12, pix20, pix21, pix22, fScale);
if (pPointOperation != NULL) {
tmp = (*pPointOperation)(tmp, 150.0);
}
pSobel[i] = tmp;
}
}
extern "C" void setupTexture(int iw, int ih, Pixel *data, int Bpp) {
cudaChannelFormatDesc desc;
if (Bpp == 1) {
desc = cudaCreateChannelDesc<unsigned char>();
} else {
desc = cudaCreateChannelDesc<uchar4>();
}
checkCudaErrors(cudaMallocArray(&array, &desc, iw, ih));
checkCudaErrors(cudaMemcpy2DToArray(
array, 0, 0, data, iw * Bpp * sizeof(Pixel), iw * Bpp * sizeof(Pixel), ih,
cudaMemcpyHostToDevice));
cudaResourceDesc texRes;
memset(&texRes, 0, sizeof(cudaResourceDesc));
texRes.resType = cudaResourceTypeArray;
texRes.res.array.array = array;
cudaTextureDesc texDescr;
memset(&texDescr, 0, sizeof(cudaTextureDesc));
checkCudaErrors(cudaCreateTextureObject(&tex, &texRes, &texDescr, NULL));
}
extern "C" void deleteTexture(void) {
checkCudaErrors(cudaFreeArray(array));
checkCudaErrors(cudaDestroyTextureObject(tex));
}
// Copy the pointers from the function tables to the host side
void setupFunctionTables() {
// Dynamically assign the function table.
// Copy the function pointers to their appropriate locations according to the
// enum
checkCudaErrors(cudaMemcpyFromSymbol(&h_blockFunction_table[SOBEL_FILTER],
pComputeSobel, sizeof(blockFunction_t)));
checkCudaErrors(cudaMemcpyFromSymbol(&h_blockFunction_table[BOX_FILTER],
pComputeBox, sizeof(blockFunction_t)));
// do the same for the point function, where the 2nd function is NULL ("no-op"
// filter, skipped in kernel code)
checkCudaErrors(cudaMemcpyFromSymbol(&h_pointFunction_table[THRESHOLD_FILTER],
pComputeThreshold,
sizeof(pointFunction_t)));
h_pointFunction_table[NULL_FILTER] = NULL;
// now copy the function tables back to the device, so if we wish we can use
// an index into the table to choose them
// We have now set the order in the function table according to our enum.
checkCudaErrors(
cudaMemcpyToSymbol(blockFunction_table, h_blockFunction_table,
sizeof(blockFunction_t) * LAST_BLOCK_FILTER));
checkCudaErrors(
cudaMemcpyToSymbol(pointFunction_table, h_pointFunction_table,
sizeof(pointFunction_t) * LAST_POINT_FILTER));
}
// Wrapper for the __global__ call that sets up the texture and threads
// Below two methods for selecting the image processing function to run are
// shown.
// BlockOperation is an integer kernel argument used as an index into the
// blockFunction_table on the device side
// pPointOp is itself a function pointer passed as a kernel argument, retrieved
// from a host side copy of the function table
extern "C" void sobelFilter(Pixel *odata, int iw, int ih,
enum SobelDisplayMode mode, float fScale,
int blockOperation, int pointOperation) {
pointFunction_t pPointOp = h_pointFunction_table[pointOperation];
switch (mode) {
case SOBELDISPLAY_IMAGE:
SobelCopyImage<<<ih, 384>>>(odata, iw, iw, ih, fScale, tex);
break;
case SOBELDISPLAY_SOBELTEX:
SobelTex<<<ih, 384>>>(odata, iw, iw, ih, fScale, blockOperation, pPointOp,
tex);
break;
case SOBELDISPLAY_SOBELSHARED: {
dim3 threads(16, 4);
#ifndef FIXED_BLOCKWIDTH
int BlockWidth = 80; // must be divisible by 16 for coalescing
#endif
dim3 blocks = dim3(iw / (4 * BlockWidth) + (0 != iw % (4 * BlockWidth)),
ih / threads.y + (0 != ih % threads.y));
int SharedPitch = ~0x3f & (4 * (BlockWidth + 2 * RADIUS) + 0x3f);
int sharedMem = SharedPitch * (threads.y + 2 * RADIUS);
// for the shared kernel, width must be divisible by 4
iw &= ~3;
SobelShared<<<blocks, threads, sharedMem>>>(
(uchar4 *)odata, iw,
#ifndef FIXED_BLOCKWIDTH
BlockWidth, SharedPitch,
#endif
iw, ih, fScale, blockOperation, pPointOp, tex);
} break;
}
}

View File

@@ -0,0 +1,58 @@
/* 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 __SOBELFILTER_KERNELS_H_
#define __SOBELFILTER_KERNELS_H_
typedef unsigned char Pixel;
// global determines which filter to invoke
enum SobelDisplayMode {
SOBELDISPLAY_IMAGE = 0,
SOBELDISPLAY_SOBELTEX,
SOBELDISPLAY_SOBELSHARED
};
// Enums to set up the function table
// note: if you change these be sure to recompile those files
// that include this header or ensure the .h is in the
// dependencies for the related object files
enum POINT_ENUM { SOBEL_FILTER = 0, BOX_FILTER, LAST_POINT_FILTER };
enum BLOCK_ENUM { THRESHOLD_FILTER = 0, NULL_FILTER, LAST_BLOCK_FILTER };
extern enum SobelDisplayMode g_SobelDisplayMode;
extern "C" void sobelFilter(Pixel *odata, int iw, int ih,
enum SobelDisplayMode mode, float fScale,
int blockOperation, int pointOperation);
extern "C" void setupTexture(int iw, int ih, Pixel *data, int Bpp);
extern "C" void deleteTexture(void);
extern "C" void initFilter(void);
void setupFunctionTables();
#endif

View File

@@ -0,0 +1,20 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2017
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FunctionPointers", "FunctionPointers_vs2017.vcxproj", "{997E0757-EA74-4A4E-A0FC-47D8C8831A15}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
Release|x64 = Release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{997E0757-EA74-4A4E-A0FC-47D8C8831A15}.Debug|x64.ActiveCfg = Debug|x64
{997E0757-EA74-4A4E-A0FC-47D8C8831A15}.Debug|x64.Build.0 = Debug|x64
{997E0757-EA74-4A4E-A0FC-47D8C8831A15}.Release|x64.ActiveCfg = Release|x64
{997E0757-EA74-4A4E-A0FC-47D8C8831A15}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

View File

@@ -0,0 +1,123 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<CUDAPropsPath Condition="'$(CUDAPropsPath)'==''">$(VCTargetsPath)\BuildCustomizations</CUDAPropsPath>
</PropertyGroup>
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{997E0757-EA74-4A4E-A0FC-47D8C8831A15}</ProjectGuid>
<RootNamespace>FunctionPointers_vs2017</RootNamespace>
<ProjectName>FunctionPointers</ProjectName>
<CudaToolkitCustomDir />
</PropertyGroup>
<PropertyGroup Condition="'$(WindowsTargetPlatformVersion)'==''">
<LatestTargetPlatformVersion>$([Microsoft.Build.Utilities.ToolLocationHelper]::GetLatestSDKTargetPlatformVersion('Windows', '10.0'))</LatestTargetPlatformVersion>
<WindowsTargetPlatformVersion Condition="'$(WindowsTargetPlatformVersion)' == ''">$(LatestTargetPlatformVersion)</WindowsTargetPlatformVersion>
<TargetPlatformVersion>$(WindowsTargetPlatformVersion)</TargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup>
<ConfigurationType>Application</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v141</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)'=='Debug'">
<UseDebugLibraries>true</UseDebugLibraries>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)'=='Release'">
<WholeProgramOptimization>true</WholeProgramOptimization>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
<Import Project="$(CUDAPropsPath)\CUDA 11.6.props" />
</ImportGroup>
<ImportGroup Label="PropertySheets">
<Import Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<IntDir>$(Platform)/$(Configuration)/</IntDir>
<IncludePath>$(IncludePath)</IncludePath>
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisRules />
<CodeAnalysisRuleAssemblies />
</PropertyGroup>
<PropertyGroup Condition="'$(Platform)'=='x64'">
<OutDir>../../../bin/win64/$(Configuration)/</OutDir>
</PropertyGroup>
<ItemDefinitionGroup>
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PreprocessorDefinitions>WIN32;_MBCS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>./;$(CudaToolkitDir)/include;../../../Common;</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<AdditionalDependencies>cudart_static.lib;freeglut.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(CudaToolkitLibDir);../../../Common/lib/$(PlatformName);</AdditionalLibraryDirectories>
<OutputFile>$(OutDir)/FunctionPointers.exe</OutputFile>
</Link>
<CudaCompile>
<CodeGeneration>compute_35,sm_35;compute_37,sm_37;compute_50,sm_50;compute_52,sm_52;compute_60,sm_60;compute_61,sm_61;compute_70,sm_70;compute_75,sm_75;compute_80,sm_80;compute_86,sm_86;</CodeGeneration>
<AdditionalOptions>-Xcompiler "/wd 4819" --threads 0 </AdditionalOptions>
<Include>./;../../../Common</Include>
<Defines>WIN32</Defines>
</CudaCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)'=='Debug'">
<ClCompile>
<Optimization>Disabled</Optimization>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<LinkTimeCodeGeneration>Default</LinkTimeCodeGeneration>
</Link>
<CudaCompile>
<Runtime>MTd</Runtime>
<TargetMachinePlatform>64</TargetMachinePlatform>
</CudaCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)'=='Release'">
<ClCompile>
<Optimization>MaxSpeed</Optimization>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
</ClCompile>
<Link>
<GenerateDebugInformation>false</GenerateDebugInformation>
<LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
</Link>
<CudaCompile>
<Runtime>MT</Runtime>
<TargetMachinePlatform>64</TargetMachinePlatform>
</CudaCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Platform)'=='Win32'">
<Link>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Platform)'=='x64'">
<Link>
<AdditionalDependencies>glew64.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="FunctionPointers.cpp" />
<CudaCompile Include="FunctionPointers_kernels.cu" />
<ClInclude Include="FunctionPointers_kernels.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
<Import Project="$(CUDAPropsPath)\CUDA 11.6.targets" />
</ImportGroup>
</Project>

View File

@@ -0,0 +1,20 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2019
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FunctionPointers", "FunctionPointers_vs2019.vcxproj", "{997E0757-EA74-4A4E-A0FC-47D8C8831A15}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
Release|x64 = Release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{997E0757-EA74-4A4E-A0FC-47D8C8831A15}.Debug|x64.ActiveCfg = Debug|x64
{997E0757-EA74-4A4E-A0FC-47D8C8831A15}.Debug|x64.Build.0 = Debug|x64
{997E0757-EA74-4A4E-A0FC-47D8C8831A15}.Release|x64.ActiveCfg = Release|x64
{997E0757-EA74-4A4E-A0FC-47D8C8831A15}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

View File

@@ -0,0 +1,119 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<CUDAPropsPath Condition="'$(CUDAPropsPath)'==''">$(VCTargetsPath)\BuildCustomizations</CUDAPropsPath>
</PropertyGroup>
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{997E0757-EA74-4A4E-A0FC-47D8C8831A15}</ProjectGuid>
<RootNamespace>FunctionPointers_vs2019</RootNamespace>
<ProjectName>FunctionPointers</ProjectName>
<CudaToolkitCustomDir />
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup>
<ConfigurationType>Application</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v142</PlatformToolset>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)'=='Debug'">
<UseDebugLibraries>true</UseDebugLibraries>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)'=='Release'">
<WholeProgramOptimization>true</WholeProgramOptimization>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
<Import Project="$(CUDAPropsPath)\CUDA 11.6.props" />
</ImportGroup>
<ImportGroup Label="PropertySheets">
<Import Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<IntDir>$(Platform)/$(Configuration)/</IntDir>
<IncludePath>$(IncludePath)</IncludePath>
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisRules />
<CodeAnalysisRuleAssemblies />
</PropertyGroup>
<PropertyGroup Condition="'$(Platform)'=='x64'">
<OutDir>../../../bin/win64/$(Configuration)/</OutDir>
</PropertyGroup>
<ItemDefinitionGroup>
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PreprocessorDefinitions>WIN32;_MBCS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>./;$(CudaToolkitDir)/include;../../../Common;</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<AdditionalDependencies>cudart_static.lib;freeglut.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(CudaToolkitLibDir);../../../Common/lib/$(PlatformName);</AdditionalLibraryDirectories>
<OutputFile>$(OutDir)/FunctionPointers.exe</OutputFile>
</Link>
<CudaCompile>
<CodeGeneration>compute_35,sm_35;compute_37,sm_37;compute_50,sm_50;compute_52,sm_52;compute_60,sm_60;compute_61,sm_61;compute_70,sm_70;compute_75,sm_75;compute_80,sm_80;compute_86,sm_86;</CodeGeneration>
<AdditionalOptions>-Xcompiler "/wd 4819" --threads 0 </AdditionalOptions>
<Include>./;../../../Common</Include>
<Defines>WIN32</Defines>
</CudaCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)'=='Debug'">
<ClCompile>
<Optimization>Disabled</Optimization>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<LinkTimeCodeGeneration>Default</LinkTimeCodeGeneration>
</Link>
<CudaCompile>
<Runtime>MTd</Runtime>
<TargetMachinePlatform>64</TargetMachinePlatform>
</CudaCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)'=='Release'">
<ClCompile>
<Optimization>MaxSpeed</Optimization>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
</ClCompile>
<Link>
<GenerateDebugInformation>false</GenerateDebugInformation>
<LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
</Link>
<CudaCompile>
<Runtime>MT</Runtime>
<TargetMachinePlatform>64</TargetMachinePlatform>
</CudaCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Platform)'=='Win32'">
<Link>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Platform)'=='x64'">
<Link>
<AdditionalDependencies>glew64.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="FunctionPointers.cpp" />
<CudaCompile Include="FunctionPointers_kernels.cu" />
<ClInclude Include="FunctionPointers_kernels.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
<Import Project="$(CUDAPropsPath)\CUDA 11.6.targets" />
</ImportGroup>
</Project>

View File

@@ -0,0 +1,20 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2022
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FunctionPointers", "FunctionPointers_vs2022.vcxproj", "{997E0757-EA74-4A4E-A0FC-47D8C8831A15}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
Release|x64 = Release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{997E0757-EA74-4A4E-A0FC-47D8C8831A15}.Debug|x64.ActiveCfg = Debug|x64
{997E0757-EA74-4A4E-A0FC-47D8C8831A15}.Debug|x64.Build.0 = Debug|x64
{997E0757-EA74-4A4E-A0FC-47D8C8831A15}.Release|x64.ActiveCfg = Release|x64
{997E0757-EA74-4A4E-A0FC-47D8C8831A15}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

View File

@@ -0,0 +1,119 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<CUDAPropsPath Condition="'$(CUDAPropsPath)'==''">$(VCTargetsPath)\BuildCustomizations</CUDAPropsPath>
</PropertyGroup>
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{997E0757-EA74-4A4E-A0FC-47D8C8831A15}</ProjectGuid>
<RootNamespace>FunctionPointers_vs2022</RootNamespace>
<ProjectName>FunctionPointers</ProjectName>
<CudaToolkitCustomDir />
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup>
<ConfigurationType>Application</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v143</PlatformToolset>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)'=='Debug'">
<UseDebugLibraries>true</UseDebugLibraries>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)'=='Release'">
<WholeProgramOptimization>true</WholeProgramOptimization>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
<Import Project="$(CUDAPropsPath)\CUDA 11.6.props" />
</ImportGroup>
<ImportGroup Label="PropertySheets">
<Import Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<IntDir>$(Platform)/$(Configuration)/</IntDir>
<IncludePath>$(IncludePath)</IncludePath>
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisRules />
<CodeAnalysisRuleAssemblies />
</PropertyGroup>
<PropertyGroup Condition="'$(Platform)'=='x64'">
<OutDir>../../../bin/win64/$(Configuration)/</OutDir>
</PropertyGroup>
<ItemDefinitionGroup>
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PreprocessorDefinitions>WIN32;_MBCS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>./;$(CudaToolkitDir)/include;../../../Common;</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<AdditionalDependencies>cudart_static.lib;freeglut.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(CudaToolkitLibDir);../../../Common/lib/$(PlatformName);</AdditionalLibraryDirectories>
<OutputFile>$(OutDir)/FunctionPointers.exe</OutputFile>
</Link>
<CudaCompile>
<CodeGeneration>compute_35,sm_35;compute_37,sm_37;compute_50,sm_50;compute_52,sm_52;compute_60,sm_60;compute_61,sm_61;compute_70,sm_70;compute_75,sm_75;compute_80,sm_80;compute_86,sm_86;</CodeGeneration>
<AdditionalOptions>-Xcompiler "/wd 4819" --threads 0 </AdditionalOptions>
<Include>./;../../../Common</Include>
<Defines>WIN32</Defines>
</CudaCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)'=='Debug'">
<ClCompile>
<Optimization>Disabled</Optimization>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<LinkTimeCodeGeneration>Default</LinkTimeCodeGeneration>
</Link>
<CudaCompile>
<Runtime>MTd</Runtime>
<TargetMachinePlatform>64</TargetMachinePlatform>
</CudaCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)'=='Release'">
<ClCompile>
<Optimization>MaxSpeed</Optimization>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
</ClCompile>
<Link>
<GenerateDebugInformation>false</GenerateDebugInformation>
<LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
</Link>
<CudaCompile>
<Runtime>MT</Runtime>
<TargetMachinePlatform>64</TargetMachinePlatform>
</CudaCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Platform)'=='Win32'">
<Link>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Platform)'=='x64'">
<Link>
<AdditionalDependencies>glew64.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="FunctionPointers.cpp" />
<CudaCompile Include="FunctionPointers_kernels.cu" />
<ClInclude Include="FunctionPointers_kernels.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
<Import Project="$(CUDAPropsPath)\CUDA 11.6.targets" />
</ImportGroup>
</Project>

View File

@@ -0,0 +1,366 @@
################################################################################
# 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.
#
################################################################################
#
# Makefile project only supported on Mac OS X and Linux Platforms)
#
################################################################################
# Location of the CUDA Toolkit
CUDA_PATH ?= /usr/local/cuda
##############################
# start deprecated interface #
##############################
ifeq ($(x86_64),1)
$(info WARNING - x86_64 variable has been deprecated)
$(info WARNING - please use TARGET_ARCH=x86_64 instead)
TARGET_ARCH ?= x86_64
endif
ifeq ($(ARMv7),1)
$(info WARNING - ARMv7 variable has been deprecated)
$(info WARNING - please use TARGET_ARCH=armv7l instead)
TARGET_ARCH ?= armv7l
endif
ifeq ($(aarch64),1)
$(info WARNING - aarch64 variable has been deprecated)
$(info WARNING - please use TARGET_ARCH=aarch64 instead)
TARGET_ARCH ?= aarch64
endif
ifeq ($(ppc64le),1)
$(info WARNING - ppc64le variable has been deprecated)
$(info WARNING - please use TARGET_ARCH=ppc64le instead)
TARGET_ARCH ?= ppc64le
endif
ifneq ($(GCC),)
$(info WARNING - GCC variable has been deprecated)
$(info WARNING - please use HOST_COMPILER=$(GCC) instead)
HOST_COMPILER ?= $(GCC)
endif
ifneq ($(abi),)
$(error ERROR - abi variable has been removed)
endif
############################
# end deprecated interface #
############################
# architecture
HOST_ARCH := $(shell uname -m)
TARGET_ARCH ?= $(HOST_ARCH)
ifneq (,$(filter $(TARGET_ARCH),x86_64 aarch64 sbsa ppc64le armv7l))
ifneq ($(TARGET_ARCH),$(HOST_ARCH))
ifneq (,$(filter $(TARGET_ARCH),x86_64 aarch64 sbsa ppc64le))
TARGET_SIZE := 64
else ifneq (,$(filter $(TARGET_ARCH),armv7l))
TARGET_SIZE := 32
endif
else
TARGET_SIZE := $(shell getconf LONG_BIT)
endif
else
$(error ERROR - unsupported value $(TARGET_ARCH) for TARGET_ARCH!)
endif
# sbsa and aarch64 systems look similar. Need to differentiate them at host level for now.
ifeq ($(HOST_ARCH),aarch64)
ifeq ($(CUDA_PATH)/targets/sbsa-linux,$(shell ls -1d $(CUDA_PATH)/targets/sbsa-linux 2>/dev/null))
HOST_ARCH := sbsa
TARGET_ARCH := sbsa
endif
endif
ifneq ($(TARGET_ARCH),$(HOST_ARCH))
ifeq (,$(filter $(HOST_ARCH)-$(TARGET_ARCH),aarch64-armv7l x86_64-armv7l x86_64-aarch64 x86_64-sbsa x86_64-ppc64le))
$(error ERROR - cross compiling from $(HOST_ARCH) to $(TARGET_ARCH) is not supported!)
endif
endif
# When on native aarch64 system with userspace of 32-bit, change TARGET_ARCH to armv7l
ifeq ($(HOST_ARCH)-$(TARGET_ARCH)-$(TARGET_SIZE),aarch64-aarch64-32)
TARGET_ARCH = armv7l
endif
# operating system
HOST_OS := $(shell uname -s 2>/dev/null | tr "[:upper:]" "[:lower:]")
TARGET_OS ?= $(HOST_OS)
ifeq (,$(filter $(TARGET_OS),linux darwin qnx android))
$(error ERROR - unsupported value $(TARGET_OS) for TARGET_OS!)
endif
# host compiler
ifeq ($(TARGET_OS),darwin)
ifeq ($(shell expr `xcodebuild -version | grep -i xcode | awk '{print $$2}' | cut -d'.' -f1` \>= 5),1)
HOST_COMPILER ?= clang++
endif
else ifneq ($(TARGET_ARCH),$(HOST_ARCH))
ifeq ($(HOST_ARCH)-$(TARGET_ARCH),x86_64-armv7l)
ifeq ($(TARGET_OS),linux)
HOST_COMPILER ?= arm-linux-gnueabihf-g++
else ifeq ($(TARGET_OS),qnx)
ifeq ($(QNX_HOST),)
$(error ERROR - QNX_HOST must be passed to the QNX host toolchain)
endif
ifeq ($(QNX_TARGET),)
$(error ERROR - QNX_TARGET must be passed to the QNX target toolchain)
endif
export QNX_HOST
export QNX_TARGET
HOST_COMPILER ?= $(QNX_HOST)/usr/bin/arm-unknown-nto-qnx6.6.0eabi-g++
else ifeq ($(TARGET_OS),android)
HOST_COMPILER ?= arm-linux-androideabi-g++
endif
else ifeq ($(TARGET_ARCH),aarch64)
ifeq ($(TARGET_OS), linux)
HOST_COMPILER ?= aarch64-linux-gnu-g++
else ifeq ($(TARGET_OS),qnx)
ifeq ($(QNX_HOST),)
$(error ERROR - QNX_HOST must be passed to the QNX host toolchain)
endif
ifeq ($(QNX_TARGET),)
$(error ERROR - QNX_TARGET must be passed to the QNX target toolchain)
endif
export QNX_HOST
export QNX_TARGET
HOST_COMPILER ?= $(QNX_HOST)/usr/bin/q++
else ifeq ($(TARGET_OS), android)
HOST_COMPILER ?= aarch64-linux-android-clang++
endif
else ifeq ($(TARGET_ARCH),sbsa)
HOST_COMPILER ?= aarch64-linux-gnu-g++
else ifeq ($(TARGET_ARCH),ppc64le)
HOST_COMPILER ?= powerpc64le-linux-gnu-g++
endif
endif
HOST_COMPILER ?= g++
NVCC := $(CUDA_PATH)/bin/nvcc -ccbin $(HOST_COMPILER)
# internal flags
NVCCFLAGS := -m${TARGET_SIZE}
CCFLAGS :=
LDFLAGS :=
# build flags
ifeq ($(TARGET_OS),darwin)
LDFLAGS += -rpath $(CUDA_PATH)/lib
CCFLAGS += -arch $(HOST_ARCH)
else ifeq ($(HOST_ARCH)-$(TARGET_ARCH)-$(TARGET_OS),x86_64-armv7l-linux)
LDFLAGS += --dynamic-linker=/lib/ld-linux-armhf.so.3
CCFLAGS += -mfloat-abi=hard
else ifeq ($(TARGET_OS),android)
LDFLAGS += -pie
CCFLAGS += -fpie -fpic -fexceptions
endif
ifneq ($(TARGET_ARCH),$(HOST_ARCH))
ifeq ($(TARGET_ARCH)-$(TARGET_OS),armv7l-linux)
ifneq ($(TARGET_FS),)
GCCVERSIONLTEQ46 := $(shell expr `$(HOST_COMPILER) -dumpversion` \<= 4.6)
ifeq ($(GCCVERSIONLTEQ46),1)
CCFLAGS += --sysroot=$(TARGET_FS)
endif
LDFLAGS += --sysroot=$(TARGET_FS)
LDFLAGS += -rpath-link=$(TARGET_FS)/lib
LDFLAGS += -rpath-link=$(TARGET_FS)/usr/lib
LDFLAGS += -rpath-link=$(TARGET_FS)/usr/lib/arm-linux-gnueabihf
endif
endif
ifeq ($(TARGET_ARCH)-$(TARGET_OS),aarch64-linux)
ifneq ($(TARGET_FS),)
GCCVERSIONLTEQ46 := $(shell expr `$(HOST_COMPILER) -dumpversion` \<= 4.6)
ifeq ($(GCCVERSIONLTEQ46),1)
CCFLAGS += --sysroot=$(TARGET_FS)
endif
LDFLAGS += --sysroot=$(TARGET_FS)
LDFLAGS += -rpath-link=$(TARGET_FS)/lib -L$(TARGET_FS)/lib
LDFLAGS += -rpath-link=$(TARGET_FS)/lib/aarch64-linux-gnu -L$(TARGET_FS)/lib/aarch64-linux-gnu
LDFLAGS += -rpath-link=$(TARGET_FS)/usr/lib -L$(TARGET_FS)/usr/lib
LDFLAGS += -rpath-link=$(TARGET_FS)/usr/lib/aarch64-linux-gnu -L$(TARGET_FS)/usr/lib/aarch64-linux-gnu
LDFLAGS += --unresolved-symbols=ignore-in-shared-libs
CCFLAGS += -isystem=$(TARGET_FS)/usr/include -I$(TARGET_FS)/usr/include -I$(TARGET_FS)/usr/include/libdrm
CCFLAGS += -isystem=$(TARGET_FS)/usr/include/aarch64-linux-gnu -I$(TARGET_FS)/usr/include/aarch64-linux-gnu
endif
endif
ifeq ($(TARGET_ARCH)-$(TARGET_OS),aarch64-qnx)
NVCCFLAGS += -D_QNX_SOURCE
NVCCFLAGS += --qpp-config 8.3.0,gcc_ntoaarch64le
CCFLAGS += -DWIN_INTERFACE_CUSTOM -I/usr/include/aarch64-qnx-gnu
LDFLAGS += -lsocket
LDFLAGS += -L/usr/lib/aarch64-qnx-gnu
CCFLAGS += "-Wl\,-rpath-link\,/usr/lib/aarch64-qnx-gnu"
ifdef TARGET_OVERRIDE
LDFLAGS += -lslog2
endif
ifneq ($(TARGET_FS),)
LDFLAGS += -L$(TARGET_FS)/usr/lib
CCFLAGS += "-Wl\,-rpath-link\,$(TARGET_FS)/usr/lib"
LDFLAGS += -L$(TARGET_FS)/usr/libnvidia
CCFLAGS += "-Wl\,-rpath-link\,$(TARGET_FS)/usr/libnvidia"
CCFLAGS += -I$(TARGET_FS)/../include
endif
endif
endif
ifdef TARGET_OVERRIDE # cuda toolkit targets override
NVCCFLAGS += -target-dir $(TARGET_OVERRIDE)
endif
# Install directory of different arch
CUDA_INSTALL_TARGET_DIR :=
ifeq ($(TARGET_ARCH)-$(TARGET_OS),armv7l-linux)
CUDA_INSTALL_TARGET_DIR = targets/armv7-linux-gnueabihf/
else ifeq ($(TARGET_ARCH)-$(TARGET_OS),aarch64-linux)
CUDA_INSTALL_TARGET_DIR = targets/aarch64-linux/
else ifeq ($(TARGET_ARCH)-$(TARGET_OS),sbsa-linux)
CUDA_INSTALL_TARGET_DIR = targets/sbsa-linux/
else ifeq ($(TARGET_ARCH)-$(TARGET_OS),armv7l-android)
CUDA_INSTALL_TARGET_DIR = targets/armv7-linux-androideabi/
else ifeq ($(TARGET_ARCH)-$(TARGET_OS),aarch64-android)
CUDA_INSTALL_TARGET_DIR = targets/aarch64-linux-androideabi/
else ifeq ($(TARGET_ARCH)-$(TARGET_OS),armv7l-qnx)
CUDA_INSTALL_TARGET_DIR = targets/ARMv7-linux-QNX/
else ifeq ($(TARGET_ARCH)-$(TARGET_OS),aarch64-qnx)
CUDA_INSTALL_TARGET_DIR = targets/aarch64-qnx/
else ifeq ($(TARGET_ARCH),ppc64le)
CUDA_INSTALL_TARGET_DIR = targets/ppc64le-linux/
endif
# Debug build flags
ifeq ($(dbg),1)
NVCCFLAGS += -g -G
BUILD_TYPE := debug
else
BUILD_TYPE := release
endif
ALL_CCFLAGS :=
ALL_CCFLAGS += $(NVCCFLAGS)
ALL_CCFLAGS += $(EXTRA_NVCCFLAGS)
ALL_CCFLAGS += $(addprefix -Xcompiler ,$(CCFLAGS))
ALL_CCFLAGS += $(addprefix -Xcompiler ,$(EXTRA_CCFLAGS))
SAMPLE_ENABLED := 1
# This sample is not supported on QNX
ifeq ($(TARGET_OS),qnx)
$(info >>> WARNING - FunctionPointers is not supported on QNX - waiving sample <<<)
SAMPLE_ENABLED := 0
endif
ALL_LDFLAGS :=
ALL_LDFLAGS += $(ALL_CCFLAGS)
ALL_LDFLAGS += $(addprefix -Xlinker ,$(LDFLAGS))
ALL_LDFLAGS += $(addprefix -Xlinker ,$(EXTRA_LDFLAGS))
# Common includes and paths for CUDA
INCLUDES := -I../../../Common
LIBRARIES :=
################################################################################
# Makefile include to help find GL Libraries
include ./findgllib.mk
# OpenGL specific libraries
ifeq ($(TARGET_OS),darwin)
# Mac OSX specific libraries and paths to include
LIBRARIES += -L/System/Library/Frameworks/OpenGL.framework/Libraries
LIBRARIES += -lGL -lGLU
ALL_LDFLAGS += -Xlinker -framework -Xlinker GLUT
else
LIBRARIES += $(GLLINK)
LIBRARIES += -lGL -lGLU -lglut
endif
# Gencode arguments
ifeq ($(TARGET_ARCH),$(filter $(TARGET_ARCH),armv7l aarch64 sbsa))
SMS ?= 53 61 70 72 75 80 86 87
else
SMS ?= 35 37 50 52 60 61 70 75 80 86
endif
ifeq ($(SMS),)
$(info >>> WARNING - no SM architectures have been specified - waiving sample <<<)
SAMPLE_ENABLED := 0
endif
ifeq ($(GENCODE_FLAGS),)
# Generate SASS code for each SM architecture listed in $(SMS)
$(foreach sm,$(SMS),$(eval GENCODE_FLAGS += -gencode arch=compute_$(sm),code=sm_$(sm)))
# Generate PTX code from the highest SM architecture in $(SMS) to guarantee forward-compatibility
HIGHEST_SM := $(lastword $(sort $(SMS)))
ifneq ($(HIGHEST_SM),)
GENCODE_FLAGS += -gencode arch=compute_$(HIGHEST_SM),code=compute_$(HIGHEST_SM)
endif
endif
ALL_CCFLAGS += --threads 0 --std=c++11
ifeq ($(SAMPLE_ENABLED),0)
EXEC ?= @echo "[@]"
endif
################################################################################
# Target rules
all: build
build: FunctionPointers
check.deps:
ifeq ($(SAMPLE_ENABLED),0)
@echo "Sample will be waived due to the above missing dependencies"
else
@echo "Sample is ready - all dependencies have been met"
endif
FunctionPointers.o:FunctionPointers.cpp
$(EXEC) $(NVCC) $(INCLUDES) $(ALL_CCFLAGS) $(GENCODE_FLAGS) -o $@ -c $<
FunctionPointers_kernels.o:FunctionPointers_kernels.cu
$(EXEC) $(NVCC) $(INCLUDES) $(ALL_CCFLAGS) $(GENCODE_FLAGS) -o $@ -c $<
FunctionPointers: FunctionPointers.o FunctionPointers_kernels.o
$(EXEC) $(NVCC) $(ALL_LDFLAGS) $(GENCODE_FLAGS) -o $@ $+ $(LIBRARIES)
$(EXEC) mkdir -p ../../../bin/$(TARGET_ARCH)/$(TARGET_OS)/$(BUILD_TYPE)
$(EXEC) cp $@ ../../../bin/$(TARGET_ARCH)/$(TARGET_OS)/$(BUILD_TYPE)
run: build
$(EXEC) ./FunctionPointers
testrun: build
$(EXEC) ./FunctionPointers -mode=0 -file=ref_orig.pgm
$(EXEC) ./FunctionPointers -mode=1 -file=ref_tex.pgm
$(EXEC) ./FunctionPointers -mode=2 -file=ref_shared.pgm
clean:
rm -f FunctionPointers FunctionPointers.o FunctionPointers_kernels.o
rm -rf ../../../bin/$(TARGET_ARCH)/$(TARGET_OS)/$(BUILD_TYPE)/FunctionPointers
clobber: clean

View File

@@ -0,0 +1,115 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE entry SYSTEM "SamplesInfo.dtd">
<entry>
<name>FunctionPointers</name>
<cuda_api_list>
<toolkit>cudaMemcpyToSymbol</toolkit>
<toolkit>cudaFree</toolkit>
<toolkit>cudaGraphicsMapResources</toolkit>
<toolkit>cudaFreeArray</toolkit>
<toolkit>cudaGraphicsGLRegisterBuffer</toolkit>
<toolkit>cudaGraphicsResourceGetMappedPointer</toolkit>
<toolkit>cudaDeviceSynchronize</toolkit>
<toolkit>cudaDestroyTextureObject</toolkit>
<toolkit>cudaCreateTextureObject</toolkit>
<toolkit>cudaMalloc</toolkit>
<toolkit>cudaMallocArray</toolkit>
<toolkit>cudaGraphicsUnregisterResource</toolkit>
<toolkit>cudaGraphicsUnmapResources</toolkit>
<toolkit>cudaMemcpy</toolkit>
<toolkit>cudaMemcpyFromSymbol</toolkit>
</cuda_api_list>
<description><![CDATA[This sample illustrates how to use function pointers and implements the Sobel Edge Detection filter for 8-bit monochrome images.]]></description>
<devicecompilation>whole</devicecompilation>
<files>
<file>data\teapot512.pgm</file>
<file>data\ref_orig.pgm</file>
<file>data\ref_tex.pgm</file>
<file>data\ref_shared.pgm</file>
</files>
<includepaths>
<path>./</path>
<path>../</path>
<path>../../../Common</path>
</includepaths>
<keyconcepts>
<concept level="advanced">Graphics Interop</concept>
<concept level="advanced">Image Processing</concept>
</keyconcepts>
<keywords>
<keyword>CUDA</keyword>
<keyword>GPGPU</keyword>
<keyword>convolution</keyword>
<keyword>separable convolution</keyword>
<keyword>Image Processing</keyword>
<keyword>filter</keyword>
<keyword>finite impulse-response filter</keyword>
<keyword>openGL</keyword>
</keywords>
<libraries>
<library>GLU</library>
<library>GL</library>
<library framework="true" os="macosx">GLUT</library>
<library os="linux">GLEW</library>
<library os="linux">glut</library>
<library os="linux">X11</library>
</libraries>
<librarypaths>
<path arch="x86_64" os="linux">../../../common/lib/linux/x86_64</path>
<path arch="armv7l" os="linux">../../../common/lib/linux/armv7l</path>
<path os="macosx">../../../common/lib/darwin</path>
</librarypaths>
<nsight_eclipse>true</nsight_eclipse>
<primary_file>FunctionPointers.cpp</primary_file>
<qatests>
<qatest>-mode=0 -file=ref_orig.pgm</qatest>
<qatest>-mode=1 -file=ref_tex.pgm</qatest>
<qatest>-mode=2 -file=ref_shared.pgm</qatest>
</qatests>
<required_dependencies>
<dependency>X11</dependency>
<dependency>GL</dependency>
</required_dependencies>
<scopes>
<scope>1:CUDA Advanced Topics</scope>
<scope>2:Graphics Interop</scope>
<scope>2:Image Processing</scope>
</scopes>
<sm-arch>sm35</sm-arch>
<sm-arch>sm37</sm-arch>
<sm-arch>sm50</sm-arch>
<sm-arch>sm52</sm-arch>
<sm-arch>sm53</sm-arch>
<sm-arch>sm60</sm-arch>
<sm-arch>sm61</sm-arch>
<sm-arch>sm70</sm-arch>
<sm-arch>sm72</sm-arch>
<sm-arch>sm75</sm-arch>
<sm-arch>sm80</sm-arch>
<sm-arch>sm86</sm-arch>
<sm-arch>sm87</sm-arch>
<supported_envs>
<env>
<arch>x86_64</arch>
<platform>linux</platform>
</env>
<env>
<platform>windows7</platform>
</env>
<env>
<arch>x86_64</arch>
<platform>macosx</platform>
</env>
<env>
<arch>arm</arch>
</env>
<env>
<arch>sbsa</arch>
</env>
</supported_envs>
<supported_sm_architectures>
<include>all</include>
</supported_sm_architectures>
<title>Function Pointers</title>
<type>exe</type>
</entry>

View File

@@ -0,0 +1,74 @@
# FunctionPointers - Function Pointers
## Description
This sample illustrates how to use function pointers and implements the Sobel Edge Detection filter for 8-bit monochrome images.
## Key Concepts
Graphics Interop, Image Processing
## Supported SM Architectures
[SM 3.5 ](https://developer.nvidia.com/cuda-gpus) [SM 3.7 ](https://developer.nvidia.com/cuda-gpus) [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)
## 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)
cudaMemcpyToSymbol, cudaFree, cudaGraphicsMapResources, cudaFreeArray, cudaGraphicsGLRegisterBuffer, cudaGraphicsResourceGetMappedPointer, cudaDeviceSynchronize, cudaDestroyTextureObject, cudaCreateTextureObject, cudaMalloc, cudaMallocArray, cudaGraphicsUnregisterResource, cudaGraphicsUnmapResources, cudaMemcpy, cudaMemcpyFromSymbol
## Dependencies needed to build/run
[X11](../../README.md#x11), [GL](../../README.md#gl)
## Prerequisites
Download and install the [CUDA Toolkit 11.6](https://developer.nvidia.com/cuda-downloads) for your corresponding platform.
Make sure the dependencies mentioned in [Dependencies]() section above are installed.
## Build and Run
### Windows
The Windows samples are built using the Visual Studio IDE. Solution files (.sln) are provided for each supported version of Visual Studio, using the format:
```
*_vs<version>.sln - for Visual Studio <version>
```
Each individual sample has its own set of solution files in its directory:
To build/examine all the samples at once, the complete solution files should be used. To build/examine a single sample, the individual sample solution files should be used.
> **Note:** Some samples require that the Microsoft DirectX SDK (June 2010 or newer) be installed and that the VC++ directory paths are properly set up (**Tools > Options...**). Check DirectX Dependencies section for details."
### Linux
The Linux samples are built using makefiles. To use the makefiles, change the current directory to the sample directory you wish to build, and run make:
```
$ cd <sample_dir>
$ make
```
The samples makefiles can take advantage of certain options:
* **TARGET_ARCH=<arch>** - cross-compile targeting a specific architecture. Allowed architectures are x86_64, armv7l.
By default, TARGET_ARCH is set to HOST_ARCH. On a x86_64 machine, not setting TARGET_ARCH is the equivalent of setting TARGET_ARCH=x86_64.<br/>
`$ make TARGET_ARCH=x86_64` <br/> `$ make TARGET_ARCH=armv7l` <br/>
See [here](http://docs.nvidia.com/cuda/cuda-samples/index.html#cross-samples) for more details.
* **dbg=1** - build with debug symbols
```
$ make dbg=1
```
* **SMS="A B ..."** - override the SM architectures for which the sample will be built, where `"A B ..."` is a space-delimited list of SM architectures. For example, to generate SASS for SM 50 and SM 60, use `SMS="50 60"`.
```
$ make SMS="50 60"
```
* **HOST_COMPILER=<host_compiler>** - override the default g++ host compiler. See the [Linux Installation Guide](http://docs.nvidia.com/cuda/cuda-installation-guide-linux/index.html#system-requirements) for a list of supported host compilers.
```
$ make HOST_COMPILER=g++
```
## References (for more details)

View File

@@ -0,0 +1,145 @@
################################################################################
# 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.
#
################################################################################
#
# findgllib.mk is used to find the necessary GL Libraries for specific distributions
# this is supported on Mac OSX and Linux Platforms
#
################################################################################
# Determine OS platform and unix distribution
ifeq ("$(TARGET_OS)","linux")
# first search lsb_release
DISTRO := $(shell lsb_release -i -s 2>/dev/null | tr "[:upper:]" "[:lower:]")
ifeq ("$(DISTRO)","")
# second search and parse /etc/issue
DISTRO := $(shell awk '{print $$1}' /etc/issue | tr -d "[:space:]" | sed -e "/^$$/d" | tr "[:upper:]" "[:lower:]")
# ensure data from /etc/issue is valid
ifeq (,$(filter $(DISTRO),ubuntu fedora red rhel centos suse))
DISTRO :=
endif
ifeq ("$(DISTRO)","")
# third, we can search in /etc/os-release or /etc/{distro}-release
DISTRO := $(shell awk '/ID/' /etc/*-release | sed 's/ID=//' | grep -v "VERSION" | grep -v "ID" | grep -v "DISTRIB")
endif
endif
endif
ifeq ("$(TARGET_OS)","linux")
# $(info) >> findgllib.mk -> LINUX path <<<)
# Each set of Linux Distros have different paths for where to find their OpenGL libraries reside
UBUNTU = $(shell echo $(DISTRO) | grep -i ubuntu >/dev/null 2>&1; echo $$?)
FEDORA = $(shell echo $(DISTRO) | grep -i fedora >/dev/null 2>&1; echo $$?)
RHEL = $(shell echo $(DISTRO) | grep -i 'red\|rhel' >/dev/null 2>&1; echo $$?)
CENTOS = $(shell echo $(DISTRO) | grep -i centos >/dev/null 2>&1; echo $$?)
SUSE = $(shell echo $(DISTRO) | grep -i 'suse\|sles' >/dev/null 2>&1; echo $$?)
ifeq ("$(UBUNTU)","0")
ifeq ($(HOST_ARCH)-$(TARGET_ARCH),x86_64-armv7l)
GLPATH := /usr/arm-linux-gnueabihf/lib
GLLINK := -L/usr/arm-linux-gnueabihf/lib
ifneq ($(TARGET_FS),)
GLPATH += $(TARGET_FS)/usr/lib/arm-linux-gnueabihf
GLLINK += -L$(TARGET_FS)/usr/lib/arm-linux-gnueabihf
endif
else ifeq ($(HOST_ARCH)-$(TARGET_ARCH),x86_64-aarch64)
GLPATH := /usr/aarch64-linux-gnu/lib
GLLINK := -L/usr/aarch64-linux-gnu/lib
ifneq ($(TARGET_FS),)
GLPATH += $(TARGET_FS)/usr/lib
GLPATH += $(TARGET_FS)/usr/lib/aarch64-linux-gnu
GLLINK += -L$(TARGET_FS)/usr/lib/aarch64-linux-gnu
endif
else ifeq ($(HOST_ARCH)-$(TARGET_ARCH),x86_64-ppc64le)
GLPATH := /usr/powerpc64le-linux-gnu/lib
GLLINK := -L/usr/powerpc64le-linux-gnu/lib
else
UBUNTU_PKG_NAME = $(shell which dpkg >/dev/null 2>&1 && dpkg -l 'nvidia-*' | grep '^ii' | awk '{print $$2}' | head -1)
ifneq ("$(UBUNTU_PKG_NAME)","")
GLPATH ?= /usr/lib/$(UBUNTU_PKG_NAME)
GLLINK ?= -L/usr/lib/$(UBUNTU_PKG_NAME)
endif
DFLT_PATH ?= /usr/lib
endif
endif
ifeq ("$(SUSE)","0")
GLPATH ?= /usr/X11R6/lib64
GLLINK ?= -L/usr/X11R6/lib64
DFLT_PATH ?= /usr/lib64
endif
ifeq ("$(FEDORA)","0")
GLPATH ?= /usr/lib64/nvidia
GLLINK ?= -L/usr/lib64/nvidia
DFLT_PATH ?= /usr/lib64
endif
ifeq ("$(RHEL)","0")
GLPATH ?= /usr/lib64/nvidia
GLLINK ?= -L/usr/lib64/nvidia
DFLT_PATH ?= /usr/lib64
endif
ifeq ("$(CENTOS)","0")
GLPATH ?= /usr/lib64/nvidia
GLLINK ?= -L/usr/lib64/nvidia
DFLT_PATH ?= /usr/lib64
endif
# find libGL, libGLU
GLLIB := $(shell find -L $(GLPATH) $(DFLT_PATH) -name libGL.so -print 2>/dev/null)
GLULIB := $(shell find -L $(GLPATH) $(DFLT_PATH) -name libGLU.so -print 2>/dev/null)
ifeq ("$(GLLIB)","")
$(info >>> WARNING - libGL.so not found, refer to CUDA Getting Started Guide for how to find and install them. <<<)
SAMPLE_ENABLED := 0
endif
ifeq ("$(GLULIB)","")
$(info >>> WARNING - libGLU.so not found, refer to CUDA Getting Started Guide for how to find and install them. <<<)
SAMPLE_ENABLED := 0
endif
HEADER_SEARCH_PATH ?= $(TARGET_FS)/usr/include
ifeq ($(HOST_ARCH)-$(TARGET_ARCH)-$(TARGET_OS),x86_64-armv7l-linux)
HEADER_SEARCH_PATH += /usr/arm-linux-gnueabihf/include
else ifeq ($(HOST_ARCH)-$(TARGET_ARCH)-$(TARGET_OS),x86_64-aarch64-linux)
HEADER_SEARCH_PATH += /usr/aarch64-linux-gnu/include
endif
GLHEADER := $(shell find -L $(HEADER_SEARCH_PATH) -name gl.h -print 2>/dev/null)
GLUHEADER := $(shell find -L $(HEADER_SEARCH_PATH) -name glu.h -print 2>/dev/null)
ifeq ("$(GLHEADER)","")
$(info >>> WARNING - gl.h not found, refer to CUDA Getting Started Guide for how to find and install them. <<<)
SAMPLE_ENABLED := 0
endif
ifeq ("$(GLUHEADER)","")
$(info >>> WARNING - glu.h not found, refer to CUDA Getting Started Guide for how to find and install them. <<<)
SAMPLE_ENABLED := 0
endif
else
# This would be the Mac OS X path if we had to do anything special
endif

View 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
}

View File

@@ -0,0 +1,7 @@
{
"recommendations": [
"nvidia.nsight-vscode-edition",
"ms-vscode.cpptools",
"ms-vscode.makefile-tools"
]
}

View File

@@ -0,0 +1,10 @@
{
"configurations": [
{
"name": "CUDA C++: Launch",
"type": "cuda-gdb",
"request": "launch",
"program": "${workspaceFolder}/MC_EstimatePiInlineP"
}
]
}

View File

@@ -0,0 +1,15 @@
{
"version": "2.0.0",
"tasks": [
{
"label": "sample",
"type": "shell",
"command": "make dbg=1",
"problemMatcher": ["$nvcc"],
"group": {
"kind": "build",
"isDefault": true
}
}
]
}

View File

@@ -0,0 +1,20 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2017
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MC_EstimatePiInlineP", "MC_EstimatePiInlineP_vs2017.vcxproj", "{997E0757-EA74-4A4E-A0FC-47D8C8831A15}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
Release|x64 = Release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{997E0757-EA74-4A4E-A0FC-47D8C8831A15}.Debug|x64.ActiveCfg = Debug|x64
{997E0757-EA74-4A4E-A0FC-47D8C8831A15}.Debug|x64.Build.0 = Debug|x64
{997E0757-EA74-4A4E-A0FC-47D8C8831A15}.Release|x64.ActiveCfg = Release|x64
{997E0757-EA74-4A4E-A0FC-47D8C8831A15}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

View File

@@ -0,0 +1,116 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<CUDAPropsPath Condition="'$(CUDAPropsPath)'==''">$(VCTargetsPath)\BuildCustomizations</CUDAPropsPath>
</PropertyGroup>
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{997E0757-EA74-4A4E-A0FC-47D8C8831A15}</ProjectGuid>
<RootNamespace>MC_EstimatePiInlineP_vs2017</RootNamespace>
<ProjectName>MC_EstimatePiInlineP</ProjectName>
<CudaToolkitCustomDir />
</PropertyGroup>
<PropertyGroup Condition="'$(WindowsTargetPlatformVersion)'==''">
<LatestTargetPlatformVersion>$([Microsoft.Build.Utilities.ToolLocationHelper]::GetLatestSDKTargetPlatformVersion('Windows', '10.0'))</LatestTargetPlatformVersion>
<WindowsTargetPlatformVersion Condition="'$(WindowsTargetPlatformVersion)' == ''">$(LatestTargetPlatformVersion)</WindowsTargetPlatformVersion>
<TargetPlatformVersion>$(WindowsTargetPlatformVersion)</TargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup>
<ConfigurationType>Application</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v141</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)'=='Debug'">
<UseDebugLibraries>true</UseDebugLibraries>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)'=='Release'">
<WholeProgramOptimization>true</WholeProgramOptimization>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
<Import Project="$(CUDAPropsPath)\CUDA 11.6.props" />
</ImportGroup>
<ImportGroup Label="PropertySheets">
<Import Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<IntDir>$(Platform)/$(Configuration)/</IntDir>
<IncludePath>$(IncludePath)</IncludePath>
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisRules />
<CodeAnalysisRuleAssemblies />
</PropertyGroup>
<PropertyGroup Condition="'$(Platform)'=='x64'">
<OutDir>../../../bin/win64/$(Configuration)/</OutDir>
</PropertyGroup>
<ItemDefinitionGroup>
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PreprocessorDefinitions>WIN32;_MBCS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>./;$(CudaToolkitDir)/include;../../../Common;$(CudaToolkitIncludeDir);</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<AdditionalDependencies>curand.lib;cudart_static.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(CudaToolkitLibDir);</AdditionalLibraryDirectories>
<OutputFile>$(OutDir)/MC_EstimatePiInlineP.exe</OutputFile>
</Link>
<CudaCompile>
<CodeGeneration>compute_35,sm_35;compute_37,sm_37;compute_50,sm_50;compute_52,sm_52;compute_60,sm_60;compute_61,sm_61;compute_70,sm_70;compute_75,sm_75;compute_80,sm_80;compute_86,sm_86;</CodeGeneration>
<AdditionalOptions>-Xcompiler "/wd 4819" --threads 0 </AdditionalOptions>
<Include>./;../../../Common</Include>
<Defines>WIN32</Defines>
</CudaCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)'=='Debug'">
<ClCompile>
<Optimization>Disabled</Optimization>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<LinkTimeCodeGeneration>Default</LinkTimeCodeGeneration>
</Link>
<CudaCompile>
<Runtime>MTd</Runtime>
<TargetMachinePlatform>64</TargetMachinePlatform>
</CudaCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)'=='Release'">
<ClCompile>
<Optimization>MaxSpeed</Optimization>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
</ClCompile>
<Link>
<GenerateDebugInformation>false</GenerateDebugInformation>
<LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
</Link>
<CudaCompile>
<Runtime>MT</Runtime>
<TargetMachinePlatform>64</TargetMachinePlatform>
</CudaCompile>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="src/main.cpp" />
<CudaCompile Include="src/piestimator.cu" />
<ClCompile Include="src/test.cpp" />
<ClInclude Include="inc/cudasharedmem.h" />
<ClInclude Include="inc/piestimator.h" />
<ClInclude Include="inc/test.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
<Import Project="$(CUDAPropsPath)\CUDA 11.6.targets" />
</ImportGroup>
</Project>

View File

@@ -0,0 +1,20 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2019
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MC_EstimatePiInlineP", "MC_EstimatePiInlineP_vs2019.vcxproj", "{997E0757-EA74-4A4E-A0FC-47D8C8831A15}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
Release|x64 = Release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{997E0757-EA74-4A4E-A0FC-47D8C8831A15}.Debug|x64.ActiveCfg = Debug|x64
{997E0757-EA74-4A4E-A0FC-47D8C8831A15}.Debug|x64.Build.0 = Debug|x64
{997E0757-EA74-4A4E-A0FC-47D8C8831A15}.Release|x64.ActiveCfg = Release|x64
{997E0757-EA74-4A4E-A0FC-47D8C8831A15}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

View File

@@ -0,0 +1,112 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<CUDAPropsPath Condition="'$(CUDAPropsPath)'==''">$(VCTargetsPath)\BuildCustomizations</CUDAPropsPath>
</PropertyGroup>
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{997E0757-EA74-4A4E-A0FC-47D8C8831A15}</ProjectGuid>
<RootNamespace>MC_EstimatePiInlineP_vs2019</RootNamespace>
<ProjectName>MC_EstimatePiInlineP</ProjectName>
<CudaToolkitCustomDir />
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup>
<ConfigurationType>Application</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v142</PlatformToolset>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)'=='Debug'">
<UseDebugLibraries>true</UseDebugLibraries>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)'=='Release'">
<WholeProgramOptimization>true</WholeProgramOptimization>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
<Import Project="$(CUDAPropsPath)\CUDA 11.6.props" />
</ImportGroup>
<ImportGroup Label="PropertySheets">
<Import Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<IntDir>$(Platform)/$(Configuration)/</IntDir>
<IncludePath>$(IncludePath)</IncludePath>
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisRules />
<CodeAnalysisRuleAssemblies />
</PropertyGroup>
<PropertyGroup Condition="'$(Platform)'=='x64'">
<OutDir>../../../bin/win64/$(Configuration)/</OutDir>
</PropertyGroup>
<ItemDefinitionGroup>
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PreprocessorDefinitions>WIN32;_MBCS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>./;$(CudaToolkitDir)/include;../../../Common;$(CudaToolkitIncludeDir);</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<AdditionalDependencies>curand.lib;cudart_static.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(CudaToolkitLibDir);</AdditionalLibraryDirectories>
<OutputFile>$(OutDir)/MC_EstimatePiInlineP.exe</OutputFile>
</Link>
<CudaCompile>
<CodeGeneration>compute_35,sm_35;compute_37,sm_37;compute_50,sm_50;compute_52,sm_52;compute_60,sm_60;compute_61,sm_61;compute_70,sm_70;compute_75,sm_75;compute_80,sm_80;compute_86,sm_86;</CodeGeneration>
<AdditionalOptions>-Xcompiler "/wd 4819" --threads 0 </AdditionalOptions>
<Include>./;../../../Common</Include>
<Defines>WIN32</Defines>
</CudaCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)'=='Debug'">
<ClCompile>
<Optimization>Disabled</Optimization>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<LinkTimeCodeGeneration>Default</LinkTimeCodeGeneration>
</Link>
<CudaCompile>
<Runtime>MTd</Runtime>
<TargetMachinePlatform>64</TargetMachinePlatform>
</CudaCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)'=='Release'">
<ClCompile>
<Optimization>MaxSpeed</Optimization>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
</ClCompile>
<Link>
<GenerateDebugInformation>false</GenerateDebugInformation>
<LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
</Link>
<CudaCompile>
<Runtime>MT</Runtime>
<TargetMachinePlatform>64</TargetMachinePlatform>
</CudaCompile>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="src/main.cpp" />
<CudaCompile Include="src/piestimator.cu" />
<ClCompile Include="src/test.cpp" />
<ClInclude Include="inc/cudasharedmem.h" />
<ClInclude Include="inc/piestimator.h" />
<ClInclude Include="inc/test.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
<Import Project="$(CUDAPropsPath)\CUDA 11.6.targets" />
</ImportGroup>
</Project>

View File

@@ -0,0 +1,20 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2022
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MC_EstimatePiInlineP", "MC_EstimatePiInlineP_vs2022.vcxproj", "{997E0757-EA74-4A4E-A0FC-47D8C8831A15}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
Release|x64 = Release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{997E0757-EA74-4A4E-A0FC-47D8C8831A15}.Debug|x64.ActiveCfg = Debug|x64
{997E0757-EA74-4A4E-A0FC-47D8C8831A15}.Debug|x64.Build.0 = Debug|x64
{997E0757-EA74-4A4E-A0FC-47D8C8831A15}.Release|x64.ActiveCfg = Release|x64
{997E0757-EA74-4A4E-A0FC-47D8C8831A15}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

View File

@@ -0,0 +1,112 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<CUDAPropsPath Condition="'$(CUDAPropsPath)'==''">$(VCTargetsPath)\BuildCustomizations</CUDAPropsPath>
</PropertyGroup>
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{997E0757-EA74-4A4E-A0FC-47D8C8831A15}</ProjectGuid>
<RootNamespace>MC_EstimatePiInlineP_vs2022</RootNamespace>
<ProjectName>MC_EstimatePiInlineP</ProjectName>
<CudaToolkitCustomDir />
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup>
<ConfigurationType>Application</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v143</PlatformToolset>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)'=='Debug'">
<UseDebugLibraries>true</UseDebugLibraries>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)'=='Release'">
<WholeProgramOptimization>true</WholeProgramOptimization>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
<Import Project="$(CUDAPropsPath)\CUDA 11.6.props" />
</ImportGroup>
<ImportGroup Label="PropertySheets">
<Import Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<IntDir>$(Platform)/$(Configuration)/</IntDir>
<IncludePath>$(IncludePath)</IncludePath>
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisRules />
<CodeAnalysisRuleAssemblies />
</PropertyGroup>
<PropertyGroup Condition="'$(Platform)'=='x64'">
<OutDir>../../../bin/win64/$(Configuration)/</OutDir>
</PropertyGroup>
<ItemDefinitionGroup>
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PreprocessorDefinitions>WIN32;_MBCS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>./;$(CudaToolkitDir)/include;../../../Common;$(CudaToolkitIncludeDir);</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<AdditionalDependencies>curand.lib;cudart_static.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(CudaToolkitLibDir);</AdditionalLibraryDirectories>
<OutputFile>$(OutDir)/MC_EstimatePiInlineP.exe</OutputFile>
</Link>
<CudaCompile>
<CodeGeneration>compute_35,sm_35;compute_37,sm_37;compute_50,sm_50;compute_52,sm_52;compute_60,sm_60;compute_61,sm_61;compute_70,sm_70;compute_75,sm_75;compute_80,sm_80;compute_86,sm_86;</CodeGeneration>
<AdditionalOptions>-Xcompiler "/wd 4819" --threads 0 </AdditionalOptions>
<Include>./;../../../Common</Include>
<Defines>WIN32</Defines>
</CudaCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)'=='Debug'">
<ClCompile>
<Optimization>Disabled</Optimization>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<LinkTimeCodeGeneration>Default</LinkTimeCodeGeneration>
</Link>
<CudaCompile>
<Runtime>MTd</Runtime>
<TargetMachinePlatform>64</TargetMachinePlatform>
</CudaCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)'=='Release'">
<ClCompile>
<Optimization>MaxSpeed</Optimization>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
</ClCompile>
<Link>
<GenerateDebugInformation>false</GenerateDebugInformation>
<LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
</Link>
<CudaCompile>
<Runtime>MT</Runtime>
<TargetMachinePlatform>64</TargetMachinePlatform>
</CudaCompile>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="src/main.cpp" />
<CudaCompile Include="src/piestimator.cu" />
<ClCompile Include="src/test.cpp" />
<ClInclude Include="inc/cudasharedmem.h" />
<ClInclude Include="inc/piestimator.h" />
<ClInclude Include="inc/test.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
<Import Project="$(CUDAPropsPath)\CUDA 11.6.targets" />
</ImportGroup>
</Project>

View File

@@ -0,0 +1,348 @@
################################################################################
# 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.
#
################################################################################
#
# Makefile project only supported on Mac OS X and Linux Platforms)
#
################################################################################
# Location of the CUDA Toolkit
CUDA_PATH ?= /usr/local/cuda
##############################
# start deprecated interface #
##############################
ifeq ($(x86_64),1)
$(info WARNING - x86_64 variable has been deprecated)
$(info WARNING - please use TARGET_ARCH=x86_64 instead)
TARGET_ARCH ?= x86_64
endif
ifeq ($(ARMv7),1)
$(info WARNING - ARMv7 variable has been deprecated)
$(info WARNING - please use TARGET_ARCH=armv7l instead)
TARGET_ARCH ?= armv7l
endif
ifeq ($(aarch64),1)
$(info WARNING - aarch64 variable has been deprecated)
$(info WARNING - please use TARGET_ARCH=aarch64 instead)
TARGET_ARCH ?= aarch64
endif
ifeq ($(ppc64le),1)
$(info WARNING - ppc64le variable has been deprecated)
$(info WARNING - please use TARGET_ARCH=ppc64le instead)
TARGET_ARCH ?= ppc64le
endif
ifneq ($(GCC),)
$(info WARNING - GCC variable has been deprecated)
$(info WARNING - please use HOST_COMPILER=$(GCC) instead)
HOST_COMPILER ?= $(GCC)
endif
ifneq ($(abi),)
$(error ERROR - abi variable has been removed)
endif
############################
# end deprecated interface #
############################
# architecture
HOST_ARCH := $(shell uname -m)
TARGET_ARCH ?= $(HOST_ARCH)
ifneq (,$(filter $(TARGET_ARCH),x86_64 aarch64 sbsa ppc64le armv7l))
ifneq ($(TARGET_ARCH),$(HOST_ARCH))
ifneq (,$(filter $(TARGET_ARCH),x86_64 aarch64 sbsa ppc64le))
TARGET_SIZE := 64
else ifneq (,$(filter $(TARGET_ARCH),armv7l))
TARGET_SIZE := 32
endif
else
TARGET_SIZE := $(shell getconf LONG_BIT)
endif
else
$(error ERROR - unsupported value $(TARGET_ARCH) for TARGET_ARCH!)
endif
# sbsa and aarch64 systems look similar. Need to differentiate them at host level for now.
ifeq ($(HOST_ARCH),aarch64)
ifeq ($(CUDA_PATH)/targets/sbsa-linux,$(shell ls -1d $(CUDA_PATH)/targets/sbsa-linux 2>/dev/null))
HOST_ARCH := sbsa
TARGET_ARCH := sbsa
endif
endif
ifneq ($(TARGET_ARCH),$(HOST_ARCH))
ifeq (,$(filter $(HOST_ARCH)-$(TARGET_ARCH),aarch64-armv7l x86_64-armv7l x86_64-aarch64 x86_64-sbsa x86_64-ppc64le))
$(error ERROR - cross compiling from $(HOST_ARCH) to $(TARGET_ARCH) is not supported!)
endif
endif
# When on native aarch64 system with userspace of 32-bit, change TARGET_ARCH to armv7l
ifeq ($(HOST_ARCH)-$(TARGET_ARCH)-$(TARGET_SIZE),aarch64-aarch64-32)
TARGET_ARCH = armv7l
endif
# operating system
HOST_OS := $(shell uname -s 2>/dev/null | tr "[:upper:]" "[:lower:]")
TARGET_OS ?= $(HOST_OS)
ifeq (,$(filter $(TARGET_OS),linux darwin qnx android))
$(error ERROR - unsupported value $(TARGET_OS) for TARGET_OS!)
endif
# host compiler
ifeq ($(TARGET_OS),darwin)
ifeq ($(shell expr `xcodebuild -version | grep -i xcode | awk '{print $$2}' | cut -d'.' -f1` \>= 5),1)
HOST_COMPILER ?= clang++
endif
else ifneq ($(TARGET_ARCH),$(HOST_ARCH))
ifeq ($(HOST_ARCH)-$(TARGET_ARCH),x86_64-armv7l)
ifeq ($(TARGET_OS),linux)
HOST_COMPILER ?= arm-linux-gnueabihf-g++
else ifeq ($(TARGET_OS),qnx)
ifeq ($(QNX_HOST),)
$(error ERROR - QNX_HOST must be passed to the QNX host toolchain)
endif
ifeq ($(QNX_TARGET),)
$(error ERROR - QNX_TARGET must be passed to the QNX target toolchain)
endif
export QNX_HOST
export QNX_TARGET
HOST_COMPILER ?= $(QNX_HOST)/usr/bin/arm-unknown-nto-qnx6.6.0eabi-g++
else ifeq ($(TARGET_OS),android)
HOST_COMPILER ?= arm-linux-androideabi-g++
endif
else ifeq ($(TARGET_ARCH),aarch64)
ifeq ($(TARGET_OS), linux)
HOST_COMPILER ?= aarch64-linux-gnu-g++
else ifeq ($(TARGET_OS),qnx)
ifeq ($(QNX_HOST),)
$(error ERROR - QNX_HOST must be passed to the QNX host toolchain)
endif
ifeq ($(QNX_TARGET),)
$(error ERROR - QNX_TARGET must be passed to the QNX target toolchain)
endif
export QNX_HOST
export QNX_TARGET
HOST_COMPILER ?= $(QNX_HOST)/usr/bin/q++
else ifeq ($(TARGET_OS), android)
HOST_COMPILER ?= aarch64-linux-android-clang++
endif
else ifeq ($(TARGET_ARCH),sbsa)
HOST_COMPILER ?= aarch64-linux-gnu-g++
else ifeq ($(TARGET_ARCH),ppc64le)
HOST_COMPILER ?= powerpc64le-linux-gnu-g++
endif
endif
HOST_COMPILER ?= g++
NVCC := $(CUDA_PATH)/bin/nvcc -ccbin $(HOST_COMPILER)
# internal flags
NVCCFLAGS := -m${TARGET_SIZE}
CCFLAGS :=
LDFLAGS :=
# build flags
ifeq ($(TARGET_OS),darwin)
LDFLAGS += -rpath $(CUDA_PATH)/lib
CCFLAGS += -arch $(HOST_ARCH)
else ifeq ($(HOST_ARCH)-$(TARGET_ARCH)-$(TARGET_OS),x86_64-armv7l-linux)
LDFLAGS += --dynamic-linker=/lib/ld-linux-armhf.so.3
CCFLAGS += -mfloat-abi=hard
else ifeq ($(TARGET_OS),android)
LDFLAGS += -pie
CCFLAGS += -fpie -fpic -fexceptions
endif
ifneq ($(TARGET_ARCH),$(HOST_ARCH))
ifeq ($(TARGET_ARCH)-$(TARGET_OS),armv7l-linux)
ifneq ($(TARGET_FS),)
GCCVERSIONLTEQ46 := $(shell expr `$(HOST_COMPILER) -dumpversion` \<= 4.6)
ifeq ($(GCCVERSIONLTEQ46),1)
CCFLAGS += --sysroot=$(TARGET_FS)
endif
LDFLAGS += --sysroot=$(TARGET_FS)
LDFLAGS += -rpath-link=$(TARGET_FS)/lib
LDFLAGS += -rpath-link=$(TARGET_FS)/usr/lib
LDFLAGS += -rpath-link=$(TARGET_FS)/usr/lib/arm-linux-gnueabihf
endif
endif
ifeq ($(TARGET_ARCH)-$(TARGET_OS),aarch64-linux)
ifneq ($(TARGET_FS),)
GCCVERSIONLTEQ46 := $(shell expr `$(HOST_COMPILER) -dumpversion` \<= 4.6)
ifeq ($(GCCVERSIONLTEQ46),1)
CCFLAGS += --sysroot=$(TARGET_FS)
endif
LDFLAGS += --sysroot=$(TARGET_FS)
LDFLAGS += -rpath-link=$(TARGET_FS)/lib -L$(TARGET_FS)/lib
LDFLAGS += -rpath-link=$(TARGET_FS)/lib/aarch64-linux-gnu -L$(TARGET_FS)/lib/aarch64-linux-gnu
LDFLAGS += -rpath-link=$(TARGET_FS)/usr/lib -L$(TARGET_FS)/usr/lib
LDFLAGS += -rpath-link=$(TARGET_FS)/usr/lib/aarch64-linux-gnu -L$(TARGET_FS)/usr/lib/aarch64-linux-gnu
LDFLAGS += --unresolved-symbols=ignore-in-shared-libs
CCFLAGS += -isystem=$(TARGET_FS)/usr/include -I$(TARGET_FS)/usr/include -I$(TARGET_FS)/usr/include/libdrm
CCFLAGS += -isystem=$(TARGET_FS)/usr/include/aarch64-linux-gnu -I$(TARGET_FS)/usr/include/aarch64-linux-gnu
endif
endif
ifeq ($(TARGET_ARCH)-$(TARGET_OS),aarch64-qnx)
NVCCFLAGS += -D_QNX_SOURCE
NVCCFLAGS += --qpp-config 8.3.0,gcc_ntoaarch64le
CCFLAGS += -DWIN_INTERFACE_CUSTOM -I/usr/include/aarch64-qnx-gnu
LDFLAGS += -lsocket
LDFLAGS += -L/usr/lib/aarch64-qnx-gnu
CCFLAGS += "-Wl\,-rpath-link\,/usr/lib/aarch64-qnx-gnu"
ifdef TARGET_OVERRIDE
LDFLAGS += -lslog2
endif
ifneq ($(TARGET_FS),)
LDFLAGS += -L$(TARGET_FS)/usr/lib
CCFLAGS += "-Wl\,-rpath-link\,$(TARGET_FS)/usr/lib"
LDFLAGS += -L$(TARGET_FS)/usr/libnvidia
CCFLAGS += "-Wl\,-rpath-link\,$(TARGET_FS)/usr/libnvidia"
CCFLAGS += -I$(TARGET_FS)/../include
endif
endif
endif
ifdef TARGET_OVERRIDE # cuda toolkit targets override
NVCCFLAGS += -target-dir $(TARGET_OVERRIDE)
endif
# Install directory of different arch
CUDA_INSTALL_TARGET_DIR :=
ifeq ($(TARGET_ARCH)-$(TARGET_OS),armv7l-linux)
CUDA_INSTALL_TARGET_DIR = targets/armv7-linux-gnueabihf/
else ifeq ($(TARGET_ARCH)-$(TARGET_OS),aarch64-linux)
CUDA_INSTALL_TARGET_DIR = targets/aarch64-linux/
else ifeq ($(TARGET_ARCH)-$(TARGET_OS),sbsa-linux)
CUDA_INSTALL_TARGET_DIR = targets/sbsa-linux/
else ifeq ($(TARGET_ARCH)-$(TARGET_OS),armv7l-android)
CUDA_INSTALL_TARGET_DIR = targets/armv7-linux-androideabi/
else ifeq ($(TARGET_ARCH)-$(TARGET_OS),aarch64-android)
CUDA_INSTALL_TARGET_DIR = targets/aarch64-linux-androideabi/
else ifeq ($(TARGET_ARCH)-$(TARGET_OS),armv7l-qnx)
CUDA_INSTALL_TARGET_DIR = targets/ARMv7-linux-QNX/
else ifeq ($(TARGET_ARCH)-$(TARGET_OS),aarch64-qnx)
CUDA_INSTALL_TARGET_DIR = targets/aarch64-qnx/
else ifeq ($(TARGET_ARCH),ppc64le)
CUDA_INSTALL_TARGET_DIR = targets/ppc64le-linux/
endif
# Debug build flags
ifeq ($(dbg),1)
NVCCFLAGS += -g -G
BUILD_TYPE := debug
else
BUILD_TYPE := release
endif
ALL_CCFLAGS :=
ALL_CCFLAGS += $(NVCCFLAGS)
ALL_CCFLAGS += $(EXTRA_NVCCFLAGS)
ALL_CCFLAGS += $(addprefix -Xcompiler ,$(CCFLAGS))
ALL_CCFLAGS += $(addprefix -Xcompiler ,$(EXTRA_CCFLAGS))
SAMPLE_ENABLED := 1
ALL_LDFLAGS :=
ALL_LDFLAGS += $(ALL_CCFLAGS)
ALL_LDFLAGS += $(addprefix -Xlinker ,$(LDFLAGS))
ALL_LDFLAGS += $(addprefix -Xlinker ,$(EXTRA_LDFLAGS))
# Common includes and paths for CUDA
INCLUDES := -I../../../Common
LIBRARIES :=
################################################################################
# Gencode arguments
ifeq ($(TARGET_ARCH),$(filter $(TARGET_ARCH),armv7l aarch64 sbsa))
SMS ?= 53 61 70 72 75 80 86 87
else
SMS ?= 35 37 50 52 60 61 70 75 80 86
endif
ifeq ($(SMS),)
$(info >>> WARNING - no SM architectures have been specified - waiving sample <<<)
SAMPLE_ENABLED := 0
endif
ifeq ($(GENCODE_FLAGS),)
# Generate SASS code for each SM architecture listed in $(SMS)
$(foreach sm,$(SMS),$(eval GENCODE_FLAGS += -gencode arch=compute_$(sm),code=sm_$(sm)))
# Generate PTX code from the highest SM architecture in $(SMS) to guarantee forward-compatibility
HIGHEST_SM := $(lastword $(sort $(SMS)))
ifneq ($(HIGHEST_SM),)
GENCODE_FLAGS += -gencode arch=compute_$(HIGHEST_SM),code=compute_$(HIGHEST_SM)
endif
endif
ALL_CCFLAGS += --threads 0 --std=c++11
LIBRARIES += -lcurand
ifeq ($(SAMPLE_ENABLED),0)
EXEC ?= @echo "[@]"
endif
################################################################################
# Target rules
all: build
build: MC_EstimatePiInlineP
check.deps:
ifeq ($(SAMPLE_ENABLED),0)
@echo "Sample will be waived due to the above missing dependencies"
else
@echo "Sample is ready - all dependencies have been met"
endif
main.o:src/main.cpp
$(EXEC) $(NVCC) $(INCLUDES) $(ALL_CCFLAGS) $(GENCODE_FLAGS) -o $@ -c $<
piestimator.o:src/piestimator.cu
$(EXEC) $(NVCC) $(INCLUDES) $(ALL_CCFLAGS) $(GENCODE_FLAGS) -o $@ -c $<
test.o:src/test.cpp
$(EXEC) $(NVCC) $(INCLUDES) $(ALL_CCFLAGS) $(GENCODE_FLAGS) -o $@ -c $<
MC_EstimatePiInlineP: main.o piestimator.o test.o
$(EXEC) $(NVCC) $(ALL_LDFLAGS) $(GENCODE_FLAGS) -o $@ $+ $(LIBRARIES)
$(EXEC) mkdir -p ../../../bin/$(TARGET_ARCH)/$(TARGET_OS)/$(BUILD_TYPE)
$(EXEC) cp $@ ../../../bin/$(TARGET_ARCH)/$(TARGET_OS)/$(BUILD_TYPE)
run: build
$(EXEC) ./MC_EstimatePiInlineP
testrun: build
clean:
rm -f MC_EstimatePiInlineP main.o piestimator.o test.o
rm -rf ../../../bin/$(TARGET_ARCH)/$(TARGET_OS)/$(BUILD_TYPE)/MC_EstimatePiInlineP
clobber: clean

View File

@@ -0,0 +1,91 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE entry SYSTEM "SamplesInfo.dtd">
<entry>
<name>MC_EstimatePiInlineP</name>
<cuda_api_list>
<toolkit>cudaFree</toolkit>
<toolkit>cudaFuncGetAttributes</toolkit>
<toolkit>cudaGetDeviceCount</toolkit>
<toolkit>cudaMalloc</toolkit>
<toolkit>cudaSetDevice</toolkit>
<toolkit>cudaMemcpy</toolkit>
<toolkit>cudaGetErrorString</toolkit>
<toolkit>cudaGetDeviceProperties</toolkit>
</cuda_api_list>
<description><![CDATA[This sample uses Monte Carlo simulation for Estimation of Pi (using inline PRNG). This sample also uses the NVIDIA CURAND library.]]></description>
<devicecompilation>whole</devicecompilation>
<includepaths>
<path>./</path>
<path>../</path>
<path>../../../Common</path>
</includepaths>
<keyconcepts>
<concept level="advanced">Random Number Generator</concept>
<concept level="advanced">Computational Finance</concept>
<concept level="advanced">CURAND Library</concept>
</keyconcepts>
<keywords>
<keyword>CUDA</keyword>
<keyword>CURAND</keyword>
<keyword>GPGPU</keyword>
<keyword>Monte Carlo</keyword>
<keyword>rng</keyword>
<keyword>prng</keyword>
<keyword>qrng</keyword>
<keyword>random number</keyword>
</keywords>
<libraries>
<library>curand</library>
</libraries>
<librarypaths>
</librarypaths>
<nsight_eclipse>true</nsight_eclipse>
<primary_file>src\main.cpp</primary_file>
<required_dependencies>
<dependency>CURAND</dependency>
</required_dependencies>
<scopes>
<scope>1:CUDA Advanced Topics</scope>
</scopes>
<sm-arch>sm35</sm-arch>
<sm-arch>sm37</sm-arch>
<sm-arch>sm50</sm-arch>
<sm-arch>sm52</sm-arch>
<sm-arch>sm53</sm-arch>
<sm-arch>sm60</sm-arch>
<sm-arch>sm61</sm-arch>
<sm-arch>sm70</sm-arch>
<sm-arch>sm72</sm-arch>
<sm-arch>sm75</sm-arch>
<sm-arch>sm80</sm-arch>
<sm-arch>sm86</sm-arch>
<sm-arch>sm87</sm-arch>
<supported_envs>
<env>
<arch>x86_64</arch>
<platform>linux</platform>
</env>
<env>
<platform>windows7</platform>
</env>
<env>
<arch>x86_64</arch>
<platform>macosx</platform>
</env>
<env>
<arch>arm</arch>
</env>
<env>
<arch>sbsa</arch>
</env>
<env>
<arch>ppc64le</arch>
<platform>linux</platform>
</env>
</supported_envs>
<supported_sm_architectures>
<include>all</include>
</supported_sm_architectures>
<title>Monte Carlo Estimation of Pi (inline PRNG)</title>
<type>exe</type>
</entry>

View File

@@ -0,0 +1,74 @@
# MC_EstimatePiInlineP - Monte Carlo Estimation of Pi (inline PRNG)
## Description
This sample uses Monte Carlo simulation for Estimation of Pi (using inline PRNG). This sample also uses the NVIDIA CURAND library.
## Key Concepts
Random Number Generator, Computational Finance, CURAND Library
## Supported SM Architectures
[SM 3.5 ](https://developer.nvidia.com/cuda-gpus) [SM 3.7 ](https://developer.nvidia.com/cuda-gpus) [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)
## Supported OSes
Linux, Windows
## Supported CPU Architecture
x86_64, ppc64le, armv7l
## CUDA APIs involved
### [CUDA Runtime API](http://docs.nvidia.com/cuda/cuda-runtime-api/index.html)
cudaFree, cudaFuncGetAttributes, cudaGetDeviceCount, cudaMalloc, cudaSetDevice, cudaMemcpy, cudaGetErrorString, cudaGetDeviceProperties
## Dependencies needed to build/run
[CURAND](../../README.md#curand)
## Prerequisites
Download and install the [CUDA Toolkit 11.6](https://developer.nvidia.com/cuda-downloads) for your corresponding platform.
Make sure the dependencies mentioned in [Dependencies]() section above are installed.
## Build and Run
### Windows
The Windows samples are built using the Visual Studio IDE. Solution files (.sln) are provided for each supported version of Visual Studio, using the format:
```
*_vs<version>.sln - for Visual Studio <version>
```
Each individual sample has its own set of solution files in its directory:
To build/examine all the samples at once, the complete solution files should be used. To build/examine a single sample, the individual sample solution files should be used.
> **Note:** Some samples require that the Microsoft DirectX SDK (June 2010 or newer) be installed and that the VC++ directory paths are properly set up (**Tools > Options...**). Check DirectX Dependencies section for details."
### Linux
The Linux samples are built using makefiles. To use the makefiles, change the current directory to the sample directory you wish to build, and run make:
```
$ cd <sample_dir>
$ make
```
The samples makefiles can take advantage of certain options:
* **TARGET_ARCH=<arch>** - cross-compile targeting a specific architecture. Allowed architectures are x86_64, ppc64le, armv7l.
By default, TARGET_ARCH is set to HOST_ARCH. On a x86_64 machine, not setting TARGET_ARCH is the equivalent of setting TARGET_ARCH=x86_64.<br/>
`$ make TARGET_ARCH=x86_64` <br/> `$ make TARGET_ARCH=ppc64le` <br/> `$ make TARGET_ARCH=armv7l` <br/>
See [here](http://docs.nvidia.com/cuda/cuda-samples/index.html#cross-samples) for more details.
* **dbg=1** - build with debug symbols
```
$ make dbg=1
```
* **SMS="A B ..."** - override the SM architectures for which the sample will be built, where `"A B ..."` is a space-delimited list of SM architectures. For example, to generate SASS for SM 50 and SM 60, use `SMS="50 60"`.
```
$ make SMS="50 60"
```
* **HOST_COMPILER=<host_compiler>** - override the default g++ host compiler. See the [Linux Installation Guide](http://docs.nvidia.com/cuda/cuda-installation-guide-linux/index.html#system-requirements) for a list of supported host compilers.
```
$ make HOST_COMPILER=g++
```
## References (for more details)

View File

@@ -0,0 +1,100 @@
/* 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 CUDASHAREDMEM_H
#define CUDASHAREDMEM_H
//****************************************************************************
// Because dynamically sized shared memory arrays are declared "extern",
// we can't templatize them directly. To get around this, we declare a
// simple wrapper struct that will declare the extern array with a different
// name depending on the type. This avoids compiler errors about duplicate
// definitions.
//
// To use dynamically allocated shared memory in a templatized __global__ or
// __device__ function, just replace code like this:
// template<class T>
// __global__ void
// foo( T* g_idata, T* g_odata)
// {
// // Shared mem size is determined by the host app at run time
// extern __shared__ T sdata[];
// ...
// x = sdata[i];
// sdata[i] = x;
// ...
// }
//
// With this:
// template<class T>
// __global__ void
// foo( T* g_idata, T* g_odata)
// {
// // Shared mem size is determined by the host app at run time
// SharedMemory<T> sdata;
// ...
// x = sdata[i];
// sdata[i] = x;
// ...
// }
//****************************************************************************
// This is the un-specialized struct. Note that we prevent instantiation of
// this struct by making it abstract (i.e. with pure virtual methods).
template <typename T>
struct SharedMemory {
// Ensure that we won't compile any un-specialized types
virtual __device__ T &operator*() = 0;
virtual __device__ T &operator[](int i) = 0;
};
#define BUILD_SHAREDMEMORY_TYPE(t, n) \
template <> \
struct SharedMemory<t> { \
__device__ t &operator*() { \
extern __shared__ t n[]; \
return *n; \
} \
__device__ t &operator[](int i) { \
extern __shared__ t n[]; \
return n[i]; \
} \
}
BUILD_SHAREDMEMORY_TYPE(int, s_int);
BUILD_SHAREDMEMORY_TYPE(unsigned int, s_uint);
BUILD_SHAREDMEMORY_TYPE(char, s_char);
BUILD_SHAREDMEMORY_TYPE(unsigned char, s_uchar);
BUILD_SHAREDMEMORY_TYPE(short, s_short);
BUILD_SHAREDMEMORY_TYPE(unsigned short, s_ushort);
BUILD_SHAREDMEMORY_TYPE(long, s_long);
BUILD_SHAREDMEMORY_TYPE(unsigned long, s_ulong);
BUILD_SHAREDMEMORY_TYPE(bool, s_bool);
BUILD_SHAREDMEMORY_TYPE(float, s_float);
BUILD_SHAREDMEMORY_TYPE(double, s_double);
#endif

View File

@@ -0,0 +1,45 @@
/* 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 PIESTIMATOR_H
#define PIESTIMATOR_H
template <typename Real>
class PiEstimator {
public:
PiEstimator(unsigned int numSims, unsigned int device,
unsigned int threadBlockSize, unsigned int seed);
Real operator()();
private:
unsigned int m_seed;
unsigned int m_numSims;
unsigned int m_device;
unsigned int m_threadBlockSize;
};
#endif

View File

@@ -0,0 +1,59 @@
/* 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 TEST_H
#define TEST_H
template <typename Real>
struct Test {
Test() : pass(false){};
int device;
unsigned int numSims;
unsigned int threadBlockSize;
unsigned int seed;
bool pass;
double elapsedTime;
bool operator()();
};
// Defaults are arbitrary to give sensible runtime
#define k_sims_min 100000
#define k_sims_max 10000000
#define k_sims_def 100000
#define k_sims_qa 100000
#define k_bsize_min 32
#define k_bsize_def 128
#define k_bsize_qa 128
#define k_seed_def 1234
// Target value
#define PI 3.14159265359
#endif

View File

@@ -0,0 +1,254 @@
/* 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.
*/
///////////////////////////////////////////////////////////////////////////////
// Monte Carlo: Estimate Pi
// ========================
//
// This sample demonstrates a very simple Monte Carlo estimation for Pi.
//
// This file, main.cpp, contains the setup information to run the test, for
// example parsing the command line and integrating this sample with the
// samples framework. As such it is perhaps less interesting than the guts of
// the sample. Readers wishing to skip the clutter are advised to skip straight
// to Test.operator() in test.cpp.
///////////////////////////////////////////////////////////////////////////////
#include <cuda_runtime.h>
#include <helper_cuda.h>
#include <iomanip>
#include <iostream>
#include <stdexcept>
#include "../inc/test.h"
// SDK information
static const char *printfFile = "MonteCarloEstimatePiInlineP.txt";
// Forward declarations
void showHelp(const int argc, const char **argv);
template <typename Real>
void runTest(int argc, const char **argv);
int main(int argc, char **argv) {
using std::invalid_argument;
using std::string;
// Open the log file
printf("Monte Carlo Estimate Pi (with inline PRNG)\n");
printf("==========================================\n\n");
// If help flag is set, display help and exit immediately
if (checkCmdLineFlag(argc, (const char **)argv, "help")) {
printf("Displaying help on console\n");
showHelp(argc, (const char **)argv);
exit(EXIT_SUCCESS);
}
// Check the precision (checked against the device capability later)
try {
char *value;
if (getCmdLineArgumentString(argc, (const char **)argv, "precision",
&value)) {
// Check requested precision is valid
string prec(value);
if (prec.compare("single") == 0 || prec.compare("\"single\"") == 0) {
runTest<float>(argc, (const char **)argv);
} else if (prec.compare("double") == 0 ||
prec.compare("\"double\"") == 0) {
runTest<double>(argc, (const char **)argv);
} else {
printf(
"specified precision (%s) is invalid, must be \"single\" or "
"\"double\".\n",
value);
throw invalid_argument("precision");
}
} else {
runTest<float>(argc, (const char **)argv);
}
} catch (invalid_argument &e) {
printf("invalid command line argument (%s)\n", e.what());
exit(EXIT_FAILURE);
}
// Finish
exit(EXIT_SUCCESS);
}
template <typename Real>
void runTest(int argc, const char **argv) {
using std::invalid_argument;
using std::runtime_error;
try {
Test<Real> test;
int deviceCount = 0;
cudaError_t cudaResult = cudaSuccess;
// by default specify GPU Device == 0
test.device = 0;
// Get number of available devices
cudaResult = cudaGetDeviceCount(&deviceCount);
if (cudaResult != cudaSuccess) {
printf("could not get device count (%s).\n",
cudaGetErrorString(cudaResult));
throw runtime_error("cudaGetDeviceCount");
}
// (default parameters)
test.numSims = k_sims_qa;
test.threadBlockSize = k_bsize_qa;
test.seed = k_seed_def;
{
char *value = 0;
if (getCmdLineArgumentString(argc, argv, "device", &value)) {
test.device = (int)atoi(value);
if (test.device >= deviceCount) {
printf(
"invalid target device specified on command line (device %d does "
"not exist).\n",
test.device);
throw invalid_argument("device");
}
} else {
test.device = gpuGetMaxGflopsDeviceId();
}
if (getCmdLineArgumentString(argc, argv, "sims", &value)) {
test.numSims = (unsigned int)atoi(value);
printf("number of simulations = %d\n", test.numSims);
if (test.numSims < k_sims_min || test.numSims > k_sims_max) {
printf(
"specified number of simulations (%d) is invalid, must be "
"between %d and %d.\n",
test.numSims, k_sims_min, k_sims_max);
throw invalid_argument("sims");
}
} else {
test.numSims = k_sims_def;
}
if (getCmdLineArgumentString(argc, argv, "block-size", &value)) {
// Determine max threads per block
cudaDeviceProp deviceProperties;
cudaResult = cudaGetDeviceProperties(&deviceProperties, test.device);
if (cudaResult != cudaSuccess) {
printf("unable to get device properties for device %d.\n",
test.device);
throw runtime_error("cudaGetDeviceProperties");
}
// Check requested size is valid
test.threadBlockSize = (unsigned int)atoi(value);
printf("block size = %d\n", test.threadBlockSize);
if (test.threadBlockSize < k_bsize_min ||
test.threadBlockSize > static_cast<unsigned int>(
deviceProperties.maxThreadsPerBlock)) {
printf(
"specified block size (%d) is invalid, must be between %d and %d "
"for device %d.\n",
test.threadBlockSize, k_bsize_min,
deviceProperties.maxThreadsPerBlock, test.device);
throw invalid_argument("block-size");
}
if (test.threadBlockSize & test.threadBlockSize - 1) {
printf(
"specified block size (%d) is invalid, must be a power of two "
"(see reduction function).\n",
test.threadBlockSize);
throw invalid_argument("block-size");
}
} else {
test.threadBlockSize = k_bsize_def;
}
if (getCmdLineArgumentString(argc, argv, "seed", &value)) {
// Check requested seed is valid
test.seed = (unsigned int)atoi(value);
printf("seed = %d\n", test.seed);
if (test.seed == 0) {
printf("specified seed (%d) is invalid, must be non-zero.\n",
test.seed);
throw invalid_argument("seed");
}
} else {
test.seed = k_seed_def;
}
}
// Execute
test();
} catch (invalid_argument &e) {
printf("invalid command line argument (%s)\n", e.what());
exit(EXIT_FAILURE);
} catch (runtime_error &e) {
printf("runtime error (%s)\n", e.what());
exit(EXIT_FAILURE);
}
}
void showHelp(int argc, const char **argv) {
using std::cout;
using std::endl;
using std::left;
using std::setw;
if (argc > 0) {
cout << endl << argv[0] << endl;
}
cout << endl << "Syntax:" << endl;
cout << left;
cout << " " << setw(20) << "--device=<device>"
<< "Specify device to use for execution" << endl;
cout << " " << setw(20) << "--sims=<N>"
<< "Specify number of Monte Carlo simulations" << endl;
cout << " " << setw(20) << "--block-size=<N>"
<< "Specify number of threads per block" << endl;
cout << " " << setw(20) << "--seed=<N>"
<< "Specify the seed to use for the random number generator" << endl;
cout << " " << setw(20) << "--precision=<P>"
<< "Specify the precision (\"single\" or \"double\")" << endl;
cout << endl;
cout << " " << setw(20) << "--noprompt"
<< "Skip prompt before exit" << endl;
cout << endl;
}

View File

@@ -0,0 +1,283 @@
/* 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.
*/
#include "../inc/piestimator.h"
#include <string>
#include <vector>
#include <numeric>
#include <stdexcept>
#include <typeinfo>
#include <cuda_runtime.h>
#include <cooperative_groups.h>
namespace cg = cooperative_groups;
#include <curand_kernel.h>
using std::string;
using std::vector;
// RNG init kernel
__global__ void initRNG(curandState *const rngStates, const unsigned int seed) {
// Determine thread ID
unsigned int tid = blockIdx.x * blockDim.x + threadIdx.x;
// Initialise the RNG
curand_init(seed, tid, 0, &rngStates[tid]);
}
__device__ unsigned int reduce_sum(unsigned int in, cg::thread_block cta) {
extern __shared__ unsigned int sdata[];
// Perform first level of reduction:
// - Write to shared memory
unsigned int ltid = threadIdx.x;
sdata[ltid] = in;
cg::sync(cta);
// Do reduction in shared mem
for (unsigned int s = blockDim.x / 2; s > 0; s >>= 1) {
if (ltid < s) {
sdata[ltid] += sdata[ltid + s];
}
cg::sync(cta);
}
return sdata[0];
}
__device__ inline void getPoint(float &x, float &y, curandState &state) {
x = curand_uniform(&state);
y = curand_uniform(&state);
}
__device__ inline void getPoint(double &x, double &y, curandState &state) {
x = curand_uniform_double(&state);
y = curand_uniform_double(&state);
}
// Estimator kernel
template <typename Real>
__global__ void computeValue(unsigned int *const results,
curandState *const rngStates,
const unsigned int numSims) {
// Handle to thread block group
cg::thread_block cta = cg::this_thread_block();
// Determine thread ID
unsigned int bid = blockIdx.x;
unsigned int tid = blockIdx.x * blockDim.x + threadIdx.x;
unsigned int step = gridDim.x * blockDim.x;
// Initialise the RNG
curandState localState = rngStates[tid];
// Count the number of points which lie inside the unit quarter-circle
unsigned int pointsInside = 0;
for (unsigned int i = tid; i < numSims; i += step) {
Real x;
Real y;
getPoint(x, y, localState);
Real l2norm2 = x * x + y * y;
if (l2norm2 < static_cast<Real>(1)) {
pointsInside++;
}
}
// Reduce within the block
pointsInside = reduce_sum(pointsInside, cta);
// Store the result
if (threadIdx.x == 0) {
results[bid] = pointsInside;
}
}
template <typename Real>
PiEstimator<Real>::PiEstimator(unsigned int numSims, unsigned int device,
unsigned int threadBlockSize, unsigned int seed)
: m_numSims(numSims),
m_device(device),
m_threadBlockSize(threadBlockSize),
m_seed(seed) {}
template <typename Real>
Real PiEstimator<Real>::operator()() {
cudaError_t cudaResult = cudaSuccess;
struct cudaDeviceProp deviceProperties;
struct cudaFuncAttributes funcAttributes;
// Get device properties
cudaResult = cudaGetDeviceProperties(&deviceProperties, m_device);
if (cudaResult != cudaSuccess) {
string msg("Could not get device properties: ");
msg += cudaGetErrorString(cudaResult);
throw std::runtime_error(msg);
}
// Check precision is valid
if (typeid(Real) == typeid(double) &&
(deviceProperties.major < 1 ||
(deviceProperties.major == 1 && deviceProperties.minor < 3))) {
throw std::runtime_error("Device does not have double precision support");
}
// Attach to GPU
cudaResult = cudaSetDevice(m_device);
if (cudaResult != cudaSuccess) {
string msg("Could not set CUDA device: ");
msg += cudaGetErrorString(cudaResult);
throw std::runtime_error(msg);
}
// Determine how to divide the work between cores
dim3 block;
dim3 grid;
block.x = m_threadBlockSize;
grid.x = (m_numSims + m_threadBlockSize - 1) / m_threadBlockSize;
// Aim to launch around ten or more times as many blocks as there
// are multiprocessors on the target device.
unsigned int blocksPerSM = 10;
unsigned int numSMs = deviceProperties.multiProcessorCount;
while (grid.x > 2 * blocksPerSM * numSMs) {
grid.x >>= 1;
}
// Get initRNG function properties and check the maximum block size
cudaResult = cudaFuncGetAttributes(&funcAttributes, initRNG);
if (cudaResult != cudaSuccess) {
string msg("Could not get function attributes: ");
msg += cudaGetErrorString(cudaResult);
throw std::runtime_error(msg);
}
if (block.x > (unsigned int)funcAttributes.maxThreadsPerBlock) {
throw std::runtime_error(
"Block X dimension is too large for initRNG kernel");
}
// Get computeValue function properties and check the maximum block size
cudaResult = cudaFuncGetAttributes(&funcAttributes, computeValue<Real>);
if (cudaResult != cudaSuccess) {
string msg("Could not get function attributes: ");
msg += cudaGetErrorString(cudaResult);
throw std::runtime_error(msg);
}
if (block.x > (unsigned int)funcAttributes.maxThreadsPerBlock) {
throw std::runtime_error(
"Block X dimension is too large for computeValue kernel");
}
// Check the dimensions are valid
if (block.x > (unsigned int)deviceProperties.maxThreadsDim[0]) {
throw std::runtime_error("Block X dimension is too large for device");
}
if (grid.x > (unsigned int)deviceProperties.maxGridSize[0]) {
throw std::runtime_error("Grid X dimension is too large for device");
}
// Allocate memory for RNG states
curandState *d_rngStates = 0;
cudaResult =
cudaMalloc((void **)&d_rngStates, grid.x * block.x * sizeof(curandState));
if (cudaResult != cudaSuccess) {
string msg("Could not allocate memory on device for RNG states: ");
msg += cudaGetErrorString(cudaResult);
throw std::runtime_error(msg);
}
// Allocate memory for result
// Each thread block will produce one result
unsigned int *d_results = 0;
cudaResult = cudaMalloc((void **)&d_results, grid.x * sizeof(unsigned int));
if (cudaResult != cudaSuccess) {
string msg("Could not allocate memory on device for partial results: ");
msg += cudaGetErrorString(cudaResult);
throw std::runtime_error(msg);
}
// Initialise RNG
initRNG<<<grid, block>>>(d_rngStates, m_seed);
// Count the points inside unit quarter-circle
computeValue<Real><<<grid, block, block.x * sizeof(unsigned int)>>>(
d_results, d_rngStates, m_numSims);
// Copy partial results back
vector<unsigned int> results(grid.x);
cudaResult = cudaMemcpy(&results[0], d_results, grid.x * sizeof(unsigned int),
cudaMemcpyDeviceToHost);
if (cudaResult != cudaSuccess) {
string msg("Could not copy partial results to host: ");
msg += cudaGetErrorString(cudaResult);
throw std::runtime_error(msg);
}
// Complete sum-reduction on host
Real value =
static_cast<Real>(std::accumulate(results.begin(), results.end(), 0));
// Determine the proportion of points inside the quarter-circle,
// i.e. the area of the unit quarter-circle
value /= m_numSims;
// Value is currently an estimate of the area of a unit quarter-circle, so we
// can scale to a full circle by multiplying by four. Now since the area of a
// circle is pi * r^2, and r is one, the value will be an estimate for the
// value of pi.
value *= 4;
// Cleanup
if (d_rngStates) {
cudaFree(d_rngStates);
d_rngStates = 0;
}
if (d_results) {
cudaFree(d_results);
d_results = 0;
}
return value;
}
// Explicit template instantiation
template class PiEstimator<float>;
template class PiEstimator<double>;

View File

@@ -0,0 +1,112 @@
/* 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.
*/
#include "../inc/test.h"
#include <sstream>
#include <iomanip>
#include <stdexcept>
#include <memory>
#include <iostream>
#include <cassert>
#include <typeinfo>
#include <stdio.h>
#include <helper_timer.h>
#include <math.h>
#include <cuda_runtime.h>
#include "../inc/piestimator.h"
template <typename Real>
bool Test<Real>::operator()() {
using std::endl;
using std::setw;
using std::stringstream;
StopWatchInterface *timer = NULL;
sdkCreateTimer(&timer);
// Get device properties
struct cudaDeviceProp deviceProperties;
cudaError_t cudaResult = cudaGetDeviceProperties(&deviceProperties, device);
if (cudaResult != cudaSuccess) {
std::string msg("Could not get device properties: ");
msg += cudaGetErrorString(cudaResult);
throw std::runtime_error(msg);
}
// Evaluate on GPU
printf("Estimating Pi on GPU (%s)\n\n", deviceProperties.name);
PiEstimator<Real> estimator(numSims, device, threadBlockSize, seed);
sdkStartTimer(&timer);
Real result = estimator();
sdkStopTimer(&timer);
elapsedTime = sdkGetAverageTimerValue(&timer) / 1000.0f;
// Tolerance to compare result with expected
// This is just to check that nothing has gone very wrong with the
// test, the actual accuracy of the result depends on the number of
// Monte Carlo trials
const Real tolerance = static_cast<Real>(0.01);
// Display results
Real abserror = fabs(result - static_cast<Real>(PI));
Real relerror = abserror / static_cast<float>(PI);
printf("Precision: %s\n",
(typeid(Real) == typeid(double)) ? "double" : "single");
printf("Number of sims: %d\n", numSims);
printf("Tolerance: %e\n", tolerance);
printf("GPU result: %e\n", result);
printf("Expected: %e\n", PI);
printf("Absolute error: %e\n", abserror);
printf("Relative error: %e\n\n", relerror);
// Check result
if (relerror > tolerance) {
printf("computed result (%e) does not match expected result (%e).\n",
result, PI);
pass = false;
} else {
pass = true;
}
// Print results
printf(
"MonteCarloEstimatePiInlineP, Performance = %.2f sims/s, Time = "
"%.2f(ms), NumDevsUsed = %u, Blocksize = %u\n",
numSims / elapsedTime, elapsedTime * 1000.0f, 1, threadBlockSize);
sdkDeleteTimer(&timer);
return pass;
}
// Explicit template instantiation
template struct Test<float>;
template struct Test<double>;

View 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
}

View File

@@ -0,0 +1,7 @@
{
"recommendations": [
"nvidia.nsight-vscode-edition",
"ms-vscode.cpptools",
"ms-vscode.makefile-tools"
]
}

View File

@@ -0,0 +1,10 @@
{
"configurations": [
{
"name": "CUDA C++: Launch",
"type": "cuda-gdb",
"request": "launch",
"program": "${workspaceFolder}/MC_EstimatePiInlineQ"
}
]
}

View File

@@ -0,0 +1,15 @@
{
"version": "2.0.0",
"tasks": [
{
"label": "sample",
"type": "shell",
"command": "make dbg=1",
"problemMatcher": ["$nvcc"],
"group": {
"kind": "build",
"isDefault": true
}
}
]
}

View File

@@ -0,0 +1,20 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2017
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MC_EstimatePiInlineQ", "MC_EstimatePiInlineQ_vs2017.vcxproj", "{997E0757-EA74-4A4E-A0FC-47D8C8831A15}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
Release|x64 = Release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{997E0757-EA74-4A4E-A0FC-47D8C8831A15}.Debug|x64.ActiveCfg = Debug|x64
{997E0757-EA74-4A4E-A0FC-47D8C8831A15}.Debug|x64.Build.0 = Debug|x64
{997E0757-EA74-4A4E-A0FC-47D8C8831A15}.Release|x64.ActiveCfg = Release|x64
{997E0757-EA74-4A4E-A0FC-47D8C8831A15}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

View File

@@ -0,0 +1,116 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<CUDAPropsPath Condition="'$(CUDAPropsPath)'==''">$(VCTargetsPath)\BuildCustomizations</CUDAPropsPath>
</PropertyGroup>
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{997E0757-EA74-4A4E-A0FC-47D8C8831A15}</ProjectGuid>
<RootNamespace>MC_EstimatePiInlineQ_vs2017</RootNamespace>
<ProjectName>MC_EstimatePiInlineQ</ProjectName>
<CudaToolkitCustomDir />
</PropertyGroup>
<PropertyGroup Condition="'$(WindowsTargetPlatformVersion)'==''">
<LatestTargetPlatformVersion>$([Microsoft.Build.Utilities.ToolLocationHelper]::GetLatestSDKTargetPlatformVersion('Windows', '10.0'))</LatestTargetPlatformVersion>
<WindowsTargetPlatformVersion Condition="'$(WindowsTargetPlatformVersion)' == ''">$(LatestTargetPlatformVersion)</WindowsTargetPlatformVersion>
<TargetPlatformVersion>$(WindowsTargetPlatformVersion)</TargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup>
<ConfigurationType>Application</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v141</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)'=='Debug'">
<UseDebugLibraries>true</UseDebugLibraries>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)'=='Release'">
<WholeProgramOptimization>true</WholeProgramOptimization>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
<Import Project="$(CUDAPropsPath)\CUDA 11.6.props" />
</ImportGroup>
<ImportGroup Label="PropertySheets">
<Import Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<IntDir>$(Platform)/$(Configuration)/</IntDir>
<IncludePath>$(IncludePath)</IncludePath>
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisRules />
<CodeAnalysisRuleAssemblies />
</PropertyGroup>
<PropertyGroup Condition="'$(Platform)'=='x64'">
<OutDir>../../../bin/win64/$(Configuration)/</OutDir>
</PropertyGroup>
<ItemDefinitionGroup>
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PreprocessorDefinitions>WIN32;_MBCS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>./;$(CudaToolkitDir)/include;../../../Common;$(CudaToolkitIncludeDir);</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<AdditionalDependencies>curand.lib;cudart_static.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(CudaToolkitLibDir);</AdditionalLibraryDirectories>
<OutputFile>$(OutDir)/MC_EstimatePiInlineQ.exe</OutputFile>
</Link>
<CudaCompile>
<CodeGeneration>compute_35,sm_35;compute_37,sm_37;compute_50,sm_50;compute_52,sm_52;compute_60,sm_60;compute_61,sm_61;compute_70,sm_70;compute_75,sm_75;compute_80,sm_80;compute_86,sm_86;</CodeGeneration>
<AdditionalOptions>-Xcompiler "/wd 4819" --threads 0 </AdditionalOptions>
<Include>./;../../../Common</Include>
<Defines>WIN32</Defines>
</CudaCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)'=='Debug'">
<ClCompile>
<Optimization>Disabled</Optimization>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<LinkTimeCodeGeneration>Default</LinkTimeCodeGeneration>
</Link>
<CudaCompile>
<Runtime>MTd</Runtime>
<TargetMachinePlatform>64</TargetMachinePlatform>
</CudaCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)'=='Release'">
<ClCompile>
<Optimization>MaxSpeed</Optimization>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
</ClCompile>
<Link>
<GenerateDebugInformation>false</GenerateDebugInformation>
<LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
</Link>
<CudaCompile>
<Runtime>MT</Runtime>
<TargetMachinePlatform>64</TargetMachinePlatform>
</CudaCompile>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="src/main.cpp" />
<CudaCompile Include="src/piestimator.cu" />
<ClCompile Include="src/test.cpp" />
<ClInclude Include="inc/cudasharedmem.h" />
<ClInclude Include="inc/piestimator.h" />
<ClInclude Include="inc/test.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
<Import Project="$(CUDAPropsPath)\CUDA 11.6.targets" />
</ImportGroup>
</Project>

View File

@@ -0,0 +1,20 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2019
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MC_EstimatePiInlineQ", "MC_EstimatePiInlineQ_vs2019.vcxproj", "{997E0757-EA74-4A4E-A0FC-47D8C8831A15}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
Release|x64 = Release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{997E0757-EA74-4A4E-A0FC-47D8C8831A15}.Debug|x64.ActiveCfg = Debug|x64
{997E0757-EA74-4A4E-A0FC-47D8C8831A15}.Debug|x64.Build.0 = Debug|x64
{997E0757-EA74-4A4E-A0FC-47D8C8831A15}.Release|x64.ActiveCfg = Release|x64
{997E0757-EA74-4A4E-A0FC-47D8C8831A15}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

View File

@@ -0,0 +1,112 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<CUDAPropsPath Condition="'$(CUDAPropsPath)'==''">$(VCTargetsPath)\BuildCustomizations</CUDAPropsPath>
</PropertyGroup>
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{997E0757-EA74-4A4E-A0FC-47D8C8831A15}</ProjectGuid>
<RootNamespace>MC_EstimatePiInlineQ_vs2019</RootNamespace>
<ProjectName>MC_EstimatePiInlineQ</ProjectName>
<CudaToolkitCustomDir />
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup>
<ConfigurationType>Application</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v142</PlatformToolset>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)'=='Debug'">
<UseDebugLibraries>true</UseDebugLibraries>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)'=='Release'">
<WholeProgramOptimization>true</WholeProgramOptimization>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
<Import Project="$(CUDAPropsPath)\CUDA 11.6.props" />
</ImportGroup>
<ImportGroup Label="PropertySheets">
<Import Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<IntDir>$(Platform)/$(Configuration)/</IntDir>
<IncludePath>$(IncludePath)</IncludePath>
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisRules />
<CodeAnalysisRuleAssemblies />
</PropertyGroup>
<PropertyGroup Condition="'$(Platform)'=='x64'">
<OutDir>../../../bin/win64/$(Configuration)/</OutDir>
</PropertyGroup>
<ItemDefinitionGroup>
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PreprocessorDefinitions>WIN32;_MBCS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>./;$(CudaToolkitDir)/include;../../../Common;$(CudaToolkitIncludeDir);</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<AdditionalDependencies>curand.lib;cudart_static.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(CudaToolkitLibDir);</AdditionalLibraryDirectories>
<OutputFile>$(OutDir)/MC_EstimatePiInlineQ.exe</OutputFile>
</Link>
<CudaCompile>
<CodeGeneration>compute_35,sm_35;compute_37,sm_37;compute_50,sm_50;compute_52,sm_52;compute_60,sm_60;compute_61,sm_61;compute_70,sm_70;compute_75,sm_75;compute_80,sm_80;compute_86,sm_86;</CodeGeneration>
<AdditionalOptions>-Xcompiler "/wd 4819" --threads 0 </AdditionalOptions>
<Include>./;../../../Common</Include>
<Defines>WIN32</Defines>
</CudaCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)'=='Debug'">
<ClCompile>
<Optimization>Disabled</Optimization>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<LinkTimeCodeGeneration>Default</LinkTimeCodeGeneration>
</Link>
<CudaCompile>
<Runtime>MTd</Runtime>
<TargetMachinePlatform>64</TargetMachinePlatform>
</CudaCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)'=='Release'">
<ClCompile>
<Optimization>MaxSpeed</Optimization>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
</ClCompile>
<Link>
<GenerateDebugInformation>false</GenerateDebugInformation>
<LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
</Link>
<CudaCompile>
<Runtime>MT</Runtime>
<TargetMachinePlatform>64</TargetMachinePlatform>
</CudaCompile>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="src/main.cpp" />
<CudaCompile Include="src/piestimator.cu" />
<ClCompile Include="src/test.cpp" />
<ClInclude Include="inc/cudasharedmem.h" />
<ClInclude Include="inc/piestimator.h" />
<ClInclude Include="inc/test.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
<Import Project="$(CUDAPropsPath)\CUDA 11.6.targets" />
</ImportGroup>
</Project>

View File

@@ -0,0 +1,20 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2022
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MC_EstimatePiInlineQ", "MC_EstimatePiInlineQ_vs2022.vcxproj", "{997E0757-EA74-4A4E-A0FC-47D8C8831A15}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
Release|x64 = Release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{997E0757-EA74-4A4E-A0FC-47D8C8831A15}.Debug|x64.ActiveCfg = Debug|x64
{997E0757-EA74-4A4E-A0FC-47D8C8831A15}.Debug|x64.Build.0 = Debug|x64
{997E0757-EA74-4A4E-A0FC-47D8C8831A15}.Release|x64.ActiveCfg = Release|x64
{997E0757-EA74-4A4E-A0FC-47D8C8831A15}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

View File

@@ -0,0 +1,112 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<CUDAPropsPath Condition="'$(CUDAPropsPath)'==''">$(VCTargetsPath)\BuildCustomizations</CUDAPropsPath>
</PropertyGroup>
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{997E0757-EA74-4A4E-A0FC-47D8C8831A15}</ProjectGuid>
<RootNamespace>MC_EstimatePiInlineQ_vs2022</RootNamespace>
<ProjectName>MC_EstimatePiInlineQ</ProjectName>
<CudaToolkitCustomDir />
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup>
<ConfigurationType>Application</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v143</PlatformToolset>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)'=='Debug'">
<UseDebugLibraries>true</UseDebugLibraries>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)'=='Release'">
<WholeProgramOptimization>true</WholeProgramOptimization>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
<Import Project="$(CUDAPropsPath)\CUDA 11.6.props" />
</ImportGroup>
<ImportGroup Label="PropertySheets">
<Import Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<IntDir>$(Platform)/$(Configuration)/</IntDir>
<IncludePath>$(IncludePath)</IncludePath>
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisRules />
<CodeAnalysisRuleAssemblies />
</PropertyGroup>
<PropertyGroup Condition="'$(Platform)'=='x64'">
<OutDir>../../../bin/win64/$(Configuration)/</OutDir>
</PropertyGroup>
<ItemDefinitionGroup>
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PreprocessorDefinitions>WIN32;_MBCS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>./;$(CudaToolkitDir)/include;../../../Common;$(CudaToolkitIncludeDir);</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<AdditionalDependencies>curand.lib;cudart_static.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(CudaToolkitLibDir);</AdditionalLibraryDirectories>
<OutputFile>$(OutDir)/MC_EstimatePiInlineQ.exe</OutputFile>
</Link>
<CudaCompile>
<CodeGeneration>compute_35,sm_35;compute_37,sm_37;compute_50,sm_50;compute_52,sm_52;compute_60,sm_60;compute_61,sm_61;compute_70,sm_70;compute_75,sm_75;compute_80,sm_80;compute_86,sm_86;</CodeGeneration>
<AdditionalOptions>-Xcompiler "/wd 4819" --threads 0 </AdditionalOptions>
<Include>./;../../../Common</Include>
<Defines>WIN32</Defines>
</CudaCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)'=='Debug'">
<ClCompile>
<Optimization>Disabled</Optimization>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<LinkTimeCodeGeneration>Default</LinkTimeCodeGeneration>
</Link>
<CudaCompile>
<Runtime>MTd</Runtime>
<TargetMachinePlatform>64</TargetMachinePlatform>
</CudaCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)'=='Release'">
<ClCompile>
<Optimization>MaxSpeed</Optimization>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
</ClCompile>
<Link>
<GenerateDebugInformation>false</GenerateDebugInformation>
<LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
</Link>
<CudaCompile>
<Runtime>MT</Runtime>
<TargetMachinePlatform>64</TargetMachinePlatform>
</CudaCompile>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="src/main.cpp" />
<CudaCompile Include="src/piestimator.cu" />
<ClCompile Include="src/test.cpp" />
<ClInclude Include="inc/cudasharedmem.h" />
<ClInclude Include="inc/piestimator.h" />
<ClInclude Include="inc/test.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
<Import Project="$(CUDAPropsPath)\CUDA 11.6.targets" />
</ImportGroup>
</Project>

View File

@@ -0,0 +1,348 @@
################################################################################
# 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.
#
################################################################################
#
# Makefile project only supported on Mac OS X and Linux Platforms)
#
################################################################################
# Location of the CUDA Toolkit
CUDA_PATH ?= /usr/local/cuda
##############################
# start deprecated interface #
##############################
ifeq ($(x86_64),1)
$(info WARNING - x86_64 variable has been deprecated)
$(info WARNING - please use TARGET_ARCH=x86_64 instead)
TARGET_ARCH ?= x86_64
endif
ifeq ($(ARMv7),1)
$(info WARNING - ARMv7 variable has been deprecated)
$(info WARNING - please use TARGET_ARCH=armv7l instead)
TARGET_ARCH ?= armv7l
endif
ifeq ($(aarch64),1)
$(info WARNING - aarch64 variable has been deprecated)
$(info WARNING - please use TARGET_ARCH=aarch64 instead)
TARGET_ARCH ?= aarch64
endif
ifeq ($(ppc64le),1)
$(info WARNING - ppc64le variable has been deprecated)
$(info WARNING - please use TARGET_ARCH=ppc64le instead)
TARGET_ARCH ?= ppc64le
endif
ifneq ($(GCC),)
$(info WARNING - GCC variable has been deprecated)
$(info WARNING - please use HOST_COMPILER=$(GCC) instead)
HOST_COMPILER ?= $(GCC)
endif
ifneq ($(abi),)
$(error ERROR - abi variable has been removed)
endif
############################
# end deprecated interface #
############################
# architecture
HOST_ARCH := $(shell uname -m)
TARGET_ARCH ?= $(HOST_ARCH)
ifneq (,$(filter $(TARGET_ARCH),x86_64 aarch64 sbsa ppc64le armv7l))
ifneq ($(TARGET_ARCH),$(HOST_ARCH))
ifneq (,$(filter $(TARGET_ARCH),x86_64 aarch64 sbsa ppc64le))
TARGET_SIZE := 64
else ifneq (,$(filter $(TARGET_ARCH),armv7l))
TARGET_SIZE := 32
endif
else
TARGET_SIZE := $(shell getconf LONG_BIT)
endif
else
$(error ERROR - unsupported value $(TARGET_ARCH) for TARGET_ARCH!)
endif
# sbsa and aarch64 systems look similar. Need to differentiate them at host level for now.
ifeq ($(HOST_ARCH),aarch64)
ifeq ($(CUDA_PATH)/targets/sbsa-linux,$(shell ls -1d $(CUDA_PATH)/targets/sbsa-linux 2>/dev/null))
HOST_ARCH := sbsa
TARGET_ARCH := sbsa
endif
endif
ifneq ($(TARGET_ARCH),$(HOST_ARCH))
ifeq (,$(filter $(HOST_ARCH)-$(TARGET_ARCH),aarch64-armv7l x86_64-armv7l x86_64-aarch64 x86_64-sbsa x86_64-ppc64le))
$(error ERROR - cross compiling from $(HOST_ARCH) to $(TARGET_ARCH) is not supported!)
endif
endif
# When on native aarch64 system with userspace of 32-bit, change TARGET_ARCH to armv7l
ifeq ($(HOST_ARCH)-$(TARGET_ARCH)-$(TARGET_SIZE),aarch64-aarch64-32)
TARGET_ARCH = armv7l
endif
# operating system
HOST_OS := $(shell uname -s 2>/dev/null | tr "[:upper:]" "[:lower:]")
TARGET_OS ?= $(HOST_OS)
ifeq (,$(filter $(TARGET_OS),linux darwin qnx android))
$(error ERROR - unsupported value $(TARGET_OS) for TARGET_OS!)
endif
# host compiler
ifeq ($(TARGET_OS),darwin)
ifeq ($(shell expr `xcodebuild -version | grep -i xcode | awk '{print $$2}' | cut -d'.' -f1` \>= 5),1)
HOST_COMPILER ?= clang++
endif
else ifneq ($(TARGET_ARCH),$(HOST_ARCH))
ifeq ($(HOST_ARCH)-$(TARGET_ARCH),x86_64-armv7l)
ifeq ($(TARGET_OS),linux)
HOST_COMPILER ?= arm-linux-gnueabihf-g++
else ifeq ($(TARGET_OS),qnx)
ifeq ($(QNX_HOST),)
$(error ERROR - QNX_HOST must be passed to the QNX host toolchain)
endif
ifeq ($(QNX_TARGET),)
$(error ERROR - QNX_TARGET must be passed to the QNX target toolchain)
endif
export QNX_HOST
export QNX_TARGET
HOST_COMPILER ?= $(QNX_HOST)/usr/bin/arm-unknown-nto-qnx6.6.0eabi-g++
else ifeq ($(TARGET_OS),android)
HOST_COMPILER ?= arm-linux-androideabi-g++
endif
else ifeq ($(TARGET_ARCH),aarch64)
ifeq ($(TARGET_OS), linux)
HOST_COMPILER ?= aarch64-linux-gnu-g++
else ifeq ($(TARGET_OS),qnx)
ifeq ($(QNX_HOST),)
$(error ERROR - QNX_HOST must be passed to the QNX host toolchain)
endif
ifeq ($(QNX_TARGET),)
$(error ERROR - QNX_TARGET must be passed to the QNX target toolchain)
endif
export QNX_HOST
export QNX_TARGET
HOST_COMPILER ?= $(QNX_HOST)/usr/bin/q++
else ifeq ($(TARGET_OS), android)
HOST_COMPILER ?= aarch64-linux-android-clang++
endif
else ifeq ($(TARGET_ARCH),sbsa)
HOST_COMPILER ?= aarch64-linux-gnu-g++
else ifeq ($(TARGET_ARCH),ppc64le)
HOST_COMPILER ?= powerpc64le-linux-gnu-g++
endif
endif
HOST_COMPILER ?= g++
NVCC := $(CUDA_PATH)/bin/nvcc -ccbin $(HOST_COMPILER)
# internal flags
NVCCFLAGS := -m${TARGET_SIZE}
CCFLAGS :=
LDFLAGS :=
# build flags
ifeq ($(TARGET_OS),darwin)
LDFLAGS += -rpath $(CUDA_PATH)/lib
CCFLAGS += -arch $(HOST_ARCH)
else ifeq ($(HOST_ARCH)-$(TARGET_ARCH)-$(TARGET_OS),x86_64-armv7l-linux)
LDFLAGS += --dynamic-linker=/lib/ld-linux-armhf.so.3
CCFLAGS += -mfloat-abi=hard
else ifeq ($(TARGET_OS),android)
LDFLAGS += -pie
CCFLAGS += -fpie -fpic -fexceptions
endif
ifneq ($(TARGET_ARCH),$(HOST_ARCH))
ifeq ($(TARGET_ARCH)-$(TARGET_OS),armv7l-linux)
ifneq ($(TARGET_FS),)
GCCVERSIONLTEQ46 := $(shell expr `$(HOST_COMPILER) -dumpversion` \<= 4.6)
ifeq ($(GCCVERSIONLTEQ46),1)
CCFLAGS += --sysroot=$(TARGET_FS)
endif
LDFLAGS += --sysroot=$(TARGET_FS)
LDFLAGS += -rpath-link=$(TARGET_FS)/lib
LDFLAGS += -rpath-link=$(TARGET_FS)/usr/lib
LDFLAGS += -rpath-link=$(TARGET_FS)/usr/lib/arm-linux-gnueabihf
endif
endif
ifeq ($(TARGET_ARCH)-$(TARGET_OS),aarch64-linux)
ifneq ($(TARGET_FS),)
GCCVERSIONLTEQ46 := $(shell expr `$(HOST_COMPILER) -dumpversion` \<= 4.6)
ifeq ($(GCCVERSIONLTEQ46),1)
CCFLAGS += --sysroot=$(TARGET_FS)
endif
LDFLAGS += --sysroot=$(TARGET_FS)
LDFLAGS += -rpath-link=$(TARGET_FS)/lib -L$(TARGET_FS)/lib
LDFLAGS += -rpath-link=$(TARGET_FS)/lib/aarch64-linux-gnu -L$(TARGET_FS)/lib/aarch64-linux-gnu
LDFLAGS += -rpath-link=$(TARGET_FS)/usr/lib -L$(TARGET_FS)/usr/lib
LDFLAGS += -rpath-link=$(TARGET_FS)/usr/lib/aarch64-linux-gnu -L$(TARGET_FS)/usr/lib/aarch64-linux-gnu
LDFLAGS += --unresolved-symbols=ignore-in-shared-libs
CCFLAGS += -isystem=$(TARGET_FS)/usr/include -I$(TARGET_FS)/usr/include -I$(TARGET_FS)/usr/include/libdrm
CCFLAGS += -isystem=$(TARGET_FS)/usr/include/aarch64-linux-gnu -I$(TARGET_FS)/usr/include/aarch64-linux-gnu
endif
endif
ifeq ($(TARGET_ARCH)-$(TARGET_OS),aarch64-qnx)
NVCCFLAGS += -D_QNX_SOURCE
NVCCFLAGS += --qpp-config 8.3.0,gcc_ntoaarch64le
CCFLAGS += -DWIN_INTERFACE_CUSTOM -I/usr/include/aarch64-qnx-gnu
LDFLAGS += -lsocket
LDFLAGS += -L/usr/lib/aarch64-qnx-gnu
CCFLAGS += "-Wl\,-rpath-link\,/usr/lib/aarch64-qnx-gnu"
ifdef TARGET_OVERRIDE
LDFLAGS += -lslog2
endif
ifneq ($(TARGET_FS),)
LDFLAGS += -L$(TARGET_FS)/usr/lib
CCFLAGS += "-Wl\,-rpath-link\,$(TARGET_FS)/usr/lib"
LDFLAGS += -L$(TARGET_FS)/usr/libnvidia
CCFLAGS += "-Wl\,-rpath-link\,$(TARGET_FS)/usr/libnvidia"
CCFLAGS += -I$(TARGET_FS)/../include
endif
endif
endif
ifdef TARGET_OVERRIDE # cuda toolkit targets override
NVCCFLAGS += -target-dir $(TARGET_OVERRIDE)
endif
# Install directory of different arch
CUDA_INSTALL_TARGET_DIR :=
ifeq ($(TARGET_ARCH)-$(TARGET_OS),armv7l-linux)
CUDA_INSTALL_TARGET_DIR = targets/armv7-linux-gnueabihf/
else ifeq ($(TARGET_ARCH)-$(TARGET_OS),aarch64-linux)
CUDA_INSTALL_TARGET_DIR = targets/aarch64-linux/
else ifeq ($(TARGET_ARCH)-$(TARGET_OS),sbsa-linux)
CUDA_INSTALL_TARGET_DIR = targets/sbsa-linux/
else ifeq ($(TARGET_ARCH)-$(TARGET_OS),armv7l-android)
CUDA_INSTALL_TARGET_DIR = targets/armv7-linux-androideabi/
else ifeq ($(TARGET_ARCH)-$(TARGET_OS),aarch64-android)
CUDA_INSTALL_TARGET_DIR = targets/aarch64-linux-androideabi/
else ifeq ($(TARGET_ARCH)-$(TARGET_OS),armv7l-qnx)
CUDA_INSTALL_TARGET_DIR = targets/ARMv7-linux-QNX/
else ifeq ($(TARGET_ARCH)-$(TARGET_OS),aarch64-qnx)
CUDA_INSTALL_TARGET_DIR = targets/aarch64-qnx/
else ifeq ($(TARGET_ARCH),ppc64le)
CUDA_INSTALL_TARGET_DIR = targets/ppc64le-linux/
endif
# Debug build flags
ifeq ($(dbg),1)
NVCCFLAGS += -g -G
BUILD_TYPE := debug
else
BUILD_TYPE := release
endif
ALL_CCFLAGS :=
ALL_CCFLAGS += $(NVCCFLAGS)
ALL_CCFLAGS += $(EXTRA_NVCCFLAGS)
ALL_CCFLAGS += $(addprefix -Xcompiler ,$(CCFLAGS))
ALL_CCFLAGS += $(addprefix -Xcompiler ,$(EXTRA_CCFLAGS))
SAMPLE_ENABLED := 1
ALL_LDFLAGS :=
ALL_LDFLAGS += $(ALL_CCFLAGS)
ALL_LDFLAGS += $(addprefix -Xlinker ,$(LDFLAGS))
ALL_LDFLAGS += $(addprefix -Xlinker ,$(EXTRA_LDFLAGS))
# Common includes and paths for CUDA
INCLUDES := -I../../../Common
LIBRARIES :=
################################################################################
# Gencode arguments
ifeq ($(TARGET_ARCH),$(filter $(TARGET_ARCH),armv7l aarch64 sbsa))
SMS ?= 53 61 70 72 75 80 86 87
else
SMS ?= 35 37 50 52 60 61 70 75 80 86
endif
ifeq ($(SMS),)
$(info >>> WARNING - no SM architectures have been specified - waiving sample <<<)
SAMPLE_ENABLED := 0
endif
ifeq ($(GENCODE_FLAGS),)
# Generate SASS code for each SM architecture listed in $(SMS)
$(foreach sm,$(SMS),$(eval GENCODE_FLAGS += -gencode arch=compute_$(sm),code=sm_$(sm)))
# Generate PTX code from the highest SM architecture in $(SMS) to guarantee forward-compatibility
HIGHEST_SM := $(lastword $(sort $(SMS)))
ifneq ($(HIGHEST_SM),)
GENCODE_FLAGS += -gencode arch=compute_$(HIGHEST_SM),code=compute_$(HIGHEST_SM)
endif
endif
ALL_CCFLAGS += --threads 0 --std=c++11
LIBRARIES += -lcurand
ifeq ($(SAMPLE_ENABLED),0)
EXEC ?= @echo "[@]"
endif
################################################################################
# Target rules
all: build
build: MC_EstimatePiInlineQ
check.deps:
ifeq ($(SAMPLE_ENABLED),0)
@echo "Sample will be waived due to the above missing dependencies"
else
@echo "Sample is ready - all dependencies have been met"
endif
main.o:src/main.cpp
$(EXEC) $(NVCC) $(INCLUDES) $(ALL_CCFLAGS) $(GENCODE_FLAGS) -o $@ -c $<
piestimator.o:src/piestimator.cu
$(EXEC) $(NVCC) $(INCLUDES) $(ALL_CCFLAGS) $(GENCODE_FLAGS) -o $@ -c $<
test.o:src/test.cpp
$(EXEC) $(NVCC) $(INCLUDES) $(ALL_CCFLAGS) $(GENCODE_FLAGS) -o $@ -c $<
MC_EstimatePiInlineQ: main.o piestimator.o test.o
$(EXEC) $(NVCC) $(ALL_LDFLAGS) $(GENCODE_FLAGS) -o $@ $+ $(LIBRARIES)
$(EXEC) mkdir -p ../../../bin/$(TARGET_ARCH)/$(TARGET_OS)/$(BUILD_TYPE)
$(EXEC) cp $@ ../../../bin/$(TARGET_ARCH)/$(TARGET_OS)/$(BUILD_TYPE)
run: build
$(EXEC) ./MC_EstimatePiInlineQ
testrun: build
clean:
rm -f MC_EstimatePiInlineQ main.o piestimator.o test.o
rm -rf ../../../bin/$(TARGET_ARCH)/$(TARGET_OS)/$(BUILD_TYPE)/MC_EstimatePiInlineQ
clobber: clean

View File

@@ -0,0 +1,91 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE entry SYSTEM "SamplesInfo.dtd">
<entry>
<name>MC_EstimatePiInlineQ</name>
<cuda_api_list>
<toolkit>cudaFree</toolkit>
<toolkit>cudaFuncGetAttributes</toolkit>
<toolkit>cudaGetDeviceCount</toolkit>
<toolkit>cudaMalloc</toolkit>
<toolkit>cudaSetDevice</toolkit>
<toolkit>cudaMemcpy</toolkit>
<toolkit>cudaGetErrorString</toolkit>
<toolkit>cudaGetDeviceProperties</toolkit>
</cuda_api_list>
<description><![CDATA[This sample uses Monte Carlo simulation for Estimation of Pi (using inline QRNG). This sample also uses the NVIDIA CURAND library.]]></description>
<devicecompilation>whole</devicecompilation>
<includepaths>
<path>./</path>
<path>../</path>
<path>../../../Common</path>
</includepaths>
<keyconcepts>
<concept level="advanced">Random Number Generator</concept>
<concept level="advanced">Computational Finance</concept>
<concept level="advanced">CURAND Library</concept>
</keyconcepts>
<keywords>
<keyword>CUDA</keyword>
<keyword>CURAND</keyword>
<keyword>GPGPU</keyword>
<keyword>Monte Carlo</keyword>
<keyword>rng</keyword>
<keyword>prng</keyword>
<keyword>qrng</keyword>
<keyword>random number</keyword>
</keywords>
<libraries>
<library>curand</library>
</libraries>
<librarypaths>
</librarypaths>
<nsight_eclipse>true</nsight_eclipse>
<primary_file>src\main.cpp</primary_file>
<required_dependencies>
<dependency>CURAND</dependency>
</required_dependencies>
<scopes>
<scope>1:CUDA Advanced Topics</scope>
</scopes>
<sm-arch>sm35</sm-arch>
<sm-arch>sm37</sm-arch>
<sm-arch>sm50</sm-arch>
<sm-arch>sm52</sm-arch>
<sm-arch>sm53</sm-arch>
<sm-arch>sm60</sm-arch>
<sm-arch>sm61</sm-arch>
<sm-arch>sm70</sm-arch>
<sm-arch>sm72</sm-arch>
<sm-arch>sm75</sm-arch>
<sm-arch>sm80</sm-arch>
<sm-arch>sm86</sm-arch>
<sm-arch>sm87</sm-arch>
<supported_envs>
<env>
<arch>x86_64</arch>
<platform>linux</platform>
</env>
<env>
<platform>windows7</platform>
</env>
<env>
<arch>x86_64</arch>
<platform>macosx</platform>
</env>
<env>
<arch>arm</arch>
</env>
<env>
<arch>sbsa</arch>
</env>
<env>
<arch>ppc64le</arch>
<platform>linux</platform>
</env>
</supported_envs>
<supported_sm_architectures>
<include>all</include>
</supported_sm_architectures>
<title>Monte Carlo Estimation of Pi (inline QRNG) </title>
<type>exe</type>
</entry>

View File

@@ -0,0 +1,74 @@
# MC_EstimatePiInlineQ - Monte Carlo Estimation of Pi (inline QRNG)
## Description
This sample uses Monte Carlo simulation for Estimation of Pi (using inline QRNG). This sample also uses the NVIDIA CURAND library.
## Key Concepts
Random Number Generator, Computational Finance, CURAND Library
## Supported SM Architectures
[SM 3.5 ](https://developer.nvidia.com/cuda-gpus) [SM 3.7 ](https://developer.nvidia.com/cuda-gpus) [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)
## Supported OSes
Linux, Windows
## Supported CPU Architecture
x86_64, ppc64le, armv7l
## CUDA APIs involved
### [CUDA Runtime API](http://docs.nvidia.com/cuda/cuda-runtime-api/index.html)
cudaFree, cudaFuncGetAttributes, cudaGetDeviceCount, cudaMalloc, cudaSetDevice, cudaMemcpy, cudaGetErrorString, cudaGetDeviceProperties
## Dependencies needed to build/run
[CURAND](../../README.md#curand)
## Prerequisites
Download and install the [CUDA Toolkit 11.6](https://developer.nvidia.com/cuda-downloads) for your corresponding platform.
Make sure the dependencies mentioned in [Dependencies]() section above are installed.
## Build and Run
### Windows
The Windows samples are built using the Visual Studio IDE. Solution files (.sln) are provided for each supported version of Visual Studio, using the format:
```
*_vs<version>.sln - for Visual Studio <version>
```
Each individual sample has its own set of solution files in its directory:
To build/examine all the samples at once, the complete solution files should be used. To build/examine a single sample, the individual sample solution files should be used.
> **Note:** Some samples require that the Microsoft DirectX SDK (June 2010 or newer) be installed and that the VC++ directory paths are properly set up (**Tools > Options...**). Check DirectX Dependencies section for details."
### Linux
The Linux samples are built using makefiles. To use the makefiles, change the current directory to the sample directory you wish to build, and run make:
```
$ cd <sample_dir>
$ make
```
The samples makefiles can take advantage of certain options:
* **TARGET_ARCH=<arch>** - cross-compile targeting a specific architecture. Allowed architectures are x86_64, ppc64le, armv7l.
By default, TARGET_ARCH is set to HOST_ARCH. On a x86_64 machine, not setting TARGET_ARCH is the equivalent of setting TARGET_ARCH=x86_64.<br/>
`$ make TARGET_ARCH=x86_64` <br/> `$ make TARGET_ARCH=ppc64le` <br/> `$ make TARGET_ARCH=armv7l` <br/>
See [here](http://docs.nvidia.com/cuda/cuda-samples/index.html#cross-samples) for more details.
* **dbg=1** - build with debug symbols
```
$ make dbg=1
```
* **SMS="A B ..."** - override the SM architectures for which the sample will be built, where `"A B ..."` is a space-delimited list of SM architectures. For example, to generate SASS for SM 50 and SM 60, use `SMS="50 60"`.
```
$ make SMS="50 60"
```
* **HOST_COMPILER=<host_compiler>** - override the default g++ host compiler. See the [Linux Installation Guide](http://docs.nvidia.com/cuda/cuda-installation-guide-linux/index.html#system-requirements) for a list of supported host compilers.
```
$ make HOST_COMPILER=g++
```
## References (for more details)

Some files were not shown because too many files have changed in this diff Show More