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/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..f57598e 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,36 @@ 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") 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 +164,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..93f1e08 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; @@ -168,7 +165,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 +182,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 +202,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 +214,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 +271,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 +309,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 +318,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 +339,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 +349,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 +362,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 +421,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 +431,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 +479,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 +490,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 +511,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 +536,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 +557,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 +582,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 +629,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 +649,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 +690,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 +716,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 +746,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 +767,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 +809,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 +829,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 +838,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 +890,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 +900,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 +941,6 @@ static bool create_environment( } static void read_instance_file(std::string file_name) { - assert(!file_name.empty()); std::ifstream stream; @@ -987,9 +950,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 +963,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 +980,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 +999,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 +1020,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 +1034,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 +1057,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 +1081,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 +1113,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 +1141,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 +1171,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 +1192,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 +1241,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 +1296,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 +1338,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 +1372,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 @@ -1469,7 +1390,7 @@ int main(const int argc, const char* argv[]) 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 +1401,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 +1421,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 +1458,30 @@ 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"); - - - - - //*********************************************************************************************************************************** // 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 +1502,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(); @@ -1634,15 +1528,15 @@ int main(const int argc, const char* argv[]) 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 +1556,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,83 +1573,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 @@ -1764,12 +1634,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 +1660,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 +1668,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); @@ -1825,70 +1693,40 @@ 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"); + file_path.append(".jpeg"); int res = width * height; - float4 *c = (float4*)malloc(res * sizeof(float4)); + 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"); - - 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 + 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,35 +1736,34 @@ 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 + //Do Image denoising with OIDN library if (denoise) { - int resolution = width * height; - float4 *in_buffer; - float3 *temp_in_buffer, *temp_out_buffer; + float4* in_buffer; + float3* temp_in_buffer, * temp_out_buffer; in_buffer = (float4*)malloc(resolution * sizeof(float4)); @@ -1936,7 +1773,6 @@ int main(const int argc, const char* argv[]) 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; @@ -1950,31 +1786,13 @@ int main(const int argc, const char* argv[]) 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); + std::string file_path = "./render/pathtrace_denoised."; + file_path.append(std::to_string(frame)); + file_path.append(".jpg"); - frame++; + bool success = save_texture_jpg(temp_out_buffer, file_path, width, height); - } + frame++; denoise = false; } @@ -2025,4 +1843,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..930f02f 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,327 @@ #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::UINT8, buffer); + out->close(); - if (res) { - log("Saved jpg file " + filename, LOG); - return true; - } - return false; + 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]; - - image_ptr[0] = &(images[2].at(0)); // B - image_ptr[1] = &(images[1].at(0)); // G - image_ptr[2] = &(images[0].at(0)); // R + ImageSpec spec(width, height, 4, TypeDesc::FLOAT); + out->open(filename, spec); + out->write_image(TypeDesc::FLOAT, buffer); + out->close(); - 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 +378,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 +484,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/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/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/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