mirror of
https://github.com/NVIDIA/cuda-samples.git
synced 2026-10-23 21:28:17 +08:00
add and update samples for CUDA 11.6
This commit is contained in:
18
Samples/5_Domain_Specific/simpleGLES_EGLOutput/.vscode/c_cpp_properties.json
vendored
Normal file
18
Samples/5_Domain_Specific/simpleGLES_EGLOutput/.vscode/c_cpp_properties.json
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Linux",
|
||||
"includePath": [
|
||||
"${workspaceFolder}/**",
|
||||
"${workspaceFolder}/../../../Common"
|
||||
],
|
||||
"defines": [],
|
||||
"compilerPath": "/usr/local/cuda/bin/nvcc",
|
||||
"cStandard": "gnu17",
|
||||
"cppStandard": "gnu++14",
|
||||
"intelliSenseMode": "linux-gcc-x64",
|
||||
"configurationProvider": "ms-vscode.makefile-tools"
|
||||
}
|
||||
],
|
||||
"version": 4
|
||||
}
|
||||
7
Samples/5_Domain_Specific/simpleGLES_EGLOutput/.vscode/extensions.json
vendored
Normal file
7
Samples/5_Domain_Specific/simpleGLES_EGLOutput/.vscode/extensions.json
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"recommendations": [
|
||||
"nvidia.nsight-vscode-edition",
|
||||
"ms-vscode.cpptools",
|
||||
"ms-vscode.makefile-tools"
|
||||
]
|
||||
}
|
||||
10
Samples/5_Domain_Specific/simpleGLES_EGLOutput/.vscode/launch.json
vendored
Normal file
10
Samples/5_Domain_Specific/simpleGLES_EGLOutput/.vscode/launch.json
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"configurations": [
|
||||
{
|
||||
"name": "CUDA C++: Launch",
|
||||
"type": "cuda-gdb",
|
||||
"request": "launch",
|
||||
"program": "${workspaceFolder}/simpleGLES_EGLOutput"
|
||||
}
|
||||
]
|
||||
}
|
||||
15
Samples/5_Domain_Specific/simpleGLES_EGLOutput/.vscode/tasks.json
vendored
Normal file
15
Samples/5_Domain_Specific/simpleGLES_EGLOutput/.vscode/tasks.json
vendored
Normal 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
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
375
Samples/5_Domain_Specific/simpleGLES_EGLOutput/Makefile
Normal file
375
Samples/5_Domain_Specific/simpleGLES_EGLOutput/Makefile
Normal file
@@ -0,0 +1,375 @@
|
||||
################################################################################
|
||||
# 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 Linux x86_64
|
||||
ifeq ($(TARGET_OS),linux)
|
||||
ifeq ($(TARGET_ARCH),x86_64)
|
||||
$(info >>> WARNING - simpleGLES_EGLOutput 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 - simpleGLES_EGLOutput 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 - simpleGLES_EGLOutput is not supported on sbsa - waiving sample <<<)
|
||||
SAMPLE_ENABLED := 0
|
||||
endif
|
||||
|
||||
# This sample is not supported on QNX
|
||||
ifeq ($(TARGET_OS),qnx)
|
||||
$(info >>> WARNING - simpleGLES_EGLOutput 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 GLES Libraries
|
||||
include ./findgleslib.mk
|
||||
|
||||
# OpenGLES specific libraries
|
||||
ifneq ($(TARGET_OS),darwin)
|
||||
LIBRARIES += $(GLESLINK) -lGLESv2 -lEGL -ldrm
|
||||
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 += -DUSE_CUDAINTEROP -DGRAPHICS_SETUP_EGL -DUSE_GLES -I/usr/include/libdrm -I/usr/include/drm --threads 0 --std=c++11
|
||||
|
||||
ifeq ($(SAMPLE_ENABLED),0)
|
||||
EXEC ?= @echo "[@]"
|
||||
endif
|
||||
|
||||
################################################################################
|
||||
|
||||
# Target rules
|
||||
all: build
|
||||
|
||||
build: simpleGLES_EGLOutput
|
||||
|
||||
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
|
||||
|
||||
simpleGLES_EGLOutput.o:simpleGLES_EGLOutput.cu
|
||||
$(EXEC) $(NVCC) $(INCLUDES) $(ALL_CCFLAGS) $(GENCODE_FLAGS) -o $@ -c $<
|
||||
|
||||
simpleGLES_EGLOutput: simpleGLES_EGLOutput.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) ./simpleGLES_EGLOutput
|
||||
|
||||
testrun: build
|
||||
$(EXEC) ./simpleGLES_EGLOutput -file=ref_simpleGLES_EGLOutput.bin
|
||||
|
||||
clean:
|
||||
rm -f simpleGLES_EGLOutput simpleGLES_EGLOutput.o
|
||||
rm -rf ../../../bin/$(TARGET_ARCH)/$(TARGET_OS)/$(BUILD_TYPE)/simpleGLES_EGLOutput
|
||||
|
||||
clobber: clean
|
||||
@@ -0,0 +1,91 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE entry SYSTEM "SamplesInfo.dtd">
|
||||
<entry>
|
||||
<name>simpleGLES_EGLOutput</name>
|
||||
<cflags>
|
||||
<flag>-DUSE_CUDAINTEROP</flag>
|
||||
<flag>-DGRAPHICS_SETUP_EGL</flag>
|
||||
<flag>-DUSE_GLES</flag>
|
||||
<flag>-I/usr/include/libdrm</flag>
|
||||
<flag>-I/usr/include/drm</flag>
|
||||
</cflags>
|
||||
<cuda_api_list>
|
||||
<toolkit>cudaFree</toolkit>
|
||||
<toolkit>cudaGraphicsMapResources</toolkit>
|
||||
<toolkit>cudaGraphicsGLRegisterBuffer</toolkit>
|
||||
<toolkit>cudaGraphicsResourceGetMappedPointer</toolkit>
|
||||
<toolkit>cudaDeviceSynchronize</toolkit>
|
||||
<toolkit>cudaMalloc</toolkit>
|
||||
<toolkit>cudaGraphicsUnregisterResource</toolkit>
|
||||
<toolkit>cudaGraphicsUnmapResources</toolkit>
|
||||
<toolkit>cudaMemcpy</toolkit>
|
||||
</cuda_api_list>
|
||||
<description><![CDATA[Demonstrates data exchange between CUDA and OpenGL ES (aka Graphics interop). The program modifies vertex positions with CUDA and uses OpenGL ES to render the geometry, and shows how to render directly to the display using the EGLOutput mechanism and the DRM library.
|
||||
|
||||
```
|
||||
NOTE: On Orin platform, execute this command before running sample:
|
||||
$ sudo modprobe nvidia-drm modeset=1
|
||||
```
|
||||
]]></description>
|
||||
<devicecompilation>whole</devicecompilation>
|
||||
<files>
|
||||
<file>data\ref_simpleGLES_EGLOutput.bin</file>
|
||||
</files>
|
||||
<includepaths>
|
||||
<path>./</path>
|
||||
<path>../</path>
|
||||
<path>../../../Common</path>
|
||||
</includepaths>
|
||||
<keyconcepts>
|
||||
<concept level="basic">Graphics Interop</concept>
|
||||
<concept level="basic">Vertex Buffers</concept>
|
||||
<concept level="basic">3D Graphics</concept>
|
||||
</keyconcepts>
|
||||
<keywords>
|
||||
<keyword>OpenGL ES</keyword>
|
||||
<keyword>egloutput</keyword>
|
||||
</keywords>
|
||||
<libraries>
|
||||
</libraries>
|
||||
<librarypaths>
|
||||
</librarypaths>
|
||||
<nsight_eclipse>true</nsight_eclipse>
|
||||
<primary_file>simpleGLES_EGLOutput.cu</primary_file>
|
||||
<qatests>
|
||||
<qatest>-file=ref_simpleGLES_EGLOutput.bin</qatest>
|
||||
</qatests>
|
||||
<required_dependencies>
|
||||
<dependency>EGLOutput</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>
|
||||
<sources>
|
||||
<ignore>graphics_interface_egloutput_via_egl.c</ignore>
|
||||
</sources>
|
||||
<supported_envs>
|
||||
<env>
|
||||
<arch>arm</arch>
|
||||
</env>
|
||||
</supported_envs>
|
||||
<supported_sm_architectures>
|
||||
<include>all</include>
|
||||
</supported_sm_architectures>
|
||||
<title>Simple OpenGLES EGLOutput</title>
|
||||
<type>exe</type>
|
||||
</entry>
|
||||
69
Samples/5_Domain_Specific/simpleGLES_EGLOutput/README.md
Normal file
69
Samples/5_Domain_Specific/simpleGLES_EGLOutput/README.md
Normal file
@@ -0,0 +1,69 @@
|
||||
# simpleGLES_EGLOutput - Simple OpenGLES EGLOutput
|
||||
|
||||
## Description
|
||||
|
||||
Demonstrates data exchange between CUDA and OpenGL ES (aka Graphics interop). The program modifies vertex positions with CUDA and uses OpenGL ES to render the geometry, and shows how to render directly to the display using the EGLOutput mechanism and the DRM library.
|
||||
|
||||
```
|
||||
NOTE: On Orin platform, execute this command before running sample:
|
||||
$ sudo modprobe nvidia-drm modeset=1
|
||||
```
|
||||
|
||||
## Key Concepts
|
||||
|
||||
Graphics Interop, Vertex Buffers, 3D Graphics
|
||||
|
||||
## 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 Runtime API](http://docs.nvidia.com/cuda/cuda-runtime-api/index.html)
|
||||
cudaFree, cudaGraphicsMapResources, cudaGraphicsGLRegisterBuffer, cudaGraphicsResourceGetMappedPointer, cudaDeviceSynchronize, cudaMalloc, cudaGraphicsUnregisterResource, cudaGraphicsUnmapResources, cudaMemcpy
|
||||
|
||||
## Dependencies needed to build/run
|
||||
[EGLOutput](../../README.md#egloutput), [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)
|
||||
|
||||
Binary file not shown.
158
Samples/5_Domain_Specific/simpleGLES_EGLOutput/findgleslib.mk
Normal file
158
Samples/5_Domain_Specific/simpleGLES_EGLOutput/findgleslib.mk
Normal file
@@ -0,0 +1,158 @@
|
||||
################################################################################
|
||||
#
|
||||
# Copyright 1993-2013 NVIDIA Corporation. All rights reserved.
|
||||
#
|
||||
# NOTICE TO USER:
|
||||
#
|
||||
# This source code is subject to NVIDIA ownership rights under U.S. and
|
||||
# international Copyright laws.
|
||||
#
|
||||
# NVIDIA MAKES NO REPRESENTATION ABOUT THE SUITABILITY OF THIS SOURCE
|
||||
# CODE FOR ANY PURPOSE. IT IS PROVIDED "AS IS" WITHOUT EXPRESS OR
|
||||
# IMPLIED WARRANTY OF ANY KIND. NVIDIA DISCLAIMS ALL WARRANTIES WITH
|
||||
# REGARD TO THIS SOURCE CODE, INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
# MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
# IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL,
|
||||
# OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||
# OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
||||
# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
|
||||
# OR PERFORMANCE OF THIS SOURCE CODE.
|
||||
#
|
||||
# U.S. Government End Users. This source code is a "commercial item" as
|
||||
# that term is defined at 48 C.F.R. 2.101 (OCT 1995), consisting of
|
||||
# "commercial computer software" and "commercial computer software
|
||||
# documentation" as such terms are used in 48 C.F.R. 12.212 (SEPT 1995)
|
||||
# and is provided to the U.S. Government only as a commercial end item.
|
||||
# Consistent with 48 C.F.R.12.212 and 48 C.F.R. 227.7202-1 through
|
||||
# 227.7202-4 (JUNE 1995), all U.S. Government End Users acquire the
|
||||
# source code with only those rights set forth herein.
|
||||
#
|
||||
################################################################################
|
||||
#
|
||||
# findgleslib.mk is used to find the necessary GLES 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 awk '{print $$1}' /etc/issue | tr -d "[:space:]" | sed -e "/^$$/d" | tr "[:upper:]" "[:lower:]")
|
||||
# ensure data from /etc/issue is valid
|
||||
ifneq (,$(filter-out $(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
|
||||
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, libXi,
|
||||
EGLLIB := $(shell find -L $(GLPATH) $(DFLT_PATH) -name libEGL.so -print 2>/dev/null)
|
||||
GLESLIB := $(shell find -L $(GLPATH) $(DFLT_PATH) -name libGLESv2.so -print 2>/dev/null)
|
||||
X11LIB := $(shell find -L $(GLPATH) $(DFLT_PATH) -name libX11.so -print 2>/dev/null)
|
||||
|
||||
ifeq ("$(EGLLIB)","")
|
||||
$(info >>> WARNING - libEGL.so not found, please install libEGL.so <<<)
|
||||
SAMPLE_ENABLED := 0
|
||||
endif
|
||||
ifeq ("$(GLESLIB)","")
|
||||
$(info >>> WARNING - libGLES.so not found, please install libGLES.so <<<)
|
||||
SAMPLE_ENABLED := 0
|
||||
endif
|
||||
ifeq ("$(X11LIB)","")
|
||||
$(info >>> WARNING - libX11.so not found, please install libX11.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)
|
||||
GL31HEADER := $(shell find -L $(HEADER_SEARCH_PATH) -name gl31.h -print 2>/dev/null)
|
||||
X11HEADER := $(shell find -L $(HEADER_SEARCH_PATH) -name Xlib.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
|
||||
ifeq ("$(GL31HEADER)","")
|
||||
$(info >>> WARNING - gl31.h not found, please install gl31.h <<<)
|
||||
SAMPLE_ENABLED := 0
|
||||
endif
|
||||
ifeq ("$(X11HEADER)","")
|
||||
$(info >>> WARNING - Xlib.h not found, refer to CUDA Samples release notes for how to find and install them. <<<)
|
||||
SAMPLE_ENABLED := 0
|
||||
endif
|
||||
else
|
||||
endif
|
||||
|
||||
@@ -0,0 +1,627 @@
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
// Display *display;
|
||||
int screen;
|
||||
// Window win = 0;
|
||||
|
||||
#include <assert.h>
|
||||
#include <xf86drm.h>
|
||||
#include <xf86drmMode.h>
|
||||
#include <drm_fourcc.h>
|
||||
|
||||
#include <GLES3/gl31.h>
|
||||
//#include <GLES3/gl3ext.h> // not (yet) needed
|
||||
#include <EGL/egl.h>
|
||||
#include <EGL/eglext.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#define MAX_DEVICES 16
|
||||
|
||||
static PFNEGLQUERYDEVICESEXTPROC eglQueryDevicesEXT = NULL;
|
||||
static PFNEGLQUERYDEVICESTRINGEXTPROC eglQueryDeviceStringEXT = NULL;
|
||||
static PFNEGLGETPLATFORMDISPLAYEXTPROC eglGetPlatformDisplayEXT = NULL;
|
||||
static PFNEGLGETOUTPUTLAYERSEXTPROC eglGetOutputLayersEXT = NULL;
|
||||
static PFNEGLCREATESTREAMKHRPROC eglCreateStreamKHR = NULL;
|
||||
static PFNEGLDESTROYSTREAMKHRPROC eglDestroyStreamKHR = NULL;
|
||||
static PFNEGLSTREAMCONSUMEROUTPUTEXTPROC eglStreamConsumerOutputEXT = NULL;
|
||||
static PFNEGLCREATESTREAMPRODUCERSURFACEKHRPROC
|
||||
eglCreateStreamProducerSurfaceKHR = NULL;
|
||||
|
||||
#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;
|
||||
|
||||
#if 0 // needed for optional API call retrieval (= if libGLESv2.so wouldn't be
|
||||
// linked explicitly) - tedious! consider GLEW.
|
||||
typedef GLenum (* glGetErrorTYPE) (void);
|
||||
glGetErrorTYPE my_glGetError;
|
||||
|
||||
typedef GL_APICALL const GLubyte (*GL_APIENTRY glGetStringTYPE) (GLenum name);
|
||||
glGetStringTYPE my_glGetString;
|
||||
|
||||
typedef GL_APICALL void (*GL_APIENTRY glClearTYPE) (GLbitfield mask);
|
||||
glClearTYPE my_glClear;
|
||||
|
||||
typedef GL_APICALL void (*GL_APIENTRY glGetProgramivTYPE) (GLuint program, GLenum pname, GLint *params);
|
||||
glGetProgramivTYPE my_glGetProgramiv;
|
||||
#endif
|
||||
|
||||
// Extension checking utility
|
||||
static bool CheckExtension(const char *exts, const char *ext) {
|
||||
int extLen = (int)strlen(ext);
|
||||
const char *end = exts + strlen(exts);
|
||||
|
||||
while (exts < end) {
|
||||
while (*exts == ' ') {
|
||||
exts++;
|
||||
}
|
||||
int n = strcspn(exts, " ");
|
||||
if ((extLen == n) && (strncmp(ext, exts, n) == 0)) {
|
||||
return true;
|
||||
}
|
||||
exts += n;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int graphics_setup_window(int xpos, int ypos, int width, int height,
|
||||
const char *windowname) {
|
||||
int device = 0, crtc = -1, plane = -1;
|
||||
int xsurfsize = 0, ysurfsize = 0;
|
||||
int xoffset = 0, yoffset = 0;
|
||||
int xmodesize = 0, ymodesize = 0;
|
||||
// int color = 0, duration = 10;
|
||||
int fifo = 0;
|
||||
int bounce = 0;
|
||||
uint32_t fb_id = -1;
|
||||
|
||||
EGLDeviceEXT egl_devs[MAX_DEVICES], egl_dev;
|
||||
EGLOutputLayerEXT egl_lyr;
|
||||
EGLConfig egl_cfg;
|
||||
EGLStreamKHR egl_str;
|
||||
EGLint major, minor;
|
||||
|
||||
const char *drm_name;
|
||||
int drm_fd;
|
||||
uint32_t drm_conn_id, drm_enc_id, drm_crtc_id, drm_plane_id;
|
||||
uint32_t crtc_mask;
|
||||
drmModeRes *drm_res_info = NULL;
|
||||
drmModePlaneRes *drm_plane_res_info = NULL;
|
||||
drmModeCrtc *drm_crtc_info = NULL;
|
||||
drmModeConnector *drm_conn_info = NULL;
|
||||
drmModeEncoder *drm_enc_info = NULL;
|
||||
drmModePlane *drm_plane_info = NULL;
|
||||
int drm_mode_index = 0;
|
||||
|
||||
bool set_mode = false;
|
||||
int i, n;
|
||||
|
||||
// Load extension function pointers.
|
||||
eglQueryDevicesEXT =
|
||||
(PFNEGLQUERYDEVICESEXTPROC)eglGetProcAddress("eglQueryDevicesEXT");
|
||||
eglQueryDeviceStringEXT = (PFNEGLQUERYDEVICESTRINGEXTPROC)eglGetProcAddress(
|
||||
"eglQueryDeviceStringEXT");
|
||||
eglGetPlatformDisplayEXT = (PFNEGLGETPLATFORMDISPLAYEXTPROC)eglGetProcAddress(
|
||||
"eglGetPlatformDisplayEXT");
|
||||
eglGetOutputLayersEXT =
|
||||
(PFNEGLGETOUTPUTLAYERSEXTPROC)eglGetProcAddress("eglGetOutputLayersEXT");
|
||||
eglCreateStreamKHR =
|
||||
(PFNEGLCREATESTREAMKHRPROC)eglGetProcAddress("eglCreateStreamKHR");
|
||||
eglDestroyStreamKHR =
|
||||
(PFNEGLDESTROYSTREAMKHRPROC)eglGetProcAddress("eglDestroyStreamKHR");
|
||||
eglStreamConsumerOutputEXT =
|
||||
(PFNEGLSTREAMCONSUMEROUTPUTEXTPROC)eglGetProcAddress(
|
||||
"eglStreamConsumerOutputEXT");
|
||||
eglCreateStreamProducerSurfaceKHR =
|
||||
(PFNEGLCREATESTREAMPRODUCERSURFACEKHRPROC)eglGetProcAddress(
|
||||
"eglCreateStreamProducerSurfaceKHR");
|
||||
if (!eglQueryDevicesEXT || !eglQueryDeviceStringEXT ||
|
||||
!eglGetPlatformDisplayEXT || !eglGetOutputLayersEXT ||
|
||||
!eglCreateStreamKHR || !eglDestroyStreamKHR ||
|
||||
!eglStreamConsumerOutputEXT || !eglCreateStreamProducerSurfaceKHR) {
|
||||
printf("Missing required function(s)\n");
|
||||
exit(2);
|
||||
}
|
||||
printf("Loaded extension functions\n");
|
||||
|
||||
// Query device
|
||||
if (!eglQueryDevicesEXT(device + 1, egl_devs, &n) || (n <= device)) {
|
||||
printf("Requested device index (%d) not found\n", device);
|
||||
exit(2);
|
||||
}
|
||||
egl_dev = egl_devs[device];
|
||||
|
||||
// Obtain and open DRM device file
|
||||
drm_name = eglQueryDeviceStringEXT(egl_dev, EGL_DRM_DEVICE_FILE_EXT);
|
||||
if (!drm_name) {
|
||||
printf("Couldn't obtain device file from 0x%p\n",
|
||||
(void *)(uintptr_t)egl_dev);
|
||||
exit(3);
|
||||
}
|
||||
|
||||
if (!strcmp(drm_name, "drm-nvdc")) {
|
||||
drm_fd = drmOpen(drm_name, NULL);
|
||||
} else {
|
||||
drm_fd = open(drm_name, O_RDWR, 0);
|
||||
}
|
||||
|
||||
if (drm_fd == -1) {
|
||||
printf("Couldn't open device file '%s'\n", drm_name);
|
||||
exit(3);
|
||||
}
|
||||
printf("Device file: %s\n", drm_name);
|
||||
|
||||
// Obtain DRM-KMS resources
|
||||
drm_res_info = drmModeGetResources(drm_fd);
|
||||
if (!drm_res_info) {
|
||||
printf("Couldn't obtain DRM-KMS resources\n");
|
||||
exit(3);
|
||||
}
|
||||
printf("Obtained device information\n");
|
||||
|
||||
// If a specific crtc was requested, make sure it exists
|
||||
if (crtc >= drm_res_info->count_crtcs) {
|
||||
printf("Requested crtc index (%d) exceeds count (%d)\n", crtc,
|
||||
drm_res_info->count_crtcs);
|
||||
exit(4);
|
||||
}
|
||||
crtc_mask =
|
||||
(crtc >= 0) ? (1 << crtc) : ((1 << drm_res_info->count_crtcs) - 1);
|
||||
|
||||
// If drawing to a plane is requested, obtain the plane info
|
||||
if (plane >= 0) {
|
||||
drm_plane_res_info = drmModeGetPlaneResources(drm_fd);
|
||||
if (!drm_plane_res_info) {
|
||||
printf("Unable to obtain plane resource list\n");
|
||||
exit(5);
|
||||
}
|
||||
if (plane >= drm_plane_res_info->count_planes) {
|
||||
printf("Requested plane index (%d) exceeds count (%d)\n", plane,
|
||||
drm_plane_res_info->count_planes);
|
||||
exit(5);
|
||||
}
|
||||
drm_plane_id = drm_plane_res_info->planes[plane];
|
||||
drm_plane_info = drmModeGetPlane(drm_fd, drm_plane_id);
|
||||
if (!drm_plane_info) {
|
||||
printf("Unable to obtain info for plane (%d)\n", drm_plane_id);
|
||||
exit(5);
|
||||
}
|
||||
crtc_mask &= drm_plane_info->possible_crtcs;
|
||||
if (!crtc_mask) {
|
||||
printf("Requested crtc and plane not compatible\n");
|
||||
exit(5);
|
||||
}
|
||||
printf("Obtained plane information\n");
|
||||
}
|
||||
|
||||
// Query info for requested connector
|
||||
int conn = 0;
|
||||
for (conn = 0; conn < drm_res_info->count_connectors; ++conn) {
|
||||
drm_conn_id = drm_res_info->connectors[conn];
|
||||
drm_conn_info = drmModeGetConnector(drm_fd, drm_conn_id);
|
||||
if (drm_conn_info != NULL) {
|
||||
printf("connector %d found\n", drm_conn_info->connector_id);
|
||||
if (drm_conn_info->connection == DRM_MODE_CONNECTED) {
|
||||
break;
|
||||
}
|
||||
drmModeFreeConnector(drm_conn_info);
|
||||
}
|
||||
}
|
||||
|
||||
if (conn == drm_res_info->count_connectors) {
|
||||
printf("No active connectors found\n");
|
||||
exit(6);
|
||||
}
|
||||
printf("Obtained connector information\n");
|
||||
|
||||
// If there is already an encoder attached to the connector, choose
|
||||
// it unless not compatible with crtc/plane
|
||||
drm_enc_id = drm_conn_info->encoder_id;
|
||||
drm_enc_info = drmModeGetEncoder(drm_fd, drm_enc_id);
|
||||
if (drm_enc_info) {
|
||||
if (!(drm_enc_info->possible_crtcs & crtc_mask)) {
|
||||
drmModeFreeEncoder(drm_enc_info);
|
||||
drm_enc_info = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// If we didn't have a suitable encoder, find one
|
||||
if (!drm_enc_info) {
|
||||
for (i = 0; i < drm_conn_info->count_encoders; ++i) {
|
||||
drm_enc_id = drm_conn_info->encoders[i];
|
||||
drm_enc_info = drmModeGetEncoder(drm_fd, drm_enc_id);
|
||||
if (drm_enc_info) {
|
||||
if (crtc_mask & drm_enc_info->possible_crtcs) {
|
||||
crtc_mask &= drm_enc_info->possible_crtcs;
|
||||
break;
|
||||
}
|
||||
drmModeFreeEncoder(drm_enc_info);
|
||||
drm_enc_info = NULL;
|
||||
}
|
||||
}
|
||||
if (i == drm_conn_info->count_encoders) {
|
||||
printf("Unable to find suitable encoder\n");
|
||||
exit(7);
|
||||
}
|
||||
}
|
||||
printf("Obtained encoder information\n");
|
||||
|
||||
// Select a suitable crtc. Give preference to any that's already
|
||||
// attached to the encoder. (Could make this more sophisticated
|
||||
// by finding one not already bound to any other encoders. But
|
||||
// this is just a basic test, so we don't really care that much.)
|
||||
assert(crtc_mask);
|
||||
for (i = 0; i < drm_res_info->count_crtcs; ++i) {
|
||||
if (crtc_mask & (1 << i)) {
|
||||
drm_crtc_id = drm_res_info->crtcs[i];
|
||||
if (drm_res_info->crtcs[i] == drm_enc_info->crtc_id) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Query info for crtc
|
||||
drm_crtc_info = drmModeGetCrtc(drm_fd, drm_crtc_id);
|
||||
if (!drm_crtc_info) {
|
||||
printf("Unable to obtain info for crtc (%d)\n", drm_crtc_id);
|
||||
exit(4);
|
||||
}
|
||||
printf("Obtained crtc information\n");
|
||||
|
||||
// If dimensions are specified and not using a plane, find closest mode
|
||||
if ((xmodesize || ymodesize) && (plane < 0)) {
|
||||
// Find best fit among available modes
|
||||
int best_index = 0;
|
||||
int best_fit = 0x7fffffff;
|
||||
for (i = 0; i < drm_conn_info->count_modes; ++i) {
|
||||
drmModeModeInfoPtr mode = drm_conn_info->modes + i;
|
||||
int fit = 0;
|
||||
|
||||
if (xmodesize) {
|
||||
fit += abs((int)mode->hdisplay - xmodesize) * (int)mode->vdisplay;
|
||||
}
|
||||
if (ymodesize) {
|
||||
fit += abs((int)mode->vdisplay - ymodesize) * (int)mode->hdisplay;
|
||||
}
|
||||
|
||||
if (fit < best_fit) {
|
||||
best_index = i;
|
||||
best_fit = fit;
|
||||
}
|
||||
}
|
||||
|
||||
// Choose this size/mode
|
||||
drm_mode_index = best_index;
|
||||
xmodesize = (int)drm_conn_info->modes[best_index].hdisplay;
|
||||
ymodesize = (int)drm_conn_info->modes[best_index].vdisplay;
|
||||
}
|
||||
|
||||
// We'll only set the mode if we have to. This hopefully allows
|
||||
// multiple instances of this application to run, writing to
|
||||
// separate planes of the same display, as long as they don't
|
||||
// specifiy incompatible settings.
|
||||
if ((drm_conn_info->encoder_id != drm_enc_id) ||
|
||||
(drm_enc_info->crtc_id != drm_crtc_id) || !drm_crtc_info->mode_valid ||
|
||||
((plane < 0) && xmodesize &&
|
||||
(xmodesize != (int)drm_crtc_info->mode.hdisplay)) ||
|
||||
((plane < 0) && ymodesize &&
|
||||
(ymodesize != (int)drm_crtc_info->mode.vdisplay))) {
|
||||
set_mode = true;
|
||||
}
|
||||
|
||||
// If dimensions haven't been specified, figure out good values to use
|
||||
if (!xmodesize || !ymodesize) {
|
||||
// If mode requires reset, just pick the first one available
|
||||
// from the connector
|
||||
if (set_mode) {
|
||||
xmodesize = (int)drm_conn_info->modes[0].hdisplay;
|
||||
ymodesize = (int)drm_conn_info->modes[0].vdisplay;
|
||||
}
|
||||
|
||||
// Otherwise get it from the current crtc settings
|
||||
else {
|
||||
xmodesize = (int)drm_crtc_info->mode.hdisplay;
|
||||
ymodesize = (int)drm_crtc_info->mode.vdisplay;
|
||||
}
|
||||
}
|
||||
printf("Determine mode settings\n");
|
||||
|
||||
// If surf size is unspecified, default to fullscreen normally
|
||||
// or to 1/4 fullscreen if in animated bounce mode.
|
||||
if (!xsurfsize || !ysurfsize) {
|
||||
if (bounce) {
|
||||
xsurfsize = xmodesize / 2;
|
||||
ysurfsize = ymodesize / 2;
|
||||
} else {
|
||||
xsurfsize = xmodesize;
|
||||
ysurfsize = ymodesize;
|
||||
}
|
||||
}
|
||||
printf("Determine surface size\n");
|
||||
|
||||
// create framebuffer (required for nvidia-drm)
|
||||
drmVersionPtr version = drmGetVersion(drm_fd);
|
||||
if (!version) {
|
||||
printf("drmGetVersion() failed..\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (!strcmp(version->name, "nvidia-drm")) {
|
||||
drm_mode_create_dumb prop;
|
||||
memset(&prop, 0, sizeof(drm_mode_create_dumb));
|
||||
prop.width = xmodesize;
|
||||
prop.height = ymodesize;
|
||||
prop.bpp = 32;
|
||||
|
||||
int res = drmIoctl(drm_fd, DRM_IOCTL_MODE_CREATE_DUMB, &prop);
|
||||
if (res) {
|
||||
printf("drmIoctl() failed..(%d)\n", res);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
uint32_t offset = 0;
|
||||
res = drmModeAddFB2(drm_fd, xmodesize, ymodesize, DRM_FORMAT_ARGB8888,
|
||||
&(prop.handle), &(prop.pitch), &offset, &fb_id, 0);
|
||||
if (res) {
|
||||
printf("drmModeAddFB() failed..(%d)\n", res);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (version) {
|
||||
drmFreeVersion(version);
|
||||
version = NULL;
|
||||
}
|
||||
|
||||
// If necessary, set the mode
|
||||
if (set_mode) {
|
||||
drmModeSetCrtc(drm_fd, drm_crtc_id, fb_id, 0, 0, &drm_conn_id, 1,
|
||||
drm_conn_info->modes + drm_mode_index);
|
||||
printf("Set mode\n");
|
||||
}
|
||||
|
||||
// If plane is in use, set it
|
||||
if (plane >= 0) {
|
||||
drmModeSetPlane(drm_fd, drm_plane_id, drm_crtc_id, fb_id, 0, xoffset,
|
||||
yoffset, xsurfsize, ysurfsize, 0, 0, xsurfsize << 16,
|
||||
ysurfsize << 16);
|
||||
printf("Set plane configuration\n");
|
||||
}
|
||||
|
||||
// Obtain and initialize EGLDisplay
|
||||
int attr[] = {EGL_DRM_MASTER_FD_EXT, drm_fd, EGL_NONE};
|
||||
eglDisplay =
|
||||
eglGetPlatformDisplayEXT(EGL_PLATFORM_DEVICE_EXT, (void *)egl_dev, attr);
|
||||
if (eglDisplay == EGL_NO_DISPLAY) {
|
||||
printf("Couldn't obtain EGLDisplay for device\n");
|
||||
exit(8);
|
||||
}
|
||||
if (!eglInitialize(eglDisplay, &major, &minor)) {
|
||||
printf("Couldn't initialize EGLDisplay (error 0x%x)\n", eglGetError());
|
||||
exit(8);
|
||||
}
|
||||
printf("Obtained EGLDisplay\n");
|
||||
|
||||
// Check for stream_consumer_egloutput + output_drm support
|
||||
const char *dpy_exts = eglQueryString(eglDisplay, EGL_EXTENSIONS);
|
||||
const char *dev_exts = eglQueryDeviceStringEXT(egl_dev, EGL_EXTENSIONS);
|
||||
|
||||
if (!CheckExtension(dpy_exts, "EGL_EXT_output_base")) {
|
||||
printf("Missing required extension: EGL_EXT_output_base\n");
|
||||
exit(2);
|
||||
}
|
||||
|
||||
if (!CheckExtension(dev_exts, "EGL_EXT_device_drm")) {
|
||||
printf("Missing required extension: EGL_EXT_device_drm\n");
|
||||
exit(2);
|
||||
}
|
||||
|
||||
if (!CheckExtension(dpy_exts, "EGL_EXT_output_drm")) {
|
||||
printf("Missing required extension: EGL_EXT_output_drm\n");
|
||||
exit(2);
|
||||
}
|
||||
|
||||
if (!CheckExtension(dpy_exts, "EGL_EXT_stream_consumer_egloutput")) {
|
||||
printf("Missing required extension: EGL_EXT_stream_consumer_egloutput\n");
|
||||
exit(2);
|
||||
}
|
||||
|
||||
// Choose a config and create a context
|
||||
EGLint cfg_attr[] = {EGL_SURFACE_TYPE,
|
||||
EGL_STREAM_BIT_KHR,
|
||||
EGL_RENDERABLE_TYPE,
|
||||
EGL_OPENGL_ES2_BIT,
|
||||
EGL_ALPHA_SIZE,
|
||||
1,
|
||||
EGL_NONE};
|
||||
if (!eglChooseConfig(eglDisplay, cfg_attr, &egl_cfg, 1, &n) || !n) {
|
||||
printf(
|
||||
"Unable to obtain config that supports stream rendering (error 0x%x)\n",
|
||||
eglGetError());
|
||||
exit(9);
|
||||
}
|
||||
EGLint ctx_attr[] = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE};
|
||||
|
||||
eglBindAPI(EGL_OPENGL_ES_API);
|
||||
|
||||
eglContext = eglCreateContext(eglDisplay, egl_cfg, EGL_NO_CONTEXT, ctx_attr);
|
||||
if (eglContext == EGL_NO_CONTEXT) {
|
||||
printf("Unable to create context (error 0x%x)\n", eglGetError());
|
||||
exit(9);
|
||||
}
|
||||
printf("Obtained EGLConfig and EGLContext\n");
|
||||
|
||||
// Get the layer for this crtc/plane
|
||||
EGLAttrib layer_attr[] = {EGL_NONE, EGL_NONE, EGL_NONE};
|
||||
if (plane >= 0) {
|
||||
layer_attr[0] = EGL_DRM_PLANE_EXT;
|
||||
layer_attr[1] = (EGLAttrib)drm_plane_id;
|
||||
} else {
|
||||
layer_attr[0] = EGL_DRM_CRTC_EXT;
|
||||
layer_attr[1] = (EGLAttrib)drm_crtc_id;
|
||||
}
|
||||
if (!eglGetOutputLayersEXT(eglDisplay, layer_attr, &egl_lyr, 1, &n) || !n) {
|
||||
printf("Unable to obtain EGLOutputLayer for %s 0x%x\n",
|
||||
(plane >= 0) ? "plane" : "crtc", (int)layer_attr[1]);
|
||||
exit(10);
|
||||
}
|
||||
printf("Obtained EGLOutputLayer\n");
|
||||
|
||||
// Create a stream and connect to the output
|
||||
EGLint stream_attr[] = {EGL_STREAM_FIFO_LENGTH_KHR, fifo, EGL_NONE};
|
||||
egl_str = eglCreateStreamKHR(eglDisplay, stream_attr);
|
||||
if (egl_str == EGL_NO_STREAM_KHR) {
|
||||
printf("Unable to create stream (error 0x%x)\n", eglGetError());
|
||||
exit(11);
|
||||
}
|
||||
if (!eglStreamConsumerOutputEXT(eglDisplay, egl_str, egl_lyr)) {
|
||||
printf("Unable to connect stream (error 0x%x)\n", eglGetError());
|
||||
exit(11);
|
||||
}
|
||||
|
||||
// Create a surface to feed the stream
|
||||
EGLint srf_attr[] = {EGL_WIDTH, xsurfsize, EGL_HEIGHT, ysurfsize, EGL_NONE};
|
||||
eglSurface =
|
||||
eglCreateStreamProducerSurfaceKHR(eglDisplay, egl_cfg, egl_str, srf_attr);
|
||||
if (eglSurface == EGL_NO_SURFACE) {
|
||||
printf("Unable to create rendering surface (error 0x%x)\n", eglGetError());
|
||||
exit(12);
|
||||
}
|
||||
printf("Bound layer to rendering surface\n");
|
||||
|
||||
// Make current
|
||||
if (!eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext)) {
|
||||
printf("Unable to make context/surface current (error 0x%x)\n",
|
||||
eglGetError());
|
||||
exit(13);
|
||||
}
|
||||
|
||||
EGLint Context_RendererType;
|
||||
eglQueryContext(eglDisplay, eglContext, EGL_CONTEXT_CLIENT_TYPE,
|
||||
&Context_RendererType);
|
||||
|
||||
#if 0
|
||||
switch (Context_RendererType)
|
||||
{
|
||||
case EGL_OPENGL_API:
|
||||
printf("Using OpenGL API\n");
|
||||
break;
|
||||
case EGL_OPENGL_ES_API:
|
||||
printf("Using OpenGL ES API");
|
||||
break;
|
||||
case 0xB6D185E8:
|
||||
printf("Using EGLOutput context.\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);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0 // obtain API function pointers _manually_ (see function pointer
|
||||
// declarations above)
|
||||
my_glGetError = (glGetErrorTYPE) eglGetProcAddress("glGetError");
|
||||
my_glGetString = (glGetStringTYPE) eglGetProcAddress("glGetString");
|
||||
my_glGetProgramiv = (glGetProgramivTYPE) eglGetProcAddress("glGetProgramiv");
|
||||
|
||||
|
||||
GL_APICALL void (* my_glGenBuffers) (GLsizei n, GLuint *buffers);
|
||||
my_glGenBuffers = ((*) (GLsizei n, GLuint *buffers)) eglGetProcAddress("glGenBuffers");
|
||||
|
||||
GL_APICALL void (* my_glGetShaderInfoLog) (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
|
||||
my_glGetShaderInfoLog = ((*) (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog)) eglGetProcAddress("glGetShaderInfoLog");
|
||||
|
||||
GL_APICALL void GL_APIENTRY glBindBuffer (GLenum target, GLuint buffer);
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void graphics_set_windowtitle(const char *windowname) {
|
||||
printf(" Window title would have been: %s\n", 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 0
|
||||
if (plane >= 0)
|
||||
drmModeSetPlane(drm_fd, drm_plane_id, drm_crtc_id, 0, 0,
|
||||
xoffset, yoffset, xsurfsize, ysurfsize,
|
||||
0, 0, xsurfsize << 16, ysurfsize << 16);
|
||||
else
|
||||
drmModeSetCrtc(drm_fd, drm_crtc_id, 0, xoffset, yoffset, &drm_conn_id, 1,
|
||||
NULL);
|
||||
#endif
|
||||
|
||||
printf("Released display resources\n");
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
attribute vec4 position;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = position;
|
||||
}
|
||||
@@ -0,0 +1,571 @@
|
||||
/* Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
This example demonstrates how to use the CUDA C bindings to OpenGL ES to
|
||||
dynamically modify a vertex buffer using a CUDA C kernel.
|
||||
|
||||
The steps are:
|
||||
1. Create an empty vertex buffer object (VBO)
|
||||
2. Register the VBO with CUDA C
|
||||
3. Map the VBO for writing from CUDA C
|
||||
4. Run CUDA C kernel to modify the vertex positions
|
||||
5. Unmap the VBO
|
||||
6. Render the results using OpenGL ES
|
||||
|
||||
Host code
|
||||
*/
|
||||
|
||||
// includes, system
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <unistd.h>
|
||||
|
||||
void error_exit(const char *format, ...) {
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
vfprintf(stderr, format, args);
|
||||
va_end(args);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
#if 0
|
||||
#include "graphics_interface.c"
|
||||
#else
|
||||
#include "graphics_interface_egloutput_via_egl.c"
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#define WINDOWS_LEAN_AND_MEAN
|
||||
#define NOMINMAX
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
// includes, cuda
|
||||
#include <cuda_gl_interop.h>
|
||||
#include <cuda_runtime.h>
|
||||
|
||||
// Utilities and timing functions
|
||||
#include <helper_functions.h> // includes cuda.h and cuda_runtime_api.h
|
||||
|
||||
// CUDA helper functions
|
||||
#include <helper_cuda.h> // helper functions for CUDA error check
|
||||
//#include <helper_cuda_gl.h> // helper functions for CUDA/GL interop
|
||||
|
||||
#include <vector_types.h>
|
||||
|
||||
#define MAX_EPSILON_ERROR 0.0f
|
||||
#define THRESHOLD 0.0f
|
||||
#define REFRESH_DELAY 1 // ms
|
||||
|
||||
#define GUI_IDLE 0x100
|
||||
#define GUI_ROTATE 0x101
|
||||
#define GUI_TRANSLATE 0x102
|
||||
|
||||
int gui_mode;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// constants
|
||||
const unsigned int window_width = 512;
|
||||
const unsigned int window_height = 512;
|
||||
|
||||
const unsigned int mesh_width = 256;
|
||||
const unsigned int mesh_height = 256;
|
||||
|
||||
// OpenGL ES variables and interop with CUDA C
|
||||
GLuint mesh_vao, mesh_vbo;
|
||||
struct cudaGraphicsResource *cuda_vbo_resource;
|
||||
void *d_vbo_buffer = NULL;
|
||||
|
||||
float g_fAnim = 0.0;
|
||||
|
||||
// UI / mouse controls
|
||||
int mouse_old_x, mouse_old_y;
|
||||
int mouse_buttons = 0;
|
||||
float rotate_x = 0.0, rotate_y = 0.0;
|
||||
float translate_z = -3.0;
|
||||
|
||||
StopWatchInterface *timer = NULL;
|
||||
|
||||
// Frame statistics
|
||||
int frame;
|
||||
int fpsCount = 0; // FPS count for averaging
|
||||
int fpsLimit = 1; // FPS limit for sampling
|
||||
int g_Index = 0;
|
||||
float avgFPS = 0.0f;
|
||||
unsigned int frameCount = 0;
|
||||
unsigned int g_TotalErrors = 0;
|
||||
|
||||
// Auto-Verification Code
|
||||
bool g_bQAReadback = false;
|
||||
|
||||
int *pArgc = NULL;
|
||||
char **pArgv = NULL;
|
||||
|
||||
#define MAX(a, b) ((a > b) ? a : b)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// declaration, forward
|
||||
|
||||
// CUDA functionality
|
||||
void runCuda(struct cudaGraphicsResource **vbo_resource);
|
||||
void runAutoTest(int devID, char **argv, char *ref_file);
|
||||
void checkResultCuda(int argc, char **argv, const GLuint &vbo);
|
||||
|
||||
const char *sSDKsample = "simpleGLES (VBO)";
|
||||
|
||||
void computeFPS() {
|
||||
frameCount++;
|
||||
fpsCount++;
|
||||
|
||||
if (fpsCount == fpsLimit) {
|
||||
avgFPS = 1.f / (sdkGetAverageTimerValue(&timer) / 1000.f);
|
||||
fpsCount = 0;
|
||||
fpsLimit = (int)MAX(avgFPS, 1.f);
|
||||
|
||||
sdkResetTimer(&timer);
|
||||
}
|
||||
|
||||
char fps[256];
|
||||
sprintf(fps, "Cuda/OpenGL ES Interop (VBO): %3.1f fps (Max 1000 fps)",
|
||||
avgFPS);
|
||||
graphics_set_windowtitle(fps);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//! Simple kernel to modify vertex positions in sine wave pattern
|
||||
//! @param data data in global memory
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
__global__ void simple_vbo_kernel(float4 *pos, unsigned int width,
|
||||
unsigned int height, float time) {
|
||||
unsigned int x = blockIdx.x * blockDim.x + threadIdx.x;
|
||||
unsigned int y = blockIdx.y * blockDim.y + threadIdx.y;
|
||||
|
||||
// calculate uv coordinates
|
||||
float u = x / (float)width;
|
||||
float v = y / (float)height;
|
||||
u = u * 2.0f - 1.0f;
|
||||
v = v * 2.0f - 1.0f;
|
||||
|
||||
// calculate simple sine wave pattern
|
||||
float freq = 4.0f;
|
||||
float w = sinf(u * freq + time) * cosf(v * freq + time) * 0.5f;
|
||||
|
||||
// write output vertex
|
||||
pos[y * width + x] = make_float4(u, w, v, 1.0f);
|
||||
}
|
||||
|
||||
void launch_kernel(float4 *pos, unsigned int mesh_width,
|
||||
unsigned int mesh_height, float time) {
|
||||
// execute the kernel
|
||||
dim3 block(8, 8, 1);
|
||||
dim3 grid(mesh_width / block.x, mesh_height / block.y, 1);
|
||||
simple_vbo_kernel<<<grid, block>>>(pos, mesh_width, mesh_height, time);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//! Run the Cuda part of the computation
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void runCuda(struct cudaGraphicsResource **vbo_resource) {
|
||||
// map OpenGL buffer object for writing from CUDA
|
||||
float4 *dptr;
|
||||
cudaGraphicsMapResources(1, vbo_resource, 0);
|
||||
size_t num_bytes;
|
||||
cudaGraphicsResourceGetMappedPointer((void **)&dptr, &num_bytes,
|
||||
*vbo_resource);
|
||||
// printf("Sample CUDA mapped VBO: May access %ld bytes\n", num_bytes);
|
||||
|
||||
// execute the kernel
|
||||
// dim3 block(8, 8, 1);
|
||||
// dim3 grid(mesh_width / block.x, mesh_height / block.y, 1);
|
||||
// kernel<<< grid, block>>>(dptr, mesh_width, mesh_height, g_fAnim);
|
||||
|
||||
launch_kernel(dptr, mesh_width, mesh_height, g_fAnim);
|
||||
|
||||
// unmap buffer object
|
||||
cudaGraphicsUnmapResources(1, vbo_resource, 0);
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
#ifndef FOPEN
|
||||
#define FOPEN(fHandle, filename, mode) fopen_s(&fHandle, filename, mode)
|
||||
#endif
|
||||
#else
|
||||
#ifndef FOPEN
|
||||
#define FOPEN(fHandle, filename, mode) (fHandle = fopen(filename, mode))
|
||||
#endif
|
||||
#endif
|
||||
|
||||
void sdkDumpBin2(void *data, unsigned int bytes, const char *filename) {
|
||||
printf("sdkDumpBin: <%s>\n", filename);
|
||||
FILE *fp;
|
||||
FOPEN(fp, filename, "wb");
|
||||
fwrite(data, bytes, 1, fp);
|
||||
fflush(fp);
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//! Run the Cuda part of the computation
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void runAutoTest(int devID, char **argv, char *ref_file) {
|
||||
char *reference_file = NULL;
|
||||
void *imageData = malloc(mesh_width * mesh_height * sizeof(float));
|
||||
|
||||
// execute the kernel
|
||||
launch_kernel((float4 *)d_vbo_buffer, mesh_width, mesh_height, g_fAnim);
|
||||
|
||||
cudaDeviceSynchronize();
|
||||
getLastCudaError("launch_kernel failed");
|
||||
|
||||
cudaMemcpy(imageData, d_vbo_buffer, mesh_width * mesh_height * sizeof(float),
|
||||
cudaMemcpyDeviceToHost);
|
||||
|
||||
sdkDumpBin2(imageData, mesh_width * mesh_height * sizeof(float),
|
||||
"simpleGL.bin");
|
||||
reference_file = sdkFindFilePath(ref_file, argv[0]);
|
||||
|
||||
if (reference_file &&
|
||||
!sdkCompareBin2BinFloat("simpleGL.bin", reference_file,
|
||||
mesh_width * mesh_height * sizeof(float),
|
||||
MAX_EPSILON_ERROR, THRESHOLD, pArgv[0])) {
|
||||
g_TotalErrors++;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//! Display callback
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void display_thisframe(float time_delta) {
|
||||
sdkStartTimer(&timer);
|
||||
|
||||
// run CUDA kernel to generate vertex positions
|
||||
runCuda(&cuda_vbo_resource);
|
||||
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
// GET_GLERROR(0);
|
||||
|
||||
// set view matrix: broken, it doesn't work in OpenGL ES! Must put into shader
|
||||
// glMatrixMode(GL_MODELVIEW);
|
||||
// glLoadIdentity();
|
||||
// glTranslatef(0.0, 0.0, translate_z);
|
||||
// glRotatef(rotate_x, 1.0, 0.0, 0.0);
|
||||
// glRotatef(rotate_y, 0.0, 1.0, 0.0);
|
||||
|
||||
glDrawArrays(GL_POINTS, 0, mesh_width * mesh_height);
|
||||
|
||||
// GET_GLERROR(0);
|
||||
glFinish();
|
||||
// GET_GLERROR(0);
|
||||
|
||||
g_fAnim += time_delta;
|
||||
|
||||
sdkStopTimer(&timer);
|
||||
computeFPS();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//! Check if the result is correct or write data to file for external
|
||||
//! regression testing
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void checkResultCuda(int argc, char **argv, const GLuint &vbo) {
|
||||
if (!d_vbo_buffer) {
|
||||
printf("%s: Mapping result buffer from OpenGL ES\n", __FUNCTION__);
|
||||
|
||||
cudaGraphicsUnregisterResource(cuda_vbo_resource);
|
||||
|
||||
// map buffer object
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vbo);
|
||||
float *data = (float *)glMapBufferRange(
|
||||
GL_ARRAY_BUFFER, 0, mesh_width * mesh_height * 4 * sizeof(float),
|
||||
GL_READ_ONLY);
|
||||
|
||||
// check result
|
||||
if (checkCmdLineFlag(argc, (const char **)argv, "regression")) {
|
||||
// write file for regression test
|
||||
sdkWriteFile<float>("./data/regression.dat", data,
|
||||
mesh_width * mesh_height * 3, 0.0, false);
|
||||
}
|
||||
|
||||
// unmap GL buffer object
|
||||
if (!glUnmapBuffer(GL_ARRAY_BUFFER)) {
|
||||
fprintf(stderr, "Unmap buffer failed.\n");
|
||||
fflush(stderr);
|
||||
}
|
||||
|
||||
checkCudaErrors(cudaGraphicsGLRegisterBuffer(
|
||||
&cuda_vbo_resource, vbo, cudaGraphicsMapFlagsWriteDiscard));
|
||||
|
||||
GET_GLERROR(0);
|
||||
}
|
||||
}
|
||||
|
||||
GLuint mesh_shader = 0;
|
||||
|
||||
void readAndCompileShaderFromGLSLFile(GLuint new_shaderprogram,
|
||||
const char *filename, GLenum shaderType) {
|
||||
FILE *file = fopen(filename, "rb"); // open shader text file
|
||||
if (!file) error_exit("Filename %s does not exist\n", filename);
|
||||
|
||||
/* get the size of the file and read it */
|
||||
fseek(file, 0, SEEK_END);
|
||||
GLint size = ftell(file);
|
||||
char *data = (char *)malloc(sizeof(char) * (size + 1));
|
||||
memset(data, 0, sizeof(char) * (size + 1));
|
||||
fseek(file, 0, SEEK_SET);
|
||||
size_t res = fread(data, 1, size, file);
|
||||
fclose(file);
|
||||
|
||||
GLuint shader = glCreateShader(shaderType);
|
||||
glShaderSource(shader, 1, (const GLchar **)&data, &size);
|
||||
glCompileShader(shader);
|
||||
|
||||
GET_GLERROR(0);
|
||||
GLint compile_success = 0;
|
||||
glGetShaderiv(shader, GL_COMPILE_STATUS, &compile_success);
|
||||
GET_GLERROR(0);
|
||||
|
||||
if (compile_success == GL_FALSE) {
|
||||
printf("Compilation of %s failed!\n Reason:\n", filename);
|
||||
|
||||
GLint maxLength = 0;
|
||||
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &maxLength);
|
||||
|
||||
char errorLog[maxLength];
|
||||
glGetShaderInfoLog(shader, maxLength, &maxLength, &errorLog[0]);
|
||||
|
||||
printf("%s", errorLog);
|
||||
|
||||
glDeleteShader(shader);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
glAttachShader(new_shaderprogram, shader);
|
||||
glDeleteShader(shader); // good to do?
|
||||
|
||||
free(data);
|
||||
}
|
||||
|
||||
GLuint ShaderCreate(const char *vshader_filename,
|
||||
const char *fshader_filename) {
|
||||
printf("Loading GLSL shaders %s %s\n", vshader_filename, fshader_filename);
|
||||
|
||||
GLuint new_shaderprogram = glCreateProgram();
|
||||
|
||||
GET_GLERROR(0);
|
||||
if (vshader_filename)
|
||||
readAndCompileShaderFromGLSLFile(new_shaderprogram, vshader_filename,
|
||||
GL_VERTEX_SHADER);
|
||||
|
||||
GET_GLERROR(0);
|
||||
if (fshader_filename)
|
||||
readAndCompileShaderFromGLSLFile(new_shaderprogram, fshader_filename,
|
||||
GL_FRAGMENT_SHADER);
|
||||
|
||||
GET_GLERROR(0);
|
||||
|
||||
glLinkProgram(new_shaderprogram);
|
||||
|
||||
GET_GLERROR(0);
|
||||
GLint link_success;
|
||||
glGetProgramiv(new_shaderprogram, GL_LINK_STATUS, &link_success);
|
||||
|
||||
if (link_success == GL_FALSE) {
|
||||
printf("Linking of %s with %s failed!\n Reason:\n", vshader_filename,
|
||||
fshader_filename);
|
||||
|
||||
GLint maxLength = 0;
|
||||
glGetShaderiv(new_shaderprogram, GL_INFO_LOG_LENGTH, &maxLength);
|
||||
|
||||
char errorLog[maxLength];
|
||||
glGetShaderInfoLog(new_shaderprogram, maxLength, &maxLength, &errorLog[0]);
|
||||
|
||||
printf("%s", errorLog);
|
||||
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
return new_shaderprogram;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
// InitGraphicsState() - initialize OpenGL
|
||||
//===========================================================================
|
||||
static void InitGraphicsState(char **argv) {
|
||||
char *GL_version = (char *)glGetString(GL_VERSION);
|
||||
char *GL_vendor = (char *)glGetString(GL_VENDOR);
|
||||
char *GL_renderer = (char *)glGetString(GL_RENDERER);
|
||||
|
||||
printf("Version: %s\n", GL_version);
|
||||
printf("Vendor: %s\n", GL_vendor);
|
||||
printf("Renderer: %s\n", GL_renderer);
|
||||
|
||||
// RENDERING SETUP (OpenGL ES or OpenGL Core Profile!)
|
||||
glGenVertexArrays(1, &mesh_vao); // Features' Vertex Array Object allocation
|
||||
glBindVertexArray(mesh_vao); // bind VAO
|
||||
|
||||
// initialize buffer object
|
||||
glGenBuffers(1, &mesh_vbo);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, mesh_vbo);
|
||||
|
||||
unsigned int size = mesh_width * mesh_height * 4 * sizeof(float);
|
||||
glBufferData(GL_ARRAY_BUFFER, size, NULL, GL_DYNAMIC_DRAW);
|
||||
glVertexAttribPointer((GLuint)0, 4, GL_FLOAT, GL_FALSE, 0, 0);
|
||||
glEnableVertexAttribArray(0);
|
||||
|
||||
checkCudaErrors(cudaGraphicsGLRegisterBuffer(&cuda_vbo_resource, mesh_vbo,
|
||||
cudaGraphicsMapFlagsNone));
|
||||
|
||||
// glBindVertexArray(0); // keep above Vertex Array Object bound (it's the
|
||||
// only one throughout)
|
||||
|
||||
// GLSL stuff
|
||||
char *vertex_shader_path = sdkFindFilePath("mesh.vert.glsl", argv[0]);
|
||||
char *fragment_shader_path = sdkFindFilePath("mesh.frag.glsl", argv[0]);
|
||||
|
||||
if (vertex_shader_path == NULL || fragment_shader_path == NULL) {
|
||||
printf("Error finding shader file\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
mesh_shader = ShaderCreate(vertex_shader_path, fragment_shader_path);
|
||||
GET_GLERROR(0);
|
||||
|
||||
free(vertex_shader_path);
|
||||
free(fragment_shader_path);
|
||||
|
||||
glUseProgram(mesh_shader);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//! Run a simple test for CUDA
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
bool runTest(int argc, char **argv, char *ref_file) {
|
||||
// Create the CUTIL timer
|
||||
sdkCreateTimer(&timer);
|
||||
|
||||
int devID = 0;
|
||||
#if defined(__aarch64__) || defined(__arm__)
|
||||
// find iGPU on the system which is compute capable which will perform
|
||||
// GLES-CUDA interop
|
||||
devID = findIntegratedGPU();
|
||||
#else
|
||||
// use command-line specified CUDA device, otherwise use device with highest
|
||||
// Gflops/s
|
||||
devID = findCudaDevice(argc, (const char **)argv);
|
||||
#endif
|
||||
|
||||
// command line mode only
|
||||
if (ref_file != NULL) {
|
||||
// create VBO
|
||||
checkCudaErrors(cudaMalloc((void **)&d_vbo_buffer,
|
||||
mesh_width * mesh_height * 4 * sizeof(float)));
|
||||
|
||||
// run the cuda part
|
||||
runAutoTest(devID, argv, ref_file);
|
||||
|
||||
// check result of Cuda step
|
||||
checkResultCuda(argc, argv, mesh_vbo);
|
||||
|
||||
cudaFree(d_vbo_buffer);
|
||||
d_vbo_buffer = NULL;
|
||||
} else {
|
||||
// this would use command-line specified CUDA device, note that CUDA
|
||||
// defaults to highest Gflops/s device
|
||||
if (checkCmdLineFlag(argc, (const char **)argv, "device"))
|
||||
error_exit("Device setting not yet implemented!\n");
|
||||
|
||||
// create X11 window and set up associated OpenGL ES context
|
||||
graphics_setup_window(0, 0, window_width, window_height, sSDKsample);
|
||||
|
||||
InitGraphicsState(argv); // set up GLES stuff
|
||||
|
||||
glClearColor(0, 0.5, 1, 1); // blue-ish background
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
// printf("WP%d\n", __LINE__);
|
||||
graphics_swap_buffers();
|
||||
|
||||
int frame = 0;
|
||||
|
||||
while (frame < 1000) {
|
||||
display_thisframe(0.010);
|
||||
usleep(1000); // need not take full CPU and GPU
|
||||
|
||||
graphics_swap_buffers();
|
||||
// printf("frame %d\n",frame++);
|
||||
}
|
||||
|
||||
// NOTE: Before destroying OpenGL ES context, must unregister all shared
|
||||
// resources from CUDA !
|
||||
cudaGraphicsUnregisterResource(cuda_vbo_resource);
|
||||
|
||||
graphics_close_window(); // close window and destroy OpenGL ES context
|
||||
|
||||
sdkDeleteTimer(&timer);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Program main
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
int main(int argc, char **argv) {
|
||||
char *ref_file = NULL;
|
||||
|
||||
pArgc = &argc;
|
||||
pArgv = argv;
|
||||
|
||||
#if defined(__linux__)
|
||||
setenv("DISPLAY", ":0", 0);
|
||||
#endif
|
||||
|
||||
printf("%s starting...\n", sSDKsample);
|
||||
|
||||
if (argc > 1) {
|
||||
if (checkCmdLineFlag(argc, (const char **)argv, "file")) {
|
||||
// In this mode, we run without OpenGL and see if VBO is generated
|
||||
// correctly
|
||||
getCmdLineArgumentString(argc, (const char **)argv, "file",
|
||||
(char **)&ref_file);
|
||||
}
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
|
||||
runTest(argc, argv, ref_file);
|
||||
|
||||
printf("%s completed, returned %s\n", sSDKsample,
|
||||
(g_TotalErrors == 0) ? "OK" : "ERROR!");
|
||||
|
||||
exit(g_TotalErrors == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
|
||||
}
|
||||
Reference in New Issue
Block a user