├── .gitignore
├── CMakeLists.txt
├── LICENSE
├── README.md
├── build.bat
├── cmake
├── FindBoostNumpy.cmake
├── FindCUDADriver.cmake
├── FindGLFW.cmake
├── FindOpenCL.cmake
├── FindOpenEXR.cmake
└── cmake_uninstall.cmake.in
├── cpack
└── CMakeCPackOptions.cmake.in
├── doc
├── CMakeLists.txt
├── Doxyfile.in
├── mainpage.h
└── update-web-api.sh
├── examples
├── boxblur_cuda.ip
├── boxblur_glsl.ip
├── boxblur_opencl.ip
├── example.cpp
├── gaussblur_cuda.ip
├── gaussblur_glsl.ip
├── gaussblur_opencl.ip
├── gaussblur_separable_cuda.ip
├── gaussblur_separable_glsl.ip
├── gaussblur_separable_opencl.ip
├── images
│ └── README
├── kernels
│ ├── box_blur.cl
│ ├── box_blur.cu
│ ├── box_blur.glsl
│ ├── gaussian_blur.cl
│ ├── gaussian_blur.cu
│ ├── gaussian_blur.glsl
│ ├── gaussian_blur_hor.cl
│ ├── gaussian_blur_hor.cu
│ ├── gaussian_blur_hor.glsl
│ ├── gaussian_blur_vert.cl
│ ├── gaussian_blur_vert.cu
│ ├── gaussian_blur_vert.glsl
│ ├── lerp.cl
│ ├── lerp.cu
│ ├── lerp.glsl
│ ├── lerp_float.cl
│ ├── lerp_float.cu
│ ├── lerp_ubyte.cl
│ ├── lerp_ubyte.cu
│ ├── sobel.cl
│ ├── sobel.cu
│ └── sobel.glsl
├── lerp_cuda.ip
├── lerp_cuda_float.ip
├── lerp_cuda_ubyte.ip
├── lerp_glsl.ip
├── lerp_glsl_float.ip
├── lerp_glsl_ubyte.ip
├── lerp_opencl.ip
├── lerp_opencl_float.ip
├── lerp_opencl_ubyte.ip
├── sobel_cuda.ip
├── sobel_glsl.ip
└── sobel_opencl.ip
├── install.bat
├── python
├── CMakeLists.txt
├── bufferswidget.py
├── displaywidget.py
├── gpuip.py
├── icons
│ ├── boilerplate.png
│ ├── build.png
│ ├── export.png
│ ├── generateIcons.py
│ ├── import.png
│ ├── init.png
│ ├── new.png
│ ├── newExisting.png
│ ├── open.png
│ ├── process.png
│ ├── pug.png
│ ├── refresh.png
│ ├── run.png
│ └── save.png
├── kernelwidget.py
├── mainwindow.py
├── newdialog.py
├── settings.py
├── stylesheet.py
└── utils.py
├── src
├── CMakeLists.txt
├── cuda.cpp
├── cuda.h
├── cuda_error.h
├── glcontext.h
├── glcontext.m
├── glsl.cpp
├── glsl.h
├── glsl_error.h
├── gpuip.cpp
├── gpuip.h
├── helper_math.cuh
├── io_wrapper.cpp
├── io_wrapper.h
├── opencl.cpp
├── opencl.h
├── opencl_error.h
└── python.cpp
└── test
├── CMakeLists.txt
├── performance.cpp
├── test.cpp
└── test.py
/.gitignore:
--------------------------------------------------------------------------------
1 | build
2 | doc/html
3 | doc/man
4 | doc/Doxyfile
5 | thirdparty
6 | *.exr
7 | *.png
8 | *.pyc
9 | python/icons.py
10 | python/gpuip
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2014 Per Karlsson
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | gpuip
2 | =====
3 |
4 | Gpuip is a C++ cross-platform framework for Image Processing on the GPU architechure. It tries to simplify the image processing pipeline on the GPU and make it more generic across the thre most common environments: OpenCL, CUDA and OpenGL GLSL. It provides a simple interface to copy data from and to the GPU and makes it easy to compile and run GPU kernel code.
5 |
6 | ### API
7 | The online API documentation [can be found here.] (http://karlssonper.github.io/gpuip/api/)
8 |
9 | ### pygpuip
10 | The gpuip library comes with optional python bindings to the C++ code. The python bindings have I/O operations included with .exr and .png support (and .jpeg, .tiff and .tga if dev libraries are found at build time). Numpy arrays are used to tranfser data to/from the GPU.
11 |
12 | ### bin/gpuip
13 | If python bindings are available, gpuip comes with an executable program that has both a GUI version for debugging and development of GPU kernels and a command line version to plug into existing pipelines. The progam uses the gpuip specific XML-based file format *.ip to store settings.
14 | ```
15 | usage: Framework for Image Processing on the GPU [-h] [-f FILE]
16 | [-p kernel param value]
17 | [-i buffer path]
18 | [-o buffer path] [-v]
19 | [--timestamp] [--nogui]
20 |
21 | optional arguments:
22 | -h, --help show this help message and exit
23 | -f FILE, --file FILE Image Processing file *.ip
24 | -p kernel param value, --param kernel param value
25 | Change value of a parameter.
26 | -i buffer path, --inbuffer buffer path
27 | Set input image to a buffer
28 | -o buffer path, --outbuffer buffer path
29 | Set output image to a buffer
30 | -v, --verbose Outputs information
31 | --timestamp Add timestamp in log output
32 | --nogui Command line version
33 |
34 | ```
35 |
36 | ### Dependencies
37 | * gpuip:
38 | * [`OpenCL`](https://www.khronos.org/opencl/) *optional*
39 | * [`CUDA`](https://developer.nvidia.com/cuda-zone) *optional*
40 | * [`OpenGL`](http://www.opengl.org/) *optional*
41 | * [`GLFW`] (http://www.glfw.org/) *OpenGL context creation*
42 | * [`GLEW`](http://glew.sourceforge.net/) *OpenGL extensions*
43 |
44 | * pygpuip:
45 | * [`Python`](http://www.python.org/) *version 2.6 or newer*
46 | * [`Boost Python`](http://www.boost.org/) *python C++ bindings*
47 | * [`Boost NumPy`] (https://github.com/ndarray/Boost.NumPy) *numpy C++ bindings*
48 | * [`OpenEXR`] (http://www.openexr.com/) *exr i/o*
49 | * [`CImg`] (http://cimg.sourceforge.net/) *png, jpeg,t iff, tga i/o*
50 | * [`libpng`] (http://www.libpng.org/pub/png/libpng.html) *png format*
51 | * [`zlib`] (http://www.zlib.net) *compression used by OpenEXR and libpng*
52 |
53 | * bin/gpuip
54 | * [`numpy`](http://www.numpy.org/) *python array object*
55 | * [`Qt`] (http://qt-project.org/) *GUI (optional)*
56 | * [`PIL`] (https://pypi.python.org/pypi/Pillow) *GUI icons (optional, needed at build)*
57 | * [`PySide`] (http://qt-project.org/wiki/PySide) *Qt python bindings*
58 |
59 |
60 | ### Build/Install ###
61 |
62 | #### Linux/OSX
63 |
64 | There are two bash scripts provided, `build.sh` and `install.sh`. If you want to generate your own Makefiles, use CMake:
65 | ```
66 | mkdir build
67 | cd build
68 | cmake ..
69 | make
70 | sudo make install
71 | ```
72 |
73 | #### Windows
74 | There are two batch scripts provided, `build.bat` and `install.bat`. If you want to generate your own Visual Studio Solution, use CMake:
75 | ```
76 | mkdir build
77 | cd build
78 | cmake ..
79 | cmake --build . --config Release
80 | ```
81 |
82 | If you have admin rights, you can add `--target INSTALL` to the last command to install files
83 |
84 |
85 | ### CMake options
86 |
87 | ```
88 | BUILD_THIRD_PARTY_LIBS // Build and link missing third party libraries
89 | BUILD_SHARED_LIB // Make gpuip a shared library
90 | BUILD_WITH_OPENCL // Support OpenCL (if found)
91 | BUILD_WITH_CUDA // Support CUDA (if found)
92 | BUILD_WITH_GLSL // Support GLSL (if found)
93 | BUILD_PYTHON_BINDINGS // Build Python bindings
94 | BUILD_TESTS // Build unit tests
95 | BUILD_DOCS // Generate Doxygen documenation
96 | DOWNLOAD_EXAMPLES_IMAGES // Download examples input images
97 | ```
98 |
99 | ### Third party libraries
100 | If the CMake option `BUILD_THIRD_PARTY_LIBS` is set to ON, the build will download the source code from the missing libraries and compile. This does not apply for the core libs OpenCL, CUDA and OpenGL since they are not open source. Although supported, it is not recommended to download and build boost from the git repo as it takes a long time to clone the submodules.
101 |
102 | Following CMake variables can be set to help CMake find the third party libraries:
103 |
104 | ```
105 | -DBOOST_ROOT=...
106 | -DZLIB_ROOT=...
107 | -DGLFW_ROOT=...
108 | ```
109 |
110 | ### Examples ###
111 | The following examples are included the `examples` directory (can be run with `bin/gpuip`):
112 |
113 | ```
114 | - linear interpolation
115 | - box blur
116 | - gaussian blur
117 | - separable gaussian blur
118 | ```
119 |
120 | ### Tests ###
121 |
122 | To run all tests, run `ctest` from the `build` directory.
123 |
124 | ```
125 | test_cpp // Test C++ api
126 | test_py // Test Python bindings
127 | test_performance // Tests the performance, compare against CPU
128 | ```
129 |
--------------------------------------------------------------------------------
/build.bat:
--------------------------------------------------------------------------------
1 | pushd %~dp0
2 | if not exist build\ (
3 | mkdir build
4 | )
5 | cd build
6 | cmake ..
7 | cmake --build . --config Release
8 | cd ..
9 | pause
10 | popd
--------------------------------------------------------------------------------
/cmake/FindBoostNumpy.cmake:
--------------------------------------------------------------------------------
1 | FIND_PACKAGE(PackageHandleStandardArgs)
2 |
3 | FIND_LIBRARY(
4 | Boost_NUMPY_LIBRARY
5 | NAMES boost_numpy
6 | PATHS
7 | /usr/local/lib/
8 | /usr/lib64/
9 | ${Boost_LIBRARY_DIRS})
10 |
11 | FIND_PATH(Boost_NUMPY_INCLUDE_DIRS
12 | NAMES
13 | boost/numpy.hpp
14 | PATHS
15 | /usr/local/include
16 | ${Boost_INCLUDE_DIRS})
17 |
18 | FIND_PACKAGE_HANDLE_STANDARD_ARGS(BoostNumpy DEFAULT_MSG Boost_NUMPY_LIBRARY Boost_NUMPY_INCLUDE_DIRS)
19 |
20 | SET(Boost_NUMPY_FOUND 0)
21 | IF(Boost_NUMPY_LIBRARY AND Boost_NUMPY_INCLUDE_DIRS)
22 | SET(Boost_NUMPY_FOUND 1)
23 | message(STATUS "Boost numpy found!")
24 | ENDIF(Boost_NUMPY_LIBRARY AND Boost_NUMPY_INCLUDE_DIRS)
--------------------------------------------------------------------------------
/cmake/FindCUDADriver.cmake:
--------------------------------------------------------------------------------
1 | FIND_PACKAGE(PackageHandleStandardArgs)
2 |
3 | FIND_LIBRARY(
4 | CUDA_DRIVER_LIBRARY
5 | NAMES cuda
6 | PATHS
7 | /usr/local/lib/
8 | /usr/lib64/
9 | $ENV{CUDA_PATH}/lib/Win32)
10 | #$ENV{CUDA_LIB_PATH})
11 | #${CUDA_TOOLKIT_ROOT_DIR}/lib64)
12 |
13 | FIND_PACKAGE_HANDLE_STANDARD_ARGS(CUDADriver DEFAULT_MSG CUDA_DRIVER_LIBRARY)
--------------------------------------------------------------------------------
/cmake/FindGLFW.cmake:
--------------------------------------------------------------------------------
1 | # Locate the glfw library
2 | # This module defines the following variables:
3 | # GLFW_LIBRARY, the name of the library;
4 | # GLFW_INCLUDE_DIR, where to find glfw include files.
5 | # GLFW_FOUND, true if both the GLFW_LIBRARY and GLFW_INCLUDE_DIR have been found.
6 | #
7 | # To help locate the library and include file, you could define an environment variable called
8 | # GLFW_ROOT which points to the root of the glfw library installation. This is pretty useful
9 | # on a Windows platform.
10 | #
11 | #
12 | # Usage example to compile an "executable" target to the glfw library:
13 | #
14 | # FIND_PACKAGE (glfw REQUIRED)
15 | # INCLUDE_DIRECTORIES (${GLFW_INCLUDE_DIR})
16 | # ADD_EXECUTABLE (executable ${EXECUTABLE_SRCS})
17 | # TARGET_LINK_LIBRARIES (executable ${GLFW_LIBRARY})
18 | #
19 | # TODO:
20 | # Allow the user to select to link to a shared library or to a static library.
21 |
22 | #Search for the include file...
23 | FIND_PATH(GLFW_INCLUDE_DIRS GLFW/glfw3.h DOC "Path to GLFW include directory."
24 | HINTS
25 | $ENV{GLFW_ROOT}
26 | PATH_SUFFIX include #For finding the include file under the root of the glfw expanded archive, typically on Windows.
27 | PATHS
28 | /usr/include/
29 | /usr/local/include/
30 | # By default headers are under GL subfolder
31 | /usr/include/GL
32 | /usr/local/include/GL
33 | "C:/Program Files (x86)/GLFW/include"
34 | ${GLFW_ROOT_DIR}/include/ # added by ptr
35 |
36 | )
37 |
38 | FIND_LIBRARY(GLFW_LIBRARIES DOC "Absolute path to GLFW library."
39 | NAMES glfw glfw3
40 | HINTS
41 | $ENV{GLFW_ROOT}
42 | PATH_SUFFIXES lib/win32 #For finding the library file under the root of the glfw expanded archive, typically on Windows.
43 | PATHS
44 | "C:/Program Files (x86)/GLFW/lib"
45 | /usr/local/lib
46 | /usr/lib
47 | ${GLFW_ROOT_DIR}/lib-msvc100/release # added by ptr
48 | )
49 |
50 | SET(GLFW_FOUND 0)
51 | IF(GLFW_LIBRARY AND GLFW_INCLUDE_DIR)
52 | SET(GLFW_FOUND 1)
53 | message(STATUS "GLFW found!")
54 | ENDIF(GLFW_LIBRARY AND GLFW_INCLUDE_DIR)
55 |
--------------------------------------------------------------------------------
/cmake/FindOpenCL.cmake:
--------------------------------------------------------------------------------
1 | #.rst:
2 | # FindOpenCL
3 | # ----------
4 | #
5 | # Try to find OpenCL
6 | #
7 | # Once done this will define::
8 | #
9 | # OpenCL_FOUND - True if OpenCL was found
10 | # OpenCL_INCLUDE_DIRS - include directories for OpenCL
11 | # OpenCL_LIBRARIES - link against this library to use OpenCL
12 | # OpenCL_VERSION_STRING - Highest supported OpenCL version (eg. 1.2)
13 | # OpenCL_VERSION_MAJOR - The major version of the OpenCL implementation
14 | # OpenCL_VERSION_MINOR - The minor version of the OpenCL implementation
15 | #
16 | # The module will also define two cache variables::
17 | #
18 | # OpenCL_INCLUDE_DIR - the OpenCL include directory
19 | # OpenCL_LIBRARY - the path to the OpenCL library
20 | #
21 |
22 | #=============================================================================
23 | # Copyright 2014 Matthaeus G. Chajdas
24 | #
25 | # Distributed under the OSI-approved BSD License (the "License");
26 | # see accompanying file Copyright.txt for details.
27 | #
28 | # This software is distributed WITHOUT ANY WARRANTY; without even the
29 | # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
30 | # See the License for more information.
31 | #=============================================================================
32 | # (To distribute this file outside of CMake, substitute the full
33 | # License text for the above reference.)
34 |
35 | function(_FIND_OPENCL_VERSION)
36 | include(CheckSymbolExists)
37 | include(CMakePushCheckState)
38 | set(CMAKE_REQUIRED_QUIET ${OpenCL_FIND_QUIETLY})
39 |
40 | CMAKE_PUSH_CHECK_STATE()
41 | foreach(VERSION "2_0" "1_2" "1_1" "1_0")
42 | set(CMAKE_REQUIRED_INCLUDES "${OpenCL_INCLUDE_DIR}")
43 |
44 | if(APPLE)
45 | CHECK_SYMBOL_EXISTS(
46 | CL_VERSION_${VERSION}
47 | "${OpenCL_INCLUDE_DIR}/OpenCL/cl.h"
48 | OPENCL_VERSION_${VERSION})
49 | else()
50 | CHECK_SYMBOL_EXISTS(
51 | CL_VERSION_${VERSION}
52 | "${OpenCL_INCLUDE_DIR}/CL/cl.h"
53 | OPENCL_VERSION_${VERSION})
54 | endif()
55 |
56 | if(OPENCL_VERSION_${VERSION})
57 | string(REPLACE "_" "." VERSION "${VERSION}")
58 | set(OpenCL_VERSION_STRING ${VERSION} PARENT_SCOPE)
59 | string(REGEX MATCHALL "[0-9]+" version_components "${VERSION}")
60 | list(GET version_components 0 major_version)
61 | list(GET version_components 1 minor_version)
62 | set(OpenCL_VERSION_MAJOR ${major_version} PARENT_SCOPE)
63 | set(OpenCL_VERSION_MINOR ${minor_version} PARENT_SCOPE)
64 | break()
65 | endif()
66 | endforeach()
67 | CMAKE_POP_CHECK_STATE()
68 | endfunction()
69 |
70 | find_path(OpenCL_INCLUDE_DIR
71 | NAMES
72 | CL/cl.h OpenCL/cl.h
73 | PATHS
74 | ENV "PROGRAMFILES(X86)"
75 | ENV AMDAPPSDKROOT
76 | ENV INTELOCLSDKROOT
77 | ENV NVSDKCOMPUTE_ROOT
78 | ENV CUDA_PATH
79 | ENV ATISTREAMSDKROOT
80 | PATH_SUFFIXES
81 | include
82 | OpenCL/common/inc
83 | "AMD APP/include")
84 |
85 | _FIND_OPENCL_VERSION()
86 |
87 | if(WIN32)
88 | if(CMAKE_SIZEOF_VOID_P EQUAL 4)
89 | find_library(OpenCL_LIBRARY
90 | NAMES OpenCL
91 | PATHS
92 | ENV "PROGRAMFILES(X86)"
93 | ENV AMDAPPSDKROOT
94 | ENV INTELOCLSDKROOT
95 | ENV CUDA_PATH
96 | ENV NVSDKCOMPUTE_ROOT
97 | ENV ATISTREAMSDKROOT
98 | PATH_SUFFIXES
99 | "AMD APP/lib/x86"
100 | lib/x86
101 | lib/Win32
102 | OpenCL/common/lib/Win32)
103 | elseif(CMAKE_SIZEOF_VOID_P EQUAL 8)
104 | find_library(OpenCL_LIBRARY
105 | NAMES OpenCL
106 | PATHS
107 | ENV "PROGRAMFILES(X86)"
108 | ENV AMDAPPSDKROOT
109 | ENV INTELOCLSDKROOT
110 | ENV CUDA_PATH
111 | ENV NVSDKCOMPUTE_ROOT
112 | ENV ATISTREAMSDKROOT
113 | PATH_SUFFIXES
114 | "AMD APP/lib/x86_64"
115 | lib/x86_64
116 | lib/x64
117 | OpenCL/common/lib/x64)
118 | endif()
119 | else()
120 | find_library(OpenCL_LIBRARY
121 | NAMES OpenCL)
122 | endif()
123 |
124 | set(OpenCL_LIBRARIES ${OpenCL_LIBRARY})
125 | set(OpenCL_INCLUDE_DIRS ${OpenCL_INCLUDE_DIR})
126 | FIND_PACKAGE(PackageHandleStandardArgs)
127 | find_package_handle_standard_args(
128 | OpenCL
129 | FOUND_VAR OpenCL_FOUND
130 | REQUIRED_VARS OpenCL_LIBRARY OpenCL_INCLUDE_DIR
131 | VERSION_VAR OpenCL_VERSION_STRING)
132 |
133 | mark_as_advanced(
134 | OpenCL_INCLUDE_DIR
135 | OpenCL_LIBRARY)
136 |
--------------------------------------------------------------------------------
/cmake/FindOpenEXR.cmake:
--------------------------------------------------------------------------------
1 | #
2 | # Try to find OpenEXR's libraries, and include path.
3 | # Once done this will define:
4 | #
5 | # OPENEXR_FOUND = OpenEXR found.
6 | # OPENEXR_INCLUDE_PATHS = OpenEXR include directories.
7 | # OPENEXR_LIBRARIES = libraries that are needed to use OpenEXR.
8 | #
9 |
10 | INCLUDE(FindZLIB)
11 |
12 |
13 | IF(ZLIB_FOUND)
14 |
15 | SET(LIBRARY_PATHS
16 | /usr/lib
17 | /usr/local/lib
18 | /sw/lib
19 | /opt/local/lib
20 | $ENV{PROGRAM_FILES}/OpenEXR/lib/static)
21 |
22 | FIND_PATH(OPENEXR_INCLUDE_PATH OpenEXR/ImfRgbaFile.h
23 | /usr/include
24 | /usr/local/include
25 | /sw/include
26 | /opt/local/include)
27 |
28 | FIND_LIBRARY(OPENEXR_HALF_LIBRARY
29 | NAMES Half
30 | PATHS ${LIBRARY_PATHS})
31 |
32 | FIND_LIBRARY(OPENEXR_IEX_LIBRARY
33 | NAMES Iex
34 | PATHS ${LIBRARY_PATHS})
35 |
36 | FIND_LIBRARY(OPENEXR_IMATH_LIBRARY
37 | NAMES Imath
38 | PATHS ${LIBRARY_PATHS})
39 |
40 | FIND_LIBRARY(OPENEXR_ILMIMF_LIBRARY
41 | NAMES IlmImf
42 | PATHS ${LIBRARY_PATHS})
43 |
44 | FIND_LIBRARY(OPENEXR_ILMTHREAD_LIBRARY
45 | NAMES IlmThread
46 | PATHS ${LIBRARY_PATHS})
47 |
48 | ENDIF(ZLIB_FOUND)
49 |
50 | #MESSAGE(STATUS ${OPENEXR_IMATH_LIBRARY} ${OPENEXR_ILMIMF_LIBRARY} ${OPENEXR_IEX_LIBRARY} ${OPENEXR_HALF_LIBRARY} ${OPENEXR_ILMTHREAD_LIBRARY} ${ZLIB_LIBRARY})
51 |
52 | IF (OPENEXR_INCLUDE_PATH AND OPENEXR_IMATH_LIBRARY AND OPENEXR_ILMIMF_LIBRARY AND OPENEXR_IEX_LIBRARY AND OPENEXR_HALF_LIBRARY)
53 | SET(OPENEXR_FOUND TRUE)
54 | SET(OPENEXR_INCLUDE_PATHS ${OPENEXR_INCLUDE_PATH} CACHE STRING "The include paths needed to use OpenEXR")
55 | SET(OPENEXR_LIBRARIES ${OPENEXR_IMATH_LIBRARY} ${OPENEXR_ILMIMF_LIBRARY} ${OPENEXR_IEX_LIBRARY} ${OPENEXR_HALF_LIBRARY} ${OPENEXR_ILMTHREAD_LIBRARY} ${ZLIB_LIBRARY} CACHE STRING "The libraries needed to use OpenEXR")
56 | ENDIF (OPENEXR_INCLUDE_PATH AND OPENEXR_IMATH_LIBRARY AND OPENEXR_ILMIMF_LIBRARY AND OPENEXR_IEX_LIBRARY AND OPENEXR_HALF_LIBRARY)
57 |
58 | IF(OPENEXR_FOUND)
59 | IF(NOT OPENEXR_FIND_QUIETLY)
60 | MESSAGE(STATUS "Found OpenEXR: ${OPENEXR_ILMIMF_LIBRARY}")
61 | ENDIF(NOT OPENEXR_FIND_QUIETLY)
62 | ELSE(OPENEXR_FOUND)
63 | IF(OPENEXR_FIND_REQUIRED)
64 | MESSAGE(FATAL_ERROR "Could not find OpenEXR library")
65 | ENDIF(OPENEXR_FIND_REQUIRED)
66 | ENDIF(OPENEXR_FOUND)
67 |
68 | MARK_AS_ADVANCED(
69 | OPENEXR_INCLUDE_PATHS
70 | OPENEXR_LIBRARIES
71 | OPENEXR_ILMIMF_LIBRARY
72 | OPENEXR_IMATH_LIBRARY
73 | OPENEXR_IEX_LIBRARY
74 | OPENEXR_HALF_LIBRARY)
75 |
--------------------------------------------------------------------------------
/cmake/cmake_uninstall.cmake.in:
--------------------------------------------------------------------------------
1 | if(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
2 | message(FATAL_ERROR "Cannot find install manifest: @CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
3 | endif(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
4 |
5 | file(READ "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt" files)
6 | string(REGEX REPLACE "\n" ";" files "${files}")
7 | foreach(file ${files})
8 | message(STATUS "Uninstalling $ENV{DESTDIR}${file}")
9 | if(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}")
10 | exec_program(
11 | "@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\""
12 | OUTPUT_VARIABLE rm_out
13 | RETURN_VALUE rm_retval
14 | )
15 | if(NOT "${rm_retval}" STREQUAL 0)
16 | message(FATAL_ERROR "Problem when removing $ENV{DESTDIR}${file}")
17 | endif(NOT "${rm_retval}" STREQUAL 0)
18 | else(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}")
19 | message(STATUS "File $ENV{DESTDIR}${file} does not exist.")
20 | endif(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}")
21 | endforeach(file)
--------------------------------------------------------------------------------
/cpack/CMakeCPackOptions.cmake.in:
--------------------------------------------------------------------------------
1 | #CPack
2 | set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Framework for Image Processing on the GPU")
3 | set(CPACK_PACKAGE_VERSION ${VERSION})
4 | set(CPACK_COMPONENTS_ALL devel python bin)
5 | set(CPACK_PACKAGE_FILE_NAME ${CPACK_PACKAGE_NAME}-${GPUIP_VERSION})
6 | set(CPACK_COMPONENTS_GROUPING ALL_COMPONENTS_IN_ONE)
7 |
8 |
9 | if(${CPACK_GENERATOR} MATCHES "RPM")
10 | set(CPACK_RPM_COMPONENT_INSTALL ON)
11 | set(CPACK_RPM_PACKAGE_GROUP "Applications/Engineering")
12 | endif()
--------------------------------------------------------------------------------
/doc/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | find_package(Doxygen REQUIRED)
2 | configure_file(
3 | ${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in
4 | ${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile)
5 | add_custom_target(doc ALL ${DOXYGEN_EXECUTABLE}
6 | WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
7 | COMMENT "Generating documentation" VERBATIM)
--------------------------------------------------------------------------------
/doc/mainpage.h:
--------------------------------------------------------------------------------
1 | /*!
2 | \example box_blur.cl
3 | \example lerp_ubyte.cu
4 | \example gaussian_blur_hor.cl
5 | \example box_blur.glsl
6 | \example sobel.glsl
7 | \example lerp_float.cu
8 | \example lerp.cu
9 | \example gaussian_blur_vert.cu
10 | \example box_blur.cl
11 | \example gaussian_blur_vert.glsl
12 | \example box_blur.cu
13 | \example lerp.glsl
14 | \example gaussian_blur.cu
15 | \example sobel.cu
16 | \example gaussian_blur_vert.cl
17 | \example lerp_float.cl
18 | \example lerp.cl
19 | \example gaussian_blur_hor.cu
20 | \example gaussian_blur_hor.glsl
21 | \example gaussian_blur.cl
22 | \example sobel.cl
23 | \example lerp_ubyte.cl
24 | \example gaussian_blur.glsl
25 | */
26 |
27 | /*!
28 | \mainpage
29 | gpuip is a C++ cross-platform framework for Image Processing on the GPU architechure. It tries to simplify the image processing pipeline on the GPU and make it more generic across the thre most common environments: OpenCL, CUDA and OpenGL GLSL. It provides a simple interface to copy data from and to the GPU and makes it easy to compile and run GPU kernel code.
30 |
31 | Example:
32 | \include ../examples/example.cpp
33 | */
34 | //----------------------------------------------------------------------------//
35 |
--------------------------------------------------------------------------------
/doc/update-web-api.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | mkdir -p ~/tmp/
3 | git clone git@github.com:karlssonper/gpuip -b gh-pages ~/tmp/gpuip-web
4 | cur=$(pwd)
5 | echo $cur
6 | cd ~/tmp/gpuip-web
7 | git pull origin
8 | git rm -r api/*
9 | mkdir api
10 | cp -r $cur/html/* api/
11 | git add api/*
12 | git commit -m "api update"
13 | git push
14 | cd $cur
15 | rm -rf ~/tmp/gpuip-web
--------------------------------------------------------------------------------
/examples/boxblur_cuda.ip:
--------------------------------------------------------------------------------
1 |
2 | CUDA
3 |
4 | buffer1
5 | half
6 | 4
7 | images/bridge.exr
8 |
9 |
10 | buffer2
11 | half
12 | 4
13 |
14 |
15 |
16 | box_blur
17 | kernels/box_blur.cu
18 |
19 | in
20 | buffer1
21 |
22 |
23 | out
24 | buffer2
25 |
26 |
27 | n
28 | int
29 | 1
30 | 1
31 | 1
32 | 15
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/examples/boxblur_glsl.ip:
--------------------------------------------------------------------------------
1 |
2 | GLSL
3 |
4 | buffer1
5 | half
6 | 4
7 | images/bridge.exr
8 |
9 |
10 | buffer2
11 | half
12 | 4
13 |
14 |
15 |
16 | box_blur
17 | kernels/box_blur.glsl
18 |
19 | input
20 | buffer1
21 |
22 |
23 | output
24 | buffer2
25 |
26 |
27 | n
28 | int
29 | 9
30 | 1
31 | 1
32 | 15
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/examples/boxblur_opencl.ip:
--------------------------------------------------------------------------------
1 |
2 | OpenCL
3 |
4 | buffer1
5 | half
6 | 4
7 | images/bridge.exr
8 |
9 |
10 | buffer2
11 | half
12 | 4
13 |
14 |
15 |
16 | box_blur
17 | kernels/box_blur.cl
18 |
19 | in
20 | buffer1
21 |
22 |
23 | out
24 | buffer2
25 |
26 |
27 | n
28 | int
29 | 1
30 | 1
31 | 1
32 | 15
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/examples/example.cpp:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | void print_timings(const char * func_name, double ms, std::string * err)
4 | {
5 | if (ms != GPUIP_ERROR) {
6 | printf("%s took %.2lf ms.\n", func_name, ms);
7 | } else {
8 | printf("Error in %s: %s\n", func_name, err->c_str());
9 | }
10 | }
11 |
12 | void use_gpuip()
13 | {
14 | std::string err;
15 | float * data;
16 | unsigned int width, height;
17 | ReadImage(&data, &width, &height); // definied somewhere else
18 |
19 | if (!gpuip::ImageProcessor::CanCreateGpuEnvironment(gpuip::GLSL)) {
20 | // ... deal with error - throw exception, return function etc
21 | }
22 | gpuip::ImageProcessor::Ptr ip = gpuip::ImageProcessor::Create(gpuip::GLSL);
23 | ip->SetDimensions(width, height);
24 | gpuip::Buffer::Ptr b0 = ip->CreateBuffer("b0", gpuip::FLOAT, 4);
25 | gpuip::Buffer::Ptr b1 = ip->CreateBuffer("b1", gpuip::FLOAT, 4);
26 | gpuip::Kernel::Ptr kernel = gpuipip->CreateKernel("modify_red");
27 | kernel->code = GetKernelCode(); // definied somewhere else
28 | kernel->inBuffers.push_back(gpuip::Kernel::BufferLink(b0, "img"));
29 | kernel->outBuffers.push_back(gpuip::Kernel::BufferLink(b1, "out_img"));
30 | kernel->paramsFloat.push_back(gpuip::Parameter("alpha", 0.4));
31 | print_timings("Build", ip->Build(&err), &err);
32 | print_timings("Allocate", ip->Allocate(&err), &err);
33 | print_timings("Copy", ip->Copy(b0, gpuip::Buffer::COPY_TO_GPU, data, &err), &err);
34 | print_timings("Run", ip->Run(&err), &err);
35 | print_timings("Copy", ip->Copy(b1, gpuip::Buffer::COPY_FROM_GPU, data, &err), &err);
36 | }
37 |
--------------------------------------------------------------------------------
/examples/gaussblur_cuda.ip:
--------------------------------------------------------------------------------
1 |
2 | CUDA
3 |
4 | buffer1
5 | half
6 | 4
7 | images/bridge.exr
8 |
9 |
10 | buffer2
11 | half
12 | 4
13 |
14 |
15 |
16 | gaussian_blur
17 | kernels/gaussian_blur.cu
18 |
19 | in
20 | buffer1
21 |
22 |
23 | out
24 | buffer2
25 |
26 |
27 | n
28 | int
29 | 1
30 | 1
31 | 1
32 | 16
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/examples/gaussblur_glsl.ip:
--------------------------------------------------------------------------------
1 |
2 | GLSL
3 |
4 | buffer1
5 | half
6 | 4
7 | images/bridge.exr
8 |
9 |
10 | buffer2
11 | half
12 | 4
13 |
14 |
15 |
16 | gaussian_blur
17 | kernels/gaussian_blur.glsl
18 |
19 | input
20 | buffer1
21 |
22 |
23 | output
24 | buffer2
25 |
26 |
27 | n
28 | int
29 | 1
30 | 1
31 | 1
32 | 16
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/examples/gaussblur_opencl.ip:
--------------------------------------------------------------------------------
1 |
2 | OpenCL
3 |
4 | buffer1
5 | half
6 | 4
7 | images/bridge.exr
8 |
9 |
10 | buffer2
11 | half
12 | 4
13 |
14 |
15 |
16 | gaussian_blur
17 | kernels/gaussian_blur.cl
18 |
19 | in
20 | buffer1
21 |
22 |
23 | out
24 | buffer2
25 |
26 |
27 | n
28 | int
29 | 1
30 | 1
31 | 1
32 | 16
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/examples/gaussblur_separable_cuda.ip:
--------------------------------------------------------------------------------
1 |
2 | CUDA
3 |
4 | buffer1
5 | half
6 | 4
7 | images/bridge.exr
8 |
9 |
10 | buffer2
11 | half
12 | 4
13 |
14 |
15 | buffer3
16 | half
17 | 4
18 |
19 |
20 |
21 | gaussian_blur_hor
22 | kernels/gaussian_blur_hor.cu
23 |
24 | in
25 | buffer1
26 |
27 |
28 | out
29 | buffer2
30 |
31 |
32 | n
33 | int
34 | 4
35 | 1
36 | 1
37 | 16
38 |
39 |
40 |
41 | gaussian_blur_vert
42 | kernels/gaussian_blur_vert.cu
43 |
44 | in
45 | buffer2
46 |
47 |
48 | out
49 | buffer3
50 |
51 |
52 | n
53 | int
54 | 4
55 | 1
56 | 1
57 | 16
58 |
59 |
60 |
61 |
--------------------------------------------------------------------------------
/examples/gaussblur_separable_glsl.ip:
--------------------------------------------------------------------------------
1 |
2 | GLSL
3 |
4 | buffer1
5 | half
6 | 4
7 | images/bridge.exr
8 |
9 |
10 | buffer2
11 | half
12 | 4
13 |
14 |
15 | buffer3
16 | half
17 | 4
18 |
19 |
20 |
21 | gaussian_blur_hor
22 | kernels/gaussian_blur_hor.glsl
23 |
24 | input
25 | buffer1
26 |
27 |
28 | out
29 | buffer2
30 |
31 |
32 | n
33 | int
34 | 4
35 | 1
36 | 1
37 | 16
38 |
39 |
40 |
41 | gaussian_blur_vert
42 | kernels/gaussian_blur_vert.glsl
43 |
44 | input
45 | buffer2
46 |
47 |
48 | out
49 | buffer3
50 |
51 |
52 | n
53 | int
54 | 4
55 | 1
56 | 1
57 | 16
58 |
59 |
60 |
61 |
--------------------------------------------------------------------------------
/examples/gaussblur_separable_opencl.ip:
--------------------------------------------------------------------------------
1 |
2 | OpenCL
3 |
4 | buffer1
5 | half
6 | 4
7 | images/bridge.exr
8 |
9 |
10 | buffer2
11 | half
12 | 4
13 |
14 |
15 | buffer3
16 | half
17 | 4
18 |
19 |
20 |
21 | gaussian_blur_hor
22 | kernels/gaussian_blur_hor.cl
23 |
24 | in
25 | buffer1
26 |
27 |
28 | out
29 | buffer2
30 |
31 |
32 | n
33 | int
34 | 4
35 | 1
36 | 1
37 | 16
38 |
39 |
40 |
41 | gaussian_blur_vert
42 | kernels/gaussian_blur_vert.cl
43 |
44 | in
45 | buffer2
46 |
47 |
48 | out
49 | buffer3
50 |
51 |
52 | n
53 | int
54 | 4
55 | 1
56 | 1
57 | 16
58 |
59 |
60 |
61 |
--------------------------------------------------------------------------------
/examples/images/README:
--------------------------------------------------------------------------------
1 | This directory contains the input images used in the examples.
2 |
3 | If this directory is empty, make sure the CMake option DOWNLOAD_EXAMPLES_IMAGEs
4 | is set to ON.
5 |
6 | You can also download the images yourself at:
7 | https://github.com/karlssonper/gpuip-examples-images
--------------------------------------------------------------------------------
/examples/kernels/box_blur.cl:
--------------------------------------------------------------------------------
1 | float4 read(__global const half * in_half, int x, int y, int w)
2 | {
3 | const int idx = x + w * y;
4 | return (float4)(vload_half(4 * idx + 0, in_half),
5 | vload_half(4 * idx + 1, in_half),
6 | vload_half(4 * idx + 2, in_half),
7 | vload_half(4 * idx + 3, in_half));
8 | }
9 |
10 | __kernel void
11 | box_blur(__global const half * in_half,
12 | __global half * out_half,
13 | const int n,
14 | const int width,
15 | const int height)
16 | {
17 | const int x = get_global_id(0);
18 | const int y = get_global_id(1);
19 |
20 | // array index
21 | const int idx = x + width * y;
22 |
23 | // inside image bounds check
24 | if (x >= width || y >= height) {
25 | return;
26 | }
27 |
28 | // kernel code
29 | float4 out = (float4)(0, 0, 0, 0);
30 | int count = 0;
31 | for(int j = y - n; j <= y + n; ++j) {
32 | for(int i = x - n; i <= x+n; ++i) {
33 | if (i>=0 && j>= 0 && i < width && j < height) {
34 | out += read(in_half, i, j, width);
35 | count += 1;
36 | }
37 | }
38 | }
39 | out /= count;
40 |
41 | // float to half conversion
42 | vstore_half(out.x, 4 * idx + 0, out_half);
43 | vstore_half(out.y, 4 * idx + 1, out_half);
44 | vstore_half(out.z, 4 * idx + 2, out_half);
45 | vstore_half(out.w, 4 * idx + 3, out_half);
46 | }
--------------------------------------------------------------------------------
/examples/kernels/box_blur.cu:
--------------------------------------------------------------------------------
1 | __device__ float4 read(const unsigned short * in_half, int x, int y, int w)
2 | {
3 | return make_float4(__half2float(in_half[4 * (x + y * w) + 0]),
4 | __half2float(in_half[4 * (x + y * w) + 1]),
5 | __half2float(in_half[4 * (x + y * w) + 2]),
6 | __half2float(in_half[4 * (x + y * w) + 3]));
7 | }
8 |
9 | __global__ void
10 | box_blur(const unsigned short * in_half,
11 | unsigned short * out_half,
12 | const int n,
13 | const int width,
14 | const int height)
15 | {
16 | const int x = blockIdx.x * blockDim.x + threadIdx.x;
17 | const int y = blockIdx.y * blockDim.y + threadIdx.y;
18 |
19 | // array index
20 | const int idx = x + width * y;
21 |
22 | // inside image bounds check
23 | if (x >= width || y >= height) {
24 | return;
25 | }
26 |
27 | // kernel code
28 | float4 out = make_float4(0, 0, 0, 0);
29 | int count = 0;
30 | for(int j = y - n; j <= y + n; ++j) {
31 | for(int i = x - n; i <= x + n; ++i) {
32 | if (i>=0 && j>= 0 && i < width && j < height) {
33 | out += read(in_half, i, j, width);
34 | count += 1;
35 | }
36 | }
37 | }
38 | out /= count;
39 |
40 | // float to half conversion
41 | out_half[4 * idx + 0] = __float2half_rn(out.x);
42 | out_half[4 * idx + 1] = __float2half_rn(out.y);
43 | out_half[4 * idx + 2] = __float2half_rn(out.z);
44 | out_half[4 * idx + 3] = __float2half_rn(out.w);
45 | }
46 |
--------------------------------------------------------------------------------
/examples/kernels/box_blur.glsl:
--------------------------------------------------------------------------------
1 | #version 120
2 | uniform sampler2D input;
3 | uniform int n;
4 | varying vec2 x; // texture coordinates
5 | uniform float dx; // delta
6 |
7 | void main()
8 | {
9 | vec3 v = vec3(0,0,0);
10 | float count;
11 | for(int j = -n; j<=n; ++j) {
12 | for(int i = -n; i<=n; ++i) {
13 | vec2 tx = x + vec2(i*dx,j*dx);
14 | v+= texture2D(input, tx).xyz;
15 | count += 1;
16 | }
17 | }
18 |
19 | // gl_FragData[0] is buffer output
20 | gl_FragData[0] = vec4(v/count,1);
21 | }
22 |
--------------------------------------------------------------------------------
/examples/kernels/gaussian_blur.cl:
--------------------------------------------------------------------------------
1 | float4 read(__global const half * in_half, int x, int y, int w)
2 | {
3 | const int idx = x + w * y;
4 | return (float4)(vload_half(4 * idx + 0, in_half),
5 | vload_half(4 * idx + 1, in_half),
6 | vload_half(4 * idx + 2, in_half),
7 | vload_half(4 * idx + 3, in_half));
8 | }
9 |
10 | float weight(int i, int j, int x, int y, float invdx2)
11 | {
12 | return exp(-invdx2*((i-x)*(i-x) + (j-y)*(j-y)));
13 | }
14 |
15 | __kernel void
16 | gaussian_blur(__global const half * in_half,
17 | __global half * out_half,
18 | const int n,
19 | const int width,
20 | const int height)
21 | {
22 | const int x = get_global_id(0);
23 | const int y = get_global_id(1);
24 |
25 | // array index
26 | const int idx = x + width * y;
27 |
28 | // inside image bounds check
29 | if (x >= width || y >= height) {
30 | return;
31 | }
32 |
33 | // kernel code
34 | float4 out = (float4)(0, 0, 0, 0);
35 | const float invdx2 = 1.0/(width*width);
36 | float totWeight = 0;
37 | float w;
38 | for(int j = y - n; j <= y + n; ++j) {
39 | for(int i = x - n; i <= x+n; ++i) {
40 | if (i>=0 && j>= 0 && i < width && j < height) {
41 | w = weight(i, j, x, y, invdx2);
42 | out += w * read(in_half, i, j, width);
43 | totWeight += w;
44 | }
45 | }
46 | }
47 | out /= totWeight;
48 |
49 | // float to half conversion
50 | vstore_half(out.x, 4 * idx + 0, out_half);
51 | vstore_half(out.y, 4 * idx + 1, out_half);
52 | vstore_half(out.z, 4 * idx + 2, out_half);
53 | vstore_half(out.w, 4 * idx + 3, out_half);
54 | }
55 |
--------------------------------------------------------------------------------
/examples/kernels/gaussian_blur.cu:
--------------------------------------------------------------------------------
1 | __device__ float4 read(const unsigned short * in_half, int x, int y, int w)
2 | {
3 | return make_float4(__half2float(in_half[4 * (x + y * w) + 0]),
4 | __half2float(in_half[4 * (x + y * w) + 1]),
5 | __half2float(in_half[4 * (x + y * w) + 2]),
6 | __half2float(in_half[4 * (x + y * w) + 3]));
7 | }
8 |
9 | __device__ float weight(int i, int j, int x, int y, float invdx2)
10 | {
11 | return exp(-invdx2*((i-x)*(i-x) + (j-y)*(j-y)));
12 | }
13 |
14 | __global__ void
15 | gaussian_blur(const unsigned short * in_half,
16 | unsigned short * out_half,
17 | const int n,
18 | const int width,
19 | const int height)
20 | {
21 | const int x = blockIdx.x * blockDim.x + threadIdx.x;
22 | const int y = blockIdx.y * blockDim.y + threadIdx.y;
23 |
24 | // array index
25 | const int idx = x + width * y;
26 |
27 | // inside image bounds check
28 | if (x >= width || y >= height) {
29 | return;
30 | }
31 |
32 | // kernel code
33 | float4 out = make_float4(0, 0, 0, 0);
34 | const float invdx2 = 1.0/(width*width);
35 | float totWeight = 0;
36 | float w;
37 | for(int j = y - n; j <= y + n; ++j) {
38 | for(int i = x - n; i <= x + n; ++i) {
39 | if (i>=0 && j>= 0 && i < width && j < height) {
40 | w = weight(i, j, x, y, invdx2);
41 | out += w * read(in_half, i, j, width);
42 | totWeight += w;
43 | }
44 | }
45 | }
46 | out /= totWeight;
47 |
48 | // float to half conversion
49 | out_half[4 * idx + 0] = __float2half_rn(out.x);
50 | out_half[4 * idx + 1] = __float2half_rn(out.y);
51 | out_half[4 * idx + 2] = __float2half_rn(out.z);
52 | out_half[4 * idx + 3] = __float2half_rn(out.w);
53 | }
54 |
--------------------------------------------------------------------------------
/examples/kernels/gaussian_blur.glsl:
--------------------------------------------------------------------------------
1 | #version 120
2 | uniform sampler2D input;
3 | uniform int n;
4 | varying vec2 x; // texture coordinates
5 | uniform float dx; // delta
6 |
7 | void main()
8 | {
9 | vec3 v = vec3(0,0,0);
10 | float totWeight = 0;
11 | for(int j = -n; j<=n; ++j) {
12 | for(int i = -n; i<=n; ++i) {
13 | vec2 tx = x + vec2(i*dx,j*dx);
14 | float weight = exp(-((tx.x-x.x)*(tx.x-x.x)+(tx.y-x.y)*(tx.y-x.y)));
15 | v+= weight * texture2D(input, tx).xyz;
16 | totWeight += weight;
17 | }
18 | }
19 |
20 | // gl_FragData[0] is buffer output
21 | gl_FragData[0] = vec4(v/totWeight,1);
22 | }
23 |
--------------------------------------------------------------------------------
/examples/kernels/gaussian_blur_hor.cl:
--------------------------------------------------------------------------------
1 | float4 read(__global const half * in_half, int x, int y, int w)
2 | {
3 | const int idx = x + w * y;
4 | return (float4)(vload_half(4 * idx + 0, in_half),
5 | vload_half(4 * idx + 1, in_half),
6 | vload_half(4 * idx + 2, in_half),
7 | vload_half(4 * idx + 3, in_half));
8 | }
9 |
10 | float weight(int i, int x,float invdx2)
11 | {
12 | return exp(-invdx2*((i-x)*(i-x)));
13 | }
14 |
15 | __kernel void
16 | gaussian_blur_hor(__global const half * in_half,
17 | __global half * out_half,
18 | const int n,
19 | const int width,
20 | const int height)
21 | {
22 | const int x = get_global_id(0);
23 | const int y = get_global_id(1);
24 |
25 | // array index
26 | const int idx = x + width * y;
27 |
28 | // inside image bounds check
29 | if (x >= width || y >= height) {
30 | return;
31 | }
32 |
33 | // kernel code
34 | float4 out = (float4)(0, 0, 0, 0);
35 | const float invdx2 = 1.0/(width*width);
36 | float totWeight = 0;
37 | float w;
38 | for(int i = x - n; i <= x+n; ++i) {
39 | if (i>=0 && i < width) {
40 | w = weight(i, x, invdx2);
41 | out += w * read(in_half, i, y, width);
42 | totWeight += w;
43 | }
44 | }
45 | out /= totWeight;
46 |
47 | // float to half conversion
48 | vstore_half(out.x, 4 * idx + 0, out_half);
49 | vstore_half(out.y, 4 * idx + 1, out_half);
50 | vstore_half(out.z, 4 * idx + 2, out_half);
51 | vstore_half(out.w, 4 * idx + 3, out_half);
52 | }
53 |
--------------------------------------------------------------------------------
/examples/kernels/gaussian_blur_hor.cu:
--------------------------------------------------------------------------------
1 | __device__ float4 readx(const unsigned short * in_half, int x, int y, int w)
2 | {
3 | return make_float4(__half2float(in_half[4 * (x + y * w) + 0]),
4 | __half2float(in_half[4 * (x + y * w) + 1]),
5 | __half2float(in_half[4 * (x + y * w) + 2]),
6 | __half2float(in_half[4 * (x + y * w) + 3]));
7 | }
8 |
9 | __device__ float weightx(int i, int x, float invdx2)
10 | {
11 | return exp(-invdx2*((i-x)*(i-x)));
12 | }
13 |
14 | __global__ void
15 | gaussian_blur_hor(const unsigned short * in_half,
16 | unsigned short * out_half,
17 | const int n,
18 | const int width,
19 | const int height)
20 | {
21 | const int x = blockIdx.x * blockDim.x + threadIdx.x;
22 | const int y = blockIdx.y * blockDim.y + threadIdx.y;
23 |
24 | // array index
25 | const int idx = x + width * y;
26 |
27 | // inside image bounds check
28 | if (x >= width || y >= height) {
29 | return;
30 | }
31 |
32 | // kernel code
33 | float4 out = make_float4(0, 0, 0, 0);
34 | const float invdx2 = 1.0/(width*width);
35 | float totWeight = 0;
36 | float w;
37 | for(int i = x - n; i <= x + n; ++i) {
38 | if (x>= 0 && x < width) {
39 | w = weightx(i, x, invdx2);
40 | out += w * readx(in_half, i, y, width);
41 | totWeight += w;
42 | }
43 | }
44 | out /= totWeight;
45 |
46 | // float to half conversion
47 | out_half[4 * idx + 0] = __float2half_rn(out.x);
48 | out_half[4 * idx + 1] = __float2half_rn(out.y);
49 | out_half[4 * idx + 2] = __float2half_rn(out.z);
50 | out_half[4 * idx + 3] = __float2half_rn(out.w);
51 | }
52 |
--------------------------------------------------------------------------------
/examples/kernels/gaussian_blur_hor.glsl:
--------------------------------------------------------------------------------
1 | #version 120
2 | uniform sampler2D input;
3 | uniform int n;
4 | varying vec2 x; // texture coordinates
5 | uniform float dx; // delta
6 |
7 | void main()
8 | {
9 | vec3 v = vec3(0,0,0);
10 | float totWeight = 0;
11 | for(int i = -n; i<=n; ++i) {
12 | vec2 tx = x + vec2(i*dx,0);
13 | float weight = exp(-((tx.x-x.x)*(tx.x-x.x)));
14 | v+= weight * texture2D(input, tx).xyz;
15 | totWeight += weight;
16 | }
17 |
18 | // gl_FragData[0] is buffer output
19 | gl_FragData[0] = vec4(v/totWeight,1);
20 | }
21 |
--------------------------------------------------------------------------------
/examples/kernels/gaussian_blur_vert.cl:
--------------------------------------------------------------------------------
1 | float4 read(__global const half * in_half, int x, int y, int w)
2 | {
3 | const int idx = x + w * y;
4 | return (float4)(vload_half(4 * idx + 0, in_half),
5 | vload_half(4 * idx + 1, in_half),
6 | vload_half(4 * idx + 2, in_half),
7 | vload_half(4 * idx + 3, in_half));
8 | }
9 |
10 | float weight(int j, int y,float invdx2)
11 | {
12 | return exp(-invdx2*((j-y)*(j-y)));
13 | }
14 |
15 | __kernel void
16 | gaussian_blur_vert(__global const half * in_half,
17 | __global half * out_half,
18 | const int n,
19 | const int width,
20 | const int height)
21 | {
22 | const int x = get_global_id(0);
23 | const int y = get_global_id(1);
24 |
25 | // array index
26 | const int idx = x + width * y;
27 |
28 | // inside image bounds check
29 | if (x >= width || y >= height) {
30 | return;
31 | }
32 |
33 | // kernel code
34 | float4 out = (float4)(0, 0, 0, 0);
35 | const float invdx2 = 1.0/(width*width);
36 | float totWeight = 0;
37 | float w;
38 | for(int j = y - n; j <= y+n; ++j) {
39 | if (j>=0 && j < height) {
40 | w = weight(j, y, invdx2);
41 | out += w * read(in_half, x, j, width);
42 | totWeight += w;
43 | }
44 | }
45 | out /= totWeight;
46 |
47 | // float to half conversion
48 | vstore_half(out.x, 4 * idx + 0, out_half);
49 | vstore_half(out.y, 4 * idx + 1, out_half);
50 | vstore_half(out.z, 4 * idx + 2, out_half);
51 | vstore_half(out.w, 4 * idx + 3, out_half);
52 | }
53 |
--------------------------------------------------------------------------------
/examples/kernels/gaussian_blur_vert.cu:
--------------------------------------------------------------------------------
1 | __device__ float4 ready(const unsigned short * in_half, int x, int y, int w)
2 | {
3 | return make_float4(__half2float(in_half[4 * (x + y * w) + 0]),
4 | __half2float(in_half[4 * (x + y * w) + 1]),
5 | __half2float(in_half[4 * (x + y * w) + 2]),
6 | __half2float(in_half[4 * (x + y * w) + 3]));
7 | }
8 |
9 | __device__ float weighty(int j, int y, float invdx2)
10 | {
11 | return exp(-invdx2*((j-y)*(j-y)));
12 | }
13 |
14 | __global__ void
15 | gaussian_blur_vert(const unsigned short * in_half,
16 | unsigned short * out_half,
17 | const int n,
18 | const int width,
19 | const int height)
20 | {
21 | const int x = blockIdx.x * blockDim.x + threadIdx.x;
22 | const int y = blockIdx.y * blockDim.y + threadIdx.y;
23 |
24 | // array index
25 | const int idx = x + width * y;
26 |
27 | // inside image bounds check
28 | if (x >= width || y >= height) {
29 | return;
30 | }
31 |
32 | // kernel code
33 | float4 out = make_float4(0, 0, 0, 0);
34 | const float invdx2 = 1.0/(width*width);
35 | float totWeight = 0;
36 | float w;
37 | for(int j = y - n; j <= y + n; ++j) {
38 | if (j>= 0 && j < height) {
39 | w = weighty(j, y, invdx2);
40 | out += w * ready(in_half, x, j, width);
41 | totWeight += w;
42 | }
43 | }
44 | out /= totWeight;
45 |
46 | // float to half conversion
47 | out_half[4 * idx + 0] = __float2half_rn(out.x);
48 | out_half[4 * idx + 1] = __float2half_rn(out.y);
49 | out_half[4 * idx + 2] = __float2half_rn(out.z);
50 | out_half[4 * idx + 3] = __float2half_rn(out.w);
51 | }
52 |
--------------------------------------------------------------------------------
/examples/kernels/gaussian_blur_vert.glsl:
--------------------------------------------------------------------------------
1 | #version 120
2 | uniform sampler2D input;
3 | uniform int n;
4 | varying vec2 x; // texture coordinates
5 | uniform float dx; // delta
6 |
7 | void main()
8 | {
9 | vec3 v = vec3(0,0,0);
10 | float totWeight = 0;
11 | for(int j = -n; j<=n; ++j) {
12 | vec2 tx = x + vec2(0,j*dx);
13 | float weight = exp(-((tx.y-x.y)*(tx.y-x.y)));
14 | v+= weight * texture2D(input, tx).xyz;
15 | totWeight += weight;
16 | }
17 |
18 | // gl_FragData[0] is buffer output
19 | gl_FragData[0] = vec4(v/totWeight,1);
20 | }
21 |
--------------------------------------------------------------------------------
/examples/kernels/lerp.cl:
--------------------------------------------------------------------------------
1 | __kernel void
2 | lerp(__global const half * a_half,
3 | __global const half * b_half,
4 | __global half * out_half,
5 | const float alpha,
6 | const int width,
7 | const int height)
8 | {
9 | const int x = get_global_id(0);
10 | const int y = get_global_id(1);
11 |
12 | // array index
13 | const int idx = x + width * y;
14 |
15 | // inside image bounds check
16 | if (x >= width || y >= height) {
17 | return;
18 | }
19 |
20 | // half to float conversion
21 | const float4 a = (float4)(vload_half(4 * idx + 0, a_half),
22 | vload_half(4 * idx + 1, a_half),
23 | vload_half(4 * idx + 2, a_half),
24 | vload_half(4 * idx + 3, a_half));
25 | const float4 b = (float4)(vload_half(4 * idx + 0, b_half),
26 | vload_half(4 * idx + 1, b_half),
27 | vload_half(4 * idx + 2, b_half),
28 | vload_half(4 * idx + 3, b_half));
29 |
30 | // kernel code
31 | float4 out = (1-alpha) * a + alpha * b;
32 |
33 | // float to half conversion
34 | vstore_half(out.x, 4 * idx + 0, out_half);
35 | vstore_half(out.y, 4 * idx + 1, out_half);
36 | vstore_half(out.z, 4 * idx + 2, out_half);
37 | vstore_half(out.w, 4 * idx + 3, out_half);
38 | }
--------------------------------------------------------------------------------
/examples/kernels/lerp.cu:
--------------------------------------------------------------------------------
1 | __global__ void
2 | lerp(const unsigned short * a_half,
3 | const unsigned short * b_half,
4 | unsigned short * out_half,
5 | const float alpha,
6 | const int width,
7 | const int height)
8 | {
9 | const int x = blockIdx.x * blockDim.x + threadIdx.x;
10 | const int y = blockIdx.y * blockDim.y + threadIdx.y;
11 |
12 | // array index
13 | const int idx = x + width * y;
14 |
15 | // inside image bounds check
16 | if (x >= width || y >= height) {
17 | return;
18 | }
19 |
20 | // half to float conversion
21 | const float4 a = make_float4(__half2float(a_half[4 * idx + 0]),
22 | __half2float(a_half[4 * idx + 1]),
23 | __half2float(a_half[4 * idx + 2]),
24 | __half2float(a_half[4 * idx + 3]));
25 | const float4 b = make_float4(__half2float(b_half[4 * idx + 0]),
26 | __half2float(b_half[4 * idx + 1]),
27 | __half2float(b_half[4 * idx + 2]),
28 | __half2float(b_half[4 * idx + 3]));
29 |
30 | // kernel code
31 | float4 out = (1-alpha) * a + alpha * b;
32 |
33 | // float to half conversion
34 | out_half[4 * idx + 0] = __float2half_rn(out.x);
35 | out_half[4 * idx + 1] = __float2half_rn(out.y);
36 | out_half[4 * idx + 2] = __float2half_rn(out.z);
37 | out_half[4 * idx + 3] = __float2half_rn(out.w);
38 | }
--------------------------------------------------------------------------------
/examples/kernels/lerp.glsl:
--------------------------------------------------------------------------------
1 | #version 120
2 | uniform sampler2D a;
3 | uniform sampler2D b;
4 | uniform float alpha;
5 | varying vec2 x; // texture coordinates
6 | uniform float dx; // delta
7 |
8 | void main()
9 | {
10 | // gl_FragData[0] is buffer out
11 | vec4 c = (1-alpha)*texture2D(a,x) + alpha*texture2D(b,x);
12 | c.w = 1;
13 | gl_FragData[0] = c;
14 | }
--------------------------------------------------------------------------------
/examples/kernels/lerp_float.cl:
--------------------------------------------------------------------------------
1 | __kernel void
2 | lerp(__global const float4 * a,
3 | __global const float4 * b,
4 | __global float4 * out,
5 | const float alpha,
6 | const int width,
7 | const int height)
8 | {
9 | const int x = get_global_id(0);
10 | const int y = get_global_id(1);
11 |
12 | // array index
13 | const int idx = x + width * y;
14 |
15 | // inside image bounds check
16 | if (x >= width || y >= height) {
17 | return;
18 | }
19 |
20 | // kernel code
21 | out[idx] = (1-alpha) * a[idx] + alpha * b[idx];
22 | }
--------------------------------------------------------------------------------
/examples/kernels/lerp_float.cu:
--------------------------------------------------------------------------------
1 | __kernel void
2 | lerp(__global const float4 * a,
3 | __global const float4 * b,
4 | __global float4 * out,
5 | const float alpha,
6 | const int width,
7 | const int height)
8 | {
9 | const int x = get_global_id(0);
10 | const int y = get_global_id(1);
11 |
12 | // array index
13 | const int idx = x + width * y;
14 |
15 | // inside image bounds check
16 | if (x >= width || y >= height) {
17 | return;
18 | }
19 |
20 | // kernel code
21 | out[idx] = (1-alpha) * a[idx] + alpha * b[idx];
22 | }
--------------------------------------------------------------------------------
/examples/kernels/lerp_ubyte.cl:
--------------------------------------------------------------------------------
1 | __kernel void
2 | lerp(__global const uchar4 * a,
3 | __global const uchar4 * b,
4 | __global uchar4 * out,
5 | const float alpha,
6 | const int width,
7 | const int height)
8 | {
9 | const int x = get_global_id(0);
10 | const int y = get_global_id(1);
11 |
12 | // array index
13 | const int idx = x + width * y;
14 |
15 | // inside image bounds check
16 | if (x >= width || y >= height) {
17 | return;
18 | }
19 |
20 | // kernel code
21 | const float4 af = convert_float4(a[idx]);
22 | const float4 bf = convert_float4(b[idx]);
23 | uchar4 tmp = convert_uchar4((1-alpha)*af+alpha*bf);
24 |
25 | // set alpha
26 | tmp.w = 255;
27 |
28 | out[idx] = tmp;
29 | }
--------------------------------------------------------------------------------
/examples/kernels/lerp_ubyte.cu:
--------------------------------------------------------------------------------
1 | __kernel void
2 | lerp(__global const uchar4 * a,
3 | __global const uchar4 * b,
4 | __global uchar4 * out,
5 | const float alpha,
6 | const int width,
7 | const int height)
8 | {
9 | const int x = get_global_id(0);
10 | const int y = get_global_id(1);
11 |
12 | // array index
13 | const int idx = x + width * y;
14 |
15 | // inside image bounds check
16 | if (x >= width || y >= height) {
17 | return;
18 | }
19 |
20 |
21 | // kernel code
22 | const uchar4 aa = a[idx];
23 | const uchar4 bb = b[idx];
24 |
25 | out[idx] = (uchar4)((1-alpha)*aa.x + alpha*bb.x,
26 | (1-alpha)*aa.y + alpha*bb.y,
27 | (1-alpha)*aa.z + alpha*bb.z,
28 | 255);
29 | }
--------------------------------------------------------------------------------
/examples/kernels/sobel.cl:
--------------------------------------------------------------------------------
1 | float4 read(__global const uchar4 * in, int x, int y, int width)
2 | {
3 | return convert_float4(in[x + width * y]);
4 | }
5 |
6 | float4 compute_sobelx(__global const uchar4 * in, int x, int y, int w)
7 | {
8 | return -2*read(in,x-1,y-1,w) - read(in,x-1,y,w) - read(in,x-1,y+1,w)
9 | +2*read(in,x+1,y-1,w) + read(in,x+1,y,w) + read(in,x+1,y+1,w);
10 | }
11 |
12 | float4 compute_sobely(__global const uchar4 * in, int x, int y, int w)
13 | {
14 | return -2*read(in,x-1,y-1,w) - read(in,x,y-1,w) - read(in,x+1,y-1,w)
15 | +2*read(in,x-1,y+1,w) + read(in,x,y+1,w) + read(in,x+1,y+1,w);
16 | }
17 |
18 | __kernel void
19 | sobel(__global const uchar4 * in,
20 | __global uchar4 * sobelx,
21 | __global uchar4 * sobely,
22 | __global uchar4 * gradient,
23 | __global uchar4 * edges,
24 | float primary_treshold,
25 | float secondary_treshold,
26 | const int width,
27 | const int height)
28 | {
29 | const int x = get_global_id(0);
30 | const int y = get_global_id(1);
31 |
32 | // array index
33 | const int idx = x + width * y;
34 |
35 | // inside image bounds check
36 | if (x >= width || y >= height) {
37 | return;
38 | }
39 |
40 | // kernel code
41 | if (x == 0 || y == 0 || x == width - 1 || y == height - 1) {
42 | sobelx[idx] = (uchar4)(0, 0, 0, 255);
43 | sobely[idx] = (uchar4)(0, 0, 0, 255);
44 | gradient[idx] = (uchar4)(0, 0, 0, 255);
45 | edges[idx] = (uchar4)(0, 0, 0, 255);
46 | return;
47 | }
48 |
49 | const float4 sx = compute_sobelx(in, x, y, width);
50 | const float4 sy = compute_sobely(in, x, y, width);
51 | const float grad = (fabs(sx.x)+fabs(sx.y)+fabs(sx.z)+
52 | fabs(sy.x)+fabs(sy.y)+fabs(sy.z))/3.0;
53 |
54 | sobelx[idx] = convert_uchar4(sx);
55 | sobely[idx] = convert_uchar4(sy);
56 |
57 | const unsigned char gradu = convert_uchar(grad);
58 | gradient[idx] = (uchar4)(gradu, gradu, gradu, 255);
59 |
60 | const bool prim_edge = grad > primary_treshold;
61 | const bool sec_edge = grad > secondary_treshold;
62 | const uchar edge = 255 * prim_edge | 125 * sec_edge;
63 |
64 | edges[idx] = (uchar4)(edge, edge, edge, 255);
65 | }
66 |
--------------------------------------------------------------------------------
/examples/kernels/sobel.cu:
--------------------------------------------------------------------------------
1 | __device__ float4 read(const uchar4 * in, int x, int y, int width)
2 | {
3 | const uchar4 v = in[x + y * width];
4 | return make_float4(v.x, v.y, v.z, v.w);
5 | }
6 |
7 | __device__ float4 compute_sobelx(const uchar4 * in, int x, int y, int w)
8 | {
9 | return -2*read(in,x-1,y-1,w) - read(in,x-1,y,w) - read(in,x-1,y+1,w)
10 | +2*read(in,x+1,y-1,w) + read(in,x+1,y,w) + read(in,x+1,y+1,w);
11 | }
12 |
13 | __device__ float4 compute_sobely(const uchar4 * in, int x, int y, int w)
14 | {
15 | return -2*read(in,x-1,y-1,w) - read(in,x,y-1,w) - read(in,x+1,y-1,w)
16 | +2*read(in,x-1,y+1,w) + read(in,x,y+1,w) + read(in,x+1,y+1,w);
17 | }
18 |
19 | __global__ void
20 | sobel(const uchar4 * in,
21 | uchar4 * sobelx,
22 | uchar4 * sobely,
23 | uchar4 * gradient,
24 | uchar4 * edges,
25 | const float primary_treshold,
26 | const float secondary_treshold,
27 | const int width,
28 | const int height)
29 | {
30 | const int x = blockIdx.x * blockDim.x + threadIdx.x;
31 | const int y = blockIdx.y * blockDim.y + threadIdx.y;
32 |
33 | // array index
34 | const int idx = x + width * y;
35 |
36 | // inside image bounds check
37 | if (x >= width || y >= height) {
38 | return;
39 | }
40 |
41 | // kernel code
42 | if (x == 0 || y == 0 || x == width - 1 || y == height - 1) {
43 | sobelx[idx] = make_uchar4(0,0,0,255);
44 | sobely[idx] = make_uchar4(0,0,0,255);
45 | gradient[idx] = make_uchar4(0,0,0,255);
46 | edges[idx] = make_uchar4(0,0,0,255);
47 | return;
48 | }
49 |
50 | float4 sx = compute_sobelx(in,x,y,width);
51 | float4 sy = compute_sobely(in,x,y,width);
52 |
53 | sobelx[idx] = make_uchar4(abs(sx.x), abs(sx.y), abs(sx.z), 255);
54 | sobely[idx] = make_uchar4(abs(sy.x), abs(sy.y), abs(sy.z), 255);
55 |
56 | float grad = (abs(sx.x)+abs(sx.y)+abs(sx.z)+
57 | abs(sy.x)+abs(sy.y)+abs(sy.z))/3.0;
58 | gradient[idx] = make_uchar4(grad, grad, grad, 255);
59 |
60 | const bool prim_edge = grad > primary_treshold;
61 | const bool sec_edge = grad > secondary_treshold;
62 | const unsigned char edge = prim_edge * 255 | sec_edge * 125;
63 | edges[idx] = make_uchar4(edge,edge,edge,255);
64 | }
65 |
--------------------------------------------------------------------------------
/examples/kernels/sobel.glsl:
--------------------------------------------------------------------------------
1 | #version 120
2 | uniform sampler2D input;
3 | uniform float primary_treshold;
4 | uniform float secondary_treshold;
5 | varying vec2 x; // texture coordinates
6 | uniform float dx; // delta
7 |
8 | vec4 compute_sobelx()
9 | {
10 | return -2*texture2D(input, x + vec2(-dx,0))
11 | - texture2D(input, x + vec2(-dx,dx))
12 | - texture2D(input, x + vec2(-dx,-dx))
13 | + 2*texture2D(input, x + vec2(dx,0))
14 | + texture2D(input, x + vec2(dx,dx))
15 | + texture2D(input, x + vec2(dx,-dx));
16 | }
17 |
18 | vec4 compute_sobely()
19 | {
20 | return -2*texture2D(input, x + vec2(-dx,-dx))
21 | - texture2D(input, x + vec2(0,-dx))
22 | - texture2D(input, x + vec2(dx,-dx))
23 | + 2*texture2D(input, x + vec2(-dx,dx))
24 | + texture2D(input, x + vec2(0,dx))
25 | + texture2D(input, x + vec2(dx,dx));
26 | }
27 |
28 | float edge(float grad)
29 | {
30 | if (grad > primary_treshold) {
31 | return 1.0;
32 | } else if (grad > secondary_treshold){
33 | return 0.5;
34 | } else {
35 | return 0.0;
36 | }
37 | }
38 |
39 | void main()
40 | {
41 | vec4 sx = compute_sobelx();
42 | vec4 sy = compute_sobely();
43 | float grad = (abs(sx.x)+abs(sx.y)+abs(sx.z)+
44 | abs(sx.x)+abs(sy.y)+abs(sy.z))/3.0;
45 |
46 | // gl_FragData[0] is buffer sobelx
47 | gl_FragData[0] = vec4(sx.xyz,1);
48 |
49 | // gl_FragData[1] is buffer sobely
50 | gl_FragData[1] = vec4(sy.xyz,1);
51 |
52 | // gl_FragData[2] is buffer gradient
53 | gl_FragData[2] = vec4(vec3(grad),1);
54 |
55 | // gl_FragData[3] is buffer edges
56 | gl_FragData[3] = vec4(vec3(edge(grad)),1);
57 | }
58 |
--------------------------------------------------------------------------------
/examples/lerp_cuda.ip:
--------------------------------------------------------------------------------
1 |
2 | CUDA
3 |
4 | buffer1
5 | half
6 | 4
7 | images/bridge.exr
8 |
9 |
10 | buffer2
11 | half
12 | 4
13 | images/river.exr
14 |
15 |
16 | buffer3
17 | half
18 | 4
19 |
20 |
21 |
22 | lerp
23 | kernels/lerp.cu
24 |
25 | a
26 | buffer1
27 |
28 |
29 | b
30 | buffer2
31 |
32 |
33 | out
34 | buffer3
35 |
36 |
37 | alpha
38 | float
39 | 0.0
40 | 0.0
41 | 0.0
42 | 1.0
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/examples/lerp_cuda_float.ip:
--------------------------------------------------------------------------------
1 |
2 | OpenCL
3 |
4 | buffer1
5 | float
6 | 4
7 | images/bridge.exr
8 |
9 |
10 | buffer2
11 | float
12 | 4
13 | images/river.exr
14 |
15 |
16 | buffer3
17 | float
18 | 4
19 |
20 |
21 |
22 | lerp
23 | kernels/lerp_float.cu
24 |
25 | a
26 | buffer1
27 |
28 |
29 | b
30 | buffer2
31 |
32 |
33 | out
34 | buffer3
35 |
36 |
37 | alpha
38 | float
39 | 0.0
40 | 0.0
41 | 0.0
42 | 1.0
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/examples/lerp_cuda_ubyte.ip:
--------------------------------------------------------------------------------
1 |
2 | OpenCL
3 |
4 | buffer1
5 | ubyte
6 | 4
7 | images/lena.png
8 |
9 |
10 | buffer2
11 | ubyte
12 | 4
13 | images/baboon.png
14 |
15 |
16 | buffer3
17 | ubyte
18 | 4
19 |
20 |
21 |
22 | lerp
23 | kernels/lerp_ubyte.cu
24 |
25 | a
26 | buffer1
27 |
28 |
29 | b
30 | buffer2
31 |
32 |
33 | out
34 | buffer3
35 |
36 |
37 | alpha
38 | float
39 | 0.0
40 | 0.0
41 | 0.0
42 | 1.0
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/examples/lerp_glsl.ip:
--------------------------------------------------------------------------------
1 |
2 | GLSL
3 |
4 | buffer1
5 | half
6 | 4
7 | images/bridge.exr
8 |
9 |
10 | buffer2
11 | half
12 | 4
13 | images/river.exr
14 |
15 |
16 | buffer3
17 | half
18 | 4
19 |
20 |
21 |
22 | lerp
23 | kernels/lerp.glsl
24 |
25 | a
26 | buffer1
27 |
28 |
29 | b
30 | buffer2
31 |
32 |
33 | out
34 | buffer3
35 |
36 |
37 | alpha
38 | float
39 | 0.39
40 | 0.0
41 | 0.0
42 | 1.0
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/examples/lerp_glsl_float.ip:
--------------------------------------------------------------------------------
1 |
2 | GLSL
3 |
4 | buffer1
5 | float
6 | 4
7 | images/bridge.exr
8 |
9 |
10 | buffer2
11 | float
12 | 4
13 | images/river.exr
14 |
15 |
16 | buffer3
17 | float
18 | 4
19 |
20 |
21 |
22 | lerp
23 | kernels/lerp.glsl
24 |
25 | a
26 | buffer1
27 |
28 |
29 | b
30 | buffer2
31 |
32 |
33 | out
34 | buffer3
35 |
36 |
37 | alpha
38 | float
39 | 0
40 | 0.0
41 | 0.0
42 | 1.0
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/examples/lerp_glsl_ubyte.ip:
--------------------------------------------------------------------------------
1 |
2 | GLSL
3 |
4 | buffer1
5 | ubyte
6 | 4
7 | images/lena.png
8 |
9 |
10 | buffer2
11 | ubyte
12 | 4
13 | images/baboon.png
14 |
15 |
16 | buffer3
17 | ubyte
18 | 4
19 |
20 |
21 |
22 | lerp
23 | kernels/lerp.glsl
24 |
25 | a
26 | buffer1
27 |
28 |
29 | b
30 | buffer2
31 |
32 |
33 | out
34 | buffer3
35 |
36 |
37 | alpha
38 | float
39 | 0.35
40 | 0.0
41 | 0.0
42 | 1.0
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/examples/lerp_opencl.ip:
--------------------------------------------------------------------------------
1 |
2 | OpenCL
3 |
4 | buffer1
5 | half
6 | 4
7 | images/bridge.exr
8 |
9 |
10 | buffer2
11 | half
12 | 4
13 | images/river.exr
14 |
15 |
16 | buffer3
17 | half
18 | 4
19 |
20 |
21 |
22 | lerp
23 | kernels/lerp.cl
24 |
25 | a
26 | buffer1
27 |
28 |
29 | b
30 | buffer2
31 |
32 |
33 | out
34 | buffer3
35 |
36 |
37 | alpha
38 | float
39 | 0.74
40 | 0.0
41 | 0.0
42 | 1.0
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/examples/lerp_opencl_float.ip:
--------------------------------------------------------------------------------
1 |
2 | OpenCL
3 |
4 | buffer1
5 | float
6 | 4
7 | images/bridge.exr
8 |
9 |
10 | buffer2
11 | float
12 | 4
13 | images/river.exr
14 |
15 |
16 | buffer3
17 | float
18 | 4
19 |
20 |
21 |
22 | lerp
23 | kernels/lerp_float.cl
24 |
25 | a
26 | buffer1
27 |
28 |
29 | b
30 | buffer2
31 |
32 |
33 | out
34 | buffer3
35 |
36 |
37 | alpha
38 | float
39 | 0.84
40 | 0.0
41 | 0.0
42 | 1.0
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/examples/lerp_opencl_ubyte.ip:
--------------------------------------------------------------------------------
1 |
2 | OpenCL
3 |
4 | buffer1
5 | ubyte
6 | 4
7 | images/lena.png
8 |
9 |
10 | buffer2
11 | ubyte
12 | 4
13 | images/baboon.png
14 |
15 |
16 | buffer3
17 | ubyte
18 | 4
19 |
20 |
21 |
22 | lerp
23 | kernels/lerp_ubyte.cl
24 |
25 | a
26 | buffer1
27 |
28 |
29 | b
30 | buffer2
31 |
32 |
33 | out
34 | buffer3
35 |
36 |
37 | alpha
38 | float
39 | 0.46
40 | 0.0
41 | 0.0
42 | 1.0
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/examples/sobel_cuda.ip:
--------------------------------------------------------------------------------
1 |
2 | CUDA
3 |
4 | buffer1
5 | ubyte
6 | 4
7 | images/lena.png
8 |
9 |
10 | buffer2
11 | ubyte
12 | 4
13 |
14 |
15 | buffer3
16 | ubyte
17 | 4
18 |
19 |
20 | buffer4
21 | ubyte
22 | 4
23 |
24 |
25 | buffer5
26 | ubyte
27 | 4
28 |
29 |
30 | sobel
31 | kernels/sobel.cu
32 |
33 | in
34 | buffer1
35 |
36 |
37 | sobelx
38 | buffer2
39 |
40 |
41 | sobely
42 | buffer3
43 |
44 |
45 | gradient
46 | buffer4
47 |
48 |
49 | edges
50 | buffer5
51 |
52 |
53 | primary_treshold
54 | float
55 | 250
56 | 250.0
57 | 0.0
58 | 500.0
59 |
60 |
61 | secondary_treshold
62 | float
63 | 160
64 | 160.0
65 | 0.0
66 | 500.0
67 |
68 |
69 |
70 |
--------------------------------------------------------------------------------
/examples/sobel_glsl.ip:
--------------------------------------------------------------------------------
1 |
2 | GLSL
3 |
4 | buffer1
5 | ubyte
6 | 4
7 | images/lena.png
8 |
9 |
10 | buffer2
11 | ubyte
12 | 4
13 |
14 |
15 | buffer3
16 | ubyte
17 | 4
18 |
19 |
20 | buffer4
21 | ubyte
22 | 4
23 |
24 |
25 | buffer5
26 | ubyte
27 | 4
28 |
29 |
30 | sobel
31 | kernels/sobel.glsl
32 |
33 | input
34 | buffer1
35 |
36 |
37 | sobelx
38 | buffer2
39 |
40 |
41 | sobely
42 | buffer3
43 |
44 |
45 | gradient
46 | buffer4
47 |
48 |
49 | edges
50 | buffer5
51 |
52 |
53 | primary_treshold
54 | float
55 | 250
56 | 250.0
57 | 0.0
58 | 500.0
59 |
60 |
61 | secondary_treshold
62 | float
63 | 150
64 | 150.0
65 | 0.0
66 | 500.0
67 |
68 |
69 |
70 |
--------------------------------------------------------------------------------
/examples/sobel_opencl.ip:
--------------------------------------------------------------------------------
1 |
2 | OpenCL
3 |
4 | buffer1
5 | ubyte
6 | 4
7 | images/lena.png
8 |
9 |
10 | buffer2
11 | ubyte
12 | 4
13 |
14 |
15 |
16 | buffer3
17 | ubyte
18 | 4
19 |
20 |
21 |
22 | buffer4
23 | ubyte
24 | 4
25 |
26 |
27 |
28 | buffer5
29 | ubyte
30 | 4
31 |
32 |
33 |
34 | sobel
35 | kernels/sobel.cl
36 |
37 | in
38 | buffer1
39 |
40 |
41 | sobelx
42 | buffer2
43 |
44 |
45 | sobely
46 | buffer3
47 |
48 |
49 | gradient
50 | buffer4
51 |
52 |
53 | edges
54 | buffer5
55 |
56 |
57 | primary_treshold
58 | float
59 | 250.0
60 | 250.0
61 | 0.0
62 | 500.0
63 |
64 |
65 | secondary_treshold
66 | float
67 | 160.0
68 | 160.0
69 | 0.0
70 | 500.0
71 |
72 |
73 |
74 |
--------------------------------------------------------------------------------
/install.bat:
--------------------------------------------------------------------------------
1 | pushd %~dp0
2 | if not exist build\ (
3 | echo "Run 'build.bat' first to build gpuip"
4 |
5 | ) else (
6 | cd build
7 | cmake --build . --config Release --target INSTALL
8 | )
9 | pause
10 | popd
--------------------------------------------------------------------------------
/python/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | # The MIT License (MIT)
2 | #
3 | # Copyright (c) 2014 Per Karlsson
4 | #
5 | # Permission is hereby granted, free of charge, to any person obtaining a copy
6 | # of this software and associated documentation files (the "Software"), to deal
7 | # in the Software without restriction, including without limitation the rights
8 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | # copies of the Software, and to permit persons to whom the Software is
10 | # furnished to do so, subject to the following conditions:
11 | #
12 | # The above copyright notice and this permission notice shall be included in all
13 | # copies or substantial portions of the Software.
14 | #
15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | # SOFTWARE.
22 |
23 | project(gpuip_python)
24 |
25 | set(PYTHON_ICONS_FILE ${GPUIP_ROOT_DIR}/python/icons.py)
26 | add_custom_target(generateIcons ALL
27 | ${PYTHON_EXECUTABLE} generateIcons.py ${PYTHON_ICONS_FILE}
28 | WORKING_DIRECTORY ${GPUIP_ROOT_DIR}/python/icons)
29 |
30 | file(GLOB PYTHON_FILES "*.py")
31 | install(FILES ${PYTHON_FILES} ${PYTHON_ICONS_FILE} DESTINATION gpuip
32 | COMPONENT bin)
33 | install(FILES gpuip.py DESTINATION gpuip
34 | PERMISSIONS OWNER_EXECUTE GROUP_EXECUTE WORLD_EXECUTE
35 | OWNER_READ GROUP_READ WORLD_READ COMPONENT bin)
36 |
37 | if(NOT WIN32)
38 | # Create symlink in CMAKE_INSTALL_PREFIX/bin
39 | set(GPUIP_PY ${CMAKE_INSTALL_PREFIX}/gpuip/gpuip.py)
40 | add_custom_target(symlink ALL
41 | ln -sf ${GPUIP_PY} gpuip
42 | WORKING_DIRECTORY ${GPUIP_ROOT_DIR}/python)
43 | install(FILES gpuip DESTINATION bin COMPONENT bin)
44 | endif()
45 |
46 |
47 |
48 |
49 |
50 |
51 |
--------------------------------------------------------------------------------
/python/bufferswidget.py:
--------------------------------------------------------------------------------
1 | from PySide import QtGui, QtCore
2 |
3 | class BuffersWidget(QtGui.QWidget):
4 | class Buffer(object):
5 | def __init__(self, name, format, channels, input, output, parent):
6 | self.layout = QtGui.QVBoxLayout()
7 |
8 | self.inputLineEdit = QtGui.QLineEdit(input, parent)
9 | self.outputLineEdit = QtGui.QLineEdit(output, parent)
10 | self.inputLineEdit.setMinimumWidth(100)
11 | self.outputLineEdit.setMinimumWidth(99)
12 | inputButton = QtGui.QPushButton("...", parent)
13 | inputButton.clicked.connect(self.selectInput)
14 | outputButton = QtGui.QPushButton("...", parent)
15 | outputButton.clicked.connect(self.selectOutput)
16 |
17 | labelNames = ["Name", "Format", "Channels", "Input", "Output" ]
18 | rhsWidgets = [[QtGui.QLabel(name,parent)] ,
19 | [QtGui.QLabel(format,parent)],
20 | [QtGui.QLabel(str(channels),parent)],
21 | [self.inputLineEdit, inputButton],
22 | [self.outputLineEdit, outputButton]]
23 |
24 | for name, widgets in zip(labelNames, rhsWidgets):
25 | lhs = QtGui.QLabel(""+name+": ", parent)
26 | layout = QtGui.QHBoxLayout()
27 | layout.addWidget(lhs)
28 | for widget in widgets:
29 | layout.addWidget(widget)
30 | if len(widgets) == 1:
31 | layout.addStretch()
32 | self.layout.addLayout(layout)
33 |
34 | def selectInput(self):
35 | inputImageFile = QtGui.QFileDialog.getOpenFileName(
36 | None, "Select input image",
37 | QtCore.QDir.currentPath(), "Exr (*exr);;Png (*png)")
38 | if inputImageFile[0]:
39 | self.inputLineEdit.setText(inputImageFile[0])
40 |
41 | def selectOutput(self):
42 | outputImageFile = QtGui.QFileDialog.getSaveFileName(
43 | None, "Choose output image",
44 | QtCore.QDir.currentPath(), "Exr(*exr);;Png (*png)")
45 | if outputImageFile[0]:
46 | self.outputLineEdit.setText(outputImageFile[0])
47 |
48 | def __init__(self, parent = None):
49 | super(BuffersWidget, self).__init__( parent)
50 |
51 | self.layout = QtGui.QVBoxLayout()
52 | self.setLayout(self.layout)
53 | self.buffers = {}
54 |
55 | def addBuffer(self, name, format, channels, input, output):
56 | self.buffers[name] = BuffersWidget.Buffer(name, format, channels,
57 | input, output, self)
58 | self.layout.addLayout(self.buffers[name].layout)
59 |
60 | # Add separating line after each buffer
61 | separator = QtGui.QFrame(self)
62 | separator.setFrameShape(QtGui.QFrame.HLine)
63 | separator.setFrameShadow(QtGui.QFrame.Sunken)
64 | self.layout.addWidget(separator)
65 |
66 | def getBufferInput(self, name):
67 | return str(self.buffers[name].inputLineEdit.text())
68 |
69 | def getBufferOutput(self, name):
70 | return str(self.buffers[name].outputLineEdit.text())
71 |
72 |
--------------------------------------------------------------------------------
/python/gpuip.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | import utils
3 | import sys
4 | import signal
5 | import os
6 | try:
7 | import argparse
8 | parsermodule = argparse.ArgumentParser
9 | except:
10 | import optparse
11 | parsermodule = optparse.OptionParser
12 | parsermodule.add_argument = parsermodule.add_option
13 |
14 | def getCommandLineArguments():
15 | # Command line arguments
16 | desc = "Framework for Image Processing on the GPU"
17 | parser = parsermodule("gpuip", description=desc)
18 | parser.add_argument("-f", "--file",
19 | help="Image Processing file *.ip")
20 | parser.add_argument("-p", "--param",
21 | action="append",
22 | nargs = 3,
23 | metavar = ("kernel", "param", "value"),
24 | help="Change value of a parameter.")
25 | parser.add_argument("-i", "--inbuffer",
26 | action="append",
27 | nargs = 2,
28 | metavar = ("buffer", "path"),
29 | help = "Set input image to a buffer")
30 | parser.add_argument("-o", "--outbuffer",
31 | action="append",
32 | nargs = 2,
33 | metavar = ("buffer", "path"),
34 | help = "Set output image to a buffer")
35 | parser.add_argument("-v","--verbose",
36 | action="store_true",
37 | help="Outputs information")
38 | parser.add_argument("--timestamp",
39 | action="store_true",
40 | help="Add timestamp in log output")
41 | parser.add_argument("--nogui",
42 | action="store_true",
43 | help="Command line version")
44 |
45 | if parsermodule.__name__ == "ArgumentParser":
46 | return parser.parse_args()
47 | else:
48 | return parser.parse_args()[0]
49 |
50 | def terminate(msg):
51 | print msg
52 | sys.exit(1)
53 |
54 | def getSettings(args):
55 | import settings
56 |
57 | if not args.file or not os.path.isfile(args.file):
58 | return None
59 |
60 | ipsettings = settings.Settings()
61 | ipsettings.read(args.file)
62 |
63 | # Change parameter values
64 | if args.param:
65 | for p in args.param:
66 | kernelName, paramName, value = p
67 | kernel = ipsettings.getKernel(kernelName)
68 | if not kernel:
69 | terminate("gpuip error: No kernel %s found." % kernelName)
70 | param = kernel.getParam(paramName)
71 | if param:
72 | param.setValue(utils.safeEval(value))
73 | else:
74 | terminate("gpuip error: No param %s found in kernel %s." \
75 | % (paramName, kernelName))
76 |
77 | # Change input buffers
78 | if args.inbuffer:
79 | for inb in args.inbuffer:
80 | bufferName, path = inb[0], inb[1]
81 | buffer = ipsettings.getBuffer(bufferName)
82 | if buffer:
83 | buffer.input = path
84 | if not os.path.isfile(buffer.input):
85 | raise IOError("No such file: '%s'" % buffer.input)
86 | else:
87 | terminate("gpuip error: No buffer %s found." % buffer)
88 |
89 | # Change output buffers
90 | if args.outbuffer:
91 | for outb in args.outbuffer:
92 | bufferName, path = outb[0], outb[1]
93 | buffer = ipsettings.getBuffer(bufferName)
94 | if buffer:
95 | buffer.output = path
96 | os.makedirs(os.path.dirname(os.path.realpath(path)))
97 | else:
98 | terminate("gpuip error: No buffer %s found." % bufferName)
99 |
100 | return ipsettings
101 |
102 | def runGUI(ippath, ipsettings):
103 | # Run GUI version
104 | from PySide import QtGui
105 | import mainwindow
106 |
107 | # Makes it possible to close program with ctrl+c in a terminal
108 | signal.signal(signal.SIGINT, signal.SIG_DFL)
109 | app = QtGui.QApplication(sys.argv)
110 | app.setStyle("plastique")
111 | mainwindow = mainwindow.MainWindow(path = ippath, settings = ipsettings)
112 | mainwindow.show()
113 | sys.exit(app.exec_())
114 |
115 | def runCommandLine(ipsettings, verbose):
116 | # Can't run non-gui version if there's no *.ip file
117 | if not ipsettings:
118 | err = "Must specify an existing *.ip file in the command-line version\n"
119 | err += "example: \n"
120 | err += " gpuip --nogui smooth.ip"""
121 | terminate(err)
122 |
123 | def check_error(err):
124 | if err:
125 | terminate(err)
126 |
127 | def log(text, stopwatch = None, time = True):
128 | time = time and args.timestamp
129 | if verbose:
130 | stopwatchStr = str(stopwatch) if stopwatch else ""
131 | timeStr = utils.getTimeStr() if time else ""
132 | print timeStr + text + " " + stopwatchStr
133 |
134 | overall_clock = utils.StopWatch()
135 |
136 | ### 0. Create gpuip items from settings
137 | ip, buffers, kernels = ipsettings.create()
138 | log("Created elements from settings.", overall_clock)
139 |
140 | ### 1. Build
141 | c = utils.StopWatch()
142 | check_error(ip.Build())
143 | log("Building kernels [%s]." % [k.name for k in kernels], c)
144 |
145 | ### 2. Import data from images
146 | c = utils.StopWatch()
147 | for b in ipsettings.buffers:
148 | if b.input:
149 | log("Importing data from %s to %s" %(b.input, b.name))
150 | check_error(buffers[b.name].Read(b.input, utils.getNumCores()))
151 | log("Importing data done.", c)
152 |
153 | ### 3. Allocate and transfer data to GPU
154 | c = utils.StopWatch()
155 | width, height = utils.allocateBufferData(buffers)
156 | ip.SetDimensions(width, height)
157 | check_error(ip.Allocate())
158 | log("Allocating done.", c)
159 | c = utils.StopWatch()
160 | for b in ipsettings.buffers:
161 | if b.input:
162 | check_error(ip.WriteBufferToGPU(buffers[b.name]))
163 | log("Transfering data to GPU done.", c)
164 |
165 | ### 4. Process
166 | c = utils.StopWatch()
167 | check_error(ip.Run())
168 | log("Processing done.", c)
169 |
170 | ### 5. Export buffers to images
171 | c = utils.StopWatch()
172 | for b in ipsettings.buffers:
173 | if b.output:
174 | log("Exporting data from %s to %s" %(b.name, b.output))
175 | check_error(ip.ReadBufferFromGPU(buffers[b.name]))
176 | check_error(buffers[b.name].Write(b.output,utils.getNumCores()))
177 | log("Exporting data done.", c)
178 |
179 | log("\nAll steps done. Total runtime:", overall_clock, time = False)
180 |
181 | if __name__ == "__main__":
182 | args = getCommandLineArguments()
183 | ipsettings = getSettings(args)
184 | if args.nogui:
185 | runCommandLine(ipsettings, args.verbose)
186 | else:
187 | runGUI(args.file if ipsettings else None, ipsettings)
188 |
189 |
--------------------------------------------------------------------------------
/python/icons/boilerplate.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/karlssonper/gpuip/ce9a62ea9ced3f167a2477bf58944281dac6d45b/python/icons/boilerplate.png
--------------------------------------------------------------------------------
/python/icons/build.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/karlssonper/gpuip/ce9a62ea9ced3f167a2477bf58944281dac6d45b/python/icons/build.png
--------------------------------------------------------------------------------
/python/icons/export.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/karlssonper/gpuip/ce9a62ea9ced3f167a2477bf58944281dac6d45b/python/icons/export.png
--------------------------------------------------------------------------------
/python/icons/generateIcons.py:
--------------------------------------------------------------------------------
1 | import os
2 | import glob
3 | import sys
4 | import numpy
5 | # no need to generate again
6 | if os.path.exists(sys.argv[1]):
7 | sys.exit(0)
8 | try:
9 | from PIL import Image
10 | except:
11 | txt = ("raise Exception('gpuip: Icons were not generated. "
12 | "Install the Python module PIL and rebuild.')")
13 | open(sys.argv[1], "w").write(txt)
14 | sys.exit(0)
15 |
16 | out = """from PySide import QtGui
17 | data, width, height = {}, {}, {}
18 | def get(name):
19 | image = QtGui.QImage(data[name], width[name], height[name],
20 | QtGui.QImage.Format_ARGB32)
21 | return QtGui.QIcon(QtGui.QPixmap.fromImage(image))
22 | """
23 |
24 | for i in glob.glob("*.png"):
25 | name = i[:i.find(".")]
26 | data = numpy.asarray(Image.open(i).convert("RGBA"))
27 | data_flip = numpy.array(data, copy=True)
28 | data_flip[:,:,0] = data[:,:,2]
29 | data_flip[:,:,2] = data[:,:,0]
30 | out += "data['" + name + "'] = " + repr(data_flip.tostring()) + " \n"
31 | out += "width['" + name + "'] = " + str(data_flip.shape[0]) + "\n"
32 | out += "height['" + name + "'] = " + str(data_flip.shape[1]) + "\n"
33 |
34 | open(sys.argv[1], "w").write(out)
35 |
--------------------------------------------------------------------------------
/python/icons/import.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/karlssonper/gpuip/ce9a62ea9ced3f167a2477bf58944281dac6d45b/python/icons/import.png
--------------------------------------------------------------------------------
/python/icons/init.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/karlssonper/gpuip/ce9a62ea9ced3f167a2477bf58944281dac6d45b/python/icons/init.png
--------------------------------------------------------------------------------
/python/icons/new.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/karlssonper/gpuip/ce9a62ea9ced3f167a2477bf58944281dac6d45b/python/icons/new.png
--------------------------------------------------------------------------------
/python/icons/newExisting.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/karlssonper/gpuip/ce9a62ea9ced3f167a2477bf58944281dac6d45b/python/icons/newExisting.png
--------------------------------------------------------------------------------
/python/icons/open.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/karlssonper/gpuip/ce9a62ea9ced3f167a2477bf58944281dac6d45b/python/icons/open.png
--------------------------------------------------------------------------------
/python/icons/process.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/karlssonper/gpuip/ce9a62ea9ced3f167a2477bf58944281dac6d45b/python/icons/process.png
--------------------------------------------------------------------------------
/python/icons/pug.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/karlssonper/gpuip/ce9a62ea9ced3f167a2477bf58944281dac6d45b/python/icons/pug.png
--------------------------------------------------------------------------------
/python/icons/refresh.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/karlssonper/gpuip/ce9a62ea9ced3f167a2477bf58944281dac6d45b/python/icons/refresh.png
--------------------------------------------------------------------------------
/python/icons/run.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/karlssonper/gpuip/ce9a62ea9ced3f167a2477bf58944281dac6d45b/python/icons/run.png
--------------------------------------------------------------------------------
/python/icons/save.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/karlssonper/gpuip/ce9a62ea9ced3f167a2477bf58944281dac6d45b/python/icons/save.png
--------------------------------------------------------------------------------
/python/kernelwidget.py:
--------------------------------------------------------------------------------
1 | from PySide import QtGui, QtCore
2 | import sys
3 | import utils
4 |
5 | class KernelWidget(QtGui.QSplitter):
6 | def __init__(self, parent = None, callbackFunc = None):
7 | super(KernelWidget, self).__init__(QtCore.Qt.Horizontal,parent)
8 |
9 | #Optional callback function. Called everytime a paramter is changed
10 | self.callbackFunc = callbackFunc
11 |
12 | # Left side is a Text Editor where the kernel code is displayed
13 | self.codeEditor = CodeEditor(self)
14 |
15 | # Right side is going to vertically placed group boxes
16 | # rightWidget is a work around since you can't add layouts to QSplitters
17 | rightWidget = QtGui.QWidget(self)
18 | rightLayout = QtGui.QVBoxLayout()
19 | rightWidget.setLayout(rightLayout)
20 | rightWidget.setSizePolicy(QtGui.QSizePolicy.Minimum,
21 | QtGui.QSizePolicy.Minimum)
22 |
23 | # Three group boxes for in buffers, out buffers and parameters
24 | groupBoxesNames = ["Input Buffers", "Output Buffers", "Parameters"]
25 | groupBoxes = [QtGui.QGroupBox(s,self) for s in groupBoxesNames]
26 | self.gridLayouts= {}
27 | for i,groupBox in enumerate(groupBoxes):
28 | self.gridLayouts[groupBoxesNames[i]] = QtGui.QGridLayout()
29 | groupBox.setLayout(self.gridLayouts[groupBoxesNames[i]])
30 | groupBox.setSizePolicy(QtGui.QSizePolicy.Minimum,
31 | QtGui.QSizePolicy.Minimum)
32 | rightLayout.addWidget(groupBox)
33 | rightLayout.addStretch()
34 |
35 | # Add widgets to splitter
36 | self.addWidget(self.codeEditor)
37 | self.addWidget(rightWidget)
38 |
39 | self.inBuffers = {}
40 | self.outBuffers = {}
41 | self.params = {}
42 |
43 | def addInBuffer(self, name, buffer, bufferNames):
44 | self.inBuffers[name] = Buffer(self, name, buffer, bufferNames,
45 | self.gridLayouts["Input Buffers"],
46 | len(self.inBuffers))
47 |
48 | def addOutBuffer(self, name, buffer, bufferNames):
49 | self.outBuffers[name] = Buffer(self, name, buffer, bufferNames,
50 | self.gridLayouts["Output Buffers"],
51 | len(self.outBuffers))
52 |
53 | def addParameter(self, name, val, defVal, minVal, maxVal, typename):
54 | self.params[name] = Parameter(self.gridLayouts["Parameters"],
55 | len(self.params), name, val, defVal,
56 | minVal, maxVal, typename,
57 | self.callbackFunc)
58 | class Buffer(object):
59 | def __init__(self, parent, name, buffer, bufferNames, grid, row):
60 | self.name = name
61 | label = QtGui.QLabel(name+": ", parent)
62 | label.setSizePolicy(QtGui.QSizePolicy.Maximum,
63 | QtGui.QSizePolicy.Maximum)
64 | self.cbox = QtGui.QComboBox(parent)
65 | self.cbox.addItems(bufferNames)
66 | if buffer != "":
67 | idx = bufferNames.index(buffer)
68 | if idx != -1:
69 | self.cbox.setCurrentIndex(idx)
70 |
71 | grid.addWidget(label, row, 0)
72 | grid.addWidget(self.cbox, row, 1)
73 |
74 | class Parameter(object):
75 | def __init__(self, gridLayout, row, name, val, defVal, minVal, maxVal,
76 | typename, callbackFunc = None):
77 | self.name = name
78 | self.defaultVal = defVal
79 | self.minVal = minVal
80 | self.maxVal = maxVal
81 | self.typename = typename
82 | self.callbackFunc = callbackFunc
83 |
84 | # Each parameters has a label with the name, a lineedit with text value
85 | # and a slider with the value (relative to min max)
86 | self.label = QtGui.QLabel(name)
87 | self.lineEdit = QtGui.QLineEdit()
88 | self.lineEdit.setFixedWidth(60)
89 |
90 | # Custom slider with a minimum width
91 | class _Slider(QtGui.QSlider):
92 | def __init__(self):
93 | super(_Slider, self).__init__(QtCore.Qt.Horizontal)
94 | self.setSizePolicy(QtGui.QSizePolicy.MinimumExpanding,
95 | QtGui.QSizePolicy.Maximum)
96 | def sizeHint(self):
97 | return QtCore.QSize(80,20)
98 | self.slider = _Slider()
99 | self.slider.setRange(0,100)
100 |
101 | gridLayout.addWidget(self.label, row, 0)
102 | gridLayout.addWidget(self.lineEdit, row, 1)
103 | gridLayout.addWidget(self.slider, row, 2)
104 |
105 | # When a slider is changed it should update the line edit and vice verse
106 | self.lineEdit.textChanged.connect(self.onLineEditChange)
107 | self.slider.valueChanged.connect(self.onSliderChange)
108 |
109 | # Helper variables to know when to trigger updates
110 | self.updateSlider = True
111 | self.updateLineEdit = True
112 |
113 | txt = str(int(val)) if typename == "int" else str(val)
114 | self.lineEdit.setText(txt)
115 |
116 | def onLineEditChange(self):
117 | # Changing the line edit triggers slider update that triggers
118 | # line edit update again. This is to prevent the second update
119 | if not self.updateLineEdit:
120 | return
121 |
122 | # Evaluate the line edit text to get the number
123 | val = utils.safeEval(self.lineEdit.text(),self.defaultVal,self.typename)
124 | if self.typename == "int":
125 | # If the parameter is of int, format line edit to be int too.
126 | self.lineEdit.setText(str(val))
127 |
128 | # Don't run the onSliderChange function
129 | self.updateSlider = False
130 |
131 | # Update the slider position
132 | if val < self.minVal:
133 | self.slider.setSliderPosition(0)
134 | elif val > self.maxVal:
135 | self.slider.setSliderPosition(100)
136 | else:
137 | t = (val - self.minVal) / float(self.maxVal - self.minVal)
138 | self.slider.setSliderPosition(100 * t)
139 |
140 | # Slider has been updated, safe to set this variable to true again
141 | self.updateSlider = True
142 |
143 | # If a callback function was added, call it
144 | if self.callbackFunc:
145 | self.callbackFunc()
146 |
147 | def onSliderChange(self):
148 | # Changing the slider triggers line edit update that triggers
149 | # slider update again. This is to prevent the second update
150 | if not self.updateSlider:
151 | return
152 |
153 | # Evaluate val based on slider position
154 | val = 0.01*self.slider.value() * (self.maxVal-self.minVal) + self.minVal
155 |
156 | # Don't run the onLineEditChange function
157 | self.updateLineEdit = False
158 |
159 | # Update LineEdit text
160 | txt = str(int(val))if self.typename == "int" else str(val)
161 | self.lineEdit.setText(txt)
162 |
163 | # LineEdit has been updated, safe to set this variable to true again
164 | self.updateLineEdit = True
165 |
166 | # If a callback function was added, call it
167 | if self.callbackFunc:
168 | self.callbackFunc()
169 |
170 | class CodeEditor(QtGui.QTextEdit):
171 | def __init__(self, parent):
172 | super(CodeEditor, self).__init__(parent)
173 | font = QtGui.QFont()
174 | font.setFamily("Monospace")
175 | font.setFixedPitch(True);
176 | metrics = QtGui.QFontMetrics(font)
177 | self.setTabStopWidth(4 * metrics.width(' '))
178 | self.w = 55 * metrics.width(' ')
179 | self.setFont(font)
180 | color = QtGui.QColor(0,0,0)
181 | color.setNamedColor("#F8F8F2")
182 | self.setTextColor(color)
183 | self.setSizePolicy(QtGui.QSizePolicy.Minimum,
184 | QtGui.QSizePolicy.Minimum)
185 | self.highlighter = Highlighter(self.document())
186 |
187 | def sizeHint(self):
188 | return QtCore.QSize(self.w,200)
189 |
190 | class Highlighter(QtGui.QSyntaxHighlighter):
191 | def __init__(self, parent=None):
192 | super(Highlighter, self).__init__(parent)
193 |
194 | keywordFormat = QtGui.QTextCharFormat()
195 | color = QtGui.QColor(0,0,0)
196 | color.setNamedColor("#66D9EF")
197 | keywordFormat.setForeground(color)
198 |
199 | keywords = ["char", "double", "sampler2D",
200 | "vec2", "vec3", "vec4",
201 | "half", "bool",
202 | "float", "float2", "float3", "float4",
203 | "uchar", "uchar2", "uchar3", "uchar4",
204 | "int", "int2", "int3", "int4", "long",
205 | "short", "signed", "unsigned", "union", "void"]
206 | keywordPatterns = ["\\b" + kw + "\\b" for kw in keywords]
207 | self.highlightingRules = [(QtCore.QRegExp(pattern), keywordFormat)
208 | for pattern in keywordPatterns]
209 |
210 | keywordFormat = QtGui.QTextCharFormat()
211 | color = QtGui.QColor(0,0,0)
212 | color.setNamedColor("#4e9a06")
213 | keywordFormat.setForeground(color)
214 | keywords = ["__kernel", "__device__", "__global", "__global__",
215 | "uniform", "varying", "#version", "texture2D"]
216 | keywordPatterns = ["\\b" + kw + "\\b" for kw in keywords]
217 | self.highlightingRules += [(QtCore.QRegExp(pattern), keywordFormat)
218 | for pattern in keywordPatterns]
219 |
220 | keywordFormat = QtGui.QTextCharFormat()
221 | color = QtGui.QColor(0,0,0)
222 | color.setNamedColor("#F92672")
223 | keywordFormat.setForeground(color)
224 | keywords = ["const", "inline", "template", "typedef", "typename",
225 | "if", "for", "while", "switch", "case",
226 | "return", "break", "else"]
227 | keywordPatterns = ["\\b" + kw + "\\b" for kw in keywords]
228 | self.highlightingRules += [(QtCore.QRegExp(pattern), keywordFormat)
229 | for pattern in keywordPatterns]
230 |
231 | color = QtGui.QColor(0,0,0)
232 | color.setNamedColor("#75715E")
233 | singleLineCommentFormat = QtGui.QTextCharFormat()
234 | singleLineCommentFormat.setForeground(color)
235 | self.highlightingRules.append((QtCore.QRegExp("//[^\n]*"),
236 | singleLineCommentFormat))
237 |
238 | self.multiLineCommentFormat = QtGui.QTextCharFormat()
239 | self.multiLineCommentFormat.setForeground(color)#QtCore.Qt.red)
240 |
241 | quotationFormat = QtGui.QTextCharFormat()
242 | quotationFormat.setForeground(QtCore.Qt.darkGreen)
243 | self.highlightingRules.append((QtCore.QRegExp("\".*\""),
244 | quotationFormat))
245 |
246 | self.commentStartExpression = QtCore.QRegExp("/\\*")
247 | self.commentEndExpression = QtCore.QRegExp("\\*/")
248 |
249 | def highlightBlock(self, text):
250 | for pattern, format in self.highlightingRules:
251 | expression = QtCore.QRegExp(pattern)
252 | index = expression.indexIn(text)
253 | while index >= 0:
254 | length = expression.matchedLength()
255 | self.setFormat(index, length, format)
256 | index = expression.indexIn(text, index + length)
257 |
258 | self.setCurrentBlockState(0)
259 |
260 | startIndex = 0
261 | if self.previousBlockState() != 1:
262 | startIndex = self.commentStartExpression.indexIn(text)
263 |
264 | while startIndex >= 0:
265 | endIndex = self.commentEndExpression.indexIn(text, startIndex)
266 |
267 | if endIndex == -1:
268 | self.setCurrentBlockState(1)
269 | commentLength = len(text) - startIndex
270 | else:
271 | commentLength = endIndex - startIndex + \
272 | self.commentEndExpression.matchedLength()
273 |
274 | self.setFormat(startIndex, commentLength,
275 | self.multiLineCommentFormat)
276 | startIndex = self.commentStartExpression.indexIn(text,
277 | startIndex + commentLength);
278 |
279 |
--------------------------------------------------------------------------------
/python/settings.py:
--------------------------------------------------------------------------------
1 | from xml.dom import minidom
2 | import pygpuip
3 | import numpy
4 | import utils
5 | import os
6 |
7 | class Settings(object):
8 | class Buffer(object):
9 | def __init__(self, name, type, channels):
10 | self.name = name
11 | self.type = type
12 | self.channels = channels
13 | self.input = ""
14 | self.output = ""
15 |
16 | class Param(object):
17 | def __init__(self, name, type, default, min, max):
18 | self.name = name
19 | self.type = type
20 | self.default = default if type == "float" else int(default)
21 | self.min = min if type == "float" else int(min)
22 | self.max = max if type == "float" else int(max)
23 | self.setValue(self.default)
24 |
25 | def setValue(self, value):
26 | self.value = value if type == "float" else int(value)
27 |
28 | class Kernel(object):
29 | class KernelBuffer(object):
30 | def __init__(self, name, buffer):
31 | self.name = name
32 | self.buffer = buffer
33 | def __init__(self, name, code_file):
34 | self.name = name
35 | self.code = ""
36 | self.code_file = code_file
37 | self.params = []
38 | self.inBuffers = []
39 | self.outBuffers = []
40 |
41 | def getParam(self, name):
42 | for p in self.params:
43 | if p.name == name:
44 | return p
45 | return None
46 |
47 | def __init__(self):
48 | self.buffers = []
49 | self.kernels = []
50 | self.environment = ""
51 |
52 | def getKernel(self, name):
53 | for k in self.kernels:
54 | if k.name == name:
55 | return k
56 | return None
57 |
58 | def getBuffer(self, name):
59 | for b in self.buffers:
60 | if b.name == name:
61 | return b
62 | return None
63 |
64 | def updateCode(self):
65 | for k in self.kernels:
66 | if os.path.isfile(k.code_file):
67 | k.code = open(k.code_file).read()
68 |
69 | def read(self, xml_file):
70 | xmldom = minidom.parse(xml_file)
71 | path = os.path.realpath(os.path.dirname(xml_file))
72 |
73 | # Environment
74 | self.environment = str(self.data(
75 | xmldom.getElementsByTagName("gpuip")[0],
76 | "environment"))
77 |
78 | # Buffers
79 | for b in xmldom.getElementsByTagName("buffer"):
80 | buffer = Settings.Buffer(self.data(b, "name"),
81 | self.data(b, "type"),
82 | utils.safeEval(self.data(b, "channels")))
83 | if b.getElementsByTagName("input"):
84 | buffer.input = os.path.join(path,self.data(b, "input"))
85 | if b.getElementsByTagName("output"):
86 | buffer.output = os.path.join(path,self.data(b, "output"))
87 | if not os.path.exists(os.path.dirname(buffer.output)):
88 | os.makedirs(os.path.dirname(buffer.output))
89 | self.buffers.append(buffer)
90 |
91 | # Kernels
92 | for k in xmldom.getElementsByTagName("kernel"):
93 | kernel = Settings.Kernel(
94 | self.data(k, "name"),
95 | os.path.join(path, self.data(k, "code_file")))
96 |
97 | # In Buffers
98 | for inb in k.getElementsByTagName("inbuffer"):
99 | name = self.data(inb, "name")
100 | hasBuffer = inb.getElementsByTagName("targetbuffer")
101 | buf = self.data(inb, "targetbuffer") if hasBuffer else ""
102 | kernel.inBuffers.append(Settings.Kernel.KernelBuffer(name,buf))
103 |
104 | # Out Buffers
105 | for outb in k.getElementsByTagName("outbuffer"):
106 | name = self.data(outb, "name")
107 | hasBuffer = outb.getElementsByTagName("targetbuffer")
108 | buf = self.data(outb, "targetbuffer") if hasBuffer else ""
109 | kernel.outBuffers.append(Settings.Kernel.KernelBuffer(name,buf))
110 |
111 | # Params
112 | for p in k.getElementsByTagName("param"):
113 | type = self.data(p, "type")
114 | param = Settings.Param(
115 | self.data(p, "name"), type,
116 | utils.safeEval(self.data(p, "default"),type),
117 | utils.safeEval(self.data(p, "min"),type),
118 | utils.safeEval(self.data(p, "max"),type))
119 | param.value = utils.safeEval(self.data(p, "value"),type)
120 | kernel.params.append(param)
121 | self.kernels.append(kernel)
122 |
123 | self.updateCode()
124 |
125 | def write(self, xml_file):
126 | path = os.path.realpath(os.path.dirname(xml_file))
127 | doc = minidom.Document()
128 | root = doc.createElement("gpuip")
129 |
130 | # Environment
131 | node = doc.createElement("environment")
132 | root.appendChild(node)
133 | node.appendChild(doc.createTextNode(self.environment))
134 |
135 | # Buffers
136 | bufferAttrs = ["name", "type", "channels", "input", "output"]
137 | for b in self.buffers:
138 | bufferNode = doc.createElement("buffer")
139 | root.appendChild(bufferNode)
140 |
141 | for attr in bufferAttrs:
142 | value = str(getattr(b, attr))
143 | if value != "":
144 | node = doc.createElement(attr)
145 | bufferNode.appendChild(node)
146 | node.appendChild(doc.createTextNode(value))
147 |
148 | # Kernels
149 | paramAttrs = ["name", "type", "value", "default", "min", "max"]
150 | for k in self.kernels:
151 | # Write kernel code to file
152 | code_file_path = os.path.join(path,k.code_file)
153 | open(code_file_path, "w").write(k.code.replace("\t"," "))
154 |
155 | kernelNode = doc.createElement("kernel")
156 | root.appendChild(kernelNode)
157 |
158 | node = doc.createElement("name")
159 | kernelNode.appendChild(node)
160 | node.appendChild(doc.createTextNode(k.name))
161 |
162 | node = doc.createElement("code_file")
163 | kernelNode.appendChild(node)
164 | node.appendChild(doc.createTextNode(k.code_file))
165 |
166 | # In Buffers
167 | for inb in k.inBuffers:
168 | inbufferNode = doc.createElement("inbuffer")
169 | kernelNode.appendChild(inbufferNode)
170 | node = doc.createElement("name")
171 | inbufferNode.appendChild(node)
172 | node.appendChild(doc.createTextNode(inb.name))
173 | if inb.buffer != "":
174 | node = doc.createElement("targetbuffer")
175 | inbufferNode.appendChild(node)
176 | node.appendChild(doc.createTextNode(inb.buffer))
177 |
178 | # In Buffers
179 | for outb in k.outBuffers:
180 | outbufferNode = doc.createElement("outbuffer")
181 | kernelNode.appendChild(outbufferNode)
182 | node = doc.createElement("name")
183 | outbufferNode.appendChild(node)
184 | node.appendChild(doc.createTextNode(outb.name))
185 | if outb.buffer != "":
186 | node = doc.createElement("targetbuffer")
187 | outbufferNode.appendChild(node)
188 | node.appendChild(doc.createTextNode(outb.buffer))
189 |
190 | # Params
191 | for p in k.params:
192 | paramNode = doc.createElement("param")
193 | kernelNode.appendChild(paramNode)
194 | for attr in paramAttrs:
195 | node = doc.createElement(attr)
196 | paramNode.appendChild(node)
197 | node.appendChild(doc.createTextNode(str(getattr(p, attr))))
198 |
199 | # Ugly result :(
200 | #root.writexml(open(xml_file,'w'), addindent=" ", newl='\n')
201 |
202 | # Work-around to get one line text nodes, taken from
203 | #http://stackoverflow.com/questions/749796/pretty-printing-xml-in-python
204 | import re
205 | xml = root.toprettyxml(indent=" ")
206 | text_re = re.compile('>\n\s+([^<>\s].*?)\n\s+', re.DOTALL)
207 | file_handle = open(xml_file, 'w')
208 | file_handle.write(text_re.sub('>\g<1>', xml))
209 | file_handle.close()
210 |
211 | @staticmethod
212 | def data(n, name):
213 | return str(n.getElementsByTagName(name)[0].childNodes[0].data).strip()
214 |
215 | def create(self):
216 | if self.environment == "OpenCL":
217 | env = pygpuip.Environment.OpenCL
218 | elif self.environment == "CUDA":
219 | env = pygpuip.Environment.CUDA
220 | elif self.environment == "GLSL":
221 | env = pygpuip.Environment.GLSL
222 | ip = pygpuip.ImageProcessor(env)
223 |
224 | # Create and add buffers
225 | buffers = {}
226 | for b in self.buffers:
227 | channels = b.channels
228 |
229 | # Special case and has to do with how OpenCL
230 | # aligns vector types with n = 3
231 | if env == pygpuip.Environment.OpenCL and channels == 3:
232 | channels = 4;
233 |
234 | type = type = pygpuip.BufferType.HALF
235 | if b.type == "float":
236 | type = pygpuip.BufferType.FLOAT
237 | elif b.type == "ubyte":
238 | type = pygpuip.BufferType.UNSIGNED_BYTE
239 |
240 | buffers[b.name] = ip.CreateBuffer(b.name, type, channels)
241 |
242 | # Create kernels
243 | kernels = []
244 | for k in self.kernels:
245 | kernel = ip.CreateKernel(k.name)
246 | kernels.append(kernel)
247 |
248 | # Set buffer linking and parameters for each kernels
249 | self.updateKernels(kernels, buffers)
250 |
251 | return ip, buffers, kernels
252 |
253 | def updateKernels(self, kernels, buffers):
254 | for kernel, k in zip(kernels, self.kernels):
255 | # If no buffers were added but kernels have buffers -> error
256 | if not len(buffers) and (len(k.inBuffers) or len(k.outBuffers)):
257 | raise Exception("no buffers found")
258 |
259 | # Backup buffer if no buffer is set in kernels
260 | firstBuf = buffers.values()[0] if len(buffers) else None
261 |
262 | # Input buffers
263 | for inb in k.inBuffers:
264 | buf = buffers[inb.buffer] if inb.buffer != "" else firstBuf
265 | kernel.SetInBuffer(inb.name, buf)
266 |
267 | # Output buffers
268 | for outb in k.outBuffers:
269 | buf = buffers[outb.buffer] if outb.buffer != "" else firstBuf
270 | kernel.SetOutBuffer(outb.name, buf)
271 |
272 | # Params
273 | for p in k.params:
274 | c= pygpuip.ParamFloat if p.type == "float" else pygpuip.ParamInt
275 | kernel.SetParam(c(p.name,p.value))
276 |
277 | # Code
278 | kernel.code = k.code
279 |
280 |
--------------------------------------------------------------------------------
/python/stylesheet.py:
--------------------------------------------------------------------------------
1 | data = """
2 | QToolTip
3 | {
4 | border: 1px solid black;
5 | background-color: #ffa02f;
6 | padding: 1px;
7 | border-radius: 3px;
8 | opacity: 100;
9 | }
10 |
11 | QWidget
12 | {
13 | color: #b1b1b1;
14 | background-color: #323232;
15 | }
16 |
17 | QWidget:item:hover
18 | {
19 | background-color: QLinearGradient( x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #ffa02f, stop: 1 #ca0619);
20 | color: #000000;
21 | }
22 |
23 | QWidget:item:selected
24 | {
25 | background-color: QLinearGradient( x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #ffa02f, stop: 1 #d7801a);
26 | }
27 |
28 | QMenuBar::item
29 | {
30 | background: transparent;
31 | }
32 |
33 | QMenuBar::item:selected
34 | {
35 | background: transparent;
36 | border: 1px solid #ffaa00;
37 | }
38 |
39 | QMenuBar::item:pressed
40 | {
41 | background: #444;
42 | border: 1px solid #000;
43 | background-color: QLinearGradient(
44 | x1:0, y1:0,
45 | x2:0, y2:1,
46 | stop:1 #212121,
47 | stop:0.4 #343434/*,
48 | stop:0.2 #343434,
49 | stop:0.1 #ffaa00*/
50 | );
51 | margin-bottom:-1px;
52 | padding-bottom:1px;
53 | }
54 |
55 | QMenu
56 | {
57 | border: 1px solid #000;
58 | }
59 |
60 | QMenu::item
61 | {
62 | padding: 2px 20px 2px 20px;
63 | }
64 |
65 | QMenu::item:selected
66 | {
67 | color: #000000;
68 | }
69 |
70 | QWidget:disabled
71 | {
72 | color: #404040;
73 | background-color: #323232;
74 | }
75 |
76 | QAbstractItemView
77 | {
78 | background-color: QLinearGradient( x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #4d4d4d, stop: 0.1 #646464, stop: 1 #5d5d5d);
79 | }
80 |
81 | QWidget:focus
82 | {
83 | /*border: 2px solid QLinearGradient( x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #ffa02f, stop: 1 #d7801a);*/
84 | }
85 |
86 | QLineEdit
87 | {
88 | background-color: QLinearGradient( x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #4d4d4d, stop: 0 #646464, stop: 1 #5d5d5d);
89 | padding: 1px;
90 | border-style: solid;
91 | border: 1px solid #1e1e1e;
92 | border-radius: 5;
93 | }
94 |
95 | QPushButton
96 | {
97 | color: #b1b1b1;
98 | background-color: QLinearGradient( x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #565656, stop: 0.1 #525252, stop: 0.5 #4e4e4e, stop: 0.9 #4a4a4a, stop: 1 #464646);
99 | border-width: 1px;
100 | border-color: #1e1e1e;
101 | border-style: solid;
102 | border-radius: 6;
103 | padding: 3px;
104 | font-size: 12px;
105 | padding-left: 5px;
106 | padding-right: 5px;
107 | }
108 |
109 | QPushButton:pressed
110 | {
111 | background-color: QLinearGradient( x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #2d2d2d, stop: 0.1 #2b2b2b, stop: 0.5 #292929, stop: 0.9 #282828, stop: 1 #252525);
112 | }
113 |
114 | QComboBox
115 | {
116 | selection-background-color: #ffaa00;
117 | background-color: QLinearGradient( x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #565656, stop: 0.1 #525252, stop: 0.5 #4e4e4e, stop: 0.9 #4a4a4a, stop: 1 #464646);
118 | border-style: solid;
119 | border: 1px solid #1e1e1e;
120 | border-radius: 5;
121 | }
122 |
123 | QComboBox:hover,QPushButton:hover
124 | {
125 | border: 2px solid QLinearGradient( x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #ffa02f, stop: 1 #d7801a);
126 | }
127 |
128 |
129 | QComboBox:on
130 | {
131 | padding-top: 3px;
132 | padding-left: 4px;
133 | background-color: QLinearGradient( x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #2d2d2d, stop: 0.1 #2b2b2b, stop: 0.5 #292929, stop: 0.9 #282828, stop: 1 #252525);
134 | selection-background-color: #ffaa00;
135 | }
136 |
137 | QComboBox QAbstractItemView
138 | {
139 | border: 2px solid darkgray;
140 | selection-background-color: QLinearGradient( x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #ffa02f, stop: 1 #d7801a);
141 | }
142 |
143 | QComboBox::drop-down
144 | {
145 | subcontrol-origin: padding;
146 | subcontrol-position: top right;
147 | width: 15px;
148 |
149 | border-left-width: 0px;
150 | border-left-color: darkgray;
151 | border-left-style: solid; /* just a single line */
152 | border-top-right-radius: 3px; /* same radius as the QComboBox */
153 | border-bottom-right-radius: 3px;
154 | }
155 |
156 | QGroupBox:focus
157 | {
158 | border: 2px solid QLinearGradient( x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #ffa02f, stop: 1 #d7801a);
159 | }
160 |
161 | QTextEdit:focus
162 | {
163 | border: 2px solid QLinearGradient( x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #ffa02f, stop: 1 #d7801a);
164 | }
165 |
166 | QScrollBar:horizontal {
167 | border: 1px solid #222222;
168 | background: QLinearGradient( x1: 0, y1: 0, x2: 0, y2: 1, stop: 0.0 #121212, stop: 0.2 #282828, stop: 1 #484848);
169 | height: 7px;
170 | margin: 0px 16px 0 16px;
171 | }
172 |
173 | QScrollBar::handle:horizontal
174 | {
175 | background: QLinearGradient( x1: 0, y1: 0, x2: 1, y2: 0, stop: 0 #ffa02f, stop: 0.5 #d7801a, stop: 1 #ffa02f);
176 | min-height: 20px;
177 | border-radius: 2px;
178 | }
179 |
180 | QScrollBar::add-line:horizontal {
181 | border: 1px solid #1b1b19;
182 | border-radius: 2px;
183 | background: QLinearGradient( x1: 0, y1: 0, x2: 1, y2: 0, stop: 0 #ffa02f, stop: 1 #d7801a);
184 | width: 14px;
185 | subcontrol-position: right;
186 | subcontrol-origin: margin;
187 | }
188 |
189 | QScrollBar::sub-line:horizontal {
190 | border: 1px solid #1b1b19;
191 | border-radius: 2px;
192 | background: QLinearGradient( x1: 0, y1: 0, x2: 1, y2: 0, stop: 0 #ffa02f, stop: 1 #d7801a);
193 | width: 14px;
194 | subcontrol-position: left;
195 | subcontrol-origin: margin;
196 | }
197 |
198 | QScrollBar::right-arrow:horizontal, QScrollBar::left-arrow:horizontal
199 | {
200 | border: 1px solid black;
201 | width: 1px;
202 | height: 1px;
203 | background: white;
204 | }
205 |
206 | QScrollBar::add-page:horizontal, QScrollBar::sub-page:horizontal
207 | {
208 | background: none;
209 | }
210 |
211 | QScrollBar:vertical
212 | {
213 | background: QLinearGradient( x1: 0, y1: 0, x2: 1, y2: 0, stop: 0.0 #121212, stop: 0.2 #282828, stop: 1 #484848);
214 | width: 7px;
215 | margin: 16px 0 16px 0;
216 | border: 1px solid #222222;
217 | }
218 |
219 | QScrollBar::handle:vertical
220 | {
221 | background: QLinearGradient( x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #ffa02f, stop: 0.5 #d7801a, stop: 1 #ffa02f);
222 | min-height: 20px;
223 | border-radius: 2px;
224 | }
225 |
226 | QScrollBar::add-line:vertical
227 | {
228 | border: 1px solid #1b1b19;
229 | border-radius: 2px;
230 | background: QLinearGradient( x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #ffa02f, stop: 1 #d7801a);
231 | height: 14px;
232 | subcontrol-position: bottom;
233 | subcontrol-origin: margin;
234 | }
235 |
236 | QScrollBar::sub-line:vertical
237 | {
238 | border: 1px solid #1b1b19;
239 | border-radius: 2px;
240 | background: QLinearGradient( x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #d7801a, stop: 1 #ffa02f);
241 | height: 14px;
242 | subcontrol-position: top;
243 | subcontrol-origin: margin;
244 | }
245 |
246 | QScrollBar::up-arrow:vertical, QScrollBar::down-arrow:vertical
247 | {
248 | border: 1px solid black;
249 | width: 1px;
250 | height: 1px;
251 | background: white;
252 | }
253 |
254 |
255 | QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical
256 | {
257 | background: none;
258 | }
259 |
260 | QTextEdit
261 | {
262 | background-color: #242424;
263 | }
264 |
265 | QPlainTextEdit
266 | {
267 | background-color: #242424;
268 | }
269 |
270 | QHeaderView::section
271 | {
272 | background-color: QLinearGradient(x1:0, y1:0, x2:0, y2:1, stop:0 #616161, stop: 0.5 #505050, stop: 0.6 #434343, stop:1 #656565);
273 | color: white;
274 | padding-left: 4px;
275 | border: 1px solid #6c6c6c;
276 | }
277 |
278 |
279 | QDockWidget::title
280 | {
281 | text-align: center;
282 | spacing: 3px; /* spacing between items in the tool bar */
283 | background-color: QLinearGradient(x1:0, y1:0, x2:0, y2:1, stop:0 #323232, stop: 0.5 #242424, stop:1 #323232);
284 | }
285 |
286 | QDockWidget::close-button, QDockWidget::float-button
287 | {
288 | text-align: center;
289 | spacing: 1px; /* spacing between items in the tool bar */
290 | background-color: QLinearGradient(x1:0, y1:0, x2:0, y2:1, stop:0 #323232, stop: 0.5 #242424, stop:1 #323232);
291 | }
292 |
293 | QDockWidget::close-button:hover, QDockWidget::float-button:hover
294 | {
295 | background: #242424;
296 | }
297 |
298 | QDockWidget::close-button:pressed, QDockWidget::float-button:pressed
299 | {
300 | padding: 1px -1px -1px 1px;
301 | }
302 |
303 | QMainWindow::separator
304 | {
305 | background-color: QLinearGradient(x1:0, y1:0, x2:0, y2:1, stop:0 #161616, stop: 0.5 #151515, stop: 0.6 #212121, stop:1 #343434);
306 | color: white;
307 | padding-left: 4px;
308 | border: 1px solid #4c4c4c;
309 | spacing: 3px; /* spacing between items in the tool bar */
310 | }
311 |
312 | QMainWindow::separator:hover
313 | {
314 |
315 | background-color: QLinearGradient(x1:0, y1:0, x2:0, y2:1, stop:0 #d7801a, stop:0.5 #b56c17 stop:1 #ffa02f);
316 | color: white;
317 | padding-left: 4px;
318 | border: 1px solid #6c6c6c;
319 | spacing: 3px; /* spacing between items in the tool bar */
320 | }
321 |
322 | QMenu::separator
323 | {
324 | height: 2px;
325 | background-color: QLinearGradient(x1:0, y1:0, x2:0, y2:1, stop:0 #161616, stop: 0.5 #151515, stop: 0.6 #212121, stop:1 #343434);
326 | color: white;
327 | padding-left: 4px;
328 | margin-left: 10px;
329 | margin-right: 5px;
330 | }
331 |
332 | QProgressBar
333 | {
334 | border: 2px solid grey;
335 | border-radius: 5px;
336 | text-align: center;
337 | }
338 |
339 | QProgressBar::chunk
340 | {
341 | background-color: #d7801a;
342 | width: 2.15px;
343 | margin: 0.5px;
344 | }
345 |
346 | QTabBar::tab {
347 | color: #b1b1b1;
348 | border: 1px solid #444;
349 | border-bottom-style: none;
350 | background-color: #323232;
351 | padding-left: 10px;
352 | padding-right: 10px;
353 | padding-top: 3px;
354 | padding-bottom: 2px;
355 | margin-right: -1px;
356 | }
357 |
358 | QTabWidget::pane {
359 | border: 1px solid #444;
360 | top: 1px;
361 | }
362 |
363 | QTabBar::tab:last
364 | {
365 | margin-right: 0; /* the last selected tab has nothing to overlap with on the right */
366 | border-top-right-radius: 3px;
367 | }
368 |
369 | QTabBar::tab:first:!selected
370 | {
371 | margin-left: 0px; /* the last selected tab has nothing to overlap with on the right */
372 |
373 |
374 | border-top-left-radius: 3px;
375 | }
376 |
377 | QTabBar::tab:!selected
378 | {
379 | color: #b1b1b1;
380 | border-bottom-style: solid;
381 | margin-top: 3px;
382 | background-color: QLinearGradient(x1:0, y1:0, x2:0, y2:1, stop:1 #212121, stop:.4 #343434);
383 | }
384 |
385 | QTabBar::tab:selected
386 | {
387 | border-top-left-radius: 3px;
388 | border-top-right-radius: 3px;
389 | margin-bottom: 0px;
390 | }
391 |
392 | QTabBar::tab:!selected:hover
393 | {
394 | /*border-top: 2px solid #ffaa00;
395 | padding-bottom: 3px;*/
396 | border-top-left-radius: 3px;
397 | border-top-right-radius: 3px;
398 | background-color: QLinearGradient(x1:0, y1:0, x2:0, y2:1, stop:1 #212121, stop:0.4 #343434, stop:0.2 #343434, stop:0.1 #ffaa00);
399 | }
400 |
401 | QRadioButton::indicator:checked, QRadioButton::indicator:unchecked{
402 | color: #b1b1b1;
403 | background-color: #323232;
404 | border: 1px solid #b1b1b1;
405 | border-radius: 6px;
406 | }
407 |
408 | QRadioButton::indicator:checked
409 | {
410 | background-color: qradialgradient(
411 | cx: 0.5, cy: 0.5,
412 | fx: 0.5, fy: 0.5,
413 | radius: 1.0,
414 | stop: 0.25 #ffaa00,
415 | stop: 0.3 #323232
416 | );
417 | }
418 |
419 |
420 |
421 | QRadioButton::indicator
422 | {
423 | border-radius: 6px;
424 | }
425 | """
426 |
--------------------------------------------------------------------------------
/python/utils.py:
--------------------------------------------------------------------------------
1 | import pygpuip
2 | import numpy
3 | from time import gmtime, strftime, time
4 |
5 | class StopWatch(object):
6 | def __init__(self):
7 | self.t = time()
8 |
9 | def __str__(self):
10 | return "%.2f" %((time() - self.t) * 1000.0) + " ms"
11 |
12 | def allocateBufferData(buffers):
13 | maxw, maxh = 0,0
14 | for bname in buffers:
15 | buf = buffers[bname]
16 | maxw = max(buf.data.shape[0], maxw)
17 | maxh = max(buf.data.shape[1], maxh)
18 |
19 | for bname in buffers:
20 | buf = buffers[bname]
21 | if buf.data.shape[0] != maxw or buf.data.shape[1] != maxh:
22 | if buf.type == pygpuip.BufferType.UNSIGNED_BYTE:
23 | ndtype = numpy.ubyte
24 | elif buf.type == pygpuip.BufferType.HALF:
25 | ndtype = numpy.float16
26 | elif buf.type == pygpuip.BufferType.FLOAT:
27 | ndtype = numpy.float32
28 | elif buf.type == pygpuip.BufferType.DOUBLE:
29 | ndtype = numpy.float64
30 | buf.data = numpy.zeros((maxw, maxh, buf.channels), dtype = ndtype)
31 |
32 | return maxw, maxh
33 |
34 | def getNumCores():
35 | import multiprocessing
36 | return multiprocessing.cpu_count()
37 |
38 | def getTimeStr():
39 | return str(strftime("[%Y-%m-%d %H:%M:%S] ", gmtime()))
40 |
41 | def safeEval(text, fallback = 0.0, type = "float"):
42 | try:
43 | val = eval(text)
44 | return int(val) if type == "int" else val
45 | except SyntaxError:
46 | return int(fallback) if type == "int" else fallback
47 |
48 |
--------------------------------------------------------------------------------
/src/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | # The MIT License (MIT)
2 | #
3 | # Copyright (c) 2014 Per Karlsson
4 | #
5 | # Permission is hereby granted, free of charge, to any person obtaining a copy
6 | # of this software and associated documentation files (the "Software"), to deal
7 | # in the Software without restriction, including without limitation the rights
8 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | # copies of the Software, and to permit persons to whom the Software is
10 | # furnished to do so, subject to the following conditions:
11 | #
12 | # The above copyright notice and this permission notice shall be included in all
13 | # copies or substantial portions of the Software.
14 | #
15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | # SOFTWARE.
22 |
23 | project(gpuip_src)
24 |
25 | if(NOT WIN32)
26 | add_definitions(-Wall)
27 | add_definitions(-fPIC)
28 | add_definitions(-O3)
29 | endif()
30 |
31 | # Common variables for compling the library
32 | set(SOURCE gpuip)
33 |
34 | # Build with OpenCL
35 | if(OpenCL_FOUND AND BUILD_WITH_OPENCL)
36 | add_definitions(-D_GPUIP_OPENCL)
37 | set(SOURCE ${SOURCE} opencl)
38 | endif()
39 |
40 | # Build with CUDA
41 | if(CUDA_FOUND AND BUILD_WITH_CUDA)
42 | add_definitions(-D_GPUIP_CUDA)
43 | set(SOURCE ${SOURCE} cuda)
44 | endif()
45 |
46 | # Build with GLSL (needs OpenGL)
47 | if(OPENGL_FOUND AND BUILD_WITH_GLSL)
48 | add_definitions(-D_GPUIP_GLSL)
49 | set(SOURCE ${SOURCE} glsl)
50 | if(APPLE)
51 | set(SOURCE ${SOURCE} glcontext.m)
52 | endif()
53 | endif()
54 |
55 | # Build the gpuip library
56 | if(BUILD_SHARED_LIB)
57 | set(LIBRARY_TYPE SHARED)
58 | else()
59 | set(LIBRARY_TYPE STATIC)
60 | endif()
61 | add_definitions(-DGPUIP_VERSION=${GPUIP_VERSION})
62 | add_library(gpuip ${LIBRARY_TYPE} ${SOURCE})
63 | target_link_libraries(gpuip ${GPUIP_LIBRARIES})
64 | install(TARGETS gpuip DESTINATION lib COMPONENT devel)
65 | install(FILES gpuip.h DESTINATION include COMPONENT devel)
66 | if (THIRD_PARTY_TARGETS)
67 | add_dependencies(gpuip ${THIRD_PARTY_TARGETS})
68 | endif()
69 |
70 | # Build python bindings (using boost python)
71 | if(BUILD_PYTHON_BINDINGS)
72 | add_library(pygpuip SHARED python.cpp io_wrapper.cpp)
73 | target_link_libraries(pygpuip gpuip ${GPUIP_PYTHON_LIBRARIES})
74 |
75 | # Rename python shared lib from libpyGpuip.{so,lib} to pyGpuip.{so,pyd}
76 | set_target_properties(pygpuip PROPERTIES PREFIX "")
77 | if(WIN32)
78 | set_target_properties(pygpuip PROPERTIES SUFFIX ".pyd")
79 | else()
80 | set_target_properties(pygpuip PROPERTIES SUFFIX ".so")
81 | endif()
82 |
83 | # Install python bindings in the python site-packages
84 | execute_process(COMMAND
85 | ${PYTHON_EXECUTABLE} -c
86 | "from distutils.sysconfig import get_python_lib; print get_python_lib()"
87 | OUTPUT_VARIABLE PYTHON_SITE_PACKAGES OUTPUT_STRIP_TRAILING_WHITESPACE)
88 | install(TARGETS pygpuip DESTINATION ${PYTHON_SITE_PACKAGES} COMPONENT python)
89 | endif()
90 |
91 |
92 |
93 |
--------------------------------------------------------------------------------
/src/cuda.h:
--------------------------------------------------------------------------------
1 | /*
2 | The MIT License (MIT)
3 |
4 | Copyright (c) 2014 Per Karlsson
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a copy
7 | of this software and associated documentation files (the "Software"), to deal
8 | in the Software without restriction, including without limitation the rights
9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | copies of the Software, and to permit persons to whom the Software is
11 | furnished to do so, subject to the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be included in all
14 | copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | SOFTWARE.
23 | */
24 |
25 | #ifndef GPUIP_CUDA_H_
26 | #define GPUIP_CUDA_H_
27 | //----------------------------------------------------------------------------//
28 | #include "gpuip.h"
29 | #include
30 | #include
31 | //----------------------------------------------------------------------------//
32 | namespace gpuip {
33 | //----------------------------------------------------------------------------//
34 | class CUDAImpl : public ImageProcessor
35 | {
36 | public:
37 | CUDAImpl();
38 |
39 | virtual ~CUDAImpl();
40 |
41 | virtual double Allocate(std::string * err);
42 |
43 | virtual double Build(std::string * err);
44 |
45 | virtual double Run(std::string * err);
46 |
47 | virtual double Copy(Buffer::Ptr buffer,
48 | Buffer::CopyOperation op,
49 | void * data,
50 | std::string * err);
51 |
52 | virtual std::string BoilerplateCode(Kernel::Ptr kernel) const;
53 |
54 | protected:
55 | std::vector _cudaKernels;
56 | bool _cudaBuild;
57 | CUmodule _cudaModule;
58 | cudaEvent_t _start,_stop;
59 | std::map _cudaBuffers;
60 |
61 | bool _LaunchKernel(Kernel & kernel,
62 | const CUfunction & cudaKernel,
63 | std::string * err);
64 |
65 | void _StartTimer();
66 |
67 | double _StopTimer();
68 |
69 | bool _FreeBuffers(std::string * err);
70 |
71 | bool _UnloadModule(std::string * err);
72 | };
73 | //----------------------------------------------------------------------------//
74 | } // end namespace gpuip
75 |
76 | #endif
77 |
--------------------------------------------------------------------------------
/src/cuda_error.h:
--------------------------------------------------------------------------------
1 | /*
2 | The MIT License (MIT)
3 |
4 | Copyright (c) 2014 Per Karlsson
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a copy
7 | of this software and associated documentation files (the "Software"), to deal
8 | in the Software without restriction, including without limitation the rights
9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | copies of the Software, and to permit persons to whom the Software is
11 | furnished to do so, subject to the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be included in all
14 | copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | SOFTWARE.
23 | */
24 |
25 | #ifndef GPUIP_CUDA_ERROR_H_
26 | #define GPUIP_CUDA_ERROR_H_
27 | //----------------------------------------------------------------------------//
28 | #include
29 | //----------------------------------------------------------------------------//
30 | namespace gpuip {
31 | //----------------------------------------------------------------------------//
32 | inline bool _cudaErrorGetFunction(CUresult c_err, std::string * err,
33 | const std::string & kernel_name)
34 | {
35 | if (c_err != CUDA_SUCCESS) {
36 | (*err) += "Cuda: Error, could not find kernel named ";
37 | (*err) += kernel_name;
38 | (*err) += "\n";
39 | switch(c_err) {
40 | //TODO: add cases here
41 | default:
42 | break;
43 | }
44 | return true;
45 | }
46 | return false;
47 | }
48 | //----------------------------------------------------------------------------//
49 | inline bool _cudaErrorMalloc(cudaError_t c_err, std::string * err)
50 | {
51 | if (c_err != cudaSuccess) {
52 | (*err) += "Cuda: error when allocating buffers\n";
53 | switch(c_err) {
54 | //TODO: add cases here
55 | default:
56 | break;
57 | }
58 | return true;
59 | }
60 | return false;
61 | }
62 | //----------------------------------------------------------------------------//
63 | inline bool _cudaErrorFree(cudaError_t c_err, std::string * err)
64 | {
65 | if (c_err != cudaSuccess) {
66 | (*err) += "Cuda: error when releasing buffers\n";
67 | switch(c_err) {
68 | //TODO: add cases here
69 | default:
70 | break;
71 | }
72 | return true;
73 | }
74 | return false;
75 | }
76 | //----------------------------------------------------------------------------//
77 | inline bool _cudaErrorCopy(cudaError_t c_err, std::string * err,
78 | const std::string & buffer, Buffer::CopyOperation op)
79 | {
80 | if (c_err != cudaSuccess) {
81 | (*err) += "CUDA: error when copying data ";
82 | (*err) += op == Buffer::COPY_FROM_GPU ? "FROM" : "TO";
83 | (*err) += " buffer ";
84 | (*err) += buffer;
85 | switch(c_err) {
86 | case cudaErrorInvalidValue:
87 | (*err) += ". Invalid value.\n";
88 | break;
89 | case cudaErrorInvalidDevicePointer:
90 | (*err) += ". Invalid device pointer.\n";
91 | break;
92 | case cudaErrorInvalidMemcpyDirection:
93 | (*err) += ". Invalid Memcpy direction.\n";
94 | break;
95 | case cudaErrorIllegalAddress:
96 | (*err) += ". Illegal address.\n";
97 | break;
98 | //TODO: add cases here
99 | default: {
100 | (*err) += ". Unknown error enum: ";
101 | std::stringstream ss;
102 | ss << c_err << std::endl;
103 | (*err) += ss.str();
104 | }
105 | }
106 | return true;
107 | }
108 | return false;
109 | }
110 | //----------------------------------------------------------------------------//
111 | inline bool _cudaErrorUnloadModule(CUresult c_err, std::string * err)
112 | {
113 | if (c_err != CUDA_SUCCESS) {
114 | (*err) += "Cuda: Error, could not unload module\n";
115 | switch(c_err) {
116 | //TODO: add cases here
117 | default:
118 | break;
119 | }
120 | return true;
121 | }
122 | return false;
123 | }
124 | //----------------------------------------------------------------------------//
125 | inline bool _cudaErrorLoadModule(CUresult c_err, std::string * err)
126 | {
127 | if (c_err != CUDA_SUCCESS) {
128 | (*err) += "Cuda: Error, could not load module\n";
129 | switch(c_err) {
130 | //TODO: add cases here
131 | default:
132 | break;
133 | }
134 | return true;
135 | }
136 | return false;
137 | }
138 | //----------------------------------------------------------------------------//
139 | inline bool _cudaErrorCheckParamSet(CUresult c_err, std::string * err,
140 | const std::string & kernel_name)
141 | {
142 | if (c_err != CUDA_SUCCESS) {
143 | (*err) += "Cuda: Error, could not set arguments for kernel named ";
144 | (*err) += kernel_name;
145 | (*err) += "\n";
146 | switch(c_err) {
147 | //TODO: add cases here
148 | default:
149 | break;
150 | }
151 | return true;
152 | }
153 | return false;
154 | }
155 | //----------------------------------------------------------------------------//
156 | inline bool _cudaErrorParamSetSize(CUresult c_err, std::string * err,
157 | const std::string & kernel_name)
158 | {
159 | if (c_err != CUDA_SUCCESS) {
160 | (*err) += "Cuda: Error, could not set arguments size for kernel named ";
161 | (*err) += kernel_name;
162 | (*err) += "\n";
163 | switch(c_err) {
164 | //TODO: add cases here
165 | default:
166 | break;
167 | }
168 | return true;
169 | }
170 | return false;
171 | }
172 | //----------------------------------------------------------------------------//
173 | inline bool _cudaErrorLaunchKernel(CUresult c_err, std::string * err,
174 | const std::string & kernel_name)
175 | {
176 | if (c_err != CUDA_SUCCESS) {
177 | (*err) += "Cuda: Error, could not launch kernel ";
178 | (*err) += kernel_name;
179 | (*err) += "\n";
180 | switch(c_err) {
181 | //TODO: add cases here
182 | default:
183 | break;
184 | }
185 | return true;
186 | }
187 | return false;
188 | }
189 | //----------------------------------------------------------------------------//
190 | } // end namespace gpuip
191 | //----------------------------------------------------------------------------//
192 | #endif
193 |
--------------------------------------------------------------------------------
/src/glcontext.h:
--------------------------------------------------------------------------------
1 | /*
2 | The MIT License (MIT)
3 |
4 | Copyright (c) 2014 Per Karlsson
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a copy
7 | of this software and associated documentation files (the "Software"), to deal
8 | in the Software without restriction, including without limitation the rights
9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | copies of the Software, and to permit persons to whom the Software is
11 | furnished to do so, subject to the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be included in all
14 | copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | SOFTWARE.
23 | */
24 |
25 | #ifndef GPUIP_GL_CONTEXT_H_
26 | #define GPUIP_GL_CONTEXT_H_
27 |
28 | #ifdef __APPLE__
29 | extern "C" {
30 | bool _HasNSGLContext();
31 | }
32 | #else
33 | # ifdef _WIN32
34 | # include
35 | # include
36 | # else
37 | # include
38 | # endif
39 | #endif
40 | #include
41 | #include
42 |
43 | //----------------------------------------------------------------------------//
44 | namespace gpuip {
45 | //----------------------------------------------------------------------------//
46 | class GLContext
47 | {
48 | public:
49 | static bool Exists()
50 | {
51 | #ifdef __APPLE__
52 | if (_HasNSGLContext()) {
53 | return true;
54 | }
55 | #else
56 | # ifdef _WIN32
57 | if (wglGetCurrentContext()) {
58 | return true;
59 | }
60 | # else
61 | if (glXGetCurrentContext()) {
62 | return true;
63 | }
64 | # endif
65 | #endif
66 | return false;
67 | }
68 |
69 | static bool Create(std::string * err)
70 | {
71 | if (!glfwInit()) {
72 | (*err) += "gpuip could not initiate GLFW";
73 | return false;
74 | }
75 | GLFWwindow * window = glfwCreateWindow(1, 1, "", NULL, NULL);
76 | if (!window) {
77 | (*err) += "gpuip could not create window with glfw";
78 | return false;
79 | }
80 | glfwMakeContextCurrent(window);
81 | return true;
82 | }
83 |
84 | static void Delete()
85 | {
86 | if(glfwGetCurrentContext()) {
87 | glfwTerminate();
88 | }
89 | }
90 | };
91 | //----------------------------------------------------------------------------//
92 | }// end namespace gpuip
93 |
94 | #endif
95 |
--------------------------------------------------------------------------------
/src/glcontext.m:
--------------------------------------------------------------------------------
1 | /*
2 | The MIT License (MIT)
3 |
4 | Copyright (c) 2014 Per Karlsson
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a copy
7 | of this software and associated documentation files (the "Software"), to deal
8 | in the Software without restriction, including without limitation the rights
9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | copies of the Software, and to permit persons to whom the Software is
11 | furnished to do so, subject to the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be included in all
14 | copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | SOFTWARE.
23 | */
24 |
25 | #if defined(__OBJC__)
26 | #import
27 | #else
28 | #error "No objective C found"
29 | #endif
30 | //----------------------------------------------------------------------------//
31 | bool _HasNSGLContext()
32 | {
33 | NSOpenGLContext* context = [NSOpenGLContext currentContext];
34 | if (context) {
35 | return true;
36 | } else {
37 | return false;
38 | }
39 | }
40 | //----------------------------------------------------------------------------//
41 |
--------------------------------------------------------------------------------
/src/glsl.h:
--------------------------------------------------------------------------------
1 | /*
2 | The MIT License (MIT)
3 |
4 | Copyright (c) 2014 Per Karlsson
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a copy
7 | of this software and associated documentation files (the "Software"), to deal
8 | in the Software without restriction, including without limitation the rights
9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | copies of the Software, and to permit persons to whom the Software is
11 | furnished to do so, subject to the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be included in all
14 | copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | SOFTWARE.
23 | */
24 |
25 | #ifndef GPUIP_GLSL_H_
26 | #define GPUIP_GLSL_H_
27 | //----------------------------------------------------------------------------//
28 | #include "gpuip.h"
29 | #include
30 | //----------------------------------------------------------------------------//
31 | namespace gpuip {
32 | //----------------------------------------------------------------------------//
33 | class GLSLImpl : public ImageProcessor
34 | {
35 | public:
36 | GLSLImpl();
37 |
38 | virtual ~GLSLImpl();
39 |
40 | virtual double Allocate(std::string * err);
41 |
42 | virtual double Build(std::string * err);
43 |
44 | virtual double Run(std::string * err);
45 |
46 | virtual double Copy(Buffer::Ptr buffer,
47 | Buffer::CopyOperation op,
48 | void * data,
49 | std::string * err);
50 |
51 | virtual std::string BoilerplateCode(Kernel::Ptr kernel) const;
52 |
53 | protected:
54 | bool _glewInit;
55 | bool _glContextCreated;
56 | GLint64 _timer;
57 | GLuint _vbo;
58 | GLuint _rboId;
59 | GLuint _vertexShaderID;
60 | std::vector _fbos;
61 | std::vector _programs;
62 | std::map _textures;
63 |
64 | bool _DrawQuad(const Kernel & kernel,
65 | GLuint fbo,
66 | GLuint program,
67 | std::string * error);
68 |
69 | bool _InitGLEW(std::string * err);
70 |
71 | void _StartTimer();
72 |
73 | double _StopTimer();
74 |
75 | void _DeleteBuffers();
76 | };
77 | //----------------------------------------------------------------------------//
78 | } // end namespace gpuip
79 | //----------------------------------------------------------------------------//
80 | #endif
81 |
--------------------------------------------------------------------------------
/src/glsl_error.h:
--------------------------------------------------------------------------------
1 | /*
2 | The MIT License (MIT)
3 |
4 | Copyright (c) 2014 Per Karlsson
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a copy
7 | of this software and associated documentation files (the "Software"), to deal
8 | in the Software without restriction, including without limitation the rights
9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | copies of the Software, and to permit persons to whom the Software is
11 | furnished to do so, subject to the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be included in all
14 | copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | SOFTWARE.
23 | */
24 |
25 | #ifndef GPUIP_OPENCL_ERROR_H_
26 | #define GPUIP_OPENCL_ERROR_H_
27 | //----------------------------------------------------------------------------//
28 | #include
29 | //----------------------------------------------------------------------------//
30 | namespace gpuip {
31 | //----------------------------------------------------------------------------//
32 | inline std::string _glErrorToString(GLenum error)
33 | {
34 | std::stringstream ss;
35 | //deprecated in mac os
36 | #ifndef __APPLE__
37 | const GLubyte * errLog = gluErrorString(error);
38 | ss << errLog;
39 | #endif
40 | return ss.str();
41 | }
42 | //----------------------------------------------------------------------------//
43 | inline bool _glCheckBuildError(GLuint shader,
44 | GLuint vert_shader,
45 | GLuint frag_shader,
46 | std::string * err)
47 | {
48 | GLint gl_err;
49 | glGetProgramiv(shader, GL_LINK_STATUS, &gl_err);
50 | if (gl_err == 0) {
51 | std::stringstream ss;
52 | #define ERROR_BUFSIZE 1024
53 | GLchar errorLog[ERROR_BUFSIZE];
54 | GLsizei length;
55 |
56 | ss << "GLSL build error.\n";
57 |
58 | glGetShaderInfoLog(vert_shader, ERROR_BUFSIZE, &length, errorLog);
59 | ss << "Vertex shader errors:\n" << std::string(errorLog, length);
60 |
61 | glGetShaderInfoLog(frag_shader, ERROR_BUFSIZE, &length, errorLog);
62 | ss << "\nFragment shader errors:\n" << std::string(errorLog, length);
63 |
64 | glGetShaderInfoLog(shader, ERROR_BUFSIZE, &length, errorLog);
65 | ss << "\nLinker errors:\n" << std::string(errorLog, length);
66 |
67 | (*err) += ss.str();
68 |
69 | return true;
70 | }
71 | return false;
72 | }
73 | //----------------------------------------------------------------------------//
74 | inline bool _glErrorFramebuffer(std::string * err)
75 | {
76 | GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
77 | if(status != GL_FRAMEBUFFER_COMPLETE) {
78 | (*err) += "GLSL error: Framebuffer error. ";
79 | switch(status) {
80 | case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
81 | (*err) += "At least one attachment point with a renderbuffer "
82 | "or texture attached has its attached object no longer "
83 | "in existence or has an attached image with a width or "
84 | "height of zero.\n";
85 | break;
86 | // This enum doesn't exist in older OpenGL versions.
87 | //case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS:
88 | // (*err) += "Not all attached images have the same width and "
89 | // "height.\n";
90 | // break;
91 | case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
92 | (*err) += "No images are attached to the framebuffer.\n";
93 | case GL_FRAMEBUFFER_UNSUPPORTED:
94 | (*err) += "The combination of internal formats of the attached "
95 | "images violates an implementation-dependent set of "
96 | "restrictions.\n";
97 | break;
98 | default:
99 | break;
100 | };
101 |
102 |
103 | return true;
104 | }
105 | return false;
106 | }
107 | //----------------------------------------------------------------------------//
108 | inline bool _glErrorCreateTexture(std::string * err)
109 | {
110 | GLenum gl_err = glGetError();
111 | if (gl_err != GL_NO_ERROR) {
112 | (*err) += "GLSL error when creating textures.\n";
113 | (*err) += _glErrorToString(gl_err);
114 | return true;
115 | };
116 | return false;
117 | }
118 | //----------------------------------------------------------------------------//
119 | inline bool _glErrorDrawSetup(std::string * err,
120 | const std::string & kernel_name)
121 | {
122 | GLenum gl_err = glGetError();
123 | if (gl_err != GL_NO_ERROR) {
124 | (*err) += "GLSL error in setup for kernel: ";
125 | (*err) += kernel_name;
126 | (*err) += "\n";
127 | (*err) += _glErrorToString(gl_err);
128 | return true;
129 | };
130 | return false;
131 | }
132 | //----------------------------------------------------------------------------//
133 | inline bool _glErrorDraw(std::string * err, const std::string & kernel_name)
134 | {
135 | GLenum gl_err = glGetError();
136 | if (gl_err != GL_NO_ERROR) {
137 | (*err) += "GLSL error when drawing kernel:";
138 | (*err) += kernel_name;
139 | (*err) += "\n";
140 | (*err) += _glErrorToString(gl_err);
141 | return true;
142 | };
143 | return false;
144 | }
145 | //----------------------------------------------------------------------------//
146 | inline bool _glErrorCopy(std::string * err,
147 | const std::string & buffer,
148 | Buffer::CopyOperation op)
149 | {
150 | GLenum gl_err = glGetError();
151 | if (gl_err != GL_NO_ERROR) {
152 | (*err) += "GLSL: error when copying data ";
153 | (*err) += op == Buffer::COPY_FROM_GPU ? "FROM" : "TO";
154 | (*err) += " buffer ";
155 | (*err) += buffer;
156 | (*err) += "\n";
157 | (*err) += _glErrorToString(gl_err);
158 | return true;
159 | }
160 | return false;
161 | }
162 |
163 | } // end namespace gpuip
164 | //----------------------------------------------------------------------------//
165 | #endif
166 |
--------------------------------------------------------------------------------
/src/gpuip.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | The MIT License (MIT)
3 |
4 | Copyright (c) 2014 Per Karlsson
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a copy
7 | of this software and associated documentation files (the "Software"), to deal
8 | in the Software without restriction, including without limitation the rights
9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | copies of the Software, and to permit persons to whom the Software is
11 | furnished to do so, subject to the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be included in all
14 | copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | SOFTWARE.
23 | */
24 |
25 | #include "gpuip.h"
26 | //----------------------------------------------------------------------------//
27 | #ifdef _GPUIP_OPENCL
28 | #include "opencl.h"
29 | #endif
30 | //----------------------------------------------------------------------------//
31 | #ifdef _GPUIP_CUDA
32 | #include "cuda.h"
33 | #endif
34 | //----------------------------------------------------------------------------//
35 | #ifdef _GPUIP_GLSL
36 | #include "glsl.h"
37 | #endif
38 | //----------------------------------------------------------------------------//
39 | namespace gpuip {
40 | //----------------------------------------------------------------------------//
41 | ImageProcessor::Ptr ImageProcessor::Create(GpuEnvironment env)
42 | {
43 | switch(env) {
44 | case OpenCL:
45 | #ifdef _GPUIP_OPENCL
46 | return ImageProcessor::Ptr(new OpenCLImpl());
47 | #else
48 | throw std::logic_error("gpuip was not built with OpenCL");
49 | #endif
50 | case CUDA:
51 | #ifdef _GPUIP_CUDA
52 | return ImageProcessor::Ptr(new CUDAImpl());
53 | #else
54 | throw std::logic_error("gpuip was not built with CUDA");
55 | #endif
56 | case GLSL:
57 | #ifdef _GPUIP_GLSL
58 | return ImageProcessor::Ptr(new GLSLImpl());
59 | #else
60 | throw std::logic_error("gpuip was not built with GLSL");
61 | #endif
62 | default:
63 | std::cerr << "gpuip error: Could not create env" << std::endl;
64 | return ImageProcessor::Ptr();
65 | }
66 | }
67 | //----------------------------------------------------------------------------//
68 | bool ImageProcessor::CanCreate(GpuEnvironment env)
69 | {
70 | switch(env) {
71 | case OpenCL:
72 | #ifdef _GPUIP_OPENCL
73 | return true;
74 | #else
75 | return false;
76 | #endif
77 | case CUDA:
78 | #ifdef _GPUIP_CUDA
79 | return true;
80 | #else
81 | return false;
82 | #endif
83 | case GLSL:
84 | #ifdef _GPUIP_GLSL
85 | return true;
86 | #else
87 | return false;
88 | #endif
89 | default:
90 | return false;
91 | }
92 | }
93 | //----------------------------------------------------------------------------//
94 | Buffer::Buffer(const std::string & name_, Type type_, unsigned int channels_)
95 | : name(name_), type(type_), channels(channels_)
96 | {
97 | }
98 | //----------------------------------------------------------------------------//
99 | Kernel::Kernel(const std::string & name_)
100 | : name(name_)
101 | {
102 | }
103 | //----------------------------------------------------------------------------//
104 | Kernel::BufferLink::BufferLink(Buffer::Ptr buffer_, const std::string & name_)
105 | : buffer(buffer_), name(name_)
106 | {
107 | }
108 | //----------------------------------------------------------------------------//
109 | ImageProcessor::ImageProcessor(GpuEnvironment env)
110 | : _env(env), _w(0), _h(0)
111 | {
112 |
113 | }
114 | //----------------------------------------------------------------------------//
115 | Buffer::Ptr
116 | ImageProcessor::CreateBuffer(const std::string & name,
117 | Buffer::Type type,
118 | unsigned int channels)
119 | {
120 | if (_buffers.find(name) == _buffers.end()) {
121 | Buffer::Ptr p = Buffer::Ptr(new Buffer(name, type, channels));
122 | _buffers[name] = p;
123 | return p;
124 | } else {
125 | std::cerr << "gpuip error: Buffer named " << name
126 | << " already exists. Skipping..." << std::endl;
127 | return Buffer::Ptr(new Buffer(name, type, channels));
128 | }
129 | }
130 | //----------------------------------------------------------------------------//
131 | Kernel::Ptr ImageProcessor::CreateKernel(const std::string & name)
132 | {
133 | _kernels.push_back(Kernel::Ptr(new Kernel(name)));
134 | return _kernels.back();
135 | }
136 | //----------------------------------------------------------------------------//
137 | void ImageProcessor::SetDimensions(unsigned int width, unsigned int height)
138 | {
139 | _w = width;
140 | _h = height;
141 | }
142 | //----------------------------------------------------------------------------//
143 | double ImageProcessor::Allocate(std::string * error)
144 | {
145 | throw std::logic_error("'Allocate' not implemented in subclass");
146 | }
147 | //----------------------------------------------------------------------------//
148 | double ImageProcessor::Build(std::string * error)
149 | {
150 | throw std::logic_error("'Build' not implemented in subclass");
151 | }
152 | //----------------------------------------------------------------------------//
153 | double ImageProcessor::Run(std::string * error)
154 | {
155 | throw std::logic_error("'Run' not implemented in subclass");
156 | }
157 | //----------------------------------------------------------------------------//
158 | double ImageProcessor::Copy(Buffer::Ptr buffer,
159 | Buffer::CopyOperation operation,
160 | void * data,
161 | std::string * error)
162 | {
163 | throw std::logic_error("'Copy' not implemented in subclass");
164 | }
165 | //----------------------------------------------------------------------------//
166 | std::string ImageProcessor::BoilerplateCode(Kernel::Ptr kernel) const
167 | {
168 | throw std::logic_error("'BoilerplateCode' not implemented in subclass");
169 | }
170 | //----------------------------------------------------------------------------//
171 | unsigned int ImageProcessor::_BufferSize(Buffer::Ptr buffer) const
172 | {
173 | unsigned int bpp = 0; // bytes per pixel
174 | switch(buffer->type) {
175 | case Buffer::UNSIGNED_BYTE:
176 | bpp = buffer->channels;
177 | break;
178 | case Buffer::HALF:
179 | bpp = sizeof(float)/2 * buffer->channels;
180 | break;
181 | case Buffer::FLOAT:
182 | bpp = sizeof(float) * buffer->channels;
183 | break;
184 | }
185 | return bpp * _w * _h;
186 | }
187 | //----------------------------------------------------------------------------//
188 | } // end namespace gpuip
189 | //----------------------------------------------------------------------------//
190 |
--------------------------------------------------------------------------------
/src/gpuip.h:
--------------------------------------------------------------------------------
1 | /*
2 | The MIT License (MIT)
3 |
4 | Copyright (c) 2014 Per Karlsson
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a copy
7 | of this software and associated documentation files (the "Software"), to deal
8 | in the Software without restriction, including without limitation the rights
9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | copies of the Software, and to permit persons to whom the Software is
11 | furnished to do so, subject to the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be included in all
14 | copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | SOFTWARE.
23 | */
24 |
25 | #ifndef GPUIP_H_
26 | #define GPUIP_H_
27 | //----------------------------------------------------------------------------//
28 | #include
29 | #include