├── .gitignore ├── tools └── premake5 │ ├── osx │ └── premake5 │ ├── linux64 │ └── premake5 │ └── win │ └── premake5.exe ├── tutorials ├── imgs │ ├── 12_cutout.png │ ├── 04_compaction.png │ ├── 18_shadow_ray.png │ ├── 05_global_stack.png │ ├── 14_batch_build.png │ ├── 19_primary_ray.png │ ├── 06_dynamic_stack.png │ ├── 09_motion_blur_srt.png │ ├── 01_geom_intersection.png │ ├── 07_custom_bvh_import.png │ ├── 08_ambient_occlusion.png │ ├── 16_fluid_simulation.png │ ├── 02_scene_intersection.png │ ├── 03_custom_intersection.png │ ├── 10_motion_blur_matrix.png │ ├── 13_concurrent_scene_build.png │ ├── 15_multi_level_instancing.png │ └── 11_multi_custom_intersection.png ├── 12_cutout │ ├── premake5.lua │ └── main.cpp ├── 04_compaction │ ├── premake5.lua │ └── main.cpp ├── 14_batch_build │ ├── premake5.lua │ └── main.cpp ├── 05_global_stack │ ├── premake5.lua │ └── main.cpp ├── 06_dynamic_stack │ ├── premake5.lua │ └── main.cpp ├── 18_shadow_ray │ ├── premake5.lua │ └── main.cpp ├── 09_motion_blur_srt │ ├── premake5.lua │ └── main.cpp ├── 19_primary_ray │ ├── premake5.lua │ └── main.cpp ├── 01_geom_intersection │ ├── premake5.lua │ └── main.cpp ├── 02_scene_intersection │ ├── premake5.lua │ └── main.cpp ├── 03_custom_intersection │ ├── premake5.lua │ └── main.cpp ├── 07_custom_bvh_import │ ├── premake5.lua │ └── main.cpp ├── 10_motion_blur_matrix │ └── premake5.lua ├── 08_ambient_occlusion │ ├── premake5.lua │ └── main.cpp ├── 13_concurrent_scene_build │ ├── premake5.lua │ └── main.cpp ├── 15_multi_level_instancing │ └── premake5.lua ├── 16_fluid_simulation │ └── premake5.lua ├── 11_multi_custom_intersection │ ├── premake5.lua │ └── main.cpp ├── 00_context_creation │ ├── premake5.lua │ └── main.cpp ├── common │ ├── dependency.lua │ ├── meshes │ │ ├── cornellbox │ │ │ ├── cornellBox.mtl │ │ │ └── cornellBox.obj │ │ └── cornellpot │ │ │ └── cornellpot.mtl │ ├── FluidSimulation.h │ ├── TutorialBase.h │ ├── Aabb.h │ ├── SceneDemo.h │ ├── BvhBuilder.h │ ├── CornellBox.h │ ├── Common.h │ ├── ShadowRayKernel.h │ └── TutorialBase.cpp ├── 17_hiprt_hip │ ├── premake5.lua │ └── main.cpp ├── scripts │ ├── test.bat │ └── test.sh ├── premake5.lua └── readme.md ├── .gitmodules ├── hiprt └── README.md ├── .github └── workflows │ └── format.yaml ├── .clang-format ├── doc ├── 11_multi_custom_intersection.md ├── 02_scene_intersection.md ├── 19_primary_ray.md ├── 01_geom_intersection.md ├── 03_custom_intersection.md ├── 08_ambient_occlusion.md └── 07_custom_bvh_import.md └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | *.vs 2 | *.vscode 3 | *.sln 4 | *.png 5 | build/ 6 | hiprt/ 7 | tutorials/dist/ 8 | 9 | -------------------------------------------------------------------------------- /tools/premake5/osx/premake5: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GPUOpen-LibrariesAndSDKs/HIPRTSDK/HEAD/tools/premake5/osx/premake5 -------------------------------------------------------------------------------- /tutorials/imgs/12_cutout.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GPUOpen-LibrariesAndSDKs/HIPRTSDK/HEAD/tutorials/imgs/12_cutout.png -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "contrib/Orochi"] 2 | path = contrib/Orochi 3 | url = https://github.com/GPUOpen-LibrariesAndSDKs/Orochi 4 | -------------------------------------------------------------------------------- /tools/premake5/linux64/premake5: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GPUOpen-LibrariesAndSDKs/HIPRTSDK/HEAD/tools/premake5/linux64/premake5 -------------------------------------------------------------------------------- /tools/premake5/win/premake5.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GPUOpen-LibrariesAndSDKs/HIPRTSDK/HEAD/tools/premake5/win/premake5.exe -------------------------------------------------------------------------------- /tutorials/imgs/04_compaction.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GPUOpen-LibrariesAndSDKs/HIPRTSDK/HEAD/tutorials/imgs/04_compaction.png -------------------------------------------------------------------------------- /tutorials/imgs/18_shadow_ray.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GPUOpen-LibrariesAndSDKs/HIPRTSDK/HEAD/tutorials/imgs/18_shadow_ray.png -------------------------------------------------------------------------------- /tutorials/imgs/05_global_stack.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GPUOpen-LibrariesAndSDKs/HIPRTSDK/HEAD/tutorials/imgs/05_global_stack.png -------------------------------------------------------------------------------- /tutorials/imgs/14_batch_build.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GPUOpen-LibrariesAndSDKs/HIPRTSDK/HEAD/tutorials/imgs/14_batch_build.png -------------------------------------------------------------------------------- /tutorials/imgs/19_primary_ray.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GPUOpen-LibrariesAndSDKs/HIPRTSDK/HEAD/tutorials/imgs/19_primary_ray.png -------------------------------------------------------------------------------- /tutorials/imgs/06_dynamic_stack.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GPUOpen-LibrariesAndSDKs/HIPRTSDK/HEAD/tutorials/imgs/06_dynamic_stack.png -------------------------------------------------------------------------------- /tutorials/imgs/09_motion_blur_srt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GPUOpen-LibrariesAndSDKs/HIPRTSDK/HEAD/tutorials/imgs/09_motion_blur_srt.png -------------------------------------------------------------------------------- /tutorials/imgs/01_geom_intersection.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GPUOpen-LibrariesAndSDKs/HIPRTSDK/HEAD/tutorials/imgs/01_geom_intersection.png -------------------------------------------------------------------------------- /tutorials/imgs/07_custom_bvh_import.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GPUOpen-LibrariesAndSDKs/HIPRTSDK/HEAD/tutorials/imgs/07_custom_bvh_import.png -------------------------------------------------------------------------------- /tutorials/imgs/08_ambient_occlusion.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GPUOpen-LibrariesAndSDKs/HIPRTSDK/HEAD/tutorials/imgs/08_ambient_occlusion.png -------------------------------------------------------------------------------- /tutorials/imgs/16_fluid_simulation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GPUOpen-LibrariesAndSDKs/HIPRTSDK/HEAD/tutorials/imgs/16_fluid_simulation.png -------------------------------------------------------------------------------- /tutorials/imgs/02_scene_intersection.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GPUOpen-LibrariesAndSDKs/HIPRTSDK/HEAD/tutorials/imgs/02_scene_intersection.png -------------------------------------------------------------------------------- /tutorials/imgs/03_custom_intersection.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GPUOpen-LibrariesAndSDKs/HIPRTSDK/HEAD/tutorials/imgs/03_custom_intersection.png -------------------------------------------------------------------------------- /tutorials/imgs/10_motion_blur_matrix.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GPUOpen-LibrariesAndSDKs/HIPRTSDK/HEAD/tutorials/imgs/10_motion_blur_matrix.png -------------------------------------------------------------------------------- /tutorials/imgs/13_concurrent_scene_build.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GPUOpen-LibrariesAndSDKs/HIPRTSDK/HEAD/tutorials/imgs/13_concurrent_scene_build.png -------------------------------------------------------------------------------- /tutorials/imgs/15_multi_level_instancing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GPUOpen-LibrariesAndSDKs/HIPRTSDK/HEAD/tutorials/imgs/15_multi_level_instancing.png -------------------------------------------------------------------------------- /tutorials/imgs/11_multi_custom_intersection.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GPUOpen-LibrariesAndSDKs/HIPRTSDK/HEAD/tutorials/imgs/11_multi_custom_intersection.png -------------------------------------------------------------------------------- /tutorials/12_cutout/premake5.lua: -------------------------------------------------------------------------------- 1 | project "12_cutout" 2 | cppdialect "C++17" 3 | kind "ConsoleApp" 4 | location "../build" 5 | 6 | dofile "../common/dependency.lua" 7 | 8 | files { "../common/**.h", "../common/**.cpp"} 9 | files { "./**.h", "./**.cpp"} 10 | 11 | includedirs{ "../../" } 12 | 13 | targetdir "../dist/bin/%{cfg.buildcfg}" -------------------------------------------------------------------------------- /tutorials/04_compaction/premake5.lua: -------------------------------------------------------------------------------- 1 | project "04_compaction" 2 | cppdialect "C++17" 3 | kind "ConsoleApp" 4 | location "../build" 5 | 6 | dofile "../common/dependency.lua" 7 | 8 | files { "../common/**.h", "../common/**.cpp"} 9 | files { "./**.h", "./**.cpp"} 10 | 11 | includedirs{ "../../" } 12 | 13 | targetdir "../dist/bin/%{cfg.buildcfg}" -------------------------------------------------------------------------------- /tutorials/14_batch_build/premake5.lua: -------------------------------------------------------------------------------- 1 | project "14_batch_build" 2 | cppdialect "C++17" 3 | kind "ConsoleApp" 4 | location "../build" 5 | 6 | dofile "../common/dependency.lua" 7 | 8 | files { "../common/**.h", "../common/**.cpp"} 9 | files { "./**.h", "./**.cpp"} 10 | 11 | includedirs{ "../../" } 12 | 13 | targetdir "../dist/bin/%{cfg.buildcfg}" -------------------------------------------------------------------------------- /tutorials/05_global_stack/premake5.lua: -------------------------------------------------------------------------------- 1 | project "05_global_stack" 2 | cppdialect "C++17" 3 | kind "ConsoleApp" 4 | location "../build" 5 | 6 | dofile "../common/dependency.lua" 7 | 8 | files { "../common/**.h", "../common/**.cpp"} 9 | files { "./**.h", "./**.cpp"} 10 | 11 | includedirs{ "../../" } 12 | 13 | targetdir "../dist/bin/%{cfg.buildcfg}" -------------------------------------------------------------------------------- /tutorials/06_dynamic_stack/premake5.lua: -------------------------------------------------------------------------------- 1 | project "06_dynamic_stack" 2 | cppdialect "C++17" 3 | kind "ConsoleApp" 4 | location "../build" 5 | 6 | dofile "../common/dependency.lua" 7 | 8 | files { "../common/**.h", "../common/**.cpp"} 9 | files { "./**.h", "./**.cpp"} 10 | 11 | includedirs{ "../../" } 12 | 13 | targetdir "../dist/bin/%{cfg.buildcfg}" -------------------------------------------------------------------------------- /tutorials/18_shadow_ray/premake5.lua: -------------------------------------------------------------------------------- 1 | project "18_shadow_ray" 2 | cppdialect "C++17" 3 | kind "ConsoleApp" 4 | location "../build" 5 | 6 | dofile "../common/dependency.lua" 7 | 8 | files { "../common/**.h", "../common/**.cpp"} 9 | files { "./**.h", "./**.cpp"} 10 | 11 | includedirs{ "../../", "../" } 12 | 13 | targetdir "../dist/bin/%{cfg.buildcfg}" -------------------------------------------------------------------------------- /tutorials/09_motion_blur_srt/premake5.lua: -------------------------------------------------------------------------------- 1 | project "09_motion_blur_srt" 2 | cppdialect "C++17" 3 | kind "ConsoleApp" 4 | location "../build" 5 | 6 | dofile "../common/dependency.lua" 7 | 8 | files { "../common/**.h", "../common/**.cpp"} 9 | files { "./**.h", "./**.cpp"} 10 | 11 | includedirs{ "../../" } 12 | 13 | targetdir "../dist/bin/%{cfg.buildcfg}" -------------------------------------------------------------------------------- /tutorials/19_primary_ray/premake5.lua: -------------------------------------------------------------------------------- 1 | project "19_primary_ray" 2 | cppdialect "C++17" 3 | kind "ConsoleApp" 4 | location "../build" 5 | 6 | dofile "../common/dependency.lua" 7 | 8 | files { "../common/**.h", "../common/**.cpp"} 9 | files { "./**.h", "./**.cpp"} 10 | 11 | includedirs{ "../../", "../" } 12 | 13 | targetdir "../dist/bin/%{cfg.buildcfg}" -------------------------------------------------------------------------------- /tutorials/01_geom_intersection/premake5.lua: -------------------------------------------------------------------------------- 1 | project "01_geom_intersection" 2 | cppdialect "C++17" 3 | kind "ConsoleApp" 4 | location "../build" 5 | 6 | dofile "../common/dependency.lua" 7 | 8 | files { "../common/**.h", "../common/**.cpp"} 9 | files { "./**.h", "./**.cpp"} 10 | 11 | includedirs{ "../../" } 12 | 13 | targetdir "../dist/bin/%{cfg.buildcfg}" -------------------------------------------------------------------------------- /tutorials/02_scene_intersection/premake5.lua: -------------------------------------------------------------------------------- 1 | project "02_scene_intersection" 2 | cppdialect "C++17" 3 | kind "ConsoleApp" 4 | location "../build" 5 | 6 | dofile "../common/dependency.lua" 7 | 8 | files { "../common/**.h", "../common/**.cpp"} 9 | files { "./**.h", "./**.cpp"} 10 | 11 | includedirs{ "../../" } 12 | 13 | targetdir "../dist/bin/%{cfg.buildcfg}" -------------------------------------------------------------------------------- /tutorials/03_custom_intersection/premake5.lua: -------------------------------------------------------------------------------- 1 | project "03_custom_intersection" 2 | cppdialect "C++17" 3 | kind "ConsoleApp" 4 | location "../build" 5 | 6 | dofile "../common/dependency.lua" 7 | 8 | files { "../common/**.h", "../common/**.cpp"} 9 | files { "./**.h", "./**.cpp"} 10 | 11 | includedirs{ "../../" } 12 | 13 | targetdir "../dist/bin/%{cfg.buildcfg}" -------------------------------------------------------------------------------- /tutorials/07_custom_bvh_import/premake5.lua: -------------------------------------------------------------------------------- 1 | project "07_custom_bvh_import" 2 | cppdialect "C++17" 3 | kind "ConsoleApp" 4 | location "../build" 5 | 6 | dofile "../common/dependency.lua" 7 | 8 | files { "../common/**.h", "../common/**.cpp"} 9 | files { "./**.h", "./**.cpp"} 10 | 11 | includedirs{ "../../" } 12 | 13 | targetdir "../dist/bin/%{cfg.buildcfg}" -------------------------------------------------------------------------------- /tutorials/10_motion_blur_matrix/premake5.lua: -------------------------------------------------------------------------------- 1 | project "10_motion_blur_matrix" 2 | cppdialect "C++17" 3 | kind "ConsoleApp" 4 | location "../build" 5 | 6 | dofile "../common/dependency.lua" 7 | 8 | files { "../common/**.h", "../common/**.cpp"} 9 | files { "./**.h", "./**.cpp"} 10 | 11 | includedirs{ "../../" } 12 | 13 | targetdir "../dist/bin/%{cfg.buildcfg}" -------------------------------------------------------------------------------- /tutorials/08_ambient_occlusion/premake5.lua: -------------------------------------------------------------------------------- 1 | project "08_ambient_occlusion" 2 | cppdialect "C++17" 3 | kind "ConsoleApp" 4 | location "../build" 5 | 6 | dofile "../common/dependency.lua" 7 | 8 | files { "../common/**.h", "../common/**.cpp"} 9 | files { "./**.h", "./**.cpp"} 10 | 11 | includedirs{ "../../", "../" } 12 | 13 | targetdir "../dist/bin/%{cfg.buildcfg}" -------------------------------------------------------------------------------- /tutorials/13_concurrent_scene_build/premake5.lua: -------------------------------------------------------------------------------- 1 | project "13_concurrent_scene_build" 2 | cppdialect "C++17" 3 | kind "ConsoleApp" 4 | location "../build" 5 | 6 | dofile "../common/dependency.lua" 7 | 8 | files { "../common/**.h", "../common/**.cpp"} 9 | files { "./**.h", "./**.cpp"} 10 | 11 | includedirs{ "../../" } 12 | 13 | targetdir "../dist/bin/%{cfg.buildcfg}" -------------------------------------------------------------------------------- /tutorials/15_multi_level_instancing/premake5.lua: -------------------------------------------------------------------------------- 1 | project "15_multi_level_instancing" 2 | cppdialect "C++17" 3 | kind "ConsoleApp" 4 | location "../build" 5 | 6 | dofile "../common/dependency.lua" 7 | 8 | files { "../common/**.h", "../common/**.cpp"} 9 | files { "./**.h", "./**.cpp"} 10 | 11 | includedirs{ "../../" } 12 | 13 | targetdir "../dist/bin/%{cfg.buildcfg}" -------------------------------------------------------------------------------- /tutorials/16_fluid_simulation/premake5.lua: -------------------------------------------------------------------------------- 1 | project "16_fluid_simulation" 2 | cppdialect "C++17" 3 | kind "ConsoleApp" 4 | location "../build" 5 | 6 | dofile "../common/dependency.lua" 7 | 8 | files { "../common/**.h", "../common/**.cpp"} 9 | files { "./**.h", "./**.cpp"} 10 | 11 | includedirs{ "../../" } 12 | 13 | targetdir "../dist/bin/%{cfg.buildcfg}" -------------------------------------------------------------------------------- /tutorials/11_multi_custom_intersection/premake5.lua: -------------------------------------------------------------------------------- 1 | project "11_multi_custom_intersection" 2 | cppdialect "C++17" 3 | kind "ConsoleApp" 4 | location "../build" 5 | 6 | dofile "../common/dependency.lua" 7 | 8 | files { "../common/**.h", "../common/**.cpp"} 9 | files { "./**.h", "./**.cpp"} 10 | 11 | includedirs{ "../../" } 12 | 13 | targetdir "../dist/bin/%{cfg.buildcfg}" -------------------------------------------------------------------------------- /tutorials/00_context_creation/premake5.lua: -------------------------------------------------------------------------------- 1 | project "00_context_creation" 2 | cppdialect "C++17" 3 | kind "ConsoleApp" 4 | location "../build" 5 | 6 | dofile "../common/dependency.lua" 7 | 8 | files { "../common/**.h", "../common/**.cpp"} 9 | files { "./**.h", "./**.cpp"} 10 | 11 | includedirs{ "../../" } 12 | 13 | targetdir "../dist/bin/%{cfg.buildcfg}" 14 | 15 | defines {"HIPRT_EXPORTS"} 16 | 17 | -------------------------------------------------------------------------------- /hiprt/README.md: -------------------------------------------------------------------------------- 1 | **This repository is only for tutorials. The SDK binaries needs to be downloaded from [HIP RT project page](https://gpuopen.com/hiprt/).** 2 | 3 | Download and extract the binaries so that the file/folder structure inside this 'hiprt' folder looks like: 4 | ``` 5 | linux64/ 6 | win/ 7 | hiprt_common.h 8 | hiprt_device.h 9 | hiprt_libpath.h 10 | hiprt_math.h 11 | hiprt_types.h 12 | hiprt_vec.h 13 | hiprt.h 14 | hiprtew.h 15 | ``` 16 | -------------------------------------------------------------------------------- /tutorials/common/dependency.lua: -------------------------------------------------------------------------------- 1 | includedirs { "../../contrib/Orochi/" } 2 | files {"../../contrib/Orochi/Orochi/**.h", "../../contrib/Orochi/Orochi/**.cpp"} 3 | files {"../../contrib/Orochi/contrib/**.h", "../../contrib/Orochi/contrib/**.cpp"} 4 | 5 | if os.istarget("windows") then 6 | links{ "version" } 7 | libdirs{"../../hiprt/win/"} 8 | end 9 | if os.ishost("linux") then 10 | links { "pthread", "dl" } 11 | libdirs{"../../hiprt/linux64/"} 12 | end 13 | 14 | files { "../../hiprt/*.h"} 15 | links {"hiprt0300064"} 16 | 17 | -------------------------------------------------------------------------------- /.github/workflows/format.yaml: -------------------------------------------------------------------------------- 1 | name: Run clang-format Linter 2 | 3 | on: 4 | pull_request: 5 | branches: 6 | - main 7 | 8 | 9 | jobs: 10 | build: 11 | runs-on: ubuntu-latest 12 | 13 | steps: 14 | - uses: actions/checkout@v3 15 | with: 16 | ref: ${{ github.event.pull_request.head.ref }} 17 | - uses: DoozyX/clang-format-lint-action@v0.15 18 | with: 19 | source: './tutorials' 20 | exclude: './contrib ./tools ./hiprt' 21 | extensions: 'h,cpp,c' 22 | clangFormatVersion: 15 23 | inplace: True 24 | - uses: EndBug/add-and-commit@v9.1.1 25 | with: 26 | author_name: rprbuild 27 | author_email: a1rpr@amd.com 28 | message: 'Automatic: Committing clang-format changes' -------------------------------------------------------------------------------- /tutorials/17_hiprt_hip/premake5.lua: -------------------------------------------------------------------------------- 1 | project "17_hiprt_hip" 2 | cppdialect "C++17" 3 | kind "ConsoleApp" 4 | location "../build" 5 | 6 | local hiproot = os.getenv("HIP_PATH") 7 | if hiproot == nil or hiproot == '' then 8 | if os.ishost("linux") then 9 | hiproot = "/opt/rocm" 10 | end 11 | end 12 | 13 | if hiproot ~= nil then 14 | defines {"__USE_HIP__"} 15 | defines {"__HIP_PLATFORM_AMD__"} 16 | 17 | externalincludedirs {hiproot .. "/include/"} 18 | 19 | libdirs {hiproot .. "/lib/"} 20 | links { "amdhip64" } 21 | if os.istarget("windows") then 22 | libdirs {"../../hiprt/win/" } 23 | elseif os.ishost("linux") then 24 | libdirs { "../../hiprt/linux64/" } 25 | end 26 | end 27 | includedirs { "../../" } 28 | 29 | files { "./**.h", "./**.cpp"} 30 | files { "../../hiprt/*.h"} 31 | 32 | links {"hiprt0300064"} 33 | targetdir "../dist/bin/%{cfg.buildcfg}" 34 | -------------------------------------------------------------------------------- /tutorials/scripts/test.bat: -------------------------------------------------------------------------------- 1 | ..\dist\bin\Release\00_context_creation64.exe 2 | ..\dist\bin\Release\01_geom_intersection64.exe 3 | ..\dist\bin\Release\02_scene_intersection64.exe 4 | ..\dist\bin\Release\03_custom_intersection64.exe 5 | ..\dist\bin\Release\04_compaction64.exe 6 | ..\dist\bin\Release\05_global_stack64.exe 7 | ..\dist\bin\Release\06_dynamic_stack64.exe 8 | ..\dist\bin\Release\07_custom_bvh_import64.exe 9 | ..\dist\bin\Release\08_ambient_occlusion64.exe 10 | ..\dist\bin\Release\09_motion_blur_srt64.exe 11 | ..\dist\bin\Release\10_motion_blur_matrix64.exe 12 | ..\dist\bin\Release\11_multi_custom_intersection64.exe 13 | ..\dist\bin\Release\12_cutout64.exe 14 | ..\dist\bin\Release\13_concurrent_scene_build64.exe 15 | ..\dist\bin\Release\14_batch_build64.exe 16 | ..\dist\bin\Release\15_multi_level_instancing64.exe 17 | ..\dist\bin\Release\16_fluid_simulation64.exe 18 | ..\dist\bin\Release\18_shadow_ray64.exe 19 | ..\dist\bin\Release\19_primary_ray64.exe 20 | -------------------------------------------------------------------------------- /tutorials/scripts/test.sh: -------------------------------------------------------------------------------- 1 | PWD_PATH=`pwd` 2 | export LD_LIBRARY_PATH="$PWD_PATH/../../hiprt/linux64:${LD_LIBRARY_PATH}" 3 | 4 | ../dist/bin/Release/00_context_creation64 5 | ../dist/bin/Release/01_geom_intersection64 6 | ../dist/bin/Release/02_scene_intersection64 7 | ../dist/bin/Release/03_custom_intersection64 8 | ../dist/bin/Release/04_compaction64 9 | ../dist/bin/Release/05_global_stack64 10 | ../dist/bin/Release/06_dynamic_stack64 11 | ../dist/bin/Release/07_custom_bvh_import64 12 | ../dist/bin/Release/08_ambient_occlusion64 13 | ../dist/bin/Release/09_motion_blur_srt64 14 | ../dist/bin/Release/10_motion_blur_matrix64 15 | ../dist/bin/Release/11_multi_custom_intersection64 16 | ../dist/bin/Release/12_cutout64 17 | ../dist/bin/Release/13_concurrent_scene_build64 18 | ../dist/bin/Release/14_batch_build64 19 | ../dist/bin/Release/15_multi_level_instancing64 20 | ../dist/bin/Release/16_fluid_simulation64 21 | ../dist/bin/Release/18_shadow_ray64 22 | ../dist/bin/Release/19_primary_ray64 23 | -------------------------------------------------------------------------------- /.clang-format: -------------------------------------------------------------------------------- 1 | BasedOnStyle: LLVM 2 | IndentWidth: 4 3 | TabWidth: 4 4 | UseTab: Always 5 | BreakBeforeBraces: Custom 6 | ColumnLimit: 128 7 | AllowShortBlocksOnASingleLine: false 8 | AllowShortIfStatementsOnASingleLine: true 9 | NamespaceIndentation: None 10 | SpacesInParentheses: true 11 | SpaceBeforeParens: ControlStatements 12 | SpaceAfterTemplateKeyword: true 13 | AlwaysBreakTemplateDeclarations: Yes 14 | PointerAlignment: Left 15 | 16 | SortIncludes: true 17 | AlignConsecutiveAssignments: true 18 | AlignConsecutiveDeclarations: true 19 | 20 | AlignEscapedNewlinesLeft: true 21 | AlignAfterOpenBracket: AlwaysBreak 22 | BinPackArguments: false 23 | BinPackParameters: false 24 | ExperimentalAutoDetectBinPacking: false 25 | AllowAllParametersOfDeclarationOnNextLine: true 26 | 27 | IndentExternBlock: NoIndent 28 | 29 | BreakBeforeBraces: Custom 30 | BraceWrapping: 31 | AfterClass: true 32 | AfterControlStatement: true 33 | AfterEnum: true 34 | AfterFunction: true 35 | AfterNamespace: true 36 | AfterObjCDeclaration: true 37 | AfterStruct: true 38 | AfterUnion: true 39 | BeforeCatch: true 40 | BeforeElse: true 41 | IndentBraces: false -------------------------------------------------------------------------------- /tutorials/common/meshes/cornellbox/cornellBox.mtl: -------------------------------------------------------------------------------- 1 | newmtl Light 2 | Ns 00.000000 3 | Ka 1.000000 1.000000 1.000000 4 | Kd 1.000000 1.000000 1.000000 5 | Ks 0.000000 0.000000 0.000000 6 | Ke 1.000000 1.000000 1.000000 7 | Ni 1.000000 8 | d 1.000000 9 | illum 2 10 | 11 | newmtl DarkGreen 12 | Ns 96.078431 13 | Ka 1.000000 1.000000 1.000000 14 | Kd 0.000000 0.320000 0.000000 15 | Ks 0.500000 0.500000 0.500000 16 | Ke 0.000000 0.000000 0.000000 17 | Ni 1.000000 18 | d 1.000000 19 | illum 2 20 | 21 | newmtl Khaki 22 | Ns 96.078431 23 | Ka 1.000000 1.000000 1.000000 24 | Kd 0.800000 0.659341 0.439560 25 | Ks 0.500000 0.500000 0.500000 26 | Ke 0.000000 0.000000 0.000000 27 | Ni 1.000000 28 | d 1.000000 29 | illum 2 30 | 31 | newmtl Grey 32 | Ns 96.078431 33 | Ka 1.000000 1.000000 1.000000 34 | Kd 0.500000 0.500000 0.500000 35 | Ks 0.500000 0.500000 0.500000 36 | Ke 0.000000 0.000000 0.000000 37 | Ni 1.000000 38 | d 1.000000 39 | illum 2 40 | 41 | newmtl BloodyRed 42 | Ns 96.078431 43 | Ka 1.000000 1.000000 1.000000 44 | Kd 0.445000 0.000000 0.000000 45 | Ks 0.500000 0.500000 0.500000 46 | Ke 0.000000 0.000000 0.000000 47 | Ni 1.000000 48 | d 1.000000 49 | illum 2 -------------------------------------------------------------------------------- /tutorials/common/meshes/cornellpot/cornellpot.mtl: -------------------------------------------------------------------------------- 1 | # Blender 4.1.0 MTL File: 'teapot_temp_2.blend' 2 | # www.blender.org 3 | 4 | newmtl BloodyRed 5 | Ns 96.078453 6 | Ka 1.000000 1.000000 1.000000 7 | Kd 0.445000 0.000000 0.000000 8 | Ks 0.500000 0.500000 0.500000 9 | Ke 0.000000 0.000000 0.000000 10 | Ni 1.000000 11 | d 1.000000 12 | illum 2 13 | 14 | newmtl DarkGreen 15 | Ns 96.078453 16 | Ka 1.000000 1.000000 1.000000 17 | Kd 0.000000 0.320000 0.000000 18 | Ks 0.500000 0.500000 0.500000 19 | Ke 0.000000 0.000000 0.000000 20 | Ni 1.000000 21 | d 1.000000 22 | illum 2 23 | 24 | newmtl Grey 25 | Ns 96.078453 26 | Ka 1.000000 1.000000 1.000000 27 | Kd 0.500000 0.500000 0.500000 28 | Ks 0.500000 0.500000 0.500000 29 | Ke 0.000000 0.000000 0.000000 30 | Ni 1.000000 31 | d 1.000000 32 | illum 2 33 | 34 | newmtl Khaki 35 | Ns 96.078453 36 | Ka 1.000000 1.000000 1.000000 37 | Kd 0.800000 0.659341 0.439560 38 | Ks 0.500000 0.500000 0.500000 39 | Ke 0.000000 0.000000 0.000000 40 | Ni 1.000000 41 | d 1.000000 42 | illum 2 43 | 44 | newmtl Light 45 | Ns 0.000000 46 | Ka 1.000000 1.000000 1.000000 47 | Kd 1.000000 1.000000 1.000000 48 | Ks 0.000000 0.000000 0.000000 49 | Ke 50.000000 50.000000 50.000000 50 | Ni 1.000000 51 | d 1.000000 52 | illum 1 53 | 54 | newmtl Material.001 55 | Ns 194.993576 56 | Ka 1.000000 1.000000 1.000000 57 | Kd 0.019456 0.765403 1.000000 58 | Ks 0.500000 0.500000 0.500000 59 | Ke 0.000000 0.000000 0.000000 60 | Ni 1.500000 61 | d 1.000000 62 | illum 2 63 | -------------------------------------------------------------------------------- /tutorials/common/FluidSimulation.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2021-2023 Advanced Micro Devices, Inc. All rights reserved. 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE. 21 | // 22 | 23 | #pragma once 24 | #include 25 | 26 | struct Simulation 27 | { 28 | float m_smoothRadius; 29 | float m_pressureStiffness; 30 | float m_restDensity; 31 | float m_densityCoef; 32 | float m_pressureGradCoef; 33 | float m_viscosityLaplaceCoef; 34 | float m_wallStiffness; 35 | uint32_t m_particleCount; 36 | float4 m_planes[6]; 37 | }; 38 | 39 | struct PerFrame 40 | { 41 | float m_timeStep; 42 | float3 m_gravity; 43 | }; 44 | 45 | struct Particle 46 | { 47 | float3 Pos; 48 | float3 Velocity; 49 | }; 50 | -------------------------------------------------------------------------------- /tutorials/18_shadow_ray/main.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2021-2024 Advanced Micro Devices, Inc. All rights reserved. 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE. 21 | // 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | class Tutorial : public SceneDemo 29 | { 30 | public: 31 | void run() 32 | { 33 | Camera camera = createCamera(); 34 | 35 | setupScene( camera, "../common/meshes/cornellpot/cornellpot.obj", "../common/meshes/cornellpot/" ); 36 | render( "18_shadow_ray.png", "../common/ShadowRayKernel.h", "ShadowRayKernel" ); 37 | deleteScene( m_scene ); 38 | return; 39 | } 40 | }; 41 | 42 | int main( int argc, char** argv ) 43 | { 44 | Tutorial tutorial; 45 | tutorial.init( 0 ); 46 | tutorial.run(); 47 | 48 | return 0; 49 | } 50 | -------------------------------------------------------------------------------- /doc/11_multi_custom_intersection.md: -------------------------------------------------------------------------------- 1 | # [11_multi_custom_intersection](../tutorials/11_multi_custom_intersection) 2 | 3 |
4 | 5 |
6 | img 7 |
8 | 9 | There is not much to say about this demo as custom intersection is already detailed in [this other demo](03_custom_intersection.md). 10 | 11 | One difference compared to the previous demo is that we use 2 custom functions: 12 | 13 | 14 | ```cpp 15 | std::vector funcNameSets( GeomTypesCount ); 16 | funcNameSets[SphereTypeIndex].intersectFuncName = "intersectSphere"; 17 | funcNameSets[CircleTypeIndex].intersectFuncName = "intersectCircle"; 18 | ``` 19 |
20 | 21 | we use the same `intersectSphere` than in the previous demo, but we also introduce this new `intersectCircle` custom intersection: 22 | 23 | ```cpp 24 | // check if there is a hit before ray.maxT. if there is, set it to tOut. hiprt will overwrite ray.maxT after this function 25 | __device__ bool intersectCircle( const hiprtRay& ray, const void* data, void* payload, hiprtHit& hit ) 26 | { 27 | const float4* o = reinterpret_cast( data ); 28 | float2 c = make_float2( o[hit.primID].x, o[hit.primID].y ); 29 | const float r = o[hit.primID].w; 30 | 31 | c.x = c.x - ray.origin.x; 32 | c.y = c.y - ray.origin.y; 33 | float d = sqrtf( c.x * c.x + c.y * c.y ); 34 | bool hasHit = d < r; 35 | if ( !hasHit ) return false; 36 | 37 | hit.normal = normalize( make_float3( d, d, d ) ); 38 | 39 | return true; 40 | } 41 | ``` 42 | 43 |
44 | 45 | 46 | Note that we now have 2 `geomType`: 47 | ```cpp 48 | constexpr uint32_t SphereTypeIndex = 0; 49 | constexpr uint32_t CircleTypeIndex = 1; 50 | ``` 51 | 52 |
53 | 54 | Another difference is that in this demo, we use a `hiprtScene`, so in the kernel, we have to use `hiprtSceneTraversalClosest` instead of `hiprtGeomCustomTraversalClosest`, as explained in the [demo introducing the hiprtScene](02_scene_intersection.md). 55 | 56 | 57 | -------------------------------------------------------------------------------- /tutorials/00_context_creation/main.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2021-2023 Advanced Micro Devices, Inc. All rights reserved. 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE. 21 | // 22 | 23 | #include 24 | 25 | int main( int argc, char** argv ) 26 | { 27 | const int deviceIndex = 0; 28 | 29 | CHECK_ORO( (oroError)oroInitialize( (oroApi)( ORO_API_HIP | ORO_API_CUDA ), 0 ) ); 30 | 31 | CHECK_ORO( oroInit( 0 ) ); 32 | 33 | oroDevice oroDevice; 34 | CHECK_ORO( oroDeviceGet( &oroDevice, deviceIndex ) ); 35 | 36 | oroCtx oroCtx; 37 | CHECK_ORO( oroCtxCreate( &oroCtx, 0, oroDevice ) ); 38 | 39 | oroDeviceProp props; 40 | CHECK_ORO( oroGetDeviceProperties( &props, oroDevice ) ); 41 | std::cout << "Executing on '" << props.name << "'" << std::endl; 42 | 43 | hiprtContextCreationInput ctxtInput; 44 | if ( std::string( props.name ).find( "NVIDIA" ) != std::string::npos ) 45 | ctxtInput.deviceType = hiprtDeviceNVIDIA; 46 | else 47 | ctxtInput.deviceType = hiprtDeviceAMD; 48 | ctxtInput.ctxt = oroGetRawCtx( oroCtx ); 49 | ctxtInput.device = oroGetRawDevice( oroDevice ); 50 | 51 | hiprtContext ctxt; 52 | CHECK_HIPRT( hiprtCreateContext( HIPRT_API_VERSION, ctxtInput, ctxt ) ); 53 | CHECK_HIPRT( hiprtDestroyContext( ctxt ) ); 54 | 55 | return 0; 56 | } 57 | -------------------------------------------------------------------------------- /tutorials/19_primary_ray/main.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2021-2024 Advanced Micro Devices, Inc. All rights reserved. 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE. 21 | // 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | class Tutorial : public SceneDemo 29 | { 30 | public: 31 | void run() 32 | { 33 | 34 | struct OPTION_DEF 35 | { 36 | OPTION_DEF( uint32_t i_, const std::string& name_ ) 37 | { 38 | i = i_; 39 | name = name_; 40 | } 41 | uint32_t i; 42 | std::string name; 43 | }; 44 | std::vector optionsList = { 45 | OPTION_DEF( VisualizeNormal, "normal" ), 46 | OPTION_DEF( VisualizeUv, "uv" ), 47 | OPTION_DEF( VisualizeId, "primId" ), 48 | OPTION_DEF( VisualizeHitDist, "depth" ), 49 | }; 50 | 51 | Camera camera = createCamera(); 52 | setupScene( 53 | camera, 54 | "../common/meshes/cornellpot/cornellpot.obj", 55 | "../common/meshes/cornellpot/", 56 | false, 57 | std::nullopt, 58 | hiprtBuildFlagBitPreferFastBuild ); 59 | 60 | for ( const auto& o : optionsList ) 61 | { 62 | const std::string kernelName = "PrimaryRayKernel_" + std::to_string( o.i ); 63 | 64 | render( "19_primary_ray_" + o.name + ".png", "../common/PrimaryRayKernel.h", kernelName ); 65 | } 66 | 67 | deleteScene( m_scene ); 68 | } 69 | }; 70 | 71 | int main( int argc, char** argv ) 72 | { 73 | Tutorial tutorial; 74 | tutorial.init( 0 ); 75 | tutorial.run(); 76 | return 0; 77 | } 78 | -------------------------------------------------------------------------------- /tutorials/17_hiprt_hip/main.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2021-2023 Advanced Micro Devices, Inc. All rights reserved. 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE. 21 | // 22 | 23 | #if defined( __USE_HIP__ ) 24 | #include 25 | #include 26 | #include 27 | 28 | #define CHECK_HIP( error ) ( checkHip( error, __FILE__, __LINE__ ) ) 29 | void checkHip( hipError_t res, const char* file, int line ) 30 | { 31 | if ( res != hipSuccess ) 32 | { 33 | std::cerr << "HIP error: '" << hipGetErrorString( res ) << "' on line " << line << " " 34 | << " in '" << file << "'." << std::endl; 35 | exit( EXIT_FAILURE ); 36 | } 37 | } 38 | 39 | #define CHECK_HIPRT( error ) ( checkHiprt( error, __FILE__, __LINE__ ) ) 40 | void checkHiprt( hiprtError res, const char* file, int line ) 41 | { 42 | if ( res != hiprtSuccess ) 43 | { 44 | std::cerr << "HIPRT error: '" << res << "' on line " << line << " " 45 | << " in '" << file << "'." << std::endl; 46 | exit( EXIT_FAILURE ); 47 | } 48 | } 49 | #endif 50 | 51 | int main( int argc, char** argv ) 52 | { 53 | #if defined( __USE_HIP__ ) 54 | CHECK_HIP( hipInit( 0 ) ); 55 | 56 | hipDevice_t hipDevice; 57 | CHECK_HIP( hipGetDevice( &hipDevice ) ); 58 | 59 | hipCtx_t hipCtx; 60 | CHECK_HIP( hipCtxCreate( &hipCtx, 0, hipDevice ) ); 61 | 62 | hipDeviceProp_t props; 63 | CHECK_HIP( hipGetDeviceProperties( &props, hipDevice ) ); 64 | std::cout << "Executing on '" << props.name << "'" << std::endl; 65 | 66 | hiprtContextCreationInput ctxtInput; 67 | if ( std::string( props.name ).find( "NVIDIA" ) != std::string::npos ) 68 | ctxtInput.deviceType = hiprtDeviceNVIDIA; 69 | else 70 | ctxtInput.deviceType = hiprtDeviceAMD; 71 | ctxtInput.ctxt = hipCtx; 72 | ctxtInput.device = hipDevice; 73 | 74 | hiprtContext ctxt; 75 | CHECK_HIPRT( hiprtCreateContext( HIPRT_API_VERSION, ctxtInput, ctxt ) ); 76 | CHECK_HIPRT( hiprtDestroyContext( ctxt ) ); 77 | #endif 78 | return 0; 79 | } 80 | -------------------------------------------------------------------------------- /tutorials/premake5.lua: -------------------------------------------------------------------------------- 1 | 2 | function copydir(src_dir, dst_dir, filter, single_dst_dir) 3 | filter = filter or "**" 4 | src_dir = src_dir .. "/" 5 | print('copy "' .. src_dir .. filter .. '" to "' .. dst_dir .. '".') 6 | dst_dir = dst_dir .. "/" 7 | local dir = path.rebase(".", path.getabsolute("."), src_dir) -- root dir, relative from src_dir 8 | 9 | os.chdir(src_dir) -- change current directory to src_dir 10 | local matches = os.matchfiles(filter) 11 | os.chdir(dir) -- change current directory back to root 12 | 13 | local counter = 0 14 | for k, v in ipairs(matches) do 15 | local target = iif(single_dst_dir, path.getname(v), v) 16 | --make sure, that directory exists or os.copyfile() fails 17 | os.mkdir(path.getdirectory(dst_dir .. target)) 18 | if os.copyfile(src_dir .. v, dst_dir .. target) then 19 | counter = counter + 1 20 | end 21 | end 22 | 23 | if counter == #matches then 24 | print(counter .. " files copied.") 25 | return true 26 | else 27 | print("Error: " .. counter .. "/" .. #matches .. " files copied.") 28 | return nil 29 | end 30 | end 31 | 32 | workspace "hiprtSdkTutorial" 33 | configurations {"Debug", "Release", "RelWithDebInfo", "DebugGpu" } 34 | language "C++" 35 | platforms "x64" 36 | architecture "x86_64" 37 | 38 | if os.ishost("windows") then 39 | defines {"__WINDOWS__"} 40 | end 41 | characterset("MBCS") 42 | 43 | filter {"platforms:x64", "configurations:Debug or configurations:DebugGpu"} 44 | targetsuffix "64D" 45 | defines {"DEBUG"} 46 | symbols "On" 47 | filter {"platforms:x64", "configurations:DebugGpu"} 48 | defines {"DEBUG_GPU"} 49 | filter {"platforms:x64", "configurations:Release or configurations:RelWithDebInfo"} 50 | targetsuffix "64" 51 | defines {"NDEBUG"} 52 | optimize "On" 53 | filter {"platforms:x64", "configurations:RelWithDebInfo"} 54 | symbols "On" 55 | filter {} 56 | 57 | if os.ishost("windows") then 58 | buildoptions {"/wd4244", "/wd4305", "/wd4018", "/wd4996"} 59 | end 60 | 61 | include "00_context_creation" 62 | include "01_geom_intersection" 63 | include "02_scene_intersection" 64 | include "03_custom_intersection" 65 | include "04_compaction" 66 | include "05_global_stack" 67 | include "06_dynamic_stack" 68 | include "07_custom_bvh_import" 69 | include "08_ambient_occlusion" 70 | include "09_motion_blur_srt" 71 | include "10_motion_blur_matrix" 72 | include "11_multi_custom_intersection" 73 | include "12_cutout" 74 | include "13_concurrent_scene_build" 75 | include "14_batch_build" 76 | include "15_multi_level_instancing" 77 | include "16_fluid_simulation" 78 | include "17_hiprt_hip" 79 | include "18_shadow_ray" 80 | include "19_primary_ray" 81 | 82 | if os.ishost("windows") then 83 | copydir( "../hiprt/win/", "./dist/bin/Release/" ) 84 | copydir( "../hiprt/win/", "./dist/bin/Debug/" ) 85 | end 86 | -------------------------------------------------------------------------------- /tutorials/common/TutorialBase.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2021-2023 Advanced Micro Devices, Inc. All rights reserved. 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE. 21 | // 22 | 23 | #pragma once 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | 34 | #define CHECK_ORO( error ) ( checkOro( error, __FILE__, __LINE__ ) ) 35 | void checkOro( oroError res, const char* file, uint32_t line ); 36 | 37 | #define CHECK_HIPRT( error ) ( checkHiprt( error, __FILE__, __LINE__ ) ) 38 | void checkHiprt( hiprtError res, const char* file, uint32_t line ); 39 | 40 | #define CHECK_ORORTC( error ) ( checkOrortc( error, __FILE__, __LINE__ ) ) 41 | void checkOrortc( orortcResult res, const char* file, uint32_t line ); 42 | 43 | class TutorialBase 44 | { 45 | public: 46 | virtual ~TutorialBase() { printf( "success\n" ); } 47 | void init( uint32_t deviceIndex = 0 ); 48 | 49 | virtual void run() = 0; 50 | 51 | void buildTraceKernelFromBitcode( 52 | hiprtContext ctxt, 53 | const char* path, 54 | const char* functionName, 55 | oroFunction& functionOut, 56 | std::vector* opts = nullptr, 57 | std::vector* funcNameSets = nullptr, 58 | uint32_t numGeomTypes = 0, 59 | uint32_t numRayTypes = 1 ); 60 | 61 | void launchKernel( oroFunction func, uint32_t nx, uint32_t ny, void** args ); 62 | void launchKernel( oroFunction func, uint32_t nx, uint32_t ny, uint32_t bx, uint32_t by, void** args ); 63 | 64 | static void writeImage( const std::string& path, uint32_t width, uint32_t height, uint8_t* pixels ); 65 | 66 | static bool readSourceCode( 67 | const std::filesystem::path& path, 68 | std::string& sourceCode, 69 | std::optional> includes = std::nullopt ); 70 | 71 | protected: 72 | hiprtContextCreationInput m_ctxtInput; 73 | oroCtx m_oroCtx; 74 | oroDevice m_oroDevice; 75 | hiprtInt2 m_res; 76 | }; 77 | -------------------------------------------------------------------------------- /tutorials/readme.md: -------------------------------------------------------------------------------- 1 | # HIPRT Tutorials 2 | 3 | ## List of tutorials 4 | 5 | | Demo name | Image | Documentation | Description | 6 | |---|:---:|:--:|--| 7 | |[01_geom_intersection](./01_geom_intersection) | drawing | [:page_facing_up:](../doc/01_geom_intersection.md) | Intersection using hiprtGeometry. | 8 | |[02_scene_intersection](./02_scene_intersection) | drawing | [:page_facing_up:](../doc/02_scene_intersection.md) | Intersection using hiprtScene. | 9 | |[03_custom_intersection](./03_custom_intersection) | drawing | [:page_facing_up:](../doc/03_custom_intersection.md) | Using a custom intersection function. | 10 | |[04_compaction](./04_compaction) | drawing | | Acceleration structure compaction. | 11 | |[05_global_stack](./05_global_stack) | drawing | | Global traversal stack for good performance. | 12 | |[06_dynamic_stack](./06_dynamic_stack) | drawing | | Dynamic traversal stack for balancing performance and memory requirements. | 13 | |[07_custom_bvh](./07_custom_bvh_import) | drawing | [:page_facing_up:](../doc/07_custom_bvh_import.md) | Loading a BVH a user provides. | 14 | |[08_ambient_occlusion](./08_ambient_occlusion) | drawing | [:page_facing_up:](../doc/08_ambient_occlusion.md) | Ambient occlusion. | 15 | |[09_motion_blur_srt](./09_motion_blur) | drawing | | Rendering objects under motion using SRT components. | 16 | |[10_motion_blur_matrix](./10_motion_blur) | drawing | | Rendering objects under motion using Matrix. | 17 | |[11_multi_custom_intersection](./11_multi_custom_intersection) | drawing | [:page_facing_up:](../doc/11_multi_custom_intersection.md) | Multiple primitives with custom intersection. | 18 | |[12_cutout](./12_cutout) | drawing | | Alpha masking using the intersection filter. | 19 | |[13_concurrent_scene_build](./13_concurrent_scene_build) | drawing | | Build geometries using multiple streams concurrently. | 20 | |[14_batch_build](./14_batch_build) | drawing | | Build small geometries concurrently in a single batch. | 21 | |[15_multi_level_instancing](./15_multi_level_instancing) | drawing | | Multi-level instancing. | 22 | |[16_fluid_simulation](./16_fluid_simulation) | drawing | | A simple fluid simulation. | 23 | |[18_shadow_ray](./18_shadow_ray) | drawing | [:page_facing_up:](../doc/18_shadow_ray.md) | Shows how to trace a shadow ray in an OBJ scene. | 24 | |[19_primary_ray](./19_primary_ray) | drawing | [:page_facing_up:](../doc/19_primary_ray.md) | Shows how to trace different types of primary rays in an OBJ scene. | 25 | -------------------------------------------------------------------------------- /doc/02_scene_intersection.md: -------------------------------------------------------------------------------- 1 | # [02_scene_intersection](../tutorials/02_scene_intersection) 2 | 3 |
4 | 5 | This demo illustrates the usage of the `hiprtScene` object in the HIPRT API, focusing on creating, building, and using a scene for ray tracing.
6 | The triangle mesh is the basic primitive of HIPRT from which we build `hiprtGeometry`. 7 | In general, scenes are comprised of many meshes. Developers can utilize `hiprtScene` support on top of these meshes to create an acceleration structure which can be used to search for a mesh efficiently when there are many meshes. 8 | 9 |
10 | img 11 |
12 | 13 | 14 | The geometry setup of this demo is close to the [previous demo](01_geom_intersection.md). We are just creating 2 triangles instead of 1. 15 | 16 |
17 |
18 | 19 | The difference compared to the previous demo is that we use `hiprtScene`. First, we need to set the `sceneInput` that will be used to create and build the `hiprtScene`. 20 | An instance of the geometry is created and added to the scene. The `sceneInput` is configured with this instance, and transformation parameters are set: 21 | 22 | ```cpp 23 | hiprtInstance instance; 24 | instance.type = hiprtInstanceTypeGeometry; 25 | instance.geometry = geom; 26 | 27 | hiprtSceneBuildInput sceneInput; 28 | sceneInput.instanceCount = 1; 29 | sceneInput.instanceMasks = nullptr; 30 | sceneInput.instanceTransformHeaders = nullptr; 31 | oroMalloc( reinterpret_cast( &sceneInput.instances ), sizeof( hiprtInstance ) ); 32 | oroMemcpyHtoD( reinterpret_cast( sceneInput.instances ), &instance, sizeof( hiprtInstance ) ); 33 | 34 | hiprtFrameSRT frame; 35 | frame.translation = make_hiprtFloat3( 0.0f, 0.0f, 0.0f ); 36 | frame.scale = make_hiprtFloat3( 0.5f, 0.5f, 0.5f ); 37 | frame.rotation = make_hiprtFloat4( 0.0f, 0.0f, 1.0f, 0.0f ); 38 | sceneInput.frameCount = 1; 39 | oroMalloc( reinterpret_cast( &sceneInput.instanceFrames ), sizeof( hiprtFrameSRT ) ); 40 | oroMemcpyHtoD( reinterpret_cast( sceneInput.instanceFrames ), &frame, sizeof( hiprtFrameSRT ) ); 41 | ``` 42 | 43 | If there are more meshes in a scene, we need to create many geometries. 44 | 45 |
46 |
47 | 48 | The scene is built using HIPRT functions. Note that we need to create a temporary buffer. Temporary buffers are intermediate memory allocations used during the construction of the geometry and scene in HIPRT. 49 | These buffers are necessary for storing intermediate data required by the HIPRT API to build complex structures, such as BVHs or other acceleration structures, but are not needed once the build process is complete. Therefore, we can release it after the build. 50 | 51 | ```cpp 52 | size_t sceneTempSize; 53 | hiprtDevicePtr sceneTemp = nullptr; 54 | hiprtGetSceneBuildTemporaryBufferSize( ctxt, sceneInput, options, sceneTempSize ); 55 | oroMalloc( reinterpret_cast( &sceneTemp ), sceneTempSize ); 56 | 57 | hiprtScene scene = nullptr; 58 | hiprtCreateScene( ctxt, sceneInput, options, scene ); 59 | hiprtBuildScene( ctxt, hiprtBuildOperationBuild, sceneInput, options, sceneTemp, 0, scene ); 60 | 61 | // we can free the Temporary Buffer just after hiprtBuildScene, as this buffer is only used during the build. 62 | oroFree( reinterpret_cast( sceneTemp ) ); 63 | sceneTemp = nullptr; 64 | ``` 65 |
66 |
67 | 68 | Concerning the kernel it is also close to the previous demo, but instead of manipulating `hiprtGeometry`, it uses `hiprtScene`.
69 | so, `hiprtGeometry` is replaced by `hiprtScene`, and `hiprtGeomTraversalClosest` is replaced by `hiprtSceneTraversalClosest`. 70 | 71 | 72 | 73 | 74 | -------------------------------------------------------------------------------- /tutorials/common/Aabb.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2021-2023 Advanced Micro Devices, Inc. All rights reserved. 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE. 21 | // 22 | 23 | #pragma once 24 | #include 25 | #include 26 | 27 | struct Aabb 28 | { 29 | HIPRT_HOST_DEVICE HIPRT_INLINE Aabb() { reset(); } 30 | 31 | HIPRT_HOST_DEVICE HIPRT_INLINE Aabb( const hiprtFloat3& p ) : m_min( p ), m_max( p ) {} 32 | 33 | HIPRT_HOST_DEVICE HIPRT_INLINE Aabb( const hiprtFloat3& mi, const hiprtFloat3& ma ) : m_min( mi ), m_max( ma ) {} 34 | 35 | HIPRT_HOST_DEVICE HIPRT_INLINE Aabb( const Aabb& rhs, const Aabb& lhs ) 36 | { 37 | m_min.x = fminf( lhs.m_min.x, rhs.m_min.x ); 38 | m_min.y = fminf( lhs.m_min.y, rhs.m_min.y ); 39 | m_min.z = fminf( lhs.m_min.z, rhs.m_min.z ); 40 | m_max.x = fmaxf( lhs.m_max.x, rhs.m_max.x ); 41 | m_max.y = fmaxf( lhs.m_max.y, rhs.m_max.y ); 42 | m_max.z = fmaxf( lhs.m_max.z, rhs.m_max.z ); 43 | } 44 | 45 | HIPRT_HOST_DEVICE HIPRT_INLINE void reset( void ) 46 | { 47 | m_min = { hiprt::FltMax, hiprt::FltMax, hiprt::FltMax }; 48 | m_max = { -hiprt::FltMax, -hiprt::FltMax, -hiprt::FltMax }; 49 | } 50 | 51 | HIPRT_HOST_DEVICE HIPRT_INLINE Aabb& grow( const hiprtFloat3& p ) 52 | { 53 | m_min.x = fminf( m_min.x, p.x ); 54 | m_min.y = fminf( m_min.y, p.y ); 55 | m_min.z = fminf( m_min.z, p.z ); 56 | m_max.x = fmaxf( m_max.x, p.x ); 57 | m_max.y = fmaxf( m_max.y, p.y ); 58 | m_max.z = fmaxf( m_max.z, p.z ); 59 | return *this; 60 | } 61 | 62 | HIPRT_HOST_DEVICE HIPRT_INLINE Aabb& grow( const Aabb& rhs ) 63 | { 64 | m_min.x = fminf( m_min.x, rhs.m_min.x ); 65 | m_min.y = fminf( m_min.y, rhs.m_min.y ); 66 | m_min.z = fminf( m_min.z, rhs.m_min.z ); 67 | m_max.x = fmaxf( m_max.x, rhs.m_max.x ); 68 | m_max.y = fmaxf( m_max.y, rhs.m_max.y ); 69 | m_max.z = fmaxf( m_max.z, rhs.m_max.z ); 70 | return *this; 71 | } 72 | 73 | HIPRT_HOST_DEVICE HIPRT_INLINE hiprtFloat3 center() const 74 | { 75 | hiprtFloat3 c; 76 | c.x = ( m_max.x + m_min.x ) * 0.5f; 77 | c.y = ( m_max.y + m_min.y ) * 0.5f; 78 | c.z = ( m_max.z + m_min.z ) * 0.5f; 79 | return c; 80 | } 81 | 82 | HIPRT_HOST_DEVICE HIPRT_INLINE hiprtFloat3 extent() const 83 | { 84 | hiprtFloat3 e; 85 | e.x = m_max.x - m_min.x; 86 | e.y = m_max.y - m_min.y; 87 | e.z = m_max.z - m_min.z; 88 | return e; 89 | } 90 | 91 | HIPRT_HOST_DEVICE HIPRT_INLINE float area() const 92 | { 93 | hiprtFloat3 ext = extent(); 94 | return 2 * ( ext.x * ext.y + ext.x * ext.z + ext.y * ext.z ); 95 | } 96 | 97 | hiprtFloat3 m_min; 98 | hiprtFloat3 m_max; 99 | }; 100 | -------------------------------------------------------------------------------- /tutorials/common/meshes/cornellbox/cornellBox.obj: -------------------------------------------------------------------------------- 1 | mtllib cornellBox.mtl 2 | o area_light 3 | v -0.884011 5.319334 -2.517968 4 | v -0.884011 5.318497 -3.567968 5 | v 0.415989 5.318497 -3.567968 6 | v 0.415989 5.319334 -2.517968 7 | vn 0.0000 -1.0000 0.0008 8 | usemtl Light 9 | s off 10 | f 2//1 4//1 1//1 11 | f 2//1 3//1 4//1 12 | o back_wall 13 | v -2.950011 -0.162686 -5.835598 14 | v 2.545989 -0.162686 -5.835598 15 | v 2.545989 5.325313 -5.839967 16 | v -3.014011 5.325313 -5.839967 17 | vn 0.0000 0.0008 1.0000 18 | usemtl Grey 19 | s off 20 | f 5//2 7//2 8//2 21 | f 5//2 6//2 7//2 22 | o ceiling 23 | v -3.014011 5.329765 -0.247969 24 | v -3.014011 5.325313 -5.839968 25 | v 2.545989 5.325313 -5.839968 26 | v 2.545989 5.329765 -0.247969 27 | vn 0.0000 -1.0000 0.0008 28 | usemtl Grey 29 | s off 30 | f 10//3 12//3 9//3 31 | f 10//3 11//3 12//3 32 | o floor 33 | v -2.982011 -0.158233 -0.243599 34 | v 2.545989 -0.158233 -0.243599 35 | v 2.545989 -0.162686 -5.835598 36 | v -2.950011 -0.162686 -5.835598 37 | vn 0.0000 1.0000 -0.0008 38 | usemtl Grey 39 | s off 40 | f 14//4 16//4 13//4 41 | f 14//4 15//4 16//4 42 | o left_wall 43 | v -2.982011 -0.158233 -0.243599 44 | v -2.950011 -0.162686 -5.835598 45 | v -3.014011 5.325313 -5.839968 46 | v -3.014011 5.329765 -0.247969 47 | vn 1.0000 0.0058 -0.0000 48 | vn 0.9999 0.0117 0.0057 49 | usemtl BloodyRed 50 | s off 51 | f 17//5 19//5 20//5 52 | f 17//6 18//6 19//6 53 | o right_wall 54 | v 2.545989 -0.162686 -5.835598 55 | v 2.545989 -0.158233 -0.243599 56 | v 2.545989 5.329765 -0.247969 57 | v 2.545989 5.325313 -5.839968 58 | vn -1.0000 0.0000 0.0000 59 | usemtl DarkGreen 60 | s off 61 | f 22//7 24//7 21//7 62 | f 22//7 23//7 24//7 63 | o short_box 64 | v 1.245989 1.491249 -0.894913 65 | v 1.725989 1.489975 -2.494912 66 | v 0.145989 1.489601 -2.964912 67 | v -0.354011 1.490859 -1.384912 68 | v -0.354011 -0.159141 -1.383599 69 | v -0.354011 1.490859 -1.384912 70 | v 0.145989 1.489601 -2.964912 71 | v 0.145989 -0.160399 -2.963598 72 | v 1.245989 -0.158750 -0.893599 73 | v 1.245989 1.491249 -0.894913 74 | v -0.354011 1.490859 -1.384912 75 | v -0.354011 -0.159141 -1.383599 76 | v 1.725989 -0.160024 -2.493598 77 | v 1.725989 1.489975 -2.494912 78 | v 1.245989 1.491249 -0.894913 79 | v 1.245989 -0.158750 -0.893599 80 | v 0.145989 -0.160399 -2.963598 81 | v 0.145989 1.489601 -2.964912 82 | v 1.725989 1.489975 -2.494912 83 | v 1.725989 -0.160024 -2.493598 84 | vn 0.0000 1.0000 -0.0008 85 | vn -0.9534 -0.0002 -0.3017 86 | vn -0.2928 0.0008 0.9562 87 | vn 0.9578 0.0002 0.2873 88 | vn 0.2851 -0.0008 -0.9585 89 | usemtl Khaki 90 | s off 91 | f 25//8 27//8 28//8 92 | f 30//9 32//9 29//9 93 | f 34//10 36//10 33//10 94 | f 38//11 40//11 37//11 95 | f 42//12 44//12 41//12 96 | f 25//8 26//8 27//8 97 | f 30//9 31//9 32//9 98 | f 34//10 35//10 36//10 99 | f 38//11 39//11 40//11 100 | f 42//12 43//12 44//12 101 | o tall_box 102 | v -1.684011 3.139799 -2.716226 103 | v -0.104011 3.139409 -3.206226 104 | v -0.594011 3.138135 -4.806226 105 | v -2.174011 3.138533 -4.306226 106 | v -1.684011 -0.160200 -2.713598 107 | v -1.684011 3.139799 -2.716226 108 | v -2.174011 3.138533 -4.306226 109 | v -2.174011 -0.161466 -4.303598 110 | v -2.174011 -0.161466 -4.303598 111 | v -2.174011 3.138533 -4.306226 112 | v -0.594011 3.138135 -4.806226 113 | v -0.594011 -0.161864 -4.803598 114 | v -0.594011 -0.161864 -4.803598 115 | v -0.594011 3.138135 -4.806226 116 | v -0.104011 3.139409 -3.206226 117 | v -0.104011 -0.160590 -3.203598 118 | v -0.104011 -0.160590 -3.203598 119 | v -0.104011 3.139409 -3.206226 120 | v -1.684011 3.139799 -2.716226 121 | v -1.684011 -0.160200 -2.713598 122 | vn -0.0000 1.0000 -0.0008 123 | vn -0.9556 0.0002 0.2945 124 | vn -0.3017 -0.0008 -0.9534 125 | vn 0.9562 -0.0002 -0.2928 126 | vn 0.2962 0.0008 0.9551 127 | usemtl Khaki 128 | s off 129 | f 46//13 48//13 45//13 130 | f 49//14 51//14 52//14 131 | f 54//15 56//15 53//15 132 | f 58//16 60//16 57//16 133 | f 62//17 64//17 61//17 134 | f 46//13 47//13 48//13 135 | f 49//14 50//14 51//14 136 | f 54//15 55//15 56//15 137 | f 58//16 59//16 60//16 138 | f 62//17 63//17 64//17 -------------------------------------------------------------------------------- /tutorials/01_geom_intersection/main.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2021-2023 Advanced Micro Devices, Inc. All rights reserved. 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE. 21 | // 22 | 23 | #include 24 | 25 | class Tutorial : public TutorialBase 26 | { 27 | public: 28 | void run() 29 | { 30 | hiprtContext ctxt; 31 | CHECK_HIPRT( hiprtCreateContext( HIPRT_API_VERSION, m_ctxtInput, ctxt ) ); 32 | 33 | hiprtTriangleMeshPrimitive mesh; 34 | mesh.triangleCount = 1; 35 | mesh.triangleStride = sizeof( hiprtInt3 ); 36 | uint32_t triangleIndices[] = { 0, 1, 2 }; 37 | CHECK_ORO( 38 | oroMalloc( reinterpret_cast( &mesh.triangleIndices ), mesh.triangleCount * sizeof( hiprtInt3 ) ) ); 39 | CHECK_ORO( oroMemcpyHtoD( 40 | reinterpret_cast( mesh.triangleIndices ), 41 | triangleIndices, 42 | mesh.triangleCount * sizeof( hiprtInt3 ) ) ); 43 | 44 | mesh.vertexCount = 3; 45 | mesh.vertexStride = sizeof( hiprtFloat3 ); 46 | hiprtFloat3 vertices[] = { { 0.0f, 0.0f, 0.0f }, { 1.0f, 0.0f, 0.0f }, { 0.5f, 1.0f, 0.0f } }; 47 | CHECK_ORO( oroMalloc( reinterpret_cast( &mesh.vertices ), mesh.vertexCount * sizeof( hiprtFloat3 ) ) ); 48 | CHECK_ORO( oroMemcpyHtoD( 49 | reinterpret_cast( mesh.vertices ), vertices, mesh.vertexCount * sizeof( hiprtFloat3 ) ) ); 50 | 51 | hiprtGeometryBuildInput geomInput; 52 | geomInput.type = hiprtPrimitiveTypeTriangleMesh; 53 | geomInput.primitive.triangleMesh = mesh; 54 | 55 | size_t geomTempSize; 56 | hiprtDevicePtr geomTemp; 57 | hiprtBuildOptions options; 58 | options.buildFlags = hiprtBuildFlagBitPreferFastBuild; 59 | CHECK_HIPRT( hiprtGetGeometryBuildTemporaryBufferSize( ctxt, geomInput, options, geomTempSize ) ); 60 | CHECK_ORO( oroMalloc( reinterpret_cast( &geomTemp ), geomTempSize ) ); 61 | 62 | hiprtGeometry geom; 63 | CHECK_HIPRT( hiprtCreateGeometry( ctxt, geomInput, options, geom ) ); 64 | CHECK_HIPRT( hiprtBuildGeometry( ctxt, hiprtBuildOperationBuild, geomInput, options, geomTemp, 0, geom ) ); 65 | 66 | oroFunction func; 67 | buildTraceKernelFromBitcode( ctxt, "../common/TutorialKernels.h", "GeomIntersectionKernel", func ); 68 | 69 | uint8_t* pixels; 70 | CHECK_ORO( oroMalloc( reinterpret_cast( &pixels ), m_res.x * m_res.y * 4 ) ); 71 | 72 | void* args[] = { &geom, &pixels, &m_res }; 73 | launchKernel( func, m_res.x, m_res.y, args ); 74 | writeImage( "01_geom_intersection.png", m_res.x, m_res.y, pixels ); 75 | 76 | CHECK_ORO( oroFree( reinterpret_cast( mesh.triangleIndices ) ) ); 77 | CHECK_ORO( oroFree( reinterpret_cast( mesh.vertices ) ) ); 78 | CHECK_ORO( oroFree( reinterpret_cast( geomTemp ) ) ); 79 | CHECK_ORO( oroFree( reinterpret_cast( pixels ) ) ); 80 | 81 | CHECK_HIPRT( hiprtDestroyGeometry( ctxt, geom ) ); 82 | CHECK_HIPRT( hiprtDestroyContext( ctxt ) ); 83 | } 84 | }; 85 | 86 | int main( int argc, char** argv ) 87 | { 88 | Tutorial tutorial; 89 | tutorial.init( 0 ); 90 | tutorial.run(); 91 | 92 | return 0; 93 | } 94 | -------------------------------------------------------------------------------- /doc/19_primary_ray.md: -------------------------------------------------------------------------------- 1 | # [19_primary_ray](../tutorials/19_primary_ray) 2 | 3 |
4 | 5 | This demo shows examples of primary ray renderings. It can be useful for obtaining various information about the rendered scene and is quite straightforward to implement. 6 | 7 |
8 | img 9 |
10 | 11 | ## Overview 12 | 13 | This demo uses the same framework presented in [the demo of shadow ray](18_shadow_ray.md), so we won't describe it in detail again. Here is the high-level source code for creating the scene.
14 | It creates the scene and renders it with different primary ray options using the `PrimaryRayKernel`. 15 | 16 | 17 | ```cpp 18 | std::vector optionsList = { 19 | OPTION_DEF(VisualizeNormal,"normal"), 20 | OPTION_DEF(VisualizeUv,"uv"), 21 | OPTION_DEF(VisualizeId,"primId"), 22 | OPTION_DEF(VisualizeHitDist,"depth"), 23 | }; 24 | 25 | Camera camera = createCamera(); 26 | setupScene( 27 | camera, 28 | "../common/meshes/cornellpot/cornellpot.obj", 29 | "../common/meshes/cornellpot/", 30 | false, 31 | std::nullopt, 32 | hiprtBuildFlagBitPreferFastBuild 33 | ); 34 | 35 | for(const auto& o : optionsList) 36 | { 37 | const std::string kernelName = "PrimaryRayKernel_" + std::to_string( o.i ); 38 | render( 39 | "19_primaryRay_" + o.name + ".png", 40 | "../common/PrimaryRayKernel.h", 41 | kernelName 42 | ); 43 | } 44 | 45 | deleteScene( m_scene ); 46 | ``` 47 | 48 |
49 | 50 | ## Primary Ray Kernel 51 | 52 | This kernel is designed to demonstrate primary ray tracing, capturing various attributes such as UV coordinates, depth, and more from primary ray information. 53 | 54 |
55 | 56 | 57 | ### Kernel Entry Points 58 | 59 | The kernel has multiple entry points, each configured to visualize a different attribute. These entry points call a templated PrimaryRayKernel with specific visualization options: 60 | 61 | ```cpp 62 | extern "C" __global__ void PrimaryRayKernel_0(...){ PrimaryRayKernel(...); } 63 | extern "C" __global__ void PrimaryRayKernel_1(...){ PrimaryRayKernel(...); } 64 | extern "C" __global__ void PrimaryRayKernel_2(...){ PrimaryRayKernel(...); } 65 | extern "C" __global__ void PrimaryRayKernel_3(...){ PrimaryRayKernel(...); } 66 | extern "C" __global__ void PrimaryRayKernel_4(...){ PrimaryRayKernel(...); } 67 | extern "C" __global__ void PrimaryRayKernel_5(...){ PrimaryRayKernel(...); } 68 | ``` 69 |
70 | 71 | 72 | ### Ray Generation and Traversal 73 | 74 | Each thread generates a primary ray for a pixel, performs scene traversal to find intersections, and determines the hit information: 75 | 76 | ```cpp 77 | hiprtRay ray = generateRay(x, y, resolution, camera, seed, false); 78 | hiprtSceneTraversalClosestCustomStack tr(scene, ray, stack, instanceStack); 79 | hiprtHit hit = tr.getNextHit(); 80 | ``` 81 |
82 | 83 | 84 | ### Color Computation 85 | 86 | Based on the template parameter, different attributes are visualized: 87 | 88 | for example, the Diffuse Color: 89 | 90 | ```cpp 91 | template <> 92 | __device__ int3 getColor(hiprtScene scene, const hiprtHit& hit, uint32_t* matIndices, 93 | Material* materials, uint32_t* matOffsetPerInstance) { 94 | const uint32_t matOffset = matOffsetPerInstance[hit.instanceID] + hit.primID; 95 | const uint32_t matIndex = matIndices[matOffset]; 96 | float3 diffuseColor = materials[matIndex].m_diffuse; 97 | int3 color = {diffuseColor.x * 255, diffuseColor.y * 255, diffuseColor.z * 255}; 98 | return color; 99 | } 100 | ``` 101 | 102 | Another example, the UV Coordinates: 103 | 104 | ```cpp 105 | template <> 106 | __device__ int3 getColor(hiprtScene scene, const hiprtHit& hit, uint32_t* matIndices, 107 | Material* materials, uint32_t* matOffsetPerInstance) { 108 | int3 color = {clamp(static_cast(hit.uv.x * 255), 0, 255), clamp(static_cast(hit.uv.y * 255), 0, 255), 0}; 109 | return color; 110 | } 111 | 112 | ``` 113 | 114 | 115 | 116 | 117 | 118 | -------------------------------------------------------------------------------- /tutorials/04_compaction/main.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2021-2023 Advanced Micro Devices, Inc. All rights reserved. 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE. 21 | // 22 | 23 | #include 24 | #include 25 | #include 26 | 27 | class Tutorial : public TutorialBase 28 | { 29 | public: 30 | void run() 31 | { 32 | hiprtContext ctxt; 33 | CHECK_HIPRT( hiprtCreateContext( HIPRT_API_VERSION, m_ctxtInput, ctxt ) ); 34 | 35 | hiprtTriangleMeshPrimitive mesh; 36 | mesh.triangleCount = CornellBoxTriangleCount; 37 | mesh.triangleStride = sizeof( hiprtInt3 ); 38 | std::array triangleIndices; 39 | std::iota( triangleIndices.begin(), triangleIndices.end(), 0 ); 40 | CHECK_ORO( 41 | oroMalloc( reinterpret_cast( &mesh.triangleIndices ), mesh.triangleCount * sizeof( hiprtInt3 ) ) ); 42 | CHECK_ORO( oroMemcpyHtoD( 43 | reinterpret_cast( mesh.triangleIndices ), 44 | triangleIndices.data(), 45 | mesh.triangleCount * sizeof( hiprtInt3 ) ) ); 46 | 47 | mesh.vertexCount = 3 * mesh.triangleCount; 48 | mesh.vertexStride = sizeof( hiprtFloat3 ); 49 | CHECK_ORO( oroMalloc( reinterpret_cast( &mesh.vertices ), mesh.vertexCount * sizeof( hiprtFloat3 ) ) ); 50 | CHECK_ORO( oroMemcpyHtoD( 51 | reinterpret_cast( mesh.vertices ), 52 | const_cast( cornellBoxVertices.data() ), 53 | mesh.vertexCount * sizeof( hiprtFloat3 ) ) ); 54 | 55 | hiprtGeometryBuildInput geomInput; 56 | geomInput.type = hiprtPrimitiveTypeTriangleMesh; 57 | geomInput.primitive.triangleMesh = mesh; 58 | 59 | size_t geomTempSize; 60 | hiprtDevicePtr geomTemp; 61 | hiprtBuildOptions options; 62 | options.buildFlags = hiprtBuildFlagBitPreferFastBuild; 63 | CHECK_HIPRT( hiprtGetGeometryBuildTemporaryBufferSize( ctxt, geomInput, options, geomTempSize ) ); 64 | CHECK_ORO( oroMalloc( reinterpret_cast( &geomTemp ), geomTempSize ) ); 65 | 66 | hiprtGeometry geom; 67 | CHECK_HIPRT( hiprtCreateGeometry( ctxt, geomInput, options, geom ) ); 68 | CHECK_HIPRT( hiprtBuildGeometry( ctxt, hiprtBuildOperationBuild, geomInput, options, geomTemp, 0, geom ) ); 69 | CHECK_HIPRT( hiprtCompactGeometry( ctxt, 0, geom, geom ) ); 70 | 71 | oroFunction func; 72 | buildTraceKernelFromBitcode( ctxt, "../common/TutorialKernels.h", "CornellBoxKernel", func ); 73 | 74 | uint8_t* pixels; 75 | CHECK_ORO( oroMalloc( reinterpret_cast( &pixels ), m_res.x * m_res.y * 4 ) ); 76 | 77 | void* args[] = { &geom, &pixels, &m_res }; 78 | launchKernel( func, m_res.x, m_res.y, args ); 79 | writeImage( "04_compaction.png", m_res.x, m_res.y, pixels ); 80 | 81 | CHECK_ORO( oroFree( reinterpret_cast( mesh.triangleIndices ) ) ); 82 | CHECK_ORO( oroFree( reinterpret_cast( mesh.vertices ) ) ); 83 | CHECK_ORO( oroFree( reinterpret_cast( geomTemp ) ) ); 84 | CHECK_ORO( oroFree( reinterpret_cast( pixels ) ) ); 85 | 86 | CHECK_HIPRT( hiprtDestroyGeometry( ctxt, geom ) ); 87 | CHECK_HIPRT( hiprtDestroyContext( ctxt ) ); 88 | } 89 | }; 90 | 91 | int main( int argc, char** argv ) 92 | { 93 | Tutorial tutorial; 94 | tutorial.init( 0 ); 95 | tutorial.run(); 96 | 97 | return 0; 98 | } 99 | -------------------------------------------------------------------------------- /tutorials/08_ambient_occlusion/main.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2021-2023 Advanced Micro Devices, Inc. All rights reserved. 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE. 21 | // 22 | 23 | #include 24 | #include 25 | #include 26 | 27 | class Tutorial : public TutorialBase 28 | { 29 | public: 30 | void run() 31 | { 32 | hiprtContext ctxt; 33 | CHECK_HIPRT( hiprtCreateContext( HIPRT_API_VERSION, m_ctxtInput, ctxt ) ); 34 | 35 | hiprtTriangleMeshPrimitive mesh; 36 | mesh.triangleCount = CornellBoxTriangleCount; 37 | mesh.triangleStride = sizeof( hiprtInt3 ); 38 | std::array triangleIndices; 39 | std::iota( triangleIndices.begin(), triangleIndices.end(), 0 ); 40 | CHECK_ORO( 41 | oroMalloc( reinterpret_cast( &mesh.triangleIndices ), mesh.triangleCount * sizeof( hiprtInt3 ) ) ); 42 | CHECK_ORO( oroMemcpyHtoD( 43 | reinterpret_cast( mesh.triangleIndices ), 44 | triangleIndices.data(), 45 | mesh.triangleCount * sizeof( hiprtInt3 ) ) ); 46 | 47 | mesh.vertexCount = 3 * mesh.triangleCount; 48 | mesh.vertexStride = sizeof( hiprtFloat3 ); 49 | CHECK_ORO( oroMalloc( reinterpret_cast( &mesh.vertices ), mesh.vertexCount * sizeof( hiprtFloat3 ) ) ); 50 | CHECK_ORO( oroMemcpyHtoD( 51 | reinterpret_cast( mesh.vertices ), 52 | const_cast( cornellBoxVertices.data() ), 53 | mesh.vertexCount * sizeof( hiprtFloat3 ) ) ); 54 | 55 | hiprtGeometryBuildInput geomInput; 56 | geomInput.type = hiprtPrimitiveTypeTriangleMesh; 57 | geomInput.primitive.triangleMesh = mesh; 58 | 59 | size_t geomTempSize; 60 | hiprtDevicePtr geomTemp; 61 | hiprtBuildOptions options; 62 | options.buildFlags = hiprtBuildFlagBitPreferFastBuild; 63 | CHECK_HIPRT( hiprtGetGeometryBuildTemporaryBufferSize( ctxt, geomInput, options, geomTempSize ) ); 64 | CHECK_ORO( oroMalloc( reinterpret_cast( &geomTemp ), geomTempSize ) ); 65 | 66 | hiprtGeometry geom; 67 | CHECK_HIPRT( hiprtCreateGeometry( ctxt, geomInput, options, geom ) ); 68 | CHECK_HIPRT( hiprtBuildGeometry( ctxt, hiprtBuildOperationBuild, geomInput, options, geomTemp, 0, geom ) ); 69 | 70 | oroFunction func; 71 | buildTraceKernelFromBitcode( ctxt, "../common/TutorialKernels.h", "AmbientOcclusionKernel", func ); 72 | 73 | uint8_t* pixels; 74 | CHECK_ORO( oroMalloc( reinterpret_cast( &pixels ), m_res.x * m_res.y * 4 ) ); 75 | 76 | float aoRadius = 200.0f; 77 | void* args[] = { &geom, &pixels, &m_res, &aoRadius }; 78 | launchKernel( func, m_res.x, m_res.y, args ); 79 | writeImage( "08_ambient_occlusion.png", m_res.x, m_res.y, pixels ); 80 | 81 | CHECK_ORO( oroFree( reinterpret_cast( mesh.triangleIndices ) ) ); 82 | CHECK_ORO( oroFree( reinterpret_cast( mesh.vertices ) ) ); 83 | CHECK_ORO( oroFree( reinterpret_cast( geomTemp ) ) ); 84 | CHECK_ORO( oroFree( reinterpret_cast( pixels ) ) ); 85 | 86 | CHECK_HIPRT( hiprtDestroyGeometry( ctxt, geom ) ); 87 | CHECK_HIPRT( hiprtDestroyContext( ctxt ) ); 88 | } 89 | }; 90 | 91 | int main( int argc, char** argv ) 92 | { 93 | Tutorial tutorial; 94 | tutorial.init( 0 ); 95 | tutorial.run(); 96 | 97 | return 0; 98 | } 99 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # HIP RT SDK 2 | 3 | **This repository is only for tutorials. The SDK binaries needs to be downloaded from [HIP RT project page](https://gpuopen.com/hiprt/) and the full source code of HIP RT can be found [here](https://github.com/GPUOpen-LibrariesAndSDKs/HIPRT).** 4 | 5 | HIP RT is a ray tracing library in HIP. The APIs are designed to be minimal and low level, making it easy to write a ray tracing application in HIP. We designed the library and APIs to be simple to use and integrate into any existing HIP applications. Although there are a few other ray tracing APIs which, we designed HIP RT to be simpler and easier to use, so you do not need to learn many new kernel types. 6 | 7 | ## Features 8 | 9 | - Ray-triangle intersection 10 | - Ray-custom primitive intersection 11 | - Ray mask to filter geometries 12 | - Several bounding volume hierarchy (BVH) options 13 | - Offline BVH load and store 14 | - BVH import 15 | - Motion blur 16 | 17 | ## Requirement 18 | 19 | HIP RT runs on AMD and NVIDIA® GPUs. HIP and CUDA® APIs are dynamically loaded so you do not need to have these SDKs if your have these DLLs installed with the driver package. Hardware-accelerated ray tracing only works on RDNA™ 2 GPUs (Radeon™ RX 6000 series or newer). 20 | 21 | The supported AMD GPU architecture families are: 22 | 23 | - Navi3x (Radeon™ RX 7000 series) 24 | - Navi2x (Radeon™ RX 6000 series) 25 | - Navi1x (Radeon™ RX 5000 series) 26 | 27 | You will also need AMD Software: Adrenalin Edition 23.30 or later for Windows and ROCm 5.7 for Linux. 28 | 29 | ---- 30 | 31 | 32 | ## Directories 33 | 34 | - [hiprt](hiprt) 35 | - The header and the library which you need to download from [HIP RT project page](https://gpuopen.com/hiprt/). 36 | - [tutorials](tutorials) 37 | - Tutorial source code 38 | - [contrib](contrib) 39 | - External dependencies 40 | 41 | 42 | ## Building the tutorials 43 | 44 | 1. First you need to clone the repository, then init and update the submodules if you didn't clone with `--recursive`: 45 | 46 | ```` 47 | git submodule init 48 | git submodule update 49 | ```` 50 | 2. Download the HIP RT SDK from [HIP RT prject page](https://gpuopen.com/hiprt/), copy the 'hiprt' directory as explained [here](./hiprt/README.md). 51 | 52 | ### Windows: 53 | 3. Run premake to generate a solution for Visual Studio 2022: 54 | ```` 55 | cd tutorials 56 | "../tools/premake5/win/premake5.exe" vs2022 57 | ```` 58 | 59 | 4. Open the solution, compile & run. 60 | 61 | ### Linux: 62 | 3. Run premake like this on Linux, which will generate a make file: 63 | ```` 64 | cd tutorials 65 | ../tools/premake5/linux64/premake5 gmake2 66 | ```` 67 | 68 | 4. Compile using the make file. 69 | ```` 70 | make config=release_x64 71 | ```` 72 | 73 | 5. Run a demo. 74 | ```` 75 | cd dist 76 | export LD_LIBRARY_PATH=../../hiprt/linux64/:$LD_LIBRARY_PATH 77 | bin/Release/19_primary_ray64 78 | ```` 79 | 80 | These tutorials are made to run on both AMD and NVIDIA by specifying the device index. 81 | 82 | ## Introduction to the HIP RT APIs 83 | 84 | The minimum example can be found at [tutorials/00_context_creation/main.cpp](tutorials/00_context_creation/main.cpp). On AMD platforms, you need to create a HIP context and device to initialize `hiprt` using `hiprtCreateContext` by passing `hiprtContextCreationInput` object where you need to set the native API context, device, and device type (HIP or CUDA). 85 | 86 | After that, use `hiprtCreateGeometry` and `hiprtBuildGeometry` to create `hiprtGeometry`. Once you have finished setting up objects on the host side, you can pass the context object to your kernel. 87 | 88 | An example of a minimum kernel can be found at [here](tutorials/01_geom_intersection/TestKernel.h). This is a simple HIP kernel that we are passing `hiprtGeometry ` to. To perform an intersection test, simply fill in `hiprtRay`, then create a `hiprtGeomTraversalClosest` object, then call `getNextHit()`. It is that simple. 89 | 90 | ## References 91 | - Introducing HIP RT – a ray tracing library in HIP, [GPUOpen Blog](https://gpuopen.com/learn/introducing-hiprt/) 92 | - HIP Ray Tracing 2.0 introduces improved custom function handling, Bitcode linking, and more, [GPUOpen Blog](https://gpuopen.com/learn/hiprt-v2-release-optimizations-and-updates/) 93 | - Introducing HIP RT v2.1 - batch construction for small geometries, transformation query functions, and more, [GPUOpen Blog](https://gpuopen.com/learn/hiprt_2_1_batch_construction_transformation_functions/) 94 | - Introducing HIP RT v2.2, [GPUOpen Blog](https://gpuopen.com/learn/introducing-hip-rt-v2-2/) 95 | -------------------------------------------------------------------------------- /doc/01_geom_intersection.md: -------------------------------------------------------------------------------- 1 | # [01_geom_intersection](../tutorials/01_geom_intersection) 2 | 3 |
4 | img 5 |
6 | 7 |
8 | First, we create hiprt context. 9 | 10 | ```cpp 11 | hiprtContext ctxt; 12 | hiprtCreateContext( HIPRT_API_VERSION, m_ctxtInput, ctxt ); 13 | ``` 14 | 15 |
16 |
17 | Then we create vertex and index buffers. 18 | 19 | ```cpp 20 | hiprtTriangleMeshPrimitive mesh; 21 | mesh.triangleCount = 1; 22 | mesh.triangleStride = sizeof( hiprtInt3 ); 23 | uint32_t triangleIndices[] = { 0, 1, 2 }; 24 | oroMalloc( reinterpret_cast( &mesh.triangleIndices ), mesh.triangleCount * sizeof( hiprtInt3 ) ); 25 | oroMemcpyHtoD( reinterpret_cast( mesh.triangleIndices ), 26 | triangleIndices, 27 | mesh.triangleCount * sizeof( hiprtInt3 ) ); 28 | 29 | mesh.vertexCount = 3; 30 | mesh.vertexStride = sizeof( hiprtFloat3 ); 31 | hiprtFloat3 vertices[] = { { 0.0f, 0.0f, 0.0f }, { 1.0f, 0.0f, 0.0f }, { 0.5f, 1.0f, 0.0f } }; 32 | oroMalloc( reinterpret_cast( &mesh.vertices ), mesh.vertexCount * sizeof( hiprtFloat3 ) ); 33 | oroMemcpyHtoD( reinterpret_cast( mesh.vertices ), vertices, mesh.vertexCount * sizeof( hiprtFloat3 ) ); 34 | ``` 35 | 36 |
37 |
38 | The next is preparation of spatial acceleration structure from the vertex, index buffers. A spatial acceleration structure is called `hiprtGeometry`. In the code below, we create a temporary buffer used for the build, create `hiprtGeometry`, then build the geometry with the inputs we provide. 39 | 40 | ```cpp 41 | hiprtGeometryBuildInput geomInput; 42 | geomInput.type = hiprtPrimitiveTypeTriangleMesh; 43 | geomInput.primitive.triangleMesh = mesh; 44 | 45 | size_t geomTempSize; 46 | hiprtDevicePtr geomTemp; 47 | hiprtBuildOptions options; 48 | options.buildFlags = hiprtBuildFlagBitPreferFastBuild; 49 | hiprtGetGeometryBuildTemporaryBufferSize( ctxt, geomInput, options, geomTempSize ); 50 | oroMalloc( reinterpret_cast( &geomTemp ), geomTempSize ); 51 | 52 | hiprtGeometry geom; 53 | hiprtCreateGeometry( ctxt, geomInput, options, geom ); 54 | hiprtBuildGeometry( ctxt, hiprtBuildOperationBuild, geomInput, options, geomTemp, 0, geom ); 55 | ``` 56 | 57 |
58 |
59 | Once it is done, we are ready to trace rays on the GPU in a kernel you write. Here is a kernel used in this tutorial. 60 | 61 | ```cpp 62 | #include 63 | #include 64 | 65 | extern "C" __global__ void GeomIntersectionKernel( hiprtGeometry geom, uint8_t* pixels, int2 res ) 66 | { 67 | const uint32_t x = blockIdx.x * blockDim.x + threadIdx.x; 68 | const uint32_t y = blockIdx.y * blockDim.y + threadIdx.y; 69 | const uint32_t index = x + y * res.x; 70 | 71 | float3 o = { x / static_cast( res.x ), y / static_cast( res.y ), -1.0f }; 72 | float3 d = { 0.0f, 0.0f, 1.0f }; 73 | 74 | hiprtRay ray; 75 | ray.origin = o; 76 | ray.direction = d; 77 | 78 | hiprtGeomTraversalClosest tr( geom, ray ); 79 | hiprtHit hit = tr.getNextHit(); 80 | 81 | pixels[index * 4 + 0] = hit.hasHit() ? ( static_cast( x ) / res.x ) * 255 : 0; 82 | pixels[index * 4 + 1] = hit.hasHit() ? ( static_cast( y ) / res.y ) * 255 : 0; 83 | pixels[index * 4 + 2] = 0; 84 | pixels[index * 4 + 3] = 255; 85 | } 86 | ``` 87 | 88 |
89 |
90 | This is nothing but just a regular HIP kernel other than passing `hiprtGeometry`. What you find new in the kernel is the 2 lines. We create traversal object which keeps the state of the ray and execute the traversal. `tr.getNextHit()` does the ray tracing and find the hit we need. 91 | 92 | ```cpp 93 | hiprtGeomTraversalClosest tr( geom, ray ); 94 | hiprtHit hit = tr.getNextHit(); 95 | ``` 96 | 97 |
98 |
99 | The kernel above has hiprt functions in it. Thus, it needs to be compiled with the hiprt headers (and bitcodes) which is done in this line. 100 | 101 | ```cpp 102 | oroFunction func; 103 | buildTraceKernelFromBitcode( ctxt, "../common/TutorialKernels.h", "GeomIntersectionKernel", func ); 104 | ``` 105 | 106 |
107 |
108 | That’s all we need to do for preparation. Now we can launch the kernel and see the first triangle. 109 | 110 | ```cpp 111 | uint8_t* pixels; 112 | oroMalloc( reinterpret_cast( &pixels ), m_res.x * m_res.y * 4 ); 113 | 114 | void* args[] = { &geom, &pixels, &m_res }; 115 | launchKernel( func, m_res.x, m_res.y, args ); 116 | writeImage( "01_geom_intersection.png", m_res.x, m_res.y, pixels ); 117 | ``` 118 | -------------------------------------------------------------------------------- /tutorials/12_cutout/main.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2021-2023 Advanced Micro Devices, Inc. All rights reserved. 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE. 21 | // 22 | 23 | #include 24 | 25 | class Tutorial : public TutorialBase 26 | { 27 | public: 28 | void run() 29 | { 30 | hiprtContext ctxt; 31 | CHECK_HIPRT( hiprtCreateContext( HIPRT_API_VERSION, m_ctxtInput, ctxt ) ); 32 | 33 | hiprtTriangleMeshPrimitive mesh; 34 | mesh.triangleCount = 2; 35 | mesh.triangleStride = sizeof( hiprtInt3 ); 36 | uint32_t triangleIndices[] = { 0, 1, 2, 0, 2, 3 }; 37 | CHECK_ORO( 38 | oroMalloc( reinterpret_cast( &mesh.triangleIndices ), mesh.triangleCount * sizeof( hiprtInt3 ) ) ); 39 | CHECK_ORO( oroMemcpyHtoD( 40 | reinterpret_cast( mesh.triangleIndices ), 41 | triangleIndices, 42 | mesh.triangleCount * sizeof( hiprtInt3 ) ) ); 43 | 44 | mesh.vertexCount = 4; 45 | mesh.vertexStride = sizeof( hiprtFloat3 ); 46 | float3 vertices[] = { { 0.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }, { 1.0f, 1.0f, 0.0f }, { 1.0f, 0.0f, 0.0f } }; 47 | CHECK_ORO( oroMalloc( reinterpret_cast( &mesh.vertices ), mesh.vertexCount * sizeof( hiprtFloat3 ) ) ); 48 | CHECK_ORO( oroMemcpyHtoD( 49 | reinterpret_cast( mesh.vertices ), vertices, mesh.vertexCount * sizeof( hiprtFloat3 ) ) ); 50 | 51 | hiprtGeometryBuildInput geomInput; 52 | geomInput.type = hiprtPrimitiveTypeTriangleMesh; 53 | geomInput.primitive.triangleMesh = mesh; 54 | geomInput.geomType = 0; 55 | 56 | size_t geomTempSize; 57 | hiprtDevicePtr geomTemp; 58 | hiprtBuildOptions options; 59 | options.buildFlags = hiprtBuildFlagBitPreferFastBuild; 60 | CHECK_HIPRT( hiprtGetGeometryBuildTemporaryBufferSize( ctxt, geomInput, options, geomTempSize ) ); 61 | CHECK_ORO( oroMalloc( reinterpret_cast( &geomTemp ), geomTempSize ) ); 62 | 63 | hiprtGeometry geom; 64 | CHECK_HIPRT( hiprtCreateGeometry( ctxt, geomInput, options, geom ) ); 65 | CHECK_HIPRT( hiprtBuildGeometry( ctxt, hiprtBuildOperationBuild, geomInput, options, geomTemp, 0, geom ) ); 66 | 67 | oroFunction func; 68 | hiprtFuncNameSet funcNameSet; 69 | funcNameSet.filterFuncName = "cutoutFilter"; 70 | std::vector funcNameSets = { funcNameSet }; 71 | 72 | buildTraceKernelFromBitcode( ctxt, "../common/TutorialKernels.h", "CutoutKernel", func, nullptr, &funcNameSets, 1, 1 ); 73 | 74 | hiprtFuncDataSet funcDataSet; 75 | hiprtFuncTable funcTable; 76 | CHECK_HIPRT( hiprtCreateFuncTable( ctxt, 1, 1, funcTable ) ); 77 | CHECK_HIPRT( hiprtSetFuncTable( ctxt, funcTable, 0, 0, funcDataSet ) ); 78 | 79 | uint8_t* pixels; 80 | CHECK_ORO( oroMalloc( reinterpret_cast( &pixels ), m_res.x * m_res.y * 4 ) ); 81 | 82 | void* args[] = { &geom, &pixels, &funcTable, &m_res }; 83 | launchKernel( func, m_res.x, m_res.y, args ); 84 | writeImage( "12_cutout.png", m_res.x, m_res.y, pixels ); 85 | 86 | CHECK_ORO( oroFree( reinterpret_cast( mesh.triangleIndices ) ) ); 87 | CHECK_ORO( oroFree( reinterpret_cast( mesh.vertices ) ) ); 88 | CHECK_ORO( oroFree( reinterpret_cast( geomTemp ) ) ); 89 | CHECK_ORO( oroFree( reinterpret_cast( pixels ) ) ); 90 | 91 | CHECK_HIPRT( hiprtDestroyFuncTable( ctxt, funcTable ) ); 92 | CHECK_HIPRT( hiprtDestroyGeometry( ctxt, geom ) ); 93 | CHECK_HIPRT( hiprtDestroyContext( ctxt ) ); 94 | } 95 | }; 96 | 97 | int main( int argc, char** argv ) 98 | { 99 | Tutorial tutorial; 100 | tutorial.init( 0 ); 101 | tutorial.run(); 102 | 103 | return 0; 104 | } 105 | -------------------------------------------------------------------------------- /tutorials/common/SceneDemo.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2021-2024 Advanced Micro Devices, Inc. All rights reserved. 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE. 21 | // 22 | 23 | #pragma once 24 | 25 | #include 26 | 27 | class SceneDemo : public TutorialBase 28 | { 29 | public: 30 | SceneDemo() 31 | { 32 | m_oroCtx = nullptr; 33 | 34 | m_ctxtInput.ctxt = nullptr; 35 | m_ctxtInput.device = 0; 36 | m_ctxtInput.deviceType = (hiprtDeviceType)-1; 37 | 38 | m_scene.Clear(); 39 | } 40 | 41 | void buildBvh( hiprtGeometryBuildInput& buildInput ); 42 | 43 | #ifdef ENABLE_EMBREE 44 | void buildEmbreeBvh( 45 | RTCDevice embreeDevice, std::vector& embreePrims, std::vector& nodes, void* geomData ); 46 | 47 | void buildEmbreeGeometryBvh( 48 | RTCDevice embreeDevice, const float3* vertices, const uint32_t* indices, hiprtGeometryBuildInput& buildInput ); 49 | 50 | void buildEmbreeSceneBvh( 51 | RTCDevice embreeDevice, 52 | const std::vector& geomBoxes, 53 | const std::vector& frames, 54 | hiprtSceneBuildInput& buildInput ); 55 | #endif 56 | 57 | struct SceneData 58 | { 59 | void Clear() 60 | { 61 | m_bufMaterialIndices = nullptr; 62 | m_bufMatIdsPerInstance = nullptr; 63 | m_bufMaterials = nullptr; 64 | m_vertices = nullptr; 65 | m_vertexOffsets = nullptr; 66 | m_normals = nullptr; 67 | m_normalOffsets = nullptr; 68 | m_indices = nullptr; 69 | m_indexOffsets = nullptr; 70 | m_lights = nullptr; 71 | m_numOfLights = nullptr; 72 | m_scene = nullptr; 73 | m_ctx = nullptr; 74 | } 75 | 76 | uint32_t* m_bufMaterialIndices; 77 | uint32_t* m_bufMatIdsPerInstance; // count of material ids per instance use to calculate offset in material Idx buffer 78 | // for instance 79 | Material* m_bufMaterials; 80 | float3* m_vertices; 81 | uint32_t* m_vertexOffsets; 82 | float3* m_normals; 83 | uint32_t* m_normalOffsets; 84 | uint32_t* m_indices; 85 | uint32_t* m_indexOffsets; 86 | Light* m_lights; 87 | uint32_t* m_numOfLights; 88 | hiprtScene m_scene; 89 | std::vector m_geometries; 90 | std::vector m_instances; 91 | std::vector m_garbageCollector; 92 | hiprtContext m_ctx; 93 | }; 94 | 95 | Camera createCamera() 96 | { 97 | Camera camera; 98 | camera.m_translation = { 0.0f, 2.5f, 5.8f }; 99 | camera.m_rotation = { 0.0f, 0.0f, 1.0f, 0.0f }; 100 | camera.m_fov = 45.0f * hiprt::Pi / 180.f; 101 | return camera; 102 | } 103 | 104 | void createScene( 105 | SceneData& scene, 106 | const std::string& filename, 107 | const std::string& mtlBaseDir, 108 | bool enableRayMask = false, 109 | std::optional frame = std::nullopt, 110 | hiprtBuildFlags bvhBuildFlag = hiprtBuildFlagBitPreferFastBuild ); 111 | 112 | void setupScene( 113 | Camera& camera, 114 | const std::string& filePath, 115 | const std::string& dirPath, 116 | bool enableRayMask = false, 117 | std::optional frame = std::nullopt, 118 | hiprtBuildFlags bvhBuildFlag = hiprtBuildFlagBitPreferFastBuild ); 119 | 120 | void deleteScene( SceneData& scene ); 121 | 122 | void TearDown() 123 | { 124 | for ( auto p : m_scene.m_garbageCollector ) 125 | free( p ); 126 | 127 | CHECK_ORO( oroCtxDestroy( m_oroCtx ) ); 128 | } 129 | 130 | void render( 131 | std::optional imgPath, 132 | const std::filesystem::path& kernelPath, 133 | const std::string& funcName = "PrimaryRayKernel", 134 | float aoRadius = 0.0f ); 135 | 136 | SceneData m_scene; 137 | Camera m_camera; 138 | }; 139 | -------------------------------------------------------------------------------- /doc/03_custom_intersection.md: -------------------------------------------------------------------------------- 1 | # [03_custom_intersection](../tutorials/03_custom_intersection) 2 | 3 |
4 | 5 | If your scene contains primitives other than triangles, HIPRT can handle them too. All you need to do is provide a custom intersection function for the geometry, register the function in HIPRT, then this function will be called when a ray intersects with the primitive. 6 | 7 |
8 | img 9 |
10 | 11 |
12 | 13 | Here `intersectSphere` is the custom intersection kernel we want to execute on our geometry. 14 | 15 | ```cpp 16 | // check if there is a hit before ray.maxT. if there is, set it to tOut. hiprt will overwrite ray.maxT after this function 17 | __device__ bool intersectSphere( const hiprtRay& ray, const void* data, void* payload, hiprtHit& hit ) 18 | { 19 | float3 from = ray.origin; 20 | float3 to = from + ray.direction * ray.maxT; 21 | float4 sphere = reinterpret_cast( data )[hit.primID]; 22 | float3 center = make_float3( sphere ); 23 | float r = sphere.w; 24 | 25 | float3 m = from - center; 26 | float3 d = to - from; 27 | float a = dot( d, d ); 28 | float b = 2.0f * dot( m, d ); 29 | float c = dot( m, m ) - r * r; 30 | float dd = b * b - 4.0f * a * c; 31 | if ( dd < 0.0f ) return false; 32 | 33 | float t = ( -b - sqrtf( dd ) ) / ( 2.0f * a ); 34 | if ( t > 1.0f ) return false; 35 | 36 | hit.t = t * ray.maxT; 37 | hit.normal = normalize( from + ray.direction * hit.t - center ); 38 | 39 | return true; 40 | } 41 | ``` 42 | 43 |
44 |
45 | 46 | 47 | To execute this kernel on our geometry, first we need to set the `geomType` on it. here we use 1 custom types, so `0` is the first index in our function table 48 | ```cpp 49 | hiprtGeometryBuildInput geomInput; 50 | geomInput.type = hiprtPrimitiveTypeAABBList; 51 | geomInput.primitive.aabbList = list; 52 | geomInput.geomType = 0; 53 | ``` 54 | 55 |
56 |
57 | 58 | We also need to define our function table, containing the list of all the custom functions. In our demo, we have only 1 custom function. 59 | ```cpp 60 | hiprtFuncNameSet funcNameSet; 61 | funcNameSet.intersectFuncName = "intersectSphere"; 62 | std::vector funcNameSets = { funcNameSet }; 63 | ``` 64 | 65 |
66 |
67 | 68 | When we build the kernel, we need to use the arguments: `funcNameSets`, `numGeomTypes`, `numRayTypes`.
69 | - `funcNameSets`, the `std::vector` we created previously. 70 | - `numGeomTypes`, the number of geometry types we use. In our sample we use 1. 71 | - `numRayTypes`, the number of ray types we use. Keep it to 1 ( which is the default value ) as we do not want different ray types in this demo. 72 | ```cpp 73 | oroFunction func; 74 | buildTraceKernelFromBitcode(ctxt, "../common/TutorialKernels.h", "CustomIntersectionKernel", func, nullptr, &funcNameSets, 1, 1 ); 75 | ``` 76 | 77 |
78 |
79 | 80 | We also need to build a `hiprtFuncTable`, 81 | 82 | ```cpp 83 | hiprtFuncTable funcTable; 84 | hiprtCreateFuncTable( ctxt, 1, 1, funcTable ); 85 | hiprtSetFuncTable( ctxt, funcTable, 0, 0, funcDataSet ); 86 | ``` 87 | 88 |
89 | 90 | and give it as an argument to the main kernel execution... 91 | ```cpp 92 | void* args[] = { &geom, &pixels, &funcTable, &m_res }; 93 | ``` 94 |
95 | 96 | ... as the kernel needs it.
97 | Here is how `hiprtFuncTable table` is used on the kernel side : 98 | 99 | ```cpp 100 | extern "C" __global__ void CustomIntersectionKernel( hiprtGeometry geom, uint8_t* pixels, hiprtFuncTable table, int2 res ) 101 | { 102 | const uint32_t x = blockIdx.x * blockDim.x + threadIdx.x; 103 | const uint32_t y = blockIdx.y * blockDim.y + threadIdx.y; 104 | const uint32_t index = x + y * res.x; 105 | 106 | hiprtRay ray; 107 | ray.origin = { x / static_cast( res.x ) - 0.5f, y / static_cast( res.y ) - 0.5f, -1.0f }; 108 | ray.direction = { 0.0f, 0.0f, 1.0f }; 109 | ray.maxT = 100000.0f; 110 | 111 | hiprtGeomCustomTraversalClosest tr( geom, ray, hiprtTraversalHintDefault, nullptr, table ); 112 | hiprtHit hit = tr.getNextHit(); 113 | 114 | pixels[index * 4 + 0] = hit.hasHit() ? ( hit.normal.x + 1.0f ) / 2.0f * 255 : 0; 115 | pixels[index * 4 + 1] = hit.hasHit() ? ( hit.normal.y + 1.0f ) / 2.0f * 255 : 0; 116 | pixels[index * 4 + 2] = hit.hasHit() ? ( hit.normal.z + 1.0f ) / 2.0f * 255 : 0; 117 | pixels[index * 4 + 3] = 255; 118 | } 119 | ``` 120 | 121 |
122 | 123 | In this tutorial, we explained simple usage of custom intersection where there is only single custom geometry type. More complex example can be found at the demo [11_multi_custom_intersection](../tutorials/11_multi_custom_intersection) which is similar but uses several custom types. 124 | 125 | 126 | 127 | -------------------------------------------------------------------------------- /doc/08_ambient_occlusion.md: -------------------------------------------------------------------------------- 1 | # [08_ambient_occlusion](../tutorials/08_ambient_occlusion) 2 | 3 | 4 | This demos shows how to compute Ambient Occlusion with HIPRT in the Cornell box scene. 5 | 6 |
7 | Description of the image 8 |
9 | 10 |
11 | 12 | The source code on The C++ side ( [main.cpp](../tutorials/08_ambient_occlusion/main.cpp) ) is very close to the one from the first demo: [main.cpp from 01_geom_intersection](../tutorials/01_geom_intersection/main.cpp) presented [here](01_geom_intersection.md). So we won't give much details. 13 | The first difference is that instead of creating one triangle, we create the list of triangles to render the Cornell box scene: 14 | 15 | ```cpp 16 | hiprtTriangleMeshPrimitive mesh; 17 | mesh.triangleCount = CornellBoxTriangleCount; 18 | mesh.triangleStride = sizeof( hiprtInt3 ); 19 | std::array triangleIndices; 20 | std::iota( triangleIndices.begin(), triangleIndices.end(), 0 ); 21 | oroMalloc( reinterpret_cast( &mesh.triangleIndices ), mesh.triangleCount * sizeof( hiprtInt3 ) ); 22 | oroMemcpyHtoD( 23 | reinterpret_cast( mesh.triangleIndices ), 24 | triangleIndices.data(), 25 | mesh.triangleCount * sizeof( hiprtInt3 ) ); 26 | 27 | mesh.vertexCount = 3 * mesh.triangleCount; 28 | mesh.vertexStride = sizeof( hiprtFloat3 ); 29 | oroMalloc( reinterpret_cast( &mesh.vertices ), mesh.vertexCount * sizeof( hiprtFloat3 ) ); 30 | oroMemcpyHtoD( 31 | reinterpret_cast( mesh.vertices ), 32 | const_cast( cornellBoxVertices.data() ), 33 | mesh.vertexCount * sizeof( hiprtFloat3 ) ) ; 34 | ``` 35 | 36 |
37 |
38 | The second difference is we executing another kernel called "AmbientOcclusionKernel". Note that this kernel takes an additional argument which is the radius of the Ambint Occlusion we want to apply: 39 | 40 | ```cpp 41 | oroFunction func; 42 | buildTraceKernelFromBitcode( ctxt, "../common/TutorialKernels.h", "AmbientOcclusionKernel", func ); 43 | 44 | float aoRadius = 200.0f; 45 | void* args[] = { &geom, &pixels, &m_res, &aoRadius }; 46 | launchKernel( func, m_res.x, m_res.y, args ); 47 | ``` 48 | 49 |
50 |
51 | 52 | Concerning the kernel itself, it is a bit more complex than the one used in the [first demo](01_geom_intersection.md). 53 | This kernel is executing an AO loop inside the loop. 54 | The loop launches several rays (32 iterations in this example) with slightly different directions within the same pixel: 55 | 56 | ```cpp 57 | const uint32_t x = blockIdx.x * blockDim.x + threadIdx.x; 58 | const uint32_t y = blockIdx.y * blockDim.y + threadIdx.y; 59 | const uint32_t index = x + y * res.x; 60 | 61 | constexpr uint32_t Spp = 32u; 62 | constexpr uint32_t AoSamples = 32u; 63 | int3 color = { 0, 0, 0 }; 64 | float4 diffuseColor = make_float4( 1.0f, 1.0f, 1.0f, 1.0f ); 65 | float ao = 0.0f; 66 | 67 | for ( int p = 0; p < Spp; p++ ) 68 | { 69 | uint32_t seed = tea<16>( x + y * res.x, p ).x; 70 | 71 | float3 o = { 278.0f, 273.0f, -900.0f }; 72 | float2 d = { 73 | 2.0f * ( x + randf( seed ) ) / static_cast( res.x ) - 1.0f, 74 | 2.0f * ( y + randf( seed ) ) / static_cast( res.y ) - 1.0f }; 75 | float3 uvw = { -387.817566f, -387.817566f, 1230.0f }; 76 | 77 | hiprtRay ray; 78 | ray.origin = o; 79 | ray.direction = { uvw.x * d.x, uvw.y * d.y, uvw.z }; 80 | ray.direction = 81 | ray.direction / 82 | sqrtf( ray.direction.x * ray.direction.x + ray.direction.y * ray.direction.y + ray.direction.z * ray.direction.z ); 83 | 84 | // ..... AO done here ..... 85 | 86 | } 87 | ``` 88 | 89 |
90 |
91 | 92 | The AO loop launches several rays (32 iterations in this example) in random directions using the 'sampleHemisphereCosine' function. Each bouncing ray's result is accumulated in the 'ao' variable: 93 | 94 | ```cpp 95 | hiprtGeomTraversalClosest tr( geom, ray ); 96 | 97 | hiprtHit hit = tr.getNextHit(); 98 | 99 | if ( hit.hasHit() ) 100 | { 101 | float3 surfacePt = ray.origin + hit.t * ( 1.0f - 1.0e-2f ) * ray.direction; 102 | 103 | float3 Ng = hit.normal; 104 | if ( dot( ray.direction, Ng ) > 0.0f ) Ng = -Ng; 105 | Ng = normalize( Ng ); 106 | 107 | hiprtRay aoRay; 108 | aoRay.origin = surfacePt; 109 | aoRay.maxT = aoRadius; 110 | hiprtHit aoHit; 111 | 112 | for ( int i = 0; i < AoSamples; i++ ) 113 | { 114 | aoRay.direction = sampleHemisphereCosine( Ng, seed ); 115 | hiprtGeomTraversalAnyHit tr( geom, aoRay ); 116 | aoHit = tr.getNextHit(); 117 | ao += !aoHit.hasHit() ? 1.0f : 0.0f; 118 | } 119 | } 120 | ``` 121 |
122 |
123 | 124 | Finally, we output the accumulated Ambient Occlusion to the result framebuffer by averaging the samples: 125 | 126 | ```cpp 127 | ao = ao / ( Spp * AoSamples ); 128 | 129 | color.x = ( ao * diffuseColor.x ) * 255; 130 | color.y = ( ao * diffuseColor.y ) * 255; 131 | color.z = ( ao * diffuseColor.z ) * 255; 132 | 133 | pixels[index * 4 + 0] = color.x; 134 | pixels[index * 4 + 1] = color.y; 135 | pixels[index * 4 + 2] = color.z; 136 | pixels[index * 4 + 3] = 255; 137 | 138 | ``` 139 | -------------------------------------------------------------------------------- /tutorials/03_custom_intersection/main.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2021-2023 Advanced Micro Devices, Inc. All rights reserved. 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE. 21 | // 22 | 23 | #include 24 | 25 | class Tutorial : public TutorialBase 26 | { 27 | public: 28 | void run() 29 | { 30 | constexpr uint32_t SphereCount = 8 * 2; 31 | hiprtFloat4 spheres[SphereCount]; 32 | for ( uint32_t i = 0; i < SphereCount / 2; i++ ) 33 | { 34 | float r = 0.1f; 35 | float t = i / (float)( SphereCount / 2 ) * 2.f * 3.1415f; 36 | spheres[i] = { sinf( t ) * 0.4f, cosf( t ) * 0.4f, 0.f, r }; 37 | } 38 | for ( uint32_t i = 0; i < SphereCount / 2; i++ ) 39 | { 40 | float r = 0.1f; 41 | float t = i / (float)( SphereCount / 2 ) * 2.f * 3.1415f + 0.2f; 42 | spheres[i + SphereCount / 2] = { sinf( t ) * 0.35f, cosf( t ) * 0.35f, 0.4f, r }; 43 | } 44 | 45 | hiprtContext ctxt; 46 | CHECK_HIPRT( hiprtCreateContext( HIPRT_API_VERSION, m_ctxtInput, ctxt ) ); 47 | 48 | hiprtAABBListPrimitive list; 49 | list.aabbCount = SphereCount; 50 | list.aabbStride = 2 * sizeof( hiprtFloat4 ); 51 | hiprtFloat4 aabbs[2 * SphereCount]; 52 | for ( uint32_t i = 0; i < SphereCount; i++ ) 53 | { 54 | const hiprtFloat4& c = spheres[i]; 55 | aabbs[i * 2 + 0] = { c.x - c.w, c.y - c.w, c.z - c.w, 0.0f }; 56 | aabbs[i * 2 + 1] = { c.x + c.w, c.y + c.w, c.z + c.w, 0.0f }; 57 | } 58 | CHECK_ORO( oroMalloc( reinterpret_cast( &list.aabbs ), 2 * SphereCount * sizeof( hiprtFloat4 ) ) ); 59 | CHECK_ORO( 60 | oroMemcpyHtoD( reinterpret_cast( list.aabbs ), aabbs, 2 * SphereCount * sizeof( hiprtFloat4 ) ) ); 61 | 62 | hiprtGeometryBuildInput geomInput; 63 | geomInput.type = hiprtPrimitiveTypeAABBList; 64 | geomInput.primitive.aabbList = list; 65 | geomInput.geomType = 0; 66 | 67 | size_t geomTempSize; 68 | hiprtDevicePtr geomTemp; 69 | hiprtBuildOptions options; 70 | options.buildFlags = hiprtBuildFlagBitPreferFastBuild; 71 | CHECK_HIPRT( hiprtGetGeometryBuildTemporaryBufferSize( ctxt, geomInput, options, geomTempSize ) ); 72 | CHECK_ORO( oroMalloc( reinterpret_cast( &geomTemp ), geomTempSize ) ); 73 | 74 | hiprtGeometry geom; 75 | CHECK_HIPRT( hiprtCreateGeometry( ctxt, geomInput, options, geom ) ); 76 | CHECK_HIPRT( hiprtBuildGeometry( ctxt, hiprtBuildOperationBuild, geomInput, options, geomTemp, 0, geom ) ); 77 | 78 | hiprtFuncNameSet funcNameSet; 79 | funcNameSet.intersectFuncName = "intersectSphere"; 80 | std::vector funcNameSets = { funcNameSet }; 81 | 82 | hiprtFuncDataSet funcDataSet; 83 | CHECK_ORO( 84 | oroMalloc( const_cast( &funcDataSet.intersectFuncData ), SphereCount * sizeof( hiprtFloat4 ) ) ); 85 | CHECK_ORO( oroMemcpyHtoD( 86 | const_cast( funcDataSet.intersectFuncData ), spheres, SphereCount * sizeof( hiprtFloat4 ) ) ); 87 | 88 | hiprtFuncTable funcTable; 89 | CHECK_HIPRT( hiprtCreateFuncTable( ctxt, 1, 1, funcTable ) ); 90 | CHECK_HIPRT( hiprtSetFuncTable( ctxt, funcTable, 0, 0, funcDataSet ) ); 91 | 92 | oroFunction func; 93 | buildTraceKernelFromBitcode( 94 | ctxt, "../common/TutorialKernels.h", "CustomIntersectionKernel", func, nullptr, &funcNameSets, 1, 1 ); 95 | 96 | uint8_t* pixels; 97 | CHECK_ORO( oroMalloc( reinterpret_cast( &pixels ), m_res.x * m_res.y * 4 ) ); 98 | 99 | void* args[] = { &geom, &pixels, &funcTable, &m_res }; 100 | launchKernel( func, m_res.x, m_res.y, args ); 101 | writeImage( "03_custom_intersection.png", m_res.x, m_res.y, pixels ); 102 | 103 | CHECK_ORO( oroFree( const_cast( funcDataSet.intersectFuncData ) ) ); 104 | CHECK_ORO( oroFree( reinterpret_cast( list.aabbs ) ) ); 105 | CHECK_ORO( oroFree( reinterpret_cast( geomTemp ) ) ); 106 | CHECK_ORO( oroFree( reinterpret_cast( pixels ) ) ); 107 | 108 | CHECK_HIPRT( hiprtDestroyFuncTable( ctxt, funcTable ) ); 109 | CHECK_HIPRT( hiprtDestroyGeometry( ctxt, geom ) ); 110 | CHECK_HIPRT( hiprtDestroyContext( ctxt ) ); 111 | } 112 | }; 113 | 114 | int main( int argc, char** argv ) 115 | { 116 | Tutorial tutorial; 117 | tutorial.init( 0 ); 118 | tutorial.run(); 119 | 120 | return 0; 121 | } 122 | -------------------------------------------------------------------------------- /tutorials/05_global_stack/main.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2021-2023 Advanced Micro Devices, Inc. All rights reserved. 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE. 21 | // 22 | 23 | #include 24 | #include 25 | #include 26 | 27 | class Tutorial : public TutorialBase 28 | { 29 | public: 30 | void run() 31 | { 32 | hiprtContext ctxt; 33 | CHECK_HIPRT( hiprtCreateContext( HIPRT_API_VERSION, m_ctxtInput, ctxt ) ); 34 | 35 | constexpr uint32_t StackSize = 64u; 36 | constexpr uint32_t SharedStackSize = 16u; 37 | constexpr uint32_t BlockWidth = 8u; 38 | constexpr uint32_t BlockHeight = 8u; 39 | constexpr uint32_t BlockSize = BlockWidth * BlockHeight; 40 | std::string BlockSizeDef = "-D BLOCK_SIZE=" + std::to_string( BlockSize ); 41 | std::string SharedStackSizeDef = "-D SHARED_STACK_SIZE=" + std::to_string( SharedStackSize ); 42 | 43 | std::vector opts; 44 | opts.push_back( BlockSizeDef.c_str() ); 45 | opts.push_back( SharedStackSizeDef.c_str() ); 46 | 47 | hiprtTriangleMeshPrimitive mesh; 48 | mesh.triangleCount = CornellBoxTriangleCount; 49 | mesh.triangleStride = sizeof( hiprtInt3 ); 50 | std::array triangleIndices; 51 | std::iota( triangleIndices.begin(), triangleIndices.end(), 0 ); 52 | CHECK_ORO( 53 | oroMalloc( reinterpret_cast( &mesh.triangleIndices ), mesh.triangleCount * sizeof( hiprtInt3 ) ) ); 54 | CHECK_ORO( oroMemcpyHtoD( 55 | reinterpret_cast( mesh.triangleIndices ), 56 | triangleIndices.data(), 57 | mesh.triangleCount * sizeof( hiprtInt3 ) ) ); 58 | 59 | mesh.vertexCount = 3 * mesh.triangleCount; 60 | mesh.vertexStride = sizeof( hiprtFloat3 ); 61 | CHECK_ORO( oroMalloc( reinterpret_cast( &mesh.vertices ), mesh.vertexCount * sizeof( hiprtFloat3 ) ) ); 62 | CHECK_ORO( oroMemcpyHtoD( 63 | reinterpret_cast( mesh.vertices ), 64 | const_cast( cornellBoxVertices.data() ), 65 | mesh.vertexCount * sizeof( hiprtFloat3 ) ) ); 66 | 67 | hiprtGeometryBuildInput geomInput; 68 | geomInput.type = hiprtPrimitiveTypeTriangleMesh; 69 | geomInput.primitive.triangleMesh = mesh; 70 | 71 | size_t geomTempSize; 72 | hiprtDevicePtr geomTemp; 73 | hiprtBuildOptions options; 74 | options.buildFlags = hiprtBuildFlagBitPreferFastBuild; 75 | CHECK_HIPRT( hiprtGetGeometryBuildTemporaryBufferSize( ctxt, geomInput, options, geomTempSize ) ); 76 | CHECK_ORO( oroMalloc( reinterpret_cast( &geomTemp ), geomTempSize ) ); 77 | 78 | hiprtGeometry geom; 79 | CHECK_HIPRT( hiprtCreateGeometry( ctxt, geomInput, options, geom ) ); 80 | CHECK_HIPRT( hiprtBuildGeometry( ctxt, hiprtBuildOperationBuild, geomInput, options, geomTemp, 0, geom ) ); 81 | 82 | oroFunction func; 83 | buildTraceKernelFromBitcode( ctxt, "../common/TutorialKernels.h", "SharedStackKernel", func, &opts ); 84 | 85 | uint8_t* pixels; 86 | CHECK_ORO( oroMalloc( reinterpret_cast( &pixels ), m_res.x * m_res.y * 4 ) ); 87 | 88 | hiprtGlobalStackBufferInput stackBufferInput{ 89 | hiprtStackTypeGlobal, hiprtStackEntryTypeInteger, StackSize, static_cast( m_res.x * m_res.y ) }; 90 | hiprtGlobalStackBuffer stackBuffer; 91 | CHECK_HIPRT( hiprtCreateGlobalStackBuffer( ctxt, stackBufferInput, stackBuffer ) ); 92 | 93 | void* args[] = { &geom, &pixels, &m_res, &stackBuffer }; 94 | launchKernel( func, m_res.x, m_res.y, BlockWidth, BlockHeight, args ); 95 | writeImage( "05_global_stack.png", m_res.x, m_res.y, pixels ); 96 | 97 | CHECK_ORO( oroFree( reinterpret_cast( mesh.triangleIndices ) ) ); 98 | CHECK_ORO( oroFree( reinterpret_cast( mesh.vertices ) ) ); 99 | CHECK_ORO( oroFree( reinterpret_cast( geomTemp ) ) ); 100 | CHECK_ORO( oroFree( reinterpret_cast( pixels ) ) ); 101 | 102 | CHECK_HIPRT( hiprtDestroyGlobalStackBuffer( ctxt, stackBuffer ) ); 103 | CHECK_HIPRT( hiprtDestroyGeometry( ctxt, geom ) ); 104 | CHECK_HIPRT( hiprtDestroyContext( ctxt ) ); 105 | } 106 | }; 107 | 108 | int main( int argc, char** argv ) 109 | { 110 | Tutorial tutorial; 111 | tutorial.init( 0 ); 112 | tutorial.run(); 113 | 114 | return 0; 115 | } 116 | -------------------------------------------------------------------------------- /tutorials/06_dynamic_stack/main.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2021-2023 Advanced Micro Devices, Inc. All rights reserved. 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE. 21 | // 22 | 23 | #include 24 | #include 25 | #include 26 | 27 | class Tutorial : public TutorialBase 28 | { 29 | public: 30 | void run() 31 | { 32 | hiprtContext ctxt; 33 | CHECK_HIPRT( hiprtCreateContext( HIPRT_API_VERSION, m_ctxtInput, ctxt ) ); 34 | 35 | constexpr uint32_t StackSize = 64u; 36 | constexpr uint32_t SharedStackSize = 16u; 37 | constexpr uint32_t BlockWidth = 8u; 38 | constexpr uint32_t BlockHeight = 8u; 39 | constexpr uint32_t BlockSize = BlockWidth * BlockHeight; 40 | constexpr uint32_t ThreadCount = 100000u; 41 | std::string BlockSizeDef = "-D BLOCK_SIZE=" + std::to_string( BlockSize ); 42 | std::string SharedStackSizeDef = "-D SHARED_STACK_SIZE=" + std::to_string( SharedStackSize ); 43 | 44 | std::vector opts; 45 | opts.push_back( BlockSizeDef.c_str() ); 46 | opts.push_back( SharedStackSizeDef.c_str() ); 47 | 48 | hiprtTriangleMeshPrimitive mesh; 49 | mesh.triangleCount = CornellBoxTriangleCount; 50 | mesh.triangleStride = sizeof( hiprtInt3 ); 51 | std::array triangleIndices; 52 | std::iota( triangleIndices.begin(), triangleIndices.end(), 0 ); 53 | CHECK_ORO( 54 | oroMalloc( reinterpret_cast( &mesh.triangleIndices ), mesh.triangleCount * sizeof( hiprtInt3 ) ) ); 55 | CHECK_ORO( oroMemcpyHtoD( 56 | reinterpret_cast( mesh.triangleIndices ), 57 | triangleIndices.data(), 58 | mesh.triangleCount * sizeof( hiprtInt3 ) ) ); 59 | 60 | mesh.vertexCount = 3 * mesh.triangleCount; 61 | mesh.vertexStride = sizeof( hiprtFloat3 ); 62 | CHECK_ORO( oroMalloc( reinterpret_cast( &mesh.vertices ), mesh.vertexCount * sizeof( hiprtFloat3 ) ) ); 63 | CHECK_ORO( oroMemcpyHtoD( 64 | reinterpret_cast( mesh.vertices ), 65 | const_cast( cornellBoxVertices.data() ), 66 | mesh.vertexCount * sizeof( hiprtFloat3 ) ) ); 67 | 68 | hiprtGeometryBuildInput geomInput; 69 | geomInput.type = hiprtPrimitiveTypeTriangleMesh; 70 | geomInput.primitive.triangleMesh = mesh; 71 | 72 | size_t geomTempSize; 73 | hiprtDevicePtr geomTemp; 74 | hiprtBuildOptions options; 75 | options.buildFlags = hiprtBuildFlagBitPreferFastBuild; 76 | CHECK_HIPRT( hiprtGetGeometryBuildTemporaryBufferSize( ctxt, geomInput, options, geomTempSize ) ); 77 | CHECK_ORO( oroMalloc( reinterpret_cast( &geomTemp ), geomTempSize ) ); 78 | 79 | hiprtGeometry geom; 80 | CHECK_HIPRT( hiprtCreateGeometry( ctxt, geomInput, options, geom ) ); 81 | CHECK_HIPRT( hiprtBuildGeometry( ctxt, hiprtBuildOperationBuild, geomInput, options, geomTemp, 0, geom ) ); 82 | 83 | oroFunction func; 84 | buildTraceKernelFromBitcode( ctxt, "../common/TutorialKernels.h", "SharedStackKernel", func, &opts ); 85 | 86 | uint8_t* pixels; 87 | CHECK_ORO( oroMalloc( reinterpret_cast( &pixels ), m_res.x * m_res.y * 4 ) ); 88 | 89 | hiprtGlobalStackBufferInput stackBufferInput{ 90 | hiprtStackTypeDynamic, hiprtStackEntryTypeInteger, StackSize, ThreadCount }; 91 | hiprtGlobalStackBuffer stackBuffer; 92 | CHECK_HIPRT( hiprtCreateGlobalStackBuffer( ctxt, stackBufferInput, stackBuffer ) ); 93 | 94 | void* args[] = { &geom, &pixels, &m_res, &stackBuffer }; 95 | launchKernel( func, m_res.x, m_res.y, BlockWidth, BlockHeight, args ); 96 | writeImage( "06_dynamic_stack.png", m_res.x, m_res.y, pixels ); 97 | 98 | CHECK_ORO( oroFree( reinterpret_cast( mesh.triangleIndices ) ) ); 99 | CHECK_ORO( oroFree( reinterpret_cast( mesh.vertices ) ) ); 100 | CHECK_ORO( oroFree( reinterpret_cast( geomTemp ) ) ); 101 | CHECK_ORO( oroFree( reinterpret_cast( pixels ) ) ); 102 | 103 | CHECK_HIPRT( hiprtDestroyGlobalStackBuffer( ctxt, stackBuffer ) ); 104 | CHECK_HIPRT( hiprtDestroyGeometry( ctxt, geom ) ); 105 | CHECK_HIPRT( hiprtDestroyContext( ctxt ) ); 106 | } 107 | }; 108 | 109 | int main( int argc, char** argv ) 110 | { 111 | Tutorial tutorial; 112 | tutorial.init( 0 ); 113 | tutorial.run(); 114 | 115 | return 0; 116 | } 117 | -------------------------------------------------------------------------------- /tutorials/common/BvhBuilder.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2021-2023 Advanced Micro Devices, Inc. All rights reserved. 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE. 21 | // 22 | 23 | #pragma once 24 | #include 25 | #include 26 | #include 27 | #include 28 | 29 | struct QueueEntry 30 | { 31 | int m_nodeIndex; 32 | int m_begin; 33 | int m_end; 34 | Aabb m_box; 35 | QueueEntry( int nodeIndex, int begin, int end, const Aabb& box ) 36 | : m_nodeIndex( nodeIndex ), m_begin( begin ), m_end( end ), m_box( box ) 37 | { 38 | } 39 | }; 40 | 41 | class BvhBuilder 42 | { 43 | public: 44 | BvhBuilder( void ) = delete; 45 | BvhBuilder& operator=( const BvhBuilder& ) = delete; 46 | 47 | static void build( uint32_t nPrims, const std::vector& primBoxes, std::vector& nodes ) 48 | { 49 | assert( nPrims >= 2 ); 50 | std::vector rightBoxes( nPrims ); 51 | std::vector tmpIndices( nPrims ); 52 | std::vector leftIndices( nPrims ); 53 | 54 | std::vector indices[3]; 55 | for ( int k = 0; k < 3; ++k ) 56 | { 57 | indices[k].resize( nPrims ); 58 | for ( int i = 0; i < nPrims; ++i ) 59 | indices[k][i] = i; 60 | std::sort( indices[k].begin(), indices[k].end(), [&]( int a, int b ) { 61 | hiprtFloat3 ca = primBoxes[a].center(); 62 | hiprtFloat3 cb = primBoxes[b].center(); 63 | return reinterpret_cast( &ca )[k] > reinterpret_cast( &cb )[k]; 64 | } ); 65 | } 66 | 67 | Aabb box; 68 | for ( int i = 0; i < nPrims; ++i ) 69 | box.grow( primBoxes[i] ); 70 | 71 | std::queue queue; 72 | queue.push( QueueEntry( 0, 0, nPrims, box ) ); 73 | nodes.push_back( hiprtInternalNode() ); 74 | while ( !queue.empty() ) 75 | { 76 | int nodeIndex = queue.front().m_nodeIndex; 77 | int begin = queue.front().m_begin; 78 | int end = queue.front().m_end; 79 | Aabb box = queue.front().m_box; 80 | queue.pop(); 81 | 82 | float minCost = FLT_MAX; 83 | int minAxis = 0; 84 | int minIndex = 0; 85 | Aabb minLeftBox, minRightBox; 86 | for ( int k = 0; k < 3; ++k ) 87 | { 88 | 89 | rightBoxes[end - 1] = primBoxes[indices[k][end - 1]]; 90 | for ( int i = end - 2; i >= begin; --i ) 91 | rightBoxes[i] = Aabb( primBoxes[indices[k][i]], rightBoxes[i + 1] ); 92 | 93 | Aabb leftBox, rightBox; 94 | for ( int i = begin; i < end - 1; ++i ) 95 | { 96 | int leftCount = ( i + 1 ) - begin; 97 | int rightCount = end - ( i + 1 ); 98 | leftBox.grow( primBoxes[indices[k][i]] ); 99 | rightBox = rightBoxes[i + 1]; 100 | float cost = leftBox.area() * leftCount + rightBox.area() * rightCount; 101 | if ( cost < minCost ) 102 | { 103 | minCost = cost; 104 | minIndex = i + 1; 105 | minAxis = k; 106 | minLeftBox = leftBox; 107 | minRightBox = rightBox; 108 | } 109 | assert( leftBox.area() <= box.area() ); 110 | assert( rightBox.area() <= box.area() ); 111 | } 112 | } 113 | 114 | assert( minIndex > begin ); 115 | assert( end > minIndex ); 116 | 117 | memset( leftIndices.data(), 0, nPrims * sizeof( int ) ); 118 | for ( int i = begin; i < minIndex; ++i ) 119 | { 120 | int index = indices[minAxis][i]; 121 | leftIndices[index] = 1; 122 | } 123 | 124 | for ( int j = 0; j < 3; ++j ) 125 | { 126 | if ( j != minAxis ) 127 | { 128 | int k = begin; 129 | int l = minIndex; 130 | for ( int i = begin; i < end; ++i ) 131 | { 132 | int index = indices[j][i]; 133 | if ( leftIndices[indices[j][i]] ) 134 | tmpIndices[k++] = index; 135 | else 136 | tmpIndices[l++] = index; 137 | } 138 | assert( k == minIndex ); 139 | assert( l == end ); 140 | memcpy( &indices[j][begin], &tmpIndices[begin], ( end - begin ) * sizeof( int ) ); 141 | } 142 | } 143 | 144 | nodes[nodeIndex].aabbMin = min( minLeftBox.m_min, minRightBox.m_min ); 145 | nodes[nodeIndex].aabbMax = max( minLeftBox.m_max, minRightBox.m_max ); 146 | if ( minIndex - begin == 1 ) 147 | { 148 | nodes[nodeIndex].childIndices[0] = indices[minAxis][begin]; 149 | nodes[nodeIndex].childNodeTypes[0] = hiprtBvhNodeTypeLeaf; 150 | } 151 | else 152 | { 153 | nodes[nodeIndex].childIndices[0] = static_cast( nodes.size() ); 154 | nodes[nodeIndex].childNodeTypes[0] = hiprtBvhNodeTypeInternal; 155 | queue.push( QueueEntry( nodes[nodeIndex].childIndices[0], begin, minIndex, minLeftBox ) ); 156 | nodes.push_back( hiprtInternalNode() ); 157 | } 158 | 159 | if ( end - minIndex == 1 ) 160 | { 161 | nodes[nodeIndex].childIndices[1] = indices[minAxis][minIndex]; 162 | nodes[nodeIndex].childNodeTypes[1] = hiprtBvhNodeTypeLeaf; 163 | } 164 | else 165 | { 166 | nodes[nodeIndex].childIndices[1] = static_cast( nodes.size() ); 167 | nodes[nodeIndex].childNodeTypes[1] = hiprtBvhNodeTypeInternal; 168 | queue.push( QueueEntry( nodes[nodeIndex].childIndices[1], minIndex, end, minRightBox ) ); 169 | nodes.push_back( hiprtInternalNode() ); 170 | } 171 | } 172 | } 173 | }; 174 | -------------------------------------------------------------------------------- /tutorials/02_scene_intersection/main.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2021-2023 Advanced Micro Devices, Inc. All rights reserved. 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE. 21 | // 22 | 23 | #include 24 | 25 | class Tutorial : public TutorialBase 26 | { 27 | public: 28 | void run() 29 | { 30 | hiprtContext ctxt; 31 | CHECK_HIPRT( hiprtCreateContext( HIPRT_API_VERSION, m_ctxtInput, ctxt ) ); 32 | 33 | hiprtTriangleMeshPrimitive mesh; 34 | mesh.triangleCount = 2; 35 | mesh.triangleStride = sizeof( hiprtInt3 ); 36 | uint32_t triangleIndices[] = { 0, 1, 2, 3, 4, 5 }; 37 | CHECK_ORO( 38 | oroMalloc( reinterpret_cast( &mesh.triangleIndices ), mesh.triangleCount * sizeof( hiprtInt3 ) ) ); 39 | CHECK_ORO( oroMemcpyHtoD( 40 | reinterpret_cast( mesh.triangleIndices ), 41 | triangleIndices, 42 | mesh.triangleCount * sizeof( hiprtInt3 ) ) ); 43 | 44 | mesh.vertexCount = 6; 45 | mesh.vertexStride = sizeof( hiprtFloat3 ); 46 | constexpr float S = 0.5f; 47 | constexpr float T = 0.8f; 48 | hiprtFloat3 vertices[] = { 49 | { S, S, 0.0f }, 50 | { S + T * S, -S * S, 0.0f }, 51 | { S - T * S, -S * S, 0.0f }, 52 | { -S, S, 0.0f }, 53 | { -S + T * S, -S * S, 0.0f }, 54 | { -S - T * S, -S * S, 0.0f } }; 55 | CHECK_ORO( oroMalloc( reinterpret_cast( &mesh.vertices ), mesh.vertexCount * sizeof( hiprtFloat3 ) ) ); 56 | CHECK_ORO( oroMemcpyHtoD( 57 | reinterpret_cast( mesh.vertices ), vertices, mesh.vertexCount * sizeof( hiprtFloat3 ) ) ); 58 | 59 | hiprtGeometryBuildInput geomInput; 60 | geomInput.type = hiprtPrimitiveTypeTriangleMesh; 61 | geomInput.primitive.triangleMesh = mesh; 62 | 63 | size_t geomTempSize; 64 | hiprtDevicePtr geomTemp; 65 | hiprtBuildOptions options; 66 | options.buildFlags = hiprtBuildFlagBitPreferFastBuild; 67 | CHECK_HIPRT( hiprtGetGeometryBuildTemporaryBufferSize( ctxt, geomInput, options, geomTempSize ) ); 68 | CHECK_ORO( oroMalloc( reinterpret_cast( &geomTemp ), geomTempSize ) ); 69 | 70 | hiprtGeometry geom; 71 | CHECK_HIPRT( hiprtCreateGeometry( ctxt, geomInput, options, geom ) ); 72 | CHECK_HIPRT( hiprtBuildGeometry( ctxt, hiprtBuildOperationBuild, geomInput, options, geomTemp, 0, geom ) ); 73 | 74 | hiprtInstance instance; 75 | instance.type = hiprtInstanceTypeGeometry; 76 | instance.geometry = geom; 77 | 78 | hiprtSceneBuildInput sceneInput; 79 | sceneInput.instanceCount = 1; 80 | sceneInput.instanceMasks = nullptr; 81 | sceneInput.instanceTransformHeaders = nullptr; 82 | CHECK_ORO( oroMalloc( reinterpret_cast( &sceneInput.instances ), sizeof( hiprtInstance ) ) ); 83 | CHECK_ORO( 84 | oroMemcpyHtoD( reinterpret_cast( sceneInput.instances ), &instance, sizeof( hiprtInstance ) ) ); 85 | 86 | hiprtFrameSRT frame; 87 | frame.translation = { 0.0f, 0.0f, 0.0f }; 88 | frame.scale = { 0.5f, 0.5f, 0.5f }; 89 | frame.rotation = { 0.0f, 0.0f, 1.0f, 0.0f }; 90 | sceneInput.frameCount = 1; 91 | CHECK_ORO( oroMalloc( reinterpret_cast( &sceneInput.instanceFrames ), sizeof( hiprtFrameSRT ) ) ); 92 | CHECK_ORO( 93 | oroMemcpyHtoD( reinterpret_cast( sceneInput.instanceFrames ), &frame, sizeof( hiprtFrameSRT ) ) ); 94 | 95 | size_t sceneTempSize; 96 | hiprtDevicePtr sceneTemp = nullptr; 97 | CHECK_HIPRT( hiprtGetSceneBuildTemporaryBufferSize( ctxt, sceneInput, options, sceneTempSize ) ); 98 | CHECK_ORO( oroMalloc( reinterpret_cast( &sceneTemp ), sceneTempSize ) ); 99 | 100 | hiprtScene scene = nullptr; 101 | CHECK_HIPRT( hiprtCreateScene( ctxt, sceneInput, options, scene ) ); 102 | CHECK_HIPRT( hiprtBuildScene( ctxt, hiprtBuildOperationBuild, sceneInput, options, sceneTemp, 0, scene ) ); 103 | 104 | // we can free the Temporary Buffer just after hiprtBuildScene, as this buffer is only used during the build. 105 | CHECK_ORO( oroFree( reinterpret_cast( sceneTemp ) ) ); 106 | sceneTemp = nullptr; 107 | 108 | oroFunction func = nullptr; 109 | buildTraceKernelFromBitcode( ctxt, "../common/TutorialKernels.h", "SceneIntersectionKernel", func ); 110 | 111 | uint8_t* pixels = nullptr; 112 | CHECK_ORO( oroMalloc( reinterpret_cast( &pixels ), m_res.x * m_res.y * 4 ) ); 113 | 114 | void* args[] = { &scene, &pixels, &m_res }; 115 | launchKernel( func, m_res.x, m_res.y, args ); 116 | writeImage( "02_scene_intersection.png", m_res.x, m_res.y, pixels ); 117 | 118 | CHECK_ORO( oroFree( reinterpret_cast( sceneInput.instances ) ) ); 119 | CHECK_ORO( oroFree( reinterpret_cast( sceneInput.instanceFrames ) ) ); 120 | CHECK_ORO( oroFree( reinterpret_cast( mesh.triangleIndices ) ) ); 121 | CHECK_ORO( oroFree( reinterpret_cast( mesh.vertices ) ) ); 122 | CHECK_ORO( oroFree( reinterpret_cast( geomTemp ) ) ); 123 | CHECK_ORO( oroFree( reinterpret_cast( pixels ) ) ); 124 | 125 | CHECK_HIPRT( hiprtDestroyGeometry( ctxt, geom ) ); 126 | CHECK_HIPRT( hiprtDestroyScene( ctxt, scene ) ); 127 | CHECK_HIPRT( hiprtDestroyContext( ctxt ) ); 128 | } 129 | }; 130 | 131 | int main( int argc, char** argv ) 132 | { 133 | Tutorial tutorial; 134 | tutorial.init( 0 ); 135 | tutorial.run(); 136 | 137 | return 0; 138 | } 139 | -------------------------------------------------------------------------------- /tutorials/common/CornellBox.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | constexpr uint32_t CornellBoxTriangleCount = 32; 6 | constexpr uint32_t CornellBoxMaterialCount = 4; 7 | 8 | const static std::array cornellBoxVertices = { { // Floor -- white lambert 9 | { 0.0f, 0.0f, 0.0f }, 10 | { 0.0f, 0.0f, 559.2f }, 11 | { 556.0f, 0.0f, 559.2f }, 12 | { 0.0f, 0.0f, 0.0f }, 13 | { 556.0f, 0.0f, 559.2f }, 14 | { 556.0f, 0.0f, 0.0f }, 15 | 16 | // Ceiling -- white lambert 17 | { 0.0f, 548.8f, 0.0f }, 18 | { 556.0f, 548.8f, 0.0f }, 19 | { 556.0f, 548.8f, 559.2f }, 20 | 21 | { 0.0f, 548.8f, 0.0f }, 22 | { 556.0f, 548.8f, 559.2f }, 23 | { 0.0f, 548.8f, 559.2f }, 24 | 25 | // Back wall -- white lambert 26 | { 0.0f, 0.0f, 559.2f }, 27 | { 0.0f, 548.8f, 559.2f }, 28 | { 556.0f, 548.8f, 559.2f }, 29 | 30 | { 0.0f, 0.0f, 559.2f }, 31 | { 556.0f, 548.8f, 559.2f }, 32 | { 556.0f, 0.0f, 559.2f }, 33 | 34 | // Right wall -- green lambert 35 | { 0.0f, 0.0f, 0.0f }, 36 | { 0.0f, 548.8f, 0.0f }, 37 | { 0.0f, 548.8f, 559.2f }, 38 | 39 | { 0.0f, 0.0f, 0.0f }, 40 | { 0.0f, 548.8f, 559.2f }, 41 | { 0.0f, 0.0f, 559.2f }, 42 | 43 | // Left wall -- red lambert 44 | { 556.0f, 0.0f, 0.0f }, 45 | { 556.0f, 0.0f, 559.2f }, 46 | { 556.0f, 548.8f, 559.2f }, 47 | 48 | { 556.0f, 0.0f, 0.0f }, 49 | { 556.0f, 548.8f, 559.2f }, 50 | { 556.0f, 548.8f, 0.0f }, 51 | 52 | // Short block -- white lambert 53 | { 130.0f, 165.0f, 65.0f }, 54 | { 82.0f, 165.0f, 225.0f }, 55 | { 242.0f, 165.0f, 274.0f }, 56 | 57 | { 130.0f, 165.0f, 65.0f }, 58 | { 242.0f, 165.0f, 274.0f }, 59 | { 290.0f, 165.0f, 114.0f }, 60 | 61 | { 290.0f, 0.0f, 114.0f }, 62 | { 290.0f, 165.0f, 114.0f }, 63 | { 240.0f, 165.0f, 272.0f }, 64 | 65 | { 290.0f, 0.0f, 114.0f }, 66 | { 240.0f, 165.0f, 272.0f }, 67 | { 240.0f, 0.0f, 272.0f }, 68 | 69 | { 130.0f, 0.0f, 65.0f }, 70 | { 130.0f, 165.0f, 65.0f }, 71 | { 290.0f, 165.0f, 114.0f }, 72 | 73 | { 130.0f, 0.0f, 65.0f }, 74 | { 290.0f, 165.0f, 114.0f }, 75 | { 290.0f, 0.0f, 114.0f }, 76 | 77 | { 82.0f, 0.0f, 225.0f }, 78 | { 82.0f, 165.0f, 225.0f }, 79 | { 130.0f, 165.0f, 65.0f }, 80 | 81 | { 82.0f, 0.0f, 225.0f }, 82 | { 130.0f, 165.0f, 65.0f }, 83 | { 130.0f, 0.0f, 65.0f }, 84 | 85 | { 240.0f, 0.0f, 272.0f }, 86 | { 240.0f, 165.0f, 272.0f }, 87 | { 82.0f, 165.0f, 225.0f }, 88 | 89 | { 240.0f, 0.0f, 272.0f }, 90 | { 82.0f, 165.0f, 225.0f }, 91 | { 82.0f, 0.0f, 225.0f }, 92 | 93 | // Tall block -- white lambert 94 | { 423.0f, 330.0f, 247.0f }, 95 | { 265.0f, 330.0f, 296.0f }, 96 | { 314.0f, 330.0f, 455.0f }, 97 | 98 | { 423.0f, 330.0f, 247.0f }, 99 | { 314.0f, 330.0f, 455.0f }, 100 | { 472.0f, 330.0f, 406.0f }, 101 | 102 | { 423.0f, 0.0f, 247.0f }, 103 | { 423.0f, 330.0f, 247.0f }, 104 | { 472.0f, 330.0f, 406.0f }, 105 | 106 | { 423.0f, 0.0f, 247.0f }, 107 | { 472.0f, 330.0f, 406.0f }, 108 | { 472.0f, 0.0f, 406.0f }, 109 | 110 | { 472.0f, 0.0f, 406.0f }, 111 | { 472.0f, 330.0f, 406.0f }, 112 | { 314.0f, 330.0f, 456.0f }, 113 | 114 | { 472.0f, 0.0f, 406.0f }, 115 | { 314.0f, 330.0f, 456.0f }, 116 | { 314.0f, 0.0f, 456.0f }, 117 | 118 | { 314.0f, 0.0f, 456.0f }, 119 | { 314.0f, 330.0f, 456.0f }, 120 | { 265.0f, 330.0f, 296.0f }, 121 | 122 | { 314.0f, 0.0f, 456.0f }, 123 | { 265.0f, 330.0f, 296.0f }, 124 | { 265.0f, 0.0f, 296.0f }, 125 | 126 | { 265.0f, 0.0f, 296.0f }, 127 | { 265.0f, 330.0f, 296.0f }, 128 | { 423.0f, 330.0f, 247.0f }, 129 | 130 | { 265.0f, 0.0f, 296.0f }, 131 | { 423.0f, 330.0f, 247.0f }, 132 | { 423.0f, 0.0f, 247.0f }, 133 | 134 | // Ceiling light -- emmissive 135 | { 343.0f, 548.6f, 227.0f }, 136 | { 213.0f, 548.6f, 227.0f }, 137 | { 213.0f, 548.6f, 332.0f }, 138 | 139 | { 343.0f, 548.6f, 227.0f }, 140 | { 213.0f, 548.6f, 332.0f }, 141 | { 343.0f, 548.6f, 332.0f } } }; 142 | 143 | static std::array cornellBoxMatIndices = { { 144 | 0, 0, // Floor -- white lambert 145 | 0, 0, // Ceiling -- white lambert 146 | 0, 0, // Back wall -- white lambert 147 | 1, 1, // Right wall -- green lambert 148 | 2, 2, // Left wall -- red lambert 149 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // Short block -- white lambert 150 | 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // Tall block -- white lambert 151 | 3, 3 // Ceiling light -- emmissive 152 | } }; 153 | 154 | const std::array cornellBoxEmissionColors = { 155 | { { 0.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 0.0f }, { 15.0f, 15.0f, 5.0f } 156 | 157 | } }; 158 | 159 | const std::array cornellBoxDiffuseColors = { 160 | { { 0.80f, 0.80f, 0.80f }, { 0.05f, 0.80f, 0.05f }, { 0.80f, 0.05f, 0.05f }, { 0.50f, 0.00f, 0.00f } } }; 161 | -------------------------------------------------------------------------------- /tutorials/common/Common.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2021-2023 Advanced Micro Devices, Inc. All rights reserved. 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE. 21 | // 22 | 23 | #pragma once 24 | 25 | #if ( defined( __CUDACC__ ) || defined( __HIPCC__ ) ) 26 | #define __KERNELCC__ 27 | #endif 28 | 29 | #include 30 | 31 | #if !defined( __KERNELCC__ ) 32 | using int2 = hiprt::Vector; 33 | using int3 = hiprt::Vector; 34 | using int4 = hiprt::Vector; 35 | using uint2 = hiprt::Vector; 36 | using uint3 = hiprt::Vector; 37 | using uint4 = hiprt::Vector; 38 | using float2 = hiprt::Vector; 39 | using float3 = hiprt::Vector; 40 | using float4 = hiprt::Vector; 41 | #endif 42 | 43 | #include 44 | 45 | #if !defined( __KERNELCC__ ) 46 | #include 47 | #endif 48 | 49 | #include 50 | #if defined( __KERNELCC__ ) 51 | #include 52 | #endif 53 | 54 | static constexpr bool UseDynamicStack = false; 55 | 56 | #if defined( __KERNELCC__ ) 57 | typedef typename hiprt::conditional::type Stack; 58 | typedef hiprtEmptyInstanceStack InstanceStack; 59 | #endif 60 | 61 | struct float4x4 62 | { 63 | union 64 | { 65 | float4 r[4]; 66 | float e[4][4]; 67 | }; 68 | }; 69 | 70 | enum 71 | { 72 | VisualizeColor, 73 | VisualizeUv, 74 | VisualizeId, 75 | VisualizeHitDist, 76 | VisualizeNormal, 77 | VisualizeAo 78 | }; 79 | 80 | struct Material 81 | { 82 | float3 m_diffuse; 83 | float3 m_emission; 84 | 85 | HIPRT_HOST_DEVICE HIPRT_INLINE bool light() { return m_emission.x + m_emission.y + m_emission.z > 0.0f; } 86 | }; 87 | 88 | struct Light 89 | { 90 | float3 m_le; 91 | float3 m_lv0; 92 | float3 m_lv1; 93 | float3 m_lv2; 94 | float3 pad; 95 | }; 96 | 97 | struct Camera 98 | { 99 | float4 m_rotation; 100 | float3 m_translation; 101 | float m_fov; 102 | }; 103 | 104 | HIPRT_HOST_DEVICE HIPRT_INLINE uint32_t lcg( uint32_t& seed ) 105 | { 106 | constexpr uint32_t LcgA = 1103515245u; 107 | constexpr uint32_t LcgC = 12345u; 108 | constexpr uint32_t LcgM = 0x00FFFFFFu; 109 | seed = ( LcgA * seed + LcgC ); 110 | return seed & LcgM; 111 | } 112 | 113 | HIPRT_HOST_DEVICE HIPRT_INLINE float randf( uint32_t& seed ) 114 | { 115 | return ( static_cast( lcg( seed ) ) / static_cast( 0x01000000 ) ); 116 | } 117 | 118 | template 119 | HIPRT_HOST_DEVICE HIPRT_INLINE uint2 tea( uint32_t val0, uint32_t val1 ) 120 | { 121 | uint32_t v0 = val0; 122 | uint32_t v1 = val1; 123 | uint32_t s0 = 0; 124 | 125 | for ( uint32_t n = 0; n < N; n++ ) 126 | { 127 | s0 += 0x9e3779b9; 128 | v0 += ( ( v1 << 4 ) + 0xa341316c ) ^ ( v1 + s0 ) ^ ( ( v1 >> 5 ) + 0xc8013ea4 ); 129 | v1 += ( ( v0 << 4 ) + 0xad90777d ) ^ ( v0 + s0 ) ^ ( ( v0 >> 5 ) + 0x7e95761e ); 130 | } 131 | 132 | return { v0, v1 }; 133 | } 134 | 135 | HIPRT_HOST_DEVICE HIPRT_INLINE float dot4( const float4& a, const float4& b ) 136 | { 137 | return a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w; 138 | } 139 | 140 | HIPRT_HOST_DEVICE HIPRT_INLINE float4 operator*( const float4x4& m, const float4& v ) 141 | { 142 | return { dot4( m.r[0], v ), dot4( m.r[1], v ), dot4( m.r[2], v ), dot4( m.r[3], v ) }; 143 | } 144 | 145 | HIPRT_HOST_DEVICE HIPRT_INLINE float4x4 Perspective( float y_fov, float aspect, float n, float f ) 146 | { 147 | float a = 1.0f / tanf( y_fov / 2.0f ); 148 | 149 | float4x4 m; 150 | m.r[0] = { a / aspect, 0.0f, 0.0f, 0.0f }; 151 | m.r[1] = { 0.0f, a, 0.0f, 0.0f }; 152 | m.r[2] = { 0.0f, 0.0f, f / ( f - n ), n * f / ( n - f ) }; 153 | m.r[3] = { 0.0f, 0.0f, 1.0f, 0.0f }; 154 | 155 | return m; 156 | } 157 | 158 | HIPRT_HOST_DEVICE HIPRT_INLINE float4x4 LookAt( const float3& eye, const float3& at, const float3& up ) 159 | { 160 | float3 f = hiprt::normalize( at - eye ); 161 | float3 s = hiprt::normalize( hiprt::cross( up, f ) ); 162 | float3 t = hiprt::cross( f, s ); 163 | 164 | float4x4 m; 165 | m.r[0] = hiprt::make_float4( s, -hiprt::dot( s, eye ) ); 166 | m.r[1] = hiprt::make_float4( t, -hiprt::dot( t, eye ) ); 167 | m.r[2] = hiprt::make_float4( f, -hiprt::dot( f, eye ) ); 168 | m.r[3] = { 0.0f, 0.0f, 0.0f, 1.0f }; 169 | 170 | return m; 171 | } 172 | 173 | HIPRT_HOST_DEVICE HIPRT_INLINE float4x4 operator*( const float4x4& a, const float4x4& b ) 174 | { 175 | float4x4 m; 176 | for ( int r = 0; r < 4; ++r ) 177 | { 178 | for ( int c = 0; c < 4; ++c ) 179 | { 180 | m.e[r][c] = 0.0f; 181 | for ( int k = 0; k < 4; ++k ) 182 | m.e[r][c] += a.e[r][k] * b.e[k][c]; 183 | } 184 | } 185 | 186 | return m; 187 | } 188 | 189 | HIPRT_HOST_DEVICE HIPRT_INLINE float3 rotate( const float4& rotation, const float3& p ) 190 | { 191 | float3 a = sinf( rotation.w / 2.0f ) * hiprt::normalize( hiprt::make_float3( rotation ) ); 192 | float c = cosf( rotation.w / 2.0f ); 193 | return 2.0f * hiprt::dot( a, p ) * a + ( c * c - hiprt::dot( a, a ) ) * p + 2.0f * c * hiprt::cross( a, p ); 194 | } 195 | 196 | HIPRT_HOST_DEVICE HIPRT_INLINE hiprtRay 197 | generateRay( float x, float y, int2 res, const Camera& camera, uint32_t& seed, bool isMultiSamples ) 198 | { 199 | const float offset = ( isMultiSamples ) ? randf( seed ) : 0.5f; 200 | const float2 sensorSize = { 0.024f * ( res.x / static_cast( res.y ) ), 0.024f }; 201 | const float2 xy = float2{ ( x + offset ) / res.x, ( y + offset ) / res.y } - float2{ 0.5f, 0.5f }; 202 | const float3 dir = { xy.x * sensorSize.x, xy.y * sensorSize.y, sensorSize.y / ( 2.0f * tan( camera.m_fov / 2.0f ) ) }; 203 | 204 | const float3 holDir = rotate( camera.m_rotation, { 1.0f, 0.0f, 0.0f } ); 205 | const float3 upDir = rotate( camera.m_rotation, { 0.0f, -1.0f, 0.0f } ); 206 | const float3 viewDir = rotate( camera.m_rotation, { 0.0f, 0.0f, -1.0f } ); 207 | 208 | hiprtRay ray; 209 | ray.origin = camera.m_translation; 210 | ray.direction = hiprt::normalize( dir.x * holDir + dir.y * upDir + dir.z * viewDir ); 211 | return ray; 212 | } 213 | -------------------------------------------------------------------------------- /tutorials/common/ShadowRayKernel.h: -------------------------------------------------------------------------------- 1 | ////////////////////////////////////////////////////////////////////////////////////////// 2 | // 3 | // Copyright (c) 2024 Advanced Micro Devices, Inc. All Rights Reserved. 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | // SOFTWARE. 22 | // 23 | ////////////////////////////////////////////////////////////////////////////////////////// 24 | 25 | #include 26 | #include 27 | #include 28 | 29 | #include 30 | #include 31 | 32 | // #include 33 | 34 | #ifndef BLOCK_SIZE 35 | #define BLOCK_SIZE 1 36 | #endif 37 | 38 | #ifndef SHARED_STACK_SIZE 39 | #define SHARED_STACK_SIZE 1 40 | #endif 41 | 42 | __device__ float3 sampleLightVertex( const Light& light, float3 x, float3& lVtxOut, float3& lNormalOut, float& pdf, float2 xi ) 43 | { 44 | 45 | float3 le{}; 46 | lNormalOut = hiprt::cross( light.m_lv1 - light.m_lv0, light.m_lv2 - light.m_lv0 ); 47 | float area = sqrtf( hiprt::dot( lNormalOut, lNormalOut ) ) / 2.0f; 48 | lNormalOut = hiprt::normalize( lNormalOut ); 49 | const float2 w = { 1.f - sqrtf( xi.x ), xi.y * sqrtf( xi.x ) }; 50 | lVtxOut = light.m_lv0 + w.x * ( light.m_lv1 - light.m_lv0 ) + w.y * ( light.m_lv2 - light.m_lv0 ); 51 | 52 | // evaluate light surface integral part here for convenience 53 | float3 r = lVtxOut - x; 54 | // light surface cos term 55 | float cos = fabs( hiprt::dot( lNormalOut, -hiprt::normalize( r ) ) ); 56 | if ( sqrtf( hiprt::dot( r, r ) ) < 0.0001f || cos < 0.0001f ) 57 | { 58 | pdf = 0.0f; 59 | return le; 60 | } 61 | 62 | if ( hiprt::dot( r, lNormalOut ) > 0.0f ) 63 | { 64 | pdf = 0.0f; 65 | return le; 66 | } 67 | 68 | // inverse of cos(theta) / r ^2 / p_i as we will be dividing by pdf 69 | pdf = hiprt::dot( r, r ) * ( 1.0f / area ) / cos; 70 | return light.m_le; 71 | } 72 | 73 | extern "C" __global__ void __launch_bounds__( 64 ) ShadowRayKernel( 74 | hiprtScene scene, 75 | uint8_t* image, 76 | int2 resolution, 77 | hiprtGlobalStackBuffer globalStackBuffer, 78 | Camera camera, 79 | uint32_t* matIndices, 80 | Material* materials, 81 | uint32_t* matOffsetPerInstance, 82 | uint32_t* indices, 83 | uint32_t* indxOffsets, 84 | float3* normals, 85 | uint32_t* normOffset, 86 | uint32_t* numOfLights, 87 | Light* lights, 88 | float aoRadius ) 89 | { 90 | const uint32_t x = blockIdx.x * blockDim.x + threadIdx.x; 91 | const uint32_t y = blockIdx.y * blockDim.y + threadIdx.y; 92 | const uint32_t index = x + y * resolution.x; 93 | 94 | uint32_t seed = tea<16>( x, y ).x; 95 | 96 | __shared__ uint32_t sharedStackCache[SHARED_STACK_SIZE * BLOCK_SIZE]; 97 | hiprtSharedStackBuffer sharedStackBuffer{ SHARED_STACK_SIZE, sharedStackCache }; 98 | 99 | Stack stack( globalStackBuffer, sharedStackBuffer ); 100 | InstanceStack instanceStack; 101 | 102 | hiprtRay ray = generateRay( x, y, resolution, camera, seed, false ); 103 | hiprtSceneTraversalClosestCustomStack tr( scene, ray, stack, instanceStack ); 104 | hiprtHit hit = tr.getNextHit(); 105 | 106 | int3 color{}; 107 | if ( hit.hasHit() ) 108 | { 109 | const uint32_t idxOffset = indxOffsets[hit.instanceID]; 110 | const uint32_t idx0 = indices[idxOffset + ( ( hit.primID * 3 ) + 0 )]; 111 | const uint32_t idx1 = indices[idxOffset + ( ( hit.primID * 3 ) + 1 )]; 112 | const uint32_t idx2 = indices[idxOffset + ( ( hit.primID * 3 ) + 2 )]; 113 | 114 | const uint32_t nOffset = normOffset[hit.instanceID]; 115 | const float3 n0 = normals[nOffset + idx0]; 116 | const float3 n1 = normals[nOffset + idx1]; 117 | const float3 n2 = normals[nOffset + idx2]; 118 | 119 | float3 Ns = ( 1.0f - hit.uv.x - hit.uv.y ) * n0 + hit.uv.x * n1 + hit.uv.y * n2; 120 | 121 | // float3 Ng = hiprtVectorObjectToWorld( hit.normal, scene, hit.instanceID ); 122 | float3 Ng = hit.normal; 123 | 124 | if ( hiprt::dot( ray.direction, Ng ) > 0.f ) Ng = -Ng; 125 | Ng = hiprt::normalize( Ng ); 126 | 127 | if ( hiprt::dot( Ng, Ns ) < 0.0f ) Ns = Ns - 2.0f * hiprt::dot( Ng, Ns ) * Ng; 128 | Ns = hiprt::normalize( Ns ); 129 | 130 | const uint32_t matOffset = matOffsetPerInstance[hit.instanceID] + hit.primID; 131 | const uint32_t matIndex = matIndices[matOffset]; 132 | 133 | const float3 diffuseColor = materials[matIndex].m_diffuse; 134 | const float3 emissiveColor = materials[matIndex].m_emission; 135 | float3 finalColor = emissiveColor; 136 | 137 | const float3 surfacePt = ray.origin + hit.t * ray.direction; 138 | if ( matIndex == hiprtInvalidValue || !materials[matIndex].light() ) 139 | { 140 | constexpr uint32_t Spp = 256; 141 | float3 est{}; 142 | for ( uint32_t l = 0; l < numOfLights[0]; l++ ) 143 | { 144 | for ( uint32_t p = 0; p < Spp; p++ ) 145 | { 146 | 147 | float3 lightVtx; 148 | float3 lNormal; 149 | Light light = lights[l]; 150 | float pdf = 0.0f; 151 | 152 | float3 le = sampleLightVertex( 153 | light, surfacePt, lightVtx, lNormal, pdf, make_float2( randf( seed ), randf( seed ) ) ); 154 | 155 | float3 lightDir = lightVtx - surfacePt; 156 | float3 lightPt = lightVtx + 1.0e-3f * lNormal; 157 | float3 lightVec = lightPt - surfacePt; 158 | 159 | hiprtRay shadowRay; 160 | shadowRay.origin = surfacePt + 1.0e-3f * Ng; 161 | shadowRay.direction = hiprt::normalize( lightDir ); 162 | shadowRay.maxT = 0.99f * sqrtf( hiprt::dot( lightVec, lightVec ) ); 163 | 164 | hiprtSceneTraversalAnyHitCustomStack tr( scene, shadowRay, stack, instanceStack ); 165 | hiprtHit hitShadow = tr.getNextHit(); 166 | int lightVisibility = hitShadow.hasHit() ? 0 : 1; 167 | 168 | if ( pdf != 0.0f ) 169 | est += lightVisibility * le * max( 0.0f, hiprt::dot( Ng, hiprt::normalize( lightDir ) ) ) / pdf; 170 | } 171 | } 172 | 173 | finalColor = 1.0f / Spp * est * diffuseColor / hiprt::Pi; 174 | } 175 | 176 | color.x = finalColor.x * 255; 177 | color.y = finalColor.y * 255; 178 | color.z = finalColor.z * 255; 179 | } 180 | 181 | image[index * 4 + 0] = hiprt::clamp( color.x, 0, 255 ); 182 | image[index * 4 + 1] = hiprt::clamp( color.y, 0, 255 ); 183 | image[index * 4 + 2] = hiprt::clamp( color.z, 0, 255 ); 184 | image[index * 4 + 3] = 255; 185 | } 186 | -------------------------------------------------------------------------------- /doc/07_custom_bvh_import.md: -------------------------------------------------------------------------------- 1 | # [07_custom_bvh_import](../tutorials/07_custom_bvh_import) 2 | 3 |
4 | 5 |
6 | img 7 |
8 | 9 | 10 | One interesting feature that HIPRT supports is importing a custom BVH. The 11 | build input structure has an optional list of nodes defining a topology and bounding boxes of the 12 | custom BVH. If the list is specified, then HIPRT skips the build and just converts the nodes from 13 | the API format to the internal format. This feature might be useful for research, allowing users to 14 | benchmark their BVH builders with HIPRT hardware-accelerated kernels. This demo illustrates the process. 15 | 16 |
17 | 18 | Steps to Import a custom BVH: 19 | 20 | - Skip the geometry temporary buffer: You do not need to use the usual `geomTemp` buffer, which is typically built with `hiprtGetGeometryBuildTemporaryBufferSize`. 21 | - Set the build flags: In the `buildFlags` of `hiprtBuildOptions`, specify the `hiprtBuildFlagBitCustomBvhImport` flag. 22 | - Build your custom BVH. 23 | 24 |
25 |
26 | 27 | The BVH building is done inside `buildBvh` in the demo. 28 | The main task of `buildBvh` is to build the `nodeList` of `hiprtGeometryBuildInput`. This node list is optional and only used for custom BVH.
29 |
30 | First, `buildBvh` builds of list of AABB boxes, from the Device's data. 31 | 32 | ```cpp 33 | std::vector primBoxes( buildInput.primitive.triangleMesh.triangleCount ); 34 | std::vector verticesRaw(buildInput.primitive.triangleMesh.vertexCount * 35 | buildInput.primitive.triangleMesh.vertexStride ); 36 | std::vector trianglesRaw(buildInput.primitive.triangleMesh.triangleCount * 37 | buildInput.primitive.triangleMesh.triangleStride ); 38 | oroMemcpyDtoH( 39 | verticesRaw.data(), 40 | reinterpret_cast( buildInput.primitive.triangleMesh.vertices ), 41 | buildInput.primitive.triangleMesh.vertexCount * buildInput.primitive.triangleMesh.vertexStride ); 42 | oroMemcpyDtoH( 43 | trianglesRaw.data(), 44 | reinterpret_cast( buildInput.primitive.triangleMesh.triangleIndices ), 45 | buildInput.primitive.triangleMesh.triangleCount * buildInput.primitive.triangleMesh.triangleStride ); 46 | for ( uint32_t i = 0; i < buildInput.primitive.triangleMesh.triangleCount; ++i ) 47 | { 48 | hiprtInt3 triangle = *reinterpret_cast( trianglesRaw.data() + 49 | i * buildInput.primitive.triangleMesh.triangleStride ); 50 | hiprtFloat3 v0 = *reinterpret_cast( verticesRaw.data() + 51 | triangle.x * buildInput.primitive.triangleMesh.vertexStride ); 52 | hiprtFloat3 v1 = *reinterpret_cast( verticesRaw.data() + 53 | triangle.y * buildInput.primitive.triangleMesh.vertexStride ); 54 | hiprtFloat3 v2 = *reinterpret_cast( verticesRaw.data() + 55 | triangle.z * buildInput.primitive.triangleMesh.vertexStride ); 56 | primBoxes[i].reset(); 57 | primBoxes[i].grow( v0 ); 58 | primBoxes[i].grow( v1 ); 59 | primBoxes[i].grow( v2 ); 60 | } 61 | ``` 62 | 63 |
64 |
65 | 66 | Then, it's calling `BvhBuilder::build`. This function builds a BVH from a list of bounding boxes. 67 | It sorts and splits these boxes along different axes to create a tree structure. Each node in the tree represents a bounding box, helping to quickly find intersections in ray tracing. 68 | 69 | ```cpp 70 | static void build( uint32_t nPrims, const std::vector& primBoxes, std::vector& nodes ) 71 | { 72 | assert( nPrims >= 2 ); 73 | std::vector rightBoxes( nPrims ); 74 | std::vector tmpIndices( nPrims ); 75 | std::vector leftIndices( nPrims ); 76 | 77 | std::vector indices[3]; 78 | for ( int k = 0; k < 3; ++k ) 79 | { 80 | indices[k].resize( nPrims ); 81 | for ( int i = 0; i < nPrims; ++i ) 82 | indices[k][i] = i; 83 | std::sort( indices[k].begin(), indices[k].end(), [&]( int a, int b ) { 84 | hiprtFloat3 ca = primBoxes[a].center(); 85 | hiprtFloat3 cb = primBoxes[b].center(); 86 | return reinterpret_cast( &ca )[k] > reinterpret_cast( &cb )[k]; 87 | } ); 88 | } 89 | 90 | Aabb box; 91 | for ( int i = 0; i < nPrims; ++i ) 92 | box.grow( primBoxes[i] ); 93 | 94 | std::queue queue; 95 | queue.push( QueueEntry( 0, 0, nPrims, box ) ); 96 | nodes.push_back( hiprtBvhNode() ); 97 | while ( !queue.empty() ) 98 | { 99 | int nodeIndex = queue.front().m_nodeIndex; 100 | int begin = queue.front().m_begin; 101 | int end = queue.front().m_end; 102 | Aabb box = queue.front().m_box; 103 | queue.pop(); 104 | 105 | float minCost = FLT_MAX; 106 | int minAxis = 0; 107 | int minIndex = 0; 108 | Aabb minLeftBox, minRightBox; 109 | for ( int k = 0; k < 3; ++k ) 110 | { 111 | 112 | rightBoxes[end - 1] = primBoxes[indices[k][end - 1]]; 113 | for ( int i = end - 2; i >= begin; --i ) 114 | rightBoxes[i] = Aabb( primBoxes[indices[k][i]], rightBoxes[i + 1] ); 115 | 116 | Aabb leftBox, rightBox; 117 | for ( int i = begin; i < end - 1; ++i ) 118 | { 119 | int leftCount = ( i + 1 ) - begin; 120 | int rightCount = end - ( i + 1 ); 121 | leftBox.grow( primBoxes[indices[k][i]] ); 122 | rightBox = rightBoxes[i + 1]; 123 | float cost = leftBox.area() * leftCount + rightBox.area() * rightCount; 124 | if ( cost < minCost ) 125 | { 126 | minCost = cost; 127 | minIndex = i + 1; 128 | minAxis = k; 129 | minLeftBox = leftBox; 130 | minRightBox = rightBox; 131 | } 132 | assert( leftBox.area() <= box.area() ); 133 | assert( rightBox.area() <= box.area() ); 134 | } 135 | } 136 | 137 | assert( minIndex > begin ); 138 | assert( end > minIndex ); 139 | 140 | memset( leftIndices.data(), 0, nPrims * sizeof( int ) ); 141 | for ( int i = begin; i < minIndex; ++i ) 142 | { 143 | int index = indices[minAxis][i]; 144 | leftIndices[index] = 1; 145 | } 146 | 147 | for ( int j = 0; j < 3; ++j ) 148 | { 149 | if ( j != minAxis ) 150 | { 151 | int k = begin; 152 | int l = minIndex; 153 | for ( int i = begin; i < end; ++i ) 154 | { 155 | int index = indices[j][i]; 156 | if ( leftIndices[indices[j][i]] ) 157 | tmpIndices[k++] = index; 158 | else 159 | tmpIndices[l++] = index; 160 | } 161 | assert( k == minIndex ); 162 | assert( l == end ); 163 | memcpy( &indices[j][begin], &tmpIndices[begin], ( end - begin ) * sizeof( int ) ); 164 | } 165 | } 166 | 167 | nodes[nodeIndex].childAabbsMin[0] = minLeftBox.m_min; 168 | nodes[nodeIndex].childAabbsMax[0] = minLeftBox.m_max; 169 | nodes[nodeIndex].childAabbsMin[1] = minRightBox.m_min; 170 | nodes[nodeIndex].childAabbsMax[1] = minRightBox.m_max; 171 | nodes[nodeIndex].childIndices[2] = hiprtInvalidValue; 172 | nodes[nodeIndex].childIndices[3] = hiprtInvalidValue; 173 | 174 | if ( minIndex - begin == 1 ) 175 | { 176 | nodes[nodeIndex].childIndices[0] = indices[minAxis][begin]; 177 | nodes[nodeIndex].childNodeTypes[0] = hiprtBvhNodeTypeLeaf; 178 | } 179 | else 180 | { 181 | nodes[nodeIndex].childIndices[0] = static_cast( nodes.size() ); 182 | nodes[nodeIndex].childNodeTypes[0] = hiprtBvhNodeTypeInternal; 183 | queue.push( QueueEntry( nodes[nodeIndex].childIndices[0], begin, minIndex, minLeftBox ) ); 184 | nodes.push_back( hiprtBvhNode() ); 185 | } 186 | 187 | if ( end - minIndex == 1 ) 188 | { 189 | nodes[nodeIndex].childIndices[1] = indices[minAxis][minIndex]; 190 | nodes[nodeIndex].childNodeTypes[1] = hiprtBvhNodeTypeLeaf; 191 | } 192 | else 193 | { 194 | nodes[nodeIndex].childIndices[1] = static_cast( nodes.size() ); 195 | nodes[nodeIndex].childNodeTypes[1] = hiprtBvhNodeTypeInternal; 196 | queue.push( QueueEntry( nodes[nodeIndex].childIndices[1], minIndex, end, minRightBox ) ); 197 | nodes.push_back( hiprtBvhNode() ); 198 | } 199 | } 200 | } 201 | ``` 202 | 203 | 204 | 205 | -------------------------------------------------------------------------------- /tutorials/common/TutorialBase.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2021-2023 Advanced Micro Devices, Inc. All rights reserved. 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE. 21 | // 22 | 23 | #include 24 | 25 | #include 26 | 27 | #define STB_IMAGE_WRITE_IMPLEMENTATION 28 | #include 29 | 30 | void checkOro( oroError res, const char* file, uint32_t line ) 31 | { 32 | if ( res != oroSuccess ) 33 | { 34 | const char* msg; 35 | oroGetErrorString( res, &msg ); 36 | std::cerr << "Orochi error: '" << msg << "' on line " << line << " " 37 | << " in '" << file << "'." << std::endl; 38 | exit( EXIT_FAILURE ); 39 | } 40 | } 41 | 42 | void checkOrortc( orortcResult res, const char* file, uint32_t line ) 43 | { 44 | if ( res != ORORTC_SUCCESS ) 45 | { 46 | std::cerr << "ORORTC error: '" << orortcGetErrorString( res ) << "' [ " << res << " ] on line " << line << " " 47 | << " in '" << file << "'." << std::endl; 48 | exit( EXIT_FAILURE ); 49 | } 50 | } 51 | 52 | void checkHiprt( hiprtError res, const char* file, uint32_t line ) 53 | { 54 | if ( res != hiprtSuccess ) 55 | { 56 | std::cerr << "HIPRT error: '" << res << "' on line " << line << " " 57 | << " in '" << file << "'." << std::endl; 58 | exit( EXIT_FAILURE ); 59 | } 60 | } 61 | 62 | void TutorialBase::init( uint32_t deviceIndex ) 63 | { 64 | m_res = { 512, 512 }; 65 | 66 | CHECK_ORO( 67 | static_cast( oroInitialize( (oroApi)( ORO_API_HIP | ORO_API_CUDA ), 0, g_hip_paths, g_hiprtc_paths ) ) ); 68 | 69 | CHECK_ORO( oroInit( 0 ) ); 70 | CHECK_ORO( oroDeviceGet( &m_oroDevice, deviceIndex ) ); 71 | CHECK_ORO( oroCtxCreate( &m_oroCtx, 0, m_oroDevice ) ); 72 | 73 | oroDeviceProp props; 74 | CHECK_ORO( oroGetDeviceProperties( &props, m_oroDevice ) ); 75 | 76 | std::cout << "hiprt ver." << HIPRT_VERSION_STR << std::endl; 77 | std::cout << "Executing on '" << props.name << "'" << std::endl; 78 | if ( std::string( props.name ).find( "NVIDIA" ) != std::string::npos ) 79 | m_ctxtInput.deviceType = hiprtDeviceNVIDIA; 80 | else 81 | m_ctxtInput.deviceType = hiprtDeviceAMD; 82 | 83 | m_ctxtInput.ctxt = oroGetRawCtx( m_oroCtx ); 84 | m_ctxtInput.device = oroGetRawDevice( m_oroDevice ); 85 | } 86 | 87 | bool TutorialBase::readSourceCode( 88 | const std::filesystem::path& path, std::string& sourceCode, std::optional> includes ) 89 | { 90 | std::fstream f( path ); 91 | if ( f.is_open() ) 92 | { 93 | size_t sizeFile; 94 | f.seekg( 0, std::fstream::end ); 95 | size_t size = sizeFile = static_cast( f.tellg() ); 96 | f.seekg( 0, std::fstream::beg ); 97 | if ( includes ) 98 | { 99 | sourceCode.clear(); 100 | std::string line; 101 | while ( std::getline( f, line ) ) 102 | { 103 | if ( line.find( "#include" ) != std::string::npos ) 104 | { 105 | size_t pa = line.find( "<" ); 106 | size_t pb = line.find( ">" ); 107 | std::string buf = line.substr( pa + 1, pb - pa - 1 ); 108 | includes.value().push_back( buf ); 109 | sourceCode += line + '\n'; 110 | } 111 | sourceCode += line + '\n'; 112 | } 113 | } 114 | else 115 | { 116 | sourceCode.resize( size, ' ' ); 117 | f.read( &sourceCode[0], size ); 118 | } 119 | f.close(); 120 | } 121 | else 122 | return false; 123 | return true; 124 | } 125 | 126 | void TutorialBase::buildTraceKernelFromBitcode( 127 | hiprtContext ctxt, 128 | const char* path, 129 | const char* functionName, 130 | oroFunction& functionOut, 131 | std::vector* opts, 132 | std::vector* funcNameSets, 133 | uint32_t numGeomTypes, 134 | uint32_t numRayTypes ) 135 | { 136 | std::vector options; 137 | std::vector includeNamesData; 138 | std::string sourceCode; 139 | 140 | if ( !readSourceCode( path, sourceCode, includeNamesData ) ) 141 | { 142 | std::cerr << "Unable to find file '" << path << "'" << std::endl; 143 | ; 144 | exit( EXIT_FAILURE ); 145 | } 146 | 147 | std::vector headersData( includeNamesData.size() ); 148 | std::vector headers; 149 | std::vector includeNames; 150 | for ( int i = 0; i < includeNamesData.size(); i++ ) 151 | { 152 | if ( !readSourceCode( std::string( "../../" ) / includeNamesData[i], headersData[i] ) ) 153 | { 154 | if ( !readSourceCode( std::string( "../" ) / includeNamesData[i], headersData[i] ) ) 155 | { 156 | std::cerr << "Failed to find header file '" << includeNamesData[i] << "' in path ../ or ../../!" << std::endl; 157 | exit( EXIT_FAILURE ); 158 | } 159 | } 160 | includeNames.push_back( includeNamesData[i].string().c_str() ); 161 | headers.push_back( headersData[i].c_str() ); 162 | } 163 | 164 | if ( opts ) 165 | { 166 | for ( const auto o : *opts ) 167 | options.push_back( o ); 168 | } 169 | 170 | const bool isAmd = oroGetCurAPI( 0 ) == ORO_API_HIP; 171 | if ( isAmd ) 172 | { 173 | options.push_back( "-fgpu-rdc" ); 174 | options.push_back( "-Xclang" ); 175 | options.push_back( "-disable-llvm-passes" ); 176 | options.push_back( "-Xclang" ); 177 | options.push_back( "-mno-constructor-aliases" ); 178 | } 179 | else 180 | { 181 | options.push_back( "--device-c" ); 182 | options.push_back( "-arch=compute_60" ); 183 | } 184 | options.push_back( "-std=c++17" ); 185 | options.push_back( "-I../" ); 186 | options.push_back( "-I../../" ); 187 | 188 | orortcProgram prog; 189 | CHECK_ORORTC( orortcCreateProgram( 190 | &prog, sourceCode.data(), path, static_cast( headers.size() ), headers.data(), includeNames.data() ) ); 191 | CHECK_ORORTC( orortcAddNameExpression( prog, functionName ) ); 192 | 193 | orortcResult e = orortcCompileProgram( prog, static_cast( options.size() ), options.data() ); 194 | if ( e != ORORTC_SUCCESS ) 195 | { 196 | size_t logSize; 197 | CHECK_ORORTC( orortcGetProgramLogSize( prog, &logSize ) ); 198 | 199 | if ( logSize ) 200 | { 201 | std::string log( logSize, '\0' ); 202 | orortcGetProgramLog( prog, &log[0] ); 203 | std::cerr << log << std::endl; 204 | } 205 | exit( EXIT_FAILURE ); 206 | } 207 | 208 | std::string bitCodeBinary; 209 | size_t size = 0; 210 | if ( isAmd ) 211 | CHECK_ORORTC( orortcGetBitcodeSize( prog, &size ) ); 212 | else 213 | CHECK_ORORTC( orortcGetCodeSize( prog, &size ) ); 214 | assert( size != 0 ); 215 | 216 | bitCodeBinary.resize( size ); 217 | if ( isAmd ) 218 | CHECK_ORORTC( orortcGetBitcode( prog, (char*)bitCodeBinary.data() ) ); 219 | else 220 | CHECK_ORORTC( orortcGetCode( prog, (char*)bitCodeBinary.data() ) ); 221 | 222 | hiprtApiFunction function; 223 | CHECK_HIPRT( hiprtBuildTraceKernelsFromBitcode( 224 | ctxt, 225 | 1, 226 | &functionName, 227 | path, 228 | bitCodeBinary.data(), 229 | size, 230 | numGeomTypes, 231 | numRayTypes, 232 | funcNameSets != nullptr ? funcNameSets->data() : nullptr, 233 | &function, 234 | false ) ); 235 | 236 | functionOut = *reinterpret_cast( &function ); 237 | } 238 | 239 | void TutorialBase::launchKernel( oroFunction func, uint32_t nx, uint32_t ny, void** args ) 240 | { 241 | launchKernel( func, nx, ny, 8, 8, args ); 242 | } 243 | 244 | void TutorialBase::launchKernel( oroFunction func, uint32_t nx, uint32_t ny, uint32_t bx, uint32_t by, void** args ) 245 | { 246 | hiprtInt3 nb; 247 | nb.x = ( nx + bx - 1 ) / bx; 248 | nb.y = ( ny + by - 1 ) / by; 249 | CHECK_ORO( oroModuleLaunchKernel( func, nb.x, nb.y, 1, bx, by, 1, 0, 0, args, 0 ) ); 250 | } 251 | 252 | void TutorialBase::writeImage( const std::string& path, uint32_t width, uint32_t height, uint8_t* pixels ) 253 | { 254 | std::vector image( width * height * 4 ); 255 | CHECK_ORO( oroMemcpyDtoH( image.data(), reinterpret_cast( pixels ), width * height * 4 ) ); 256 | stbi_write_png( path.c_str(), width, height, 4, image.data(), width * 4 ); 257 | std::cout << "image written at " << path.c_str() << std::endl; 258 | } 259 | -------------------------------------------------------------------------------- /tutorials/14_batch_build/main.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2021-2023 Advanced Micro Devices, Inc. All rights reserved. 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE. 21 | // 22 | 23 | #include 24 | #include 25 | 26 | class Tutorial : public TutorialBase 27 | { 28 | public: 29 | void run() 30 | { 31 | constexpr uint32_t CircleCount = 3u; 32 | hiprtFloat4 circles[] = { { 0.25f, 0.5f, 0.0f, 0.1f }, { 0.5f, 0.5f, 0.0f, 0.1f }, { 0.75f, 0.5f, 0.0f, 0.1f } }; 33 | 34 | hiprtContext ctxt; 35 | CHECK_HIPRT( hiprtCreateContext( HIPRT_API_VERSION, m_ctxtInput, ctxt ) ); 36 | 37 | hiprtGeometryBuildInput geomBuildInputs[2]; 38 | hiprtGeometry geoms[2]; 39 | 40 | hiprtAABBListPrimitive list; 41 | { 42 | list.aabbCount = CircleCount; 43 | list.aabbStride = 2 * sizeof( hiprtFloat4 ); 44 | hiprtFloat4 aabbs[2 * CircleCount]; 45 | for ( int i = 0; i < CircleCount; i++ ) 46 | { 47 | const hiprtFloat4& c = circles[i]; 48 | aabbs[i * 2 + 0] = { c.x - c.w, c.y - c.w, c.z, 0.0f }; 49 | aabbs[i * 2 + 1] = { c.x + c.w, c.y + c.w, c.z, 0.0f }; 50 | } 51 | CHECK_ORO( 52 | oroMalloc( reinterpret_cast( &list.aabbs ), 2 * list.aabbCount * sizeof( hiprtFloat4 ) ) ); 53 | CHECK_ORO( oroMemcpyHtoD( 54 | reinterpret_cast( list.aabbs ), aabbs, 2 * list.aabbCount * sizeof( hiprtFloat4 ) ) ); 55 | 56 | geomBuildInputs[0].type = hiprtPrimitiveTypeAABBList; 57 | geomBuildInputs[0].primitive.aabbList = list; 58 | geomBuildInputs[0].geomType = 0; 59 | } 60 | 61 | hiprtTriangleMeshPrimitive mesh; 62 | { 63 | mesh.triangleCount = 3; 64 | mesh.triangleStride = sizeof( hiprtInt3 ); 65 | std::vector triangleIndices( 3 * mesh.triangleCount ); 66 | std::iota( triangleIndices.begin(), triangleIndices.end(), 0 ); 67 | CHECK_ORO( oroMalloc( 68 | reinterpret_cast( &mesh.triangleIndices ), mesh.triangleCount * sizeof( hiprtInt3 ) ) ); 69 | CHECK_ORO( oroMemcpyHtoD( 70 | reinterpret_cast( mesh.triangleIndices ), 71 | triangleIndices.data(), 72 | mesh.triangleCount * sizeof( hiprtInt3 ) ) ); 73 | 74 | mesh.vertexCount = 9; 75 | mesh.vertexStride = sizeof( hiprtFloat3 ); 76 | hiprtFloat3 vertices[] = { 77 | { 0.15f, 0.40f, 0.0f }, 78 | { 0.35f, 0.40f, 0.0f }, 79 | { 0.25f, 0.60f, 0.0f }, 80 | { 0.40f, 0.40f, 0.0f }, 81 | { 0.60f, 0.40f, 0.0f }, 82 | { 0.50f, 0.60f, 0.0f }, 83 | { 0.65f, 0.40f, 0.0f }, 84 | { 0.85f, 0.40f, 0.0f }, 85 | { 0.75f, 0.60f, 0.0f } }; 86 | CHECK_ORO( 87 | oroMalloc( reinterpret_cast( &mesh.vertices ), mesh.vertexCount * sizeof( hiprtFloat3 ) ) ); 88 | CHECK_ORO( oroMemcpyHtoD( 89 | reinterpret_cast( mesh.vertices ), vertices, mesh.vertexCount * sizeof( hiprtFloat3 ) ) ); 90 | 91 | geomBuildInputs[1].type = hiprtPrimitiveTypeTriangleMesh; 92 | geomBuildInputs[1].primitive.triangleMesh = mesh; 93 | } 94 | 95 | { 96 | hiprtBuildOptions options; 97 | options.buildFlags = hiprtBuildFlagBitPreferFastBuild; 98 | options.batchBuildMaxPrimCount = 16u; // this enables batch construction 99 | 100 | size_t geomTempSize; 101 | hiprtDevicePtr geomTemp; 102 | CHECK_HIPRT( hiprtGetGeometriesBuildTemporaryBufferSize( ctxt, 2, geomBuildInputs, options, geomTempSize ) ); 103 | CHECK_ORO( oroMalloc( reinterpret_cast( &geomTemp ), geomTempSize ) ); 104 | 105 | hiprtGeometry* geomAddrs[] = { &geoms[0], &geoms[1] }; 106 | CHECK_HIPRT( hiprtCreateGeometries( ctxt, 2, geomBuildInputs, options, geomAddrs ) ); 107 | CHECK_HIPRT( 108 | hiprtBuildGeometries( ctxt, hiprtBuildOperationBuild, 2, geomBuildInputs, options, geomTemp, 0, geoms ) ); 109 | CHECK_ORO( oroFree( reinterpret_cast( geomTemp ) ) ); 110 | } 111 | 112 | hiprtScene scene; 113 | hiprtSceneBuildInput sceneInput; 114 | { 115 | hiprtInstance instance0; 116 | instance0.type = hiprtInstanceTypeGeometry; 117 | instance0.geometry = geoms[0]; 118 | 119 | hiprtInstance instance1; 120 | instance1.type = hiprtInstanceTypeGeometry; 121 | instance1.geometry = geoms[1]; 122 | 123 | hiprtInstance instances[] = { instance0, instance1 }; 124 | 125 | sceneInput.instanceCount = 2; 126 | sceneInput.instanceMasks = nullptr; 127 | sceneInput.instanceTransformHeaders = nullptr; 128 | CHECK_ORO( oroMalloc( 129 | reinterpret_cast( &sceneInput.instances ), 130 | sceneInput.instanceCount * sizeof( hiprtInstance ) ) ); 131 | CHECK_ORO( oroMemcpyHtoD( 132 | reinterpret_cast( sceneInput.instances ), 133 | instances, 134 | sceneInput.instanceCount * sizeof( hiprtInstance ) ) ); 135 | 136 | const float o = 0.05f; 137 | hiprtFrameSRT frames[2]; 138 | frames[0].translation = { 0.0f, o, 0.0f }; 139 | frames[0].scale = { 1.0f, 1.0f, 1.0f }; 140 | frames[0].rotation = { 0.0f, 0.0f, 1.0f, 0.0f }; 141 | frames[1].translation = { 0.0f, -o, 0.0f }; 142 | frames[1].scale = { 1.0f, 1.0f, 1.0f }; 143 | frames[1].rotation = { 0.0f, 0.0f, 1.0f, 0.0f }; 144 | 145 | sceneInput.frameCount = 2; 146 | CHECK_ORO( oroMalloc( 147 | reinterpret_cast( &sceneInput.instanceFrames ), 148 | sceneInput.frameCount * sizeof( hiprtFrameSRT ) ) ); 149 | CHECK_ORO( oroMemcpyHtoD( 150 | reinterpret_cast( sceneInput.instanceFrames ), 151 | frames, 152 | sceneInput.frameCount * sizeof( hiprtFrameSRT ) ) ); 153 | 154 | size_t sceneTempSize; 155 | hiprtDevicePtr sceneTemp; 156 | hiprtBuildOptions options; 157 | options.buildFlags = hiprtBuildFlagBitPreferFastBuild; 158 | CHECK_HIPRT( hiprtGetSceneBuildTemporaryBufferSize( ctxt, sceneInput, options, sceneTempSize ) ); 159 | CHECK_ORO( oroMalloc( reinterpret_cast( &sceneTemp ), sceneTempSize ) ); 160 | 161 | CHECK_HIPRT( hiprtCreateScene( ctxt, sceneInput, options, scene ) ); 162 | CHECK_HIPRT( hiprtBuildScene( ctxt, hiprtBuildOperationBuild, sceneInput, options, sceneTemp, 0, scene ) ); 163 | CHECK_ORO( oroFree( reinterpret_cast( sceneTemp ) ) ); 164 | } 165 | 166 | hiprtFuncNameSet funcNameSet; 167 | funcNameSet.intersectFuncName = "intersectCircle"; 168 | std::vector funcNameSets = { funcNameSet }; 169 | 170 | oroFunction func; 171 | buildTraceKernelFromBitcode( 172 | ctxt, "../common/TutorialKernels.h", "SceneBuildKernel", func, nullptr, &funcNameSets, 1, 1 ); 173 | 174 | hiprtFuncDataSet funcDataSet; 175 | CHECK_ORO( oroMalloc( const_cast( &funcDataSet.intersectFuncData ), CircleCount * sizeof( hiprtFloat4 ) ) ); 176 | CHECK_ORO( oroMemcpyHtoD( 177 | const_cast( funcDataSet.intersectFuncData ), circles, CircleCount * sizeof( hiprtFloat4 ) ) ); 178 | 179 | hiprtFuncTable funcTable; 180 | CHECK_HIPRT( hiprtCreateFuncTable( ctxt, 1, 1, funcTable ) ); 181 | CHECK_HIPRT( hiprtSetFuncTable( ctxt, funcTable, 0, 0, funcDataSet ) ); 182 | 183 | uint8_t* pixels; 184 | CHECK_ORO( oroMalloc( reinterpret_cast( &pixels ), m_res.x * m_res.y * 4 ) ); 185 | CHECK_ORO( oroMemset( reinterpret_cast( pixels ), 0, m_res.x * m_res.y * 4 ) ); 186 | 187 | void* args[] = { &scene, &pixels, &funcTable, &m_res }; 188 | launchKernel( func, m_res.x, m_res.y, args ); 189 | writeImage( "14_batch_build.png", m_res.x, m_res.y, pixels ); 190 | 191 | CHECK_ORO( oroFree( const_cast( funcDataSet.intersectFuncData ) ) ); 192 | CHECK_ORO( oroFree( reinterpret_cast( sceneInput.instances ) ) ); 193 | CHECK_ORO( oroFree( reinterpret_cast( sceneInput.instanceFrames ) ) ); 194 | CHECK_ORO( oroFree( reinterpret_cast( mesh.triangleIndices ) ) ); 195 | CHECK_ORO( oroFree( reinterpret_cast( mesh.vertices ) ) ); 196 | CHECK_ORO( oroFree( reinterpret_cast( list.aabbs ) ) ); 197 | CHECK_ORO( oroFree( reinterpret_cast( pixels ) ) ); 198 | 199 | CHECK_HIPRT( hiprtDestroyFuncTable( ctxt, funcTable ) ); 200 | CHECK_HIPRT( hiprtDestroyGeometries( ctxt, 2, geoms ) ); 201 | CHECK_HIPRT( hiprtDestroyScene( ctxt, scene ) ); 202 | CHECK_HIPRT( hiprtDestroyContext( ctxt ) ); 203 | } 204 | }; 205 | 206 | int main( int argc, char** argv ) 207 | { 208 | Tutorial tutorial; 209 | tutorial.init( 0 ); 210 | tutorial.run(); 211 | 212 | return 0; 213 | } 214 | -------------------------------------------------------------------------------- /tutorials/07_custom_bvh_import/main.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2021-2023 Advanced Micro Devices, Inc. All rights reserved. 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE. 21 | // 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | class Tutorial : public TutorialBase 29 | { 30 | public: 31 | void buildBvh( hiprtGeometryBuildInput& buildInput ); 32 | void run() 33 | { 34 | hiprtContext ctxt; 35 | CHECK_HIPRT( hiprtCreateContext( HIPRT_API_VERSION, m_ctxtInput, ctxt ) ); 36 | 37 | hiprtTriangleMeshPrimitive mesh; 38 | mesh.triangleCount = CornellBoxTriangleCount; 39 | mesh.triangleStride = sizeof( hiprtInt3 ); 40 | std::array triangleIndices; 41 | std::iota( triangleIndices.begin(), triangleIndices.end(), 0 ); 42 | CHECK_ORO( 43 | oroMalloc( reinterpret_cast( &mesh.triangleIndices ), mesh.triangleCount * sizeof( hiprtInt3 ) ) ); 44 | CHECK_ORO( oroMemcpyHtoD( 45 | reinterpret_cast( mesh.triangleIndices ), 46 | triangleIndices.data(), 47 | mesh.triangleCount * sizeof( hiprtInt3 ) ) ); 48 | 49 | mesh.vertexCount = 3 * mesh.triangleCount; 50 | mesh.vertexStride = sizeof( hiprtFloat3 ); 51 | CHECK_ORO( oroMalloc( reinterpret_cast( &mesh.vertices ), mesh.vertexCount * sizeof( hiprtFloat3 ) ) ); 52 | CHECK_ORO( oroMemcpyHtoD( 53 | reinterpret_cast( mesh.vertices ), 54 | const_cast( cornellBoxVertices.data() ), 55 | mesh.vertexCount * sizeof( hiprtFloat3 ) ) ); 56 | 57 | hiprtGeometryBuildInput geomInput; 58 | geomInput.type = hiprtPrimitiveTypeTriangleMesh; 59 | geomInput.primitive.triangleMesh = mesh; 60 | buildBvh( geomInput ); 61 | 62 | size_t geomTempSize; 63 | hiprtDevicePtr geomTemp; 64 | hiprtBuildOptions options; 65 | options.buildFlags = hiprtBuildFlagBitCustomBvhImport; 66 | CHECK_HIPRT( hiprtGetGeometryBuildTemporaryBufferSize( ctxt, geomInput, options, geomTempSize ) ); 67 | CHECK_ORO( oroMalloc( reinterpret_cast( &geomTemp ), geomTempSize ) ); 68 | 69 | hiprtGeometry geom; 70 | CHECK_HIPRT( hiprtCreateGeometry( ctxt, geomInput, options, geom ) ); 71 | CHECK_HIPRT( hiprtBuildGeometry( ctxt, hiprtBuildOperationBuild, geomInput, options, geomTemp, 0, geom ) ); 72 | 73 | oroFunction func; 74 | buildTraceKernelFromBitcode( ctxt, "../common/TutorialKernels.h", "CustomBvhImportKernel", func ); 75 | 76 | uint8_t* pixels; 77 | CHECK_ORO( oroMalloc( reinterpret_cast( &pixels ), m_res.x * m_res.y * 4 ) ); 78 | 79 | uint32_t* matIndices; 80 | CHECK_ORO( oroMalloc( reinterpret_cast( &matIndices ), mesh.triangleCount * sizeof( uint32_t ) ) ); 81 | CHECK_ORO( oroMemcpyHtoD( 82 | reinterpret_cast( matIndices ), 83 | cornellBoxMatIndices.data(), 84 | mesh.triangleCount * sizeof( uint32_t ) ) ); 85 | 86 | hiprtFloat3* diffusColors; 87 | CHECK_ORO( 88 | oroMalloc( reinterpret_cast( &diffusColors ), CornellBoxMaterialCount * sizeof( hiprtFloat3 ) ) ); 89 | CHECK_ORO( oroMemcpyHtoD( 90 | reinterpret_cast( diffusColors ), 91 | const_cast( cornellBoxDiffuseColors.data() ), 92 | CornellBoxMaterialCount * sizeof( hiprtFloat3 ) ) ); 93 | 94 | void* args[] = { &geom, &pixels, &m_res, &matIndices, &diffusColors }; 95 | launchKernel( func, m_res.x, m_res.y, args ); 96 | writeImage( "07_custom_bvh_import.png", m_res.x, m_res.y, pixels ); 97 | 98 | CHECK_ORO( oroFree( reinterpret_cast( matIndices ) ) ); 99 | CHECK_ORO( oroFree( reinterpret_cast( diffusColors ) ) ); 100 | CHECK_ORO( oroFree( reinterpret_cast( mesh.triangleIndices ) ) ); 101 | CHECK_ORO( oroFree( reinterpret_cast( mesh.vertices ) ) ); 102 | CHECK_ORO( oroFree( reinterpret_cast( pixels ) ) ); 103 | CHECK_ORO( oroFree( reinterpret_cast( geomInput.nodeList.leafNodes ) ) ); 104 | CHECK_ORO( oroFree( reinterpret_cast( geomInput.nodeList.internalNodes ) ) ); 105 | 106 | CHECK_HIPRT( hiprtDestroyGeometry( ctxt, geom ) ); 107 | CHECK_HIPRT( hiprtDestroyContext( ctxt ) ); 108 | } 109 | }; 110 | 111 | void Tutorial::buildBvh( hiprtGeometryBuildInput& buildInput ) 112 | { 113 | std::vector internalNodes; 114 | std::vector primBoxes; 115 | if ( buildInput.type == hiprtPrimitiveTypeTriangleMesh ) 116 | { 117 | primBoxes.resize( buildInput.primitive.triangleMesh.triangleCount ); 118 | std::vector verticesRaw( 119 | buildInput.primitive.triangleMesh.vertexCount * buildInput.primitive.triangleMesh.vertexStride ); 120 | std::vector trianglesRaw( 121 | buildInput.primitive.triangleMesh.triangleCount * buildInput.primitive.triangleMesh.triangleStride ); 122 | CHECK_ORO( oroMemcpyDtoH( 123 | verticesRaw.data(), 124 | reinterpret_cast( buildInput.primitive.triangleMesh.vertices ), 125 | buildInput.primitive.triangleMesh.vertexCount * buildInput.primitive.triangleMesh.vertexStride ) ); 126 | CHECK_ORO( oroMemcpyDtoH( 127 | trianglesRaw.data(), 128 | reinterpret_cast( buildInput.primitive.triangleMesh.triangleIndices ), 129 | buildInput.primitive.triangleMesh.triangleCount * buildInput.primitive.triangleMesh.triangleStride ) ); 130 | for ( uint32_t i = 0; i < buildInput.primitive.triangleMesh.triangleCount; ++i ) 131 | { 132 | hiprtInt3 triangle = 133 | *reinterpret_cast( trianglesRaw.data() + i * buildInput.primitive.triangleMesh.triangleStride ); 134 | hiprtFloat3 v0 = *reinterpret_cast( 135 | verticesRaw.data() + triangle.x * buildInput.primitive.triangleMesh.vertexStride ); 136 | hiprtFloat3 v1 = *reinterpret_cast( 137 | verticesRaw.data() + triangle.y * buildInput.primitive.triangleMesh.vertexStride ); 138 | hiprtFloat3 v2 = *reinterpret_cast( 139 | verticesRaw.data() + triangle.z * buildInput.primitive.triangleMesh.vertexStride ); 140 | primBoxes[i].reset(); 141 | primBoxes[i].grow( v0 ); 142 | primBoxes[i].grow( v1 ); 143 | primBoxes[i].grow( v2 ); 144 | } 145 | BvhBuilder::build( buildInput.primitive.triangleMesh.triangleCount, primBoxes, internalNodes ); 146 | } 147 | else if ( buildInput.type == hiprtPrimitiveTypeAABBList ) 148 | { 149 | primBoxes.resize( buildInput.primitive.aabbList.aabbCount ); 150 | std::vector primBoxesRaw( buildInput.primitive.aabbList.aabbCount * buildInput.primitive.aabbList.aabbStride ); 151 | CHECK_ORO( oroMemcpyDtoH( 152 | primBoxesRaw.data(), 153 | reinterpret_cast( buildInput.primitive.aabbList.aabbs ), 154 | buildInput.primitive.aabbList.aabbCount * buildInput.primitive.aabbList.aabbStride ) ); 155 | for ( uint32_t i = 0; i < buildInput.primitive.aabbList.aabbCount; ++i ) 156 | { 157 | hiprtFloat4* ptr = 158 | reinterpret_cast( primBoxesRaw.data() + i * buildInput.primitive.aabbList.aabbStride ); 159 | primBoxes[i].m_min = make_float3( ptr[0] ); 160 | primBoxes[i].m_max = make_float3( ptr[1] ); 161 | } 162 | BvhBuilder::build( buildInput.primitive.aabbList.aabbCount, primBoxes, internalNodes ); 163 | } 164 | 165 | std::vector leafNodes( primBoxes.size() ); 166 | for ( uint32_t i = 0; i < primBoxes.size(); ++i ) 167 | { 168 | leafNodes[i].primID = i; 169 | leafNodes[i].aabbMin = primBoxes[i].m_min; 170 | leafNodes[i].aabbMax = primBoxes[i].m_max; 171 | } 172 | 173 | buildInput.nodeList.nodeCount = static_cast( leafNodes.size() ); 174 | 175 | CHECK_ORO( oroMalloc( 176 | reinterpret_cast( &buildInput.nodeList.leafNodes ), leafNodes.size() * sizeof( hiprtLeafNode ) ) ); 177 | CHECK_ORO( oroMemcpyHtoD( 178 | reinterpret_cast( buildInput.nodeList.leafNodes ), 179 | leafNodes.data(), 180 | leafNodes.size() * sizeof( hiprtLeafNode ) ) ); 181 | CHECK_ORO( oroMalloc( 182 | reinterpret_cast( &buildInput.nodeList.internalNodes ), 183 | internalNodes.size() * sizeof( hiprtInternalNode ) ) ); 184 | CHECK_ORO( oroMemcpyHtoD( 185 | reinterpret_cast( buildInput.nodeList.internalNodes ), 186 | internalNodes.data(), 187 | internalNodes.size() * sizeof( hiprtInternalNode ) ) ); 188 | } 189 | 190 | int main( int argc, char** argv ) 191 | { 192 | Tutorial tutorial; 193 | tutorial.init( 0 ); 194 | tutorial.run(); 195 | 196 | return 0; 197 | } 198 | -------------------------------------------------------------------------------- /tutorials/11_multi_custom_intersection/main.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2021-2023 Advanced Micro Devices, Inc. All rights reserved. 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE. 21 | // 22 | 23 | #include 24 | 25 | class Tutorial : public TutorialBase 26 | { 27 | public: 28 | void run() 29 | { 30 | constexpr uint32_t SphereTypeIndex = 0; 31 | constexpr uint32_t CircleTypeIndex = 1; 32 | constexpr uint32_t GeomTypesCount = 2; 33 | 34 | hiprtFloat4 sphere = { -0.3f, 0.0f, 0.0f, 0.2f }; 35 | hiprtFloat4 circle = { 0.3f, 0.0f, 0.0f, 0.2f }; 36 | 37 | hiprtContext ctxt; 38 | CHECK_HIPRT( hiprtCreateContext( HIPRT_API_VERSION, m_ctxtInput, ctxt ) ); 39 | 40 | hiprtGeometry geomSpheres; 41 | hiprtAABBListPrimitive listSpheres; 42 | { 43 | listSpheres.aabbCount = 1; 44 | listSpheres.aabbStride = 2 * sizeof( hiprtFloat4 ); 45 | hiprtFloat4 aabb[] = { 46 | { sphere.x - sphere.w, sphere.y - sphere.w, sphere.z - sphere.w, 0.0f }, 47 | { sphere.x + sphere.w, sphere.y + sphere.w, sphere.z + sphere.w, 0.0f } }; 48 | CHECK_ORO( oroMalloc( reinterpret_cast( &listSpheres.aabbs ), 2 * sizeof( hiprtFloat4 ) ) ); 49 | CHECK_ORO( oroMemcpyHtoD( reinterpret_cast( listSpheres.aabbs ), aabb, 2 * sizeof( hiprtFloat4 ) ) ); 50 | 51 | hiprtGeometryBuildInput geomInput; 52 | geomInput.type = hiprtPrimitiveTypeAABBList; 53 | geomInput.primitive.aabbList = listSpheres; 54 | geomInput.geomType = SphereTypeIndex; 55 | 56 | size_t geomTempSize; 57 | hiprtDevicePtr geomTemp; 58 | hiprtBuildOptions options; 59 | options.buildFlags = hiprtBuildFlagBitPreferFastBuild; 60 | CHECK_HIPRT( hiprtGetGeometryBuildTemporaryBufferSize( ctxt, geomInput, options, geomTempSize ) ); 61 | CHECK_ORO( oroMalloc( reinterpret_cast( &geomTemp ), geomTempSize ) ); 62 | 63 | CHECK_HIPRT( hiprtCreateGeometry( ctxt, geomInput, options, geomSpheres ) ); 64 | CHECK_HIPRT( hiprtBuildGeometry( ctxt, hiprtBuildOperationBuild, geomInput, options, geomTemp, 0, geomSpheres ) ); 65 | CHECK_ORO( oroFree( reinterpret_cast( geomTemp ) ) ); 66 | } 67 | 68 | hiprtGeometry geomCircles; 69 | hiprtAABBListPrimitive listCircles; 70 | { 71 | listCircles.aabbCount = 1; 72 | listCircles.aabbStride = 2 * sizeof( hiprtFloat4 ); 73 | hiprtFloat4 aabb[] = { 74 | { circle.x - circle.w, circle.y - circle.w, circle.z - circle.w, 0.0f }, 75 | { circle.x + circle.w, circle.y + circle.w, circle.z + circle.w, 0.0f } }; 76 | CHECK_ORO( oroMalloc( reinterpret_cast( &listCircles.aabbs ), 2 * sizeof( hiprtFloat4 ) ) ); 77 | CHECK_ORO( oroMemcpyHtoD( reinterpret_cast( listCircles.aabbs ), aabb, 2 * sizeof( hiprtFloat4 ) ) ); 78 | 79 | hiprtGeometryBuildInput geomInput; 80 | geomInput.type = hiprtPrimitiveTypeAABBList; 81 | geomInput.primitive.aabbList = listCircles; 82 | geomInput.geomType = CircleTypeIndex; 83 | 84 | size_t geomTempSize; 85 | hiprtDevicePtr geomTemp; 86 | hiprtBuildOptions options; 87 | options.buildFlags = hiprtBuildFlagBitPreferFastBuild; 88 | CHECK_HIPRT( hiprtGetGeometryBuildTemporaryBufferSize( ctxt, geomInput, options, geomTempSize ) ); 89 | CHECK_ORO( oroMalloc( reinterpret_cast( &geomTemp ), geomTempSize ) ); 90 | 91 | CHECK_HIPRT( hiprtCreateGeometry( ctxt, geomInput, options, geomCircles ) ); 92 | CHECK_HIPRT( hiprtBuildGeometry( ctxt, hiprtBuildOperationBuild, geomInput, options, geomTemp, 0, geomCircles ) ); 93 | CHECK_ORO( oroFree( reinterpret_cast( geomTemp ) ) ); 94 | } 95 | 96 | hiprtScene scene; 97 | hiprtSceneBuildInput sceneInput; 98 | { 99 | hiprtInstance instSpheres; 100 | instSpheres.type = hiprtInstanceTypeGeometry; 101 | instSpheres.geometry = geomSpheres; 102 | 103 | hiprtInstance instCircles; 104 | instCircles.type = hiprtInstanceTypeGeometry; 105 | instCircles.geometry = geomCircles; 106 | 107 | hiprtInstance instances[] = { instSpheres, instCircles }; 108 | 109 | sceneInput.instanceCount = GeomTypesCount; 110 | sceneInput.instanceMasks = nullptr; 111 | sceneInput.instanceTransformHeaders = nullptr; 112 | sceneInput.frameCount = sceneInput.instanceCount; 113 | CHECK_ORO( oroMalloc( 114 | reinterpret_cast( &sceneInput.instances ), 115 | sceneInput.instanceCount * sizeof( hiprtInstance ) ) ); 116 | CHECK_ORO( oroMemcpyHtoD( 117 | reinterpret_cast( sceneInput.instances ), 118 | instances, 119 | sceneInput.instanceCount * sizeof( hiprtInstance ) ) ); 120 | 121 | std::vector frames; 122 | hiprtFrameSRT frame; 123 | frame.translation = { 0.0f, 0.0f, 0.0f }; 124 | frame.scale = { 1.0f, 1.0f, 1.0f }; 125 | frame.rotation = { 0.0f, 0.0f, 1.0f, 0.0f }; 126 | for ( int i = 0; i < sceneInput.instanceCount; i++ ) 127 | frames.push_back( frame ); 128 | 129 | CHECK_ORO( oroMalloc( 130 | reinterpret_cast( &sceneInput.instanceFrames ), frames.size() * sizeof( hiprtFrameSRT ) ) ); 131 | CHECK_ORO( oroMemcpyHtoD( 132 | reinterpret_cast( sceneInput.instanceFrames ), 133 | frames.data(), 134 | frames.size() * sizeof( hiprtFrameSRT ) ) ); 135 | 136 | size_t sceneTempSize; 137 | hiprtDevicePtr sceneTemp; 138 | hiprtBuildOptions options; 139 | options.buildFlags = hiprtBuildFlagBitPreferFastBuild; 140 | CHECK_HIPRT( hiprtGetSceneBuildTemporaryBufferSize( ctxt, sceneInput, options, sceneTempSize ) ); 141 | CHECK_ORO( oroMalloc( reinterpret_cast( &sceneTemp ), sceneTempSize ) ); 142 | 143 | CHECK_HIPRT( hiprtCreateScene( ctxt, sceneInput, options, scene ) ); 144 | CHECK_HIPRT( hiprtBuildScene( ctxt, hiprtBuildOperationBuild, sceneInput, options, sceneTemp, 0, scene ) ); 145 | CHECK_ORO( oroFree( reinterpret_cast( sceneTemp ) ) ); 146 | } 147 | 148 | std::vector funcNameSets( GeomTypesCount ); 149 | funcNameSets[SphereTypeIndex].intersectFuncName = "intersectSphere"; 150 | funcNameSets[CircleTypeIndex].intersectFuncName = "intersectCircle"; 151 | 152 | oroFunction func; 153 | buildTraceKernelFromBitcode( 154 | ctxt, 155 | "../common/TutorialKernels.h", 156 | "MultiCustomIntersectionKernel", 157 | func, 158 | nullptr, 159 | &funcNameSets, 160 | GeomTypesCount, 161 | 1 ); 162 | 163 | std::vector funcDataSets( GeomTypesCount ); 164 | CHECK_ORO( 165 | oroMalloc( const_cast( &funcDataSets[SphereTypeIndex].intersectFuncData ), sizeof( hiprtFloat4 ) ) ); 166 | CHECK_ORO( oroMemcpyHtoD( 167 | const_cast( funcDataSets[SphereTypeIndex].intersectFuncData ), &sphere, sizeof( hiprtFloat4 ) ) ); 168 | CHECK_ORO( 169 | oroMalloc( const_cast( &funcDataSets[CircleTypeIndex].intersectFuncData ), sizeof( hiprtFloat4 ) ) ); 170 | CHECK_ORO( oroMemcpyHtoD( 171 | const_cast( funcDataSets[CircleTypeIndex].intersectFuncData ), &circle, sizeof( hiprtFloat4 ) ) ); 172 | 173 | hiprtFuncTable funcTable; 174 | CHECK_HIPRT( hiprtCreateFuncTable( ctxt, GeomTypesCount, 1, funcTable ) ); 175 | CHECK_HIPRT( hiprtSetFuncTable( ctxt, funcTable, SphereTypeIndex, 0, funcDataSets[SphereTypeIndex] ) ); 176 | CHECK_HIPRT( hiprtSetFuncTable( ctxt, funcTable, CircleTypeIndex, 0, funcDataSets[CircleTypeIndex] ) ); 177 | 178 | uint8_t* pixels; 179 | CHECK_ORO( oroMalloc( reinterpret_cast( &pixels ), m_res.x * m_res.y * 4 ) ); 180 | 181 | void* args[] = { &scene, &pixels, &funcTable, &m_res }; 182 | launchKernel( func, m_res.x, m_res.y, args ); 183 | writeImage( "11_multi_custom_intersection.png", m_res.x, m_res.y, pixels ); 184 | 185 | CHECK_ORO( oroFree( reinterpret_cast( listSpheres.aabbs ) ) ); 186 | CHECK_ORO( oroFree( reinterpret_cast( listCircles.aabbs ) ) ); 187 | CHECK_ORO( oroFree( reinterpret_cast( sceneInput.instanceFrames ) ) ); 188 | CHECK_ORO( oroFree( reinterpret_cast( sceneInput.instances ) ) ); 189 | CHECK_ORO( oroFree( const_cast( funcDataSets[SphereTypeIndex].intersectFuncData ) ) ); 190 | CHECK_ORO( oroFree( const_cast( funcDataSets[CircleTypeIndex].intersectFuncData ) ) ); 191 | CHECK_ORO( oroFree( reinterpret_cast( pixels ) ) ); 192 | 193 | CHECK_HIPRT( hiprtDestroyGeometry( ctxt, geomSpheres ) ); 194 | CHECK_HIPRT( hiprtDestroyGeometry( ctxt, geomCircles ) ); 195 | CHECK_HIPRT( hiprtDestroyScene( ctxt, scene ) ); 196 | CHECK_HIPRT( hiprtDestroyContext( ctxt ) ); 197 | } 198 | }; 199 | 200 | int main( int argc, char** argv ) 201 | { 202 | Tutorial tutorial; 203 | tutorial.init( 0 ); 204 | tutorial.run(); 205 | 206 | return 0; 207 | } 208 | -------------------------------------------------------------------------------- /tutorials/13_concurrent_scene_build/main.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2021-2023 Advanced Micro Devices, Inc. All rights reserved. 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE. 21 | // 22 | 23 | #include 24 | #include 25 | 26 | class Tutorial : public TutorialBase 27 | { 28 | public: 29 | void run() 30 | { 31 | constexpr uint32_t CircleCount = 3u; 32 | hiprtFloat4 circles[] = { { 0.25f, 0.5f, 0.0f, 0.1f }, { 0.5f, 0.5f, 0.0f, 0.1f }, { 0.75f, 0.5f, 0.0f, 0.1f } }; 33 | 34 | hiprtContext ctxt; 35 | CHECK_HIPRT( hiprtCreateContext( HIPRT_API_VERSION, m_ctxtInput, ctxt ) ); 36 | 37 | hiprtGeometry geomCircles; 38 | hiprtApiStream streamCircles; 39 | hiprtAABBListPrimitive list; 40 | { 41 | list.aabbCount = CircleCount; 42 | list.aabbStride = 2 * sizeof( hiprtFloat4 ); 43 | hiprtFloat4 aabbs[2 * CircleCount]; 44 | for ( int i = 0; i < CircleCount; i++ ) 45 | { 46 | const hiprtFloat4& c = circles[i]; 47 | aabbs[i * 2 + 0] = { c.x - c.w, c.y - c.w, c.z, 0.0f }; 48 | aabbs[i * 2 + 1] = { c.x + c.w, c.y + c.w, c.z, 0.0f }; 49 | } 50 | CHECK_ORO( 51 | oroMalloc( reinterpret_cast( &list.aabbs ), 2 * list.aabbCount * sizeof( hiprtFloat4 ) ) ); 52 | CHECK_ORO( oroMemcpyHtoD( 53 | reinterpret_cast( list.aabbs ), aabbs, 2 * list.aabbCount * sizeof( hiprtFloat4 ) ) ); 54 | 55 | hiprtGeometryBuildInput geomInput; 56 | geomInput.type = hiprtPrimitiveTypeAABBList; 57 | geomInput.primitive.aabbList = list; 58 | geomInput.geomType = 0; 59 | 60 | size_t geomTempSize; 61 | hiprtDevicePtr geomTemp; 62 | hiprtBuildOptions options; 63 | options.buildFlags = hiprtBuildFlagBitPreferFastBuild; 64 | CHECK_HIPRT( hiprtGetGeometryBuildTemporaryBufferSize( ctxt, geomInput, options, geomTempSize ) ); 65 | CHECK_ORO( oroMalloc( reinterpret_cast( &geomTemp ), geomTempSize ) ); 66 | 67 | CHECK_ORO( oroStreamCreate( reinterpret_cast( &streamCircles ) ) ); 68 | CHECK_HIPRT( hiprtCreateGeometry( ctxt, geomInput, options, geomCircles ) ); 69 | CHECK_HIPRT( hiprtBuildGeometry( 70 | ctxt, hiprtBuildOperationBuild, geomInput, options, geomTemp, streamCircles, geomCircles ) ); 71 | CHECK_ORO( oroFree( reinterpret_cast( geomTemp ) ) ); 72 | } 73 | 74 | hiprtGeometry geomTris; 75 | hiprtApiStream streamTris; 76 | hiprtTriangleMeshPrimitive mesh; 77 | { 78 | mesh.triangleCount = 3; 79 | mesh.triangleStride = sizeof( hiprtInt3 ); 80 | std::vector triangleIndices( 3 * mesh.triangleCount ); 81 | std::iota( triangleIndices.begin(), triangleIndices.end(), 0 ); 82 | CHECK_ORO( oroMalloc( 83 | reinterpret_cast( &mesh.triangleIndices ), mesh.triangleCount * sizeof( hiprtInt3 ) ) ); 84 | CHECK_ORO( oroMemcpyHtoD( 85 | reinterpret_cast( mesh.triangleIndices ), 86 | triangleIndices.data(), 87 | mesh.triangleCount * sizeof( hiprtInt3 ) ) ); 88 | 89 | mesh.vertexCount = 9; 90 | mesh.vertexStride = sizeof( hiprtFloat3 ); 91 | hiprtFloat3 vertices[] = { 92 | { 0.15f, 0.40f, 0.0f }, 93 | { 0.35f, 0.40f, 0.0f }, 94 | { 0.25f, 0.60f, 0.0f }, 95 | { 0.40f, 0.40f, 0.0f }, 96 | { 0.60f, 0.40f, 0.0f }, 97 | { 0.50f, 0.60f, 0.0f }, 98 | { 0.65f, 0.40f, 0.0f }, 99 | { 0.85f, 0.40f, 0.0f }, 100 | { 0.75f, 0.60f, 0.0f } }; 101 | CHECK_ORO( 102 | oroMalloc( reinterpret_cast( &mesh.vertices ), mesh.vertexCount * sizeof( hiprtFloat3 ) ) ); 103 | CHECK_ORO( oroMemcpyHtoD( 104 | reinterpret_cast( mesh.vertices ), vertices, mesh.vertexCount * sizeof( hiprtFloat3 ) ) ); 105 | 106 | hiprtGeometryBuildInput geomInput; 107 | geomInput.type = hiprtPrimitiveTypeTriangleMesh; 108 | geomInput.primitive.triangleMesh = mesh; 109 | 110 | size_t geomTempSize; 111 | hiprtDevicePtr geomTemp; 112 | hiprtBuildOptions options; 113 | options.buildFlags = hiprtBuildFlagBitPreferFastBuild; 114 | CHECK_HIPRT( hiprtGetGeometryBuildTemporaryBufferSize( ctxt, geomInput, options, geomTempSize ) ); 115 | CHECK_ORO( oroMalloc( reinterpret_cast( &geomTemp ), geomTempSize ) ); 116 | 117 | CHECK_ORO( oroStreamCreate( reinterpret_cast( &streamTris ) ) ); 118 | CHECK_HIPRT( hiprtCreateGeometry( ctxt, geomInput, options, geomTris ) ); 119 | CHECK_HIPRT( 120 | hiprtBuildGeometry( ctxt, hiprtBuildOperationBuild, geomInput, options, geomTemp, streamTris, geomTris ) ); 121 | CHECK_ORO( oroFree( reinterpret_cast( geomTemp ) ) ); 122 | } 123 | 124 | CHECK_ORO( oroDeviceSynchronize() ); 125 | 126 | hiprtScene scene; 127 | hiprtSceneBuildInput sceneInput; 128 | { 129 | hiprtInstance instCircles; 130 | instCircles.type = hiprtInstanceTypeGeometry; 131 | instCircles.geometry = geomCircles; 132 | 133 | hiprtInstance instTris; 134 | instTris.type = hiprtInstanceTypeGeometry; 135 | instTris.geometry = geomTris; 136 | 137 | hiprtInstance instances[] = { instCircles, instTris }; 138 | 139 | sceneInput.instanceCount = 2; 140 | sceneInput.instanceMasks = nullptr; 141 | sceneInput.instanceTransformHeaders = nullptr; 142 | CHECK_ORO( oroMalloc( 143 | reinterpret_cast( &sceneInput.instances ), 144 | sceneInput.instanceCount * sizeof( hiprtInstance ) ) ); 145 | CHECK_ORO( oroMemcpyHtoD( 146 | reinterpret_cast( sceneInput.instances ), 147 | instances, 148 | sceneInput.instanceCount * sizeof( hiprtInstance ) ) ); 149 | 150 | const float o = 0.05f; 151 | hiprtFrameSRT frames[2]; 152 | frames[0].translation = { 0.0f, o, 0.0f }; 153 | frames[0].scale = { 1.0f, 1.0f, 1.0f }; 154 | frames[0].rotation = { 0.0f, 0.0f, 1.0f, 0.0f }; 155 | frames[1].translation = { 0.0f, -o, 0.0f }; 156 | frames[1].scale = { 1.0f, 1.0f, 1.0f }; 157 | frames[1].rotation = { 0.0f, 0.0f, 1.0f, 0.0f }; 158 | 159 | sceneInput.frameCount = 2; 160 | CHECK_ORO( oroMalloc( 161 | reinterpret_cast( &sceneInput.instanceFrames ), 162 | sceneInput.frameCount * sizeof( hiprtFrameSRT ) ) ); 163 | CHECK_ORO( oroMemcpyHtoD( 164 | reinterpret_cast( sceneInput.instanceFrames ), 165 | frames, 166 | sceneInput.frameCount * sizeof( hiprtFrameSRT ) ) ); 167 | 168 | size_t sceneTempSize; 169 | hiprtDevicePtr sceneTemp; 170 | hiprtBuildOptions options; 171 | options.buildFlags = hiprtBuildFlagBitPreferFastBuild; 172 | CHECK_HIPRT( hiprtGetSceneBuildTemporaryBufferSize( ctxt, sceneInput, options, sceneTempSize ) ); 173 | CHECK_ORO( oroMalloc( reinterpret_cast( &sceneTemp ), sceneTempSize ) ); 174 | 175 | CHECK_HIPRT( hiprtCreateScene( ctxt, sceneInput, options, scene ) ); 176 | CHECK_HIPRT( hiprtBuildScene( ctxt, hiprtBuildOperationBuild, sceneInput, options, sceneTemp, 0, scene ) ); 177 | CHECK_ORO( oroFree( reinterpret_cast( sceneTemp ) ) ); 178 | } 179 | 180 | hiprtFuncNameSet funcNameSet; 181 | funcNameSet.intersectFuncName = "intersectCircle"; 182 | std::vector funcNameSets = { funcNameSet }; 183 | 184 | oroFunction func; 185 | buildTraceKernelFromBitcode( 186 | ctxt, "../common/TutorialKernels.h", "SceneBuildKernel", func, nullptr, &funcNameSets, 1, 1 ); 187 | 188 | hiprtFuncDataSet funcDataSet; 189 | CHECK_ORO( 190 | oroMalloc( const_cast( &funcDataSet.intersectFuncData ), CircleCount * sizeof( hiprtFloat4 ) ) ); 191 | CHECK_ORO( oroMemcpyHtoD( 192 | const_cast( funcDataSet.intersectFuncData ), circles, CircleCount * sizeof( hiprtFloat4 ) ) ); 193 | 194 | hiprtFuncTable funcTable; 195 | CHECK_HIPRT( hiprtCreateFuncTable( ctxt, 1, 1, funcTable ) ); 196 | CHECK_HIPRT( hiprtSetFuncTable( ctxt, funcTable, 0, 0, funcDataSet ) ); 197 | 198 | uint8_t* pixels; 199 | CHECK_ORO( oroMalloc( reinterpret_cast( &pixels ), m_res.x * m_res.y * 4 ) ); 200 | CHECK_ORO( oroMemset( reinterpret_cast( pixels ), 0, m_res.x * m_res.y * 4 ) ); 201 | 202 | void* args[] = { &scene, &pixels, &funcTable, &m_res }; 203 | launchKernel( func, m_res.x, m_res.y, args ); 204 | writeImage( "13_concurrent_scene_build.png", m_res.x, m_res.y, pixels ); 205 | 206 | CHECK_ORO( oroFree( const_cast( funcDataSet.intersectFuncData ) ) ); 207 | CHECK_ORO( oroFree( reinterpret_cast( sceneInput.instances ) ) ); 208 | CHECK_ORO( oroFree( reinterpret_cast( sceneInput.instanceFrames ) ) ); 209 | CHECK_ORO( oroFree( reinterpret_cast( mesh.triangleIndices ) ) ); 210 | CHECK_ORO( oroFree( reinterpret_cast( mesh.vertices ) ) ); 211 | CHECK_ORO( oroFree( reinterpret_cast( list.aabbs ) ) ); 212 | CHECK_ORO( oroFree( reinterpret_cast( pixels ) ) ); 213 | 214 | CHECK_ORO( oroStreamDestroy( reinterpret_cast( streamCircles ) ) ); 215 | CHECK_ORO( oroStreamDestroy( reinterpret_cast( streamTris ) ) ); 216 | 217 | CHECK_HIPRT( hiprtDestroyFuncTable( ctxt, funcTable ) ); 218 | CHECK_HIPRT( hiprtDestroyGeometry( ctxt, geomTris ) ); 219 | CHECK_HIPRT( hiprtDestroyGeometry( ctxt, geomCircles ) ); 220 | CHECK_HIPRT( hiprtDestroyScene( ctxt, scene ) ); 221 | CHECK_HIPRT( hiprtDestroyContext( ctxt ) ); 222 | } 223 | }; 224 | 225 | int main( int argc, char** argv ) 226 | { 227 | Tutorial tutorial; 228 | tutorial.init( 0 ); 229 | tutorial.run(); 230 | 231 | return 0; 232 | } 233 | -------------------------------------------------------------------------------- /tutorials/09_motion_blur_srt/main.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2021-2023 Advanced Micro Devices, Inc. All rights reserved. 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE. 21 | // 22 | 23 | #include 24 | 25 | class Tutorial : public TutorialBase 26 | { 27 | public: 28 | void run() 29 | { 30 | hiprtContext ctxt; 31 | CHECK_HIPRT( hiprtCreateContext( HIPRT_API_VERSION, m_ctxtInput, ctxt ) ); 32 | 33 | hiprtGeometry geom0; 34 | hiprtTriangleMeshPrimitive mesh0; 35 | { 36 | mesh0.triangleCount = 1; 37 | mesh0.triangleStride = sizeof( hiprtInt3 ); 38 | uint32_t triangleIndices[] = { 0, 1, 2 }; 39 | CHECK_ORO( oroMalloc( 40 | reinterpret_cast( &mesh0.triangleIndices ), mesh0.triangleCount * sizeof( hiprtInt3 ) ) ); 41 | CHECK_ORO( oroMemcpyHtoD( 42 | reinterpret_cast( mesh0.triangleIndices ), 43 | triangleIndices, 44 | mesh0.triangleCount * sizeof( hiprtInt3 ) ) ); 45 | 46 | mesh0.vertexCount = 3; 47 | mesh0.vertexStride = sizeof( hiprtFloat3 ); 48 | constexpr float Scale = 0.15f; 49 | hiprtFloat3 vertices[] = { 50 | { Scale * sinf( 0.0f ), Scale * cosf( 0.0f ), 0.0f }, 51 | { Scale * sinf( hiprt::Pi * 2.0f / 3.0f ), Scale * cosf( hiprt::Pi * 2.0f / 3.0f ), 0.0f }, 52 | { Scale * sinf( hiprt::Pi * 4.0f / 3.0f ), Scale * cosf( hiprt::Pi * 4.0f / 3.0f ), 0.0f } }; 53 | CHECK_ORO( 54 | oroMalloc( reinterpret_cast( &mesh0.vertices ), mesh0.vertexCount * sizeof( hiprtFloat3 ) ) ); 55 | CHECK_ORO( oroMemcpyHtoD( 56 | reinterpret_cast( mesh0.vertices ), vertices, mesh0.vertexCount * sizeof( hiprtFloat3 ) ) ); 57 | 58 | hiprtGeometryBuildInput geomInput; 59 | geomInput.type = hiprtPrimitiveTypeTriangleMesh; 60 | geomInput.primitive.triangleMesh = mesh0; 61 | 62 | size_t geomTempSize; 63 | hiprtDevicePtr geomTemp; 64 | hiprtBuildOptions options; 65 | options.buildFlags = hiprtBuildFlagBitPreferFastBuild; 66 | CHECK_HIPRT( hiprtGetGeometryBuildTemporaryBufferSize( ctxt, geomInput, options, geomTempSize ) ); 67 | CHECK_ORO( oroMalloc( reinterpret_cast( &geomTemp ), geomTempSize ) ); 68 | 69 | CHECK_HIPRT( hiprtCreateGeometry( ctxt, geomInput, options, geom0 ) ); 70 | CHECK_HIPRT( hiprtBuildGeometry( ctxt, hiprtBuildOperationBuild, geomInput, options, geomTemp, 0, geom0 ) ); 71 | CHECK_ORO( oroFree( reinterpret_cast( geomTemp ) ) ); 72 | } 73 | 74 | hiprtGeometry geom1; 75 | hiprtTriangleMeshPrimitive mesh1; 76 | { 77 | mesh1.triangleCount = 1; 78 | mesh1.triangleStride = sizeof( hiprtInt3 ); 79 | uint32_t triangleIndices[] = { 0, 1, 2 }; 80 | CHECK_ORO( oroMalloc( 81 | reinterpret_cast( &mesh1.triangleIndices ), mesh1.triangleCount * sizeof( hiprtInt3 ) ) ); 82 | CHECK_ORO( oroMemcpyHtoD( 83 | reinterpret_cast( mesh1.triangleIndices ), 84 | triangleIndices, 85 | mesh1.triangleCount * sizeof( hiprtInt3 ) ) ); 86 | 87 | mesh1.vertexCount = 3; 88 | mesh1.vertexStride = sizeof( hiprtFloat3 ); 89 | constexpr float Scale = 0.15f; 90 | hiprtFloat3 vertices[] = { 91 | { Scale * sinf( 0.0f ), Scale * cosf( 0.0f ), 0.0f }, 92 | { Scale * sinf( hiprt::Pi * 2.0f / 3.0f ), Scale * cosf( hiprt::Pi * 2.0f / 3.0f ), 0.0f }, 93 | { Scale * sinf( hiprt::Pi * 4.0f / 3.0f ), Scale * cosf( hiprt::Pi * 4.0f / 3.0f ), 0.0f } }; 94 | CHECK_ORO( 95 | oroMalloc( reinterpret_cast( &mesh1.vertices ), mesh1.vertexCount * sizeof( hiprtFloat3 ) ) ); 96 | CHECK_ORO( oroMemcpyHtoD( 97 | reinterpret_cast( mesh1.vertices ), vertices, mesh1.vertexCount * sizeof( hiprtFloat3 ) ) ); 98 | 99 | hiprtGeometryBuildInput geomInput; 100 | geomInput.type = hiprtPrimitiveTypeTriangleMesh; 101 | geomInput.primitive.triangleMesh = mesh1; 102 | 103 | size_t geomTempSize; 104 | hiprtDevicePtr geomTemp; 105 | hiprtBuildOptions options; 106 | options.buildFlags = hiprtBuildFlagBitPreferFastBuild; 107 | CHECK_HIPRT( hiprtGetGeometryBuildTemporaryBufferSize( ctxt, geomInput, options, geomTempSize ) ); 108 | CHECK_ORO( oroMalloc( reinterpret_cast( &geomTemp ), geomTempSize ) ); 109 | 110 | CHECK_HIPRT( hiprtCreateGeometry( ctxt, geomInput, options, geom1 ) ); 111 | CHECK_HIPRT( hiprtBuildGeometry( ctxt, hiprtBuildOperationBuild, geomInput, options, geomTemp, 0, geom1 ) ); 112 | CHECK_ORO( oroFree( reinterpret_cast( geomTemp ) ) ); 113 | } 114 | 115 | hiprtScene scene; 116 | hiprtSceneBuildInput sceneInput; 117 | { 118 | hiprtInstance instance0; 119 | instance0.type = hiprtInstanceTypeGeometry; 120 | instance0.geometry = geom0; 121 | 122 | hiprtInstance instance1; 123 | instance1.type = hiprtInstanceTypeGeometry; 124 | instance1.geometry = geom1; 125 | 126 | hiprtInstance instances[] = { instance0, instance1 }; 127 | 128 | sceneInput.instanceCount = 2; 129 | sceneInput.instanceMasks = nullptr; 130 | CHECK_ORO( oroMalloc( 131 | reinterpret_cast( &sceneInput.instances ), 132 | sceneInput.instanceCount * sizeof( hiprtInstance ) ) ); 133 | CHECK_ORO( oroMemcpyHtoD( 134 | reinterpret_cast( sceneInput.instances ), 135 | instances, 136 | sceneInput.instanceCount * sizeof( hiprtInstance ) ) ); 137 | 138 | constexpr float Offset = 0.3f; 139 | hiprtFrameSRT frames[5]; 140 | frames[0].translation = { -0.25f, -Offset, 0.0f }; 141 | frames[0].scale = { 1.0f, 1.0f, 1.0f }; 142 | frames[0].rotation = { 0.0f, 0.0f, 1.0f, 0.0f }; 143 | frames[0].time = 0.0f; 144 | frames[1].translation = { 0.0f, -Offset, 0.0f }; 145 | frames[1].scale = { 1.0f, 1.0f, 1.0f }; 146 | frames[1].rotation = { 0.0f, 0.0f, 1.0f, 0.0f }; 147 | frames[1].time = 0.35f; 148 | frames[2].translation = { 0.25f, -Offset, 0.0f }; 149 | frames[2].scale = { 1.0f, 1.0f, 1.0f }; 150 | frames[2].rotation = { 0.0f, 0.0f, 1.0f, hiprt::Pi * 0.25f }; 151 | frames[2].time = 1.0f; 152 | frames[3].translation = { 0.0f, Offset, 0.0f }; 153 | frames[3].scale = { 1.0f, 1.0f, 1.0f }; 154 | frames[3].rotation = { 0.0f, 0.0f, 1.0f, 0.f }; 155 | frames[3].time = 0.0f; 156 | frames[4].translation = { 0.0f, Offset, 0.0f }; 157 | frames[4].scale = { 1.0f, 1.0f, 1.0f }; 158 | frames[4].rotation = { 0.0f, 0.0f, 1.0f, hiprt::Pi * 0.5f }; 159 | frames[4].time = 1.0f; 160 | 161 | sceneInput.frameCount = 5; 162 | sceneInput.frameType = hiprtFrameTypeSRT; 163 | CHECK_ORO( oroMalloc( 164 | reinterpret_cast( &sceneInput.instanceFrames ), 165 | sceneInput.frameCount * sizeof( hiprtFrameSRT ) ) ); 166 | CHECK_ORO( oroMemcpyHtoD( 167 | reinterpret_cast( sceneInput.instanceFrames ), 168 | frames, 169 | sceneInput.frameCount * sizeof( hiprtFrameSRT ) ) ); 170 | 171 | hiprtTransformHeader headers[2]; 172 | headers[0].frameIndex = 0; 173 | headers[0].frameCount = 3; 174 | headers[1].frameIndex = 3; 175 | headers[1].frameCount = 2; 176 | CHECK_ORO( oroMalloc( 177 | reinterpret_cast( &sceneInput.instanceTransformHeaders ), 178 | sceneInput.instanceCount * sizeof( hiprtTransformHeader ) ) ); 179 | CHECK_ORO( oroMemcpyHtoD( 180 | reinterpret_cast( sceneInput.instanceTransformHeaders ), 181 | headers, 182 | sceneInput.instanceCount * sizeof( hiprtTransformHeader ) ) ); 183 | 184 | size_t sceneTempSize; 185 | hiprtDevicePtr sceneTemp; 186 | hiprtBuildOptions options; 187 | options.buildFlags = hiprtBuildFlagBitPreferFastBuild; 188 | CHECK_HIPRT( hiprtGetSceneBuildTemporaryBufferSize( ctxt, sceneInput, options, sceneTempSize ) ); 189 | CHECK_ORO( oroMalloc( reinterpret_cast( &sceneTemp ), sceneTempSize ) ); 190 | 191 | CHECK_HIPRT( hiprtCreateScene( ctxt, sceneInput, options, scene ) ); 192 | CHECK_HIPRT( hiprtBuildScene( ctxt, hiprtBuildOperationBuild, sceneInput, options, sceneTemp, 0, scene ) ); 193 | CHECK_ORO( oroFree( reinterpret_cast( sceneTemp ) ) ); 194 | } 195 | 196 | oroFunction func; 197 | buildTraceKernelFromBitcode( ctxt, "../common/TutorialKernels.h", "MotionBlurKernel", func ); 198 | 199 | uint8_t* pixels; 200 | CHECK_ORO( oroMalloc( reinterpret_cast( &pixels ), m_res.x * m_res.y * 4 ) ); 201 | 202 | void* args[] = { &scene, &pixels, &m_res }; 203 | launchKernel( func, m_res.x, m_res.y, args ); 204 | writeImage( "09_motion_blur_srt.png", m_res.x, m_res.y, pixels ); 205 | 206 | CHECK_ORO( oroFree( reinterpret_cast( sceneInput.instances ) ) ); 207 | CHECK_ORO( oroFree( reinterpret_cast( sceneInput.instanceFrames ) ) ); 208 | CHECK_ORO( oroFree( reinterpret_cast( sceneInput.instanceTransformHeaders ) ) ); 209 | CHECK_ORO( oroFree( reinterpret_cast( mesh0.vertices ) ) ); 210 | CHECK_ORO( oroFree( reinterpret_cast( mesh0.triangleIndices ) ) ); 211 | CHECK_ORO( oroFree( reinterpret_cast( mesh1.vertices ) ) ); 212 | CHECK_ORO( oroFree( reinterpret_cast( mesh1.triangleIndices ) ) ); 213 | CHECK_ORO( oroFree( reinterpret_cast( pixels ) ) ); 214 | 215 | CHECK_HIPRT( hiprtDestroyGeometry( ctxt, geom0 ) ); 216 | CHECK_HIPRT( hiprtDestroyGeometry( ctxt, geom1 ) ); 217 | CHECK_HIPRT( hiprtDestroyScene( ctxt, scene ) ); 218 | CHECK_HIPRT( hiprtDestroyContext( ctxt ) ); 219 | } 220 | }; 221 | 222 | int main( int argc, char** argv ) 223 | { 224 | Tutorial tutorial; 225 | tutorial.init( 0 ); 226 | tutorial.run(); 227 | 228 | return 0; 229 | } 230 | --------------------------------------------------------------------------------