diff --git a/.gitignore b/.gitignore index be5f812..60584db 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,6 @@ [Aa]ssets/[Tt]emp thirdparty/gvdb-voxels/ -instancer_hda/scenes/backup \ No newline at end of file +instancer_hda/scenes/backup + +*.pdb \ No newline at end of file diff --git a/.gitmodules b/.gitmodules index 805b1f4..b8972d2 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,6 @@ [submodule "thirdparty/cuda-noise"] path = thirdparty/cuda-noise url = https://github.com/sergeneren/cuda-noise +[submodule "vcpkg"] + path = vcpkg + url = https://github.com/microsoft/vcpkg diff --git a/CMakeLists.txt b/CMakeLists.txt index 8e78492..7d0dd6b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,28 +1,34 @@ -cmake_minimum_required(VERSION 3.8.0 FATAL_ERROR) +cmake_minimum_required(VERSION 3.23.0 FATAL_ERROR) project(VPT LANGUAGES CXX CUDA) set(CMAKE_INCLUDE_CURRENT_DIR ON) -set(_VCPKG_INCLUDE_DIR "${_VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}/include/") - ################################################################## ## Set output directories -set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/vpt/lib) -set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/vpt/lib) -set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/vpt/bin) +set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) +set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) + +set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_DEBUG ${CMAKE_BINARY_DIR}/lib) +set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_DEBUG ${CMAKE_BINARY_DIR}/lib) +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_BINARY_DIR}/bin) -set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_DEBUG ${CMAKE_BINARY_DIR}/vpt/lib) -set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_DEBUG ${CMAKE_BINARY_DIR}/vpt/lib) -set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_BINARY_DIR}/vpt/bin) +set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_RELEASE ${CMAKE_BINARY_DIR}/lib) +set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_RELEASE ${CMAKE_BINARY_DIR}/lib) +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_BINARY_DIR}/bin) -set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_RELEASE ${CMAKE_BINARY_DIR}/vpt/lib) -set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_RELEASE ${CMAKE_BINARY_DIR}/vpt/lib) -set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_BINARY_DIR}/vpt/bin) +set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_RELWITHDEBINFO ${CMAKE_BINARY_DIR}/lib) +set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_RELWITHDEBINFO ${CMAKE_BINARY_DIR}/lib) +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO ${CMAKE_BINARY_DIR}/bin) ################################################################## +set(_VCPKG_INCLUDE_DIR "${_VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}/include") +set(_VCPKG_LIB_DIR "${_VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}/lib") +set(_VCPKG_BIN_DIR "${_VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}/bin") + option (BUILD_VPT "Builds Volumetric Path Tracer" ON) option (BUILD_INSTANCER "Builds Houdini plugin to save instance files" OFF) @@ -39,7 +45,6 @@ elseif(${DebugLevel} STREQUAL "Log") endif() - if(BUILD_VPT) add_subdirectory(${CMAKE_SOURCE_DIR}/source) endif(BUILD_VPT) diff --git a/CMakePresets.json b/CMakePresets.json new file mode 100644 index 0000000..1a3354e --- /dev/null +++ b/CMakePresets.json @@ -0,0 +1,41 @@ +{ + "version": 4, + "cmakeMinimumRequired": { + "major": 3, + "minor": 25, + "patch": 0 + }, + "configurePresets": [ + { + "name": "Default", + "displayName": "Development Configuration", + "description": "Default configuration for dev environment", + "binaryDir": "${sourceDir}/build/", + "cacheVariables": { + "CMAKE_TOOLCHAIN_FILE": { + "type": "FILEPATH", + "value": "${sourceDir}/vcpkg/scripts/buildsystems/vcpkg.cmake" + }, + "BUILD_VPT": { + "type": "BOOLEAN", + "value": "ON" + }, + "OpenImageDenoise_DIR": "${sourceDir}/thirdparty/OpenImageDenoise/lib/cmake/OpenImageDenoise-2.1.0", + "CMAKE_CONFIGURATION_TYPES": "RelWithDebInfo", + "CMAKE_BUILD_TYPE": "RelWithDebInfo", + "VCPKG_INSTALLED_DIR": "${sourceDir}/vcpkg/vcpkg_installed", + "VCPKG_BUILD_TYPE": "release", + "VCPKG_TARGET_TRIPLET": "x64-windows" + } + } + ], + "buildPresets": [ + { + "name": "Default", + "configurePreset": "Default", + "displayName": "Build RelWithDebInfo", + "description": "Build RelWithDebInfo configuration", + "configuration": "RelWithDebInfo" + } + ] +} \ No newline at end of file diff --git a/README.md b/README.md index f601955..fa9b348 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,8 @@ v 1.0.2 Alpha ## Installation, Build and Usage -Please see [this](https://sergeneren.com/2020/01/07/using-vpt/) detailed article for installing building and using VPT +Use the `build_windows.cmd` file for building automatically on windows. Also see [this](https://sergeneren.com/2020/01/07/using-vpt/) detailed article for using VPT. +This repo is tested with Cuda 12.1 and Nvidia Driver 546.65 ## Author diff --git a/build_windows.cmd b/build_windows.cmd new file mode 100644 index 0000000..9bcfd90 --- /dev/null +++ b/build_windows.cmd @@ -0,0 +1,32 @@ +@echo off + +setlocal + +git submodule init +git submodule update + +if not exist ./vcpkg/vcpkg.exe ( + call ./vcpkg/bootstrap-vcpkg.bat +) + +if not exist ./vcpkg/vcpkg.exe ( + echo Unable to bootstrap vcpkg! + exit 1 +) + +if exist build rmdir /s /q build + +cmake --preset Default . +if errorlevel 1 ( + echo failed to configure + exit 1 +) + + +cmake --build ./build --preset Default +if errorlevel 1 ( + echo failed to build + exit 1 +) + +echo Successfully built VPT! You can find the executable under build/bin directory \ No newline at end of file diff --git a/source/CMakeLists.txt b/source/CMakeLists.txt index 15a0fc6..25f5011 100644 --- a/source/CMakeLists.txt +++ b/source/CMakeLists.txt @@ -1,22 +1,22 @@ set(CMAKE_INCLUDE_CURRENT_DIR ON) find_package(glfw3 CONFIG REQUIRED) +find_package(glew CONFIG REQUIRED) find_package(imgui CONFIG REQUIRED) +find_package(OpenVDB CONFIG REQUIRED) +find_package(OpenImageIO CONFIG REQUIRED) +find_package(tinyexr CONFIG REQUIRED) +find_package(tbb CONFIG REQUIRED) +find_package(OpenImageDenoise CONFIG REQUIRED) + include(${CMAKE_CURRENT_SOURCE_DIR}/Helpers.cmake) +include(${CMAKE_CURRENT_SOURCE_DIR}/CompileObj.cmake) ################################################################## # set external directories -set(THIRDPARTY_DIR "${CMAKE_SOURCE_DIR}/thirdparty/") - -#set OIDN libraries -set(OID_DIR "${THIRDPARTY_DIR}/OpenImageDenoise") -find_library(OIDN_LIB "OpenImageDenoise" "${OID_DIR}/lib") -find_library(OIDN_MKLDNN_LIB "mkldnn" "${OID_DIR}/lib") -find_library(OIDN_COMMON_LIB "common" "${OID_DIR}/lib") - -set(OIDN_LIBRARIES ${OIDN_LIB} ${OIDN_MKLDNN_LIB} ${OIDN_COMMON_LIB}) +set(THIRDPARTY_DIR "${CMAKE_SOURCE_DIR}/thirdparty") ##Set env mapping renders variable @@ -83,6 +83,9 @@ file ( GLOB GEOMETRY file ( GLOB BVH "${CMAKE_CURRENT_SOURCE_DIR}/bvh/*.h" "${CMAKE_CURRENT_SOURCE_DIR}/bvh/*.cpp" + ) + +file ( GLOB CUDA_FUNCTIONS "${CMAKE_CURRENT_SOURCE_DIR}/bvh/*.cu" ) @@ -102,6 +105,7 @@ file( GLOB IMGUI_IMPL_SOURCES set(SOURCE_FILES ${HEADERS} ${CUDA_SOURCES} + ${CUDA_FUNCTIONS} ${SOURCE_CPP} ${BVH} ${IMGUI_IMPL_SOURCES} @@ -113,7 +117,7 @@ set(SOURCE_FILES ## Group source files source_group(Cuda FILES ${CUDA_SOURCES}) -source_group(bvh FILES ${BVH}) +source_group(bvh FILES ${BVH} ${CUDA_FUNCTIONS}) source_group(Imgui FILES ${IMGUI_IMPL_SOURCES}) source_group(Helpers FILES ${COMMON} ${UTIL}) source_group(Atmosphere FILES ${ATMOSPHERE}) @@ -123,23 +127,42 @@ source_group(Geometry FILES ${GEOMETRY}) find_program(CUDA_NVCC_EXECUTABLE nvcc) message ( STATUS "Build CUDA kernels: ${CUDA_SOURCES}" ) -_COMPILEPTX ( SOURCES ${CUDA_SOURCES} +COMPILE_PTX ( SOURCES ${CUDA_SOURCES} TARGET_PATH ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} - GENERATED CUDA_PTX GENPATHS CUDA_PTX_PATHS - INCLUDE "${CMAKE_CURRENT_SOURCE_DIR},${_VCPKG_INCLUDE_DIR},${CMAKE_CURRENT_SOURCE_DIR}/common, ${THIRDPARTY_DIR}/cuda-noise/include, ${CMAKE_CURRENT_SOURCE_DIR}/gpu_vdb" + INCLUDE ${CMAKE_CURRENT_SOURCE_DIR} ${_VCPKG_INCLUDE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/common ${THIRDPARTY_DIR}/cuda-noise/include ${CMAKE_CURRENT_SOURCE_DIR}/gpu_vdb OPTIONS -arch=compute_61 -code=sm_61 --ptxas-options=-v -O3 --use_fast_math --maxrregcount=128) + +COMPILE_OBJ( + SOURCES ${CUDA_FUNCTIONS} + TYPE ${CMAKE_BUILD_TYPE} + TARGET_PATH ${CMAKE_BINARY_DIR}/lib + GENPATHS GEN_CUDA_FUNC_OBJS + INCLUDE ${CMAKE_CURRENT_SOURCE_DIR} ${_VCPKG_INCLUDE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/common ${THIRDPARTY_DIR}/cuda-noise/include ${CMAKE_CURRENT_SOURCE_DIR}/gpu_vdb +) +message(STATUS "Genrated cuda functions objects ${GEN_CUDA_FUNC_OBJS}") + ################################################################### ################################################################### add_executable(vpt ${SOURCE_FILES}) -target_link_libraries(vpt PRIVATE glfw imgui::imgui cudart cuda openvdb ${OIDN_LIBRARIES}) +target_link_libraries(vpt PRIVATE glfw GLEW::GLEW imgui::imgui cudart cuda OpenImageDenoise + TBB::tbb OpenVDB::openvdb opengl32 OpenImageIO::OpenImageIO ${OIDN_LIBRARIES} ${_VCPKG_LIB_DIR}/tinyexr.lib ${GEN_CUDA_FUNC_OBJS}) + set_target_properties(vpt PROPERTIES VS_GLOBAL_VcpkgEnabled true) +set_target_properties(vpt PROPERTIES VS_GLOBAL_VcpkgEnableManifest true) +target_compile_features(vpt PUBLIC cxx_std_17) + set_target_properties(vpt PROPERTIES CUDA_ARCHITECTURES "61;75;86") + +file ( GLOB OIDN_DLLS "${THIRDPARTY_DIR}/OpenImageDenoise/bin/*.dll" ) +add_custom_command( + TARGET vpt PRE_BUILD + COMMAND ${CMAKE_COMMAND} -E copy ${OIDN_DLLS} ${CMAKE_BINARY_DIR}/bin) + include_directories(${_VCPKG_INCLUDE_DIR}) include_directories(${CMAKE_SOURCE_DIR}) -include_directories(${CMAKE_CURRENT_SOURCE_DIR}/imgui) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/atmosphere) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/common) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/util) @@ -147,4 +170,4 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR}/gpu_vdb) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/bvh) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/geometry) include_directories(${THIRDPARTY_DIR}/cuda-noise/include) -include_directories(${OID_DIR}/include) +include_directories(${THIRDPARTY_DIR}/OpenImageDenoise/include) diff --git a/source/CompileObj.cmake b/source/CompileObj.cmake new file mode 100644 index 0000000..b16ee76 --- /dev/null +++ b/source/CompileObj.cmake @@ -0,0 +1,72 @@ + +#------------------------------------ CROSS-PLATFORM OBJ COMPILE + +FUNCTION( COMPILE_OBJ ) + set(options "") + set(oneValueArgs TARGET_PATH TYPE GENERATED GENPATHS) + set(multiValueArgs OPTIONS SOURCES ARCHS INCLUDE) + CMAKE_PARSE_ARGUMENTS( _FUNCTION "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + + # Match the bitness of the ptx to the bitness of the application + set( MACHINE "--machine=32" ) + if( CMAKE_SIZEOF_VOID_P EQUAL 8) + set( MACHINE "--machine=64" ) + endif() + unset ( CUBIN_FILES CACHE ) + unset ( CUBIN_FILES_PATH CACHE ) + unset ( EMBEDDED_FILES CACHE ) + + FOREACH(INCLUDE_DIR ${_FUNCTION_INCLUDE}) + set ( INCL ${INCL} "-I\"${INCLUDE_DIR}\"" ) + ENDFOREACH() + + set ( ARCHS -arch=sm_61 ) + + message(STATUS "Compiling for architecture ${ARCH}") + + file ( MAKE_DIRECTORY "${_FUNCTION_TARGET_PATH}" ) + string (REPLACE ";" " " _FUNCTION_OPTIONS "${_FUNCTION_OPTIONS}") + separate_arguments( _OPTS WINDOWS_COMMAND "${_FUNCTION_OPTIONS}" ) + message ( STATUS "NVCC Options: ${_FUNCTION_OPTIONS}" ) + message ( STATUS "NVCC Include: ${_FUNCTION_INCLUDE}" ) + + #Set initial options + set(_OPTS ${_OPTS} -Xcompiler "/EHsc,/Od,/Zi,/RTC1" ${ARCHS}) + + #Set debug or relase linking + if(_FUNCTION_TYPE MATCHES "Debug") + set(_OPTS ${_OPTS} -Xcompiler "/MDd") + else() + set(_OPTS ${_OPTS} -Xcompiler "/MD") + endif() + + set(_OPTS ${_OPTS} -w) + + FOREACH( input ${_FUNCTION_SOURCES} ) + get_filename_component( input_ext ${input} EXT ) + get_filename_component( input_without_ext ${input} NAME_WE ) + if ( ${input_ext} STREQUAL ".cu" ) + set(_EXT .lib) + + set( output "${input_without_ext}.lib" ) + set( output_with_path "${_FUNCTION_TARGET_PATH}/${input_without_ext}${_EXT}" ) + set( output_with_quote "\"${output_with_path}\"" ) + LIST( APPEND OBJ_FILES ${output} ) + LIST( APPEND OBJ_FILES_PATH ${output_with_path} ) + + message( STATUS "NVCC Compile: ${CUDA_NVCC_EXECUTABLE} ${MACHINE} --lib -cudart static ${DEBUG_FLAGS} ${_OPTS} ${input} -o ${output_with_path} WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}") + add_custom_command( + OUTPUT ${output_with_path} + MAIN_DEPENDENCY ${input} + DEPENDS ${_FILE_DEPENDENCY} + COMMAND ${CUDA_NVCC_EXECUTABLE} ${MACHINE} --compile ${DEBUG_FLAGS} ${OPT_FLAGS} ${_OPTS} ${input} ${INCL} -o ${output_with_quote} + WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" + ) + + endif() + ENDFOREACH( ) + + set( ${_FUNCTION_GENERATED} ${OBJ_FILES} PARENT_SCOPE) + set( ${_FUNCTION_GENPATHS} ${OBJ_FILES_PATH} PARENT_SCOPE) + +ENDFUNCTION() diff --git a/source/Helpers.cmake b/source/Helpers.cmake index 3afac9e..629a40d 100644 --- a/source/Helpers.cmake +++ b/source/Helpers.cmake @@ -1,309 +1,66 @@ -#----- copy_cuda_bins -# This macro copies all binaries for the CUDA library to the target executale location. -# -macro(_copy_cuda_bins projname ) - add_custom_command( - TARGET ${projname} POST_BUILD - COMMAND ${CMAKE_COMMAND} -E copy ${CUDA_DLL} $ - ) -endmacro() - -#------------------------------------ CROSS-PLATFORM PTX COMPILE -# -# _COMPILEPTX( SOURCES file1.cu file2.cu TARGET_PATH GENERATED_FILES ptx_sources NVCC_OPTIONS -arch=sm_20) -# Generates ptx files for the given source files. ptx_sources will contain the list of generated files. -# -FUNCTION( _COMPILEPTX ) +FUNCTION( COMPILE_PTX ) set(options "") - set(oneValueArgs TARGET_PATH GENERATED GENPATHS INCLUDE) - set(multiValueArgs OPTIONS SOURCES) - CMAKE_PARSE_ARGUMENTS( _COMPILEPTX "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + set(oneValueArgs TARGET_PATH) + set(multiValueArgs OPTIONS SOURCES INCLUDE) + CMAKE_PARSE_ARGUMENTS( _FUNCTION "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) # Match the bitness of the ptx to the bitness of the application set( MACHINE "--machine=32" ) if( CMAKE_SIZEOF_VOID_P EQUAL 8) set( MACHINE "--machine=64" ) endif() - unset ( PTX_FILES CACHE ) - unset ( PTX_FILES_PATH CACHE ) - - set( USE_DEBUG_PTX OFF CACHE BOOL "Enable CUDA debugging with NSight") - if ( USE_DEBUG_PTX ) - set ( DEBUG_FLAGS ";-g;-G;-D_DEBUG;-DEBUG") + + set( DEBUG_PTX OFF CACHE BOOL "Enable CUDA debugging") + if ( DEBUG_PTX ) + set ( DEBUG_FLAGS "-G") else() set ( DEBUG_FLAGS "") endif() - if ( WIN32 ) - # Windows - PTX compile - file ( MAKE_DIRECTORY "${_COMPILEPTX_TARGET_PATH}" ) - string (REPLACE ";" " " _COMPILEPTX_OPTIONS "${_COMPILEPTX_OPTIONS}") - separate_arguments( _OPTS WINDOWS_COMMAND "${_COMPILEPTX_OPTIONS}" ) - message ( STATUS "NVCC Options: ${_COMPILEPTX_OPTIONS}" ) - message ( STATUS "NVCC Include: ${_COMPILEPTX_INCLUDE}" ) - - set ( INCL "-I\"${_COMPILEPTX_INCLUDE}\"" ) - - # Custom build rule to generate ptx files from cuda files - FOREACH( input ${_COMPILEPTX_SOURCES} ) - get_filename_component( input_ext ${input} EXT ) # Input extension - get_filename_component( input_without_ext ${input} NAME_WE ) # Input base - if ( ${input_ext} STREQUAL ".cu" ) - - # Set output names - set( output "${input_without_ext}.ptx" ) # Output name - set( output_with_path "${_COMPILEPTX_TARGET_PATH}/${input_without_ext}.ptx" ) # Output with path - set( output_with_quote "\"${output_with_path}\"" ) - LIST( APPEND PTX_FILES ${output} ) # Append to output list - LIST( APPEND PTX_FILES_PATH ${output_with_path} ) - - message( STATUS "NVCC Compile: ${CUDA_NVCC_EXECUTABLE} ${MACHINE} --ptx ${_COMPILEPTX_OPTIONS} ${input} ${INCL} -o ${output_with_path} WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}") - - add_custom_command( - OUTPUT ${output_with_path} - MAIN_DEPENDENCY ${input} - COMMAND ${CUDA_NVCC_EXECUTABLE} ${MACHINE} --ptx ${_OPTS} ${input} ${INCL} -o ${output_with_quote} WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" - ) - endif() - ENDFOREACH( ) - else () - # Linux - PTX compile - file ( MAKE_DIRECTORY "${_COMPILEPTX_TARGET_PATH}" ) - FOREACH(input ${_COMPILEPTX_SOURCES}) - get_filename_component( input_ext ${input} EXT ) # Input extension - get_filename_component( input_without_ext ${input} NAME_WE ) # Input base - if ( ${input_ext} STREQUAL ".cu" ) - # Set output names - set( output "${input_without_ext}.ptx" ) # Output name - set( output_with_path "${_COMPILEPTX_TARGET_PATH}/${input_without_ext}.ptx" ) # Output with path - - set( compile_target_ptx "${input_without_ext}_PTX") - set( custom_command_var "${input_without_ext}_OUTPUT") - # compile ptx - cuda_compile_ptx(custom_command_var ${input} OPTIONS "${DEBUG_FLAGS}") - # This will only configure file generation, we need to add a target to - # generate a file cuda_generated__${input_without_ext}.ptx - # Add custom command to rename to simply ${input_without_ext}.ptx - add_custom_command(OUTPUT ${output_with_path} - COMMAND ${CMAKE_COMMAND} -E rename ${custom_command_var} ${output_with_path} - DEPENDS ${custom_command_var}) - add_custom_target(${compile_target_ptx} ALL DEPENDS ${input} ${output_with_path} SOURCES ${input}) - - # Add this output file to list of generated ptx files - LIST(APPEND PTX_FILES ${output}) - LIST(APPEND PTX_FILES_PATH ${output_with_path} ) - endif() - ENDFOREACH() - endif() - - set( ${_COMPILEPTX_GENERATED} ${PTX_FILES} PARENT_SCOPE) - set( ${_COMPILEPTX_GENPATHS} ${PTX_FILES_PATH} PARENT_SCOPE) - -ENDFUNCTION() - -#------------------------------------ CROSS-PLATFORM INSTALL -function( _INSTALL ) - set (options "") - set (oneValueArgs DESTINATION SOURCE OUTPUT ) - set (multiValueArgs FILES ) - CMAKE_PARSE_ARGUMENTS(_INSTALL "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) - if ( _INSTALL_SOURCE ) - set ( _INSTALL_SOURCE "${_INSTALL_SOURCE}/" ) - endif() - set ( OUT_LIST ${${_INSTALL_OUTPUT}} ) - - if ( WIN32 ) - # Windows - copy to desintation at post-build - file ( MAKE_DIRECTORY "${_INSTALL_DESTINATION}/" ) - foreach (_file ${_INSTALL_FILES} ) - message ( STATUS "Install: ${_INSTALL_SOURCE}${_file} -> ${_INSTALL_DESTINATION}" ) - add_custom_command( - TARGET ${PROJNAME} POST_BUILD - COMMAND ${CMAKE_COMMAND} -E copy ${_INSTALL_SOURCE}${_file} ${_INSTALL_DESTINATION} - ) - list ( APPEND OUT_LIST "${_INSTALL_SOURCE}${_file}" ) - endforeach() - else () - # Linux - if ( _INSTALL_SOURCE ) - foreach ( _file ${_INSTALL_FILES} ) - list ( APPEND OUT_LIST "${_INSTALL_SOURCE}${_file}" ) - endforeach() - else() - list ( APPEND OUT_LIST ${_INSTALL_FILES} ) - endif() - endif( ) - set ( ${_INSTALL_OUTPUT} ${OUT_LIST} PARENT_SCOPE ) - -endfunction() - -#------------------------------------------------- CROSS-PLATFORM INSTALL PTX -# -function( _INSTALL_PTX ) - set (options "") - set (oneValueArgs DESTINATION OUTPUT ) - set (multiValueArgs FILES ) - CMAKE_PARSE_ARGUMENTS(_INSTALL_PTX "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) - - set ( OUT_LIST ${${_INSTALL_PTX_OUTPUT}} ) - - unset ( PTX_FIXED ) - - if ( WIN32 ) - - foreach ( _file IN ITEMS ${_INSTALL_PTX_FILES} ) - get_filename_component ( _ptxbase ${_file} NAME_WE ) - get_filename_component ( _ptxpath ${_file} DIRECTORY ) - get_filename_component ( _ptxparent ${_ptxpath} DIRECTORY ) # parent directory - set ( _fixed "${_ptxparent}/${_ptxbase}.ptx" ) # copy to parent to remove compile time $(Configuration) path - add_custom_command ( TARGET ${PROJNAME} POST_BUILD - COMMAND ${CMAKE_COMMAND} -E copy ${_file} ${_fixed} - ) - list ( APPEND PTX_FIXED ${_file} ) # NOTE: Input of FILES must be list of ptx *with paths* - list ( APPEND OUT_LIST ${_fixed} ) - endforeach() - - else() - - foreach ( _file IN ITEMS ${_INSTALL_PTX_FILES} ) - get_filename_component ( _ptxpath ${_file} DIRECTORY ) - get_filename_component ( _ptxbase ${_file} NAME_WE ) - get_filename_component ( _ptxparent ${_ptxpath} DIRECTORY ) # parent directory - set ( _fixed "${_file}" ) - list ( APPEND PTX_FIXED ${_fixed} ) - list ( APPEND OUT_LIST ${_fixed} ) - endforeach() - endif() + set( LINE_GENERATE OFF CACHE BOOL "Generate line information in ptx files") - # Install PTX - message ( STATUS "PTX files: ${PTX_FIXED}" ) - _INSTALL ( FILES ${PTX_FIXED} DESTINATION ${_INSTALL_PTX_DESTINATION} ) - - set ( ${_INSTALL_PTX_OUTPUT} ${OUT_LIST} PARENT_SCOPE ) - -endfunction() - - -#----------------------------------------------- CROSS-PLATFORM FIND FILES -# Find one or more of a specific file in the given folder -# Returns the file name w/o path - -macro(_FIND_FILE targetVar searchDir nameWin64 nameLnx cnt) - unset ( fileList ) - unset ( nameFind ) - unset ( targetVar ) - if ( WIN32 ) - SET ( nameFind ${nameWin64} ) - else() - SET ( nameFind ${nameLnx} ) - endif() - if ( "${nameFind}" STREQUAL "" ) - MATH (EXPR ${cnt} "${${cnt}}+1" ) - else() - file(GLOB fileList "${${searchDir}}/${nameFind}") - list(LENGTH fileList NUMLIST) - if (NUMLIST GREATER 0) - MATH (EXPR ${cnt} "${${cnt}}+1" ) - list(APPEND ${targetVar} ${nameFind} ) - endif() - endif() -endmacro() - -#----------------------------------------------- CROSS-PLATFORM FIND MULTIPLE -# Find all files in specified folder with the given extension. -# This creates a file list, where each entry is only the filename w/o path -# Return the count of files -macro(_FIND_MULTIPLE targetVar searchDir extWin64 extLnx cnt) - unset ( fileList ) - unset ( targetVar ) - unset ( ${cnt} ) - set ( ${cnt} "0" ) - if ( WIN32 ) - SET ( extFind ${extWin64} ) - else() - SET ( extFind ${extLnx} ) - endif() - file( GLOB fileList "${${searchDir}}/*.${extFind}") - list( LENGTH fileList NUMLIST) - math( EXPR ${cnt} "${${cnt}}+${NUMLIST}" ) - foreach ( _file ${fileList} ) - get_filename_component ( fname ${_file} NAME ) - list( APPEND ${targetVar} ${fname} ) - endforeach() -endmacro() - -#----------------------------------------------- LIST ALL source -function(_LIST_ALL_SOURCE ) - set (options "") - set (oneValueArgs "" ) - set (multiValueArgs FILES ) - CMAKE_PARSE_ARGUMENTS(_LIST_ALL_SOURCE "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) - - unset ( SOURCE_LIST ) - foreach ( _file IN ITEMS ${_LIST_ALL_SOURCE_FILES} ) - message ( STATUS "Source: ${_file}") # uncomment to check source files - list ( APPEND SOURCE_LIST ${_file} ) - endforeach() - - set ( ALL_SOURCE_FILES ${SOURCE_LIST} PARENT_SCOPE ) -endfunction() - -function(_LINK ) - set (options "") - set (multiValueArgs PROJECT OPT DEBUG PLATFORM ) - CMAKE_PARSE_ARGUMENTS(_LINK "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) - - set_property(GLOBAL PROPERTY DEBUG_CONFIGURATIONS Debug PARENT_SCOPE ) - - set (PROJ_NAME ${_LINK_PROJECT}) + + message(STATUS "_FUNCTION_INCLUDE: ${_FUNCTION_INCLUDE}") + FOREACH(INCLUDE_DIR ${_FUNCTION_INCLUDE}) + set ( INCL ${INCL} "-I\"${INCLUDE_DIR}\"" ) + ENDFOREACH() + + message(STATUS "Compiling for architecture ${ARCH}") - foreach (loop_var IN ITEMS ${_LINK_PLATFORM} ) - target_link_libraries( ${PROJ_NAME} general ${loop_var} ) - list (APPEND LIBLIST ${loop_var}) - endforeach() + file ( MAKE_DIRECTORY "${_FUNCTION_TARGET_PATH}" ) + string (REPLACE ";" " " _FUNCTION_OPTIONS "${_FUNCTION_OPTIONS}") + separate_arguments( _OPTS WINDOWS_COMMAND "${_FUNCTION_OPTIONS}" ) + message ( STATUS "NVCC Options: ${_FUNCTION_OPTIONS}" ) + message ( STATUS "NVCC Include: ${_FUNCTION_INCLUDE}" ) - foreach (loop_var IN ITEMS ${_LINK_DEBUG} ) - target_link_libraries ( ${PROJ_NAME} debug ${loop_var} ) - list (APPEND LIBLIST ${loop_var}) - endforeach() - - foreach (loop_var IN ITEMS ${_LINK_OPT} ) - target_link_libraries ( ${PROJ_NAME} optimized ${loop_var} ) - endforeach() - - string (REPLACE ";" "\n " OUTSTR "${LIBLIST}") - message ( STATUS "Libraries used:\n ${OUTSTR}" ) -endfunction() + set(_COMPILE_TYPE --ptx) -macro(_MSVC_PROPERTIES) - # Instruct CMake to automatically build INSTALL project in Visual Studio - set(CMAKE_VS_INCLUDE_INSTALL_TO_DEFAULT_BUILD 1) + if ( LINE_GENERATE ) + set(_OPTS ${_OPTS} -lineinfo) + endif() - set_target_properties( ${PROJNAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${EXECUTABLE_OUTPUT_PATH} ) - set_target_properties( ${PROJNAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY_DEBUG ${EXECUTABLE_OUTPUT_PATH} ) - set_target_properties( ${PROJNAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY_RELEASE ${EXECUTABLE_OUTPUT_PATH} ) + FOREACH( input ${_FUNCTION_SOURCES} ) + get_filename_component( input_ext ${input} EXT ) + get_filename_component( input_without_ext ${input} NAME_WE ) + if ( ${input_ext} STREQUAL ".cu" ) + set(_EXT .ptx) + set( output "${input_without_ext}.ptx" ) + set( embedded_file "${input_without_ext}_embed.c") + set( output_with_path "${_FUNCTION_TARGET_PATH}/${input_without_ext}${_EXT}" ) + + message( STATUS "NVCC Compile: $${CUDA_NVCC_EXECUTABLE} ${MACHINE} ${_COMPILE_TYPE} ${DEBUG_FLAGS} ${OPT_FLAGS} ${_OPTS} ${input} ${INCL} -o ${output_with_path}") + add_custom_command( + OUTPUT ${output_with_path} + MAIN_DEPENDENCY ${input} + DEPENDS ${_FILE_DEPENDENCY} + COMMAND ${CUDA_NVCC_EXECUTABLE} ${MACHINE} ${_COMPILE_TYPE} ${DEBUG_FLAGS} ${OPT_FLAGS} ${_OPTS} ${input} ${INCL} -o ${output_with_path} + WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" + ) + + endif() + ENDFOREACH() - # Set startup PROJECT - if ( (${CMAKE_MAJOR_VERSION} EQUAL 3 AND ${CMAKE_MINOR_VERSION} GREATER 5) OR (${CMAKE_MAJOR_VERSION} GREATER 3) ) - message ( STATUS "VS Startup Project: ${CMAKE_CURRENT_BINARY_DIR}, ${PROJNAME}") - set_property ( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJNAME} ) - endif() +ENDFUNCTION() - # Source groups - source_group(CUDA FILES ${CUDA_FILES}) - source_group(PTX FILES ${PTX_FILES}) - source_group(OPTIX FILES ${UTIL_OPTIX_KERNELS}) -endmacro () -macro(_DEFAULT_INSTALL_PATH) - if ( CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT ) - if (WIN32) - get_filename_component ( _instpath "${CMAKE_CURRENT_SOURCE_DIR}/../../_output" REALPATH ) - else() - get_filename_component ( _instpath "/usr/local/gvdb/_output" REALPATH ) - endif() - set ( CMAKE_INSTALL_PREFIX ${_instpath} CACHE PATH "default install path" FORCE) - endif() - get_filename_component( BIN_INSTALL_PATH ${CMAKE_INSTALL_PREFIX}/bin REALPATH) -endmacro() diff --git a/source/atmosphere/atmosphere.cpp b/source/atmosphere/atmosphere.cpp index e40b35e..fd1a662 100644 --- a/source/atmosphere/atmosphere.cpp +++ b/source/atmosphere/atmosphere.cpp @@ -50,8 +50,8 @@ #include #include -#include "boost/filesystem.hpp" -namespace fs = boost::filesystem; +#include +namespace fs = std::filesystem; // TODO convert all device pointers to thrust device pointers //#include "thrust/device_ptr.h" @@ -258,7 +258,7 @@ atmosphere_error_t atmosphere::load_textures() file_path.append("/transmittance.exr"); if (!fs::exists(fs::path(file_path))) { - log("File doesn't exists" + file_path, ERROR); + log("File doesn't exists" + file_path, VPT_ERROR); return ATMO_LOAD_FILE_ERR; } @@ -271,7 +271,7 @@ atmosphere_error_t atmosphere::load_textures() file_path = texture_folder; file_path.append("/irradiance.exr"); if (!fs::exists(fs::path(file_path))) { - log("File doesn't exists" + file_path, ERROR); + log("File doesn't exists" + file_path, VPT_ERROR); return ATMO_LOAD_FILE_ERR; } @@ -294,7 +294,7 @@ atmosphere_error_t atmosphere::load_textures() file_path.append(".exr"); if (!fs::exists(fs::path(file_path))) { - log("File doesn't exists" + file_path, ERROR); + log("File doesn't exists" + file_path, VPT_ERROR); return ATMO_LOAD_FILE_ERR; } @@ -332,7 +332,7 @@ atmosphere_error_t atmosphere::load_textures() file_path.append(".exr"); if (!fs::exists(fs::path(file_path))) { - log("File doesn't exists" + file_path, ERROR); + log("File doesn't exists" + file_path, VPT_ERROR); return ATMO_LOAD_FILE_ERR; } float4* host_scattering_buffer_2D = NULL; @@ -366,7 +366,7 @@ atmosphere_error_t atmosphere::save_textures() std::string file_path; // Save transmittance buffer to exr file - log("Saving transmittance texture", LOG); + log("Saving transmittance texture", VPT_LOG); int transmittance_size = TRANSMITTANCE_TEXTURE_WIDTH * TRANSMITTANCE_TEXTURE_HEIGHT * sizeof(float4); float4* host_transmittance_buffer = new float4[TRANSMITTANCE_TEXTURE_WIDTH * TRANSMITTANCE_TEXTURE_HEIGHT]; checkCudaErrors(cudaMemcpy(host_transmittance_buffer, atmosphere_parameters.transmittance_buffer, transmittance_size, cudaMemcpyDeviceToHost)); @@ -376,7 +376,7 @@ atmosphere_error_t atmosphere::save_textures() delete[] host_transmittance_buffer; // Save irradiance buffer to exr file - log("Saving irradiance texture", LOG); + log("Saving irradiance texture", VPT_LOG); int irradiance_size = IRRADIANCE_TEXTURE_WIDTH * IRRADIANCE_TEXTURE_HEIGHT * sizeof(float4); float4* host_irradiance_buffer = new float4[IRRADIANCE_TEXTURE_WIDTH * IRRADIANCE_TEXTURE_HEIGHT]; checkCudaErrors(cudaMemcpy(host_irradiance_buffer, atmosphere_parameters.delta_irradience_buffer, irradiance_size, cudaMemcpyDeviceToHost)); @@ -389,7 +389,7 @@ atmosphere_error_t atmosphere::save_textures() // Save scattering textures // Save multiple scattering textures - log("Saving scattering textures", LOG); + log("Saving scattering textures", VPT_LOG); int scattering_size = SCATTERING_TEXTURE_WIDTH * SCATTERING_TEXTURE_HEIGHT * SCATTERING_TEXTURE_DEPTH * sizeof(float4); float4* host_scattering_buffer = new float4[SCATTERING_TEXTURE_WIDTH * SCATTERING_TEXTURE_HEIGHT * SCATTERING_TEXTURE_DEPTH]; float4* host_scattering_buffer_2D = new float4[SCATTERING_TEXTURE_WIDTH * SCATTERING_TEXTURE_HEIGHT]; @@ -421,7 +421,7 @@ atmosphere_error_t atmosphere::save_textures() } // Save optional single scattering textures - log("Saving single scattering textures", LOG); + log("Saving single scattering textures", VPT_LOG); checkCudaErrors(cudaMemcpy(host_scattering_buffer, atmosphere_parameters.optional_mie_single_scattering_buffer, scattering_size, cudaMemcpyDeviceToHost)); for (int i = 0; i < SCATTERING_TEXTURE_DEPTH; ++i) { @@ -1180,15 +1180,15 @@ atmosphere_error_t atmosphere::init() atmosphere_error_t load_error = load_textures(); if (load_error == ATMO_LOAD_FILE_ERR) { - log("Couldn't find precomputed textures to load. Computing textures...", WARNING); + log("Couldn't find precomputed textures to load. Computing textures...", VPT_WARNING); m_need_compute = true; } else m_need_compute = false; - log("loading atmosphere module", LOG); + log("loading atmosphere module", VPT_LOG); // Bind precomputation functions from ptx file CUresult error = cuModuleLoad(&atmosphere_module, "atmosphere_kernels.ptx"); - if (error != CUDA_SUCCESS) printf("ERROR: cuModuleLoad, %i\n", error); + if (error != CUDA_SUCCESS) printf("VPT_ERROR: cuModuleLoad, %i\n", error); init_functions(atmosphere_module); diff --git a/source/bvh/bvh_builder.cpp b/source/bvh/bvh_builder.cpp index af70ac8..41ee31d 100644 --- a/source/bvh/bvh_builder.cpp +++ b/source/bvh/bvh_builder.cpp @@ -52,11 +52,11 @@ bvh_error_t BVH_Builder::build_bvh(std::vector vdbs, int num_volumes, A checkCudaErrors(cudaMalloc(&volumes, num_volumes * sizeof(GPU_VDB))); checkCudaErrors(cudaMemcpy(volumes, vdbs.data(), num_volumes * sizeof(GPU_VDB), cudaMemcpyHostToDevice)); - log("Building BVH structure...", LOG); + log("Building BVH structure...", VPT_LOG); BuildBVH(bvh, volumes, num_volumes, sceneBounds, m_debug_bvh); - log("Building Octree root...", LOG); + log("Building Octree root...", VPT_LOG); // Build octree octree.root_node = new OCTNode; // <3, 3, 3> Octree @@ -92,7 +92,7 @@ bvh_error_t BVH_Builder::build_bvh(std::vector vdbs, int num_volumes, A checkCudaErrors(cudaMalloc(&root, sizeof(OCTNode))); checkCudaErrors(cudaMemcpy(root, octree.root_node, sizeof(OCTNode), cudaMemcpyHostToDevice)); - log("Building Octree structure...", LOG); + log("Building Octree structure...", VPT_LOG); build_octree(root, volumes, vdbs.size(), /*octree depth*/ octree.root_node->depth - 1, octree.m_debug); // GPU path //octree.create_tree(vdbs, octree.root_node, 3); // CPU path diff --git a/source/bvh/bvh_kernels.cu b/source/bvh/bvh_kernels.cu index bae139b..193fdb5 100644 --- a/source/bvh/bvh_kernels.cu +++ b/source/bvh/bvh_kernels.cu @@ -47,6 +47,7 @@ #include #include #include +#include #include #include diff --git a/source/common/helper_image.h b/source/common/helper_image.h index ee7e665..cb3bb0b 100644 --- a/source/common/helper_image.h +++ b/source/common/helper_image.h @@ -517,7 +517,7 @@ inline bool compareData(const T *reference, const T *data, #if 0 if (!comp) { - std::cerr << "ERROR, i = " << i << ",\t " + std::cerr << "VPT_ERROR, i = " << i << ",\t " << reference[i] << " / " << data[i] << " (reference / data)\n"; @@ -789,7 +789,7 @@ inline bool sdkCompareL2fe(const float *reference, const float *data, if (fabs(ref) < 1e-7) { #ifdef _DEBUG - std::cerr << "ERROR, reference l2-norm is 0\n"; + std::cerr << "VPT_ERROR, reference l2-norm is 0\n"; #endif return false; } @@ -800,7 +800,7 @@ inline bool sdkCompareL2fe(const float *reference, const float *data, #ifdef _DEBUG if (!result) { - std::cerr << "ERROR, l2-norm error " << error << " is greater than epsilon " + std::cerr << "VPT_ERROR, l2-norm error " << error << " is greater than epsilon " << epsilon << "\n"; } diff --git a/source/common/helper_math.h b/source/common/helper_math.h index cb15e1c..d3df176 100644 --- a/source/common/helper_math.h +++ b/source/common/helper_math.h @@ -25,6 +25,11 @@ #include "cuda_runtime.h" +#ifdef _MSC_VER +#pragma warning( disable : 4244 4305 4005 4267) +#endif // _MSC_VER + + typedef unsigned int uint; typedef unsigned short ushort; @@ -32,7 +37,6 @@ typedef unsigned short ushort; #define EXIT_WAIVED 2 #endif - #define M_EPSILON 0.00001f #define M_INF 3.402823466e+38F #define M_E 2.71828182845904523536f @@ -1401,28 +1405,28 @@ inline __host__ __device__ float4 fmodf(float4 a, float4 b) inline __host__ __device__ float2 fabs(float2 v) { - return make_float2(fabs(v.x), fabs(v.y)); + return make_float2(fabsf(v.x), fabsf(v.y)); } inline __host__ __device__ float3 fabs(float3 v) { - return make_float3(fabs(v.x), fabs(v.y), fabs(v.z)); + return make_float3(fabsf(v.x), fabsf(v.y), fabsf(v.z)); } inline __host__ __device__ float4 fabs(float4 v) { - return make_float4(fabs(v.x), fabs(v.y), fabs(v.z), fabs(v.w)); + return make_float4(fabsf(v.x), fabsf(v.y), fabsf(v.z), fabsf(v.w)); } -inline __host__ __device__ int2 abs(int2 v) +inline __host__ __device__ int2 fabsf(int2 v) { - return make_int2(abs(v.x), abs(v.y)); + return make_int2(fabsf(v.x), fabsf(v.y)); } -inline __host__ __device__ int3 abs(int3 v) +inline __host__ __device__ int3 fabsf(int3 v) { - return make_int3(abs(v.x), abs(v.y), abs(v.z)); + return make_int3(fabsf(v.x), fabsf(v.y), fabsf(v.z)); } -inline __host__ __device__ int4 abs(int4 v) +inline __host__ __device__ int4 fabsf(int4 v) { - return make_int4(abs(v.x), abs(v.y), abs(v.z), abs(v.w)); + return make_int4(fabsf(v.x), fabsf(v.y), fabsf(v.z), fabsf(v.w)); } //////////////////////////////////////////////////////////////////////////////// @@ -1551,19 +1555,19 @@ inline __host__ __device__ float DegToRad(float degrees) { return degrees * M_PI inline __host__ __device__ float signf(float a) { - return a < 0 ? -1 : 1; + return a < 0.0f ? -1.0f : 1.0f; } inline __host__ __device__ float2 signf(float2 a) { - return make_float2(a.x < 0 ? -1 : 1, a.y < 0 ? -1 : 1); + return make_float2(a.x < 0.0f ? -1.0f : 1.0f, a.y < 0.0f ? -1.0f : 1.0f); } inline __host__ __device__ float3 signf(float3 a) { - return make_float3(a.x < 0 ? -1 : 1, a.y < 0 ? -1 : 1, a.z < 0 ? -1 : 1) ; + return make_float3(a.x < 0.0f ? -1.0f : 1.0f, a.y < 0.0f ? -1.0f : 1.0f, a.z < 0.0f ? -1.0f : 1.0f) ; } @@ -1571,17 +1575,17 @@ inline __host__ __device__ float3 signf(float3 a) { // Conversion //////////////////////////////////////////////////////////////////////////////// -inline __host__ __device__ float3 quaternion_to_euler(double x, double y, double z, double w) { +inline __host__ __device__ float3 quaternion_to_euler(float x, float y, float z, float w) { float heading, attitude, bank; // x, y, z rotations - double sw = w*w; - double sx = x*x; - double sy = y*y; - double sz = z*z; + float sw = w*w; + float sx = x*x; + float sy = y*y; + float sz = z*z; - double unit = sx + sy + sz + sw; - double test = x*y + z*w; + float unit = sx + sy + sz + sw; + float test = x*y + z*w; if (test > 0.4999 * unit) { // singularity at north pole heading = 2.0f * atan2f(x, w); diff --git a/source/gpu_vdb/gpu_vdb.cpp b/source/gpu_vdb/gpu_vdb.cpp index 5b6d6ee..7b6ea3c 100644 --- a/source/gpu_vdb/gpu_vdb.cpp +++ b/source/gpu_vdb/gpu_vdb.cpp @@ -47,8 +47,8 @@ #include #include -#include "boost/filesystem.hpp" -namespace fs = boost::filesystem; +#include +namespace fs = std::filesystem; GPU_VDB::GPU_VDB() {} @@ -106,20 +106,20 @@ bool GPU_VDB::loadVDB(std::string filename, std::string density_channel, std::st if (!fs::exists(fs::path(filename))) { - log("File doesn't exists " + filename , ERROR); + log("File doesn't exists " + filename , VPT_ERROR); return false; } if (filename.empty()) { - log("File name is empty " + filename, ERROR); + log("File name is empty " + filename, VPT_ERROR); return false; } if (density_channel.empty()) { - log("Density channel can't be empty!!!", ERROR); + log("Density channel can't be empty!!!", VPT_ERROR); return false; } @@ -137,7 +137,7 @@ bool GPU_VDB::loadVDB(std::string filename, std::string density_channel, std::st // Print grid attributes auto grids = file.readAllGridMetadata(); for (auto grid : *grids) { - log("Grid " + grid->getName() + " " + grid->valueType(), LOG); + log("Grid " + grid->getName() + " " + grid->valueType(), VPT_LOG); } // Read density and emission channel from the file @@ -158,7 +158,7 @@ bool GPU_VDB::loadVDB(std::string filename, std::string density_channel, std::st colorGridBase = file.readGrid(nameIter.gridName()); } else { - log("skipping grid " + nameIter.gridName(), WARNING); + log("skipping grid " + nameIter.gridName(), VPT_WARNING); } } @@ -183,7 +183,7 @@ bool GPU_VDB::loadVDB(std::string filename, std::string density_channel, std::st dense.print(); #endif - log("value count: " + std::to_string(dense.valueCount()), LOG); + log("value count: " + std::to_string(dense.valueCount()), VPT_LOG); int dim_x = bbox.dim().x(); int dim_y = bbox.dim().y(); @@ -266,7 +266,7 @@ bool GPU_VDB::loadVDB(std::string filename, std::string density_channel, std::st dense.print(); #endif - log("value count: " + std::to_string(dense.valueCount()), LOG); + log("value count: " + std::to_string(dense.valueCount()), VPT_LOG); int dim_x = bbox.dim().x(); int dim_y = bbox.dim().y(); @@ -346,7 +346,7 @@ bool GPU_VDB::loadVDB(std::string filename, std::string density_channel, std::st dense.print(); #endif - log("value count: " + std::to_string(dense.valueCount()), LOG); + log("value count: " + std::to_string(dense.valueCount()), VPT_LOG); int dim_x = bbox.dim().x(); int dim_y = bbox.dim().y(); @@ -460,12 +460,12 @@ bool GPU_VDB::loadVDB(std::string filename, std::string density_channel, std::st mat4 xform_temp = convert_to_mat4(ref_xform); #ifdef LOG_LEVEL_LOG - log("XForm: ", LOG); + log("XForm: ", VPT_LOG); xform_temp.print(); #endif - log("max density: " + std::to_string(vdb_info.max_density), LOG); - log("min density: " + std::to_string(vdb_info.min_density), LOG); + log("max density: " + std::to_string(vdb_info.max_density), VPT_LOG); + log("min density: " + std::to_string(vdb_info.min_density), VPT_LOG); set_xform(xform_temp); return true; @@ -495,11 +495,11 @@ GPU_PROC_VOL::GPU_PROC_VOL(const GPU_PROC_VOL& copy){ GPU_PROC_VOL::GPU_PROC_VOL() { CUresult error = cuModuleLoad(&texture_module, "texture_kernels.ptx"); - if (error != CUDA_SUCCESS) log("cuModuleLoad" + std::to_string(error), ERROR); + if (error != CUDA_SUCCESS) log("cuModuleLoad" + std::to_string(error), VPT_ERROR); error = cuModuleGetFunction(&fill_buffer_function, texture_module, "fill_volume_buffer"); if (error != CUDA_SUCCESS) { - log("Unable to bind buffer fill function!", ERROR); + log("Unable to bind buffer fill function!", VPT_ERROR); } } @@ -507,10 +507,10 @@ GPU_PROC_VOL::GPU_PROC_VOL() { // fill vdb_info density texture with procedural noise texture bool GPU_PROC_VOL::create_volume(float3 min, float3 max, float res, int noise_type, float scale) { - log("Creating procedural volume...", LOG); + log("Creating procedural volume...", VPT_LOG); if (min.x > max.x&& min.y > max.y&& min.z > max.z) { - log("max < min", ERROR); + log("max < min", VPT_ERROR); return false; } @@ -518,15 +518,15 @@ bool GPU_PROC_VOL::create_volume(float3 min, float3 max, float res, int noise_ty xform.scale(make_float3(res)); #ifdef LOG_LEVEL_LOG - log("XForm: ", LOG); + log("XForm: ", VPT_LOG); xform.print(); #endif // LOG_LEVEL_LOG set_xform(xform); - int dim_x = floorf((max.x - min.x) / res); - int dim_y = floorf((max.y - min.y) / res); - int dim_z = floorf((max.z - min.z) / res); + int dim_x = int(floorf((max.x - min.x) / res)); + int dim_y = int(floorf((max.y - min.y) / res)); + int dim_z = int(floorf((max.z - min.z) / res)); dimensions = make_int3(dim_x, dim_y, dim_z); @@ -541,13 +541,13 @@ bool GPU_PROC_VOL::create_volume(float3 min, float3 max, float res, int noise_ty vdb_info.has_color = false; // Allocate device memory for volume buffer - log("Allocating device memory for volume buffer...", LOG); + log("Allocating device memory for volume buffer...", VPT_LOG); checkCudaErrors(cudaMalloc(&device_density_buffer, dimensions.x * dimensions.y * dimensions.z * sizeof(float))); dim3 block(8, 8, 8); dim3 grid(int(dimensions.x / block.x) + 1, int(dimensions.y / block.y) + 1, int(dimensions.z / block.z) + 1); - log("filling volume buffer in device...", LOG); + log("filling volume buffer in device...", VPT_LOG); void* params[] = { &device_density_buffer , &dimensions, &scale, &noise_type}; CUresult result = cuLaunchKernel(fill_buffer_function, grid.x, grid.y, grid.z, block.x, block.y, block.z, 0, NULL, params, NULL); checkCudaErrors(cudaDeviceSynchronize()); @@ -563,7 +563,7 @@ bool GPU_PROC_VOL::create_volume(float3 min, float3 max, float res, int noise_ty vol_size.height = dim_y; vol_size.depth = dim_z; - log("transport volume buffer from device to host...", LOG); + log("transport volume buffer from device to host...", VPT_LOG); float* volume_data_host = (float*)malloc(dim_x * dim_y * dim_z * sizeof(float)); checkCudaErrors(cudaMemcpy(volume_data_host, device_density_buffer, dim_x * dim_y * dim_z * sizeof(float), cudaMemcpyDeviceToHost)); diff --git a/source/gpu_vdb/gpu_vdb.h b/source/gpu_vdb/gpu_vdb.h index 927d675..76c801d 100644 --- a/source/gpu_vdb/gpu_vdb.h +++ b/source/gpu_vdb/gpu_vdb.h @@ -90,7 +90,7 @@ class GPU_VDB { ray_pos = xform.transpose().inverse().transform_point(ray_pos); ray_dir = xform.transpose().inverse().transform_vector(ray_dir); - register float ht[8]; + float ht[8]; ht[0] = (vdb_info.bmin.x - ray_pos.x) / ray_dir.x; ht[1] = (vdb_info.bmax.x - ray_pos.x) / ray_dir.x; ht[2] = (vdb_info.bmin.y - ray_pos.y) / ray_dir.y; diff --git a/source/gpu_vdb/matrix_math.h b/source/gpu_vdb/matrix_math.h index 53b616d..0572e81 100644 --- a/source/gpu_vdb/matrix_math.h +++ b/source/gpu_vdb/matrix_math.h @@ -9,11 +9,11 @@ // * Redistributions in binary form must reproduce the above copyright notice, // this list of conditions and the following disclaimer in the documentation // and/or other materials provided with the distribution. -// +// // * Neither the name of the copyright holder nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. -// +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE @@ -24,11 +24,11 @@ // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, // OR TORT(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// +// // Copyright(c) 2019, Sergen Eren // All rights reserved. //---------------------------------------------------------------------------------- -// +// // Version 1.0: Sergen Eren, 27/10/2019 // // File: Column major 4x4 matrix for CUDA. @@ -39,6 +39,9 @@ #ifndef MATRIX_MATH_H #define MATRIX_MATH_H +#ifdef _MSC_VER +#pragma warning( disable : 4244) +#endif // _MSC_VER #include "cuda_runtime.h" #include "helper_cuda.h" @@ -69,7 +72,7 @@ struct mat4 { return m[idx]; } - __host__ __device__ __forceinline__ float4 operator*(const float4 &v) const { + __host__ __device__ __forceinline__ float4 operator*(const float4& v) const { float4 ret; ret.x = m[0][0] * v.x + m[1][0] * v.y + m[2][0] * v.z + m[3][0] * v.w; ret.y = m[0][1] * v.x + m[1][1] * v.y + m[2][1] * v.z + m[3][1] * v.w; @@ -78,13 +81,12 @@ struct mat4 { return ret; } - __host__ __device__ __forceinline__ float3 operator*(const float3 &v) const { - + __host__ __device__ __forceinline__ float3 operator*(const float3& v) const { float3 ret; - ret.x = m[0][0] * v.x + m[1][0] * v.y + m[2][0] * v.z + m[3][0] ; - ret.y = m[0][1] * v.x + m[1][1] * v.y + m[2][1] * v.z + m[3][1] ; - ret.z = m[0][2] * v.x + m[1][2] * v.y + m[2][2] * v.z + m[3][2] ; + ret.x = m[0][0] * v.x + m[1][0] * v.y + m[2][0] * v.z + m[3][0]; + ret.y = m[0][1] * v.x + m[1][1] * v.y + m[2][1] * v.z + m[3][1]; + ret.z = m[0][2] * v.x + m[1][2] * v.y + m[2][2] * v.z + m[3][2]; return ret; } @@ -107,7 +109,7 @@ struct mat4 { return ret; } - __host__ __device__ __forceinline__ mat4 operator+(const mat4 &other) const { + __host__ __device__ __forceinline__ mat4 operator+(const mat4& other) const { mat4 ret; ret[0][0] = m[0][0] + other.m[0][0]; ret[1][0] = m[1][0] + other.m[1][0]; ret[2][0] = m[2][0] + other.m[2][0]; ret[3][0] = m[3][0] + other.m[3][0]; ret[0][1] = m[0][1] + other.m[0][1]; ret[1][1] = m[1][1] + other.m[1][1]; ret[2][1] = m[2][1] + other.m[2][1]; ret[3][1] = m[3][1] + other.m[3][1]; @@ -116,7 +118,7 @@ struct mat4 { return ret; } - __host__ __device__ __forceinline__ mat4 operator-(const mat4 &other) const { + __host__ __device__ __forceinline__ mat4 operator-(const mat4& other) const { mat4 ret; ret[0][0] = m[0][0] - other.m[0][0]; ret[1][0] = m[1][0] - other.m[1][0]; ret[2][0] = m[2][0] - other.m[2][0]; ret[3][0] = m[3][0] - other.m[3][0]; ret[0][1] = m[0][1] - other.m[0][1]; ret[1][1] = m[1][1] - other.m[1][1]; ret[2][1] = m[2][1] - other.m[2][1]; ret[3][1] = m[3][1] - other.m[3][1]; @@ -125,7 +127,7 @@ struct mat4 { return ret; } - __host__ __device__ __forceinline__ mat4 operator*(const mat4 &other) const { + __host__ __device__ __forceinline__ mat4 operator*(const mat4& other) const { auto a11 = m[0][0], a12 = m[1][0], a13 = m[2][0], a14 = m[3][0]; auto a21 = m[0][1], a22 = m[1][1], a23 = m[2][1], a24 = m[3][1]; auto a31 = m[0][2], a32 = m[1][2], a33 = m[2][2], a34 = m[3][2]; @@ -263,8 +265,7 @@ struct mat4 { m[0][3] = 0.0; m[1][3] = 0.0; m[2][3] = 0.0; m[3][3] = 1.0; } - __host__ __device__ __forceinline__ mat4 abs() const{ - + __host__ __device__ __forceinline__ mat4 abs() const { mat4 ret; for (int i = 0; i < 4; ++i) { @@ -277,9 +278,7 @@ struct mat4 { return ret; } - __host__ __device__ __forceinline__ void print() { - for (int j = 0; j < 4; j++) { for (int i = 0; i < 4; i++) { printf("%f ", m[i][j]); @@ -289,19 +288,18 @@ struct mat4 { printf("\n"); } - __host__ __device__ __forceinline__ float3 transform_point(const float3 &pt) const { + __host__ __device__ __forceinline__ float3 transform_point(const float3& pt) const { float4 temp = make_float4(pt.x, pt.y, pt.z, 1.0f); temp = *this * temp; return make_float3(temp.x, temp.y, temp.z); } - __host__ __device__ __forceinline__ float3 transform_vector(const float3 &pt) const { + __host__ __device__ __forceinline__ float3 transform_vector(const float3& pt) const { float4 temp = make_float4(pt.x, pt.y, pt.z, 0.0f); temp = *this * temp; return make_float3(temp.x, temp.y, temp.z); } - __host__ __device__ __forceinline__ mat4 rotate_zyx(const float3 &angs) { - + __host__ __device__ __forceinline__ mat4 rotate_zyx(const float3& angs) { float cx, sx, cy, sy, cz, sz; cx = (float)cos(angs.x); sx = (float)sin(angs.x); @@ -313,26 +311,23 @@ struct mat4 { m[0][0] = cz * cy; m[1][0] = sz * cy; m[2][0] = -sy; - - m[0][1] = -sz * cx + cz * sy*sx; - m[1][1] = cz * cx - sz * sy*sz; + + m[0][1] = -sz * cx + cz * sy * sx; + m[1][1] = cz * cx - sz * sy * sz; m[2][1] = -cy * sx; - m[0][2] = -sz * sx + cz * sy*cx; - m[1][2] = cz * sx + sz * sy*cx; + m[0][2] = -sz * sx + cz * sy * cx; + m[1][2] = cz * sx + sz * sy * cx; m[2][2] = cy * cx; return *this; - } __host__ __device__ __forceinline__ float3 extract_translate() { - return make_float3(m[0][3], m[1][3], m[2][3]); } - __host__ __device__ __forceinline__ mat4 translate(const float3 &val) { - + __host__ __device__ __forceinline__ mat4 translate(const float3& val) { m[0][3] += val.x; m[1][3] += val.y; m[2][3] += val.z; @@ -340,8 +335,7 @@ struct mat4 { return *this; } - __host__ __device__ __forceinline__ mat4 scale(const float3 &val) { - + __host__ __device__ __forceinline__ mat4 scale(const float3& val) { m[0][0] *= val.x; m[1][1] *= val.y; m[2][2] *= val.z; @@ -349,22 +343,18 @@ struct mat4 { return *this; } - - __host__ __device__ __forceinline__ mat4 &operator*=(const float f) { return *this = *this * f; } - __host__ __device__ __forceinline__ mat4 &operator/=(const float f) { return *this = *this / f; } - __host__ __device__ __forceinline__ mat4 &operator+=(const mat4 &m) { return *this = *this + m; } - __host__ __device__ __forceinline__ mat4 &operator-=(const mat4 &m) { return *this = *this - m; } - __host__ __device__ __forceinline__ mat4 &operator*=(const mat4 &m) { return *this = *this * m; } - + __host__ __device__ __forceinline__ mat4& operator*=(const float f) { return *this = *this * f; } + __host__ __device__ __forceinline__ mat4& operator/=(const float f) { return *this = *this / f; } + __host__ __device__ __forceinline__ mat4& operator+=(const mat4& m) { return *this = *this + m; } + __host__ __device__ __forceinline__ mat4& operator-=(const mat4& m) { return *this = *this - m; } + __host__ __device__ __forceinline__ mat4& operator*=(const mat4& m) { return *this = *this * m; } }; - ////////////////////////////////////////////////////////////////////////// // Inline Functions ////////////////////////////////////////////////////////////////////////// -__host__ __device__ __forceinline__ mat4 toMatrix(double *arr) { - +__host__ __device__ __forceinline__ mat4 toMatrix(double* arr) { mat4 ret; ret[0][0] = arr[0]; ret[1][0] = arr[1]; ret[2][0] = arr[2]; ret[3][0] = 0.0f; @@ -375,8 +365,7 @@ __host__ __device__ __forceinline__ mat4 toMatrix(double *arr) { return ret; } -__host__ __device__ __forceinline__ mat4 toMatrix(float *arr) { - +__host__ __device__ __forceinline__ mat4 toMatrix(float* arr) { mat4 ret; ret[0][0] = arr[0]; ret[1][0] = arr[1]; ret[2][0] = arr[2]; ret[3][0] = 0.0f; @@ -388,27 +377,26 @@ __host__ __device__ __forceinline__ mat4 toMatrix(float *arr) { } __host__ __device__ __forceinline__ mat4 quaternion_to_mat4(double x, double y, double z, double w) { - - const double n = 1.0 / sqrtf(x*x + y * y + z * z + w * w); + const double n = 1.0 / sqrtf(x * x + y * y + z * z + w * w); x *= n; y *= n; z *= n; w *= n; - float m11 = 1.0f - 2.0f*y*y - 2.0f*z*z; - float m12 = 2.0f*x*y + 2.0f*z*w; - float m13 = 2.0f*x*z - 2.0f*y*w; - float m14 = .0f; + float m11 = float(1.0f - 2.0f * y * y - 2.0f * z * z); + float m12 = float(2.0f * x * y + 2.0f * z * w); + float m13 = float(2.0f * x * z - 2.0f * y * w); + float m14 = 0.0f; - float m21 = 2.0f*x*y - 2.0f*z*w; - float m22 = 1.0f - 2.0f*x*x - 2.0f*z*z; - float m23 = 2.0f*y*z + 2.0f*x*w; + float m21 = float(2.0f * x * y - 2.0f * z * w); + float m22 = float(1.0f - 2.0f * x * x - 2.0f * z * z); + float m23 = float(2.0f * y * z + 2.0f * x * w); float m24 = 0.0f; - float m31 = 2.0f*x*z + 2.0f*y*w; - float m32 = 2.0f*y*z - 2.0f*x*w; - float m33 = 1.0f - 2.0f*x*x - 2.0f*y*y; + float m31 = float(2.0f * x * z + 2.0f * y * w); + float m32 = float(2.0f * y * z - 2.0f * x * w); + float m33 = float(1.0f - 2.0f * x * x - 2.0f * y * y); float m34 = 0.0f; float m41 = 0.0f; @@ -416,112 +404,105 @@ __host__ __device__ __forceinline__ mat4 quaternion_to_mat4(double x, double y, float m43 = 0.0f; float m44 = 1.0f; - mat4 ret(m11, m12, m13, m14, m21, m22, m23, m24, m31, m32, m33, m34, m41, m42, m43, m44); return ret; - } __host__ __device__ __forceinline__ mat4 quaternion_to_mat4(float4 quaternion) { - float x = quaternion.x; float y = quaternion.y; float z = quaternion.z; float w = quaternion.w; - const float n = 1.0f / sqrtf(x*x + y * y + z * z + w * w); + const float n = 1.0f / sqrtf(x * x + y * y + z * z + w * w); x *= n; y *= n; z *= n; w *= n; - mat4 m1 = mat4(w , z , -y , x, - -z , w , x, y, - y, -x, w, z, - -x, -y, -z, w); + mat4 m1 = mat4(w, z, -y, x, + -z, w, x, y, + y, -x, w, z, + -x, -y, -z, w); - mat4 m2 = mat4(w , z , -y , -x, - -z , w , x, -y, - y, -x, w, -z, - x, y, z, w); + mat4 m2 = mat4(w, z, -y, -x, + -z, w, x, -y, + y, -x, w, -z, + x, y, z, w); mat4 ret = m1 * m2; return ret; - } // Rotation by quaternion about point __host__ __device__ __forceinline__ mat4 rotate_by_point(float4 q, float3 center) { - mat4 ret; - float sqw = q.w*q.w; - float sqx = q.x*q.x; - float sqy = q.y*q.y; - float sqz = q.z*q.z; + float sqw = q.w * q.w; + float sqx = q.x * q.x; + float sqy = q.y * q.y; + float sqz = q.z * q.z; ret[0][0] = sqx - sqy - sqz + sqw; // since sqw + sqx + sqy + sqz =1 ret[1][1] = -sqx + sqy - sqz + sqw; ret[2][2] = -sqx - sqy + sqz + sqw; - float tmp1 = q.x*q.y; - float tmp2 = q.z*q.w; - ret[1][0] = 2.0 * (tmp1 + tmp2); - ret[0][1] = 2.0 * (tmp1 - tmp2); + float tmp1 = q.x * q.y; + float tmp2 = q.z * q.w; + ret[1][0] = 2.0f * (tmp1 + tmp2); + ret[0][1] = 2.0f * (tmp1 - tmp2); - tmp1 = q.x*q.z; - tmp2 = q.y*q.w; - ret[2][0] = 2.0 * (tmp1 - tmp2); - ret[0][2] = 2.0 * (tmp1 + tmp2); + tmp1 = q.x * q.z; + tmp2 = q.y * q.w; + ret[2][0] = 2.0f * (tmp1 - tmp2); + ret[0][2] = 2.0f * (tmp1 + tmp2); - tmp1 = q.y*q.z; - tmp2 = q.x*q.w; - ret[2][1] = 2.0 * (tmp1 + tmp2); - ret[1][2] = 2.0 * (tmp1 - tmp2); + tmp1 = q.y * q.z; + tmp2 = q.x * q.w; + ret[2][1] = 2.0f * (tmp1 + tmp2); + ret[1][2] = 2.0f * (tmp1 - tmp2); float a1 = center.x, a2 = center.y, a3 = center.z; ret[3][0] = a1 - a1 * ret[0][0] - a2 * ret[1][0] - a3 * ret[2][0]; ret[3][1] = a2 - a1 * ret[0][1] - a2 * ret[1][1] - a3 * ret[2][1]; ret[3][2] = a3 - a1 * ret[0][2] - a2 * ret[1][2] - a3 * ret[2][2]; - ret[0][3] = ret[1][3] = ret[2][3] = 0.0; - ret[3][3] = 1.0; + ret[0][3] = ret[1][3] = ret[2][3] = 0.0f; + ret[3][3] = 1.0f; return ret; - } struct mat3 { float m[3][3]; __host__ __device__ __forceinline__ mat3() { - m[0][0] = 1.0; m[1][0] = 0.0; m[2][0] = 0.0; - m[0][1] = 0.0; m[1][1] = 1.0; m[2][1] = 0.0; - m[0][2] = 0.0; m[1][2] = 0.0; m[2][2] = 1.0; + m[0][0] = 1.0; m[1][0] = 0.0; m[2][0] = 0.0; + m[0][1] = 0.0; m[1][1] = 1.0; m[2][1] = 0.0; + m[0][2] = 0.0; m[1][2] = 0.0; m[2][2] = 1.0; } __host__ __device__ __forceinline__ mat3( - const float m11, const float m12, const float m13, - const float m21, const float m22, const float m23, + const float m11, const float m12, const float m13, + const float m21, const float m22, const float m23, const float m31, const float m32, const float m33 ) { - m[0][0] = m11; m[1][0] = m12; m[2][0] = m13; - m[0][1] = m21; m[1][1] = m22; m[2][1] = m23; - m[0][2] = m31; m[1][2] = m32; m[2][2] = m33; + m[0][0] = m11; m[1][0] = m12; m[2][0] = m13; + m[0][1] = m21; m[1][1] = m22; m[2][1] = m23; + m[0][2] = m31; m[1][2] = m32; m[2][2] = m33; } __host__ __device__ __forceinline__ float* operator[] (const size_t idx) { return m[idx]; } - __host__ __device__ __forceinline__ float3 operator*(const float3 &v) const { - + __host__ __device__ __forceinline__ float3 operator*(const float3& v) const { float3 ret; ret.x = m[0][0] * v.x + m[1][0] * v.y + m[2][0] * v.z; @@ -533,37 +514,37 @@ struct mat3 { __host__ __device__ __forceinline__ mat3 operator*(const float f) const { mat3 ret; - ret[0][0] = m[0][0] * f; ret[1][0] = m[1][0] * f; ret[2][0] = m[2][0] * f; - ret[0][1] = m[0][1] * f; ret[1][1] = m[1][1] * f; ret[2][1] = m[2][1] * f; + ret[0][0] = m[0][0] * f; ret[1][0] = m[1][0] * f; ret[2][0] = m[2][0] * f; + ret[0][1] = m[0][1] * f; ret[1][1] = m[1][1] * f; ret[2][1] = m[2][1] * f; ret[0][2] = m[0][2] * f; ret[1][2] = m[1][2] * f; ret[2][2] = m[2][2] * f; return ret; } __host__ __device__ __forceinline__ mat3 operator/(const float f) const { mat3 ret; - ret[0][0] = m[0][0] / f; ret[1][0] = m[1][0] / f; ret[2][0] = m[2][0] / f; - ret[0][1] = m[0][1] / f; ret[1][1] = m[1][1] / f; ret[2][1] = m[2][1] / f; - ret[0][2] = m[0][2] / f; ret[1][2] = m[1][2] / f; ret[2][2] = m[2][2] / f; + ret[0][0] = m[0][0] / f; ret[1][0] = m[1][0] / f; ret[2][0] = m[2][0] / f; + ret[0][1] = m[0][1] / f; ret[1][1] = m[1][1] / f; ret[2][1] = m[2][1] / f; + ret[0][2] = m[0][2] / f; ret[1][2] = m[1][2] / f; ret[2][2] = m[2][2] / f; return ret; } - __host__ __device__ __forceinline__ mat3 operator+(const mat3 &other) const { + __host__ __device__ __forceinline__ mat3 operator+(const mat3& other) const { mat3 ret; - ret[0][0] = m[0][0] + other.m[0][0]; ret[1][0] = m[1][0] + other.m[1][0]; ret[2][0] = m[2][0] + other.m[2][0]; - ret[0][1] = m[0][1] + other.m[0][1]; ret[1][1] = m[1][1] + other.m[1][1]; ret[2][1] = m[2][1] + other.m[2][1]; - ret[0][2] = m[0][2] + other.m[0][2]; ret[1][2] = m[1][2] + other.m[1][2]; ret[2][2] = m[2][2] + other.m[2][2]; + ret[0][0] = m[0][0] + other.m[0][0]; ret[1][0] = m[1][0] + other.m[1][0]; ret[2][0] = m[2][0] + other.m[2][0]; + ret[0][1] = m[0][1] + other.m[0][1]; ret[1][1] = m[1][1] + other.m[1][1]; ret[2][1] = m[2][1] + other.m[2][1]; + ret[0][2] = m[0][2] + other.m[0][2]; ret[1][2] = m[1][2] + other.m[1][2]; ret[2][2] = m[2][2] + other.m[2][2]; return ret; } - __host__ __device__ __forceinline__ mat3 operator-(const mat3 &other) const { + __host__ __device__ __forceinline__ mat3 operator-(const mat3& other) const { mat3 ret; - ret[0][0] = m[0][0] - other.m[0][0]; ret[1][0] = m[1][0] - other.m[1][0]; ret[2][0] = m[2][0] - other.m[2][0]; - ret[0][1] = m[0][1] - other.m[0][1]; ret[1][1] = m[1][1] - other.m[1][1]; ret[2][1] = m[2][1] - other.m[2][1]; - ret[0][2] = m[0][2] - other.m[0][2]; ret[1][2] = m[1][2] - other.m[1][2]; ret[2][2] = m[2][2] - other.m[2][2]; + ret[0][0] = m[0][0] - other.m[0][0]; ret[1][0] = m[1][0] - other.m[1][0]; ret[2][0] = m[2][0] - other.m[2][0]; + ret[0][1] = m[0][1] - other.m[0][1]; ret[1][1] = m[1][1] - other.m[1][1]; ret[2][1] = m[2][1] - other.m[2][1]; + ret[0][2] = m[0][2] - other.m[0][2]; ret[1][2] = m[1][2] - other.m[1][2]; ret[2][2] = m[2][2] - other.m[2][2]; return ret; } - __host__ __device__ __forceinline__ mat3 operator*(const mat3 &other) const { + __host__ __device__ __forceinline__ mat3 operator*(const mat3& other) const { auto a11 = m[0][0], a12 = m[1][0], a13 = m[2][0]; auto a21 = m[0][1], a22 = m[1][1], a23 = m[2][1]; auto a31 = m[0][2], a32 = m[1][2], a33 = m[2][2]; @@ -590,9 +571,9 @@ struct mat3 { __host__ __device__ __forceinline__ mat3 transpose() const { mat3 ret; - ret[0][0] = m[0][0]; ret[0][1] = m[1][0]; ret[0][2] = m[2][0]; - ret[1][0] = m[0][1]; ret[1][1] = m[1][1]; ret[1][2] = m[2][1]; - ret[2][0] = m[0][2]; ret[2][1] = m[1][2]; ret[2][2] = m[2][2]; + ret[0][0] = m[0][0]; ret[0][1] = m[1][0]; ret[0][2] = m[2][0]; + ret[1][0] = m[0][1]; ret[1][1] = m[1][1]; ret[1][2] = m[2][1]; + ret[2][0] = m[0][2]; ret[2][1] = m[1][2]; ret[2][2] = m[2][2]; return ret; } @@ -601,19 +582,18 @@ struct mat3 { auto n21 = m[0][1], n22 = m[1][1], n23 = m[2][1]; auto n31 = m[0][2], n32 = m[1][2], n33 = m[2][2]; - return (n11 * (n22*n33 - n23*n32) - n12 * (n21*n33 - n23*n31) + n13 * (n21*n32 - n22*n31) ); + return (n11 * (n22 * n33 - n23 * n32) - n12 * (n21 * n33 - n23 * n31) + n13 * (n21 * n32 - n22 * n31)); } __host__ __device__ __forceinline__ mat3 inverse() const { - float det = this->det(); if (det == 0) return *this; - - mat3 ret; + + mat3 ret; ret = this->transpose(); - + auto det1 = ret[2][2] * ret[1][1] - ret[2][1] * ret[1][2]; auto det2 = ret[0][1] * ret[2][2] - ret[2][1] * ret[0][2]; auto det3 = ret[0][1] * ret[1][1] - ret[1][1] * ret[0][2]; @@ -621,33 +601,31 @@ struct mat3 { auto det4 = ret[1][0] * ret[2][2] - ret[2][0] * ret[1][2]; auto det5 = ret[0][0] * ret[2][2] - ret[2][0] * ret[0][2]; auto det6 = ret[0][0] * ret[1][2] - ret[0][1] * ret[0][2]; - + auto det7 = ret[1][0] * ret[2][1] - ret[2][0] * ret[1][1]; auto det8 = ret[0][0] * ret[2][1] - ret[2][0] * ret[0][1]; auto det9 = ret[0][0] * ret[1][1] - ret[1][0] * ret[0][1]; - - ret = mat3(det1, det2, det3, det4, det5, det6, det7, det8, det9); - ret = ret * mat3(1, -1, 1, -1, 1, -1, 1, -1, 1); // Adjoint matrix + + ret = mat3(det1, det2, det3, det4, det5, det6, det7, det8, det9); + ret = ret * mat3(1, -1, 1, -1, 1, -1, 1, -1, 1); // Adjoint matrix ret = ret * (1 / det); return ret; } __host__ __device__ __forceinline__ void zero() { - m[0][0] = 0.0; m[1][0] = 0.0; m[2][0] = 0.0; + m[0][0] = 0.0; m[1][0] = 0.0; m[2][0] = 0.0; m[0][1] = 0.0; m[1][1] = 0.0; m[2][1] = 0.0; - m[0][2] = 0.0; m[1][2] = 0.0; m[2][2] = 0.0; + m[0][2] = 0.0; m[1][2] = 0.0; m[2][2] = 0.0; } __host__ __device__ __forceinline__ void identity() { - m[0][0] = 1.0; m[1][0] = 0.0; m[2][0] = 0.0; - m[0][1] = 0.0; m[1][1] = 1.0; m[2][1] = 0.0; - m[0][2] = 0.0; m[1][2] = 0.0; m[2][2] = 1.0; + m[0][0] = 1.0; m[1][0] = 0.0; m[2][0] = 0.0; + m[0][1] = 0.0; m[1][1] = 1.0; m[2][1] = 0.0; + m[0][2] = 0.0; m[1][2] = 0.0; m[2][2] = 1.0; } - __host__ __device__ __forceinline__ void print() { - for (int j = 0; j < 3; j++) { for (int i = 0; i < 3; i++) { printf("%f ", m[i][j]); @@ -657,16 +635,15 @@ struct mat3 { printf("\n"); } - __host__ __device__ __forceinline__ float3 transform_point(const float3 &pt) const { + __host__ __device__ __forceinline__ float3 transform_point(const float3& pt) const { float3 temp = *this * pt; return make_float3(temp.x, temp.y, temp.z); } - __host__ __device__ __forceinline__ float3 transform_vector(const float3 &pt) const { + __host__ __device__ __forceinline__ float3 transform_vector(const float3& pt) const { float3 temp = *this * pt; return make_float3(temp.x, temp.y, temp.z); } - __host__ __device__ __forceinline__ mat3 rotate_zyx(const float3 &angs) { - + __host__ __device__ __forceinline__ mat3 rotate_zyx(const float3& angs) { float cx, sx, cy, sy, cz, sz; cx = (float)cos(angs.x); sx = (float)sin(angs.x); @@ -679,20 +656,18 @@ struct mat3 { m[1][0] = sz * cy; m[2][0] = -sy; - m[0][1] = -sz * cx + cz * sy*sx; - m[1][1] = cz * cx - sz * sy*sz; + m[0][1] = -sz * cx + cz * sy * sx; + m[1][1] = cz * cx - sz * sy * sz; m[2][1] = -cy * sx; - m[0][2] = -sz * sx + cz * sy*cx; - m[1][2] = cz * sx + sz * sy*cx; + m[0][2] = -sz * sx + cz * sy * cx; + m[1][2] = cz * sx + sz * sy * cx; m[2][2] = cy * cx; return *this; - } - __host__ __device__ __forceinline__ mat3 translate(const float3 &val) { - + __host__ __device__ __forceinline__ mat3 translate(const float3& val) { m[0][2] += val.x; m[1][2] += val.y; m[2][2] += val.z; @@ -700,8 +675,7 @@ struct mat3 { return *this; } - __host__ __device__ __forceinline__ mat3 scale(const float3 &val) { - + __host__ __device__ __forceinline__ mat3 scale(const float3& val) { m[0][0] *= val.x; m[1][1] *= val.y; m[2][2] *= val.z; @@ -709,30 +683,26 @@ struct mat3 { return *this; } - __host__ __device__ __forceinline__ mat3 toMatrix(double *arr) { - + __host__ __device__ __forceinline__ mat3 toMatrix(double* arr) { m[0][0] = arr[0]; m[1][0] = arr[1]; m[2][0] = arr[2]; m[0][1] = arr[3]; m[1][1] = arr[4]; m[2][1] = arr[5]; - m[0][2] = arr[6]; m[1][2] = arr[7]; m[2][2] = arr[8]; + m[0][2] = arr[6]; m[1][2] = arr[7]; m[2][2] = arr[8]; return *this; } - __host__ __device__ __forceinline__ mat3 toMatrix(float *arr) { - - m[0][0] = arr[0]; m[1][0] = arr[1]; m[2][0] = arr[2]; + __host__ __device__ __forceinline__ mat3 toMatrix(float* arr) { + m[0][0] = arr[0]; m[1][0] = arr[1]; m[2][0] = arr[2]; m[0][1] = arr[3]; m[1][1] = arr[4]; m[2][1] = arr[5]; m[0][2] = arr[6]; m[1][2] = arr[7]; m[2][2] = arr[8]; return *this; } - - __host__ __device__ __forceinline__ mat3 &operator*=(const float f) { return *this = *this * f; } - __host__ __device__ __forceinline__ mat3 &operator/=(const float f) { return *this = *this / f; } - __host__ __device__ __forceinline__ mat3 &operator+=(const mat3 &m) { return *this = *this + m; } - __host__ __device__ __forceinline__ mat3 &operator-=(const mat3 &m) { return *this = *this - m; } - __host__ __device__ __forceinline__ mat3 &operator*=(const mat3 &m) { return *this = *this * m; } - + __host__ __device__ __forceinline__ mat3& operator*=(const float f) { return *this = *this * f; } + __host__ __device__ __forceinline__ mat3& operator/=(const float f) { return *this = *this / f; } + __host__ __device__ __forceinline__ mat3& operator+=(const mat3& m) { return *this = *this + m; } + __host__ __device__ __forceinline__ mat3& operator-=(const mat3& m) { return *this = *this - m; } + __host__ __device__ __forceinline__ mat3& operator*=(const mat3& m) { return *this = *this * m; } }; #endif \ No newline at end of file diff --git a/source/hdr_loader.h b/source/hdr_loader.h index b420529..5d19160 100644 --- a/source/hdr_loader.h +++ b/source/hdr_loader.h @@ -68,13 +68,13 @@ static hdr_error_code_t hdr_read_image_header( if ((c = find_identifier(line, "EXPOSURE="))) { float f = 1.0f; - if (sscanf(c, "%f", &f)) + if (sscanf_s(c, "%f", &f)) header->exposure = f; } else if ((c = find_identifier(line, "GAMMA="))) { float f = 1.0f; - if (sscanf(c, "%f", &f)) + if (sscanf_s(c, "%f", &f)) header->gamma = f; } else if ((c = find_identifier(line, "FORMAT="))) @@ -90,11 +90,11 @@ static hdr_error_code_t hdr_read_image_header( { //!! extract flips, order? const char *x = strchr(line, 'X'); - if (!x || (x <= line) || !sscanf(x + 1, "%u", &header->rx)) + if (!x || (x <= line) || !sscanf_s(x + 1, "%u", &header->rx)) return HDR_ERROR_INVALID_HEADER; const char *y = strchr(line, 'Y'); - if (!y || (y <= line) || !sscanf(y + 1, "%u", &header->ry)) + if (!y || (y <= line) || !sscanf_s(y + 1, "%u", &header->ry)) return HDR_ERROR_INVALID_HEADER; break; @@ -250,7 +250,8 @@ static bool load_hdr_float4(float **pixels, unsigned int *rx, unsigned int *ry, { *pixels = NULL; *rx = *ry = 0; - FILE *fp = fopen(filename, "rb"); + FILE* fp = NULL; + fopen_s(&fp, filename, "rb"); if (!fp) return false; diff --git a/source/imgui/imgui_impl_glfw.cpp b/source/imgui/imgui_impl_glfw.cpp deleted file mode 100644 index 6467984..0000000 --- a/source/imgui/imgui_impl_glfw.cpp +++ /dev/null @@ -1,331 +0,0 @@ -// dear imgui: Platform Binding for GLFW -// This needs to be used along with a Renderer (e.g. OpenGL3, Vulkan..) -// (Info: GLFW is a cross-platform general purpose library for handling windows, inputs, OpenGL/Vulkan graphics context creation, etc.) -// (Requires: GLFW 3.1+) - -// Implemented features: -// [X] Platform: Clipboard support. -// [X] Platform: Gamepad support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'. -// [x] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'. FIXME: 3 cursors types are missing from GLFW. -// [X] Platform: Keyboard arrays indexed using GLFW_KEY_* codes, e.g. ImGui::IsKeyPressed(GLFW_KEY_SPACE). - -// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. -// If you are new to dear imgui, read examples/README.txt and read the documentation at the top of imgui.cpp. -// https://github.com/ocornut/imgui - -// CHANGELOG -// (minor and older changes stripped away, please see git history for details) -// 2019-03-12: Misc: Preserve DisplayFramebufferScale when main window is minimized. -// 2018-11-30: Misc: Setting up io.BackendPlatformName so it can be displayed in the About Window. -// 2018-11-07: Inputs: When installing our GLFW callbacks, we save user's previously installed ones - if any - and chain call them. -// 2018-08-01: Inputs: Workaround for Emscripten which doesn't seem to handle focus related calls. -// 2018-06-29: Inputs: Added support for the ImGuiMouseCursor_Hand cursor. -// 2018-06-08: Misc: Extracted imgui_impl_glfw.cpp/.h away from the old combined GLFW+OpenGL/Vulkan examples. -// 2018-03-20: Misc: Setup io.BackendFlags ImGuiBackendFlags_HasMouseCursors flag + honor ImGuiConfigFlags_NoMouseCursorChange flag. -// 2018-02-20: Inputs: Added support for mouse cursors (ImGui::GetMouseCursor() value, passed to glfwSetCursor()). -// 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves. -// 2018-02-06: Inputs: Added mapping for ImGuiKey_Space. -// 2018-01-25: Inputs: Added gamepad support if ImGuiConfigFlags_NavEnableGamepad is set. -// 2018-01-25: Inputs: Honoring the io.WantSetMousePos by repositioning the mouse (when using navigation and ImGuiConfigFlags_NavMoveMouse is set). -// 2018-01-20: Inputs: Added Horizontal Mouse Wheel support. -// 2018-01-18: Inputs: Added mapping for ImGuiKey_Insert. -// 2017-08-25: Inputs: MousePos set to -FLT_MAX,-FLT_MAX when mouse is unavailable/missing (instead of -1,-1). -// 2016-10-15: Misc: Added a void* user_data parameter to Clipboard function handlers. - -#include "imgui.h" -#include "imgui_impl_glfw.h" - -// GLFW -#include -#ifdef _WIN32 -#undef APIENTRY -#define GLFW_EXPOSE_NATIVE_WIN32 -#include // for glfwGetWin32Window -#endif -#define GLFW_HAS_WINDOW_TOPMOST (GLFW_VERSION_MAJOR * 1000 + GLFW_VERSION_MINOR * 100 >= 3200) // 3.2+ GLFW_FLOATING -#define GLFW_HAS_WINDOW_HOVERED (GLFW_VERSION_MAJOR * 1000 + GLFW_VERSION_MINOR * 100 >= 3300) // 3.3+ GLFW_HOVERED -#define GLFW_HAS_WINDOW_ALPHA (GLFW_VERSION_MAJOR * 1000 + GLFW_VERSION_MINOR * 100 >= 3300) // 3.3+ glfwSetWindowOpacity -#define GLFW_HAS_PER_MONITOR_DPI (GLFW_VERSION_MAJOR * 1000 + GLFW_VERSION_MINOR * 100 >= 3300) // 3.3+ glfwGetMonitorContentScale -#define GLFW_HAS_VULKAN (GLFW_VERSION_MAJOR * 1000 + GLFW_VERSION_MINOR * 100 >= 3200) // 3.2+ glfwCreateWindowSurface - -// Data -enum GlfwClientApi -{ - GlfwClientApi_Unknown, - GlfwClientApi_OpenGL, - GlfwClientApi_Vulkan -}; -static GLFWwindow* g_Window = NULL; -static GlfwClientApi g_ClientApi = GlfwClientApi_Unknown; -static double g_Time = 0.0; -static bool g_MouseJustPressed[5] = { false, false, false, false, false }; -static GLFWcursor* g_MouseCursors[ImGuiMouseCursor_COUNT] = { 0 }; - -// Chain GLFW callbacks: our callbacks will call the user's previously installed callbacks, if any. -static GLFWmousebuttonfun g_PrevUserCallbackMousebutton = NULL; -static GLFWscrollfun g_PrevUserCallbackScroll = NULL; -static GLFWkeyfun g_PrevUserCallbackKey = NULL; -static GLFWcharfun g_PrevUserCallbackChar = NULL; - -static const char* ImGui_ImplGlfw_GetClipboardText(void* user_data) -{ - return glfwGetClipboardString((GLFWwindow*)user_data); -} - -static void ImGui_ImplGlfw_SetClipboardText(void* user_data, const char* text) -{ - glfwSetClipboardString((GLFWwindow*)user_data, text); -} - -void ImGui_ImplGlfw_MouseButtonCallback(GLFWwindow* window, int button, int action, int mods) -{ - if (g_PrevUserCallbackMousebutton != NULL) - g_PrevUserCallbackMousebutton(window, button, action, mods); - - if (action == GLFW_PRESS && button >= 0 && button < IM_ARRAYSIZE(g_MouseJustPressed)) - g_MouseJustPressed[button] = true; -} - -void ImGui_ImplGlfw_ScrollCallback(GLFWwindow* window, double xoffset, double yoffset) -{ - if (g_PrevUserCallbackScroll != NULL) - g_PrevUserCallbackScroll(window, xoffset, yoffset); - - ImGuiIO& io = ImGui::GetIO(); - io.MouseWheelH += (float)xoffset; - io.MouseWheel += (float)yoffset; -} - -void ImGui_ImplGlfw_KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods) -{ - if (g_PrevUserCallbackKey != NULL) - g_PrevUserCallbackKey(window, key, scancode, action, mods); - - ImGuiIO& io = ImGui::GetIO(); - if (action == GLFW_PRESS) - io.KeysDown[key] = true; - if (action == GLFW_RELEASE) - io.KeysDown[key] = false; - - // Modifiers are not reliable across systems - io.KeyCtrl = io.KeysDown[GLFW_KEY_LEFT_CONTROL] || io.KeysDown[GLFW_KEY_RIGHT_CONTROL]; - io.KeyShift = io.KeysDown[GLFW_KEY_LEFT_SHIFT] || io.KeysDown[GLFW_KEY_RIGHT_SHIFT]; - io.KeyAlt = io.KeysDown[GLFW_KEY_LEFT_ALT] || io.KeysDown[GLFW_KEY_RIGHT_ALT]; - io.KeySuper = io.KeysDown[GLFW_KEY_LEFT_SUPER] || io.KeysDown[GLFW_KEY_RIGHT_SUPER]; -} - -void ImGui_ImplGlfw_CharCallback(GLFWwindow* window, unsigned int c) -{ - if (g_PrevUserCallbackChar != NULL) - g_PrevUserCallbackChar(window, c); - - ImGuiIO& io = ImGui::GetIO(); - if (c > 0 && c < 0x10000) - io.AddInputCharacter((unsigned int)c); - -} - -static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, GlfwClientApi client_api) -{ - g_Window = window; - g_Time = 0.0; - - // Setup back-end capabilities flags - ImGuiIO& io = ImGui::GetIO(); - io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; // We can honor GetMouseCursor() values (optional) - io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos; // We can honor io.WantSetMousePos requests (optional, rarely used) - io.BackendPlatformName = "imgui_impl_glfw"; - - // Keyboard mapping. ImGui will use those indices to peek into the io.KeysDown[] array. - io.KeyMap[ImGuiKey_Tab] = GLFW_KEY_TAB; - io.KeyMap[ImGuiKey_LeftArrow] = GLFW_KEY_LEFT; - io.KeyMap[ImGuiKey_RightArrow] = GLFW_KEY_RIGHT; - io.KeyMap[ImGuiKey_UpArrow] = GLFW_KEY_UP; - io.KeyMap[ImGuiKey_DownArrow] = GLFW_KEY_DOWN; - io.KeyMap[ImGuiKey_PageUp] = GLFW_KEY_PAGE_UP; - io.KeyMap[ImGuiKey_PageDown] = GLFW_KEY_PAGE_DOWN; - io.KeyMap[ImGuiKey_Home] = GLFW_KEY_HOME; - io.KeyMap[ImGuiKey_End] = GLFW_KEY_END; - io.KeyMap[ImGuiKey_Insert] = GLFW_KEY_INSERT; - io.KeyMap[ImGuiKey_Delete] = GLFW_KEY_DELETE; - io.KeyMap[ImGuiKey_Backspace] = GLFW_KEY_BACKSPACE; - io.KeyMap[ImGuiKey_Space] = GLFW_KEY_SPACE; - io.KeyMap[ImGuiKey_Enter] = GLFW_KEY_ENTER; - io.KeyMap[ImGuiKey_Escape] = GLFW_KEY_ESCAPE; - io.KeyMap[ImGuiKey_A] = GLFW_KEY_A; - io.KeyMap[ImGuiKey_C] = GLFW_KEY_C; - io.KeyMap[ImGuiKey_V] = GLFW_KEY_V; - io.KeyMap[ImGuiKey_X] = GLFW_KEY_X; - io.KeyMap[ImGuiKey_Y] = GLFW_KEY_Y; - io.KeyMap[ImGuiKey_Z] = GLFW_KEY_Z; - - io.SetClipboardTextFn = ImGui_ImplGlfw_SetClipboardText; - io.GetClipboardTextFn = ImGui_ImplGlfw_GetClipboardText; - io.ClipboardUserData = g_Window; -#if defined(_WIN32) - io.ImeWindowHandle = (void*)glfwGetWin32Window(g_Window); -#endif - - g_MouseCursors[ImGuiMouseCursor_Arrow] = glfwCreateStandardCursor(GLFW_ARROW_CURSOR); - g_MouseCursors[ImGuiMouseCursor_TextInput] = glfwCreateStandardCursor(GLFW_IBEAM_CURSOR); - g_MouseCursors[ImGuiMouseCursor_ResizeAll] = glfwCreateStandardCursor(GLFW_ARROW_CURSOR); // FIXME: GLFW doesn't have this. - g_MouseCursors[ImGuiMouseCursor_ResizeNS] = glfwCreateStandardCursor(GLFW_VRESIZE_CURSOR); - g_MouseCursors[ImGuiMouseCursor_ResizeEW] = glfwCreateStandardCursor(GLFW_HRESIZE_CURSOR); - g_MouseCursors[ImGuiMouseCursor_ResizeNESW] = glfwCreateStandardCursor(GLFW_ARROW_CURSOR); // FIXME: GLFW doesn't have this. - g_MouseCursors[ImGuiMouseCursor_ResizeNWSE] = glfwCreateStandardCursor(GLFW_ARROW_CURSOR); // FIXME: GLFW doesn't have this. - g_MouseCursors[ImGuiMouseCursor_Hand] = glfwCreateStandardCursor(GLFW_HAND_CURSOR); - - // Chain GLFW callbacks: our callbacks will call the user's previously installed callbacks, if any. - g_PrevUserCallbackMousebutton = NULL; - g_PrevUserCallbackScroll = NULL; - g_PrevUserCallbackKey = NULL; - g_PrevUserCallbackChar = NULL; - if (install_callbacks) - { - g_PrevUserCallbackMousebutton = glfwSetMouseButtonCallback(window, ImGui_ImplGlfw_MouseButtonCallback); - g_PrevUserCallbackScroll = glfwSetScrollCallback(window, ImGui_ImplGlfw_ScrollCallback); - g_PrevUserCallbackKey = glfwSetKeyCallback(window, ImGui_ImplGlfw_KeyCallback); - g_PrevUserCallbackChar = glfwSetCharCallback(window, ImGui_ImplGlfw_CharCallback); - } - - g_ClientApi = client_api; - return true; -} - -bool ImGui_ImplGlfw_InitForOpenGL(GLFWwindow* window, bool install_callbacks) -{ - return ImGui_ImplGlfw_Init(window, install_callbacks, GlfwClientApi_OpenGL); -} - -bool ImGui_ImplGlfw_InitForVulkan(GLFWwindow* window, bool install_callbacks) -{ - return ImGui_ImplGlfw_Init(window, install_callbacks, GlfwClientApi_Vulkan); -} - -void ImGui_ImplGlfw_Shutdown() -{ - for (ImGuiMouseCursor cursor_n = 0; cursor_n < ImGuiMouseCursor_COUNT; cursor_n++) - { - glfwDestroyCursor(g_MouseCursors[cursor_n]); - g_MouseCursors[cursor_n] = NULL; - } - g_ClientApi = GlfwClientApi_Unknown; -} - -static void ImGui_ImplGlfw_UpdateMousePosAndButtons() -{ - // Update buttons - ImGuiIO& io = ImGui::GetIO(); - for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++) - { - // If a mouse press event came, always pass it as "mouse held this frame", so we don't miss click-release events that are shorter than 1 frame. - io.MouseDown[i] = g_MouseJustPressed[i] || glfwGetMouseButton(g_Window, i) != 0; - g_MouseJustPressed[i] = false; - } - - // Update mouse position - const ImVec2 mouse_pos_backup = io.MousePos; - io.MousePos = ImVec2(-FLT_MAX, -FLT_MAX); -#ifdef __EMSCRIPTEN__ - const bool focused = true; // Emscripten -#else - const bool focused = glfwGetWindowAttrib(g_Window, GLFW_FOCUSED) != 0; -#endif - if (focused) - { - if (io.WantSetMousePos) - { - glfwSetCursorPos(g_Window, (double)mouse_pos_backup.x, (double)mouse_pos_backup.y); - } - else - { - double mouse_x, mouse_y; - glfwGetCursorPos(g_Window, &mouse_x, &mouse_y); - io.MousePos = ImVec2((float)mouse_x, (float)mouse_y); - } - } -} - -static void ImGui_ImplGlfw_UpdateMouseCursor() -{ - ImGuiIO& io = ImGui::GetIO(); - if ((io.ConfigFlags & ImGuiConfigFlags_NoMouseCursorChange) || glfwGetInputMode(g_Window, GLFW_CURSOR) == GLFW_CURSOR_DISABLED) - return; - - ImGuiMouseCursor imgui_cursor = ImGui::GetMouseCursor(); - if (imgui_cursor == ImGuiMouseCursor_None || io.MouseDrawCursor) - { - // Hide OS mouse cursor if imgui is drawing it or if it wants no cursor - glfwSetInputMode(g_Window, GLFW_CURSOR, GLFW_CURSOR_HIDDEN); - } - else - { - // Show OS mouse cursor - // FIXME-PLATFORM: Unfocused windows seems to fail changing the mouse cursor with GLFW 3.2, but 3.3 works here. - glfwSetCursor(g_Window, g_MouseCursors[imgui_cursor] ? g_MouseCursors[imgui_cursor] : g_MouseCursors[ImGuiMouseCursor_Arrow]); - glfwSetInputMode(g_Window, GLFW_CURSOR, GLFW_CURSOR_NORMAL); - } -} - -static void ImGui_ImplGlfw_UpdateGamepads() -{ - ImGuiIO& io = ImGui::GetIO(); - memset(io.NavInputs, 0, sizeof(io.NavInputs)); - if ((io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) == 0) - return; - - // Update gamepad inputs - #define MAP_BUTTON(NAV_NO, BUTTON_NO) { if (buttons_count > BUTTON_NO && buttons[BUTTON_NO] == GLFW_PRESS) io.NavInputs[NAV_NO] = 1.0f; } - #define MAP_ANALOG(NAV_NO, AXIS_NO, V0, V1) { float v = (axes_count > AXIS_NO) ? axes[AXIS_NO] : V0; v = (v - V0) / (V1 - V0); if (v > 1.0f) v = 1.0f; if (io.NavInputs[NAV_NO] < v) io.NavInputs[NAV_NO] = v; } - int axes_count = 0, buttons_count = 0; - const float* axes = glfwGetJoystickAxes(GLFW_JOYSTICK_1, &axes_count); - const unsigned char* buttons = glfwGetJoystickButtons(GLFW_JOYSTICK_1, &buttons_count); - MAP_BUTTON(ImGuiNavInput_Activate, 0); // Cross / A - MAP_BUTTON(ImGuiNavInput_Cancel, 1); // Circle / B - MAP_BUTTON(ImGuiNavInput_Menu, 2); // Square / X - MAP_BUTTON(ImGuiNavInput_Input, 3); // Triangle / Y - MAP_BUTTON(ImGuiNavInput_DpadLeft, 13); // D-Pad Left - MAP_BUTTON(ImGuiNavInput_DpadRight, 11); // D-Pad Right - MAP_BUTTON(ImGuiNavInput_DpadUp, 10); // D-Pad Up - MAP_BUTTON(ImGuiNavInput_DpadDown, 12); // D-Pad Down - MAP_BUTTON(ImGuiNavInput_FocusPrev, 4); // L1 / LB - MAP_BUTTON(ImGuiNavInput_FocusNext, 5); // R1 / RB - MAP_BUTTON(ImGuiNavInput_TweakSlow, 4); // L1 / LB - MAP_BUTTON(ImGuiNavInput_TweakFast, 5); // R1 / RB - MAP_ANALOG(ImGuiNavInput_LStickLeft, 0, -0.3f, -0.9f); - MAP_ANALOG(ImGuiNavInput_LStickRight,0, +0.3f, +0.9f); - MAP_ANALOG(ImGuiNavInput_LStickUp, 1, +0.3f, +0.9f); - MAP_ANALOG(ImGuiNavInput_LStickDown, 1, -0.3f, -0.9f); - #undef MAP_BUTTON - #undef MAP_ANALOG - if (axes_count > 0 && buttons_count > 0) - io.BackendFlags |= ImGuiBackendFlags_HasGamepad; - else - io.BackendFlags &= ~ImGuiBackendFlags_HasGamepad; -} - -void ImGui_ImplGlfw_NewFrame() -{ - ImGuiIO& io = ImGui::GetIO(); - IM_ASSERT(io.Fonts->IsBuilt() && "Font atlas not built! It is generally built by the renderer back-end. Missing call to renderer _NewFrame() function? e.g. ImGui_ImplOpenGL3_NewFrame()."); - - // Setup display size (every frame to accommodate for window resizing) - int w, h; - int display_w, display_h; - glfwGetWindowSize(g_Window, &w, &h); - glfwGetFramebufferSize(g_Window, &display_w, &display_h); - io.DisplaySize = ImVec2((float)w, (float)h); - if (w > 0 && h > 0) - io.DisplayFramebufferScale = ImVec2((float)display_w / w, (float)display_h / h); - - // Setup time step - double current_time = glfwGetTime(); - io.DeltaTime = g_Time > 0.0 ? (float)(current_time - g_Time) : (float)(1.0f/60.0f); - g_Time = current_time; - - ImGui_ImplGlfw_UpdateMousePosAndButtons(); - ImGui_ImplGlfw_UpdateMouseCursor(); - - // Gamepad navigation mapping - ImGui_ImplGlfw_UpdateGamepads(); -} diff --git a/source/imgui/imgui_impl_glfw.h b/source/imgui/imgui_impl_glfw.h deleted file mode 100644 index ccbe840..0000000 --- a/source/imgui/imgui_impl_glfw.h +++ /dev/null @@ -1,33 +0,0 @@ -// dear imgui: Platform Binding for GLFW -// This needs to be used along with a Renderer (e.g. OpenGL3, Vulkan..) -// (Info: GLFW is a cross-platform general purpose library for handling windows, inputs, OpenGL/Vulkan graphics context creation, etc.) - -// Implemented features: -// [X] Platform: Clipboard support. -// [X] Platform: Gamepad support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'. -// [x] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'. FIXME: 3 cursors types are missing from GLFW. -// [X] Platform: Keyboard arrays indexed using GLFW_KEY_* codes, e.g. ImGui::IsKeyPressed(GLFW_KEY_SPACE). - -// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. -// If you are new to dear imgui, read examples/README.txt and read the documentation at the top of imgui.cpp. -// https://github.com/ocornut/imgui - -// About GLSL version: -// The 'glsl_version' initialization parameter defaults to "#version 150" if NULL. -// Only override if your GL version doesn't handle this GLSL version. Keep NULL if unsure! - -#pragma once - -struct GLFWwindow; - -IMGUI_IMPL_API bool ImGui_ImplGlfw_InitForOpenGL(GLFWwindow* window, bool install_callbacks); -IMGUI_IMPL_API bool ImGui_ImplGlfw_InitForVulkan(GLFWwindow* window, bool install_callbacks); -IMGUI_IMPL_API void ImGui_ImplGlfw_Shutdown(); -IMGUI_IMPL_API void ImGui_ImplGlfw_NewFrame(); - -// InitXXX function with 'install_callbacks=true': install GLFW callbacks. They will call user's previously installed callbacks, if any. -// InitXXX function with 'install_callbacks=false': do not install GLFW callbacks. You will need to call them yourself from your own GLFW callbacks. -IMGUI_IMPL_API void ImGui_ImplGlfw_MouseButtonCallback(GLFWwindow* window, int button, int action, int mods); -IMGUI_IMPL_API void ImGui_ImplGlfw_ScrollCallback(GLFWwindow* window, double xoffset, double yoffset); -IMGUI_IMPL_API void ImGui_ImplGlfw_KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods); -IMGUI_IMPL_API void ImGui_ImplGlfw_CharCallback(GLFWwindow* window, unsigned int c); diff --git a/source/imgui/imgui_impl_opengl3.cpp b/source/imgui/imgui_impl_opengl3.cpp deleted file mode 100644 index 347da47..0000000 --- a/source/imgui/imgui_impl_opengl3.cpp +++ /dev/null @@ -1,599 +0,0 @@ -// dear imgui: Renderer for modern OpenGL with shaders / programmatic pipeline -// - Desktop GL: 3.x 4.x -// - Embedded GL: ES 2.0 (WebGL 1.0), ES 3.0 (WebGL 2.0) -// This needs to be used along with a Platform Binding (e.g. GLFW, SDL, Win32, custom..) - -// Implemented features: -// [X] Renderer: User texture binding. Use 'GLuint' OpenGL texture identifier as void*/ImTextureID. Read the FAQ about ImTextureID in imgui.cpp. - -// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. -// If you are new to dear imgui, read examples/README.txt and read the documentation at the top of imgui.cpp. -// https://github.com/ocornut/imgui - -// CHANGELOG -// (minor and older changes stripped away, please see git history for details) -// 2019-03-29: OpenGL: Not calling glBindBuffer more than necessary in the render loop. -// 2019-03-15: OpenGL: Added a dummy GL call + comments in ImGui_ImplOpenGL3_Init() to detect uninitialized GL function loaders early. -// 2019-03-03: OpenGL: Fix support for ES 2.0 (WebGL 1.0). -// 2019-02-20: OpenGL: Fix for OSX not supporting OpenGL 4.5, we don't try to read GL_CLIP_ORIGIN even if defined by the headers/loader. -// 2019-02-11: OpenGL: Projecting clipping rectangles correctly using draw_data->FramebufferScale to allow multi-viewports for retina display. -// 2019-02-01: OpenGL: Using GLSL 410 shaders for any version over 410 (e.g. 430, 450). -// 2018-11-30: Misc: Setting up io.BackendRendererName so it can be displayed in the About Window. -// 2018-11-13: OpenGL: Support for GL 4.5's glClipControl(GL_UPPER_LEFT) / GL_CLIP_ORIGIN. -// 2018-08-29: OpenGL: Added support for more OpenGL loaders: glew and glad, with comments indicative that any loader can be used. -// 2018-08-09: OpenGL: Default to OpenGL ES 3 on iOS and Android. GLSL version default to "#version 300 ES". -// 2018-07-30: OpenGL: Support for GLSL 300 ES and 410 core. Fixes for Emscripten compilation. -// 2018-07-10: OpenGL: Support for more GLSL versions (based on the GLSL version string). Added error output when shaders fail to compile/link. -// 2018-06-08: Misc: Extracted imgui_impl_opengl3.cpp/.h away from the old combined GLFW/SDL+OpenGL3 examples. -// 2018-06-08: OpenGL: Use draw_data->DisplayPos and draw_data->DisplaySize to setup projection matrix and clipping rectangle. -// 2018-05-25: OpenGL: Removed unnecessary backup/restore of GL_ELEMENT_ARRAY_BUFFER_BINDING since this is part of the VAO state. -// 2018-05-14: OpenGL: Making the call to glBindSampler() optional so 3.2 context won't fail if the function is a NULL pointer. -// 2018-03-06: OpenGL: Added const char* glsl_version parameter to ImGui_ImplOpenGL3_Init() so user can override the GLSL version e.g. "#version 150". -// 2018-02-23: OpenGL: Create the VAO in the render function so the setup can more easily be used with multiple shared GL context. -// 2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback and exposed ImGui_ImplSdlGL3_RenderDrawData() in the .h file so you can call it yourself. -// 2018-01-07: OpenGL: Changed GLSL shader version from 330 to 150. -// 2017-09-01: OpenGL: Save and restore current bound sampler. Save and restore current polygon mode. -// 2017-05-01: OpenGL: Fixed save and restore of current blend func state. -// 2017-05-01: OpenGL: Fixed save and restore of current GL_ACTIVE_TEXTURE. -// 2016-09-05: OpenGL: Fixed save and restore of current scissor rectangle. -// 2016-07-29: OpenGL: Explicitly setting GL_UNPACK_ROW_LENGTH to reduce issues because SDL changes it. (#752) - -//---------------------------------------- -// OpenGL GLSL GLSL -// version version string -//---------------------------------------- -// 2.0 110 "#version 110" -// 2.1 120 "#version 120" -// 3.0 130 "#version 130" -// 3.1 140 "#version 140" -// 3.2 150 "#version 150" -// 3.3 330 "#version 330 core" -// 4.0 400 "#version 400 core" -// 4.1 410 "#version 410 core" -// 4.2 420 "#version 410 core" -// 4.3 430 "#version 430 core" -// ES 2.0 100 "#version 100" = WebGL 1.0 -// ES 3.0 300 "#version 300 es" = WebGL 2.0 -//---------------------------------------- - -#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS) -#define _CRT_SECURE_NO_WARNINGS -#endif - -#include "imgui.h" -#include "imgui_impl_opengl3.h" -#include -#if defined(_MSC_VER) && _MSC_VER <= 1500 // MSVC 2008 or earlier -#include // intptr_t -#else -#include // intptr_t -#endif -#if defined(__APPLE__) -#include "TargetConditionals.h" -#endif - -// Auto-detect GL version -#if !defined(IMGUI_IMPL_OPENGL_ES2) && !defined(IMGUI_IMPL_OPENGL_ES3) -#if (defined(__APPLE__) && TARGET_OS_IOS) || (defined(__ANDROID__)) -#define IMGUI_IMPL_OPENGL_ES3 // iOS, Android -> GL ES 3, "#version 300 es" -#elif defined(__EMSCRIPTEN__) -#define IMGUI_IMPL_OPENGL_ES2 // Emscripten -> GL ES 2, "#version 100" -#endif -#endif - -#if defined(IMGUI_IMPL_OPENGL_ES2) -#include -#elif defined(IMGUI_IMPL_OPENGL_ES3) -#include // Use GL ES 3 -#else -// About Desktop OpenGL function loaders: -// Modern desktop OpenGL doesn't have a standard portable header file to load OpenGL function pointers. -// Helper libraries are often used for this purpose! Here we are supporting a few common ones (gl3w, glew, glad). -// You may use another loader/header of your choice (glext, glLoadGen, etc.), or chose to manually implement your own. -#if defined(IMGUI_IMPL_OPENGL_LOADER_GL3W) -#include // Needs to be initialized with gl3wInit() in user's code -#elif defined(IMGUI_IMPL_OPENGL_LOADER_GLEW) -#include // Needs to be initialized with glewInit() in user's code -#elif defined(IMGUI_IMPL_OPENGL_LOADER_GLAD) -#include // Needs to be initialized with gladLoadGL() in user's code -#else -#include IMGUI_IMPL_OPENGL_LOADER_CUSTOM -#endif -#endif - -// OpenGL Data -static char g_GlslVersionString[32] = ""; -static GLuint g_FontTexture = 0; -static GLuint g_ShaderHandle = 0, g_VertHandle = 0, g_FragHandle = 0; -static int g_AttribLocationTex = 0, g_AttribLocationProjMtx = 0; // Uniforms location -static int g_AttribLocationVtxPos = 0, g_AttribLocationVtxUV = 0, g_AttribLocationVtxColor = 0; // Vertex attributes location -static unsigned int g_VboHandle = 0, g_ElementsHandle = 0; - -// Functions -bool ImGui_ImplOpenGL3_Init(const char* glsl_version) -{ - ImGuiIO& io = ImGui::GetIO(); - io.BackendRendererName = "imgui_impl_opengl3"; - - // Store GLSL version string so we can refer to it later in case we recreate shaders. Note: GLSL version is NOT the same as GL version. Leave this to NULL if unsure. -#if defined(IMGUI_IMPL_OPENGL_ES2) - if (glsl_version == NULL) - glsl_version = "#version 100"; -#elif defined(IMGUI_IMPL_OPENGL_ES3) - if (glsl_version == NULL) - glsl_version = "#version 300 es"; -#else - if (glsl_version == NULL) - glsl_version = "#version 130"; -#endif - IM_ASSERT((int)strlen(glsl_version) + 2 < IM_ARRAYSIZE(g_GlslVersionString)); - strcpy(g_GlslVersionString, glsl_version); - strcat(g_GlslVersionString, "\n"); - - // Make a dummy GL call (we don't actually need the result) - // IF YOU GET A CRASH HERE: it probably means that you haven't initialized the OpenGL function loader used by this code. - // Desktop OpenGL 3/4 need a function loader. See the IMGUI_IMPL_OPENGL_LOADER_xxx explanation above. - GLint current_texture; - glGetIntegerv(GL_TEXTURE_BINDING_2D, ¤t_texture); - - return true; -} - -void ImGui_ImplOpenGL3_Shutdown() -{ - ImGui_ImplOpenGL3_DestroyDeviceObjects(); -} - -void ImGui_ImplOpenGL3_NewFrame() -{ - if (!g_FontTexture) - ImGui_ImplOpenGL3_CreateDeviceObjects(); -} - -// OpenGL3 Render function. -// (this used to be set in io.RenderDrawListsFn and called by ImGui::Render(), but you can now call this directly from your main loop) -// Note that this implementation is little overcomplicated because we are saving/setting up/restoring every OpenGL state explicitly, in order to be able to run within any OpenGL engine that doesn't do so. -void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data) -{ - // Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates) - int fb_width = (int)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x); - int fb_height = (int)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y); - if (fb_width <= 0 || fb_height <= 0) - return; - - // Backup GL state - GLenum last_active_texture; glGetIntegerv(GL_ACTIVE_TEXTURE, (GLint*)&last_active_texture); - glActiveTexture(GL_TEXTURE0); - GLint last_program; glGetIntegerv(GL_CURRENT_PROGRAM, &last_program); - GLint last_texture; glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); -#ifdef GL_SAMPLER_BINDING - GLint last_sampler; glGetIntegerv(GL_SAMPLER_BINDING, &last_sampler); -#endif - GLint last_array_buffer; glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &last_array_buffer); -#ifndef IMGUI_IMPL_OPENGL_ES2 - GLint last_vertex_array_object; glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &last_vertex_array_object); -#endif -#ifdef GL_POLYGON_MODE - GLint last_polygon_mode[2]; glGetIntegerv(GL_POLYGON_MODE, last_polygon_mode); -#endif - GLint last_viewport[4]; glGetIntegerv(GL_VIEWPORT, last_viewport); - GLint last_scissor_box[4]; glGetIntegerv(GL_SCISSOR_BOX, last_scissor_box); - GLenum last_blend_src_rgb; glGetIntegerv(GL_BLEND_SRC_RGB, (GLint*)&last_blend_src_rgb); - GLenum last_blend_dst_rgb; glGetIntegerv(GL_BLEND_DST_RGB, (GLint*)&last_blend_dst_rgb); - GLenum last_blend_src_alpha; glGetIntegerv(GL_BLEND_SRC_ALPHA, (GLint*)&last_blend_src_alpha); - GLenum last_blend_dst_alpha; glGetIntegerv(GL_BLEND_DST_ALPHA, (GLint*)&last_blend_dst_alpha); - GLenum last_blend_equation_rgb; glGetIntegerv(GL_BLEND_EQUATION_RGB, (GLint*)&last_blend_equation_rgb); - GLenum last_blend_equation_alpha; glGetIntegerv(GL_BLEND_EQUATION_ALPHA, (GLint*)&last_blend_equation_alpha); - GLboolean last_enable_blend = glIsEnabled(GL_BLEND); - GLboolean last_enable_cull_face = glIsEnabled(GL_CULL_FACE); - GLboolean last_enable_depth_test = glIsEnabled(GL_DEPTH_TEST); - GLboolean last_enable_scissor_test = glIsEnabled(GL_SCISSOR_TEST); - bool clip_origin_lower_left = true; -#if defined(GL_CLIP_ORIGIN) && !defined(__APPLE__) - GLenum last_clip_origin = 0; glGetIntegerv(GL_CLIP_ORIGIN, (GLint*)&last_clip_origin); // Support for GL 4.5's glClipControl(GL_UPPER_LEFT) - if (last_clip_origin == GL_UPPER_LEFT) - clip_origin_lower_left = false; -#endif - - // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled, polygon fill - glEnable(GL_BLEND); - glBlendEquation(GL_FUNC_ADD); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glDisable(GL_CULL_FACE); - glDisable(GL_DEPTH_TEST); - glEnable(GL_SCISSOR_TEST); -#ifdef GL_POLYGON_MODE - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); -#endif - - // Setup viewport, orthographic projection matrix - // Our visible imgui space lies from draw_data->DisplayPos (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right). DisplayMin is typically (0,0) for single viewport apps. - glViewport(0, 0, (GLsizei)fb_width, (GLsizei)fb_height); - float L = draw_data->DisplayPos.x; - float R = draw_data->DisplayPos.x + draw_data->DisplaySize.x; - float T = draw_data->DisplayPos.y; - float B = draw_data->DisplayPos.y + draw_data->DisplaySize.y; - const float ortho_projection[4][4] = - { - { 2.0f/(R-L), 0.0f, 0.0f, 0.0f }, - { 0.0f, 2.0f/(T-B), 0.0f, 0.0f }, - { 0.0f, 0.0f, -1.0f, 0.0f }, - { (R+L)/(L-R), (T+B)/(B-T), 0.0f, 1.0f }, - }; - glUseProgram(g_ShaderHandle); - glUniform1i(g_AttribLocationTex, 0); - glUniformMatrix4fv(g_AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]); -#ifdef GL_SAMPLER_BINDING - glBindSampler(0, 0); // We use combined texture/sampler state. Applications using GL 3.3 may set that otherwise. -#endif - - // Recreate the VAO every time (this is to easily allow multiple GL contexts to be rendered to. VAO are not shared among GL contexts) - // The renderer would actually work without any VAO bound, but then our VertexAttrib calls would overwrite the default one currently bound. -#ifndef IMGUI_IMPL_OPENGL_ES2 - GLuint vertex_array_object = 0; - glGenVertexArrays(1, &vertex_array_object); - glBindVertexArray(vertex_array_object); -#endif - - // Bind vertex/index buffers and setup attributes for ImDrawVert - glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_ElementsHandle); - glEnableVertexAttribArray(g_AttribLocationVtxPos); - glEnableVertexAttribArray(g_AttribLocationVtxUV); - glEnableVertexAttribArray(g_AttribLocationVtxColor); - glVertexAttribPointer(g_AttribLocationVtxPos, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)IM_OFFSETOF(ImDrawVert, pos)); - glVertexAttribPointer(g_AttribLocationVtxUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)IM_OFFSETOF(ImDrawVert, uv)); - glVertexAttribPointer(g_AttribLocationVtxColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)IM_OFFSETOF(ImDrawVert, col)); - - // Will project scissor/clipping rectangles into framebuffer space - ImVec2 clip_off = draw_data->DisplayPos; // (0,0) unless using multi-viewports - ImVec2 clip_scale = draw_data->FramebufferScale; // (1,1) unless using retina display which are often (2,2) - - // Render command lists - for (int n = 0; n < draw_data->CmdListsCount; n++) - { - const ImDrawList* cmd_list = draw_data->CmdLists[n]; - size_t idx_buffer_offset = 0; - - // Upload vertex/index buffers - glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)cmd_list->VtxBuffer.Size * sizeof(ImDrawVert), (const GLvoid*)cmd_list->VtxBuffer.Data, GL_STREAM_DRAW); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, (GLsizeiptr)cmd_list->IdxBuffer.Size * sizeof(ImDrawIdx), (const GLvoid*)cmd_list->IdxBuffer.Data, GL_STREAM_DRAW); - - for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++) - { - const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i]; - if (pcmd->UserCallback) - { - // User callback (registered via ImDrawList::AddCallback) - pcmd->UserCallback(cmd_list, pcmd); - } - else - { - // Project scissor/clipping rectangles into framebuffer space - ImVec4 clip_rect; - clip_rect.x = (pcmd->ClipRect.x - clip_off.x) * clip_scale.x; - clip_rect.y = (pcmd->ClipRect.y - clip_off.y) * clip_scale.y; - clip_rect.z = (pcmd->ClipRect.z - clip_off.x) * clip_scale.x; - clip_rect.w = (pcmd->ClipRect.w - clip_off.y) * clip_scale.y; - - if (clip_rect.x < fb_width && clip_rect.y < fb_height && clip_rect.z >= 0.0f && clip_rect.w >= 0.0f) - { - // Apply scissor/clipping rectangle - if (clip_origin_lower_left) - glScissor((int)clip_rect.x, (int)(fb_height - clip_rect.w), (int)(clip_rect.z - clip_rect.x), (int)(clip_rect.w - clip_rect.y)); - else - glScissor((int)clip_rect.x, (int)clip_rect.y, (int)clip_rect.z, (int)clip_rect.w); // Support for GL 4.5 rarely used glClipControl(GL_UPPER_LEFT) - - // Bind texture, Draw - glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId); - glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, (void*)idx_buffer_offset); - } - } - idx_buffer_offset += pcmd->ElemCount * sizeof(ImDrawIdx); - } - } - - // Destroy the temporary VAO -#ifndef IMGUI_IMPL_OPENGL_ES2 - glDeleteVertexArrays(1, &vertex_array_object); -#endif - - // Restore modified GL state - glUseProgram(last_program); - glBindTexture(GL_TEXTURE_2D, last_texture); -#ifdef GL_SAMPLER_BINDING - glBindSampler(0, last_sampler); -#endif - glActiveTexture(last_active_texture); -#ifndef IMGUI_IMPL_OPENGL_ES2 - glBindVertexArray(last_vertex_array_object); -#endif - glBindBuffer(GL_ARRAY_BUFFER, last_array_buffer); - glBlendEquationSeparate(last_blend_equation_rgb, last_blend_equation_alpha); - glBlendFuncSeparate(last_blend_src_rgb, last_blend_dst_rgb, last_blend_src_alpha, last_blend_dst_alpha); - if (last_enable_blend) glEnable(GL_BLEND); else glDisable(GL_BLEND); - if (last_enable_cull_face) glEnable(GL_CULL_FACE); else glDisable(GL_CULL_FACE); - if (last_enable_depth_test) glEnable(GL_DEPTH_TEST); else glDisable(GL_DEPTH_TEST); - if (last_enable_scissor_test) glEnable(GL_SCISSOR_TEST); else glDisable(GL_SCISSOR_TEST); -#ifdef GL_POLYGON_MODE - glPolygonMode(GL_FRONT_AND_BACK, (GLenum)last_polygon_mode[0]); -#endif - glViewport(last_viewport[0], last_viewport[1], (GLsizei)last_viewport[2], (GLsizei)last_viewport[3]); - glScissor(last_scissor_box[0], last_scissor_box[1], (GLsizei)last_scissor_box[2], (GLsizei)last_scissor_box[3]); -} - -bool ImGui_ImplOpenGL3_CreateFontsTexture() -{ - // Build texture atlas - ImGuiIO& io = ImGui::GetIO(); - unsigned char* pixels; - int width, height; - io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); // Load as RGBA 32-bits (75% of the memory is wasted, but default font is so small) because it is more likely to be compatible with user's existing shaders. If your ImTextureId represent a higher-level concept than just a GL texture id, consider calling GetTexDataAsAlpha8() instead to save on GPU memory. - - // Upload texture to graphics system - GLint last_texture; - glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); - glGenTextures(1, &g_FontTexture); - glBindTexture(GL_TEXTURE_2D, g_FontTexture); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); -#ifdef GL_UNPACK_ROW_LENGTH - glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); -#endif - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); - - // Store our identifier - io.Fonts->TexID = (ImTextureID)(intptr_t)g_FontTexture; - - // Restore state - glBindTexture(GL_TEXTURE_2D, last_texture); - - return true; -} - -void ImGui_ImplOpenGL3_DestroyFontsTexture() -{ - if (g_FontTexture) - { - ImGuiIO& io = ImGui::GetIO(); - glDeleteTextures(1, &g_FontTexture); - io.Fonts->TexID = 0; - g_FontTexture = 0; - } -} - -// If you get an error please report on github. You may try different GL context version or GLSL version. See GL<>GLSL version table at the top of this file. -static bool CheckShader(GLuint handle, const char* desc) -{ - GLint status = 0, log_length = 0; - glGetShaderiv(handle, GL_COMPILE_STATUS, &status); - glGetShaderiv(handle, GL_INFO_LOG_LENGTH, &log_length); - if ((GLboolean)status == GL_FALSE) - fprintf(stderr, "ERROR: ImGui_ImplOpenGL3_CreateDeviceObjects: failed to compile %s!\n", desc); - if (log_length > 0) - { - ImVector buf; - buf.resize((int)(log_length + 1)); - glGetShaderInfoLog(handle, log_length, NULL, (GLchar*)buf.begin()); - fprintf(stderr, "%s\n", buf.begin()); - } - return (GLboolean)status == GL_TRUE; -} - -// If you get an error please report on GitHub. You may try different GL context version or GLSL version. -static bool CheckProgram(GLuint handle, const char* desc) -{ - GLint status = 0, log_length = 0; - glGetProgramiv(handle, GL_LINK_STATUS, &status); - glGetProgramiv(handle, GL_INFO_LOG_LENGTH, &log_length); - if ((GLboolean)status == GL_FALSE) - fprintf(stderr, "ERROR: ImGui_ImplOpenGL3_CreateDeviceObjects: failed to link %s! (with GLSL '%s')\n", desc, g_GlslVersionString); - if (log_length > 0) - { - ImVector buf; - buf.resize((int)(log_length + 1)); - glGetProgramInfoLog(handle, log_length, NULL, (GLchar*)buf.begin()); - fprintf(stderr, "%s\n", buf.begin()); - } - return (GLboolean)status == GL_TRUE; -} - -bool ImGui_ImplOpenGL3_CreateDeviceObjects() -{ - // Backup GL state - GLint last_texture, last_array_buffer; - glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); - glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &last_array_buffer); -#ifndef IMGUI_IMPL_OPENGL_ES2 - GLint last_vertex_array; - glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &last_vertex_array); -#endif - - // Parse GLSL version string - int glsl_version = 130; - sscanf(g_GlslVersionString, "#version %d", &glsl_version); - - const GLchar* vertex_shader_glsl_120 = - "uniform mat4 ProjMtx;\n" - "attribute vec2 Position;\n" - "attribute vec2 UV;\n" - "attribute vec4 Color;\n" - "varying vec2 Frag_UV;\n" - "varying vec4 Frag_Color;\n" - "void main()\n" - "{\n" - " Frag_UV = UV;\n" - " Frag_Color = Color;\n" - " gl_Position = ProjMtx * vec4(Position.xy,0,1);\n" - "}\n"; - - const GLchar* vertex_shader_glsl_130 = - "uniform mat4 ProjMtx;\n" - "in vec2 Position;\n" - "in vec2 UV;\n" - "in vec4 Color;\n" - "out vec2 Frag_UV;\n" - "out vec4 Frag_Color;\n" - "void main()\n" - "{\n" - " Frag_UV = UV;\n" - " Frag_Color = Color;\n" - " gl_Position = ProjMtx * vec4(Position.xy,0,1);\n" - "}\n"; - - const GLchar* vertex_shader_glsl_300_es = - "precision mediump float;\n" - "layout (location = 0) in vec2 Position;\n" - "layout (location = 1) in vec2 UV;\n" - "layout (location = 2) in vec4 Color;\n" - "uniform mat4 ProjMtx;\n" - "out vec2 Frag_UV;\n" - "out vec4 Frag_Color;\n" - "void main()\n" - "{\n" - " Frag_UV = UV;\n" - " Frag_Color = Color;\n" - " gl_Position = ProjMtx * vec4(Position.xy,0,1);\n" - "}\n"; - - const GLchar* vertex_shader_glsl_410_core = - "layout (location = 0) in vec2 Position;\n" - "layout (location = 1) in vec2 UV;\n" - "layout (location = 2) in vec4 Color;\n" - "uniform mat4 ProjMtx;\n" - "out vec2 Frag_UV;\n" - "out vec4 Frag_Color;\n" - "void main()\n" - "{\n" - " Frag_UV = UV;\n" - " Frag_Color = Color;\n" - " gl_Position = ProjMtx * vec4(Position.xy,0,1);\n" - "}\n"; - - const GLchar* fragment_shader_glsl_120 = - "#ifdef GL_ES\n" - " precision mediump float;\n" - "#endif\n" - "uniform sampler2D Texture;\n" - "varying vec2 Frag_UV;\n" - "varying vec4 Frag_Color;\n" - "void main()\n" - "{\n" - " gl_FragColor = Frag_Color * texture2D(Texture, Frag_UV.st);\n" - "}\n"; - - const GLchar* fragment_shader_glsl_130 = - "uniform sampler2D Texture;\n" - "in vec2 Frag_UV;\n" - "in vec4 Frag_Color;\n" - "out vec4 Out_Color;\n" - "void main()\n" - "{\n" - " Out_Color = Frag_Color * texture(Texture, Frag_UV.st);\n" - "}\n"; - - const GLchar* fragment_shader_glsl_300_es = - "precision mediump float;\n" - "uniform sampler2D Texture;\n" - "in vec2 Frag_UV;\n" - "in vec4 Frag_Color;\n" - "layout (location = 0) out vec4 Out_Color;\n" - "void main()\n" - "{\n" - " Out_Color = Frag_Color * texture(Texture, Frag_UV.st);\n" - "}\n"; - - const GLchar* fragment_shader_glsl_410_core = - "in vec2 Frag_UV;\n" - "in vec4 Frag_Color;\n" - "uniform sampler2D Texture;\n" - "layout (location = 0) out vec4 Out_Color;\n" - "void main()\n" - "{\n" - " Out_Color = Frag_Color * texture(Texture, Frag_UV.st);\n" - "}\n"; - - // Select shaders matching our GLSL versions - const GLchar* vertex_shader = NULL; - const GLchar* fragment_shader = NULL; - if (glsl_version < 130) - { - vertex_shader = vertex_shader_glsl_120; - fragment_shader = fragment_shader_glsl_120; - } - else if (glsl_version >= 410) - { - vertex_shader = vertex_shader_glsl_410_core; - fragment_shader = fragment_shader_glsl_410_core; - } - else if (glsl_version == 300) - { - vertex_shader = vertex_shader_glsl_300_es; - fragment_shader = fragment_shader_glsl_300_es; - } - else - { - vertex_shader = vertex_shader_glsl_130; - fragment_shader = fragment_shader_glsl_130; - } - - // Create shaders - const GLchar* vertex_shader_with_version[2] = { g_GlslVersionString, vertex_shader }; - g_VertHandle = glCreateShader(GL_VERTEX_SHADER); - glShaderSource(g_VertHandle, 2, vertex_shader_with_version, NULL); - glCompileShader(g_VertHandle); - CheckShader(g_VertHandle, "vertex shader"); - - const GLchar* fragment_shader_with_version[2] = { g_GlslVersionString, fragment_shader }; - g_FragHandle = glCreateShader(GL_FRAGMENT_SHADER); - glShaderSource(g_FragHandle, 2, fragment_shader_with_version, NULL); - glCompileShader(g_FragHandle); - CheckShader(g_FragHandle, "fragment shader"); - - g_ShaderHandle = glCreateProgram(); - glAttachShader(g_ShaderHandle, g_VertHandle); - glAttachShader(g_ShaderHandle, g_FragHandle); - glLinkProgram(g_ShaderHandle); - CheckProgram(g_ShaderHandle, "shader program"); - - g_AttribLocationTex = glGetUniformLocation(g_ShaderHandle, "Texture"); - g_AttribLocationProjMtx = glGetUniformLocation(g_ShaderHandle, "ProjMtx"); - g_AttribLocationVtxPos = glGetAttribLocation(g_ShaderHandle, "Position"); - g_AttribLocationVtxUV = glGetAttribLocation(g_ShaderHandle, "UV"); - g_AttribLocationVtxColor = glGetAttribLocation(g_ShaderHandle, "Color"); - - // Create buffers - glGenBuffers(1, &g_VboHandle); - glGenBuffers(1, &g_ElementsHandle); - - ImGui_ImplOpenGL3_CreateFontsTexture(); - - // Restore modified GL state - glBindTexture(GL_TEXTURE_2D, last_texture); - glBindBuffer(GL_ARRAY_BUFFER, last_array_buffer); -#ifndef IMGUI_IMPL_OPENGL_ES2 - glBindVertexArray(last_vertex_array); -#endif - - return true; -} - -void ImGui_ImplOpenGL3_DestroyDeviceObjects() -{ - if (g_VboHandle) glDeleteBuffers(1, &g_VboHandle); - if (g_ElementsHandle) glDeleteBuffers(1, &g_ElementsHandle); - g_VboHandle = g_ElementsHandle = 0; - - if (g_ShaderHandle && g_VertHandle) glDetachShader(g_ShaderHandle, g_VertHandle); - if (g_VertHandle) glDeleteShader(g_VertHandle); - g_VertHandle = 0; - - if (g_ShaderHandle && g_FragHandle) glDetachShader(g_ShaderHandle, g_FragHandle); - if (g_FragHandle) glDeleteShader(g_FragHandle); - g_FragHandle = 0; - - if (g_ShaderHandle) glDeleteProgram(g_ShaderHandle); - g_ShaderHandle = 0; - - ImGui_ImplOpenGL3_DestroyFontsTexture(); -} diff --git a/source/imgui/imgui_impl_opengl3.h b/source/imgui/imgui_impl_opengl3.h deleted file mode 100644 index a0dee5a..0000000 --- a/source/imgui/imgui_impl_opengl3.h +++ /dev/null @@ -1,46 +0,0 @@ -// dear imgui: Renderer for modern OpenGL with shaders / programmatic pipeline -// - Desktop GL: 3.x 4.x -// - Embedded GL: ES 2.0 (WebGL 1.0), ES 3.0 (WebGL 2.0) -// This needs to be used along with a Platform Binding (e.g. GLFW, SDL, Win32, custom..) - -// Implemented features: -// [X] Renderer: User texture binding. Use 'GLuint' OpenGL texture identifier as void*/ImTextureID. Read the FAQ about ImTextureID in imgui.cpp. - -// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. -// If you are new to dear imgui, read examples/README.txt and read the documentation at the top of imgui.cpp. -// https://github.com/ocornut/imgui - -// About Desktop OpenGL function loaders: -// Modern desktop OpenGL doesn't have a standard portable header file to load OpenGL function pointers. -// Helper libraries are often used for this purpose! Here we are supporting a few common ones (gl3w, glew, glad). -// You may use another loader/header of your choice (glext, glLoadGen, etc.), or chose to manually implement your own. - -// About GLSL version: -// The 'glsl_version' initialization parameter should be NULL (default) or a "#version XXX" string. -// On computer platform the GLSL version default to "#version 130". On OpenGL ES 3 platform it defaults to "#version 300 es" -// Only override if your GL version doesn't handle this GLSL version. See GLSL version table at the top of imgui_impl_opengl3.cpp. - -#pragma once - -// Specific OpenGL versions -//#define IMGUI_IMPL_OPENGL_ES2 // Auto-detected on Emscripten -//#define IMGUI_IMPL_OPENGL_ES3 // Auto-detected on iOS/Android - -// Set default OpenGL3 loader to be glew -#if !defined(IMGUI_IMPL_OPENGL_LOADER_GL3W) \ - && !defined(IMGUI_IMPL_OPENGL_LOADER_GLEW) \ - && !defined(IMGUI_IMPL_OPENGL_LOADER_GLAD) \ - && !defined(IMGUI_IMPL_OPENGL_LOADER_CUSTOM) -#define IMGUI_IMPL_OPENGL_LOADER_GLEW -#endif - -IMGUI_IMPL_API bool ImGui_ImplOpenGL3_Init(const char* glsl_version = NULL); -IMGUI_IMPL_API void ImGui_ImplOpenGL3_Shutdown(); -IMGUI_IMPL_API void ImGui_ImplOpenGL3_NewFrame(); -IMGUI_IMPL_API void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data); - -// Called by Init/NewFrame/Shutdown -IMGUI_IMPL_API bool ImGui_ImplOpenGL3_CreateFontsTexture(); -IMGUI_IMPL_API void ImGui_ImplOpenGL3_DestroyFontsTexture(); -IMGUI_IMPL_API bool ImGui_ImplOpenGL3_CreateDeviceObjects(); -IMGUI_IMPL_API void ImGui_ImplOpenGL3_DestroyDeviceObjects(); diff --git a/source/main.cpp b/source/main.cpp index 6975786..d1e9169 100644 --- a/source/main.cpp +++ b/source/main.cpp @@ -9,11 +9,11 @@ // * Redistributions in binary form must reproduce the above copyright notice, // this list of conditions and the following disclaimer in the documentation // and/or other materials provided with the distribution. -// +// // * Neither the name of the copyright holder nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. -// +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE @@ -24,18 +24,17 @@ // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, // OR TORT(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// +// // Copyright(c) 2019, Sergen Eren // All rights reserved. //---------------------------------------------------------------------------------- -// +// // Version 1.0: Sergen Eren, 21/10/2019 // -// File: Main entry point for render kernel. +// File: Main entry point for render kernel. // //----------------------------------------------- - #include "imgui.h" #include "imgui_impl_glfw.h" #include "imgui_impl_opengl3.h" @@ -63,7 +62,7 @@ #include #include -#include "boost/filesystem.hpp" +#include #undef APIENTRY @@ -84,18 +83,16 @@ // Instance file parser #include "instancer_hda/volume_instance.h" -//#define SAVE_TGA -#define SAVE_OPENEXR +#define SAVE_JPG +//#define SAVE_OPENEXR #include // Third Party -#define OIDN_STATIC_LIB #include - -namespace fs = boost::filesystem; +namespace fs = std::filesystem; // Atmosphere @@ -114,10 +111,10 @@ std::vector point_lights; light_list l_list(0); CUdeviceptr d_lights; -static int num_volumes = 3; // TODO: read number of instances from json file +static int num_volumes = 3; // TODO: read number of instances from json file BVH_Builder bvh_builder; -// Cam parameters +// Cam parameters camera cam; float3 lookfrom; float3 lookat; @@ -144,6 +141,43 @@ bool empty_volume = false; } \ } while(false) +std::string OIDNErrorToString(OIDNError errorCode) +{ + std::string ret; + switch (errorCode) + { + case OIDN_ERROR_UNKNOWN: + ret += "OIDN Error unknown "; + break; + case OIDN_ERROR_INVALID_ARGUMENT: + ret += "OIDN Error invalid argument"; + break; + case OIDN_ERROR_INVALID_OPERATION: + ret += "OIDN Error invalid operation"; + break; + case OIDN_ERROR_OUT_OF_MEMORY: + ret += "OIDN Error out of memory"; + break; + case OIDN_ERROR_UNSUPPORTED_HARDWARE: + ret += "OIDN Error unsupported hardware"; + break; + default: + break; + } + + return ret; +} + +static void OIDNErrorCallback(void* ptr, OIDNError errorCode, const char* errorStr) +{ + if (errorCode == OIDN_ERROR_CANCELLED) + return; + + std::string errorMsg = OIDNErrorToString(errorCode); + errorMsg += std::string("! msg: ") + std::string(errorStr); + printf("OIDN Error: %s \n", errorMsg.c_str()); +} + // Env sampling functions static bool solveQuadratic(float a, float b, float c, float& x1, float& x2) { @@ -168,7 +202,6 @@ static bool solveQuadratic(float a, float b, float c, float& x1, float& x2) // check ray against earth and atmosphere upper bound static bool raySphereIntersect(const float3& orig, const float3& dir, const float& radius, float& t0, float& t1) { - float A = dir.x * dir.x + dir.y * dir.y + dir.z * dir.z; float B = 2 * (dir.x * orig.x + dir.y * orig.y + dir.z * orig.z); float C = orig.x * orig.x + orig.y * orig.y + orig.z * orig.z - radius * radius; @@ -186,15 +219,12 @@ static bool raySphereIntersect(const float3& orig, const float3& dir, const floa // Degree to radians conversion static float degree_to_radians(float degree) { - return degree * float(M_PI) / 180.0f; - } // Polar coordinates to direction static float3 degree_to_cartesian(float azimuth, float elevation) { - float az = clamp(azimuth, .0f, 360.0f); float el = clamp(elevation, .0f, 90.0f); @@ -209,9 +239,8 @@ static float3 degree_to_cartesian(float azimuth, float elevation) } // Draw a sample from sky -static float3 sample_atmosphere(const Kernel_params &kernel_params, const float3 orig, const float3 dir, const float3 intensity) +static float3 sample_atmosphere(const Kernel_params& kernel_params, const float3 orig, const float3 dir, const float3 intensity) { - // initial parameters float atmosphereRadius = 6420e3f; float3 sunDirection = degree_to_cartesian(kernel_params.azimuth, kernel_params.elevation); @@ -222,7 +251,6 @@ static float3 sample_atmosphere(const Kernel_params &kernel_params, const float3 float3 betaM = make_float3(21e-6f); // - float t0, t1; float tmin, tmax = FLT_MAX; float3 pos = orig; @@ -280,31 +308,28 @@ static float3 sample_atmosphere(const Kernel_params &kernel_params, const float3 tCurrent += segmentLength; } - return (sumR * betaR * phaseR + sumM * betaM * phaseM) * intensity; } // Initialize GLFW and GLEW. -static GLFWwindow *init_opengl() +static GLFWwindow* init_opengl() { - check_success(glfwInit()); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); - - GLFWwindow *window = glfwCreateWindow(1800, 640, "volume path tracer", NULL, NULL); + GLFWwindow* window = glfwCreateWindow(1800, 640, "volume path tracer", NULL, NULL); if (!window) { - log("Error creating OpenGL window.", ERROR); + log("Error creating OpenGL window.", VPT_ERROR); glfwTerminate(); } glfwMakeContextCurrent(window); const GLenum res = glewInit(); if (res != GLEW_OK) { - log((char *)glewGetErrorString(res), ERROR); + log((char*)glewGetErrorString(res), VPT_ERROR); glfwTerminate(); } @@ -321,7 +346,7 @@ static void init_cuda() unsigned int num_cuda_devices; check_success(cudaGLGetDevices(&num_cuda_devices, cuda_devices, 1, cudaGLDeviceListAll) == cudaSuccess); if (num_cuda_devices == 0) { - log("Could not determine CUDA device for current OpenGL context", ERROR); + log("Could not determine CUDA device for current OpenGL context", VPT_ERROR); exit(EXIT_FAILURE); } @@ -330,7 +355,7 @@ static void init_cuda() } // Utility: add a GLSL shader. -static void add_shader(GLenum shader_type, const char *source_code, GLuint program) +static void add_shader(GLenum shader_type, const char* source_code, GLuint program) { GLuint shader = glCreateShader(shader_type); check_success(shader); @@ -351,7 +376,7 @@ static GLuint create_shader_program() GLint success; GLuint program = glCreateProgram(); - const char *vert = + const char* vert = "#version 330\n" "in vec3 Position;\n" "out vec2 TexCoord;\n" @@ -361,7 +386,7 @@ static GLuint create_shader_program() "}\n"; add_shader(GL_VERTEX_SHADER, vert, program); - const char *frag = + const char* frag = "#version 330\n" "in vec2 TexCoord;\n" "out vec4 FragColor;\n" @@ -374,7 +399,7 @@ static GLuint create_shader_program() glLinkProgram(program); glGetProgramiv(program, GL_LINK_STATUS, &success); if (!success) { - log("Error linking shadering program", ERROR); + log("Error linking shadering program", VPT_ERROR); glfwTerminate(); } @@ -433,9 +458,9 @@ struct Window_context }; // GLFW scroll callback. -static void handle_scroll(GLFWwindow *window, double xoffset, double yoffset) +static void handle_scroll(GLFWwindow* window, double xoffset, double yoffset) { - Window_context *ctx = static_cast(glfwGetWindowUserPointer(window)); + Window_context* ctx = static_cast(glfwGetWindowUserPointer(window)); if (yoffset > 0.0) ctx->zoom_delta = 1; else if (yoffset < 0.0) @@ -443,12 +468,12 @@ static void handle_scroll(GLFWwindow *window, double xoffset, double yoffset) } // GLFW keyboard callback. -static void handle_key(GLFWwindow *window, int key, int scancode, int action, int mods) +static void handle_key(GLFWwindow* window, int key, int scancode, int action, int mods) { float dist = 0; if (action == GLFW_PRESS) { - Window_context *ctx = static_cast(glfwGetWindowUserPointer(window)); + Window_context* ctx = static_cast(glfwGetWindowUserPointer(window)); switch (key) { case GLFW_KEY_ESCAPE: glfwSetWindowShouldClose(window, GLFW_TRUE); @@ -491,10 +516,10 @@ static void handle_key(GLFWwindow *window, int key, int scancode, int action, in cam.update_camera(lookfrom, lookat, vup, fov, aspect, aperture); ctx->change = true; break; - case GLFW_KEY_S: // Save linear image + case GLFW_KEY_S: // Save linear image ctx->save_image = true; break; - case GLFW_KEY_C: // Save cost image + case GLFW_KEY_C: // Save cost image ctx->save_cost_image = true; break; case GLFW_KEY_F: // Frame camera to include objects @@ -502,11 +527,9 @@ static void handle_key(GLFWwindow *window, int key, int scancode, int action, in float3 bbox_min = make_float3(.0f); float3 bbox_max = make_float3(.0f);; - for(GPU_VDB vdb: instances) { - - bbox_min = fminf(bbox_min ,vdb.get_xform().transpose().transform_point(vdb.vdb_info.bmin)); - bbox_max = fmaxf(bbox_max ,vdb.get_xform().transpose().transform_point(vdb.vdb_info.bmax)); - + for (GPU_VDB vdb : instances) { + bbox_min = fminf(bbox_min, vdb.get_xform().transpose().transform_point(vdb.vdb_info.bmin)); + bbox_max = fmaxf(bbox_max, vdb.get_xform().transpose().transform_point(vdb.vdb_info.bmax)); } float3 center = (bbox_max + bbox_min) / 2; @@ -525,9 +548,9 @@ static void handle_key(GLFWwindow *window, int key, int scancode, int action, in } // GLFW mouse button callback. -static void handle_mouse_button(GLFWwindow *window, int button, int action, int mods) +static void handle_mouse_button(GLFWwindow* window, int button, int action, int mods) { - Window_context *ctx = static_cast(glfwGetWindowUserPointer(window)); + Window_context* ctx = static_cast(glfwGetWindowUserPointer(window)); bool imgui_hover = ImGui::IsWindowHovered(ImGuiHoveredFlags_AnyWindow); if (button == GLFW_MOUSE_BUTTON_LEFT && !imgui_hover) { @@ -550,9 +573,9 @@ static void handle_mouse_button(GLFWwindow *window, int button, int action, int } // GLFW mouse position callback. -static void handle_mouse_pos(GLFWwindow *window, double xpos, double ypos) +static void handle_mouse_pos(GLFWwindow* window, double xpos, double ypos) { - Window_context *ctx = static_cast(glfwGetWindowUserPointer(window)); + Window_context* ctx = static_cast(glfwGetWindowUserPointer(window)); if (ctx->moving) { ctx->move_dx += xpos - ctx->move_start_x; @@ -571,9 +594,9 @@ static void handle_mouse_pos(GLFWwindow *window, double xpos, double ypos) // Resize OpenGL and CUDA buffers for a given resolution. static void resize_buffers( - float3 **accum_buffer_cuda, - float4 **raw_buffer_cuda, - cudaGraphicsResource_t *display_buffer_cuda, + float3** accum_buffer_cuda, + float4** raw_buffer_cuda, + cudaGraphicsResource_t* display_buffer_cuda, int width, int height, GLuint display_buffer) { @@ -596,49 +619,41 @@ static void resize_buffers( if (*raw_buffer_cuda) check_success(cudaFree(*raw_buffer_cuda) == cudaSuccess); check_success(cudaMalloc(raw_buffer_cuda, width * height * sizeof(float4)) == cudaSuccess); - } -static void resize_buffer(float **buffer, int width, int height) { - +static void resize_buffer(float** buffer, int width, int height) { if (*buffer) check_success(cudaFree(*buffer) == cudaSuccess); check_success(cudaMalloc(buffer, width * height * sizeof(float)) == cudaSuccess); - } -static void resize_buffer(float3 **buffer, int width, int height) { - +static void resize_buffer(float3** buffer, int width, int height) { if (*buffer) check_success(cudaFree(*buffer) == cudaSuccess); check_success(cudaMalloc(buffer, width * height * sizeof(float3)) == cudaSuccess); - } -static void resize_buffer(float4 **buffer, int width, int height) { - +static void resize_buffer(float4** buffer, int width, int height) { if (*buffer) check_success(cudaFree(*buffer) == cudaSuccess); check_success(cudaMalloc(buffer, width * height * sizeof(float4)) == cudaSuccess); - } static void update_debug_buffer( - float3 **debug_buffer_cuda, + float3** debug_buffer_cuda, Kernel_params kernel_params) { if (*debug_buffer_cuda) check_success(cudaFree(*debug_buffer_cuda) == cudaSuccess); check_success(cudaMalloc(debug_buffer_cuda, 1000 * sizeof(float3)) == cudaSuccess); } - static bool create_cdf( - Kernel_params &kernel_params, - cudaArray_t *env_val_data, - cudaArray_t *env_func_data, - cudaArray_t *env_cdf_data, - cudaArray_t *env_marginal_func_data, - cudaArray_t *env_marginal_cdf_data) + Kernel_params& kernel_params, + cudaArray_t* env_val_data, + cudaArray_t* env_func_data, + cudaArray_t* env_cdf_data, + cudaArray_t* env_marginal_func_data, + cudaArray_t* env_marginal_cdf_data) { if (kernel_params.debug) { - log("creating cdf and function textures for environment...", LOG); + log("creating cdf and function textures for environment...", VPT_LOG); } // Fill the value, function, marginal and cdf values @@ -651,11 +666,11 @@ static bool create_cdf( float az = 0; float el = 0; - float3 *val = new float3[res*res], *val_p = val; //RGB values of env sky - float *func = new float[res*res], *func_p = func; // Luminous power of sky - float *cdf = new float[res*res], *cdf_p = cdf; // constructed CDF of directions - float *marginal_func = new float[res], *marginal_func_p = marginal_func; // values for marginal distribution - float *marginal_cdf = new float[res], *marginal_cdf_p = marginal_cdf; // cdf for marginal distribution + float3* val = new float3[res * res], * val_p = val; //RGB values of env sky + float* func = new float[res * res], * func_p = func; // Luminous power of sky + float* cdf = new float[res * res], * cdf_p = cdf; // constructed CDF of directions + float* marginal_func = new float[res], * marginal_func_p = marginal_func; // values for marginal distribution + float* marginal_cdf = new float[res], * marginal_cdf_p = marginal_cdf; // cdf for marginal distribution memset(val, 0x0, sizeof(float3) * res * res); memset(func, 0x0, sizeof(float) * res * res); @@ -671,10 +686,9 @@ static bool create_cdf( el = float(y) / float(res - 1) * float(M_PI); // elevation goes from 0 to 180 degrees *(cdf_p - 1) = .0f; for (int x = 0; x < res; ++x, ++val_p, ++func_p, ++cdf_p) { + az = float(x) / float(res - 1) * float(M_PI) * 2.0f; // azimuth goes from 0 to 360 degrees - az = float(x) / float(res - 1) * float(M_PI) * 2.0f; // azimuth goes from 0 to 360 degrees - - float3 dir = make_float3(sinf(el) * cosf(az), cosf(el), sinf(el) * sinf(az)); // polar to cartesian + float3 dir = make_float3(sinf(el) * cosf(az), cosf(el), sinf(el) * sinf(az)); // polar to cartesian *val_p = sample_atmosphere(kernel_params, pos, dir, kernel_params.sky_color); *func_p = length((*val_p)); *cdf_p = *(cdf_p - 1) + *(func_p - 1) / (res); @@ -713,13 +727,11 @@ static bool create_cdf( } } - // Construct marginal distribution cdf array marginal_func_p = marginal_func; *marginal_cdf_p = 0.0f; for (int y = 0; y < res; ++y, ++marginal_func_p, ++marginal_cdf_p) { - *marginal_cdf_p = *(marginal_cdf_p - 1) + *marginal_func_p / res; //printf("\n%d %f",y ,*marginal_func_p); } @@ -741,15 +753,13 @@ static bool create_cdf( // End array filling //------------------------------------------------------------------------------------ - - - // Send data to GPU + // Send data to GPU //------------------------------------------------------------------------------------- // Send val data - float4 *texture = new float4[res*res]; - for (int i = 0; i < res*res; i++) { + float4* texture = new float4[res * res]; + for (int i = 0; i < res * res; i++) { texture[i] = make_float4(val[i].x, val[i].y, val[i].z, 1.0f); } @@ -773,7 +783,6 @@ static bool create_cdf( check_success(cudaCreateTextureObject(&kernel_params.sky_tex, &res_desc_val, &tex_desc_val, NULL) == cudaSuccess); - // Send func data const cudaChannelFormatDesc channel_desc = cudaCreateChannelDesc(); check_success(cudaMallocArray(env_func_data, &channel_desc, res, res) == cudaSuccess); @@ -795,7 +804,7 @@ static bool create_cdf( check_success(cudaCreateTextureObject(&kernel_params.env_func_tex, &res_desc_func, &tex_desc_func, NULL) == cudaSuccess); - // Send cdf data + // Send cdf data check_success(cudaMallocArray(env_cdf_data, &channel_desc, res, res) == cudaSuccess); check_success(cudaMemcpy2DToArray(*env_cdf_data, 0, 0, cdf, res * sizeof(float), res * sizeof(float), res, cudaMemcpyHostToDevice) == cudaSuccess); @@ -837,7 +846,6 @@ static bool create_cdf( check_success(cudaCreateTextureObject(&kernel_params.env_marginal_func_tex, &res_desc_marginal_func, &tex_desc_marginal_func, NULL) == cudaSuccess); - // Send Marginal 1D distribution cdf data check_success(cudaMallocArray(env_marginal_cdf_data, &channel_desc, res, 0) == cudaSuccess); @@ -858,8 +866,6 @@ static bool create_cdf( check_success(cudaCreateTextureObject(&kernel_params.env_marginal_cdf_tex, &res_desc_marginal_cdf, &tex_desc_marginal_cdf, NULL) == cudaSuccess); - - //End host to device data migration //------------------------------------------------------------------------------------------ @@ -869,10 +875,8 @@ static bool create_cdf( if (CreateDirectory("./env_sample", NULL) || ERROR_ALREADY_EXISTS == GetLastError()); else { - printf("\nError: unable to create directory for environment sample textures\n"); exit(-1); - }; std::ofstream ofs_val("./env_sample/val.ppm", std::ios::out | std::ios::binary); @@ -923,7 +927,6 @@ static bool create_cdf( ofs_cdf << (unsigned char)(min(1.0f, (*cdf_p)) * 255) << (unsigned char)(min(1.0f, (*cdf_p)) * 255) << (unsigned char)(min(1.0f, (*cdf_p)) * 255); - } } ofs_val.close(); @@ -934,22 +937,20 @@ static bool create_cdf( #endif - delete[] val, func, cdf; return true; - } // Create enviroment texture. static bool create_environment( - cudaTextureObject_t *env_tex, - cudaArray_t *env_tex_data, - const char *envmap_name) + cudaTextureObject_t* env_tex, + cudaArray_t* env_tex_data, + const char* envmap_name) { unsigned int rx, ry; - float *pixels; + float* pixels; if (!load_hdr_float4(&pixels, &rx, &ry, envmap_name)) { - log("error loading environment map file", ERROR); + log("error loading environment map file", VPT_ERROR); return false; } @@ -977,7 +978,6 @@ static bool create_environment( } static void read_instance_file(std::string file_name) { - assert(!file_name.empty()); std::ifstream stream; @@ -987,9 +987,8 @@ static void read_instance_file(std::string file_name) { std::getline(stream, num_vdbs); if (num_vdbs == "light") { + log("Setting up instanced point lights...", VPT_LOG); - log("Setting up instanced point lights...", LOG); - int num_lights; std::string num_points; std::getline(stream, num_points); @@ -1001,20 +1000,16 @@ static void read_instance_file(std::string file_name) { cudaMallocManaged(&l_list.light_ptr, num_lights * sizeof(point_light)); for (int i = 0; i < num_lights; ++i) { - std::string instance_parameters; std::getline(stream, instance_parameters); std::istringstream params(instance_parameters); double p_x, p_y, p_z, r, g, b, p; params >> p_x >> p_y >> p_z >> r >> g >> b >> p; - l_list.light_ptr[i] = point_light(); l_list.light_ptr[i].color = make_float3(r, g, b); l_list.light_ptr[i].pos = make_float3(p_x, p_y, p_z);; l_list.light_ptr[i].power = p; - - } check_success(cuMemAlloc(&d_lights, sizeof(light_list)) == cudaSuccess); @@ -1022,17 +1017,15 @@ static void read_instance_file(std::string file_name) { empty_volume = true; } else { - - log("Setting up instanced volumes...", LOG); + log("Setting up instanced volumes...", VPT_LOG); std::istringstream iss(num_vdbs); int num_volumes; iss >> num_volumes; - log("number of vdbs: " + num_volumes, LOG); + log("number of vdbs: " + num_volumes, VPT_LOG); volume_files.resize(num_volumes); for (int i = 0; i < num_volumes; ++i) { - std::string vdb_file_name; std::getline(stream, vdb_file_name); volume_files.at(i).vdb_file = vdb_file_name; @@ -1043,7 +1036,6 @@ static void read_instance_file(std::string file_name) { volume_files.at(i).instances.resize(volume_files.at(i).num_instances); for (unsigned int x = 0; x < volume_files.at(i).num_instances; ++x) { - std::string instance_parameters; std::getline(stream, instance_parameters); std::istringstream params(instance_parameters); @@ -1065,12 +1057,10 @@ static void read_instance_file(std::string file_name) { stream.close(); for (int i = 0; i < volume_files.size(); ++i) { - unique_vdb_files.push_back(GPU_VDB()); unique_vdb_files.at(i).loadVDB(volume_files.at(i).vdb_file, "density", "heat", "Cd"); for (unsigned int x = 0; x < volume_files.at(i).num_instances; ++x) { - GPU_VDB new_instance(GPU_VDB(unique_vdb_files.at(i))); mat4 xform = unique_vdb_files.at(i).get_xform(); @@ -1081,7 +1071,6 @@ static void read_instance_file(std::string file_name) { // Set scale xform.scale(make_float3(volume_files.at(i).instances.at(x).scale)); - // Apply instance rotation float3 euler = quaternion_to_euler( @@ -1105,25 +1094,23 @@ static void read_instance_file(std::string file_name) { volume_files.at(i).instances.at(x).position[1], volume_files.at(i).instances.at(x).position[2])); - new_instance.set_xform(xform); instances.push_back(new_instance); - } } } } // Process camera movement. -static void update_camera(double dx, double dy, double mx, double my, int zoom_delta, const atmosphere &atm, float scene_max) +static void update_camera(double dx, double dy, double mx, double my, int zoom_delta, const atmosphere& atm, float scene_max) { float rot_speed = 1; float zoom_speed = scene_max / 4.0f; float dist = length(lookfrom - lookat); // Rotation - lookfrom -= cam.u * float(dx) * rot_speed * dist * 0.01f; - lookfrom += cam.v * float(dy) * rot_speed * dist * 0.01f; + lookfrom -= cam.u * float(dx) * rot_speed * dist * 0.01f; + lookfrom += cam.v * float(dy) * rot_speed * dist * 0.01f; //Pan lookfrom -= cam.u * float(mx) * rot_speed; @@ -1131,23 +1118,18 @@ static void update_camera(double dx, double dy, double mx, double my, int zoom_d lookat -= cam.u * float(mx) * rot_speed; lookat += cam.v * float(my) * rot_speed; - // Zoom + // Zoom lookfrom -= cam.w * float(zoom_delta) * zoom_speed; float3 earth_center = make_float3(.0f, -atm.atmosphere_parameters.bottom_radius, .0f); if (length(lookfrom - earth_center) < atm.atmosphere_parameters.bottom_radius) lookfrom += normalize(lookfrom - earth_center) * (atm.atmosphere_parameters.bottom_radius - length(lookfrom - earth_center)); - cam.update_camera(lookfrom, lookat, vup, fov, aspect, aperture); - } - int main(const int argc, const char* argv[]) { - - //*********************************************************************************************************************************** // Create necessary folders // @@ -1168,16 +1150,15 @@ int main(const int argc, const char* argv[]) GLuint program = 0; GLuint quad_vertex_buffer = 0; GLuint quad_vao = 0; - GLFWwindow *window = NULL; + GLFWwindow* window = NULL; int width = -1; int height = -1; window_context.change = false; window_context.save_image = false; window_context.save_cost_image = false; - log("Initializing opengl...", LOG); + log("Initializing opengl...", VPT_LOG); - //*********************************************************************************************************************************** // Init OpenGL window and callbacks. // @@ -1197,27 +1178,24 @@ int main(const int argc, const char* argv[]) program = create_shader_program(); quad_vao = create_quad(program, &quad_vertex_buffer); - - log("Initializing cuda...", LOG); + log("Initializing cuda...", VPT_LOG); init_cuda(); - // SETUP IMGUI PARAMETERS - log("Setting up Imgui parameters...", LOG); + log("Setting up Imgui parameters...", VPT_LOG); const char* glsl_version = "#version 330"; IMGUI_CHECKVERSION(); ImGui::CreateContext(); - ImGuiIO &io = ImGui::GetIO(); (void)io; + ImGuiIO& io = ImGui::GetIO(); (void)io; io.ConfigWindowsMoveFromTitleBarOnly = true; ImGui::StyleColorsDark(); ImGui_ImplGlfw_InitForOpenGL(window, true); ImGui_ImplOpenGL3_Init(glsl_version); - //*********************************************************************************************************************************** - // Setup modules and contexes + // Setup modules and contexes // //*********************************************************************************************************************************** @@ -1230,14 +1208,14 @@ int main(const int argc, const char* argv[]) unsigned int num_cuda_devices; check_success(cudaGLGetDevices(&num_cuda_devices, cuda_devices, 1, cudaGLDeviceListAll) == cudaSuccess); if (num_cuda_devices == 0) { - log("Could not determine CUDA device for context", ERROR); + log("Could not determine CUDA device for context", VPT_ERROR); exit(EXIT_FAILURE); } CUcontext cuctx; cuCtxGetCurrent(&cuctx); - log("Loading Cuda kernel modules and functions...", LOG); + log("Loading Cuda kernel modules and functions...", VPT_LOG); CUresult error; CUlinkState state; @@ -1251,52 +1229,46 @@ int main(const int argc, const char* argv[]) cuLinkComplete(state, (void**)&image, &sz); error = cuModuleLoadData(&Module, image); - if (error != CUDA_SUCCESS) log("cuModuleLoad " + error, ERROR); + if (error != CUDA_SUCCESS) log("cuModuleLoad " + error, VPT_ERROR); cuLinkDestroy(state); error = cuModuleGetFunction(&cuRaycastKernel, Module, render_kernel_name); - if (error != CUDA_SUCCESS) log("cuModuleGetFunction " + error, ERROR); + if (error != CUDA_SUCCESS) log("cuModuleGetFunction " + error, VPT_ERROR); error = cuModuleGetFunction(&cuTextureKernel, Module, texture_kernel_name); - if (error != CUDA_SUCCESS) log("cuModuleGetFunction " + error, ERROR); - + if (error != CUDA_SUCCESS) log("cuModuleGetFunction " + error, VPT_ERROR); error = cuModuleGetFunction(&cuCreateGeometryKernel, Module, "create_geometry_list"); - if (error != CUDA_SUCCESS) log("cuModuleGetFunction " + error, ERROR); + if (error != CUDA_SUCCESS) log("cuModuleGetFunction " + error, VPT_ERROR); error = cuModuleGetFunction(&cuTestGeometryKernel, Module, "test_geometry_list"); - if (error != CUDA_SUCCESS) log("cuModuleGetFunction " + error, ERROR); - + if (error != CUDA_SUCCESS) log("cuModuleGetFunction " + error, VPT_ERROR); - //*********************************************************************************************************************************** // Setup gpu_vdb // //*********************************************************************************************************************************** - log("Setting up gpu_vdb instances...", LOG); + log("Setting up gpu_vdb instances...", VPT_LOG); std::string fname; if (argc >= 2) fname = argv[1]; std::string env_name; if (argc >= 3) env_name = argv[2]; - - std::string file_extension = boost::filesystem::extension(fname); - std::string file_extension_env = boost::filesystem::extension(env_name); + std::string file_extension = fs::path(fname).extension().string(); + std::string file_extension_env = fs::path(env_name).extension().string(); GPU_PROC_VOL proc_vol; float3 proc_box_min; float3 proc_box_max; if (file_extension == ".vdb") { - std::string file_path = ASSET_PATH; file_path.append(fname); instances.clear(); instances.push_back(GPU_VDB()); instances.at(0).loadVDB(file_path, "density", "heat", "Cd"); - } else if (file_extension == ".ins") { read_instance_file(fname); @@ -1306,56 +1278,46 @@ int main(const int argc, const char* argv[]) env_tex_name = ASSET_PATH; env_tex_name.append(fname); } - else { // No vdb or instance file is given procede with procedural volume - log("No vdb file or an instance file is provided. Continuing with procedural volume", LOG); - + else { // No vdb or instance file is given procede with procedural volume + log("No vdb file or an instance file is provided. Continuing with procedural volume", VPT_LOG); } - + if (file_extension_env == ".hdr") { env_tex = true; env_tex_name = ASSET_PATH; env_tex_name.append(env_name); } - if (empty_volume) { - proc_box_min = make_float3(-230, -100, -228); proc_box_max = make_float3(230, 100, 244); if (!proc_vol.create_volume(proc_box_min, proc_box_max, 1.0f, 0, 0.1f)) return 0; instances.push_back(proc_vol); } - - - // Send volume instances to gpu CUdeviceptr d_volume_ptr; check_success(cuMemAlloc(&d_volume_ptr, sizeof(GPU_VDB) * instances.size()) == cudaSuccess); check_success(cuMemcpyHtoD(d_volume_ptr, instances.data(), sizeof(GPU_VDB) * instances.size()) == cudaSuccess); - - // Create BVH from vdb vector - log("Creating BVH and Octree structures...", LOG); + // Create BVH from vdb vector + log("Creating BVH and Octree structures...", VPT_LOG); AABB scene_bounds(make_float3(.0f), make_float3(.0f)); - + #ifdef LOG_LEVEL_LOG bvh_builder.m_debug_bvh = true; #endif bvh_builder.build_bvh(instances, (int)instances.size(), scene_bounds); - - - //*********************************************************************************************************************************** - // Setup initial camera + // Setup initial camera // //*********************************************************************************************************************************** - - log("Setting up camera...", LOG); + + log("Setting up camera...", VPT_LOG); lookfrom = make_float3(1300.0f, 77.0f, 0.0f); lookat = make_float3(-10.0f, 72.0f, -43.0f); vup = make_float3(.0f, 1.0f, .0f); @@ -1371,22 +1333,19 @@ int main(const int argc, const char* argv[]) cam.update_camera(lookfrom, lookat, vup, fov, aspect, aperture); - - //*********************************************************************************************************************************** // Setup initial render kernel parameters. // //*********************************************************************************************************************************** - // Kernel param buffers - log("Setting kernel paramaters...", LOG); - float3 *accum_buffer = NULL; - float4 *raw_buffer = NULL; + log("Setting kernel paramaters...", VPT_LOG); + float3* accum_buffer = NULL; + float4* raw_buffer = NULL; cudaGraphicsResource_t display_buffer_cuda = NULL; - float3 *debug_buffer = NULL; - float3 *cost_buffer = NULL; - float *depth_buffer = NULL; + float3* debug_buffer = NULL; + float3* cost_buffer = NULL; + float* depth_buffer = NULL; Kernel_params kernel_params; memset(&kernel_params, 0, sizeof(Kernel_params)); @@ -1416,30 +1375,30 @@ int main(const int argc, const char* argv[]) kernel_params.emission_scale = 0.0f; kernel_params.emission_pivot = 1.0f; - log("Loading blue noise buffer...", LOG); + log("Loading blue noise buffer...", VPT_LOG); std::string bn_path = ASSET_PATH; bn_path.append("BN0.bmp"); - float3 *bn_buffer = NULL; + float3* bn_buffer = NULL; int bn_width, bn_height; load_texture_bmp_gpu(&bn_buffer, bn_path, bn_width, bn_height, false); kernel_params.blue_noise_buffer = bn_buffer; - - log("Setting up debug buffer...", LOG); + + log("Setting up debug buffer...", VPT_LOG); update_debug_buffer(&debug_buffer, kernel_params); kernel_params.debug_buffer = debug_buffer; - - log("Loading emission lookup texture...", LOG); + + log("Loading emission lookup texture...", VPT_LOG); std::string emm_path = ASSET_PATH; emm_path.append("blackbody_texture.exr"); - float3 *emmission_buffer = NULL; + float3* emmission_buffer = NULL; int file_width, file_height; load_texture_exr_gpu(&emmission_buffer, emm_path, file_width, file_height, false); kernel_params.emission_texture = emmission_buffer; - log("Loading density color lookup texture...", LOG); + log("Loading density color lookup texture...", VPT_LOG); std::string color_path = ASSET_PATH; color_path.append("density_color_texture2.exr"); - float3 *density_color_buffer = NULL; + float3* density_color_buffer = NULL; load_texture_exr_gpu(&density_color_buffer, color_path, file_width, file_height, false); kernel_params.density_color_texture = density_color_buffer; @@ -1450,7 +1409,6 @@ int main(const int argc, const char* argv[]) cudaArray_t env_cdf_data = 0; cudaArray_t env_marginal_func_data = 0; cudaArray_t env_marginal_cdf_data = 0; - // Imgui Parameters @@ -1464,12 +1422,11 @@ int main(const int argc, const char* argv[]) int integrator = 0; bool render = true; bool debug = false; - bool denoise = false; bool viz_dof = false; int frame = 0; float rot_amount = 0.0f; - static const char *items[] = {"NONE", "APPROXIMATE", "PRECOMPUTED"}; + static const char* items[] = { "NONE", "APPROXIMATE", "PRECOMPUTED" }; static int env_comp = 0; int temp_env_comp = 0; @@ -1480,21 +1437,18 @@ int main(const int argc, const char* argv[]) float emission_scale = 0.0f; float emission_pivot = 1.0f; - // Noise parameters - int noise_type = 0 , temp_noise_type; - float scale = 1.0f , temp_scale; - float noise_res = 1.0f , temp_res; - + int noise_type = 0, temp_noise_type; + float scale = 1.0f, temp_scale; + float noise_res = 1.0f, temp_res; + // End ImGui parameters - //*********************************************************************************************************************************** - // Create env texture + // Create env texture // //*********************************************************************************************************************************** if (env_tex) { - env_tex = create_environment(&kernel_params.env_tex, &env_tex_data, env_tex_name.c_str()); } if (env_tex) { @@ -1503,43 +1457,32 @@ int main(const int argc, const char* argv[]) } // Create env map sampling textures - log("Creating env texture CDF...", LOG); + log("Creating env texture CDF...", VPT_LOG); create_cdf(kernel_params, &env_val_data, &env_func_data, &env_cdf_data, &env_marginal_func_data, &env_marginal_cdf_data); - - - - - //*********************************************************************************************************************************** - // Init atmosphere + // Init atmosphere // //*********************************************************************************************************************************** - log("Creating atmosphere...", LOG); + log("Creating atmosphere...", VPT_LOG); earth_atmosphere.texture_folder = "./atmosphere_textures"; earth_atmosphere.texture_folder_debug = "./atmosphere_textures_debug"; earth_atmosphere.init(); - AtmosphereParameters *atmos_params = &earth_atmosphere.atmosphere_parameters; - - + AtmosphereParameters* atmos_params = &earth_atmosphere.atmosphere_parameters; - - - - //*********************************************************************************************************************************** // Setup geometry and device pointers. TODO make obj loaders and send triangle geometry // //*********************************************************************************************************************************** - log("Setting up geometry and device pointers...", LOG); + log("Setting up geometry and device pointers...", VPT_LOG); float3 center = make_float3(0, 1000, 0); float radius = 1; sphere ref_sphere(center, radius); ref_sphere.roughness = 1.0f; - ref_sphere.color = make_float3(10.0f, 0 , 0); - + ref_sphere.color = make_float3(10.0f, 0, 0); + CUdeviceptr d_geo_ptr; check_success(cuMemAlloc(&d_geo_ptr, sizeof(sphere) * 1) == cudaSuccess); check_success(cuMemcpyHtoD(d_geo_ptr, &ref_sphere, sizeof(sphere) * 1) == cudaSuccess); @@ -1551,41 +1494,40 @@ int main(const int argc, const char* argv[]) cudaMallocManaged(&geo_list.list, num_spheres * sizeof(sphere)); geo_list.list_size = num_spheres; - geo_list.list[0] = sphere(make_float3(0,10,0), 10); + geo_list.list[0] = sphere(make_float3(0, 10, 0), 10); geo_list.list[1] = sphere(make_float3(20, 10, 0), 10); CUdeviceptr d_geo_list_ptr; check_success(cuMemAlloc(&d_geo_list_ptr, sizeof(geometry_list)) == cudaSuccess); check_success(cuMemcpyHtoD(d_geo_list_ptr, &geo_list, sizeof(geometry_list)) == cudaSuccess); - - - - - //*********************************************************************************************************************************** - // Create OIDN devices + // Create OIDN devices // //*********************************************************************************************************************************** - oidn::DeviceRef oidn_device = oidn::newDevice(); - oidn_device.commit(); - oidn::FilterRef filter = oidn_device.newFilter("RT"); - - - + OIDNDevice oidnDevice = oidnNewDevice(OIDN_DEVICE_TYPE_CUDA); + const char* errorMsg; + OIDNError errorCode = oidnGetDeviceError(oidnDevice, &errorMsg); + if (errorCode != OIDN_ERROR_NONE) + { + log("Denoising Error!", VPT_ERROR); + return 1; + } + oidnSetDeviceErrorFunction(oidnDevice, OIDNErrorCallback, nullptr); + oidnCommitDevice(oidnDevice); + OIDNFilter filter = oidnNewFilter(oidnDevice, "RT"); + OIDNBuffer inputBuffer = nullptr; - //*********************************************************************************************************************************** // Main loop // //*********************************************************************************************************************************** - log("Entering main loop...", LOG); + log("Entering main loop...", VPT_LOG); while (!glfwWindowShouldClose(window)) { - // Process events. glfwPollEvents(); - Window_context *ctx = static_cast(glfwGetWindowUserPointer(window)); + Window_context* ctx = static_cast(glfwGetWindowUserPointer(window)); // Update kernel params kernel_params.exposure_scale = powf(2.0f, ctx->exposure); @@ -1606,20 +1548,18 @@ int main(const int argc, const char* argv[]) const unsigned int volume_type = ctx->config_type & 1; const unsigned int environment_type = env_tex ? ((ctx->config_type >> 1) & 1) : 0; - // Update atmosphere earth_atmosphere.m_use_constant_solar_spectrum = use_constant_solar_spectrum; earth_atmosphere.m_use_ozone = use_ozone; earth_atmosphere.m_do_white_balance = do_white_balance; earth_atmosphere.m_exposure = exposure; - + // Update temp holders temp_noise_type = noise_type; temp_scale = scale; temp_res = noise_res; - - - // Draw imgui + + // Draw imgui //------------------------------------------------------------------- ImGui_ImplOpenGL3_NewFrame(); @@ -1628,21 +1568,46 @@ int main(const int argc, const char* argv[]) ImGui::Begin("Parameters window"); ImGui::Checkbox("Render", &render); - ImGui::Checkbox("Denoise", &denoise); + if (ImGui::Button("Denoise")) + { + oidnSetFilterImage(filter, "color", inputBuffer, OIDN_FORMAT_FLOAT3, width, height, 0, sizeof(float3), sizeof(float3) * width); + oidnSetFilterImage(filter, "output", inputBuffer, OIDN_FORMAT_FLOAT3, width, height, 0, sizeof(float3), sizeof(float3) * width); + + oidnSetFilterBool(filter, "hdr", true); + oidnSetFilterBool(filter, "srgb", false); + + oidnSetFilterInt(filter, "quality", OIDN_QUALITY_DEFAULT); + //oidnSetFilterInt(filter, "quality", OIDN_QUALITY_BALANCED); + //oidnSetFilterInt(filter, "quality", OIDN_QUALITY_HIGH); + + oidnCommitFilter(filter); + oidnExecuteFilter(filter); + errorCode = oidnGetDeviceError(oidnDevice, &errorMsg); + if (errorCode != OIDN_ERROR_NONE) + { + log("Denoising Error! ", VPT_ERROR); + oidnReleaseFilter(filter); + oidnReleaseDevice(oidnDevice); + return false; + } + + oidnSyncDevice(oidnDevice); + } + ImGui::SliderFloat("exposure", &ctx->exposure, -10.0f, 10.0f); ImGui::InputInt("Max interactions", &max_interaction, 1); ImGui::InputInt("Ray Depth", &ray_depth, 1); ImGui::InputInt("Volume Depth", &volume_depth, 1); ImGui::InputInt("Integrator", &integrator, 0); - + ImGui::Checkbox("debug", &debug); ImGui::SliderFloat("phase g1", &kernel_params.phase_g1, -1.0f, 1.0f); ImGui::SliderFloat("phase g2", &kernel_params.phase_g2, -1.0f, 1.0f); ImGui::SliderFloat("phase f", &kernel_params.phase_f, 0.0f, 1.0f); ImGui::InputFloat("Density Multiplier", &kernel_params.density_mult); ImGui::InputFloat("Depth Multiplier", &kernel_params.tr_depth); - ImGui::InputFloat3("Volume Extinction", (float *)&kernel_params.extinction); - ImGui::InputFloat3("Volume Color", (float *)&kernel_params.albedo); + ImGui::InputFloat3("Volume Extinction", (float*)&kernel_params.extinction); + ImGui::InputFloat3("Volume Color", (float*)&kernel_params.albedo); ImGui::InputDouble("Energy Injection", &energy, 0.0); ImGui::SliderFloat("Emission Scale", &emission_scale, .0f, 10.0f); ImGui::SliderFloat("Emission Pivot", &emission_pivot, .0f, 10.0f); @@ -1662,9 +1627,9 @@ int main(const int argc, const char* argv[]) // Atmosphere Parameters GUI ImGui::Begin("Atmosphere Parameters"); ImGui::SliderFloat("Sky Exposure", &exposure, -10.0f, 10.0f); - ImGui::ColorEdit3("Sun Color", (float *)&kernel_params.sun_color); + ImGui::ColorEdit3("Sun Color", (float*)&kernel_params.sun_color); ImGui::InputFloat("Sun Multiplier", &kernel_params.sun_mult, 0.0f, 100.0f); - ImGui::InputFloat3("Sky Color", (float *)&kernel_params.sky_color); + ImGui::InputFloat3("Sky Color", (float*)&kernel_params.sky_color); ImGui::InputFloat("Sky Multiplier", &kernel_params.sky_mult, 0.0f, 100.0f); ImGui::SliderFloat("Azimuth", &azimuth, 0, 360); ImGui::SliderFloat("Elevation", &elevation, -90, 90); @@ -1679,84 +1644,59 @@ int main(const int argc, const char* argv[]) //----------------------------------------------------------------- if (0) { - // Reserved for host side debugging #if 0 //Copy debug buffer and print printf("ray_depth:%d\n", ray_depth); - float3 *c = new float3[1000]; + float3* c = new float3[1000]; memset(c, 0x0, sizeof(float3) * 1000); check_success(cudaMemcpy(c, debug_buffer, sizeof(float3) * 1000, cudaMemcpyDeviceToHost) == cudaSuccess); - std::ofstream ray_pos("C:/Users/Admin/Desktop/PT_Plot/Ray_tr.txt", std::ios::out); for (int y = 0; y < 1000; y++) { - if (c[y].x == .0f) continue; ray_pos << y + 1 << " " << c[y].x << "\n"; - - } #endif - } - // Restart rendering if paused and started back + // Restart rendering if paused and started back if (!render) { - kernel_params.iteration = 0; - } if (temp_noise_type != noise_type || temp_res != noise_res || temp_scale != scale) { - proc_vol.create_volume(proc_box_min, proc_box_max, noise_res, noise_type, scale); - + instances.pop_back(); instances.push_back(proc_vol); - check_success(cuMemcpyHtoD(d_volume_ptr, instances.data(), sizeof(GPU_VDB)* instances.size()) == cudaSuccess); - - kernel_params.iteration = 0; + check_success(cuMemcpyHtoD(d_volume_ptr, instances.data(), sizeof(GPU_VDB) * instances.size()) == cudaSuccess); + kernel_params.iteration = 0; } - - // Restart rendering if there is a change + // Restart rendering if there is a change if (ctx->change || max_interaction != kernel_params.max_interactions || ray_depth != kernel_params.ray_depth || integrator != kernel_params.integrator || - emission_scale != kernel_params.emission_scale || - emission_pivot != kernel_params.emission_pivot || + emission_scale != kernel_params.emission_scale || + emission_pivot != kernel_params.emission_pivot || cam.viz_dof != viz_dof) { - kernel_params.integrator = integrator; //update_debug_buffer(&debug_buffer, kernel_params); //kernel_params.debug_buffer = debug_buffer; kernel_params.iteration = 0; ctx->change = false; - } - if (kernel_params.iteration == kernel_params.max_interactions-1) ctx->save_image = true; - - // Test rotation -#if 0 - float3 rotation = make_float3(0, 0, (M_PI / 10.0f) * rot_amount); - mat4 rot = vdbs[0].get_xform().rotate_zyx(rotation); - vdbs[0].set_xform(rot); - check_success(cuMemcpyHtoD(d_volume_ptr, vdbs, sizeof(GPU_VDB) * 2) == cudaSuccess); - rot_amount += 0.1f; - kernel_params.iteration = 0; -#endif - - + if (kernel_params.iteration == kernel_params.max_interactions - 1) ctx->save_image = true; // Recreate environment sampling textures if sun position changes if (azimuth != kernel_params.azimuth || elevation != kernel_params.elevation) { @@ -1764,12 +1704,11 @@ int main(const int argc, const char* argv[]) kernel_params.iteration = 0; } - // Recompute sky if there is a change + // Recompute sky if there is a change - if (temp_env_comp != env_comp || - earth_atmosphere.m_use_constant_solar_spectrum != use_constant_solar_spectrum || + if (temp_env_comp != env_comp || + earth_atmosphere.m_use_constant_solar_spectrum != use_constant_solar_spectrum || earth_atmosphere.m_use_ozone != use_ozone) { - earth_atmosphere.m_use_constant_solar_spectrum = use_constant_solar_spectrum; earth_atmosphere.m_use_ozone = use_ozone; @@ -1791,7 +1730,7 @@ int main(const int argc, const char* argv[]) temp_env_comp = env_comp; kernel_params.iteration = 0; } - if (earth_atmosphere.m_do_white_balance != do_white_balance || + if (earth_atmosphere.m_do_white_balance != do_white_balance || earth_atmosphere.m_exposure != exposure) { earth_atmosphere.m_exposure = exposure; earth_atmosphere.m_do_white_balance = do_white_balance; @@ -1799,7 +1738,6 @@ int main(const int argc, const char* argv[]) kernel_params.iteration = 0; } - // Reallocate buffers if window size changed. int nwidth, nheight; glfwGetFramebufferSize(window, &nwidth, &nheight); @@ -1814,6 +1752,14 @@ int main(const int argc, const char* argv[]) resize_buffer(&cost_buffer, width, height); resize_buffer(&depth_buffer, width, height); + inputBuffer = oidnNewSharedBuffer(oidnDevice, accum_buffer, sizeof(float3) * width * height); + if (!inputBuffer) + { + log("Unable to create denoising buffer!", VPT_ERROR); + oidnReleaseDevice(oidnDevice); + return 1; + } + kernel_params.depth_buffer = depth_buffer; kernel_params.cost_buffer = cost_buffer; kernel_params.accum_buffer = accum_buffer; @@ -1825,70 +1771,39 @@ int main(const int argc, const char* argv[]) kernel_params.iteration = 0; } - // Restart render if camera moves + // Restart render if camera moves if (ctx->move_dx != 0.0 || ctx->move_dy != 0.0 || ctx->move_mx != 0.0 || ctx->move_my != 0.0 || ctx->zoom_delta) { - update_camera(ctx->move_dx, ctx->move_dy, ctx->move_mx, ctx->move_my, ctx->zoom_delta, earth_atmosphere, scene_max); ctx->move_dx = ctx->move_dy = ctx->move_mx = ctx->move_my = 0.0; ctx->zoom_delta = 0; kernel_params.iteration = 0; - } if (ctx->save_image) { - std::string file_path = "./render/pathtrace."; file_path.append(std::to_string(frame)); - - -#ifdef SAVE_TGA - - file_path.append(".tga"); - - int res = width * height; - float4 *c = (float4*)malloc(res * sizeof(float4)); - check_success(cudaMemcpy(c, raw_buffer, sizeof(float4) * res, cudaMemcpyDeviceToHost) == cudaSuccess); - - bool success = save_texture_tga(c, file_name, width, height); -#endif - -#ifdef SAVE_OPENEXR - - file_path.append(".exr"); + file_path.append(".jpeg"); int res = width * height; - float4 *c = (float4*)malloc(res * sizeof(float4)); - check_success(cudaMemcpy(c, raw_buffer, sizeof(float4) * res, cudaMemcpyDeviceToHost) == cudaSuccess); - - // TODO send depth buffer to Z layer - float* depth = (float*)malloc(res * sizeof(float)); - check_success(cudaMemcpy(depth, depth_buffer, sizeof(float)* res, cudaMemcpyDeviceToHost) == cudaSuccess); - - bool success = save_texture_exr(c, depth, file_path, width, height, true); - -#endif + float3* c = (float3*)malloc(res * sizeof(float3)); + check_success(cudaMemcpy(c, accum_buffer, sizeof(float3) * res, cudaMemcpyDeviceToHost) == cudaSuccess); + bool success = save_texture_jpg(c, file_path, width, height); frame++; ctx->save_image = false; } - - if (ctx->save_cost_image) { - std::string file_path = "./render/cost."; file_path.append(std::to_string(frame)); file_path.append(".exr"); #ifdef SAVE_OPENEXR int res = width * height; - float3 *c = (float3*)malloc(res * sizeof(float3)); + float3* c = (float3*)malloc(res * sizeof(float3)); check_success(cudaMemcpy(c, cost_buffer, sizeof(float3) * res, cudaMemcpyDeviceToHost) == cudaSuccess); - - - bool success = save_texture_exr(c, file_path, width, height, true); #endif @@ -1898,87 +1813,30 @@ int main(const int argc, const char* argv[]) // Map GL buffer for access with CUDA. check_success(cudaGraphicsMapResources(1, &display_buffer_cuda, /*stream=*/0) == cudaSuccess); - void *p; + void* p; size_t size_p; cudaGraphicsResourceGetMappedPointer(&p, &size_p, display_buffer_cuda); - kernel_params.display_buffer = reinterpret_cast(p); + kernel_params.display_buffer = reinterpret_cast(p); // Launch volume rendering kernel. dim3 block(16, 16, 1); dim3 grid(int(width / block.x) + 1, int(height / block.y) + 1, 1); - void *params[] = { &cam, (void *)&l_list , (void *)&d_volume_ptr, (void *)&d_geo_ptr, (void*)&d_geo_list_ptr ,&bvh_builder.bvh.BVHNodes, &bvh_builder.root ,(void *)atmos_params, &kernel_params}; + void* params[] = { &cam, (void*)&l_list , (void*)&d_volume_ptr, (void*)&d_geo_ptr, (void*)&d_geo_list_ptr ,&bvh_builder.bvh.BVHNodes, &bvh_builder.root ,(void*)atmos_params, &kernel_params }; cuLaunchKernel(cuRaycastKernel, grid.x, grid.y, 1, block.x, block.y, 1, 0, NULL, params, NULL); ++kernel_params.iteration; cudaDeviceSynchronize(); - if (0) { // TODO will do post effects after they are implemented in texture_kernels + if (0) { // TODO will do post effects after they are implemented in texture_kernels float treshold = 0.09f; - void *texture_params[] = { &kernel_params, &treshold, &width, &height }; + void* texture_params[] = { &kernel_params, &treshold, &width, &height }; cuLaunchKernel(cuTextureKernel, grid.x, grid.y, 1, block.x, block.y, 1, 0, NULL, texture_params, NULL); } + // Unmap GL buffer. check_success(cudaGraphicsUnmapResources(1, &display_buffer_cuda, /*stream=*/0) == cudaSuccess); - //Do Image denoising with OIDN library - if (denoise) { - - int resolution = width * height; - float4 *in_buffer; - float3 *temp_in_buffer, *temp_out_buffer; - - in_buffer = (float4*)malloc(resolution * sizeof(float4)); - - check_success(cudaMemcpy(in_buffer, raw_buffer, sizeof(float4) * resolution, cudaMemcpyDeviceToHost) == cudaSuccess); - - temp_in_buffer = (float3*)malloc(resolution * sizeof(float3)); - temp_out_buffer = (float3*)malloc(resolution * sizeof(float3)); - - for (int i = 0; i < resolution; i++) { - - temp_in_buffer[i].x = in_buffer[i].x; - temp_in_buffer[i].y = in_buffer[i].y; - temp_in_buffer[i].z = in_buffer[i].z; - } - - filter.setImage("color", temp_in_buffer, oidn::Format::Float3, width, height); - filter.setImage("output", temp_out_buffer, oidn::Format::Float3, width, height); - filter.set("hdr", true); - filter.set("srgb", false); - - filter.commit(); - filter.execute(); - - if (1) { // save denoised image - - /* - float3 red = make_float3(1.0f, .0f, .0f); - float3 blue = make_float3(.0f, .0f, 1.0f); - - for (int i = 0; i < resolution; i++) { - - float diff = length(temp_in_buffer[i] - temp_out_buffer[i]); - - temp_out_buffer[i] = lerp(blue, red, diff); - - } - */ - - std::string file_path = "./render/pathtrace_denoised."; - file_path.append(std::to_string(frame)); - file_path.append(".exr"); - - - bool success = save_texture_exr(temp_out_buffer, file_path, width, height, true); - - frame++; - - } - - denoise = false; - } - // Update texture for display. glBindBuffer(GL_PIXEL_UNPACK_BUFFER, display_buffer); glBindTexture(GL_TEXTURE_2D, display_tex); @@ -1999,13 +1857,18 @@ int main(const int argc, const char* argv[]) glfwSwapBuffers(window); //break; - } + } //Cleanup imgui ImGui_ImplOpenGL3_Shutdown(); ImGui_ImplGlfw_Shutdown(); ImGui::DestroyContext(); + // Cleanup OIDN + oidnReleaseBuffer(inputBuffer); + oidnReleaseFilter(filter); + oidnReleaseDevice(oidnDevice); + // Cleanup CUDA. if (env_tex) { check_success(cudaDestroyTextureObject(kernel_params.env_tex) == cudaSuccess); @@ -2025,4 +1888,4 @@ int main(const int argc, const char* argv[]) glfwTerminate(); return 0; -} + } \ No newline at end of file diff --git a/source/util/fileIO.cpp b/source/util/fileIO.cpp index 2dbc0ee..236695a 100644 --- a/source/util/fileIO.cpp +++ b/source/util/fileIO.cpp @@ -9,11 +9,11 @@ // * Redistributions in binary form must reproduce the above copyright notice, // this list of conditions and the following disclaimer in the documentation // and/or other materials provided with the distribution. -// +// // * Neither the name of the copyright holder nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. -// +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE @@ -24,11 +24,11 @@ // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, // OR TORT(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// +// // Copyright(c) 2019, Sergen Eren // All rights reserved. //---------------------------------------------------------------------------------- -// +// // Version 1.0: Sergen Eren, 15/12/2019 // // File: This is the implementation file for fileIO @@ -38,13 +38,9 @@ #define NOMINMAX #define _CRT_SECURE_NO_WARNINGS -#define STB_IMAGE_WRITE_IMPLEMENTATION -#include "stb_image_write.h" - -#define TINYEXR_USE_MINIZ 0 -#include "zlib.h" -#define TINYEXR_IMPLEMENTATION -#include "tinyexr.h" +#include +#include "OpenImageIO/imagebufalgo.h" +using namespace OIIO; #include "bitmap_image.h" @@ -54,546 +50,333 @@ #include "fileIO.h" #include "logger.h" -bool save_texture_jpg(float3 * buffer, std::string filename, const int width, const int height) +bool save_texture_jpg(float3* buffer, std::string filename, const int width, const int height) { - unsigned char *data = new unsigned char[width*height * 3]; - - int idx = 0; - for (int i = 0; i < width; ++i) { - for (int y = 0; y < height; ++y) { - - int index = i * height + y; - data[idx++] = fminf(fmaxf(0, unsigned char(buffer[index].x * 255)), 255); - data[idx++] = fminf(fmaxf(0, unsigned char(buffer[index].y * 255)), 255); - data[idx++] = fminf(fmaxf(0, unsigned char(buffer[index].z * 255)), 255); - - } + std::unique_ptr out = ImageOutput::create(filename); + if (!out) { + return false; } - stbi_flip_vertically_on_write(1); - int res = stbi_write_jpg(filename.c_str(), width, height, 3, (void*)data, 100); - delete[] data; + ImageSpec spec(width, height, 3, TypeDesc::FLOAT); + out->open(filename, spec); + out->write_image(TypeDesc::FLOAT, buffer); + out->close(); - if (res) { - log("Saved jpg file " + filename, LOG); - return true; - } - return false; + // Flip + ImageBuf A(filename); + ImageBuf B; + B = ImageBufAlgo::flip(A); + B.write(filename); + + return true; } -bool save_texture_jpg(float4 * buffer, std::string filename, const int width, const int height) +bool save_texture_jpg(float4* buffer, std::string filename, const int width, const int height) { + std::unique_ptr out = ImageOutput::create(filename); + if (!out) { + return false; + } - unsigned char *data = new unsigned char[width*height * 3]; + ImageSpec spec(width, height, 4, TypeDesc::FLOAT); + out->open(filename, spec); + out->write_image(TypeDesc::FLOAT, buffer); + out->close(); - int idx = 0; - for (int i = 0; i < width; ++i) { - for (int y = 0; y < height; ++y) { + // Flip + ImageBuf A(filename); + ImageBuf B; + B = ImageBufAlgo::flip(A); + B.write(filename); - int index = i * height + y; - data[idx++] = fminf(fmaxf(0, unsigned char(buffer[index].x * 255)), 255); - data[idx++] = fminf(fmaxf(0, unsigned char(buffer[index].y * 255)), 255); - data[idx++] = fminf(fmaxf(0, unsigned char(buffer[index].z * 255)), 255); + return true; +} - } +bool save_texture_jpg(uint32_t* buffer, std::string filename, const int width, const int height) +{ + std::unique_ptr out = ImageOutput::create(filename); + if (!out) { + return false; } - stbi_flip_vertically_on_write(1); - int res = stbi_write_jpg(filename.c_str(), width, height, 3, (void*)data, 100); - delete[] data; + ImageSpec spec(width, height, 4, TypeDesc::UINT32); + out->open(filename, spec); + out->write_image(TypeDesc::UINT8, buffer); + out->close(); - if (res) { - log("Saved jpg file " + filename, LOG); - return true; - } - return false; + return true; } -bool save_texture_png(float3 * buffer, std::string filename, const int width, const int height) +bool save_texture_png(float3* buffer, std::string filename, const int width, const int height) { - unsigned char *data = new unsigned char[width*height * 3]; - - int idx = 0; - for (int i = 0; i < width; ++i) { - for (int y = 0; y < height; ++y) { - - int index = i * height + y; - data[idx++] = fminf(fmaxf(0, unsigned char(buffer[index].x * 255)), 255); - data[idx++] = fminf(fmaxf(0, unsigned char(buffer[index].y * 255)), 255); - data[idx++] = fminf(fmaxf(0, unsigned char(buffer[index].z * 255)), 255); - - } + std::unique_ptr out = ImageOutput::create(filename); + if (!out) { + return false; } - stbi_flip_vertically_on_write(1); - int res = stbi_write_png(filename.c_str(), width, height, 3, (void*)data, 0); - delete[] data; - - if (res) { - log("Saved png file " + filename, LOG); - return true; - } - return false; + ImageSpec spec(width, height, 3, TypeDesc::FLOAT); + out->open(filename, spec); + out->write_image(TypeDesc::UINT8, buffer); + out->close(); + return true; } -bool save_texture_png(float4 * buffer, std::string filename, const int width, const int height) +bool save_texture_png(float4* buffer, std::string filename, const int width, const int height) { - unsigned char *data = new unsigned char[width*height * 4]; - - int idx = 0; - for (int i = 0; i < width; ++i) { - for (int y = 0; y < height; ++y) { - - int index = i * height + y; - data[idx++] = fminf(fmaxf(0, unsigned char(buffer[index].x * 255)), 255); - data[idx++] = fminf(fmaxf(0, unsigned char(buffer[index].y * 255)), 255); - data[idx++] = fminf(fmaxf(0, unsigned char(buffer[index].z * 255)), 255); - data[idx++] = fminf(fmaxf(0, unsigned char(buffer[index].w * 255)), 255); - } + std::unique_ptr out = ImageOutput::create(filename); + if (!out) { + return false; } - stbi_flip_vertically_on_write(1); - int res = stbi_write_png(filename.c_str(), width, height, 4, (void*)data, 0); - delete[] data; - if (res) { - log("Saved png file " + filename, LOG); - return true; - } - return false; + ImageSpec spec(width, height, 4, TypeDesc::FLOAT); + out->open(filename, spec); + out->write_image(TypeDesc::FLOAT, buffer); + out->close(); + + return true; } -bool save_texture_tga(float3 * buffer, std::string filename, const int width, const int height) +bool save_texture_png(uint32_t* buffer, std::string filename, const int width, const int height) { - - unsigned char *data = new unsigned char[width*height * 3]; - - int idx = 0; - for (int i = 0; i < width; ++i) { - for (int y = 0; y < height; ++y) { - - int index = i * height + y; - data[idx++] = (unsigned int)(255.0f * fminf(fmaxf(buffer[i].x, 0.0f), 1.0f)); - data[idx++] = (unsigned int)(255.0f * fminf(fmaxf(buffer[i].y, 0.0f), 1.0f)); - data[idx++] = (unsigned int)(255.0f * fminf(fmaxf(buffer[i].z, 0.0f), 1.0f)); - - } + std::unique_ptr out = ImageOutput::create(filename); + if (!out) { + return false; } - stbi_flip_vertically_on_write(1); - int res = stbi_write_tga(filename.c_str(), width, height, 3, data); - delete[] data; - - if (res) { - log("Saved tga file " + filename, LOG); - return true; - } - return false; + ImageSpec spec(width, height, 4, TypeDesc::UINT32); + out->open(filename, spec); + out->write_image(TypeDesc::UINT8, buffer); + out->close(); + return true; } -bool save_texture_tga(float4 * buffer, std::string filename, const int width, const int height) +bool save_texture_tga(float3* buffer, std::string filename, const int width, const int height) { - unsigned char *data = new unsigned char[width*height * 4]; - - int idx = 0; - for (int i = 0; i < width; ++i) { - for (int y = 0; y < height; ++y) { - - int index = i * height + y; - data[idx++] = (unsigned int)(255.0f * fminf(fmaxf(buffer[i].x, 0.0f), 1.0f)); - data[idx++] = (unsigned int)(255.0f * fminf(fmaxf(buffer[i].y, 0.0f), 1.0f)); - data[idx++] = (unsigned int)(255.0f * fminf(fmaxf(buffer[i].z, 0.0f), 1.0f)); - data[idx++] = (unsigned int)(255.0f * fminf(fmaxf(buffer[i].w, 0.0f), 1.0f)); - - } + std::unique_ptr out = ImageOutput::create(filename); + if (!out) { + return false; } - stbi_flip_vertically_on_write(1); - int res = stbi_write_tga(filename.c_str(), width, height, 4, data); - delete[] data; + ImageSpec spec(width, height, 3, TypeDesc::FLOAT); + out->open(filename, spec); + out->write_image(TypeDesc::FLOAT, buffer); + out->close(); - if (res) { - log("Saved tga file " + filename, LOG); - return true; - } - return false; + return true; } -bool save_texture_exr(float3 *buffer, std::string filename, const int width, const int height, bool flip) +bool save_texture_tga(float4* buffer, std::string filename, const int width, const int height) { - EXRHeader header; - InitEXRHeader(&header); - - EXRImage image; - InitEXRImage(&image); - - image.num_channels = 3; - - std::vector images[3]; - for (int i = 0; i < image.num_channels; i++) images[i].resize(width*height); - - for (int i = 0; i < height; i++) { - for (int j = 0; j < width; j++) { - - int idx = i * width + j; - - // Flip image vertically - if (flip) i = height - i - 1; - int idx2 = i * width + j; - - images[0][idx] = buffer[idx2].x; - images[1][idx] = buffer[idx2].y; - images[2][idx] = buffer[idx2].z; - } + std::unique_ptr out = ImageOutput::create(filename); + if (!out) { + return false; } - float* image_ptr[3]; + ImageSpec spec(width, height, 4, TypeDesc::FLOAT); + out->open(filename, spec); + out->write_image(TypeDesc::FLOAT, buffer); + out->close(); - image_ptr[0] = &(images[2].at(0)); // B - image_ptr[1] = &(images[1].at(0)); // G - image_ptr[2] = &(images[0].at(0)); // R - - image.images = (unsigned char**)image_ptr; - image.width = width; - image.height = height; - - header.num_channels = 3; - header.channels = (EXRChannelInfo *)malloc(sizeof(EXRChannelInfo) * header.num_channels); - // Must be (A)BGR order, since most of EXR viewers expect this channel order. - strncpy(header.channels[0].name, "B", 255); header.channels[0].name[strlen("B")] = '\0'; - strncpy(header.channels[1].name, "G", 255); header.channels[1].name[strlen("G")] = '\0'; - strncpy(header.channels[2].name, "R", 255); header.channels[2].name[strlen("R")] = '\0'; - - header.pixel_types = (int *)malloc(sizeof(int) * header.num_channels); - header.requested_pixel_types = (int *)malloc(sizeof(int) * header.num_channels); - for (int i = 0; i < header.num_channels; i++) { - header.pixel_types[i] = TINYEXR_PIXELTYPE_FLOAT; // pixel type of input image - header.requested_pixel_types[i] = TINYEXR_PIXELTYPE_HALF; // pixel type of output image to be stored in .EXR - } + return true; +} - const char* err = NULL; // or nullptr in C++11 or later. - int ret = SaveEXRImageToFile(&image, &header, filename.c_str(), &err); - if (ret != TINYEXR_SUCCESS) { - log("Save EXR err: " + *err, ERROR); +bool save_texture_exr(float3* buffer, std::string filename, const int width, const int height, bool flip) +{ + std::unique_ptr out = ImageOutput::create(filename); + if (!out) { return false; } - log("Saved exr file " + filename, LOG); - - free(header.channels); - free(header.pixel_types); - free(header.requested_pixel_types); + ImageSpec spec(width, height, 3, TypeDesc::FLOAT); + spec.channelnames.push_back("R"); + spec.channelnames.push_back("G"); + spec.channelnames.push_back("B"); + out->open(filename, spec); + out->write_image(TypeDesc::FLOAT, buffer); + out->close(); return true; } -bool save_texture_exr(float3* buffer, float *depth, std::string filename, const int width, const int height, bool flip) +bool save_texture_exr(float3* buffer, float* depth, std::string filename, const int width, const int height, bool flip) { - EXRHeader header; - InitEXRHeader(&header); - - EXRImage image; - InitEXRImage(&image); - - image.num_channels = 4; - - std::vector images[4]; - for (int i = 0; i < image.num_channels; i++) images[i].resize(width * height); - - for (int i = 0; i < height; i++) { - for (int j = 0; j < width; j++) { - - int idx = i * width + j; - - // Flip image vertically - if (flip) i = height - i - 1; - int idx2 = i * width + j; - - images[0][idx] = buffer[idx2].x; - images[1][idx] = buffer[idx2].y; - images[2][idx] = buffer[idx2].z; - images[3][idx] = depth[idx2]; - } - } - - float* image_ptr[4]; - - image_ptr[0] = &(images[2].at(0)); // B - image_ptr[1] = &(images[1].at(0)); // G - image_ptr[2] = &(images[0].at(0)); // R - image_ptr[3] = &(images[3].at(0)); // Z - - image.images = (unsigned char**)image_ptr; - image.width = width; - image.height = height; - - header.num_channels = 4; - header.channels = (EXRChannelInfo*)malloc(sizeof(EXRChannelInfo) * header.num_channels); - // Must be (A)BGR order, since most of EXR viewers expect this channel order. - strncpy(header.channels[0].name, "B", 255); header.channels[0].name[strlen("B")] = '\0'; - strncpy(header.channels[1].name, "G", 255); header.channels[1].name[strlen("G")] = '\0'; - strncpy(header.channels[2].name, "R", 255); header.channels[2].name[strlen("R")] = '\0'; - strncpy(header.channels[3].name, "Z", 255); header.channels[3].name[strlen("Z")] = '\0'; - - header.pixel_types = (int*)malloc(sizeof(int) * header.num_channels); - header.requested_pixel_types = (int*)malloc(sizeof(int) * header.num_channels); - for (int i = 0; i < header.num_channels; i++) { - header.pixel_types[i] = TINYEXR_PIXELTYPE_FLOAT; // pixel type of input image - header.requested_pixel_types[i] = TINYEXR_PIXELTYPE_HALF; // pixel type of output image to be stored in .EXR - } - - const char* err = NULL; // or nullptr in C++11 or later. - int ret = SaveEXRImageToFile(&image, &header, filename.c_str(), &err); - if (ret != TINYEXR_SUCCESS) { - log("Save EXR err: " + *err, ERROR); + std::unique_ptr out = ImageOutput::create(filename); + if (!out) { return false; } - log("Saved exr file " + filename, LOG); - - free(header.channels); - free(header.pixel_types); - free(header.requested_pixel_types); + ImageSpec spec(width, height, 4, TypeDesc::FLOAT); + spec.channelnames.push_back("R"); + spec.channelnames.push_back("G"); + spec.channelnames.push_back("B"); + spec.channelnames.push_back("Z"); + out->open(filename, spec); + out->write_image(TypeDesc::FLOAT, buffer); + out->close(); return true; } -bool save_texture_exr(float4 *buffer, std::string filename, const int width, const int height, bool flip) +bool save_texture_exr(float4* buffer, std::string filename, const int width, const int height, bool flip) { - EXRHeader header; - InitEXRHeader(&header); - - EXRImage image; - InitEXRImage(&image); - - image.num_channels = 4; - - std::vector images[4]; - for (int i = 0; i < image.num_channels; i++) images[i].resize(width*height); - - for (int i = 0; i < height; i++) { - for (int j = 0; j < width; j++) { - - int idx = i * width + j; - - // Flip image vertically - if (flip) i = height - i - 1; - int idx2 = i * width + j; - - images[0][idx] = buffer[idx2].x; - images[1][idx] = buffer[idx2].y; - images[2][idx] = buffer[idx2].z; - images[3][idx] = buffer[idx2].w; - - } - } - - float* image_ptr[4]; - - image_ptr[0] = &(images[3].at(0)); // A - image_ptr[1] = &(images[2].at(0)); // B - image_ptr[2] = &(images[1].at(0)); // G - image_ptr[3] = &(images[0].at(0)); // R - - image.images = (unsigned char**)image_ptr; - image.width = width; - image.height = height; - - header.num_channels = 4; - header.channels = (EXRChannelInfo *)malloc(sizeof(EXRChannelInfo) * header.num_channels); - // Must be (A)BGR order, since most of EXR viewers expect this channel order. - strncpy(header.channels[0].name, "A", 255); header.channels[0].name[strlen("A")] = '\0'; - strncpy(header.channels[1].name, "B", 255); header.channels[1].name[strlen("B")] = '\0'; - strncpy(header.channels[2].name, "G", 255); header.channels[2].name[strlen("G")] = '\0'; - strncpy(header.channels[3].name, "R", 255); header.channels[3].name[strlen("R")] = '\0'; - - header.pixel_types = (int *)malloc(sizeof(int) * header.num_channels); - header.requested_pixel_types = (int *)malloc(sizeof(int) * header.num_channels); - for (int i = 0; i < header.num_channels; i++) { - header.pixel_types[i] = TINYEXR_PIXELTYPE_FLOAT; // pixel type of input image - header.requested_pixel_types[i] = TINYEXR_PIXELTYPE_HALF; // pixel type of output image to be stored in .EXR - } - - const char* err = NULL; // or nullptr in C++11 or later. - int ret = SaveEXRImageToFile(&image, &header, filename.c_str(), &err); - if (ret != TINYEXR_SUCCESS) { - log("Save EXR err: " + *err, ERROR); + std::unique_ptr out = ImageOutput::create(filename); + if (!out) { return false; } - log("Saved exr file " + filename, LOG); - free(header.channels); - free(header.pixel_types); - free(header.requested_pixel_types); + ImageSpec spec(width, height, 4, TypeDesc::FLOAT); + spec.channelnames.emplace_back("R"); + spec.channelnames.emplace_back("G"); + spec.channelnames.emplace_back("B"); + spec.channelnames.emplace_back("A"); + + out->open(filename, spec); + out->write_image(TypeDesc::FLOAT, buffer); + out->close(); return true; } -bool save_texture_exr(float4* buffer, float *depth, std::string filename, const int width, const int height, bool flip) +bool save_texture_exr(float4* buffer, float* depth, std::string filename, const int width, const int height, bool flip) { - EXRHeader header; - InitEXRHeader(&header); - - EXRImage image; - InitEXRImage(&image); - - image.num_channels = 5; - - std::vector images[5]; - for (int i = 0; i < image.num_channels; i++) images[i].resize(width * height); - - for (int i = 0; i < height; i++) { - for (int j = 0; j < width; j++) { - - int idx = i * width + j; - - // Flip image vertically - if (flip) i = height - i - 1; - int idx2 = i * width + j; - - images[0][idx] = buffer[idx2].x; - images[1][idx] = buffer[idx2].y; - images[2][idx] = buffer[idx2].z; - images[3][idx] = buffer[idx2].w; - images[4][idx] = depth[idx2]; - - } - } - - float* image_ptr[5]; - - image_ptr[0] = &(images[3].at(0)); // A - image_ptr[1] = &(images[2].at(0)); // B - image_ptr[2] = &(images[1].at(0)); // G - image_ptr[3] = &(images[0].at(0)); // R - image_ptr[4] = &(images[4].at(0)); // Z - - image.images = (unsigned char**)image_ptr; - image.width = width; - image.height = height; - - header.num_channels = 5; - header.channels = (EXRChannelInfo*)malloc(sizeof(EXRChannelInfo) * header.num_channels); - // Must be (A)BGR order, since most of EXR viewers expect this channel order. - strncpy(header.channels[0].name, "A", 255); header.channels[0].name[strlen("A")] = '\0'; - strncpy(header.channels[1].name, "B", 255); header.channels[1].name[strlen("B")] = '\0'; - strncpy(header.channels[2].name, "G", 255); header.channels[2].name[strlen("G")] = '\0'; - strncpy(header.channels[3].name, "R", 255); header.channels[3].name[strlen("R")] = '\0'; - strncpy(header.channels[4].name, "Z", 255); header.channels[4].name[strlen("Z")] = '\0'; - - header.pixel_types = (int*)malloc(sizeof(int) * header.num_channels); - header.requested_pixel_types = (int*)malloc(sizeof(int) * header.num_channels); - for (int i = 0; i < header.num_channels; i++) { - header.pixel_types[i] = TINYEXR_PIXELTYPE_FLOAT; // pixel type of input image - header.requested_pixel_types[i] = TINYEXR_PIXELTYPE_HALF; // pixel type of output image to be stored in .EXR + std::unique_ptr out = ImageOutput::create(filename); + if (!out) { + return false; } + ImageSpec spec(width, height, 5, TypeDesc::FLOAT); + spec.channelnames.push_back("R"); + spec.channelnames.push_back("G"); + spec.channelnames.push_back("B"); + spec.channelnames.push_back("A"); + spec.channelnames.push_back("Z"); - const char* err = NULL; // or nullptr in C++11 or later. - int ret = SaveEXRImageToFile(&image, &header, filename.c_str(), &err); - if (ret != TINYEXR_SUCCESS) { - log("Save EXR err: " + *err, ERROR); - return false; + std::vector combined(width * height * 5); + for (size_t x = 0; x < width * height; x++) + { + combined.push_back(buffer[x].x); + combined.push_back(buffer[x].y); + combined.push_back(buffer[x].z); + combined.push_back(buffer[x].w); + combined.push_back(depth[x]); } - log("Saved exr file " + filename, LOG); - free(header.channels); - free(header.pixel_types); - free(header.requested_pixel_types); + out->open(filename, spec); + out->write_image(TypeDesc::FLOAT, combined.data()); + out->close(); return true; } -bool load_texture_exr(float3 **buffer, std::string filename, int &width, int &height, bool flip) +bool save_texture_exr(uint32_t* buffer, std::string filename, const int width, const int height, bool flip) { + std::unique_ptr out = ImageOutput::create(filename); + if (!out) { + return false; + } + ImageSpec spec(width, height, 4, TypeDesc::UINT32); + spec.channelnames.push_back("R"); + spec.channelnames.push_back("G"); + spec.channelnames.push_back("B"); + spec.channelnames.push_back("A"); + out->open(filename, spec); + out->write_image(TypeDesc::UINT32, buffer); + out->close(); - float *rgba; - const char *err; - - int ret = LoadEXR(&rgba, &width, &height, filename.c_str(), &err); - log("loaded file " + filename + " width:" + std::to_string(width) + " height:" + std::to_string(height), LOG); + return true; +} - if (ret != 0) { - log("Save EXR err: " + *err, ERROR); +bool load_texture_exr(float3** buffer, std::string filename, int& width, int& height, bool flip) +{ + auto in = ImageInput::open(filename); + if (!in) { return false; } + const ImageSpec& specInput = in->spec(); + width = specInput.width; + height = specInput.height; + int channels = specInput.nchannels; + std::vector pixels(height * width * channels); + in->read_image(TypeDesc::FLOAT, &pixels[0]); + in->close(); - *buffer = new float3[width*height]; + *buffer = new float3[width * height]; int float_idx = 0; for (int y = 0; y < height; ++y) { for (int x = 0; x < width; ++x) { int idx = y * width + x; - if (flip) idx = (width*height) - idx - 1; + if (flip) idx = (width * height) - idx - 1; - (*buffer)[idx].x = rgba[float_idx++]; // r - (*buffer)[idx].y = rgba[float_idx++]; // g - (*buffer)[idx].z = rgba[float_idx++]; // b + (*buffer)[idx].x = pixels[float_idx++]; // r + (*buffer)[idx].y = pixels[float_idx++]; // g + (*buffer)[idx].z = pixels[float_idx++]; // b float_idx++; // alpha } } - delete[] rgba; - return true; } -bool load_texture_exr(float4 **buffer, std::string filename, int &width, int &height, bool flip) +bool load_texture_exr(float4** buffer, std::string filename, int& width, int& height, bool flip) { - float *rgba; - const char *err; - - int ret = LoadEXR(&rgba, &width, &height, filename.c_str(), &err); - log("loaded file " + filename + " width:" + std::to_string(width) + " height:" + std::to_string(height), LOG); - - if (ret != 0) { - log("Save EXR err: " + *err, ERROR); + auto in = ImageInput::open(filename); + if (!in) { return false; } + const ImageSpec& specInput = in->spec(); + width = specInput.width; + height = specInput.height; + int channels = specInput.nchannels; + std::vector pixels(height * width * channels); + in->read_image(TypeDesc::FLOAT, &pixels[0]); + in->close(); - *buffer = new float4[width*height]; + *buffer = new float4[width * height]; int float_idx = 0; for (int y = 0; y < height; ++y) { for (int x = 0; x < width; ++x) { int idx = y * width + x; - if (flip) idx = (width*height) - idx - 1; + if (flip) idx = (width * height) - idx - 1; - (*buffer)[idx].x = rgba[float_idx++]; // r - (*buffer)[idx].y = rgba[float_idx++]; // g - (*buffer)[idx].z = rgba[float_idx++]; // b - (*buffer)[idx].w = rgba[float_idx++]; // b + (*buffer)[idx].x = pixels[float_idx++]; // r + (*buffer)[idx].y = pixels[float_idx++]; // g + (*buffer)[idx].z = pixels[float_idx++]; // b + (*buffer)[idx].w = pixels[float_idx++]; // b } } - delete[] rgba; - return true; } -bool load_texture_exr_gpu(float3 ** buffer, std::string filename, int & width, int & height, bool flip) +bool load_texture_exr_gpu(float3** buffer, std::string filename, int& width, int& height, bool flip) { - float *rgba; - const char *err; - int ret = LoadEXR(&rgba, &width, &height, filename.c_str(), &err); - log("loaded file " + filename + " width:" + std::to_string(width) + " height:" + std::to_string(height), LOG); - if (ret != 0) { - log("Save EXR err: " + *err, ERROR); + auto in = ImageInput::open(filename); + if (!in) { return false; } + const ImageSpec& specInput = in->spec(); + width = specInput.width; + height = specInput.height; + int channels = specInput.nchannels; + std::vector pixels(height * width * channels); + in->read_image(TypeDesc::FLOAT, &pixels[0]); + in->close(); - float3 *values = new float3[height * width]; + float3* values = new float3[height * width]; int float_idx = 0; for (int y = 0; y < height; ++y) { for (int x = 0; x < width; ++x) { int idx = y * width + x; - if (flip) idx = (width*height) - idx - 1; - values[idx].x = rgba[float_idx++]; // r - values[idx].y = rgba[float_idx++]; // g - values[idx].z = rgba[float_idx++]; // b + if (flip) idx = (width * height) - idx - 1; + values[idx].x = pixels[float_idx++]; // r + values[idx].y = pixels[float_idx++]; // g + values[idx].z = pixels[float_idx++]; // b float_idx++; // alpha } } @@ -601,106 +384,104 @@ bool load_texture_exr_gpu(float3 ** buffer, std::string filename, int & width, i checkCudaErrors(cudaMalloc(buffer, width * height * sizeof(float3))); checkCudaErrors(cudaMemcpy(*buffer, values, width * height * sizeof(float3), cudaMemcpyHostToDevice)); - delete[] rgba; delete[] values; return true; } -bool load_texture_exr_gpu(float4 ** buffer, std::string filename, int & width, int & height, bool flip) +bool load_texture_exr_gpu(float4** buffer, std::string filename, int& width, int& height, bool flip) { - float *rgba; - const char *err; - int ret = LoadEXR(&rgba, &width, &height, filename.c_str(), &err); - log("loaded file " + filename + " width:" + std::to_string(width) + " height:" + std::to_string(height), LOG); - if (ret != 0) { - log("Save EXR err: " + *err, ERROR); + auto in = ImageInput::open(filename); + if (!in) { return false; } + const ImageSpec& specInput = in->spec(); + width = specInput.width; + height = specInput.height; + int channels = specInput.nchannels; + std::vector pixels(height * width * channels); + in->read_image(TypeDesc::FLOAT, &pixels[0]); + in->close(); - float4 *values = new float4[height * width]; + float4* values = new float4[height * width]; int float_idx = 0; for (int y = 0; y < height; ++y) { for (int x = 0; x < width; ++x) { int idx = y * width + x; - if (flip) idx = (width*height) - idx - 1; - values[idx].x = rgba[float_idx++]; // r - values[idx].y = rgba[float_idx++]; // g - values[idx].z = rgba[float_idx++]; // b - values[idx].w = rgba[float_idx++]; // b + if (flip) idx = (width * height) - idx - 1; + values[idx].x = pixels[float_idx++]; // r + values[idx].y = pixels[float_idx++]; // g + values[idx].z = pixels[float_idx++]; // b + values[idx].w = pixels[float_idx++]; // b } } checkCudaErrors(cudaMalloc(buffer, width * height * sizeof(float4))); checkCudaErrors(cudaMemcpy(*buffer, values, width * height * sizeof(float4), cudaMemcpyHostToDevice)); - delete[] rgba; delete[] values; return true; } -bool load_texture_bmp(float3 ** buffer, std::string filename, int & width, int & height, bool flip) +bool load_texture_bmp(float3** buffer, std::string filename, int& width, int& height, bool flip) { - // Load blue noise texture from assets directory and send to gpu + // Load blue noise texture from assets directory and send to gpu bitmap_image image(filename.c_str()); if (!image) { - log("Unable to load file " + filename, ERROR); + log("Unable to load file " + filename, VPT_ERROR); return false; } width = image.width(); height = image.height(); - *buffer = new float3[width*height]; + *buffer = new float3[width * height]; for (int y = 0; y < height; ++y) { for (int x = 0; x < width; ++x) { - rgb_t color; image.get_pixel(x, y, color); int idx = y * width + x; - if (flip) idx = (width*height) - idx - 1; + if (flip) idx = (width * height) - idx - 1; (*buffer)[idx].x = float(color.red) / 255.0f; (*buffer)[idx].y = float(color.blue) / 255.0f; (*buffer)[idx].z = float(color.green) / 255.0f; } } - log("loaded file " + filename + " width:" + std::to_string(width) + " height:" + std::to_string(height), LOG); + log("loaded file " + filename + " width:" + std::to_string(width) + " height:" + std::to_string(height), VPT_LOG); return true; } -bool load_texture_bmp_gpu(float3 ** buffer, std::string filename, int & width, int & height, bool flip) +bool load_texture_bmp_gpu(float3** buffer, std::string filename, int& width, int& height, bool flip) { - // Load blue noise texture from assets directory and send to gpu + // Load blue noise texture from assets directory and send to gpu bitmap_image image(filename.c_str()); if (!image) { - log("Unable to load file " + filename, ERROR); + log("Unable to load file " + filename, VPT_ERROR); return false; } width = image.width(); height = image.height(); - float3 *values = new float3[height * width]; + float3* values = new float3[height * width]; for (int y = 0; y < height; ++y) { for (int x = 0; x < width; ++x) { - rgb_t color; image.get_pixel(x, y, color); int idx = y * width + x; - if (flip) idx = (width*height) - idx - 1; + if (flip) idx = (width * height) - idx - 1; values[idx].x = float(color.red) / 255.0f; values[idx].y = float(color.blue) / 255.0f; values[idx].z = float(color.green) / 255.0f; - } } @@ -709,8 +490,7 @@ bool load_texture_bmp_gpu(float3 ** buffer, std::string filename, int & width, i delete[] values; - log("loaded file " + filename + " width:" + std::to_string(width) + " height:" + std::to_string(height), LOG); + log("loaded file " + filename + " width:" + std::to_string(width) + " height:" + std::to_string(height), VPT_LOG); return true; -} - +} \ No newline at end of file diff --git a/source/util/logger.cpp b/source/util/logger.cpp index bb4b91e..70f1c49 100644 --- a/source/util/logger.cpp +++ b/source/util/logger.cpp @@ -23,15 +23,15 @@ void log(const char * message, unsigned int level) void log(std::string message, unsigned int level) { - if (level == ERROR) { + if (level == VPT_ERROR) { fprintf(stderr, "Error! %s\n", message.c_str()); } - if (level == WARNING) { + if (level == VPT_WARNING) { #if defined(LOG_LEVEL_WARNING) || defined(LOG_LEVEL_LOG) printf("Warning: %s\n", message.c_str()); #endif } - if (level == LOG) { + if (level == VPT_LOG) { #if defined(LOG_LEVEL_LOG) printf("%s\n", message.c_str()); #endif diff --git a/source/util/logger.h b/source/util/logger.h index ae7d56e..f2e47cc 100644 --- a/source/util/logger.h +++ b/source/util/logger.h @@ -41,11 +41,10 @@ #include -enum { - - ERROR = 0, - WARNING = 1, - LOG = 2 +enum LogLevel{ + VPT_ERROR = 0, + VPT_WARNING = 1, + VPT_LOG = 2 }; diff --git a/thirdparty/OpenImageDenoise/bin/OpenImageDenoise.dll b/thirdparty/OpenImageDenoise/bin/OpenImageDenoise.dll new file mode 100644 index 0000000..2af8d1b Binary files /dev/null and b/thirdparty/OpenImageDenoise/bin/OpenImageDenoise.dll differ diff --git a/thirdparty/OpenImageDenoise/bin/OpenImageDenoise_core.dll b/thirdparty/OpenImageDenoise/bin/OpenImageDenoise_core.dll new file mode 100644 index 0000000..12d6a8d Binary files /dev/null and b/thirdparty/OpenImageDenoise/bin/OpenImageDenoise_core.dll differ diff --git a/thirdparty/OpenImageDenoise/bin/OpenImageDenoise_device_cpu.dll b/thirdparty/OpenImageDenoise/bin/OpenImageDenoise_device_cpu.dll new file mode 100644 index 0000000..8cb6487 Binary files /dev/null and b/thirdparty/OpenImageDenoise/bin/OpenImageDenoise_device_cpu.dll differ diff --git a/thirdparty/OpenImageDenoise/bin/OpenImageDenoise_device_cuda.dll b/thirdparty/OpenImageDenoise/bin/OpenImageDenoise_device_cuda.dll new file mode 100644 index 0000000..cd69c44 Binary files /dev/null and b/thirdparty/OpenImageDenoise/bin/OpenImageDenoise_device_cuda.dll differ diff --git a/thirdparty/OpenImageDenoise/include/OpenImageDenoise/config.h b/thirdparty/OpenImageDenoise/include/OpenImageDenoise/config.h new file mode 100644 index 0000000..f6ee70f --- /dev/null +++ b/thirdparty/OpenImageDenoise/include/OpenImageDenoise/config.h @@ -0,0 +1,78 @@ +// Copyright 2018 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#define OIDN_VERSION_MAJOR 2 +#define OIDN_VERSION_MINOR 1 +#define OIDN_VERSION_PATCH 0 +#define OIDN_VERSION 20100 +#define OIDN_VERSION_STRING "2.1.0" + +/* #undef OIDN_API_NAMESPACE */ +/* #undef OIDN_STATIC_LIB */ + +#if defined(OIDN_API_NAMESPACE) + #define OIDN_API_NAMESPACE_BEGIN namespace { + #define OIDN_API_NAMESPACE_END } + #define OIDN_API_NAMESPACE_USING using namespace ; + #define OIDN_API_EXTERN_C + #define OIDN_NAMESPACE ::oidn + #define OIDN_NAMESPACE_C _oidn + #define OIDN_NAMESPACE_BEGIN namespace { namespace oidn { + #define OIDN_NAMESPACE_END }} +#else + #define OIDN_API_NAMESPACE_BEGIN + #define OIDN_API_NAMESPACE_END + #define OIDN_API_NAMESPACE_USING + #if defined(__cplusplus) + #define OIDN_API_EXTERN_C extern "C" + #else + #define OIDN_API_EXTERN_C + #endif + #define OIDN_NAMESPACE oidn + #define OIDN_NAMESPACE_C oidn + #define OIDN_NAMESPACE_BEGIN namespace oidn { + #define OIDN_NAMESPACE_END } +#endif + +#define OIDN_NAMESPACE_USING using namespace OIDN_NAMESPACE; + +#if defined(OIDN_STATIC_LIB) + #define OIDN_API_IMPORT OIDN_API_EXTERN_C + #define OIDN_API_EXPORT OIDN_API_EXTERN_C +#elif defined(_WIN32) + #define OIDN_API_IMPORT OIDN_API_EXTERN_C __declspec(dllimport) + #define OIDN_API_EXPORT OIDN_API_EXTERN_C __declspec(dllexport) +#else + #define OIDN_API_IMPORT OIDN_API_EXTERN_C + #define OIDN_API_EXPORT OIDN_API_EXTERN_C __attribute__((visibility ("default"))) +#endif + +#if defined(OpenImageDenoise_EXPORTS) + #define OIDN_API OIDN_API_EXPORT +#else + #define OIDN_API OIDN_API_IMPORT +#endif + +#if defined(_WIN32) + #define OIDN_DEPRECATED(msg) __declspec(deprecated(msg)) +#else + #define OIDN_DEPRECATED(msg) __attribute__((deprecated(msg))) +#endif + +#if !defined(OIDN_DEVICE_CPU) + #define OIDN_DEVICE_CPU +#endif +#if !defined(OIDN_DEVICE_SYCL) +/* #undef OIDN_DEVICE_SYCL */ +#endif +#if !defined(OIDN_DEVICE_CUDA) + #define OIDN_DEVICE_CUDA +#endif +#if !defined(OIDN_DEVICE_HIP) +/* #undef OIDN_DEVICE_HIP */ +#endif + +#define OIDN_FILTER_RT +#define OIDN_FILTER_RTLIGHTMAP diff --git a/thirdparty/OpenImageDenoise/include/OpenImageDenoise/oidn.h b/thirdparty/OpenImageDenoise/include/OpenImageDenoise/oidn.h index 57ba6ba..9cee52e 100644 --- a/thirdparty/OpenImageDenoise/include/OpenImageDenoise/oidn.h +++ b/thirdparty/OpenImageDenoise/include/OpenImageDenoise/oidn.h @@ -1,18 +1,5 @@ -// ======================================================================== // -// 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. // -// ======================================================================== // +// Copyright 2018 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 #pragma once @@ -20,30 +7,67 @@ #include #include -#include "version.h" +#include "config.h" #if defined(__cplusplus) -extern "C" { + #if defined(SYCL_LANGUAGE_VERSION) + #include + #else + namespace sycl + { + class queue; + class event; + } + #endif #endif -#ifndef OIDN_API -#if defined(_WIN32) && !defined(OIDN_STATIC_LIB) -# define OIDN_API __declspec(dllimport) -#else -# define OIDN_API -#endif -#endif +typedef struct CUstream_st* cudaStream_t; +typedef struct ihipStream_t* hipStream_t; + +OIDN_API_NAMESPACE_BEGIN + +// ------------------------------------------------------------------------------------------------- +// Physical Device +// ------------------------------------------------------------------------------------------------- + +#define OIDN_UUID_SIZE 16u // size of a universally unique identifier (UUID) of a physical device +#define OIDN_LUID_SIZE 8u // size of a locally unique identifier (LUID) of a physical device + +// Returns the number of supported physical devices. +OIDN_API int oidnGetNumPhysicalDevices(); + +// Gets a boolean parameter of the physical device. +OIDN_API bool oidnGetPhysicalDeviceBool(int physicalDeviceID, const char* name); + +// Gets an integer parameter of the physical device. +OIDN_API int oidnGetPhysicalDeviceInt(int physicalDeviceID, const char* name); + +// Gets an unsigned integer parameter of the physical device. +inline unsigned int oidnGetPhysicalDeviceUInt(int physicalDeviceID, const char* name) +{ + return (unsigned int)oidnGetPhysicalDeviceInt(physicalDeviceID, name); +} + +// Gets a string parameter of the physical device. +OIDN_API const char* oidnGetPhysicalDeviceString(int physicalDeviceID, const char* name); + +// Gets an opaque data parameter of the physical device. +OIDN_API const void* oidnGetPhysicalDeviceData(int physicalDeviceID, const char* name, + size_t* byteSize); -// ---------------------------------------------------------------------------- +// ------------------------------------------------------------------------------------------------- // Device -// ---------------------------------------------------------------------------- +// ------------------------------------------------------------------------------------------------- // Device types typedef enum { OIDN_DEVICE_TYPE_DEFAULT = 0, // select device automatically - OIDN_DEVICE_TYPE_CPU = 1, // CPU device + OIDN_DEVICE_TYPE_CPU = 1, // CPU device + OIDN_DEVICE_TYPE_SYCL = 2, // SYCL device + OIDN_DEVICE_TYPE_CUDA = 3, // CUDA device + OIDN_DEVICE_TYPE_HIP = 4, // HIP device } OIDNDeviceType; // Error codes @@ -64,9 +88,41 @@ typedef void (*OIDNErrorFunction)(void* userPtr, OIDNError code, const char* mes // Device handle typedef struct OIDNDeviceImpl* OIDNDevice; -// Creates a new device. +// Creates a device of the specified type. OIDN_API OIDNDevice oidnNewDevice(OIDNDeviceType type); +// Creates a device from a physical device specified by its ID (0 to oidnGetNumPhysicalDevices()-1). +OIDN_API OIDNDevice oidnNewDeviceByID(int physicalDeviceID); + +// Creates a device from a physical device specified by its UUID. +OIDN_API OIDNDevice oidnNewDeviceByUUID(const void* uuid); + +// Creates a device from a physical device specified by its LUID. +OIDN_API OIDNDevice oidnNewDeviceByLUID(const void* luid); + +// Creates a device from a physical device specified by its PCI address. +OIDN_API OIDNDevice oidnNewDeviceByPCIAddress(int pciDomain, int pciBus, int pciDevice, + int pciFunction); + +#if defined(__cplusplus) +// Creates a device from the specified list of SYCL queues. +// The queues should belong to different SYCL sub-devices (Xe Stack/Tile) of the same SYCL +// root-device (GPU). +OIDN_API OIDNDevice oidnNewSYCLDevice(const sycl::queue* queues, int numQueues); +#endif + +// Creates a device from the specified pairs of CUDA device IDs (negative ID corresponds to the +// current device) and streams (null stream corresponds to the default stream). +// Currently only one device ID/stream is supported. +OIDN_API OIDNDevice oidnNewCUDADevice(const int* deviceIDs, const cudaStream_t* streams, + int numPairs); + +// Creates a device from the specified pairs of HIP device IDs (negative ID corresponds to the +// current device) and streams (null stream corresponds to the default stream). +// Currently only one device ID/stream is supported. +OIDN_API OIDNDevice oidnNewHIPDevice(const int* deviceIDs, const hipStream_t* streams, + int numPairs); + // Retains the device (increments the reference count). OIDN_API void oidnRetainDevice(OIDNDevice device); @@ -74,71 +130,195 @@ OIDN_API void oidnRetainDevice(OIDNDevice device); OIDN_API void oidnReleaseDevice(OIDNDevice device); // Sets a boolean parameter of the device. -OIDN_API void oidnSetDevice1b(OIDNDevice device, const char* name, bool value); +OIDN_API void oidnSetDeviceBool(OIDNDevice device, const char* name, bool value); + +OIDN_DEPRECATED("oidnSetDevice1b is deprecated. Use oidnSetDeviceBool instead.") +inline void oidnSetDevice1b(OIDNDevice device, const char* name, bool value) +{ + oidnSetDeviceBool(device, name, value); +} // Sets an integer parameter of the device. -OIDN_API void oidnSetDevice1i(OIDNDevice device, const char* name, int value); +OIDN_API void oidnSetDeviceInt(OIDNDevice device, const char* name, int value); + +OIDN_DEPRECATED("oidnSetDevice1i is deprecated. Use oidnSetDeviceInt instead.") +inline void oidnSetDevice1i(OIDNDevice device, const char* name, int value) +{ + oidnSetDeviceInt(device, name, value); +} + +// Sets an unsigned integer parameter of the device. +inline void oidnSetDeviceUInt(OIDNDevice device, const char* name, unsigned int value) +{ + oidnSetDeviceInt(device, name, (int)value); +} // Gets a boolean parameter of the device. -OIDN_API bool oidnGetDevice1b(OIDNDevice device, const char* name); +OIDN_API bool oidnGetDeviceBool(OIDNDevice device, const char* name); -// Gets an integer parameter of the device (e.g. "version"). -OIDN_API int oidnGetDevice1i(OIDNDevice device, const char* name); +OIDN_DEPRECATED("oidnGetDevice1b is deprecated. Use oidnGetDeviceBool instead.") +inline bool oidnGetDevice1b(OIDNDevice device, const char* name) +{ + return oidnGetDeviceBool(device, name); +} + +// Gets an integer parameter of the device. +OIDN_API int oidnGetDeviceInt(OIDNDevice device, const char* name); + +// Gets an unsigned integer parameter of the device. +inline unsigned int oidnGetDeviceUInt(OIDNDevice device, const char* name) +{ + return (unsigned int)oidnGetDeviceInt(device, name); +} + +OIDN_DEPRECATED("oidnGetDevice1i is deprecated. Use oidnGetDeviceInt instead.") +inline int oidnGetDevice1i(OIDNDevice device, const char* name) +{ + return oidnGetDeviceInt(device, name); +} // Sets the error callback function of the device. OIDN_API void oidnSetDeviceErrorFunction(OIDNDevice device, OIDNErrorFunction func, void* userPtr); -// Returns the first unqueried error code stored in the device for the current -// thread, optionally also returning a string message (if not NULL), and clears -// the stored error. Can be called with a NULL device as well to check why a -// device creation failed. +// Returns the first unqueried error code stored in the device for the current thread, optionally +// also returning a string message (if not NULL), and clears the stored error. Can be called with +// a NULL device as well to check for per-thread global errors (e.g. why a device creation or +// physical device query has failed). OIDN_API OIDNError oidnGetDeviceError(OIDNDevice device, const char** outMessage); // Commits all previous changes to the device. // Must be called before first using the device (e.g. creating filters). OIDN_API void oidnCommitDevice(OIDNDevice device); -// ---------------------------------------------------------------------------- +// Waits for all asynchronous operations running on the device to complete. +OIDN_API void oidnSyncDevice(OIDNDevice device); + +// ------------------------------------------------------------------------------------------------- // Buffer -// ---------------------------------------------------------------------------- +// ------------------------------------------------------------------------------------------------- // Formats for images and other data stored in buffers typedef enum { OIDN_FORMAT_UNDEFINED = 0, - // 32-bit single-precision floating point scalar and vector formats + // 32-bit single-precision floating-point scalar and vector formats OIDN_FORMAT_FLOAT = 1, - OIDN_FORMAT_FLOAT2 = 2, - OIDN_FORMAT_FLOAT3 = 3, - OIDN_FORMAT_FLOAT4 = 4, + OIDN_FORMAT_FLOAT2, + OIDN_FORMAT_FLOAT3, + OIDN_FORMAT_FLOAT4, + + // 16-bit half-precision floating-point scalar and vector formats + OIDN_FORMAT_HALF = 257, + OIDN_FORMAT_HALF2, + OIDN_FORMAT_HALF3, + OIDN_FORMAT_HALF4, } OIDNFormat; -// Access modes for mapping buffers +// Storage modes for buffers +typedef enum +{ + OIDN_STORAGE_UNDEFINED = 0, + + // stored on the host, accessible by both host and device + OIDN_STORAGE_HOST = 1, + + // stored on the device, *not* accessible by the host + OIDN_STORAGE_DEVICE = 2, + + // automatically migrated between host and device, accessible by both + // *not* supported by all devices, "managedMemorySupported" device parameter should be checked + OIDN_STORAGE_MANAGED = 3, +} OIDNStorage; + +// External memory type flags typedef enum { - OIDN_ACCESS_READ = 0, // read-only access - OIDN_ACCESS_WRITE = 1, // write-only access - OIDN_ACCESS_READ_WRITE = 2, // read and write access - OIDN_ACCESS_WRITE_DISCARD = 3, // write-only access, previous contents discarded -} OIDNAccess; + OIDN_EXTERNAL_MEMORY_TYPE_FLAG_NONE = 0, + + // opaque POSIX file descriptor handle + OIDN_EXTERNAL_MEMORY_TYPE_FLAG_OPAQUE_FD = 1 << 0, + + // file descriptor handle for a Linux dma_buf + OIDN_EXTERNAL_MEMORY_TYPE_FLAG_DMA_BUF = 1 << 1, + + // NT handle + OIDN_EXTERNAL_MEMORY_TYPE_FLAG_OPAQUE_WIN32 = 1 << 2, + + // global share (KMT) handle + OIDN_EXTERNAL_MEMORY_TYPE_FLAG_OPAQUE_WIN32_KMT = 1 << 3, + + // NT handle returned by IDXGIResource1::CreateSharedHandle referring to a Direct3D 11 texture + // resource + OIDN_EXTERNAL_MEMORY_TYPE_FLAG_D3D11_TEXTURE = 1 << 4, + + // global share (KMT) handle returned by IDXGIResource::GetSharedHandle referring to a Direct3D 11 + // texture resource + OIDN_EXTERNAL_MEMORY_TYPE_FLAG_D3D11_TEXTURE_KMT = 1 << 5, + + // NT handle returned by IDXGIResource1::CreateSharedHandle referring to a Direct3D 11 resource + OIDN_EXTERNAL_MEMORY_TYPE_FLAG_D3D11_RESOURCE = 1 << 6, + + // global share (KMT) handle returned by IDXGIResource::GetSharedHandle referring to a Direct3D 11 + // resource + OIDN_EXTERNAL_MEMORY_TYPE_FLAG_D3D11_RESOURCE_KMT = 1 << 7, + + // NT handle returned by ID3D12Device::CreateSharedHandle referring to a Direct3D 12 heap + // resource + OIDN_EXTERNAL_MEMORY_TYPE_FLAG_D3D12_HEAP = 1 << 8, + + // NT handle returned by ID3D12Device::CreateSharedHandle referring to a Direct3D 12 committed + // resource + OIDN_EXTERNAL_MEMORY_TYPE_FLAG_D3D12_RESOURCE = 1 << 9, +} OIDNExternalMemoryTypeFlag; // Buffer handle typedef struct OIDNBufferImpl* OIDNBuffer; -// Creates a new buffer (data allocated and owned by the device). +// Creates a buffer accessible to both the host and device. OIDN_API OIDNBuffer oidnNewBuffer(OIDNDevice device, size_t byteSize); -// Creates a new shared buffer (data allocated and owned by the user). -OIDN_API OIDNBuffer oidnNewSharedBuffer(OIDNDevice device, void* ptr, size_t byteSize); +// Creates a buffer with the specified storage mode. +OIDN_API OIDNBuffer oidnNewBufferWithStorage(OIDNDevice device, size_t byteSize, OIDNStorage storage); + +// Creates a shared buffer from memory allocated and owned by the user and accessible to the device. +OIDN_API OIDNBuffer oidnNewSharedBuffer(OIDNDevice device, void* devPtr, size_t byteSize); + +// Creates a shared buffer by importing external memory from a POSIX file descriptor. +OIDN_API OIDNBuffer oidnNewSharedBufferFromFD(OIDNDevice device, + OIDNExternalMemoryTypeFlag fdType, + int fd, size_t byteSize); + +// Creates a shared buffer by importing external memory from a Win32 handle. +OIDN_API OIDNBuffer oidnNewSharedBufferFromWin32Handle(OIDNDevice device, + OIDNExternalMemoryTypeFlag handleType, + void* handle, const void* name, size_t byteSize); + +// Gets the size of the buffer in bytes. +OIDN_API size_t oidnGetBufferSize(OIDNBuffer buffer); + +// Gets the storage mode of the buffer. +OIDN_API OIDNStorage oidnGetBufferStorage(OIDNBuffer buffer); + +// Gets a pointer to the buffer data, which is accessible to the device but not necessarily to +// the host as well, depending on the storage mode. Null pointer may be returned if the buffer +// is empty or getting a pointer to data with device storage is not supported by the device. +OIDN_API void* oidnGetBufferData(OIDNBuffer buffer); -// Maps a region of the buffer to host memory. -// If byteSize is 0, the maximum available amount of memory will be mapped. -OIDN_API void* oidnMapBuffer(OIDNBuffer buffer, OIDNAccess access, size_t byteOffset, size_t byteSize); +// Copies data from a region of the buffer to host memory. +OIDN_API void oidnReadBuffer(OIDNBuffer buffer, size_t byteOffset, size_t byteSize, void* dstHostPtr); -// Unmaps a region of the buffer. -// mappedPtr must be a pointer returned by a previous call to oidnMapBuffer. -OIDN_API void oidnUnmapBuffer(OIDNBuffer buffer, void* mappedPtr); +// Copies data from a region of the buffer to host memory asynchronously. +OIDN_API void oidnReadBufferAsync(OIDNBuffer buffer, + size_t byteOffset, size_t byteSize, void* dstHostPtr); + +// Copies data to a region of the buffer from host memory. +OIDN_API void oidnWriteBuffer(OIDNBuffer buffer, + size_t byteOffset, size_t byteSize, const void* srcHostPtr); + +// Copies data to a region of the buffer from host memory asynchronously. +OIDN_API void oidnWriteBufferAsync(OIDNBuffer buffer, + size_t byteOffset, size_t byteSize, const void* srcHostPtr); // Retains the buffer (increments the reference count). OIDN_API void oidnRetainBuffer(OIDNBuffer buffer); @@ -146,9 +326,19 @@ OIDN_API void oidnRetainBuffer(OIDNBuffer buffer); // Releases the buffer (decrements the reference count). OIDN_API void oidnReleaseBuffer(OIDNBuffer buffer); -// ---------------------------------------------------------------------------- +// ------------------------------------------------------------------------------------------------- // Filter -// ---------------------------------------------------------------------------- +// ------------------------------------------------------------------------------------------------- + +// Filter quality/performance modes +typedef enum +{ + OIDN_QUALITY_DEFAULT = 0, // default quality + +//OIDN_QUALITY_FAST = 4 + OIDN_QUALITY_BALANCED = 5, // balanced quality/performance (for interactive/real-time rendering) + OIDN_QUALITY_HIGH = 6, // high quality (for final-frame rendering) +} OIDNQuality; // Progress monitor callback function typedef bool (*OIDNProgressMonitorFunction)(void* userPtr, double n); @@ -156,7 +346,7 @@ typedef bool (*OIDNProgressMonitorFunction)(void* userPtr, double n); // Filter handle typedef struct OIDNFilterImpl* OIDNFilter; -// Creates a new filter of the specified type (e.g. "RT"). +// Creates a filter of the specified type (e.g. "RT"). OIDN_API OIDNFilter oidnNewFilter(OIDNDevice device, const char* type); // Retains the filter (increments the reference count). @@ -165,42 +355,104 @@ OIDN_API void oidnRetainFilter(OIDNFilter filter); // Releases the filter (decrements the reference count). OIDN_API void oidnReleaseFilter(OIDNFilter filter); -// Sets an image parameter of the filter (stored in a buffer). -// If bytePixelStride and/or byteRowStride are zero, these will be computed automatically. +// Sets an image parameter of the filter with data stored in a buffer. +// If pixelByteStride and/or rowByteStride are zero, these will be computed automatically. OIDN_API 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); + size_t pixelByteStride, size_t rowByteStride); -// Sets an image parameter of the filter (owned by the user). -// If bytePixelStride and/or byteRowStride are zero, these will be computed automatically. +// Sets an image parameter of the filter with data owned by the user and accessible to the device. +// If pixelByteStride and/or rowByteStride are zero, these will be computed automatically. OIDN_API void oidnSetSharedFilterImage(OIDNFilter filter, const char* name, - void* ptr, OIDNFormat format, + void* devPtr, OIDNFormat format, size_t width, size_t height, size_t byteOffset, - size_t bytePixelStride, size_t byteRowStride); + size_t pixelByteStride, size_t rowByteStride); + +// Unsets an image parameter of the filter that was previously set. +OIDN_API void oidnUnsetFilterImage(OIDNFilter filter, const char* name); + +OIDN_DEPRECATED("oidnRemoveFilterImage is deprecated. Use oidnUnsetFilterImage instead.") +inline void oidnRemoveFilterImage(OIDNFilter filter, const char* name) +{ + oidnUnsetFilterImage(filter, name); +} + +// Sets an opaque data parameter of the filter owned by the user and accessible to the host. +OIDN_API void oidnSetSharedFilterData(OIDNFilter filter, const char* name, + void* hostPtr, size_t byteSize); + +// Notifies the filter that the contents of an opaque data parameter has been changed. +OIDN_API void oidnUpdateFilterData(OIDNFilter filter, const char* name); + +// Unsets an opaque data parameter of the filter that was previously set. +OIDN_API void oidnUnsetFilterData(OIDNFilter filter, const char* name); + +OIDN_DEPRECATED("oidnRemoveFilterData is deprecated. Use oidnUnsetFilterData instead.") +inline void oidnRemoveFilterData(OIDNFilter filter, const char* name) +{ + oidnUnsetFilterData(filter, name); +} // Sets a boolean parameter of the filter. -OIDN_API void oidnSetFilter1b(OIDNFilter filter, const char* name, bool value); +OIDN_API void oidnSetFilterBool(OIDNFilter filter, const char* name, bool value); + +OIDN_DEPRECATED("oidnSetFilter1b is deprecated. Use oidnSetFilterBool instead.") +inline void oidnSetFilter1b(OIDNFilter filter, const char* name, bool value) +{ + oidnSetFilterBool(filter, name, value); +} // Gets a boolean parameter of the filter. -OIDN_API bool oidnGetFilter1b(OIDNFilter filter, const char* name); +OIDN_API bool oidnGetFilterBool(OIDNFilter filter, const char* name); + +OIDN_DEPRECATED("oidnGetFilter1b is deprecated. Use oidnGetFilterBool instead.") +inline bool oidnGetFilter1b(OIDNFilter filter, const char* name) +{ + return oidnGetFilterBool(filter, name); +} // Sets an integer parameter of the filter. -OIDN_API void oidnSetFilter1i(OIDNFilter filter, const char* name, int value); +OIDN_API void oidnSetFilterInt(OIDNFilter filter, const char* name, int value); + +OIDN_DEPRECATED("oidnSetFilter1i is deprecated. Use oidnSetFilterInt instead.") +inline void oidnSetFilter1i(OIDNFilter filter, const char* name, int value) +{ + oidnSetFilterInt(filter, name, value); +} // Gets an integer parameter of the filter. -OIDN_API int oidnGetFilter1i(OIDNFilter filter, const char* name); +OIDN_API int oidnGetFilterInt(OIDNFilter filter, const char* name); + +OIDN_DEPRECATED("oidnGetFilter1i is deprecated. Use oidnGetFilterInt instead.") +inline int oidnGetFilter1i(OIDNFilter filter, const char* name) +{ + return oidnGetFilterInt(filter, name); +} // Sets a float parameter of the filter. -OIDN_API void oidnSetFilter1f(OIDNFilter filter, const char* name, float value); +OIDN_API void oidnSetFilterFloat(OIDNFilter filter, const char* name, float value); + +OIDN_DEPRECATED("oidnSetFilter1f is deprecated. Use oidnSetFilterFloat instead.") +inline void oidnSetFilter1f(OIDNFilter filter, const char* name, float value) +{ + oidnSetFilterFloat(filter, name, value); +} // Gets a float parameter of the filter. -OIDN_API float oidnGetFilter1f(OIDNFilter filter, const char* name); +OIDN_API float oidnGetFilterFloat(OIDNFilter filter, const char* name); + +OIDN_DEPRECATED("oidnGetFilter1f is deprecated. Use oidnGetFilterFloat instead.") +inline float oidnGetFilter1f(OIDNFilter filter, const char* name) +{ + return oidnGetFilterFloat(filter, name); +} // Sets the progress monitor callback function of the filter. -OIDN_API void oidnSetFilterProgressMonitorFunction(OIDNFilter filter, OIDNProgressMonitorFunction func, void* userPtr); +OIDN_API void oidnSetFilterProgressMonitorFunction(OIDNFilter filter, + OIDNProgressMonitorFunction func, void* userPtr); // Commits all previous changes to the filter. // Must be called before first executing the filter. @@ -209,6 +461,15 @@ OIDN_API void oidnCommitFilter(OIDNFilter filter); // Executes the filter. OIDN_API void oidnExecuteFilter(OIDNFilter filter); +// Executes the filter asynchronously. +OIDN_API void oidnExecuteFilterAsync(OIDNFilter filter); + #if defined(__cplusplus) -} +// Executes the filter of a SYCL device using the specified dependent events asynchronously, and +// optionally returns an event for completion. +OIDN_API void oidnExecuteSYCLFilterAsync(OIDNFilter filter, + const sycl::event* depEvents, int numDepEvents, + sycl::event* doneEvent); #endif + +OIDN_API_NAMESPACE_END diff --git a/thirdparty/OpenImageDenoise/include/OpenImageDenoise/oidn.hpp b/thirdparty/OpenImageDenoise/include/OpenImageDenoise/oidn.hpp index 9f95a56..de8e247 100644 --- a/thirdparty/OpenImageDenoise/include/OpenImageDenoise/oidn.hpp +++ b/thirdparty/OpenImageDenoise/include/OpenImageDenoise/oidn.hpp @@ -1,57 +1,201 @@ -// ======================================================================== // -// 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. // -// ======================================================================== // +// Copyright 2018 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 #pragma once -#include #include "oidn.h" +#include +#include +#include +#include +#include +#include +#include +#include + +OIDN_NAMESPACE_BEGIN + + // ----------------------------------------------------------------------------------------------- + // Flags helper type + // ----------------------------------------------------------------------------------------------- + + template + struct IsFlag + { + static constexpr bool value = false; + }; + + template + class Flags + { + public: + static_assert(IsFlag::value, "not a flag type"); + + using MaskType = typename std::underlying_type::type; + + constexpr Flags() noexcept : mask(0) {} + constexpr Flags(FlagT flag) noexcept : mask(static_cast(flag)) {} + constexpr Flags(const Flags& b) noexcept = default; + constexpr explicit Flags(MaskType mask) noexcept : mask(mask) {} + + constexpr bool operator !() const noexcept { return !mask; } + + constexpr Flags operator &(const Flags& b) const noexcept { return Flags(mask & b.mask); } + constexpr Flags operator |(const Flags& b) const noexcept { return Flags(mask | b.mask); } + constexpr Flags operator ^(const Flags& b) const noexcept { return Flags(mask ^ b.mask); } + + Flags& operator =(const Flags& b) noexcept = default; + + Flags& operator &=(const Flags& b) noexcept + { + mask &= b.mask; + return *this; + } + + Flags& operator |=(const Flags& b) noexcept + { + mask |= b.mask; + return *this; + } + + Flags& operator ^=(const Flags& b) noexcept + { + mask ^= b.mask; + return *this; + } + + constexpr bool operator ==(const Flags& b) const noexcept { return mask == b.mask; } + constexpr bool operator !=(const Flags& b) const noexcept { return mask != b.mask; } + + constexpr explicit operator bool() const noexcept { return mask; } + constexpr explicit operator MaskType() const noexcept { return mask; } + + private: + MaskType mask; + }; + + template + inline constexpr Flags operator &(FlagT a, const Flags& b) noexcept + { + return Flags(a) & b; + } + + template + inline constexpr Flags operator |(FlagT a, const Flags& b) noexcept + { + return Flags(a) | b; + } + + template + inline constexpr Flags operator ^(FlagT a, const Flags& b) noexcept + { + return Flags(a) ^ b; + } + + template::value, bool>::type = true> + inline constexpr Flags operator &(FlagT a, FlagT b) noexcept + { + return Flags(a) & b; + } -namespace oidn { + template::value, bool>::type = true> + inline constexpr Flags operator |(FlagT a, FlagT b) noexcept + { + return Flags(a) | b; + } - // -------------------------------------------------------------------------- + template::value, bool>::type = true> + inline constexpr Flags operator ^(FlagT a, FlagT b) noexcept + { + return Flags(a) ^ b; + } + + // ----------------------------------------------------------------------------------------------- // Buffer - // -------------------------------------------------------------------------- + // ----------------------------------------------------------------------------------------------- // Formats for images and other data stored in buffers enum class Format { Undefined = OIDN_FORMAT_UNDEFINED, - // 32-bit single-precision floating point scalar and vector formats + // 32-bit single-precision floating-point scalar and vector formats Float = OIDN_FORMAT_FLOAT, Float2 = OIDN_FORMAT_FLOAT2, Float3 = OIDN_FORMAT_FLOAT3, Float4 = OIDN_FORMAT_FLOAT4, + + // 16-bit half-precision floating-point scalar and vector formats + Half = OIDN_FORMAT_HALF, + Half2 = OIDN_FORMAT_HALF2, + Half3 = OIDN_FORMAT_HALF3, + Half4 = OIDN_FORMAT_HALF4, }; - // Access modes for mapping buffers - enum class Access + // Storage modes for buffers + enum class Storage { - Read = OIDN_ACCESS_READ, // read-only access - Write = OIDN_ACCESS_WRITE, // write-only access - ReadWrite = OIDN_ACCESS_READ_WRITE, // read and write access - WriteDiscard = OIDN_ACCESS_WRITE_DISCARD, // write-only access, previous contents discarded + Undefined = OIDN_STORAGE_UNDEFINED, + + // stored on the host, accessible by both host and device + Host = OIDN_STORAGE_HOST, + + // stored on the device, *not* accessible by the host + Device = OIDN_STORAGE_DEVICE, + + // automatically migrated between host and device, accessible by both + // *not* supported by all devices, "managedMemorySupported" device parameter should be checked + Managed = OIDN_STORAGE_MANAGED, }; + // External memory type flags + enum class ExternalMemoryTypeFlag + { + None = OIDN_EXTERNAL_MEMORY_TYPE_FLAG_NONE, + + // opaque POSIX file descriptor handle + OpaqueFD = OIDN_EXTERNAL_MEMORY_TYPE_FLAG_OPAQUE_FD, + + // file descriptor handle for a Linux dma_buf + DMABuf = OIDN_EXTERNAL_MEMORY_TYPE_FLAG_DMA_BUF, + + // NT handle + OpaqueWin32 = OIDN_EXTERNAL_MEMORY_TYPE_FLAG_OPAQUE_WIN32, + + // global share (KMT) handle + OpaqueWin32KMT = OIDN_EXTERNAL_MEMORY_TYPE_FLAG_OPAQUE_WIN32_KMT, + + // NT handle returned by IDXGIResource1::CreateSharedHandle referring to a Direct3D 11 + // texture resource + D3D11Texture = OIDN_EXTERNAL_MEMORY_TYPE_FLAG_D3D11_TEXTURE, + + // global share (KMT) handle returned by IDXGIResource::GetSharedHandle referring to a + // Direct3D 11 texture resource + D3D11TextureKMT = OIDN_EXTERNAL_MEMORY_TYPE_FLAG_D3D11_TEXTURE_KMT, + + // NT handle returned by IDXGIResource1::CreateSharedHandle referring to a Direct3D 11 + // resource + D3D11Resource = OIDN_EXTERNAL_MEMORY_TYPE_FLAG_D3D11_RESOURCE, + + // global share (KMT) handle returned by IDXGIResource::GetSharedHandle referring to a + // Direct3D 11 resource + D3D11ResourceKMT = OIDN_EXTERNAL_MEMORY_TYPE_FLAG_D3D11_RESOURCE_KMT, + + // NT handle returned by ID3D12Device::CreateSharedHandle referring to a Direct3D 12 + // heap resource + D3D12Heap = OIDN_EXTERNAL_MEMORY_TYPE_FLAG_D3D12_HEAP, + + // NT handle returned by ID3D12Device::CreateSharedHandle referring to a Direct3D 12 + // committed resource + D3D12Resource = OIDN_EXTERNAL_MEMORY_TYPE_FLAG_D3D12_RESOURCE, + }; + + template<> struct IsFlag { static constexpr bool value = true; }; + using ExternalMemoryTypeFlags = Flags; + // Buffer object with automatic reference counting class BufferRef { - private: - OIDNBuffer handle; - public: BufferRef() : handle(nullptr) {} BufferRef(OIDNBuffer handle) : handle(handle) {} @@ -62,7 +206,7 @@ namespace oidn { oidnRetainBuffer(handle); } - BufferRef(BufferRef&& other) : handle(other.handle) + BufferRef(BufferRef&& other) noexcept : handle(other.handle) { other.handle = nullptr; } @@ -80,7 +224,7 @@ namespace oidn { return *this; } - BufferRef& operator =(BufferRef&& other) + BufferRef& operator =(BufferRef&& other) noexcept { std::swap(handle, other.handle); return *this; @@ -112,34 +256,83 @@ namespace oidn { return handle != nullptr; } - // Maps a region of the buffer to host memory. - // If byteSize is 0, the maximum available amount of memory will be mapped. - void* map(Access access = Access::ReadWrite, size_t byteOffset = 0, size_t byteSize = 0) + // Releases the buffer (decrements the reference count). + void release() { - return oidnMapBuffer(handle, (OIDNAccess)access, byteOffset, byteSize); + if (handle) + { + oidnReleaseBuffer(handle); + handle = nullptr; + } } - // Unmaps a region of the buffer. - // mappedPtr must be a pointer returned by a previous call to map. - void unmap(void* mappedPtr) + // Gets the size of the buffer in bytes. + size_t getSize() const { - oidnUnmapBuffer(handle, mappedPtr); + return oidnGetBufferSize(handle); } + + // Gets the storage mode of the buffer. + Storage getStorage() const + { + return static_cast(oidnGetBufferStorage(handle)); + } + + // Gets a pointer to the buffer data, which is accessible to the device but not necessarily to + // the host as well, depending on the storage mode. Null pointer may be returned if the buffer + // is empty or getting a pointer to data with device storage is not supported by the device. + void* getData() const + { + return oidnGetBufferData(handle); + } + + // Copies data from a region of the buffer to host memory. + void read(size_t byteOffset, size_t byteSize, void* dstHostPtr) + { + oidnReadBuffer(handle, byteOffset, byteSize, dstHostPtr); + } + + // Copies data from a region of the buffer to host memory asynchronously. + void readAsync(size_t byteOffset, size_t byteSize, void* dstHostPtr) + { + oidnReadBufferAsync(handle, byteOffset, byteSize, dstHostPtr); + } + + // Copies data to a region of the buffer from host memory. + void write(size_t byteOffset, size_t byteSize, const void* srcHostPtr) + { + oidnWriteBuffer(handle, byteOffset, byteSize, srcHostPtr); + } + + // Copies data to a region of the buffer from host memory asynchronously. + void writeAsync(size_t byteOffset, size_t byteSize, const void* srcHostPtr) + { + oidnWriteBufferAsync(handle, byteOffset, byteSize, srcHostPtr); + } + + private: + OIDNBuffer handle; }; - // -------------------------------------------------------------------------- + // ----------------------------------------------------------------------------------------------- // Filter - // -------------------------------------------------------------------------- + // ----------------------------------------------------------------------------------------------- + + // Filter quality/performance modes + enum class Quality + { + Default = OIDN_QUALITY_DEFAULT, // default quality + + Balanced = OIDN_QUALITY_BALANCED, // balanced quality/performance (for interactive/real-time rendering) + High = OIDN_QUALITY_HIGH, // high quality (for final-frame rendering) + }; // Progress monitor callback function - typedef bool (*ProgressMonitorFunction)(void* userPtr, double n); + using ProgressMonitorFunction = OIDNProgressMonitorFunction; // Filter object with automatic reference counting class FilterRef { - private: - OIDNFilter handle; - public: FilterRef() : handle(nullptr) {} FilterRef(OIDNFilter handle) : handle(handle) {} @@ -150,7 +343,7 @@ namespace oidn { oidnRetainFilter(handle); } - FilterRef(FilterRef&& other) : handle(other.handle) + FilterRef(FilterRef&& other) noexcept : handle(other.handle) { other.handle = nullptr; } @@ -168,7 +361,7 @@ namespace oidn { return *this; } - FilterRef& operator =(FilterRef&& other) + FilterRef& operator =(FilterRef&& other) noexcept { std::swap(handle, other.handle); return *this; @@ -200,60 +393,111 @@ namespace oidn { return handle != nullptr; } - // Sets an image parameter of the filter (stored in a buffer). + // Releases the filter (decrements the reference count). + void release() + { + if (handle) + { + oidnReleaseFilter(handle); + handle = nullptr; + } + } + + // Sets an image parameter of the filter with data stored in a buffer. void setImage(const char* name, const BufferRef& buffer, Format format, size_t width, size_t height, size_t byteOffset = 0, - size_t bytePixelStride = 0, size_t byteRowStride = 0) + size_t pixelByteStride = 0, size_t rowByteStride = 0) { oidnSetFilterImage(handle, name, - buffer.getHandle(), (OIDNFormat)format, + buffer.getHandle(), static_cast(format), width, height, byteOffset, - bytePixelStride, byteRowStride); + pixelByteStride, rowByteStride); } - // Sets an image parameter of the filter (owned by the user). + // Sets an image parameter of the filter with data owned by the user and accessible to the device. void setImage(const char* name, - void* ptr, Format format, + void* devPtr, Format format, size_t width, size_t height, size_t byteOffset = 0, - size_t bytePixelStride = 0, size_t byteRowStride = 0) + size_t pixelByteStride = 0, size_t rowByteStride = 0) { oidnSetSharedFilterImage(handle, name, - ptr, (OIDNFormat)format, + devPtr, static_cast(format), width, height, byteOffset, - bytePixelStride, byteRowStride); + pixelByteStride, rowByteStride); + } + + // Unsets an image parameter of the filter that was previously set. + void unsetImage(const char* name) + { + oidnUnsetFilterImage(handle, name); + } + + OIDN_DEPRECATED("removeImage is deprecated. Use unsetImage instead.") + void removeImage(const char* name) + { + oidnUnsetFilterImage(handle, name); + } + + // Sets an opaque data parameter of the filter owned by the user and accessible to the host. + void setData(const char* name, void* hostPtr, size_t byteSize) + { + oidnSetSharedFilterData(handle, name, hostPtr, byteSize); + } + + // Notifies the filter that the contents of an opaque data parameter has been changed. + void updateData(const char* name) + { + oidnUpdateFilterData(handle, name); + } + + // Unsets an opaque data parameter of the filter that was previously set. + void unsetData(const char* name) + { + oidnUnsetFilterData(handle, name); + } + + OIDN_DEPRECATED("removeData is deprecated. Use unsetData instead.") + void removeData(const char* name) + { + oidnUnsetFilterData(handle, name); } // Sets a boolean parameter of the filter. void set(const char* name, bool value) { - oidnSetFilter1b(handle, name, value); + oidnSetFilterBool(handle, name, value); } // Sets an integer parameter of the filter. void set(const char* name, int value) { - oidnSetFilter1i(handle, name, value); + oidnSetFilterInt(handle, name, value); + } + + void set(const char* name, Quality value) + { + oidnSetFilterInt(handle, name, static_cast(value)); } // Sets a float parameter of the filter. void set(const char* name, float value) { - oidnSetFilter1f(handle, name, value); + oidnSetFilterFloat(handle, name, value); } // Gets a parameter of the filter. template - T get(const char* name); + T get(const char* name) const; // Sets the progress monitor callback function of the filter. void setProgressMonitorFunction(ProgressMonitorFunction func, void* userPtr = nullptr) { - oidnSetFilterProgressMonitorFunction(handle, (OIDNProgressMonitorFunction)func, userPtr); + oidnSetFilterProgressMonitorFunction(handle, func, userPtr); } // Commits all previous changes to the filter. @@ -267,39 +511,65 @@ namespace oidn { { oidnExecuteFilter(handle); } + + // Executes the filter asynchronously. + void executeAsync() + { + oidnExecuteFilterAsync(handle); + } + + #if defined(SYCL_LANGUAGE_VERSION) + // Executes the filter of a SYCL device using the specified dependent events asynchronously, and + // optionally returns an event for completion. + sycl::event executeAsync(const std::vector& depEvents) + { + sycl::event doneEvent; + oidnExecuteSYCLFilterAsync(handle, depEvents.data(), static_cast(depEvents.size()), &doneEvent); + return doneEvent; + } + #endif + + private: + OIDNFilter handle; }; - // Gets a boolean parameter of the filter. template<> - inline bool FilterRef::get(const char* name) + inline bool FilterRef::get(const char* name) const + { + return oidnGetFilterBool(handle, name); + } + + template<> + inline int FilterRef::get(const char* name) const { - return oidnGetFilter1b(handle, name); + return oidnGetFilterInt(handle, name); } - // Gets an integer parameter of the filter. template<> - inline int FilterRef::get(const char* name) + inline Quality FilterRef::get(const char* name) const { - return oidnGetFilter1i(handle, name); + return static_cast(oidnGetFilterInt(handle, name)); } - // Gets a float parameter of the filter. template<> - inline float FilterRef::get(const char* name) + inline float FilterRef::get(const char* name) const { - return oidnGetFilter1f(handle, name); + return oidnGetFilterFloat(handle, name); } - // -------------------------------------------------------------------------- + // ----------------------------------------------------------------------------------------------- // Device - // -------------------------------------------------------------------------- + // ----------------------------------------------------------------------------------------------- // Device types enum class DeviceType { Default = OIDN_DEVICE_TYPE_DEFAULT, // select device automatically - CPU = OIDN_DEVICE_TYPE_CPU, // CPU device + CPU = OIDN_DEVICE_TYPE_CPU, // CPU device + SYCL = OIDN_DEVICE_TYPE_SYCL, // SYCL device + CUDA = OIDN_DEVICE_TYPE_CUDA, // CUDA device + HIP = OIDN_DEVICE_TYPE_HIP, // HIP device }; // Error codes @@ -317,12 +587,29 @@ namespace oidn { // Error callback function typedef void (*ErrorFunction)(void* userPtr, Error code, const char* message); + // Opaque universally unique identifier (UUID) of a physical device + struct UUID + { + uint8_t bytes[OIDN_UUID_SIZE]; + }; + + // Opaque locally unique identifier (LUID) of a physical device + struct LUID + { + union + { + struct + { + uint32_t low; + int32_t high; + }; + uint8_t bytes[OIDN_LUID_SIZE]; + }; + }; + // Device object with automatic reference counting class DeviceRef { - private: - OIDNDevice handle; - public: DeviceRef() : handle(nullptr) {} DeviceRef(OIDNDevice handle) : handle(handle) {} @@ -333,7 +620,7 @@ namespace oidn { oidnRetainDevice(handle); } - DeviceRef(DeviceRef&& other) : handle(other.handle) + DeviceRef(DeviceRef&& other) noexcept : handle(other.handle) { other.handle = nullptr; } @@ -351,7 +638,7 @@ namespace oidn { return *this; } - DeviceRef& operator =(DeviceRef&& other) + DeviceRef& operator =(DeviceRef&& other) noexcept { std::swap(handle, other.handle); return *this; @@ -383,40 +670,57 @@ namespace oidn { return handle != nullptr; } + // Releases the device (decrements the reference count). + void release() + { + if (handle) + { + oidnReleaseDevice(handle); + handle = nullptr; + } + } + // Sets a boolean parameter of the device. void set(const char* name, bool value) { - oidnSetDevice1b(handle, name, value); + oidnSetDeviceBool(handle, name, value); } // Sets an integer parameter of the device. void set(const char* name, int value) { - oidnSetDevice1i(handle, name, value); + oidnSetDeviceInt(handle, name, value); + } + + // Sets an unsigned integer parameter of the device. + void set(const char* name, unsigned int value) + { + oidnSetDeviceUInt(handle, name, value); } // Gets a parameter of the device. template - T get(const char* name); + T get(const char* name) const; // Sets the error callback function of the device. void setErrorFunction(ErrorFunction func, void* userPtr = nullptr) { - oidnSetDeviceErrorFunction(handle, (OIDNErrorFunction)func, userPtr); + oidnSetDeviceErrorFunction(handle, reinterpret_cast(func), userPtr); } // Returns the first unqueried error code and clears the stored error. - // Can be called for a null device as well to check why a device creation failed. + // Can be called for a null device as well to check for global errors (e.g. why a device + // creation or physical device query has failed. Error getError() { - return (Error)oidnGetDeviceError(handle, nullptr); + return static_cast(oidnGetDeviceError(handle, nullptr)); } // Returns the first unqueried error code and string message, and clears the stored error. // Can be called for a null device as well to check why a device creation failed. Error getError(const char*& outMessage) { - return (Error)oidnGetDeviceError(handle, &outMessage); + return static_cast(oidnGetDeviceError(handle, &outMessage)); } // Commits all previous changes to the device. @@ -426,43 +730,299 @@ namespace oidn { oidnCommitDevice(handle); } - // Creates a new buffer (data allocated and owned by the device). - BufferRef newBuffer(size_t byteSize) + // Waits for all asynchronous operations running on the device to complete. + void sync() + { + oidnSyncDevice(handle); + } + + // Creates a buffer accessible to both the host and device. + BufferRef newBuffer(size_t byteSize) const { return oidnNewBuffer(handle, byteSize); } - // Creates a new shared buffer (data allocated and owned by the user). - BufferRef newBuffer(void* ptr, size_t byteSize) + // Creates a buffer with the specified storage mode. + BufferRef newBuffer(size_t byteSize, Storage storage) const + { + return oidnNewBufferWithStorage(handle, byteSize, static_cast(storage)); + } + + // Creates a shared buffer from memory allocated and owned by the user and accessible to the + // device. + BufferRef newBuffer(void* ptr, size_t byteSize) const { return oidnNewSharedBuffer(handle, ptr, byteSize); } - // Creates a new filter of the specified type (e.g. "RT"). - FilterRef newFilter(const char* type) + // Creates a shared buffer by importing external memory from a POSIX file descriptor. + BufferRef newBuffer(ExternalMemoryTypeFlag fdType, int fd, size_t byteSize) const + { + return oidnNewSharedBufferFromFD( + handle, static_cast(fdType), fd, byteSize); + } + + // Creates a shared buffer by importing external memory from a Win32 handle. + BufferRef newBuffer(ExternalMemoryTypeFlag handleType, void* handle, const void* name, size_t byteSize) const + { + return oidnNewSharedBufferFromWin32Handle( + this->handle, static_cast(handleType), handle, name, byteSize); + } + + // Creates a filter of the specified type (e.g. "RT"). + FilterRef newFilter(const char* type) const { return oidnNewFilter(handle, type); } + + private: + OIDNDevice handle; }; - // Gets a boolean parameter of the device. template<> - inline bool DeviceRef::get(const char* name) + inline bool DeviceRef::get(const char* name) const + { + return oidnGetDeviceBool(handle, name); + } + + template<> + inline int DeviceRef::get(const char* name) const { - return oidnGetDevice1b(handle, name); + return oidnGetDeviceInt(handle, name); } - // Gets an integer parameter of the device (e.g. "version"). template<> - inline int DeviceRef::get(const char* name) + inline unsigned int DeviceRef::get(const char* name) const { - return oidnGetDevice1i(handle, name); + return oidnGetDeviceUInt(handle, name); } - // Creates a new device. + template<> + inline DeviceType DeviceRef::get(const char* name) const + { + return static_cast(oidnGetDeviceInt(handle, name)); + } + + template<> + inline ExternalMemoryTypeFlags DeviceRef::get(const char* name) const + { + return ExternalMemoryTypeFlags(oidnGetDeviceInt(handle, name)); + } + + // Returns the first unqueried per-thread global error code and clears the stored error. + inline Error getError() + { + return static_cast(oidnGetDeviceError(nullptr, nullptr)); + } + + // Returns the first unqueried per-thread global error code and string message, and clears the + // stored error. + inline Error getError(const char*& outMessage) + { + return static_cast(oidnGetDeviceError(nullptr, &outMessage)); + } + + // Creates a device of the specified type. inline DeviceRef newDevice(DeviceType type = DeviceType::Default) { - return DeviceRef(oidnNewDevice((OIDNDeviceType)type)); + return DeviceRef(oidnNewDevice(static_cast(type))); + } + + // Creates a device from a physical device specified by its ID (0 to getNumPhysicalDevices()-1). + inline DeviceRef newDevice(int physicalDeviceID) + { + return DeviceRef(oidnNewDeviceByID(physicalDeviceID)); + } + + // Creates a device from a physical device specified by its UUID. + inline DeviceRef newDevice(const UUID& uuid) + { + return DeviceRef(oidnNewDeviceByUUID(uuid.bytes)); + } + + // Creates a device from a physical device specified by its LUID. + inline DeviceRef newDevice(const LUID& luid) + { + return DeviceRef(oidnNewDeviceByLUID(luid.bytes)); + } + + // Creates a device from a physical device specified by its PCI address. + inline DeviceRef newDevice(int pciDomain, int pciBus, int pciDevice, int pciFunction) + { + return DeviceRef(oidnNewDeviceByPCIAddress(pciDomain, pciBus, pciDevice, pciFunction)); + } + +#if defined(SYCL_LANGUAGE_VERSION) + // Creates a device from the specified SYCL queue. + inline DeviceRef newSYCLDevice(const sycl::queue& queue) + { + return DeviceRef(oidnNewSYCLDevice(&queue, 1)); + } + + // Creates a device from the specified list of SYCL queues. + // The queues should belong to different SYCL sub-devices (Xe Stack/Tile) of the same SYCL + // root-device (GPU). + inline DeviceRef newSYCLDevice(const std::vector& queues) + { + return DeviceRef(oidnNewSYCLDevice(queues.data(), static_cast(queues.size()))); + } +#endif + + // Creates a device from the specified CUDA device ID (negative value maps to the current device) + // and stream. + inline DeviceRef newCUDADevice(int deviceID, cudaStream_t stream) + { + return DeviceRef(oidnNewCUDADevice(&deviceID, &stream, 1)); + } + + // Creates a device from the specified pairs of CUDA device IDs (negative ID corresponds to the + // current device) and streams (null stream corresponds to the default stream). + // Currently only one device ID/stream is supported. + inline DeviceRef newCUDADevice(const std::vector& deviceIDs, + const std::vector& streams) + { + assert(deviceIDs.size() == streams.size()); + return DeviceRef(oidnNewCUDADevice(deviceIDs.data(), streams.data(), + static_cast(streams.size()))); + } + + // Creates a device from the specified HIP device ID (negative ID corresponds to the current + // device) and stream (null stream corresponds to the default stream). + inline DeviceRef newHIPDevice(int deviceID, hipStream_t stream) + { + return DeviceRef(oidnNewHIPDevice(&deviceID, &stream, 1)); + } + + // Creates a device from the specified pairs of HIP device IDs (negative ID corresponds to the + // current device) and streams (null stream corresponds to the default stream). + // Currently only one device ID/stream is supported. + inline DeviceRef newHIPDevice(const std::vector& deviceIDs, + const std::vector& streams) + { + assert(deviceIDs.size() == streams.size()); + return DeviceRef(oidnNewHIPDevice(deviceIDs.data(), streams.data(), + static_cast(streams.size()))); + } + + // ----------------------------------------------------------------------------------------------- + // Physical Device + // ----------------------------------------------------------------------------------------------- + + class PhysicalDeviceRef + { + public: + PhysicalDeviceRef() : id(-1) {} + PhysicalDeviceRef(int id) : id(id) {} + + PhysicalDeviceRef& operator =(int other) + { + id = other; + return *this; + } + + int getID() const + { + return id; + } + + operator bool() const + { + return id >= 0; + } + + // Gets a paramter of the physical device. + template + T get(const char* name) const; + + // Gets an opaque data parameter of the physical device. + std::pair getData(const char* name) const + { + size_t byteSize = 0; + const void* ptr = oidnGetPhysicalDeviceData(id, name, &byteSize); + return {ptr, byteSize}; + } + + // Creates a device from the physical device. + DeviceRef newDevice() + { + return DeviceRef(oidnNewDeviceByID(id)); + } + + private: + int id; + }; + + // Returns the number of supported physical devices. + inline int getNumPhysicalDevices() + { + return oidnGetNumPhysicalDevices(); + } + + template<> + inline bool PhysicalDeviceRef::get(const char* name) const + { + return oidnGetPhysicalDeviceBool(id, name); + } + + template<> + inline int PhysicalDeviceRef::get(const char* name) const + { + return oidnGetPhysicalDeviceInt(id, name); + } + + template<> + inline unsigned int PhysicalDeviceRef::get(const char* name) const + { + return oidnGetPhysicalDeviceUInt(id, name); + } + + template<> + inline DeviceType PhysicalDeviceRef::get(const char* name) const + { + return static_cast(oidnGetPhysicalDeviceInt(id, name)); + } + + template<> + inline const char* PhysicalDeviceRef::get(const char* name) const + { + return oidnGetPhysicalDeviceString(id, name); + } + + template<> + inline std::string PhysicalDeviceRef::get(const char* name) const + { + const char* str = oidnGetPhysicalDeviceString(id, name); + return str ? str : ""; + } + + template<> + inline UUID PhysicalDeviceRef::get(const char* name) const + { + UUID uuid{}; + auto data = getData(name); + if (data.first != nullptr) + { + if (data.second == sizeof(uuid.bytes)) + std::memcpy(uuid.bytes, data.first, sizeof(uuid.bytes)); + else + getData(""); // invoke an error + } + return uuid; + } + + template<> + inline LUID PhysicalDeviceRef::get(const char* name) const + { + LUID luid{}; + auto data = getData(name); + if (data.first != nullptr) + { + if (data.second == sizeof(luid.bytes)) + std::memcpy(luid.bytes, data.first, sizeof(luid.bytes)); + else + getData(""); // invoke an error + } + return luid; } -} // namespace oidn +OIDN_NAMESPACE_END diff --git a/thirdparty/OpenImageDenoise/include/OpenImageDenoise/version.h b/thirdparty/OpenImageDenoise/include/OpenImageDenoise/version.h deleted file mode 100644 index 66b347c..0000000 --- a/thirdparty/OpenImageDenoise/include/OpenImageDenoise/version.h +++ /dev/null @@ -1,23 +0,0 @@ -// ======================================================================== // -// 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 - -#define OIDN_VERSION_MAJOR 1 -#define OIDN_VERSION_MINOR 1 -#define OIDN_VERSION_PATCH 0 -#define OIDN_VERSION 10100 -#define OIDN_VERSION_STRING "1.1.0" diff --git a/thirdparty/OpenImageDenoise/include/OpenImageDenoise/version.h.in b/thirdparty/OpenImageDenoise/include/OpenImageDenoise/version.h.in deleted file mode 100644 index 69ee61b..0000000 --- a/thirdparty/OpenImageDenoise/include/OpenImageDenoise/version.h.in +++ /dev/null @@ -1,23 +0,0 @@ -// ======================================================================== // -// 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 - -#define OIDN_VERSION_MAJOR @OIDN_VERSION_MAJOR@ -#define OIDN_VERSION_MINOR @OIDN_VERSION_MINOR@ -#define OIDN_VERSION_PATCH @OIDN_VERSION_PATCH@ -#define OIDN_VERSION @OIDN_VERSION_NUMBER@ -#define OIDN_VERSION_STRING "@OIDN_VERSION_MAJOR@.@OIDN_VERSION_MINOR@.@OIDN_VERSION_PATCH@@OIDN_VERSION_NOTE@" diff --git a/thirdparty/OpenImageDenoise/lib/OpenImageDenoise.lib b/thirdparty/OpenImageDenoise/lib/OpenImageDenoise.lib index 87ecf5c..7853ef8 100644 Binary files a/thirdparty/OpenImageDenoise/lib/OpenImageDenoise.lib and b/thirdparty/OpenImageDenoise/lib/OpenImageDenoise.lib differ diff --git a/thirdparty/OpenImageDenoise/lib/OpenImageDenoise_core.lib b/thirdparty/OpenImageDenoise/lib/OpenImageDenoise_core.lib new file mode 100644 index 0000000..f06cad5 Binary files /dev/null and b/thirdparty/OpenImageDenoise/lib/OpenImageDenoise_core.lib differ diff --git a/thirdparty/OpenImageDenoise/lib/cmake/OpenImageDenoise-2.1.0/OpenImageDenoiseConfig.cmake b/thirdparty/OpenImageDenoise/lib/cmake/OpenImageDenoise-2.1.0/OpenImageDenoiseConfig.cmake new file mode 100644 index 0000000..ccacd2b --- /dev/null +++ b/thirdparty/OpenImageDenoise/lib/cmake/OpenImageDenoise-2.1.0/OpenImageDenoiseConfig.cmake @@ -0,0 +1,47 @@ +## Copyright 2023 Intel Corporation +## SPDX-License-Identifier: Apache-2.0 + + +####### Expanded from @PACKAGE_INIT@ by configure_package_config_file() ####### +####### Any changes to this file will be overwritten by the next CMake run #### +####### The input file was Config.cmake.in ######## + +get_filename_component(PACKAGE_PREFIX_DIR "${CMAKE_CURRENT_LIST_DIR}/../../../" ABSOLUTE) + +macro(set_and_check _var _file) + set(${_var} "${_file}") + if(NOT EXISTS "${_file}") + message(FATAL_ERROR "File or directory ${_file} referenced by variable ${_var} does not exist !") + endif() +endmacro() + +macro(check_required_components _NAME) + foreach(comp ${${_NAME}_FIND_COMPONENTS}) + if(NOT ${_NAME}_${comp}_FOUND) + if(${_NAME}_FIND_REQUIRED_${comp}) + set(${_NAME}_FOUND FALSE) + endif() + endif() + endforeach() +endmacro() + +#################################################################################### + +set(OIDN_DEVICE_CPU ON) +set(OIDN_DEVICE_SYCL OFF) +set(OIDN_DEVICE_CUDA ON) +set(OIDN_DEVICE_HIP OFF) + +set(OIDN_FILTER_RT ON) +set(OIDN_FILTER_RTLIGHTMAP ON) + +set(OIDN_STATIC_LIB OFF) + +if(OIDN_STATIC_LIB AND OIDN_DEVICE_CPU) + include(CMakeFindDependencyMacro) + find_dependency(TBB) +endif() + +include("${CMAKE_CURRENT_LIST_DIR}/OpenImageDenoiseTargets.cmake") + +check_required_components(OpenImageDenoise) diff --git a/thirdparty/OpenImageDenoise/lib/cmake/OpenImageDenoise-2.1.0/OpenImageDenoiseConfigVersion.cmake b/thirdparty/OpenImageDenoise/lib/cmake/OpenImageDenoise-2.1.0/OpenImageDenoiseConfigVersion.cmake new file mode 100644 index 0000000..a700e48 --- /dev/null +++ b/thirdparty/OpenImageDenoise/lib/cmake/OpenImageDenoise-2.1.0/OpenImageDenoiseConfigVersion.cmake @@ -0,0 +1,65 @@ +# This is a basic version file for the Config-mode of find_package(). +# It is used by write_basic_package_version_file() as input file for configure_file() +# to create a version-file which can be installed along a config.cmake file. +# +# The created file sets PACKAGE_VERSION_EXACT if the current version string and +# the requested version string are exactly the same and it sets +# PACKAGE_VERSION_COMPATIBLE if the current version is >= requested version, +# but only if the requested major version is the same as the current one. +# The variable CVF_VERSION must be set before calling configure_file(). + + +set(PACKAGE_VERSION "2.1.0") + +if(PACKAGE_VERSION VERSION_LESS PACKAGE_FIND_VERSION) + set(PACKAGE_VERSION_COMPATIBLE FALSE) +else() + + if("2.1.0" MATCHES "^([0-9]+)\\.") + set(CVF_VERSION_MAJOR "${CMAKE_MATCH_1}") + if(NOT CVF_VERSION_MAJOR VERSION_EQUAL 0) + string(REGEX REPLACE "^0+" "" CVF_VERSION_MAJOR "${CVF_VERSION_MAJOR}") + endif() + else() + set(CVF_VERSION_MAJOR "2.1.0") + endif() + + if(PACKAGE_FIND_VERSION_RANGE) + # both endpoints of the range must have the expected major version + math (EXPR CVF_VERSION_MAJOR_NEXT "${CVF_VERSION_MAJOR} + 1") + if (NOT PACKAGE_FIND_VERSION_MIN_MAJOR STREQUAL CVF_VERSION_MAJOR + OR ((PACKAGE_FIND_VERSION_RANGE_MAX STREQUAL "INCLUDE" AND NOT PACKAGE_FIND_VERSION_MAX_MAJOR STREQUAL CVF_VERSION_MAJOR) + OR (PACKAGE_FIND_VERSION_RANGE_MAX STREQUAL "EXCLUDE" AND NOT PACKAGE_FIND_VERSION_MAX VERSION_LESS_EQUAL CVF_VERSION_MAJOR_NEXT))) + set(PACKAGE_VERSION_COMPATIBLE FALSE) + elseif(PACKAGE_FIND_VERSION_MIN_MAJOR STREQUAL CVF_VERSION_MAJOR + AND ((PACKAGE_FIND_VERSION_RANGE_MAX STREQUAL "INCLUDE" AND PACKAGE_VERSION VERSION_LESS_EQUAL PACKAGE_FIND_VERSION_MAX) + OR (PACKAGE_FIND_VERSION_RANGE_MAX STREQUAL "EXCLUDE" AND PACKAGE_VERSION VERSION_LESS PACKAGE_FIND_VERSION_MAX))) + set(PACKAGE_VERSION_COMPATIBLE TRUE) + else() + set(PACKAGE_VERSION_COMPATIBLE FALSE) + endif() + else() + if(PACKAGE_FIND_VERSION_MAJOR STREQUAL CVF_VERSION_MAJOR) + set(PACKAGE_VERSION_COMPATIBLE TRUE) + else() + set(PACKAGE_VERSION_COMPATIBLE FALSE) + endif() + + if(PACKAGE_FIND_VERSION STREQUAL PACKAGE_VERSION) + set(PACKAGE_VERSION_EXACT TRUE) + endif() + endif() +endif() + + +# if the installed or the using project don't have CMAKE_SIZEOF_VOID_P set, ignore it: +if("${CMAKE_SIZEOF_VOID_P}" STREQUAL "" OR "8" STREQUAL "") + return() +endif() + +# check that the installed version has the same 32/64bit-ness as the one which is currently searching: +if(NOT CMAKE_SIZEOF_VOID_P STREQUAL "8") + math(EXPR installedBits "8 * 8") + set(PACKAGE_VERSION "${PACKAGE_VERSION} (${installedBits}bit)") + set(PACKAGE_VERSION_UNSUITABLE TRUE) +endif() diff --git a/thirdparty/OpenImageDenoise/lib/cmake/OpenImageDenoise-2.1.0/OpenImageDenoiseTargets-release.cmake b/thirdparty/OpenImageDenoise/lib/cmake/OpenImageDenoise-2.1.0/OpenImageDenoiseTargets-release.cmake new file mode 100644 index 0000000..90d58d2 --- /dev/null +++ b/thirdparty/OpenImageDenoise/lib/cmake/OpenImageDenoise-2.1.0/OpenImageDenoiseTargets-release.cmake @@ -0,0 +1,30 @@ +#---------------------------------------------------------------- +# Generated CMake target import file for configuration "Release". +#---------------------------------------------------------------- + +# Commands may need to know the format version. +set(CMAKE_IMPORT_FILE_VERSION 1) + +# Import target "OpenImageDenoise_core" for configuration "Release" +set_property(TARGET OpenImageDenoise_core APPEND PROPERTY IMPORTED_CONFIGURATIONS RELEASE) +set_target_properties(OpenImageDenoise_core PROPERTIES + IMPORTED_IMPLIB_RELEASE "${_IMPORT_PREFIX}/lib/OpenImageDenoise_core.lib" + IMPORTED_LOCATION_RELEASE "${_IMPORT_PREFIX}/bin/OpenImageDenoise_core.dll" + ) + +list(APPEND _cmake_import_check_targets OpenImageDenoise_core ) +list(APPEND _cmake_import_check_files_for_OpenImageDenoise_core "${_IMPORT_PREFIX}/lib/OpenImageDenoise_core.lib" "${_IMPORT_PREFIX}/bin/OpenImageDenoise_core.dll" ) + +# Import target "OpenImageDenoise" for configuration "Release" +set_property(TARGET OpenImageDenoise APPEND PROPERTY IMPORTED_CONFIGURATIONS RELEASE) +set_target_properties(OpenImageDenoise PROPERTIES + IMPORTED_IMPLIB_RELEASE "${_IMPORT_PREFIX}/lib/OpenImageDenoise.lib" + IMPORTED_LINK_DEPENDENT_LIBRARIES_RELEASE "OpenImageDenoise_core" + IMPORTED_LOCATION_RELEASE "${_IMPORT_PREFIX}/bin/OpenImageDenoise.dll" + ) + +list(APPEND _cmake_import_check_targets OpenImageDenoise ) +list(APPEND _cmake_import_check_files_for_OpenImageDenoise "${_IMPORT_PREFIX}/lib/OpenImageDenoise.lib" "${_IMPORT_PREFIX}/bin/OpenImageDenoise.dll" ) + +# Commands beyond this point should not need to know the version. +set(CMAKE_IMPORT_FILE_VERSION) diff --git a/thirdparty/OpenImageDenoise/lib/cmake/OpenImageDenoise-2.1.0/OpenImageDenoiseTargets.cmake b/thirdparty/OpenImageDenoise/lib/cmake/OpenImageDenoise-2.1.0/OpenImageDenoiseTargets.cmake new file mode 100644 index 0000000..8d36ac3 --- /dev/null +++ b/thirdparty/OpenImageDenoise/lib/cmake/OpenImageDenoise-2.1.0/OpenImageDenoiseTargets.cmake @@ -0,0 +1,119 @@ +# Generated by CMake + +if("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" LESS 2.8) + message(FATAL_ERROR "CMake >= 2.8.0 required") +endif() +if(CMAKE_VERSION VERSION_LESS "2.8.3") + message(FATAL_ERROR "CMake >= 2.8.3 required") +endif() +cmake_policy(PUSH) +cmake_policy(VERSION 2.8.3...3.25) +#---------------------------------------------------------------- +# Generated CMake target import file. +#---------------------------------------------------------------- + +# Commands may need to know the format version. +set(CMAKE_IMPORT_FILE_VERSION 1) + +# Protect against multiple inclusion, which would fail when already imported targets are added once more. +set(_cmake_targets_defined "") +set(_cmake_targets_not_defined "") +set(_cmake_expected_targets "") +foreach(_cmake_expected_target IN ITEMS OpenImageDenoise_weights OpenImageDenoise_common OpenImageDenoise_core OpenImageDenoise) + list(APPEND _cmake_expected_targets "${_cmake_expected_target}") + if(TARGET "${_cmake_expected_target}") + list(APPEND _cmake_targets_defined "${_cmake_expected_target}") + else() + list(APPEND _cmake_targets_not_defined "${_cmake_expected_target}") + endif() +endforeach() +unset(_cmake_expected_target) +if(_cmake_targets_defined STREQUAL _cmake_expected_targets) + unset(_cmake_targets_defined) + unset(_cmake_targets_not_defined) + unset(_cmake_expected_targets) + unset(CMAKE_IMPORT_FILE_VERSION) + cmake_policy(POP) + return() +endif() +if(NOT _cmake_targets_defined STREQUAL "") + string(REPLACE ";" ", " _cmake_targets_defined_text "${_cmake_targets_defined}") + string(REPLACE ";" ", " _cmake_targets_not_defined_text "${_cmake_targets_not_defined}") + message(FATAL_ERROR "Some (but not all) targets in this export set were already defined.\nTargets Defined: ${_cmake_targets_defined_text}\nTargets not yet defined: ${_cmake_targets_not_defined_text}\n") +endif() +unset(_cmake_targets_defined) +unset(_cmake_targets_not_defined) +unset(_cmake_expected_targets) + + +# Compute the installation prefix relative to this file. +get_filename_component(_IMPORT_PREFIX "${CMAKE_CURRENT_LIST_FILE}" PATH) +get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH) +get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH) +get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH) +if(_IMPORT_PREFIX STREQUAL "/") + set(_IMPORT_PREFIX "") +endif() + +# Create imported target OpenImageDenoise_weights +add_library(OpenImageDenoise_weights INTERFACE IMPORTED) + +# Create imported target OpenImageDenoise_common +add_library(OpenImageDenoise_common INTERFACE IMPORTED) + +# Create imported target OpenImageDenoise_core +add_library(OpenImageDenoise_core SHARED IMPORTED) + +set_target_properties(OpenImageDenoise_core PROPERTIES + INTERFACE_LINK_LIBRARIES "OpenImageDenoise_common" +) + +# Create imported target OpenImageDenoise +add_library(OpenImageDenoise SHARED IMPORTED) + +set_target_properties(OpenImageDenoise PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES "${_IMPORT_PREFIX}/include" +) + +if(CMAKE_VERSION VERSION_LESS 3.0.0) + message(FATAL_ERROR "This file relies on consumers using CMake 3.0.0 or greater.") +endif() + +# Load information for each installed configuration. +file(GLOB _cmake_config_files "${CMAKE_CURRENT_LIST_DIR}/OpenImageDenoiseTargets-*.cmake") +foreach(_cmake_config_file IN LISTS _cmake_config_files) + include("${_cmake_config_file}") +endforeach() +unset(_cmake_config_file) +unset(_cmake_config_files) + +# Cleanup temporary variables. +set(_IMPORT_PREFIX) + +# Loop over all imported files and verify that they actually exist +foreach(_cmake_target IN LISTS _cmake_import_check_targets) + foreach(_cmake_file IN LISTS "_cmake_import_check_files_for_${_cmake_target}") + if(NOT EXISTS "${_cmake_file}") + message(FATAL_ERROR "The imported target \"${_cmake_target}\" references the file + \"${_cmake_file}\" +but this file does not exist. Possible reasons include: +* The file was deleted, renamed, or moved to another location. +* An install or uninstall procedure did not complete successfully. +* The installation package was faulty and contained + \"${CMAKE_CURRENT_LIST_FILE}\" +but not all the files it references. +") + endif() + endforeach() + unset(_cmake_file) + unset("_cmake_import_check_files_for_${_cmake_target}") +endforeach() +unset(_cmake_target) +unset(_cmake_import_check_targets) + +# This file does not depend on other imported targets which have +# been exported from the same project but in a separate export set. + +# Commands beyond this point should not need to know the version. +set(CMAKE_IMPORT_FILE_VERSION) +cmake_policy(POP) diff --git a/thirdparty/OpenImageDenoise/lib/common.lib b/thirdparty/OpenImageDenoise/lib/common.lib deleted file mode 100644 index 6729fa5..0000000 Binary files a/thirdparty/OpenImageDenoise/lib/common.lib and /dev/null differ diff --git a/thirdparty/OpenImageDenoise/lib/mkldnn.lib b/thirdparty/OpenImageDenoise/lib/mkldnn.lib deleted file mode 100644 index 05d5901..0000000 Binary files a/thirdparty/OpenImageDenoise/lib/mkldnn.lib and /dev/null differ diff --git a/thirdparty/OpenImageDenoise/share/doc/OpenImageDenoise/CHANGELOG.md b/thirdparty/OpenImageDenoise/share/doc/OpenImageDenoise/CHANGELOG.md new file mode 100644 index 0000000..dc41741 --- /dev/null +++ b/thirdparty/OpenImageDenoise/share/doc/OpenImageDenoise/CHANGELOG.md @@ -0,0 +1,257 @@ +Version History +--------------- + +### Changes in v2.1.0: + +- Added support for denoising 1-channel (e.g. alpha) and 2-channel images +- Added support for arbitrary combinations of input image data types + (e.g. `OIDN_FORMAT_FLOAT3` for `color` but `OIDN_FORMAT_HALF3` for `albedo`) +- Improved performance for most dedicated GPU architectures +- Re-added `OIDN_STATIC_LIB` CMake option which enables building as a static + (CPU support only) or a hybrid static/shared (GPU support as well) library +- Added `release()` method to C++ API objects (`DeviceRef`, `BufferRef`, + `FilterRef`) +- Fixed possible crash when releasing GPU devices, buffers or filters +- Fixed possible crash at process exit for some SYCL runtime versions +- Fixed image quality inconsistency on Intel integrated GPUs, but at the cost + of some performance loss +- Fixed future Windows driver compatibility for Intel integrated GPUs +- Fixed rare output corruption on AMD RDNA2 GPUs +- Fixed device detection on Windows when the path to the library has non-ANSI + characters +- Added support for IntelĀ® oneAPI DPC++/C++ Compiler 2024.0 and compatible + open source compiler versions +- Upgraded to oneTBB 2021.10.0 in the official binaries +- Improved detection of old oneTBB versions + +### Changes in v2.0.1: + +- Fixed performance issue for Intel integrated GPUs using recent Linux drivers +- Fixed crash on systems with both dedicated and integrated AMD GPUs +- Fixed importing `D3D12_RESOURCE`, `D3D11_RESOURCE`, `D3D11_RESOURCE_KMT`, + `D3D11_TEXTURE` and `D3D11_TEXTURE_KMT` external memory types on CUDA and + HIP devices +- Fixed the macOS deployment target of the official x86 binaries (lowered from + 11.0 to 10.11) +- Minor improvements to verbose output + +### Changes in v2.0.0: + +- Added SYCL device for Intel Xe architecture GPUs (Xe-LP, Xe-HPG and Xe-HPC) +- Added CUDA device for NVIDIA Volta, Turing, Ampere, Ada Lovelace and Hopper + architecture GPUs +- Added HIP device for AMD RDNA2 (Navi 21 only) and RDNA3 (Navi 3x) + architecture GPUs +- Added new buffer API functions for specifying the storage type (host, device + or managed), copying data to/from the host, and importing external buffers from + graphics APIs (e.g. Vulkan, Direct3D 12) +- Removed the `oidnMapBuffer` and `oidnUnmapBuffer` functions +- Added support for asynchronous execution (e.g. `oidnExecuteFilterAsync`, + `oidnSyncDevice` functions) +- Added physical device API for querying the supported devices in the system +- Added functions for creating a device from a physical device ID, UUID, LUID + or PCI address (e.g. `oidnNewDeviceByID`) +- Added SYCL, CUDA and HIP interoperability API functions (e.g. `oidnNewSYCLDevice`, + `oidnExecuteSYCLFilterAsync`) +- Added `type` device parameter for querying the device type +- Added `systemMemorySupported` and `managedMemorySupported` device parameters + for querying memory allocations supported by the device +- Added `externalMemoryTypes` device parameter for querying the supported + external memory handle types +- Added `quality` filter parameter for setting the filtering quality mode (high + or balanced quality) +- Minor API changes with backward compatibility: + - Added `oidn(Get|Set)(Device|Filter)(Bool|Int|Float)` functions and + deprecated `oidn(Get|Set)(Device|Filter)(1b|1i|1f)` functions + - Added `oidnUnsetFilter(Image|Data)` functions and deprecated + `oidnRemoveFilter(Image|Data)` functions + - Renamed `alignment` and `overlap` filter parameters to `tileAlignment` + and `tileOverlap` but the old names remain supported +- Removed `OIDN_STATIC_LIB` and `OIDN_STATIC_RUNTIME` CMake options due to + technical limitations +- Fixed over-conservative buffer bounds checking for images with custom strides +- Upgraded to oneTBB 2021.9.0 in the official binaries + +### Changes in v1.4.3: + +- Fixed hardcoded library paths in installed macOS binaries +- Disabled VTune profiling support of oneDNN kernels by default, can be + enabled using CMake options if required (`DNNL_ENABLE_JIT_PROFILING` and + `DNNL_ENABLE_ITT_TASKS`) +- Upgraded to oneTBB 2021.5.0 in the official binaries + +### Changes in v1.4.2: + +- Added support for 16-bit half-precision floating-point images +- Added `oidnGetBufferData` and `oidnGetBufferSize` functions +- Fixed performance issue on x86 hybrid architecture CPUs (e.g. Alder Lake) +- Fixed build error when using OpenImageIO 2.3 or later +- Upgraded to oneTBB 2021.4.0 in the official binaries + +### Changes in v1.4.1: + +- Fixed crash when in-place denoising images with certain unusual resolutions +- Fixed compile error when building for Apple Silicon using some unofficial + builds of ISPC + +### Changes in v1.4.0: + +- Improved fine detail preservation +- Added the `cleanAux` filter parameter for further improving quality when the + auxiliary feature (albedo, normal) images are noise-free +- Added support for denoising auxiliary feature images, which can be used + together with the new `cleanAux` parameter for improving quality when the + auxiliary images are noisy (recommended for final frame denoising) +- Normals are expected to be in the [-1, 1] range (but still do not have to + be normalized) +- Added the `oidnUpdateFilterData` function which must be called when the + contents of an opaque data parameter bound to a filter (e.g. `weights`) has + been changed after committing the filter +- Added the `oidnRemoveFilterImage` and `oidnRemoveFilterData` functions for + removing previously set image and opaque data parameters of filters +- Reduced the overhead of `oidnCommitFilter` to zero in some cases (e.g. when + changing already set image buffers/pointers or the `inputScale` parameter) +- Reduced filter memory consumption by about 35% +- Reduced total memory consumption significantly when using multiple filters + that belong to the same device +- Reduced the default maximum memory consumption to 3000 MB +- Added the `OIDN_FILTER_RT` and `OIDN_FILTER_RTLIGHTMAP` CMake options for + excluding the trained filter weights from the build to significantly + decrease its size +- Fixed detection of static TBB builds on Windows +- Fixed compile error when using future glibc versions +- Added `oidnBenchmark` option for setting custom resolutions +- Upgraded to oneTBB 2021.2.0 in the official binaries + +### Changes in v1.3.0: + +- Improved denoising quality + - Improved sharpness of fine details / less blurriness + - Fewer noisy artifacts +- Slightly improved performance and lowered memory consumption +- Added directional (e.g. spherical harmonics) lightmap denoising to the + `RTLightmap` filter +- Added `inputScale` filter parameter which generalizes the existing + (and thus now deprecated) `hdrScale` parameter for non-HDR images +- Added native support for Apple Silicon and the BNNS library on macOS + (currently requires rebuilding from source) +- Added `OIDN_NEURAL_RUNTIME` CMake option for setting the neural network + runtime library +- Reduced the size of the library binary +- Fixed compile error on some older macOS versions +- Upgraded release builds to use oneTBB 2021.1.1 +- Removed tbbmalloc dependency +- Appended the library version to the name of the directory containing the + installed CMake files +- Training: + - Faster training performance + - Added mixed precision training (enabled by default) + - Added efficient data-parallel training on multiple GPUs + - Enabled preprocessing datasets multiple times with possibly different + options + - Minor bugfixes + +### Changes in v1.2.4: + +- Added OIDN_API_NAMESPACE CMake option that allows to put all API functions + inside a user-defined namespace +- Fixed bug when TBB_USE_GLIBCXX_VERSION is defined +- Fixed compile error when using an old compiler which does not support + OpenMP SIMD +- Added compatibility with oneTBB 2021 +- Export only necessary symbols on Linux and macOS + +### Changes in v1.2.3: + +- Fixed incorrect detection of AVX-512 on macOS (sometimes causing a crash) +- Fixed inconsistent performance and costly initialization for AVX-512 +- Fixed JIT'ed AVX-512 kernels not showing up correctly in VTune + +### Changes in v1.2.2: + +- Fixed unhandled exception when canceling filter execution from the + progress monitor callback function + +### Changes in v1.2.1: + +- Fixed tiling artifacts when in-place denoising (using one of the input + images as the output) high-resolution (> 1080p) images +- Fixed ghosting/color bleeding artifacts in black regions when using + albedo/normal buffers +- Fixed error when building as a static library (`OIDN_STATIC_LIB` option) +- Fixed compile error for ISPC 1.13 and later +- Fixed minor TBB detection issues +- Fixed crash on pre-SSE4 CPUs when using some recent compilers (e.g. GCC 10) +- Link C/C++ runtime library dynamically on Windows too by default +- Renamed example apps (`oidnDenoise`, `oidnTest`) +- Added benchmark app (`oidnBenchmark`) +- Fixed random data augmentation seeding in training +- Fixed training warning with PyTorch 1.5 and later + +### Changes in v1.2.0: + +- Added neural network training code +- Added support for specifying user-trained models at runtime +- Slightly improved denoising quality (e.g. less ringing artifacts, less + blurriness in some cases) +- Improved denoising speed by about 7-38% (mostly depending on the compiler) +- Added `OIDN_STATIC_RUNTIME` CMake option (for Windows only) +- Added support for OpenImageIO to the example apps (disabled by default) +- Added check for minimum supported TBB version +- Find debug versions of TBB +- Added testing + +### Changes in v1.1.0: + +- Added `RTLightmap` filter optimized for lightmaps +- Added `hdrScale` filter parameter for manually specifying the mapping + of HDR color values to luminance levels + +### 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/thirdparty/OpenImageDenoise/share/doc/OpenImageDenoise/LICENSE.txt b/thirdparty/OpenImageDenoise/share/doc/OpenImageDenoise/LICENSE.txt new file mode 100644 index 0000000..5b39b49 --- /dev/null +++ b/thirdparty/OpenImageDenoise/share/doc/OpenImageDenoise/LICENSE.txt @@ -0,0 +1,269 @@ +INTELĀ® OPEN IMAGE DENOISE SOFTWARE +BINARY SOFTWARE LICENSE AGREEMENT + +IMPORTANT NOTICE ā€“ PLEASE READ AND AGREE BEFORE DOWNLOADING, INSTALLING, COPYING +OR USING THE SOFTWARE + +This agreement (the "Agreement") is between you, or the company or other legal +entity that you represent and warrant you have the legal authority to bind, +(each, "You" or "Your") and Intel Corporation and its subsidiaries +(collectively, "Intel") regarding Your use of the Software. By downloading, +installing, copying or otherwise using the Software, You agree to be bound by +the terms of this Agreement. If You do not agree to the terms of this +Agreement, or do not have legal authority or required age to agree to them, do +not download, install, copy or otherwise use the Software. + +1. DEFINITIONS. "Derivative Works" means derivative works of the Software as +defined in 17 U.S.C. Ā§ 101 et seq. "Reciprocal Open Source Software" means any +software that is subject to a license which requires that (a) it must be +distributed in source code form; (b) it must be licensed under the same open +source license terms; and (c) its Derivative Works must be licensed under the +same open source license terms. Examples of this type of license are the GNU +General Public License or the Mozilla Public License. "Software" means the +IntelĀ® Open Image Denoise software in binary form, printed or electronic +documentation, and any other collateral including any updates and upgrades that +are made available to You by Intel under this Agreement. The Software does not +include Third Party Software. "Third Party Software" mean the third party +software (if any) listed in the "third-party-programs.txt" or other +similarly-named text file that may be included in the Software. + +2. LIMITED LICENSE. Subject to compliance with the terms and conditions of this +Agreement, Intel grants You a limited, nonexclusive, nontransferable, revocable, +worldwide, no fee license during the term of this Agreement, without the right +to sublicense, under Intelā€™s copyrights, for Your (a) reasonable internal +reproduction and internal use, and (b) redistribution of the Software to end +users provided that: (i) the Software is provided under a written, legally +enforceable end user license agreement that has the effect of protecting the +Software and the rights of Intel and its licensors under terms no less +restrictive than this Agreement, and (ii) You indemnify, defend, and hold +harmless Intel and its licensors from any claims, including attorneysā€™ fees, +related to the Your redistribution or use of the Software. + +3. OWNERSHIP/LICENSE RESTRICTIONS. All right, title and interest in and to the +Software are and will remain the exclusive property of Intel and its licensors. +Unless expressly permitted under the Agreement, You will not, and will not allow +any third party to (i) use, copy, distribute, transfer, sublicense, rent, sell +or offer to sell the Software or associated documentation; (ii) modify, adapt, +enhance, disassemble, decompile, reverse engineer, change or create Derivative +Works from the Software except and only to the extent as specifically required +by mandatory applicable laws; (iii) use or make the Software available for the +use or benefit of third parties; (iv) modify, create a Derivative Work, link, or +distribute the Software so that any part of it becomes subject to the license +requirements of Reciprocal Open Source Software; (v) remove or alter any +copyright, trademark or patent notice in the Software or any portion; (vi) use +Intelā€™s or its licensorsā€™ trademarks in Your distribution names or in a way that +suggests Your distributions comes from or is endorsed by Intel or its licensors; +(vii) bypass, disable, or circumvent any encryption, security, digital rights +management or authentication mechanism in the Software; (viii) include the +Software in malicious, deceptive or unlawful programs; (ix) distribute the +Software in source code form; (x) grant the right to modify the Software; or +(xi) reverse engineer, decompile or disassemble any portion of the output +generated using the Software for the purpose of translating such output +artifacts to target a non-NVIDIA platform if the output is intended for use on +an NVIDIA platform. Furthermore, You: (a) acknowledge that an essential basis of +the bargain in this Agreement is that Intel grants You no licenses or other +rights including, but not limited to, patent, copyright, and trade secret, or +other intellectual property licenses or rights to the Software, by implication, +estoppel or otherwise, except for the licenses expressly granted above; (b) +acknowledge there are significant uses of the Software in its original, +unmodified and uncombined form. You may not remove any copyright notices from +the Software; (c) agree to notify Intel in writing of any known or suspected +distribution or use of the Software not in compliance with the requirements of +this Agreement, and to enforce the terms of your agreements with respect to +distributed Software; (d) agree to cooperate with Intel and provide reasonably +requested information to verify your compliance with this Agreement; and (e) +are solely responsible for ensuring that any product or service developed with +the Software includes sufficient features to comply with all applicable legal +and regulatory standards and requirements. + +4. THIRD PARTY SOFTWARE. Third Party Software, even if included with the +distribution of the Software, may be governed by separate license terms, +including without limitation, open source software notices and terms, third +party license terms, other Intel software license terms. Such separate license +terms (and not this Agreement) govern Your use of the Third Party Programs. + +5. Media Format Codecs and Digital Rights Management. You acknowledge and agree +that Your use of the Software as permitted by this Agreement may require You to +procure license(s) from third parties that may hold intellectual property rights +applicable to any media decoding, encoding or transcoding technology (e.g., the +use of an audio or video codec) or software, content, and/or digital rights +management capabilities (the "Technology") of the Software, if any. Should any +such additional licenses be required, You are solely responsible for obtaining +any such licenses and agree to obtain any such licenses at Your own expense. +Intel does not grant any necessary patent or other rights with respect to the +Technology. + +6. LICENSE TO FEEDBACK. This Agreement does not obligate You to provide Intel +with materials, information, comments, suggestions, or other communication +regarding the features, functions, performance or use of the Software +("Feedback"). To the extent You provide Intel with Feedback in a tangible form, +You grant to Intel and its affiliates a non-exclusive, perpetual, sublicensable, +irrevocable, worldwide, royalty-free, fully paid-up and transferable license, to +and under all of Your intellectual property rights, whether perfected or not, to +publicly perform, publicly display, reproduce, use, make, have made, sell, offer +for sale, distribute, import, create Derivative Works of and otherwise exploit +any comments, suggestions, descriptions, ideas or other feedback regarding the +Software provided by You or on Your behalf. + +7. SAFETY-CRITICAL, AND LIFE-SAVING APPLICATIONS; INDEMNITY. The Software may +provide information relevant to safety-critical applications ("Safety-Critical +Applications") to allow compliance with functional safety standards or +requirements. You acknowledge and agree that safety is Your responsibility. To +the extent You use the Software to create, or as part of, products used in +Safety-Critical Applications, it is Your responsibility to design, manage, and +ensure that there are system-level safeguards to anticipate, monitor, and +control system failures, and You agree that You are solely responsible for all +applicable regulatory standards and safety-related requirements concerning Your +use of the Software in Safety Critical Applications. +Should You use the Software for Safety-Critical Applications or in any type of a +system or application in which the failure of the Software could create a +situation where personal injury or death may occur (e.g., medical systems, +life-sustaining or life-saving systems) ("Life-Saving Applications"), You agree +to indemnify, defend, and hold Intel and its representatives harmless against +any claims or lawsuits, costs, damages, and expenses, including reasonable +attorney fees, arising in any way out of Your use of the Software in +Safety-Critical Applications or Life-Saving Applications and claims of product +liability, personal injury or death associated with those applications; even if +such claims allege that Intel was negligent or strictly liable regarding the +design or manufacture of the Software or its failure to warn regarding the +Software. + +8. NO OBLIGATION; NO AGENCY. Intel may make changes to the Software, or items +referenced therein, at any time without notice. Intel is not obligated to +support, update, provide training for, or develop any further versions of the +Software or to grant any license thereto. No agency, franchise, partnership, +joint venture, or employee-employer relationship is intended or created by this +Agreement. + +9. NO WARRANTY. DISCLAIMER. THE SOFTWARE IS PROVIDED "AS IS" AND "WITH ALL +FAULTS.ā€™ INTEL AND ITS LICENSORS EXPRESSLY DISCLAIM ALL WARRANTIES OF ANY KIND +OR NATURE, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING BUT NOT LIMITED TO +ANY WARRANTIES OF MERCHANTABILITY, TITLE, NONINFRINGEMENT, FITNESS FOR A +PARTICULAR PURPOSE, OR THE ABSENCE OF ANY DEFECTS THEREIN, WHETHER LATENT OR +PATENT. NO WARRANTY IS MADE ON THE BASIS OF TRADE USAGE, COURSE OF DEALING OR +COURSE OF TRADE. Intel does not assume, and does not authorize any person to +assume on its behalf, any other liability. Intel may make changes to the +Software, or to items referenced therein, at any time without notice, but is not +obligated to support, update or provide training for the Software under the +terms of this Agreement. + +10. LIMITATION OF LIABILITY. IN NO EVENT WILL INTEL OR ITS AFFILIATES, +LICENSORS OR SUPPLIERS (INCLUDING THEIR RESPECTIVE DIRECTORS, OFFICERS, +EMPLOYEES, AND AGENTS) BE LIABLE FOR ANY DAMAGES WHATSOEVER (INCLUDING, WITHOUT +LIMITATION, LOST PROFITS, LOSS OF USE, LOSS OF GOODWILL, BUSINESS INTERRUPTION, +COSTS OF PROCURING SUBSTITUTE PRODUCTS OR LOST DATA) ARISING OUT OF OR IN +RELATION TO THIS AGREEMENT, INCLUDING THE USE OF OR INABILITY TO USE THE +SOFTWARE, WHETHER SUCH LIABILITY ARISES FROM ANY CLAIM BASED UPON BREACH OF +CONTRACT, BREACH OF WARRANTY, TORT (INCLUDING NEGLIGENCE), PRODUCT LIABILITY OR +ANY OTHER CAUSE OF ACTION OR THEORY OF LIABILITY, EVEN IF INTEL HAS BEEN ADVISED +OF THE POSSIBILITY OF SUCH DAMAGES. SOME JURISDICTIONS PROHIBIT EXCLUSION OR +LIMITATION OF LIABILITY FOR IMPLIED WARRANTIES OR CONSEQUENTIAL OR INCIDENTAL +DAMAGES, SO THE ABOVE LIMITATION MAY IN PART NOT APPLY TO YOU. YOU MAY ALSO +HAVE OTHER LEGAL RIGHTS THAT VARY FROM JURISDICTION TO JURISDICTION. IN NO EVENT +WILL INTELā€™S, ITS AFFILIATESā€™ AND LICENSORSā€™ TOTAL CUMULATIVE LIABILITY UNDER OR +ARISING OUT OF THIS AGREEMENT EXCEED US$10.00. THE LIMITED REMEDIES, WARRANTY +DISCLAIMER AND LIMITED LIABILITY ARE FUNDAMENTAL ELEMENTS OF THE BASIS OF THE +BARGAIN BETWEEN INTEL AND YOU. YOU ACKNOWLEDGE INTEL WOULD BE UNABLE TO PROVIDE +THE SOFTWARE WITHOUT SUCH LIMITATIONS. + +11. TERMINATION AND SURVIVAL. This Agreement will terminate immediately if You +violate any of its terms or conditions. Intel may, at any time, terminate this +Agreement if (i) you commence or participate in any legal proceeding against +Intel or its licensors with respect to the Software; (ii) if Intel decides to no +longer provide the Software in a particular country; or (iii) if Intel, in its +sole discretion, decides to no longer make the Software commercially available. +Upon any termination of this Agreement, all licenses granted to You hereunder +terminate immediately. Upon termination, You will immediately stop use of the +Software, permanently remove the Software from your systems, destroy the +Software, and keep no copies. If requested in writing, you will certify in +writing that you have complied with your obligations under this Section. The +following sections will survive termination of this Agreement: Section 1, 3 +(only with respect to the first sentence), 4, 5, 6, 7, 9, 10, 11, 12, 16, 17, 18 +and 19. + +12. GOVERNING LAW AND JURISDICTION. This Agreement and any dispute arising out +of or relating to it will be governed by the laws of the U.S.A. and Delaware, +without regard to conflict of laws principles. The parties exclude the +application of the United Nations Convention on Contracts for the International +Sale of Goods (1980). The state and federal courts sitting in Delaware, U.S.A. +will have exclusive jurisdiction over any dispute arising out of or relating to +this Agreement. The parties consent to personal jurisdiction and venue in those +courts. A party that obtains a judgment against the other party in the courts +identified in this Section may enforce that judgment in any court that has +jurisdiction over the parties. + +13. EXPORT. You acknowledge that the Software and all related technical +information are subject to export controls and You agree to comply with all laws +and regulations of the United States and other applicable governments governing +export, re-export, import, transfer, distribution, and use of the Software. In +particular, but without limitation, the Software may not be exported or +re-exported (a) into any U.S. embargoed countries or (b) to any person or entity +listed on a denial order published by the U.S. government or any other +applicable governments. By using the Software, You represent and warrant that +You are not located in any such country or on any such list. You also agree +that You will not use the Software for, or sell or transfer them to a third +party who is known or suspected to be involved in, any purposes prohibited by +the U.S. government or other applicable governments, including, without +limitation, the development, design, manufacture, or production of nuclear, +missile, chemical or biological weapons. + +14. GOVERNMENT RESTRICTED RIGHTS. The technical data and computer software +covered by this license is a "Commercial Item," as such term is defined by the +FAR 2.101 (48 C.F.R. 2.101) and is "commercial computer software" and +"commercial computer software documentation" as specified under FAR 12.212 (48 +C.F.R. 12.212) or DFARS 227.7202 (48 C.F.R. 227.7202), as applicable. This +commercial computer software and related documentation is provided to end users +for use by and on behalf of the U.S. Government, with only those rights as are +granted to all other end users pursuant to the terms and conditions herein. + +15. ASSIGNMENT. You may not delegate, assign or transfer this Agreement, the +license(s) granted or any of Your rights or duties hereunder, expressly, by +implication, by operation of law, or otherwise and any attempt to do so, without +Intelā€™s express prior written consent, will be null and void. Intel may assign, +delegate and transfer this Agreement, and its rights and obligations hereunder, +in its sole discretion. + +16. ENTIRE AGREEMENT. This Agreement contains the complete and exclusive +agreement and understanding between the parties concerning the subject matter of +this Agreement, and supersedes all prior and contemporaneous proposals, +agreements, understanding, negotiations, representations, warranties, +conditions, and communications, oral or written, between the parties relating to +the same subject matter. You acknowledge and agree that in entering into this +Agreement You have not relied on, and will not be entitled to rely on, any oral +or written representations, warranties, conditions, understanding, or +communications that are not expressly set forth in this Agreement. The express +provisions of this Agreement control over any course of performance, course of +dealing, or usage of the trade inconsistent with any of the provisions of this +Agreement. The provisions of this Agreement will prevail notwithstanding any +different, conflicting, or additional provisions that may appear on any purchase +order, acknowledgement, invoice, or other writing issued by either party in +connection with this Agreement. No modification or amendment to this Agreement +will be effective unless in writing and signed by authorized representatives of +each party, and must specifically identify this Agreement by its title and +version; , except that Intel may make changes to the Agreement as it distributes +new versions of the Software. If You received a copy of this Agreement +translated into another language, the English language version of this Agreement +will prevail in the event of any conflict between versions. + +17. SEVERABILITY AND WAIVER. The parties intend that if a court holds that any +provision or part of this Agreement is invalid or unenforceable under applicable +law, the court will modify the provision to the minimum extent necessary to make +it valid and enforceable, or if it cannot be made valid and enforceable, the +parties intend that the court will sever and delete the provision or part from +this Agreement. Any change to or deletion of a provision or part of this +Agreement under this Section will not affect the validity or enforceability of +the remainder of this Agreement, which will continue in full force and effect. +The failure of a party to require performance by the other party of any +provision hereof will not affect the full right to require such performance at +any time thereafter; nor will waiver by a party of a breach of any provision +hereof constitute a waiver of the provision itself. + +18. PRIVACY. YOUR PRIVACY RIGHTS ARE SET FORTH IN INTELā€™S PRIVACY NOTICE, WHICH +FORMS A PART OF THIS AGREEMENT. PLEASE REVIEW THE PRIVACY NOTICE AT +HTTP://WWW.INTEL.COM/PRIVACY TO LEARN HOW INTEL COLLECTS, USES AND SHARES +INFORMATION ABOUT YOU. + +19. THIRD PARTY BENEFICIARIES. The Software includes software and materials +from Intelā€™s licensors. These licensors are intended third party beneficiaries +that may enforce this Agreement with respect to their intellectual property +rights. diff --git a/thirdparty/OpenImageDenoise/share/doc/OpenImageDenoise/README.md b/thirdparty/OpenImageDenoise/share/doc/OpenImageDenoise/README.md new file mode 100644 index 0000000..8b85547 --- /dev/null +++ b/thirdparty/OpenImageDenoise/share/doc/OpenImageDenoise/README.md @@ -0,0 +1,2073 @@ +# IntelĀ® Open Image Denoise + +This is release v2.1.0 of Intel Open Image Denoise. For changes and new +features see the [changelog](CHANGELOG.md). Visit +https://www.openimagedenoise.org for more information. + +# Overview + +Intel Open Image Denoise is an open source library of high-performance, +high-quality denoising filters for images rendered with ray tracing. +Intel Open Image Denoise is part of the [IntelĀ® oneAPI Rendering +Toolkit](https://software.intel.com/en-us/oneapi/render-kit) and is +released under the permissive [Apache 2.0 +license](http://www.apache.org/licenses/LICENSE-2.0). + +The purpose of Intel 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 Intel Open Image Denoise library is a collection of +efficient deep learning based denoising filters, which were 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. + +Although the library ships with a set of pre-trained filter models, it +is not mandatory to use these. To optimize a filter for a specific +renderer, sample count, content type, scene, etc., it is possible to +train the model using the included training toolkit and user-provided +image datasets. + +Intel Open Image Denoise supports a wide variety of CPUs and GPUs from +different vendors: + + - IntelĀ® 64 architecture compatible CPUs (with at least SSE4.1) + + - Apple Silicon CPUs + + - Intel Xe architecture GPUs, both dedicated and integrated, including + IntelĀ® Arcā„¢ A-Series Graphics, IntelĀ® Data Center GPU Flex Series + (Xe-HPG microarchitecture), IntelĀ® Data Center GPU Max Series + (Xe-HPC), 11th-13th Gen IntelĀ® Coreā„¢ processor graphics, and related + Intel PentiumĀ® and CeleronĀ® processors (Xe-LP) + + - NVIDIA GPUs with Volta, Turing, Ampere, Ada Lovelace, and Hopper + architectures + + - AMD GPUs with RDNA2 (Navi 21 only) and RDNA3 (Navi 3x) architectures + +It runs on most machines ranging from laptops to workstations and +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 or even real-time ray tracing. + +Intel Open Image Denoise exploits modern instruction sets like Intel +SSE4, AVX2, and AVX-512 on CPUs, IntelĀ® Xe Matrix Extensions (IntelĀ® +XMX) on Intel GPUs, and tensor cores on NVIDIA GPUs to achieve high +denoising performance. + +## System Requirements + +You need a CPU with SSE4.1 support or Apple Silicon to run Intel Open +Image Denoise, and you need a 64-bit Windows, Linux, or macOS operating +system as well. + +For Intel GPU support, please also install the latest Intel graphics +drivers: + + - Windows: [IntelĀ® Graphics + Driver](https://www.intel.com/content/www/us/en/download/726609/intel-arc-iris-xe-graphics-whql-windows.html) + 31.0.101.4314 or newer for IntelĀ® Arcā„¢ Graphics, 11th-13th Gen + IntelĀ® Coreā„¢ processor graphics, and related Intel PentiumĀ® and + CeleronĀ® processors + + - Linux: [IntelĀ® software for General Purpose GPU + capabilities](https://dgpu-docs.intel.com/driver/installation.html) + release + [20230323](https://dgpu-docs.intel.com/releases/stable_602_20230323.html) + or newer + +Using older driver versions is *not* supported and Intel Open Image +Denoise might run with only limited capabilities, have suboptimal +performance or might be unstable. Also, Resizable BAR *must* be enabled +in the BIOS for Intel dedicated GPUs if running on Linux, and strongly +recommended if running on Windows. + +For NVIDIA GPU support, please also install the latest [NVIDIA graphics +drivers](https://www.nvidia.com/en-us/geforce/drivers/): + + - Windows: Version 522.06 or newer + + - Linux: Version 520.61.05 or newer + +For AMD GPU support, please also install the latest [AMD graphics +drivers](https://www.amd.com/en/support): + + - Windows: AMD Software: Adrenalin Edition 23.4.3 Driver Version + 22.40.51.05 or newer + + - Linux: [Radeon Software for + Linux](https://www.amd.com/en/support/linux-drivers) version 22.40.5 + or newer + +## Support and Contact + +Intel 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 [Intel 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 +. + +Join our [mailing +list](https://groups.google.com/d/forum/openimagedenoise/) to receive +release announcements and major news regarding Intel Open Image Denoise. + +## Citation + +If you use Intel Open Image Denoise in a research publication, please +cite the project using the following BibTeX entry: + +``` bibtex +@misc{OpenImageDenoise, + author = {Attila T. {\'A}fra}, + title = {{Intel\textsuperscript{\textregistered} Open Image Denoise}}, + year = {2023}, + note = {\url{https://www.openimagedenoise.org}} +} +``` + +# Compilation + +The latest Intel Open Image Denoise sources are always available at the +[Intel Open Image Denoise GitHub +repository](http://github.com/OpenImageDenoise/oidn). The default +`master` branch should always point to the latest tested bugfix release. + +## Prerequisites + +You can clone the latest Intel Open Image Denoise sources using Git with +the [Git Large File Storage (LFS)](https://git-lfs.github.com/) +extension installed: + + git clone --recursive https://github.com/OpenImageDenoise/oidn.git + +Please note that installing the Git LFS extension is *required* to +correctly clone the repository. Cloning without Git LFS will seemingly +succeed but actually some of the files will be invalid and thus +compilation will fail. + +Intel Open Image Denoise currently supports 64-bit Linux, Windows, and +macOS operating systems. Before you can build Intel Open Image Denoise +you need the following basic prerequisites: + + - [CMake](http://www.cmake.org) 3.15 or newer + + - A C++11 compiler (we recommend using a Clang-based compiler but also + support GCC and Microsoft Visual Studio 2015 and newer) + + - Python 3 + +To build support for different types of CPUs and GPUs, the following +additional prerequisites are needed: + +#### CPU device: + + - [IntelĀ® SPMD Program Compiler (ISPC)](http://ispc.github.io) 1.14.1 + or newer. Please obtain a release of ISPC from the [ISPC downloads + page](https://ispc.github.io/downloads.html). The build system looks + for ISPC in the `PATH` and in the directory right ā€œnext toā€ the + checked-out Intel Open Image Denoise sources.\[1\] Alternatively set + the CMake variable `ISPC_EXECUTABLE` to the location of the ISPC + compiler. + + - [IntelĀ® Threading Building + Blocks](https://github.com/oneapi-src/oneTBB) (TBB) 2017 or newer + +#### SYCL device for Intel GPUs: + + - [IntelĀ® oneAPI DPC++/C++ + Compiler](https://www.intel.com/content/www/us/en/developer/tools/oneapi/dpc-compiler.html) + 2024.0 or newer, or the open source [oneAPI DPC++ + Compiler 2023-09-22](https://github.com/intel/llvm/releases/tag/nightly-2023-09-22). + Other SYCL compilers are *not* supported. The open source version of + the compiler is more up-to-date but less stable, so we *strongly* + recommend to use the exact version listed here, and on Linux we also + recommend to rebuild it from source with the `--disable-fusion` + flag. + + - IntelĀ® Graphics Offline Compiler for OpenCLā„¢ Code (OCLOC) + + - Windows: Version + [31.0.101.4824](https://registrationcenter-download.intel.com/akdlm/IRC_NAS/fcd74e0e-43b3-4930-9bad-29c8b9581339/ocloc_win_101.4824.zip) + or newer as a [standalone component of IntelĀ® oneAPI + Toolkits](https://www.intel.com/content/www/us/en/developer/articles/tool/oneapi-standalone-components.html), + which must be extracted and its contents added to the `PATH`. + Also included with [IntelĀ® oneAPI Base + Toolkit](https://www.intel.com/content/www/us/en/developer/tools/oneapi/toolkits.html#base-kit). + + - Linux: Included with [IntelĀ® software for General Purpose GPU + capabilities](https://dgpu-docs.intel.com) release + [20230918](https://dgpu-docs.intel.com/releases/stable_704_30_20230918.html) + or newer (install at least `intel-opencl-icd` on Ubuntu, + `intel-ocloc` on RHEL or SLES). Also available with [IntelĀ® + Graphics Compute Runtime for oneAPI Level Zero and OpenCLā„¢ + Driver](https://github.com/intel/compute-runtime). + + - If using IntelĀ® oneAPI DPC++/C++ Compiler: + [CMake](http://www.cmake.org) 3.25.2 or newer + + - [Ninja](https://ninja-build.org) or Make as the CMake generator. The + Visual Studio generator is *not* supported. + +#### CUDA device for NVIDIA GPUs: + + - [CMake](http://www.cmake.org) 3.18 or newer + + - [NVIDIA CUDA Toolkit](https://developer.nvidia.com/cuda-toolkit) + 11.8 or newer + +#### HIP device for AMD GPUs: + + - [CMake](http://www.cmake.org) 3.21 or newer + + - [Ninja](https://ninja-build.org) or Make as the CMake generator. The + Visual Studio generator is *not* supported. + + - [AMD ROCm (HIP SDK)](https://rocm.docs.amd.com) v5.5.0 or newer. + +Depending on your operating system, you can install some required +dependencies (e.g., TBB) using `yum` or `apt-get` on Linux, +[Homebrew](https://brew.sh) or [MacPorts](https://www.macports.org) on +macOS, and [`vcpkg`](https://vcpkg.io) on Windows. For the other +dependencies please download the necessary packages or installers and +follow the included instructions. + +## Compiling on Linux/macOS + +If you are building with SYCL support on Linux, make sure that the DPC++ +compiler is properly set up. The open source oneAPI DPC++ Compiler can +be downloaded and simply extracted. However, before using the compiler, +the environment must be set up as well with the following command: + + source ./dpcpp_compiler/startup.sh + +The `startup.sh` script will put `clang` and `clang++` from the oneAPI +DPC++ Compiler into your `PATH`. + +Alternatively, if you have installed IntelĀ® oneAPI DPC++/C++ Compiler +instead, you can set up the compiler by sourcing the `vars.sh` script in +the `env` directory of the compiler install directory, for example, + + source /opt/intel/oneAPI/compiler/latest/env/vars.sh + +This script will put the `icx` and `icpx` compiler executables from the +Intel(R) oneAPI DPC++/C++ Compiler in your `PATH`. + + - Create a build directory, and go into it using a command prompt + + mkdir oidn/build + cd oidn/build + + (We do recommend having separate build directories for different + configurations such as release, debug, etc.). + + - CMake will use the default compiler, which on most Linux machines is + `gcc`, but it can be switched to `clang` by executing the following: + + cmake -G Ninja -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ .. + + If you are building with SYCL support, you must set the DPC++ + compiler (`clang`/`clang++` or `icx`/`icpx`) as the C/C++ compiler + here. 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 + and options you need. By default only CPU support is built, so SYCL + and other device support must be enabled manually (e.g.Ā with the + `OIDN_DEVICE_SYCL` option). Then type ā€™cā€™onfigure and ā€™gā€™enerate. + When back on the command prompt, build the library using + + ninja + +### Entitlements on macOS + +macOS requires notarization of applications as a security mechanism, and +[entitlements must be +declared](https://developer.apple.com/documentation/bundleresources/entitlements) +during the notarization process. Intel Open Image Denoise uses +just-in-time compilation through +[oneDNN](https://github.com/oneapi-src/oneDNN) and requires the +following entitlements: + + - [`com.apple.security.cs.allow-jit`](https://developer.apple.com/documentation/bundleresources/entitlements/com_apple_security_cs_allow-jit) + - [`com.apple.security.cs.allow-unsigned-executable-memory`](https://developer.apple.com/documentation/bundleresources/entitlements/com_apple_security_cs_allow-unsigned-executable-memory) + - [`com.apple.security.cs.disable-executable-page-protection`](https://developer.apple.com/documentation/bundleresources/entitlements/com_apple_security_cs_disable-executable-page-protection) + +## Compiling on Windows + +If you are building with SYCL support, make sure that the DPC++ compiler +is properly set up. The open source oneAPI DPC++ Compiler can be +downloaded and simply extracted. However, before using the compiler, the +environment must be set up. To achieve this, open the ā€œx64 Native Tools +Command Prompt for VSā€ that ships with Visual Studio and execute the +following commands: + + set "DPCPP_DIR=path_to_dpcpp_compiler" + set "PATH=%DPCPP_DIR%\bin;%PATH%" + set "PATH=%DPCPP_DIR%\lib;%PATH%" + set "CPATH=%DPCPP_DIR%\include;%CPATH%" + set "INCLUDE=%DPCPP_DIR%\include;%INCLUDE%" + set "LIB=%DPCPP_DIR%\lib;%LIB%" + +The `path_to_dpcpp_compiler` should point to the unpacked oneAPI DPC++ +Compiler. + +Alternatively, if you have installed IntelĀ® oneAPI DPC++/C++ Compiler +instead, you can either open a regular ā€œCommand Promptā€ and execute the +`vars.bat` script in the `env` directory of the compiler install +directory, for example + + C:\Program Files (x86)\Intel\oneAPI\compiler\latest\env\vars.bat + +or simply open the installed ā€œIntel oneAPI command prompt for Intel 64 +for Visual Studioā€. Either way, the `icx` compiler executable from the +IntelĀ® oneAPI DPC++/C++ Compiler will be added to your `PATH`. + +On Windows we highly recommend to use Ninja as the CMake generator +because not all devices can be built using the Visual Studio generator +(e.g.Ā SYCL). + + - Create a build directory, and go into it using a Visual Studio + command prompt + + mkdir oidn/build + cd oidn/build + + (We do recommend having separate build directories for different + configurations such as release, debug, etc.). + + - CMake will use the default compiler, which on most Windows machines + is MSVC, but it can be switched to `clang` by executing the + following: + + cmake -G Ninja -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ .. + + If you are building with SYCL support, you must set the DPC++ + compiler (`clang`/`clang++` or `icx`) as the C/C++ compiler here. + Note that the compiler variables cannot be changed after the first + `cmake` or `cmake-gui` run. + + - Open the CMake GUI (`cmake-gui.exe`) + + cmake-gui .. + + - Make sure to properly set the build mode and enable the components + and options you need. By default only CPU support is built, so SYCL + and other device support must be enabled manually + (e.g.Ā `OIDN_DEVICE_SYCL` option). Then click on Configure and + Generate. When back on the command prompt, build the library using + + ninja + +## CMake Configuration + +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`: Build Open Image Denoise as a static (if only CPU + support is enabled) or a hybrid static/shared (if GPU support is + enabled as well) library. + + - `OIDN_API_NAMESPACE`: Specifies a namespace to put all Intel Open + Image Denoise API symbols inside. This is also added as an outer + namespace for the C++ wrapper API. By default no namespace is used + and plain C symbols are exported. + + - `OIDN_DEVICE_CPU`: Enable CPU device support (ON by default). + + - `OIDN_DEVICE_SYCL`: Enable SYCL device support for Intel GPUs (OFF + by default). + + - `OIDN_DEVICE_SYCL_AOT`: Enable ahead-of-time (AOT) compilation for + SYCL kernels (ON by default). Turning this off removes dependency on + OCLOC at build time and decreases binary size but significantly + increases initialization time at runtime, so it is recommended only + for development. + + - `OIDN_DEVICE_CUDA`: Enable CUDA device support for NVIDIA GPUs (OFF + by default). + + - `OIDN_DEVICE_HIP`: Enable HIP device support for AMD GPUs (OFF by + default). + + - `OIDN_FILTER_RT`: Include the trained weights of the `RT` filter in + the build (ON by default). Turning this OFF significantly decreases + the size of the library binary, while the filter remains functional + if the weights are set by the user at runtime. + + - `OIDN_FILTER_RTLIGHTMAP`: Include the trained weights of the + `RTLightmap` filter in the build (ON by default). + + - `OIDN_APPS`: Enable building example and test applications (ON by + default). + + - `OIDN_APPS_OPENIMAGEIO`: Enable + [OpenImageIO](http://openimageio.org/) support in the example and + test applications to be able to load/save OpenEXR, PNG, and other + image file formats (OFF by default). + + - `OIDN_INSTALL_DEPENDENCIES`: Enable installing the dependencies + (e.g.Ā TBB, SYCL runtime) as well. + + - `TBB_ROOT`: The path to the TBB installation (autodetected by + default). + + - `ROCM_PATH`: The path to the ROCm installation (autodetected by + default). + + - `OPENIMAGEIO_ROOT`: The path to the OpenImageIO installation + (autodetected by default). + +# Documentation + +The following +[documentation](https://github.com/OpenImageDenoise/oidn/blob/master/readme.pdf "Intel Open Image Denoise Documentation") +of Intel Open Image Denoise can also be found as a [pdf +document](https://github.com/OpenImageDenoise/oidn/blob/master/readme.pdf "Intel 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. + +## Examples + +To have a quick overview of the C99 and C++11 APIs, see the following +simple example code snippets. + +### Basic Denoising (C99 API) + +``` cpp +#include +... + +// Create an Open Image Denoise device +OIDNDevice device = oidnNewDevice(OIDN_DEVICE_TYPE_DEFAULT); // CPU or GPU if available +oidnCommitDevice(device); + +// Create buffers for input/output images accessible by both host (CPU) and device (CPU/GPU) +OIDNBuffer colorBuf = oidnNewBuffer(device, width * height * 3 * sizeof(float)); +OIDNBuffer albedoBuf = ... + +// Create a filter for denoising a beauty (color) image using optional auxiliary images too +// This can be an expensive operation, so try not to create a new filter for every image! +OIDNFilter filter = oidnNewFilter(device, "RT"); // generic ray tracing filter +oidnSetFilterImage(filter, "color", colorBuf, + OIDN_FORMAT_FLOAT3, width, height, 0, 0, 0); // beauty +oidnSetFilterImage(filter, "albedo", albedoBuf, + OIDN_FORMAT_FLOAT3, width, height, 0, 0, 0); // auxiliary +oidnSetFilterImage(filter, "normal", normalBuf, + OIDN_FORMAT_FLOAT3, width, height, 0, 0, 0); // auxiliary +oidnSetFilterImage(filter, "output", colorBuf, + OIDN_FORMAT_FLOAT3, width, height, 0, 0, 0); // denoised beauty +oidnSetFilterBool(filter, "hdr", true); // beauty image is HDR +oidnCommitFilter(filter); + +// Fill the input image buffers +float* colorPtr = (float*)oidnGetBufferData(colorBuf); +... + +// Filter the beauty image +oidnExecuteFilter(filter); + +// Check for errors +const char* errorMessage; +if (oidnGetDeviceError(device, &errorMessage) != OIDN_ERROR_NONE) + printf("Error: %s\n", errorMessage); + +// Cleanup +oidnReleaseBuffer(colorBuf); +... +oidnReleaseFilter(filter); +oidnReleaseDevice(device); +``` + +### Basic Denoising (C++11 API) + +``` cpp +#include +... + +// Create an Open Image Denoise device +oidn::DeviceRef device = oidn::newDevice(); // CPU or GPU if available +device.commit(); + +// Create buffers for input/output images accessible by both host (CPU) and device (CPU/GPU) +oidn::BufferRef colorBuf = device.newBuffer(width * height * 3 * sizeof(float)); +oidn::BufferRef albedoBuf = ... + +// Create a filter for denoising a beauty (color) image using optional auxiliary images too +// This can be an expensive operation, so try no to create a new filter for every image! +oidn::FilterRef filter = device.newFilter("RT"); // generic ray tracing filter +filter.setImage("color", colorBuf, oidn::Format::Float3, width, height); // beauty +filter.setImage("albedo", albedoBuf, oidn::Format::Float3, width, height); // auxiliary +filter.setImage("normal", normalBuf, oidn::Format::Float3, width, height); // auxiliary +filter.setImage("output", colorBuf, oidn::Format::Float3, width, height); // denoised beauty +filter.set("hdr", true); // beauty image is HDR +filter.commit(); + +// Fill the input image buffers +float* colorPtr = (float*)colorBuf.getData(); +... + +// Filter the beauty image +filter.execute(); + +// Check for errors +const char* errorMessage; +if (device.getError(errorMessage) != oidn::Error::None) + std::cout << "Error: " << errorMessage << std::endl; +``` + +### Denoising with Prefiltering (C++11 API) + +``` cpp +// Create a filter for denoising a beauty (color) image using prefiltered auxiliary images too +oidn::FilterRef filter = device.newFilter("RT"); // generic ray tracing filter +filter.setImage("color", colorBuf, oidn::Format::Float3, width, height); // beauty +filter.setImage("albedo", albedoBuf, oidn::Format::Float3, width, height); // auxiliary +filter.setImage("normal", normalBuf, oidn::Format::Float3, width, height); // auxiliary +filter.setImage("output", outputBuf, oidn::Format::Float3, width, height); // denoised beauty +filter.set("hdr", true); // beauty image is HDR +filter.set("cleanAux", true); // auxiliary images will be prefiltered +filter.commit(); + +// Create a separate filter for denoising an auxiliary albedo image (in-place) +oidn::FilterRef albedoFilter = device.newFilter("RT"); // same filter type as for beauty +albedoFilter.setImage("albedo", albedoBuf, oidn::Format::Float3, width, height); +albedoFilter.setImage("output", albedoBuf, oidn::Format::Float3, width, height); +albedoFilter.commit(); + +// Create a separate filter for denoising an auxiliary normal image (in-place) +oidn::FilterRef normalFilter = device.newFilter("RT"); // same filter type as for beauty +normalFilter.setImage("normal", normalBuf, oidn::Format::Float3, width, height); +normalFilter.setImage("output", normalBuf, oidn::Format::Float3, width, height); +normalFilter.commit(); + +// Prefilter the auxiliary images +albedoFilter.execute(); +normalFilter.execute(); + +// Filter the beauty image +filter.execute(); +``` + +## Upgrading from Open Image Denoise 1.x + +Open Image Denoise 2.0 introduces GPU support, which requires +implementing some minor changes in applications. There are also small +API changes, additions and improvements in this new version. In this +section we summarize the necessary code modifications and also briefly +mention the new features that users might find useful when upgrading to +2.0. For a full description of the changes and new functionality, please +see the API reference. + +### Buffers + +The most important required change is related to how data is passed to +Open Image Denoise. If the application is explicitly using only the CPU +(by specifying `OIDN_DEVICE_TYPE_CPU`), no changes should be necessary. +But if it wants to support GPUs as well, passing pointers to memory +allocated with the system allocator (e.g.Ā `malloc`) would raise an error +because GPUs cannot access such memory in almost all cases. + +To ensure compatibility with any kind of device, including GPUs, the +application should use `OIDNBuffer` objects to store all image data +passed to the library. Memory allocated using buffers is by default +accessible by both the host (CPU) and the device (CPU or GPU). + +Ideally, the application should directly read and write image data +to/from such buffers to avoid redundant and inefficient data copying. If +this cannot be implemented, the application should try to minimize the +overhead of copying as much as possible: + + - Data should be copied to/from buffers only if the data in system + memory indeed cannot be accessed by the device. This can be + determined by simply querying the `systemMemorySupported` device + parameter. If system memory is accessible by the device, no buffers + are necessary and filter image parameters can be set with + `oidnSetSharedFilterImage`. + + - If the image data cannot be accessed by the device, buffers must be + created and the data must be copied to/from these buffers. These + buffers should be directly passed to filters as image parameters + instead of the original pointers using `oidnSetFilterImage`. + + - Data should be copied asynchronously using using the new + `oidnReadBufferAsync` and `oidnWriteBufferAsync` functions, which + may achieve higher performance than plain `memcpy`. + + - If image data must be copied, using the default buffer allocation + may not be the most efficient method. If the device memory is not + physically shared with the host memory (e.g.Ā for dedicated GPUs), + higher performance may be achieved by creating the buffers with + device storage (`OIDN_STORAGE_DEVICE`) using the new + `oidnNewBufferWithStorage` function. This way, the buffer data + cannot be directly accessed by the host anymore but this should not + matter because the data must be copied from some other memory + location anyway. However, this ensures that the data is stored only + in high-performance device memory, and the user has full control + over when and how the data is transferred between host and device. + +The `oidnMapBuffer` and `oidnUnmapBuffer` functions have been removed +from the API due to these not being supported by any of the device +backends. Please use `oidnReadBuffer(Async)` and +`oidnWriteBuffer(Async)` instead. + +### Interop with Compute (SYCL, CUDA, HIP) and Graphics (DX, Vulkan) APIs + +If the application is explicitly using a particular device type which +supports unified memory allocations, e.g.Ā SYCL or CUDA, it may directly +pass pointers allocated using the native allocator of the respective +compute API (e.g.Ā `sycl::malloc_device`, `cudaMalloc`) instead of using +buffers. This way, it is the responsibility of the user to correctly +allocate the memory for the device. + +In such cases, it often necessary to have more control over the device +creation as well, to ensure that filtering is running on the intended +device and command queues or streams from the application can be shared +to improve performance. If the application is using the same compute or +graphics API as the Open Image Denoise device, this can be achieved by +creating devices with `oidnNewSYCLDevice`, `oidnNewCUDADevice`, etc. For +some APIs there are additional interoperability functions as well, +e.g.Ā `oidnExecuteSYCLFilterAsync`. + +If the application is using a graphics API which does not support +unified memory allocations, e.g.Ā DX12 or Vulkan, it may be still +possible to share memory between the application and Open Image Denoise +using buffers, avoiding expensive copying through host memory. External +buffers can be imported from graphics APIs with the new +`oidnNewSharedBufferFromFD` and `oidnNewSharedBufferFromWin32Handle` +functions. To use this feature, buffers must be exported in the graphics +API and must be imported in Open Image Denoise using the same kind of +handle. Care must be taken to select an external memory handle type +which is supported by both APIs. The external memory types supported by +an Open Image Denoise device can be queried using the +`externalMemoryTypes` device parameter. Note that some devices do not +support importing external memory at all (e.g.Ā CPUs, and on GPUs it +primarily depends on the installed drivers), so the application should +always implement a fallback too, which copies the data through the host +if there is no other supported way. + +Sharing textures is currently not supported natively but it is still +possible avoid copying texture data by using a linear texture layout +(e.g.Ā `VK_IMAGE_TILING_LINEAR` in Vulkan) and sharing the buffer that +backs this data. In this case, you should ensure that the row stride of +the linear texture data is correctly set. + +Importing external synchronization primitives (e.g.Ā semaphores) from +graphics APIs is not yet supported either but it is planned for a future +release. Meanwhile, synchronizing access to shared memory should be done +on the host using `oidnSyncDevice` and the used graphics API. + +When importing external memory, the application also needs to make sure +that the Open Image Denoise device is running on the same *physical* +device as the graphics API. This can be easily achieved by using the new +physical device feature, described in the next section. + +### Physical Devices + +Although it is possible to explicitly create devices of a particular +type (with, e.g., `OIDN_DEVICE_TYPE_SYCL`), this is often insufficient, +especially if the system has multiple devices of the same type, and with +GPU support it is very common that there are multiple different types of +supported devices in the system (e.g.Ā a CPU and one or more GPUs). + +The 2.0 version of the library introduces a simple *physical device* +API, which enables the application to query the list of supported +physical devices in the system, including their name, type, UUID, LUID, +PCI address, etc. (see `oidnGetNumPhysicalDevices`, +`oidnGetPhysicalDeviceString`, etc.). New logical device +(i.e.Ā `OIDNDevice`) creation functions for have been also introduced, +which enable creating a logical device on a specific physical device: +`oidnNewDeviceByID`, `oidnNewDeviceByUUID`, etc. + +Creating a logical device on a physical device having a particular UUID, +LUID or PCI address is particularly important when importing external +memory from graphics APIs. However, not all device types support all +types of IDs, and some graphics drivers may even report mismatching +UUIDs or LUIDs for the same physical device, so applications should try +to implement multiple identification methods, or at least assume that +identification might fail. + +### Asynchronous Execution + +With the introduction of GPU support, it is now possible to execute some +operations asynchronously, most importantly filtering +(`oidnExecuteFilterAsync`, `oidnExecuteSYCLFilterAsync`) and copying +data (the already mentioned `oidnReadBufferAsync` and +`oidnWriteBufferAsync`). Although these new asynchronous functions can +be used with any device type, it is *not* guaranteed that these will be +actually executed asynchronously. The most important such exceptions are +CPU devices, which are still blocking the calling thread when these +functions are called. + +When using any asynchronous function it is the responsibility of the +application to handle correct synchronization using `oidnSyncDevice`. + +### Filter Quality + +Open Image Denoise still delivers the same high image quality on all +device types as before, including on GPUs. But often filtering +performance is more important than having the highest possible image +quality, so it is now possible to switch between multiple filter quality +modes. Filters have a new parameter called `quality`, which defaults to +the existing high image quality (`OIDN_QUALITY_HIGH`) but a balanced +quality mode (`OIDN_QUALITY_BALANCED`) has been added as well for even +higher performance. We recommend using balanced quality for interactive +and real-time use cases. + +### Small API Changes + +A few existing API functions have been renamed to improve clarity (e.g. +`oidnSetFilter1i` to `oidnSetFilterInt`) but the old function names are +still available as deprecated functions. When compiling legacy code, +warnings will be emitted for these deprecated functions. To upgrade to +the new API, please simply follow the instructions in the warnings. + +Some filter parameters have been also renamed (`alignment` to +`tileAlignment`, `overlap` to `tileOverlap`). When using the old names, +warnings will be emitted at runtime. + +### Building as a Static Library + +The support to build Open Image Denoise as a static library +(`OIDN_STATIC_LIB` CMake option) has been removed due to switching to a +modular library design, which was necessary for adding multi-vendor GPU +support. + +If the main reason for building as a static library would be is the +ability to use multiple versions of Open Image Denoise in the same +process, please use the existing `OIDN_API_NAMESPACE` CMake option +instead. With this feature all symbols of the library will be put into a +custom namespace, which can prevent symbol clashes. + +## Physical Devices + +Systems often have multiple different types of devices supported by Open +Image Denoise (CPUs and GPUs). The application can get the list of +supported *physical devices* and select which of these to use for +denoising. + +The number of supported physical devices can be queried with + +``` cpp +int oidnGetNumPhysicalDevices(); +``` + +The physical devices can be identified using IDs between 0 and +(`oidnGetNumPhysicalDevices()` \(-\) 1), and are ordered *approximately* +from fastest to slowest (e.g., ID of 0 corresponds to the likely fastest +physical device). Note that the reported number and order of physical +devices may change between application runs, so no assumptions should be +made about this list. + +Parameters of these physical devices can be queried using + +``` cpp +bool oidnGetPhysicalDeviceBool (int physicalDeviceID, const char* name); +int oidnGetPhysicalDeviceInt (int physicalDeviceID, const char* name); +unsigned int oidnGetPhysicalDeviceUInt (int physicalDeviceID, const char* name); +const char* oidnGetPhysicalDeviceString(int physicalDeviceID, const char* name); +const void* oidnGetPhysicalDeviceData (int physicalDeviceID, const char* name, + size_t* byteSize); +``` + +where `name` is the name of the parameter, and `byteSize` is the number +of returned bytes for data parameters. The following parameters can be +queried: + +| Type | Name | Description | +| :------- | :-------------------- | :---------------------------------------------------------------------------------------------------------------------------------- | +| `Int` | `type` | device type as an `OIDNDeviceType` value | +| `String` | `name` | name string | +| `Bool` | `uuidSupported` | device supports universally unique identifier (UUID) | +| `Data` | `uuid` | opaque UUID (`OIDN_UUID_SIZE` bytes, exists only if `uuidSupported` is `true`) | +| `Bool` | `luidSupported` | device supports locally unique identifier (UUID) | +| `Data` | `luid` | opaque LUID (`OIDN_LUID_SIZE` bytes, exists only if `luidSupported` is `true`) | +| `UInt` | `nodeMask` | bitfield identifying the node within a linked device adapter corresponding to the device (exists only if `luidSupported` is `true`) | +| `Bool` | `pciAddressSupported` | device supports PCI address | +| `Int` | `pciDomain` | PCI domain (exists only if `pciAddressSupported` is `true`) | +| `Int` | `pciBus` | PCI bus (exists only if `pciAddressSupported` is `true`) | +| `Int` | `pciDevice` | PCI device (exists only if `pciAddressSupported` is `true`) | +| `Int` | `pciFunction` | PCI function (exists only if `pciAddressSupported` is `true`) | + +Constant parameters supported by physical devices. + +## Devices + +Open Image Denoise has a *logical* device concept as well, or simply +referred to as *device*, which allows different components of the +application to use the Open Image Denoise API without interfering with +each other. Each physical device may be associated with one ore more +logical devices. A basic way to create a device is by calling + +``` 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 likely fastest device (same as physical device with ID 0) | +| `OIDN_DEVICE_TYPE_CPU` | CPU device | +| `OIDN_DEVICE_TYPE_SYCL` | SYCL device (requires a supported Intel GPU) | +| `OIDN_DEVICE_TYPE_CUDA` | CUDA device (requires a supported NVIDIA GPU) | +| `OIDN_DEVICE_TYPE_HIP` | HIP device (requires a supported AMD GPU) | + +Supported device types, i.e., valid constants of type `OIDNDeviceType`. + +If there are multiple supported devices of the specified type, an +implementation-dependent default will be selected. + +A device can be created by specifying a physical device ID as well using + +``` cpp +OIDNDevice oidnNewDeviceByID(int physicalDeviceID); +``` + +Applications can manually iterate over the list of physical devices and +select from them based on their properties but there are also some +built-in helper functions as well, which make creating a device by a +particular physical device property easier: + +``` cpp +OIDNDevice oidnNewDeviceByUUID(const void* uuid); +OIDNDevice oidnNewDeviceByLUID(const void* luid); +OIDNDevice oidnNewDeviceByPCIAddress(int pciDomain, int pciBus, int pciDevice, + int pciFunction); +``` + +These functions are particularly useful when the application needs +interoperability with a graphics API (e.g.Ā DX12, Vulkan). However, not +all of these properties may be supported by the intended physical device +(or drivers might even report inconsistent identifiers), so it is +recommended to select by more than one property, if possible. + +If the application requires interoperability with a particular compute +API (SYCL, CUDA, HIP), it is recommended to use one of the following +dedicated functions instead: + +``` cpp +OIDNDevice oidnNewSYCLDevice(const sycl::queue* queues, int numQueues); +OIDNDevice oidnNewCUDADevice(const int* deviceIDs, const cudaStream_t* streams, + int numPairs); +OIDNDevice oidnNewHIPDevice (const int* deviceIDs, const hipStream_t* streams, + int numPairs); +``` + +For SYCL, it is possible to pass one or more SYCL queues which will be +used by Open Image Denoise for all device operations. This is useful +when the application wants to use the same queues for both denoising and +its own operations (e.g.Ā rendering). Passing multiple queues is not +intended to be used for different physical devices but just for a single +SYCL root-device which consists of multiple sub-devices (e.g.Ā IntelĀ® +Data Center GPU Max Series having multiple Xe-Stacks/tiles). The only +supported SYCL backend is oneAPI Level Zero. + +For CUDA and HIP, pairs of CUDA/HIP device IDs and corresponding streams +can be specified but the current implementation supports only one pair. +Negative device IDs correspond to the default device, and a `NULL` +stream corresponds to the default stream on the corresponding device. +Open Image Denoise automatically sets and restores the current CUDA/HIP +device on the calling thread when necessary, thus the current device +does not have to be changed manually by the application. + +Once a device is created, you can call + +``` cpp +bool oidnGetDeviceBool(OIDNDevice device, const char* name); +void oidnSetDeviceBool(OIDNDevice device, const char* name, bool value); +int oidnGetDeviceInt (OIDNDevice device, const char* name); +void oidnSetDeviceInt (OIDNDevice device, const char* name, int value); +int oidnGetDeviceUInt(OIDNDevice device, const char* name); +void oidnSetDeviceUInt(OIDNDevice device, const char* name, unsigned int value); +``` + +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 | +| :----- | :----------------------- | ---------: | :---------------------------------------------------------------------------------------------------------------------------------------- | +| `Int` | `type` | *constant* | device type as an `OIDNDeviceType` value | +| `Int` | `version` | *constant* | combined version number (major.minor.patch) with two decimal digits per component | +| `Int` | `versionMajor` | *constant* | major version number | +| `Int` | `versionMinor` | *constant* | minor version number | +| `Int` | `versionPatch` | *constant* | patch version number | +| `Bool` | `systemMemorySupported` | *constant* | device can directly access memory allocated with the system allocator (e.g.Ā `malloc`) | +| `Bool` | `managedMemorySupported` | *constant* | device supports buffers created with managed storage (`OIDN_STORAGE_MANAGED`) | +| `Int` | `externalMemoryTypes` | *constant* | bitfield of `OIDNExternalMemoryTypeFlag` values representing the external memory types supported by the device | +| `Int` | `verbose` | 0 | verbosity level of the console output between 0ā€“4; 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 the library should use; 0 will set it automatically to get the best performance | +| `Bool` | `setAffinity` | `true` | enables thread affinitization (pinning software threads to hardware threads) if it is necessary for achieving optimal performance | + +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. + +Some functions may execute asynchronously with respect to the host. The +names of these functions are suffixed with `Async`. Asynchronous +operations are executed *in order* on the device but may not block on +the host. Eventually, it is necessary to wait for all asynchronous +operations to complete, which can be done by calling + +``` cpp +void oidnSyncDevice(OIDNDevice device); +``` + +Currently the CPU device does not support asynchronous execution, and +thus the asynchronous versions of functions will block as well. However, +`oidnSyncDevice` should be always called to ensure correctness on GPU +devices too, which do support asynchronous execution. + +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 should typically create only a single device object per +physical device (one for *all* CPUs or one per GPU) as creation can be +very expensive and additional device objects may incur a significant +memory overhead. If required differently, it should only use a small +number of device objects 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 (CPU/GPU) is not supported | +| `OIDN_ERROR_CANCELLED` | the operation was cancelled by the user | + +Possible error codes, i.e., valid constants of type `OIDNError`. + +### Environment Variables + +Open Image Denoise supports environment variables for overriding certain +settings at runtime, which can be useful for debugging and development: + +| Name | Description | +| :-------------------- | :---------------------------------------------------------------------------------------------------------------------------------- | +| `OIDN_DEFAULT_DEVICE` | overrides what physical device to use with `OIDN_DEVICE_TYPE_DEFAULT`; can be `cpu`, `sycl`, `cuda`, `hip`, or a physical device ID | +| `OIDN_DEVICE_CPU` | value of 0 disables CPU device support | +| `OIDN_DEVICE_SYCL` | value of 0 disables SYCL device support | +| `OIDN_DEVICE_CUDA` | value of 0 disables CUDA device support | +| `OIDN_DEVICE_HIP` | value of 0 disables HIP device support | +| `OIDN_NUM_THREADS` | overrides `numThreads` device parameter | +| `OIDN_SET_AFFINITY` | overrides `setAffinity` device parameter | +| `OIDN_NUM_SUBDEVICES` | overrides number of SYCL sub-devices to use (e.g.Ā for IntelĀ® Data Center GPU Max Series) | +| `OIDN_VERBOSE` | overrides `verbose` device parameter | + +Environment variables supported by Open Image Denoise. + +## Buffers + +Image data can be passed to Open Image Denoise either via pointers to +memory allocated and managed by the user or by creating buffer objects. +Regardless of which method is used, the data must be allocated in a way +that it is accessible by the device (either CPU or GPU). Using buffers +is typically the preferred approach because this ensures that the +allocation requirements are fulfilled regardless of device type. To +create a new data buffer with memory allocated and owned by the device, +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 (`byteSize`) are allocated at buffer +construction time and deallocated when the buffer is destroyed. The +memory is by default allocated as managed memory automatically migrated +between host and device, if supported, or as pinned host memory +otherwise. + +If this default buffer allocation is not suitable, a buffer can be +created with a manually specified storage mode as well: + +``` cpp +OIDNBuffer oidnNewBufferWithStorage(OIDNDevice device, size_t byteSize, OIDNStorage storage); +``` + +The supported storage modes are the following: + +| Name | Description | +| :----------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| `OIDN_STORAGE_UNDEFINED` | undefined storage mode | +| `OIDN_STORAGE_HOST` | pinned host memory, accessible by both host and device | +| `OIDN_STORAGE_DEVICE` | device memory, *not* accessible by the host | +| `OIDN_STORAGE_MANAGED` | automatically migrated between host and device, accessible by both (*not* supported by all devices, `managedMemorySupported` device parameter must be checked before use) | + +Supported storage modes for buffers, i.e., valid constants of type +`OIDNStorage`. + +Note that the host and device storage modes are supported by all devices +but managed storage is an optional feature. Before using managed +storage, the `managedMemorySupported` device parameter should be +queried. + +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* devPtr, size_t byteSize); +``` + +where `devPtr` points to user-managed device-accessible 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. +The user must also ensure that the memory is accessible by the device by +using allocation functions supported by the device +(e.g.Ā `sycl::malloc_device`, `cudaMalloc`, `hipMalloc`). + +Buffers can be also imported from graphics APIs as external memory, to +avoid expensive copying of data through host memory. Different types of +external memory can be imported from either POSIX file descriptors or +Win32 handles using + +``` cpp +OIDNBuffer oidnNewSharedBufferFromFD(OIDNDevice device, + OIDNExternalMemoryTypeFlag fdType, + int fd, size_t byteSize); + +OIDNBuffer oidnNewSharedBufferFromWin32Handle(OIDNDevice device, + OIDNExternalMemoryTypeFlag handleType, + void* handle, const void* name, size_t byteSize); +``` + +Before exporting memory from the graphics API, the application should +find a handle type which is supported by both the Open Image Denoise +device (see `externalMemoryTypes` device parameter) and the graphics +API. Note that different GPU vendors may support different handle types. +To ensure compatibility with all device types, applications should +support at least `OIDN_EXTERNAL_MEMORY_TYPE_FLAG_OPAQUE_FD` on Windows +and both `OIDN_EXTERNAL_MEMORY_TYPE_FLAG_OPAQUE_FD` and +`OIDN_EXTERNAL_MEMORY_TYPE_FLAG_DMA_BUF` on Linux. All possible external +memory types are listed in the table below. + +| Name | Description | +| :-------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------- | +| `OIDN_EXTERNAL_MEMORY_TYPE_FLAG_NONE` | | +| `OIDN_EXTERNAL_MEMORY_TYPE_FLAG_OPAQUE_FD` | opaque POSIX file descriptor handle (recommended on Linux) | +| `OIDN_EXTERNAL_MEMORY_TYPE_FLAG_DMA_BUF` | file descriptor handle for a Linux dma\_buf (recommended on Linux) | +| `OIDN_EXTERNAL_MEMORY_TYPE_FLAG_OPAQUE_WIN32` | NT handle (recommended on Windows) | +| `OIDN_EXTERNAL_MEMORY_TYPE_FLAG_OPAQUE_WIN32_KMT` | global share (KMT) handle | +| `OIDN_EXTERNAL_MEMORY_TYPE_FLAG_D3D11_TEXTURE` | NT handle returned by `IDXGIResource1::CreateSharedHandle` referring to a Direct3D 11 texture resource | +| `OIDN_EXTERNAL_MEMORY_TYPE_FLAG_D3D11_TEXTURE_KMT` | global share (KMT) handle returned by `IDXGIResource::GetSharedHandle` referring to a Direct3D 11 texture resource | +| `OIDN_EXTERNAL_MEMORY_TYPE_FLAG_D3D11_RESOURCE` | NT handle returned by `IDXGIResource1::CreateSharedHandle` referring to a Direct3D 11 resource | +| `OIDN_EXTERNAL_MEMORY_TYPE_FLAG_D3D11_RESOURCE_KMT` | global share (KMT) handle returned by `IDXGIResource::GetSharedHandle` referring to a Direct3D 11 resource | +| `OIDN_EXTERNAL_MEMORY_TYPE_FLAG_D3D12_HEAP` | NT handle returned by `ID3D12Device::CreateSharedHandle` referring to a Direct3D 12 heap resource | +| `OIDN_EXTERNAL_MEMORY_TYPE_FLAG_D3D12_RESOURCE` | NT handle returned by `ID3D12Device::CreateSharedHandle` referring to a Direct3D 12 committed resource | + +Supported external memory type flags, i.e., valid constants of type +`OIDNExternalMemoryTypeFlag`. + +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); +``` + +The size of in bytes and storage mode of the buffer can be queried using + +``` cpp +size_t oidnGetBufferSize (OIDNBuffer buffer); +OIDNStorage oidnGetBufferStorage(OIDNBuffer buffer); +``` + +It is possible to get a pointer directly to the buffer data, which is +usually the preferred way to access the data stored in the buffer: + +``` cpp +void* oidnGetBufferData(OIDNBuffer buffer); +``` + +However, accessing the data on the host through this pointer is possible +only if the buffer was created with a storage mode that enables this, +i.e., any mode *except* `OIDN_STORAGE_DEVICE`. Note that a `NULL` +pointer may be returned if the buffer is empty or getting a pointer to +data with device storage is not supported by the device. + +In some cases better performance can be achieved by using device storage +for buffers. Such data can be accessed on the host by copying to/from +host memory (including pageable system memory) using the following +functions: + +``` cpp +void oidnReadBuffer(OIDNBuffer buffer, + size_t byteOffset, size_t byteSize, void* dstHostPtr); + +void oidnWriteBuffer(OIDNBuffer buffer, + size_t byteOffset, size_t byteSize, const void* srcHostPtr); +``` + +These functions will always block until the read/write operation has +been completed, which is often suboptimal. The following functions may +execute the operation asynchronously if it is supported by the device +(GPUs), or still block otherwise (CPUs): + +``` cpp +void oidnReadBufferAsync(OIDNBuffer buffer, + size_t byteOffset, size_t byteSize, void* dstHostPtr); + +void oidnWriteBufferAsync(OIDNBuffer buffer, + size_t byteOffset, size_t byteSize, const void* srcHostPtr); +``` + +When copying asynchronously, the user must ensure correct +synchronization with the device by calling `oidnSyncDevice` before +accessing the copied data or releasing the buffer. Failure to do so will +result in undefined behavior. + +### 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 floating-point scalar | +| `OIDN_FORMAT_FLOAT[234]` | 32-bit floating-point \[234\]-element vector | +| `OIDN_FORMAT_HALF` | 16-bit floating-point scalar | +| `OIDN_FORMAT_HALF[234]` | 16-bit floating-point \[234\]-element vector | + +Supported data formats, i.e., valid constants of type `OIDNFormat`. + +## Filters + +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. + +Creating filter objects can be very expensive, therefore it is +*strongly* recommended to reuse the same filter for denoising as many +images as possible, as long as the these images have the same same size, +format, and features (i.e., only the memory locations and pixel values +may be different). Otherwise (e.g.Ā for images with different +resolutions), reusing the same filter would not have any benefits. + +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 images, and potentially setting other parameter values as +well. + +To set image parameters of a 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 pixelByteStride, size_t rowByteStride); + +void oidnSetSharedFilterImage(OIDNFilter filter, const char* name, + void* devPtr, OIDNFormat format, + size_t width, size_t height, + size_t byteOffset, + size_t pixelByteStride, size_t rowByteStride); +``` + +It is possible to specify either a data buffer object (`buffer` +argument) with the `oidnSetFilterImage` function, or directly a pointer +to user-managed device-accessible data (`devPtr` argument) with the +`oidnSetSharedFilterImage` function. Regardless of whether a buffer or a +pointer is specified, the data *must* be accessible to the device. The +easiest way to guarantee this regardless of the device type (CPU or GPU) +is using buffer objects. + +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 (`pixelByteStride` +argument) and the row stride (`rowByteStride` argument), in number of +bytes. + +If the pixels and/or rows are stored contiguously (tightly packed +without any gaps), you can set `pixelByteStride` and/or `rowByteStride` +to 0 to let the library compute the actual strides automatically, as a +convenience. + +Images support only `FLOAT` and `HALF` pixel formats with up to 3 +channels. Custom image layouts with extra channels (e.g.Ā alpha channel) +or other data are supported as well by specifying a non-zero pixel +stride. This way, expensive image layout conversion and copying can be +avoided but the extra channels will be ignored by the filter. If these +channels also need to be denoised, separate filters can be used. + +To unset a previously set image parameter, returning it to a state as if +it had not been set, call + +``` cpp +void oidnRemoveFilterImage(OIDNFilter filter, const char* name); +``` + +Some special data used by filters are opaque/untyped (e.g.Ā trained model +weights blobs), which can be specified with the +`oidnSetSharedFilterData` function: + +``` cpp +void oidnSetSharedFilterData(OIDNFilter filter, const char* name, + void* hostPtr, size_t byteSize); +``` + +This data (`hostPtr`) must be accessible to the *host*, therefore system +memory allocation is suitable (i.e., there is no reason to use buffer +objects for allocation). + +Modifying the contents of an opaque data parameter after setting it as a +filter parameter is allowed but the filter needs to be notified that the +data has been updated by calling + +``` cpp +void oidnUpdateFilterData(OIDNFilter filter, const char* name); +``` + +Unsetting an opaque data parameter can be performed with + +``` cpp +void oidnRemoveFilterData(OIDNFilter filter, const char* name); +``` + +Filters may have parameters other than buffers as well, which you can +set and get using the following functions: + +``` cpp +bool oidnGetFilterBool (OIDNFilter filter, const char* name); +void oidnSetFilterBool (OIDNFilter filter, const char* name, bool value); +int oidnGetFilterInt (OIDNFilter filter, const char* name); +void oidnSetFilterInt (OIDNFilter filter, const char* name, int value); +float oidnGetFilterFloat(OIDNFilter filter, const char* name); +void oidnSetFilterFloat(OIDNFilter filter, const char* name, float value); +``` + +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 attempt to cancel the filter operation as soon +as possible, and if that is fulfilled, it will raise an +`OIDN_ERROR_CANCELLED` error. + +Please note that using a progress monitor callback function introduces +some overhead, which may be significant on GPU devices, hurting +performance. Therefore we recommend progress monitoring only for offline +denoising, when denoising an image is expected to take several seconds. + +After setting all necessary parameters for the filter, the changes must +be committed by calling + +``` cpp +void oidnCommitFilter(OIDNFilter filter); +``` + +The parameters can be updated after committing the filter, but it must +be re-committed for any new changes to take effect. Committing major +changes to the filter (e.g.Ā setting new image parameters, changing the +image resolution) can be expensive, and thus should not be done +frequently (e.g.Ā per frame). + +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. + +This function will always block until the filtering operation has been +completed. The following function may execute the operation +asynchronously if it is supported by the device (GPUs), or block +otherwise (CPUs): + +``` cpp +void oidnExecuteFilterAsync(OIDNFilter filter); +``` + +For filters created on a SYCL device it is also possible to specify +dependent SYCL events (`depEvents` and `numDepEvents` arguments, may be +`NULL`/0) and get a completion event as well (`doneEvent` argument, may +be `NULL`): + +``` cpp +void oidnExecuteSYCLFilterAsync(OIDNFilter filter, + const sycl::event* depEvents, int numDepEvents, + sycl::event* doneEvent); +``` + +When filtering asynchronously, the user must ensure correct +synchronization with the device by calling `oidnSyncDevice` before +accessing the output image data or releasing the filter. Failure to do +so will result in undefined behavior. + +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 convolutional neural network +(CNN) and comes with a set of pre-trained models that work well with a +wide range of ray tracing based renderers and noise levels. + +![](https://openimagedenoise.github.io/images/mazda_4spp_input.jpg) +Example noisy beauty image rendered using unidirectional path tracing +(4 samples per pixel). *Scene by +Evermotion.* + +![](https://openimagedenoise.github.io/images/mazda_4spp_oidn.jpg) +Example output beauty image denoised using prefiltered auxiliary +feature images (albedo and normal) +too. + +For denoising *beauty* images, it accepts either a low dynamic range +(LDR) or high dynamic range (HDR) image (`color`) as the main input +image. In addition to this, it also accepts *auxiliary feature* images, +`albedo` and `normal`, which are optional inputs that usually improve +the denoising quality significantly, preserving more details. + +It is possible to denoise auxiliary images as well, in which case only +the respective auxiliary image has to be specified as input, instead of +the beauty image. This can be done as a *prefiltering* step to further +improve the quality of the denoised beauty 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 parameters listed +in the table below. All specified images must have the same dimensions. +The output image can be one of the input images (i.e.Ā in-place denoising +is supported). See section [Examples](#examples) for simple code +snippets that demonstrate the usage of the filter. + +| Type | Name | Default | Description | +| :------ | :-------------- | ---------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `Image` | `color` | *optional* | input beauty image (1ā€“3 channels, LDR values in \[0, 1\] or HDR values in \[0, +āˆž), values being interpreted such that, after scaling with the `inputScale` parameter, a value of 1 corresponds to a luminance level of 100 cd/mĀ²) | +| `Image` | `albedo` | *optional* | input auxiliary image containing the albedo per pixel (3 channels, values in \[0, 1\]) | +| `Image` | `normal` | *optional* | input auxiliary image containing the shading normal per pixel (3 channels, world-space or view-space vectors with arbitrary length, values in \[-1, 1\]) | +| `Image` | `output` | *required* | output image (1ā€“3 channels); can be one of the input images | +| `Bool` | `hdr` | `false` | the main input image is HDR | +| `Bool` | `srgb` | `false` | the main input image is encoded with the sRGB (or 2.2 gamma) curve (LDR only) or is linear; the output will be encoded with the same curve | +| `Float` | `inputScale` | NaN | scales values in the main input image before filtering, without scaling the output too, which can be used to map color or auxiliary feature values to the expected range, e.g.Ā for mapping HDR values to physical units (which affects the quality of the output but *not* the range of the output values); if set to NaN, the scale is computed implicitly for HDR images or set to 1 otherwise | +| `Bool` | `cleanAux` | `false` | the auxiliary feature (albedo, normal) images are noise-free; recommended for highest quality but should *not* be enabled for noisy auxiliary images to avoid residual noise | +| `Int` | `quality` | high | image quality mode as an `OIDNQuality` value | +| `Data` | `weights` | *optional* | trained model weights blob | +| `Int` | `maxMemoryMB` | \-1 | if set to \>= 0, an attempt will be made to limit the memory usage below the specified amount in megabytes at the potential cost of slower performance but actual memory usage may be higher (the target may not be achievable or the device may not support this feature at all); otherwise memory usage will be limited to an unspecified device-dependent amount | +| `Int` | `tileAlignment` | *constant* | when manually denoising in tiles, the tile size and offsets should be multiples of this amount of pixels to avoid artifacts; when denoising HDR images `inputScale` *must* be set by the user to avoid seam artifacts | +| `Int` | `tileOverlap` | *constant* | when manually denoising in tiles, the tiles should overlap by this amount of pixels | + +Parameters supported by the `RT` filter. + +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, this +issue can be usually 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. Ideally, these should be completely +noise-free. If this is the case, this should be hinted to the filter +using the `cleanAux` parameter to ensure the highest possible image +quality. But this parameter should be used with care: if enabled, any +noise present in the auxiliary images will end up in the denoised image +as well, as residual noise. Thus, `cleanAux` should be enabled only if +the auxiliary images are guaranteed to be noise-free. + +Usually it is difficult to provide clean feature images, and some +residual noise might be present in the output even with `cleanAux` being +disabled. To eliminate this noise and to even improve the sharpness of +texture details, the auxiliary images should be first denoised in a +prefiltering step, as mentioned earlier. Then, these denoised auxiliary +images could be used for denoising the beauty image. Since these are now +noise-free, the `cleanAux` parameter should be enabled. See section +[Denoising with prefiltering (C++11 +API)](#denoising-with-prefiltering-c11-api) for a simple code example. +Prefiltering makes denoising much more expensive but if there are +multiple color AOVs to denoise, the prefiltered auxiliary images can be +reused for denoising multiple AOVs, amortizing the cost of the +prefiltering step. + +Thus, for final-frame denoising, where the best possible image quality +is required, it is recommended to prefilter the auxiliary features if +they are noisy and enable the `cleanAux` parameter. Denoising with noisy +auxiliary features should be reserved for previews and interactive +rendering. + +All auxiliary images should use the same pixel reconstruction filter as +the beauty image. Using a properly anti-aliased beauty image but aliased +albedo or normal images will likely introduce artifacts around edges. + +#### Albedos + +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. + +![](https://openimagedenoise.github.io/images/mazda_firsthit_512spp_albedo.jpg) +Example albedo image obtained using the first hit. Note that the +albedos of all transparent surfaces are +1. + +![](https://openimagedenoise.github.io/images/mazda_nondeltahit_512spp_albedo.jpg) +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 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 +flexible 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. + +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. The latter usually works +better but only if it does not introduce too much noise or the albedo is +prefiltered. If noise is an issue, 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. 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. + +#### Normals + +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. + +![](https://openimagedenoise.github.io/images/mazda_firsthit_512spp_normal.jpg) +Example normal image obtained using the first hit (the values are +actually in \[āˆ’1, 1\] but were mapped to \[0, 1\] for illustration +purposes). + +![](https://openimagedenoise.github.io/images/mazda_nondeltahit_512spp_normal.jpg) +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. + +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 the +\[-1, 1\] range (i.e.Ā normals mapped to \[0, 1\] are *not* acceptable +and must be remapped to \[āˆ’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). + +#### Quality + +The filter supports setting an image quality mode, which determines +whether to favor quality, performance, or have a balanced solution +between the two. The supported quality modes are listed in the following +table. + +| Name | Description | +| :---------------------- | :----------------------------------------------------------------- | +| `OIDN_QUALITY_DEFAULT` | default quality | +| `OIDN_QUALITY_BALANCED` | balanced quality/performance (for interactive/real-time rendering) | +| `OIDN_QUALITY_HIGH` | high quality (for final-frame rendering); *default* | + +Supported image quality modes, i.e., valid constants of type +`OIDNQuality`. + +By default filtering is performed in high quality mode, which is +recommended for final-frame rendering. Using this setting the results +have the same high quality regardless of what kind of device (CPU or +GPU) is used. However, due to significant hardware architecture +differences between devices, there might be small numerical differences +between the produced outputs. + +The balanced quality mode is very close in image quality to the high +quality mode except that lower numerical precision is used, if this is +supported by the device. This may result in significantly higher +performance on some devices but on others there might be no difference +at all due to hardware specifics. This mode is recommended for +interactive and real-time rendering. + +Note that in balanced quality mode a higher variation in image quality +should be expected across devices. + +#### Weights + +Instead of using the built-in trained models for filtering, it is also +possible to specify user-trained models at runtime. This can be achieved +by passing the model *weights* blob corresponding to the specified set +of features and other filter parameters, produced by the included +training tool. See Section [Training](#training) for details. + +### RTLightmap + +The `RTLightmap` filter is a variant of the `RT` filter optimized for +denoising HDR and normalized directional (e.g.Ā spherical harmonics) +lightmaps. It does not support LDR images. + +The filter can be created by passing `"RTLightmap"` to the +`oidnNewFilter` function as the filter type. The filter supports the +following parameters: + +| Type | Name | Default | Description | +| :------ | :-------------- | ---------: | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| `Image` | `color` | *required* | input beauty image (3 channels, HDR values in \[0, +āˆž), interpreted such that, after scaling with the `inputScale` parameter, a value of 1 corresponds to a luminance level of 100 cd/mĀ²; directional values in \[-1, 1\]) | +| `Image` | `output` | *required* | output image (3 channels); can be one of the input images | +| `Bool` | `directional` | `false` | whether the input contains normalized coefficients (in \[-1, 1\]) of a directional lightmap (e.g.Ā normalized L1 or higher spherical harmonics band with the L0 band divided out); if the range of the coefficients is different from \[-1, 1\], the `inputScale` parameter can be used to adjust the range without changing the stored values | +| `Float` | `inputScale` | NaN | scales input color values before filtering, without scaling the output too, which can be used to map color values to the expected range, e.g.Ā for mapping HDR values to physical units (which affects the quality of the output but *not* the range of the output values); if set to NaN, the scale is computed implicitly for HDR images or set to 1 otherwise | +| `Int` | `quality` | high | image quality mode as an `OIDNQuality` value | +| `Data` | `weights` | *optional* | trained model weights blob | +| `Int` | `maxMemoryMB` | \-1 | if set to \>= 0, an attempt will be made to limit the memory usage below the specified amount in megabytes at the potential cost of slower performance but actual memory usage may be higher (the target may not be achievable or the device may not support this feature at all); otherwise memory usage will be limited to an unspecified device-dependent amount | +| `Int` | `tileAlignment` | *constant* | when manually denoising in tiles, the tile size and offsets should be multiples of this amount of pixels to avoid artifacts; when denoising HDR images `inputScale` *must* be set by the user to avoid seam artifacts | +| `Int` | `tileOverlap` | *constant* | when manually denoising in tiles, the tiles should overlap by this amount of pixels | + +Parameters supported by the `RTLightmap` filter. + +# Examples + +Intel Open Image Denoise ships with a couple of simple example +applications. + +## oidnDenoise + +`oidnDenoise` is a minimal working example demonstrating how to use +Intel Open Image Denoise, which can be found at `apps/oidnDenoise.cpp`. +It 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). By default 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. To enable other image formats (e.g.Ā OpenEXR, PNG) as well, the +project has to be rebuilt with OpenImageIO support enabled. + +Running `oidnDenoise` without any arguments or the `-h` argument will +bring up a list of command-line options. + +## oidnBenchmark + +`oidnBenchmark` is a basic command-line benchmarking application for +measuring denoising speed, which can be found at +`apps/oidnBenchmark.cpp`. + +Running `oidnBenchmark` with the `-h` argument will bring up a list of +command-line options. + +# Training + +The Intel Open Image Denoise source distribution includes a Python-based +neural network training toolkit (located in the `training` directory), +which can be used to train the denoising filter models with image +datasets provided by the user. This is an advanced feature of the +library which usage requires some background knowledge of machine +learning and basic familiarity with deep learning frameworks and +toolkits (e.g.Ā PyTorch or TensorFlow, TensorBoard). + +The training toolkit consists of the following command-line scripts: + + - `preprocess.py`: Preprocesses training and validation datasets. + + - `train.py`: Trains a model using preprocessed datasets. + + - `infer.py`: Performs inference on a dataset using the specified + training result. + + - `export.py`: Exports a training result to the runtime model weights + format. + + - `find_lr.py`: Tool for finding the optimal minimum and maximum + learning rates. + + - `visualize.py`: Invokes TensorBoard for visualizing statistics of a + training result. + + - `split_exr.py`: Splits a multi-channel EXR image into multiple + feature images. + + - `convert_image.py`: Converts a feature image to a different image + format. + + - `compare_image.py`: Compares two feature images using the specified + quality metrics. + +## Prerequisites + +Before you can run the training toolkit you need the following +prerequisites: + + - Linux (other operating systems are currently not supported) + + - Python 3.7 or later + + - [PyTorch](https://pytorch.org/) 1.8 or later + + - [NumPy](https://numpy.org/) 1.19 or later + + - [OpenImageIO](http://openimageio.org/) 2.1 or later + + - [TensorBoard](https://www.tensorflow.org/tensorboard) 2.4 or later + (*optional*) + +## Devices + +Most scripts in the training toolkit support selecting what kind of +device (e.g.Ā CPU, GPU) to use for the computations (`--device` or `-d` +option). If multiple devices of the same kind are available +(e.g.Ā multiple GPUs), the user can specify which one of these to use +(`--device_id` or `-k` option). Additionally, some scripts, like +`train.py`, support data-parallel execution on multiple devices for +faster performance (`--num_devices` or `-n` option). + +## Datasets + +A dataset should consist of a collection of noisy and corresponding +noise-free reference images. It is possible to have more than one noisy +version of the same image in the dataset, e.g.Ā rendered at different +samples per pixel and/or using different seeds. + +The training toolkit expects to have all datasets (e.g.Ā training, +validation) in the same parent directory (e.g.Ā `data`). Each dataset is +stored in its own subdirectory (e.g.Ā `train`, `valid`), which can have +an arbitrary name. + +The images must be stored in [OpenEXR](https://www.openexr.com/) format +(`.exr` files), and the filenames must have a specific format but the +files can be stored in an arbitrary directory structure inside the +dataset directory. The only restriction is that all versions of an image +(noisy images and the reference image) must be located in the same +subdirectory. Each feature of an image (e.g.Ā color, albedo) must be +stored in a separate image file, i.e. multi-channel EXR image files are +not supported. If you have multi-channel EXRs, you can split them into +separate images per feature using the included `split_exr.py` tool. + +An image filename must consist of a base name, a suffix with the number +of samples per pixel or whether it is the reference image +(e.g.Ā `_0128spp`, `_ref`), the feature type extension (e.g.Ā `.hdr`, +`.alb`), and the image format extension (`.exr`). The exact filename +format as a regular expression is the following: + +``` regexp +.+_([0-9]+(spp)?|ref|reference|gt|target)\.(hdr|ldr|sh1[xyz]|alb|nrm)\.exr +``` + +The number of samples per pixel should be padded with leading zeros to +have a fixed number of digits. If the reference image is not explicitly +named as such (i.e.Ā has the number of samples instead), the image with +the most samples per pixel will be considered the reference. + +The following image features are supported: + +| Feature | Description | Channels | File extension | +| ------- | :---------------------------------------- | :----------- | :------------------------------------ | +| `hdr` | color (HDR) | 3 | `.hdr.exr` | +| `ldr` | color (LDR) | 3 | `.ldr.exr` | +| `sh1` | color (normalized L1 spherical harmonics) | 3 Ɨ 3 images | `.sh1x.exr`, `.sh1y.exr`, `.sh1z.exr` | +| `alb` | albedo | 3 | `.alb.exr` | +| `nrm` | normal | 3 | `.nrm.exr` | + +Image features supported by the training toolkit. + +The following directory tree demonstrates an example root dataset +directory (`data`) containing one dataset (`rt_train`) with HDR color +and albedo feature images: + + data + `-- rt_train + |-- scene1 + | |-- view1_0001.alb.exr + | |-- view1_0001.hdr.exr + | |-- view1_0004.alb.exr + | |-- view1_0004.hdr.exr + | |-- view1_8192.alb.exr + | |-- view1_8192.hdr.exr + | |-- view2_0001.alb.exr + | |-- view2_0001.hdr.exr + | |-- view2_8192.alb.exr + | `-- view2_8192.hdr.exr + |-- scene2_000008spp.alb.exr + |-- scene2_000008spp.hdr.exr + |-- scene2_000064spp.alb.exr + |-- scene2_000064spp.hdr.exr + |-- scene2_reference.alb.exr + `-- scene2_reference.hdr.exr + +## Preprocessing (preprocess.py) + +Training and validation datasets can be used only after preprocessing +them using the `preprocess.py` script. This will convert the specified +training (`--train_data` or `-t` option) and validation datasets +(`--valid_data` or `-v` option) located in the root dataset directory +(`--data_dir` or `-D` option) to a format that can be loaded more +efficiently during training. All preprocessed datasets will be stored in +a root preprocessed dataset directory (`--preproc_dir` or `-P` option). + +The preprocessing script requires the set of image features to include +in the preprocessed dataset as command-line arguments. Only these +specified features will be available for training but it is not required +to use all of them at the same time. Thus, a single preprocessed dataset +can be reused for training multiple models with different combinations +of the preprocessed features. + +By default, all input features are assumed to be noisy, including the +auxiliary features (e.g.Ā albedo, normal), each having versions at +different samples per pixel. However, it is also possible to train with +noise-free auxiliary features, in which case the reference auxiliary +features are used instead of the various noisy ones (`--clean_aux` +option). + +Preprocessing also depends on the filter that will be trained +(e.g.Ā determines which HDR/LDR transfer function has to be used), which +should be also specified (`--filter` or `-f` option). The alternative is +to manually specify the transfer function (`--transfer` or `-x` option) +and other filter-specific parameters, which could be useful for training +custom filters. + +For example, to preprocess the training and validation datasets +(`rt_train` and `rt_valid`) with HDR color, albedo, and normal image +features, for training the `RT` filter, the following command can be +used: + + ./preprocess.py hdr alb nrm --filter RT --train_data rt_train --valid_data rt_valid + +It is possible to preprocess the same dataset multiple times, with +possibly different combinations of features and options. The training +script will use the most suitable and most recent preprocessed version +depending on the training parameters. + +For more details about using the preprocessing script, including other +options, please have a look at the help message: + + ./preprocess.py -h + +## Training (train.py) + +The filters require separate trained models for each supported +combination of input features. Thus, depending on which combinations of +features the user wants to support for a particular filter, one or more +models have to be trained. + +After preprocessing the datasets, it is possible to start training a +model using the `train.py` script. Similar to the preprocessing script, +the input features must be specified (could be a subset of the +preprocessed features), and the dataset names, directory paths, and the +filter can be also passed. + +The tool will produce a training *result*, the name of which can be +either specified (`--result` or `-r` option) or automatically generated +(by default). Each result is stored in its own subdirectory, and these +are located in a common parent directory (`--results_dir` or `-R` +option). If a training result already exists, the tool will resume +training that result from the latest checkpoint. + +The default training hyperparameters should work reasonably well in +general, but some adjustments might be necessary for certain datasets to +attain optimal performance, most importantly: the number of epochs +(`--num_epochs` or `-e` option), the global mini-batch size +(`--batch_size` or `-b` option), and the learning rate. The training +tool uses a one-cycle learning rate schedule with cosine annealing, +which can be configured by setting the base learning rate +(`--learning_rate` or `--lr` option), the maximum learning rate +(`--max_learning_rate` or `--max_lr` option), and the percentage of the +cycle spent increasing the learning rate (`--learning_rate_warmup` or +`--lr_warmup` option). + +Example usage: + + ./train.py hdr alb --filter RT --train_data rt_train --valid_data rt_valid --result rt_hdr_alb + +For finding the optimal learning rate range, we recommend using the +included `find_lr.py` script, which trains one epoch using an increasing +learning rate and logs the resulting losses in a comma-separated values +(CSV) file. Plotting the loss curve can show when the model starts to +learn (the base learning rate) and when it starts to diverge (the +maximum learning rate). + +The model is evaluated with the validation dataset at regular intervals +(`--num_valid_epochs` option), and checkpoints are also regularly +created (`--num_save_epochs` option) to save training progress. Also, +some statistics are logged (e.g.Ā training and validation losses, +learning rate) per epoch, which can be later visualized with TensorBoard +by running the `visualize.py` script, e.g.: + + ./visualize.py --result rt_hdr_alb + +Training is performed with mixed precision (FP16 and FP32) by default, +if it supported by the hardware, which makes training faster and use +less memory. However, in some rare cases this might cause some +convergence issues. The training precision can be manually set to FP32 +if necessary (`--precision` or `-p` option). + +## Inference (infer.py) + +A training result can be tested by performing inference on an image +dataset (`--input_data` or `-i` option) using the `infer.py` script. The +dataset does *not* have to be preprocessed. In addition to the result to +use, it is possible to specify which checkpoint to load as well (`-e` or +`--num_epochs` option). By default the latest checkpoint is loaded. + +The tool saves the output images in a separate directory (`--output_dir` +or `-O` option) in the requested formats (`--format` or `-F` option). It +also evaluates a set of image quality metrics (`--metric` or `-M` +option), e.g.Ā PSNR, SSIM, for images that have reference images +available. All metrics are computed in tonemapped non-linear sRGB space. +Thus, HDR images are first tonemapped (with Naughty Dogā€™s Filmic +Tonemapper from John Hableā€™s *Uncharted 2: HDR Lighting* presentation) +and converted to sRGB before evaluating the metrics. + +Example usage: + + ./infer.py --result rt_hdr_alb --input_data rt_test --format exr png --metric ssim + +The inference tool supports prefiltering of auxiliary features as well, +which can be performed by specifying the list of training results for +each feature to prefilter (`--aux_results` or `-a` option). This is +primarily useful for evaluating the quality of models trained with clean +auxiliary features. + +## Exporting Results (export.py) + +The training result produced by the `train.py` script cannot be +immediately used by the main library. It has to be first exported to the +runtime model weights format, a *Tensor Archive* (TZA) file. Running the +`export.py` script for a training result (and optionally a checkpoint +epoch) will create a binary `.tza` file in the directory of the result, +which can be either used at runtime through the API or it can be +included in the library build by replacing one of the built-in weights +files. + +Example usage: + + ./export.py --result rt_hdr_alb + +## Image Conversion and Comparison + +In addition to the already mentioned `split_exr.py` script, the toolkit +contains a few other image utilities as well. + +`convert_image.py` converts a feature image to a different image format +(and/or a different feature, e.g.Ā HDR color to LDR), performing +tonemapping and other transforms as well if needed. For HDR images the +exposure can be adjusted by passing a linear exposure scale +(`--exposure` or `-E` option). Example usage: + + ./convert_image.py view1_0004.hdr.exr view1_0004.png --exposure 2.5 + +The `compare_image.py` script compares two feature images (preferably +having the dataset filename format to correctly detect the feature) +using the specified image quality metrics, similar to the `infer.py` +tool. Example usage: + + ./compare_image.py view1_0004.hdr.exr view1_8192.hdr.exr --exposure 2.5 --metric mse ssim + +1. For example, if Intel Open Image Denoise is in `~/Projects/oidn`, + ISPC will also be searched in `~/Projects/ispc-v1.14.1-linux` diff --git a/thirdparty/OpenImageDenoise/share/doc/OpenImageDenoise/readme.pdf b/thirdparty/OpenImageDenoise/share/doc/OpenImageDenoise/readme.pdf new file mode 100644 index 0000000..1bc5c1e Binary files /dev/null and b/thirdparty/OpenImageDenoise/share/doc/OpenImageDenoise/readme.pdf differ diff --git a/thirdparty/OpenImageDenoise/share/doc/OpenImageDenoise/third-party-programs-DPCPP.txt b/thirdparty/OpenImageDenoise/share/doc/OpenImageDenoise/third-party-programs-DPCPP.txt new file mode 100644 index 0000000..0e55972 --- /dev/null +++ b/thirdparty/OpenImageDenoise/share/doc/OpenImageDenoise/third-party-programs-DPCPP.txt @@ -0,0 +1,110 @@ + +The oneAPI DPC++ Compiler can be found here: + + https://github.com/intel/llvm + +It uses various components with following licenses: + + https://github.com/intel/llvm/blob/master/flang/LICENSE.TXT + https://github.com/intel/llvm/blob/master/compiler-rt/LICENSE.TXT + https://github.com/intel/llvm/blob/master/mlir/LICENSE.TXT + https://github.com/intel/llvm/blob/master/libclc/LICENSE.TXT + https://github.com/intel/llvm/blob/master/libcxxabi/LICENSE.TXT + https://github.com/intel/llvm/blob/master/lld/LICENSE.TXT + https://github.com/intel/llvm/blob/master/cross-project-tests/debuginfo-tests/dexter/LICENSE.txt + https://github.com/intel/llvm/blob/master/libc/LICENSE.TXT + https://github.com/intel/llvm/blob/master/clang-tools-extra/LICENSE.TXT + https://github.com/intel/llvm/blob/master/clang-tools-extra/clang-tidy/cert/LICENSE.TXT + https://github.com/intel/llvm/blob/master/clang-tools-extra/clang-tidy/hicpp/LICENSE.TXT + https://github.com/intel/llvm/blob/master/lldb/LICENSE.TXT + https://github.com/intel/llvm/blob/master/lldb/third_party/Python/module/ptyprocess-0.6.0/LICENSE + https://github.com/intel/llvm/blob/master/lldb/third_party/Python/module/six/LICENSE + https://github.com/intel/llvm/blob/master/lldb/third_party/Python/module/pexpect-4.6/LICENSE + https://github.com/intel/llvm/blob/master/polly/LICENSE.TXT + https://github.com/intel/llvm/blob/master/polly/lib/External/isl/LICENSE + https://github.com/intel/llvm/blob/master/polly/lib/External/isl/imath/LICENSE + https://github.com/intel/llvm/blob/master/polly/tools/GPURuntime/LICENSE.TXT + https://github.com/intel/llvm/blob/master/sycl/LICENSE.TXT + https://github.com/intel/llvm/blob/master/llvm-spirv/LICENSE.TXT + https://github.com/intel/llvm/blob/master/bolt/LICENSE.TXT + https://github.com/intel/llvm/blob/master/pstl/LICENSE.TXT + https://github.com/intel/llvm/blob/master/clang/LICENSE.TXT + https://github.com/intel/llvm/blob/master/llvm/utils/lit/LICENSE.TXT + https://github.com/intel/llvm/blob/master/llvm/utils/unittest/googletest/LICENSE.TXT + https://github.com/intel/llvm/blob/master/llvm/utils/unittest/googlemock/LICENSE.txt + https://github.com/intel/llvm/blob/master/llvm/LICENSE.TXT + https://github.com/intel/llvm/blob/master/llvm/include/llvm/Support/LICENSE.TXT + https://github.com/intel/llvm/blob/master/llvm/lib/Support/BLAKE3/LICENSE + https://github.com/intel/llvm/blob/master/llvm/test/YAMLParser/LICENSE.txt + https://github.com/intel/llvm/blob/master/libunwind/LICENSE.TXT + https://github.com/intel/llvm/blob/master/openmp/LICENSE.TXT + https://github.com/intel/llvm/blob/master/openmp/runtime/src/thirdparty/ittnotify/LICENSE.txt + https://github.com/intel/llvm/blob/master/third-party/benchmark/LICENSE + https://github.com/intel/llvm/blob/master/libcxx/LICENSE.TXT + +The following people and companies contributed to the LLVM project: + + https://github.com/intel/llvm/blob/master/compiler-rt/CREDITS.TXT + https://github.com/intel/llvm/blob/master/libclc/CREDITS.TXT + https://github.com/intel/llvm/blob/master/libcxxabi/CREDITS.TXT + https://github.com/intel/llvm/blob/master/polly/CREDITS.txt + https://github.com/intel/llvm/blob/master/pstl/CREDITS.txt + https://github.com/intel/llvm/blob/master/llvm/CREDITS.TXT + https://github.com/intel/llvm/blob/master/openmp/CREDITS.txt + https://github.com/intel/llvm/blob/master/libcxx/CREDITS.TXT + +============================================================================== +Software from third parties included in the LLVM Project: +============================================================================== +The LLVM Project contains third party software which is under different license +terms. All such code will be identified clearly using at least one of two +mechanisms: +1) It will be in a separate directory tree with its own `LICENSE.txt` or + `LICENSE` file at the top containing the specific license and restrictions + which apply to that software, or +2) It will contain specific license and restriction terms at the top of every + file. + +============================================================================== +Legacy LLVM License (https://llvm.org/docs/DeveloperPolicy.html#legacy): +============================================================================== +University of Illinois/NCSA +Open Source License + +Copyright (c) 2003-2020 University of Illinois at Urbana-Champaign. +All rights reserved. + +Developed by: + + LLVM Team + + University of Illinois at Urbana-Champaign + + http://llvm.org + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal with +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimers. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimers in the + documentation and/or other materials provided with the distribution. + + * Neither the names of the LLVM Team, University of Illinois at + Urbana-Champaign, nor the names of its contributors may be used to + endorse or promote products derived from this Software without specific + prior written permission. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE +SOFTWARE. diff --git a/thirdparty/OpenImageDenoise/share/doc/OpenImageDenoise/third-party-programs-oneDNN.txt b/thirdparty/OpenImageDenoise/share/doc/OpenImageDenoise/third-party-programs-oneDNN.txt new file mode 100644 index 0000000..1b8bbcc --- /dev/null +++ b/thirdparty/OpenImageDenoise/share/doc/OpenImageDenoise/third-party-programs-oneDNN.txt @@ -0,0 +1,583 @@ +oneAPI Deep Neural Network Library (oneDNN) Third Party Programs File + +This file contains the list of third party software ("third party programs") +contained in the Intel software and their required notices and/or license +terms. This third party software, even if included with the distribution of +the Intel software, may be governed by separate license terms, including +without limitation, third party license terms, other Intel software license +terms, and open source software license terms. These separate license terms +govern your use of the third party programs as set forth in in the +"THIRD-PARTY-PROGRAMS" file. + +Third party programs and their corresponding required notices and/or license +terms are listed below. + +-------------------------------------------------------------------------------- +1. XByak (src/cpu/xbyak/) +Copyright (c) 2007 MITSUNARI Shigeo +All rights reserved. + +3-Clause BSD License + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this +list of conditions and the following disclaimer. +Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. +Neither the name of the copyright owner nor the names of its contributors may +be used to endorse or promote products derived from this software without +specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +THE POSSIBILITY OF SUCH DAMAGE. + + +ć‚½ćƒ¼ć‚¹ć‚³ćƒ¼ćƒ‰å½¢å¼ć‹ćƒć‚¤ćƒŠćƒŖå½¢å¼ć‹ć€å¤‰ę›“ć™ć‚‹ć‹ć—ćŖć„ć‹ć‚’å•ć‚ćšć€ä»„äø‹ć®ę”件悒ęŗ€ćŸ +ć™å “åˆć«é™ć‚Šć€å†é ’åøƒćŠć‚ˆć³ä½æē”Ø恌čرåÆć•ć‚Œć¾ć™ć€‚ + +ć‚½ćƒ¼ć‚¹ć‚³ćƒ¼ćƒ‰ć‚’å†é ’åøƒć™ć‚‹å “åˆć€äøŠčØ˜ć®č‘—ä½œęØ©č”Øē¤ŗć€ęœ¬ę”ä»¶äø€č¦§ć€ćŠć‚ˆć³äø‹čØ˜å…č²¬ę”é … +ć‚’å«ć‚ć‚‹ć“ćØ怂 +惐悤惊ćƒŖå½¢å¼ć§å†é ’åøƒć™ć‚‹å “åˆć€é ’åøƒē‰©ć«ä»˜å±žć®ćƒ‰ć‚­ćƒ„ćƒ”ćƒ³ćƒˆē­‰ć®č³‡ę–™ć«ć€äøŠčØ˜ć®č‘—ä½œ +ęØ©č”Øē¤ŗć€ęœ¬ę”ä»¶äø€č¦§ć€ćŠć‚ˆć³äø‹čØ˜å…č²¬ę”é …ć‚’å«ć‚ć‚‹ć“ćØ怂 +ę›øé¢ć«ć‚ˆć‚‹ē‰¹åˆ„恮čرåÆćŖć—ć«ć€ęœ¬ć‚½ćƒ•ćƒˆć‚¦ć‚§ć‚¢ć‹ć‚‰ę“¾ē”Ÿć—ćŸč£½å“ć®å®£ä¼ć¾ćŸćÆč²©å£²äæƒé€² +ć«ć€č‘—ä½œęØ©č€…ć®åå‰ć¾ćŸćÆć‚³ćƒ³ćƒˆćƒŖćƒ“ćƒ„ćƒ¼ć‚æćƒ¼ć®åå‰ć‚’ä½æē”Ø恗恦ćÆćŖ悉ćŖ恄怂 +ęœ¬ć‚½ćƒ•ćƒˆć‚¦ć‚§ć‚¢ćÆć€č‘—ä½œęØ©č€…ćŠć‚ˆć³ć‚³ćƒ³ćƒˆćƒŖćƒ“ćƒ„ćƒ¼ć‚æćƒ¼ć«ć‚ˆć£ć¦ć€Œē¾ēŠ¶ć®ć¾ć¾ć€ęä¾›ć• +ć‚Œć¦ćŠć‚Šć€ę˜Žē¤ŗ黙ē¤ŗć‚’å•ć‚ćšć€å•†ę„­ēš„ćŖä½æē”ØåÆčƒ½ę€§ć€ćŠć‚ˆć³ē‰¹å®šć®ē›®ēš„恫åÆ¾ć™ć‚‹é©åˆę€§ +ć«é–¢ć™ć‚‹ęš—é»™ć®äæčØ¼ć‚‚å«ć‚ć€ć¾ćŸćć‚Œć«é™å®šć•ć‚ŒćŖ恄态恄恋ćŖ悋äæčØ¼ć‚‚ć‚ć‚Šć¾ć›ć‚“ć€‚ +č‘—ä½œęØ©č€…ć‚‚ć‚³ćƒ³ćƒˆćƒŖćƒ“ćƒ„ćƒ¼ć‚æćƒ¼ć‚‚ć€äŗ‹ē”±ć®ć„ć‹ć‚“ć‚’å•ć‚ćšć€ ęå®³ē™ŗē”Ÿć®åŽŸå› ć„恋悓悒 +å•ć‚ćšć€ć‹ć¤č²¬ä»»ć®ę ¹ę‹ ćŒå„‘ē“„ć§ć‚ć‚‹ć‹åŽ³ę ¼č²¬ä»»ć§ć‚ć‚‹ć‹ļ¼ˆéŽå¤±ćć®ä»–恮ļ¼‰äøę³•č”Œē‚ŗ恧 +ć‚ć‚‹ć‹ć‚’å•ć‚ćšć€ä»®ć«ćć®ć‚ˆć†ćŖęå®³ćŒē™ŗē”Ÿć™ć‚‹åÆčƒ½ę€§ć‚’ēŸ„ć‚‰ć•ć‚Œć¦ć„ćŸćØ恗恦悂态 +ęœ¬ć‚½ćƒ•ćƒˆć‚¦ć‚§ć‚¢ć®ä½æē”Øć«ć‚ˆć£ć¦ē™ŗē”Ÿć—ćŸļ¼ˆä»£ę›æå“ć¾ćŸćÆ代ē”Øć‚µćƒ¼ćƒ“ć‚¹ć®čŖæ達态ä½æē”Ø恮 +å–Ŗå¤±ć€ćƒ‡ćƒ¼ć‚æ恮å–Ŗå¤±ć€åˆ©ē›Šć®å–Ŗå¤±ć€ę„­å‹™ć®äø­ę–­ć‚‚å«ć‚ć€ć¾ćŸćć‚Œć«é™å®šć•ć‚ŒćŖ恄ļ¼‰ē›“ꎄ +ęå®³ć€é–“ęŽ„ęå®³ć€å¶ē™ŗēš„ćŖęå®³ć€ē‰¹åˆ„ęå®³ć€ę‡²ē½°ēš„ęå®³ć€ć¾ćŸćÆēµęžœęå®³ć«ć¤ć„恦态 +äø€åˆ‡č²¬ä»»ć‚’č² ć‚ćŖ恄悂恮ćØć—ć¾ć™ć€‚ + +-------------------------------------------------------------------------------- +2. Googletest (tests/gtests/gtest/) +Copyright 2005, Google Inc. +Copyright 2006, Google Inc. +Copyright 2007, Google Inc. +Copyright 2008, Google Inc. +Copyright 2015, Google Inc. +All rights reserved. + +3-Clause BSD License + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +-------------------------------------------------------------------------------- +3. Instrumentation and Tracing Technology API (src/common/ittnotify/) +Copyright (c) 2011, Intel Corporation. All rights reserved. +Copyright (c) 2005-2014 Intel Corporation. All rights reserved. + +3-Clause BSD License + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +3. Neither the name of Intel Corporation nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +-------------------------------------------------------------------------------- +4. CMake (cmake/FindOpenCL.cmake, cmake/FindBLAS.cmake, cmake/FindACL.cmake) +CMake - Cross Platform Makefile Generator +Copyright 2000-2020 Kitware, Inc. and Contributors +All rights reserved. + +3-Clause BSD License + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +* Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +* Neither the name of Kitware, Inc. nor the names of Contributors + may be used to endorse or promote products derived from this + software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +------------------------------------------------------------------------------ + +The following individuals and institutions are among the Contributors: + +* Aaron C. Meadows +* Adriaan de Groot +* Aleksey Avdeev +* Alexander Neundorf +* Alexander Smorkalov +* Alexey Sokolov +* Alex Merry +* Alex Turbov +* Andreas Pakulat +* Andreas Schneider +* AndrĆ© Rigland Brodtkorb +* Axel Huebl, Helmholtz-Zentrum Dresden - Rossendorf +* Benjamin Eikel +* Bjoern Ricks +* Brad Hards +* Christopher Harvey +* Christoph GrĆ¼ninger +* Clement Creusot +* Daniel Blezek +* Daniel Pfeifer +* Enrico Scholz +* Eran Ifrah +* Esben Mose Hansen, Ange Optimization ApS +* Geoffrey Viola +* Google Inc +* Gregor Jasny +* Helio Chissini de Castro +* Ilya Lavrenov +* Insight Software Consortium +* Jan Woetzel +* Julien Schueller +* Kelly Thompson +* Konstantin Podsvirov +* Laurent Montel +* Mario Bensi +* Martin GrƤƟlin +* Mathieu Malaterre +* Matthaeus G. Chajdas +* Matthias Kretz +* Matthias Maennich +* Michael Hirsch, Ph.D. +* Michael StĆ¼rmer +* Miguel A. Figueroa-Villanueva +* Mike Jackson +* Mike McQuaid +* Nicolas Bock +* Nicolas Despres +* Nikita Krupen'ko +* NVIDIA Corporation +* OpenGamma Ltd. +* Patrick Stotko +* Per Ƙyvind Karlsen +* Peter Collingbourne +* Petr Gotthard +* Philip Lowman +* Philippe Proulx +* Raffi Enficiaud, Max Planck Society +* Raumfeld +* Roger Leigh +* Rolf Eike Beer +* Roman Donchenko +* Roman Kharitonov +* Ruslan Baratov +* Sebastian Holtermann +* Stephen Kelly +* Sylvain Joubert +* The Qt Company Ltd. +* Thomas Sondergaard +* Tobias Hunger +* Todd Gamblin +* Tristan Carel +* University of Dundee +* Vadim Zhukov +* Will Dicharry + +See version control history for details of individual contributions. + +The above copyright and license notice applies to distributions of +CMake in source and binary form. Third-party software packages supplied +with CMake under compatible licenses provide their own copyright notices +documented in corresponding subdirectories or source files. + +------------------------------------------------------------------------------ + +CMake was initially developed by Kitware with the following sponsorship: + + * National Library of Medicine at the National Institutes of Health + as part of the Insight Segmentation and Registration Toolkit (ITK). + + * US National Labs (Los Alamos, Livermore, Sandia) ASC Parallel + Visualization Initiative. + + * National Alliance for Medical Image Computing (NAMIC) is funded by the + National Institutes of Health through the NIH Roadmap for Medical Research, + Grant U54 EB005149. + + * Kitware, Inc. + +-------------------------------------------------------------------------------- +5. Xbyak_aarch64 (src/cpu/aarch64/xbyak_aarch64/) +Copyright 2019-2020 FUJITSU LIMITED + +Apache License, Version 2.0 + +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. + + + 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 + +-------------------------------------------------------------------------------- +6. Boost C++ Libraries (src/common/primitive_hashing.hpp) +Copyright 2005-2014 Daniel James. + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +-------------------------------------------------------------------------------- +7. Intel(R) Graphics Compute Runtime for oneAPI Level Zero and OpenCL(TM) +Driver (src/gpu/jit/ngen/npack/{elf_structs,hash}.hpp) +Copyright (c) 2018 Intel Corporation + +Intel(R) Graphics Compiler (src/gpu/jit/ngen/npack/neo_structs.hpp) +Copyright (c) 2019 Intel Corporation + +oneAPI Level Zero (src/sycl/level_zero) +Copyright (C) 2019-2021 Intel Corporation + +Doxyrest toolkit (doc/doxyrest/*) +Copyright (c) 2016, Tibbo Technology Inc +Copyright (c) 2016, Vladimir Gladkov +Copyright (c) 2016, Doxyrest maintainers + +MIT License + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +8. Sphinx (doc/sphinx/conf/py) +Copyright (c) 2007-2021 by the Sphinx team (see AUTHORS file). +All rights reserved. + +2-Clause BSD License + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +* Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +-------------------------------------------------------------------------------- +9. Intel(R) Metrics Discovery Application Programming Interface (src/gpu/ocl/mdapi/metrics_discovery_api.h) +MIT License + +Copyright (c) 2019, Intel Corporation + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +IN THE SOFTWARE. diff --git a/thirdparty/OpenImageDenoise/share/doc/OpenImageDenoise/third-party-programs-oneTBB.txt b/thirdparty/OpenImageDenoise/share/doc/OpenImageDenoise/third-party-programs-oneTBB.txt new file mode 100644 index 0000000..b555450 --- /dev/null +++ b/thirdparty/OpenImageDenoise/share/doc/OpenImageDenoise/third-party-programs-oneTBB.txt @@ -0,0 +1,411 @@ +oneAPI Threading Building Blocks (oneTBB) Third Party Programs File + +This file contains the list of third party software ("third party programs") +contained in the Intel software and their required notices and/or license terms. +This third party software, even if included with the distribution of the Intel +software, may be governed by separate license terms, including without limitation, +third party license terms, other Intel software license terms, and open source +software license terms. These separate license terms govern your use of the third +party programs as set forth in the "third-party-programs.txt" or other similarlynamed text file. + +The third party programs and their corresponding required notices and/or license +terms are listed below. +_______________________________________________________________________________________________________ + +1. Intel(R) Instrumentation and Tracing Technology (ITT) + Copyright (c) 2022 Intel Corporation. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be + used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. + +_______________________________________________________________________________________________________ + +2. ActiveState Thread pool with same API as (multi) processing.Pool (Python recipe): + Copyright (c) 2008,2016 david decotigny (this file) + Copyright (c) 2006-2008, R Oudkerk (multiprocessing.Pool) + + Portable Hardware Locality (hwloc) + Copyright (c) 2004-2006 The Trustees of Indiana University and Indiana University Research and Technology Corporation. All rights reserved. + Copyright (c) 2004-2005 The University of Tennessee and The University of Tennessee Research Foundation. All rights reserved. + Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, University of Stuttgart. All rights reserved. + Copyright (c) 2004-2005 The Regents of the University of California. All rights reserved. + Copyright (c) 2009 CNRS + Copyright (c) 2009-2016 Inria. All rights reserved. + Copyright (c) 2009-2015 Université Bordeaux + Copyright (c) 2009-2015 Cisco Systems, Inc. All rights reserved. + Copyright (c) 2009-2012 Oracle and/or its affiliates. All rights reserved. + Copyright (c) 2010 IBM + Copyright (c) 2010 Jirka Hladky + Copyright (c) 2012 Aleksej Saushev, The NetBSD Foundation + Copyright (c) 2012 Blue Brain Project, EPFL. All rights reserved. + Copyright (c) 2013-2014 University of Wisconsin-La Crosse. All rights reserved. + Copyright (c) 2015 Research Organization for Information Science and Technology (RIST). All rights reserved. + Copyright (c) 2015-2016 Intel, Inc. All rights reserved. + + BSD 3-clause "New" or "Revised" License + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. Neither the name of author nor the names of any contributors may be + used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. +_______________________________________________________________________________________________________ + +3. gperftools: Copyright (c) 2011, Google Inc. + + Tachyon: Copyright (c) 1994-2008 John E. Stone. All rights reserved. + + BSD 3-Clause "New" or "Revised" License + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + * Neither the name of Google Inc. nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +_______________________________________________________________________________________________________ + +4. Mateusz Kwiatkowski Workaround for bug 62258 in libstdc++ + + GPL 3.0 with GCC Runtime Library Exception 3.1 + + GNU GENERAL PUBLIC LICENSE + + Version 3, 29 June 2007 + + Copyright (c) 2007 Free Software Foundation, Inc. + + Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. + + Preamble + The GNU General Public License is a free, copyleft license for software and other kinds of works. + + The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too. + + When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. + + Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. + + Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and modification follow. + + TERMS AND CONDITIONS + 0. Definitions. + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based on the Program. + + To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. + + 1. Source Code. + The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work. + + A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. + + The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. + + The Corresponding Source for a work in source code form is that same work. + + 2. Basic Permissions. + All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. + + When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. + + 4. Conveying Verbatim Copies. + You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified it, and giving a relevant date. + b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". + c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. + d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. + A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. + + 6. Conveying Non-Source Forms. + You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: + + a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. + b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. + c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. + d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. + e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. + A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. + + If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). + + The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. + + 7. Additional Terms. + "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or + b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or + c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or + d) Limiting the use for publicity purposes of names of licensors or authors of the material; or + e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or + f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. + All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. + + 8. Termination. + You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). + + However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. + + Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. + + 9. Acceptance Not Required for Having Copies. + You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. + + 11. Patents. + A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. + + If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. + + A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. + + 14. Revised Versions of this License. + The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. + + Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. + + 15. Disclaimer of Warranty. + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see . + + The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . + + + GCC RUNTIME LIBRARY EXCEPTION + + Version 3.1, 31 March 2009 + + Copyright (c) 2009 Free Software Foundation, Inc. + + Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. + + This GCC Runtime Library Exception ("Exception") is an additional permission under section 7 of the GNU General Public License, version 3 ("GPLv3"). It applies to a given file (the "Runtime Library") that bears a notice placed by the copyright holder of the file stating that the file is governed by GPLv3 along with this Exception. + + When you use GCC to compile a program, GCC may combine portions of certain GCC header files and runtime libraries with the compiled program. The purpose of this Exception is to allow compilation of non-GPL (including proprietary) programs to use, in this way, the header files and runtime libraries covered by this Exception. + + 0. Definitions. + A file is an "Independent Module" if it either requires the Runtime Library for execution after a Compilation Process, or makes use of an interface provided by the Runtime Library, but is not otherwise based on the Runtime Library. + + "GCC" means a version of the GNU Compiler Collection, with or without modifications, governed by version 3 (or a specified later version) of the GNU General Public License (GPL) with the option of using any subsequent versions published by the FSF. + + "GPL-compatible Software" is software whose conditions of propagation, modification and use would permit combination with GCC in accord with the license of GCC. + + "Target Code" refers to output from any compiler for a real or virtual target processor architecture, in executable form or suitable for input to an assembler, loader, linker and/or execution phase. Notwithstanding that, Target Code does not include data in any format that is used as a compiler intermediate representation, or used for producing a compiler intermediate representation. + + The "Compilation Process" transforms code entirely represented in non-intermediate languages designed for human-written code, and/or in Java Virtual Machine byte code, into Target Code. Thus, for example, use of source code generators and preprocessors need not be considered part of the Compilation Process, since the Compilation Process can be understood as starting with the output of the generators or preprocessors. + + A Compilation Process is "Eligible" if it is done using GCC, alone or with other GPL-compatible software, or if it is done without using any work based on GCC. For example, using non-GPL-compatible Software to optimize any GCC intermediate representations would not qualify as an Eligible Compilation Process. + + 1. Grant of Additional Permission. + You have permission to propagate a work of Target Code formed by combining the Runtime Library with Independent Modules, even if such propagation would otherwise violate the terms of GPLv3, provided that all Target Code was generated by Eligible Compilation Processes. You may then convey such a combination under terms of your choice, consistent with the licensing of the Independent Modules. + + 2. No Weakening of GCC Copyleft. + The availability of this Exception does not imply any general presumption that third-party software is unaffected by the copyleft requirements of the license of GCC. + +_______________________________________________________________________________________________________ + +5. Doctest + + Copyright (c) 2016-2021 Viktor Kirilov + + The MIT License (MIT) + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +_______________________________________________________________________________________________________ + +*Other names and brands may be claimed as the property of others. diff --git a/thirdparty/OpenImageDenoise/share/doc/OpenImageDenoise/third-party-programs.txt b/thirdparty/OpenImageDenoise/share/doc/OpenImageDenoise/third-party-programs.txt new file mode 100644 index 0000000..f3d76ae --- /dev/null +++ b/thirdparty/OpenImageDenoise/share/doc/OpenImageDenoise/third-party-programs.txt @@ -0,0 +1,645 @@ +Intel(R) Open Image Denoise Third Party Programs File + +This file contains the list of third party software ("third party programs") +contained in the Intel software and their required notices and/or license +terms. This third party software, even if included with the distribution of the +Intel software, may be governed by separate license terms, including without +limitation, third party license terms, other Intel software license terms, and +open source software license terms. These separate license terms govern your use +of the third party programs as set forth in the "third-party-programs.txt" or +other similarly named text file. + +Third party programs and their corresponding required notices and/or license +terms are listed below. + +-------------------------------------------------------------------------------- + +1. Intel(R) oneAPI Deep Neural Network Library (oneDNN) + Copyright 2016-2023 Intel Corporation + + Intel(R) oneAPI Threading Building Blocks (oneTBB) + Copyright 2005-2023 Intel Corporation + + IntelĀ® Embree (snippets) + Copyright Intel Corporation + + IntelĀ® OSPRay (snippets) + Copyright Intel Corporation + + 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. + +-------------------------------------------------------------------------------- + +2. PyTorch + + From PyTorch: + + Copyright (c) 2016- Facebook, Inc (Adam Paszke) + Copyright (c) 2014- Facebook, Inc (Soumith Chintala) + Copyright (c) 2011-2014 Idiap Research Institute (Ronan Collobert) + Copyright (c) 2012-2014 Deepmind Technologies (Koray Kavukcuoglu) + Copyright (c) 2011-2012 NEC Laboratories America (Koray Kavukcuoglu) + Copyright (c) 2011-2013 NYU (Clement Farabet) + Copyright (c) 2006-2010 NEC Laboratories America (Ronan Collobert, Leon Bottou, Iain Melvin, Jason Weston) + Copyright (c) 2006 Idiap Research Institute (Samy Bengio) + Copyright (c) 2001-2004 Idiap Research Institute (Ronan Collobert, Samy Bengio, Johnny Mariethoz) + + From Caffe2: + + Copyright (c) 2016-present, Facebook Inc. All rights reserved. + + All contributions by Facebook: + Copyright (c) 2016 Facebook Inc. + + All contributions by Google: + Copyright (c) 2015 Google Inc. + All rights reserved. + + All contributions by Yangqing Jia: + Copyright (c) 2015 Yangqing Jia + All rights reserved. + + All contributions from Caffe: + Copyright(c) 2013, 2014, 2015, the respective contributors + All rights reserved. + + All other contributions: + Copyright(c) 2015, 2016 the respective contributors + All rights reserved. + + Caffe2 uses a copyright model similar to Caffe: each contributor holds + copyright over their contributions to Caffe2. The project versioning records + all such contribution and copyright details. If a contributor wants to further + mark their specific copyright on a particular contribution, they should + indicate their copyright solely in the commit message of the change when it is + committed. + + All rights reserved. + + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +3. Neither the names of Facebook, Deepmind Technologies, NYU, NEC Laboratories America + and IDIAP Research Institute nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + +-------------------------------------------------------------------------------- + +3. pytorch-msssim + Copyright (c) 2019 Gongfan Fang + + ROCmSoftwarePlatform/composable_kernel + Copyright (c) 2018- , Advanced Micro Devices, Inc. (Chao Liu, Jing Zhang) + Copyright (c) 2019- , Advanced Micro Devices, Inc. (Letao Qin, Qianfeng Zhang, Liang Huang, Shaojie Wang) + Copyright (c) 2022- , Advanced Micro Devices, Inc. (Anthony Chang, Chunyu Lai, Illia Silin, Adam Osewski, Poyen Chen, Jehandad Khan) + Copyright (c) 2019-2021, Advanced Micro Devices, Inc. (Hanwen Chang) + Copyright (c) 2019-2020, Advanced Micro Devices, Inc. (Tejash Shah) + Copyright (c) 2020 , Advanced Micro Devices, Inc. (Xiaoyan Zhou) + Copyright (c) 2021-2022, Advanced Micro Devices, Inc. (Jianfeng Yan) + Copyright (c) 2018-2022, Advanced Micro Devices, Inc. All rights reserved. + +MIT License + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +-------------------------------------------------------------------------------- + +4. Catch2 + Copyright (c) 2021 Two Blue Cubes Ltd. All rights reserved. + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +-------------------------------------------------------------------------------- + +5. CUTLASS + Copyright (c) 2017 - 2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved. + +SPDX-License-Identifier: BSD-3-Clause + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this +list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +-------------------------------------------------------------------------------- + +6. oneAPI Data Parallel C++ Compiler + Copyright Intel Corporation + +============================================================================== +The LLVM Project is under the Apache License v2.0 with LLVM Exceptions: +============================================================================== + + 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. + + +---- LLVM Exceptions to the Apache 2.0 License ---- + +As an exception, if, as a result of your compiling your source code, portions +of this Software are embedded into an Object form of such source code, you +may redistribute such embedded portions in such Object form without complying +with the conditions of Sections 4(a), 4(b) and 4(d) of the License. + +In addition, if you combine or link compiled forms of this Software with +software that is licensed under the GPLv2 ("Combined Software") and if a +court of competent jurisdiction determines that the patent provision (Section +3), the indemnity provision (Section 9) or other Section of the License +conflicts with the conditions of the GPLv2, you may retroactively and +prospectively choose to deem waived or otherwise exclude such Section(s) of +the License, but only in their entirety and only with respect to the Combined +Software. + +-------------------------------------------------------------------------------- + +The following third party programs have their own third party programs. These +additional third party program files are as follows: + +1. Intel(R) oneAPI Deep Neural Network Library (oneDNN) + ./third-party-programs-oneDNN.txt + +2. Intel(R) oneAPI Threading Building Blocks (oneTBB) + ./third-party-programs-oneTBB.txt + +3. oneAPI DPC++ Compiler + ./third-party-programs-DPCPP.txt + +-------------------------------------------------------------------------------- \ No newline at end of file diff --git a/vcpkg b/vcpkg new file mode 160000 index 0000000..df2f1a4 --- /dev/null +++ b/vcpkg @@ -0,0 +1 @@ +Subproject commit df2f1a4872ab0d682cda2c442b97363165eccf58 diff --git a/vcpkg.json b/vcpkg.json new file mode 100644 index 0000000..22e6f42 --- /dev/null +++ b/vcpkg.json @@ -0,0 +1,17 @@ +{ + "name": "main", + "version-string": "latest", + "dependencies": [ + "openvdb", + "glfw3", + "glew", + "openimageio", + { + "name": "imgui", + "default-features": true, + "features": [ "glfw-binding", "opengl3-binding" ] + }, + "tinyexr", + "stb" + ] +} \ No newline at end of file