├── .args ├── .clang-format ├── .github └── workflows │ └── build.yml ├── .gitignore ├── .gitmodules ├── 1-Deploy.bat ├── 1-Deploy.sh ├── 2-Build.bat ├── 2-Build.sh ├── 3-Test samples.bat ├── 4-Clean.bat ├── 4-Clean.sh ├── CMakeLists.txt ├── Dependencies.xml ├── External └── Packman │ ├── bootstrap │ ├── configure.bat │ ├── download_file_from_url.ps1 │ ├── fetch_file_from_packman_bootstrap.cmd │ ├── generate_temp_file_name.ps1 │ ├── generate_temp_folder.ps1 │ └── install_package.py │ ├── config.packman.xml │ ├── packman.cmd │ ├── packman.sh │ ├── python.bat │ └── python.sh ├── LICENSE.txt ├── README.md ├── Shaders ├── Box.vs.hlsl ├── Box0.fs.hlsl ├── Box1.fs.hlsl ├── Box2.fs.hlsl ├── Box3.fs.hlsl ├── Box4.fs.hlsl ├── Box5.fs.hlsl ├── Box6.fs.hlsl ├── Box7.fs.hlsl ├── Compute.cs.hlsl ├── Forward.fs.hlsl ├── Forward.vs.hlsl ├── ForwardBindless.fs.hlsl ├── ForwardBindless.vs.hlsl ├── ForwardDiscard.fs.hlsl ├── ForwardResources.hlsli ├── ForwardTransparent.fs.hlsl ├── GenerateSceneDrawCalls.cs.hlsl ├── RayTracingBox.rchit.hlsl ├── RayTracingBox.rgen.hlsl ├── RayTracingBox.rmiss.hlsl ├── RayTracingTriangle.rchit.hlsl ├── RayTracingTriangle.rgen.hlsl ├── RayTracingTriangle.rmiss.hlsl ├── SceneViewerBindlessStructs.h ├── Shaders.cfg ├── Simple.fs.hlsl ├── Simple.vs.hlsl ├── Surface.cs.hlsl ├── Triangle.fs.hlsl ├── Triangle.vs.hlsl ├── TriangleFlexibleMultiview.vs.hlsl ├── Triangles.fs.hlsl └── Triangles.vs.hlsl └── Source ├── AsyncCompute.cpp ├── BindlessSceneViewer.cpp ├── Buffers.c ├── Clear.cpp ├── DeviceInfo.c ├── LowLatency.cpp ├── MultiThreading.cpp ├── Multisample.cpp ├── Multiview.cpp ├── RayTracingBoxes.cpp ├── RayTracingTriangle.cpp ├── Readback.cpp ├── Resize.cpp ├── SceneViewer.cpp ├── Triangle.cpp └── Wrapper.cpp /.args: -------------------------------------------------------------------------------- 1 | { 2 | "FileVersion": 2, 3 | "Items": [ 4 | { 5 | "Command": "API", 6 | "Items": [ 7 | { 8 | "Command": "--api=D3D11" 9 | }, 10 | { 11 | "Command": "--api=D3D12" 12 | }, 13 | { 14 | "Command": "--api=VULKAN" 15 | } 16 | ] 17 | }, 18 | { 19 | "Command": "RESOLUTION", 20 | "Items": [ 21 | { 22 | "Command": "--width=800 --height=600" 23 | }, 24 | { 25 | "Command": "--width=1280 --height=720" 26 | }, 27 | { 28 | "Command": "--width=1920 --height=1080" 29 | }, 30 | { 31 | "Command": "--width=2560 --height=1440" 32 | }, 33 | { 34 | "Command": "--width=3440 --height=1440" 35 | }, 36 | { 37 | "Command": "--width=5120 --height=1440" 38 | }, 39 | { 40 | "Command": "--width=3840 --height=2160" 41 | } 42 | ] 43 | }, 44 | { 45 | "Command": "VSYNC", 46 | "Items": [ 47 | { 48 | "Command": "--vsyncInterval=0" 49 | }, 50 | { 51 | "Command": "--vsyncInterval=1" 52 | } 53 | ] 54 | }, 55 | { 56 | "Command": "DPI", 57 | "Items": [ 58 | { 59 | "Command": "--dpiMode=0" 60 | }, 61 | { 62 | "Command": "--dpiMode=1" 63 | }, 64 | { 65 | "Command": "--dpiMode=2" 66 | } 67 | ] 68 | }, 69 | { 70 | "Command": "OTHER", 71 | "Items": [ 72 | { 73 | "Command": "--debugAPI" 74 | }, 75 | { 76 | "Command": "--debugNRI" 77 | }, 78 | { 79 | "Command": "--testMode" 80 | }, 81 | { 82 | "Command": "--adapter=0" 83 | }, 84 | { 85 | "Command": "--adapter=1" 86 | } 87 | ] 88 | } 89 | ] 90 | } -------------------------------------------------------------------------------- /.clang-format: -------------------------------------------------------------------------------- 1 | --- 2 | BasedOnStyle: Google 3 | AccessModifierOffset: -4 4 | AlignAfterOpenBracket: DontAlign 5 | AlignArrayOfStructures: None 6 | AlignConsecutiveAssignments: 7 | Enabled: false 8 | AcrossEmptyLines: false 9 | AcrossComments: false 10 | AlignCompound: false 11 | AlignFunctionPointers: false 12 | PadOperators: true 13 | AlignConsecutiveBitFields: 14 | Enabled: true 15 | AcrossEmptyLines: false 16 | AcrossComments: false 17 | AlignCompound: false 18 | AlignFunctionPointers: false 19 | PadOperators: false 20 | AlignConsecutiveDeclarations: 21 | Enabled: false 22 | AcrossEmptyLines: false 23 | AcrossComments: false 24 | AlignCompound: false 25 | AlignFunctionPointers: false 26 | PadOperators: false 27 | AlignConsecutiveMacros: 28 | Enabled: true 29 | AcrossEmptyLines: false 30 | AcrossComments: false 31 | AlignCompound: false 32 | AlignFunctionPointers: false 33 | PadOperators: false 34 | AlignConsecutiveShortCaseStatements: 35 | Enabled: false 36 | AcrossEmptyLines: false 37 | AcrossComments: false 38 | AlignCaseArrows: false 39 | AlignCaseColons: false 40 | AlignConsecutiveTableGenBreakingDAGArgColons: 41 | Enabled: false 42 | AcrossEmptyLines: false 43 | AcrossComments: false 44 | AlignCompound: false 45 | AlignFunctionPointers: false 46 | PadOperators: false 47 | AlignConsecutiveTableGenCondOperatorColons: 48 | Enabled: false 49 | AcrossEmptyLines: false 50 | AcrossComments: false 51 | AlignCompound: false 52 | AlignFunctionPointers: false 53 | PadOperators: false 54 | AlignConsecutiveTableGenDefinitionColons: 55 | Enabled: false 56 | AcrossEmptyLines: false 57 | AcrossComments: false 58 | AlignCompound: false 59 | AlignFunctionPointers: false 60 | PadOperators: false 61 | AlignEscapedNewlines: DontAlign 62 | AlignOperands: DontAlign 63 | AlignTrailingComments: 64 | Kind: Always 65 | OverEmptyLines: 0 66 | AllowAllArgumentsOnNextLine: true 67 | AllowAllParametersOfDeclarationOnNextLine: true 68 | AllowBreakBeforeNoexceptSpecifier: Never 69 | AllowShortBlocksOnASingleLine: Never 70 | AllowShortCaseExpressionOnASingleLine: true 71 | AllowShortCaseLabelsOnASingleLine: false 72 | AllowShortCompoundRequirementOnASingleLine: true 73 | AllowShortEnumsOnASingleLine: false 74 | AllowShortFunctionsOnASingleLine: None 75 | AllowShortIfStatementsOnASingleLine: Never 76 | AllowShortLambdasOnASingleLine: All 77 | AllowShortLoopsOnASingleLine: false 78 | AlwaysBreakAfterDefinitionReturnType: None 79 | AlwaysBreakBeforeMultilineStrings: true 80 | AttributeMacros: 81 | - CPP 82 | BinPackArguments: true 83 | BinPackParameters: true 84 | BitFieldColonSpacing: Both 85 | BraceWrapping: 86 | AfterCaseLabel: false 87 | AfterClass: false 88 | AfterControlStatement: Never 89 | AfterEnum: false 90 | AfterFunction: false 91 | AfterNamespace: false 92 | AfterObjCDeclaration: false 93 | AfterStruct: false 94 | AfterUnion: false 95 | AfterExternBlock: false 96 | BeforeCatch: false 97 | BeforeElse: false 98 | BeforeLambdaBody: false 99 | BeforeWhile: false 100 | IndentBraces: false 101 | SplitEmptyFunction: true 102 | SplitEmptyRecord: true 103 | SplitEmptyNamespace: true 104 | BreakAdjacentStringLiterals: true 105 | BreakAfterAttributes: Leave 106 | BreakAfterJavaFieldAnnotations: false 107 | BreakAfterReturnType: None 108 | BreakArrays: true 109 | BreakBeforeBinaryOperators: All 110 | BreakBeforeBraces: Attach 111 | BreakBeforeConceptDeclarations: Always 112 | BreakBeforeInlineASMColon: OnlyMultiline 113 | BreakBeforeTernaryOperators: true 114 | BreakConstructorInitializers: BeforeComma 115 | BreakFunctionDefinitionParameters: false 116 | BreakInheritanceList: BeforeColon 117 | BreakStringLiterals: true 118 | BreakTemplateDeclarations: Yes 119 | ColumnLimit: 0 120 | CommentPragmas: "^ IWYU pragma:" 121 | CompactNamespaces: false 122 | ConstructorInitializerIndentWidth: 4 123 | ContinuationIndentWidth: 4 124 | Cpp11BracedListStyle: true 125 | DerivePointerAlignment: false 126 | DisableFormat: false 127 | EmptyLineAfterAccessModifier: Never 128 | EmptyLineBeforeAccessModifier: LogicalBlock 129 | ExperimentalAutoDetectBinPacking: false 130 | FixNamespaceComments: true 131 | ForEachMacros: 132 | - BLABLA 133 | IfMacros: 134 | - BLABLA 135 | IncludeBlocks: Preserve 136 | IncludeCategories: 137 | - Regex: ^ 138 | Priority: 2 139 | SortPriority: 0 140 | CaseSensitive: false 141 | - Regex: ^<.*\.h> 142 | Priority: 1 143 | SortPriority: 0 144 | CaseSensitive: false 145 | - Regex: ^<.* 146 | Priority: 2 147 | SortPriority: 0 148 | CaseSensitive: false 149 | - Regex: .* 150 | Priority: 3 151 | SortPriority: 0 152 | CaseSensitive: false 153 | IncludeIsMainRegex: ([-_](test|unittest))?$ 154 | IncludeIsMainSourceRegex: "" 155 | IndentAccessModifiers: false 156 | IndentCaseBlocks: false 157 | IndentCaseLabels: true 158 | IndentExternBlock: NoIndent 159 | IndentGotoLabels: true 160 | IndentPPDirectives: AfterHash 161 | IndentRequiresClause: true 162 | IndentWidth: 4 163 | IndentWrappedFunctionNames: false 164 | InsertBraces: false 165 | InsertNewlineAtEOF: false 166 | InsertTrailingCommas: None 167 | IntegerLiteralSeparator: 168 | Binary: 0 169 | BinaryMinDigits: 0 170 | Decimal: 0 171 | DecimalMinDigits: 0 172 | Hex: 0 173 | HexMinDigits: 0 174 | JavaScriptQuotes: Leave 175 | JavaScriptWrapImports: true 176 | KeepEmptyLines: 177 | AtEndOfFile: false 178 | AtStartOfBlock: false 179 | AtStartOfFile: true 180 | LambdaBodyIndentation: Signature 181 | LineEnding: DeriveLF 182 | MacroBlockBegin: "" 183 | MacroBlockEnd: "" 184 | MainIncludeChar: Quote 185 | MaxEmptyLinesToKeep: 1 186 | NamespaceIndentation: None 187 | ObjCBinPackProtocolList: Never 188 | ObjCBlockIndentWidth: 2 189 | ObjCBreakBeforeNestedBlockParam: true 190 | ObjCSpaceAfterProperty: false 191 | ObjCSpaceBeforeProtocolList: true 192 | PPIndentWidth: -1 193 | PackConstructorInitializers: NextLine 194 | PenaltyBreakAssignment: 2 195 | PenaltyBreakBeforeFirstCallParameter: 1 196 | PenaltyBreakComment: 300 197 | PenaltyBreakFirstLessLess: 120 198 | PenaltyBreakOpenParenthesis: 0 199 | PenaltyBreakScopeResolution: 500 200 | PenaltyBreakString: 1000 201 | PenaltyBreakTemplateDeclaration: 10 202 | PenaltyExcessCharacter: 1000000 203 | PenaltyIndentedWhitespace: 0 204 | PenaltyReturnTypeOnItsOwnLine: 200 205 | PointerAlignment: Left 206 | QualifierAlignment: Leave 207 | RawStringFormats: 208 | - Language: Cpp 209 | Delimiters: 210 | - cc 211 | - CC 212 | - cpp 213 | - Cpp 214 | - CPP 215 | - c++ 216 | - C++ 217 | CanonicalDelimiter: "" 218 | BasedOnStyle: google 219 | - Language: TextProto 220 | Delimiters: 221 | - pb 222 | - PB 223 | - proto 224 | - PROTO 225 | EnclosingFunctions: 226 | - EqualsProto 227 | - EquivToProto 228 | - PARSE_PARTIAL_TEXT_PROTO 229 | - PARSE_TEST_PROTO 230 | - PARSE_TEXT_PROTO 231 | - ParseTextOrDie 232 | - ParseTextProtoOrDie 233 | - ParseTestProto 234 | - ParsePartialTestProto 235 | CanonicalDelimiter: pb 236 | BasedOnStyle: google 237 | ReferenceAlignment: Pointer 238 | ReflowComments: true 239 | RemoveBracesLLVM: false 240 | RemoveParentheses: Leave 241 | RemoveSemicolon: false 242 | RequiresClausePosition: OwnLine 243 | RequiresExpressionIndentation: OuterScope 244 | SeparateDefinitionBlocks: Always 245 | ShortNamespaceLines: 1 246 | SkipMacroDefinitionBody: false 247 | SortIncludes: CaseSensitive 248 | SortJavaStaticImport: Before 249 | SortUsingDeclarations: LexicographicNumeric 250 | SpaceAfterCStyleCast: false 251 | SpaceAfterLogicalNot: false 252 | SpaceAfterTemplateKeyword: true 253 | SpaceAroundPointerQualifiers: Default 254 | SpaceBeforeAssignmentOperators: true 255 | SpaceBeforeCaseColon: false 256 | SpaceBeforeCpp11BracedList: false 257 | SpaceBeforeCtorInitializerColon: true 258 | SpaceBeforeInheritanceColon: true 259 | SpaceBeforeJsonColon: false 260 | SpaceBeforeParens: ControlStatements 261 | SpaceBeforeParensOptions: 262 | AfterControlStatements: true 263 | AfterForeachMacros: true 264 | AfterFunctionDeclarationName: false 265 | AfterFunctionDefinitionName: false 266 | AfterIfMacros: true 267 | AfterOverloadedOperator: false 268 | AfterPlacementOperator: true 269 | AfterRequiresInClause: false 270 | AfterRequiresInExpression: false 271 | BeforeNonEmptyParentheses: false 272 | SpaceBeforeRangeBasedForLoopColon: true 273 | SpaceBeforeSquareBrackets: false 274 | SpaceInEmptyBlock: false 275 | SpacesBeforeTrailingComments: 1 276 | SpacesInAngles: Never 277 | SpacesInContainerLiterals: true 278 | SpacesInLineCommentPrefix: 279 | Minimum: 1 280 | Maximum: -1 281 | SpacesInParens: Never 282 | SpacesInParensOptions: 283 | ExceptDoubleParentheses: false 284 | InConditionalStatements: false 285 | InCStyleCasts: false 286 | InEmptyParentheses: false 287 | Other: false 288 | SpacesInSquareBrackets: false 289 | Standard: Auto 290 | StatementAttributeLikeMacros: 291 | - BLABLA 292 | StatementMacros: 293 | - BLABLA 294 | TabWidth: 4 295 | TableGenBreakInsideDAGArg: DontBreak 296 | UseTab: Never 297 | VerilogBreakBetweenInstancePorts: true 298 | WhitespaceSensitiveMacros: 299 | - BLABLA 300 | AlwaysBreakAfterReturnType: None 301 | AlwaysBreakTemplateDeclarations: Yes 302 | KeepEmptyLinesAtTheStartOfBlocks: false 303 | Language: Cpp 304 | SpaceInEmptyParentheses: false 305 | SpacesInCStyleCastParentheses: false 306 | SpacesInConditionalStatement: false 307 | SpacesInParentheses: false 308 | TypenameMacros: 309 | - BLABLA 310 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: NRI samples 2 | on: 3 | pull_request: 4 | branches: 5 | - main 6 | push: 7 | branches: 8 | - main 9 | 10 | jobs: 11 | Build-Windows: 12 | runs-on: windows-latest 13 | steps: 14 | - name : Checkout 15 | uses: actions/checkout@v4 16 | with: 17 | submodules: true 18 | 19 | - name: Deploy 20 | run: .\1-Deploy.bat 21 | 22 | - name: Build 23 | run: .\2-Build.bat 24 | 25 | Build-Ubuntu: 26 | runs-on: ubuntu-22.04 27 | steps: 28 | - name : Checkout 29 | uses: actions/checkout@v4 30 | with: 31 | submodules: true 32 | 33 | - name: Setup CMake 34 | uses: jwlawson/actions-setup-cmake@v2 35 | with: 36 | cmake-version: '3.30.x' 37 | 38 | - name: Setup Ninja 39 | uses: seanmiddleditch/gha-setup-ninja@master 40 | 41 | - name: Install dependencies 42 | run: sudo apt install -y xorg-dev libwayland-dev 43 | 44 | - name: Deploy 45 | run: bash 1-Deploy.sh 46 | 47 | - name: Build 48 | run: bash 2-Build.sh 49 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # VS Code 2 | .vscode/ 3 | 4 | #CLion 5 | .idea 6 | 7 | # ninja 8 | .ninja_deps 9 | .ninja_log 10 | build.ninja 11 | compile_commands.json 12 | *.log 13 | *.ninja 14 | 15 | # generated folders 16 | _Bin/ 17 | _Build/ 18 | _Shaders/ 19 | _Data/ 20 | 21 | # can be a symbolic link 22 | _Data 23 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "External/NRIFramework"] 2 | path = External/NRIFramework 3 | url = https://github.com/NVIDIA-RTX/NRIFramework.git 4 | branch = main 5 | update = merge 6 | -------------------------------------------------------------------------------- /1-Deploy.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | git submodule update --init --recursive 4 | 5 | mkdir "_Build" 6 | 7 | cd "_Build" 8 | cmake .. -A x64 9 | cd .. 10 | -------------------------------------------------------------------------------- /1-Deploy.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | git submodule update --init --recursive 4 | 5 | mkdir -p "_Build" 6 | 7 | cd "_Build" 8 | cmake .. 9 | cd .. 10 | -------------------------------------------------------------------------------- /2-Build.bat: -------------------------------------------------------------------------------- 1 | 2 | @echo off 3 | 4 | cd "_Build" 5 | cmake --build . --config Release -j %NUMBER_OF_PROCESSORS% 6 | cmake --build . --config Debug -j %NUMBER_OF_PROCESSORS% 7 | cd .. 8 | -------------------------------------------------------------------------------- /2-Build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | mkdir -p "_Build" 4 | 5 | cd "_Build" 6 | cmake .. 7 | cmake --build . --config Release -j $(nproc) 8 | cmake --build . --config Debug -j $(nproc) 9 | cd .. 10 | -------------------------------------------------------------------------------- /3-Test samples.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | set DIR_DATA=_Data 4 | set DIR_BIN=_Bin\Release 5 | set ADAPTER=0 6 | 7 | if not exist "%DIR_BIN%" ( 8 | set DIR_BIN=_Bin\Debug 9 | ) 10 | 11 | if not exist "%DIR_BIN%" ( 12 | echo The project is not compiled! 13 | pause 14 | exit /b 15 | ) 16 | echo Running samples from '%DIR_BIN%'... 17 | echo. 18 | 19 | :: API independent samples 20 | "%DIR_BIN%\DeviceInfo.exe" 21 | if %ERRORLEVEL% equ 0 ( 22 | echo =^> OK 23 | ) else ( 24 | echo =^> FAILED! 25 | ) 26 | echo. 27 | 28 | :: API dependent samples 29 | call :TestSample AsyncCompute 30 | call :TestSample BindlessSceneViewer 31 | call :TestSample Buffers 32 | call :TestSample LowLatency 33 | call :TestSample MultiThreading 34 | call :TestSample Multiview 35 | call :TestSample Multisample 36 | call :TestSample RayTracingBoxes 37 | call :TestSample RayTracingTriangle 38 | call :TestSample Readback 39 | call :TestSample Resize 40 | call :TestSample SceneViewer 41 | call :TestSample Triangle 42 | call :TestSample Wrapper 43 | 44 | pause 45 | 46 | exit /b 47 | 48 | ::======================================================================================== 49 | :TestSample 50 | 51 | echo %1 [D3D11] 52 | "%DIR_BIN%\%1.exe" --api=D3D11 --timeLimit=3 --debugAPI --debugNRI --adapter=%ADAPTER% 53 | if %ERRORLEVEL% equ 0 ( 54 | echo =^> OK 55 | ) else ( 56 | echo =^> FAILED! 57 | ) 58 | echo. 59 | 60 | echo %1 [D3D12] 61 | "%DIR_BIN%\%1.exe" --api=D3D12 --timeLimit=3 --debugAPI --debugNRI --adapter=%ADAPTER% 62 | if %ERRORLEVEL% equ 0 ( 63 | echo =^> OK 64 | ) else ( 65 | echo =^> FAILED! 66 | ) 67 | echo. 68 | 69 | echo %1 [VULKAN] 70 | "%DIR_BIN%\%1.exe" --api=VULKAN --timeLimit=3 --debugAPI --debugNRI --adapter=%ADAPTER% 71 | if %ERRORLEVEL% equ 0 ( 72 | echo =^> OK 73 | ) else ( 74 | echo =^> FAILED! 75 | ) 76 | echo. 77 | 78 | exit /b 79 | -------------------------------------------------------------------------------- /4-Clean.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | rd /q /s "_Bin" 4 | rd /q /s "_Build" 5 | rd /q /s "_Data" 6 | rd /q /s "_Shaders" 7 | 8 | rd /q /s "build" 9 | 10 | cd "External/NRIFramework" 11 | call "4-Clean.bat" 12 | cd "../.." 13 | -------------------------------------------------------------------------------- /4-Clean.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | rm -rf "_Bin" 4 | rm -rf "_Build" 5 | rm -rf "_Data" 6 | rm -rf "_Shaders" 7 | 8 | rm -rf "build" 9 | 10 | cd "External/NRIFramework" 11 | source "4-Clean.sh" 12 | cd "../.." 13 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.30) 2 | 3 | # Options 4 | set(SHADER_OUTPUT_PATH "${CMAKE_CURRENT_SOURCE_DIR}/_Shaders") 5 | 6 | # Cached 7 | set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/_Bin" CACHE STRING "") 8 | 9 | get_property(IS_MULTI_CONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) 10 | 11 | if(IS_MULTI_CONFIG) 12 | set(CMAKE_CONFIGURATION_TYPES "Debug;Release" CACHE STRING "") 13 | endif() 14 | 15 | # Create project 16 | project(NRISamples LANGUAGES C CXX) 17 | 18 | if(APPLE) 19 | enable_language(OBJC) 20 | endif() 21 | 22 | # Globals? 23 | set_property(GLOBAL PROPERTY USE_FOLDERS ON) 24 | 25 | set(CMAKE_CXX_STANDARD 17) 26 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 27 | set(CMAKE_C_STANDARD 17) 28 | 29 | # Download dependencies using Packman 30 | if(WIN32) 31 | set(PACKMAN_EXT ".cmd") 32 | else() 33 | set(PACKMAN_EXT ".sh") 34 | endif() 35 | 36 | if((CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64") OR(CMAKE_SYSTEM_PROCESSOR MATCHES "AMD64")) 37 | if(WIN32) 38 | set(PACKMAN_PLATFORM "windows-x86_64") 39 | else() 40 | set(PACKMAN_PLATFORM "linux-x86_64") 41 | endif() 42 | elseif((CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64") OR(CMAKE_SYSTEM_PROCESSOR MATCHES "arm64")) 43 | set(PACKMAN_PLATFORM "linux-aarch64") 44 | else() 45 | message(FATAL_ERROR "Unsupported architecture: '${CMAKE_SYSTEM_PROCESSOR}'") 46 | endif() 47 | 48 | message("Packman platform: ${PACKMAN_PLATFORM}") 49 | 50 | execute_process(COMMAND "${CMAKE_CURRENT_SOURCE_DIR}/External/Packman/packman${PACKMAN_EXT}" pull "${CMAKE_CURRENT_SOURCE_DIR}/Dependencies.xml" -p ${PACKMAN_PLATFORM} -t nri_data_version=2.3_minimal 51 | WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" 52 | RESULT_VARIABLE PACKMAN_RESULT) 53 | 54 | if(NOT "${PACKMAN_RESULT}" STREQUAL "0") 55 | message(FATAL_ERROR "Packman failed(code = ${PACKMAN_RESULT})") 56 | endif() 57 | 58 | # Compile options 59 | if(NOT((CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64") OR(CMAKE_SYSTEM_PROCESSOR MATCHES "arm64"))) 60 | set(SIMD -mssse3) 61 | endif() 62 | 63 | if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") 64 | set(COMPILE_OPTIONS ${SIMD} -Wextra -Wno-missing-field-initializers) 65 | elseif(CMAKE_CXX_COMPILER_ID MATCHES "GNU") 66 | set(COMPILE_OPTIONS ${SIMD} -Wextra -Wno-missing-field-initializers) 67 | elseif(MSVC) 68 | set(COMPILE_OPTIONS /W4 /WX 69 | /wd4324 # padding was added at the end of a structure because you specified an alignment specifier 70 | ) 71 | else() 72 | message(WARNING "Unknown compiler!") 73 | endif() 74 | 75 | # Compile definitions 76 | if(WIN32) 77 | set(COMPILE_DEFINITIONS WIN32_LEAN_AND_MEAN NOMINMAX _CRT_SECURE_NO_WARNINGS) 78 | endif() 79 | 80 | # External/NRIFramework 81 | set(NRIF_SHADERS_PATH "${SHADER_OUTPUT_PATH}" CACHE STRING "") 82 | add_subdirectory("External/NRIFramework") 83 | 84 | # Move dependencies into "External" 85 | function(fix_folders _DIRECTORY _FOLDER) 86 | get_property(_TARGETS DIRECTORY "${_DIRECTORY}" PROPERTY BUILDSYSTEM_TARGETS) 87 | 88 | foreach(_TARGET IN LISTS _TARGETS) 89 | get_property(_FOLDER_ORIGINAL TARGET ${_TARGET} PROPERTY FOLDER) 90 | set_property(TARGET ${_TARGET} PROPERTY FOLDER "${_FOLDER}/${_FOLDER_ORIGINAL}") 91 | endforeach() 92 | 93 | get_property(SUBDIRS DIRECTORY "${_DIRECTORY}" PROPERTY SUBDIRECTORIES) 94 | 95 | foreach(SUBDIR IN LISTS SUBDIRS) 96 | fix_folders("${SUBDIR}" "${_FOLDER}") 97 | endforeach() 98 | endfunction() 99 | 100 | fix_folders("External/NRIFramework" "External") 101 | 102 | # Shaders 103 | file(GLOB_RECURSE SHADERS "Shaders/*.hlsl" "Shaders/*.hlsli") 104 | set_source_files_properties(${SHADERS} PROPERTIES VS_TOOL_OVERRIDE "None") 105 | 106 | get_target_property(ML_SOURCE_DIR MathLib SOURCE_DIR) 107 | get_target_property(NRI_SOURCE_DIR NRI SOURCE_DIR) 108 | 109 | set(SHADERMAKE_GENERAL_ARGS 110 | --project "NRISamples" 111 | --compactProgress 112 | --binary 113 | --flatten 114 | --stripReflection 115 | --WX 116 | --sRegShift 0 --bRegShift 32 --uRegShift 64 --tRegShift 128 # TODO: must be in sync with "VK_BINDING_OFFSETS" 117 | --sourceDir "Shaders" 118 | --ignoreConfigDir 119 | -c "Shaders/Shaders.cfg" 120 | -o "${SHADER_OUTPUT_PATH}" 121 | -I "Shaders" 122 | -I "${ML_SOURCE_DIR}" 123 | -I "${NRI_SOURCE_DIR}/Include" 124 | ) 125 | 126 | set(SHADERMAKE_COMMANDS "") 127 | 128 | if(NRI_ENABLE_D3D11_SUPPORT) 129 | set(SHADERMAKE_COMMANDS ${SHADERMAKE_COMMANDS} COMMAND ${SHADERMAKE_PATH} -p DXBC --compiler "${SHADERMAKE_FXC_PATH}" ${SHADERMAKE_GENERAL_ARGS}) 130 | endif() 131 | 132 | if(NRI_ENABLE_D3D12_SUPPORT) 133 | set(SHADERMAKE_COMMANDS ${SHADERMAKE_COMMANDS} COMMAND ${SHADERMAKE_PATH} -p DXIL --compiler "${SHADERMAKE_DXC_PATH}" ${SHADERMAKE_GENERAL_ARGS}) 134 | endif() 135 | 136 | if(NRI_ENABLE_VK_SUPPORT) 137 | set(SHADERMAKE_COMMANDS ${SHADERMAKE_COMMANDS} COMMAND ${SHADERMAKE_PATH} -p SPIRV --compiler "${SHADERMAKE_DXC_VK_PATH}" ${SHADERMAKE_GENERAL_ARGS}) 138 | endif() 139 | 140 | add_custom_target(${PROJECT_NAME}Shaders ALL 141 | ${SHADERMAKE_COMMANDS} 142 | DEPENDS ShaderMake 143 | WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" 144 | VERBATIM 145 | SOURCES ${SHADERS} 146 | ) 147 | 148 | set_property(TARGET ${PROJECT_NAME}Shaders PROPERTY FOLDER ${PROJECT_NAME}) 149 | 150 | # Samples 151 | function(add_sample NAME EXT) 152 | add_executable(${NAME} "Source/${NAME}.${EXT}") 153 | source_group("" FILES "Source/${NAME}.${EXT}") 154 | add_dependencies(${NAME} ${PROJECT_NAME}Shaders) 155 | 156 | target_compile_definitions(${NAME} PRIVATE ${COMPILE_DEFINITIONS} PROJECT_NAME=${NAME}) 157 | target_compile_options(${NAME} PRIVATE ${COMPILE_OPTIONS}) 158 | target_link_libraries(${NAME} PRIVATE NRIFramework NRI) 159 | 160 | set_property(TARGET ${NAME} PROPERTY FOLDER ${PROJECT_NAME}) 161 | set_property(TARGET ${NAME} PROPERTY VS_DEBUGGER_WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}") 162 | 163 | # Copy arguments for Visual Studio Smart Command Line Arguments extension 164 | if(WIN32 AND MSVC) 165 | configure_file(.args "${CMAKE_BINARY_DIR}/${NAME}.args.json" COPYONLY) 166 | endif() 167 | endfunction() 168 | 169 | add_sample(AsyncCompute cpp) 170 | add_sample(Clear cpp) 171 | add_sample(Buffers c) 172 | add_sample(DeviceInfo c) 173 | add_sample(LowLatency cpp) 174 | add_sample(Multisample cpp) 175 | add_sample(MultiThreading cpp) 176 | add_sample(Multiview cpp) 177 | add_sample(RayTracingTriangle cpp) 178 | add_sample(RayTracingBoxes cpp) 179 | add_sample(Readback cpp) 180 | add_sample(SceneViewer cpp) 181 | add_sample(BindlessSceneViewer cpp) 182 | add_sample(Triangle cpp) 183 | add_sample(Resize cpp) 184 | 185 | # Wrapper depends on Vulkan SDK availability 186 | if(DEFINED ENV{VULKAN_SDK}) 187 | add_sample(Wrapper cpp) 188 | target_include_directories(Wrapper PRIVATE "$ENV{VULKAN_SDK}/include") 189 | 190 | if(WIN32) 191 | target_link_libraries(Wrapper PRIVATE d3d11 d3d12) 192 | endif() 193 | endif() 194 | -------------------------------------------------------------------------------- /Dependencies.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /External/Packman/bootstrap/configure.bat: -------------------------------------------------------------------------------- 1 | :: Copyright 2019-2023 NVIDIA CORPORATION 2 | :: 3 | :: Licensed under the Apache License, Version 2.0 (the "License"); 4 | :: you may not use this file except in compliance with the License. 5 | :: You may obtain a copy of the License at 6 | :: 7 | :: http://www.apache.org/licenses/LICENSE-2.0 8 | :: 9 | :: Unless required by applicable law or agreed to in writing, software 10 | :: distributed under the License is distributed on an "AS IS" BASIS, 11 | :: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | :: See the License for the specific language governing permissions and 13 | :: limitations under the License. 14 | 15 | set PM_PACKMAN_VERSION=7.18.1 16 | 17 | :: Specify where packman command is rooted 18 | set PM_INSTALL_PATH=%~dp0.. 19 | 20 | :: The external root may already be configured and we should do minimal work in that case 21 | if defined PM_PACKAGES_ROOT goto ENSURE_DIR 22 | 23 | :: If the folder isn't set we assume that the best place for it is on the drive that we are currently 24 | :: running from 25 | set PM_DRIVE=%CD:~0,2% 26 | 27 | set PM_PACKAGES_ROOT=%PM_DRIVE%\packman-repo 28 | 29 | :: We use *setx* here so that the variable is persisted in the user environment 30 | echo Setting user environment variable PM_PACKAGES_ROOT to %PM_PACKAGES_ROOT% 31 | setx PM_PACKAGES_ROOT %PM_PACKAGES_ROOT% 32 | if %errorlevel% neq 0 ( goto ERROR ) 33 | 34 | :: The above doesn't work properly from a build step in VisualStudio because a separate process is 35 | :: spawned for it so it will be lost for subsequent compilation steps - VisualStudio must 36 | :: be launched from a new process. We catch this odd-ball case here: 37 | if defined PM_DISABLE_VS_WARNING goto ENSURE_DIR 38 | if not defined VSLANG goto ENSURE_DIR 39 | echo The above is a once-per-computer operation. Unfortunately VisualStudio cannot pick up environment change 40 | echo unless *VisualStudio is RELAUNCHED*. 41 | echo If you are launching VisualStudio from command line or command line utility make sure 42 | echo you have a fresh launch environment (relaunch the command line or utility). 43 | echo If you are using 'linkPath' and referring to packages via local folder links you can safely ignore this warning. 44 | echo You can disable this warning by setting the environment variable PM_DISABLE_VS_WARNING. 45 | echo. 46 | 47 | :: Check for the directory that we need. Note that mkdir will create any directories 48 | :: that may be needed in the path 49 | :ENSURE_DIR 50 | if not exist "%PM_PACKAGES_ROOT%" ( 51 | echo Creating packman packages cache at %PM_PACKAGES_ROOT% 52 | mkdir "%PM_PACKAGES_ROOT%" 53 | ) 54 | if %errorlevel% neq 0 ( goto ERROR_MKDIR_PACKAGES_ROOT ) 55 | 56 | :: The Python interpreter may already be externally configured 57 | if defined PM_PYTHON_EXT ( 58 | set PM_PYTHON=%PM_PYTHON_EXT% 59 | goto PACKMAN 60 | ) 61 | 62 | set PM_PYTHON_VERSION=3.10.5-1-windows-x86_64 63 | set PM_PYTHON_BASE_DIR=%PM_PACKAGES_ROOT%\python 64 | set PM_PYTHON_DIR=%PM_PYTHON_BASE_DIR%\%PM_PYTHON_VERSION% 65 | set PM_PYTHON=%PM_PYTHON_DIR%\python.exe 66 | 67 | if exist "%PM_PYTHON%" goto PACKMAN 68 | if not exist "%PM_PYTHON_BASE_DIR%" call :CREATE_PYTHON_BASE_DIR 69 | 70 | set PM_PYTHON_PACKAGE=python@%PM_PYTHON_VERSION%.cab 71 | for /f "delims=" %%a in ('powershell -ExecutionPolicy ByPass -NoLogo -NoProfile -File "%~dp0\generate_temp_file_name.ps1"') do set TEMP_FILE_NAME=%%a 72 | set TARGET=%TEMP_FILE_NAME%.zip 73 | call "%~dp0fetch_file_from_packman_bootstrap.cmd" %PM_PYTHON_PACKAGE% "%TARGET%" 74 | if %errorlevel% neq 0 ( 75 | echo !!! Error fetching python from CDN !!! 76 | goto ERROR 77 | ) 78 | 79 | for /f "delims=" %%a in ('powershell -ExecutionPolicy ByPass -NoLogo -NoProfile -File "%~dp0\generate_temp_folder.ps1" -parentPath "%PM_PYTHON_BASE_DIR%"') do set TEMP_FOLDER_NAME=%%a 80 | echo Unpacking Python interpreter ... 81 | "%SystemRoot%\system32\expand.exe" -F:* "%TARGET%" "%TEMP_FOLDER_NAME%" 1> nul 82 | del "%TARGET%" 83 | :: Failure during extraction to temp folder name, need to clean up and abort 84 | if %errorlevel% neq 0 ( 85 | echo !!! Error unpacking python !!! 86 | call :CLEAN_UP_TEMP_FOLDER 87 | goto ERROR 88 | ) 89 | 90 | :: If python has now been installed by a concurrent process we need to clean up and then continue 91 | if exist "%PM_PYTHON%" ( 92 | call :CLEAN_UP_TEMP_FOLDER 93 | goto PACKMAN 94 | ) else ( 95 | if exist "%PM_PYTHON_DIR%" ( rd /s /q "%PM_PYTHON_DIR%" > nul ) 96 | ) 97 | 98 | :: Perform atomic move (allowing overwrite, /y) 99 | move /y "%TEMP_FOLDER_NAME%" "%PM_PYTHON_DIR%" 1> nul 100 | :: Verify that python.exe is now where we expect 101 | if exist "%PM_PYTHON%" goto PACKMAN 102 | 103 | :: Wait a second and try again (can help with access denied weirdness) 104 | timeout /t 1 /nobreak 1> nul 105 | move /y "%TEMP_FOLDER_NAME%" "%PM_PYTHON_DIR%" 1> nul 106 | if %errorlevel% neq 0 ( 107 | echo !!! Error moving python %TEMP_FOLDER_NAME% -> %PM_PYTHON_DIR% !!! 108 | call :CLEAN_UP_TEMP_FOLDER 109 | goto ERROR 110 | ) 111 | 112 | :PACKMAN 113 | :: The packman module may already be externally configured 114 | if defined PM_MODULE_DIR_EXT ( 115 | set PM_MODULE_DIR=%PM_MODULE_DIR_EXT% 116 | ) else ( 117 | set PM_MODULE_DIR=%PM_PACKAGES_ROOT%\packman-common\%PM_PACKMAN_VERSION% 118 | ) 119 | 120 | set PM_MODULE=%PM_MODULE_DIR%\run.py 121 | 122 | if exist "%PM_MODULE%" goto END 123 | 124 | :: Clean out broken PM_MODULE_DIR if it exists 125 | if exist "%PM_MODULE_DIR%" ( rd /s /q "%PM_MODULE_DIR%" > nul ) 126 | 127 | set PM_MODULE_PACKAGE=packman-common@%PM_PACKMAN_VERSION%.zip 128 | for /f "delims=" %%a in ('powershell -ExecutionPolicy ByPass -NoLogo -NoProfile -File "%~dp0\generate_temp_file_name.ps1"') do set TEMP_FILE_NAME=%%a 129 | set TARGET=%TEMP_FILE_NAME% 130 | call "%~dp0fetch_file_from_packman_bootstrap.cmd" %PM_MODULE_PACKAGE% "%TARGET%" 131 | if %errorlevel% neq 0 ( 132 | echo !!! Error fetching packman from CDN !!! 133 | goto ERROR 134 | ) 135 | 136 | echo Unpacking ... 137 | "%PM_PYTHON%" -S -s -u -E "%~dp0\install_package.py" "%TARGET%" "%PM_MODULE_DIR%" 138 | if %errorlevel% neq 0 ( 139 | echo !!! Error unpacking packman !!! 140 | goto ERROR 141 | ) 142 | 143 | del "%TARGET%" 144 | 145 | goto END 146 | 147 | :ERROR_MKDIR_PACKAGES_ROOT 148 | echo Failed to automatically create packman packages repo at %PM_PACKAGES_ROOT%. 149 | echo Please set a location explicitly that packman has permission to write to, by issuing: 150 | echo. 151 | echo setx PM_PACKAGES_ROOT {path-you-choose-for-storing-packman-packages-locally} 152 | echo. 153 | echo Then launch a new command console for the changes to take effect and run packman command again. 154 | exit /B %errorlevel% 155 | 156 | :ERROR 157 | echo !!! Failure while configuring local machine :( !!! 158 | exit /B %errorlevel% 159 | 160 | :CLEAN_UP_TEMP_FOLDER 161 | rd /S /Q "%TEMP_FOLDER_NAME%" 162 | exit /B 163 | 164 | :CREATE_PYTHON_BASE_DIR 165 | :: We ignore errors and clean error state - if two processes create the directory one will fail which is fine 166 | md "%PM_PYTHON_BASE_DIR%" > nul 2>&1 167 | exit /B 0 168 | 169 | :END 170 | -------------------------------------------------------------------------------- /External/Packman/bootstrap/download_file_from_url.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | Copyright 2019 NVIDIA CORPORATION 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | #> 16 | 17 | param( 18 | [Parameter(Mandatory=$true)][string]$source=$null, 19 | [string]$output="out.exe" 20 | ) 21 | $filename = $output 22 | 23 | $triesLeft = 4 24 | $delay = 2 25 | do 26 | { 27 | $triesLeft -= 1 28 | 29 | try 30 | { 31 | Write-Host "Downloading from bootstrap.packman.nvidia.com ..." 32 | $wc = New-Object net.webclient 33 | $wc.Downloadfile($source, $fileName) 34 | exit 0 35 | } 36 | catch 37 | { 38 | Write-Host "Error downloading $source!" 39 | Write-Host $_.Exception|format-list -force 40 | if ($triesLeft) 41 | { 42 | Write-Host "Retrying in $delay seconds ..." 43 | Start-Sleep -seconds $delay 44 | } 45 | $delay = $delay * $delay 46 | } 47 | } while ($triesLeft -gt 0) 48 | # We only get here if the retries have been exhausted, remove any left-overs: 49 | if (Test-Path $fileName) 50 | { 51 | Remove-Item $fileName 52 | } 53 | exit 1 -------------------------------------------------------------------------------- /External/Packman/bootstrap/fetch_file_from_packman_bootstrap.cmd: -------------------------------------------------------------------------------- 1 | :: Copyright 2019 NVIDIA CORPORATION 2 | :: 3 | :: Licensed under the Apache License, Version 2.0 (the "License"); 4 | :: you may not use this file except in compliance with the License. 5 | :: You may obtain a copy of the License at 6 | :: 7 | :: http://www.apache.org/licenses/LICENSE-2.0 8 | :: 9 | :: Unless required by applicable law or agreed to in writing, software 10 | :: distributed under the License is distributed on an "AS IS" BASIS, 11 | :: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | :: See the License for the specific language governing permissions and 13 | :: limitations under the License. 14 | 15 | :: You need to specify as input to this command 16 | @setlocal 17 | @set PACKAGE_NAME=%1 18 | @set TARGET_PATH=%2 19 | 20 | @echo Fetching %PACKAGE_NAME% ... 21 | 22 | @powershell -ExecutionPolicy ByPass -NoLogo -NoProfile -File "%~dp0download_file_from_url.ps1" ^ 23 | -source "http://bootstrap.packman.nvidia.com/%PACKAGE_NAME%" -output %TARGET_PATH% 24 | :: A bug in powershell prevents the errorlevel code from being set when using the -File execution option 25 | :: We must therefore do our own failure analysis, basically make sure the file exists: 26 | @if not exist %TARGET_PATH% goto ERROR_DOWNLOAD_FAILED 27 | 28 | @endlocal 29 | @exit /b 0 30 | 31 | :ERROR_DOWNLOAD_FAILED 32 | @echo Failed to download file from S3 33 | @echo Most likely because endpoint cannot be reached or file %PACKAGE_NAME% doesn't exist 34 | @endlocal 35 | @exit /b 1 -------------------------------------------------------------------------------- /External/Packman/bootstrap/generate_temp_file_name.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | Copyright 2019 NVIDIA CORPORATION 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | #> 16 | 17 | $out = [System.IO.Path]::GetTempFileName() 18 | Write-Host $out 19 | # SIG # Begin signature block 20 | # MIIaVwYJKoZIhvcNAQcCoIIaSDCCGkQCAQExDzANBglghkgBZQMEAgEFADB5Bgor 21 | # BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG 22 | # KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCAK+Ewup1N0/mdf 23 | # 1l4R58rxyumHgZvTmEhrYTb2Zf0zd6CCCiIwggTTMIIDu6ADAgECAhBi50XpIWUh 24 | # PJcfXEkK6hKlMA0GCSqGSIb3DQEBCwUAMIGEMQswCQYDVQQGEwJVUzEdMBsGA1UE 25 | # ChMUU3ltYW50ZWMgQ29ycG9yYXRpb24xHzAdBgNVBAsTFlN5bWFudGVjIFRydXN0 26 | # IE5ldHdvcmsxNTAzBgNVBAMTLFN5bWFudGVjIENsYXNzIDMgU0hBMjU2IENvZGUg 27 | # U2lnbmluZyBDQSAtIEcyMB4XDTE4MDcwOTAwMDAwMFoXDTIxMDcwOTIzNTk1OVow 28 | # gYMxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRQwEgYDVQQHDAtT 29 | # YW50YSBDbGFyYTEbMBkGA1UECgwSTlZJRElBIENvcnBvcmF0aW9uMQ8wDQYDVQQL 30 | # DAZJVC1NSVMxGzAZBgNVBAMMEk5WSURJQSBDb3Jwb3JhdGlvbjCCASIwDQYJKoZI 31 | # hvcNAQEBBQADggEPADCCAQoCggEBALEZN63dA47T4i90jZ84CJ/aWUwVtLff8AyP 32 | # YspFfIZGdZYiMgdb8A5tBh7653y0G/LZL6CVUkgejcpvBU/Dl/52a+gSWy2qJ2bH 33 | # jMFMKCyQDhdpCAKMOUKSC9rfzm4cFeA9ct91LQCAait4LhLlZt/HF7aG+r0FgCZa 34 | # HJjJvE7KNY9G4AZXxjSt8CXS8/8NQMANqjLX1r+F+Hl8PzQ1fVx0mMsbdtaIV4Pj 35 | # 5flAeTUnz6+dCTx3vTUo8MYtkS2UBaQv7t7H2B7iwJDakEQKk1XHswJdeqG0osDU 36 | # z6+NVks7uWE1N8UIhvzbw0FEX/U2kpfyWaB/J3gMl8rVR8idPj8CAwEAAaOCAT4w 37 | # ggE6MAkGA1UdEwQCMAAwDgYDVR0PAQH/BAQDAgeAMBMGA1UdJQQMMAoGCCsGAQUF 38 | # BwMDMGEGA1UdIARaMFgwVgYGZ4EMAQQBMEwwIwYIKwYBBQUHAgEWF2h0dHBzOi8v 39 | # ZC5zeW1jYi5jb20vY3BzMCUGCCsGAQUFBwICMBkMF2h0dHBzOi8vZC5zeW1jYi5j 40 | # b20vcnBhMB8GA1UdIwQYMBaAFNTABiJJ6zlL3ZPiXKG4R3YJcgNYMCsGA1UdHwQk 41 | # MCIwIKAeoByGGmh0dHA6Ly9yYi5zeW1jYi5jb20vcmIuY3JsMFcGCCsGAQUFBwEB 42 | # BEswSTAfBggrBgEFBQcwAYYTaHR0cDovL3JiLnN5bWNkLmNvbTAmBggrBgEFBQcw 43 | # AoYaaHR0cDovL3JiLnN5bWNiLmNvbS9yYi5jcnQwDQYJKoZIhvcNAQELBQADggEB 44 | # AIJKh5vKJdhHJtMzATmc1BmXIQ3RaJONOZ5jMHn7HOkYU1JP0OIzb4pXXkH8Xwfr 45 | # K6bnd72IhcteyksvKsGpSvK0PBBwzodERTAu1Os2N+EaakxQwV/xtqDm1E3IhjHk 46 | # fRshyKKzmFk2Ci323J4lHtpWUj5Hz61b8gd72jH7xnihGi+LORJ2uRNZ3YuqMNC3 47 | # SBC8tAyoJqEoTJirULUCXW6wX4XUm5P2sx+htPw7szGblVKbQ+PFinNGnsSEZeKz 48 | # D8jUb++1cvgTKH59Y6lm43nsJjkZU77tNqyq4ABwgQRk6lt8cS2PPwjZvTmvdnla 49 | # ZhR0K4of+pQaUQHXVIBdji8wggVHMIIEL6ADAgECAhB8GzU1SufbdOdBXxFpymuo 50 | # MA0GCSqGSIb3DQEBCwUAMIG9MQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNp 51 | # Z24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNV 52 | # BAsTMShjKSAyMDA4IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNl 53 | # IG9ubHkxODA2BgNVBAMTL1ZlcmlTaWduIFVuaXZlcnNhbCBSb290IENlcnRpZmlj 54 | # YXRpb24gQXV0aG9yaXR5MB4XDTE0MDcyMjAwMDAwMFoXDTI0MDcyMTIzNTk1OVow 55 | # gYQxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEf 56 | # MB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazE1MDMGA1UEAxMsU3ltYW50 57 | # ZWMgQ2xhc3MgMyBTSEEyNTYgQ29kZSBTaWduaW5nIENBIC0gRzIwggEiMA0GCSqG 58 | # SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDXlUPU3N9nrjn7UqS2JjEEcOm3jlsqujdp 59 | # NZWPu8Aw54bYc7vf69F2P4pWjustS/BXGE6xjaUz0wt1I9VqeSfdo9P3Dodltd6t 60 | # HPH1NbQiUa8iocFdS5B/wFlOq515qQLXHkmxO02H/sJ4q7/vUq6crwjZOeWaUT5p 61 | # XzAQTnFjbFjh8CAzGw90vlvLEuHbjMSAlHK79kWansElC/ujHJ7YpglwcezAR0yP 62 | # fcPeGc4+7gRyjhfT//CyBTIZTNOwHJ/+pXggQnBBsCaMbwDIOgARQXpBsKeKkQSg 63 | # mXj0d7TzYCrmbFAEtxRg/w1R9KiLhP4h2lxeffUpeU+wRHRvbXL/AgMBAAGjggF4 64 | # MIIBdDAuBggrBgEFBQcBAQQiMCAwHgYIKwYBBQUHMAGGEmh0dHA6Ly9zLnN5bWNk 65 | # LmNvbTASBgNVHRMBAf8ECDAGAQH/AgEAMGYGA1UdIARfMF0wWwYLYIZIAYb4RQEH 66 | # FwMwTDAjBggrBgEFBQcCARYXaHR0cHM6Ly9kLnN5bWNiLmNvbS9jcHMwJQYIKwYB 67 | # BQUHAgIwGRoXaHR0cHM6Ly9kLnN5bWNiLmNvbS9ycGEwNgYDVR0fBC8wLTAroCmg 68 | # J4YlaHR0cDovL3Muc3ltY2IuY29tL3VuaXZlcnNhbC1yb290LmNybDATBgNVHSUE 69 | # DDAKBggrBgEFBQcDAzAOBgNVHQ8BAf8EBAMCAQYwKQYDVR0RBCIwIKQeMBwxGjAY 70 | # BgNVBAMTEVN5bWFudGVjUEtJLTEtNzI0MB0GA1UdDgQWBBTUwAYiSes5S92T4lyh 71 | # uEd2CXIDWDAfBgNVHSMEGDAWgBS2d/ppSEefUxLVwuoHMnYH0ZcHGTANBgkqhkiG 72 | # 9w0BAQsFAAOCAQEAf+vKp+qLdkLrPo4gVDDjt7nc+kg+FscPRZUQzSeGo2bzAu1x 73 | # +KrCVZeRcIP5Un5SaTzJ8eCURoAYu6HUpFam8x0AkdWG80iH4MvENGggXrTL+QXt 74 | # nK9wUye56D5+UaBpcYvcUe2AOiUyn0SvbkMo0yF1u5fYi4uM/qkERgSF9xWcSxGN 75 | # xCwX/tVuf5riVpLxlrOtLfn039qJmc6yOETA90d7yiW5+ipoM5tQct6on9TNLAs0 76 | # vYsweEDgjY4nG5BvGr4IFYFd6y/iUedRHsl4KeceZb847wFKAQkkDhbEFHnBQTc0 77 | # 0D2RUpSd4WjvCPDiaZxnbpALGpNx1CYCw8BaIzGCD4swgg+HAgEBMIGZMIGEMQsw 78 | # CQYDVQQGEwJVUzEdMBsGA1UEChMUU3ltYW50ZWMgQ29ycG9yYXRpb24xHzAdBgNV 79 | # BAsTFlN5bWFudGVjIFRydXN0IE5ldHdvcmsxNTAzBgNVBAMTLFN5bWFudGVjIENs 80 | # YXNzIDMgU0hBMjU2IENvZGUgU2lnbmluZyBDQSAtIEcyAhBi50XpIWUhPJcfXEkK 81 | # 6hKlMA0GCWCGSAFlAwQCAQUAoHwwEAYKKwYBBAGCNwIBDDECMAAwGQYJKoZIhvcN 82 | # AQkDMQwGCisGAQQBgjcCAQQwHAYKKwYBBAGCNwIBCzEOMAwGCisGAQQBgjcCARUw 83 | # LwYJKoZIhvcNAQkEMSIEIPW+EpFrZSdzrjFFo0UT+PzFeYn/GcWNyWFaU/JMrMfR 84 | # MA0GCSqGSIb3DQEBAQUABIIBAA8fmU/RJcF9t60DZZAjf8FB3EZddOaHgI9z40nV 85 | # CnfTGi0OEYU48Pe9jkQQV2fABpACfW74xmNv3QNgP2qP++mkpKBVv28EIAuINsFt 86 | # YAITEljLN/VOVul8lvjxar5GSFFgpE5F6j4xcvI69LuCWbN8cteTVsBGg+eGmjfx 87 | # QZxP252z3FqPN+mihtFegF2wx6Mg6/8jZjkO0xjBOwSdpTL4uyQfHvaPBKXuWxRx 88 | # ioXw4ezGAwkuBoxWK8UG7Qu+7CSfQ3wMOjvyH2+qn30lWEsvRMdbGAp7kvfr3EGZ 89 | # a3WN7zXZ+6KyZeLeEH7yCDzukAjptaY/+iLVjJsuzC6tCSqhgg1EMIINQAYKKwYB 90 | # BAGCNwMDATGCDTAwgg0sBgkqhkiG9w0BBwKggg0dMIINGQIBAzEPMA0GCWCGSAFl 91 | # AwQCAQUAMHcGCyqGSIb3DQEJEAEEoGgEZjBkAgEBBglghkgBhv1sBwEwMTANBglg 92 | # hkgBZQMEAgEFAAQg14BnPazQkW9whhZu1d0bC3lqqScvxb3SSb1QT8e3Xg0CEFhw 93 | # aMBZ2hExXhr79A9+bXEYDzIwMjEwNDA4MDkxMTA5WqCCCjcwggT+MIID5qADAgEC 94 | # AhANQkrgvjqI/2BAIc4UAPDdMA0GCSqGSIb3DQEBCwUAMHIxCzAJBgNVBAYTAlVT 95 | # MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j 96 | # b20xMTAvBgNVBAMTKERpZ2lDZXJ0IFNIQTIgQXNzdXJlZCBJRCBUaW1lc3RhbXBp 97 | # bmcgQ0EwHhcNMjEwMTAxMDAwMDAwWhcNMzEwMTA2MDAwMDAwWjBIMQswCQYDVQQG 98 | # EwJVUzEXMBUGA1UEChMORGlnaUNlcnQsIEluYy4xIDAeBgNVBAMTF0RpZ2lDZXJ0 99 | # IFRpbWVzdGFtcCAyMDIxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA 100 | # wuZhhGfFivUNCKRFymNrUdc6EUK9CnV1TZS0DFC1JhD+HchvkWsMlucaXEjvROW/ 101 | # m2HNFZFiWrj/ZwucY/02aoH6KfjdK3CF3gIY83htvH35x20JPb5qdofpir34hF0e 102 | # dsnkxnZ2OlPR0dNaNo/Go+EvGzq3YdZz7E5tM4p8XUUtS7FQ5kE6N1aG3JMjjfdQ 103 | # Jehk5t3Tjy9XtYcg6w6OLNUj2vRNeEbjA4MxKUpcDDGKSoyIxfcwWvkUrxVfbENJ 104 | # Cf0mI1P2jWPoGqtbsR0wwptpgrTb/FZUvB+hh6u+elsKIC9LCcmVp42y+tZji06l 105 | # chzun3oBc/gZ1v4NSYS9AQIDAQABo4IBuDCCAbQwDgYDVR0PAQH/BAQDAgeAMAwG 106 | # A1UdEwEB/wQCMAAwFgYDVR0lAQH/BAwwCgYIKwYBBQUHAwgwQQYDVR0gBDowODA2 107 | # BglghkgBhv1sBwEwKTAnBggrBgEFBQcCARYbaHR0cDovL3d3dy5kaWdpY2VydC5j 108 | # b20vQ1BTMB8GA1UdIwQYMBaAFPS24SAd/imu0uRhpbKiJbLIFzVuMB0GA1UdDgQW 109 | # BBQ2RIaOpLqwZr68KC0dRDbd42p6vDBxBgNVHR8EajBoMDKgMKAuhixodHRwOi8v 110 | # Y3JsMy5kaWdpY2VydC5jb20vc2hhMi1hc3N1cmVkLXRzLmNybDAyoDCgLoYsaHR0 111 | # cDovL2NybDQuZGlnaWNlcnQuY29tL3NoYTItYXNzdXJlZC10cy5jcmwwgYUGCCsG 112 | # AQUFBwEBBHkwdzAkBggrBgEFBQcwAYYYaHR0cDovL29jc3AuZGlnaWNlcnQuY29t 113 | # ME8GCCsGAQUFBzAChkNodHRwOi8vY2FjZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNl 114 | # cnRTSEEyQXNzdXJlZElEVGltZXN0YW1waW5nQ0EuY3J0MA0GCSqGSIb3DQEBCwUA 115 | # A4IBAQBIHNy16ZojvOca5yAOjmdG/UJyUXQKI0ejq5LSJcRwWb4UoOUngaVNFBUZ 116 | # B3nw0QTDhtk7vf5EAmZN7WmkD/a4cM9i6PVRSnh5Nnont/PnUp+Tp+1DnnvntN1B 117 | # Ion7h6JGA0789P63ZHdjXyNSaYOC+hpT7ZDMjaEXcw3082U5cEvznNZ6e9oMvD0y 118 | # 0BvL9WH8dQgAdryBDvjA4VzPxBFy5xtkSdgimnUVQvUtMjiB2vRgorq0Uvtc4GEk 119 | # JU+y38kpqHNDUdq9Y9YfW5v3LhtPEx33Sg1xfpe39D+E68Hjo0mh+s6nv1bPull2 120 | # YYlffqe0jmd4+TaY4cso2luHpoovMIIFMTCCBBmgAwIBAgIQCqEl1tYyG35B5AXa 121 | # NpfCFTANBgkqhkiG9w0BAQsFADBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGln 122 | # aUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtE 123 | # aWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0EwHhcNMTYwMTA3MTIwMDAwWhcNMzEw 124 | # MTA3MTIwMDAwWjByMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5j 125 | # MRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMTEwLwYDVQQDEyhEaWdpQ2VydCBT 126 | # SEEyIEFzc3VyZWQgSUQgVGltZXN0YW1waW5nIENBMIIBIjANBgkqhkiG9w0BAQEF 127 | # AAOCAQ8AMIIBCgKCAQEAvdAy7kvNj3/dqbqCmcU5VChXtiNKxA4HRTNREH3Q+X1N 128 | # aH7ntqD0jbOI5Je/YyGQmL8TvFfTw+F+CNZqFAA49y4eO+7MpvYyWf5fZT/gm+vj 129 | # RkcGGlV+Cyd+wKL1oODeIj8O/36V+/OjuiI+GKwR5PCZA207hXwJ0+5dyJoLVOOo 130 | # CXFr4M8iEA91z3FyTgqt30A6XLdR4aF5FMZNJCMwXbzsPGBqrC8HzP3w6kfZiFBe 131 | # /WZuVmEnKYmEUeaC50ZQ/ZQqLKfkdT66mA+Ef58xFNat1fJky3seBdCEGXIX8RcG 132 | # 7z3N1k3vBkL9olMqT4UdxB08r8/arBD13ays6Vb/kwIDAQABo4IBzjCCAcowHQYD 133 | # VR0OBBYEFPS24SAd/imu0uRhpbKiJbLIFzVuMB8GA1UdIwQYMBaAFEXroq/0ksuC 134 | # MS1Ri6enIZ3zbcgPMBIGA1UdEwEB/wQIMAYBAf8CAQAwDgYDVR0PAQH/BAQDAgGG 135 | # MBMGA1UdJQQMMAoGCCsGAQUFBwMIMHkGCCsGAQUFBwEBBG0wazAkBggrBgEFBQcw 136 | # AYYYaHR0cDovL29jc3AuZGlnaWNlcnQuY29tMEMGCCsGAQUFBzAChjdodHRwOi8v 137 | # Y2FjZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNlcnRBc3N1cmVkSURSb290Q0EuY3J0 138 | # MIGBBgNVHR8EejB4MDqgOKA2hjRodHRwOi8vY3JsNC5kaWdpY2VydC5jb20vRGln 139 | # aUNlcnRBc3N1cmVkSURSb290Q0EuY3JsMDqgOKA2hjRodHRwOi8vY3JsMy5kaWdp 140 | # Y2VydC5jb20vRGlnaUNlcnRBc3N1cmVkSURSb290Q0EuY3JsMFAGA1UdIARJMEcw 141 | # OAYKYIZIAYb9bAACBDAqMCgGCCsGAQUFBwIBFhxodHRwczovL3d3dy5kaWdpY2Vy 142 | # dC5jb20vQ1BTMAsGCWCGSAGG/WwHATANBgkqhkiG9w0BAQsFAAOCAQEAcZUS6VGH 143 | # VmnN793afKpjerN4zwY3QITvS4S/ys8DAv3Fp8MOIEIsr3fzKx8MIVoqtwU0HWqu 144 | # mfgnoma/Capg33akOpMP+LLR2HwZYuhegiUexLoceywh4tZbLBQ1QwRostt1AuBy 145 | # x5jWPGTlH0gQGF+JOGFNYkYkh2OMkVIsrymJ5Xgf1gsUpYDXEkdws3XVk4WTfraS 146 | # Z/tTYYmo9WuWwPRYaQ18yAGxuSh1t5ljhSKMYcp5lH5Z/IwP42+1ASa2bKXuh1Eh 147 | # 5Fhgm7oMLSttosR+u8QlK0cCCHxJrhO24XxCQijGGFbPQTS2Zl22dHv1VjMiLyI2 148 | # skuiSpXY9aaOUjGCAk0wggJJAgEBMIGGMHIxCzAJBgNVBAYTAlVTMRUwEwYDVQQK 149 | # EwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xMTAvBgNV 150 | # BAMTKERpZ2lDZXJ0IFNIQTIgQXNzdXJlZCBJRCBUaW1lc3RhbXBpbmcgQ0ECEA1C 151 | # SuC+Ooj/YEAhzhQA8N0wDQYJYIZIAWUDBAIBBQCggZgwGgYJKoZIhvcNAQkDMQ0G 152 | # CyqGSIb3DQEJEAEEMBwGCSqGSIb3DQEJBTEPFw0yMTA0MDgwOTExMDlaMCsGCyqG 153 | # SIb3DQEJEAIMMRwwGjAYMBYEFOHXgqjhkb7va8oWkbWqtJSmJJvzMC8GCSqGSIb3 154 | # DQEJBDEiBCCHEAmNNj2zWjWYRfEi4FgzZvrI16kv/U2b9b3oHw6UVDANBgkqhkiG 155 | # 9w0BAQEFAASCAQCdefEKh6Qmwx7xGCkrYi/A+/Cla6LdnYJp38eMs3fqTTvjhyDw 156 | # HffXrwdqWy5/fgW3o3qJXqa5o7hLxYIoWSULOCpJRGdt+w7XKPAbZqHrN9elAhWJ 157 | # vpBTCEaj7dVxr1Ka4NsoPSYe0eidDBmmvGvp02J4Z1j8+ImQPKN6Hv/L8Ixaxe7V 158 | # mH4VtXIiBK8xXdi4wzO+A+qLtHEJXz3Gw8Bp3BNtlDGIUkIhVTM3Q1xcSEqhOLqo 159 | # PGdwCw9acxdXNWWPjOJkNH656Bvmkml+0p6MTGIeG4JCeRh1Wpqm1ZGSoEcXNaof 160 | # wOgj48YzI+dNqBD9i7RSWCqJr2ygYKRTxnuU 161 | # SIG # End signature block 162 | -------------------------------------------------------------------------------- /External/Packman/bootstrap/generate_temp_folder.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | Copyright 2019 NVIDIA CORPORATION 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | #> 16 | 17 | param( 18 | [Parameter(Mandatory=$true)][string]$parentPath=$null 19 | ) 20 | [string] $name = [System.Guid]::NewGuid() 21 | $out = Join-Path $parentPath $name 22 | New-Item -ItemType Directory -Path ($out) | Out-Null 23 | Write-Host $out 24 | 25 | # SIG # Begin signature block 26 | # MIIaVwYJKoZIhvcNAQcCoIIaSDCCGkQCAQExDzANBglghkgBZQMEAgEFADB5Bgor 27 | # BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG 28 | # KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCB29nsqMEu+VmSF 29 | # 7ckeVTPrEZ6hsXjOgPFlJm9ilgHUB6CCCiIwggTTMIIDu6ADAgECAhBi50XpIWUh 30 | # PJcfXEkK6hKlMA0GCSqGSIb3DQEBCwUAMIGEMQswCQYDVQQGEwJVUzEdMBsGA1UE 31 | # ChMUU3ltYW50ZWMgQ29ycG9yYXRpb24xHzAdBgNVBAsTFlN5bWFudGVjIFRydXN0 32 | # IE5ldHdvcmsxNTAzBgNVBAMTLFN5bWFudGVjIENsYXNzIDMgU0hBMjU2IENvZGUg 33 | # U2lnbmluZyBDQSAtIEcyMB4XDTE4MDcwOTAwMDAwMFoXDTIxMDcwOTIzNTk1OVow 34 | # gYMxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRQwEgYDVQQHDAtT 35 | # YW50YSBDbGFyYTEbMBkGA1UECgwSTlZJRElBIENvcnBvcmF0aW9uMQ8wDQYDVQQL 36 | # DAZJVC1NSVMxGzAZBgNVBAMMEk5WSURJQSBDb3Jwb3JhdGlvbjCCASIwDQYJKoZI 37 | # hvcNAQEBBQADggEPADCCAQoCggEBALEZN63dA47T4i90jZ84CJ/aWUwVtLff8AyP 38 | # YspFfIZGdZYiMgdb8A5tBh7653y0G/LZL6CVUkgejcpvBU/Dl/52a+gSWy2qJ2bH 39 | # jMFMKCyQDhdpCAKMOUKSC9rfzm4cFeA9ct91LQCAait4LhLlZt/HF7aG+r0FgCZa 40 | # HJjJvE7KNY9G4AZXxjSt8CXS8/8NQMANqjLX1r+F+Hl8PzQ1fVx0mMsbdtaIV4Pj 41 | # 5flAeTUnz6+dCTx3vTUo8MYtkS2UBaQv7t7H2B7iwJDakEQKk1XHswJdeqG0osDU 42 | # z6+NVks7uWE1N8UIhvzbw0FEX/U2kpfyWaB/J3gMl8rVR8idPj8CAwEAAaOCAT4w 43 | # ggE6MAkGA1UdEwQCMAAwDgYDVR0PAQH/BAQDAgeAMBMGA1UdJQQMMAoGCCsGAQUF 44 | # BwMDMGEGA1UdIARaMFgwVgYGZ4EMAQQBMEwwIwYIKwYBBQUHAgEWF2h0dHBzOi8v 45 | # ZC5zeW1jYi5jb20vY3BzMCUGCCsGAQUFBwICMBkMF2h0dHBzOi8vZC5zeW1jYi5j 46 | # b20vcnBhMB8GA1UdIwQYMBaAFNTABiJJ6zlL3ZPiXKG4R3YJcgNYMCsGA1UdHwQk 47 | # MCIwIKAeoByGGmh0dHA6Ly9yYi5zeW1jYi5jb20vcmIuY3JsMFcGCCsGAQUFBwEB 48 | # BEswSTAfBggrBgEFBQcwAYYTaHR0cDovL3JiLnN5bWNkLmNvbTAmBggrBgEFBQcw 49 | # AoYaaHR0cDovL3JiLnN5bWNiLmNvbS9yYi5jcnQwDQYJKoZIhvcNAQELBQADggEB 50 | # AIJKh5vKJdhHJtMzATmc1BmXIQ3RaJONOZ5jMHn7HOkYU1JP0OIzb4pXXkH8Xwfr 51 | # K6bnd72IhcteyksvKsGpSvK0PBBwzodERTAu1Os2N+EaakxQwV/xtqDm1E3IhjHk 52 | # fRshyKKzmFk2Ci323J4lHtpWUj5Hz61b8gd72jH7xnihGi+LORJ2uRNZ3YuqMNC3 53 | # SBC8tAyoJqEoTJirULUCXW6wX4XUm5P2sx+htPw7szGblVKbQ+PFinNGnsSEZeKz 54 | # D8jUb++1cvgTKH59Y6lm43nsJjkZU77tNqyq4ABwgQRk6lt8cS2PPwjZvTmvdnla 55 | # ZhR0K4of+pQaUQHXVIBdji8wggVHMIIEL6ADAgECAhB8GzU1SufbdOdBXxFpymuo 56 | # MA0GCSqGSIb3DQEBCwUAMIG9MQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNp 57 | # Z24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNV 58 | # BAsTMShjKSAyMDA4IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNl 59 | # IG9ubHkxODA2BgNVBAMTL1ZlcmlTaWduIFVuaXZlcnNhbCBSb290IENlcnRpZmlj 60 | # YXRpb24gQXV0aG9yaXR5MB4XDTE0MDcyMjAwMDAwMFoXDTI0MDcyMTIzNTk1OVow 61 | # gYQxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEf 62 | # MB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazE1MDMGA1UEAxMsU3ltYW50 63 | # ZWMgQ2xhc3MgMyBTSEEyNTYgQ29kZSBTaWduaW5nIENBIC0gRzIwggEiMA0GCSqG 64 | # SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDXlUPU3N9nrjn7UqS2JjEEcOm3jlsqujdp 65 | # NZWPu8Aw54bYc7vf69F2P4pWjustS/BXGE6xjaUz0wt1I9VqeSfdo9P3Dodltd6t 66 | # HPH1NbQiUa8iocFdS5B/wFlOq515qQLXHkmxO02H/sJ4q7/vUq6crwjZOeWaUT5p 67 | # XzAQTnFjbFjh8CAzGw90vlvLEuHbjMSAlHK79kWansElC/ujHJ7YpglwcezAR0yP 68 | # fcPeGc4+7gRyjhfT//CyBTIZTNOwHJ/+pXggQnBBsCaMbwDIOgARQXpBsKeKkQSg 69 | # mXj0d7TzYCrmbFAEtxRg/w1R9KiLhP4h2lxeffUpeU+wRHRvbXL/AgMBAAGjggF4 70 | # MIIBdDAuBggrBgEFBQcBAQQiMCAwHgYIKwYBBQUHMAGGEmh0dHA6Ly9zLnN5bWNk 71 | # LmNvbTASBgNVHRMBAf8ECDAGAQH/AgEAMGYGA1UdIARfMF0wWwYLYIZIAYb4RQEH 72 | # FwMwTDAjBggrBgEFBQcCARYXaHR0cHM6Ly9kLnN5bWNiLmNvbS9jcHMwJQYIKwYB 73 | # BQUHAgIwGRoXaHR0cHM6Ly9kLnN5bWNiLmNvbS9ycGEwNgYDVR0fBC8wLTAroCmg 74 | # J4YlaHR0cDovL3Muc3ltY2IuY29tL3VuaXZlcnNhbC1yb290LmNybDATBgNVHSUE 75 | # DDAKBggrBgEFBQcDAzAOBgNVHQ8BAf8EBAMCAQYwKQYDVR0RBCIwIKQeMBwxGjAY 76 | # BgNVBAMTEVN5bWFudGVjUEtJLTEtNzI0MB0GA1UdDgQWBBTUwAYiSes5S92T4lyh 77 | # uEd2CXIDWDAfBgNVHSMEGDAWgBS2d/ppSEefUxLVwuoHMnYH0ZcHGTANBgkqhkiG 78 | # 9w0BAQsFAAOCAQEAf+vKp+qLdkLrPo4gVDDjt7nc+kg+FscPRZUQzSeGo2bzAu1x 79 | # +KrCVZeRcIP5Un5SaTzJ8eCURoAYu6HUpFam8x0AkdWG80iH4MvENGggXrTL+QXt 80 | # nK9wUye56D5+UaBpcYvcUe2AOiUyn0SvbkMo0yF1u5fYi4uM/qkERgSF9xWcSxGN 81 | # xCwX/tVuf5riVpLxlrOtLfn039qJmc6yOETA90d7yiW5+ipoM5tQct6on9TNLAs0 82 | # vYsweEDgjY4nG5BvGr4IFYFd6y/iUedRHsl4KeceZb847wFKAQkkDhbEFHnBQTc0 83 | # 0D2RUpSd4WjvCPDiaZxnbpALGpNx1CYCw8BaIzGCD4swgg+HAgEBMIGZMIGEMQsw 84 | # CQYDVQQGEwJVUzEdMBsGA1UEChMUU3ltYW50ZWMgQ29ycG9yYXRpb24xHzAdBgNV 85 | # BAsTFlN5bWFudGVjIFRydXN0IE5ldHdvcmsxNTAzBgNVBAMTLFN5bWFudGVjIENs 86 | # YXNzIDMgU0hBMjU2IENvZGUgU2lnbmluZyBDQSAtIEcyAhBi50XpIWUhPJcfXEkK 87 | # 6hKlMA0GCWCGSAFlAwQCAQUAoHwwEAYKKwYBBAGCNwIBDDECMAAwGQYJKoZIhvcN 88 | # AQkDMQwGCisGAQQBgjcCAQQwHAYKKwYBBAGCNwIBCzEOMAwGCisGAQQBgjcCARUw 89 | # LwYJKoZIhvcNAQkEMSIEIG5YDmcpqLxn4SB0H6OnuVkZRPh6OJ77eGW/6Su/uuJg 90 | # MA0GCSqGSIb3DQEBAQUABIIBAA3N2vqfA6WDgqz/7EoAKVIE5Hn7xpYDGhPvFAMV 91 | # BslVpeqE3apTcYFCEcwLtzIEc/zmpULxsX8B0SUT2VXbJN3zzQ80b+gbgpq62Zk+ 92 | # dQLOtLSiPhGW7MXLahgES6Oc2dUFaQ+wDfcelkrQaOVZkM4wwAzSapxuf/13oSIk 93 | # ZX2ewQEwTZrVYXELO02KQIKUR30s/oslGVg77ALnfK9qSS96Iwjd4MyT7PzCkHUi 94 | # ilwyGJi5a4ofiULiPSwUQNynSBqxa+JQALkHP682b5xhjoDfyG8laR234FTPtYgs 95 | # P/FaeviwENU5Pl+812NbbtRD+gKlWBZz+7FKykOT/CG8sZahgg1EMIINQAYKKwYB 96 | # BAGCNwMDATGCDTAwgg0sBgkqhkiG9w0BBwKggg0dMIINGQIBAzEPMA0GCWCGSAFl 97 | # AwQCAQUAMHcGCyqGSIb3DQEJEAEEoGgEZjBkAgEBBglghkgBhv1sBwEwMTANBglg 98 | # hkgBZQMEAgEFAAQgJhABfkDIPbI+nWYnA30FLTyaPK+W3QieT21B/vK+CMICEDF0 99 | # worcGsdd7OxpXLP60xgYDzIwMjEwNDA4MDkxMTA5WqCCCjcwggT+MIID5qADAgEC 100 | # AhANQkrgvjqI/2BAIc4UAPDdMA0GCSqGSIb3DQEBCwUAMHIxCzAJBgNVBAYTAlVT 101 | # MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j 102 | # b20xMTAvBgNVBAMTKERpZ2lDZXJ0IFNIQTIgQXNzdXJlZCBJRCBUaW1lc3RhbXBp 103 | # bmcgQ0EwHhcNMjEwMTAxMDAwMDAwWhcNMzEwMTA2MDAwMDAwWjBIMQswCQYDVQQG 104 | # EwJVUzEXMBUGA1UEChMORGlnaUNlcnQsIEluYy4xIDAeBgNVBAMTF0RpZ2lDZXJ0 105 | # IFRpbWVzdGFtcCAyMDIxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA 106 | # wuZhhGfFivUNCKRFymNrUdc6EUK9CnV1TZS0DFC1JhD+HchvkWsMlucaXEjvROW/ 107 | # m2HNFZFiWrj/ZwucY/02aoH6KfjdK3CF3gIY83htvH35x20JPb5qdofpir34hF0e 108 | # dsnkxnZ2OlPR0dNaNo/Go+EvGzq3YdZz7E5tM4p8XUUtS7FQ5kE6N1aG3JMjjfdQ 109 | # Jehk5t3Tjy9XtYcg6w6OLNUj2vRNeEbjA4MxKUpcDDGKSoyIxfcwWvkUrxVfbENJ 110 | # Cf0mI1P2jWPoGqtbsR0wwptpgrTb/FZUvB+hh6u+elsKIC9LCcmVp42y+tZji06l 111 | # chzun3oBc/gZ1v4NSYS9AQIDAQABo4IBuDCCAbQwDgYDVR0PAQH/BAQDAgeAMAwG 112 | # A1UdEwEB/wQCMAAwFgYDVR0lAQH/BAwwCgYIKwYBBQUHAwgwQQYDVR0gBDowODA2 113 | # BglghkgBhv1sBwEwKTAnBggrBgEFBQcCARYbaHR0cDovL3d3dy5kaWdpY2VydC5j 114 | # b20vQ1BTMB8GA1UdIwQYMBaAFPS24SAd/imu0uRhpbKiJbLIFzVuMB0GA1UdDgQW 115 | # BBQ2RIaOpLqwZr68KC0dRDbd42p6vDBxBgNVHR8EajBoMDKgMKAuhixodHRwOi8v 116 | # Y3JsMy5kaWdpY2VydC5jb20vc2hhMi1hc3N1cmVkLXRzLmNybDAyoDCgLoYsaHR0 117 | # cDovL2NybDQuZGlnaWNlcnQuY29tL3NoYTItYXNzdXJlZC10cy5jcmwwgYUGCCsG 118 | # AQUFBwEBBHkwdzAkBggrBgEFBQcwAYYYaHR0cDovL29jc3AuZGlnaWNlcnQuY29t 119 | # ME8GCCsGAQUFBzAChkNodHRwOi8vY2FjZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNl 120 | # cnRTSEEyQXNzdXJlZElEVGltZXN0YW1waW5nQ0EuY3J0MA0GCSqGSIb3DQEBCwUA 121 | # A4IBAQBIHNy16ZojvOca5yAOjmdG/UJyUXQKI0ejq5LSJcRwWb4UoOUngaVNFBUZ 122 | # B3nw0QTDhtk7vf5EAmZN7WmkD/a4cM9i6PVRSnh5Nnont/PnUp+Tp+1DnnvntN1B 123 | # Ion7h6JGA0789P63ZHdjXyNSaYOC+hpT7ZDMjaEXcw3082U5cEvznNZ6e9oMvD0y 124 | # 0BvL9WH8dQgAdryBDvjA4VzPxBFy5xtkSdgimnUVQvUtMjiB2vRgorq0Uvtc4GEk 125 | # JU+y38kpqHNDUdq9Y9YfW5v3LhtPEx33Sg1xfpe39D+E68Hjo0mh+s6nv1bPull2 126 | # YYlffqe0jmd4+TaY4cso2luHpoovMIIFMTCCBBmgAwIBAgIQCqEl1tYyG35B5AXa 127 | # NpfCFTANBgkqhkiG9w0BAQsFADBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGln 128 | # aUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtE 129 | # aWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0EwHhcNMTYwMTA3MTIwMDAwWhcNMzEw 130 | # MTA3MTIwMDAwWjByMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5j 131 | # MRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMTEwLwYDVQQDEyhEaWdpQ2VydCBT 132 | # SEEyIEFzc3VyZWQgSUQgVGltZXN0YW1waW5nIENBMIIBIjANBgkqhkiG9w0BAQEF 133 | # AAOCAQ8AMIIBCgKCAQEAvdAy7kvNj3/dqbqCmcU5VChXtiNKxA4HRTNREH3Q+X1N 134 | # aH7ntqD0jbOI5Je/YyGQmL8TvFfTw+F+CNZqFAA49y4eO+7MpvYyWf5fZT/gm+vj 135 | # RkcGGlV+Cyd+wKL1oODeIj8O/36V+/OjuiI+GKwR5PCZA207hXwJ0+5dyJoLVOOo 136 | # CXFr4M8iEA91z3FyTgqt30A6XLdR4aF5FMZNJCMwXbzsPGBqrC8HzP3w6kfZiFBe 137 | # /WZuVmEnKYmEUeaC50ZQ/ZQqLKfkdT66mA+Ef58xFNat1fJky3seBdCEGXIX8RcG 138 | # 7z3N1k3vBkL9olMqT4UdxB08r8/arBD13ays6Vb/kwIDAQABo4IBzjCCAcowHQYD 139 | # VR0OBBYEFPS24SAd/imu0uRhpbKiJbLIFzVuMB8GA1UdIwQYMBaAFEXroq/0ksuC 140 | # MS1Ri6enIZ3zbcgPMBIGA1UdEwEB/wQIMAYBAf8CAQAwDgYDVR0PAQH/BAQDAgGG 141 | # MBMGA1UdJQQMMAoGCCsGAQUFBwMIMHkGCCsGAQUFBwEBBG0wazAkBggrBgEFBQcw 142 | # AYYYaHR0cDovL29jc3AuZGlnaWNlcnQuY29tMEMGCCsGAQUFBzAChjdodHRwOi8v 143 | # Y2FjZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNlcnRBc3N1cmVkSURSb290Q0EuY3J0 144 | # MIGBBgNVHR8EejB4MDqgOKA2hjRodHRwOi8vY3JsNC5kaWdpY2VydC5jb20vRGln 145 | # aUNlcnRBc3N1cmVkSURSb290Q0EuY3JsMDqgOKA2hjRodHRwOi8vY3JsMy5kaWdp 146 | # Y2VydC5jb20vRGlnaUNlcnRBc3N1cmVkSURSb290Q0EuY3JsMFAGA1UdIARJMEcw 147 | # OAYKYIZIAYb9bAACBDAqMCgGCCsGAQUFBwIBFhxodHRwczovL3d3dy5kaWdpY2Vy 148 | # dC5jb20vQ1BTMAsGCWCGSAGG/WwHATANBgkqhkiG9w0BAQsFAAOCAQEAcZUS6VGH 149 | # VmnN793afKpjerN4zwY3QITvS4S/ys8DAv3Fp8MOIEIsr3fzKx8MIVoqtwU0HWqu 150 | # mfgnoma/Capg33akOpMP+LLR2HwZYuhegiUexLoceywh4tZbLBQ1QwRostt1AuBy 151 | # x5jWPGTlH0gQGF+JOGFNYkYkh2OMkVIsrymJ5Xgf1gsUpYDXEkdws3XVk4WTfraS 152 | # Z/tTYYmo9WuWwPRYaQ18yAGxuSh1t5ljhSKMYcp5lH5Z/IwP42+1ASa2bKXuh1Eh 153 | # 5Fhgm7oMLSttosR+u8QlK0cCCHxJrhO24XxCQijGGFbPQTS2Zl22dHv1VjMiLyI2 154 | # skuiSpXY9aaOUjGCAk0wggJJAgEBMIGGMHIxCzAJBgNVBAYTAlVTMRUwEwYDVQQK 155 | # EwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xMTAvBgNV 156 | # BAMTKERpZ2lDZXJ0IFNIQTIgQXNzdXJlZCBJRCBUaW1lc3RhbXBpbmcgQ0ECEA1C 157 | # SuC+Ooj/YEAhzhQA8N0wDQYJYIZIAWUDBAIBBQCggZgwGgYJKoZIhvcNAQkDMQ0G 158 | # CyqGSIb3DQEJEAEEMBwGCSqGSIb3DQEJBTEPFw0yMTA0MDgwOTExMDlaMCsGCyqG 159 | # SIb3DQEJEAIMMRwwGjAYMBYEFOHXgqjhkb7va8oWkbWqtJSmJJvzMC8GCSqGSIb3 160 | # DQEJBDEiBCDvFxQ6lYLr8vB+9czUl19rjCw1pWhhUXw/SqOmvIa/VDANBgkqhkiG 161 | # 9w0BAQEFAASCAQB9ox2UrcUXQsBI4Uycnhl4AMpvhVXJME62tygFMppW1l7QftDy 162 | # LvfPKRYm2YUioak/APxAS6geRKpeMkLvXuQS/Jlv0kY3BjxkeG0eVjvyjF4SvXbZ 163 | # 3JCk9m7wLNE+xqOo0ICjYlIJJgRLudjWkC5Skpb1NpPS8DOaIYwRV+AWaSOUPd9P 164 | # O5yVcnbl7OpK3EAEtwDrybCVBMPn2MGhAXybIHnth3+MFp1b6Blhz3WlReQyarjq 165 | # 1f+zaFB79rg6JswXoOTJhwICBP3hO2Ua3dMAswbfl+QNXF+igKLJPYnaeSVhBbm6 166 | # VCu2io27t4ixqvoD0RuPObNX/P3oVA38afiM 167 | # SIG # End signature block 168 | -------------------------------------------------------------------------------- /External/Packman/bootstrap/install_package.py: -------------------------------------------------------------------------------- 1 | # Copyright 2019 NVIDIA CORPORATION 2 | 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | import logging 16 | import zipfile 17 | import tempfile 18 | import sys 19 | import os 20 | import stat 21 | import time 22 | import hashlib 23 | from typing import Any, Callable, Union 24 | 25 | 26 | RENAME_RETRY_COUNT = 100 27 | RENAME_RETRY_DELAY = 0.1 28 | 29 | logging.basicConfig(level=logging.WARNING, format="%(message)s") 30 | logger = logging.getLogger("install_package") 31 | 32 | 33 | def remove_directory_item(path): 34 | if os.path.islink(path) or os.path.isfile(path): 35 | try: 36 | os.remove(path) 37 | except PermissionError: 38 | # make sure we have access and try again: 39 | os.chmod(path, stat.S_IRWXU) 40 | os.remove(path) 41 | else: 42 | # try first to delete the dir because this will work for folder junctions, otherwise we would follow the junctions and cause destruction! 43 | clean_out_folder = False 44 | try: 45 | # make sure we have access preemptively - this is necessary because recursing into a directory without permissions 46 | # will only lead to heart ache 47 | os.chmod(path, stat.S_IRWXU) 48 | os.rmdir(path) 49 | except OSError: 50 | clean_out_folder = True 51 | 52 | if clean_out_folder: 53 | # we should make sure the directory is empty 54 | names = os.listdir(path) 55 | for name in names: 56 | fullname = os.path.join(path, name) 57 | remove_directory_item(fullname) 58 | # now try to again get rid of the folder - and not catch if it raises: 59 | os.rmdir(path) 60 | 61 | 62 | class StagingDirectory: 63 | def __init__(self, staging_path): 64 | self.staging_path = staging_path 65 | self.temp_folder_path = None 66 | os.makedirs(staging_path, exist_ok=True) 67 | 68 | def __enter__(self): 69 | self.temp_folder_path = tempfile.mkdtemp(prefix="ver-", dir=self.staging_path) 70 | return self 71 | 72 | def get_temp_folder_path(self): 73 | return self.temp_folder_path 74 | 75 | # this function renames the temp staging folder to folder_name, it is required that the parent path exists! 76 | def promote_and_rename(self, folder_name): 77 | abs_dst_folder_name = os.path.join(self.staging_path, folder_name) 78 | os.rename(self.temp_folder_path, abs_dst_folder_name) 79 | 80 | def __exit__(self, type, value, traceback): 81 | # Remove temp staging folder if it's still there (something went wrong): 82 | path = self.temp_folder_path 83 | if os.path.isdir(path): 84 | remove_directory_item(path) 85 | 86 | 87 | def rename_folder(staging_dir: StagingDirectory, folder_name: str): 88 | try: 89 | staging_dir.promote_and_rename(folder_name) 90 | except OSError as exc: 91 | # if we failed to rename because the folder now exists we can assume that another packman process 92 | # has managed to update the package before us - in all other cases we re-raise the exception 93 | abs_dst_folder_name = os.path.join(staging_dir.staging_path, folder_name) 94 | if os.path.exists(abs_dst_folder_name): 95 | logger.warning( 96 | f"Directory {abs_dst_folder_name} already present, package installation already completed" 97 | ) 98 | else: 99 | raise 100 | 101 | 102 | def call_with_retry( 103 | op_name: str, func: Callable, retry_count: int = 3, retry_delay: float = 20 104 | ) -> Any: 105 | retries_left = retry_count 106 | while True: 107 | try: 108 | return func() 109 | except (OSError, IOError) as exc: 110 | logger.warning(f"Failure while executing {op_name} [{str(exc)}]") 111 | if retries_left: 112 | retry_str = "retry" if retries_left == 1 else "retries" 113 | logger.warning( 114 | f"Retrying after {retry_delay} seconds" 115 | f" ({retries_left} {retry_str} left) ..." 116 | ) 117 | time.sleep(retry_delay) 118 | else: 119 | logger.error("Maximum retries exceeded, giving up") 120 | raise 121 | retries_left -= 1 122 | 123 | 124 | def rename_folder_with_retry(staging_dir: StagingDirectory, folder_name): 125 | dst_path = os.path.join(staging_dir.staging_path, folder_name) 126 | call_with_retry( 127 | f"rename {staging_dir.get_temp_folder_path()} -> {dst_path}", 128 | lambda: rename_folder(staging_dir, folder_name), 129 | RENAME_RETRY_COUNT, 130 | RENAME_RETRY_DELAY, 131 | ) 132 | 133 | 134 | def generate_sha256_for_file(file_path: Union[str, os.PathLike]) -> str: 135 | """Returns the SHA-256 hex digest for the file at `file_path`""" 136 | hash = hashlib.sha256() 137 | # Read the file in binary mode and update the hash object with data 138 | with open(file_path, "rb") as file: 139 | for chunk in iter(lambda: file.read(4096), b""): 140 | hash.update(chunk) 141 | return hash.hexdigest() 142 | 143 | 144 | def install_common_module(package_path, install_path): 145 | COMMON_SHA256 = "95960c8c3feaf93dc662a55e6f92f23673fa3aa93394f80717c98514b4812d9f" 146 | package_sha256 = generate_sha256_for_file(package_path) 147 | if package_sha256 != COMMON_SHA256: 148 | raise RuntimeError(f"Package at '{package_path}' must have a sha256 of '{COMMON_SHA256}' " 149 | f"but was found to have '{package_sha256}'") 150 | staging_path, version = os.path.split(install_path) 151 | with StagingDirectory(staging_path) as staging_dir: 152 | output_folder = staging_dir.get_temp_folder_path() 153 | with zipfile.ZipFile(package_path, allowZip64=True) as zip_file: 154 | zip_file.extractall(output_folder) 155 | 156 | # attempt the rename operation 157 | rename_folder_with_retry(staging_dir, version) 158 | 159 | print(f"Package successfully installed to {install_path}") 160 | 161 | 162 | if __name__ == "__main__": 163 | executable_paths = os.getenv("PATH") 164 | paths_list = executable_paths.split(os.path.pathsep) if executable_paths else [] 165 | target_path_np = os.path.normpath(sys.argv[2]) 166 | target_path_np_nc = os.path.normcase(target_path_np) 167 | for exec_path in paths_list: 168 | if os.path.normcase(os.path.normpath(exec_path)) == target_path_np_nc: 169 | raise RuntimeError(f"packman will not install to executable path '{exec_path}'") 170 | install_common_module(sys.argv[1], target_path_np) 171 | -------------------------------------------------------------------------------- /External/Packman/config.packman.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /External/Packman/packman.cmd: -------------------------------------------------------------------------------- 1 | :: RUN_PM_MODULE must always be at the same spot for packman update to work (batch reloads file during update!) 2 | :: [xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx] 3 | :: Reset errorlevel status (don't inherit from caller) 4 | @call :ECHO_AND_RESET_ERROR 5 | 6 | :: You can remove this section if you do your own manual configuration of the dev machines 7 | call :CONFIGURE 8 | if %errorlevel% neq 0 ( exit /b %errorlevel% ) 9 | 10 | :: Everything below is mandatory 11 | if not defined PM_PYTHON goto :PYTHON_ENV_ERROR 12 | if not defined PM_MODULE goto :MODULE_ENV_ERROR 13 | 14 | set PM_VAR_PATH_ARG= 15 | 16 | if "%1"=="pull" goto :SET_VAR_PATH 17 | if "%1"=="install" goto :SET_VAR_PATH 18 | 19 | :RUN_PM_MODULE 20 | "%PM_PYTHON%" -S -s -u -E "%PM_MODULE%" %* %PM_VAR_PATH_ARG% 21 | if %errorlevel% neq 0 ( exit /b %errorlevel% ) 22 | 23 | :: Marshall environment variables into the current environment if they have been generated and remove temporary file 24 | if exist "%PM_VAR_PATH%" ( 25 | for /F "usebackq tokens=*" %%A in ("%PM_VAR_PATH%") do set "%%A" 26 | ) 27 | if %errorlevel% neq 0 ( goto :VAR_ERROR ) 28 | 29 | if exist "%PM_VAR_PATH%" ( 30 | del /F "%PM_VAR_PATH%" 31 | ) 32 | if %errorlevel% neq 0 ( goto :VAR_ERROR ) 33 | 34 | set PM_VAR_PATH= 35 | goto :eof 36 | 37 | :: Subroutines below 38 | :PYTHON_ENV_ERROR 39 | @echo User environment variable PM_PYTHON is not set! Please configure machine for packman or call configure.bat. 40 | exit /b 1 41 | 42 | :MODULE_ENV_ERROR 43 | @echo User environment variable PM_MODULE is not set! Please configure machine for packman or call configure.bat. 44 | exit /b 1 45 | 46 | :VAR_ERROR 47 | @echo Error while processing and setting environment variables! 48 | exit /b 1 49 | 50 | :: pad [xxxx] 51 | :ECHO_AND_RESET_ERROR 52 | @echo off 53 | if /I "%PM_VERBOSITY%"=="debug" ( 54 | @echo on 55 | ) 56 | exit /b 0 57 | 58 | :SET_VAR_PATH 59 | :: Generate temporary path for variable file 60 | for /f "delims=" %%a in ('%PM_PYTHON% -S -s -u -E -c "import tempfile;file = tempfile.NamedTemporaryFile(mode='w+t', delete=False);print(file.name)"') do (set PM_VAR_PATH=%%a) 61 | set PM_VAR_PATH_ARG=--var-path="%PM_VAR_PATH%" 62 | goto :RUN_PM_MODULE 63 | 64 | :CONFIGURE 65 | :: Must capture and set code page to work around issue #279, powershell invocation mutates console font 66 | :: This issue only happens in Windows CMD shell when using 65001 code page. Some Git Bash implementations 67 | :: don't support chcp so this workaround is a bit convoluted. 68 | :: Test for chcp: 69 | chcp > nul 2>&1 70 | if %errorlevel% equ 0 ( 71 | for /f "tokens=2 delims=:" %%a in ('chcp') do (set PM_OLD_CODE_PAGE=%%a) 72 | ) else ( 73 | call :ECHO_AND_RESET_ERROR 74 | ) 75 | :: trim leading space (this is safe even when PM_OLD_CODE_PAGE has not been set) 76 | set PM_OLD_CODE_PAGE=%PM_OLD_CODE_PAGE:~1% 77 | if "%PM_OLD_CODE_PAGE%" equ "65001" ( 78 | chcp 437 > nul 79 | set PM_RESTORE_CODE_PAGE=1 80 | ) 81 | call "%~dp0\bootstrap\configure.bat" 82 | set PM_CONFIG_ERRORLEVEL=%errorlevel% 83 | if defined PM_RESTORE_CODE_PAGE ( 84 | :: Restore code page 85 | chcp %PM_OLD_CODE_PAGE% > nul 86 | ) 87 | set PM_OLD_CODE_PAGE= 88 | set PM_RESTORE_CODE_PAGE= 89 | exit /b %PM_CONFIG_ERRORLEVEL% 90 | -------------------------------------------------------------------------------- /External/Packman/packman.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright 2019-2023 NVIDIA CORPORATION 4 | 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | SAVED_SETTINGS="$-" 17 | set -eu 18 | 19 | if echo ${PM_VERBOSITY-} | grep -i "debug" > /dev/null ; then 20 | set -x 21 | PM_CURL_SILENT="" 22 | PM_WGET_QUIET="" 23 | else 24 | PM_CURL_SILENT="-s -S" 25 | PM_WGET_QUIET="--quiet" 26 | fi 27 | export PM_PACKMAN_VERSION=7.18.1 28 | 29 | # This is necessary for newer macOS 30 | if [ `uname` == 'Darwin' ]; then 31 | export LC_ALL=en_US.UTF-8 32 | export LANG=en_US.UTF-8 33 | fi 34 | 35 | # We cannot rely on realpath, it isn't installed on macOS and some Linux distros 36 | get_abs_filename() { 37 | echo "$(cd "$(dirname "$1")" && pwd)/$(basename "$1")" 38 | } 39 | 40 | # Specify where packman command exists 41 | export PM_INSTALL_PATH="$(get_abs_filename "$(dirname "${BASH_SOURCE}")")" 42 | 43 | # The packages root may already be configured by the user 44 | if [ -z "${PM_PACKAGES_ROOT:-}" ]; then 45 | # Set variable temporarily in this process so that the following execution will work 46 | if [ `uname` == 'Darwin' ]; then 47 | export PM_PACKAGES_ROOT="${HOME}/Library/Application Support/packman-cache" 48 | else 49 | if [ -z "${XDG_CACHE_HOME:-}" ]; then 50 | export PM_PACKAGES_ROOT="${HOME}/.cache/packman" 51 | else 52 | export PM_PACKAGES_ROOT="${XDG_CACHE_HOME}/packman" 53 | fi 54 | fi 55 | fi 56 | 57 | # Ensure the packages root path exists: 58 | if [ ! -d "$PM_PACKAGES_ROOT" ]; then 59 | echo "Creating packman packages cache at $PM_PACKAGES_ROOT" 60 | mkdir -p -m a+rwx "$PM_PACKAGES_ROOT" 61 | fi 62 | 63 | fetch_file_from_s3() 64 | { 65 | SOURCE=$1 66 | SOURCE_URL=http://bootstrap.packman.nvidia.com/$SOURCE 67 | TARGET=$2 68 | echo "Fetching $SOURCE from bootstrap.packman.nvidia.com ..." 69 | if command -v wget >/dev/null 2>&1; then 70 | wget $PM_WGET_QUIET -O$TARGET $SOURCE_URL 71 | else 72 | curl -o $TARGET $SOURCE_URL $PM_CURL_SILENT 73 | fi 74 | } 75 | 76 | generate_temp_file_name() 77 | { 78 | if [ `uname` == "Darwin" ]; then 79 | local tmpfile=`mktemp -t packman` 80 | else 81 | local tmpfile=`mktemp -t packman.XXXXXXXX` 82 | fi 83 | echo "$tmpfile" 84 | } 85 | 86 | install_python() 87 | { 88 | PLATFORM=`uname` 89 | PROCESSOR=`uname -m` 90 | PYTHON_VERSION=3.10.5-1 91 | 92 | if [ $PLATFORM == 'Darwin' ]; then 93 | PYTHON_PACKAGE=$PYTHON_VERSION-macos-x86_64 94 | elif [ $PLATFORM == 'Linux' ] && [ $PROCESSOR == 'x86_64' ]; then 95 | PYTHON_PACKAGE=$PYTHON_VERSION-linux-x86_64 96 | elif [ $PLATFORM == 'Linux' ] && [ $PROCESSOR == 'aarch64' ]; then 97 | PYTHON_PACKAGE=$PYTHON_VERSION-linux-aarch64 98 | else 99 | echo "Operating system not supported" 100 | exit 1 101 | fi 102 | 103 | PYTHON_INSTALL_FOLDER="$PM_PACKAGES_ROOT/python/$PYTHON_PACKAGE" 104 | if [ ! -d "$PYTHON_INSTALL_FOLDER" ]; then 105 | mkdir -p "$PYTHON_INSTALL_FOLDER" 106 | fi 107 | 108 | export PM_PYTHON="$PYTHON_INSTALL_FOLDER/python" 109 | 110 | if [ ! -f "$PM_PYTHON" ]; then 111 | PYTHON_PACKAGE_TMP=$(generate_temp_file_name) 112 | fetch_file_from_s3 "python@$PYTHON_PACKAGE.tar.gz" "$PYTHON_PACKAGE_TMP" 113 | if [ "$?" -eq "0" ]; then 114 | echo "Unpacking python" 115 | tar -xf "$PYTHON_PACKAGE_TMP" -C "$PYTHON_INSTALL_FOLDER" 116 | rm "$PYTHON_PACKAGE_TMP" 117 | else 118 | echo "Failed downloading the Python interpreter" 119 | exit $? 120 | fi 121 | fi 122 | } 123 | 124 | # Ensure python is available: 125 | if [ -z "${PM_PYTHON_EXT:-}" ]; then 126 | install_python 127 | else 128 | PM_PYTHON="$PM_PYTHON_EXT" 129 | fi 130 | 131 | # The packman module may be externally configured 132 | if [ -z "${PM_MODULE_DIR_EXT:-}" ]; then 133 | PM_MODULE_DIR="$PM_PACKAGES_ROOT/packman-common/$PM_PACKMAN_VERSION" 134 | else 135 | PM_MODULE_DIR="$PM_MODULE_DIR_EXT" 136 | fi 137 | export PM_MODULE="$PM_MODULE_DIR/run.py" 138 | 139 | # Ensure the packman package exists: 140 | if [ ! -f "$PM_MODULE" ]; then 141 | # Remove a previously corrupt packman-common if it's there 142 | if [ -d "$PM_MODULE_DIR" ]; then 143 | rm -rf "$PM_MODULE_DIR" 144 | fi 145 | PM_MODULE_PACKAGE="packman-common@$PM_PACKMAN_VERSION.zip" 146 | TARGET=$(generate_temp_file_name) 147 | # We always fetch packman from S3: 148 | fetch_file_from_s3 "$PM_MODULE_PACKAGE" "$TARGET" 149 | if [ "$?" -eq "0" ]; then 150 | echo "Unpacking ..." 151 | "$PM_PYTHON" -S -s -u -E "$PM_INSTALL_PATH/bootstrap/install_package.py" "$TARGET" "$PM_MODULE_DIR" 152 | rm "$TARGET" 153 | else 154 | echo "Failure while fetching packman module from S3!" 155 | exit 1 156 | fi 157 | fi 158 | 159 | # Generate temporary file name for environment variables: 160 | PM_VAR_PATH=`mktemp -u -t tmp.$$.pmvars.XXXXXX` 161 | 162 | if [ $# -ne 0 ] 163 | then 164 | PM_VAR_PATH_ARG=--var-path="$PM_VAR_PATH" 165 | fi 166 | 167 | "$PM_PYTHON" -S -s -u -E "$PM_MODULE" "$@" ${PM_VAR_PATH_ARG:-} 168 | exit_code=$? 169 | # Export the variables if the file was used and remove the file: 170 | if [ -f "$PM_VAR_PATH" ]; then 171 | while read -r line 172 | do 173 | if [ ${#line} -gt 0 ]; then 174 | export "$line" 175 | fi 176 | done < "$PM_VAR_PATH" 177 | rm -f "$PM_VAR_PATH" 178 | fi 179 | 180 | # avoid leaking -e and -u into the host script if they weren't originally set 181 | if [[ ! ( "$SAVED_SETTINGS" =~ e ) ]]; then 182 | set +e 183 | fi 184 | 185 | if [[ ! ( "$SAVED_SETTINGS" =~ u ) ]]; then 186 | set +u 187 | fi 188 | 189 | # Return the exit code from python 190 | if [ "$exit_code" != 0 ]; then 191 | exit "$exit_code" 192 | fi 193 | -------------------------------------------------------------------------------- /External/Packman/python.bat: -------------------------------------------------------------------------------- 1 | :: Copyright 2019-2020 NVIDIA CORPORATION 2 | :: 3 | :: Licensed under the Apache License, Version 2.0 (the "License"); 4 | :: you may not use this file except in compliance with the License. 5 | :: You may obtain a copy of the License at 6 | :: 7 | :: http://www.apache.org/licenses/LICENSE-2.0 8 | :: 9 | :: Unless required by applicable law or agreed to in writing, software 10 | :: distributed under the License is distributed on an "AS IS" BASIS, 11 | :: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | :: See the License for the specific language governing permissions and 13 | :: limitations under the License. 14 | 15 | @echo off 16 | setlocal enableextensions 17 | 18 | call "%~dp0\packman" init 19 | set "PYTHONPATH=%PM_MODULE_DIR%;%PYTHONPATH%" 20 | 21 | if not defined PYTHONNOUSERSITE ( 22 | set PYTHONNOUSERSITE=1 23 | ) 24 | 25 | REM For performance, default to unbuffered; however, allow overriding via 26 | REM PYTHONUNBUFFERED=0 since PYTHONUNBUFFERED on windows can truncate output 27 | REM when printing long strings 28 | if not defined PYTHONUNBUFFERED ( 29 | set PYTHONUNBUFFERED=1 30 | ) 31 | 32 | "%PM_PYTHON%" %* -------------------------------------------------------------------------------- /External/Packman/python.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright 2019-2020 NVIDIA CORPORATION 4 | 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | set -e 18 | 19 | PACKMAN_CMD="$(dirname "${BASH_SOURCE}")/packman" 20 | if [ ! -f "$PACKMAN_CMD" ]; then 21 | PACKMAN_CMD="${PACKMAN_CMD}.sh" 22 | fi 23 | source "$PACKMAN_CMD" init 24 | export PYTHONPATH="${PM_MODULE_DIR}:${PYTHONPATH}" 25 | 26 | if [ -z "${PYTHONNOUSERSITE:-}" ]; then 27 | export PYTHONNOUSERSITE=1 28 | fi 29 | 30 | # For performance, default to unbuffered; however, allow overriding via 31 | # PYTHONUNBUFFERED=0 since PYTHONUNBUFFERED on windows can truncate output 32 | # when printing long strings 33 | if [ -z "${PYTHONUNBUFFERED:-}" ]; then 34 | export PYTHONUNBUFFERED=1 35 | fi 36 | 37 | # workaround for our python not shipping with certs 38 | if [[ -z ${SSL_CERT_DIR:-} ]]; then 39 | export SSL_CERT_DIR=/etc/ssl/certs/ 40 | fi 41 | 42 | "${PM_PYTHON}" "$@" 43 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014-2021, NVIDIA CORPORATION. All rights reserved. 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a 4 | copy of this software and associated documentation files (the "Software"), 5 | to deal in the Software without restriction, including without limitation 6 | the rights to use, copy, modify, merge, publish, distribute, sublicense, 7 | and/or sell copies of the Software, and to permit persons to whom the 8 | Software is furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 16 | THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 18 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 19 | DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # NRI Samples 2 | 3 | [![Status](https://github.com/NVIDIA-RTX/NRISamples/actions/workflows/build.yml/badge.svg)](https://github.com/NVIDIA-RTX/NRISamples/actions/workflows/build.yml) 4 | 5 | This is the test bench for [*NRI (NVIDIA Rendering Interface)*](https://github.com/NVIDIA-RTX/NRI). 6 | 7 | ## Build instructions 8 | 9 | ### Windows 10 | 11 | - Install **WindowsSDK** and **VulkanSDK** 12 | - Clone project and init submodules 13 | - Generate and build project using **cmake** 14 | - To build the binary with static MSVC runtime, add `-DCMAKE_MSVC_RUNTIME_LIBRARY="MultiThreaded$<$:Debug>"` parameter 15 | 16 | Or by running scripts only: 17 | - Run ``1-Deploy.bat`` 18 | - Run ``2-Build.bat`` 19 | 20 | ### Linux 21 | 22 | - Install **VulkanSDK**, **xorg-dev**, 23 | - Clone project and init submodules 24 | - Generate and build project using **cmake** 25 | 26 | Or by running scripts only: 27 | - Run `./1-Deploy.sh` 28 | - RUn `./2-Build.sh` 29 | 30 | ### CMake options 31 | 32 | - `DISABLE_SHADER_COMPILATION` - disable compilation of shaders (shaders can be built on other platform) 33 | - `NRIF_USE_WAYLAND` - use Wayland instead of X11 on Linux 34 | 35 | ## How to run 36 | 37 | The executables from `_Bin` directory load resources from `_Data`, therefore the samples need to be run with the working directory set to the project root folder. But the simplest way to run ALL samples sequentially is to click on `3-Test samples.bat`. 38 | -------------------------------------------------------------------------------- /Shaders/Box.vs.hlsl: -------------------------------------------------------------------------------- 1 | // © 2021 NVIDIA Corporation 2 | 3 | #include "NRI.hlsl" 4 | 5 | struct InputVS 6 | { 7 | float3 position : POSITION; 8 | float2 texCoords : TEXCOORD0; 9 | }; 10 | 11 | struct OutputVS 12 | { 13 | float4 position : SV_Position; 14 | float2 texCoords : TEXCOORD0; 15 | }; 16 | 17 | NRI_RESOURCE( cbuffer, GeometryConstants, b, 0, 0 ) 18 | { 19 | float4x4 transform; 20 | }; 21 | 22 | NRI_RESOURCE( cbuffer, GlobalConstants, b, 1, 0 ) 23 | { 24 | float4 globalConstants; 25 | }; 26 | 27 | NRI_RESOURCE( cbuffer, ViewConstants, b, 2, 0 ) 28 | { 29 | float4x4 projView; 30 | float4 viewConstants; 31 | }; 32 | 33 | NRI_RESOURCE( cbuffer, MaterialConstants, b, 3, 0 ) 34 | { 35 | float4 materialConstants; 36 | }; 37 | 38 | OutputVS main( in InputVS input ) 39 | { 40 | const float4 constants = globalConstants + viewConstants + materialConstants; 41 | 42 | OutputVS output; 43 | output.position = mul( projView, mul( transform, float4( input.position, 1 ) + constants ) ); 44 | output.texCoords = input.texCoords; 45 | 46 | return output; 47 | } 48 | -------------------------------------------------------------------------------- /Shaders/Box0.fs.hlsl: -------------------------------------------------------------------------------- 1 | // © 2021 NVIDIA Corporation 2 | 3 | #include "NRI.hlsl" 4 | 5 | NRI_RESOURCE( cbuffer, GlobalConstants, b, 1, 0 ) 6 | { 7 | float4 globalConstants; 8 | }; 9 | 10 | NRI_RESOURCE( cbuffer, ViewConstants, b, 2, 0 ) 11 | { 12 | float4 viewConstants; 13 | }; 14 | 15 | NRI_RESOURCE( cbuffer, MaterialConstants, b, 3, 0 ) 16 | { 17 | float4 materialConstants; 18 | }; 19 | 20 | NRI_RESOURCE( SamplerState, sampler0, s, 0, 1 ); 21 | NRI_RESOURCE( Texture2D, texture0, t, 0, 0 ); 22 | NRI_RESOURCE( Texture2D, texture1, t, 1, 0 ); 23 | NRI_RESOURCE( Texture2D, texture2, t, 2, 0 ); 24 | 25 | struct OutputVS 26 | { 27 | float4 position : SV_Position; 28 | float2 texCoords : TEXCOORD0; 29 | }; 30 | 31 | float4 main( in OutputVS input ) : SV_Target 32 | { 33 | const float4 constants = globalConstants + viewConstants + materialConstants; 34 | const float4 sample0 = texture0.Sample( sampler0, input.texCoords ); 35 | const float4 sample1 = texture1.Sample( sampler0, input.texCoords ); 36 | const float4 sample2 = texture2.Sample( sampler0, input.texCoords ); 37 | 38 | return sample0 + constants + sample1 * 0.001 + sample2 * 0.001; 39 | } 40 | -------------------------------------------------------------------------------- /Shaders/Box1.fs.hlsl: -------------------------------------------------------------------------------- 1 | // © 2021 NVIDIA Corporation 2 | 3 | #include "NRI.hlsl" 4 | 5 | NRI_RESOURCE( cbuffer, GlobalConstants, b, 1, 0 ) 6 | { 7 | float4 globalConstants; 8 | }; 9 | 10 | NRI_RESOURCE( cbuffer, ViewConstants, b, 2, 0 ) 11 | { 12 | float4 viewConstants; 13 | }; 14 | 15 | NRI_RESOURCE( cbuffer, MaterialConstants, b, 3, 0 ) 16 | { 17 | float4 materialConstants; 18 | }; 19 | 20 | NRI_RESOURCE( SamplerState, sampler0, s, 0, 1 ); 21 | NRI_RESOURCE( Texture2D, texture0, t, 0, 0 ); 22 | NRI_RESOURCE( Texture2D, texture1, t, 1, 0 ); 23 | NRI_RESOURCE( Texture2D, texture2, t, 2, 0 ); 24 | 25 | struct OutputVS 26 | { 27 | float4 position : SV_Position; 28 | float2 texCoords : TEXCOORD0; 29 | }; 30 | 31 | float4 main( in OutputVS input ) : SV_Target 32 | { 33 | const float4 constants = globalConstants + viewConstants + materialConstants; 34 | const float4 sample0 = texture0.Sample( sampler0, input.texCoords ); 35 | const float4 sample1 = texture1.Sample( sampler0, input.texCoords ); 36 | const float4 sample2 = texture2.Sample( sampler0, input.texCoords ); 37 | 38 | return sample0 + constants + sample1 * 0.001 + sample2 * 0.002; 39 | } 40 | -------------------------------------------------------------------------------- /Shaders/Box2.fs.hlsl: -------------------------------------------------------------------------------- 1 | // © 2021 NVIDIA Corporation 2 | 3 | #include "NRI.hlsl" 4 | 5 | NRI_RESOURCE( cbuffer, GlobalConstants, b, 1, 0 ) 6 | { 7 | float4 globalConstants; 8 | }; 9 | 10 | NRI_RESOURCE( cbuffer, ViewConstants, b, 2, 0 ) 11 | { 12 | float4 viewConstants; 13 | }; 14 | 15 | NRI_RESOURCE( cbuffer, MaterialConstants, b, 3, 0 ) 16 | { 17 | float4 materialConstants; 18 | }; 19 | 20 | NRI_RESOURCE( SamplerState, sampler0, s, 0, 1 ); 21 | NRI_RESOURCE( Texture2D, texture0, t, 0, 0 ); 22 | NRI_RESOURCE( Texture2D, texture1, t, 1, 0 ); 23 | NRI_RESOURCE( Texture2D, texture2, t, 2, 0 ); 24 | 25 | struct OutputVS 26 | { 27 | float4 position : SV_Position; 28 | float2 texCoords : TEXCOORD0; 29 | }; 30 | 31 | float4 main( in OutputVS input ) : SV_Target 32 | { 33 | const float4 constants = globalConstants + viewConstants + materialConstants; 34 | const float4 sample0 = texture0.Sample( sampler0, input.texCoords ); 35 | const float4 sample1 = texture1.Sample( sampler0, input.texCoords ); 36 | const float4 sample2 = texture2.Sample( sampler0, input.texCoords ); 37 | 38 | return sample0 + constants + sample1 * 0.001 + sample2 * 0.0028; 39 | } 40 | -------------------------------------------------------------------------------- /Shaders/Box3.fs.hlsl: -------------------------------------------------------------------------------- 1 | // © 2021 NVIDIA Corporation 2 | 3 | #include "NRI.hlsl" 4 | 5 | NRI_RESOURCE( cbuffer, GlobalConstants, b, 1, 0 ) 6 | { 7 | float4 globalConstants; 8 | }; 9 | 10 | NRI_RESOURCE( cbuffer, ViewConstants, b, 2, 0 ) 11 | { 12 | float4 viewConstants; 13 | }; 14 | 15 | NRI_RESOURCE( cbuffer, MaterialConstants, b, 3, 0 ) 16 | { 17 | float4 materialConstants; 18 | }; 19 | 20 | NRI_RESOURCE( SamplerState, sampler0, s, 0, 1 ); 21 | NRI_RESOURCE( Texture2D, texture0, t, 0, 0 ); 22 | NRI_RESOURCE( Texture2D, texture1, t, 1, 0 ); 23 | NRI_RESOURCE( Texture2D, texture2, t, 2, 0 ); 24 | 25 | struct OutputVS 26 | { 27 | float4 position : SV_Position; 28 | float2 texCoords : TEXCOORD0; 29 | }; 30 | 31 | float4 main( in OutputVS input ) : SV_Target 32 | { 33 | const float4 constants = globalConstants + viewConstants + materialConstants; 34 | const float4 sample0 = texture0.Sample( sampler0, input.texCoords ); 35 | const float4 sample1 = texture1.Sample( sampler0, input.texCoords ); 36 | const float4 sample2 = texture2.Sample( sampler0, input.texCoords ); 37 | 38 | return sample0 + constants + sample1 * 0.001 + sample2 * 0.0022; 39 | } 40 | -------------------------------------------------------------------------------- /Shaders/Box4.fs.hlsl: -------------------------------------------------------------------------------- 1 | // © 2021 NVIDIA Corporation 2 | 3 | #include "NRI.hlsl" 4 | 5 | NRI_RESOURCE( cbuffer, GlobalConstants, b, 1, 0 ) 6 | { 7 | float4 globalConstants; 8 | }; 9 | 10 | NRI_RESOURCE( cbuffer, ViewConstants, b, 2, 0 ) 11 | { 12 | float4 viewConstants; 13 | }; 14 | 15 | NRI_RESOURCE( cbuffer, MaterialConstants, b, 3, 0 ) 16 | { 17 | float4 materialConstants; 18 | }; 19 | 20 | NRI_RESOURCE( SamplerState, sampler0, s, 0, 1 ); 21 | NRI_RESOURCE( Texture2D, texture0, t, 0, 0 ); 22 | NRI_RESOURCE( Texture2D, texture1, t, 1, 0 ); 23 | NRI_RESOURCE( Texture2D, texture2, t, 2, 0 ); 24 | 25 | struct OutputVS 26 | { 27 | float4 position : SV_Position; 28 | float2 texCoords : TEXCOORD0; 29 | }; 30 | 31 | float4 main( in OutputVS input ) : SV_Target 32 | { 33 | const float4 constants = globalConstants + viewConstants + materialConstants; 34 | const float4 sample0 = texture0.Sample( sampler0, input.texCoords ); 35 | const float4 sample1 = texture1.Sample( sampler0, input.texCoords ); 36 | const float4 sample2 = texture2.Sample( sampler0, input.texCoords ); 37 | 38 | return sample0 + constants + sample1 * 0.001 + sample2 * 0.0029; 39 | } 40 | -------------------------------------------------------------------------------- /Shaders/Box5.fs.hlsl: -------------------------------------------------------------------------------- 1 | // © 2021 NVIDIA Corporation 2 | 3 | #include "NRI.hlsl" 4 | 5 | NRI_RESOURCE( cbuffer, GlobalConstants, b, 1, 0 ) 6 | { 7 | float4 globalConstants; 8 | }; 9 | 10 | NRI_RESOURCE( cbuffer, ViewConstants, b, 2, 0 ) 11 | { 12 | float4 viewConstants; 13 | }; 14 | 15 | NRI_RESOURCE( cbuffer, MaterialConstants, b, 3, 0 ) 16 | { 17 | float4 materialConstants; 18 | }; 19 | 20 | NRI_RESOURCE( SamplerState, sampler0, s, 0, 1 ); 21 | NRI_RESOURCE( Texture2D, texture0, t, 0, 0 ); 22 | NRI_RESOURCE( Texture2D, texture1, t, 1, 0 ); 23 | NRI_RESOURCE( Texture2D, texture2, t, 2, 0 ); 24 | 25 | struct OutputVS 26 | { 27 | float4 position : SV_Position; 28 | float2 texCoords : TEXCOORD0; 29 | }; 30 | 31 | float4 main( in OutputVS input ) : SV_Target 32 | { 33 | const float4 constants = globalConstants + viewConstants + materialConstants; 34 | const float4 sample0 = texture0.Sample( sampler0, input.texCoords ); 35 | const float4 sample1 = texture1.Sample( sampler0, input.texCoords ); 36 | const float4 sample2 = texture2.Sample( sampler0, input.texCoords ); 37 | 38 | return sample0 + constants + sample1 * 0.001 + sample2 * 0.0026; 39 | } 40 | -------------------------------------------------------------------------------- /Shaders/Box6.fs.hlsl: -------------------------------------------------------------------------------- 1 | // © 2021 NVIDIA Corporation 2 | 3 | #include "NRI.hlsl" 4 | 5 | NRI_RESOURCE( cbuffer, GlobalConstants, b, 1, 0 ) 6 | { 7 | float4 globalConstants; 8 | }; 9 | 10 | NRI_RESOURCE( cbuffer, ViewConstants, b, 2, 0 ) 11 | { 12 | float4 viewConstants; 13 | }; 14 | 15 | NRI_RESOURCE( cbuffer, MaterialConstants, b, 3, 0 ) 16 | { 17 | float4 materialConstants; 18 | }; 19 | 20 | NRI_RESOURCE( SamplerState, sampler0, s, 0, 1 ); 21 | NRI_RESOURCE( Texture2D, texture0, t, 0, 0 ); 22 | NRI_RESOURCE( Texture2D, texture1, t, 1, 0 ); 23 | NRI_RESOURCE( Texture2D, texture2, t, 2, 0 ); 24 | 25 | struct OutputVS 26 | { 27 | float4 position : SV_Position; 28 | float2 texCoords : TEXCOORD0; 29 | }; 30 | 31 | float4 main( in OutputVS input ) : SV_Target 32 | { 33 | const float4 constants = globalConstants + viewConstants + materialConstants; 34 | const float4 sample0 = texture0.Sample( sampler0, input.texCoords ); 35 | const float4 sample1 = texture1.Sample( sampler0, input.texCoords ); 36 | const float4 sample2 = texture2.Sample( sampler0, input.texCoords ); 37 | 38 | return sample0 + constants + sample1 * 0.001 + sample2 * 0.0023; 39 | } 40 | -------------------------------------------------------------------------------- /Shaders/Box7.fs.hlsl: -------------------------------------------------------------------------------- 1 | // © 2021 NVIDIA Corporation 2 | 3 | #include "NRI.hlsl" 4 | 5 | NRI_RESOURCE( cbuffer, GlobalConstants, b, 1, 0 ) 6 | { 7 | float4 globalConstants; 8 | }; 9 | 10 | NRI_RESOURCE( cbuffer, ViewConstants, b, 2, 0 ) 11 | { 12 | float4 viewConstants; 13 | }; 14 | 15 | NRI_RESOURCE( cbuffer, MaterialConstants, b, 3, 0 ) 16 | { 17 | float4 materialConstants; 18 | }; 19 | 20 | NRI_RESOURCE( SamplerState, sampler0, s, 0, 1 ); 21 | NRI_RESOURCE( Texture2D, texture0, t, 0, 0 ); 22 | NRI_RESOURCE( Texture2D, texture1, t, 1, 0 ); 23 | NRI_RESOURCE( Texture2D, texture2, t, 2, 0 ); 24 | 25 | struct OutputVS 26 | { 27 | float4 position : SV_Position; 28 | float2 texCoords : TEXCOORD0; 29 | }; 30 | 31 | float4 main( in OutputVS input ) : SV_Target 32 | { 33 | const float4 constants = globalConstants + viewConstants + materialConstants; 34 | const float4 sample0 = texture0.Sample( sampler0, input.texCoords ); 35 | const float4 sample1 = texture1.Sample( sampler0, input.texCoords ); 36 | const float4 sample2 = texture2.Sample( sampler0, input.texCoords ); 37 | 38 | return sample0 + constants + sample1 * 0.001 + sample2 * 0.0021; 39 | } 40 | -------------------------------------------------------------------------------- /Shaders/Compute.cs.hlsl: -------------------------------------------------------------------------------- 1 | // © 2021 NVIDIA Corporation 2 | 3 | #include "NRI.hlsl" 4 | 5 | NRI_FORMAT("r16f") NRI_RESOURCE(RWBuffer, buffer, u, 0, 0); 6 | 7 | uint3 pcg3d(uint3 v) 8 | { 9 | v = v * 1664525u + 1013904223u; 10 | 11 | v.x += v.y * v.z; 12 | v.y += v.z * v.x; 13 | v.z += v.x * v.y; 14 | 15 | v ^= v >> 16u; 16 | 17 | v.x += v.y * v.z; 18 | v.y += v.z * v.x; 19 | v.z += v.x * v.y; 20 | 21 | return v; 22 | } 23 | 24 | [numthreads(256, 1, 1)] 25 | void main(uint threadID : SV_DispatchThreadId) 26 | { 27 | float value = buffer[threadID]; 28 | uint3 result = uint3(asuint(value), asuint(value) >> 12, asuint(value) * asuint(value)); 29 | 30 | [loop] 31 | for (uint i = 0; i < 128; i++) 32 | result = pcg3d(result); 33 | 34 | buffer[threadID] = result.x * result.y * result.z; 35 | } -------------------------------------------------------------------------------- /Shaders/Forward.fs.hlsl: -------------------------------------------------------------------------------- 1 | // © 2021 NVIDIA Corporation 2 | 3 | #include "NRI.hlsl" 4 | #include "ForwardResources.hlsli" 5 | 6 | [earlydepthstencil] 7 | float4 main( in Attributes input ) : SV_Target 8 | { 9 | PS_INPUT; 10 | float4 output = Shade( float4( albedo, diffuse.w ), Rf0, roughness, emissive, N, L, V, Clight, FAKE_AMBIENT ); 11 | 12 | output.xyz = Color::HdrToLinear( output.xyz * exposure ); 13 | return output; 14 | } 15 | -------------------------------------------------------------------------------- /Shaders/Forward.vs.hlsl: -------------------------------------------------------------------------------- 1 | // © 2021 NVIDIA Corporation 2 | 3 | #include "NRI.hlsl" 4 | 5 | struct Input 6 | { 7 | float3 Position : POSITION; 8 | float2 TexCoord : TEXCOORD0; 9 | float3 Normal : NORMAL; 10 | float4 Tangent : TANGENT; 11 | }; 12 | 13 | struct Attributes 14 | { 15 | float4 Position : SV_Position; 16 | float4 Normal : TEXCOORD0; //.w = TexCoord.x 17 | float4 View : TEXCOORD1; //.w = TexCoord.y 18 | float4 Tangent : TEXCOORD2; 19 | }; 20 | 21 | NRI_RESOURCE( cbuffer, Global, b, 0, 0 ) 22 | { 23 | float4x4 gWorldToClip; 24 | float3 gCameraPos; 25 | }; 26 | 27 | Attributes main( in Input input ) 28 | { 29 | Attributes output; 30 | 31 | float3 N = input.Normal * 2.0 - 1.0; 32 | float4 T = input.Tangent * 2.0 - 1.0; 33 | float3 V = gCameraPos - input.Position; 34 | 35 | output.Position = mul( gWorldToClip, float4( input.Position, 1 ) ); 36 | output.Normal = float4( N, input.TexCoord.x ); 37 | output.View = float4( V, input.TexCoord.y ); 38 | output.Tangent = T; 39 | 40 | return output; 41 | } 42 | -------------------------------------------------------------------------------- /Shaders/ForwardBindless.fs.hlsl: -------------------------------------------------------------------------------- 1 | // © 2021 NVIDIA Corporation 2 | 3 | #define DONT_DECLARE_RESOURCES 4 | 5 | #include "NRI.hlsl" 6 | 7 | #ifndef NRI_DXBC 8 | 9 | #include "ForwardResources.hlsli" 10 | #include "SceneViewerBindlessStructs.h" 11 | 12 | NRI_RESOURCE(SamplerState, AnisotropicSampler, s, 0, 0 ); 13 | NRI_RESOURCE(StructuredBuffer, Materials, t, 0, 0); 14 | NRI_RESOURCE(StructuredBuffer, Meshes, t, 1, 0); 15 | NRI_RESOURCE(StructuredBuffer, Instances, t, 2, 0); 16 | NRI_RESOURCE(Texture2D, Textures[], t, 0, 1); 17 | 18 | struct BindlessAttributes 19 | { 20 | float4 Position : SV_Position; 21 | float4 Normal : TEXCOORD0; //.w = TexCoord.x 22 | float4 View : TEXCOORD1; //.w = TexCoord.y 23 | float4 Tangent : TEXCOORD2; 24 | nointerpolation uint DrawParameters : ATTRIBUTES; 25 | }; 26 | 27 | [earlydepthstencil] 28 | float4 main( in BindlessAttributes input ) : SV_Target 29 | { 30 | uint instanceIndex = input.DrawParameters; 31 | uint materialIndex = Instances[instanceIndex].materialIndex; 32 | 33 | uint baseColorTexIndex = Materials[materialIndex].baseColorTexIndex; 34 | uint roughnessMetalnessTexIndex = Materials[materialIndex].roughnessMetalnessTexIndex; 35 | uint normalTexIndex = Materials[materialIndex].normalTexIndex; 36 | uint emissiveTexIndex = Materials[materialIndex].emissiveTexIndex; 37 | 38 | Texture2D DiffuseMap = Textures[baseColorTexIndex]; 39 | Texture2D SpecularMap = Textures[roughnessMetalnessTexIndex]; 40 | Texture2D NormalMap = Textures[normalTexIndex]; 41 | Texture2D EmissiveMap = Textures[emissiveTexIndex]; 42 | 43 | float2 uv = float2( input.Normal.w, input.View.w ); 44 | float3 V = normalize( input.View.xyz ); 45 | float3 Nvertex = input.Normal.xyz; 46 | Nvertex = normalize( Nvertex ); 47 | float4 T = input.Tangent; 48 | T.xyz = normalize( T.xyz ); 49 | 50 | float4 diffuse = DiffuseMap.Sample( AnisotropicSampler, uv ); 51 | float3 materialProps = SpecularMap.Sample( AnisotropicSampler, uv ).xyz; 52 | float3 emissive = EmissiveMap.Sample( AnisotropicSampler, uv ).xyz; 53 | float2 packedNormal = NormalMap.Sample( AnisotropicSampler, uv ).xy; 54 | 55 | float3 N = Geometry::TransformLocalNormal( packedNormal, T, Nvertex ); 56 | float3 albedo, Rf0; 57 | BRDF::ConvertBaseColorMetalnessToAlbedoRf0( diffuse.xyz, materialProps.z, albedo, Rf0 ); 58 | float roughness = materialProps.y; 59 | const float3 sunDirection = normalize( float3( -0.8, -0.8, 1.0 ) ); 60 | float3 L = ImportanceSampling::CorrectDirectionToInfiniteSource( N, sunDirection, V, tan( SUN_ANGULAR_SIZE ) ); 61 | const float3 Clight = 80000.0; 62 | const float exposure = 0.00025; 63 | 64 | float4 output = Shade( float4( albedo, diffuse.w ), Rf0, roughness, emissive, N, L, V, Clight, FAKE_AMBIENT ); 65 | output.xyz = Color::HdrToLinear( output.xyz * exposure ); 66 | 67 | return output; 68 | } 69 | 70 | #else 71 | 72 | [earlydepthstencil] 73 | float4 main() : SV_Target 74 | { 75 | return 0; 76 | } 77 | 78 | #endif 79 | -------------------------------------------------------------------------------- /Shaders/ForwardBindless.vs.hlsl: -------------------------------------------------------------------------------- 1 | // © 2021 NVIDIA Corporation 2 | 3 | #define NRI_ENABLE_DRAW_PARAMETERS_EMULATION 4 | 5 | #include "NRI.hlsl" 6 | #include "SceneViewerBindlessStructs.h" 7 | 8 | NRI_ENABLE_DRAW_PARAMETERS; 9 | 10 | struct Input 11 | { 12 | float3 Position : POSITION; 13 | float2 TexCoord : TEXCOORD0; 14 | float3 Normal : NORMAL; 15 | float4 Tangent : TANGENT; 16 | }; 17 | 18 | struct Attributes 19 | { 20 | float4 Position : SV_Position; 21 | float4 Normal : TEXCOORD0; //.w = TexCoord.x 22 | float4 View : TEXCOORD1; //.w = TexCoord.y 23 | float4 Tangent : TEXCOORD2; 24 | nointerpolation uint DrawParameters : ATTRIBUTES; 25 | }; 26 | 27 | Attributes main( in Input input, NRI_DECLARE_DRAW_PARAMETERS ) 28 | { 29 | Attributes output = (Attributes)0; 30 | 31 | #ifndef NRI_DXBC 32 | float3 N = input.Normal * 2.0 - 1.0; 33 | float4 T = input.Tangent * 2.0 - 1.0; 34 | float3 V = gCameraPos - input.Position; 35 | 36 | output.Position = mul( gWorldToClip, float4( input.Position, 1 ) ); 37 | output.Normal = float4( N, input.TexCoord.x ); 38 | output.View = float4( V, input.TexCoord.y ); 39 | output.Tangent = T; 40 | output.DrawParameters = NRI_INSTANCE_ID_OFFSET; 41 | #endif 42 | 43 | return output; 44 | } 45 | -------------------------------------------------------------------------------- /Shaders/ForwardDiscard.fs.hlsl: -------------------------------------------------------------------------------- 1 | // © 2021 NVIDIA Corporation 2 | 3 | #include "NRI.hlsl" 4 | #include "ForwardResources.hlsli" 5 | 6 | float4 main( in Attributes input ) : SV_Target 7 | { 8 | PS_INPUT; 9 | float4 output = Shade( float4( albedo, diffuse.w ), Rf0, roughness, emissive, N, L, V, Clight, FAKE_AMBIENT ); 10 | if( output.w < 0.5 ) 11 | discard; 12 | 13 | output.xyz = Color::HdrToLinear( output.xyz * exposure ); 14 | return output; 15 | } 16 | -------------------------------------------------------------------------------- /Shaders/ForwardResources.hlsli: -------------------------------------------------------------------------------- 1 | // © 2021 NVIDIA Corporation 2 | 3 | #include "ml.hlsli" 4 | 5 | struct Attributes 6 | { 7 | float4 Position : SV_Position; 8 | float4 Normal : TEXCOORD0; //.w = TexCoord.x 9 | float4 View : TEXCOORD1; //.w = TexCoord.y 10 | float4 Tangent : TEXCOORD2; 11 | }; 12 | 13 | #ifndef DONT_DECLARE_RESOURCES 14 | NRI_RESOURCE( Texture2D, DiffuseMap, t, 0, 1 ); 15 | NRI_RESOURCE( Texture2D, SpecularMap, t, 1, 1 ); 16 | NRI_RESOURCE( Texture2D, NormalMap, t, 2, 1 ); 17 | NRI_RESOURCE( Texture2D, EmissiveMap, t, 3, 1 ); 18 | NRI_RESOURCE( SamplerState, AnisotropicSampler, s, 0, 0 ); 19 | #endif 20 | 21 | #define SUN_ANGULAR_SIZE radians( 0.533 ) 22 | 23 | #define PS_INPUT \ 24 | float2 uv = float2( input.Normal.w, input.View.w ); \ 25 | float3 V = normalize( input.View.xyz ); \ 26 | float3 Nvertex = input.Normal.xyz; \ 27 | Nvertex = normalize( Nvertex ); \ 28 | float4 T = input.Tangent; \ 29 | T.xyz = normalize( T.xyz ); \ 30 | float4 diffuse = DiffuseMap.Sample( AnisotropicSampler, uv ); \ 31 | float3 materialProps = SpecularMap.Sample( AnisotropicSampler, uv ).xyz; \ 32 | float3 emissive = EmissiveMap.Sample( AnisotropicSampler, uv ).xyz; \ 33 | float2 packedNormal = NormalMap.Sample( AnisotropicSampler, uv ).xy; \ 34 | float3 N = Geometry::TransformLocalNormal( packedNormal, T, Nvertex ); \ 35 | float3 albedo, Rf0; \ 36 | BRDF::ConvertBaseColorMetalnessToAlbedoRf0( diffuse.xyz, materialProps.z, albedo, Rf0 ); \ 37 | float roughness = materialProps.y; \ 38 | const float3 sunDirection = normalize( float3( -0.8, -0.8, 1.0 ) ); \ 39 | float3 L = ImportanceSampling::CorrectDirectionToInfiniteSource( N, sunDirection, V, tan( SUN_ANGULAR_SIZE ) ); \ 40 | const float3 Clight = 80000.0; \ 41 | const float exposure = 0.00025 42 | 43 | // LIGHTING 44 | 45 | #define GLASS_HACK 0x1 46 | #define FAKE_AMBIENT 0x2 47 | 48 | float4 Shade( float4 albedo, float3 Rf0, float roughness, float3 emissive, float3 N, float3 L, float3 V, float3 Clight, uint flags ) 49 | { 50 | if( flags & GLASS_HACK ) 51 | { 52 | Rf0 = 0.04; 53 | roughness = 0.1; 54 | } 55 | 56 | // Direct lighting 57 | float3 Cdiff, Cspec; 58 | BRDF::DirectLighting( N, L, V, Rf0, roughness, Cdiff, Cspec ); 59 | 60 | if( flags & FAKE_AMBIENT ) 61 | { 62 | // Ambient 63 | const float3 ambient = float3( 1.0, 1.0, 0.8 ) * 0.1; 64 | Cdiff += ambient; 65 | 66 | // Environment 67 | const float3 fakeTopColor = float3( 0.8, 0.8, 1.0 ); 68 | const float3 fakeBottomColor = float3( 0.2, 0.15, 0.15 ); 69 | float3 R = reflect( -V, N ); 70 | float3 environment = lerp( fakeBottomColor, fakeTopColor, R.z * 0.5 + 0.5 ) * 0.3; 71 | float NoV = saturate( dot( N, V ) ); 72 | float3 Kenv = BRDF::EnvironmentTerm( Rf0, NoV, roughness ); 73 | Cspec += Kenv * environment; 74 | } 75 | 76 | // Output 77 | float3 Lsum = ( Cdiff * albedo.xyz + Cspec ) * Clight + emissive; 78 | 79 | float4 output; 80 | output.xyz = Lsum; 81 | output.w = albedo.w; 82 | 83 | float NoL = saturate( dot( N, L ) ); 84 | float specIntensity = Color::Luminance( Cspec * NoL ); 85 | if( flags & GLASS_HACK ) 86 | output.w = saturate( 0.5 + specIntensity ); 87 | 88 | return output; 89 | } 90 | -------------------------------------------------------------------------------- /Shaders/ForwardTransparent.fs.hlsl: -------------------------------------------------------------------------------- 1 | // © 2021 NVIDIA Corporation 2 | 3 | #include "NRI.hlsl" 4 | #include "ForwardResources.hlsli" 5 | 6 | float4 main( in Attributes input, bool isFrontFace : SV_IsFrontFace ) : SV_Target 7 | { 8 | PS_INPUT; 9 | N = isFrontFace ? N : -N; 10 | 11 | float4 output = Shade( float4( albedo, diffuse.w ), Rf0, roughness, emissive, N, L, V, Clight, FAKE_AMBIENT | GLASS_HACK ); 12 | 13 | output.xyz = Color::HdrToLinear( output.xyz * exposure ); 14 | return output; 15 | } 16 | -------------------------------------------------------------------------------- /Shaders/GenerateSceneDrawCalls.cs.hlsl: -------------------------------------------------------------------------------- 1 | #define NRI_ENABLE_DRAW_PARAMETERS_EMULATION 2 | 3 | #include "NRI.hlsl" 4 | #include "SceneViewerBindlessStructs.h" 5 | 6 | NRI_ROOT_CONSTANTS(CullingConstants, Constants, 0, 0); 7 | NRI_RESOURCE(StructuredBuffer, Materials, t, 0, 0); 8 | NRI_RESOURCE(StructuredBuffer, Meshes, t, 1, 0); 9 | NRI_RESOURCE(StructuredBuffer, Instances, t, 2, 0); 10 | NRI_FORMAT("r32ui") NRI_RESOURCE(RWBuffer, DrawCount, u, 0, 0); 11 | NRI_FORMAT("r32ui") NRI_RESOURCE(RWBuffer, Commands, u, 1, 0); 12 | 13 | groupshared uint s_DrawCount; 14 | 15 | #define CTA_SIZE 256 16 | 17 | [numthreads(CTA_SIZE, 1, 1)] 18 | void main(uint threadId : SV_DispatchThreadId) 19 | { 20 | if (threadId == 0) 21 | s_DrawCount = 0; 22 | 23 | GroupMemoryBarrierWithGroupSync(); 24 | 25 | for (uint instanceIndex = threadId; instanceIndex < Constants.DrawCount; instanceIndex += CTA_SIZE) 26 | { 27 | uint drawIndex = 0; 28 | InterlockedAdd(s_DrawCount, 1, drawIndex); 29 | 30 | uint meshIndex = Instances[instanceIndex].meshIndex; 31 | NRI_FILL_DRAW_INDEXED_DESC(Commands, drawIndex, 32 | Meshes[meshIndex].idxCount, 33 | 1, // TODO: batch draw instances with same mesh into one draw call 34 | Meshes[meshIndex].idxOffset, 35 | Meshes[meshIndex].vtxOffset, 36 | instanceIndex 37 | ); 38 | } 39 | 40 | GroupMemoryBarrierWithGroupSync(); 41 | 42 | if (threadId == 0) 43 | DrawCount[0] = s_DrawCount; 44 | } -------------------------------------------------------------------------------- /Shaders/RayTracingBox.rchit.hlsl: -------------------------------------------------------------------------------- 1 | // © 2021 NVIDIA Corporation 2 | 3 | #include "NRI.hlsl" 4 | 5 | NRI_RESOURCE(Buffer, vertexBuffers[], t, 0, 1); 6 | NRI_RESOURCE(Buffer, indexBuffers[], t, 0, 2); 7 | 8 | struct Payload 9 | { 10 | float3 hitValue; 11 | }; 12 | 13 | struct IntersectionAttributes 14 | { 15 | float2 barycentrics; 16 | }; 17 | 18 | [shader( "closesthit" )] 19 | void closest_hit( inout Payload payload : SV_RayPayload, in IntersectionAttributes intersectionAttributes : SV_IntersectionAttributes ) 20 | { 21 | uint instanceID = InstanceID( ); 22 | uint primitiveIndex = PrimitiveIndex( ); 23 | 24 | uint3 indices = indexBuffers[instanceID][primitiveIndex].xyz; 25 | 26 | float2 texCoords0 = vertexBuffers[instanceID][indices.x]; 27 | float2 texCoords1 = vertexBuffers[instanceID][indices.y]; 28 | float2 texCoords2 = vertexBuffers[instanceID][indices.z]; 29 | 30 | float3 barycentrics; 31 | barycentrics.yz = intersectionAttributes.barycentrics.xy; 32 | barycentrics.x = 1.0 - barycentrics.y - barycentrics.z; 33 | 34 | float2 texcoords = barycentrics.x * texCoords0 + barycentrics.y * texCoords1 + barycentrics.z * texCoords2; 35 | 36 | payload.hitValue = float3( texcoords, 0 ); 37 | } 38 | -------------------------------------------------------------------------------- /Shaders/RayTracingBox.rgen.hlsl: -------------------------------------------------------------------------------- 1 | // © 2021 NVIDIA Corporation 2 | 3 | #include "NRI.hlsl" 4 | 5 | NRI_FORMAT("rgba8") NRI_RESOURCE(RWTexture2D, outputImage, u, 0, 0); 6 | NRI_RESOURCE(RaytracingAccelerationStructure, topLevelAS, t, 1, 0); 7 | 8 | struct Payload 9 | { 10 | float3 hitValue; 11 | }; 12 | 13 | [shader( "raygeneration" )] 14 | void raygen( ) 15 | { 16 | uint2 dispatchRaysIndex = DispatchRaysIndex( ).xy; 17 | uint2 dispatchRaysDimensions = DispatchRaysDimensions( ).xy; 18 | 19 | const float2 pixelCenter = float2( dispatchRaysIndex.xy ) + float2( 0.5, 0.5 ); 20 | const float2 inUV = pixelCenter / float2( dispatchRaysDimensions.xy ); 21 | 22 | float2 d = inUV * 2.0 - 1.0; 23 | float aspectRatio = float( dispatchRaysDimensions.x ) / float( dispatchRaysDimensions.y ); 24 | 25 | RayDesc rayDesc; 26 | rayDesc.Origin = float3( 0, 0, -2.0 ); 27 | rayDesc.Direction = normalize( float3( d.x * aspectRatio, -d.y, 1 ) ); 28 | rayDesc.TMin = 0.001; 29 | rayDesc.TMax = 1000.0; 30 | 31 | uint rayFlags = RAY_FLAG_FORCE_OPAQUE; 32 | uint instanceInclusionMask = 0xff; 33 | uint rayContributionToHitGroupIndex = 0; 34 | uint multiplierForGeometryContributionToHitGroupIndex = 1; 35 | uint missShaderIndex = 0; 36 | 37 | Payload payload = (Payload)0; 38 | TraceRay( topLevelAS, rayFlags, instanceInclusionMask, rayContributionToHitGroupIndex, multiplierForGeometryContributionToHitGroupIndex, missShaderIndex, rayDesc, payload ); 39 | 40 | outputImage[dispatchRaysIndex] = float4( payload.hitValue, 0 ); 41 | } 42 | -------------------------------------------------------------------------------- /Shaders/RayTracingBox.rmiss.hlsl: -------------------------------------------------------------------------------- 1 | // © 2021 NVIDIA Corporation 2 | 3 | struct Payload 4 | { 5 | float3 hitValue; 6 | }; 7 | 8 | [shader( "miss" )] 9 | void miss( inout Payload payload : SV_RayPayload ) 10 | { 11 | payload.hitValue = float3( 0.4, 0.3, 0.35 ); 12 | } 13 | -------------------------------------------------------------------------------- /Shaders/RayTracingTriangle.rchit.hlsl: -------------------------------------------------------------------------------- 1 | // © 2021 NVIDIA Corporation 2 | 3 | struct Payload 4 | { 5 | float3 hitValue; 6 | }; 7 | 8 | struct IntersectionAttributes 9 | { 10 | float2 barycentrics; 11 | }; 12 | 13 | [shader( "closesthit" )] 14 | void closest_hit( inout Payload payload : SV_RayPayload, in IntersectionAttributes intersectionAttributes : SV_IntersectionAttributes ) 15 | { 16 | float2 barycentrics = intersectionAttributes.barycentrics; 17 | 18 | payload.hitValue = float3( 1.0 - barycentrics.x - barycentrics.y, barycentrics.x, barycentrics.y ); 19 | } 20 | -------------------------------------------------------------------------------- /Shaders/RayTracingTriangle.rgen.hlsl: -------------------------------------------------------------------------------- 1 | // © 2021 NVIDIA Corporation 2 | 3 | #include "NRI.hlsl" 4 | 5 | NRI_FORMAT("rgba8") NRI_RESOURCE(RWTexture2D, outputImage, u, 0, 0); 6 | NRI_RESOURCE(RaytracingAccelerationStructure, topLevelAS, t, 1, 0); 7 | 8 | struct Payload 9 | { 10 | float3 hitValue; 11 | }; 12 | 13 | [shader( "raygeneration" )] 14 | void raygen() 15 | { 16 | uint2 dispatchRaysIndex = DispatchRaysIndex().xy; 17 | uint2 dispatchRaysDimensions = DispatchRaysDimensions().xy; 18 | 19 | const float2 pixelCenter = float2( dispatchRaysIndex.xy ) + float2( 0.5, 0.5 ); 20 | const float2 inUV = pixelCenter / float2( dispatchRaysDimensions.xy ); 21 | 22 | float2 d = inUV * 2.0 - 1.0; 23 | float aspectRatio = float( dispatchRaysDimensions.x ) / float( dispatchRaysDimensions.y ); 24 | 25 | RayDesc rayDesc; 26 | rayDesc.Origin = float3( 0, 0, -2.0 ); 27 | rayDesc.Direction = normalize( float3( d.x * aspectRatio, -d.y, 1 ) ); 28 | rayDesc.TMin = 0.001; 29 | rayDesc.TMax = 100.0; 30 | 31 | uint rayFlags = RAY_FLAG_FORCE_OPAQUE; 32 | uint instanceInclusionMask = 0xff; 33 | uint rayContributionToHitGroupIndex = 0; 34 | uint multiplierForGeometryContributionToHitGroupIndex = 1; 35 | uint missShaderIndex = 0; 36 | 37 | Payload payload = (Payload)0; 38 | TraceRay( topLevelAS, rayFlags, instanceInclusionMask, rayContributionToHitGroupIndex, multiplierForGeometryContributionToHitGroupIndex, missShaderIndex, rayDesc, payload ); 39 | 40 | outputImage[dispatchRaysIndex] = float4( payload.hitValue, 0 ); 41 | } 42 | -------------------------------------------------------------------------------- /Shaders/RayTracingTriangle.rmiss.hlsl: -------------------------------------------------------------------------------- 1 | // © 2021 NVIDIA Corporation 2 | 3 | struct Payload 4 | { 5 | float3 hitValue; 6 | }; 7 | 8 | [shader( "miss" )] 9 | void miss( inout Payload payload : SV_RayPayload ) 10 | { 11 | payload.hitValue = float3( 0.4, 0.3, 0.35 ); 12 | } 13 | -------------------------------------------------------------------------------- /Shaders/SceneViewerBindlessStructs.h: -------------------------------------------------------------------------------- 1 | 2 | struct CullingConstants 3 | { 4 | float4 Frustum; 5 | uint32_t DrawCount; 6 | uint32_t EnableCulling; 7 | uint32_t ScreenWidth; 8 | uint32_t ScreenHeight; 9 | }; 10 | 11 | struct MaterialData 12 | { 13 | float4 baseColorAndMetallic; 14 | float4 emissiveColorAndRoughness; 15 | uint32_t baseColorTexIndex; 16 | uint32_t roughnessMetalnessTexIndex; 17 | uint32_t normalTexIndex; 18 | uint32_t emissiveTexIndex; 19 | }; 20 | 21 | struct MeshData 22 | { 23 | uint32_t vtxOffset; 24 | uint32_t vtxCount; 25 | uint32_t idxOffset; 26 | uint32_t idxCount; 27 | }; 28 | 29 | struct InstanceData 30 | { 31 | uint32_t meshIndex; 32 | uint32_t materialIndex; 33 | }; 34 | 35 | NRI_RESOURCE( cbuffer, GlobalConstants, b, 0, 0 ) 36 | { 37 | float4x4 gWorldToClip; 38 | float3 gCameraPos; 39 | }; 40 | -------------------------------------------------------------------------------- /Shaders/Shaders.cfg: -------------------------------------------------------------------------------- 1 | Box.vs.hlsl -T vs 2 | Box0.fs.hlsl -T ps 3 | Box1.fs.hlsl -T ps 4 | Box2.fs.hlsl -T ps 5 | Box3.fs.hlsl -T ps 6 | Box4.fs.hlsl -T ps 7 | Box5.fs.hlsl -T ps 8 | Box6.fs.hlsl -T ps 9 | Box7.fs.hlsl -T ps 10 | Compute.cs.hlsl -T cs 11 | GenerateSceneDrawCalls.cs.hlsl -T cs 12 | Forward.fs.hlsl -T ps 13 | Forward.vs.hlsl -T vs 14 | ForwardBindless.fs.hlsl -T ps 15 | ForwardBindless.vs.hlsl -T vs 16 | ForwardDiscard.fs.hlsl -T ps 17 | ForwardTransparent.fs.hlsl -T ps 18 | RayTracingBox.rchit.hlsl -T lib 19 | RayTracingBox.rgen.hlsl -T lib 20 | RayTracingBox.rmiss.hlsl -T lib 21 | RayTracingTriangle.rchit.hlsl -T lib 22 | RayTracingTriangle.rgen.hlsl -T lib 23 | RayTracingTriangle.rmiss.hlsl -T lib 24 | Simple.fs.hlsl -T ps 25 | Simple.vs.hlsl -T vs 26 | Surface.cs.hlsl -T cs 27 | Triangle.fs.hlsl -T ps 28 | Triangle.vs.hlsl -T vs 29 | TriangleFlexibleMultiview.vs.hlsl -T vs 30 | Triangles.fs.hlsl -T ps 31 | Triangles.vs.hlsl -T vs 32 | -------------------------------------------------------------------------------- /Shaders/Simple.fs.hlsl: -------------------------------------------------------------------------------- 1 | // © 2021 NVIDIA Corporation 2 | 3 | struct OutputVS 4 | { 5 | float4 position : SV_Position; 6 | float2 texCoords : TEXCOORD0; 7 | }; 8 | 9 | float4 main( in OutputVS input ) : SV_Target 10 | { 11 | return float4( input.texCoords, 0, 1 ); 12 | } 13 | -------------------------------------------------------------------------------- /Shaders/Simple.vs.hlsl: -------------------------------------------------------------------------------- 1 | // © 2021 NVIDIA Corporation 2 | 3 | #include "NRI.hlsl" 4 | 5 | struct InputVS 6 | { 7 | float3 position : POSITION; 8 | float2 texCoords : TEXCOORD0; 9 | }; 10 | 11 | struct OutputVS 12 | { 13 | float4 position : SV_Position; 14 | float2 texCoords : TEXCOORD0; 15 | }; 16 | 17 | NRI_RESOURCE( cbuffer, Constants, b, 0, 0 ) 18 | { 19 | float4x4 transform; 20 | }; 21 | 22 | OutputVS main( in InputVS input ) 23 | { 24 | OutputVS output; 25 | output.position = mul( transform, float4( input.position, 1 ) ); 26 | output.texCoords = input.texCoords; 27 | return output; 28 | } 29 | -------------------------------------------------------------------------------- /Shaders/Surface.cs.hlsl: -------------------------------------------------------------------------------- 1 | // © 2021 NVIDIA Corporation 2 | 3 | #include "NRI.hlsl" 4 | 5 | NRI_FORMAT("rgba8") NRI_RESOURCE(RWTexture2D, g_Result, u, 0, 0); 6 | 7 | [numthreads( 16, 16, 1 )] 8 | void main( uint2 pixelID : SV_DispatchThreadId ) 9 | { 10 | float3 result = float3( 0.0, 0.0, 0.0 ); 11 | 12 | for( float i = 1.0; i < 200.0; i += 0.1 ) 13 | { 14 | const float2 uv = float2( pixelID ) * i * 0.1; 15 | 16 | result.x += sin( uv.x * 0.1 ) + sin( uv.y * 0.3 ); 17 | result.y += sin( uv.x * 0.2 ) + sin( uv.y * 0.2 ); 18 | result.z += sin( uv.x * 0.3 ) + sin( uv.y * 0.1 ); 19 | } 20 | 21 | result = result * 0.5 + 0.5; 22 | float norm = max( result.x, max( result.y, result.z ) ); 23 | result /= norm; 24 | 25 | g_Result[pixelID] = float4( result * 0.5 + 0.5, 1.0 ); 26 | } 27 | -------------------------------------------------------------------------------- /Shaders/Triangle.fs.hlsl: -------------------------------------------------------------------------------- 1 | // © 2021 NVIDIA Corporation 2 | 3 | #include "NRI.hlsl" 4 | 5 | NRI_RESOURCE( cbuffer, CommonConstants, b, 0, 0 ) 6 | { 7 | float3 color; 8 | float scale; 9 | }; 10 | 11 | struct PushConstants 12 | { 13 | float transparency; 14 | }; 15 | 16 | NRI_ROOT_CONSTANTS( PushConstants, g_PushConstants, 1, 0 ); 17 | 18 | NRI_RESOURCE( Texture2D, g_DiffuseTexture, t, 0, 1 ); 19 | NRI_RESOURCE( SamplerState, g_Sampler, s, 0, 1 ); 20 | 21 | struct outputVS 22 | { 23 | float4 position : SV_Position; 24 | float2 texCoord : TEXCOORD0; 25 | }; 26 | 27 | float4 main( in outputVS input ) : SV_Target 28 | { 29 | float4 output; 30 | output.xyz = g_DiffuseTexture.Sample( g_Sampler, input.texCoord ).xyz * color; 31 | output.w = g_PushConstants.transparency; 32 | 33 | return output; 34 | } 35 | -------------------------------------------------------------------------------- /Shaders/Triangle.vs.hlsl: -------------------------------------------------------------------------------- 1 | // © 2021 NVIDIA Corporation 2 | 3 | #include "NRI.hlsl" 4 | 5 | NRI_RESOURCE( cbuffer, CommonConstants, b, 0, 0 ) 6 | { 7 | float3 color; 8 | float scale; 9 | }; 10 | 11 | struct outputVS 12 | { 13 | float4 position : SV_Position; 14 | float2 texCoord : TEXCOORD0; 15 | }; 16 | 17 | outputVS main 18 | ( 19 | float2 inPos : POSITION0, 20 | float2 inTexCoord : TEXCOORD0 21 | ) 22 | { 23 | outputVS output; 24 | 25 | output.position.xy = inPos * scale; 26 | output.position.zw = float2( 0.0, 1.0 ); 27 | output.texCoord = inTexCoord; 28 | 29 | return output; 30 | } 31 | -------------------------------------------------------------------------------- /Shaders/TriangleFlexibleMultiview.vs.hlsl: -------------------------------------------------------------------------------- 1 | // © 2021 NVIDIA Corporation 2 | 3 | #include "NRI.hlsl" 4 | 5 | NRI_RESOURCE( cbuffer, CommonConstants, b, 0, 0 ) 6 | { 7 | float3 color; 8 | float scale; 9 | }; 10 | 11 | struct outputVS 12 | { 13 | float4 position : SV_Position; 14 | float2 texCoord : TEXCOORD0; 15 | #ifdef NRI_DXIL 16 | uint viewportIndex : SV_ViewportArrayIndex; 17 | #endif 18 | }; 19 | 20 | outputVS main 21 | ( 22 | float2 inPos : POSITION0, 23 | float2 inTexCoord : TEXCOORD0 24 | #ifdef NRI_DXIL 25 | , uint viewID : SV_ViewID 26 | #endif 27 | ) 28 | { 29 | outputVS output; 30 | 31 | output.position.xy = inPos * scale; 32 | output.position.zw = float2( 0.0, 1.0 ); 33 | output.texCoord = inTexCoord; 34 | #ifdef NRI_DXIL 35 | output.viewportIndex = viewID; 36 | #endif 37 | 38 | return output; 39 | } 40 | -------------------------------------------------------------------------------- /Shaders/Triangles.fs.hlsl: -------------------------------------------------------------------------------- 1 | // © 2021 NVIDIA Corporation 2 | 3 | float4 main( float4 inPixelCoord : SV_POSITION ) : SV_Target 4 | { 5 | return float4( inPixelCoord.zzz, 1.0 ); 6 | } 7 | -------------------------------------------------------------------------------- /Shaders/Triangles.vs.hlsl: -------------------------------------------------------------------------------- 1 | // © 2021 NVIDIA Corporation 2 | 3 | struct OutputVS 4 | { 5 | float4 position : SV_Position; 6 | }; 7 | 8 | OutputVS main( float3 inPos : POSITION0 ) 9 | { 10 | OutputVS output; 11 | output.position = float4( inPos, 1.0 ); 12 | 13 | return output; 14 | } 15 | -------------------------------------------------------------------------------- /Source/AsyncCompute.cpp: -------------------------------------------------------------------------------- 1 | // © 2021 NVIDIA Corporation 2 | 3 | #include "NRIFramework.h" 4 | 5 | #include 6 | 7 | constexpr uint32_t VERTEX_NUM = 100000 * 3; 8 | 9 | struct NRIInterface 10 | : public nri::CoreInterface, 11 | public nri::HelperInterface, 12 | public nri::StreamerInterface, 13 | public nri::SwapChainInterface {}; 14 | 15 | struct QueuedFrame { 16 | nri::CommandAllocator* commandAllocatorGraphics; 17 | nri::CommandAllocator* commandAllocatorCompute; 18 | std::array commandBufferGraphics; 19 | nri::CommandBuffer* commandBufferCompute; 20 | }; 21 | 22 | struct Vertex { 23 | float position[3]; 24 | }; 25 | 26 | class Sample : public SampleBase { 27 | public: 28 | Sample() { 29 | } 30 | 31 | ~Sample(); 32 | 33 | bool Initialize(nri::GraphicsAPI graphicsAPI) override; 34 | void LatencySleep(uint32_t frameIndex) override; 35 | void PrepareFrame(uint32_t frameIndex) override; 36 | void RenderFrame(uint32_t frameIndex) override; 37 | 38 | private: 39 | NRIInterface NRI = {}; 40 | nri::Device* m_Device = nullptr; 41 | nri::Streamer* m_Streamer = nullptr; 42 | nri::SwapChain* m_SwapChain = nullptr; 43 | nri::Queue* m_GraphicsQueue = nullptr; 44 | nri::Queue* m_ComputeQueue = nullptr; 45 | nri::Fence* m_FrameFence = nullptr; 46 | nri::Fence* m_ComputeFence = nullptr; 47 | nri::DescriptorPool* m_DescriptorPool = nullptr; 48 | nri::PipelineLayout* m_GraphicsPipelineLayout = nullptr; 49 | nri::PipelineLayout* m_ComputePipelineLayout = nullptr; 50 | nri::Pipeline* m_GraphicsPipeline = nullptr; 51 | nri::Pipeline* m_ComputePipeline = nullptr; 52 | nri::Buffer* m_GeometryBuffer = nullptr; 53 | nri::Texture* m_Texture = nullptr; 54 | nri::DescriptorSet* m_DescriptorSet = nullptr; 55 | nri::Descriptor* m_Descriptor = nullptr; 56 | std::vector m_QueuedFrames = {}; 57 | std::vector m_SwapChainTextures; 58 | std::vector m_MemoryAllocations; 59 | bool m_IsAsyncMode = false; 60 | bool m_HasComputeQueue = false; 61 | }; 62 | 63 | Sample::~Sample() { 64 | NRI.WaitForIdle(*m_GraphicsQueue); 65 | 66 | for (QueuedFrame& queuedFrame : m_QueuedFrames) { 67 | for (size_t i = 0; i < queuedFrame.commandBufferGraphics.size(); i++) 68 | NRI.DestroyCommandBuffer(*queuedFrame.commandBufferGraphics[i]); 69 | 70 | NRI.DestroyCommandBuffer(*queuedFrame.commandBufferCompute); 71 | NRI.DestroyCommandAllocator(*queuedFrame.commandAllocatorCompute); 72 | NRI.DestroyCommandAllocator(*queuedFrame.commandAllocatorGraphics); 73 | } 74 | 75 | for (SwapChainTexture& swapChainTexture : m_SwapChainTextures) { 76 | NRI.DestroyFence(*swapChainTexture.acquireSemaphore); 77 | NRI.DestroyFence(*swapChainTexture.releaseSemaphore); 78 | NRI.DestroyDescriptor(*swapChainTexture.colorAttachment); 79 | } 80 | 81 | NRI.DestroyDescriptor(*m_Descriptor); 82 | NRI.DestroyTexture(*m_Texture); 83 | NRI.DestroyBuffer(*m_GeometryBuffer); 84 | NRI.DestroyPipeline(*m_GraphicsPipeline); 85 | NRI.DestroyPipeline(*m_ComputePipeline); 86 | NRI.DestroyPipelineLayout(*m_GraphicsPipelineLayout); 87 | NRI.DestroyPipelineLayout(*m_ComputePipelineLayout); 88 | NRI.DestroyDescriptorPool(*m_DescriptorPool); 89 | NRI.DestroyFence(*m_ComputeFence); 90 | NRI.DestroyFence(*m_FrameFence); 91 | NRI.DestroySwapChain(*m_SwapChain); 92 | NRI.DestroyStreamer(*m_Streamer); 93 | 94 | for (size_t i = 0; i < m_MemoryAllocations.size(); i++) 95 | NRI.FreeMemory(*m_MemoryAllocations[i]); 96 | 97 | DestroyImgui(); 98 | 99 | nri::nriDestroyDevice(*m_Device); 100 | } 101 | 102 | bool Sample::Initialize(nri::GraphicsAPI graphicsAPI) { 103 | // Adapters 104 | nri::AdapterDesc adapterDesc[2] = {}; 105 | uint32_t adapterDescsNum = helper::GetCountOf(adapterDesc); 106 | NRI_ABORT_ON_FAILURE(nri::nriEnumerateAdapters(adapterDesc, adapterDescsNum)); 107 | 108 | // Device 109 | nri::QueueFamilyDesc queueFamilies[2] = {}; 110 | queueFamilies[0].queueNum = 1; 111 | queueFamilies[0].queueType = nri::QueueType::GRAPHICS; 112 | queueFamilies[1].queueNum = 1; 113 | queueFamilies[1].queueType = nri::QueueType::COMPUTE; 114 | 115 | nri::DeviceCreationDesc deviceCreationDesc = {}; 116 | deviceCreationDesc.graphicsAPI = graphicsAPI; 117 | deviceCreationDesc.queueFamilies = queueFamilies; 118 | deviceCreationDesc.queueFamilyNum = helper::GetCountOf(queueFamilies); 119 | deviceCreationDesc.enableGraphicsAPIValidation = m_DebugAPI; 120 | deviceCreationDesc.enableNRIValidation = m_DebugNRI; 121 | deviceCreationDesc.enableD3D11CommandBufferEmulation = D3D11_COMMANDBUFFER_EMULATION; 122 | deviceCreationDesc.vkBindingOffsets = VK_BINDING_OFFSETS; 123 | deviceCreationDesc.adapterDesc = &adapterDesc[std::min(m_AdapterIndex, adapterDescsNum - 1)]; 124 | deviceCreationDesc.allocationCallbacks = m_AllocationCallbacks; 125 | NRI_ABORT_ON_FAILURE(nri::nriCreateDevice(deviceCreationDesc, m_Device)); 126 | 127 | // NRI 128 | NRI_ABORT_ON_FAILURE(nri::nriGetInterface(*m_Device, NRI_INTERFACE(nri::CoreInterface), (nri::CoreInterface*)&NRI)); 129 | NRI_ABORT_ON_FAILURE(nri::nriGetInterface(*m_Device, NRI_INTERFACE(nri::HelperInterface), (nri::HelperInterface*)&NRI)); 130 | NRI_ABORT_ON_FAILURE(nri::nriGetInterface(*m_Device, NRI_INTERFACE(nri::StreamerInterface), (nri::StreamerInterface*)&NRI)); 131 | NRI_ABORT_ON_FAILURE(nri::nriGetInterface(*m_Device, NRI_INTERFACE(nri::SwapChainInterface), (nri::SwapChainInterface*)&NRI)); 132 | 133 | const nri::DeviceDesc& deviceDesc = NRI.GetDeviceDesc(*m_Device); 134 | 135 | // Create streamer 136 | nri::StreamerDesc streamerDesc = {}; 137 | streamerDesc.dynamicBufferMemoryLocation = nri::MemoryLocation::HOST_UPLOAD; 138 | streamerDesc.dynamicBufferUsageBits = nri::BufferUsageBits::VERTEX_BUFFER | nri::BufferUsageBits::INDEX_BUFFER; 139 | streamerDesc.constantBufferMemoryLocation = nri::MemoryLocation::HOST_UPLOAD; 140 | streamerDesc.queuedFrameNum = GetQueuedFrameNum(); 141 | NRI_ABORT_ON_FAILURE(NRI.CreateStreamer(*m_Device, streamerDesc, m_Streamer)); 142 | 143 | // Command queues 144 | NRI_ABORT_ON_FAILURE(NRI.GetQueue(*m_Device, nri::QueueType::GRAPHICS, 0, m_GraphicsQueue)); 145 | NRI.SetDebugName(m_GraphicsQueue, "GraphicsQueue"); 146 | 147 | NRI.GetQueue(*m_Device, nri::QueueType::COMPUTE, 0, m_ComputeQueue); 148 | if (m_ComputeQueue) 149 | NRI.SetDebugName(m_ComputeQueue, "ComputeQueue"); 150 | 151 | m_HasComputeQueue = m_ComputeQueue && graphicsAPI != nri::GraphicsAPI::D3D11; 152 | m_IsAsyncMode = m_HasComputeQueue; 153 | 154 | // Fences 155 | NRI_ABORT_ON_FAILURE(NRI.CreateFence(*m_Device, 0, m_ComputeFence)); 156 | NRI_ABORT_ON_FAILURE(NRI.CreateFence(*m_Device, 0, m_FrameFence)); 157 | 158 | // Swap chain 159 | nri::Format swapChainFormat; 160 | { 161 | nri::SwapChainDesc swapChainDesc = {}; 162 | swapChainDesc.window = GetWindow(); 163 | swapChainDesc.queue = m_GraphicsQueue; 164 | swapChainDesc.format = nri::SwapChainFormat::BT709_G22_8BIT; 165 | swapChainDesc.verticalSyncInterval = m_VsyncInterval; 166 | swapChainDesc.width = (uint16_t)GetWindowResolution().x; 167 | swapChainDesc.height = (uint16_t)GetWindowResolution().y; 168 | swapChainDesc.textureNum = GetOptimalSwapChainTextureNum(); 169 | swapChainDesc.queuedFrameNum = GetQueuedFrameNum(); 170 | NRI_ABORT_ON_FAILURE(NRI.CreateSwapChain(*m_Device, swapChainDesc, m_SwapChain)); 171 | 172 | uint32_t swapChainTextureNum; 173 | nri::Texture* const* swapChainTextures = NRI.GetSwapChainTextures(*m_SwapChain, swapChainTextureNum); 174 | 175 | swapChainFormat = NRI.GetTextureDesc(*swapChainTextures[0]).format; 176 | 177 | for (uint32_t i = 0; i < swapChainTextureNum; i++) { 178 | nri::Texture2DViewDesc textureViewDesc = {swapChainTextures[i], nri::Texture2DViewType::COLOR_ATTACHMENT, swapChainFormat}; 179 | 180 | nri::Descriptor* colorAttachment = nullptr; 181 | NRI_ABORT_ON_FAILURE(NRI.CreateTexture2DView(textureViewDesc, colorAttachment)); 182 | 183 | nri::Fence* acquireSemaphore = nullptr; 184 | NRI_ABORT_ON_FAILURE(NRI.CreateFence(*m_Device, nri::SWAPCHAIN_SEMAPHORE, acquireSemaphore)); 185 | 186 | nri::Fence* releaseSemaphore = nullptr; 187 | NRI_ABORT_ON_FAILURE(NRI.CreateFence(*m_Device, nri::SWAPCHAIN_SEMAPHORE, releaseSemaphore)); 188 | 189 | SwapChainTexture& swapChainTexture = m_SwapChainTextures.emplace_back(); 190 | 191 | swapChainTexture = {}; 192 | swapChainTexture.acquireSemaphore = acquireSemaphore; 193 | swapChainTexture.releaseSemaphore = releaseSemaphore; 194 | swapChainTexture.texture = swapChainTextures[i]; 195 | swapChainTexture.colorAttachment = colorAttachment; 196 | swapChainTexture.attachmentFormat = swapChainFormat; 197 | } 198 | } 199 | 200 | // Queued frames 201 | m_QueuedFrames.resize(GetQueuedFrameNum()); 202 | for (QueuedFrame& queuedFrame : m_QueuedFrames) { 203 | NRI_ABORT_ON_FAILURE(NRI.CreateCommandAllocator(*m_GraphicsQueue, queuedFrame.commandAllocatorGraphics)); 204 | for (size_t i = 0; i < queuedFrame.commandBufferGraphics.size(); i++) 205 | NRI_ABORT_ON_FAILURE(NRI.CreateCommandBuffer(*queuedFrame.commandAllocatorGraphics, queuedFrame.commandBufferGraphics[i])); 206 | 207 | if (m_IsAsyncMode) { 208 | NRI_ABORT_ON_FAILURE(NRI.CreateCommandAllocator(*m_ComputeQueue, queuedFrame.commandAllocatorCompute)); 209 | NRI_ABORT_ON_FAILURE(NRI.CreateCommandBuffer(*queuedFrame.commandAllocatorCompute, queuedFrame.commandBufferCompute)); 210 | } 211 | } 212 | 213 | utils::ShaderCodeStorage shaderCodeStorage; 214 | { // Graphics pipeline 215 | nri::PipelineLayoutDesc pipelineLayoutDesc = {}; 216 | pipelineLayoutDesc.shaderStages = nri::StageBits::VERTEX_SHADER | nri::StageBits::FRAGMENT_SHADER; 217 | NRI_ABORT_ON_FAILURE(NRI.CreatePipelineLayout(*m_Device, pipelineLayoutDesc, m_GraphicsPipelineLayout)); 218 | 219 | nri::VertexStreamDesc vertexStreamDesc = {}; 220 | vertexStreamDesc.bindingSlot = 0; 221 | 222 | nri::VertexAttributeDesc vertexAttributeDesc[1] = {}; 223 | { 224 | vertexAttributeDesc[0].format = nri::Format::RGB32_SFLOAT; 225 | vertexAttributeDesc[0].streamIndex = 0; 226 | vertexAttributeDesc[0].offset = helper::GetOffsetOf(&Vertex::position); 227 | vertexAttributeDesc[0].d3d = {"POSITION", 0}; 228 | vertexAttributeDesc[0].vk.location = {0}; 229 | } 230 | 231 | nri::VertexInputDesc vertexInputDesc = {}; 232 | vertexInputDesc.attributes = vertexAttributeDesc; 233 | vertexInputDesc.attributeNum = (uint8_t)helper::GetCountOf(vertexAttributeDesc); 234 | vertexInputDesc.streams = &vertexStreamDesc; 235 | vertexInputDesc.streamNum = 1; 236 | 237 | nri::InputAssemblyDesc inputAssemblyDesc = {}; 238 | inputAssemblyDesc.topology = nri::Topology::TRIANGLE_LIST; 239 | 240 | nri::RasterizationDesc rasterizationDesc = {}; 241 | rasterizationDesc.fillMode = nri::FillMode::SOLID; 242 | rasterizationDesc.cullMode = nri::CullMode::NONE; 243 | 244 | nri::ColorAttachmentDesc colorAttachmentDesc = {}; 245 | colorAttachmentDesc.format = swapChainFormat; 246 | colorAttachmentDesc.colorWriteMask = nri::ColorWriteBits::RGBA; 247 | 248 | nri::OutputMergerDesc outputMergerDesc = {}; 249 | outputMergerDesc.colors = &colorAttachmentDesc; 250 | outputMergerDesc.colorNum = 1; 251 | 252 | nri::ShaderDesc shaderStages[] = { 253 | utils::LoadShader(deviceDesc.graphicsAPI, "Triangles.vs", shaderCodeStorage), 254 | utils::LoadShader(deviceDesc.graphicsAPI, "Triangles.fs", shaderCodeStorage), 255 | }; 256 | 257 | nri::GraphicsPipelineDesc graphicsPipelineDesc = {}; 258 | graphicsPipelineDesc.pipelineLayout = m_GraphicsPipelineLayout; 259 | graphicsPipelineDesc.vertexInput = &vertexInputDesc; 260 | graphicsPipelineDesc.inputAssembly = inputAssemblyDesc; 261 | graphicsPipelineDesc.rasterization = rasterizationDesc; 262 | graphicsPipelineDesc.outputMerger = outputMergerDesc; 263 | graphicsPipelineDesc.shaders = shaderStages; 264 | graphicsPipelineDesc.shaderNum = helper::GetCountOf(shaderStages); 265 | NRI_ABORT_ON_FAILURE(NRI.CreateGraphicsPipeline(*m_Device, graphicsPipelineDesc, m_GraphicsPipeline)); 266 | } 267 | 268 | { // Compute pipeline 269 | nri::DescriptorRangeDesc descriptorRangeStorage = {0, 1, nri::DescriptorType::STORAGE_TEXTURE, nri::StageBits::COMPUTE_SHADER}; 270 | 271 | nri::DescriptorSetDesc descriptorSetDesc = {0, &descriptorRangeStorage, 1}; 272 | 273 | nri::PipelineLayoutDesc pipelineLayoutDesc = {}; 274 | pipelineLayoutDesc.descriptorSetNum = 1; 275 | pipelineLayoutDesc.descriptorSets = &descriptorSetDesc; 276 | pipelineLayoutDesc.shaderStages = nri::StageBits::COMPUTE_SHADER; 277 | NRI_ABORT_ON_FAILURE(NRI.CreatePipelineLayout(*m_Device, pipelineLayoutDesc, m_ComputePipelineLayout)); 278 | 279 | nri::ComputePipelineDesc computePipelineDesc = {}; 280 | computePipelineDesc.pipelineLayout = m_ComputePipelineLayout; 281 | computePipelineDesc.shader = utils::LoadShader(deviceDesc.graphicsAPI, "Surface.cs", shaderCodeStorage); 282 | NRI_ABORT_ON_FAILURE(NRI.CreateComputePipeline(*m_Device, computePipelineDesc, m_ComputePipeline)); 283 | } 284 | 285 | { // Storage texture 286 | nri::TextureDesc textureDesc = {}; 287 | textureDesc.type = nri::TextureType::TEXTURE_2D; 288 | textureDesc.usage = nri::TextureUsageBits::SHADER_RESOURCE_STORAGE; 289 | textureDesc.format = swapChainFormat; 290 | textureDesc.width = (uint16_t)GetWindowResolution().x / 2; 291 | textureDesc.height = (uint16_t)GetWindowResolution().y; 292 | textureDesc.mipNum = 1; 293 | 294 | NRI_ABORT_ON_FAILURE(NRI.CreateTexture(*m_Device, textureDesc, m_Texture)); 295 | } 296 | 297 | { // Geometry buffer 298 | nri::BufferDesc bufferDesc = {}; 299 | bufferDesc.size = sizeof(Vertex) * VERTEX_NUM; 300 | bufferDesc.usage = nri::BufferUsageBits::VERTEX_BUFFER | nri::BufferUsageBits::INDEX_BUFFER; 301 | NRI_ABORT_ON_FAILURE(NRI.CreateBuffer(*m_Device, bufferDesc, m_GeometryBuffer)); 302 | } 303 | 304 | nri::ResourceGroupDesc resourceGroupDesc = {}; 305 | resourceGroupDesc.memoryLocation = nri::MemoryLocation::DEVICE; 306 | resourceGroupDesc.bufferNum = 1; 307 | resourceGroupDesc.buffers = &m_GeometryBuffer; 308 | resourceGroupDesc.textureNum = 1; 309 | resourceGroupDesc.textures = &m_Texture; 310 | 311 | m_MemoryAllocations.resize(NRI.CalculateAllocationNumber(*m_Device, resourceGroupDesc), nullptr); 312 | NRI_ABORT_ON_FAILURE(NRI.AllocateAndBindMemory(*m_Device, resourceGroupDesc, m_MemoryAllocations.data())) 313 | 314 | { // Descriptor pool 315 | nri::DescriptorPoolDesc descriptorPoolDesc = {}; 316 | descriptorPoolDesc.descriptorSetMaxNum = 1; 317 | descriptorPoolDesc.storageTextureMaxNum = 1; 318 | 319 | NRI_ABORT_ON_FAILURE(NRI.CreateDescriptorPool(*m_Device, descriptorPoolDesc, m_DescriptorPool)); 320 | } 321 | 322 | { // Storage descriptor 323 | nri::Texture2DViewDesc texture2DViewDesc = {m_Texture, nri::Texture2DViewType::SHADER_RESOURCE_STORAGE_2D, swapChainFormat}; 324 | 325 | NRI_ABORT_ON_FAILURE(NRI.CreateTexture2DView(texture2DViewDesc, m_Descriptor)); 326 | } 327 | 328 | { // Descriptor set 329 | NRI_ABORT_ON_FAILURE(NRI.AllocateDescriptorSets(*m_DescriptorPool, *m_ComputePipelineLayout, 0, &m_DescriptorSet, 1, 330 | 0)); 331 | 332 | nri::DescriptorRangeUpdateDesc descriptorRangeUpdateDesc = {&m_Descriptor, 1, 0}; 333 | NRI.UpdateDescriptorRanges(*m_DescriptorSet, 0, 1, &descriptorRangeUpdateDesc); 334 | } 335 | 336 | Rng::Hash::Initialize(m_RngState, 567, 57); 337 | 338 | { // Upload data 339 | std::vector geometryBufferData(VERTEX_NUM); 340 | for (uint32_t i = 0; i < VERTEX_NUM; i += 3) { 341 | Vertex& v0 = geometryBufferData[i]; 342 | v0.position[0] = Rng::Hash::GetFloat(m_RngState) * 2.0f - 1.0f; 343 | v0.position[1] = Rng::Hash::GetFloat(m_RngState) * 2.0f - 1.0f; 344 | v0.position[2] = Rng::Hash::GetFloat(m_RngState); 345 | 346 | Vertex& v1 = geometryBufferData[i + 1]; 347 | v1.position[0] = v0.position[0] + (Rng::Hash::GetFloat(m_RngState) * 2.0f - 1.0f) * 0.3f; 348 | v1.position[1] = v0.position[1] + (Rng::Hash::GetFloat(m_RngState) * 2.0f - 1.0f) * 0.3f; 349 | v1.position[2] = Rng::Hash::GetFloat(m_RngState); 350 | 351 | Vertex& v2 = geometryBufferData[i + 2]; 352 | v2.position[0] = v0.position[0] + (Rng::Hash::GetFloat(m_RngState) * 2.0f - 1.0f) * 0.3f; 353 | v2.position[1] = v0.position[1] + (Rng::Hash::GetFloat(m_RngState) * 2.0f - 1.0f) * 0.3f; 354 | v2.position[2] = Rng::Hash::GetFloat(m_RngState); 355 | } 356 | 357 | nri::TextureUploadDesc textureData = {}; 358 | textureData.subresources = nullptr; 359 | textureData.texture = m_Texture; 360 | textureData.after = {nri::AccessBits::SHADER_RESOURCE_STORAGE, nri::Layout::SHADER_RESOURCE_STORAGE}; 361 | 362 | nri::BufferUploadDesc bufferData = {}; 363 | bufferData.buffer = m_GeometryBuffer; 364 | bufferData.data = geometryBufferData.data(); 365 | bufferData.after = {nri::AccessBits::VERTEX_BUFFER}; 366 | 367 | NRI_ABORT_ON_FAILURE(NRI.UploadData(*m_GraphicsQueue, &textureData, 1, &bufferData, 1)); 368 | } 369 | 370 | return InitImgui(*m_Device); 371 | } 372 | 373 | void Sample::LatencySleep(uint32_t frameIndex) { 374 | uint32_t queuedFrameIndex = frameIndex % GetQueuedFrameNum(); 375 | const QueuedFrame& queuedFrame = m_QueuedFrames[queuedFrameIndex]; 376 | 377 | NRI.Wait(*m_FrameFence, frameIndex >= GetQueuedFrameNum() ? 1 + frameIndex - GetQueuedFrameNum() : 0); 378 | NRI.ResetCommandAllocator(*queuedFrame.commandAllocatorGraphics); 379 | 380 | if (m_IsAsyncMode) 381 | NRI.ResetCommandAllocator(*queuedFrame.commandAllocatorCompute); 382 | } 383 | 384 | void Sample::PrepareFrame(uint32_t) { 385 | ImGui::NewFrame(); 386 | { 387 | ImGui::SetNextWindowPos(ImVec2(30, 30), ImGuiCond_Once); 388 | ImGui::SetNextWindowSize(ImVec2(0, 0)); 389 | ImGui::Begin("Settings", nullptr, ImGuiWindowFlags_NoResize); 390 | { 391 | ImGui::Text("Left - graphics, Right - compute"); 392 | ImGui::BeginDisabled(!m_HasComputeQueue); 393 | ImGui::Checkbox("Use ASYNC compute", &m_IsAsyncMode); 394 | ImGui::EndDisabled(); 395 | } 396 | ImGui::End(); 397 | } 398 | ImGui::EndFrame(); 399 | ImGui::Render(); 400 | } 401 | 402 | void Sample::RenderFrame(uint32_t frameIndex) { 403 | const uint32_t windowWidth = GetWindowResolution().x; 404 | const uint32_t windowHeight = GetWindowResolution().y; 405 | uint32_t queuedFrameIndex = frameIndex % GetQueuedFrameNum(); 406 | const QueuedFrame& queuedFrame = m_QueuedFrames[queuedFrameIndex]; 407 | 408 | // Acquire a swap chain texture 409 | uint32_t recycledSemaphoreIndex = frameIndex % (uint32_t)m_SwapChainTextures.size(); 410 | nri::Fence* swapChainAcquireSemaphore = m_SwapChainTextures[recycledSemaphoreIndex].acquireSemaphore; 411 | 412 | uint32_t currentSwapChainTextureIndex = 0; 413 | NRI.AcquireNextTexture(*m_SwapChain, *swapChainAcquireSemaphore, currentSwapChainTextureIndex); 414 | 415 | const SwapChainTexture& swapChainTexture = m_SwapChainTextures[currentSwapChainTextureIndex]; 416 | 417 | // Record command buffer #0 (graphics or compute) 418 | nri::TextureBarrierDesc textureBarriers[2] = {}; 419 | 420 | textureBarriers[0].texture = swapChainTexture.texture; 421 | textureBarriers[0].after = {nri::AccessBits::COLOR_ATTACHMENT, nri::Layout::COLOR_ATTACHMENT}; 422 | textureBarriers[0].layerNum = 1; 423 | textureBarriers[0].mipNum = 1; 424 | 425 | textureBarriers[1].texture = m_Texture; 426 | textureBarriers[1].layerNum = 1; 427 | textureBarriers[1].mipNum = 1; 428 | 429 | nri::BarrierGroupDesc barrierGroupDesc = {}; 430 | barrierGroupDesc.textures = textureBarriers; 431 | 432 | nri::CommandBuffer& commandBuffer0 = m_IsAsyncMode ? *queuedFrame.commandBufferCompute : *queuedFrame.commandBufferGraphics[0]; 433 | NRI.BeginCommandBuffer(commandBuffer0, m_DescriptorPool); 434 | { 435 | helper::Annotation annotation(NRI, commandBuffer0, "Compute"); 436 | 437 | const uint32_t nx = ((windowWidth / 2) + 15) / 16; 438 | const uint32_t ny = (windowHeight + 15) / 16; 439 | 440 | NRI.CmdSetPipelineLayout(commandBuffer0, *m_ComputePipelineLayout); 441 | NRI.CmdSetPipeline(commandBuffer0, *m_ComputePipeline); 442 | NRI.CmdSetDescriptorSet(commandBuffer0, 0, *m_DescriptorSet, nullptr); 443 | NRI.CmdDispatch(commandBuffer0, {nx, ny, 1}); 444 | } 445 | NRI.EndCommandBuffer(commandBuffer0); 446 | 447 | // Record command buffer #1 (graphics) 448 | nri::CommandBuffer& commandBuffer1 = *queuedFrame.commandBufferGraphics[1]; 449 | NRI.BeginCommandBuffer(commandBuffer1, nullptr); 450 | { 451 | helper::Annotation annotation(NRI, commandBuffer1, "Graphics"); 452 | 453 | barrierGroupDesc.textureNum = 1; 454 | NRI.CmdBarrier(commandBuffer1, barrierGroupDesc); 455 | 456 | nri::AttachmentsDesc attachmentsDesc = {}; 457 | attachmentsDesc.colorNum = 1; 458 | attachmentsDesc.colors = &swapChainTexture.colorAttachment; 459 | 460 | NRI.CmdBeginRendering(commandBuffer1, attachmentsDesc); 461 | { 462 | const nri::Viewport viewport = {0.0f, 0.0f, (float)windowWidth, (float)windowHeight, 0.0f, 1.0f}; 463 | const nri::Rect scissorRect = {0, 0, (nri::Dim_t)windowWidth, (nri::Dim_t)windowHeight}; 464 | NRI.CmdSetViewports(commandBuffer1, &viewport, 1); 465 | NRI.CmdSetScissors(commandBuffer1, &scissorRect, 1); 466 | 467 | nri::ClearDesc clearDesc = {}; 468 | clearDesc.colorAttachmentIndex = 0; 469 | clearDesc.planes = nri::PlaneBits::COLOR; 470 | NRI.CmdClearAttachments(commandBuffer1, &clearDesc, 1, nullptr, 0); 471 | 472 | NRI.CmdSetPipelineLayout(commandBuffer1, *m_GraphicsPipelineLayout); 473 | NRI.CmdSetPipeline(commandBuffer1, *m_GraphicsPipeline); 474 | NRI.CmdSetIndexBuffer(commandBuffer1, *m_GeometryBuffer, 0, nri::IndexType::UINT16); 475 | 476 | nri::VertexBufferDesc vertexBufferDesc = {}; 477 | vertexBufferDesc.buffer = m_GeometryBuffer; 478 | vertexBufferDesc.offset = 0; 479 | vertexBufferDesc.stride = sizeof(Vertex); 480 | NRI.CmdSetVertexBuffers(commandBuffer1, 0, &vertexBufferDesc, 1); 481 | 482 | NRI.CmdDraw(commandBuffer1, {VERTEX_NUM, 1, 0, 0}); 483 | 484 | RenderImgui(commandBuffer1, *m_Streamer, swapChainTexture.attachmentFormat, 1.0f, true); 485 | } 486 | NRI.CmdEndRendering(commandBuffer1); 487 | } 488 | NRI.EndCommandBuffer(commandBuffer1); 489 | 490 | // Record command buffer #2 (graphics) 491 | nri::CommandBuffer& commandBuffer2 = *queuedFrame.commandBufferGraphics[2]; 492 | NRI.BeginCommandBuffer(commandBuffer2, nullptr); 493 | { 494 | helper::Annotation annotation(NRI, commandBuffer2, "Composition"); 495 | 496 | // Resource transitions 497 | textureBarriers[0].before = {nri::AccessBits::COLOR_ATTACHMENT, nri::Layout::COLOR_ATTACHMENT, nri::StageBits::COLOR_ATTACHMENT}; 498 | textureBarriers[0].after = {nri::AccessBits::COPY_DESTINATION, nri::Layout::COPY_DESTINATION, nri::StageBits::COPY}; 499 | 500 | textureBarriers[1].before = {nri::AccessBits::SHADER_RESOURCE_STORAGE, nri::Layout::SHADER_RESOURCE_STORAGE, nri::StageBits::COMPUTE_SHADER}; 501 | textureBarriers[1].after = {nri::AccessBits::COPY_SOURCE, nri::Layout::COPY_SOURCE, nri::StageBits::COPY}; 502 | 503 | barrierGroupDesc.textureNum = 2; 504 | NRI.CmdBarrier(commandBuffer2, barrierGroupDesc); 505 | 506 | // Copy texture produced by compute to back buffer 507 | nri::TextureRegionDesc dstRegion = {}; 508 | dstRegion.x = (uint16_t)windowWidth / 2; 509 | 510 | nri::TextureRegionDesc srcRegion = {}; 511 | srcRegion.width = (uint16_t)windowWidth / 2; 512 | srcRegion.height = (uint16_t)windowHeight; 513 | srcRegion.depth = 1; 514 | 515 | NRI.CmdCopyTexture(commandBuffer2, *swapChainTexture.texture, &dstRegion, *m_Texture, &srcRegion); 516 | 517 | // Resource transitions 518 | textureBarriers[0].before = {nri::AccessBits::COPY_DESTINATION, nri::Layout::COPY_DESTINATION, nri::StageBits::COPY}; 519 | textureBarriers[0].after = {nri::AccessBits::UNKNOWN, nri::Layout::PRESENT}; 520 | 521 | textureBarriers[1].before = {nri::AccessBits::COPY_SOURCE, nri::Layout::COPY_SOURCE, nri::StageBits::COPY}; 522 | textureBarriers[1].after = {nri::AccessBits::SHADER_RESOURCE_STORAGE, nri::Layout::SHADER_RESOURCE_STORAGE, nri::StageBits::COMPUTE_SHADER}; 523 | 524 | barrierGroupDesc.textureNum = 2; 525 | NRI.CmdBarrier(commandBuffer2, barrierGroupDesc); 526 | } 527 | NRI.EndCommandBuffer(commandBuffer2); 528 | 529 | nri::CommandBuffer* commandBufferArray[3] = {&commandBuffer0, &commandBuffer1, &commandBuffer2}; 530 | 531 | { // Submit work 532 | nri::FenceSubmitDesc textureAcquiredFence = {}; 533 | textureAcquiredFence.fence = swapChainAcquireSemaphore; 534 | textureAcquiredFence.stages = nri::StageBits::COPY; 535 | 536 | nri::FenceSubmitDesc renderingFinishedFence = {}; 537 | renderingFinishedFence.fence = swapChainTexture.releaseSemaphore; 538 | 539 | if (m_IsAsyncMode) { 540 | nri::FenceSubmitDesc computeFinishedFence = {}; 541 | computeFinishedFence.fence = m_ComputeFence; 542 | computeFinishedFence.value = 1 + frameIndex; 543 | 544 | { // Submit the Compute task into the COMPUTE queue 545 | nri::FenceSubmitDesc waitFence = {}; 546 | waitFence.fence = m_FrameFence; 547 | waitFence.value = frameIndex; 548 | 549 | nri::QueueSubmitDesc computeTask = {}; 550 | computeTask.waitFences = &waitFence; // Wait for the previous frame completion before execution 551 | computeTask.waitFenceNum = 1; 552 | computeTask.commandBuffers = &commandBufferArray[0]; 553 | computeTask.commandBufferNum = 1; 554 | computeTask.signalFences = &computeFinishedFence; 555 | computeTask.signalFenceNum = 1; 556 | 557 | NRI.QueueSubmit(*m_ComputeQueue, computeTask); 558 | } 559 | 560 | { // Submit the Graphics task into the GRAPHICS queue 561 | nri::QueueSubmitDesc graphicsTask = {}; 562 | graphicsTask.commandBuffers = &commandBufferArray[1]; 563 | graphicsTask.commandBufferNum = 1; 564 | 565 | NRI.QueueSubmit(*m_GraphicsQueue, graphicsTask); 566 | } 567 | 568 | { // Submit the Composition task into the GRAPHICS queue 569 | nri::FenceSubmitDesc waitFences[] = {textureAcquiredFence, computeFinishedFence}; 570 | 571 | nri::QueueSubmitDesc compositionTask = {}; 572 | compositionTask.waitFences = waitFences; // Wait for the Compute task completion before execution 573 | compositionTask.waitFenceNum = helper::GetCountOf(waitFences); 574 | compositionTask.commandBuffers = &commandBufferArray[2]; 575 | compositionTask.commandBufferNum = 1; 576 | compositionTask.signalFences = &renderingFinishedFence; 577 | compositionTask.signalFenceNum = 1; 578 | 579 | NRI.QueueSubmit(*m_GraphicsQueue, compositionTask); 580 | } 581 | } else { 582 | // Submit all tasks to the GRAPHICS queue 583 | nri::QueueSubmitDesc allTasks = {}; 584 | allTasks.waitFences = &textureAcquiredFence; 585 | allTasks.waitFenceNum = 1; 586 | allTasks.commandBuffers = commandBufferArray; 587 | allTasks.commandBufferNum = helper::GetCountOf(commandBufferArray); 588 | allTasks.signalFences = &renderingFinishedFence; 589 | allTasks.signalFenceNum = 1; 590 | 591 | NRI.QueueSubmit(*m_GraphicsQueue, allTasks); 592 | } 593 | } 594 | 595 | NRI.EndStreamerFrame(*m_Streamer); 596 | 597 | // Present 598 | NRI.QueuePresent(*m_SwapChain, *swapChainTexture.releaseSemaphore); 599 | 600 | { // Signaling after "Present" improves D3D11 performance a bit 601 | nri::FenceSubmitDesc signalFence = {}; 602 | signalFence.fence = m_FrameFence; 603 | signalFence.value = 1 + frameIndex; 604 | 605 | nri::QueueSubmitDesc queueSubmitDesc = {}; 606 | queueSubmitDesc.signalFences = &signalFence; 607 | queueSubmitDesc.signalFenceNum = 1; 608 | 609 | NRI.QueueSubmit(*m_GraphicsQueue, queueSubmitDesc); 610 | } 611 | } 612 | 613 | SAMPLE_MAIN(Sample, 0); 614 | -------------------------------------------------------------------------------- /Source/Buffers.c: -------------------------------------------------------------------------------- 1 | // © 2021 NVIDIA Corporation 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "NRI.h" 9 | 10 | #include "Extensions/NRIDeviceCreation.h" 11 | #include "Extensions/NRIHelper.h" 12 | #include "Extensions/NRIResourceAllocator.h" 13 | 14 | #define NRI_ABORT_ON_FAILURE(result) \ 15 | if (result != NriResult_SUCCESS) \ 16 | exit(1); 17 | 18 | int main(int argc, char** argv) { 19 | // Settings 20 | bool useSelfCopies = true; // works only with barriers in-between 21 | const bool useBarriersBetweenSelfCopies = true; 22 | const uint32_t bufferZeroSize = 1024; 23 | const uint32_t bufferOneSize = 64 * 1024; 24 | NriGraphicsAPI graphicsAPI = NriGraphicsAPI_VK; 25 | 26 | bool debugAPI = false; 27 | bool debugNRI = false; 28 | uint32_t adapterIndex = 0; 29 | for (int i = 0; i < argc; i++) { 30 | if (!strcmp(argv[i], "--api=D3D12")) 31 | graphicsAPI = NriGraphicsAPI_D3D12; 32 | else if (!strcmp(argv[i], "--api=VULKAN")) 33 | graphicsAPI = NriGraphicsAPI_VK; 34 | else if (!strcmp(argv[i], "--debugAPI")) 35 | debugAPI = true; 36 | else if (!strcmp(argv[i], "--debugNRI")) 37 | debugNRI = true; 38 | else if (!strcmp(argv[i], "--adapter=1")) 39 | adapterIndex = 1; 40 | } 41 | 42 | // Create device 43 | NriDevice* device = NULL; 44 | { 45 | NriAdapterDesc adapterDescs[2] = {0}; 46 | uint32_t adapterDescsNum = 2; 47 | NRI_ABORT_ON_FAILURE(nriEnumerateAdapters( 48 | adapterDescs, &adapterDescsNum)); 49 | 50 | NRI_ABORT_ON_FAILURE(nriCreateDevice( 51 | &(NriDeviceCreationDesc){ 52 | .graphicsAPI = graphicsAPI, 53 | .enableGraphicsAPIValidation = debugAPI, 54 | .enableNRIValidation = debugNRI, 55 | .adapterDesc = &adapterDescs[adapterIndex < adapterDescsNum ? adapterIndex : adapterDescsNum - 1], 56 | }, 57 | &device)); 58 | } 59 | 60 | // Query interfaces 61 | NriCoreInterface iCore = {0}; 62 | NriHelperInterface iHelper = {0}; 63 | NriResourceAllocatorInterface iResourceAllocator = {0}; 64 | { 65 | NRI_ABORT_ON_FAILURE(nriGetInterface( 66 | device, NRI_INTERFACE(NriCoreInterface), &iCore)); 67 | 68 | NRI_ABORT_ON_FAILURE(nriGetInterface( 69 | device, NRI_INTERFACE(NriHelperInterface), &iHelper)); 70 | 71 | NRI_ABORT_ON_FAILURE(nriGetInterface( 72 | device, NRI_INTERFACE(NriResourceAllocatorInterface), &iResourceAllocator)); 73 | 74 | const NriDeviceDesc* deviceDesc = iCore.GetDeviceDesc(device); 75 | if (deviceDesc->graphicsAPI == NriGraphicsAPI_D3D11 || !deviceDesc->features.enchancedBarrier) 76 | useSelfCopies = false; // Vulkan or D3D12 with AgilitySDK required 77 | } 78 | 79 | // Create buffers 80 | NriBuffer* bufferZero; 81 | NriBuffer* bufferOne; 82 | NriBuffer* bufferReadback; 83 | { 84 | NRI_ABORT_ON_FAILURE(iResourceAllocator.AllocateBuffer( 85 | device, &(NriAllocateBufferDesc){ 86 | .memoryLocation = NriMemoryLocation_DEVICE, 87 | .desc = (NriBufferDesc){ 88 | .size = bufferZeroSize, 89 | .usage = NriBufferUsageBits_NONE, 90 | }, 91 | }, 92 | &bufferZero)); 93 | 94 | NRI_ABORT_ON_FAILURE(iResourceAllocator.AllocateBuffer( 95 | device, &(NriAllocateBufferDesc){ 96 | .memoryLocation = NriMemoryLocation_DEVICE, 97 | .desc = (NriBufferDesc){ 98 | .size = bufferOneSize, 99 | .usage = NriBufferUsageBits_NONE, 100 | }, 101 | }, 102 | &bufferOne)); 103 | 104 | NRI_ABORT_ON_FAILURE(iResourceAllocator.AllocateBuffer( 105 | device, &(NriAllocateBufferDesc){ 106 | .memoryLocation = NriMemoryLocation_HOST_READBACK, 107 | .desc = (NriBufferDesc){ 108 | .size = bufferOneSize, 109 | .usage = NriBufferUsageBits_NONE, 110 | }, 111 | }, 112 | &bufferReadback)); 113 | } 114 | 115 | // Fill buffers 116 | NriQueue* queue = NULL; 117 | { 118 | NRI_ABORT_ON_FAILURE(iCore.GetQueue(device, NriQueueType_GRAPHICS, 0, &queue)); 119 | 120 | uint8_t* zeroData = (uint8_t*)malloc(bufferZeroSize); 121 | memset(zeroData, 0, bufferZeroSize); 122 | 123 | uint8_t* garbageData = (uint8_t*)malloc(bufferOneSize); 124 | memset(garbageData, 1, bufferOneSize); 125 | 126 | NriBufferUploadDesc bufferUploads[2] = { 127 | (NriBufferUploadDesc){ 128 | // fill "bufferZero" with "0" 129 | .data = zeroData, 130 | .buffer = bufferZero, 131 | .after = (NriAccessStage){ 132 | .access = NriAccessBits_COPY_SOURCE, 133 | }, 134 | }, 135 | (NriBufferUploadDesc){ 136 | // fill "bufferOne" with "1" 137 | .data = garbageData, 138 | .buffer = bufferOne, 139 | .after = (NriAccessStage){ 140 | .access = NriAccessBits_COPY_DESTINATION, 141 | }, 142 | }, 143 | }; 144 | 145 | iHelper.UploadData(queue, NULL, 0, bufferUploads, 2); 146 | 147 | free(zeroData); 148 | free(garbageData); 149 | } 150 | 151 | // Main 152 | NriCommandAllocator* commandAllocator = NULL; 153 | NriCommandBuffer* commandBuffer = NULL; 154 | { 155 | NRI_ABORT_ON_FAILURE(iCore.CreateCommandAllocator(queue, &commandAllocator)); 156 | NRI_ABORT_ON_FAILURE(iCore.CreateCommandBuffer(commandAllocator, &commandBuffer)); 157 | 158 | iCore.BeginCommandBuffer(commandBuffer, NULL); 159 | { 160 | // Clear "bufferOne" using "bufferZero" 161 | uint32_t size = bufferOneSize; 162 | uint32_t offset = 0; 163 | 164 | if (useSelfCopies) { 165 | // Self copies 166 | uint32_t blockSize = size < bufferZeroSize ? size : bufferZeroSize; 167 | uint32_t offsetOrig = offset; 168 | 169 | iCore.CmdCopyBuffer(commandBuffer, bufferOne, offset, bufferZero, 0, blockSize); 170 | 171 | offset += blockSize; 172 | size -= blockSize; 173 | 174 | while (size >= blockSize) { 175 | if (useBarriersBetweenSelfCopies) { 176 | iCore.CmdBarrier(commandBuffer, 177 | &(NriBarrierGroupDesc){ 178 | .bufferNum = 1, 179 | .buffers = &(NriBufferBarrierDesc){ 180 | .buffer = bufferOne, 181 | .before = (NriAccessStage){ 182 | .access = NriAccessBits_COPY_DESTINATION | NriAccessBits_COPY_SOURCE, 183 | .stages = NriStageBits_COPY, 184 | }, 185 | .after = (NriAccessStage){ 186 | .access = NriAccessBits_COPY_DESTINATION | NriAccessBits_COPY_SOURCE, 187 | .stages = NriStageBits_COPY, 188 | }, 189 | }, 190 | }); 191 | } 192 | 193 | iCore.CmdCopyBuffer(commandBuffer, bufferOne, offset, bufferOne, offsetOrig, blockSize); 194 | 195 | offset += blockSize; 196 | size -= blockSize; 197 | 198 | blockSize <<= 1; 199 | } 200 | 201 | if (size) 202 | iCore.CmdCopyBuffer(commandBuffer, bufferOne, offset, bufferOne, offsetOrig, size); 203 | } else { 204 | // No self copies 205 | while (size) { 206 | uint32_t blockSize = size < bufferZeroSize ? size : bufferZeroSize; 207 | 208 | iCore.CmdCopyBuffer(commandBuffer, bufferOne, offset, bufferZero, 0, blockSize); 209 | 210 | offset += blockSize; 211 | size -= blockSize; 212 | } 213 | } 214 | 215 | // Copy to readback 216 | iCore.CmdBarrier(commandBuffer, 217 | &(NriBarrierGroupDesc){ 218 | .bufferNum = 1, 219 | .buffers = &(NriBufferBarrierDesc){ 220 | .buffer = bufferOne, 221 | .before = (NriAccessStage){ 222 | .access = NriAccessBits_COPY_DESTINATION, 223 | }, 224 | .after = (NriAccessStage){ 225 | .access = NriAccessBits_COPY_SOURCE, 226 | }, 227 | }, 228 | }); 229 | 230 | iCore.CmdCopyBuffer(commandBuffer, bufferReadback, 0, bufferOne, 0, NRI_WHOLE_SIZE); 231 | } 232 | iCore.EndCommandBuffer(commandBuffer); 233 | 234 | // Submit 235 | iCore.QueueSubmit(queue, 236 | &(NriQueueSubmitDesc){ 237 | .commandBufferNum = 1, 238 | .commandBuffers = &commandBuffer, 239 | }); 240 | 241 | // Wait for idle 242 | iHelper.WaitForIdle(queue); 243 | } 244 | 245 | { // Validate result 246 | const uint8_t* result = (uint8_t*)iCore.MapBuffer(bufferReadback, 0, NRI_WHOLE_SIZE); 247 | { 248 | uint32_t sum = 0; 249 | for (uint32_t i = 0; i < bufferOneSize; i++) 250 | sum += result[i]; 251 | 252 | printf("Result = %u (0 expected)\n", sum); 253 | } 254 | iCore.UnmapBuffer(bufferReadback); 255 | } 256 | 257 | { // Cleanup 258 | iCore.DestroyCommandBuffer(commandBuffer); 259 | iCore.DestroyCommandAllocator(commandAllocator); 260 | 261 | iCore.DestroyBuffer(bufferZero); 262 | iCore.DestroyBuffer(bufferOne); 263 | iCore.DestroyBuffer(bufferReadback); 264 | 265 | nriDestroyDevice(device); 266 | } 267 | 268 | return 0; 269 | } 270 | -------------------------------------------------------------------------------- /Source/Clear.cpp: -------------------------------------------------------------------------------- 1 | // © 2021 NVIDIA Corporation 2 | 3 | #include "NRIFramework.h" 4 | 5 | #include 6 | 7 | struct NRIInterface 8 | : public nri::CoreInterface, 9 | public nri::SwapChainInterface, 10 | public nri::HelperInterface {}; 11 | 12 | struct QueuedFrame { 13 | nri::CommandAllocator* commandAllocator; 14 | nri::CommandBuffer* commandBuffer; 15 | }; 16 | 17 | class Sample : public SampleBase { 18 | public: 19 | Sample() { 20 | } 21 | 22 | ~Sample(); 23 | 24 | bool Initialize(nri::GraphicsAPI graphicsAPI) override; 25 | void LatencySleep(uint32_t frameIndex) override; 26 | void RenderFrame(uint32_t frameIndex) override; 27 | 28 | private: 29 | NRIInterface NRI = {}; 30 | nri::Device* m_Device = nullptr; 31 | nri::SwapChain* m_SwapChain = nullptr; 32 | nri::Queue* m_GraphicsQueue = nullptr; 33 | nri::Fence* m_FrameFence = nullptr; 34 | 35 | std::vector m_QueuedFrames = {}; 36 | std::vector m_SwapChainTextures; 37 | }; 38 | 39 | Sample::~Sample() { 40 | NRI.WaitForIdle(*m_GraphicsQueue); 41 | 42 | for (QueuedFrame& queuedFrame : m_QueuedFrames) { 43 | NRI.DestroyCommandBuffer(*queuedFrame.commandBuffer); 44 | NRI.DestroyCommandAllocator(*queuedFrame.commandAllocator); 45 | } 46 | 47 | for (SwapChainTexture& swapChainTexture : m_SwapChainTextures) { 48 | NRI.DestroyFence(*swapChainTexture.acquireSemaphore); 49 | NRI.DestroyFence(*swapChainTexture.releaseSemaphore); 50 | NRI.DestroyDescriptor(*swapChainTexture.colorAttachment); 51 | } 52 | 53 | NRI.DestroyFence(*m_FrameFence); 54 | NRI.DestroySwapChain(*m_SwapChain); 55 | 56 | nri::nriDestroyDevice(*m_Device); 57 | } 58 | 59 | bool Sample::Initialize(nri::GraphicsAPI graphicsAPI) { 60 | // Adapters 61 | nri::AdapterDesc adapterDesc[2] = {}; 62 | uint32_t adapterDescsNum = helper::GetCountOf(adapterDesc); 63 | NRI_ABORT_ON_FAILURE(nri::nriEnumerateAdapters(adapterDesc, adapterDescsNum)); 64 | 65 | // Device 66 | nri::DeviceCreationDesc deviceCreationDesc = {}; 67 | deviceCreationDesc.graphicsAPI = graphicsAPI; 68 | deviceCreationDesc.enableGraphicsAPIValidation = m_DebugAPI; 69 | deviceCreationDesc.enableNRIValidation = m_DebugNRI; 70 | deviceCreationDesc.enableD3D11CommandBufferEmulation = D3D11_COMMANDBUFFER_EMULATION; 71 | deviceCreationDesc.vkBindingOffsets = VK_BINDING_OFFSETS; 72 | deviceCreationDesc.adapterDesc = &adapterDesc[std::min(m_AdapterIndex, adapterDescsNum - 1)]; 73 | deviceCreationDesc.allocationCallbacks = m_AllocationCallbacks; 74 | NRI_ABORT_ON_FAILURE(nri::nriCreateDevice(deviceCreationDesc, m_Device)); 75 | 76 | // NRI 77 | NRI_ABORT_ON_FAILURE(nri::nriGetInterface(*m_Device, NRI_INTERFACE(nri::CoreInterface), (nri::CoreInterface*)&NRI)); 78 | NRI_ABORT_ON_FAILURE(nri::nriGetInterface(*m_Device, NRI_INTERFACE(nri::SwapChainInterface), (nri::SwapChainInterface*)&NRI)); 79 | NRI_ABORT_ON_FAILURE(nri::nriGetInterface(*m_Device, NRI_INTERFACE(nri::HelperInterface), (nri::HelperInterface*)&NRI)); 80 | 81 | // Command queue 82 | NRI_ABORT_ON_FAILURE(NRI.GetQueue(*m_Device, nri::QueueType::GRAPHICS, 0, m_GraphicsQueue)); 83 | 84 | // Fences 85 | NRI_ABORT_ON_FAILURE(NRI.CreateFence(*m_Device, 0, m_FrameFence)); 86 | 87 | // Swap chain 88 | { 89 | nri::SwapChainDesc swapChainDesc = {}; 90 | swapChainDesc.window = GetWindow(); 91 | swapChainDesc.queue = m_GraphicsQueue; 92 | swapChainDesc.format = nri::SwapChainFormat::BT709_G22_8BIT; 93 | swapChainDesc.verticalSyncInterval = m_VsyncInterval; 94 | swapChainDesc.width = (uint16_t)GetWindowResolution().x; 95 | swapChainDesc.height = (uint16_t)GetWindowResolution().y; 96 | swapChainDesc.textureNum = GetOptimalSwapChainTextureNum(); 97 | swapChainDesc.queuedFrameNum = GetQueuedFrameNum(); 98 | NRI_ABORT_ON_FAILURE(NRI.CreateSwapChain(*m_Device, swapChainDesc, m_SwapChain)); 99 | 100 | uint32_t swapChainTextureNum; 101 | nri::Texture* const* swapChainTextures = NRI.GetSwapChainTextures(*m_SwapChain, swapChainTextureNum); 102 | 103 | nri::Format swapChainFormat = NRI.GetTextureDesc(*swapChainTextures[0]).format; 104 | 105 | for (uint32_t i = 0; i < swapChainTextureNum; i++) { 106 | nri::Texture2DViewDesc textureViewDesc = {swapChainTextures[i], nri::Texture2DViewType::COLOR_ATTACHMENT, swapChainFormat}; 107 | 108 | nri::Descriptor* colorAttachment = nullptr; 109 | NRI_ABORT_ON_FAILURE(NRI.CreateTexture2DView(textureViewDesc, colorAttachment)); 110 | 111 | nri::Fence* acquireSemaphore = nullptr; 112 | NRI_ABORT_ON_FAILURE(NRI.CreateFence(*m_Device, nri::SWAPCHAIN_SEMAPHORE, acquireSemaphore)); 113 | 114 | nri::Fence* releaseSemaphore = nullptr; 115 | NRI_ABORT_ON_FAILURE(NRI.CreateFence(*m_Device, nri::SWAPCHAIN_SEMAPHORE, releaseSemaphore)); 116 | 117 | SwapChainTexture& swapChainTexture = m_SwapChainTextures.emplace_back(); 118 | 119 | swapChainTexture = {}; 120 | swapChainTexture.acquireSemaphore = acquireSemaphore; 121 | swapChainTexture.releaseSemaphore = releaseSemaphore; 122 | swapChainTexture.texture = swapChainTextures[i]; 123 | swapChainTexture.colorAttachment = colorAttachment; 124 | swapChainTexture.attachmentFormat = swapChainFormat; 125 | } 126 | } 127 | 128 | // Queued frames 129 | m_QueuedFrames.resize(GetQueuedFrameNum()); 130 | for (QueuedFrame& queuedFrame : m_QueuedFrames) { 131 | NRI_ABORT_ON_FAILURE(NRI.CreateCommandAllocator(*m_GraphicsQueue, queuedFrame.commandAllocator)); 132 | NRI_ABORT_ON_FAILURE(NRI.CreateCommandBuffer(*queuedFrame.commandAllocator, queuedFrame.commandBuffer)); 133 | } 134 | 135 | return true; 136 | } 137 | 138 | void Sample::LatencySleep(uint32_t frameIndex) { 139 | uint32_t queuedFrameIndex = frameIndex % GetQueuedFrameNum(); 140 | const QueuedFrame& queuedFrame = m_QueuedFrames[queuedFrameIndex]; 141 | 142 | NRI.Wait(*m_FrameFence, frameIndex >= GetQueuedFrameNum() ? 1 + frameIndex - GetQueuedFrameNum() : 0); 143 | NRI.ResetCommandAllocator(*queuedFrame.commandAllocator); 144 | } 145 | 146 | void Sample::RenderFrame(uint32_t frameIndex) { 147 | uint32_t queuedFrameIndex = frameIndex % GetQueuedFrameNum(); 148 | const QueuedFrame& queuedFrame = m_QueuedFrames[queuedFrameIndex]; 149 | 150 | // Acquire a swap chain texture 151 | uint32_t recycledSemaphoreIndex = frameIndex % (uint32_t)m_SwapChainTextures.size(); 152 | nri::Fence* swapChainAcquireSemaphore = m_SwapChainTextures[recycledSemaphoreIndex].acquireSemaphore; 153 | 154 | uint32_t currentSwapChainTextureIndex = 0; 155 | NRI.AcquireNextTexture(*m_SwapChain, *swapChainAcquireSemaphore, currentSwapChainTextureIndex); 156 | 157 | const SwapChainTexture& swapChainTexture = m_SwapChainTextures[currentSwapChainTextureIndex]; 158 | 159 | // Record 160 | nri::CommandBuffer& commandBuffer = *queuedFrame.commandBuffer; 161 | NRI.BeginCommandBuffer(commandBuffer, nullptr); 162 | { 163 | nri::TextureBarrierDesc textureBarriers = {}; 164 | textureBarriers.texture = swapChainTexture.texture; 165 | textureBarriers.after = {nri::AccessBits::COLOR_ATTACHMENT, nri::Layout::COLOR_ATTACHMENT}; 166 | textureBarriers.layerNum = 1; 167 | textureBarriers.mipNum = 1; 168 | 169 | nri::BarrierGroupDesc barrierGroupDesc = {}; 170 | barrierGroupDesc.textureNum = 1; 171 | barrierGroupDesc.textures = &textureBarriers; 172 | NRI.CmdBarrier(commandBuffer, barrierGroupDesc); 173 | 174 | nri::AttachmentsDesc attachmentsDesc = {}; 175 | attachmentsDesc.colorNum = 1; 176 | attachmentsDesc.colors = &swapChainTexture.colorAttachment; 177 | 178 | NRI.CmdBeginRendering(commandBuffer, attachmentsDesc); 179 | { 180 | helper::Annotation annotation(NRI, commandBuffer, "Clear"); 181 | 182 | nri::ClearDesc clearDesc = {}; 183 | clearDesc.colorAttachmentIndex = 0; 184 | clearDesc.planes = nri::PlaneBits::COLOR; 185 | 186 | nri::Dim_t w = (nri::Dim_t)GetWindowResolution().x; 187 | nri::Dim_t h = (nri::Dim_t)GetWindowResolution().y; 188 | nri::Dim_t h3 = h / 3; 189 | int16_t y = (int16_t)h3; 190 | 191 | clearDesc.value.color.f = {1.0f, 0.0f, 0.0f, 1.0f}; 192 | nri::Rect rect1 = {0, 0, w, h3}; 193 | NRI.CmdClearAttachments(commandBuffer, &clearDesc, 1, &rect1, 1); 194 | 195 | clearDesc.value.color.f = {0.0f, 1.0f, 0.0f, 1.0f}; 196 | nri::Rect rect2 = {0, y, w, h3}; 197 | NRI.CmdClearAttachments(commandBuffer, &clearDesc, 1, &rect2, 1); 198 | 199 | clearDesc.value.color.f = {0.0f, 0.0f, 1.0f, 1.0f}; 200 | nri::Rect rect3 = {0, static_cast(y * 2), w, h3}; 201 | NRI.CmdClearAttachments(commandBuffer, &clearDesc, 1, &rect3, 1); 202 | } 203 | NRI.CmdEndRendering(commandBuffer); 204 | 205 | textureBarriers.before = textureBarriers.after; 206 | textureBarriers.after = {nri::AccessBits::UNKNOWN, nri::Layout::PRESENT}; 207 | 208 | NRI.CmdBarrier(commandBuffer, barrierGroupDesc); 209 | } 210 | NRI.EndCommandBuffer(commandBuffer); 211 | 212 | { // Submit 213 | nri::FenceSubmitDesc textureAcquiredFence = {}; 214 | textureAcquiredFence.fence = swapChainAcquireSemaphore; 215 | textureAcquiredFence.stages = nri::StageBits::COLOR_ATTACHMENT; 216 | 217 | nri::FenceSubmitDesc renderingFinishedFence = {}; 218 | renderingFinishedFence.fence = swapChainTexture.releaseSemaphore; 219 | 220 | nri::QueueSubmitDesc queueSubmitDesc = {}; 221 | queueSubmitDesc.waitFences = &textureAcquiredFence; 222 | queueSubmitDesc.waitFenceNum = 1; 223 | queueSubmitDesc.commandBuffers = &queuedFrame.commandBuffer; 224 | queueSubmitDesc.commandBufferNum = 1; 225 | queueSubmitDesc.signalFences = &renderingFinishedFence; 226 | queueSubmitDesc.signalFenceNum = 1; 227 | 228 | NRI.QueueSubmit(*m_GraphicsQueue, queueSubmitDesc); 229 | } 230 | 231 | // Present 232 | NRI.QueuePresent(*m_SwapChain, *swapChainTexture.releaseSemaphore); 233 | 234 | { // Signaling after "Present" improves D3D11 performance a bit 235 | nri::FenceSubmitDesc signalFence = {}; 236 | signalFence.fence = m_FrameFence; 237 | signalFence.value = 1 + frameIndex; 238 | 239 | nri::QueueSubmitDesc queueSubmitDesc = {}; 240 | queueSubmitDesc.signalFences = &signalFence; 241 | queueSubmitDesc.signalFenceNum = 1; 242 | 243 | NRI.QueueSubmit(*m_GraphicsQueue, queueSubmitDesc); 244 | } 245 | } 246 | 247 | SAMPLE_MAIN(Sample, 0); 248 | -------------------------------------------------------------------------------- /Source/DeviceInfo.c: -------------------------------------------------------------------------------- 1 | // © 2021 NVIDIA Corporation 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #if _WIN32 9 | # include 10 | # define alloca _alloca 11 | #else 12 | # include 13 | #endif 14 | 15 | #include "NRI.h" 16 | 17 | #include "Extensions/NRIDeviceCreation.h" 18 | #include "Extensions/NRIHelper.h" 19 | 20 | static const char* vendors[] = { 21 | "unknown", 22 | "NVIDIA", 23 | "AMD", 24 | "INTEL", 25 | }; 26 | 27 | static const char* architectures[] = { 28 | "unknown", 29 | "INTEGRATED", 30 | "DESCRETE", 31 | }; 32 | 33 | #define NRI_ABORT_ON_FAILURE(result) \ 34 | if (result != NriResult_SUCCESS) \ 35 | exit(1); 36 | 37 | void SilencePlease(NriMessage messageType, const char* file, uint32_t line, const char* message, void* userArg) { 38 | (void)messageType, file, line, message, userArg; 39 | } 40 | 41 | int main(int argc, char** argv) { 42 | // Settings 43 | NriGraphicsAPI graphicsAPI = NriGraphicsAPI_D3D11; 44 | for (int i = 0; i < argc; i++) { 45 | if (!strcmp(argv[i], "--api=D3D12")) 46 | graphicsAPI = NriGraphicsAPI_D3D12; 47 | else if (!strcmp(argv[i], "--api=VULKAN")) 48 | graphicsAPI = NriGraphicsAPI_VK; 49 | } 50 | 51 | // Query adapters number 52 | uint32_t adaptersNum = 0; 53 | NRI_ABORT_ON_FAILURE(nriEnumerateAdapters( 54 | NULL, &adaptersNum)); 55 | 56 | // Query adapters 57 | size_t bytes = adaptersNum * sizeof(NriAdapterDesc); 58 | NriAdapterDesc* adapterDescs = (NriAdapterDesc*)alloca(bytes); 59 | NRI_ABORT_ON_FAILURE(nriEnumerateAdapters( 60 | adapterDescs, &adaptersNum)); 61 | 62 | // Print adapters info 63 | printf("nriEnumerateAdapters: %u adapters reported\n", adaptersNum); 64 | 65 | for (uint32_t i = 0; i < adaptersNum; i++) { 66 | const NriAdapterDesc* adapterDesc = adapterDescs + i; 67 | 68 | printf("\nAdapter #%u\n", i + 1); 69 | printf("\tName : %s\n", adapterDesc->name); 70 | printf("\tVendor : %s\n", vendors[adapterDesc->vendor]); 71 | printf("\tArchitecture : %s\n", architectures[adapterDesc->architecture]); 72 | printf("\tVideo memory : %" PRIu64 " Mb\n", adapterDesc->videoMemorySize >> 20); 73 | printf("\tShared system memory : %" PRIu64 " Mb\n", adapterDesc->sharedSystemMemorySize >> 20); 74 | printf("\tQueues : {%u, %u, %u}\n", adapterDesc->queueNum[0], adapterDesc->queueNum[1], adapterDesc->queueNum[2]); 75 | printf("\tID : 0x%08X\n", adapterDesc->deviceId); 76 | printf("\tLUID : 0x%016" PRIX64 "\n", adapterDesc->luid); 77 | 78 | // Print formats info 79 | NriDevice* device = NULL; 80 | NRI_ABORT_ON_FAILURE(nriCreateDevice( 81 | &(NriDeviceCreationDesc){ 82 | .graphicsAPI = graphicsAPI, 83 | .adapterDesc = adapterDesc, 84 | .callbackInterface.MessageCallback = SilencePlease, 85 | }, 86 | &device)); 87 | 88 | NriCoreInterface iCore = {0}; 89 | NRI_ABORT_ON_FAILURE(nriGetInterface( 90 | device, NRI_INTERFACE(NriCoreInterface), &iCore)); 91 | 92 | printf("\n"); 93 | printf("%54.54s\n", "STORAGE_LOAD_WITHOUT_FORMAT"); 94 | printf("%54.54s\n", "VERTEX_BUFFER |"); 95 | printf("%54.54s\n", "STORAGE_BUFFER_ATOMICS | |"); 96 | printf("%54.54s\n", "STORAGE_BUFFER | | |"); 97 | printf("%54.54s\n", "BUFFER | | | |"); 98 | printf("%54.54s\n", "MULTISAMPLE_8X | | | | |"); 99 | printf("%54.54s\n", "MULTISAMPLE_4X | | | | | |"); 100 | printf("%54.54s\n", "MULTISAMPLE_2X | | | | | | |"); 101 | printf("%54.54s\n", "BLEND | | | | | | | |"); 102 | printf("%54.54s\n", "DEPTH_STENCIL_ATTACHMENT | | | | | | | | |"); 103 | printf("%54.54s\n", "COLOR_ATTACHMENT | | | | | | | | | |"); 104 | printf("%54.54s\n", "STORAGE_TEXTURE_ATOMICS | | | | | | | | | | |"); 105 | printf("%54.54s\n", "STORAGE_TEXTURE | | | | | | | | | | | |"); 106 | printf("%54.54s\n", "TEXTURE | | | | | | | | | | | | |"); 107 | printf("%54.54s\n", "| | | | | | | | | | | | | |"); 108 | 109 | for (uint32_t f = 0; f < NriFormat_MAX_NUM; f++) { 110 | const NriFormatProps* formatProps = nriGetFormatProps((NriFormat)f); 111 | NriFormatSupportBits formatSupportBits = iCore.GetFormatSupport(device, (NriFormat)f); 112 | 113 | printf("%24.24s : ", formatProps->name); 114 | 115 | for (uint32_t bit = 0; bit < 14; bit++) { 116 | if (formatSupportBits & (1 << bit)) 117 | printf("+ "); 118 | else 119 | printf(". "); 120 | } 121 | 122 | printf("\n"); 123 | } 124 | 125 | nriDestroyDevice(device); 126 | } 127 | 128 | return 0; 129 | } 130 | -------------------------------------------------------------------------------- /Source/LowLatency.cpp: -------------------------------------------------------------------------------- 1 | // © 2024 NVIDIA Corporation 2 | 3 | #include "NRIFramework.h" 4 | 5 | #include 6 | 7 | // Tweakables, which must be set only once 8 | #define ALLOW_LOW_LATENCY true 9 | #define WAITABLE_SWAP_CHAIN false 10 | #define WAITABLE_SWAP_CHAIN_MAX_FRAME_LATENCY 1 // 2 helps to avoid "TOTAL = GPU + CPU" time issue 11 | #define EMULATE_BAD_PRACTICE false 12 | #define VSYNC_INTERVAL 0 13 | #define QUEUED_FRAMES_MAX_NUM 3 14 | #define CTA_NUM 38000 // TODO: tuned to reach ~1ms on RTX 4080 15 | #define COLOR_LATENCY_SLEEP NriBgra(255, 0, 0) 16 | #define COLOR_SIMULATION NriBgra(0, 255, 0) 17 | #define COLOR_RENDER NriBgra(0, 0, 255) 18 | 19 | struct NRIInterface 20 | : public nri::CoreInterface, 21 | public nri::HelperInterface, 22 | public nri::StreamerInterface, 23 | public nri::SwapChainInterface, 24 | public nri::LowLatencyInterface {}; 25 | 26 | struct QueuedFrame { 27 | nri::CommandAllocator* commandAllocator; 28 | nri::CommandBuffer* commandBuffer; 29 | }; 30 | 31 | class Sample : public SampleBase { 32 | public: 33 | Sample() { 34 | m_QueuedFrames.resize(QUEUED_FRAMES_MAX_NUM); 35 | } 36 | 37 | ~Sample(); 38 | 39 | bool Initialize(nri::GraphicsAPI graphicsAPI) override; 40 | void LatencySleep(uint32_t) override; 41 | void PrepareFrame(uint32_t) override; 42 | void RenderFrame(uint32_t frameIndex) override; 43 | 44 | private: 45 | NRIInterface NRI = {}; 46 | nri::Device* m_Device = nullptr; 47 | nri::Streamer* m_Streamer = nullptr; 48 | nri::SwapChain* m_SwapChain = nullptr; 49 | nri::Queue* m_GraphicsQueue = nullptr; 50 | nri::PipelineLayout* m_PipelineLayout = nullptr; 51 | nri::Pipeline* m_Pipeline = nullptr; 52 | nri::Fence* m_FrameFence = nullptr; 53 | nri::DescriptorPool* m_DescriptorPool = nullptr; 54 | nri::DescriptorSet* m_DescriptorSet = nullptr; 55 | nri::Buffer* m_Buffer = nullptr; 56 | nri::Memory* m_Memory = nullptr; 57 | nri::Descriptor* m_BufferStorage = nullptr; 58 | 59 | std::vector m_QueuedFrames = {}; 60 | std::vector m_SwapChainTextures; 61 | float m_CpuWorkload = 4.0f; // ms 62 | uint32_t m_GpuWorkload = 10; // in pigeons, current settings give ~10 ms on RTX 4080 63 | uint32_t m_QueuedFrameNum = QUEUED_FRAMES_MAX_NUM; // [1; QUEUED_FRAMES_MAX_NUM] 64 | bool m_AllowLowLatency = false; 65 | bool m_EnableLowLatency = false; 66 | }; 67 | 68 | Sample::~Sample() { 69 | NRI.WaitForIdle(*m_GraphicsQueue); 70 | 71 | for (QueuedFrame& queuedFrame : m_QueuedFrames) { 72 | NRI.DestroyCommandBuffer(*queuedFrame.commandBuffer); 73 | NRI.DestroyCommandAllocator(*queuedFrame.commandAllocator); 74 | } 75 | 76 | for (SwapChainTexture& swapChainTexture : m_SwapChainTextures) { 77 | NRI.DestroyFence(*swapChainTexture.acquireSemaphore); 78 | NRI.DestroyFence(*swapChainTexture.releaseSemaphore); 79 | NRI.DestroyDescriptor(*swapChainTexture.colorAttachment); 80 | } 81 | 82 | NRI.DestroyDescriptorPool(*m_DescriptorPool); 83 | NRI.DestroyDescriptor(*m_BufferStorage); 84 | NRI.DestroyBuffer(*m_Buffer); 85 | NRI.DestroyPipeline(*m_Pipeline); 86 | NRI.DestroyPipelineLayout(*m_PipelineLayout); 87 | NRI.DestroyFence(*m_FrameFence); 88 | NRI.DestroySwapChain(*m_SwapChain); 89 | NRI.DestroyStreamer(*m_Streamer); 90 | 91 | NRI.FreeMemory(*m_Memory); 92 | 93 | DestroyImgui(); 94 | 95 | nri::nriDestroyDevice(*m_Device); 96 | } 97 | 98 | bool Sample::Initialize(nri::GraphicsAPI graphicsAPI) { 99 | // Adapters 100 | nri::AdapterDesc adapterDesc[2] = {}; 101 | uint32_t adapterDescsNum = helper::GetCountOf(adapterDesc); 102 | NRI_ABORT_ON_FAILURE(nri::nriEnumerateAdapters(adapterDesc, adapterDescsNum)); 103 | 104 | // Device 105 | nri::DeviceCreationDesc deviceCreationDesc = {}; 106 | deviceCreationDesc.graphicsAPI = graphicsAPI; 107 | deviceCreationDesc.enableGraphicsAPIValidation = m_DebugAPI; 108 | deviceCreationDesc.enableNRIValidation = m_DebugNRI; 109 | deviceCreationDesc.enableD3D11CommandBufferEmulation = D3D11_COMMANDBUFFER_EMULATION; 110 | deviceCreationDesc.vkBindingOffsets = VK_BINDING_OFFSETS; 111 | deviceCreationDesc.adapterDesc = &adapterDesc[std::min(m_AdapterIndex, adapterDescsNum - 1)]; 112 | deviceCreationDesc.allocationCallbacks = m_AllocationCallbacks; 113 | NRI_ABORT_ON_FAILURE(nri::nriCreateDevice(deviceCreationDesc, m_Device)); 114 | 115 | // NRI 116 | NRI_ABORT_ON_FAILURE(nri::nriGetInterface(*m_Device, NRI_INTERFACE(nri::CoreInterface), (nri::CoreInterface*)&NRI)); 117 | NRI_ABORT_ON_FAILURE(nri::nriGetInterface(*m_Device, NRI_INTERFACE(nri::HelperInterface), (nri::HelperInterface*)&NRI)); 118 | NRI_ABORT_ON_FAILURE(nri::nriGetInterface(*m_Device, NRI_INTERFACE(nri::StreamerInterface), (nri::StreamerInterface*)&NRI)); 119 | NRI_ABORT_ON_FAILURE(nri::nriGetInterface(*m_Device, NRI_INTERFACE(nri::SwapChainInterface), (nri::SwapChainInterface*)&NRI)); 120 | 121 | const nri::DeviceDesc& deviceDesc = NRI.GetDeviceDesc(*m_Device); 122 | 123 | // Create streamer 124 | nri::StreamerDesc streamerDesc = {}; 125 | streamerDesc.dynamicBufferMemoryLocation = nri::MemoryLocation::HOST_UPLOAD; 126 | streamerDesc.dynamicBufferUsageBits = nri::BufferUsageBits::VERTEX_BUFFER | nri::BufferUsageBits::INDEX_BUFFER; 127 | streamerDesc.constantBufferMemoryLocation = nri::MemoryLocation::HOST_UPLOAD; 128 | streamerDesc.queuedFrameNum = QUEUED_FRAMES_MAX_NUM; 129 | NRI_ABORT_ON_FAILURE(NRI.CreateStreamer(*m_Device, streamerDesc, m_Streamer)); 130 | 131 | // Low latency 132 | m_AllowLowLatency = ALLOW_LOW_LATENCY && deviceDesc.features.lowLatency; 133 | 134 | if (m_AllowLowLatency) 135 | NRI_ABORT_ON_FAILURE(nri::nriGetInterface(*m_Device, NRI_INTERFACE(nri::LowLatencyInterface), (nri::LowLatencyInterface*)&NRI)); 136 | 137 | // Command queue 138 | NRI_ABORT_ON_FAILURE(NRI.GetQueue(*m_Device, nri::QueueType::GRAPHICS, 0, m_GraphicsQueue)); 139 | 140 | // Fence 141 | NRI_ABORT_ON_FAILURE(NRI.CreateFence(*m_Device, 0, m_FrameFence)); 142 | 143 | { // Swap chain 144 | nri::SwapChainDesc swapChainDesc = {}; 145 | swapChainDesc.window = GetWindow(); 146 | swapChainDesc.queue = m_GraphicsQueue; 147 | swapChainDesc.format = nri::SwapChainFormat::BT709_G22_8BIT; 148 | swapChainDesc.verticalSyncInterval = m_VsyncInterval; 149 | swapChainDesc.width = (uint16_t)GetWindowResolution().x; 150 | swapChainDesc.height = (uint16_t)GetWindowResolution().y; 151 | swapChainDesc.textureNum = QUEUED_FRAMES_MAX_NUM + 1; 152 | swapChainDesc.verticalSyncInterval = VSYNC_INTERVAL; 153 | swapChainDesc.queuedFrameNum = WAITABLE_SWAP_CHAIN ? WAITABLE_SWAP_CHAIN_MAX_FRAME_LATENCY : QUEUED_FRAMES_MAX_NUM; 154 | swapChainDesc.waitable = WAITABLE_SWAP_CHAIN; 155 | swapChainDesc.allowLowLatency = m_AllowLowLatency; 156 | NRI_ABORT_ON_FAILURE(NRI.CreateSwapChain(*m_Device, swapChainDesc, m_SwapChain)); 157 | 158 | uint32_t swapChainTextureNum; 159 | nri::Texture* const* swapChainTextures = NRI.GetSwapChainTextures(*m_SwapChain, swapChainTextureNum); 160 | 161 | nri::Format swapChainFormat = NRI.GetTextureDesc(*swapChainTextures[0]).format; 162 | 163 | for (uint32_t i = 0; i < swapChainTextureNum; i++) { 164 | nri::Texture2DViewDesc textureViewDesc = {swapChainTextures[i], nri::Texture2DViewType::COLOR_ATTACHMENT, swapChainFormat}; 165 | 166 | nri::Descriptor* colorAttachment = nullptr; 167 | NRI_ABORT_ON_FAILURE(NRI.CreateTexture2DView(textureViewDesc, colorAttachment)); 168 | 169 | nri::Fence* acquireSemaphore = nullptr; 170 | NRI_ABORT_ON_FAILURE(NRI.CreateFence(*m_Device, nri::SWAPCHAIN_SEMAPHORE, acquireSemaphore)); 171 | 172 | nri::Fence* releaseSemaphore = nullptr; 173 | NRI_ABORT_ON_FAILURE(NRI.CreateFence(*m_Device, nri::SWAPCHAIN_SEMAPHORE, releaseSemaphore)); 174 | 175 | SwapChainTexture& swapChainTexture = m_SwapChainTextures.emplace_back(); 176 | 177 | swapChainTexture = {}; 178 | swapChainTexture.acquireSemaphore = acquireSemaphore; 179 | swapChainTexture.releaseSemaphore = releaseSemaphore; 180 | swapChainTexture.texture = swapChainTextures[i]; 181 | swapChainTexture.colorAttachment = colorAttachment; 182 | swapChainTexture.attachmentFormat = swapChainFormat; 183 | } 184 | } 185 | 186 | { // Buffer 187 | nri::BufferDesc bufferDesc = {}; 188 | bufferDesc.size = CTA_NUM * 256 * sizeof(float); 189 | bufferDesc.usage = nri::BufferUsageBits::SHADER_RESOURCE_STORAGE; 190 | 191 | NRI_ABORT_ON_FAILURE(NRI.CreateBuffer(*m_Device, bufferDesc, m_Buffer)); 192 | 193 | nri::ResourceGroupDesc resourceGroupDesc = {}; 194 | resourceGroupDesc.memoryLocation = nri::MemoryLocation::DEVICE; 195 | resourceGroupDesc.bufferNum = 1; 196 | resourceGroupDesc.buffers = &m_Buffer; 197 | 198 | NRI_ABORT_ON_FAILURE(NRI.AllocateAndBindMemory(*m_Device, resourceGroupDesc, &m_Memory)); 199 | 200 | nri::BufferViewDesc bufferViewDesc = {}; 201 | bufferViewDesc.buffer = m_Buffer; 202 | bufferViewDesc.format = nri::Format::R16_SFLOAT; 203 | bufferViewDesc.viewType = nri::BufferViewType::SHADER_RESOURCE_STORAGE; 204 | 205 | NRI_ABORT_ON_FAILURE(NRI.CreateBufferView(bufferViewDesc, m_BufferStorage)); 206 | } 207 | 208 | { // Compute pipeline 209 | utils::ShaderCodeStorage shaderCodeStorage; 210 | 211 | nri::DescriptorRangeDesc descriptorRangeStorage = {0, 1, nri::DescriptorType::STORAGE_BUFFER, nri::StageBits::COMPUTE_SHADER}; 212 | nri::DescriptorSetDesc descriptorSetDesc = {0, &descriptorRangeStorage, 1}; 213 | 214 | nri::PipelineLayoutDesc pipelineLayoutDesc = {}; 215 | pipelineLayoutDesc.descriptorSetNum = 1; 216 | pipelineLayoutDesc.descriptorSets = &descriptorSetDesc; 217 | pipelineLayoutDesc.shaderStages = nri::StageBits::COMPUTE_SHADER; 218 | NRI_ABORT_ON_FAILURE(NRI.CreatePipelineLayout(*m_Device, pipelineLayoutDesc, m_PipelineLayout)); 219 | 220 | nri::ComputePipelineDesc computePipelineDesc = {}; 221 | computePipelineDesc.pipelineLayout = m_PipelineLayout; 222 | computePipelineDesc.shader = utils::LoadShader(deviceDesc.graphicsAPI, "Compute.cs", shaderCodeStorage); 223 | NRI_ABORT_ON_FAILURE(NRI.CreateComputePipeline(*m_Device, computePipelineDesc, m_Pipeline)); 224 | } 225 | 226 | { // Descriptor pool 227 | nri::DescriptorPoolDesc descriptorPoolDesc = {}; 228 | descriptorPoolDesc.descriptorSetMaxNum = 1; 229 | descriptorPoolDesc.storageBufferMaxNum = 1; 230 | 231 | NRI_ABORT_ON_FAILURE(NRI.CreateDescriptorPool(*m_Device, descriptorPoolDesc, m_DescriptorPool)); 232 | NRI_ABORT_ON_FAILURE(NRI.AllocateDescriptorSets(*m_DescriptorPool, *m_PipelineLayout, 0, &m_DescriptorSet, 1, 0)); 233 | 234 | nri::DescriptorRangeUpdateDesc descriptorRangeUpdateDesc = {&m_BufferStorage, 1, 0}; 235 | NRI.UpdateDescriptorRanges(*m_DescriptorSet, 0, 1, &descriptorRangeUpdateDesc); 236 | } 237 | 238 | // Queued frames 239 | for (QueuedFrame& queuedFrame : m_QueuedFrames) { 240 | NRI_ABORT_ON_FAILURE(NRI.CreateCommandAllocator(*m_GraphicsQueue, queuedFrame.commandAllocator)); 241 | NRI_ABORT_ON_FAILURE(NRI.CreateCommandBuffer(*queuedFrame.commandAllocator, queuedFrame.commandBuffer)); 242 | } 243 | 244 | return InitImgui(*m_Device); 245 | } 246 | 247 | void Sample::LatencySleep(uint32_t frameIndex) { 248 | nri::nriBeginAnnotation("LatencySleep", COLOR_LATENCY_SLEEP); 249 | 250 | // Marker 251 | if (m_AllowLowLatency) 252 | NRI.SetLatencyMarker(*m_SwapChain, nri::LatencyMarker::SIMULATION_START); 253 | 254 | // Wait for present 255 | if constexpr (WAITABLE_SWAP_CHAIN) 256 | NRI.WaitForPresent(*m_SwapChain); 257 | 258 | // Preserve frame queue (optimal place for "non-waitable" swap chain) 259 | if constexpr (WAITABLE_SWAP_CHAIN == EMULATE_BAD_PRACTICE) { 260 | const QueuedFrame& queuedFrame = m_QueuedFrames[frameIndex % m_QueuedFrameNum]; 261 | 262 | NRI.Wait(*m_FrameFence, frameIndex >= m_QueuedFrameNum ? 1 + frameIndex - m_QueuedFrameNum : 0); 263 | NRI.ResetCommandAllocator(*queuedFrame.commandAllocator); 264 | } 265 | 266 | // Sleep just before sampling input 267 | if (m_AllowLowLatency) { 268 | NRI.LatencySleep(*m_SwapChain); 269 | NRI.SetLatencyMarker(*m_SwapChain, nri::LatencyMarker::INPUT_SAMPLE); 270 | } 271 | 272 | nri::nriEndAnnotation(); 273 | } 274 | 275 | void Sample::PrepareFrame(uint32_t) { 276 | nri::nriBeginAnnotation("Simulation", COLOR_SIMULATION); 277 | 278 | // Emulate CPU workload 279 | double begin = m_Timer.GetTimeStamp() + m_CpuWorkload; 280 | while (m_Timer.GetTimeStamp() < begin) 281 | ; 282 | 283 | bool enableLowLatencyPrev = m_EnableLowLatency; 284 | uint32_t queuedFrameNumPrev = m_QueuedFrameNum; 285 | 286 | ImGui::NewFrame(); 287 | { 288 | // Lagometer 289 | ImVec2 p = ImGui::GetIO().MousePos; 290 | ImGui::GetForegroundDrawList()->AddRectFilled(p, ImVec2(p.x + 20, p.y + 20), IM_COL32(128, 10, 10, 255)); 291 | 292 | // Stats 293 | nri::LatencyReport latencyReport = {}; 294 | if (m_AllowLowLatency) 295 | NRI.GetLatencyReport(*m_SwapChain, latencyReport); 296 | 297 | ImGui::SetNextWindowPos(ImVec2(30, 30), ImGuiCond_Once); 298 | ImGui::SetNextWindowSize(ImVec2(0, 0)); 299 | ImGui::Begin("Low latency"); 300 | { 301 | ImGui::Text("X (end) - Input = .... ms"); 302 | ImGui::Separator(); 303 | ImGui::Text(" Input : %+6.2f", 0.0); 304 | ImGui::Text(" Simulation : %+6.2f", (int64_t)(latencyReport.simulationEndTimeUs - latencyReport.inputSampleTimeUs) / 1000.0); 305 | ImGui::Text(" Render : %+6.2f", (int64_t)(latencyReport.renderSubmitEndTimeUs - latencyReport.inputSampleTimeUs) / 1000.0); 306 | ImGui::Text(" Present : %+6.2f", (int64_t)(latencyReport.presentEndTimeUs - latencyReport.inputSampleTimeUs) / 1000.0); 307 | ImGui::Text(" Driver : %+6.2f", (int64_t)(latencyReport.driverEndTimeUs - latencyReport.inputSampleTimeUs) / 1000.0); 308 | ImGui::Text(" OS render queue : %+6.2f", (int64_t)(latencyReport.osRenderQueueEndTimeUs - latencyReport.inputSampleTimeUs) / 1000.0); 309 | ImGui::Text(" GPU render : %+6.2f", (int64_t)(latencyReport.gpuRenderEndTimeUs - latencyReport.inputSampleTimeUs) / 1000.0); 310 | ImGui::Separator(); 311 | ImGui::Text("Frame time : %6.2f ms", m_Timer.GetSmoothedFrameTime()); 312 | ImGui::Separator(); 313 | 314 | ImGui::Text("CPU workload (ms):"); 315 | ImGui::SetNextItemWidth(210.0f); 316 | ImGui::SliderFloat("##CPU", &m_CpuWorkload, 0.0f, 1000.0f / 30.0f, "%.1f", ImGuiSliderFlags_NoInput); 317 | ImGui::Text("GPU workload (pigeons):"); 318 | ImGui::SetNextItemWidth(210.0f); 319 | ImGui::SliderInt("##GPU", (int32_t*)&m_GpuWorkload, 1, 20, "%d", ImGuiSliderFlags_NoInput); 320 | ImGui::Text("Queued frames:"); 321 | ImGui::SetNextItemWidth(210.0f); 322 | ImGui::SliderInt("##Frames", (int32_t*)&m_QueuedFrameNum, 1, QUEUED_FRAMES_MAX_NUM, "%d", ImGuiSliderFlags_NoInput); 323 | 324 | if (!m_AllowLowLatency) 325 | ImGui::BeginDisabled(); 326 | ImGui::Checkbox("Low latency (F1)", &m_EnableLowLatency); 327 | if (m_AllowLowLatency && IsKeyToggled(Key::F1)) 328 | m_EnableLowLatency = !m_EnableLowLatency; 329 | if (!m_AllowLowLatency) 330 | ImGui::EndDisabled(); 331 | 332 | ImGui::BeginDisabled(); 333 | bool waitable = WAITABLE_SWAP_CHAIN; 334 | ImGui::Checkbox("Waitable swapchain (" STRINGIFY(WAITABLE_SWAP_CHAIN_MAX_FRAME_LATENCY) ")", &waitable); 335 | bool badPractice = EMULATE_BAD_PRACTICE; 336 | ImGui::Checkbox("Bad practice", &badPractice); 337 | ImGui::EndDisabled(); 338 | } 339 | ImGui::End(); 340 | } 341 | ImGui::EndFrame(); 342 | ImGui::Render(); 343 | 344 | if (enableLowLatencyPrev != m_EnableLowLatency) { 345 | nri::LatencySleepMode sleepMode = {}; 346 | sleepMode.lowLatencyMode = m_EnableLowLatency; 347 | sleepMode.lowLatencyBoost = m_EnableLowLatency; 348 | 349 | NRI.SetLatencySleepMode(*m_SwapChain, sleepMode); 350 | } 351 | 352 | if (queuedFrameNumPrev != m_QueuedFrameNum) 353 | NRI.WaitForIdle(*m_GraphicsQueue); 354 | 355 | // Marker 356 | if (m_AllowLowLatency) 357 | NRI.SetLatencyMarker(*m_SwapChain, nri::LatencyMarker::SIMULATION_END); 358 | 359 | nri::nriEndAnnotation(); 360 | } 361 | 362 | void Sample::RenderFrame(uint32_t frameIndex) { 363 | nri::nriBeginAnnotation("Render", COLOR_RENDER); 364 | 365 | const QueuedFrame& queuedFrame = m_QueuedFrames[frameIndex % m_QueuedFrameNum]; 366 | 367 | // Preserve frame queue (optimal place for "waitable" swapchain) 368 | if constexpr (WAITABLE_SWAP_CHAIN != EMULATE_BAD_PRACTICE) { 369 | NRI.Wait(*m_FrameFence, frameIndex >= m_QueuedFrameNum ? 1 + frameIndex - m_QueuedFrameNum : 0); 370 | NRI.ResetCommandAllocator(*queuedFrame.commandAllocator); 371 | } 372 | 373 | // Acquire a swap chain texture 374 | uint32_t recycledSemaphoreIndex = frameIndex % (uint32_t)m_SwapChainTextures.size(); 375 | nri::Fence* swapChainAcquireSemaphore = m_SwapChainTextures[recycledSemaphoreIndex].acquireSemaphore; 376 | 377 | uint32_t currentSwapChainTextureIndex = 0; 378 | NRI.AcquireNextTexture(*m_SwapChain, *swapChainAcquireSemaphore, currentSwapChainTextureIndex); 379 | 380 | const SwapChainTexture& swapChainTexture = m_SwapChainTextures[currentSwapChainTextureIndex]; 381 | 382 | // Record 383 | nri::CommandBuffer& commandBuffer = *queuedFrame.commandBuffer; 384 | NRI.BeginCommandBuffer(commandBuffer, m_DescriptorPool); 385 | { 386 | NRI.CmdBeginAnnotation(commandBuffer, "Render", COLOR_RENDER); 387 | 388 | nri::TextureBarrierDesc swapchainBarrier = {}; 389 | swapchainBarrier.texture = swapChainTexture.texture; 390 | swapchainBarrier.after = {nri::AccessBits::COLOR_ATTACHMENT, nri::Layout::COLOR_ATTACHMENT}; 391 | swapchainBarrier.layerNum = 1; 392 | swapchainBarrier.mipNum = 1; 393 | 394 | { // Barrier 395 | nri::BarrierGroupDesc barriers = {}; 396 | barriers.textureNum = 1; 397 | barriers.textures = &swapchainBarrier; 398 | 399 | NRI.CmdBarrier(commandBuffer, barriers); 400 | } 401 | 402 | // Compute workload (main, resolution independent) 403 | NRI.CmdSetPipelineLayout(commandBuffer, *m_PipelineLayout); 404 | NRI.CmdSetPipeline(commandBuffer, *m_Pipeline); 405 | NRI.CmdSetDescriptorSet(commandBuffer, 0, *m_DescriptorSet, nullptr); 406 | 407 | for (uint32_t i = 0; i < m_GpuWorkload; i++) { 408 | NRI.CmdDispatch(commandBuffer, {CTA_NUM, 1, 1}); 409 | 410 | { // Barrier 411 | nri::GlobalBarrierDesc storageBarrier = {}; 412 | storageBarrier.before = {nri::AccessBits::SHADER_RESOURCE_STORAGE, nri::StageBits::COMPUTE_SHADER}; 413 | storageBarrier.after = {nri::AccessBits::SHADER_RESOURCE_STORAGE, nri::StageBits::COMPUTE_SHADER}; 414 | 415 | nri::BarrierGroupDesc barriers = {}; 416 | barriers.globalNum = 1; 417 | barriers.globals = &storageBarrier; 418 | 419 | NRI.CmdBarrier(commandBuffer, barriers); 420 | } 421 | } 422 | 423 | // Clear and UI 424 | nri::AttachmentsDesc attachmentsDesc = {}; 425 | attachmentsDesc.colorNum = 1; 426 | attachmentsDesc.colors = &swapChainTexture.colorAttachment; 427 | 428 | NRI.CmdBeginRendering(commandBuffer, attachmentsDesc); 429 | { 430 | nri::ClearDesc clearDesc = {}; 431 | clearDesc.colorAttachmentIndex = 0; 432 | clearDesc.planes = nri::PlaneBits::COLOR; 433 | clearDesc.value.color.f = {0.0f, 0.1f, 0.0f, 1.0f}; 434 | 435 | NRI.CmdClearAttachments(commandBuffer, &clearDesc, 1, nullptr, 0); 436 | 437 | RenderImgui(commandBuffer, *m_Streamer, swapChainTexture.attachmentFormat, 1.0f, true); 438 | } 439 | NRI.CmdEndRendering(commandBuffer); 440 | 441 | { // Barrier 442 | swapchainBarrier.before = swapchainBarrier.after; 443 | swapchainBarrier.after = {nri::AccessBits::UNKNOWN, nri::Layout::PRESENT}; 444 | 445 | nri::BarrierGroupDesc barriers = {}; 446 | barriers.textureNum = 1; 447 | barriers.textures = &swapchainBarrier; 448 | 449 | NRI.CmdBarrier(commandBuffer, barriers); 450 | } 451 | 452 | NRI.CmdEndAnnotation(commandBuffer); 453 | } 454 | NRI.EndCommandBuffer(commandBuffer); 455 | 456 | { // Submit 457 | nri::FenceSubmitDesc frameFence = {}; 458 | frameFence.fence = m_FrameFence; 459 | frameFence.value = 1 + frameIndex; 460 | 461 | nri::FenceSubmitDesc textureAcquiredFence = {}; 462 | textureAcquiredFence.fence = swapChainAcquireSemaphore; 463 | textureAcquiredFence.stages = nri::StageBits::COLOR_ATTACHMENT; 464 | 465 | nri::FenceSubmitDesc renderingFinishedFence = {}; 466 | renderingFinishedFence.fence = swapChainTexture.releaseSemaphore; 467 | 468 | nri::FenceSubmitDesc signalFences[] = {renderingFinishedFence, frameFence}; 469 | 470 | nri::QueueSubmitDesc queueSubmitDesc = {}; 471 | queueSubmitDesc.waitFences = &textureAcquiredFence; 472 | queueSubmitDesc.waitFenceNum = 1; 473 | queueSubmitDesc.commandBuffers = &queuedFrame.commandBuffer; 474 | queueSubmitDesc.commandBufferNum = 1; 475 | queueSubmitDesc.signalFences = signalFences; 476 | queueSubmitDesc.signalFenceNum = helper::GetCountOf(signalFences); 477 | 478 | NRI.QueueAnnotation(*m_GraphicsQueue, "Submit", COLOR_RENDER); 479 | 480 | if (m_AllowLowLatency) { 481 | NRI.SetLatencyMarker(*m_SwapChain, nri::LatencyMarker::RENDER_SUBMIT_START); 482 | NRI.QueueSubmitTrackable(*m_GraphicsQueue, queueSubmitDesc, *m_SwapChain); 483 | NRI.SetLatencyMarker(*m_SwapChain, nri::LatencyMarker::RENDER_SUBMIT_END); 484 | } else 485 | NRI.QueueSubmit(*m_GraphicsQueue, queueSubmitDesc); 486 | } 487 | 488 | NRI.EndStreamerFrame(*m_Streamer); 489 | 490 | // Present 491 | NRI.QueuePresent(*m_SwapChain, *swapChainTexture.releaseSemaphore); 492 | 493 | nri::nriEndAnnotation(); 494 | } 495 | 496 | SAMPLE_MAIN(Sample, 0); 497 | -------------------------------------------------------------------------------- /Source/Readback.cpp: -------------------------------------------------------------------------------- 1 | // © 2021 NVIDIA Corporation 2 | 3 | #include "NRIFramework.h" 4 | 5 | #include 6 | 7 | struct NRIInterface 8 | : public nri::CoreInterface, 9 | public nri::HelperInterface, 10 | public nri::StreamerInterface, 11 | public nri::SwapChainInterface {}; 12 | 13 | struct QueuedFrame { 14 | nri::CommandAllocator* commandAllocator; 15 | nri::CommandBuffer* commandBuffer; 16 | }; 17 | 18 | class Sample : public SampleBase { 19 | public: 20 | Sample() { 21 | } 22 | 23 | ~Sample(); 24 | 25 | bool Initialize(nri::GraphicsAPI graphicsAPI) override; 26 | void LatencySleep(uint32_t frameIndex) override; 27 | void PrepareFrame(uint32_t frameIndex) override; 28 | void RenderFrame(uint32_t frameIndex) override; 29 | 30 | private: 31 | NRIInterface NRI = {}; 32 | nri::Device* m_Device = nullptr; 33 | nri::Streamer* m_Streamer = nullptr; 34 | nri::SwapChain* m_SwapChain = nullptr; 35 | nri::Queue* m_GraphicsQueue = nullptr; 36 | nri::Buffer* m_ReadbackBuffer = nullptr; 37 | nri::Fence* m_FrameFence = nullptr; 38 | 39 | std::vector m_QueuedFrames = {}; 40 | std::vector m_MemoryAllocations; 41 | std::vector m_SwapChainTextures; 42 | 43 | nri::Format m_SwapChainFormat; 44 | }; 45 | 46 | Sample::~Sample() { 47 | NRI.WaitForIdle(*m_GraphicsQueue); 48 | 49 | for (QueuedFrame& queuedFrame : m_QueuedFrames) { 50 | NRI.DestroyCommandBuffer(*queuedFrame.commandBuffer); 51 | NRI.DestroyCommandAllocator(*queuedFrame.commandAllocator); 52 | } 53 | 54 | for (SwapChainTexture& swapChainTexture : m_SwapChainTextures) { 55 | NRI.DestroyFence(*swapChainTexture.acquireSemaphore); 56 | NRI.DestroyFence(*swapChainTexture.releaseSemaphore); 57 | NRI.DestroyDescriptor(*swapChainTexture.colorAttachment); 58 | } 59 | 60 | NRI.DestroyBuffer(*m_ReadbackBuffer); 61 | NRI.DestroyFence(*m_FrameFence); 62 | NRI.DestroySwapChain(*m_SwapChain); 63 | NRI.DestroyStreamer(*m_Streamer); 64 | 65 | for (size_t i = 0; i < m_MemoryAllocations.size(); i++) 66 | NRI.FreeMemory(*m_MemoryAllocations[i]); 67 | 68 | DestroyImgui(); 69 | 70 | nri::nriDestroyDevice(*m_Device); 71 | } 72 | 73 | bool Sample::Initialize(nri::GraphicsAPI graphicsAPI) { 74 | // Adapters 75 | nri::AdapterDesc adapterDesc[2] = {}; 76 | uint32_t adapterDescsNum = helper::GetCountOf(adapterDesc); 77 | NRI_ABORT_ON_FAILURE(nri::nriEnumerateAdapters(adapterDesc, adapterDescsNum)); 78 | 79 | // Device 80 | nri::DeviceCreationDesc deviceCreationDesc = {}; 81 | deviceCreationDesc.graphicsAPI = graphicsAPI; 82 | deviceCreationDesc.enableGraphicsAPIValidation = m_DebugAPI; 83 | deviceCreationDesc.enableNRIValidation = m_DebugNRI; 84 | deviceCreationDesc.enableD3D11CommandBufferEmulation = D3D11_COMMANDBUFFER_EMULATION; 85 | deviceCreationDesc.vkBindingOffsets = VK_BINDING_OFFSETS; 86 | deviceCreationDesc.adapterDesc = &adapterDesc[std::min(m_AdapterIndex, adapterDescsNum - 1)]; 87 | deviceCreationDesc.allocationCallbacks = m_AllocationCallbacks; 88 | NRI_ABORT_ON_FAILURE(nri::nriCreateDevice(deviceCreationDesc, m_Device)); 89 | 90 | // NRI 91 | NRI_ABORT_ON_FAILURE(nri::nriGetInterface(*m_Device, NRI_INTERFACE(nri::CoreInterface), (nri::CoreInterface*)&NRI)); 92 | NRI_ABORT_ON_FAILURE(nri::nriGetInterface(*m_Device, NRI_INTERFACE(nri::HelperInterface), (nri::HelperInterface*)&NRI)); 93 | NRI_ABORT_ON_FAILURE(nri::nriGetInterface(*m_Device, NRI_INTERFACE(nri::StreamerInterface), (nri::StreamerInterface*)&NRI)); 94 | NRI_ABORT_ON_FAILURE(nri::nriGetInterface(*m_Device, NRI_INTERFACE(nri::SwapChainInterface), (nri::SwapChainInterface*)&NRI)); 95 | 96 | // Create streamer 97 | nri::StreamerDesc streamerDesc = {}; 98 | streamerDesc.dynamicBufferMemoryLocation = nri::MemoryLocation::HOST_UPLOAD; 99 | streamerDesc.dynamicBufferUsageBits = nri::BufferUsageBits::VERTEX_BUFFER | nri::BufferUsageBits::INDEX_BUFFER; 100 | streamerDesc.constantBufferMemoryLocation = nri::MemoryLocation::HOST_UPLOAD; 101 | streamerDesc.queuedFrameNum = GetQueuedFrameNum(); 102 | NRI_ABORT_ON_FAILURE(NRI.CreateStreamer(*m_Device, streamerDesc, m_Streamer)); 103 | 104 | // Command queue 105 | NRI_ABORT_ON_FAILURE(NRI.GetQueue(*m_Device, nri::QueueType::GRAPHICS, 0, m_GraphicsQueue)); 106 | 107 | // Fences 108 | NRI_ABORT_ON_FAILURE(NRI.CreateFence(*m_Device, 0, m_FrameFence)); 109 | 110 | { // Swap chain 111 | nri::SwapChainDesc swapChainDesc = {}; 112 | swapChainDesc.window = GetWindow(); 113 | swapChainDesc.queue = m_GraphicsQueue; 114 | swapChainDesc.format = nri::SwapChainFormat::BT709_G22_8BIT; 115 | swapChainDesc.verticalSyncInterval = m_VsyncInterval; 116 | swapChainDesc.width = (uint16_t)GetWindowResolution().x; 117 | swapChainDesc.height = (uint16_t)GetWindowResolution().y; 118 | swapChainDesc.textureNum = GetOptimalSwapChainTextureNum(); 119 | swapChainDesc.queuedFrameNum = GetQueuedFrameNum(); 120 | NRI_ABORT_ON_FAILURE(NRI.CreateSwapChain(*m_Device, swapChainDesc, m_SwapChain)); 121 | 122 | uint32_t swapChainTextureNum; 123 | nri::Texture* const* swapChainTextures = NRI.GetSwapChainTextures(*m_SwapChain, swapChainTextureNum); 124 | 125 | m_SwapChainFormat = NRI.GetTextureDesc(*swapChainTextures[0]).format; 126 | 127 | for (uint32_t i = 0; i < swapChainTextureNum; i++) { 128 | nri::Texture2DViewDesc textureViewDesc = {swapChainTextures[i], nri::Texture2DViewType::COLOR_ATTACHMENT, m_SwapChainFormat}; 129 | 130 | nri::Descriptor* colorAttachment = nullptr; 131 | NRI_ABORT_ON_FAILURE(NRI.CreateTexture2DView(textureViewDesc, colorAttachment)); 132 | 133 | nri::Fence* acquireSemaphore = nullptr; 134 | NRI_ABORT_ON_FAILURE(NRI.CreateFence(*m_Device, nri::SWAPCHAIN_SEMAPHORE, acquireSemaphore)); 135 | 136 | nri::Fence* releaseSemaphore = nullptr; 137 | NRI_ABORT_ON_FAILURE(NRI.CreateFence(*m_Device, nri::SWAPCHAIN_SEMAPHORE, releaseSemaphore)); 138 | 139 | SwapChainTexture& swapChainTexture = m_SwapChainTextures.emplace_back(); 140 | 141 | swapChainTexture = {}; 142 | swapChainTexture.acquireSemaphore = acquireSemaphore; 143 | swapChainTexture.releaseSemaphore = releaseSemaphore; 144 | swapChainTexture.texture = swapChainTextures[i]; 145 | swapChainTexture.colorAttachment = colorAttachment; 146 | swapChainTexture.attachmentFormat = m_SwapChainFormat; 147 | } 148 | } 149 | 150 | // Queued frames 151 | m_QueuedFrames.resize(GetQueuedFrameNum()); 152 | for (QueuedFrame& queuedFrame : m_QueuedFrames) { 153 | NRI_ABORT_ON_FAILURE(NRI.CreateCommandAllocator(*m_GraphicsQueue, queuedFrame.commandAllocator)); 154 | NRI_ABORT_ON_FAILURE(NRI.CreateCommandBuffer(*queuedFrame.commandAllocator, queuedFrame.commandBuffer)); 155 | } 156 | 157 | const nri::DeviceDesc& deviceDesc = NRI.GetDeviceDesc(*m_Device); 158 | 159 | { // Readback buffer 160 | nri::BufferDesc bufferDesc = {}; 161 | bufferDesc.size = helper::Align(4, deviceDesc.memoryAlignment.uploadBufferTextureRow); 162 | NRI_ABORT_ON_FAILURE(NRI.CreateBuffer(*m_Device, bufferDesc, m_ReadbackBuffer)); 163 | 164 | nri::ResourceGroupDesc resourceGroupDesc = {}; 165 | resourceGroupDesc.memoryLocation = nri::MemoryLocation::HOST_READBACK; 166 | resourceGroupDesc.bufferNum = 1; 167 | resourceGroupDesc.buffers = &m_ReadbackBuffer; 168 | 169 | m_MemoryAllocations.resize(1, nullptr); 170 | NRI_ABORT_ON_FAILURE(NRI.AllocateAndBindMemory(*m_Device, resourceGroupDesc, m_MemoryAllocations.data())); 171 | } 172 | 173 | return InitImgui(*m_Device); 174 | } 175 | 176 | void Sample::LatencySleep(uint32_t frameIndex) { 177 | uint32_t queuedFrameIndex = frameIndex % GetQueuedFrameNum(); 178 | const QueuedFrame& queuedFrame = m_QueuedFrames[queuedFrameIndex]; 179 | 180 | NRI.Wait(*m_FrameFence, frameIndex >= GetQueuedFrameNum() ? 1 + frameIndex - GetQueuedFrameNum() : 0); 181 | NRI.ResetCommandAllocator(*queuedFrame.commandAllocator); 182 | } 183 | 184 | void Sample::PrepareFrame(uint32_t) { 185 | ImGui::NewFrame(); 186 | { 187 | uint32_t color = 0; 188 | const uint32_t* data = (uint32_t*)NRI.MapBuffer(*m_ReadbackBuffer, 0, nri::WHOLE_SIZE); 189 | if (data) { 190 | color = *data | 0xFF000000; 191 | NRI.UnmapBuffer(*m_ReadbackBuffer); 192 | } 193 | 194 | if (m_SwapChainFormat == nri::Format::BGRA8_UNORM) { 195 | uint8_t* bgra = (uint8_t*)&color; 196 | Swap(bgra[0], bgra[2]); 197 | } 198 | 199 | ImVec2 p = ImGui::GetIO().MousePos; 200 | p.x += 24; 201 | 202 | float sz = ImGui::GetTextLineHeight(); 203 | ImGui::SetNextWindowPos(p, ImGuiCond_Always); 204 | ImGui::Begin("ColorWindow", nullptr, ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize); 205 | { 206 | p = ImGui::GetCursorScreenPos(); 207 | ImGui::GetWindowDrawList()->AddRectFilled(p, ImVec2(p.x + sz, p.y + sz), color); 208 | ImGui::Dummy(ImVec2(sz, sz)); 209 | ImGui::SameLine(); 210 | ImGui::Text("Color"); 211 | } 212 | ImGui::End(); 213 | } 214 | ImGui::EndFrame(); 215 | ImGui::Render(); 216 | } 217 | 218 | void Sample::RenderFrame(uint32_t frameIndex) { 219 | const uint32_t windowWidth = GetWindowResolution().x; 220 | const uint32_t windowHeight = GetWindowResolution().y; 221 | uint32_t queuedFrameIndex = frameIndex % GetQueuedFrameNum(); 222 | const QueuedFrame& queuedFrame = m_QueuedFrames[queuedFrameIndex]; 223 | 224 | // Acquire a swap chain texture 225 | uint32_t recycledSemaphoreIndex = frameIndex % (uint32_t)m_SwapChainTextures.size(); 226 | nri::Fence* swapChainAcquireSemaphore = m_SwapChainTextures[recycledSemaphoreIndex].acquireSemaphore; 227 | 228 | uint32_t currentSwapChainTextureIndex = 0; 229 | NRI.AcquireNextTexture(*m_SwapChain, *swapChainAcquireSemaphore, currentSwapChainTextureIndex); 230 | 231 | const SwapChainTexture& swapChainTexture = m_SwapChainTextures[currentSwapChainTextureIndex]; 232 | 233 | // Record 234 | nri::CommandBuffer& commandBuffer = *queuedFrame.commandBuffer; 235 | NRI.BeginCommandBuffer(commandBuffer, nullptr); 236 | { 237 | nri::TextureBarrierDesc textureBarriers = {}; 238 | textureBarriers.texture = swapChainTexture.texture; 239 | textureBarriers.after = {nri::AccessBits::COPY_SOURCE, nri::Layout::COPY_SOURCE}; 240 | textureBarriers.layerNum = 1; 241 | textureBarriers.mipNum = 1; 242 | 243 | nri::BarrierGroupDesc barrierGroupDesc = {}; 244 | barrierGroupDesc.textureNum = 1; 245 | barrierGroupDesc.textures = &textureBarriers; 246 | NRI.CmdBarrier(commandBuffer, barrierGroupDesc); 247 | 248 | nri::TextureDataLayoutDesc dstDataLayoutDesc = {}; 249 | dstDataLayoutDesc.rowPitch = helper::Align(4, NRI.GetDeviceDesc(*m_Device).memoryAlignment.uploadBufferTextureRow); 250 | 251 | nri::TextureRegionDesc srcRegionDesc = {}; 252 | srcRegionDesc.x = (uint16_t)clamp(ImGui::GetMousePos().x, 0.0f, float(windowWidth - 1)); 253 | srcRegionDesc.y = (uint16_t)clamp(ImGui::GetMousePos().y, 0.0f, float(windowHeight - 1)); 254 | srcRegionDesc.width = 1; 255 | srcRegionDesc.height = 1; 256 | srcRegionDesc.depth = 1; 257 | 258 | // before clearing the texture read back contents under the mouse cursor 259 | NRI.CmdReadbackTextureToBuffer(commandBuffer, *m_ReadbackBuffer, dstDataLayoutDesc, *swapChainTexture.texture, srcRegionDesc); 260 | 261 | textureBarriers.before = textureBarriers.after; 262 | textureBarriers.after = {nri::AccessBits::COLOR_ATTACHMENT, nri::Layout::COLOR_ATTACHMENT}; 263 | NRI.CmdBarrier(commandBuffer, barrierGroupDesc); 264 | 265 | nri::AttachmentsDesc attachmentsDesc = {}; 266 | attachmentsDesc.colorNum = 1; 267 | attachmentsDesc.colors = &swapChainTexture.colorAttachment; 268 | 269 | NRI.CmdBeginRendering(commandBuffer, attachmentsDesc); 270 | { 271 | helper::Annotation annotation(NRI, commandBuffer, "Clear"); 272 | 273 | nri::ClearDesc clearDesc = {}; 274 | clearDesc.colorAttachmentIndex = 0; 275 | clearDesc.planes = nri::PlaneBits::COLOR; 276 | 277 | nri::Dim_t w = (nri::Dim_t)GetWindowResolution().x; 278 | nri::Dim_t h = (nri::Dim_t)GetWindowResolution().y; 279 | nri::Dim_t h3 = h / 3; 280 | int16_t y = (int16_t)h3; 281 | 282 | clearDesc.value.color.f = {1.0f, 0.0f, 0.0f, 1.0f}; 283 | nri::Rect rect1 = {0, 0, w, h3}; 284 | NRI.CmdClearAttachments(commandBuffer, &clearDesc, 1, &rect1, 1); 285 | 286 | clearDesc.value.color.f = {0.0f, 1.0f, 0.0f, 1.0f}; 287 | nri::Rect rect2 = {0, y, w, h3}; 288 | NRI.CmdClearAttachments(commandBuffer, &clearDesc, 1, &rect2, 1); 289 | 290 | clearDesc.value.color.f = {0.0f, 0.0f, 1.0f, 1.0f}; 291 | nri::Rect rect3 = {0, static_cast(y * 2), w, h3}; 292 | NRI.CmdClearAttachments(commandBuffer, &clearDesc, 1, &rect3, 1); 293 | 294 | RenderImgui(commandBuffer, *m_Streamer, swapChainTexture.attachmentFormat, 1.0f, true); 295 | } 296 | NRI.CmdEndRendering(commandBuffer); 297 | 298 | textureBarriers.before = textureBarriers.after; 299 | textureBarriers.after = {nri::AccessBits::UNKNOWN, nri::Layout::PRESENT}; 300 | 301 | NRI.CmdBarrier(commandBuffer, barrierGroupDesc); 302 | } 303 | NRI.EndCommandBuffer(commandBuffer); 304 | 305 | { // Submit 306 | nri::FenceSubmitDesc textureAcquiredFence = {}; 307 | textureAcquiredFence.fence = swapChainAcquireSemaphore; 308 | textureAcquiredFence.stages = nri::StageBits::COLOR_ATTACHMENT; 309 | 310 | nri::FenceSubmitDesc renderingFinishedFence = {}; 311 | renderingFinishedFence.fence = swapChainTexture.releaseSemaphore; 312 | 313 | nri::QueueSubmitDesc queueSubmitDesc = {}; 314 | queueSubmitDesc.waitFences = &textureAcquiredFence; 315 | queueSubmitDesc.waitFenceNum = 1; 316 | queueSubmitDesc.commandBuffers = &queuedFrame.commandBuffer; 317 | queueSubmitDesc.commandBufferNum = 1; 318 | queueSubmitDesc.signalFences = &renderingFinishedFence; 319 | queueSubmitDesc.signalFenceNum = 1; 320 | 321 | NRI.QueueSubmit(*m_GraphicsQueue, queueSubmitDesc); 322 | } 323 | 324 | NRI.EndStreamerFrame(*m_Streamer); 325 | 326 | // Present 327 | NRI.QueuePresent(*m_SwapChain, *swapChainTexture.releaseSemaphore); 328 | 329 | { // Signaling after "Present" improves D3D11 performance a bit 330 | nri::FenceSubmitDesc signalFence = {}; 331 | signalFence.fence = m_FrameFence; 332 | signalFence.value = 1 + frameIndex; 333 | 334 | nri::QueueSubmitDesc queueSubmitDesc = {}; 335 | queueSubmitDesc.signalFences = &signalFence; 336 | queueSubmitDesc.signalFenceNum = 1; 337 | 338 | NRI.QueueSubmit(*m_GraphicsQueue, queueSubmitDesc); 339 | } 340 | } 341 | 342 | SAMPLE_MAIN(Sample, 0); 343 | -------------------------------------------------------------------------------- /Source/Resize.cpp: -------------------------------------------------------------------------------- 1 | // © 2023 NVIDIA Corporation 2 | 3 | #include "NRIFramework.h" 4 | 5 | #define SWITCH_TIME 2.5f 6 | 7 | struct NRIInterface 8 | : public nri::CoreInterface, 9 | public nri::HelperInterface, 10 | public nri::StreamerInterface, 11 | public nri::SwapChainInterface {}; 12 | 13 | struct QueuedFrame { 14 | nri::CommandAllocator* commandAllocator; 15 | nri::CommandBuffer* commandBuffer; 16 | }; 17 | 18 | class Sample : public SampleBase { 19 | public: 20 | Sample() { 21 | } 22 | 23 | ~Sample(); 24 | 25 | bool Initialize(nri::GraphicsAPI graphicsAPI) override; 26 | void LatencySleep(uint32_t frameIndex) override; 27 | void PrepareFrame(uint32_t frameIndex) override; 28 | void RenderFrame(uint32_t frameIndex) override; 29 | 30 | void ResizeSwapChain(); 31 | 32 | private: 33 | NRIInterface NRI = {}; 34 | nri::Device* m_Device = nullptr; 35 | nri::Streamer* m_Streamer = nullptr; 36 | nri::SwapChain* m_SwapChain = nullptr; 37 | nri::Queue* m_GraphicsQueue = nullptr; 38 | nri::Fence* m_FrameFence = nullptr; 39 | 40 | std::vector m_QueuedFrames = {}; 41 | std::vector m_MemoryAllocations; 42 | std::vector m_SwapChainTextures; 43 | 44 | float m_Time = SWITCH_TIME; 45 | uint2 m_PrevWindowResolution; 46 | bool m_IsFullscreen = false; 47 | }; 48 | 49 | Sample::~Sample() { 50 | NRI.WaitForIdle(*m_GraphicsQueue); 51 | 52 | for (QueuedFrame& queuedFrame : m_QueuedFrames) { 53 | NRI.DestroyCommandBuffer(*queuedFrame.commandBuffer); 54 | NRI.DestroyCommandAllocator(*queuedFrame.commandAllocator); 55 | } 56 | 57 | for (SwapChainTexture& swapChainTexture : m_SwapChainTextures) { 58 | NRI.DestroyFence(*swapChainTexture.acquireSemaphore); 59 | NRI.DestroyFence(*swapChainTexture.releaseSemaphore); 60 | NRI.DestroyDescriptor(*swapChainTexture.colorAttachment); 61 | } 62 | 63 | NRI.DestroyFence(*m_FrameFence); 64 | NRI.DestroySwapChain(*m_SwapChain); 65 | NRI.DestroyStreamer(*m_Streamer); 66 | 67 | for (size_t i = 0; i < m_MemoryAllocations.size(); i++) 68 | NRI.FreeMemory(*m_MemoryAllocations[i]); 69 | 70 | DestroyImgui(); 71 | 72 | nri::nriDestroyDevice(*m_Device); 73 | } 74 | 75 | bool Sample::Initialize(nri::GraphicsAPI graphicsAPI) { 76 | m_PrevWindowResolution = m_WindowResolution; 77 | 78 | // Adapters 79 | nri::AdapterDesc adapterDesc[2] = {}; 80 | uint32_t adapterDescsNum = helper::GetCountOf(adapterDesc); 81 | NRI_ABORT_ON_FAILURE(nri::nriEnumerateAdapters(adapterDesc, adapterDescsNum)); 82 | 83 | // Device 84 | nri::DeviceCreationDesc deviceCreationDesc = {}; 85 | deviceCreationDesc.graphicsAPI = graphicsAPI; 86 | deviceCreationDesc.enableGraphicsAPIValidation = m_DebugAPI; 87 | deviceCreationDesc.enableNRIValidation = m_DebugNRI; 88 | deviceCreationDesc.enableD3D11CommandBufferEmulation = D3D11_COMMANDBUFFER_EMULATION; 89 | deviceCreationDesc.vkBindingOffsets = VK_BINDING_OFFSETS; 90 | deviceCreationDesc.adapterDesc = &adapterDesc[std::min(m_AdapterIndex, adapterDescsNum - 1)]; 91 | deviceCreationDesc.allocationCallbacks = m_AllocationCallbacks; 92 | NRI_ABORT_ON_FAILURE(nri::nriCreateDevice(deviceCreationDesc, m_Device)); 93 | 94 | // NRI 95 | NRI_ABORT_ON_FAILURE(nri::nriGetInterface(*m_Device, NRI_INTERFACE(nri::CoreInterface), (nri::CoreInterface*)&NRI)); 96 | NRI_ABORT_ON_FAILURE(nri::nriGetInterface(*m_Device, NRI_INTERFACE(nri::HelperInterface), (nri::HelperInterface*)&NRI)); 97 | NRI_ABORT_ON_FAILURE(nri::nriGetInterface(*m_Device, NRI_INTERFACE(nri::StreamerInterface), (nri::StreamerInterface*)&NRI)); 98 | NRI_ABORT_ON_FAILURE(nri::nriGetInterface(*m_Device, NRI_INTERFACE(nri::SwapChainInterface), (nri::SwapChainInterface*)&NRI)); 99 | 100 | // Create streamer 101 | nri::StreamerDesc streamerDesc = {}; 102 | streamerDesc.dynamicBufferMemoryLocation = nri::MemoryLocation::HOST_UPLOAD; 103 | streamerDesc.dynamicBufferUsageBits = nri::BufferUsageBits::VERTEX_BUFFER | nri::BufferUsageBits::INDEX_BUFFER; 104 | streamerDesc.constantBufferMemoryLocation = nri::MemoryLocation::HOST_UPLOAD; 105 | streamerDesc.queuedFrameNum = GetQueuedFrameNum(); 106 | NRI_ABORT_ON_FAILURE(NRI.CreateStreamer(*m_Device, streamerDesc, m_Streamer)); 107 | 108 | // Command queue 109 | NRI_ABORT_ON_FAILURE(NRI.GetQueue(*m_Device, nri::QueueType::GRAPHICS, 0, m_GraphicsQueue)); 110 | 111 | // Fences 112 | NRI_ABORT_ON_FAILURE(NRI.CreateFence(*m_Device, 0, m_FrameFence)); 113 | 114 | { // Swap chain 115 | nri::SwapChainDesc swapChainDesc = {}; 116 | swapChainDesc.window = GetWindow(); 117 | swapChainDesc.queue = m_GraphicsQueue; 118 | swapChainDesc.format = nri::SwapChainFormat::BT709_G22_8BIT; 119 | swapChainDesc.verticalSyncInterval = m_VsyncInterval; 120 | swapChainDesc.width = (uint16_t)m_WindowResolution.x; 121 | swapChainDesc.height = (uint16_t)m_WindowResolution.y; 122 | swapChainDesc.textureNum = GetOptimalSwapChainTextureNum(); 123 | swapChainDesc.queuedFrameNum = GetQueuedFrameNum(); 124 | NRI_ABORT_ON_FAILURE(NRI.CreateSwapChain(*m_Device, swapChainDesc, m_SwapChain)); 125 | 126 | uint32_t swapChainTextureNum; 127 | nri::Texture* const* swapChainTextures = NRI.GetSwapChainTextures(*m_SwapChain, swapChainTextureNum); 128 | 129 | nri::Format swapChainFormat = NRI.GetTextureDesc(*swapChainTextures[0]).format; 130 | 131 | for (uint32_t i = 0; i < swapChainTextureNum; i++) { 132 | nri::Texture2DViewDesc textureViewDesc = {swapChainTextures[i], nri::Texture2DViewType::COLOR_ATTACHMENT, swapChainFormat}; 133 | 134 | nri::Descriptor* colorAttachment = nullptr; 135 | NRI_ABORT_ON_FAILURE(NRI.CreateTexture2DView(textureViewDesc, colorAttachment)); 136 | 137 | nri::Fence* acquireSemaphore = nullptr; 138 | NRI_ABORT_ON_FAILURE(NRI.CreateFence(*m_Device, nri::SWAPCHAIN_SEMAPHORE, acquireSemaphore)); 139 | 140 | nri::Fence* releaseSemaphore = nullptr; 141 | NRI_ABORT_ON_FAILURE(NRI.CreateFence(*m_Device, nri::SWAPCHAIN_SEMAPHORE, releaseSemaphore)); 142 | 143 | SwapChainTexture& swapChainTexture = m_SwapChainTextures.emplace_back(); 144 | 145 | swapChainTexture = {}; 146 | swapChainTexture.acquireSemaphore = acquireSemaphore; 147 | swapChainTexture.releaseSemaphore = releaseSemaphore; 148 | swapChainTexture.texture = swapChainTextures[i]; 149 | swapChainTexture.colorAttachment = colorAttachment; 150 | swapChainTexture.attachmentFormat = swapChainFormat; 151 | } 152 | } 153 | 154 | // Queued frames 155 | m_QueuedFrames.resize(GetQueuedFrameNum()); 156 | for (QueuedFrame& queuedFrame : m_QueuedFrames) { 157 | NRI_ABORT_ON_FAILURE(NRI.CreateCommandAllocator(*m_GraphicsQueue, queuedFrame.commandAllocator)); 158 | NRI_ABORT_ON_FAILURE(NRI.CreateCommandBuffer(*queuedFrame.commandAllocator, queuedFrame.commandBuffer)); 159 | } 160 | 161 | return InitImgui(*m_Device); 162 | } 163 | 164 | void Sample::LatencySleep(uint32_t frameIndex) { 165 | uint32_t queuedFrameIndex = frameIndex % GetQueuedFrameNum(); 166 | const QueuedFrame& queuedFrame = m_QueuedFrames[queuedFrameIndex]; 167 | 168 | NRI.Wait(*m_FrameFence, frameIndex >= GetQueuedFrameNum() ? 1 + frameIndex - GetQueuedFrameNum() : 0); 169 | NRI.ResetCommandAllocator(*queuedFrame.commandAllocator); 170 | } 171 | 172 | void Sample::PrepareFrame(uint32_t) { 173 | // Info text 174 | m_Time -= m_Timer.GetSmoothedFrameTime() / 1000.0f; 175 | m_Time = std::max(m_Time, 0.0f); 176 | 177 | char s[64]; 178 | if (m_IsFullscreen) 179 | snprintf(s, sizeof(s), "Going windowed in %.1f...", m_Time); 180 | else 181 | snprintf(s, sizeof(s), "Going fullscreen in %.1f...", m_Time); 182 | 183 | // Resize 184 | if (m_Time == 0.0f) { 185 | m_IsFullscreen = !m_IsFullscreen; 186 | m_Time = SWITCH_TIME; 187 | 188 | GLFWmonitor* monitor = glfwGetPrimaryMonitor(); 189 | const GLFWvidmode* vidmode = glfwGetVideoMode(monitor); 190 | uint32_t w = (uint32_t)vidmode->width; 191 | uint32_t h = (uint32_t)vidmode->height; 192 | 193 | if (m_IsFullscreen) 194 | m_WindowResolution = uint2(w, h); 195 | else 196 | m_WindowResolution = m_PrevWindowResolution; 197 | 198 | uint32_t x = (w - m_WindowResolution.x) >> 1; 199 | uint32_t y = (h - m_WindowResolution.y) >> 1; 200 | 201 | glfwSetWindowAttrib(m_Window, GLFW_DECORATED, m_IsFullscreen ? 0 : 1); 202 | #if (NRIF_PLATFORM != NRIF_WAYLAND) 203 | glfwSetWindowPos(m_Window, x, y); 204 | #endif 205 | glfwSetWindowSize(m_Window, m_WindowResolution.x, m_WindowResolution.y); 206 | 207 | ResizeSwapChain(); 208 | } 209 | 210 | // UI 211 | ImGui::NewFrame(); 212 | { 213 | ImVec2 dims = ImGui::CalcTextSize(s); 214 | 215 | ImVec2 p; 216 | p.x = ((float)m_WindowResolution.x - dims.x) * 0.5f; 217 | p.y = ((float)m_WindowResolution.y - dims.y) * 0.5f; 218 | 219 | ImGui::SetNextWindowPos(p); 220 | ImGui::Begin("Color", nullptr, ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize); 221 | { 222 | ImGui::Text("%s", s); 223 | } 224 | ImGui::End(); 225 | } 226 | ImGui::EndFrame(); 227 | ImGui::Render(); 228 | } 229 | 230 | void Sample::ResizeSwapChain() { 231 | // Wait for idle 232 | NRI.WaitForIdle(*m_GraphicsQueue); 233 | 234 | // Destroy old swapchain 235 | for (SwapChainTexture& swapChainTexture : m_SwapChainTextures) { 236 | NRI.DestroyFence(*swapChainTexture.acquireSemaphore); 237 | NRI.DestroyFence(*swapChainTexture.releaseSemaphore); 238 | NRI.DestroyDescriptor(*swapChainTexture.colorAttachment); 239 | } 240 | 241 | NRI.DestroySwapChain(*m_SwapChain); 242 | 243 | // Create new swapchain 244 | nri::SwapChainDesc swapChainDesc = {}; 245 | swapChainDesc.window = GetWindow(); 246 | swapChainDesc.queue = m_GraphicsQueue; 247 | swapChainDesc.format = nri::SwapChainFormat::BT709_G22_8BIT; 248 | swapChainDesc.verticalSyncInterval = m_VsyncInterval; 249 | swapChainDesc.width = (uint16_t)m_WindowResolution.x; 250 | swapChainDesc.height = (uint16_t)m_WindowResolution.y; 251 | swapChainDesc.textureNum = GetOptimalSwapChainTextureNum(); 252 | swapChainDesc.queuedFrameNum = GetQueuedFrameNum(); 253 | NRI_ABORT_ON_FAILURE(NRI.CreateSwapChain(*m_Device, swapChainDesc, m_SwapChain)); 254 | 255 | uint32_t swapChainTextureNum; 256 | nri::Texture* const* swapChainTextures = NRI.GetSwapChainTextures(*m_SwapChain, swapChainTextureNum); 257 | 258 | nri::Format swapChainFormat = NRI.GetTextureDesc(*swapChainTextures[0]).format; 259 | 260 | m_SwapChainTextures.clear(); 261 | for (uint32_t i = 0; i < swapChainTextureNum; i++) { 262 | nri::Texture2DViewDesc textureViewDesc = {swapChainTextures[i], nri::Texture2DViewType::COLOR_ATTACHMENT, swapChainFormat}; 263 | 264 | nri::Descriptor* colorAttachment = nullptr; 265 | NRI_ABORT_ON_FAILURE(NRI.CreateTexture2DView(textureViewDesc, colorAttachment)); 266 | 267 | nri::Fence* acquireSemaphore = nullptr; 268 | NRI_ABORT_ON_FAILURE(NRI.CreateFence(*m_Device, nri::SWAPCHAIN_SEMAPHORE, acquireSemaphore)); 269 | 270 | nri::Fence* releaseSemaphore = nullptr; 271 | NRI_ABORT_ON_FAILURE(NRI.CreateFence(*m_Device, nri::SWAPCHAIN_SEMAPHORE, releaseSemaphore)); 272 | 273 | SwapChainTexture& swapChainTexture = m_SwapChainTextures.emplace_back(); 274 | 275 | swapChainTexture = {}; 276 | swapChainTexture.acquireSemaphore = acquireSemaphore; 277 | swapChainTexture.releaseSemaphore = releaseSemaphore; 278 | swapChainTexture.texture = swapChainTextures[i]; 279 | swapChainTexture.colorAttachment = colorAttachment; 280 | swapChainTexture.attachmentFormat = swapChainFormat; 281 | } 282 | } 283 | 284 | void Sample::RenderFrame(uint32_t frameIndex) { 285 | uint32_t queuedFrameIndex = frameIndex % GetQueuedFrameNum(); 286 | const QueuedFrame& queuedFrame = m_QueuedFrames[queuedFrameIndex]; 287 | 288 | // Acquire a swap chain texture 289 | uint32_t recycledSemaphoreIndex = frameIndex % (uint32_t)m_SwapChainTextures.size(); 290 | nri::Fence* swapChainAcquireSemaphore = m_SwapChainTextures[recycledSemaphoreIndex].acquireSemaphore; 291 | 292 | uint32_t currentSwapChainTextureIndex = 0; 293 | NRI.AcquireNextTexture(*m_SwapChain, *swapChainAcquireSemaphore, currentSwapChainTextureIndex); 294 | 295 | const SwapChainTexture& swapChainTexture = m_SwapChainTextures[currentSwapChainTextureIndex]; 296 | 297 | // Record 298 | nri::CommandBuffer& commandBuffer = *queuedFrame.commandBuffer; 299 | NRI.BeginCommandBuffer(commandBuffer, nullptr); 300 | { 301 | nri::TextureBarrierDesc textureBarriers = {}; 302 | textureBarriers.texture = swapChainTexture.texture; 303 | textureBarriers.after = {nri::AccessBits::COPY_SOURCE, nri::Layout::COPY_SOURCE}; 304 | textureBarriers.layerNum = 1; 305 | textureBarriers.mipNum = 1; 306 | 307 | nri::BarrierGroupDesc barrierGroupDesc = {}; 308 | barrierGroupDesc.textureNum = 1; 309 | barrierGroupDesc.textures = &textureBarriers; 310 | NRI.CmdBarrier(commandBuffer, barrierGroupDesc); 311 | 312 | nri::TextureDataLayoutDesc dstDataLayoutDesc = {}; 313 | dstDataLayoutDesc.rowPitch = NRI.GetDeviceDesc(*m_Device).memoryAlignment.uploadBufferTextureRow; 314 | 315 | textureBarriers.before = textureBarriers.after; 316 | textureBarriers.after = {nri::AccessBits::COLOR_ATTACHMENT, nri::Layout::COLOR_ATTACHMENT}; 317 | NRI.CmdBarrier(commandBuffer, barrierGroupDesc); 318 | 319 | nri::AttachmentsDesc attachmentsDesc = {}; 320 | attachmentsDesc.colorNum = 1; 321 | attachmentsDesc.colors = &swapChainTexture.colorAttachment; 322 | 323 | NRI.CmdBeginRendering(commandBuffer, attachmentsDesc); 324 | { 325 | helper::Annotation annotation(NRI, commandBuffer, "Clear"); 326 | 327 | nri::ClearDesc clearDesc = {}; 328 | clearDesc.planes = nri::PlaneBits::COLOR; 329 | if (m_IsFullscreen) 330 | clearDesc.value.color.f = {0.0f, 1.0f, 0.0f, 1.0f}; 331 | else 332 | clearDesc.value.color.f = {1.0f, 0.0f, 0.0f, 1.0f}; 333 | NRI.CmdClearAttachments(commandBuffer, &clearDesc, 1, nullptr, 0); 334 | 335 | RenderImgui(commandBuffer, *m_Streamer, swapChainTexture.attachmentFormat, 1.0f, true); 336 | } 337 | NRI.CmdEndRendering(commandBuffer); 338 | 339 | textureBarriers.before = textureBarriers.after; 340 | textureBarriers.after = {nri::AccessBits::UNKNOWN, nri::Layout::PRESENT}; 341 | 342 | NRI.CmdBarrier(commandBuffer, barrierGroupDesc); 343 | } 344 | NRI.EndCommandBuffer(commandBuffer); 345 | 346 | { // Submit 347 | nri::FenceSubmitDesc textureAcquiredFence = {}; 348 | textureAcquiredFence.fence = swapChainAcquireSemaphore; 349 | textureAcquiredFence.stages = nri::StageBits::COLOR_ATTACHMENT; 350 | 351 | nri::FenceSubmitDesc renderingFinishedFence = {}; 352 | renderingFinishedFence.fence = swapChainTexture.releaseSemaphore; 353 | 354 | nri::QueueSubmitDesc queueSubmitDesc = {}; 355 | queueSubmitDesc.waitFences = &textureAcquiredFence; 356 | queueSubmitDesc.waitFenceNum = 1; 357 | queueSubmitDesc.commandBuffers = &queuedFrame.commandBuffer; 358 | queueSubmitDesc.commandBufferNum = 1; 359 | queueSubmitDesc.signalFences = &renderingFinishedFence; 360 | queueSubmitDesc.signalFenceNum = 1; 361 | 362 | NRI.QueueSubmit(*m_GraphicsQueue, queueSubmitDesc); 363 | } 364 | 365 | NRI.EndStreamerFrame(*m_Streamer); 366 | 367 | // Present 368 | NRI.QueuePresent(*m_SwapChain, *swapChainTexture.releaseSemaphore); 369 | 370 | { // Signaling after "Present" improves D3D11 performance a bit 371 | nri::FenceSubmitDesc signalFence = {}; 372 | signalFence.fence = m_FrameFence; 373 | signalFence.value = 1 + frameIndex; 374 | 375 | nri::QueueSubmitDesc queueSubmitDesc = {}; 376 | queueSubmitDesc.signalFences = &signalFence; 377 | queueSubmitDesc.signalFenceNum = 1; 378 | 379 | NRI.QueueSubmit(*m_GraphicsQueue, queueSubmitDesc); 380 | } 381 | } 382 | 383 | SAMPLE_MAIN(Sample, 0); 384 | --------------------------------------------------------------------------------