diff --git a/CMakeLists.txt b/CMakeLists.txt
index 62c0e59..96b8d63 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -92,10 +92,12 @@ list(SORT sources)
source_group(Headers FILES ${headers})
source_group(Sources FILES ${sources})
-#add_subdirectory(stream_compaction) # TODO: uncomment if using your stream compaction
+add_subdirectory(stream_compaction)
+add_subdirectory(oidn) # TODO: uncomment if using your stream compaction
cuda_add_executable(${CMAKE_PROJECT_NAME} ${sources} ${headers})
target_link_libraries(${CMAKE_PROJECT_NAME}
${LIBRARIES}
- #stream_compaction # TODO: uncomment if using your stream compaction
+ stream_compaction # TODO: uncomment if using your stream compaction
+ OpenImageDenoise
)
diff --git a/README.md b/README.md
index 110697c..c339ec0 100644
--- a/README.md
+++ b/README.md
@@ -3,11 +3,165 @@ CUDA Path Tracer
**University of Pennsylvania, CIS 565: GPU Programming and Architecture, Project 3**
-* (TODO) YOUR NAME HERE
-* Tested on: (TODO) Windows 22, i7-2222 @ 2.22GHz 22GB, GTX 222 222MB (Moore 2222 Lab)
+* Dewang Sultania
+ * [LinkedIn](https://www.linkedin.com/in/dewang-sultania/)
+* Tested on: Windows 10, Intel Xeon E-2176M @ 2.70GHz 16GB, Quadro P2000 4GB (Personal Computer)
-### (TODO: Your README)
+
-*DO NOT* leave the README to the last minute! It is a crucial part of the
-project, and we will not be able to grade you without a good README.
+### Table of Contents
+1. [Overview](#overview)
+2. [Graphics Features](#graphics)
+ 1. [Diffusion](#diffusion)
+ 2. [Reflection](#reflection)
+ 3. [Refraction with Fresnel effects using Schlick's approximation](#refraction)
+ 4. [Anti Aliasing](#anti-alias)
+ 5. [Motion Blur](#motion-blur)
+ 6. [Open Image AI Denoiser](#denoiser)
+3. [Optimization Features](#optimization)
+ 1. [Stream Compaction](#stream)
+ 2. [Material Sorting](#material-sort)
+ 3. [Cache First Bounce](#cache)
+4. [References](#references)
+
+
+
+## Overview
+
+This repository contains code for GPU implementation of a Monte-Carlo Path Tracer. It is a rendering technique for generating an image by tracing the path of light as pixel in an image plane and simulating the effects of its encounters with virtual objects. The technique is capable of producing a very high degree of visual realism, usually higher than that of typical scanline rendering methods, but at a greater computational cost. This makes ray tracing best suited for applications where taking a relatively long time to render a frame can be tolerated, such as in still images and film and television visual effects, and more poorly suited for real-time applications such as video games where speed is critical. Ray tracing is capable of simulating a wide variety of optical effects, such as reflection and refraction, scattering, and dispersion phenomena (such as chromatic aberration).
+
+
+
+
+
+## Graphics Features
+
+This section contains description and results of the graphics features that were implemented.
+
+
+
+#### Diffusion
+
+Diffuse Shading is obtained using a cosine-weighted sampling function. It basically means that the incident light is uniformly scattered in all directions.
+
+
+
+#### Reflection
+
+Reflection is implemented using glm::reflect.
+
+
+
+
+
+#### Refraction with Fresnel effects using Schlick's approximation
+
+
+
+
+Refraction was implemented using glm::refract and there is also a toggle for if we want to use Schlick's approximation. Special Case of total internal reflection was also handled.
+
+Without Schlick's approximation | With Schlick's approximation
+:-------------------------:|:-------------------------:
+ | 
+
+
+
+#### Anti Aliasing
+
+Anti aliasing is achieved by jittering the origin of a ray sent out from each pixel using unifrom sampling.
+
+With Anti Aliasing | Without Anti Aliasing
+:-------------------------:|:-------------------------:
+ | 
+
+
+
+#### Motion Blur
+Motion blur is the averaging of multiple shots in a motion.
+ 
+
+
+
+#### Open Image AI Denoiser
+I was able to get the denoiser kind of working and all credits to Intel's out of the world documentation (Really only aliens can understand it). Here is my blooper reel from that.
+
+Blooper 1 | Blooper 2 | Blooper 3 | Blooper 4
+:-------------------------:|:-------------------------:|:-------------------------:|:-------------------------:
+ | |  | 
+
+Finally after fixing my issues I was able to get it working:
+
+
+
+The library expects the pixel values to be in little endian format according to the documentation, so I had written a ReverseFloat function to convert big-endian to little endian, but doing so resulted in the blooper reel, when I did not use that function, I got this result for output after 5 iterations.
+
+
+
+Original | Denoised
+:-------------------------:|:-------------------------:
+ | 
+
+
+Then I also passed albedos and normals buffers to the library, the results after doing that were:
+
+Original | Denoised
+:-------------------------:|:-------------------------:
+ | 
+
+It was a hard task to set it up and build it. I have listed down the steps I had to take here and I think this can serve as an easy documentation of how to set it up and get it running because the existing one is simply great!!
+
+* Install tbb from here: https://github.com/intel/tbb/releases
+* Then run this command : ```git clone --recursive https://github.com/OpenImageDenoise/oidn.git```
+* Then copy the oidn folder into your Path Tracer folder
+* Now in your CMakeLists.txt add the lines ```add_subdirectory(oidn)``` and add ```OpenImageDenoise``` to target_link_libraries
+* Then run ```cmake-gui ..``` and add the following four entries before clicking configure:
+
+ * ```TBB_ROOT``` which is equal to something like ```C:/Users/dewan/Desktop/tbb2019_20190605oss_win/tbb2019_20190605oss```
+* ```TBB_INCLUDE_DIR``` which is something like ```C:\Users\dewan\Desktop\tbb2019_20190605oss_win\tbb2019_20190605oss\include```
+ * ```TBB_LIBRARY``` which is something like ```C:\Users\dewan\Desktop\tbb2019_20190605oss_win\tbb2019_20190605oss\lib\intel64\vc14\tbb_debug.lib```
+ * ```TBB_LIBRARY_MALLOC``` which is something like ```C:\Users\dewan\Desktop\tbb2019_20190605oss_win\tbb2019_20190605oss\lib\intel64\vc14\tbbmalloc_debug.lib```
+* Now install oidn from here ```https://github.com/OpenImageDenoise/oidn/releases``` and copy ```OpenImageDenoise.dll, tbb.dll, tbbmalloc.dll``` from the bin folder to your System32 windows folder.
+
+The code should build now, atleast it did for me, but I make no guarantees as these steps were results of solving all the error messages that were thrown at me when trying to run this.
+
+
+
+
+## Optimization Features
+
+
+
+#### Stream Compaction
+
+After each bounce, some rays would hit the light source and terminate. We can stop the threads that are assigned to these rays or equivalently run less threads in the next one. Using thrust::partition function all the active rays are kept together after every iteration and then only those need to be started.
+
+
+
+#### Material Sort
+
+This idea is based on the fact that if neighboring threads are executing same material type, they will run the same instructions which will result in less warp divergence.
+
+
+
+#### Cache First Bounce
+The rays always start at the pixel they belong to and shoot out at the same location. So we can cache the first bounce in the first iteration and we won't need to recalculate their intersections again.
+
+
+
+A performance comparison of these optimizations can be seen below:
+
+
+
+
+
+
+
+## References
+
+1. https://en.wikipedia.org/wiki/Ray_tracing_(graphics)
+2. https://en.wikipedia.org/wiki/Schlick%27s_approximation
+3. http://viclw17.github.io/2018/07/17/raytracing-camera-and-msaa/
+4. https://www.andrew.cmu.edu/user/hgifford/projects/msaa.pdf
+5. https://github.com/RayTracing/InOneWeekend
diff --git a/img/alias.JPG b/img/alias.JPG
new file mode 100644
index 0000000..609b54b
Binary files /dev/null and b/img/alias.JPG differ
diff --git a/img/anti-alias.JPG b/img/anti-alias.JPG
new file mode 100644
index 0000000..580334e
Binary files /dev/null and b/img/anti-alias.JPG differ
diff --git a/img/denoise_albedo_nromal.png b/img/denoise_albedo_nromal.png
new file mode 100644
index 0000000..d34ba8a
Binary files /dev/null and b/img/denoise_albedo_nromal.png differ
diff --git a/img/denoise_blooper.png b/img/denoise_blooper.png
new file mode 100644
index 0000000..0dd97a9
Binary files /dev/null and b/img/denoise_blooper.png differ
diff --git a/img/denoise_blooper2.png b/img/denoise_blooper2.png
new file mode 100644
index 0000000..4ee66a6
Binary files /dev/null and b/img/denoise_blooper2.png differ
diff --git a/img/denoise_blooper3.png b/img/denoise_blooper3.png
new file mode 100644
index 0000000..f6c86c6
Binary files /dev/null and b/img/denoise_blooper3.png differ
diff --git a/img/denoise_blooper4.png b/img/denoise_blooper4.png
new file mode 100644
index 0000000..3e33f7f
Binary files /dev/null and b/img/denoise_blooper4.png differ
diff --git a/img/denoise_decent.png b/img/denoise_decent.png
new file mode 100644
index 0000000..6aa9881
Binary files /dev/null and b/img/denoise_decent.png differ
diff --git a/img/denoise_orig.png b/img/denoise_orig.png
new file mode 100644
index 0000000..73b84ff
Binary files /dev/null and b/img/denoise_orig.png differ
diff --git a/img/fresnel.png b/img/fresnel.png
new file mode 100644
index 0000000..2881603
Binary files /dev/null and b/img/fresnel.png differ
diff --git a/img/main.png b/img/main.png
new file mode 100644
index 0000000..d08aaa1
Binary files /dev/null and b/img/main.png differ
diff --git a/img/motion_blur.png b/img/motion_blur.png
new file mode 100644
index 0000000..ba36bdf
Binary files /dev/null and b/img/motion_blur.png differ
diff --git a/img/no-alias.JPG b/img/no-alias.JPG
new file mode 100644
index 0000000..c546eb0
Binary files /dev/null and b/img/no-alias.JPG differ
diff --git a/img/original_albedo_nromal.png b/img/original_albedo_nromal.png
new file mode 100644
index 0000000..ac3dc38
Binary files /dev/null and b/img/original_albedo_nromal.png differ
diff --git a/img/path_tracer.png b/img/path_tracer.png
new file mode 100644
index 0000000..54fef69
Binary files /dev/null and b/img/path_tracer.png differ
diff --git a/img/perf.JPG b/img/perf.JPG
new file mode 100644
index 0000000..0129444
Binary files /dev/null and b/img/perf.JPG differ
diff --git a/img/reflection.jpg b/img/reflection.jpg
new file mode 100644
index 0000000..fdfebe7
Binary files /dev/null and b/img/reflection.jpg differ
diff --git a/img/refraction.png b/img/refraction.png
new file mode 100644
index 0000000..d831d98
Binary files /dev/null and b/img/refraction.png differ
diff --git a/img/refraction_no_fresnel.png b/img/refraction_no_fresnel.png
new file mode 100644
index 0000000..e2b2ad5
Binary files /dev/null and b/img/refraction_no_fresnel.png differ
diff --git a/oidn/.gitignore b/oidn/.gitignore
new file mode 100644
index 0000000..10a8f91
--- /dev/null
+++ b/oidn/.gitignore
@@ -0,0 +1,87 @@
+# This file is used to ignore files which are generated
+# ----------------------------------------------------------------------------
+
+*~
+*.autosave
+*.a
+*.core
+*.moc
+*.o
+*.obj
+*.orig
+*.rej
+*.so
+*.so.*
+*_pch.h.cpp
+*_resource.rc
+*.qm
+.#*
+*.*#
+core
+!core/
+tags
+.DS_Store
+.directory
+*.debug
+*.prl
+*.app
+moc_*.cpp
+ui_*.h
+qrc_*.cpp
+Thumbs.db
+*.res
+*.rc
+/.qmake.cache
+/.qmake.stash
+
+# Qt Creator generated files
+*.txt.user*
+*.pro.user*
+
+# xemacs temporary files
+*.flc
+
+# Vim temporary files
+.*.swp
+
+# Visual Studio generated files
+*.ib_pdb_index
+*.idb
+*.ilk
+*.pdb
+*.sln
+*.suo
+*.vcproj
+*vcproj.*.*.user
+*.ncb
+*.sdf
+*.opensdf
+*.vcxproj
+*vcxproj.*
+*.log
+
+# Visual Studio Code generated files
+.vscode
+
+# MinGW generated files
+*.Debug
+*.Release
+
+# Python byte code
+*.pyc
+
+# Binaries
+*.dll
+*.exe
+
+# Build directories
+build*
+
+# Dependencies
+deps
+
+# Data directories
+images
+
+# Generated files
+include/OpenImageDenoise/version.h
diff --git a/oidn/.gitmodules b/oidn/.gitmodules
new file mode 100644
index 0000000..d15912e
--- /dev/null
+++ b/oidn/.gitmodules
@@ -0,0 +1,6 @@
+[submodule "mkl-dnn"]
+ path = mkl-dnn
+ url = ../mkl-dnn.git
+[submodule "weights"]
+ path = weights
+ url = ../oidn-weights.git
diff --git a/oidn/CHANGELOG.md b/oidn/CHANGELOG.md
new file mode 100644
index 0000000..57107ef
--- /dev/null
+++ b/oidn/CHANGELOG.md
@@ -0,0 +1,51 @@
+Version History
+---------------
+
+### Changes in v1.0.0:
+
+- Improved denoising quality
+ - More details preserved
+ - Less artifacts (e.g. noisy spots, color bleeding with albedo/normal)
+- Added `maxMemoryMB` filter parameter for limiting the maximum memory
+ consumption regardless of the image resolution, potentially at the cost
+ of lower denoising speed. This is internally implemented by denoising the
+ image in tiles
+- Significantly reduced memory consumption (but slightly lower performance)
+ for high resolutions (> 2K) by default: limited to about 6 GB
+- Added `alignment` and `overlap` filter parameters that can be queried for
+ manual tiled denoising
+- Added `verbose` device parameter for setting the verbosity of the console
+ output, and disabled all console output by default
+- Fixed crash for zero-sized images
+
+### Changes in v0.9.0:
+
+- Reduced memory consumption by about 38%
+- Added support for progress monitor callback functions
+- Enabled fully concurrent execution when using multiple devices
+- Clamp LDR input and output colors to 1
+- Fixed issue where some memory allocation errors were not reported
+
+### Changes in v0.8.2:
+
+- Fixed wrong HDR output when the input contains infinities/NaNs
+- Fixed wrong output when multiple filters were executed concurrently on
+ separate devices with AVX-512 support. Currently the filter executions are
+ serialized as a temporary workaround, and a full fix will be included in a
+ future release.
+- Added OIDN_STATIC_LIB CMake option for building as a static library
+ (requires CMake 3.13.0 or later)
+- Fixed CMake error when adding the library with add_subdirectory() to a project
+
+### Changes in v0.8.1:
+
+- Fixed wrong path to TBB in the generated CMake configs
+- Fixed wrong rpath in the binaries
+- Fixed compile error on some macOS systems
+- Fixed minor compile issues with Visual Studio
+- Lowered the CPU requirement to SSE4.1
+- Minor example update
+
+### Changes in v0.8.0:
+
+- Initial beta release
diff --git a/oidn/CMakeLists.txt b/oidn/CMakeLists.txt
new file mode 100644
index 0000000..e5e2472
--- /dev/null
+++ b/oidn/CMakeLists.txt
@@ -0,0 +1,191 @@
+## ======================================================================== ##
+## Copyright 2009-2019 Intel Corporation ##
+## ##
+## Licensed under the Apache License, Version 2.0 (the "License"); ##
+## you may not use this file except in compliance with the License. ##
+## You may obtain a copy of the License at ##
+## ##
+## http://www.apache.org/licenses/LICENSE-2.0 ##
+## ##
+## Unless required by applicable law or agreed to in writing, software ##
+## distributed under the License is distributed on an "AS IS" BASIS, ##
+## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ##
+## See the License for the specific language governing permissions and ##
+## limitations under the License. ##
+## ======================================================================== ##
+
+cmake_minimum_required(VERSION 3.1)
+
+set(OIDN_VERSION_MAJOR 1)
+set(OIDN_VERSION_MINOR 0)
+set(OIDN_VERSION_PATCH 0)
+set(OIDN_VERSION_NOTE "")
+
+set(OIDN_VERSION ${OIDN_VERSION_MAJOR}.${OIDN_VERSION_MINOR}.${OIDN_VERSION_PATCH})
+math(EXPR OIDN_VERSION_NUMBER "10000*${OIDN_VERSION_MAJOR} + 100*${OIDN_VERSION_MINOR} + ${OIDN_VERSION_PATCH}")
+
+project(OpenImageDenoise
+ VERSION ${OIDN_VERSION}
+ LANGUAGES CXX
+)
+
+set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${PROJECT_SOURCE_DIR}/cmake")
+
+# Build as shared or static library
+if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.13.0")
+ option(OIDN_STATIC_LIB "Build Open Image Denoise as a static library.")
+ mark_as_advanced(CLEAR OIDN_STATIC_LIB)
+else()
+ set(OIDN_STATIC_LIB OFF CACHE BOOL "Build Open Image Denoise as a static library." FORCE)
+ mark_as_advanced(OIDN_STATIC_LIB)
+endif()
+if(OIDN_STATIC_LIB)
+ set(OIDN_LIB_TYPE STATIC)
+else()
+ set(OIDN_LIB_TYPE SHARED)
+endif()
+
+# Configuration types
+set(CONFIGURATION_TYPES "Debug;Release;RelWithDebInfo")
+if(win32)
+ if(NOT OIDN_DEFAULT_CMAKE_CONFIGURATION_TYPES_SET)
+ set(CMAKE_CONFIGURATION_TYPES "${CONFIGURATION_TYPES}"
+ CACHE STRING "List of generated configurations." FORCE)
+ set(OOIDN_DEFAULT_CMAKE_CONFIGURATION_TYPES_SET ON
+ CACHE INTERNAL "Default CMake configuration types set.")
+ endif()
+else()
+ if(NOT CMAKE_BUILD_TYPE)
+ set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Choose the build type." FORCE)
+ endif()
+ set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS ${CONFIGURATION_TYPES})
+endif()
+
+# Output paths
+set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}")
+set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}")
+set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}")
+
+# Configure packaging
+include(package)
+
+## ----------------------------------------------------------------------------
+## MKL-DNN
+## ----------------------------------------------------------------------------
+
+# Configure MKL-DNN
+set(MKLDNN_LIBRARY_TYPE "STATIC" CACHE INTERNAL "")
+set(MKLDNN_THREADING "TBB" CACHE INTERNAL "")
+set(MKLDNN_USE_MKL "NONE" CACHE INTERNAL "")
+set(MKLDNN_ENABLE_CONCURRENT_EXEC ON CACHE INTERNAL "")
+set(MKLDNN_USE_CLANG_SANITIZER "" CACHE INTERNAL "")
+set(MKLDNN_VERBOSE OFF CACHE BOOL "")
+set(MKLDNN_BUILD_EXAMPLES OFF CACHE INTERNAL "")
+set(MKLDNN_BUILD_TESTS OFF CACHE INTERNAL "")
+set(BENCHDNN_USE_RDPMC OFF CACHE INTERNAL "")
+
+# Add modified version of MKL-DNN
+add_subdirectory(mkl-dnn EXCLUDE_FROM_ALL)
+
+# Include some modules from MKL-DNN
+include(mkl-dnn/cmake/Threading.cmake)
+include(mkl-dnn/cmake/TBB.cmake)
+include(mkl-dnn/cmake/platform.cmake)
+include(mkl-dnn/cmake/SDL.cmake)
+
+# Propagate no warning flags
+append(CMAKE_C_FLAGS "${CMAKE_CCXX_NOWARN_FLAGS}")
+append(CMAKE_CXX_FLAGS "${CMAKE_CCXX_NOWARN_FLAGS}")
+
+## ----------------------------------------------------------------------------
+## Open Image Denoise library
+## ----------------------------------------------------------------------------
+
+# Generate version.h
+configure_file(
+ "${PROJECT_SOURCE_DIR}/include/OpenImageDenoise/version.h.in"
+ "${PROJECT_SOURCE_DIR}/include/OpenImageDenoise/version.h"
+)
+
+add_subdirectory(common EXCLUDE_FROM_ALL)
+
+set(CORE_SOURCES
+ include/OpenImageDenoise/oidn.h
+ include/OpenImageDenoise/oidn.hpp
+ include/OpenImageDenoise/version.h
+ core/api.cpp
+ core/common.h
+ core/math.h
+ core/device.h
+ core/device.cpp
+ core/buffer.h
+ core/image.h
+ core/filter.h
+ core/filter.cpp
+ core/node.h
+ core/input_reorder.h
+ core/output_reorder.h
+ core/weights_reorder.h
+ core/transfer_function.h
+ core/upsample.h
+ core/network.h
+ core/autoencoder.h
+)
+
+set(CORE_SOURCES_SSE41
+ core/network.cpp
+ core/autoencoder.cpp
+ core/transfer_function.cpp
+)
+
+include(resource)
+generate_cpp_resources(WEIGHTS_SOURCES "oidn::weights"
+ weights/rt_ldr.tza
+ weights/rt_ldr_alb.tza
+ weights/rt_ldr_alb_nrm.tza
+ weights/rt_hdr.tza
+ weights/rt_hdr_alb.tza
+ weights/rt_hdr_alb_nrm.tza
+)
+
+set_source_files_properties(${CORE_SOURCES_SSE41} PROPERTIES COMPILE_FLAGS "${ISA_FLAGS_SSE41}")
+
+add_library(${PROJECT_NAME} ${OIDN_LIB_TYPE} ${CORE_SOURCES} ${CORE_SOURCES_SSE41} ${WEIGHTS_SOURCES})
+
+if(OIDN_STATIC_LIB)
+ target_compile_definitions(${PROJECT_NAME} INTERFACE -DOIDN_STATIC_LIB)
+endif()
+
+target_include_directories(${PROJECT_NAME}
+ PUBLIC
+ $
+ $
+ PRIVATE
+ ${PROJECT_SOURCE_DIR}/mkl-dnn/include
+ ${PROJECT_SOURCE_DIR}/mkl-dnn/src
+ ${PROJECT_SOURCE_DIR}/mkl-dnn/src/common
+ ${PROJECT_SOURCE_DIR}/mkl-dnn/src/cpu/xbyak
+)
+
+target_link_libraries(${PROJECT_NAME}
+ PRIVATE
+ common mkldnn
+)
+
+set_property(TARGET ${PROJECT_NAME} PROPERTY VERSION ${PROJECT_VERSION})
+set_property(TARGET ${PROJECT_NAME} PROPERTY SOVERSION "0")
+
+## ----------------------------------------------------------------------------
+## Open Image Denoise examples
+## ----------------------------------------------------------------------------
+
+add_subdirectory(examples)
+
+## ----------------------------------------------------------------------------
+## Open Image Denoise install and packaging
+## ----------------------------------------------------------------------------
+
+include(install)
+
+# Has to be last
+include(CPack)
diff --git a/oidn/LICENSE.txt b/oidn/LICENSE.txt
new file mode 100644
index 0000000..d645695
--- /dev/null
+++ b/oidn/LICENSE.txt
@@ -0,0 +1,202 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/oidn/README.md b/oidn/README.md
new file mode 100644
index 0000000..cee01ea
--- /dev/null
+++ b/oidn/README.md
@@ -0,0 +1,848 @@
+# Intel® Open Image Denoise
+
+This is release v1.0.0 of Open Image Denoise. For changes and new
+features see the [changelog](CHANGELOG.md). Visit
+http://www.openimagedenoise.org for more information.
+
+# Open Image Denoise Overview
+
+Intel® Open Image Denoise is an open source library of high-performance,
+high-quality denoising filters for images rendered with ray tracing.
+Open Image Denoise is part of the [Intel Rendering
+Framework](https://software.intel.com/en-us/rendering-framework) and is
+released under the permissive [Apache 2.0
+license](http://www.apache.org/licenses/LICENSE-2.0).
+
+The purpose of Open Image Denoise is to provide an open, high-quality,
+efficient, and easy-to-use denoising library that allows one to
+significantly reduce rendering times in ray tracing based rendering
+applications. It filters out the Monte Carlo noise inherent to
+stochastic ray tracing methods like path tracing, reducing the amount of
+necessary samples per pixel by even multiple orders of magnitude
+(depending on the desired closeness to the ground truth). A simple but
+flexible C/C++ API ensures that the library can be easily integrated
+into most existing or new rendering solutions.
+
+At the heart of the Open Image Denoise library is an efficient deep
+learning based denoising filter, which was trained to handle a wide
+range of samples per pixel (spp), from 1 spp to almost fully converged.
+Thus it is suitable for both preview and final-frame rendering. The
+filters can denoise images either using only the noisy color (*beauty*)
+buffer, or, to preserve as much detail as possible, can optionally
+utilize auxiliary feature buffers as well (e.g. albedo, normal). Such
+buffers are supported by most renderers as arbitrary output variables
+(AOVs) or can be usually implemented with little effort.
+
+Open Image Denoise supports Intel® 64 architecture based CPUs and
+compatible architectures, and runs on anything from laptops, to
+workstations, to compute nodes in HPC systems. It is efficient enough to
+be suitable not only for offline rendering, but, depending on the
+hardware used, also for interactive ray tracing.
+
+Open Image Denoise internally builds on top of [Intel® Math Kernel
+Library for Deep Neural Networks
+(MKL-DNN)](https://github.com/intel/mkl-dnn), and automatically exploits
+modern instruction sets like Intel SSE4, AVX2, and AVX-512 to achieve
+high denoising performance. A CPU with support for at least SSE4.1 is
+required to run Open Image Denoise.
+
+## Support and Contact
+
+Open Image Denoise is under active development, and though we do our
+best to guarantee stable release versions a certain number of bugs,
+as-yet-missing features, inconsistencies, or any other issues are still
+possible. Should you find any such issues please report them immediately
+via the [Open Image Denoise GitHub Issue
+Tracker](https://github.com/OpenImageDenoise/oidn/issues) (or, if you
+should happen to have a fix for it, you can also send us a pull
+request); for missing features please contact us via email at
+.
+
+For recent news, updates, and announcements, please see our complete
+[news/updates](https://openimagedenoise.github.io/news.html) page.
+
+Join our [mailing
+list](https://groups.google.com/d/forum/openimagedenoise/) to receive
+release announcements and major news regarding Open Image Denoise.
+
+# Building Open Image Denoise from Source
+
+The latest Open Image Denoise sources are always available at the [Open
+Image Denoise GitHub
+repository](http://github.com/OpenImageDenoise/oidn). The default
+`master` branch should always point to the latest tested bugfix release.
+
+## Prerequisites
+
+Open Image Denoise currently supports 64-bit Linux, Windows, and macOS
+operating systems. In addition, before you can build Open Image Denoise
+you need the following prerequisites:
+
+ - You can clone the latest Open Image Denoise sources
+ via:
+
+ git clone --recursive https://github.com/OpenImageDenoise/oidn.git
+
+ - To build Open Image Denoise you need [CMake](http://www.cmake.org)
+ 3.1 or later, a C++11 compiler (we recommend using Clang, but also
+ support GCC, Microsoft Visual Studio 2015 or later, and [Intel® C++
+ Compiler](https://software.intel.com/en-us/c-compilers) 17.0 or
+ later), and Python 2.7 or later.
+
+ - Additionally you require a copy of [Intel® Threading Building
+ Blocks](https://www.threadingbuildingblocks.org/) (TBB) 2017 or
+ later.
+
+Depending on your Linux distribution you can install these dependencies
+using `yum` or `apt-get`. Some of these packages might already be
+installed or might have slightly different names.
+
+Type the following to install the dependencies using `yum`:
+
+ sudo yum install cmake
+ sudo yum install tbb-devel
+
+Type the following to install the dependencies using `apt-get`:
+
+ sudo apt-get install cmake-curses-gui
+ sudo apt-get install libtbb-dev
+
+Under macOS these dependencies can be installed using
+[MacPorts](http://www.macports.org/):
+
+ sudo port install cmake tbb
+
+Under Windows please directly use the appropriate installers or packages
+for [CMake](https://cmake.org/download/),
+[Python](https://www.python.org/downloads/), and
+[TBB](https://github.com/01org/tbb/releases).
+
+## Compiling Open Image Denoise on Linux/macOS
+
+Assuming the above prerequisites are all fulfilled, building Open Image
+Denoise through CMake is easy:
+
+ - Create a build directory, and go into it
+
+ mkdir oidn/build
+ cd oidn/build
+
+ (We do recommend having separate build directories for different
+ configurations such as release, debug, etc.).
+
+ - The compiler CMake will use by default will be whatever the `CC` and
+ `CXX` environment variables point to. Should you want to specify a
+ different compiler, run cmake manually while specifying the desired
+ compiler. The default compiler on most Linux machines is `gcc`, but
+ it can be pointed to `clang` instead by executing the following:
+
+ cmake -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_C_COMPILER=clang ..
+
+ CMake will now use Clang instead of GCC. If you are OK with using
+ the default compiler on your system, then simply skip this step.
+ Note that the compiler variables cannot be changed after the first
+ `cmake` or `ccmake` run.
+
+ - Open the CMake configuration dialog
+
+ ccmake ..
+
+ - Make sure to properly set the build mode and enable the components
+ you need, etc.; then type ’c’onfigure and ’g’enerate. When back on
+ the command prompt, build it using
+
+ make
+
+ - You should now have `libOpenImageDenoise.so` as well as a set of
+ example applications.
+
+## Compiling Open Image Denoise on Windows
+
+On Windows using the CMake GUI (`cmake-gui.exe`) is the most convenient
+way to configure Open Image Denoise and to create the Visual Studio
+solution files:
+
+ - Browse to the Open Image Denoise sources and specify a build
+ directory (if it does not exist yet CMake will create it).
+
+ - Click “Configure” and select as generator the Visual Studio version
+ you have (Open Image Denoise needs Visual Studio 14 2015 or newer),
+ for Win64 (32-bit builds are not supported), e.g., “Visual Studio 15
+ 2017 Win64”.
+
+ - If the configuration fails because some dependencies could not be
+ found then follow the instructions given in the error message, e.g.,
+ set the variable `TBB_ROOT` to the folder where TBB was installed.
+
+ - Optionally change the default build options, and then click
+ “Generate” to create the solution and project files in the build
+ directory.
+
+ - Open the generated `OpenImageDenoise.sln` in Visual Studio, select
+ the build configuration and compile the project.
+
+Alternatively, Open Image Denoise can also be built without any GUI,
+entirely on the console. In the Visual Studio command prompt type:
+
+ cd path\to\oidn
+ mkdir build
+ cd build
+ cmake -G "Visual Studio 15 2017 Win64" [-D VARIABLE=value] ..
+ cmake --build . --config Release
+
+Use `-D` to set variables for CMake, e.g., the path to TBB with “`-D
+TBB_ROOT=\path\to\tbb`”.
+
+## CMake Configuration
+
+The default CMake configuration in the configuration dialog should be
+appropriate for most usages. The following list describes the options
+that can be configured in CMake:
+
+ - `CMAKE_BUILD_TYPE`: Can be used to switch between Debug mode
+ (Debug), Release mode (Release) (default), and Release mode with
+ enabled assertions and debug symbols (RelWithDebInfo).
+
+ - `OIDN_STATIC_LIB`: Builds Open Image Denoise as a static library
+ (OFF by default). CMake 3.13.0 or later is required to enable this
+ option. When using the statically compiled Open Image Denoise
+ library, you either have to use the generated CMake configuration
+ files (recommended), or you have to manually define
+ `OIDN_STATIC_LIB` before including the library headers in your
+ application.
+
+ - `TBB_ROOT`: The path to the TBB installation (autodetected by
+ default).
+
+# Documentation
+
+The following [API
+documentation](https://github.com/OpenImageDenoise/oidn/blob/master/readme.pdf "Open Image Denoise Documentation")
+of Open Image Denoise can also be found as a [pdf
+document](https://github.com/OpenImageDenoise/oidn/blob/master/readme.pdf "Open Image Denoise Documentation").
+
+# Open Image Denoise API
+
+Open Image Denoise provides a C99 API (also compatible with C++) and a
+C++11 wrapper API as well. For simplicity, this document mostly refers
+to the C99 version of the API.
+
+The API is designed in an object-oriented manner, e.g. it contains
+device objects (`OIDNDevice` type), buffer objects (`OIDNBuffer` type),
+and filter objects (`OIDNFilter` type). All objects are
+reference-counted, and handles can be released by calling the
+appropriate release function (e.g. `oidnReleaseDevice`) or retained by
+incrementing the reference count (e.g. `oidnRetainDevice`).
+
+An important aspect of objects is that setting their parameters do not
+have an immediate effect (with a few exceptions). Instead, objects with
+updated parameters are in an unusable state until the parameters get
+explicitly committed to a given object. The commit semantic allows for
+batching up multiple small changes, and specifies exactly when changes
+to objects will occur.
+
+All API calls are thread-safe, but operations that use the same device
+will be serialized, so the amount of API calls from different threads
+should be minimized.
+
+To have a quick overview of the C99 and C++11 APIs, see the following
+simple example code snippets.
+
+### C99 API Example
+
+``` cpp
+#include
+...
+// Create an Open Image Denoise device
+OIDNDevice device = oidnNewDevice(OIDN_DEVICE_TYPE_DEFAULT);
+oidnCommitDevice(device);
+
+// Create a denoising filter
+OIDNFilter filter = oidnNewFilter(device, "RT"); // generic ray tracing filter
+oidnSetSharedFilterImage(filter, "color", colorPtr,
+ OIDN_FORMAT_FLOAT3, width, height, 0, 0, 0);
+oidnSetSharedFilterImage(filter, "albedo", albedoPtr,
+ OIDN_FORMAT_FLOAT3, width, height, 0, 0, 0); // optional
+oidnSetSharedFilterImage(filter, "normal", normalPtr,
+ OIDN_FORMAT_FLOAT3, width, height, 0, 0, 0); // optional
+oidnSetSharedFilterImage(filter, "output", outputPtr,
+ OIDN_FORMAT_FLOAT3, width, height, 0, 0, 0);
+oidnSetFilter1b(filter, "hdr", true); // image is HDR
+oidnCommitFilter(filter);
+
+// Filter the image
+oidnExecuteFilter(filter);
+
+// Check for errors
+const char* errorMessage;
+if (oidnGetDeviceError(device, &errorMessage) != OIDN_ERROR_NONE)
+ printf("Error: %s\n", errorMessage);
+
+// Cleanup
+oidnReleaseFilter(filter);
+oidnReleaseDevice(device);
+```
+
+### C++11 API Example
+
+``` cpp
+#include
+...
+// Create an Open Image Denoise device
+oidn::DeviceRef device = oidn::newDevice();
+device.commit();
+
+// Create a denoising filter
+oidn::FilterRef filter = device.newFilter("RT"); // generic ray tracing filter
+filter.setImage("color", colorPtr, oidn::Format::Float3, width, height);
+filter.setImage("albedo", albedoPtr, oidn::Format::Float3, width, height); // optional
+filter.setImage("normal", normalPtr, oidn::Format::Float3, width, height); // optional
+filter.setImage("output", outputPtr, oidn::Format::Float3, width, height);
+filter.set("hdr", true); // image is HDR
+filter.commit();
+
+// Filter the image
+filter.execute();
+
+// Check for errors
+const char* errorMessage;
+if (device.getError(errorMessage) != oidn::Error::None)
+ std::cout << "Error: " << errorMessage << std::endl;
+```
+
+## Device
+
+Open Image Denoise supports a device concept, which allows different
+components of the application to use the Open Image Denoise API without
+interfering with each other. An application first needs to create a
+device with
+
+``` cpp
+OIDNDevice oidnNewDevice(OIDNDeviceType type);
+```
+
+where the `type` enumeration maps to a specific device implementation,
+which can be one of the
+following:
+
+| Name | Description |
+| :-------------------------- | :-------------------------------------- |
+| OIDN\_DEVICE\_TYPE\_DEFAULT | select the approximately fastest device |
+| OIDN\_DEVICE\_TYPE\_CPU | CPU device (requires SSE4.1 support) |
+
+Supported device types, i.e., valid constants of type `OIDNDeviceType`.
+
+Once a device is created, you can call
+
+``` cpp
+void oidnSetDevice1b(OIDNDevice device, const char* name, bool value);
+void oidnSetDevice1i(OIDNDevice device, const char* name, int value);
+bool oidnGetDevice1b(OIDNDevice device, const char* name);
+int oidnGetDevice1i(OIDNDevice device, const char* name);
+```
+
+to set and get parameter values on the device. Note that some parameters
+are constants, thus trying to set them is an error. See the tables below
+for the parameters supported by
+devices.
+
+| Type | Name | Default | Description |
+| :-------- | :----------- | ------: | :---------------------------------------------------------------------------------------------------------------------------------------- |
+| const int | version | | combined version number (major.minor.patch) with two decimal digits per component |
+| const int | versionMajor | | major version number |
+| const int | versionMinor | | minor version number |
+| const int | versionPatch | | patch version number |
+| int | verbose | 0 | verbosity level of the console output between 0–3; when set to 0, no output is printed, when set to a higher level more output is printed |
+
+Parameters supported by all
+devices.
+
+| Type | Name | Default | Description |
+| :--- | :---------- | ------: | :--------------------------------------------------------------------------------------------------------------------- |
+| int | numThreads | 0 | maximum number of threads which Open Image Denoise should use; 0 will set it automatically to get the best performance |
+| bool | setAffinity | true | bind software threads to hardware threads if set to true (improves performance); false disables binding |
+
+Additional parameters supported only by CPU devices.
+
+Note that the CPU device heavily relies on setting the thread affinities
+to achieve optimal performance, so it is highly recommended to leave
+this option enabled. However, this may interfere with the application if
+that also sets the thread affinities, potentially causing performance
+degradation. In such cases, the recommended solution is to either
+disable setting the affinities in the application or in Open Image
+Denoise, or to always set/reset the affinities before/after each
+parallel region in the application (e.g., if using TBB, with
+`tbb::task_arena` and `tbb::task_scheduler_observer`).
+
+Once parameters are set on the created device, the device must be
+committed with
+
+``` cpp
+void oidnCommitDevice(OIDNDevice device);
+```
+
+This device can then be used to construct further objects, such as
+buffers and filters. Note that a device can be committed only once
+during its lifetime. Before the application exits, it should release all
+devices by invoking
+
+``` cpp
+void oidnReleaseDevice(OIDNDevice device);
+```
+
+Note that Open Image Denoise uses reference counting for all object
+types, so this function decreases the reference count of the device, and
+if the count reaches 0 the device will automatically get deleted. It is
+also possible to increase the reference count by calling
+
+``` cpp
+void oidnRetainDevice(OIDNDevice device);
+```
+
+An application typically creates only a single device. If required
+differently, it should only use a small number of devices at any given
+time.
+
+### Error Handling
+
+Each user thread has its own error code per device. If an error occurs
+when calling an API function, this error code is set to the occurred
+error if it stores no previous error. The currently stored error can be
+queried by the application
+via
+
+``` cpp
+OIDNError oidnGetDeviceError(OIDNDevice device, const char** outMessage);
+```
+
+where `outMessage` can be a pointer to a C string which will be set to a
+more descriptive error message, or it can be `NULL`. This function also
+clears the error code, which assures that the returned error code is
+always the first error occurred since the last invocation of
+`oidnGetDeviceError` on the current thread. Note that the optionally
+returned error message string is valid only until the next invocation of
+the function.
+
+Alternatively, the application can also register a callback function of
+type
+
+``` cpp
+typedef void (*OIDNErrorFunction)(void* userPtr, OIDNError code, const char* message);
+```
+
+via
+
+``` cpp
+void oidnSetDeviceErrorFunction(OIDNDevice device, OIDNErrorFunction func, void* userPtr);
+```
+
+to get notified when errors occur. Only a single callback function can
+be registered per device, and further invocations overwrite the
+previously set callback function, which do *not* require also calling
+the `oidnCommitDevice` function. Passing `NULL` as function pointer
+disables the registered callback function. When the registered callback
+function is invoked, it gets passed the user-defined payload (`userPtr`
+argument as specified at registration time), the error code (`code`
+argument) of the occurred error, as well as a string (`message`
+argument) that further describes the error. The error code is always set
+even if an error callback function is registered. It is recommended to
+always set a error callback function, to detect all errors.
+
+When the device construction fails, `oidnNewDevice` returns `NULL` as
+device. To detect the error code of a such failed device construction,
+pass `NULL` as device to the `oidnGetDeviceError` function. For all
+other invocations of `oidnGetDeviceError`, a proper device handle must
+be specified.
+
+The following errors are currently used by Open Image
+Denoise:
+
+| Name | Description |
+| :--------------------------------- | :----------------------------------------- |
+| OIDN\_ERROR\_NONE | no error occurred |
+| OIDN\_ERROR\_UNKNOWN | an unknown error occurred |
+| OIDN\_ERROR\_INVALID\_ARGUMENT | an invalid argument was specified |
+| OIDN\_ERROR\_INVALID\_OPERATION | the operation is not allowed |
+| OIDN\_ERROR\_OUT\_OF\_MEMORY | not enough memory to execute the operation |
+| OIDN\_ERROR\_UNSUPPORTED\_HARDWARE | the hardware (e.g., CPU) is not supported |
+| OIDN\_ERROR\_CANCELLED | the operation was cancelled by the user |
+
+Possible error codes, i.e., valid constants of type `OIDNError`.
+
+## Buffer
+
+Large data like images can be passed to Open Image Denoise either via
+pointers to memory allocated and managed by the user (this is the
+recommended, often easier and more efficient approach, if supported by
+the device) or by creating buffer objects (supported by all devices). To
+create a new data buffer with memory allocated and owned by the device,
+holding `byteSize` number of bytes, use
+
+``` cpp
+OIDNBuffer oidnNewBuffer(OIDNDevice device, size_t byteSize);
+```
+
+The created buffer is bound to the specified device (`device` argument).
+The specified number of bytes are allocated at buffer construction time
+and deallocated when the buffer is destroyed.
+
+It is also possible to create a “shared” data buffer with memory
+allocated and managed by the user
+with
+
+``` cpp
+OIDNBuffer oidnNewSharedBuffer(OIDNDevice device, void* ptr, size_t byteSize);
+```
+
+where `ptr` points to the user-managed memory and `byteSize` is its size
+in bytes. At buffer construction time no buffer data is allocated, but
+the buffer data provided by the user is used. The buffer data must
+remain valid for as long as the buffer may be used, and the user is
+responsible to free the buffer data when no longer required.
+
+Similar to device objects, buffer objects are also reference-counted and
+can be retained and released by calling the following functions:
+
+``` cpp
+void oidnRetainBuffer(OIDNBuffer buffer);
+void oidnReleaseBuffer(OIDNBuffer buffer);
+```
+
+Accessing the data stored in a buffer object is possible by mapping it
+into the address space of the application
+using
+
+``` cpp
+void* oidnMapBuffer(OIDNBuffer buffer, OIDNAccess access, size_t byteOffset, size_t byteSize)
+```
+
+where `access` is the desired access mode of the mapped memory,
+`byteOffset` is the offset to the beginning of the mapped memory region
+in bytes, and `byteSize` is the number of bytes to map. The function
+returns a pointer to the mapped buffer data. If the specified `byteSize`
+is 0, the maximum available amount of memory will be mapped. The
+`access` argument must be one of the access modes in the following
+table:
+
+| Name | Description |
+| :--------------------------- | :------------------------------------------------------------ |
+| OIDN\_ACCESS\_READ | read-only access |
+| OIDN\_ACCESS\_WRITE | write-only access |
+| OIDN\_ACCESS\_READ\_WRITE | read and write access |
+| OIDN\_ACCESS\_WRITE\_DISCARD | write-only access but the previous contents will be discarded |
+
+Access modes for memory regions mapped with `oidnMapBuffer`, i.e., valid
+constants of type `OIDNAccess`.
+
+After accessing the mapped data in the buffer, the memory region must be
+unmapped with
+
+``` cpp
+void oidnUnmapBuffer(OIDNBuffer buffer, void* mappedPtr);
+```
+
+where `mappedPtr` must be a pointer returned by a call to
+`oidnMapBuffer` for the specified buffer. Any change to the mapped data
+is guaranteed to take effect only after unmapping the memory region.
+
+### Data Format
+
+Buffers store opaque data and thus have no information about the type
+and format of the data. Other objects, e.g. filters, typically require
+specifying the format of the data stored in buffers or shared via
+pointers. This can be done using the `OIDNFormat` enumeration
+type:
+
+| Name | Description |
+| :------------------------- | :-------------------------------------------- |
+| OIDN\_FORMAT\_UNDEFINED | undefined format |
+| OIDN\_FORMAT\_FLOAT | 32-bit single-precision floating point scalar |
+| OIDN\_FORMAT\_FLOAT\[234\] | … and \[234\]-element vector |
+
+Supported data formats, i.e., valid constants of type `OIDNFormat`.
+
+## Filter
+
+Filters are the main objects in Open Image Denoise that are responsible
+for the actual denoising. The library ships with a collection of filters
+which are optimized for different types of images and use cases. To
+create a filter object, call
+
+``` cpp
+OIDNFilter oidnNewFilter(OIDNDevice device, const char* type);
+```
+
+where `type` is the name of the filter type to create. The supported
+filter types are documented later in this section. Once created, filter
+objects can be retained and released with
+
+``` cpp
+void oidnRetainFilter(OIDNFilter filter);
+void oidnReleaseFilter(OIDNFilter filter);
+```
+
+After creating a filter, it needs to be set up by specifying the input
+and output image buffers, and potentially setting other parameter values
+as well.
+
+To bind image buffers to the filter, you can use one of the following
+functions:
+
+``` cpp
+void oidnSetFilterImage(OIDNFilter filter, const char* name,
+ OIDNBuffer buffer, OIDNFormat format,
+ size_t width, size_t height,
+ size_t byteOffset,
+ size_t bytePixelStride, size_t byteRowStride);
+
+void oidnSetSharedFilterImage(OIDNFilter filter, const char* name,
+ void* ptr, OIDNFormat format,
+ size_t width, size_t height,
+ size_t byteOffset,
+ size_t bytePixelStride, size_t byteRowStride);
+```
+
+It is possible to specify either a data buffer object (`buffer`
+argument) with the `oidnSetFilterImage` function, or directly a pointer
+to shared user-managed data (`ptr` argument) with the
+`oidnSetSharedFilterImage` function.
+
+In both cases, you must also specify the name of the image parameter to
+set (`name` argument, e.g. `"color"`, `"output"`), the pixel format
+(`format` argument), the width and height of the image in number of
+pixels (`width` and `height` arguments), the starting offset of the
+image data (`byteOffset` argument), the pixel stride (`bytePixelStride`
+argument) and the row stride (`byteRowStride` argument), in number of
+bytes. Note that the row stride must be an integer multiple of the pixel
+stride.
+
+If the pixels and/or rows are stored contiguously (tightly packed
+without any gaps), you can set `bytePixelStride` and/or `byteRowStride`
+to 0 to let the library compute the actual strides automatically, as a
+convenience.
+
+Filters may have parameters other than buffers as well, which you can
+set and get using the following functions:
+
+``` cpp
+void oidnSetFilter1b(OIDNFilter filter, const char* name, bool value);
+void oidnSetFilter1i(OIDNFilter filter, const char* name, int value);
+bool oidnGetFilter1b(OIDNFilter filter, const char* name);
+int oidnGetFilter1i(OIDNFilter filter, const char* name);
+```
+
+Filters support a progress monitor callback mechanism that can be used
+to report progress of filter operations and to cancel them as well.
+Calling `oidnSetFilterProgressMonitorFunction` registers a progress
+monitor callback function (`func` argument) with payload (`userPtr`
+argument) for the specified filter (`filter` argument):
+
+``` cpp
+typedef bool (*OIDNProgressMonitorFunction)(void* userPtr, double n);
+
+void oidnSetFilterProgressMonitorFunction(OIDNFilter filter,
+ OIDNProgressMonitorFunction func,
+ void* userPtr);
+```
+
+Only a single callback function can be registered per filter, and
+further invocations overwrite the previously set callback function.
+Passing `NULL` as function pointer disables the registered callback
+function. Once registered, Open Image Denoise will invoke the callback
+function multiple times during filter operations, by passing the payload
+as set at registration time (`userPtr` argument), and a `double` in the
+range \[0, 1\] which estimates the progress of the operation (`n`
+argument). When returning `true` from the callback function, Open Image
+Denoise will continue the filter operation normally. When returning
+`false`, the library will cancel the filter operation with the
+`OIDN_ERROR_CANCELLED` error code.
+
+After setting all necessary parameters for the filter, the changes must
+be commmitted by calling
+
+``` cpp
+void oidnCommitFilter(OIDNFilter filter);
+```
+
+The parameters can be updated after committing the filter, but it must
+be re-committed for the changes to take effect.
+
+Finally, an image can be filtered by executing the filter with
+
+``` cpp
+void oidnExecuteFilter(OIDNFilter filter);
+```
+
+which will read the input image data from the specified buffers and
+produce the denoised output image.
+
+In the following we describe the different filters that are currently
+implemented in Open Image Denoise.
+
+### RT
+
+The `RT` (**r**ay **t**racing) filter is a generic ray tracing denoising
+filter which is suitable for denoising images rendered with Monte Carlo
+ray tracing methods like unidirectional and bidirectional path tracing.
+It supports depth of field and motion blur as well, but it is *not*
+temporally stable. The filter is based on a deep learning based
+denoising algorithm, and it aims to provide a good balance between
+denoising performance and quality for a wide range of samples per pixel.
+
+It accepts either a low dynamic range (LDR) or high dynamic range (HDR)
+color image as input. Optionally, it also accepts auxiliary *feature*
+images, e.g. albedo and normal, which improve the denoising quality,
+preserving more details in the image.
+
+The `RT` filter has certain limitations regarding the supported input
+images. Most notably, it cannot denoise images that were not rendered
+with ray tracing. Another important limitation is related to
+anti-aliasing filters. Most renderers use a high-quality pixel
+reconstruction filter instead of a trivial box filter to minimize
+aliasing artifacts (e.g. Gaussian, Blackman-Harris). The `RT` filter
+does support such pixel filters but only if implemented with importance
+sampling. Weighted pixel sampling (sometimes called *splatting*)
+introduces correlation between neighboring pixels, which causes the
+denoising to fail (the noise will not be filtered), thus it is not
+supported.
+
+The filter can be created by passing `"RT"` to the `oidnNewFilter`
+function as the filter type. The filter supports the following
+parameters:
+
+| Type | Format | Name | Default | Description |
+| :-------- | :----- | :---------- | ------: | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| Image | float3 | color | | input color image (LDR values in \[0, 1\] or HDR values in \[0, +∞)) |
+| Image | float3 | albedo | | input feature image containing the albedo (values in \[0, 1\]) of the first hit per pixel; *optional* |
+| Image | float3 | normal | | input feature image containing the shading normal (world-space or view-space, arbitrary length, values in (−∞, +∞)) of the first hit per pixel; *optional*, requires setting the albedo image too |
+| Image | float3 | output | | output image; can be one of the input images |
+| bool | | hdr | false | whether the color is HDR |
+| bool | | srgb | false | whether the color is encoded with the sRGB (or 2.2 gamma) curve (LDR only) or is linear; the output will be encoded with the same curve |
+| int | | maxMemoryMB | 6000 | approximate maximum amount of memory to use in megabytes (actual memory usage may be higher); limiting memory usage may cause slower denoising due to internally splitting the image into overlapping tiles, but cannot cause the denoising to fail |
+| const int | | alignment | | when manually denoising the image in tiles, the tile size and offsets should be multiples of this amount of pixels to avoid artifacts; note that manual tiled denoising is supported *only* for LDR images |
+| const int | | overlap | | when manually denoising the image in tiles, the tiles should overlap by this amount of pixels |
+
+Parameters supported by the `RT` filter.
+
+All specified images must have the same dimensions.
+
+
+Example noisy color image rendered using unidirectional path tracing
+(512 spp). *Scene by
+Evermotion.*
+
+
+Example output image denoised using color and auxiliary feature images
+(albedo and
+normal).
+
+Using auxiliary feature images like albedo and normal helps preserving
+fine details and textures in the image thus can significantly improve
+denoising quality. These images should typically contain feature values
+for the first hit (i.e. the surface which is directly visible) per
+pixel. This works well for most surfaces but does not provide any
+benefits for reflections and objects visible through transparent
+surfaces (compared to just using the color as input). However, in
+certain cases this issue can be fixed by storing feature values for a
+subsequent hit (i.e. the reflection and/or refraction) instead of the
+first hit. For example, it usually works well to follow perfect specular
+(*delta*) paths and store features for the first diffuse or glossy
+surface hit instead (e.g. for perfect specular dielectrics and mirrors).
+This can greatly improve the quality of reflections and transmission. We
+will describe this approach in more detail in the following subsections.
+
+The auxiliary feature images should be as noise-free as possible. It is
+not a strict requirement but too much noise in the feature images may
+cause residual noise in the output. Also, all feature images should use
+the same pixel reconstruction filter as the color image. Using a
+properly anti-aliased color image but aliased albedo or normal images
+will likely introduce artifacts around edges.
+
+#### Albedo
+
+The albedo image is the feature image that usually provides the biggest
+quality improvement. It should contain the approximate color of the
+surfaces independent of illumination and viewing angle.
+
+For simple matte surfaces this means using the diffuse color/texture as
+the albedo. For other, more complex surfaces it is not always obvious
+what is the best way to compute the albedo, but the denoising filter is
+flexibile to a certain extent and works well with differently computed
+albedos. Thus it is not necessary to compute the strict, exact albedo
+values but must be always between 0 and 1.
+
+
+Example albedo image obtained using the first hit. Note that the
+albedos of all transparent surfaces are
+1.
+
+
+Example albedo image obtained using the first diffuse or glossy
+(non-delta) hit. Note that the albedos of perfect specular (delta)
+transparent surfaces are computed as the Fresnel blend of the reflected
+and transmitted
+albedos.
+
+For metallic surfaces the albedo should be either the reflectivity at
+normal incidence (e.g. from the artist friendly metallic Fresnel model)
+or the average reflectivity; or if these are constant (not textured) or
+unknown, the albedo can be simply 1 as well.
+
+The albedo for dielectric surfaces (e.g. glass) should be either 1 or,
+if the surface is perfect specular (i.e. has a delta BSDF), the Fresnel
+blend of the reflected and transmitted albedos (as previously
+discussed). The latter usually works better but *only* if it does not
+introduce too much additional noise due to random sampling. Thus we
+recommend to split the path into a reflected and a transmitted path at
+the first hit, and perhaps fall back to an albedo of 1 for subsequent
+dielectric hits, to avoid noise. The reflected albedo in itself can be
+used for mirror-like surfaces as well.
+
+The albedo for layered surfaces can be computed as the weighted sum of
+the albedos of the individual layers. Non-absorbing clear coat layers
+can be simply ignored (or the albedo of the perfect specular reflection
+can be used as well) but absorption should be taken into account.
+
+#### Normal
+
+The normal image should contain the shading normals of the surfaces
+either in world-space or view-space. It is recommended to include normal
+maps to preserve as much detail as possible.
+
+Just like any other input image, the normal image should be anti-aliased
+(i.e. by accumulating the normalized normals per pixel). The final
+accumulated normals do not have to be normalized but must be in a range
+symmetric about 0 (i.e. normals mapped to \[0, 1\] are *not* acceptable
+and must be remapped to e.g. \[−1, 1\]).
+
+Similar to the albedo, the normal can be stored for either the first or
+a subsequent hit (if the first hit has a perfect specular/delta BSDF).
+
+
+Example normal image obtained using the first hit (the values are
+actually in \[−1, 1\] but were mapped to \[0, 1\] for illustration
+purposes).
+
+
+Example normal image obtained using the first diffuse or glossy
+(non-delta) hit. Note that the normals of perfect specular (delta)
+transparent surfaces are computed as the Fresnel blend of the reflected
+and transmitted
+normals.
+
+# Examples
+
+## Denoise
+
+A minimal working example demonstrating how to use Open Image Denoise
+can be found at `examples/denoise.cpp`, which uses the C++11 convenience
+wrappers of the C99 API.
+
+This example is a simple command-line application that denoises the
+provided image, which can optionally have auxiliary feature images as
+well (e.g. albedo and normal). The images must be stored in the
+[Portable FloatMap](http://www.pauldebevec.com/Research/HDR/PFM/) (PFM)
+format, and the color values must be encoded in little-endian format.
+
+Running `./denoise` without any arguments will bring up a list of
+command line options.
diff --git a/oidn/cmake/install.cmake b/oidn/cmake/install.cmake
new file mode 100644
index 0000000..fb018da
--- /dev/null
+++ b/oidn/cmake/install.cmake
@@ -0,0 +1,94 @@
+## ======================================================================== ##
+## Copyright 2009-2019 Intel Corporation ##
+## ##
+## Licensed under the Apache License, Version 2.0 (the "License"); ##
+## you may not use this file except in compliance with the License. ##
+## You may obtain a copy of the License at ##
+## ##
+## http://www.apache.org/licenses/LICENSE-2.0 ##
+## ##
+## Unless required by applicable law or agreed to in writing, software ##
+## distributed under the License is distributed on an "AS IS" BASIS, ##
+## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ##
+## See the License for the specific language governing permissions and ##
+## limitations under the License. ##
+## ======================================================================== ##
+
+## ----------------------------------------------------------------------------
+## Install library
+## ----------------------------------------------------------------------------
+
+install(TARGETS ${PROJECT_NAME}
+ EXPORT
+ ${PROJECT_NAME}_Export
+ ARCHIVE
+ DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT devel
+ LIBRARY
+ DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT devel
+ # On Windows put the dlls into bin
+ RUNTIME
+ DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT lib
+)
+
+if(OIDN_STATIC_LIB)
+ install(TARGETS common mkldnn
+ EXPORT
+ ${PROJECT_NAME}_Export
+ ARCHIVE
+ DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT devel
+ )
+endif()
+
+## ----------------------------------------------------------------------------
+## Install headers
+## ----------------------------------------------------------------------------
+
+install(DIRECTORY include/OpenImageDenoise
+ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
+ COMPONENT devel
+ PATTERN "*.in" EXCLUDE
+)
+
+## ----------------------------------------------------------------------------
+## Install documentation
+## ----------------------------------------------------------------------------
+
+install(FILES ${PROJECT_SOURCE_DIR}/LICENSE.txt DESTINATION ${CMAKE_INSTALL_DOCDIR} COMPONENT lib)
+install(FILES ${PROJECT_SOURCE_DIR}/CHANGELOG.md DESTINATION ${CMAKE_INSTALL_DOCDIR} COMPONENT lib)
+install(FILES ${PROJECT_SOURCE_DIR}/README.md DESTINATION ${CMAKE_INSTALL_DOCDIR} COMPONENT lib)
+install(FILES ${PROJECT_SOURCE_DIR}/readme.pdf DESTINATION ${CMAKE_INSTALL_DOCDIR} COMPONENT lib)
+
+## ----------------------------------------------------------------------------
+## Install dependencies
+## ----------------------------------------------------------------------------
+
+# Install TBB
+if(OIDN_ZIP_MODE)
+ if(WIN32)
+ install(PROGRAMS ${TBB_BIN_DIR}/tbb.dll ${TBB_BIN_DIR}/tbbmalloc.dll DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT lib)
+ install(PROGRAMS ${TBB_LIBRARY} ${TBB_LIBRARY_MALLOC} DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT lib)
+ elseif(APPLE)
+ install(PROGRAMS ${TBB_ROOT}/lib/libtbb.dylib ${TBB_ROOT}/lib/libtbbmalloc.dylib DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT lib)
+ else()
+ install(PROGRAMS ${TBB_ROOT}/lib/intel64/gcc4.4/libtbb.so.2 ${TBB_ROOT}/lib/intel64/gcc4.4/libtbbmalloc.so.2 DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT lib)
+ endif()
+endif()
+
+## ----------------------------------------------------------------------------
+## Install CMake configuration files
+## ----------------------------------------------------------------------------
+
+install(EXPORT ${PROJECT_NAME}_Export
+ DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}
+ #NAMESPACE ${PROJECT_NAME}::
+ FILE ${PROJECT_NAME}Config.cmake
+ COMPONENT devel
+)
+
+include(CMakePackageConfigHelpers)
+write_basic_package_version_file(${PROJECT_NAME}ConfigVersion.cmake
+ COMPATIBILITY SameMajorVersion)
+install(FILES ${CMAKE_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake
+ DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}
+ COMPONENT devel
+)
diff --git a/oidn/cmake/package.cmake b/oidn/cmake/package.cmake
new file mode 100644
index 0000000..ded24ba
--- /dev/null
+++ b/oidn/cmake/package.cmake
@@ -0,0 +1,106 @@
+## ======================================================================== ##
+## Copyright 2009-2019 Intel Corporation ##
+## ##
+## Licensed under the Apache License, Version 2.0 (the "License"); ##
+## you may not use this file except in compliance with the License. ##
+## You may obtain a copy of the License at ##
+## ##
+## http://www.apache.org/licenses/LICENSE-2.0 ##
+## ##
+## Unless required by applicable law or agreed to in writing, software ##
+## distributed under the License is distributed on an "AS IS" BASIS, ##
+## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ##
+## See the License for the specific language governing permissions and ##
+## limitations under the License. ##
+## ======================================================================== ##
+
+option(OIDN_ZIP_MODE off)
+mark_as_advanced(OIDN_ZIP_MODE)
+
+## ----------------------------------------------------------------------------
+## Set install directories
+## ----------------------------------------------------------------------------
+
+include(GNUInstallDirs)
+
+if(OIDN_ZIP_MODE)
+ set(CMAKE_INSTALL_BINDIR bin)
+ set(CMAKE_INSTALL_LIBDIR lib)
+ set(CMAKE_INSTALL_DOCDIR doc)
+endif()
+
+## ----------------------------------------------------------------------------
+## Set rpath
+## ----------------------------------------------------------------------------
+
+if(OIDN_ZIP_MODE)
+ # In tgz / zip let's have relative rpath
+ set(CMAKE_SKIP_INSTALL_RPATH OFF)
+ if(APPLE)
+ set(CMAKE_MACOSX_RPATH ON)
+ set(CMAKE_INSTALL_RPATH "@executable_path/" "@executable_path/../lib")
+ else()
+ set(CMAKE_INSTALL_RPATH "\$ORIGIN:\$ORIGIN/../lib")
+ endif()
+else()
+ set(CMAKE_INSTALL_NAME_DIR ${CMAKE_INSTALL_FULL_LIBDIR})
+ if(APPLE)
+ # Use rpath on macOS
+ set(CMAKE_SKIP_INSTALL_RPATH OFF)
+ else()
+ # We do not want any rpath for installed binaries
+ set(CMAKE_SKIP_INSTALL_RPATH ON)
+ endif()
+endif()
+
+## ----------------------------------------------------------------------------
+## Configure CPack
+## ----------------------------------------------------------------------------
+
+set(CPACK_PACKAGE_NAME ${PROJECT_NAME})
+set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Open Image Denoise library")
+set(CPACK_PACKAGE_VENDOR "Intel Corporation")
+set(CPACK_PACKAGE_INSTALL_DIRECTORY ${CPACK_PACKAGE_NAME})
+set(CPACK_PACKAGE_VERSION ${PROJECT_VERSION})
+set(CPACK_PACKAGE_VERSION_MAJOR ${PROJECT_VERSION_MAJOR})
+set(CPACK_PACKAGE_VERSION_MINOR ${PROJECT_VERSION_MINOR})
+set(CPACK_PACKAGE_VERSION_PATCH ${PROJECT_VERSION_PATCH})
+set(CPACK_PACKAGE_FILE_NAME oidn-${CPACK_PACKAGE_VERSION})
+set(CPACK_VERBATIM_VARIABLES YES)
+
+if(WIN32)
+
+ # Windows specific settings
+ if(CMAKE_SIZEOF_VOID_P EQUAL 8)
+ set(ARCH x64)
+ set(CPACK_PACKAGE_NAME "${CPACK_PACKAGE_NAME} x64")
+ else()
+ set(ARCH win32)
+ set(CPACK_PACKAGE_NAME "${CPACK_PACKAGE_NAME} Win32")
+ endif()
+
+ if(MSVC12)
+ set(VCVER vc12)
+ elseif(MSVC14) # also for VC15, which is toolset v141
+ set(VCVER vc14)
+ endif()
+
+ set(CPACK_GENERATOR ZIP)
+ set(CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_FILE_NAME}.${ARCH}.${VCVER}.windows")
+ set(CPACK_MONOLITHIC_INSTALL 1)
+
+elseif(APPLE)
+
+ # macOS specific settings
+ set(CPACK_GENERATOR TGZ)
+ set(CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_FILE_NAME}.x86_64.macos")
+ set(CPACK_MONOLITHIC_INSTALL 1)
+
+else()
+
+ # Linux specific settings
+ set(CPACK_GENERATOR TGZ)
+ set(CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_FILE_NAME}.x86_64.linux")
+ set(CPACK_MONOLITHIC_INSTALL 1)
+
+endif()
\ No newline at end of file
diff --git a/oidn/cmake/resource.cmake b/oidn/cmake/resource.cmake
new file mode 100644
index 0000000..6a4ac46
--- /dev/null
+++ b/oidn/cmake/resource.cmake
@@ -0,0 +1,39 @@
+## ======================================================================== ##
+## Copyright 2009-2019 Intel Corporation ##
+## ##
+## Licensed under the Apache License, Version 2.0 (the "License"); ##
+## you may not use this file except in compliance with the License. ##
+## You may obtain a copy of the License at ##
+## ##
+## http://www.apache.org/licenses/LICENSE-2.0 ##
+## ##
+## Unless required by applicable law or agreed to in writing, software ##
+## distributed under the License is distributed on an "AS IS" BASIS, ##
+## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ##
+## See the License for the specific language governing permissions and ##
+## limitations under the License. ##
+## ======================================================================== ##
+
+# Generates C++ files from the specified binary resource files
+find_package(PythonInterp REQUIRED)
+function(generate_cpp_resources out_sources namespace)
+ set(${out_sources})
+ foreach(in_file ${ARGN})
+ get_filename_component(in_file_we ${in_file} NAME_WE)
+ get_filename_component(in_dir ${in_file} PATH)
+ get_filename_component(in_path ${in_file} ABSOLUTE)
+ set(out_dir ${CMAKE_CURRENT_BINARY_DIR}/${in_dir})
+ set(out_path ${out_dir}/${in_file_we}.cpp)
+ list(APPEND ${out_sources} ${out_path})
+ add_custom_command(
+ OUTPUT ${out_path}
+ COMMAND ${CMAKE_COMMAND} -E make_directory ${out_dir}
+ COMMAND ${PYTHON_EXECUTABLE}
+ ARGS ${PROJECT_SOURCE_DIR}/scripts/resource_to_cpp.py ${in_path} -o ${out_path} -n ${namespace}
+ DEPENDS ${in_path}
+ COMMENT "Generating CXX resource object ${out_path}"
+ VERBATIM)
+ endforeach()
+ set_source_files_properties(${${out_sources}} PROPERTIES GENERATED TRUE)
+ set(${out_sources} ${${out_sources}} PARENT_SCOPE)
+endfunction()
diff --git a/oidn/common/CMakeLists.txt b/oidn/common/CMakeLists.txt
new file mode 100644
index 0000000..955f30c
--- /dev/null
+++ b/oidn/common/CMakeLists.txt
@@ -0,0 +1,47 @@
+## ======================================================================== ##
+## Copyright 2009-2019 Intel Corporation ##
+## ##
+## Licensed under the Apache License, Version 2.0 (the "License"); ##
+## you may not use this file except in compliance with the License. ##
+## You may obtain a copy of the License at ##
+## ##
+## http://www.apache.org/licenses/LICENSE-2.0 ##
+## ##
+## Unless required by applicable law or agreed to in writing, software ##
+## distributed under the License is distributed on an "AS IS" BASIS, ##
+## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ##
+## See the License for the specific language governing permissions and ##
+## limitations under the License. ##
+## ======================================================================== ##
+
+add_library(common STATIC
+ platform.h
+ platform.cpp
+ exception.h
+ ref.h
+ barrier.h
+ timer.h
+ thread.h
+ thread.cpp
+ tasking.h
+ tasking.cpp
+ tensor.h
+ tensor.cpp
+)
+
+if(OIDN_STATIC_LIB)
+ target_compile_definitions(common PUBLIC -DOIDN_STATIC_LIB)
+endif()
+
+target_include_directories(common
+ PUBLIC
+ $
+)
+
+target_link_libraries(common PUBLIC ${TBB_LIBRARIES})
+if(UNIX)
+ target_link_libraries(common PUBLIC pthread)
+ if(NOT(APPLE))
+ target_link_libraries(common PUBLIC rt)
+ endif()
+endif()
diff --git a/oidn/common/barrier.h b/oidn/common/barrier.h
new file mode 100644
index 0000000..b20f670
--- /dev/null
+++ b/oidn/common/barrier.h
@@ -0,0 +1,52 @@
+// ======================================================================== //
+// Copyright 2009-2019 Intel Corporation //
+// //
+// Licensed under the Apache License, Version 2.0 (the "License"); //
+// you may not use this file except in compliance with the License. //
+// You may obtain a copy of the License at //
+// //
+// http://www.apache.org/licenses/LICENSE-2.0 //
+// //
+// Unless required by applicable law or agreed to in writing, software //
+// distributed under the License is distributed on an "AS IS" BASIS, //
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
+// See the License for the specific language governing permissions and //
+// limitations under the License. //
+// ======================================================================== //
+
+#pragma once
+
+#include "platform.h"
+#include
+#include
+
+namespace oidn {
+
+ class Barrier
+ {
+ private:
+ std::mutex m;
+ std::condition_variable cv;
+ volatile int count;
+
+ public:
+ Barrier(int count) : count(count) {}
+
+ void wait()
+ {
+ std::unique_lock lk(m);
+ count--;
+
+ if (count == 0)
+ {
+ lk.unlock();
+ cv.notify_all();
+ }
+ else
+ {
+ cv.wait(lk, [&]{ return count == 0; });
+ }
+ }
+ };
+
+} // namespace oidn
diff --git a/oidn/common/exception.h b/oidn/common/exception.h
new file mode 100644
index 0000000..18069c6
--- /dev/null
+++ b/oidn/common/exception.h
@@ -0,0 +1,45 @@
+// ======================================================================== //
+// Copyright 2009-2019 Intel Corporation //
+// //
+// Licensed under the Apache License, Version 2.0 (the "License"); //
+// you may not use this file except in compliance with the License. //
+// You may obtain a copy of the License at //
+// //
+// http://www.apache.org/licenses/LICENSE-2.0 //
+// //
+// Unless required by applicable law or agreed to in writing, software //
+// distributed under the License is distributed on an "AS IS" BASIS, //
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
+// See the License for the specific language governing permissions and //
+// limitations under the License. //
+// ======================================================================== //
+
+#pragma once
+
+#include
+#include "platform.h"
+
+namespace oidn {
+
+ class Exception : public std::exception
+ {
+ private:
+ Error error;
+ const char* message;
+
+ public:
+ Exception(Error error, const char* message)
+ : error(error), message(message) {}
+
+ Error code() const noexcept
+ {
+ return error;
+ }
+
+ const char* what() const noexcept override
+ {
+ return message;
+ }
+ };
+
+} // namespace oidn
diff --git a/oidn/common/platform.cpp b/oidn/common/platform.cpp
new file mode 100644
index 0000000..59a14ff
--- /dev/null
+++ b/oidn/common/platform.cpp
@@ -0,0 +1,114 @@
+// ======================================================================== //
+// Copyright 2009-2019 Intel Corporation //
+// //
+// Licensed under the Apache License, Version 2.0 (the "License"); //
+// you may not use this file except in compliance with the License. //
+// You may obtain a copy of the License at //
+// //
+// http://www.apache.org/licenses/LICENSE-2.0 //
+// //
+// Unless required by applicable law or agreed to in writing, software //
+// distributed under the License is distributed on an "AS IS" BASIS, //
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
+// See the License for the specific language governing permissions and //
+// limitations under the License. //
+// ======================================================================== //
+
+#include "platform.h"
+
+namespace oidn {
+
+ // ----------------------------------------------------------------------------
+ // Common functions
+ // ----------------------------------------------------------------------------
+
+ void* alignedMalloc(size_t size, size_t alignment)
+ {
+ if (size == 0)
+ return nullptr;
+
+ assert((alignment & (alignment-1)) == 0);
+ void* ptr = _mm_malloc(size, alignment);
+
+ if (ptr == nullptr)
+ throw std::bad_alloc();
+
+ return ptr;
+ }
+
+ void alignedFree(void* ptr)
+ {
+ if (ptr)
+ _mm_free(ptr);
+ }
+
+ // ----------------------------------------------------------------------------
+ // System information
+ // ----------------------------------------------------------------------------
+
+ std::string getPlatformName()
+ {
+ std::string name;
+
+ #if defined(__linux__)
+ name = "Linux";
+ #elif defined(__FreeBSD__)
+ name = "FreeBSD";
+ #elif defined(__CYGWIN__)
+ name = "Cygwin";
+ #elif defined(_WIN32)
+ name = "Windows";
+ #elif defined(__APPLE__)
+ name = "macOS";
+ #elif defined(__unix__)
+ name = "Unix";
+ #else
+ return "Unknown";
+ #endif
+
+ #if defined(__x86_64__) || defined(_M_X64) || defined(__ia64__) || defined(__aarch64__)
+ name += " (64-bit)";
+ #else
+ name += " (32-bit)";
+ #endif
+
+ return name;
+ }
+
+ std::string getCompilerName()
+ {
+ #if defined(__INTEL_COMPILER)
+ int mayor = __INTEL_COMPILER / 100 % 100;
+ int minor = __INTEL_COMPILER % 100;
+ std::string version = "Intel Compiler ";
+ version += toString(mayor);
+ version += "." + toString(minor);
+ #if defined(__INTEL_COMPILER_UPDATE)
+ version += "." + toString(__INTEL_COMPILER_UPDATE);
+ #endif
+ return version;
+ #elif defined(__clang__)
+ return "Clang " __clang_version__;
+ #elif defined(__GNUC__)
+ return "GCC " __VERSION__;
+ #elif defined(_MSC_VER)
+ std::string version = toString(_MSC_FULL_VER);
+ version.insert(4, ".");
+ version.insert(9, ".");
+ version.insert(2, ".");
+ return "Visual C++ Compiler " + version;
+ #else
+ return "Unknown";
+ #endif
+ }
+
+ std::string getBuildName()
+ {
+ #if defined(NDEBUG)
+ return "Release";
+ #else
+ return "Debug";
+ #endif
+ }
+
+} // namespace oidn
diff --git a/oidn/common/platform.h b/oidn/common/platform.h
new file mode 100644
index 0000000..a9dd871
--- /dev/null
+++ b/oidn/common/platform.h
@@ -0,0 +1,131 @@
+// ======================================================================== //
+// Copyright 2009-2019 Intel Corporation //
+// //
+// Licensed under the Apache License, Version 2.0 (the "License"); //
+// you may not use this file except in compliance with the License. //
+// You may obtain a copy of the License at //
+// //
+// http://www.apache.org/licenses/LICENSE-2.0 //
+// //
+// Unless required by applicable law or agreed to in writing, software //
+// distributed under the License is distributed on an "AS IS" BASIS, //
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
+// See the License for the specific language governing permissions and //
+// limitations under the License. //
+// ======================================================================== //
+
+#pragma once
+
+#if defined(_WIN32)
+ #define WIN32_LEAN_AND_MEAN
+ #define NOMINMAX
+ #include
+#elif defined(__APPLE__)
+ #include
+#endif
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include "include/OpenImageDenoise/oidn.hpp"
+
+namespace oidn {
+
+ // ----------------------------------------------------------------------------
+ // Macros
+ // ----------------------------------------------------------------------------
+
+ #if defined(_WIN32)
+ // Windows
+ #if !defined(__noinline)
+ #define __noinline __declspec(noinline)
+ #endif
+ #else
+ // Unix
+ #if !defined(__forceinline)
+ #define __forceinline inline __attribute__((always_inline))
+ #endif
+ #if !defined(__noinline)
+ #define __noinline __attribute__((noinline))
+ #endif
+ #endif
+
+ #ifndef UNUSED
+ #define UNUSED(x) ((void)x)
+ #endif
+ #ifndef MAYBE_UNUSED
+ #define MAYBE_UNUSED(x) UNUSED(x)
+ #endif
+
+ // ----------------------------------------------------------------------------
+ // Error handling and debugging
+ // ----------------------------------------------------------------------------
+
+ struct Verbose
+ {
+ int verbose;
+
+ Verbose(int v = 0) : verbose(v) {}
+ __forceinline bool isVerbose(int v = 1) const { return v <= verbose; }
+ };
+
+ #define OIDN_WARNING(message) { if (isVerbose()) std::cerr << "Warning: " << message << std::endl; }
+ #define OIDN_FATAL(message) throw std::runtime_error(message);
+
+ // ----------------------------------------------------------------------------
+ // Common functions
+ // ----------------------------------------------------------------------------
+
+ using std::min;
+ using std::max;
+
+ template
+ __forceinline T clamp(const T& value, const T& minValue, const T& maxValue)
+ {
+ return min(max(value, minValue), maxValue);
+ }
+
+ void* alignedMalloc(size_t size, size_t alignment);
+ void alignedFree(void* ptr);
+
+ template
+ inline std::string toString(const T& a)
+ {
+ std::stringstream sm;
+ sm << a;
+ return sm.str();
+ }
+
+#if defined(__APPLE__)
+ template
+ bool getSysctl(const char* name, T& value)
+ {
+ int64_t result = 0;
+ size_t size = sizeof(result);
+
+ if (sysctlbyname(name, &result, &size, nullptr, 0) != 0)
+ return false;
+
+ value = T(result);
+ return true;
+ }
+#endif
+
+ // ----------------------------------------------------------------------------
+ // System information
+ // ----------------------------------------------------------------------------
+
+ std::string getPlatformName();
+ std::string getCompilerName();
+ std::string getBuildName();
+
+} // namespace oidn
+
diff --git a/oidn/common/ref.h b/oidn/common/ref.h
new file mode 100644
index 0000000..8b2b2de
--- /dev/null
+++ b/oidn/common/ref.h
@@ -0,0 +1,163 @@
+// ======================================================================== //
+// Copyright 2009-2019 Intel Corporation //
+// //
+// Licensed under the Apache License, Version 2.0 (the "License"); //
+// you may not use this file except in compliance with the License. //
+// You may obtain a copy of the License at //
+// //
+// http://www.apache.org/licenses/LICENSE-2.0 //
+// //
+// Unless required by applicable law or agreed to in writing, software //
+// distributed under the License is distributed on an "AS IS" BASIS, //
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
+// See the License for the specific language governing permissions and //
+// limitations under the License. //
+// ======================================================================== //
+
+#pragma once
+
+#include "platform.h"
+
+namespace oidn {
+
+ class RefCount
+ {
+ private:
+ std::atomic count;
+
+ public:
+ __forceinline RefCount(int count = 0) noexcept : count(count) {}
+
+ __forceinline size_t incRef() noexcept
+ {
+ return count.fetch_add(1) + 1;
+ }
+
+ __forceinline size_t decRef()
+ {
+ const size_t newCount = decRefKeep();
+ if (newCount == 0)
+ destroy();
+ return newCount;
+ }
+
+ __forceinline size_t decRefKeep() noexcept
+ {
+ return count.fetch_add(-1) - 1;
+ }
+
+ __forceinline void destroy()
+ {
+ delete this;
+ }
+
+ protected:
+ // Disable copying
+ RefCount(const RefCount&) = delete;
+ RefCount& operator =(const RefCount&) = delete;
+
+ virtual ~RefCount() noexcept = default;
+ };
+
+ template
+ class Ref
+ {
+ private:
+ T* ptr;
+
+ public:
+ __forceinline Ref() noexcept : ptr(nullptr) {}
+ __forceinline Ref(std::nullptr_t) noexcept : ptr(nullptr) {}
+ __forceinline Ref(const Ref& other) noexcept : ptr(other.ptr) { if (ptr) ptr->incRef(); }
+ __forceinline Ref(Ref&& other) noexcept : ptr(other.ptr) { other.ptr = nullptr; }
+ __forceinline Ref(T* ptr) noexcept : ptr(ptr) { if (ptr) ptr->incRef(); }
+
+ template
+ __forceinline Ref(const Ref& other) noexcept : ptr(other.get()) { if (ptr) ptr->incRef(); }
+
+ template
+ __forceinline explicit Ref(Y* ptr) noexcept : ptr(ptr) { if (ptr) ptr->incRef(); }
+
+ __forceinline ~Ref() { if (ptr) ptr->decRef(); }
+
+ __forceinline Ref& operator =(const Ref& other)
+ {
+ if (other.ptr)
+ other.ptr->incRef();
+ if (ptr)
+ ptr->decRef();
+ ptr = other.ptr;
+ return *this;
+ }
+
+ __forceinline Ref& operator =(Ref&& other)
+ {
+ if (ptr)
+ ptr->decRef();
+ ptr = other.ptr;
+ other.ptr = nullptr;
+ return *this;
+ }
+
+ __forceinline Ref& operator =(T* other)
+ {
+ if (other)
+ other->incRef();
+ if (ptr)
+ ptr->decRef();
+ ptr = other;
+ return *this;
+ }
+
+ __forceinline Ref& operator =(std::nullptr_t)
+ {
+ if (ptr)
+ ptr->decRef();
+ ptr = nullptr;
+ return *this;
+ }
+
+ __forceinline operator bool() const noexcept { return ptr != nullptr; }
+
+ __forceinline T& operator *() const noexcept { return *ptr; }
+ __forceinline T* operator ->() const noexcept { return ptr; }
+
+ __forceinline T* get() const noexcept { return ptr; }
+
+ __forceinline T* detach() noexcept
+ {
+ T* res = ptr;
+ ptr = nullptr;
+ return res;
+ }
+ };
+
+ template __forceinline bool operator < (const Ref& a, const Ref& b) noexcept { return a.ptr < b.ptr; }
+
+ template __forceinline bool operator ==(const Ref& a, std::nullptr_t) noexcept { return a.ptr == nullptr; }
+ template __forceinline bool operator ==(std::nullptr_t, const Ref& b) noexcept { return nullptr == b.ptr; }
+ template __forceinline bool operator ==(const Ref& a, const Ref& b) noexcept { return a.ptr == b.ptr; }
+
+ template __forceinline bool operator !=(const Ref& a, std::nullptr_t) noexcept { return a.ptr != nullptr; }
+ template __forceinline bool operator !=(std::nullptr_t, const Ref& b) noexcept { return nullptr != b.ptr; }
+ template __forceinline bool operator !=(const Ref& a, const Ref& b) noexcept { return a.ptr != b.ptr; }
+
+ template
+ __forceinline Ref makeRef(Args&&... args)
+ {
+ return Ref(new T(std::forward(args)...));
+ }
+
+ template
+ __forceinline Ref staticRefCast(const Ref& a)
+ {
+ return Ref(static_cast(a.get()));
+ }
+
+ template
+ __forceinline Ref dynamicRefCast(const Ref& a)
+ {
+ return Ref(dynamic_cast(a.get()));
+ }
+
+} // namespace oidn
diff --git a/oidn/common/tasking.cpp b/oidn/common/tasking.cpp
new file mode 100644
index 0000000..e30c179
--- /dev/null
+++ b/oidn/common/tasking.cpp
@@ -0,0 +1,55 @@
+// ======================================================================== //
+// Copyright 2009-2019 Intel Corporation //
+// //
+// Licensed under the Apache License, Version 2.0 (the "License"); //
+// you may not use this file except in compliance with the License. //
+// You may obtain a copy of the License at //
+// //
+// http://www.apache.org/licenses/LICENSE-2.0 //
+// //
+// Unless required by applicable law or agreed to in writing, software //
+// distributed under the License is distributed on an "AS IS" BASIS, //
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
+// See the License for the specific language governing permissions and //
+// limitations under the License. //
+// ======================================================================== //
+
+#include "tasking.h"
+
+namespace oidn {
+
+ // --------------------------------------------------------------------------
+ // PinningObserver
+ // --------------------------------------------------------------------------
+
+ PinningObserver::PinningObserver(const std::shared_ptr& affinity)
+ : affinity(affinity)
+ {
+ observe(true);
+ }
+
+ PinningObserver::PinningObserver(const std::shared_ptr& affinity, tbb::task_arena& arena)
+ : tbb::task_scheduler_observer(arena),
+ affinity(affinity)
+ {
+ observe(true);
+ }
+
+ PinningObserver::~PinningObserver()
+ {
+ observe(false);
+ }
+
+ void PinningObserver::on_scheduler_entry(bool isWorker)
+ {
+ const int threadIndex = tbb::this_task_arena::current_thread_index();
+ affinity->set(threadIndex);
+ }
+
+ void PinningObserver::on_scheduler_exit(bool isWorker)
+ {
+ const int threadIndex = tbb::this_task_arena::current_thread_index();
+ affinity->restore(threadIndex);
+ }
+
+} // namespace oidn
diff --git a/oidn/common/tasking.h b/oidn/common/tasking.h
new file mode 100644
index 0000000..3856bee
--- /dev/null
+++ b/oidn/common/tasking.h
@@ -0,0 +1,50 @@
+// ======================================================================== //
+// Copyright 2009-2019 Intel Corporation //
+// //
+// Licensed under the Apache License, Version 2.0 (the "License"); //
+// you may not use this file except in compliance with the License. //
+// You may obtain a copy of the License at //
+// //
+// http://www.apache.org/licenses/LICENSE-2.0 //
+// //
+// Unless required by applicable law or agreed to in writing, software //
+// distributed under the License is distributed on an "AS IS" BASIS, //
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
+// See the License for the specific language governing permissions and //
+// limitations under the License. //
+// ======================================================================== //
+
+#pragma once
+
+#include "thread.h"
+
+#define TBB_PREVIEW_LOCAL_OBSERVER 1
+#include "tbb/task_scheduler_init.h"
+#include "tbb/task_scheduler_observer.h"
+#include "tbb/task_arena.h"
+#include "tbb/parallel_for.h"
+#include "tbb/parallel_reduce.h"
+#include "tbb/blocked_range.h"
+#include "tbb/blocked_range2d.h"
+
+namespace oidn {
+
+ // --------------------------------------------------------------------------
+ // PinningObserver
+ // --------------------------------------------------------------------------
+
+ class PinningObserver : public tbb::task_scheduler_observer
+ {
+ private:
+ std::shared_ptr affinity;
+
+ public:
+ explicit PinningObserver(const std::shared_ptr& affinity);
+ PinningObserver(const std::shared_ptr& affinity, tbb::task_arena& arena);
+ ~PinningObserver();
+
+ void on_scheduler_entry(bool isWorker) override;
+ void on_scheduler_exit(bool isWorker) override;
+ };
+
+} // namespace oidn
diff --git a/oidn/common/tensor.cpp b/oidn/common/tensor.cpp
new file mode 100644
index 0000000..0249f2e
--- /dev/null
+++ b/oidn/common/tensor.cpp
@@ -0,0 +1,83 @@
+// ======================================================================== //
+// Copyright 2009-2019 Intel Corporation //
+// //
+// Licensed under the Apache License, Version 2.0 (the "License"); //
+// you may not use this file except in compliance with the License. //
+// You may obtain a copy of the License at //
+// //
+// http://www.apache.org/licenses/LICENSE-2.0 //
+// //
+// Unless required by applicable law or agreed to in writing, software //
+// distributed under the License is distributed on an "AS IS" BASIS, //
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
+// See the License for the specific language governing permissions and //
+// limitations under the License. //
+// ======================================================================== //
+
+#include "exception.h"
+#include "tensor.h"
+
+namespace oidn {
+
+ std::map parseTensors(void* buffer)
+ {
+ char* input = (char*)buffer;
+
+ // Parse the magic value
+ const int magic = *(unsigned short*)input;
+ if (magic != 0x41D7)
+ throw Exception(Error::InvalidOperation, "invalid tensor archive");
+ input += sizeof(unsigned short);
+
+ // Parse the version
+ const int majorVersion = *(unsigned char*)input++;
+ const int minorVersion = *(unsigned char*)input++;
+ UNUSED(minorVersion);
+ if (majorVersion > 1)
+ throw Exception(Error::InvalidOperation, "unsupported tensor archive version");
+
+ // Parse the number of tensors
+ const int numTensors = *(int*)input;
+ input += sizeof(int);
+
+ // Parse the tensors
+ std::map tensorMap;
+ for (int i = 0; i < numTensors; ++i)
+ {
+ Tensor tensor;
+
+ // Parse the name
+ const int nameLen = *(unsigned char*)input++;
+ std::string name(input, nameLen);
+ input += nameLen;
+
+ // Parse the number of dimensions
+ const int ndims = *(unsigned char*)input++;
+
+ // Parse the shape of the tensor
+ tensor.dims.resize(ndims);
+ for (int i = 0; i < ndims; ++i)
+ tensor.dims[i] = ((int*)input)[i];
+ input += ndims * sizeof(int);
+
+ // Parse the format of the tensor
+ tensor.format = std::string(input, input + ndims);
+ input += ndims;
+
+ // Parse the data type of the tensor
+ const char type = *(unsigned char*)input++;
+ if (type != 'f') // only float32 is supported
+ throw Exception(Error::InvalidOperation, "unsupported tensor data type");
+
+ // Skip the data
+ tensor.data = (float*)input;
+ input += tensor.size() * sizeof(float);
+
+ // Add the tensor to the map
+ tensorMap.emplace(name, std::move(tensor));
+ }
+
+ return tensorMap;
+ }
+
+} // namespace oidn
diff --git a/oidn/common/tensor.h b/oidn/common/tensor.h
new file mode 100644
index 0000000..48e7d11
--- /dev/null
+++ b/oidn/common/tensor.h
@@ -0,0 +1,66 @@
+// ======================================================================== //
+// Copyright 2009-2019 Intel Corporation //
+// //
+// Licensed under the Apache License, Version 2.0 (the "License"); //
+// you may not use this file except in compliance with the License. //
+// You may obtain a copy of the License at //
+// //
+// http://www.apache.org/licenses/LICENSE-2.0 //
+// //
+// Unless required by applicable law or agreed to in writing, software //
+// distributed under the License is distributed on an "AS IS" BASIS, //
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
+// See the License for the specific language governing permissions and //
+// limitations under the License. //
+// ======================================================================== //
+
+#pragma once
+
+#include "platform.h"
+#include
+#include